home *** CD-ROM | disk | FTP | other *** search
/ BURKS 2 / BURKS_AUG97.ISO / BURKS / SOFTWARE / SOURCES / MAWK11AS.ZIP / SCAN.C (.txt) < prev    next >
C/C++ Source or Header  |  1991-12-18  |  22KB  |  833 lines

  1.  
  2. /********************************************
  3. scan.c
  4. copyright 1991, Michael D. Brennan
  5.  
  6. This is a source file for mawk, an implementation of
  7. the AWK programming language.
  8.  
  9. Mawk is distributed without warranty under the terms of
  10. the GNU General Public License, version 2, 1991.
  11. ********************************************/
  12.  
  13.  
  14. /* $Log:    scan.c,v $
  15.  * Revision 5.1  91/12/05  07:56:27  brennan
  16.  * 1.1 pre-release
  17.  * 
  18. */
  19.  
  20.  
  21. #include  "mawk.h"
  22. #include  "sizes.h"
  23. #include  "scan.h"
  24. #include  "memory.h"
  25. #include  "field.h"
  26. #include  "init.h"
  27. #include  "fin.h"
  28. #include  "repl.h"
  29. #include  "code.h"
  30.  
  31. #if HAVE_FCNTL_H
  32. #include  <fcntl.h>
  33. #endif
  34.  
  35. #include  "files.h"
  36.  
  37.  
  38. /* static functions */
  39. static void PROTO(scan_fillbuff, (void) ) ;
  40. static void PROTO(scan_open, (void) ) ;
  41. static int PROTO(slow_next, (void) ) ;
  42. static void PROTO(eat_comment, (void) ) ;
  43. static void PROTO(eat_semi_colon, (void) ) ;
  44. static double PROTO(collect_decimal, (int, int *) ) ;
  45. static int PROTO(collect_string, (void) ) ;
  46. static int  PROTO(collect_RE, (void) ) ;
  47.  
  48.  
  49. /*-----------------------------
  50.   program file management
  51.  *----------------------------*/
  52.  
  53. char *pfile_name ;
  54. STRING  *program_string ;
  55. PFILE *pfile_list ;
  56. static  unsigned char *buffer ;
  57. static  unsigned char *buffp ;  
  58.     /* unsigned so it works with 8 bit chars */
  59. static  int  program_fd   ; 
  60. static  int  eof_flag ;
  61.  
  62. void  scan_init(cmdline_program)
  63.   char * cmdline_program ;
  64.   if ( cmdline_program )
  65.   {
  66.     program_fd = -1 ; /* command line program */
  67.     program_string = new_STRING((char *)0, 
  68.                 strlen(cmdline_program) + 1 ) ;
  69.     (void) strcpy(program_string->str, cmdline_program) ;
  70.     /* simulate file termination */
  71.     program_string->str[program_string->len-1] = '\n' ;
  72.     buffp = (unsigned char *)  program_string->str ;
  73.     eof_flag = 1 ;
  74.   }
  75.   else /* program from file[s] */
  76.   {
  77.     scan_open() ;
  78.     buffp = buffer = (unsigned char *) zmalloc( BUFFSZ+1 ) ;
  79.     scan_fillbuff() ;
  80.   }
  81.  
  82.   eat_nl() ; /* scan to first token */
  83.   if ( next() == 0 ) { errmsg(0, "no program") ; mawk_exit(1) ; }
  84.   un_next() ;
  85.   
  86. }
  87.  
  88. static void  scan_open() /* open pfile_name */
  89. {
  90.   if ( pfile_name[0] == '-' && pfile_name[1] == 0 )
  91.         program_fd = 0 ;
  92.   else
  93.   if ( (program_fd = open(pfile_name, O_RDONLY, 0)) == -1 )
  94.   { errmsg( errno, "cannot open %s", pfile_name) ; mawk_exit(1) ; }
  95. }
  96.  
  97. void scan_cleanup()
  98.   if ( program_fd >= 0 ) zfree(buffer, BUFFSZ+1) ;
  99.   else  free_STRING(program_string) ;
  100.  
  101.   if ( program_fd > 0 )  (void) close(program_fd) ;
  102.  
  103.   /* redefine SPACE as [ \t\n] */
  104.  
  105.   scan_code['\n'] = posix_space_flag && rs_shadow.type != SEP_MLR
  106.             ? SC_UNEXPECTED : SC_SPACE ;
  107.   scan_code['\f'] = SC_UNEXPECTED ; /*value doesn't matter */
  108.   scan_code['\013'] = SC_UNEXPECTED ; /* \v not space */
  109.   scan_code['\r'] = SC_UNEXPECTED ;
  110. }
  111.  
  112. /*--------------------------------
  113.   global variables shared by yyparse() and yylex()
  114.   and used for error messages too
  115.  *-------------------------------*/
  116.  
  117. int  current_token = -1 ; 
  118. unsigned  token_lineno ;
  119. unsigned  compile_error_count ;
  120. int   NR_flag ; /* are we tracking NR */
  121. int   paren_cnt ;
  122. int   brace_cnt ;
  123. int   print_flag ;  /* changes meaning of '>' */
  124. int   getline_flag ; /* changes meaning of '<' */
  125.  
  126. extern  YYSTYPE  yylval ;
  127.  
  128. /*----------------------------------------
  129.  file reading functions
  130.  next() and un_next(c) are macros in scan.h
  131.  
  132.  *---------------------*/
  133.  
  134. static  unsigned lineno = 1 ;
  135.  
  136.  
  137. static  void scan_fillbuff()
  138. { unsigned r ;
  139.  
  140.   r = fillbuff(program_fd, (char *)buffer, BUFFSZ) ;
  141.   if ( r < BUFFSZ ) 
  142.   { eof_flag = 1 ;
  143.     /* check eof is terminated */
  144.     if ( r && buffer[r-1] != '\n' )
  145.     { buffer[r] = '\n' ; buffer[r+1] = 0 ; }
  146.   }
  147. }
  148.  
  149. /* read one character -- slowly */
  150. static int slow_next()
  151.    
  152.   while ( *buffp == 0 )
  153.   {
  154.     if ( !eof_flag ) 
  155.     { buffp = buffer ; scan_fillbuff() ; }
  156.     else
  157.     if ( pfile_list /* open another program file */ )
  158.     {
  159.       PFILE *q ;
  160.  
  161.       if ( program_fd > 0 ) (void) close(program_fd) ;
  162.       eof_flag = 0 ;
  163.       pfile_name = pfile_list->fname ;
  164.       q = pfile_list ;
  165.       pfile_list = pfile_list->link ;
  166.       ZFREE(q) ;
  167.       scan_open() ;
  168.       token_lineno = lineno = 1 ;
  169.     }
  170.     else  break /* real eof */ ;
  171.   }
  172.  
  173.   return *buffp++ ; /* note can un_next() , eof which is zero */
  174. }
  175.  
  176. static void eat_comment()
  177. { register int c ;
  178.  
  179.   while ( (c = next()) != '\n' && scan_code[c] ) ;
  180.   un_next() ;
  181. }
  182.  
  183. /* this is how we handle extra semi-colons that are
  184.    now allowed to separate pattern-action blocks
  185.  
  186.    A proof that they are useless clutter to the language:
  187.    we throw them away
  188. */
  189.  
  190. static  void  eat_semi_colon()
  191. /* eat one semi-colon on the current line */
  192. { register int c ;
  193.  
  194.   while ( scan_code[c = next()] == SC_SPACE )  ;
  195.   if ( c != ';' )  un_next() ;
  196. }
  197.  
  198. void eat_nl() /* eat all space including newlines */
  199. {
  200.   while ( 1 )
  201.     switch( scan_code[next()] )
  202.     { 
  203.       case SC_COMMENT : 
  204.          eat_comment() ;
  205.          break ;
  206.          
  207.       case  SC_NL  :   lineno++ ;
  208.       /* fall thru  */
  209.       case  SC_SPACE  :   break ;
  210.       default :  
  211.           un_next() ; return ;
  212.     }
  213. }
  214.  
  215. int yylex()
  216.   register int c ;
  217.  
  218.   token_lineno = lineno ;
  219.  
  220. reswitch:
  221.  
  222.     switch( scan_code[c = next()] )
  223.     {
  224.       case  0  :  
  225.           ct_ret(EOF) ;
  226.           
  227.       case  SC_SPACE  :   goto reswitch ;
  228.  
  229.       case  SC_COMMENT :
  230.           eat_comment() ; goto reswitch ;
  231.  
  232.       case  SC_NL  : 
  233.           lineno++ ; eat_nl() ;
  234.           ct_ret(NL) ;
  235.  
  236.       case SC_ESCAPE :
  237.           while ( scan_code[ c = next() ] == SC_SPACE ) ;
  238.           if ( c == '\n')
  239.           { token_lineno = ++lineno ; goto reswitch ; }
  240.           if ( c == 0 )  ct_ret(EOF) ;
  241.           un_next() ;
  242.           yylval.ival = '\\' ;
  243.           ct_ret(UNEXPECTED) ;
  244.  
  245.  
  246.       case  SC_SEMI_COLON  : 
  247.           eat_nl() ;
  248.           ct_ret(SEMI_COLON) ;
  249.  
  250.       case  SC_LBRACE :  
  251.           eat_nl() ; brace_cnt++ ;
  252.           ct_ret(LBRACE) ;
  253.  
  254.       case  SC_PLUS  :
  255.           switch( next() )
  256.           {
  257.             case '+' :  
  258.                 yylval.ival = '+' ;
  259.                 string_buff[0] = 
  260.                      string_buff[1] = '+' ;
  261.                 string_buff[2] = 0 ;
  262.                 ct_ret(INC_or_DEC) ;
  263.  
  264.             case  '=' :
  265.                 ct_ret(ADD_ASG) ;
  266.  
  267.             default :  un_next() ; ct_ret(PLUS) ;
  268.           }
  269.  
  270.       case  SC_MINUS :
  271.           switch( next() )
  272.           {
  273.             case '-' :  
  274.                 yylval.ival = '-' ;
  275.                 string_buff[0] = 
  276.                      string_buff[1] = '-' ;
  277.                 string_buff[2] = 0 ;
  278.                 ct_ret(INC_or_DEC) ;
  279.  
  280.             case  '=' :
  281.                 ct_ret(SUB_ASG) ;
  282.  
  283.             default :  un_next() ; ct_ret(MINUS) ;
  284.           }
  285.  
  286.       case  SC_COMMA :  eat_nl() ; ct_ret(COMMA) ;
  287.  
  288.       case  SC_MUL  :  test1_ret('=', MUL_ASG, MUL) ;
  289.       case  SC_DIV :   
  290.           { static int can_precede_div[] =
  291.         { DOUBLE, STRING_, RPAREN, ID, D_ID, RE, RBOX, FIELD,
  292.           GETLINE, INC_or_DEC, -1 } ;
  293.           
  294.           int *p = can_precede_div ;
  295.  
  296.             do
  297.                 if ( *p == current_token )
  298.         {
  299.           if ( *p != INC_or_DEC ) 
  300.             test1_ret('=', DIV_ASG, DIV) ;
  301.  
  302.           if ( next() == '=' )
  303.           { un_next() ; ct_ret( collect_RE() ) ;  }
  304.         }
  305.                  
  306.             while ( * ++p != -1 ) ;
  307.  
  308.             ct_ret( collect_RE() ) ;
  309.           }
  310.  
  311.       case  SC_MOD  :  test1_ret('=', MOD_ASG, MOD) ;
  312.       case  SC_POW :   test1_ret('=' , POW_ASG, POW) ;
  313.       case  SC_LPAREN : 
  314.           paren_cnt++ ;
  315.           ct_ret(LPAREN) ;
  316.  
  317.       case  SC_RPAREN : 
  318.           if ( --paren_cnt < 0 )
  319.           { compile_error( "extra ')'" ) ;
  320.             paren_cnt = 0 ;
  321.             goto reswitch ; }
  322.  
  323.           ct_ret(RPAREN) ;
  324.  
  325.       case  SC_LBOX   : ct_ret(LBOX) ;
  326.       case  SC_RBOX   : ct_ret(RBOX) ;
  327.  
  328.       case  SC_MATCH  : 
  329.       string_buff[0] = '~' ; string_buff[0] = 0 ;