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

  1. From: brennan@ssc-vax.UUCP (Mike Brennan)
  2. Newsgroups: alt.sources
  3. Subject: mawk0.97.shar 6 of 6
  4. Message-ID: <3968@ssc-bee.ssc-vax.UUCP>
  5. Date: 11 May 91 14:59:19 GMT
  6.  
  7.  
  8. ------------------cut here----------------
  9.                           else\
  10.                           { stackp->m=mx;stackp->s=sx;stackp->u=ux;}
  11. #endif
  12.  
  13.  
  14. #define   CASE_UANY(x)  case  x + U_OFF :  case  x + U_ON
  15.  
  16.  
  17. int  REtest( str, machine)
  18.   char *str ;
  19.   VOID *machine ;
  20. { register STATE *m = (STATE *) machine ;
  21.   register char *s = str ;
  22.   register RT_STATE *stackp ;
  23.   int u_flag ;
  24.   char *str_end ;
  25.   char *ts ; /*convenient temps */
  26.   STATE *tm ;
  27.  
  28.   /* handle the easy case quickly */
  29.   if ( (m+1)->type == M_ACCEPT && m->type == M_STR )
  30.         return  (int ) str_str(s, m->data.str, m->len) ;
  31.   else
  32.   { u_flag = U_ON ; str_end = (char *) 0 ;
  33.     stackp = RE_run_stack_base - 1 ;
  34.     goto  reswitch ;
  35.   }
  36.  
  37. refill :
  38.   if ( stackp < RE_run_stack_base )  return  0 ;
  39.   m = stackp->m ;
  40.   s = stackp->s ;
  41.   u_flag  = stackp-- -> u ;
  42.  
  43.  
  44. reswitch  :
  45.  
  46.   switch( m->type + u_flag )
  47.   {
  48.     case M_STR + U_OFF + END_OFF :
  49.             if ( strncmp(s, m->data.str, m->len) ) goto refill ;
  50.             s += m->len ;  m++ ;
  51.             goto reswitch ;
  52.  
  53.     case M_STR + U_OFF + END_ON :
  54.             if ( strcmp(s, m->data.str) ) goto refill ;
  55.             s += m->len ;  m++ ;
  56.             goto reswitch ;
  57.  
  58.     case M_STR + U_ON + END_OFF :
  59.             if ( !(s = str_str(s, m->data.str, m->len)) ) goto refill ;
  60.             push(m, s+1, U_ON) ;
  61.             s += m->len ; m++ ; u_flag = U_OFF ;
  62.             goto reswitch ;
  63.  
  64.     case M_STR + U_ON + END_ON :
  65.             if ( !str_end )  str_end = strchr(s, 0) ;
  66.             ts = str_end - m->len ;
  67.             if (ts < s || memcmp(ts,m->data.str,m->len+1)) goto refill ; 
  68.             s = str_end ; m++ ; u_flag = U_OFF ;
  69.             goto reswitch ;
  70.  
  71.     case M_CLASS + U_OFF + END_OFF :
  72.             if ( !ison(*m->data.bvp, s[0] ) )  goto refill ;
  73.             s++ ; m++ ;
  74.             goto reswitch ;
  75.  
  76.     case M_CLASS + U_OFF + END_ON :
  77.             if ( s[1] || !ison(*m->data.bvp,s[0]) )  goto refill ;
  78.             s++ ; m++ ;
  79.             goto reswitch ;
  80.  
  81.     case M_CLASS + U_ON + END_OFF :
  82.             while ( !ison(*m->data.bvp,s[0]) )
  83.                 if ( s[0] == 0 )  goto refill ;
  84.                 else  s++ ;
  85.             s++ ;
  86.             push(m, s, U_ON) ;
  87.             m++ ; u_flag = U_OFF ;
  88.             goto reswitch ;
  89.  
  90.     case M_CLASS + U_ON + END_ON :
  91.             if ( ! str_end )  str_end = strchr(s,0) ;
  92.             if ( ! ison(*m->data.bvp, str_end[-1]) ) goto refill ;
  93.             s = str_end ; m++ ; u_flag = U_OFF ;
  94.             goto reswitch ;
  95.  
  96.     case M_ANY + U_OFF + END_OFF :
  97.             if ( s[0] == 0 )  goto refill ;
  98.             s++ ; m++ ;
  99.             goto  reswitch ;
  100.  
  101.     case M_ANY + U_OFF + END_ON :
  102.             if ( s[0] == 0 || s[1] != 0 )  goto refill ;
  103.             s++ ; m++ ;
  104.             goto reswitch ;
  105.  
  106.     case M_ANY + U_ON + END_OFF :
  107.             if ( s[0] == 0 )  goto refill ;
  108.             s++ ; 
  109.             push(m, s, U_ON) ;
  110.             m++ ; u_flag = U_OFF ;
  111.             goto  reswitch ;
  112.  
  113.     case M_ANY + U_ON + END_ON :
  114.             if ( s[0] == 0 )  goto refill ;
  115.             if ( ! str_end )  str_end = strchr(s,0) ;
  116.             s = str_end ; m++ ; u_flag = U_OFF ;
  117.             goto reswitch ;
  118.  
  119.     case  M_START + U_OFF + END_OFF :
  120.     case  M_START + U_ON  + END_OFF :
  121.             if ( s != str )  goto  refill ;
  122.             m++ ;  u_flag = U_OFF ;
  123.             goto  reswitch ;
  124.  
  125.     case  M_START + U_OFF + END_ON :
  126.     case  M_START + U_ON  + END_ON :
  127.             if ( s != str || s[0] != 0 )  goto  refill ;
  128.             m++ ; u_flag = U_OFF ;
  129.             goto  reswitch ;
  130.  
  131.     case  M_END + U_OFF  :
  132.             if ( s[0]  != 0 )  goto  refill ;
  133.             m++ ; goto reswitch ;
  134.  
  135.     case  M_END + U_ON :
  136.             s = strchr(s, 0) ;
  137.             m++ ; u_flag = U_OFF ;
  138.             goto reswitch ;
  139.  
  140.     CASE_UANY(M_U) :
  141.             u_flag = U_ON ; m++ ;
  142.             goto reswitch ;
  143.  
  144.     CASE_UANY(M_1J) :
  145.             m += m->data.jump ;
  146.             goto reswitch ;
  147.  
  148.     CASE_UANY(M_2JA) : /* take the non jump branch */
  149.             /* don't stack an ACCEPT */
  150.             if ( (tm = m + m->data.jump)->type == M_ACCEPT ) return 1 ;
  151.             push(tm, s, u_flag) ;
  152.             m++ ;
  153.             goto reswitch ;
  154.  
  155.     CASE_UANY(M_2JB) : /* take the jump branch */
  156.             /* don't stack an ACCEPT */
  157.             if ( (tm = m + 1)->type == M_ACCEPT ) return 1 ;
  158.             push(tm, s, u_flag) ;
  159.             m += m->data.jump ;
  160.             goto reswitch ;
  161.  
  162.     CASE_UANY(M_ACCEPT) :
  163.             return 1 ;
  164.  
  165.     default :
  166.             RE_panic("unexpected case in REtest") ;
  167.   }
  168. }
  169.  
  170.   
  171.  
  172. #ifdef  MAWK
  173.  
  174. char *is_string_split( p, lenp )
  175.   register STATE *p ;
  176.   unsigned *lenp ;
  177. {
  178.   if ( p[0].type == M_STR && p[1].type == M_ACCEPT )
  179.   { *lenp = p->len ;
  180.     return  p->data.str ;
  181.   }
  182.   else   return  (char *) 0 ;
  183. }
  184. #else /* mawk provides its own str_str */
  185.  
  186. char *str_str(target, key, klen)
  187.   register char *target ;
  188.   register char *key ;
  189.   unsigned klen ;
  190. { int c = key[0] ;
  191.  
  192.   switch( klen )
  193.   { case 0 :  return (char *) 0 ;
  194.     case 1 :  return strchr(target, c) ;
  195.     case 2 :  
  196.               while ( target = strchr(target, c) )
  197.                     if ( target[1] == key[1] ) return target ;
  198.                     else target++ ;
  199.               break ;
  200.  
  201.     default :
  202.               klen-- ; key++ ;
  203.               while ( target = strchr(target, c) )
  204.                     if ( memcmp(target+1,key,klen) == 0 ) return target ;
  205.                     else target++ ;
  206.               break ;
  207.   }
  208.   return (char *) 0 ;
  209. }
  210.               
  211.  
  212. #endif  /* MAWK */
  213. @//E*O*F mawk0.97/rexp/rexp2.c//
  214. chmod u=rw,g=r,o=r mawk0.97/rexp/rexp2.c
  215.  
  216. echo x - mawk0.97/rexp/rexp3.c
  217. sed 's/^@//' > "mawk0.97/rexp/rexp3.c" <<'@//E*O*F mawk0.97/rexp/rexp3.c//'
  218.  
  219. /********************************************
  220. rexp3.c
  221. copyright 1991, Michael D. Brennan
  222.  
  223. This is a source file for mawk an implementation of
  224. the Awk programming language as defined in
  225. Aho, Kernighan and Weinberger, The AWK Programming Language,
  226. Addison-Wesley, 1988.
  227.  
  228. See the accompaning file, LIMITATIONS, for restrictions
  229. regarding modification and redistribution of this
  230. program in source or binary form.
  231. ********************************************/
  232.  
  233. /*  rexp3.c   */
  234.  
  235. /*  match a string against a machine   */
  236.  
  237. #include "rexp.h"
  238. #include <string.h>
  239.  
  240.  
  241. /*  check that a bit is on  */
  242. #define  ison(b,x) ( (b)[(x)>>3] & ( 1 << ((x)&7)  ))
  243.  
  244.  
  245. extern RT_STATE *RE_run_stack_base; 
  246. extern RT_STATE *RE_run_stack_limit ;
  247. RT_STATE  *RE_new_run_stack() ;
  248.  
  249.  
  250. #define  push(mx,sx,ssx,ux)   if (++stackp == RE_run_stack_limit)\
  251.                                 stackp = RE_new_run_stack() ;\
  252.                stackp->m=mx;stackp->s=sx;stackp->ss=ssx;stackp->u=ux;
  253.  
  254.  
  255. #define   CASE_UANY(x)  case  x + U_OFF :  case  x + U_ON
  256.  
  257. /* returns start of first longest match and the length by
  258.    reference.  If no match returns NULL and length zero */
  259.  
  260. char *REmatch(str, machine, lenp)
  261.   char *str ;
  262.   VOID   *machine ;
  263.   unsigned *lenp ;
  264. { register STATE *m = (STATE *) machine ;
  265.   register char *s = str ;
  266.   char *ss ;
  267.   register RT_STATE *stackp ;
  268.   int u_flag ;
  269.   char *str_end, *ts ;
  270.  
  271.   /* state of current best match stored here */
  272.   char *cb_ss ;  /* the start */
  273.   char *cb_e  ;  /* the end , pts at first char not matched */
  274.  
  275.   *lenp = 0 ;
  276.  
  277.   /* check for the easy case */
  278.   if ( (m+1)->type == M_ACCEPT && m->type == M_STR )
  279.   { if ( ts = str_str(s, m->data.str, m->len) ) *lenp = m->len ;
  280.     return ts ;
  281.   }
  282.     
  283.   u_flag = U_ON ; cb_ss = ss = str_end = (char *) 0 ;
  284.   stackp = RE_run_stack_base - 1 ;
  285.   goto  reswitch ;
  286.  
  287. refill :
  288.   if ( stackp < RE_run_stack_base )  /* empty stack */
  289.   { if ( cb_ss )  *lenp = cb_e - cb_ss ;
  290.     return cb_ss ;
  291.   }
  292.   ss = stackp->ss ;
  293.   s = stackp-- -> s ;
  294.   if ( cb_ss )  /* does new state start too late ? */
  295.       if ( ss )
  296.       { if ( cb_ss < ss )  goto refill ; }
  297.       else
  298.       if ( cb_ss < s ) goto refill ;
  299.  
  300.   m = (stackp+1)->m ;
  301.   u_flag  = (stackp+1)->u ;
  302.  
  303.  
  304. reswitch  :
  305.  
  306.   switch( m->type + u_flag )
  307.   {
  308.     case M_STR + U_OFF + END_OFF :
  309.             if ( strncmp(s, m->data.str, m->len) ) goto refill ;
  310.         if ( !ss )  
  311.             if ( cb_ss && s > cb_ss ) goto refill ;
  312.         else ss = s ;
  313.             s += m->len ;  m++ ;
  314.             goto reswitch ;
  315.  
  316.     case M_STR + U_OFF + END_ON :
  317.             if ( strcmp(s, m->data.str) ) goto refill ;
  318.         if ( !ss )  
  319.             if ( cb_ss && s > cb_ss ) goto refill ;
  320.         else ss = s ;
  321.             s += m->len ;  m++ ;
  322.             goto reswitch ;
  323.  
  324.     case M_STR + U_ON + END_OFF :
  325.             if ( !(s = str_str(s, m->data.str, m->len)) ) goto refill ;
  326.             push(m, s+1,ss, U_ON) ;
  327.         if ( !ss )  
  328.             if ( cb_ss && s > cb_ss ) goto refill ;
  329.         else ss = s ;
  330.             s += m->len ; m++ ; u_flag = U_OFF ;
  331.             goto reswitch ;
  332.  
  333.     case M_STR + U_ON + END_ON :
  334.             if ( !str_end )  str_end = strchr(s, 0) ;
  335.             ts = str_end - m->len ;
  336.             if (ts < s || memcmp(ts,m->data.str,m->len+1)) goto refill ; 
  337.         if ( !ss )  
  338.         if ( cb_ss && ts > cb_ss )  goto refill ;
  339.         else  ss = ts ;
  340.             s = str_end ; m++ ; u_flag = U_OFF ;
  341.             goto reswitch ;
  342.  
  343.     case M_CLASS + U_OFF + END_OFF :
  344.             if ( !ison(*m->data.bvp, s[0] ) )  goto refill ;
  345.         if ( !ss )
  346.         if ( cb_ss && s > cb_ss )  goto refill ;
  347.         else  ss = s ;
  348.             s++ ; m++ ;
  349.             goto reswitch ;
  350.  
  351.     case M_CLASS + U_OFF + END_ON :
  352.             if ( s[1] || !ison(*m->data.bvp,s[0]) )  goto refill ;
  353.         if ( !ss )
  354.         if ( cb_ss && s > cb_ss )  goto refill ;
  355.         else  ss = s ;
  356.             s++ ; m++ ;
  357.             goto reswitch ;
  358.  
  359.     case M_CLASS + U_ON + END_OFF :
  360.             while ( !ison(*m->data.bvp,s[0]) )
  361.                 if ( s[0] == 0 )  goto refill ;
  362.                 else  s++ ;
  363.  
  364.             s++ ;
  365.             push(m, s, ss, U_ON) ;
  366.         if ( !ss )
  367.         if ( cb_ss && s-1 > cb_ss )  goto refill ;
  368.         else  ss = s-1 ;
  369.             m++ ; u_flag = U_OFF ;
  370.             goto reswitch ;
  371.  
  372.     case M_CLASS + U_ON + END_ON :
  373.             if ( ! str_end )  str_end = strchr(s,0) ;
  374.             if ( ! ison(*m->data.bvp, str_end[-1]) ) goto refill ;
  375.         if ( !ss )
  376.         if ( cb_ss && str_end-1 > cb_ss )  goto refill ;
  377.         else  ss = str_end-1 ;
  378.             s = str_end ; m++ ; u_flag = U_OFF ;
  379.             goto reswitch ;
  380.  
  381.     case M_ANY + U_OFF + END_OFF :
  382.             if ( s[0] == 0 )  goto refill ;
  383.         if ( !ss )
  384.         if ( cb_ss && s > cb_ss )  goto refill ;
  385.         else ss = s ;
  386.             s++ ; m++ ;
  387.             goto  reswitch ;
  388.  
  389.     case M_ANY + U_OFF + END_ON :
  390.             if ( s[0] == 0 || s[1] != 0 )  goto refill ;
  391.         if ( !ss )
  392.         if ( cb_ss && s > cb_ss )  goto refill ;
  393.         else ss = s ;
  394.             s++ ; m++ ;
  395.             goto reswitch ;
  396.  
  397.     case M_ANY + U_ON + END_OFF :
  398.             if ( s[0] == 0 )  goto refill ;
  399.             s++ ; 
  400.             push(m, s, ss, U_ON) ;
  401.         if ( !ss )
  402.         if ( cb_ss && s-1 > cb_ss )  goto refill ;
  403.         else  ss = s-1 ;
  404.             m++ ; u_flag = U_OFF ;
  405.             goto  reswitch ;
  406.  
  407.     case M_ANY + U_ON + END_ON :
  408.             if ( s[0] == 0 )  goto refill ;
  409.             if ( ! str_end )  str_end = strchr(s,0) ;
  410.         if ( !ss )
  411.         if ( cb_ss && str_end-1 > cb_ss )  goto refill ;
  412.         else  ss = str_end - 1 ;
  413.             s = str_end ; m++ ; u_flag = U_OFF ;
  414.             goto reswitch ;
  415.  
  416.     case  M_START + U_OFF + END_OFF :
  417.     case  M_START + U_ON  + END_OFF :
  418.             if ( s != str )  goto  refill ;
  419.         ss = s ;
  420.             m++ ;  u_flag = U_OFF ;
  421.             goto  reswitch ;
  422.  
  423.     case  M_START + U_OFF + END_ON :
  424.     case  M_START + U_ON  + END_ON :
  425.             if ( s != str || s[0] != 0 )  goto  refill ;
  426.         ss = s ;
  427.             m++ ; u_flag = U_OFF ;
  428.             goto  reswitch ;
  429.  
  430.     case  M_END + U_OFF  :
  431.             if ( s[0]  != 0 )  goto  refill ;
  432.         if ( !ss ) 
  433.         if ( cb_ss && s > cb_ss )  goto refill ;
  434.         else  ss = s ;
  435.             m++ ; goto reswitch ;
  436.  
  437.     case  M_END + U_ON :
  438.         s = str_end ? str_end : (str_end =  strchr(s,0)) ;
  439.         if ( !ss ) 
  440.         if ( cb_ss && s > cb_ss )  goto refill ;
  441.         else  ss = s ;
  442.             m++ ; u_flag = U_OFF ;
  443.             goto reswitch ;
  444.  
  445.     CASE_UANY(M_U) :
  446.         if ( !ss ) 
  447.         if ( cb_ss && s > cb_ss )  goto refill ;
  448.         else  ss = s ;
  449.             u_flag = U_ON ; m++ ;
  450.             goto reswitch ;
  451.  
  452.     CASE_UANY(M_1J) :
  453.             m += m->data.jump ;
  454.             goto reswitch ;
  455.  
  456.     CASE_UANY(M_2JA) : /* take the non jump branch */
  457.             push(m+m->data.jump, s, ss, u_flag) ;
  458.             m++ ;
  459.             goto reswitch ;
  460.  
  461.     CASE_UANY(M_2JB) : /* take the jump branch */
  462.             push(m+1, s, ss, u_flag) ;
  463.             m += m->data.jump ;
  464.             goto reswitch ;
  465.  
  466.     case M_ACCEPT + U_OFF :
  467.         if ( !ss )  ss = s ;
  468.         if ( !cb_ss || ss < cb_ss || ss == cb_ss && s > cb_e )
  469.         { /* we have a new current best */
  470.           cb_ss = ss ; cb_e = s ;
  471.         }
  472.         goto  refill ;
  473.  
  474.     case  M_ACCEPT + U_ON :
  475.         if ( !ss )  ss = s ;
  476.         else
  477.         s = str_end ? str_end : (str_end = strchr(s,0)) ;
  478.  
  479.         if ( !cb_ss || ss < cb_ss || ss == cb_ss && s > cb_e )
  480.         { /* we have a new current best */
  481.           cb_ss = ss ; cb_e = s ;
  482.         }
  483.         goto  refill ;
  484.  
  485.     default :
  486.             RE_panic("unexpected case in REmatch") ;
  487.   }
  488. }
  489.  
  490. @//E*O*F mawk0.97/rexp/rexp3.c//
  491. chmod u=rw,g=r,o=r mawk0.97/rexp/rexp3.c
  492.  
  493. echo x - mawk0.97/rexp/rexpdb.c
  494. sed 's/^@//' > "mawk0.97/rexp/rexpdb.c" <<'@//E*O*F mawk0.97/rexp/rexpdb.c//'
  495.  
  496. /********************************************
  497. rexpdb.c
  498. copyright 1991, Michael D. Brennan
  499.  
  500. This is a source file for mawk an implementation of
  501. the Awk programming language as defined in
  502. Aho, Kernighan and Weinberger, The AWK Programming Language,
  503. Addison-Wesley, 1988.
  504.  
  505. See the accompaning file, LIMITATIONS, for restrictions
  506. regarding modification and redistribution of this
  507. program in source or binary form.
  508. ********************************************/
  509.  
  510.  
  511. /* rexpdb.c */
  512.  
  513.  
  514. #include "rexp.h"
  515. #include <ctype.h>
  516.  
  517. /*  print a machine for debugging  */
  518.  
  519. static  char *xlat[] = {
  520. "M_STR"  ,
  521. "M_CLASS" ,
  522. "M_ANY" ,
  523. "M_START" ,
  524. "M_END" ,
  525. "M_U",
  526. "M_1J" ,
  527. "M_2JA" ,
  528. "M_2JB" ,
  529. "M_ACCEPT" } ;
  530.  
  531. void  REmprint(m, f)
  532.   VOID *m ; FILE *f ;
  533. { register STATE *p = (STATE *) m ;
  534.   char *end_on_string ;
  535.  
  536.   while ( 1 )
  537.   { 
  538.     if ( p->type >= END_ON ) 
  539.     { p->type -= END_ON ; end_on_string = "$" ; }
  540.     else end_on_string = "" ;
  541.  
  542.     if ( p->type < 0 || p->type >= END_ON )
  543.     { fprintf(f, "unknown STATE type\n") ; return ; }
  544.  
  545.     fprintf(f, "%-10s" , xlat[p->type]) ;
  546.     switch( p->type )
  547.     {
  548.      case M_STR : fprintf(f, "%s", p->data.str ) ;
  549.                   break ;
  550.  
  551.      case M_1J:
  552.      case M_2JA:  
  553.      case M_2JB : fprintf(f, "%d", p->data.jump) ;
  554.                  break ;
  555.      case M_CLASS:
  556.           { unsigned char *q = (unsigned char *) p->data.bvp ;
  557.             unsigned char *r = q +  sizeof(BV) ;
  558.             while ( q < r )  fprintf(f, "%x " , *q++) ;
  559.           }
  560.           break ;
  561.     }
  562.     fprintf(f, "%s\n" , end_on_string) ;
  563.     if ( end_on_string[0] )  p->type += END_ON ;
  564.     if ( p->type == M_ACCEPT )  return ;
  565.     p++ ;
  566.    }
  567. }
  568.  
  569. @//E*O*F mawk0.97/rexp/rexpdb.c//
  570. chmod u=rw,g=r,o=r mawk0.97/rexp/rexpdb.c
  571.  
  572. echo mkdir - mawk0.97/test
  573. mkdir mawk0.97/test
  574. chmod u=rwx,g=rx,o=rx mawk0.97/test
  575.  
  576. echo x - mawk0.97/test/README
  577. sed 's/^@//' > "mawk0.97/test/README" <<'@//E*O*F mawk0.97/test/README//'
  578.  
  579. Some benchmarks of Mawk and other (new) awks are in the file
  580. benchmarks.
  581.  
  582. Most of the programs are one liners, but a few are interesting
  583. and duplicated in examples directory.
  584.  
  585. To run these tests or others yourself, use the
  586. shell script test.sh
  587.  
  588. ----------------------------------------------------
  589.  
  590. One area mawk needs to improve is array[expr] access when
  591. expr is numeric (see primes and qsort).
  592. Mawk always converts numeric expressions to string for
  593. array access which leads to a lot of redundant conversions.
  594. Better array access will be added for release 1.0.
  595.  
  596. -------------------------------------------
  597.  
  598. run wfrq0.awk or words0.awk to see how much RS as a 
  599. regular expression can speed up some programs
  600.  
  601. @//E*O*F mawk0.97/test/README//
  602. chmod u=r,g=r,o=r mawk0.97/test/README
  603.  
  604. echo x - mawk0.97/test/benchmarks
  605. sed 's/^@//' > "mawk0.97/test/benchmarks" <<'@//E*O*F mawk0.97/test/benchmarks//'
  606. The following are some timing tests of Mawk versus three
  607. other (new) awks.  Times are user + sys in seconds. First
  608. col is mawk time, second col is other awk time and last
  609. col is the ratio.
  610.  
  611.  
  612. Mawk vs.  Awk  on Stardent 3000, SysV 3.0
  613.     cat           4.0    4.8   1.20
  614.     wc            8.1    6.1   0.75
  615.     fields       20.8   26.3   1.26
  616.     reg0          4.7    6.0   1.28
  617.     reg1          5.6    6.0   1.07
  618.     reg2         18.1    6.0   0.33
  619.     loops         6.0   12.6   2.10
  620.     words        18.1   18.4   1.02
  621.     newton *      0.9    1.7   1.89
  622.     concat       14.1   15.0   1.06
  623.     primes *      2.6    3.1   1.19
  624.     squeeze       5.3    2.9   0.55
  625.     qsort         6.8   21.3   3.13
  626.     wfrq          8.9   10.0   1.12
  627.     deps **       3.1    5.2   1.68
  628.                    1.15 #
  629.  
  630. Mawk vs.  Gawk 2.11.1  on Sun3, SunOS 4.0
  631.     cat           6.1    8.1   1.33
  632.     wc           12.6   40.6   3.22
  633.     fields       35.7  117.6   3.29
  634.     reg0          6.7   11.0   1.64
  635.     reg1          8.5   12.6   1.48
  636.     reg2         34.3   55.5   1.62
  637.     loops        40.4  214.6   5.31
  638.     words        31.3  110.8   3.54
  639.     newton        6.7   25.4   3.79
  640.     concat       20.9   65.7   3.14
  641.     primes       38.8   28.3   0.73
  642.     squeeze       2.2    4.6   2.09
  643.     qsort        36.1   42.3   1.17
  644.     wfrq         66.5  199.4   3.00
  645.     deps         16.2   42.9   2.65
  646.                    2.24 #
  647.  
  648. Mawk vs.  Nawk  on  VAX  3600  Ultrix 4.1
  649.     cat           5.7    7.7   1.35
  650.     wc           12.8   12.4   0.97
  651.     fields       34.1   58.9   1.73
  652.     reg0          7.1    8.6   1.21
  653.     reg1          8.9   21.8   2.45
  654.     reg2         36.7   58.4   1.59
  655.     loops        30.5  117.7   3.86
  656.     words        31.0   58.7   1.89
  657.     newton        5.6   11.9   2.12
  658.     concat       21.3   28.9   1.36
  659.     primes       36.3   17.2   0.47
  660.     squeeze       2.2    3.1   1.41
  661.     qsort        39.3   29.5   0.75
  662.     wfrq         76.2  173.9   2.28
  663.     deps         18.1   32.4   1.79
  664.                    1.50 #
  665.  
  666. * newton , primes and loops take no input. 
  667. Newton computed the square roots of 1 to 1000 by Newtons method 
  668. and primes was a sieve for primes < 5000.  Loops was three nested
  669. loops 100 x 50 x 50 with a sum on the inside.
  670.  
  671. ** deps input was *.c on mawk source
  672.  
  673. The other programs read a file of 20000+ C source lines.
  674. The input files were blownup by 4 (80000+) on the Stardent.
  675.  
  676. # geometric mean of col 3 --  (a1 * a2 * ... an ) ^ (1/n) .
  677.  
  678. @//E*O*F mawk0.97/test/benchmarks//
  679. chmod u=r,g=r,o=r mawk0.97/test/benchmarks
  680.  
  681. echo x - mawk0.97/test/cat.awk
  682. sed 's/^@//' > "mawk0.97/test/cat.awk" <<'@//E*O*F mawk0.97/test/cat.awk//'
  683. { print } 
  684. @//E*O*F mawk0.97/test/cat.awk//
  685. chmod u=r,g=r,o=r mawk0.97/test/cat.awk
  686.  
  687. echo x - mawk0.97/test/concat.awk
  688. sed 's/^@//' > "mawk0.97/test/concat.awk" <<'@//E*O*F mawk0.97/test/concat.awk//'
  689.  
  690.  
  691. # test concatenation
  692. #
  693.  
  694. { print $NF  $( (NF+1)/2 )  $1 }
  695. @//E*O*F mawk0.97/test/concat.awk//
  696. chmod u=r,g=r,o=r mawk0.97/test/concat.awk
  697.  
  698. echo x - mawk0.97/test/fields.awk
  699. sed 's/^@//' > "mawk0.97/test/fields.awk" <<'@//E*O*F mawk0.97/test/fields.awk//'
  700.  
  701. # print each field
  702. # one per line
  703. #
  704.  
  705. { for(i=1;i<=NF;i++) print $i}
  706. @//E*O*F mawk0.97/test/fields.awk//
  707. chmod u=r,g=r,o=r mawk0.97/test/fields.awk
  708.  
  709. echo x - mawk0.97/test/loops.awk
  710. sed 's/^@//' > "mawk0.97/test/loops.awk" <<'@//E*O*F mawk0.97/test/loops.awk//'
  711.  
  712. # test looping speed
  713. #
  714.  
  715. BEGIN {
  716.  
  717. for(i=1; i<=100 ; i++)
  718.   j = i ;
  719.   while ( j >= 0 ) 
  720.   {
  721.     k = 0 
  722.     do  
  723.     { sum += k + j + i
  724.       k++
  725.     }
  726.     while ( k <= j )
  727.     j--
  728.   }
  729. }
  730.  
  731. print sum
  732. }
  733. @//E*O*F mawk0.97/test/loops.awk//
  734. chmod u=r,g=r,o=r mawk0.97/test/loops.awk
  735.  
  736. echo x - mawk0.97/test/newton.awk
  737. sed 's/^@//' > "mawk0.97/test/newton.awk" <<'@//E*O*F mawk0.97/test/newton.awk//'
  738.  
  739.  
  740. # compute square root by newton's method
  741. #
  742. function SQRT(x)
  743. { new = x/2
  744.   do  
  745.   { old = new
  746.     new = (old*old+x)/(2*old)
  747.   }
  748.   while ( abs(new-old) > 1e-6 )
  749.  
  750.   return  (new+old)/2
  751. }
  752.  
  753. function abs(x)
  754. { return x>=0?x:-x }
  755.  
  756.   
  757. BEGIN {
  758.   for(i = 1 ; i <= 1000 ; i++) print i, SQRT(i)
  759. }
  760. @//E*O*F mawk0.97/test/newton.awk//
  761. chmod u=r,g=r,o=r mawk0.97/test/newton.awk
  762.  
  763. echo x - mawk0.97/test/primes.awk
  764. sed 's/^@//' > "mawk0.97/test/primes.awk" <<'@//E*O*F mawk0.97/test/primes.awk//'
  765.  
  766. # find all primes 
  767. #  <= ARGV[1]
  768. #
  769. BEGIN {  stop = ARGV[1]
  770.    prime[ p_cnt = 1 ] =  3
  771.  
  772. # keep track of integer part of square root by adding
  773. # odd integers 
  774.    odd = test = 5
  775.    root = 2
  776.    squares = 9
  777.  
  778.    
  779. while ( test <= stop )
  780. {
  781.    if ( test >= squares )
  782.    { root++
  783.      odd += 2
  784.      squares += odd 
  785.    }
  786.  
  787.    flag = 1
  788.    for ( i = 1 ; prime[i] <= root ; i++ )
  789.        if ( test % prime[i] == 0 )  #  not prime
  790.     { flag = 0 ; break }
  791.  
  792.    if ( flag )  prime[ ++p_cnt ] = test
  793.  
  794.    test += 2
  795. }
  796.  
  797. prime[0] = 2
  798.  
  799. for(i = 0 ; i <= p_cnt ; i++ )  print prime[i]
  800.  
  801. }
  802.  
  803.  
  804.      
  805. @//E*O*F mawk0.97/test/primes.awk//
  806. chmod u=r,g=r,o=r mawk0.97/test/primes.awk
  807.  
  808. echo x - mawk0.97/test/qsort.awk
  809. sed 's/^@//' > "mawk0.97/test/qsort.awk" <<'@//E*O*F mawk0.97/test/qsort.awk//'
  810.  
  811.  
  812. # qsort text files
  813. #
  814.  
  815. function middle(x,y,z)  #return middle of 3
  816. {
  817.   if ( x <= y )  
  818.   { if ( z >= y )  return y
  819.     if ( z <  x )  return x
  820.     return z
  821.   }
  822.  
  823.   if ( z >= x )  return x
  824.   if ( z <  y )  return y
  825.   return z
  826. }
  827.  
  828.  
  829. function  isort(A , n,    i, j, hold)
  830. {
  831.   # if needed a sentinal at A[0] will be created
  832.  
  833.   for( i = 2 ; i <= n ; i++)
  834.   {
  835.     hold = A[ j = i ]
  836.     while ( A[j-1] > hold )
  837.     { j-- ; A[j+1] = A[j] }
  838.  
  839.     A[j] = hold
  840.   }
  841. }
  842.  
  843.  
  844. # recursive quicksort
  845. function  qsort(A, left, right    ,i , j, pivot, hold)
  846. {
  847.   
  848.   pivot = middle(A[left], A[int((left+right)/2)], A[right])
  849.  
  850.   i = left
  851.   j = right
  852.  
  853.   while ( i <= j )
  854.   {
  855.     while ( A[i] < pivot )  i++ 
  856.     while ( A[j] > pivot )  j--
  857.  
  858.     if ( i <= j )
  859.     { hold = A[i]
  860.       A[i++] = A[j]
  861.       A[j--] = hold
  862.     }
  863.   }
  864.  
  865.   if ( j - left > BLOCK )  qsort(A,left,j)
  866.   if ( right - i > BLOCK )  qsort(A,i,right)
  867. }
  868.  
  869. BEGIN { BLOCK = 5 }
  870.  
  871.  
  872. { line[NR] = $0 ""   # sort as string
  873. }
  874.  
  875. END  {
  876.  
  877.   if ( NR > BLOCK )  qsort(line, 1, NR)
  878.  
  879.   isort(line, NR)
  880.  
  881.   for(i = 1 ; i <= NR ; i++) print line[i]
  882. }
  883.   
  884.  
  885.  
  886.  
  887.     
  888. @//E*O*F mawk0.97/test/qsort.awk//
  889. chmod u=r,g=r,o=r mawk0.97/test/qsort.awk
  890.  
  891. echo x - mawk0.97/test/reg0.awk
  892. sed 's/^@//' > "mawk0.97/test/reg0.awk" <<'@//E*O*F mawk0.97/test/reg0.awk//'
  893.  
  894. /return/ {cnt++}  END{print cnt}
  895. @//E*O*F mawk0.97/test/reg0.awk//
  896. chmod u=r,g=r,o=r mawk0.97/test/reg0.awk
  897.  
  898. echo x - mawk0.97/test/reg1.awk
  899. sed 's/^@//' > "mawk0.97/test/reg1.awk" <<'@//E*O*F mawk0.97/test/reg1.awk//'
  900.  
  901. /return|switch/ {cnt++}  END{print cnt}
  902. @//E*O*F mawk0.97/test/reg1.awk//
  903. chmod u=r,g=r,o=r mawk0.97/test/reg1.awk
  904.  
  905. echo x - mawk0.97/test/reg2.awk
  906. sed 's/^@//' > "mawk0.97/test/reg2.awk" <<'@//E*O*F mawk0.97/test/reg2.awk//'
  907.  
  908. /[A-Za-z_][A-Za-z0-9_]*\[.*\][ \t]*=/ {cnt++}  END{print cnt}
  909. @//E*O*F mawk0.97/test/reg2.awk//
  910. chmod u=r,g=r,o=r mawk0.97/test/reg2.awk
  911.  
  912. echo x - mawk0.97/test/sample
  913. sed 's/^@//' > "mawk0.97/test/sample" <<'@//E*O*F mawk0.97/test/sample//'
  914. dump  cat.awk  ../TB  mawk gawk awk
  915. out   wc.awk ../TB  mawk gawk awk
  916. dump  fields.awk ../TB mawk gawk awk
  917. out  reg0.awk ../TB mawk gawk awk
  918. out  reg1.awk ../TB mawk gawk awk
  919. out  reg2.awk ../TB mawk gawk awk
  920. out  words0.awk  ../TB  mawk gawk
  921. out  words1.awk  ../TB  mawk
  922. dump newton.awk  /dev/null  mawk  gawk
  923. dump concat.awk  ../TB  mawk gawk awk
  924. dump primes.awk  5000   mawk gawk
  925. dump squeeze.awk  ../parse.y mawk gawk
  926. dump qsort.awk  ../parse.y  mawk  gawk
  927. @//E*O*F mawk0.97/test/sample//
  928. chmod u=r,g=r,o=r mawk0.97/test/sample
  929.  
  930. echo x - mawk0.97/test/squeeze.awk
  931. sed 's/^@//' > "mawk0.97/test/squeeze.awk" <<'@//E*O*F mawk0.97/test/squeeze.awk//'
  932.  
  933. # test gsub
  934. #
  935. # squeeze space to single space
  936.  
  937.  
  938. { gsub( /[ \t]+/, " ") ; print }
  939. @//E*O*F mawk0.97/test/squeeze.awk//
  940. chmod u=r,g=r,o=r mawk0.97/test/squeeze.awk
  941.  
  942. echo x - mawk0.97/test/test.sh
  943. sed 's/^@//' > "mawk0.97/test/test.sh" <<'@//E*O*F mawk0.97/test/test.sh//'
  944. #! /bin/sh
  945.  
  946. ###############
  947. #  shell script for timing mawk and other awks
  948. #
  949. #  reads input file of the form
  950. #  dump_or_not  program_file  input_file  list of awks
  951. #
  952. #  usage:  test.sh < input_file
  953. #
  954.  
  955.  
  956. if [ $# != 0 ]
  957. then
  958.   name=`basename $0`
  959.   echo "usage: $name < input_file"  1>&2
  960.   exit 1
  961. fi
  962.  
  963.  
  964. while  read  direct program file  awk_list
  965. do
  966.  
  967. echo 
  968. echo
  969.  
  970. if [ $direct = dump ]
  971. then
  972. for i in $awk_list
  973. do
  974. echo "$i -f $program $file"
  975. /bin/time $i -f $program $file >/dev/null
  976. done
  977.  
  978. else
  979. for i in $awk_list
  980. do
  981. echo "$i -f $program $file"
  982. /bin/time $i -f $program $file 
  983. done
  984. fi
  985.  
  986. done   2>&1    # send the timing to stdout
  987. @//E*O*F mawk0.97/test/test.sh//
  988. chmod u=rx,g=rx,o=rx mawk0.97/test/test.sh
  989.  
  990. echo x - mawk0.97/test/wc.awk
  991. sed 's/^@//' > "mawk0.97/test/wc.awk" <<'@//E*O*F mawk0.97/test/wc.awk//'
  992.  
  993. {sum += NF}
  994. END{ print NR, sum}
  995. @//E*O*F mawk0.97/test/wc.awk//
  996. chmod u=r,g=r,o=r mawk0.97/test/wc.awk
  997.  
  998. echo x - mawk0.97/test/wfrq.awk
  999. sed 's/^@//' > "mawk0.97/test/wfrq.awk" <<'@//E*O*F mawk0.97/test/wfrq.awk//'
  1000.  
  1001.  
  1002. # wfrq.awk 
  1003. # find the twenty most frequent words in a document
  1004. # counts words in   array   cnt[ word ]
  1005. #
  1006. # uses a heap to select the twenty most frequent
  1007. #
  1008. #
  1009.  
  1010.  
  1011. BEGIN { FS = "[^a-zA-Z]+" ;  BIG = 999999 }
  1012.  
  1013. { for( i = 1 ; i <= NF ; i++ )  cnt[$i]++ }
  1014.  
  1015. END { delete  cnt[ "" ]
  1016.  
  1017. # load twenty values
  1018. # into the heap   word[1..20] and count[1..20]
  1019. #
  1020. #   heap condition --
  1021. #   count[i] <= count[2*i] and count[i] <= count[2*i+1]
  1022.  
  1023. j = 1
  1024.  
  1025. # remove twenty values from cnt[] , put in the heap
  1026.  
  1027. for( i in cnt )
  1028. {
  1029.   word[j] = i  ; count[j] = cnt[i] 
  1030.   delete cnt[i] ;
  1031.   if ( ++j == 21 )  break ;
  1032. }
  1033.  
  1034. # make some sentinals
  1035. # to stop down_heap()
  1036. #
  1037.  
  1038. for( i = j ; i < 43 ; i++ )  count[i] = BIG
  1039.  
  1040. h_empty = j  # save the first empty slot
  1041. # make a heap with the smallest in slot 1
  1042. for( i = h_empty - 1 ; i > 0 ; i-- )  down_heap(i) 
  1043.  
  1044. # examine the rest of the values
  1045. for ( i in cnt )
  1046.   if ( (j = cnt[i]) > count[1] )
  1047.   { # its bigger
  1048.     # take the smallest out of the heap and readjust
  1049.     word[1] = i ; count[1] = j
  1050.     down_heap(1)
  1051.   }
  1052.  
  1053. h_empty-- ;
  1054.  
  1055. # what's left are the twenty largest
  1056. # smallest at the top
  1057. #
  1058.  
  1059. i = 20
  1060. while ( h_empty > 1 )
  1061. {
  1062.   buffer[i--] = sprintf ("%3d %s"  , count[1], word[1])
  1063.   count[1] = count[h_empty] ; word[1] = word[h_empty]
  1064.   count[h_empty] = BIG
  1065.   down_heap(1)
  1066.   h_empty--
  1067. }
  1068.   buffer[i--] = sprintf ("%3d %s"  , count[1], word[1])
  1069.  
  1070.   for(j = 1 ; j <= 20 ; j++ )  print buffer[j]
  1071. }
  1072.  
  1073. # let the i th element drop to its correct position
  1074.  
  1075. function down_heap(i,       k) 
  1076. {
  1077.   while ( 1 )
  1078.   {
  1079.       if ( count[2*i] <= count[2*i+1] )  k = 2*i
  1080.       else  k = 2*i + 1 
  1081.  
  1082.       if ( count[i] <= count[k] )  return
  1083.  
  1084.       hold = word[k] ; word[k] = word[i] ; word[i] = hold
  1085.       hold = count[k] ; count[k] = count[i] ; count[i] = hold
  1086.       i = k
  1087.    }
  1088. }
  1089.  
  1090. @//E*O*F mawk0.97/test/wfrq.awk//
  1091. chmod u=r,g=r,o=r mawk0.97/test/wfrq.awk
  1092.  
  1093. echo x - mawk0.97/test/wfrq0.awk
  1094. sed 's/^@//' > "mawk0.97/test/wfrq0.awk" <<'@//E*O*F mawk0.97/test/wfrq0.awk//'
  1095.  
  1096. #  this program is the same as wfrq.awk except it runs
  1097. #  about twice as fast because it uses RS as a regular 
  1098. #  expression
  1099. #
  1100.  
  1101. function down_heap(i,  k) 
  1102. {
  1103.   while ( 1 )
  1104.   {
  1105.       if ( count[2*i] <= count[2*i+1] )  k = 2*i
  1106.       else  k = 2*i + 1 
  1107.  
  1108.       if ( count[i] <= count[k] )  return
  1109.  
  1110.       hold = word[k] ; word[k] = word[i] ; word[i] = hold
  1111.       hold = count[k] ; count[k] = count[i] ; count[i] = hold
  1112.       i = k
  1113.    }
  1114. }
  1115.  
  1116.  
  1117. BEGIN { RS = "[^a-zA-Z]+" ;  BIG = 999999 }
  1118.  
  1119. { cnt[$0]++ }
  1120.  
  1121. END { delete  cnt[ "" ]
  1122.  
  1123. # load twenty values
  1124. j = 1
  1125. for( i in cnt )
  1126. {
  1127.   word[j] = i  ; count[j] = cnt[i] 
  1128.   delete cnt[i] ;
  1129.   if ( ++j == 21 )  break ;
  1130. }
  1131.  
  1132. # make some sentinals
  1133. for( i = j ; i < 43 ; i++ )  count[i] = BIG
  1134.  
  1135. h_empty = j  # save the first empty slot
  1136. # make a heap with the smallest in slot 1
  1137. for( i = h_empty - 1 ; i > 0 ; i-- )  down_heap(i) 
  1138.  
  1139. # examine the rest of the values
  1140. for ( i in cnt )
  1141.   if ( (j = cnt[i]) > count[1] )
  1142.   { # its bigger
  1143.     # take the smallest out of the heap and readjust
  1144.     word[1] = i ; count[1] = j
  1145.     down_heap(1)
  1146.   }
  1147.  
  1148. h_empty-- ;
  1149.  
  1150. # what's left are the twenty largest
  1151. # smallest at the top
  1152. #
  1153.  
  1154. i = 20
  1155. while ( h_empty > 1 )
  1156. {
  1157.   buffer[i--] = sprintf ("%3d %s"  , count[1], word[1])
  1158.   count[1] = count[h_empty] ; word[1] = word[h_empty]
  1159.   count[h_empty] = BIG
  1160.   down_heap(1)
  1161.   h_empty--
  1162. }
  1163.   buffer[i--] = sprintf ("%3d %s"  , count[1], word[1])
  1164.  
  1165.   for(j = 1 ; j <= 20 ; j++ )  print buffer[j]
  1166. }
  1167. @//E*O*F mawk0.97/test/wfrq0.awk//
  1168. chmod u=r,g=r,o=r mawk0.97/test/wfrq0.awk
  1169.  
  1170. echo x - mawk0.97/test/words.awk
  1171. sed 's/^@//' > "mawk0.97/test/words.awk" <<'@//E*O*F mawk0.97/test/words.awk//'
  1172.  
  1173. # words0.awk
  1174.  
  1175. # find real words
  1176. # i.e contigous letters
  1177.  
  1178. BEGIN { FS = "[^A-Za-z]+" } # split fields on not letters
  1179.  
  1180. {
  1181. # $1 and $NF  might be  empty
  1182.  
  1183.   if ( NF > 0 )
  1184.   {
  1185.     cnt += NF
  1186.  
  1187.     if ( $NF == "" )  cnt--
  1188.     if ( NF > 1 && $1 == "" ) cnt--
  1189.   }
  1190. }
  1191.  
  1192. END { print cnt}
  1193.  
  1194.  
  1195. @//E*O*F mawk0.97/test/words.awk//
  1196. chmod u=r,g=r,o=r mawk0.97/test/words.awk
  1197.  
  1198. echo x - mawk0.97/test/words0.awk
  1199. sed 's/^@//' > "mawk0.97/test/words0.awk" <<'@//E*O*F mawk0.97/test/words0.awk//'
  1200.  
  1201.  
  1202. # use non letters as RS
  1203. #
  1204. #
  1205.  
  1206. BEGIN { RS = "[^A-Za-z][^A-Za-z]*" 
  1207.     getline
  1208.     if ( $0 == "" )  NR = 0
  1209. }
  1210.  
  1211. END { print NR }
  1212. @//E*O*F mawk0.97/test/words0.awk//
  1213. chmod u=r,g=r,o=r mawk0.97/test/words0.awk
  1214.  
  1215. echo mkdir - mawk0.97/examples
  1216. mkdir mawk0.97/examples
  1217. chmod u=rwx,g=rx,o=rx mawk0.97/examples
  1218.  
  1219. echo x - mawk0.97/examples/decl.awk
  1220. sed 's/^@//' > "mawk0.97/examples/decl.awk" <<'@//E*O*F mawk0.97/examples/decl.awk//'
  1221.  
  1222. # parse a C declaration by recursive descent
  1223. # based on a C program in KR ANSI edition
  1224. #
  1225. # run on a C file it finds the declarations
  1226. #
  1227. # restrictions: one declaration per line
  1228. #               doesn't understand struct {...}
  1229. #               makes assumptions about type names
  1230. #
  1231. #
  1232. #  some awks need double escapes on strings used as
  1233. #  regular expressions.  If not run on mawk, use gdecl.awk
  1234.  
  1235.  
  1236. ################################################
  1237. #   lexical scanner -- gobble()
  1238. #   input : string s -- treated as a regular expression
  1239. #   gobble eats SPACE, then eats longest match of s off front
  1240. #   of global variable line.
  1241. #   Cuts the matched part off of line
  1242. #
  1243.  
  1244.  
  1245. function gobble(s,  x)  
  1246. {
  1247.   sub( /^ /, "", line)  # eat SPACE if any
  1248.  
  1249.   # surround s with parenthesis to make sure ^ acts on the
  1250.   # whole thing
  1251.  
  1252.   match(line, "^" "(" s ")")
  1253.   x = substr(line, 1, RLENGTH)
  1254.   line = substr(line, RLENGTH+1)
  1255.   return x 
  1256. }
  1257.  
  1258.  
  1259. function ptr_to(n,  x)  # print "pointer to" , n times
  1260. { n = int(n)
  1261.   if ( n <= 0 )  return ""
  1262.   x = "pointer to" ; n--
  1263.   while ( n-- )  x = x " pointer to"
  1264.   return x
  1265. }
  1266.  
  1267.  
  1268. #recursively get a decl
  1269. # returns an english description of the declaration or
  1270. # "" if not a C declaration.
  1271.  
  1272. function  decl(   x, t, ptr_part)
  1273. {
  1274.  
  1275.   x = gobble("[* ]+")   # get list of *** ...
  1276.   gsub(/ /, "", x)   # remove all SPACES
  1277.   ptr_part = ptr_to( length(x) )
  1278.  
  1279.   # We expect to see either an identifier or '('
  1280.   #
  1281.  
  1282.   if ( gobble("\(") )
  1283.   { 
  1284.     # this is the recursive descent part
  1285.     # we expect to match a declaration and closing ')'
  1286.     # If not return "" to indicate  failure
  1287.  
  1288.       if ( (x = decl()) == "" || gobble( "\)" ) == "" ) return ""
  1289.  
  1290.   }
  1291.   else  #  expecting an identifier
  1292.   {
  1293.     if ( (x = gobble(id)) == "" )  return ""
  1294.     x = x ":"
  1295.   }
  1296.  
  1297.   # finally look for ()
  1298.   # or  [ opt_size ]
  1299.  
  1300.   while ( 1 )
  1301.      if ( gobble( funct_mark ) )  x = x " function returning"
  1302.      else
  1303.      if ( t = gobble( array_mark ) )
  1304.      { gsub(/ /, "", t)
  1305.        x = x " array" t " of"
  1306.      }
  1307.      else  break
  1308.  
  1309.  
  1310.    x = x " "  ptr_part
  1311.    return x
  1312. }
  1313.     
  1314.  
  1315. BEGIN { id = "[_A-Za-z][_A-Za-z0-9]*" 
  1316.         funct_mark = "\([ \t]*\)"
  1317.     array_mark = "\[[ \t]*[_A-Za-z0-9]*[ \t]*\]"
  1318.  
  1319. # I've assumed types are keywords or all CAPS or end in _t
  1320. # Other conventions could be added.
  1321.  
  1322.     type0 = "int|char|short|long|double|float|void" 
  1323.     type1 = "[_A-Z][_A-Z0-9]*"  #  types are CAPS
  1324.     type2 = "[_A-Za-z][_A-Za-z0-9]*_t"  # end in _t
  1325.  
  1326.     types = "(" type0 "|" type1 "|" type2 ")"
  1327. }
  1328.  
  1329.  
  1330. {   
  1331.  
  1332.     gsub( "/\*([^*]|\*[^/])*(\*/|$)" , " ") # remove comments
  1333.     gsub( /[ \t]+/, " ")  # squeeze white space to a single space
  1334.  
  1335.  
  1336.     line = $0
  1337.  
  1338.     scope = gobble( "extern|static" )
  1339.  
  1340.     if ( type = gobble("(struct|union|enum) ") )
  1341.             type = type gobble(id)  #  get the tag
  1342.     else
  1343.     {
  1344.  
  1345.        type = gobble("(un)?signed ") gobble( types )
  1346.  
  1347.     }
  1348.     
  1349.     if ( ! type )  next
  1350.     
  1351.     if ( (x = decl()) && gobble( ";") )
  1352.     {
  1353.       x  =  x " " type
  1354.       if ( scope )  x = x " (" scope ")"
  1355.       gsub( /  +/, " ", x)  # 
  1356.       print x
  1357.     }
  1358.  
  1359. }
  1360.  
  1361.  
  1362.  
  1363.  
  1364. @//E*O*F mawk0.97/examples/decl.awk//
  1365. chmod u=rx,g=rx,o=rx mawk0.97/examples/decl.awk
  1366.  
  1367. echo x - mawk0.97/examples/deps.awk
  1368. sed 's/^@//' > "mawk0.97/examples/deps.awk" <<'@//E*O*F mawk0.97/examples/deps.awk//'
  1369.  
  1370. # find include dependencies in C source
  1371. #
  1372. # mawk -f deps.awk  C_source_files
  1373. #         -- prints a dependency list suitable for make
  1374. #         -- ignores   #include <   >
  1375. #
  1376.  
  1377.  
  1378. BEGIN {  stack_index = 0 # stack[] holds the input files
  1379.  
  1380.   for(i = 1 ; i < ARGC ; i++)
  1381.   { 
  1382.     file = ARGV[i]
  1383.     if ( file !~ /\.c$/ )  continue  # skip it
  1384.     outfile = substr(file, 1, length(file)-2) ".o"
  1385.  
  1386.     # INCLUDED[] stores the set of included files
  1387.     # -- start with the empty set
  1388.     for( j in INCLUDED ) delete INCLUDED[j]
  1389.  
  1390.     while ( 1 )
  1391.     {
  1392.         if ( getline line < file <= 0 )  # no open or EOF
  1393.     { close(file)
  1394.       if ( stack_index == 0 )  break # empty stack
  1395.       else  
  1396.       { file = stack[ stack_index-- ]
  1397.         continue
  1398.       }
  1399.         }
  1400.  
  1401.     if ( line ~ /^#include[ \t]+".*"/ )
  1402.     {
  1403.       split(line, X, "\"")  # filename is in X[2]
  1404.  
  1405.       if ( X[2] in INCLUDED ) # we've already included it
  1406.         continue
  1407.  
  1408.       #push current file 
  1409.       stack[ ++stack_index ] = file
  1410.       INCLUDED[ file = X[2] ] = ""
  1411.         }
  1412.     }  # end of while
  1413.     
  1414.    # test if INCLUDED is empty
  1415.    flag = 0 # on once the front is printed 
  1416.    for( j in INCLUDED )
  1417.       if ( ! flag )  
  1418.       { printf "%s : %s" , outfile, j ; flag = 1 }
  1419.       else  printf " %s" , j
  1420.  
  1421.    if ( flag )  print ""
  1422.  
  1423.   }# end of loop over files in ARGV[i]
  1424.  
  1425. }
  1426. @//E*O*F mawk0.97/examples/deps.awk//
  1427. chmod u=rx,g=rx,o=rx mawk0.97/examples/deps.awk
  1428.  
  1429. echo x - mawk0.97/examples/gdecl.awk
  1430. sed 's/^@//' > "mawk0.97/examples/gdecl.awk" <<'@//E*O*F mawk0.97/examples/gdecl.awk//'
  1431.  
  1432. # parse a C declaration by recursive descent
  1433. #  decl.awk with extra escapes \
  1434.  
  1435. ################################################
  1436. ############################################
  1437.  
  1438.  
  1439. #   lexical scanner -- gobble()
  1440. #   input : string s -- treated as a regular expression
  1441. #   gobble eats SPACE, then eats longest match of s off front
  1442. #   of global variable line.
  1443. #   Cuts the matched part off of line
  1444. #
  1445.  
  1446.  
  1447. function gobble(s,  x)  
  1448. {
  1449.   sub( /^ /, "", line)  # eat SPACE if any
  1450.  
  1451.   # surround s with parenthesis to make sure ^ acts on the
  1452.   # whole thing
  1453.  
  1454.   match(line, "^" "(" s ")")
  1455.   x = substr(line, 1, RLENGTH)
  1456.   line = substr(line, RLENGTH+1)
  1457.   return x 
  1458. }
  1459.  
  1460.  
  1461. function ptr_to(n,  x)  # print "pointer to" , n times
  1462. { n = int(n)
  1463.   if ( n <= 0 )  return ""
  1464.   x = "pointer to" ; n--
  1465.   while ( n-- )  x = x " pointer to"
  1466.   return x
  1467. }
  1468.  
  1469.  
  1470. #recursively get a decl
  1471. # returns an english description of the declaration or
  1472. # "" if not a C declaration.
  1473.  
  1474. function  decl(   x, t, ptr_part)
  1475. {
  1476.  
  1477.   x = gobble("[* ]+")   # get list of *** ...
  1478.   gsub(/ /, "", x)   # remove all SPACES
  1479.   ptr_part = ptr_to( length(x) )
  1480.  
  1481.   # We expect to see either an identifier or '('
  1482.   #
  1483.  
  1484.   if ( gobble("\\(") )
  1485.   { 
  1486.     # this is the recursive descent part
  1487.     # we expect to match a declaration and closing ')'
  1488.     # If not return "" to indicate  failure
  1489.  
  1490.       if ( (x = decl()) == "" || gobble( "\\)" ) == "" ) return ""
  1491.  
  1492.   }
  1493.   else  #  expecting an identifier
  1494.   {
  1495.     if ( (x = gobble(id)) == "" )  return ""
  1496.     x = x ":"
  1497.   }
  1498.  
  1499.   # finally look for ()
  1500.   # or  [ opt_size ]
  1501.  
  1502.   while ( 1 )
  1503.      if ( gobble( funct_mark ) )  x = x " function returning"
  1504.      else
  1505.      if ( t = gobble( array_mark ) )
  1506.      { gsub(/ /, "", t)
  1507.        x = x " array" t " of"
  1508.      }
  1509.      else  break
  1510.  
  1511.  
  1512.    x = x " "  ptr_part
  1513.    return x
  1514. }
  1515.     
  1516.  
  1517. BEGIN { id = "[_A-Za-z][_A-Za-z0-9]*" 
  1518.         funct_mark = "\\([ \t]*\\)"
  1519.     array_mark = "\\[[ \t]*[_A-Za-z0-9]*[ \t]*\\]"
  1520.  
  1521. # I've assumed types are keywords or all CAPS or end in _t
  1522. # Other conventions could be added.
  1523.  
  1524.     type0 = "int|char|short|long|double|float|void" 
  1525.     type1 = "[_A-Z][_A-Z0-9]*"  #  types are CAPS
  1526.     type2 = "[_A-Za-z][_A-Za-z0-9]*_t"  # end in _t
  1527.  
  1528.     types = "(" type0 "|" type1 "|" type2 ")"
  1529. }
  1530.  
  1531.  
  1532. {   
  1533.  
  1534.     gsub( /\/\*([^*]|\*[^\/])*(\*\/|$)/ , " ") # remove comments
  1535.     gsub( /[ \t]+/, " ")  # squeeze white space to a single space
  1536.  
  1537.  
  1538.     line = $0
  1539.  
  1540.     scope = gobble( "extern|static" )
  1541.  
  1542.     if ( type = gobble("(struct|union|enum) ") )
  1543.             type = type gobble(id)  #  get the tag
  1544.     else
  1545.     {
  1546.  
  1547.        type = gobble("(un)?signed ") gobble( types )
  1548.  
  1549.     }
  1550.     
  1551.     if ( ! type )  next
  1552.     
  1553.     if ( (x = decl()) && gobble( ";") )
  1554.     {
  1555.       x  =  x " " type
  1556.       if ( scope )  x = x " (" scope ")"
  1557.       gsub( /  +/, " ", x)  # 
  1558.       print x
  1559.     }
  1560.  
  1561. }
  1562.  
  1563.  
  1564.  
  1565.  
  1566. @//E*O*F mawk0.97/examples/gdecl.awk//
  1567. chmod u=rx,g=rx,o=rx mawk0.97/examples/gdecl.awk
  1568.  
  1569. echo x - mawk0.97/examples/nocomment.awk
  1570. sed 's/^@//' > "mawk0.97/examples/nocomment.awk" <<'@//E*O*F mawk0.97/examples/nocomment.awk//'
  1571.  
  1572. # remove C comments
  1573. #
  1574.  
  1575. BEGIN {
  1576.  RS = "/\*([^*]|\*[^/])*\*/"
  1577.  ORS = " "
  1578.  getline hold
  1579. }
  1580.  
  1581. { # hold one record because we don't want ORS on the last
  1582.   # record
  1583.  
  1584.   print hold
  1585.   hold = $0
  1586. }
  1587.  
  1588. END { printf "%s", hold }
  1589. @//E*O*F mawk0.97/examples/nocomment.awk//
  1590. chmod u=r,g=r,o=r mawk0.97/examples/nocomment.awk
  1591.  
  1592. echo mkdir - mawk0.97/msdos
  1593. mkdir mawk0.97/msdos
  1594. chmod u=rwx,g=rx,o=rx mawk0.97/msdos
  1595.  
  1596. echo x - mawk0.97/msdos/INSTALL
  1597. sed 's/^@//' > "mawk0.97/msdos/INSTALL" <<'@//E*O*F mawk0.97/msdos/INSTALL//'
  1598.  
  1599. how to make mawk under MsDOS
  1600. ---------------------------
  1601.  
  1602. Read the DOS section in the manual first.
  1603.  
  1604. In addition to a C compiler, you will need an
  1605. assembler and a yacc compatable parser generator.
  1606.  
  1607. Assuming you keep the same directory structure:
  1608.  
  1609. 1)  run  mklib.bat in this directory to create msdos.lib
  1610.  
  1611. 2)  move the makefile and mawk.dep  to ..
  1612.     ( The supplied dos makefile is for Borland's make.  I used to
  1613.       make mawk with MS make -- which make you use is no big deal.)
  1614.  
  1615. 3)  If you want a Unix style command line for mawk, you'll need to
  1616.     write a function called reargv(int *, char ***) which passes
  1617.     mawk the modified argc and argv.  Compile and add to
  1618.     msdos.lib.
  1619.  
  1620.     The supplied reargv.c works with POLYSHELL by Polytron; for a
  1621.     different shell you could use it as an example.
  1622.  
  1623.     If this made sense and all went well, go to machine.h
  1624.     and
  1625.       #define  HAVE_REARGV   1
  1626.  
  1627.     If ! (sense || well ) , don't worry HAVE_REARGV is 0 by
  1628.     default.
  1629.  
  1630. 4)  YACC --
  1631. On the PC I use bison.1.14, it works fine and is easy to find.
  1632. Surely easier to get than mawk.  Unfortunately I cannot distribute
  1633. the generated parse.c file.
  1634.  
  1635.     If you use bison, I suggest #if 0  in parse.c
  1636.     on the part that grows the parser stack.
  1637.     Then you won't need alloca().
  1638.     ( For mawk programs if the parser stack needs to grow, something
  1639.       is fatally wrong.)
  1640.     Also unless you are debugging the grammar, you don't need
  1641.     the tables yyrhs[] or yyprhs[] -- cut them out and save some data
  1642.     space.
  1643.  
  1644. You can make parse.c under unix with bison or another yacc and
  1645. move it to dos.
  1646.  
  1647. 5)  The rand48.asm is hardwired for small model.  I've never made
  1648. a large model mawk, but as far as I can tell I think the only problem
  1649. is in rand48.asm.  The stack machine instructions (INST) assume a
  1650. pointer is a pointer is a pointer, so if you change to far data
  1651. pointers you'll also need to change to far code pointers.
  1652.  
  1653. Rand48 is overkill, you could use another random number generator
  1654. although the one supplied with your compiler is a near 
  1655. certainty to be poor.
  1656.  
  1657. On small model, you have about 40K of free data space which is plenty
  1658. except for programs that hold a medium or larger data file entirely
  1659. in memory.
  1660.  
  1661. ==================================================================
  1662.  
  1663. The reason system() and pipes are missing is I haven't decided
  1664. entirely how to handle the runaway loop problem.  Dos makes
  1665. asynchronous termination of a program difficult, because DOS
  1666. itself might not be able to handle exit().
  1667.  
  1668. Hooking int 0x1a forces me to deal with cleanup and makes ^C
  1669. a pain.  What is the effect of my 0x1a on children? (That's why
  1670. no system() or pipes yet).  What do I have to check after a child
  1671. terminates, children can muck up the state of the parent process.
  1672.  
  1673.  
  1674. I have used mawk as is on DOS for about 6 months, what's missing
  1675. I rarely use  except to emit error messages and I use
  1676. errmsg() for that.  If I stall about fixing this stuff, DOS
  1677. might go away and I'll never have to deal with it.
  1678. @//E*O*F mawk0.97/msdos/INSTALL//
  1679. chmod u=r,g=r,o=r mawk0.97/msdos/INSTALL
  1680.  
  1681. echo x - mawk0.97/msdos/makefile
  1682. sed 's/^@//' > "mawk0.97/msdos/makefile" <<'@//E*O*F mawk0.97/msdos/makefile//'
  1683.  
  1684. #  this is a makefile for mawk 
  1685. #  using Borland's make v3.0
  1686. #  and CFLAGS for TurboC
  1687.  
  1688. @.SWAP
  1689.  
  1690. CFLAGS = -c -ms -f -wnod -wpro -A
  1691. LINKFLAGS = /c/m
  1692.  
  1693. !if $d(DEBUG)
  1694. CFLAGS = $(CFLAGS) -DDEBUG
  1695. LINKFLAGS = $(LINKFLAGS)/v
  1696. !else
  1697. #  optimize
  1698. CFLAGS = $(CFLAGS) -v- -O -DHAVE_REARGV=1
  1699. !endif
  1700.  
  1701.  
  1702. ####################
  1703. #  user tuned macros
  1704. ####################
  1705.  
  1706. # location of your C library
  1707. CLIB=c:\lib
  1708.  
  1709. # if you have a 80x87 coprocessor
  1710. #FLOATLIB=fp87
  1711. # otherwise
  1712. FLOATLIB=emu
  1713.  
  1714. #take this out if you don't need it, i.e.,
  1715. # if you have a reargv()
  1716. WILDARGS=\lib\wildargs.obj  #expand filenames
  1717.  
  1718. #  You'll need a yacc like parser
  1719. YACC = bison -dyv
  1720.  
  1721. ######################  end of tuneable macros
  1722.  
  1723.  
  1724. OBS = parse.obj \
  1725. array.obj \
  1726. bi_funct.obj \
  1727. bi_vars.obj \
  1728. cast.obj \
  1729. code.obj \
  1730. da.obj \
  1731. error.obj \
  1732. execute.obj \
  1733. fcall.obj \
  1734. field.obj \
  1735. files.obj \
  1736. fin.obj \
  1737. hash.obj \
  1738. init.obj \
  1739. jmp.obj \
  1740. kw.obj \
  1741. main.obj \
  1742. matherr.obj \
  1743. memory.obj \
  1744. print.obj \
  1745. re_cmpl.obj \
  1746. scan.obj \
  1747. scancode.obj \
  1748. split.obj \
  1749. zmalloc.obj
  1750.  
  1751. REXP_C = rexp\rexp.c \
  1752. rexp\rexp0.c \
  1753. rexp\rexp1.c \
  1754. rexp\rexp2.c  \
  1755. rexp\rexpdb.c
  1756.  
  1757.  
  1758. LIBS = msdos\msdos.lib \
  1759. rexp\rexp.lib \
  1760. $(CLIB)\$(FLOATLIB) \
  1761. $(CLIB)\maths \
  1762. $(CLIB)\cs
  1763.  
  1764. mawk.exe : $(OBS)  rexp\rexp.lib
  1765.     tlink $(LINKFLAGS) @&&!
  1766.     $(CLIB)\c0s $(WILDARGS) $(OBS)
  1767.     mawk,mawk
  1768.     $(LIBS)
  1769. !
  1770.  
  1771. rexp\rexp.lib : $(REXP_C)
  1772.     cd rexp
  1773.     del *.obj
  1774.     make
  1775.  
  1776. @.c.obj :
  1777.     tcc $(CFLAGS) $*.c 
  1778.  
  1779. parse.c :  parse.y
  1780.     $(YACC)  parse.y
  1781.     rename y_tab.c parse.c
  1782.     rename  y_tab.h parse.h
  1783.  
  1784. scancode.c :  makescan.c  scan.h
  1785.     tcc makescan.c
  1786.     makescan.exe > scancode.c
  1787.     rm makescan.obj  makescan.exe
  1788.  
  1789.  
  1790.  
  1791. # the dependencies of the obj's on h's
  1792. # you can make this with mawk -f deps.awk *.c
  1793.  
  1794. array.o : bi_vars.h sizes.h zmalloc.h memory.h types.h machine.h mawk.h symtype.h
  1795. bi_funct.o : fin.h bi_vars.h sizes.h memory.h zmalloc.h regexp.h types.h machine.h field.h repl.h files.h bi_funct.h mawk.h symtype.h init.h
  1796. bi_vars.o : bi_vars.h sizes.h memory.h zmalloc.h types.h machine.h field.h mawk.h symtype.h init.h
  1797. cast.o : parse.h sizes.h memory.h zmalloc.h types.h machine.h field.h scan.h repl.h mawk.h symtype.h
  1798. code.o : sizes.h memory.h zmalloc.h types.h machine.h code.h mawk.h init.h
  1799. da.o : sizes.h memory.h zmalloc.h types.h machine.h field.h repl.h code.h bi_funct.h mawk.h symtype.h
  1800. error.o : parse.h bi_vars.h sizes.h types.h machine.h scan.h mawk.h symtype.h
  1801. execute.o : sizes.h memory.h zmalloc.h regexp.h types.h machine.h field.h code.h repl.h bi_funct.h mawk.h symtype.h
  1802. fcall.o : sizes.h memory.h zmalloc.h types.h machine.h code.h mawk.h symtype.h
  1803. field.o : parse.h bi_vars.h sizes.h memory.h zmalloc.h regexp.h types.h machine.h field.h scan.h repl.h mawk.h symtype.h init.h
  1804. files.o : fin.h sizes.h memory.h zmalloc.h types.h machine.h files.h mawk.h
  1805. fin.o : parse.h fin.h bi_vars.h sizes.h memory.h zmalloc.h types.h machine.h field.h scan.h mawk.h symtype.h
  1806. hash.o : sizes.h memory.h zmalloc.h types.h machine.h mawk.h symtype.h
  1807. init.o : bi_vars.h sizes.h memory.h zmalloc.h types.h machine.h field.h code.h mawk.h symtype.h init.h
  1808. jmp.o : sizes.h memory.h zmalloc.h types.h machine.h code.h jmp.h mawk.h init.h
  1809. kw.o : parse.h sizes.h types.h machine.h mawk.h symtype.h init.h
  1810. main.o : fin.h bi_vars.h sizes.h memory.h zmalloc.h types.h machine.h field.h code.h files.h mawk.h init.h
  1811. makescan.o : parse.h scan.h symtype.h
  1812. matherr.o : sizes.h types.h machine.h mawk.h
  1813. memory.o : sizes.h memory.h zmalloc.h types.h machine.h mawk.h
  1814. parse.o : bi_vars.h sizes.h memory.h zmalloc.h types.h machine.h field.h code.h files.h bi_funct.h mawk.h jmp.h symtype.h
  1815. print.o : bi_vars.h parse.h sizes.h memory.h zmalloc.h types.h machine.h field.h scan.h files.h bi_funct.h mawk.h symtype.h
  1816. re_cmpl.o : parse.h sizes.h memory.h zmalloc.h regexp.h types.h machine.h scan.h repl.h mawk.h symtype.h
  1817. scan.o : parse.h fin.h sizes.h memory.h zmalloc.h types.h machine.h field.h scan.h repl.h files.h mawk.h symtype.h init.h
  1818. split.o : bi_vars.h parse.h sizes.h memory.h zmalloc.h regexp.h types.h machine.h field.h scan.h bi_funct.h mawk.h symtype.h
  1819. zmalloc.o : sizes.h zmalloc.h types.h machine.h mawk.h
  1820. @//E*O*F mawk0.97/msdos/makefile//
  1821. chmod u=r,g=r,o=r mawk0.97/msdos/makefile
  1822.  
  1823. echo x - mawk0.97/msdos/mklib.bat
  1824. sed 's/^@//' > "mawk0.97/msdos/mklib.bat" <<'@//E*O*F mawk0.97/msdos/mklib.bat//'
  1825.  
  1826. masm /mx /z  rand48.asm ;
  1827. tcc -c -f -O -v-  rand48_0.c
  1828.  
  1829. lib  msdos.lib  -+rand48.obj -+rand48_0.obj  ;
  1830.  
  1831.  
  1832.  
  1833. @//E*O*F mawk0.97/msdos/mklib.bat//
  1834. chmod u=r,g=r,o=r mawk0.97/msdos/mklib.bat
  1835.  
  1836. echo x - mawk0.97/msdos/rand48.asm
  1837. sed 's/^@//' > "mawk0.97/msdos/rand48.asm" <<'@//E*O*F mawk0.97/msdos/rand48.asm//'
  1838.  
  1839. ;**************************************************
  1840. ;  rand.asm
  1841. ;  PC versions of the rand48 family
  1842. ;  1988 Michael D. Brennan
  1843. ;  
  1844. ;
  1845. ;  rand.asm  and rand0.c  are the source files
  1846. ;     for rand.lib  (see also rand48.h)
  1847. ;**************************************************
  1848.  
  1849.  
  1850. public   _srand48, _seed48 , _lcong48
  1851. public     _mrand48, _jrand48 ; uniform on [0,2^32)
  1852. public   _lrand48, _nrand48 ; uniform on [0,2^31)
  1853. public   _urand48, _vrand48 ; uniform on [0,2^16)
  1854.  
  1855. ;  rand.asm
  1856.  
  1857. standard_scale0 = 0e66dh
  1858. standard_scale1 = 0deech
  1859. standard_scale2 = 5h
  1860. standard_shift  = 0bh
  1861.  
  1862. @.model  small
  1863.  
  1864. @.data
  1865. prod   dw   3 dup(?)  ;  build  scale*seed here
  1866. seed   dw   3 dup(?)  ;  default seed storage for drand, lrand etc
  1867. scale  dw   standard_scale0
  1868.        dw   standard_scale1
  1869.        dw   standard_scale2
  1870. shift  dw   standard_shift
  1871. seedbuf    dw    3 dup(?)  ;  place old seed  for seed48()
  1872.  
  1873. @.code
  1874.  
  1875.  
  1876. ;****************************************
  1877. ;  rgen -- the basic linear congruence
  1878. ;  call with  bx->the seed
  1879. ;*************************************
  1880.  
  1881. rgen    proc    near
  1882.      ;   seed <- scale * seed + shift  with overflow
  1883.  
  1884.      ;  first get  scale*seed into prod
  1885.  
  1886.     mov    ax, scale   ;  0,0
  1887.     mul    word ptr [bx]
  1888.     mov    prod, ax
  1889.     mov    cx, dx     ;   save the overflow in cx
  1890.  
  1891.     mov    ax, scale+2    ; 1,0
  1892.     mul    word ptr [bx]
  1893.     add    ax, cx
  1894.     adc    dx, 0
  1895.     mov    prod+2, ax
  1896.     mov    cx, dx
  1897.  
  1898.     mov    ax, scale+4   ;  2,0
  1899.     mul    word ptr [bx]
  1900.     add    ax, cx
  1901.     mov    prod+4, ax
  1902.  
  1903.     mov    ax, scale     ;  0,1
  1904.     mul    word ptr [bx+2]
  1905.     add    ax, prod+2
  1906.     adc    dx, 0
  1907.     mov    prod+2, ax
  1908.     mov    cx, dx
  1909.  
  1910.     mov    ax, scale+2   ;   1,1
  1911.     mul    word ptr [bx+2]
  1912.     add    ax, cx
  1913.     add    prod+4, ax
  1914.  
  1915.     mov    ax, scale   ;  0,2
  1916.     mul    word ptr [bx+4]
  1917.     add     ax, prod+4
  1918.                      ;  move product to seed
  1919.     mov    word ptr [bx+4], ax
  1920.     mov    ax, prod+2
  1921.     mov    word ptr [bx+2], ax
  1922.     mov    ax, prod
  1923.     mov    word ptr [bx], ax
  1924.               ;   add shift to seed
  1925.     mov    ax, shift
  1926.     add    word ptr [bx], ax
  1927.     adc    word ptr [bx+2], 0
  1928.     adc    word ptr [bx+4], 0
  1929.  
  1930.     ret
  1931. rgen    endp
  1932.  
  1933. set_scale    proc   near ;  set scale and shift to standard
  1934.     mov    scale, standard_scale0
  1935.     mov    scale+2, standard_scale1
  1936.     mov    scale+4, standard_scale2
  1937.     mov    shift, standard_shift
  1938.     ret
  1939. set_scale    endp
  1940.  
  1941. ;  void  srand48(long seedval)
  1942.  
  1943. _srand48    proc    near
  1944.     push    bp
  1945.     mov    bp, sp
  1946.     mov    seed, 330eh ;
  1947.     mov    ax, [bp+4]
  1948.     mov    seed+2, ax
  1949.     mov    ax, [bp+6]
  1950.     mov    seed+4, ax
  1951.     call    set_scale
  1952.     pop    bp
  1953.     ret
  1954. _srand48    endp
  1955.  
  1956.  
  1957. ;  short  *seed48( short  newseed[3] )
  1958.  
  1959. _seed48        proc   near
  1960.     push    bp
  1961.     mov    bp, sp
  1962.     push    si
  1963.     push    di
  1964.     push    ds
  1965.     pop    es
  1966.     cld
  1967.     mov    di, offset seedbuf  ;  save old seed
  1968.     mov    si, offset seed
  1969.     mov    cx, 3
  1970.     rep    movsw
  1971.     mov    si, [bp+4]   ;  load the new seed
  1972.     mov    di, offset seed
  1973.     mov    cx, 3
  1974.     rep    movsw
  1975.     call    set_scale
  1976.     mov    ax, offset seedbuf
  1977.     pop    di
  1978.     pop    si
  1979.     pop    bp
  1980.     ret
  1981. _seed48    endp
  1982.  
  1983.  
  1984. ;  long  mrand48()
  1985. ;  long  jrand48(short seed[3])
  1986.  
  1987. _mrand48    proc    near
  1988.     mov    bx, offset seed
  1989.     call    rgen
  1990.     mov    dx, seed+4
  1991.     mov    ax, seed+2
  1992.     ret
  1993. _mrand48    endp
  1994.  
  1995. _jrand48    proc    near
  1996.     push    bp
  1997.     mov    bp, sp
  1998.     mov    bx, [bp+4]
  1999.     call    rgen
  2000.     mov    dx, word ptr [bx+4]
  2001.     mov    ax, word ptr [bx+2]
  2002.     pop    bp
  2003.     ret
  2004. _jrand48    endp
  2005.  
  2006. _nrand48    proc     near
  2007.     push    bp
  2008.     mov    bp, sp
  2009.     mov    bx, [bp+4]
  2010.     call    rgen
  2011.     mov    dx, [bx+4]
  2012.     mov    ax, [bx+2]
  2013.     shr    dx, 1
  2014.     rcr    ax, 1
  2015.     pop    bp
  2016.     ret
  2017. _nrand48    endp
  2018.  
  2019. _lrand48    proc    near
  2020.     mov    bx, offset seed
  2021.     call    rgen
  2022.     mov    dx, seed+4
  2023.     mov    ax, seed+2
  2024.     shr     dx, 1
  2025.     rcr     ax, 1
  2026.     ret
  2027. _lrand48    endp
  2028.  
  2029. _vrand48    proc   near
  2030.     push    bp
  2031.     mov    bp, sp
  2032.     mov    bx, [bp+4]
  2033.     call    rgen
  2034.     mov    ax, [bx+4]
  2035.     pop    bp
  2036.     ret
  2037. _vrand48    endp
  2038.  
  2039. _urand48    proc    near
  2040.     mov    bx, offset seed
  2041.     call    rgen
  2042.     mov    ax, seed+4
  2043.     ret
  2044. _urand48    endp
  2045.  
  2046. _lcong48    proc     near
  2047.     push    bp
  2048.     mov    bp, sp
  2049.     push    si
  2050.     push    di
  2051.     push    ds
  2052.     pop    es
  2053.     cld
  2054.     mov    si, [bp+4]
  2055.     mov    di, offset seed
  2056.     mov    cx, 7
  2057.     rep    movsw
  2058.     pop    di
  2059.     pop    si
  2060.     pop    bp
  2061.     ret
  2062. _lcong48    endp
  2063.  
  2064. end
  2065. @//E*O*F mawk0.97/msdos/rand48.asm//
  2066. chmod u=r,g=r,o=r mawk0.97/msdos/rand48.asm
  2067.  
  2068. echo x - mawk0.97/msdos/rand48.h
  2069. sed 's/^@//' > "mawk0.97/msdos/rand48.h" <<'@//E*O*F mawk0.97/msdos/rand48.h//'
  2070.  
  2071. /*  rand48.h  */
  2072. /*  see Unix drand(3) for expansive discussion */
  2073.  
  2074. double  drand48(void) ;
  2075. double  erand48(unsigned short[3]) ;
  2076.  
  2077. long   mrand48(void) ;
  2078. long   jrand48(unsigned short[3]) ;
  2079. /* uniform on [-2^31, 2^31)  or
  2080.    [0,2^32)  depending on how you interpret the sign bit */
  2081.  
  2082. long  lrand48(void) ;
  2083. long  nrand48(unsigned short[3]) ;
  2084. /* uniform on [0,2^31)
  2085.    lrand48() == mrand48()>>1   */
  2086.  
  2087. unsigned  urand48(void) ;
  2088. unsigned  vrand48(unsigned short[3]) ;
  2089. /*  for 16bit machines uniform on [0,2^16)  */
  2090.  
  2091. /* SEEDING  */
  2092. void  srand48(long seedval) ;
  2093. unsigned short *seed48(unsigned short seedv[3]) ;
  2094. void  lcong(unsigned short[7] ) ;
  2095.  
  2096.  
  2097. void  srand48() ;
  2098. long  mrand48(), jrand48(), lrand48(), nrand48() ;
  2099. unsigned urand48(), vrand48() ;
  2100. double  drand48(), erand48() ;
  2101. @//E*O*F mawk0.97/msdos/rand48.h//
  2102. chmod u=r,g=r,o=r mawk0.97/msdos/rand48.h
  2103.  
  2104. echo x - mawk0.97/msdos/rand48_0.c
  2105. sed 's/^@//' > "mawk0.97/msdos/rand48_0.c" <<'@//E*O*F mawk0.97/msdos/rand48_0.c//'
  2106.  
  2107.  
  2108. /*   rand0.c    */
  2109.  
  2110. unsigned long  mrand48() ;
  2111. unsigned long  jrand48(short [3]) ;
  2112.  
  2113. double  drand48()
  2114. { return  (double) mrand48() / 4294967296.0 ; }
  2115.  
  2116. double  erand48(short x[3])
  2117. { return  (double) jrand48(x) /  4294967296.0 ; }
  2118. @//E*O*F mawk0.97/msdos/rand48_0.c//
  2119. chmod u=r,g=r,o=r mawk0.97/msdos/rand48_0.c
  2120.  
  2121. echo x - mawk0.97/msdos/reargv.c
  2122. sed 's/^@//' > "mawk0.97/msdos/reargv.c" <<'@//E*O*F mawk0.97/msdos/reargv.c//'
  2123.  
  2124. /*  reargv.c
  2125.     --  set arguments via POLYSHELL
  2126.     --  no errors, don't change anything if
  2127.     --  it seems shell is not activated   */
  2128.  
  2129. char *strchr(), *getenv() ;
  2130.  
  2131. static  char *basename(char *s)
  2132. /* strip path and extension , upcase the rest */
  2133.   register char *p ;
  2134.  
  2135.   for ( p = strchr(s,0) ; p > s ; p-- )
  2136.     switch( p[-1] )
  2137.      { case '\\' :
  2138.        case ':'  :
  2139.        case '/'  :  return p ;
  2140.        case '.'  :  p[-1] = 0 ;  break ;
  2141.        default   :
  2142.         if ( p[-1] >= 'a' && p[-1] <= 'z' )   p[-1] -= 32 ;
  2143.         break ;
  2144.      }
  2145.  
  2146.   return  p ;
  2147. }
  2148.  
  2149. /*---------------------
  2150.   reargv  --  recompute  argc and argv for PolyShell
  2151.     if not under shell do nothing
  2152.  *-------------------------------  */
  2153.  
  2154. extern  char *progname ;
  2155. extern  unsigned char _osmajor ;
  2156.  
  2157. void  reargv(int *argcp , char ***argvp)
  2158. { register char *p ;
  2159.   char **v , *q, *cmdline, **vx ;
  2160.   int cnt, cntx ;
  2161.  
  2162.   if ( _osmajor == 2 )  /* ugh */
  2163.      (*argvp)[0] = progname ;
  2164.   else { (*argvp)[0] = basename( (*argvp)[0] ) ;
  2165.      progname = (*argvp)[0] ; }
  2166.  
  2167.   if ( ! (cmdline = getenv("CMDLINE")) )  return ;
  2168.  
  2169.   if ( *(q = strchr(cmdline,0) - 1) != 0xff )
  2170.       return ;  /*  shexpand set wrong */
  2171.  
  2172.   for ( *q = 0, cnt = 1 , p = cmdline ; p < q ; p++ )
  2173.      if ( *p == 0xff ) { cnt++ ; *p = 0 ; }
  2174.  
  2175.   if ( ! (v = (char **) malloc((cnt+1)*sizeof(char*))) )
  2176.        return ;  /* shouldn't happen */
  2177.  
  2178.   p = cmdline ;
  2179.   vx = v ; cntx = cnt ;
  2180.   while ( cnt )
  2181.    { *v++ = p ;
  2182.      cnt-- ;
  2183.      while ( *p )  p++ ;
  2184.      p++ ;
  2185.    }
  2186.   *v = (char *) 0 ;
  2187.   v = vx ;
  2188.  
  2189.   v[0] = basename( v[0] ) ;
  2190.   if ( strcmp(v[0], (*argvp)[0]) )  return  ;/* running under command
  2191.     and sh earlier  */
  2192.   /* running under PolyShell  */
  2193.   *argcp = cntx ;  *argvp = v ;
  2194.   progname = v[0] ;
  2195. }
  2196. @//E*O*F mawk0.97/msdos/reargv.c//
  2197. chmod u=r,g=r,o=r mawk0.97/msdos/reargv.c
  2198.  
  2199. echo Inspecting for damage in transit...
  2200. temp=/tmp/shar$$; dtemp=/tmp/.shar$$
  2201. trap "rm -f $temp $dtemp; exit" 0 1 2 3 15
  2202. cat > $temp <<\!!!
  2203.      110     194    1897 packing.list
  2204.       21      66     407 README
  2205.       38     203    1246 LIMITATIONS
  2206.       78     450    3560 Makefile
  2207.      639    3453   20668 mawk.manual
  2208.      235    1062    5676 array.c
  2209.      781    2886   17818 bi_funct.c
  2210.       68     279    1720 bi_funct.h
  2211.       87     284    1910 bi_vars.c
  2212.       61     193    1374 bi_vars.h
  2213.      354    1074    7389 cast.c
  2214.      102     361    2538 code.c
  2215.      141     407    3421 code.h
  2216.      386    1119    9666 da.c
  2217.      345    1188    7739 error.c
  2218.      927    3424   26735 execute.c
  2219.      365    1360    9733 fcall.c
  2220.      404    1378    9426 field.c
  2221.       65     199    1432 field.h
  2222.      299    1085    7060 files.c
  2223.       41     132    1006 files.h
  2224.      368    1464    8781 fin.c
  2225.       48     185    1167 fin.h
  2226.      169     622    3566 hash.c
  2227.      202     718    4475 init.c
  2228.       44     160    1143 init.h
  2229.      217     864    5679 jmp.c
  2230.       35     122     876 jmp.h
  2231.       83     270    1572 kw.c
  2232.      160     584    4357 machine.h
  2233.      151     453    3001 main.c
  2234.      107     378    2495 makescan.c
  2235.      106     285    2019 matherr.c
  2236.      142     567    3652 mawk.h
  2237.       95     312    2268 memory.c
  2238.       50     129    1088 memory.h
  2239.     1076    3677   30281 parse.y
  2240.      285    1176    7197 print.c
  2241.      321    1215    7100 re_cmpl.c
  2242.       32     112     793 regexp.h
  2243.       37     128     898 repl.h
  2244.      694    2586   18298 scan.c
  2245.      107     315    2906 scan.h
  2246.       23      36     832 scancode.c
  2247.       56     201    1446 sizes.h
  2248.      174     644    3952 split.c
  2249.      162     633    4106 symtype.h
  2250.      112     344    2840 types.h
  2251.      129     537    3196 zmalloc.c
  2252.       44     118     905 zmalloc.h
  2253.       26      72     446 Makefile
  2254.      186     815    5015 rexp.c
  2255.      153     565    3636 rexp.h
  2256.      423    1718   10188 rexp0.c
  2257.      183     708    3987 rexp1.c
  2258.      282    1139    7507 rexp2.c
  2259.      272    1335    7457 rexp3.c
  2260.       74     252    1649 rexpdb.c
  2261.       23     106     710 README
  2262.       72     343    2430 benchmarks
  2263.        1       3      11 cat.awk
  2264.        6      12      59 concat.awk
  2265.        6      13      69 fields.awk
  2266.       23      49     201 loops.awk
  2267.       22      53     286 newton.awk
  2268.       40     129     564 primes.awk
  2269.       78     234    1076 qsort.awk
  2270.        2       4      34 reg0.awk
  2271.        2       4      41 reg1.awk
  2272.        2       5      63 reg2.awk
  2273.       13      71     461 sample
  2274.        7      19      82 squeeze.awk
  2275.       43     111     621 test.sh
  2276.        3       7      33 wc.awk
  2277.       91     363    1765 wfrq.awk
  2278.       72     297    1433 wfrq0.awk
  2279.       23      64     275 words.awk
  2280.       12      29     127 words0.awk
  2281.      143     546    3030 decl.awk
  2282.       57     241    1284 deps.awk
  2283.      136     493    2776 gdecl.awk
  2284.       18      44     213 nocomment.awk
  2285.       80     522    3002 INSTALL
  2286.      137     553    4067 makefile
  2287.        8      16     107 mklib.bat
  2288.      227     620    3670 rand48.asm
  2289.       31     106     774 rand48.h
  2290.       12      33     231 rand48_0.c
  2291.       74     333    1727 reargv.c
  2292.    13839   51659  344417 total
  2293. !!!
  2294. wc mawk0.97/packing.list mawk0.97/README mawk0.97/LIMITATIONS \
  2295.  mawk0.97/Makefile mawk0.97/mawk.manual mawk0.97/array.c \
  2296.  mawk0.97/bi_funct.c mawk0.97/bi_funct.h mawk0.97/bi_vars.c \
  2297.  mawk0.97/bi_vars.h mawk0.97/cast.c mawk0.97/code.c \
  2298.  mawk0.97/code.h mawk0.97/da.c mawk0.97/error.c mawk0.97/execute.c \
  2299.  mawk0.97/fcall.c mawk0.97/field.c mawk0.97/field.h \
  2300.  mawk0.97/files.c mawk0.97/files.h mawk0.97/fin.c mawk0.97/fin.h \
  2301.  mawk0.97/hash.c mawk0.97/init.c mawk0.97/init.h mawk0.97/jmp.c \
  2302.  mawk0.97/jmp.h mawk0.97/kw.c mawk0.97/machine.h mawk0.97/main.c \
  2303.  mawk0.97/makescan.c mawk0.97/matherr.c mawk0.97/mawk.h \
  2304.  mawk0.97/memory.c mawk0.97/memory.h mawk0.97/parse.y \
  2305.  mawk0.97/print.c mawk0.97/re_cmpl.c mawk0.97/regexp.h \
  2306.  mawk0.97/repl.h mawk0.97/scan.c mawk0.97/scan.h mawk0.97/scancode.c \
  2307.  mawk0.97/sizes.h mawk0.97/split.c mawk0.97/symtype.h \
  2308.  mawk0.97/types.h mawk0.97/zmalloc.c mawk0.97/zmalloc.h \
  2309.  mawk0.97/rexp/Makefile mawk0.97/rexp/rexp.c mawk0.97/rexp/rexp.h \
  2310.  mawk0.97/rexp/rexp0.c mawk0.97/rexp/rexp1.c mawk0.97/rexp/rexp2.c \
  2311.  mawk0.97/rexp/rexp3.c mawk0.97/rexp/rexpdb.c mawk0.97/test/README \
  2312.  mawk0.97/test/benchmarks mawk0.97/test/cat.awk mawk0.97/test/concat.awk \
  2313.  mawk0.97/test/fields.awk mawk0.97/test/loops.awk mawk0.97/test/newton.awk \
  2314.  mawk0.97/test/primes.awk mawk0.97/test/qsort.awk mawk0.97/test/reg0.awk \
  2315.  mawk0.97/test/reg1.awk mawk0.97/test/reg2.awk mawk0.97/test/sample \
  2316.  mawk0.97/test/squeeze.awk mawk0.97/test/test.sh mawk0.97/test/wc.awk \
  2317.  mawk0.97/test/wfrq.awk mawk0.97/test/wfrq0.awk mawk0.97/test/words.awk \
  2318.  mawk0.97/test/words0.awk mawk0.97/examples/decl.awk \
  2319.  mawk0.97/examples/deps.awk mawk0.97/examples/gdecl.awk \
  2320.  mawk0.97/examples/nocomment.awk mawk0.97/msdos/INSTALL \
  2321.  mawk0.97/msdos/makefile mawk0.97/msdos/mklib.bat mawk0.97/msdos/rand48.asm \
  2322.  mawk0.97/msdos/rand48.h mawk0.97/msdos/rand48_0.c mawk0.97/msdos/reargv.c \
  2323.  | sed 's=[^ ]*/==' | diff -b $temp - >$dtemp
  2324. if [ -s $dtemp ]
  2325. then echo "Ouch [diff of wc output]:" ; cat $dtemp
  2326. else echo "No problems found."
  2327. fi
  2328. exit 0
  2329.