home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 May / macformat-024.iso / Shareware City / Developers / nshellmegasource1.50 / mega src / commands / read.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-09-15  |  6.6 KB  |  304 lines  |  [TEXT/KAHL]

  1. /* ========== the commmand file: ==========
  2.  
  3.     read.c
  4.     
  5.     Copyright (c) 1994 Newport Software Development
  6.     
  7.     You may distribute unmodified copies of this file for
  8.     noncommercial purposes.  You may use this file as a
  9.     reference when writing your own nShell(tm) commands.
  10.     
  11.     All other rights are reserved.
  12.     
  13.    ========== the commmand file: ========== */
  14.  
  15. #ifdef __MWERKS__            // CodeWarrior requires an A4 setup
  16. #include <A4Stuff.h>
  17. #endif
  18.  
  19. #include "nshc.h"
  20. #include "str_utl.proto.h"
  21. #include "nshc_utl.proto.h"
  22.  
  23. /* ======================================== */
  24.  
  25. typedef enum { ERROR_NONE, ERROR_USAGE, ERROR_QUOTES, ERROR_INPUT } t_read_error;
  26.  
  27. /* ======================================== */
  28.  
  29. // prototypes - for local use only
  30.  
  31. void read_error( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls, int error );
  32. void read_start( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls );
  33. void read_continue( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls );
  34. void read_stop( t_nshc_parms *nshc_parms );
  35.  
  36. /* ======================================== */
  37.  
  38. // report errors and set return code
  39.  
  40. void read_error( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls, int error )
  41. {
  42.  
  43.     switch (error) {
  44.         case ERROR_USAGE:
  45.             nshc_calls->NSH_putStr_err( "\pUsage: read variable [variable...]\r" );
  46.             nshc_parms->result = NSHC_ERR_PARMS;
  47.             break;
  48.         case ERROR_QUOTES:
  49.             nshc_calls->NSH_putStr_err( "\pread: Unbalanced quotes.\r" );
  50.             nshc_parms->result = NSHC_ERR_GENERAL;
  51.             break;
  52.         case ERROR_INPUT:
  53.             nshc_calls->NSH_putStr_err( "\pread: Input string is too long.\r" );
  54.             nshc_parms->result = NSHC_ERR_GENERAL;
  55.             break;
  56.         }
  57.         
  58.     nshc_parms->action = nsh_idle;
  59. }
  60.  
  61. /* ======================================== */
  62.  
  63. // state machine start
  64.  
  65. void read_start( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls )
  66. {
  67.     int        arg;
  68.     int        error;
  69.     int        i;
  70.     char    c;
  71.     char    *p;
  72.     char    *q;
  73.     
  74.     nshc_parms->action = nsh_continue;
  75.     nshc_parms->result = NSHC_NO_ERR;
  76.     
  77.     // bail if bad usage
  78.     
  79.     if (nshc_parms->argc < 2) {
  80.         read_error( nshc_parms, nshc_calls, ERROR_USAGE );
  81.         return;
  82.         }
  83.     
  84.     // or bail if any parameter is not a good variable
  85.     
  86.     for ( arg = 1; arg < nshc_parms->argc; arg++ ) {
  87.         p = q = &nshc_parms->arg_buf[ nshc_parms->argv[ arg ] ];
  88.         i = 0;
  89.         while (c = *p++) {
  90.             error = 1;
  91.             if ( c == '_' ) error = 0; else
  92.             if ( ( c >= 'a' ) && ( c <= 'z' ) ) error = 0; else
  93.             if ( ( c >= 'A' ) && ( c <= 'Z' ) ) error = 0; else
  94.             if ( ( c >= '0' ) && ( c <= '9' ) ) error = 0;
  95.             if (error) {
  96.                 nshc_calls->NSH_putStr_err( "\pread: Invalid variable name = " );
  97.                 nshc_calls->NSH_puts_err( q );
  98.                 nshc_calls->NSH_putchar_err( '\r' );
  99.                 nshc_parms->result = NSHC_ERR_PARMS;
  100.                 nshc_parms->action = nsh_idle;
  101.                 return;
  102.                 }
  103.             i++;
  104.             }
  105.         if ( i > 31 ) {
  106.             nshc_calls->NSH_putStr_err( "\pread: Variable name too long = " );
  107.             nshc_calls->NSH_puts_err( q );
  108.             nshc_calls->NSH_putchar_err( '\r' );
  109.             nshc_parms->result = NSHC_ERR_PARMS;
  110.             nshc_parms->action = nsh_idle;
  111.             return;
  112.             }
  113.         }
  114.     
  115.     // otherwise, might as well take one pass at some real work
  116.     
  117.     read_continue( nshc_parms, nshc_calls );
  118. }
  119.  
  120. /* ======================================== */
  121.  
  122. // state machine continue
  123.  
  124. void read_continue( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls )
  125. {
  126.     int        arg;
  127.     int        more;
  128.     int        got_one;
  129.     int        last_one;
  130.     char    c;
  131.     char    quote;
  132.     int        i,j;
  133.     char    my_buf[LINE_MAX];
  134.     Str32    name;
  135.     Str255    value;
  136.     
  137.     // try the input buffer
  138.     
  139.     i = nshc_calls->NSH_gets( my_buf, LINE_MAX );
  140.     
  141.     // if we got a line, process it
  142.     
  143.     if (i) {
  144.     
  145.         i = 0;
  146.         arg = 0;
  147.         got_one = 0;
  148.         last_one = 0;
  149.         c = my_buf[i];
  150.         
  151.         // as long as characters are in the buf and args to fill
  152.     
  153.         while ( c && ( c != '\r') && (arg < nshc_parms->argc) ) {
  154.         
  155.             // on all but last one, advance variable and set up variable name
  156.             
  157.             if (!last_one) {
  158.                 arg++;
  159.                 last_one = arg == (nshc_parms->argc - 1);
  160.                 pStrFromC( name, &nshc_parms->arg_buf[ nshc_parms->argv[ arg ] ] );
  161.                 j = 0;
  162.                 }
  163.                 
  164.             // eat whitespace
  165.  
  166.             while ( c && (( c == ' ' ) || ( c == '\t' )))
  167.                 c = my_buf[++i];
  168.                 
  169.             // if the string starts with a quote, set it up
  170.             
  171.             if ( ( c == '\'') || ( c == '"' ) ) {
  172.                 quote = c;
  173.                 c = my_buf[++i];
  174.                 }
  175.             else
  176.                 quote = 0;
  177.                 
  178.             // if this is the last_one, and we have a partial string,
  179.             // and more to add, we need to pad with a blank
  180.             
  181.             if (last_one && j && c && (c != '\r' )) 
  182.                 if ( j < 255 )
  183.                     value[++j] = ' ';
  184.                 else {
  185.                     read_error( nshc_parms, nshc_calls, ERROR_INPUT );
  186.                     return;
  187.                     }
  188.             
  189.             // put non-whitespace characters into the value string
  190.                 
  191.             while ( c ) {
  192.             
  193.                 // end an unquoted variable on a whitespace
  194.             
  195.                 if ( !quote && (( c == ' ' ) || ( c == '\t' )) )
  196.                     break;
  197.                     
  198.                 // end a quoted string on that character
  199.                     
  200.                 if ( c == quote )
  201.                     break;
  202.                     
  203.                 // end any string on a Return char
  204.                     
  205.                 if ( c == '\r' )
  206.                     break;
  207.  
  208.                 // it's an error to have quotes in non-quoted strings
  209.             
  210.                 if ( !quote && ( ( c == '\'') || ( c == '"' ) ) ) {
  211.                     read_error( nshc_parms, nshc_calls, ERROR_QUOTES );
  212.                     return;
  213.                     }
  214.                     
  215.                 // add the character if there is room
  216.                 
  217.                 if ( j < 255 )
  218.                     value[++j] = c;
  219.                 else {
  220.                     read_error( nshc_parms, nshc_calls, ERROR_INPUT );
  221.                     return;
  222.                     }
  223.                     
  224.                 c = my_buf[++i];
  225.                     
  226.                 }
  227.                     
  228.             value[0] = j;
  229.             
  230.             if (quote) {
  231.             
  232.                 // if a quoted string did not end with a quote, bail
  233.                 // otherwise, advance past last quoted string
  234.                 
  235.                 if ( c != quote ) {
  236.                     read_error( nshc_parms, nshc_calls, ERROR_QUOTES );
  237.                     return;
  238.                     }
  239.                 else
  240.                     c = my_buf[++i];
  241.     
  242.                 }
  243.                             
  244.             // figure out if there is 'more' to add to the 'last_one'
  245.             
  246.             more = last_one && ((c == ' ') || (c == '\t'));
  247.             
  248.             // if we have some strings, and there is no 'more', store them away
  249.             
  250.             if ( name[0] && value[0] && !more ) {
  251.                 nshc_calls->NSH_var_set( name, value );
  252.                 got_one = 1;
  253.                 }
  254.                     
  255.             }
  256.             
  257.         // consider it an error if no variables were filled
  258.             
  259.         if ( !got_one )
  260.             nshc_parms->result = 1;
  261.             
  262.         read_stop( nshc_parms );
  263.         
  264.         }
  265. }
  266.  
  267. /* ======================================== */
  268.  
  269. // state machine stop
  270.  
  271. void read_stop( t_nshc_parms *nshc_parms )
  272. {
  273.     nshc_parms->action = nsh_idle;
  274. }
  275.  
  276. /* ======================================== */
  277.  
  278. void main(t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls)
  279. {
  280. #ifdef __MWERKS__
  281.     long oldA4  = SetCurrentA4();
  282. #endif
  283.     
  284.     if ( !nshc_bad_version( nshc_parms, nshc_calls, NSHC_VERSION ) ) {
  285.         
  286.         switch (nshc_parms->action) {
  287.             case nsh_start:
  288.                 read_start(nshc_parms,nshc_calls);
  289.                 break;
  290.             case nsh_continue:
  291.                 read_continue(nshc_parms,nshc_calls);
  292.                 break;
  293.             default:
  294.                 read_stop(nshc_parms);
  295.                 break;
  296.             }
  297.  
  298.         }
  299.  
  300. #ifdef __MWERKS__
  301.     SetA4(oldA4);
  302. #endif
  303. }
  304.