home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 3 / 3353 < prev    next >
Internet Message Format  |  1991-05-16  |  62KB

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