home *** CD-ROM | disk | FTP | other *** search
/ Garbo / Garbo.cdr / pc / source / mawk.lzh / mawk.5 < prev    next >
Encoding:
Text File  |  1991-05-19  |  60.5 KB  |  2,445 lines

  1.       case  SC_SPACE  :   goto reswitch ;
  2.  
  3.       case  SC_COMMENT :
  4.           eat_comment() ; goto reswitch ;
  5.  
  6.       case  SC_NL  : 
  7.           lineno++ ; eat_nl() ;
  8.           ct_ret(NL) ;
  9.  
  10.       case SC_ESCAPE :
  11.           while ( scan_code[ c = next() ] == SC_SPACE ) ;
  12.           if ( c == '\n')
  13.           { token_lineno = ++lineno ; goto reswitch ; }
  14.           if ( c == 0 )  ct_ret(EOF) ;
  15.           un_next() ;
  16.           yylval.ival = '\\' ;
  17.           ct_ret(UNEXPECTED) ;
  18.  
  19.  
  20.       case  SC_SEMI_COLON  : 
  21.           eat_nl() ;
  22.           ct_ret(SEMI_COLON) ;
  23.  
  24.       case  SC_LBRACE :  
  25.           eat_nl() ; brace_cnt++ ;
  26.           ct_ret(LBRACE) ;
  27.  
  28.       case  SC_PLUS  :
  29.           test2_ret('+', INC, '=', ADD_ASG, PLUS ) ;
  30.  
  31.       case  SC_MINUS :
  32.           test2_ret('-', DEC, '=', SUB_ASG, MINUS ) ;
  33.  
  34.       case  SC_COMMA :  eat_nl() ; ct_ret(COMMA) ;
  35.  
  36.       case  SC_MUL  :  test1_ret('=', MUL_ASG, MUL) ;
  37.       case  SC_DIV :   
  38.           { int *p = can_precede_re ;
  39.  
  40.             do
  41.                 if ( *p == current_token )
  42.                     ct_ret( collect_RE() ) ;
  43.             while ( *p++ != -1 ) ;
  44.  
  45.             test1_ret( '=', DIV_ASG , DIV ) ;
  46.           }
  47.  
  48.       case  SC_MOD  :  test1_ret('=', MOD_ASG, MOD) ;
  49.       case  SC_POW :   test1_ret('=' , POW_ASG, POW) ;
  50.       case  SC_LPAREN : 
  51.           paren_cnt++ ;
  52.           ct_ret(LPAREN) ;
  53.  
  54.       case  SC_RPAREN : 
  55.           if ( --paren_cnt < 0 )
  56.           { compile_error( "extra ')'" ) ;
  57.             paren_cnt = 0 ;
  58.             goto reswitch ; }
  59.  
  60.           ct_ret(RPAREN) ;
  61.  
  62.       case  SC_LBOX   : ct_ret(LBOX) ;
  63.       case  SC_RBOX   : ct_ret(RBOX) ;
  64.  
  65.       case  SC_MATCH  : ct_ret(MATCH) ;
  66.  
  67.       case  SC_EQUAL  :
  68.           test1_ret( '=', EQ, ASSIGN ) ;
  69.  
  70.       case  SC_NOT : /* !  */
  71.           test2_ret('=', NEQ, '~', NOT_MATCH, NOT ) ;
  72.  
  73.       case  SC_LT  :  /* '<' */
  74.           if ( getline_flag )
  75.           { getline_flag = 0 ; ct_ret(IO_IN) ; }
  76.           else
  77.           { ct_ret( ifnext('=', LTE , LT) ) ; }
  78.  
  79.       case  SC_GT  :  /* '>' */
  80.           if ( print_flag && paren_cnt == 0 )
  81.           { print_flag = 0 ;
  82.             /* there are 3 types of IO_OUT 
  83.                -- build the error string in temp_buff */
  84.             temp_buff.string_buff[0] = '>' ;
  85.             if ( next() == '>' ) 
  86.             { 
  87.               yylval.ival = F_APPEND ;
  88.               temp_buff.string_buff[1] = '>' ;
  89.               temp_buff.string_buff[2] =  0 ;
  90.             }
  91.             else
  92.             { un_next() ; 
  93.               yylval.ival = F_TRUNC ; 
  94.               temp_buff.string_buff[1] = 0 ;
  95.             }
  96.             return current_token = IO_OUT ;
  97.           }
  98.  
  99.           ct_ret( ifnext('=', GTE , GT) ) ;
  100.  
  101.       case  SC_OR :
  102.           if ( next() == '|' ) 
  103.           { eat_nl() ; ct_ret(brace_cnt?OR:P_OR) ; }
  104.           else 
  105.           { un_next() ; 
  106.  
  107.             if ( print_flag && paren_cnt == 0 )
  108.             { print_flag = 0 ; 
  109.               yylval.ival = PIPE_OUT;
  110.               temp_buff.string_buff[0] = '|' ;
  111.               temp_buff.string_buff[1] = 0 ;
  112.               ct_ret(IO_OUT) ;
  113.             }
  114.             else  ct_ret(PIPE) ;
  115.           }
  116.  
  117.       case  SC_AND :
  118.           if ( next() == '&' )  
  119.           { eat_nl() ; ct_ret(brace_cnt?AND:P_AND) ; }
  120.           else 
  121.           { un_next() ; yylval.ival = '&' ; ct_ret(UNEXPECTED) ; }
  122.  
  123.       case  SC_QMARK  :  ct_ret(QMARK) ;
  124.       case  SC_COLON  :  ct_ret(COLON) ;
  125.       case  SC_RBRACE :
  126.           if ( --brace_cnt < 0 )
  127.           { compile_error("extra '}'" ) ;
  128.             brace_cnt = 0 ; goto reswitch ; }
  129.  
  130.           if ( (c = current_token) == NL || c == SEMI_COLON 
  131.                || c == SC_FAKE_SEMI_COLON  || c == RBRACE  )
  132.           { eat_nl() ; ct_ret(RBRACE) ; }
  133.  
  134.           brace_cnt++ ; un_next() ;
  135.           current_token = SC_FAKE_SEMI_COLON ;
  136.           return  SEMI_COLON ;
  137.  
  138.       case  SC_DIGIT  :
  139.       case  SC_DOT    :
  140.           { double d ;
  141.             int flag ;
  142.  
  143.             if ( (d = collect_decimal(c, &flag)) == 0.0 )
  144.                 if ( flag )  ct_ret(flag) ;
  145.                 else  yylval.cp = &cell_zero ;
  146.             else if ( d == 1.0 ) yylval.cp = &cell_one ;
  147.             else 
  148.             { yylval.cp = new_CELL() ;
  149.               yylval.cp->type = C_DOUBLE ;
  150.               yylval.cp->dval = d ; 
  151.             }
  152.             ct_ret( CONSTANT ) ;
  153.           }
  154.  
  155.       case  SC_DOLLAR :  /* '$' */
  156.           { double d ;
  157.             int flag ;
  158.  
  159.             while ( scan_code[c = next()] == SC_SPACE )  ;
  160.             if ( scan_code[c] != SC_DIGIT &&
  161.                  scan_code[c] != SC_DOT )
  162.             { un_next() ; ct_ret(DOLLAR) ; }
  163.             /* compute field address at compile time */
  164.             if ( (d = collect_decimal(c, &flag)) == 0.0 )
  165.                 if ( flag )  ct_ret(flag) ; /* an error */
  166.                 else  yylval.cp = &field[0] ;
  167.             else
  168.             { int k = (int) d ;
  169.  
  170.               if ( k > MAX_FIELD )
  171.               { compile_error(
  172.                    "maximum field index(%d) exceeded" , k ) ;
  173.                 k = MAX_FIELD ;
  174.               }
  175.               else  yylval.cp = &field[k] ;
  176.             }
  177.  
  178.             ct_ret(FIELD) ;
  179.           }
  180.  
  181.       case  SC_DQUOTE :
  182.           return current_token = collect_string() ;
  183.  
  184.       case  SC_IDCHAR : /* collect an identifier */
  185.             { unsigned char *p =
  186.                     (unsigned char *)temp_buff.string_buff + 1 ;
  187.               SYMTAB *stp ;
  188.  
  189.               temp_buff.string_buff[0] = c ;
  190.  
  191.               while ( 
  192.                 (c = scan_code[ *p++ = next()]) == SC_IDCHAR ||
  193.                        c == SC_DIGIT )  ;
  194.               
  195.               un_next() ; * --p = 0 ;
  196.  
  197.               switch( (stp = find(temp_buff.string_buff))->type )
  198.               { case ST_NONE :  
  199.                   /* check for function call before defined */
  200.                       if ( next() == '(' )
  201.                       { stp->type = ST_FUNCT ;
  202.                         stp->stval.fbp = (FBLOCK *)
  203.                                 zmalloc(sizeof(FBLOCK)) ;
  204.                         stp->stval.fbp->name = stp->name ;
  205.                         stp->stval.fbp->code = (INST *) 0 ;
  206.                         yylval.fbp = stp->stval.fbp ;
  207.                         current_token = FUNCT_ID ;
  208.                       }
  209.                       else
  210.                       { yylval.stp = stp ;
  211.                         current_token = ID ;
  212.                       }
  213.                       un_next() ;
  214.                       break ;
  215.                         
  216.                 case ST_VAR :
  217.                 case  ST_ARRAY :
  218.                 case  ST_LOCAL_NONE :
  219.                 case  ST_LOCAL_VAR :
  220.                 case  ST_LOCAL_ARRAY :
  221.  
  222.                       yylval.stp = stp ;
  223.                       current_token = ID ;
  224.                       break ;
  225.  
  226.                 case ST_FUNCT :
  227.                       yylval.fbp = stp->stval.fbp ;
  228.                       current_token = FUNCT_ID ;
  229.                       break ;
  230.  
  231.                 case ST_KEYWORD :  
  232.                       current_token = stp->stval.kw ;
  233.                       break ;
  234.  
  235.                 case  ST_BUILTIN :
  236.                       yylval.bip = stp->stval.bip ;
  237.                       current_token = BUILTIN ;
  238.                       break ;
  239.  
  240.                 case  ST_FIELD  :
  241.                       yylval.cp = stp->stval.cp ;
  242.                       current_token = FIELD ;
  243.                       break ;
  244.  
  245.                 case  ST_LENGTH  :
  246.                     { CELL *bi_length() ;
  247.                       static BI_REC length_bi_rec =
  248.                       { "length", bi_length, 1, 1 } ;
  249.  
  250.                       while ( scan_code[ c = next() ] == SC_SPACE ) ;
  251.                       un_next() ;
  252.  
  253.                       if ( c == '(' )
  254.                       { yylval.bip = &length_bi_rec ;
  255.                         current_token = BUILTIN ;
  256.                       }
  257.                       else current_token = LENGTH ;
  258.                     }
  259.                     break ;
  260.  
  261.                 default : 
  262.                       bozo("find returned bad st type") ;
  263.               }
  264.               return  current_token  ;
  265.             }
  266.  
  267.  
  268.       case  SC_UNEXPECTED :
  269.             yylval.ival = c & 0xff ;
  270.             ct_ret(UNEXPECTED) ;
  271.     }
  272.     return  0 ; /* never get here make lint happy */
  273. }
  274.  
  275. /* collect a decimal constant in temp_buff.
  276.    Return the value and error conditions by reference */
  277.  
  278. static double collect_decimal(c, flag)
  279.   int c ; int *flag ;
  280. { register unsigned char *p = (unsigned char*) temp_buff.string_buff + 1;
  281.   unsigned char *endp ;
  282.   double d ;
  283.  
  284.   *flag = 0 ;
  285.   temp_buff.string_buff[0] = c ;
  286.  
  287.   if ( c == '.' )
  288.   { if ( scan_code[*p++ = next()] != SC_DIGIT )
  289.     { *flag = UNEXPECTED ; yylval.ival = '.' ;
  290.       return 0.0 ; }
  291.   }
  292.   else
  293.   {  while ( scan_code[*p++ = next()] == SC_DIGIT ) ;
  294.      if ( p[-1] != '.' )
  295.      { un_next() ; p-- ; }
  296.   }
  297.   /* get rest of digits after decimal point */
  298.   while ( scan_code[*p++ = next()] == SC_DIGIT )  ;
  299.  
  300.   /* check for exponent */
  301.   if ( p[-1] != 'e' && p[-1] != 'E' )
  302.   { un_next() ; * --p = 0 ; }
  303.   else  /* get the exponent */
  304.     if ( scan_code[*p = next()] != SC_DIGIT &&
  305.          *p != '-' && *p != '+' )
  306.     { *++p = 0 ; *flag = BAD_DECIMAL ;
  307.       return 0.0 ; }
  308.     else  /* get the rest of the exponent */
  309.     { p++ ;
  310.       while ( scan_code[*p++ = next()] == SC_DIGIT )  ;
  311.       un_next() ; * --p = 0 ;
  312.     }
  313.  
  314.   errno = 0 ; /* check for overflow/underflow */
  315.   d = strtod( temp_buff.string_buff, &endp ) ;
  316.   if ( errno )
  317.       compile_error( "%s : decimal %sflow" , temp_buff.string_buff,
  318.         d == 0.0 ? "under" : "over") ;
  319.   if ( endp != p )
  320.   { *flag = BAD_DECIMAL ; return 0.0 ; }
  321.   return d ;
  322. }
  323.  
  324. /*----------  process escape characters ---------------*/
  325.  
  326. static char hex_val['f' - 'A' + 1] = {
  327. 10,11,12,13,14,15, 0, 0,
  328.  0, 0, 0, 0, 0, 0, 0, 0,
  329.  0, 0, 0, 0, 0, 0, 0, 0,
  330.  0, 0, 0, 0, 0, 0, 0, 0,
  331. 10,11,12,13,14,15 } ;
  332.  
  333. #define isoctal(x)  ((x)>='0'&&(x)<='7')
  334.  
  335. #define  hex_value(x)   hex_val[(x)-'A']
  336.  
  337. #define ishex(x) (scan_code[x] == SC_DIGIT ||\
  338.                   'A' <= (x) && (x) <= 'f' && hex_value(x))
  339.  
  340. static int PROTO(octal, (char **)) ;
  341. static int PROTO(hex, (char **)) ;
  342.  
  343. /* process one , two or three octal digits
  344.    moving a pointer forward by reference */
  345. static int octal( start_p )
  346.   char **start_p ;
  347. { register char *p = *start_p ;
  348.   register unsigned x ;
  349.  
  350.   x = *p++ - '0' ;
  351.   if ( isoctal(*p) )
  352.   {
  353.     x = (x<<3) + *p++ - '0' ;
  354.     if ( isoctal(*p) )   x = (x<<3) + *p++ - '0' ;
  355.   }
  356.   *start_p = p ;
  357.   return  x & 0xff ;
  358. }
  359.  
  360. /* process one or two hex digits
  361.    moving a pointer forward by reference */
  362.  
  363. static int  hex( start_p )
  364.   unsigned char **start_p ;
  365. { register unsigned char *p = *start_p ;
  366.   register unsigned x ;
  367.   unsigned t ;
  368.  
  369.   if ( scan_code[*p] == SC_DIGIT )
  370.         x = *p++ - '0' ;
  371.   else  x = hex_value(*p++) ;
  372.  
  373.   if ( scan_code[*p] == SC_DIGIT )
  374.         x = (x<<4) + *p++ - '0' ;
  375.   else
  376.   if ( 'A' <= *p && *p <= 'f' && (t = hex_value(*p)) )
  377.   { x = (x<<4) + t ; p++ ; }
  378.  
  379.   *start_p = p ;
  380.   return x ;
  381. }
  382.  
  383. static char escape_test[] = 
  384.   "n\nt\tb\br\rf\fa\07v\013\\\\\"\"\'\'" ;
  385.  
  386. /* process the escape characters in a string, in place . */
  387.  
  388. static char *rm_escape(s)
  389.   char *s ;
  390. { register char *p, *q ;
  391.   char *t ;
  392.  
  393.   q = p = s ;
  394.  
  395.   while ( *p )
  396.       if ( *p == '\\' )
  397.       { 
  398.         if ( t = strchr(escape_test, * ++p) )
  399.         { 
  400.           p++ ; *q++ = t[1] ; 
  401.         }
  402.         else
  403.         if ( isoctal(*p) ) 
  404.         {
  405.           t = p ;  *q++ = octal(&t) ; p = t ;
  406.         }
  407.         else
  408.         if ( *p == 'x' && ishex(*(unsigned char*)(p+1)) )
  409.         {
  410.           t = p+1 ; *q++ = hex(&t) ; p = t ;
  411.         }
  412.         else  /* not an escape sequence */
  413.         { 
  414.           *q++ = '\\' ; *q++ = *p++ ;
  415.         }
  416.       }
  417.       else  *q++ = *p++ ;
  418.  
  419.   *q = 0 ;
  420.   return s ;
  421. }
  422.  
  423. static  int  collect_string()
  424. { register unsigned char *p = (unsigned char *)temp_buff.string_buff ;
  425.   int c ;
  426.   int e_flag = 0 ; /* on if have an escape char */
  427.  
  428.   while ( 1 )
  429.       switch( scan_code[ *p++ = next() ] )
  430.       { case  SC_DQUOTE : /* done */
  431.               * --p = 0 ;  goto out ;
  432.  
  433.         case  SC_NL :
  434.               p[-1] = 0 ;
  435.               /* fall thru */
  436.  
  437.         case  0 :   /* unterminated string */
  438.               compile_error(
  439.               "runaway string constant \"%.10s ..." ,
  440.               temp_buff.string_buff, token_lineno ) ;
  441.               mawk_exit(1) ;
  442.  
  443.         case SC_ESCAPE :
  444.               if ( (c = next()) == '\n' )
  445.               { p-- ; lineno++ ; }
  446.               else  
  447.                 if ( c == 0 )  un_next() ;   
  448.                 else 
  449.                 { *p++ = c ; e_flag = 1 ; }
  450.  
  451.               break ;
  452.  
  453.         default : break ;
  454.       }
  455.  
  456. out:
  457.     yylval.cp = new_CELL() ;
  458.     yylval.cp->type = C_STRING ;
  459.     yylval.cp->ptr = (PTR) new_STRING(
  460.          e_flag ? rm_escape( temp_buff.string_buff ) 
  461.                 : temp_buff.string_buff ) ;
  462.     return  CONSTANT ;
  463. }
  464.  
  465.  
  466. static  int  collect_RE()
  467. { register unsigned char *p = (unsigned char*) temp_buff.string_buff ;
  468.   int c ;
  469.   STRING *sval ;
  470.  
  471.   while ( 1 )
  472.       switch( scan_code[ *p++ = next() ] )
  473.       { case  SC_DIV : /* done */
  474.               * --p = 0 ;  goto out ;
  475.  
  476.         case  SC_NL :
  477.               p[-1] = 0 ;
  478.               /* fall thru */
  479.  
  480.         case  0 :   /* unterminated re */
  481.               compile_error(
  482.               "runaway regular expression /%.10s ..." ,
  483.               temp_buff.string_buff, token_lineno ) ;
  484.               mawk_exit(1) ;
  485.  
  486.         case SC_ESCAPE :
  487.               switch( c = next() )
  488.               { case '/' :  
  489.                       p[-1] = '/' ; break ;
  490.  
  491.                 case '\n' :
  492.                       p-- ;  break ;
  493.  
  494.                 case  0   :
  495.                       un_next() ;  break ;
  496.  
  497.                 default :
  498.                       *p++ = c ; break ;
  499.               }
  500.               break ;
  501.       }
  502.  
  503. out:
  504.   /* now we've got the RE, so compile it */
  505.   sval = new_STRING( temp_buff.string_buff ) ;
  506.   yylval.cp = new_CELL() ;
  507.   yylval.cp->type = C_RE ;
  508.   yylval.cp->ptr = re_compile(sval) ;
  509.   free_STRING(sval) ;
  510.   return RE ;
  511. }
  512.  
  513. @//E*O*F mawk0.97/scan.c//
  514. chmod u=rw,g=r,o=r mawk0.97/scan.c
  515.  
  516. echo x - mawk0.97/scan.h
  517. sed 's/^@//' > "mawk0.97/scan.h" <<'@//E*O*F mawk0.97/scan.h//'
  518.  
  519. /********************************************
  520. scan.h
  521. copyright 1991, Michael D. Brennan
  522.  
  523. This is a source file for mawk, an implementation of
  524. the Awk programming language as defined in
  525. Aho, Kernighan and Weinberger, The AWK Programming Language,
  526. Addison-Wesley, 1988.
  527.  
  528. See the accompaning file, LIMITATIONS, for restrictions
  529. regarding modification and redistribution of this
  530. program in source or binary form.
  531. ********************************************/
  532.  
  533.  
  534. /* $Log:    scan.h,v $
  535.  * Revision 2.2  91/04/09  12:39:31  brennan
  536.  * added static to funct decls to satisfy STARDENT compiler
  537.  * 
  538.  * Revision 2.1  91/04/08  08:23:54  brennan
  539.  * VERSION 0.97
  540.  * 
  541. */
  542.  
  543.  
  544. /* scan.h  */
  545.  
  546. #ifndef  SCAN_H_INCLUDED
  547. #define  SCAN_H_INCLUDED   1
  548.  
  549. #include <stdio.h>
  550.  
  551. #ifndef   MAKESCAN
  552. #include  "symtype.h"
  553. #include  "parse.h"
  554. #endif
  555.  
  556.  
  557. extern  char scan_code[256] ;
  558.  
  559. /*  the scan codes to compactify the main switch */
  560.  
  561. #define  SC_SPACE               1
  562. #define  SC_NL                  2
  563. #define  SC_SEMI_COLON          3
  564. #define  SC_FAKE_SEMI_COLON     4
  565. #define  SC_LBRACE              5
  566. #define  SC_RBRACE              6
  567. #define  SC_QMARK               7
  568. #define  SC_COLON               8
  569. #define  SC_OR                  9
  570. #define  SC_AND                10
  571. #define  SC_PLUS               11
  572. #define  SC_MINUS              12
  573. #define  SC_MUL                13
  574. #define  SC_DIV                14
  575. #define  SC_MOD                15
  576. #define  SC_POW                16
  577. #define  SC_LPAREN             17
  578. #define  SC_RPAREN             18
  579. #define  SC_LBOX               19
  580. #define  SC_RBOX               20
  581. #define  SC_IDCHAR             21
  582. #define  SC_DIGIT              22
  583. #define  SC_DQUOTE             23
  584. #define  SC_ESCAPE             24
  585. #define  SC_COMMENT            25
  586. #define  SC_EQUAL              26
  587. #define  SC_NOT                27
  588. #define  SC_LT                 28
  589. #define  SC_GT                 29
  590. #define  SC_COMMA              30
  591. #define  SC_DOT                31
  592. #define  SC_MATCH              32
  593. #define  SC_DOLLAR             33
  594. #define  SC_UNEXPECTED         34
  595.  
  596. #ifndef  MAKESCAN
  597.  
  598. /* global functions in scan.c */
  599.  
  600. void  PROTO(scan_init, (int, char *) ) ;
  601. void  PROTO(scan_cleanup, (void) ) ;
  602. void  PROTO(eat_nl, (void) ) ;
  603. int   PROTO(yylex, (void) ) ;
  604.  
  605.  
  606. extern  YYSTYPE  yylval ;
  607.  
  608. #define  ct_ret(x)  return current_token = (x)
  609.  
  610. #define  next() (*buffp ? *buffp++ : slow_next())
  611. #define  un_next()  buffp--
  612.  
  613. #define  ifnext(c,x,y) (next()==c?x:(un_next(),y))
  614.  
  615. #define  test1_ret(c,x,d)  if ( next() == (c) ) ct_ret(x) ;\
  616.                            else { un_next() ; ct_ret(d) ; }
  617.  
  618. #define  test2_ret(c1,x1,c2,x2,d)   switch( next() )\
  619.                                    { case c1: ct_ret(x1) ;\
  620.                                      case c2: ct_ret(x2) ;\
  621.                                      default: un_next() ;\
  622.                                               ct_ret(d) ; }
  623. #endif  /* ! MAKESCAN  */
  624. #endif
  625. @//E*O*F mawk0.97/scan.h//
  626. chmod u=rw,g=r,o=r mawk0.97/scan.h
  627.  
  628. echo x - mawk0.97/scancode.c
  629. sed 's/^@//' > "mawk0.97/scancode.c" <<'@//E*O*F mawk0.97/scancode.c//'
  630.  
  631.  
  632. /* scancode.c */
  633.  
  634.  
  635. char scan_code[256] = {
  636.  0,34,34,34,34,34,34,34,34, 1, 2, 1, 1, 1,34,34,
  637. 34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,
  638.  1,27,23,25,33,15,10,34,17,18,13,11,30,12,31,14,
  639. 22,22,22,22,22,22,22,22,22,22, 8, 3,28,26,29, 7,
  640. 34,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,
  641. 21,21,21,21,21,21,21,21,21,21,21,19,24,20,16,21,
  642. 34,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,
  643. 21,21,21,21,21,21,21,21,21,21,21, 5, 9, 6,32,34,
  644. 34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,
  645. 34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,
  646. 34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,
  647. 34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,
  648. 34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,
  649. 34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,
  650. 34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,
  651. 34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34
  652. } ;
  653. @//E*O*F mawk0.97/scancode.c//
  654. chmod u=rw,g=r,o=r mawk0.97/scancode.c
  655.  
  656. echo x - mawk0.97/sizes.h
  657. sed 's/^@//' > "mawk0.97/sizes.h" <<'@//E*O*F mawk0.97/sizes.h//'
  658.  
  659. /********************************************
  660. sizes.h
  661. copyright 1991, Michael D. Brennan
  662.  
  663. This is a source file for mawk, an implementation of
  664. the Awk programming language as defined in
  665. Aho, Kernighan and Weinberger, The AWK Programming Language,
  666. Addison-Wesley, 1988.
  667.  
  668. See the accompaning file, LIMITATIONS, for restrictions
  669. regarding modification and redistribution of this
  670. program in source or binary form.
  671. ********************************************/
  672.  
  673. /* $Log:    sizes.h,v $
  674.  * Revision 2.1  91/04/08  08:24:09  brennan
  675.  * VERSION 0.97
  676.  * 
  677. */
  678.  
  679. /*  sizes.h  */
  680.  
  681. #ifndef  SIZES_H
  682. #define  SIZES_H
  683.  
  684. #define  HASH_PRIME  53
  685. #define  A_HASH_PRIME 37
  686.  
  687.  
  688. #if      SMALL_EVAL_STACK
  689. /* allow some put not a lot of recursion */
  690. #define  EVAL_STACK_SIZE  64
  691. #else
  692. #define  EVAL_STACK_SIZE  256
  693. #endif
  694.  
  695. #define  MAX_COMPILE_ERRORS  5 /* quit if more than 4 errors */
  696.  
  697. #define  BUFFSZ    4096   /* input buffer size */
  698.  
  699. #define  MAX_LOOP_DEPTH   20
  700. /* should never be exceeded, doesn't matter if its too
  701.    big (unless gross) because resources sized by it are freed */
  702.  
  703. #define  MAX_FIELD   100  /* biggest field number */
  704. #define  SPRINTF_SZ   300  /* biggest sprintf string length */
  705.  
  706. /* the size of the temp buffer in front of main_buff */
  707. #define  PTR_SZ   sizeof(PTR)
  708. #define  TEMP_BUFF_SZ  (MAX_FIELD*PTR_SZ > SPRINTF_SZ ?\
  709.         MAX_FIELD*PTR_SZ : SPRINTF_SZ )
  710.  
  711. #define  PAGE_SZ    1024  /* max instructions for a block */
  712.  
  713. #endif   /* SIZES_H */
  714. @//E*O*F mawk0.97/sizes.h//
  715. chmod u=rw,g=r,o=r mawk0.97/sizes.h
  716.  
  717. echo x - mawk0.97/split.c
  718. sed 's/^@//' > "mawk0.97/split.c" <<'@//E*O*F mawk0.97/split.c//'
  719.  
  720. /********************************************
  721. split.c
  722. copyright 1991, Michael D. Brennan
  723.  
  724. This is a source file for mawk, an implementation of
  725. the Awk programming language as defined in
  726. Aho, Kernighan and Weinberger, The AWK Programming Language,
  727. Addison-Wesley, 1988.
  728.  
  729. See the accompaning file, LIMITATIONS, for restrictions
  730. regarding modification and redistribution of this
  731. program in source or binary form.
  732. ********************************************/
  733.  
  734. /* $Log:    split.c,v $
  735.  * Revision 2.1  91/04/08  08:24:11  brennan
  736.  * VERSION 0.97
  737.  * 
  738. */
  739.  
  740. /* split.c */
  741.  
  742. #include "mawk.h"
  743. #include "symtype.h"
  744. #include "bi_vars.h"
  745. #include "bi_funct.h"
  746. #include "memory.h"
  747. #include "scan.h"
  748. #include "regexp.h"
  749. #include "field.h"
  750. #include <string.h>
  751.  
  752.  
  753. /* split string s on SPACE without changing s.
  754.    load the pieces into STRINGS and ptrs into
  755.    temp_buff.ptr_buff[] 
  756.    return the number of pieces */
  757.  
  758. int space_split( s )  
  759.   register char *s ;
  760. { char *back = strchr(s,0) ;
  761.   int i = 0 ;
  762.   int len ;
  763.   char *q ;
  764.   STRING  *sval ;
  765.  
  766.   while ( 1 )
  767.   { while ( scan_code[*(unsigned char*)s] == SC_SPACE )  s++ ;
  768.     if ( *s == 0 )  break ;
  769.     /* mark the front with q */
  770.     q = s++ ;
  771.     *back = ' ' ; /* sentinal */
  772.     while ( scan_code[*(unsigned char*)s] != SC_SPACE )  s++ ;
  773.     *back = 0 ;
  774.     sval = (STRING *) (temp_buff.ptr_buff[i++] = 
  775.          (PTR) new_STRING((char *) 0, len = s - q )) ;
  776.     (void) memcpy(sval->str, q, len) ;
  777.   }
  778.   if ( i > MAX_FIELD ) 
  779.      rt_overflow("maximum number of fields", MAX_FIELD) ;
  780.   return i ;
  781. }
  782.  
  783.  
  784. char *re_pos_match(s, re, lenp)
  785.   register char *s ; 
  786.   PTR re ; unsigned *lenp ;
  787. {
  788.   while ( s = REmatch(s, re, lenp) )
  789.         if ( *lenp )   return s ;
  790.         else
  791.         if ( *s == 0 )  break ;
  792.         else s++ ;
  793.  
  794.   return (char *) 0 ;
  795. }
  796.  
  797. int re_split(s, re)
  798.   char *s ;
  799.   PTR  re ;
  800. { register char *t ;
  801.   int i = 0 ;
  802.   unsigned mlen, len ;
  803.   STRING *sval ;
  804.  
  805.   while ( t = re_pos_match(s, re, &mlen) )
  806.   { sval = (STRING*)(temp_buff.ptr_buff[i++] = (PTR)
  807.             new_STRING( (char *)0, len = t-s) ) ;
  808.     (void) memcpy(sval->str, s, len) ;
  809.     s = t + mlen ;
  810.   }
  811.   temp_buff.ptr_buff[i++] = (PTR) new_STRING(s) ;
  812.   if ( i > MAX_FIELD ) 
  813.      rt_overflow("maximum number of fields", MAX_FIELD) ;
  814.   return i ;
  815. }
  816.     
  817. /*  split(s, X, r)
  818.     split s into array X on r
  819.  
  820.     entry: sp[0] holds r
  821.            sp[-1] pts at X
  822.            sp[-2] holds s
  823. */
  824. CELL *bi_split(sp)
  825.   register CELL *sp ;
  826.   int cnt ;   /* the number of pieces */
  827.   double dcnt ; /* double version of cnt */
  828.   ARRAY A ;
  829.   CELL  *cp ;
  830.   char *ofmt ;
  831.  
  832.  
  833.   if ( sp->type < C_RE )  cast_for_split(sp) ;
  834.         /* can be C_RE, C_SPACE or C_SNULL */
  835.   sp -= 2 ;
  836.   if ( sp->type < C_STRING )  cast1_to_s(sp) ;
  837.  
  838.   if ( string(sp)->len == 0 ) /* nothing to split */
  839.   { free_STRING( string(sp) ) ;
  840.     sp->type = C_DOUBLE ; sp->dval = 0.0 ;
  841.     return sp ;
  842.   }
  843.  
  844.   switch ( (sp+2)->type )
  845.   {
  846.     case C_RE :
  847.         cnt = re_split(string(sp)->str, (sp+2)->ptr) ;
  848.         break ;
  849.  
  850.     case C_SPACE :
  851.         cnt = space_split(string(sp)->str) ;
  852.         break ;
  853.  
  854.     /* this case could be done by C_RE, but very slowly.
  855.        Since it is the common way to eliminate fields,
  856.        we'll treat the special case for speed */
  857.     case C_SNULL : /* split on empty string */
  858.         cnt = 1 ;
  859.         temp_buff.ptr_buff[0] = sp->ptr ;
  860.         string(sp)->ref_cnt++ ;
  861.         break ;
  862.  
  863.     default : bozo("bad splitting cell in bi_split") ;
  864.   }
  865.  
  866.   /* now load the array */
  867.  
  868.   free_STRING( string(sp) ) ;
  869.  
  870.   sp->type = C_DOUBLE ;
  871.   sp->dval = dcnt = (double) cnt ;
  872.  
  873.   ofmt = string(field + OFMT)->str ;
  874.   A = (ARRAY) (sp+1)->ptr  ;
  875.  
  876.   while ( cnt )
  877.   { char xbuff[256] ;
  878.     /* this big in case the user did something goofy with
  879.        OFMT  */
  880.   
  881.     (void) sprintf(xbuff, ofmt, dcnt ) ;
  882.     dcnt -= 1.0 ;
  883.     cp = array_find( A, xbuff, 1) ;
  884.     cell_destroy(cp) ;
  885.     cp->ptr = temp_buff.ptr_buff[--cnt] ;
  886.     cp->type = C_MBSTRN ;
  887.   }
  888.  
  889.   return sp ;
  890. }
  891.  
  892. @//E*O*F mawk0.97/split.c//
  893. chmod u=rw,g=r,o=r mawk0.97/split.c
  894.  
  895. echo x - mawk0.97/symtype.h
  896. sed 's/^@//' > "mawk0.97/symtype.h" <<'@//E*O*F mawk0.97/symtype.h//'
  897.  
  898. /********************************************
  899. symtype.h
  900. copyright 1991, Michael D. Brennan
  901.  
  902. This is a source file for mawk, an implementation of
  903. the Awk programming language as defined in
  904. Aho, Kernighan and Weinberger, The AWK Programming Language,
  905. Addison-Wesley, 1988.
  906.  
  907. See the accompaning file, LIMITATIONS, for restrictions
  908. regarding modification and redistribution of this
  909. program in source or binary form.
  910. ********************************************/
  911.  
  912. /*$Log:    symtype.h,v $
  913.  * Revision 2.1  91/04/08  08:24:14  brennan
  914.  * VERSION 0.97
  915.  * 
  916. */
  917.  
  918. /* types related to symbols are defined here */
  919.  
  920. #ifndef  SYMTYPE_H
  921. #define  SYMTYPE_H
  922.  
  923.  
  924. /* struct to hold info about builtins */
  925. typedef struct {
  926. char *name ;
  927. PF_CP  fp ;  /* ptr to function that does the builtin */
  928. unsigned char min_args, max_args ; 
  929. /* info for parser to check correct number of arguments */
  930. } BI_REC ;
  931.  
  932. /*---------------------------
  933.    structures and types for arrays
  934.  *--------------------------*/
  935.  
  936. /* array hash nodes */
  937.  
  938. typedef  struct anode {
  939. struct anode *link ;
  940. STRING *sval ;
  941. CELL   *cp ;
  942. }  ANODE, **ARRAY ;
  943.  
  944. /* note ARRAY is a ptr to a hash table */
  945.  
  946. CELL *PROTO(array_find, (ARRAY,void *, int) ) ;
  947. int PROTO(array_test, (ARRAY, STRING *) ) ;
  948. INST *PROTO(array_loop, (INST *, CELL *, CELL *) ) ;
  949. void PROTO(array_delete, (ARRAY, STRING *) ) ;
  950. CELL *PROTO(array_cat, (CELL *, int) ) ;
  951. void PROTO(array_free, (ARRAY) ) ;
  952.  
  953. #define new_ARRAY() (ARRAY)memset(zmalloc(A_HASH_PRIME *\
  954.                         sizeof(ANODE*)), 0, A_HASH_PRIME*sizeof(ANODE*))
  955.  
  956. extern  ARRAY  Argv ;
  957.  
  958. /* for parsing  (i,j) in A  */
  959. typedef  struct {
  960. INST *start ;
  961. int cnt ;
  962. } ARG2_REC ;
  963.  
  964. /*------------------------
  965.   user defined functions
  966.   ------------------------*/
  967.  
  968. typedef  struct fblock {
  969. char *name ;
  970. INST *code  ;
  971. unsigned short nargs ;
  972. char *typev ;  /* array of size nargs holding types */
  973. } FBLOCK ;   /* function block */
  974.  
  975. void  PROTO(add_to_fdump_list, (FBLOCK *) ) ;
  976. void  PROTO( fdump, (void) ) ;
  977.  
  978. /*-------------------------
  979.   elements of the symbol table
  980.   -----------------------*/
  981.  
  982. #define  ST_NONE 0
  983. #define  ST_VAR   1
  984. #define  ST_KEYWORD   2
  985. #define  ST_BUILTIN 3 /* a pointer to a builtin record */
  986. #define  ST_ARRAY   4 /* a void * ptr to a hash table */
  987. #define  ST_FIELD   5  /* a cell ptr to a field */
  988. #define  ST_FUNCT   6
  989. #define  ST_LENGTH  7  /* length is special */
  990. #define  ST_LOCAL_NONE  8
  991. #define  ST_LOCAL_VAR   9
  992. #define  ST_LOCAL_ARRAY 10
  993.  
  994. #define  is_local(stp)   ((stp)->type>=ST_LOCAL_NONE)
  995.  
  996. typedef  struct {
  997. char *name ;
  998. char type ;
  999. unsigned char offset ;  /* offset in stack frame for local vars */
  1000. union {
  1001. CELL *cp ;
  1002. int  kw ;
  1003. PF_CP fp ;
  1004. BI_REC *bip ;
  1005. ARRAY  array ; 
  1006. FBLOCK  *fbp ;
  1007. } stval ;
  1008. }  SYMTAB ;
  1009.  
  1010.  
  1011. /*****************************
  1012.  structures for type checking function calls
  1013.  ******************************/
  1014.  
  1015. typedef  struct ca_rec {
  1016. struct ca_rec  *link ;
  1017. short type ;
  1018. short arg_num ;  /* position in callee's stack */
  1019. /*---------  this data only set if we'll  need to patch -------*/
  1020. /* happens if argument is an ID or type ST_NONE or ST_LOCAL_NONE */
  1021.  
  1022. int call_offset ;
  1023. /* where the type is stored */
  1024. SYMTAB  *sym_p ;  /* if type is ST_NONE  */
  1025. char *type_p ;  /* if type  is ST_LOCAL_NONE */
  1026. }  CA_REC  ; /* call argument record */
  1027.  
  1028. /* type field of CA_REC matches with ST_ types */
  1029. #define   CA_EXPR       ST_LOCAL_VAR
  1030. #define   CA_ARRAY      ST_LOCAL_ARRAY
  1031.  
  1032. typedef  struct fcall {
  1033. struct fcall *link ;
  1034. FBLOCK  *callee ;
  1035. short   call_scope ;
  1036. FBLOCK  *call ;  /* only used if call_scope == SCOPE_FUNCT  */
  1037. INST    *call_start ; /* computed later as code may be moved */
  1038. CA_REC  *arg_list ;
  1039. short   arg_cnt_checked ;
  1040. unsigned line_no ; /* for error messages */
  1041. } FCALL_REC ;
  1042.  
  1043. extern  FCALL_REC  *resolve_list ;
  1044.  
  1045. void PROTO(resolve_fcalls, (void) ) ;
  1046. void PROTO(check_fcall, (FBLOCK*,int,FBLOCK*,CA_REC*,unsigned) ) ;
  1047.  
  1048. /* hash.c */
  1049. unsigned  PROTO( hash, (char *) ) ;
  1050. SYMTAB *PROTO( insert, (char *) ) ;
  1051. SYMTAB *PROTO( find, (char *) ) ;
  1052. SYMTAB *PROTO( save_id, (char *) ) ;
  1053. void    PROTO( restore_ids, (void) ) ;
  1054.  
  1055. /* error.c */
  1056. void  PROTO(type_error, (SYMTAB *) ) ;
  1057.  
  1058. #endif  /* SYMTYPE_H */
  1059. @//E*O*F mawk0.97/symtype.h//
  1060. chmod u=rw,g=r,o=r mawk0.97/symtype.h
  1061.  
  1062. echo x - mawk0.97/types.h
  1063. sed 's/^@//' > "mawk0.97/types.h" <<'@//E*O*F mawk0.97/types.h//'
  1064.  
  1065. /********************************************
  1066. types.h
  1067. copyright 1991, Michael D. Brennan
  1068.  
  1069. This is a source file for mawk, an implementation of
  1070. the Awk programming language as defined in
  1071. Aho, Kernighan and Weinberger, The AWK Programming Language,
  1072. Addison-Wesley, 1988.
  1073.  
  1074. See the accompaning file, LIMITATIONS, for restrictions
  1075. regarding modification and redistribution of this
  1076. program in source or binary form.
  1077. ********************************************/
  1078.  
  1079.  
  1080. /* $Log:    types.h,v $
  1081.  * Revision 2.1  91/04/08  08:24:15  brennan
  1082.  * VERSION 0.97
  1083.  * 
  1084. */
  1085.  
  1086.  
  1087. /*  types.h  */
  1088.  
  1089. #ifndef  TYPES_H
  1090. #define  TYPES_H
  1091.  
  1092. #if     HAVE_VOID_PTR
  1093. typedef  void *PTR ;
  1094. #else
  1095. typedef  char *PTR ;
  1096. #endif
  1097.  
  1098. #include  "sizes.h"
  1099.  
  1100.  
  1101. /*  CELL  types  */
  1102.  
  1103. #define  C_NOINIT                0
  1104. #define  C_DOUBLE                1
  1105. #define  C_STRING                2
  1106. #define  C_STRNUM                3
  1107. #define  C_MBSTRN                4 
  1108.         /*could be STRNUM, has not been checked */
  1109. #define  C_RE                    5
  1110. #define  C_SPACE                 6
  1111.         /* split on space */
  1112. #define  C_SNULL                 7
  1113.         /* split on the empty string  */
  1114. #define  C_REPL                  8
  1115.         /* a replacement string   '\&' changed to &  */
  1116. #define  C_REPLV                 9
  1117.         /* a vector replacement -- broken on &  */
  1118. #define  NUM_CELL_TYPES         10
  1119.  
  1120. /* these defines are used to check types for two
  1121.    CELLs which are adjacent in memory */
  1122.  
  1123. #define  TWO_NOINITS  (2*(1<<C_NOINIT))
  1124. #define  TWO_DOUBLES  (2*(1<<C_DOUBLE))
  1125. #define  TWO_STRINGS  (2*(1<<C_STRING))
  1126. #define  TWO_STRNUMS  (2*(1<<C_STRNUM))
  1127. #define  TWO_MBSTRNS  (2*(1<<C_MBSTRN))
  1128. #define  NOINIT_AND_DOUBLE  ((1<<C_NOINIT)+(1<<C_DOUBLE))
  1129. #define  NOINIT_AND_STRING  ((1<<C_NOINIT)+(1<<C_STRING))
  1130. #define  NOINIT_AND_STRNUM  ((1<<C_NOINIT)+(1<<C_STRNUM))
  1131. #define  DOUBLE_AND_STRING  ((1<<C_DOUBLE)+(1<<C_STRING))
  1132. #define  DOUBLE_AND_STRNUM  ((1<<C_STRNUM)+(1<<C_DOUBLE))
  1133. #define  STRING_AND_STRNUM  ((1<<C_STRING)+(1<<C_STRNUM))
  1134. #define  NOINIT_AND_MBSTRN  ((1<<C_NOINIT)+(1<<C_MBSTRN))
  1135. #define  DOUBLE_AND_MBSTRN  ((1<<C_DOUBLE)+(1<<C_MBSTRN))
  1136. #define  STRING_AND_MBSTRN  ((1<<C_STRING)+(1<<C_MBSTRN))
  1137. #define  STRNUM_AND_MBSTRN  ((1<<C_STRNUM)+(1<<C_MBSTRN))
  1138.  
  1139. typedef  struct {
  1140. unsigned short ref_cnt ;
  1141. unsigned short len ;
  1142. char str[4] ;
  1143. } STRING ;
  1144.  
  1145.  
  1146. typedef  struct cell {
  1147. short type ;
  1148. short vcnt ; /* only used if type == C_REPLV   */
  1149. PTR   ptr ;
  1150. double  dval ;
  1151. }  CELL ;
  1152.  
  1153.  
  1154. /* all builtins are passed the evaluation stack pointer and
  1155.    return its new value, here is the type */
  1156.  
  1157. #ifdef __STDC__
  1158. typedef CELL *(*PF_CP)(CELL *) ;
  1159. #else
  1160. typedef CELL *(*PF_CP)() ;
  1161. #endif
  1162.  
  1163. /* an element of code (instruction) */
  1164. typedef  union {
  1165. int  op ;
  1166. PTR  ptr ;
  1167. }  INST ;
  1168.  
  1169. /* a scratch buffer type */
  1170. union tbuff {
  1171. PTR   ptr_buff[MAX_FIELD] ;
  1172. char   string_buff[TEMP_BUFF_SZ + BUFFSZ + 1] ;
  1173. } ;
  1174.  
  1175. #endif
  1176. @//E*O*F mawk0.97/types.h//
  1177. chmod u=rw,g=r,o=r mawk0.97/types.h
  1178.  
  1179. echo x - mawk0.97/zmalloc.c
  1180. sed 's/^@//' > "mawk0.97/zmalloc.c" <<'@//E*O*F mawk0.97/zmalloc.c//'
  1181.  
  1182. /********************************************
  1183. zmalloc.c
  1184. copyright 1991, Michael D. Brennan
  1185.  
  1186. This is a source file for mawk, an implementation of
  1187. the Awk programming language as defined in
  1188. Aho, Kernighan and Weinberger, The AWK Programming Language,
  1189. Addison-Wesley, 1988.
  1190.  
  1191. See the accompaning file, LIMITATIONS, for restrictions
  1192. regarding modification and redistribution of this
  1193. program in source or binary form.
  1194. ********************************************/
  1195.  
  1196. /*$Log:    zmalloc.c,v $
  1197.  * Revision 2.2  91/04/09  12:39:45  brennan
  1198.  * added static to funct decls to satisfy STARDENT compiler
  1199.  * 
  1200.  * Revision 2.1  91/04/08  08:24:17  brennan
  1201.  * VERSION 0.97
  1202.  * 
  1203. */
  1204.  
  1205. /*  zmalloc.c  */
  1206. #include  "mawk.h"
  1207. #include  "zmalloc.h"
  1208.  
  1209. void PROTO( mawk_exit, (int) ) ;
  1210.  
  1211. /*
  1212.   zmalloc() gets mem from malloc() in CHUNKS of 2048 bytes
  1213.   and cuts these blocks into smaller pieces that are multiples
  1214.   of eight bytes.  When a piece is returned via zfree(), it goes
  1215.   on a linked linear list indexed by its size.  The lists are
  1216.   an array, pool[].
  1217.  
  1218.   E.g., if you ask for 22 bytes with p = zmalloc(22), you actually get
  1219.   a piece of size 24.  When you free it with zfree(p,22) , it is added
  1220.   to the list at pool[2].
  1221. */
  1222.  
  1223. #define ZBLOCKSZ    8    
  1224. #define ZSHIFT      3
  1225. #define POOLSZ      16
  1226.  
  1227. #define  CHUNK          256    
  1228.         /* number of blocks to get from malloc */
  1229.  
  1230. static PTR  PROTO( emalloc, (unsigned) ) ;
  1231. void PROTO( errmsg, (int , char *, ...) ) ;
  1232.  
  1233. static PTR emalloc(size)
  1234.   unsigned size ;
  1235. { PTR p ;
  1236.  
  1237.   if( !(p = malloc(size)) )
  1238.   { errmsg(0, "out of memory") ; mawk_exit(1) ; }
  1239.   return p ;
  1240. }
  1241.  
  1242.  
  1243. typedef  union  zblock {
  1244. char dummy[ZBLOCKSZ] ;
  1245. union zblock *link ;
  1246. }  ZBLOCK  ;
  1247.  
  1248. /* ZBLOCKS of sizes 1, 2, ... 16
  1249.    which is bytes of sizes 8, 16, ... , 128
  1250.    are stored on the linked linear lists in
  1251.    pool[0], pool[1], ... , pool[15]
  1252. */
  1253.  
  1254. static  ZBLOCK  *pool[POOLSZ] ;
  1255.  
  1256. PTR   zmalloc( size )
  1257.   unsigned size ;
  1258. { register unsigned blocks ;
  1259.   register ZBLOCK *p ;
  1260.   static  unsigned amt_avail ;
  1261.   static  ZBLOCK  *avail ;
  1262.  
  1263.   if ( size > POOLSZ * ZBLOCKSZ )  return emalloc(size) ;
  1264.  
  1265.   blocks = (size >> ZSHIFT) + ((size & (ZBLOCKSZ-1)) != 0) ;
  1266.  
  1267.   if ( p = pool[blocks-1] )
  1268.   { pool[blocks-1] = p->link ; return (PTR) p ; }
  1269.  
  1270.   if ( blocks > amt_avail )
  1271.   { if ( amt_avail ) /* free avail */
  1272.     { avail->link = pool[--amt_avail] ; pool[amt_avail] = avail ; }
  1273.     if ( !(avail = (ZBLOCK *) malloc(CHUNK*ZBLOCKSZ)) )
  1274.     { /* if we get here, almost out of memory */
  1275.         amt_avail = 0 ;   return  emalloc(size) ; }
  1276.     amt_avail = CHUNK ;
  1277.   }
  1278.   
  1279.   /* get p from the avail pile */
  1280.   p = avail ; avail += blocks ; amt_avail -= blocks ; 
  1281.   return (PTR) p ;
  1282. }
  1283.  
  1284. void  zfree( p, size)
  1285.   register PTR p ;  unsigned size ;
  1286. { register int index ; ;
  1287.  
  1288.   if ( size > POOLSZ * ZBLOCKSZ )  free(p) ;
  1289.   else
  1290.   {
  1291.     index  = (size >> ZSHIFT) + ((size & (ZBLOCKSZ-1)) != 0) - 1;
  1292.     ((ZBLOCK *) p)->link = pool[index] ;
  1293.     pool[index] = (ZBLOCK *) p ;
  1294.   }
  1295. }
  1296.  
  1297. PTR  zrealloc( p, old_size, new_size )
  1298.   register PTR  p ;
  1299.   unsigned old_size, new_size ;
  1300. { register PTR q ;
  1301.  
  1302.   (void) memcpy(q = zmalloc(new_size), p, 
  1303.                 old_size < new_size ? old_size : new_size) ;
  1304.  
  1305.   zfree(p, old_size) ;
  1306.   return q ;
  1307. }
  1308.  
  1309.  
  1310. @//E*O*F mawk0.97/zmalloc.c//
  1311. chmod u=rw,g=r,o=r mawk0.97/zmalloc.c
  1312.  
  1313. echo x - mawk0.97/zmalloc.h
  1314. sed 's/^@//' > "mawk0.97/zmalloc.h" <<'@//E*O*F mawk0.97/zmalloc.h//'
  1315.  
  1316. /********************************************
  1317. zmalloc.h
  1318. copyright 1991, Michael D. Brennan
  1319.  
  1320. This is a source file for mawk, an implementation of
  1321. the Awk programming language as defined in
  1322. Aho, Kernighan and Weinberger, The AWK Programming Language,
  1323. Addison-Wesley, 1988.
  1324.  
  1325. See the accompaning file, LIMITATIONS, for restrictions
  1326. regarding modification and redistribution of this
  1327. program in source or binary form.
  1328. ********************************************/
  1329.  
  1330. /*$Log:    zmalloc.h,v $
  1331.  * Revision 2.1  91/04/08  08:24:19  brennan
  1332.  * VERSION 0.97
  1333.  * 
  1334. */
  1335.  
  1336. /* zmalloc.h */
  1337.  
  1338. #ifndef  ZMALLOC_H
  1339. #define  ZMALLOC_H
  1340.  
  1341. #ifdef   __STDC__
  1342. #include  <stdlib.h>
  1343. #include  <string.h>   /* memcpy() */
  1344.  
  1345. #else
  1346.  
  1347. PTR  memcpy(), malloc(), realloc() ;
  1348. void free() ;
  1349. #endif
  1350.  
  1351.  
  1352. PTR  PROTO( zmalloc, (unsigned) ) ;
  1353. void PROTO( zfree, (PTR, unsigned) ) ;
  1354. PTR  PROTO( zrealloc , (PTR,unsigned,unsigned) ) ;
  1355.  
  1356.  
  1357.  
  1358. #endif  /* ZMALLOC_H */
  1359. @//E*O*F mawk0.97/zmalloc.h//
  1360. chmod u=rw,g=r,o=r mawk0.97/zmalloc.h
  1361.  
  1362. echo mkdir - mawk0.97/rexp
  1363. mkdir mawk0.97/rexp
  1364. chmod u=rwx,g=rx,o=rx mawk0.97/rexp
  1365.  
  1366. echo x - mawk0.97/rexp/Makefile
  1367. sed 's/^@//' > "mawk0.97/rexp/Makefile" <<'@//E*O*F mawk0.97/rexp/Makefile//'
  1368.  
  1369. ####################################
  1370. # This is a makefile for mawk,
  1371. # an implementation of AWK (1988).
  1372. ####################################
  1373. #
  1374. #
  1375. # This builds a regular expression library
  1376. # Remove the -DMAWK and the library has general use.
  1377. # (Even if left in, the diff is very small)
  1378. #
  1379.  
  1380. CFLAGS = -O  -DMAWK
  1381.  
  1382. C=rexp.c rexp0.c rexp1.c rexp2.c rexp3.c rexpdb.c
  1383.  
  1384. regexp.a : $(C)
  1385.     rm -f *.o
  1386.     cc -c $(CFLAGS) $?
  1387.     ar r regexp.a *.o
  1388.     rm -f *.o
  1389.  
  1390.  
  1391.  
  1392.     
  1393.  
  1394. @//E*O*F mawk0.97/rexp/Makefile//
  1395. chmod u=rw,g=r,o=r mawk0.97/rexp/Makefile
  1396.  
  1397. echo x - mawk0.97/rexp/rexp.c
  1398. sed 's/^@//' > "mawk0.97/rexp/rexp.c" <<'@//E*O*F mawk0.97/rexp/rexp.c//'
  1399.  
  1400. /********************************************
  1401. rexp.c
  1402. copyright 1991, Michael D. Brennan
  1403.  
  1404. This is a source file for mawk an implementation of
  1405. the Awk programming language as defined in
  1406. Aho, Kernighan and Weinberger, The AWK Programming Language,
  1407. Addison-Wesley, 1988.
  1408.  
  1409. See the accompaning file, LIMITATIONS, for restrictions
  1410. regarding modification and redistribution of this
  1411. program in source or binary form.
  1412. ********************************************/
  1413.  
  1414. /*   rexp.c   */
  1415.  
  1416. /*  op precedence  parser for regular expressions  */
  1417.  
  1418. #include  "rexp.h"
  1419.  
  1420. /* static  prototypes */
  1421. void  PROTO( op_pop, (void) ) ;
  1422.  
  1423. /*  DATA   */
  1424. int   REerrno ;
  1425. char *REerrlist[] = { (char *) 0 ,
  1426. /* 1  */    "missing '('",
  1427. /* 2  */    "missing ')'",
  1428. /* 3  */    "bad class -- [], [^] or [" ,
  1429. /* 4  */    "missing operand" ,
  1430. /* 5  */    "resource exhaustion -- regular expression too large",
  1431. /* 6  */    "null regular expression" } ;
  1432.  
  1433. /* E5 is very unlikely to occur */
  1434.  
  1435. /* This table drives the operator precedence parser */
  1436. static  int  table[8][8]  =  {
  1437.  
  1438. /*        0   |   CAT   *   +   ?   (   )   */
  1439. /* 0 */   0,  L,  L,    L,  L,  L,  L,  E1,
  1440. /* | */   G,  G,  L,    L,  L,  L,  L,  G,
  1441. /* CAT*/  G,  G,  G,    L,  L,  L,  L,  G,
  1442. /* * */   G,  G,  G,    G,  G,  G, E7,  G,
  1443. /* + */   G,  G,  G,    G,  G,  G, E7,  G,
  1444. /* ? */   G,  G,  G,    G,  G,  G, E7,  G,
  1445. /* ( */   E2, L,  L,    L,  L,  L,  L,  EQ,
  1446. /* ) */   G , G,  G,    G,  G,  G,  E7,  G     }   ;
  1447.  
  1448.  
  1449. /*====================================
  1450.   THE  STACKS
  1451.  ==========================*/
  1452. typedef struct
  1453. { int  token ;
  1454.   int  prec ;   }  OP ;
  1455.  
  1456. #define  STACKSZ   96
  1457.  
  1458. /*---------------------------
  1459.   m_ptr -> top filled slot on the m_stack
  1460.   op_ptr -> top filled slot on op_stack, 
  1461.      initially this is only half filled with the token
  1462.      the precedence is added later
  1463.  *----------------------*/
  1464.  
  1465. static  OP  *op_stack, *op_limit, *op_ptr ;
  1466. static  MACHINE *m_stack, *m_limit, *m_ptr ;
  1467.  
  1468. /* inline for speed on the m_stack */
  1469. #define m_pop() (m_ptr<m_stack?RE_error_trap(-E4): *m_ptr--)
  1470. #define m_push(x)  if(++m_ptr==m_limit) RE_error_trap(-E5);*m_ptr=(x)
  1471.  
  1472. /*=======================*/
  1473.  
  1474. static jmp_buf  err_buf  ;  /*  used to trap on error */
  1475.  
  1476. MACHINE  RE_error_trap(x)  /* return is dummy to make macro OK */
  1477.   int x ;
  1478. {
  1479.   while ( m_ptr >= m_stack ) RE_free( m_ptr-- -> start ) ;
  1480.   RE_free(m_stack) ; RE_free(op_stack) ;
  1481.   REerrno = x ;
  1482.   longjmp(err_buf, 1 ) ;
  1483.   /* dummy return to make compiler happy */
  1484.   return *m_stack ;
  1485. }
  1486.  
  1487.  
  1488. VOID *REcompile(re)
  1489.   char *re ;
  1490. { MACHINE  m  ;
  1491.   register int  t ;
  1492.  
  1493.   RE_lex_init(re) ;
  1494.  
  1495.   if ( *re == 0 )
  1496.   { STATE *p = (STATE *) RE_malloc( sizeof(STATE) ) ;
  1497.     p->type = M_ACCEPT ;
  1498.     return  (VOID *) p ;
  1499.   }
  1500.  
  1501.   if ( setjmp(err_buf) )   return (VOID *) 0 ;
  1502.      /* global error trap */
  1503.  
  1504.   /* initialize the stacks  */
  1505.   m_stack =(MACHINE *) RE_malloc(STACKSZ*sizeof(MACHINE)) ;
  1506.   m_ptr = m_stack - 1 ;
  1507.   m_limit = m_stack + STACKSZ ;
  1508.   op_ptr = op_stack = (OP *) RE_malloc(STACKSZ*sizeof(OP)) ;
  1509.   op_ptr->token = 0 ;
  1510.   op_limit = op_stack + STACKSZ ;
  1511.  
  1512.  
  1513.   t = RE_lex(&m) ;
  1514.  
  1515.   while( 1 )
  1516.    { switch( t )
  1517.        { 
  1518.          case T_STR  :
  1519.          case T_ANY  :
  1520.          case T_U    :
  1521.          case T_START :
  1522.          case T_END :
  1523.          case T_CLASS :  m_push(m) ;  break ;
  1524.  
  1525.          case  0 :   /*  end of reg expr   */
  1526.            if ( op_ptr -> token == 0 )  /*  done   */
  1527.            { m = m_pop() ;
  1528.              if ( m_ptr < m_stack )  /* DONE !!! */
  1529.              { free(m_stack) ; free(op_stack) ;
  1530.                return  (VOID *) m.start ;
  1531.              }
  1532.                /*  machines still on the stack  */
  1533.              RE_panic("values still on machine stack") ;
  1534.              }
  1535.          /*  case 0  falls  thru to default
  1536.              which is operator case  */
  1537.  
  1538.          default:
  1539.  
  1540.            if ( (op_ptr -> prec = table[op_ptr -> token][t]) == G )
  1541.                { while ( op_ptr -> prec != L )  op_pop() ;
  1542.                  continue ; }
  1543.  
  1544.            if ( op_ptr -> prec < 0 )
  1545.               if ( op_ptr->prec == E7 ) 
  1546.                   RE_panic("parser returns E7") ;
  1547.               else  RE_error_trap(-op_ptr->prec) ;
  1548.  
  1549.            if ( ++op_ptr == op_stack + STACKSZ ) /* stack overflow */
  1550.                  RE_error_trap(-E5) ;
  1551.            op_ptr -> token = t ;
  1552.        }
  1553.     t = RE_lex(&m) ;
  1554.   }
  1555. }
  1556.  
  1557. static void  op_pop()
  1558. { register int  t  ;
  1559.   MACHINE m, n ;
  1560.  
  1561.   if ( (t = op_ptr-- -> token) >= T_LP ) return ;
  1562.         /* nothing to do with '(' or ')' */
  1563.   if ( t <= T_CAT )  /* binary operation */
  1564.         n = m_pop() ;
  1565.   m = m_pop() ;
  1566.  
  1567.   switch( t )
  1568.   {  case  T_CAT :  RE_cat(&m, &n) ;  break ;
  1569.      case  T_OR  :  RE_or( &m, &n) ;  break ;
  1570.      case T_STAR  :  RE_close( &m) ;  break ;
  1571.      case T_PLUS  :  RE_poscl( &m ) ; break ;
  1572.      case T_Q     :  RE_01( &m ) ;    break ;
  1573.      default       :
  1574.         RE_panic("strange token popped from op_stack") ;
  1575.   }
  1576.   m_push(m) ;
  1577. }
  1578.  
  1579. /* getting here means a logic flaw or unforeseen case */
  1580. void RE_panic( s )
  1581.   char *s ;
  1582. { fprintf( stderr, "REcompile() - panic:  %s\n", s) ;
  1583.   exit(100) ; }
  1584.  
  1585. @//E*O*F mawk0.97/rexp/rexp.c//
  1586. chmod u=rw,g=r,o=r mawk0.97/rexp/rexp.c
  1587.  
  1588. echo x - mawk0.97/rexp/rexp.h
  1589. sed 's/^@//' > "mawk0.97/rexp/rexp.h" <<'@//E*O*F mawk0.97/rexp/rexp.h//'
  1590.  
  1591. /********************************************
  1592. rexp.h
  1593. copyright 1991, Michael D. Brennan
  1594.  
  1595. This is a source file for mawk an implementation of
  1596. the Awk programming language as defined in
  1597. Aho, Kernighan and Weinberger, The AWK Programming Language,
  1598. Addison-Wesley, 1988.
  1599.  
  1600. See the accompaning file, LIMITATIONS, for restrictions
  1601. regarding modification and redistribution of this
  1602. program in source or binary form.
  1603. ********************************************/
  1604.  
  1605. /*  rexp.h    */
  1606.  
  1607. #ifndef  REXP_H
  1608. #define  REXP_H
  1609.  
  1610. #include  <string.h>
  1611. #include  <stdio.h>
  1612. #include  <setjmp.h>
  1613.  
  1614. #ifndef   PROTO
  1615. #ifdef    __STDC__
  1616. #define  PROTO(name, args)   name  args
  1617. #else
  1618. #define  PROTO(name, args)   name()
  1619. #endif
  1620. #endif   
  1621.  
  1622. #ifdef  __STDC__
  1623. #define  VOID   void
  1624. #include <stdlib.h>
  1625. #else
  1626. #define  VOID   char
  1627. char *malloc(), *realloc() ;
  1628. void free() ;
  1629. #endif
  1630.  
  1631. /* user can change this  */
  1632.  
  1633. #define  RE_malloc(x)    RE_xmalloc(x)
  1634. #define  RE_realloc(x,l)   RE_xrealloc(x,l)
  1635. #define  RE_free(x)      free(x)
  1636.  
  1637. VOID  *PROTO( RE_xmalloc, (unsigned) ) ;
  1638. VOID  *PROTO( RE_xrealloc, (void *,unsigned) ) ;
  1639.  
  1640.  
  1641. /*  finite machine  state types  */
  1642.  
  1643. #define  M_STR         0
  1644. #define  M_CLASS       1
  1645. #define  M_ANY         2
  1646. #define  M_START       3
  1647. #define  M_END         4
  1648. #define  M_U           5
  1649. #define  M_1J          6
  1650. #define  M_2JA         7
  1651. #define  M_2JB         8
  1652. #define  M_ACCEPT      9
  1653. #define  U_ON          10
  1654.  
  1655. #define  U_OFF     0
  1656. #define  END_OFF   0
  1657. #define  END_ON    (2*U_ON)
  1658.  
  1659.  
  1660. typedef  unsigned char BV[32] ;  /* bit vector */
  1661.  
  1662. typedef  struct
  1663. { char type ;
  1664.   unsigned char  len ;  /* used for M_STR  */
  1665.   union
  1666.    { 
  1667.      char *str  ;  /* string */
  1668.      BV   *bvp ;   /*  class  */
  1669.      int   jump ;
  1670.    }  data ;
  1671. }     STATE  ;
  1672.  
  1673. #define  STATESZ  (sizeof(STATE))
  1674.  
  1675. typedef  struct
  1676. { STATE  *start, *stop ; }   MACHINE ;
  1677.  
  1678.  
  1679. /*  tokens   */
  1680. #define  T_OR   1       /* | */
  1681. #define  T_CAT  2       
  1682. #define  T_STAR 3       /* * */
  1683. #define  T_PLUS 4       /* + */
  1684. #define  T_Q    5       /* ? */
  1685. #define  T_LP   6       /* ( */
  1686. #define  T_RP   7       /* ) */
  1687. #define  T_START 8      /* ^ */
  1688. #define  T_END  9       /* $ */
  1689. #define  T_ANY  10      /* . */
  1690. #define  T_CLASS 11     /* starts with [ */
  1691. #define  T_SLASH 12     /*  \  */
  1692. #define  T_CHAR  13     /* all the rest */
  1693. #define  T_STR   14
  1694. #define  T_U     15
  1695.  
  1696. /*  precedences and error codes  */
  1697. #define  L   0
  1698. #define  EQ  1
  1699. #define  G   2
  1700. #define  E1  (-1)
  1701. #define  E2  (-2)
  1702. #define  E3  (-3)
  1703. #define  E4  (-4)
  1704. #define  E5  (-5)
  1705. #define  E6  (-6)
  1706. #define  E7  (-7)
  1707.  
  1708. #define  MEMORY_FAILURE      5
  1709.  
  1710. /* struct for the run time stack */
  1711. typedef struct {
  1712. STATE *m ;   /*   save the machine ptr */
  1713. int    u ;   /*   save the u_flag */
  1714. char  *s ;   /*   save the active string ptr */
  1715. char  *ss ;  /*   save the match start -- only used by REmatch */
  1716. } RT_STATE ;   /* run time state */
  1717.  
  1718. /*  error  trap   */
  1719. extern int REerrno ;
  1720. MACHINE   PROTO(RE_error_trap, (int) ) ;
  1721.  
  1722.  
  1723. MACHINE   PROTO( RE_u, (void) ) ;
  1724. MACHINE   PROTO( RE_start, (void) ) ;
  1725. MACHINE   PROTO( RE_end, (void) ) ;
  1726. MACHINE   PROTO( RE_any, (void) ) ;
  1727. MACHINE   PROTO( RE_str, (char *, unsigned) ) ;
  1728. MACHINE   PROTO( RE_class, (BV *) ) ;
  1729. void      PROTO( RE_cat, (MACHINE *, MACHINE *) ) ;
  1730. void      PROTO( RE_or, (MACHINE *, MACHINE *) ) ;
  1731. void      PROTO( RE_close, (MACHINE *) ) ;
  1732. void      PROTO( RE_poscl, (MACHINE *) ) ;
  1733. void      PROTO( RE_01, (MACHINE *) ) ;
  1734. void      PROTO( RE_panic, (char *) ) ;
  1735. char     *PROTO( str_str, (char *, char *, unsigned) ) ;
  1736.  
  1737. void      PROTO( RE_lex_init , (char *) ) ;
  1738. int       PROTO( RE_lex , (MACHINE *) ) ;
  1739. void      PROTO( RE_run_stack_init, (void) ) ;
  1740. RT_STATE *PROTO( RE_new_run_stack, (void) ) ;
  1741.  
  1742. #endif   /* REXP_H  */
  1743. @//E*O*F mawk0.97/rexp/rexp.h//
  1744. chmod u=rw,g=r,o=r mawk0.97/rexp/rexp.h
  1745.  
  1746. echo x - mawk0.97/rexp/rexp0.c
  1747. sed 's/^@//' > "mawk0.97/rexp/rexp0.c" <<'@//E*O*F mawk0.97/rexp/rexp0.c//'
  1748.  
  1749. /********************************************
  1750. rexp0.c
  1751. copyright 1991, Michael D. Brennan
  1752.  
  1753. This is a source file for mawk an implementation of
  1754. the Awk programming language as defined in
  1755. Aho, Kernighan and Weinberger, The AWK Programming Language,
  1756. Addison-Wesley, 1988.
  1757.  
  1758. See the accompaning file, LIMITATIONS, for restrictions
  1759. regarding modification and redistribution of this
  1760. program in source or binary form.
  1761. ********************************************/
  1762.  
  1763. /*  rexp0.c   */
  1764.  
  1765. /*  lexical scanner  */
  1766.  
  1767. #include  "rexp.h"
  1768.  
  1769. /* static functions */
  1770. static int  PROTO( do_str, (int, char **, MACHINE *) ) ;
  1771. static int  PROTO( do_class, (char **, MACHINE *) ) ;
  1772. static int  PROTO( escape, (char **) ) ;
  1773. static BV   *PROTO( store_bvp, (BV *) ) ;
  1774. static int  PROTO( ctohex, (int) ) ;
  1775.  
  1776.  
  1777. #ifndef  EG  /* if EG make next array visible */
  1778. static
  1779. #endif
  1780. char  RE_char2token[ '|' + 1 ] = {
  1781. 0,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,
  1782. 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,9,13,13,13,
  1783. 6,7,3,4,13,13,10,13,13,13,13,13,13,13,13,13,13,13,13,13,13,
  1784. 13,13,5,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,
  1785. 13,13,13,13,13,13,13,13,13,13,11,12,13,8,13,13,13,13,13,13,
  1786. 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,
  1787. 13,13,13,13,1} ;
  1788.  
  1789. #define  char2token(x) ( (unsigned char)(x) > '|' ? T_CHAR : RE_char2token[x] )
  1790.  
  1791. #define NOT_STARTED    (-1)
  1792.  
  1793. static  int  prev  ;
  1794. static  char   *lp  ;     /*  ptr to reg exp string  */
  1795. static  unsigned re_len ;
  1796.  
  1797.  
  1798. void  RE_lex_init( re )
  1799.   char *re ;
  1800.   lp = re ;
  1801.   re_len = strlen(re) + 1  ;
  1802.   prev = NOT_STARTED ;
  1803.   RE_run_stack_init() ;
  1804. }
  1805.   
  1806.  
  1807. int   RE_lex( mp )
  1808.   MACHINE  *mp ;
  1809. { register int c ;
  1810.  
  1811.   switch( c = char2token(*lp) )
  1812.    {
  1813.      case T_OR :
  1814.      case T_PLUS :
  1815.      case T_STAR :
  1816.      case T_Q :
  1817.      case T_RP :
  1818.            lp++ ;  return  prev = c ;
  1819.      case T_SLASH :
  1820.            if ( lp[1] != 0 )  break ;
  1821.            /* else fall thru */
  1822.  
  1823.      case 0   :   return 0 ;
  1824.      
  1825.      case T_LP :
  1826.            switch( prev )
  1827.            { 
  1828.              case T_CHAR :
  1829.              case T_STR  :
  1830.              case T_ANY :
  1831.              case T_CLASS :
  1832.              case T_START :
  1833.              case T_RP :
  1834.              case T_PLUS :
  1835.              case T_STAR :
  1836.              case T_Q :
  1837.              case T_U :
  1838.                   return prev = T_CAT ;
  1839.              default  :
  1840.                   lp++ ;
  1841.                   return prev = T_LP ;
  1842.            }
  1843.    }
  1844.  
  1845.   /*  *lp  is  an operand, but implicit cat op is possible   */
  1846.   switch( prev )
  1847.    { case  NOT_STARTED :
  1848.      case  T_OR :
  1849.      case  T_LP :
  1850.      case T_CAT :
  1851.  
  1852.           switch( c )
  1853.            { case  T_ANY : 
  1854.              { static plus_is_star_flag = 0 ;
  1855.  
  1856.                   if ( * ++lp == '*' )
  1857.                   { lp++ ;  *mp = RE_u() ;
  1858.                     return  prev = T_U ; }
  1859.                   else
  1860.                   if ( *lp == '+' )
  1861.                       if ( plus_is_star_flag )
  1862.                       { lp++ ;  *mp = RE_u() ;
  1863.                         plus_is_star_flag = 0 ;
  1864.                         return prev = T_U ;
  1865.                       }
  1866.                       else
  1867.                       { plus_is_star_flag = 1 ;
  1868.                         lp-- ; *mp = RE_any() ;
  1869.                         return prev = T_ANY ;
  1870.                       }
  1871.                   else  
  1872.                   { *mp = RE_any() ;
  1873.                     prev = T_ANY ;
  1874.                   }
  1875.               }
  1876.               break ;
  1877.                     
  1878.              case  T_SLASH :
  1879.                   lp++ ; c = escape(&lp) ;
  1880.                   prev = do_str(c, &lp, mp) ;
  1881.                   break ;
  1882.  
  1883.              case  T_CHAR  :
  1884.                   c = *lp++ ;
  1885.                   prev = do_str(c, &lp, mp) ;
  1886.                   break ;
  1887.  
  1888.              case T_CLASS : prev = do_class(&lp, mp) ;
  1889.                             break ;
  1890.  
  1891.              case T_START : *mp = RE_start() ; lp++ ;
  1892.                             prev = T_START ;
  1893.                             break ;
  1894.  
  1895.              case T_END :  
  1896.                      lp++ ; *mp = RE_end() ;
  1897.                      return  prev = T_END ;
  1898.  
  1899.              default :
  1900.                      RE_panic("bad switch in RE_lex") ;
  1901.            }
  1902.            break ;
  1903.  
  1904.      default : /* don't advance the pointer, return T_CAT */
  1905.           return prev = T_CAT ;
  1906.     }
  1907.     /* check for end character */
  1908.     if ( *lp == '$' )
  1909.     { mp->start->type += END_ON ; lp++ ; }
  1910.     return prev ;
  1911. }
  1912.  
  1913. static  int  do_str( c, pp, mp)
  1914.   int c ; /* the first character */
  1915.   char **pp ;  /* where to put the re_char pointer on exit */
  1916.   MACHINE  *mp ;  /* where to put the string machine */
  1917. { register char *p , *s ;
  1918.   char *str ;
  1919.   unsigned len ;
  1920.  
  1921.  
  1922.   p = *pp ;
  1923.   s = str = RE_malloc( re_len ) ;
  1924.   *s++ = c ;  len = 1 ;
  1925.  
  1926.   while ( 1 )
  1927.   { char *save ;
  1928.   
  1929.     switch( char2token(*p) )
  1930.     {
  1931.       case  T_CHAR :  *s++ = *p++ ;
  1932.                       break ;
  1933.       case  T_SLASH :
  1934.                       save = ++p ;
  1935.                       *s++ = escape(&save) ;
  1936.                       p = save ;
  1937.                       break ;
  1938.  
  1939.       default  :  goto  out ;
  1940.     }
  1941.     len++ ;
  1942.   }
  1943. out:
  1944.   /* if len > 1 and we failed on a ? + or * , need to back up */
  1945.   if ( len > 1 && (*p == '*' || *p == '+' || *p == '?' ) )
  1946.   { len-- ; p-- ; s-- ; }
  1947.  
  1948.   *s = 0 ;
  1949.   *pp = p ;
  1950.   *mp = RE_str((char *) RE_realloc(str, len+1) , len) ;
  1951.   return  T_STR ;
  1952. }
  1953.  
  1954.  
  1955. /*--------------------------------------------
  1956.   BUILD A CHARACTER CLASS
  1957.  *---------------------------*/
  1958.  
  1959. #define  on( b, x)  ( (b)[(x)>>3] |= ( 1 << ((x)&7) ))
  1960.  
  1961. static  void  PROTO(block_on, (BV,int,int) ) ;
  1962.  
  1963. static  void  block_on( b, x, y)
  1964.   BV b ; int x, y ;  /* must call with x<=y */
  1965. { int lo = x >> 3 ;
  1966.   int hi = y >> 3 ;
  1967.   int  i, j, bit  ;
  1968.  
  1969.   if ( lo == hi )
  1970.     { j = x&7 ; bit =  1 << j ; i = (y&7) - j + 1 ;
  1971.       for ( ; i ; i-- , bit <<= 1 )  b[lo] |= bit ; }
  1972.   else
  1973.     { for ( i = lo + 1 ; i <= hi - 1 ; i++ )  b[i] = 0xff ;
  1974.       b[lo] |= ( 0xff << (x&7) ) ;
  1975.       b[hi] |= ~( 0xff << ((y&7)+1)) ;
  1976.     }
  1977. }
  1978.  
  1979. /* build a BV for a character class.
  1980.    *start points at the '['
  1981.    on exit:   *start points at the character after ']'
  1982.               mp points at a machine that recognizes the class
  1983. */
  1984.  
  1985. static int  do_class( start, mp)
  1986.   char **start ; MACHINE  *mp ;
  1987. { register char *p ;
  1988.   register BV   *bvp ;
  1989.   int  prev ;
  1990.   char *q , *t;
  1991.   int  cnt ;
  1992.   int comp_flag ;
  1993.  
  1994.   p = (*start) + 1 ;
  1995.   if ( *p == ']' || *p == '^' && *(p+1) == ']' )
  1996.          RE_error_trap(-E3) ;
  1997.   while ( 1 )  /* find the back of the class */
  1998.     { if ( ! (q = strchr(p,']')) )  /* no closing bracket */
  1999.          RE_error_trap(-E3) ;
  2000.       p = q-1 ;
  2001.       cnt = 0 ;
  2002.       while ( *p == '\\') { cnt++ ; p-- ; }
  2003.       if ( (cnt & 1) == 0 )  /* even number of \ */  break ;
  2004.       p = q+1 ;
  2005.     }
  2006.   /*  q  now  pts at the back of the class   */
  2007.   p = (*start) + 1 ;
  2008.   *start = q + 1 ;
  2009.  
  2010.   bvp = (BV *) RE_malloc( sizeof(BV) ) ;
  2011.   (void) memset( bvp, 0, sizeof(BV) ) ;
  2012.  
  2013.   comp_flag = *p == '^' ? p++ , 1 : 0 ;
  2014.   prev = -1 ;  /* indicates  -  cannot be part of a range  */
  2015.  
  2016.   while ( p < q )
  2017.   {
  2018.      switch( *p )
  2019.       { case '\\' :
  2020.           t = ++p ;
  2021.           prev = escape(&t) ;
  2022.           on(*bvp, prev) ;
  2023.           p = t ;
  2024.           continue ;
  2025.  
  2026.         case '-' :
  2027.           if ( prev == -1 || p+1 == q || prev > *(p+1) )
  2028.              { prev = '-' ; on(*bvp, '-') ; }
  2029.           else
  2030.              { p++ ;
  2031.                block_on(*bvp, prev, *p) ;
  2032.                prev = -1 ;
  2033.              }
  2034.           break ;
  2035.  
  2036.         default :
  2037.           prev = *p ;
  2038.           on(*bvp, *p) ;
  2039.           break ;
  2040.       }
  2041.       p++ ;
  2042.   }
  2043.  
  2044.   if ( comp_flag )
  2045.     for ( p = (char *) bvp ; p < (char *) bvp + sizeof(BV) ; p++)  *p = ~*p ;
  2046.  
  2047.   /* make sure zero is off */
  2048.   (*bvp)[0] &= 0xfe ;
  2049.  
  2050.   *mp = RE_class( store_bvp( bvp ) ) ;
  2051.   return  T_CLASS ;
  2052. }
  2053.  
  2054.  
  2055. /* storage for bit vectors so they can be reused ,
  2056.    stored in an unsorted linear array 
  2057.    the array grows as needed
  2058. */
  2059.  
  2060. #define         BV_GROWTH       6
  2061.  
  2062. static BV *store_bvp( bvp )
  2063.   BV *bvp ;
  2064. {
  2065.   static BV **bv_base, **bv_limit ;
  2066.   static BV **bv_next ; /* next empty slot in the array */
  2067.  
  2068.   register BV **p ;
  2069.   unsigned t ;
  2070.  
  2071.  
  2072.   if ( bv_next == bv_limit ) /* need to grow */
  2073.   {
  2074.     if ( ! bv_base )  /* first growth */
  2075.     {  t = 0 ; bv_base = (BV**)RE_malloc(BV_GROWTH*sizeof(BV*)) ; }
  2076.     else 
  2077.     { t = bv_next - bv_base ;
  2078.       bv_base = (BV**) RE_realloc(bv_base, (t+BV_GROWTH)*sizeof(BV*)) ;
  2079.     }
  2080.  
  2081.     bv_next = bv_base + t ;
  2082.     bv_limit = bv_next + BV_GROWTH ;
  2083.   }
  2084.  
  2085.   /* put bvp in bv_next as a sentinal */
  2086.   *bv_next = bvp ;
  2087.   p = bv_base ;
  2088.   while ( memcmp(*p, bvp, sizeof(BV)) )  p++ ;
  2089.  
  2090.   if ( p == bv_next )  /* it is new */
  2091.         bv_next++ ;
  2092.   else  /* we already have it */  RE_free(bvp) ;
  2093.  
  2094.   return *p ;
  2095. }
  2096.   
  2097.  
  2098. /* ----------   convert escape sequences  -------------*/
  2099.  
  2100. #define isoctal(x)  ((x)>='0'&&(x)<='7')
  2101.  
  2102. #define  NOT_HEX        16
  2103. static char hex_val['f' - 'A' + 1] = {
  2104. 10,11,12,13,14,15, 0, 0,
  2105.  0, 0, 0, 0, 0, 0, 0, 0,
  2106.  0, 0, 0, 0, 0, 0, 0, 0,
  2107.  0, 0, 0, 0, 0, 0, 0, 0,
  2108. 10,11,12,13,14,15 } ;
  2109.  
  2110. /* interpret 1 character as hex */
  2111. static int ctohex( c )
  2112.   register int c ;
  2113. { int t ;
  2114.  
  2115.   if ( c >= '0' && c <= '9' )  return c - '0' ;
  2116.  
  2117.   if ( c >= 'A' && c <= 'f' && ( t = hex_val[c-'A'] ))  return t ;
  2118.  
  2119.   return NOT_HEX ;
  2120. }
  2121.  
  2122. static char escape_test[] = "n\nt\tb\br\rf\fa\07v\013" ;
  2123.  
  2124. /*-----------------
  2125.   return the char 
  2126.   and move the pointer forward
  2127.   on entry *s -> at the character after the slash
  2128.  *-------------------*/
  2129.  
  2130. static int escape(start_p)
  2131.   char **start_p ;
  2132. { register char *p = *start_p ;
  2133.   register unsigned x ;
  2134.   unsigned xx ;
  2135.   char *t ;
  2136.  
  2137.   
  2138.   if ( t = strchr(escape_test, *p) )
  2139.   { *start_p = p + 1 ;
  2140.     return  t[1] ;
  2141.   }
  2142.  
  2143.   if ( isoctal(*p) )
  2144.   { x = *p++ - '0' ;
  2145.     if ( isoctal(*p) )
  2146.     { x = (x<<3) + *p++ - '0' ;
  2147.       if ( isoctal(*p) )
  2148.          x = (x<<3) + *p++ - '0' ;
  2149.     }
  2150.     *start_p = p ;
  2151.     return  x & 0xff ;
  2152.   }
  2153.  
  2154.   if ( *p == 0 )  return 0 ;
  2155.  
  2156.   if ( *p++ == 'x' ) /* might be a hex digit */
  2157.   {  if ( (x = ctohex(*p)) == NOT_HEX ) 
  2158.      { *start_p  = p ;  return 'x' ; }
  2159.  
  2160.      /* look for another hex digit */
  2161.      if ( (xx = ctohex(* ++p)) != NOT_HEX )
  2162.      { x = (x<<4) + xx ; p++ ; }
  2163.  
  2164.      *start_p = p ; return x ;
  2165.   }
  2166.   /* anything else \c -> c */
  2167.   *start_p = p ;
  2168.   return p[-1]  ;
  2169. }
  2170. @//E*O*F mawk0.97/rexp/rexp0.c//
  2171. chmod u=rw,g=r,o=r mawk0.97/rexp/rexp0.c
  2172.  
  2173. echo x - mawk0.97/rexp/rexp1.c
  2174. sed 's/^@//' > "mawk0.97/rexp/rexp1.c" <<'@//E*O*F mawk0.97/rexp/rexp1.c//'
  2175.  
  2176. /********************************************
  2177. rexp1.c
  2178. copyright 1991, Michael D. Brennan
  2179.  
  2180. This is a source file for mawk an implementation of
  2181. the Awk programming language as defined in
  2182. Aho, Kernighan and Weinberger, The AWK Programming Language,
  2183. Addison-Wesley, 1988.
  2184.  
  2185. See the accompaning file, LIMITATIONS, for restrictions
  2186. regarding modification and redistribution of this
  2187. program in source or binary form.
  2188. ********************************************/
  2189.  
  2190. /*  rexp1.c   */
  2191.  
  2192. /*  re machine  operations  */
  2193.  
  2194. #include  "rexp.h"
  2195.  
  2196. static MACHINE *PROTO( new_TWO , (int) ) ;
  2197.  
  2198.  
  2199. static  MACHINE  *new_TWO(type)
  2200.   int type ;
  2201.   static  MACHINE  x ;
  2202.  
  2203.   x.start = (STATE *) RE_malloc(2*STATESZ) ;
  2204.   x.stop = x.start + 1 ;
  2205.   x.start->type = type ;
  2206.   x.stop->type = M_ACCEPT ;
  2207.   return &x ;
  2208. } ;
  2209.  
  2210.  
  2211. /*  build a machine that recognizes any  */
  2212. MACHINE  RE_any()
  2213. { return  * new_TWO(M_ANY) ; }
  2214.  
  2215. /*  build a machine that recognizes the start of string  */
  2216. MACHINE  RE_start()
  2217. { return  * new_TWO(M_START) ; }
  2218.  
  2219. MACHINE  RE_end()
  2220. { return  * new_TWO(M_END) ; }
  2221.  
  2222. /*  build a machine that recognizes a class  */
  2223. MACHINE  RE_class( bvp )
  2224.   BV *bvp  ;
  2225. { register MACHINE *p = new_TWO(M_CLASS) ;
  2226.  
  2227.   p->start->data.bvp = bvp ;
  2228.   return *p ;
  2229. }
  2230.  
  2231.  
  2232. MACHINE  RE_u()
  2233. { return  *new_TWO(M_U) ; }
  2234.  
  2235. MACHINE  RE_str( str, len)
  2236.   char *str ;
  2237.   unsigned len ;
  2238. { register MACHINE *p = new_TWO(M_STR) ;
  2239.  
  2240.   p->start->len = len ;
  2241.   p->start->data.str = str ;
  2242.   return *p ;
  2243. }
  2244.  
  2245. /*  replace m and n by a machine that recognizes  mn   */
  2246. void  RE_cat( mp, np)
  2247.   MACHINE  *mp, *np ;
  2248. { unsigned sz1, sz2, sz ;
  2249.  
  2250.   sz1 = mp->stop - mp->start  ;
  2251.   sz2 = np->stop - np->start + 1 ;
  2252.   sz  = sz1 + sz2 ;
  2253.  
  2254.   mp->start = (STATE *) RE_realloc( mp->start, sz * STATESZ ) ;
  2255.   mp->stop = mp->start + (sz - 1) ;
  2256.   (void)  memcpy( mp->start + sz1, np->start, sz2 * STATESZ ) ;
  2257.   RE_free( np->start ) ;
  2258. }
  2259.  
  2260.  /*  replace m by a machine that recognizes m|n  */
  2261.  
  2262. void  RE_or( mp, np)
  2263.   MACHINE  *mp, *np ;
  2264. { register STATE *p ;
  2265.   unsigned szm, szn ;
  2266.  
  2267.   szm = mp->stop - mp->start + 1 ;
  2268.   szn = np->stop - np->start + 1 ;
  2269.  
  2270.   p = (STATE *) RE_malloc( (szm+szn+1) * STATESZ ) ;
  2271.   (void) memcpy( p+1, mp->start, szm * STATESZ ) ;
  2272.   RE_free( mp->start) ;
  2273.   mp->start = p ;
  2274.   (mp->stop  = p + szm + szn) -> type = M_ACCEPT ;
  2275.   p->type = M_2JA ;
  2276.   p->data.jump = szm+1 ;
  2277.   (void) memcpy( p + szm + 1 , np->start, szn * STATESZ) ;
  2278.   RE_free( np->start ) ;
  2279.   (p += szm)->type = M_1J ;
  2280.   p->data.jump = szn ;
  2281. }
  2282.  
  2283. /*  UNARY  OPERATIONS     */
  2284.  
  2285. /*  replace m by m*   */
  2286.  
  2287. void  RE_close( mp )
  2288.   MACHINE  *mp ;
  2289. { register STATE *p ;
  2290.   unsigned sz ;
  2291.  
  2292.   sz = mp->stop - mp->start + 1 ;
  2293.   p = (STATE *) RE_malloc( (sz+2) * STATESZ ) ;
  2294.   (void) memcpy( p+1, mp->start, sz * STATESZ) ;
  2295.   RE_free( mp->start ) ;
  2296.   mp->start = p ;
  2297.   mp->stop  = p + (sz+1) ;
  2298.   p->type = M_2JA ;
  2299.   p->data.jump = sz + 1 ;
  2300.   (p += sz) -> type = M_2JB ;
  2301.   p->data.jump = -(sz-1) ;
  2302.   (p+1)->type = M_ACCEPT ;
  2303. }
  2304.  
  2305. /*  replace m  by  m+  (positive closure)   */
  2306.  
  2307. void  RE_poscl( mp )
  2308.   MACHINE  *mp ;
  2309. { register STATE *p ;
  2310.   unsigned  sz ;
  2311.  
  2312.   sz = mp->stop - mp->start + 1 ;
  2313.   mp->start = p = (STATE *) RE_realloc(mp->start ,  (sz+1) * STATESZ ) ;
  2314.   mp->stop  = p + sz ;
  2315.   p +=  --sz ;
  2316.   p->type = M_2JB ;
  2317.   p->data.jump = -sz ;
  2318.   (p+1)->type = M_ACCEPT ;
  2319. }
  2320.  
  2321. /* replace  m  by  m? (zero or one)  */
  2322.  
  2323. void  RE_01( mp )
  2324.   MACHINE  *mp ;
  2325. { unsigned  sz ;
  2326.   register  STATE *p ;
  2327.  
  2328.   sz = mp->stop - mp->start + 1 ;
  2329.   p = (STATE *) RE_malloc( (sz+1) * STATESZ ) ;
  2330.   (void) memcpy( p+1, mp->start, sz * STATESZ) ;
  2331.   RE_free( mp->start ) ;
  2332.   mp->start = p ;
  2333.   mp->stop = p + sz ;
  2334.   p->type = M_2JB ;
  2335.   p->data.jump = sz ;
  2336. }
  2337.  
  2338. /*===================================
  2339. MEMORY  ALLOCATION
  2340.  *==============================*/
  2341.  
  2342.  
  2343. VOID *RE_xmalloc( sz ) 
  2344.   unsigned sz ;
  2345. { register VOID *p ;
  2346.  
  2347.   if ( ! ( p = malloc(sz) ) )  RE_error_trap(MEMORY_FAILURE) ;
  2348.   return p ;
  2349. }
  2350.  
  2351. VOID *RE_xrealloc( p, sz)
  2352.   register VOID *p ; unsigned sz ;
  2353. { if ( ! ( p = realloc( p, sz) ) )  RE_error_trap(MEMORY_FAILURE) ;
  2354.   return p ;
  2355. }
  2356.  
  2357. @//E*O*F mawk0.97/rexp/rexp1.c//
  2358. chmod u=rw,g=r,o=r mawk0.97/rexp/rexp1.c
  2359.  
  2360. echo x - mawk0.97/rexp/rexp2.c
  2361. sed 's/^@//' > "mawk0.97/rexp/rexp2.c" <<'@//E*O*F mawk0.97/rexp/rexp2.c//'
  2362.  
  2363. /********************************************
  2364. rexp2.c
  2365. copyright 1991, Michael D. Brennan
  2366.  
  2367. This is a source file for mawk an implementation of
  2368. the Awk programming language as defined in
  2369. Aho, Kernighan and Weinberger, The AWK Programming Language,
  2370. Addison-Wesley, 1988.
  2371.  
  2372. See the accompaning file, LIMITATIONS, for restrictions
  2373. regarding modification and redistribution of this
  2374. program in source or binary form.
  2375. ********************************************/
  2376.  
  2377. /*  rexp2.c   */
  2378.  
  2379. /*  test a string against a machine   */
  2380.  
  2381. #include "rexp.h"
  2382. #include <string.h>
  2383.  
  2384. /* statics */
  2385. static RT_STATE *PROTO(slow_push,(RT_STATE *,STATE*,char*,int)); 
  2386.  
  2387. /*  check that a bit is on  */
  2388. #define  ison(b,x) ( (b)[(x)>>3] & ( 1 << ((x)&7)  ))
  2389.  
  2390.  
  2391. RT_STATE *RE_run_stack_base; 
  2392. RT_STATE *RE_run_stack_limit ;
  2393. /* for statistics and debug */
  2394. static RT_STATE *stack_max ; 
  2395.  
  2396. void RE_run_stack_init()
  2397. { if ( !RE_run_stack_base )
  2398.   {
  2399.     RE_run_stack_base = (RT_STATE *)
  2400.                  RE_malloc(sizeof(RT_STATE) * 16 ) ;
  2401.     RE_run_stack_limit = RE_run_stack_base + 16 ;
  2402.     stack_max = RE_run_stack_base-1 ;
  2403.   }
  2404. }
  2405.  
  2406. RT_STATE  *RE_new_run_stack()
  2407. { int oldsize = RE_run_stack_limit - RE_run_stack_base ;
  2408.  
  2409.   RE_run_stack_base = (RT_STATE *) RE_realloc( RE_run_stack_base ,
  2410.           (oldsize+8) * sizeof(RT_STATE) ) ;
  2411.   RE_run_stack_limit = RE_run_stack_base + oldsize + 8 ;
  2412.   return  stack_max = RE_run_stack_base + oldsize ;
  2413. }
  2414.  
  2415. static RT_STATE *slow_push(sp, m, s, u)
  2416.   RT_STATE *sp ;
  2417.   STATE *m ;
  2418.   char *s ;
  2419.   int   u ;
  2420.   if ( sp > stack_max )
  2421.      if ( (stack_max = sp) == RE_run_stack_limit )
  2422.          sp = RE_new_run_stack() ;
  2423.  
  2424.   sp->m = m ; sp->s = s ; sp->u = u ;
  2425.   return sp ;
  2426. }
  2427.  
  2428. #ifdef   DEBUG
  2429. void  print_max_stack(f)
  2430.   FILE *f ;
  2431. { fprintf(f, "stack_max = %d\n", stack_max-RE_run_stack_base+1) ; }
  2432. #endif
  2433.  
  2434. #ifdef   DEBUG
  2435. #define  push(mx,sx,ux)   stackp = slow_push(++stackp, mx, sx, ux)
  2436. #else
  2437. #define  push(mx,sx,ux)   if (++stackp == RE_run_stack_limit)\
  2438.                                 stackp = slow_push(stackp,mx,sx,ux) ;\
  2439.  
  2440.  
  2441.