home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 3 / 3350 < 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 2 of 6
  4. Message-ID: <3964@ssc-bee.ssc-vax.UUCP>
  5. Date: 11 May 91 14:51:06 GMT
  6.  
  7.  
  8. ------------------cut here----------------
  9.   { case C_NOINIT :  cp->dval = 0.0 ; break ;
  10.  
  11.     case C_DOUBLE :  goto two ;
  12.     case C_STRNUM :  
  13.             free_STRING( string(cp) ) ;
  14.             break ;
  15.  
  16.     case C_MBSTRN :
  17.     case C_STRING :  
  18.             s = (STRING *) cp->ptr ;
  19.  
  20. #if FPE_TRAPS  /* look for overflow error */
  21.             errno = 0 ;
  22.             cp->dval = strtod(s->str,(char **)0) ;
  23.             if ( errno && cp->dval != 0.0 ) /* ignore underflow */
  24.                 rt_error("overflow converting %s to double", s) ;
  25. #else
  26.             cp->dval = strtod(s->str,(char **)0) ;
  27. #endif
  28.             free_STRING(s) ;
  29.             break ;
  30.  
  31.     default :
  32.             bozo("cast on bad type") ;
  33.   }
  34.   cp->type = C_DOUBLE ;
  35.  
  36. two:   cp++ ;
  37.   switch( cp->type )
  38.   { case C_NOINIT :  cp->dval = 0.0 ; break ;
  39.  
  40.     case C_DOUBLE :  return ;
  41.     case C_STRNUM :  
  42.             free_STRING( string(cp) ) ;
  43.             break ;
  44.  
  45.     case C_MBSTRN :
  46.     case C_STRING :  
  47.             s = (STRING *) cp->ptr ;
  48.  
  49. #if FPE_TRAPS  /* look for overflow error */
  50.             errno = 0 ;
  51.             cp->dval = strtod(s->str,(char **)0) ;
  52.             if ( errno && cp->dval != 0.0 ) /* ignore underflow */
  53.                 rt_error("overflow converting %s to double", s) ;
  54. #else
  55.             cp->dval = strtod(s->str,(char **)0) ;
  56. #endif
  57.             free_STRING(s) ;
  58.             break ;
  59.  
  60.     default :
  61.             bozo("cast on bad type") ;
  62.   }
  63.   cp->type = C_DOUBLE ;
  64. }
  65.  
  66. void cast1_to_s( cp )
  67.   register CELL *cp ;
  68.   switch( cp->type )
  69.   { case C_NOINIT :  
  70.         null_str.ref_cnt++ ;
  71.         cp->ptr = (PTR) &null_str ;
  72.         break ;
  73.  
  74.     case C_DOUBLE  :
  75.         (void) sprintf(temp_buff.string_buff ,
  76.             string(field+OFMT)->str, cp->dval) ;
  77.  
  78.         cp->ptr = (PTR) new_STRING(temp_buff.string_buff) ;
  79.         break ;
  80.  
  81.     case C_STRING :  return ;
  82.  
  83.     case C_MBSTRN :
  84.     case C_STRNUM :  break ;
  85.  
  86.     default :  bozo("bad type on cast") ;
  87.   }
  88.   cp->type = C_STRING ;
  89. }
  90.  
  91. void cast2_to_s( cp )
  92.   register CELL *cp ;
  93.  
  94.   switch( cp->type )
  95.   { case C_NOINIT : 
  96.         null_str.ref_cnt++ ;
  97.         cp->ptr = (PTR) &null_str ;
  98.         break ;
  99.  
  100.     case C_DOUBLE  :
  101.         (void) sprintf(temp_buff.string_buff,
  102.             string(field+OFMT)->str, cp->dval ) ;
  103.  
  104.         cp->ptr = (PTR) new_STRING(temp_buff.string_buff) ;
  105.         break ;
  106.  
  107.     case C_STRING :  goto two ;
  108.  
  109.     case C_MBSTRN :
  110.     case C_STRNUM :  break ;
  111.  
  112.     default :  bozo("bad type on cast") ;
  113.   }
  114.   cp->type = C_STRING ;
  115.  
  116. two:
  117.   cp++ ;
  118.  
  119.   switch( cp->type )
  120.   { case C_NOINIT :  
  121.         null_str.ref_cnt++ ; 
  122.         cp->ptr = (PTR) &null_str ;
  123.         break ;
  124.  
  125.     case C_DOUBLE  :
  126.         (void) sprintf(temp_buff.string_buff,
  127.             string(field+OFMT)->str, cp->dval) ;
  128.  
  129.         cp->ptr = (PTR) new_STRING(temp_buff.string_buff) ;
  130.         break ;
  131.  
  132.     case C_STRING :  return ;
  133.  
  134.     case C_MBSTRN :
  135.     case C_STRNUM :  break ;
  136.  
  137.     default :  bozo("bad type on cast") ;
  138.   }
  139.   cp->type = C_STRING ;
  140. }
  141.  
  142. void  cast_to_RE( cp )
  143.   register CELL *cp ;
  144. { register PTR p ;
  145.  
  146.   if ( cp->type < C_STRING )  cast1_to_s(cp) ;
  147.  
  148.   p = re_compile( string(cp) ) ;
  149.   free_STRING( string(cp) ) ;
  150.   cp->type = C_RE ;
  151.   cp->ptr = p ;
  152.  
  153. }
  154.  
  155. void  cast_for_split(cp)
  156.   register CELL *cp ;
  157. {
  158.   static char meta[] = "^$.*+?|[]()" ;
  159.   static char xbuff[] = "\\X" ;
  160.   int c ;
  161.   unsigned len ;
  162.     
  163.   if ( cp->type < C_STRING )  cast1_to_s(cp) ;
  164.  
  165.   if ( (len = string(cp)->len) == 1 )
  166.   {
  167.         if ( (c = string(cp)->str[0]) == ' ' )
  168.         { free_STRING(string(cp)) ;
  169.           cp->type = C_SPACE ; 
  170.           return ; 
  171.         }
  172.         else
  173.         if ( strchr(meta, c) )
  174.         { xbuff[1] = c ;
  175.           free_STRING(string(cp)) ;
  176.           cp->ptr = (PTR) new_STRING(xbuff) ;
  177.         }
  178.   }
  179.   else
  180.   if ( len == 0 ) 
  181.   { free_STRING(string(cp)) ;
  182.     cp->type = C_SNULL ; 
  183.     return ; 
  184.   }
  185.  
  186.   cast_to_RE(cp) ;
  187. }
  188.  
  189. /* input: cp-> a CELL of type C_MBSTRN (maybe strnum)
  190.    test it -- casting it to the appropriate type
  191.    which is C_STRING or C_STRNUM
  192. */
  193.  
  194. void check_strnum( cp )
  195.   CELL *cp ;
  196. { char *test ;
  197.   register unsigned char *s , *q ;
  198.  
  199.   cp->type = C_STRING ; /* assume not C_STRNUM */
  200.   s = (unsigned char *) string(cp)->str ;
  201.   q = s + string(cp)->len ;
  202.   while ( scan_code[*s] == SC_SPACE )  s++ ;
  203.   if ( s == q )  return ;
  204.  
  205.   while ( scan_code[ q[-1] ] == SC_SPACE )  q-- ;
  206.   if ( scan_code[ q[-1] ] != SC_DIGIT &&
  207.        q[-1] != '.' )   return ;
  208.  
  209.   switch ( scan_code[*s] )
  210.   {
  211.     case SC_DIGIT :
  212.     case SC_PLUS  :
  213.     case SC_MINUS :
  214.     case SC_DOT   :
  215.  
  216. #if FPE_TRAPS
  217.              errno = 0 ;
  218.              cp->dval  = strtod((char *)s, &test) ;
  219.              if ( errno && cp->dval != 0.0 )
  220.                 rt_error(
  221.                 "overflow converting %s to double" , s) ;
  222. #else
  223.              cp->dval = strtod(s, &test) ;
  224. #endif
  225.  
  226.              if ((char *) q == test )  cp->type = C_STRNUM ;
  227.   }
  228. }
  229.  
  230. /* cast a CELL to a replacement cell */
  231.  
  232. void cast_to_REPL( cp )
  233.   register CELL *cp ;
  234. { register STRING *sval ;
  235.  
  236.   if ( cp->type < C_STRING )  cast1_to_s(cp) ;
  237.   sval = (STRING *) cp->ptr ;
  238.  
  239.   (void) cellcpy(cp, repl_compile(sval)) ;
  240.   free_STRING(sval) ;
  241. }
  242.  
  243.  
  244. #if   NO_STRTOD
  245.  
  246. static char d_str[] =
  247. "^[ \t]*[-+]?([0-9]+\\.?|\\.[0-9])[0-9]*([eE][-+]?[0-9]+)?" ;
  248.  
  249. static PTR d_ptr ;
  250.  
  251. void strtod_init()
  252. { STRING *sval = new_STRING(d_str) ;
  253.  
  254.   d_ptr = re_compile(sval) ;
  255.   free_STRING(sval) ;
  256. }
  257.  
  258. double strtod( s, endptr)
  259.   char *s , **endptr ;
  260. { double atof() ;
  261.  
  262.   if ( endptr )
  263.   { unsigned len ;
  264.  
  265.     (void) REmatch(s, d_ptr, &len) ;
  266.     *endptr = s + len ;
  267.   }
  268.   return  atof(s) ;
  269. }
  270. #endif  /* NO_STRTOD */
  271.  
  272. #if   NO_FMOD
  273.  
  274. double  fmod(x, y)
  275.   double x, y ;
  276. { double modf() ;
  277.   double ipart ;
  278.  
  279.   return modf(x/y, &ipart) * y ;
  280. }
  281.  
  282. #endif  /* NO_FMOD */
  283.  
  284.  
  285.  
  286. @//E*O*F mawk0.97/cast.c//
  287. chmod u=rw,g=r,o=r mawk0.97/cast.c
  288.  
  289. echo x - mawk0.97/code.c
  290. sed 's/^@//' > "mawk0.97/code.c" <<'@//E*O*F mawk0.97/code.c//'
  291.  
  292. /********************************************
  293. code.c
  294. copyright 1991, Michael D. Brennan
  295.  
  296. This is a source file for mawk, an implementation of
  297. the Awk programming language as defined in
  298. Aho, Kernighan and Weinberger, The AWK Programming Language,
  299. Addison-Wesley, 1988.
  300.  
  301. See the accompaning file, LIMITATIONS, for restrictions
  302. regarding modification and redistribution of this
  303. program in source or binary form.
  304. ********************************************/
  305.  
  306.  
  307. /* $Log:    code.c,v $
  308.  * Revision 2.1  91/04/08  08:22:46  brennan
  309.  * VERSION 0.97
  310.  * 
  311. */
  312.  
  313. /*  code.c  */
  314.  
  315. #include "mawk.h"
  316. #include "code.h"
  317. #include "init.h"
  318.  
  319.  
  320. #define   CODE_SZ      (PAGE_SZ*sizeof(INST))
  321.  
  322. INST *code_ptr  ;
  323. INST *main_start , *main_code_ptr ;
  324. INST *begin_start , *begin_code_ptr ;
  325. INST *end_start , *end_code_ptr ;
  326. unsigned  main_size, begin_size, end_size ;
  327.  
  328. void  PROTO(fdump, (void) ) ;
  329.  
  330. void  code_init()
  331.   main_code_ptr = main_start = (INST *) zmalloc(CODE_SZ) ;
  332.   begin_code_ptr = begin_start = (INST *) zmalloc(CODE_SZ) ;
  333.   end_code_ptr = end_start = (INST *) zmalloc(CODE_SZ) ;
  334.   code_ptr = main_code_ptr ;
  335. }
  336.  
  337. void code_cleanup()
  338. {
  339.   if ( dump_code )  fdump() ; /* dumps all functions */
  340.  
  341.   begin_code_ptr++->op = _HALT ;
  342.   if ( (begin_size = begin_code_ptr - begin_start) == 1 ) /* empty */
  343.   {
  344.       zfree( begin_start, CODE_SZ ) ;
  345.       begin_start = (INST *) 0 ;
  346.   }
  347.   else
  348.   if ( begin_size > PAGE_SZ ) overflow("BEGIN code" , PAGE_SZ) ;
  349.   else
  350.   {  begin_size *= sizeof(INST) ;
  351.      begin_start = (INST *) zrealloc(begin_start,CODE_SZ,begin_size) ;
  352.      if ( dump_code )
  353.      { fprintf(stderr, "BEGIN\n") ;
  354.        da(begin_start, stderr) ; 
  355.      }
  356.   }
  357.  
  358.   end_code_ptr++->op = _HALT ;
  359.   if ( (end_size = end_code_ptr - end_start) == 1 ) /* empty */
  360.   {
  361.       zfree( end_start, CODE_SZ ) ;
  362.       end_start = (INST *) 0 ;
  363.   }
  364.   else
  365.   if ( end_size > PAGE_SZ ) overflow("END code" , PAGE_SZ) ;
  366.   else
  367.   {  end_size *= sizeof(INST) ;
  368.      end_start = (INST *) zrealloc(end_start, CODE_SZ, end_size) ;
  369.      if ( dump_code )
  370.      { fprintf(stderr, "END\n") ;
  371.        da(end_start, stderr) ;
  372.      }
  373.   }
  374.  
  375.   code_ptr++->op = _HALT ;
  376.   if ( (main_size = code_ptr - main_start) == 1 ) /* empty */
  377.   {
  378.       zfree( main_start, CODE_SZ ) ;
  379.       main_start = (INST *) 0 ;
  380.   }
  381.   else
  382.   if ( main_size > PAGE_SZ ) overflow("MAIN code" , PAGE_SZ) ;
  383.   else
  384.   {  main_size *= sizeof(INST) ;
  385.      main_start = (INST *) zrealloc(main_start, CODE_SZ, main_size) ;
  386.      if ( dump_code )
  387.      { fprintf(stderr, "MAIN\n") ;
  388.        da(main_start, stderr) ;
  389.      }
  390.   }
  391. }
  392. @//E*O*F mawk0.97/code.c//
  393. chmod u=rw,g=r,o=r mawk0.97/code.c
  394.  
  395. echo x - mawk0.97/code.h
  396. sed 's/^@//' > "mawk0.97/code.h" <<'@//E*O*F mawk0.97/code.h//'
  397.  
  398. /********************************************
  399. code.h
  400. copyright 1991, Michael D. Brennan
  401.  
  402. This is a source file for mawk, an implementation of
  403. the Awk programming language as defined in
  404. Aho, Kernighan and Weinberger, The AWK Programming Language,
  405. Addison-Wesley, 1988.
  406.  
  407. See the accompaning file, LIMITATIONS, for restrictions
  408. regarding modification and redistribution of this
  409. program in source or binary form.
  410. ********************************************/
  411.  
  412.  
  413. /* $Log:    code.h,v $
  414.  * Revision 2.1  91/04/08  08:22:48  brennan
  415.  * VERSION 0.97
  416.  * 
  417. */
  418.  
  419.  
  420. /*  code.h  */
  421.  
  422. #ifndef  CODE_H
  423. #define  CODE_H
  424.  
  425. #include "memory.h"
  426. #include <setjmp.h>
  427.  
  428. /* coding scope */
  429. #define   SCOPE_MAIN    0
  430. #define   SCOPE_BEGIN   1  
  431. #define   SCOPE_END     2
  432. #define   SCOPE_FUNCT   3
  433.  
  434.  
  435. extern  INST  *code_ptr ;
  436. extern  INST  *begin_start , *begin_code_ptr ;
  437. extern  INST  *end_start , *end_code_ptr ;
  438. extern  INST  *main_start, *main_code_ptr ;
  439. extern  unsigned begin_size, end_size, main_size ;
  440.  
  441. extern  CELL  eval_stack[] ;
  442.  
  443.  
  444. #define  code1(x)  code_ptr++ -> op = (x)
  445.  
  446. #define  code2(x,y)    (void)( code_ptr++ -> op = (x) ,\
  447.                          code_ptr++ -> ptr = (PTR)(y) )
  448.  
  449.  
  450. /*  the machine opcodes  */
  451.  
  452. #define _HALT            0
  453. #define _STOP            1
  454. #define _STOP0           2  
  455. #define _PUSHC           3
  456. #define _PUSHINT         4
  457. #define _PUSHA           5
  458. #define _PUSHI           6
  459. #define L_PUSHA          7
  460. #define L_PUSHI          8
  461. #define AE_PUSHA         9
  462. #define AE_PUSHI        10
  463. #define A_PUSHA         11
  464. #define LAE_PUSHA       12
  465. #define LAE_PUSHI       13
  466. #define LA_PUSHA        14
  467. #define F_PUSHA         15
  468. #define FE_PUSHA        16
  469. #define F_PUSHI         17
  470. #define FE_PUSHI        18
  471. #define _POP            19
  472. #define _PULL           20
  473. #define _DUP            21
  474. #define _ADD            22
  475. #define _SUB            23
  476. #define _MUL            24
  477. #define _DIV            25
  478. #define _MOD            26
  479. #define _POW            27
  480. #define _NOT            28
  481. #define _TEST           29
  482. #define A_TEST          30
  483. #define A_DEL           31
  484. #define A_LOOP          32
  485. #define A_CAT           33
  486. #define _UMINUS         34
  487. #define _UPLUS          35
  488. #define _ASSIGN         36
  489. #define _ADD_ASG        37
  490. #define _SUB_ASG        38
  491. #define _MUL_ASG        39
  492. #define _DIV_ASG        40
  493. #define _MOD_ASG        41
  494. #define _POW_ASG        42
  495. #define F_ASSIGN        43
  496. #define F_ADD_ASG       44
  497. #define F_SUB_ASG       45
  498. #define F_MUL_ASG       46
  499. #define F_DIV_ASG       47
  500. #define F_MOD_ASG       48
  501. #define F_POW_ASG       49
  502. #define _CAT            50
  503. #define _BUILTIN        51
  504. #define _PRINT          52
  505. #define _POST_INC       53
  506. #define _POST_DEC       54
  507. #define _PRE_INC        55
  508. #define _PRE_DEC        56
  509. #define F_POST_INC      57
  510. #define F_POST_DEC      58
  511. #define F_PRE_INC       59
  512. #define F_PRE_DEC       60
  513. #define _JMP            61
  514. #define _JNZ            62
  515. #define _JZ             63
  516. #define _EQ             64
  517. #define _NEQ            65
  518. #define _LT             66
  519. #define _LTE            67
  520. #define _GT             68
  521. #define _GTE            69
  522. #define _MATCH          70
  523. #define _EXIT           71
  524. #define _EXIT0          72
  525. #define _NEXT           73
  526. #define _RANGE          74
  527. #define _CALL           75
  528. #define _RET            76
  529. #define _RET0           77
  530.  
  531.  
  532. /* next and exit statements */
  533.  
  534. extern jmp_buf  exit_jump, next_jump ;
  535. extern int exit_code ;
  536.  
  537. #endif  /* CODE_H */
  538. @//E*O*F mawk0.97/code.h//
  539. chmod u=rw,g=r,o=r mawk0.97/code.h
  540.  
  541. echo x - mawk0.97/da.c
  542. sed 's/^@//' > "mawk0.97/da.c" <<'@//E*O*F mawk0.97/da.c//'
  543.  
  544. /********************************************
  545. da.c
  546. copyright 1991, Michael D. Brennan
  547.  
  548. This is a source file for mawk, an implementation of
  549. the Awk programming language as defined in
  550. Aho, Kernighan and Weinberger, The AWK Programming Language,
  551. Addison-Wesley, 1988.
  552.  
  553. See the accompaning file, LIMITATIONS, for restrictions
  554. regarding modification and redistribution of this
  555. program in source or binary form.
  556. ********************************************/
  557.  
  558.  
  559. /* $Log:    da.c,v $
  560.  * Revision 2.1  91/04/08  08:22:50  brennan
  561.  * VERSION 0.97
  562.  * 
  563. */
  564.  
  565.  
  566. /*  da.c  */
  567. /*  disassemble code */ 
  568.  
  569.  
  570. #include  "mawk.h"
  571. #include  "code.h"
  572. #include  "bi_funct.h"
  573. #include  "repl.h"
  574. #include  "field.h"
  575.  
  576. char *PROTO(find_bi_name, (PF_CP) ) ;
  577.  
  578. void  da(start, fp)
  579.   INST *start ;
  580.   FILE *fp ;
  581. { CELL *cp ;
  582.   register INST *p = start ;
  583.  
  584.   while ( 1 )
  585.   { /* print the relative code address (label) */
  586.     fprintf(fp,"%03d ", p - start) ;
  587.  
  588.     switch( p++->op )
  589.     {
  590.       case _HALT :  fprintf(fp,"halt\n") ; return ;
  591.       case _STOP :  fprintf(fp,"stop\n") ; break  ;
  592.       case _STOP0 : fprintf(fp, "stop0\n") ; break ;
  593.  
  594.       case _PUSHC :
  595.             cp = (CELL *) p++->ptr ;
  596.             switch( cp->type )
  597.             { case C_DOUBLE :
  598.                   fprintf(fp,"pushc\t%.6g\n" ,  cp ->dval) ;
  599.                   break ;
  600.  
  601.               case C_STRING :
  602.                   fprintf(fp,"pushc\t\"%s\"\n" ,
  603.                           ((STRING *)cp->ptr)->str) ;
  604.                   break ;
  605.  
  606.               case C_RE :
  607.                   fprintf(fp,"pushc\t0x%x\t/%s/\n" , cp->ptr ,
  608.                     re_uncompile(cp->ptr) ) ;
  609.                   break ;
  610.  
  611.               case C_SPACE : 
  612.                   fprintf(fp, "pushc\tspace split\n") ;
  613.                   break ;
  614.  
  615.               case C_SNULL : 
  616.                   fprintf(fp, "pushc\tnull split\n") ;
  617.                   break ;
  618.               case C_REPL  :
  619.                   fprintf(fp, "pushc\trepl\t%s\n" ,
  620.                         repl_uncompile(cp) ) ;
  621.                   break ;
  622.               case C_REPLV :
  623.                   fprintf(fp, "pushc\treplv\t%s\n" ,
  624.                         repl_uncompile(cp) ) ;
  625.                   break ;
  626.                   
  627.               default :
  628.                   fprintf(fp,"pushc\tWEIRD\n") ;  ;
  629.                   break ;
  630.             }
  631.             break ;
  632.  
  633.       case _PUSHA :
  634.             fprintf(fp,"pusha\t0x%x\n", p++ -> ptr) ;
  635.             break ;
  636.  
  637.       case _PUSHI :
  638.             if ( (CELL *)p->ptr == field )
  639.                 fprintf(fp, "pushi\t$0\n") ;
  640.             else fprintf(fp,"pushi\t0x%x\n", p -> ptr) ;
  641.             p++ ;
  642.             break ;
  643.  
  644.       case  L_PUSHA :
  645.             fprintf( fp, "l_pusha\t%d\n", p++->op) ;
  646.             break ;
  647.  
  648.       case  L_PUSHI :
  649.             fprintf( fp, "l_pushi\t%d\n", p++->op) ;
  650.             break ;
  651.  
  652.       case  LAE_PUSHI :
  653.             fprintf( fp, "lae_pushi\t%d\n", p++->op) ;
  654.             break ;
  655.  
  656.       case  LAE_PUSHA :
  657.             fprintf( fp, "lae_pusha\t%d\n", p++->op) ;
  658.             break ;
  659.  
  660.       case  LA_PUSHA :
  661.             fprintf( fp, "la_pusha\t%d\n", p++->op) ;
  662.             break ;
  663.  
  664.       case F_PUSHA :
  665.             fprintf(fp,"f_pusha\t$%d\n" , (CELL *) p++->ptr - field ) ;
  666.             break ;
  667.  
  668.       case F_PUSHI :
  669.             fprintf(fp,"f_pushi\t$%d\n" , (CELL *) p++->ptr - field ) ;
  670.             break ;
  671.  
  672.       case FE_PUSHA :
  673.             fprintf(fp,"fe_pusha\n" ) ;
  674.             break ;
  675.  
  676.       case FE_PUSHI :
  677.             fprintf(fp,"fe_pushi\n" ) ;
  678.             break ;
  679.  
  680.       case AE_PUSHA :
  681.             fprintf(fp,"ae_pusha\t0x%x\n" , p++->ptr) ;
  682.             break ;
  683.  
  684.       case AE_PUSHI :
  685.             fprintf(fp,"ae_pushi\t0x%x\n" , p++->ptr) ;
  686.             break ;
  687.  
  688.       case A_PUSHA :
  689.             fprintf(fp,"a_pusha\t0x%x\n" , p++->ptr) ;
  690.             break ;
  691.  
  692.       case A_TEST :
  693.             fprintf(fp,"a_test\n" ) ;
  694.             break ;
  695.  
  696.       case A_DEL :
  697.             fprintf(fp,"a_del\n" ) ;
  698.             break ;
  699.  
  700.       case A_CAT :
  701.             fprintf(fp,"a_cat\t%d\n", p++->op ) ;
  702.             break ;
  703.  
  704.       case _POP :
  705.             fprintf(fp,"pop\n") ;
  706.             break ;
  707.  
  708.       case  _ADD :
  709.             fprintf(fp,"add\n") ; break ;
  710.  
  711.       case  _SUB :
  712.             fprintf(fp,"sub\n") ; break ;
  713.       case  _MUL :
  714.             fprintf(fp,"mul\n") ; break ;
  715.       case  _DIV :
  716.             fprintf(fp,"div\n") ; break ;
  717.       case  _MOD :
  718.             fprintf(fp,"mod\n") ; break ;
  719.       case  _POW :
  720.             fprintf(fp,"pow\n") ; break ;
  721.       case  _NOT :
  722.             fprintf(fp,"not\n") ; break ;
  723.       case  _UMINUS :
  724.             fprintf(fp,"uminus\n") ; break ;
  725.       case  _UPLUS :
  726.             fprintf(fp,"plus\n") ; break ;
  727.       case  _DUP :
  728.             fprintf(fp,"dup\n") ; break ;
  729.       case  _TEST :
  730.             fprintf(fp,"test\n") ; break ;
  731.  
  732.       case  _CAT  :
  733.             fprintf(fp,"cat\n") ; break ;
  734.  
  735.       case  _ASSIGN :
  736.             fprintf(fp,"assign\n") ; break ;
  737.       case  _ADD_ASG :
  738.             fprintf(fp,"add_asg\n") ; break ;
  739.       case  _SUB_ASG :
  740.             fprintf(fp,"sub_asg\n") ; break ;
  741.       case  _MUL_ASG :
  742.             fprintf(fp,"mul_asg\n") ; break ;
  743.       case  _DIV_ASG :
  744.             fprintf(fp,"div_asg\n") ; break ;
  745.       case  _MOD_ASG :
  746.             fprintf(fp,"mod_asg\n") ; break ;
  747.       case  _POW_ASG :
  748.             fprintf(fp,"pow_asg\n") ; break ;
  749.  
  750.       case  F_ASSIGN :
  751.             fprintf(fp,"f_assign\n") ; break ;
  752.       case  F_ADD_ASG :
  753.             fprintf(fp,"f_add_asg\n") ; break ;
  754.       case  F_SUB_ASG :
  755.             fprintf(fp,"f_sub_asg\n") ; break ;
  756.       case  F_MUL_ASG :
  757.             fprintf(fp,"f_mul_asg\n") ; break ;
  758.       case  F_DIV_ASG :
  759.             fprintf(fp,"f_div_asg\n") ; break ;
  760.       case  F_MOD_ASG :
  761.             fprintf(fp,"f_mod_asg\n") ; break ;
  762.       case  F_POW_ASG :
  763.             fprintf(fp,"f_pow_asg\n") ; break ;
  764.  
  765.       case  _PUSHINT :
  766.             fprintf(fp,"pushint\t%d\n" , p++ -> op ) ;
  767.             break ;
  768.  
  769.       case  _BUILTIN  :
  770.             fprintf(fp,"%s\n" , 
  771.                     find_bi_name( (PF_CP) p++ -> ptr ) ) ;
  772.             break ;
  773.  
  774.       case  _PRINT :
  775.             fprintf(fp,"%s\n", 
  776.             (PF_CP) p++ -> ptr == bi_printf
  777.                 ? "printf" : "print") ;
  778.             break ;
  779.       
  780.       case  _POST_INC :
  781.             fprintf(fp,"post_inc\n") ; break ;
  782.  
  783.       case  _POST_DEC :
  784.             fprintf(fp,"post_dec\n") ; break ;
  785.  
  786.       case  _PRE_INC :
  787.             fprintf(fp,"pre_inc\n") ; break ;
  788.  
  789.       case  _PRE_DEC :
  790.             fprintf(fp,"pre_dec\n") ; break ;
  791.  
  792.       case  F_POST_INC :
  793.             fprintf(fp,"f_post_inc\n") ; break ;
  794.  
  795.       case  F_POST_DEC :
  796.             fprintf(fp,"f_post_dec\n") ; break ;
  797.  
  798.       case  F_PRE_INC :
  799.             fprintf(fp,"f_pre_inc\n") ; break ;
  800.  
  801.       case  F_PRE_DEC :
  802.             fprintf(fp,"f_pre_dec\n") ; break ;
  803.  
  804.       case  _JMP :
  805.       case  _JNZ :
  806.       case  _JZ  :
  807.           { int j = (p-1)->op ;
  808.             char *s = j == _JMP ? "jmp" : 
  809.                       j == _JNZ ? "jnz" : "jz" ;
  810.  
  811.             fprintf(fp,"%s\t\t%03d\n" , s ,
  812.               (p - start) + p->op - 1 ) ;
  813.             p++ ;
  814.             break ;
  815.           }
  816.     
  817.       case  _EQ  :
  818.             fprintf(fp,"eq\n") ; break ;
  819.  
  820.       case  _NEQ  :
  821.             fprintf(fp,"neq\n") ; break ;
  822.  
  823.       case  _LT  :
  824.             fprintf(fp,"lt\n") ; break ;
  825.  
  826.       case  _LTE  :
  827.             fprintf(fp,"lte\n") ; break ;
  828.  
  829.       case  _GT  :
  830.             fprintf(fp,"gt\n") ; break ;
  831.  
  832.       case  _GTE  :
  833.             fprintf(fp,"gte\n") ; break ;
  834.  
  835.       case  _MATCH :
  836.             fprintf(fp,"match_op\n") ; break ;
  837.  
  838.       case  A_LOOP :
  839.             fprintf(fp,"a_loop\t%03d\n", p-start+p[1].op) ;
  840.             p += 2 ;
  841.             break ;
  842.  
  843.       case  _EXIT  :
  844.             fprintf(fp, "exit\n") ; break ;
  845.  
  846.       case  _EXIT0  :
  847.             fprintf(fp, "exit0\n") ; break ;
  848.  
  849.       case  _NEXT  :
  850.             fprintf(fp, "next\n") ; break ;
  851.  
  852.       case  _RET  :
  853.             fprintf(fp, "ret\n") ; break ;
  854.       case  _RET0 :
  855.             fprintf(fp, "ret0\n") ; break ;
  856.  
  857.       case  _CALL :
  858.             fprintf(fp, "call\t%s\t%d\n", 
  859.                 ((FBLOCK*)p->ptr)->name , p[1].op) ;
  860.             p += 2 ;
  861.             break ;
  862.  
  863.       case  _RANGE :
  864.             fprintf(fp, "range\t%03d %03d %03d\n",
  865.               /* label for pat2, action, follow */
  866.               p - start + p[1].op ,
  867.               p - start + p[2].op ,
  868.               p - start + p[3].op ) ;
  869.             p += 4 ; 
  870.             break ;
  871.       default :
  872.             fprintf(fp,"bad instruction\n") ;
  873.             return ;
  874.     }
  875.   }
  876. }
  877.  
  878. static struct {
  879. PF_CP action ;
  880. char *name ;
  881. } special_cases[] = {
  882. bi_length, "length",
  883. bi_split, "split",
  884. bi_match, "match",
  885. bi_getline,"getline",
  886. bi_sub, "sub",
  887. bi_gsub , "gsub",
  888. (PF_CP) 0, (char *) 0 } ;
  889.  
  890. static char *find_bi_name( p )
  891.   PF_CP p ;
  892. { BI_REC *q ;
  893.   int i ;
  894.  
  895.   for( q = bi_funct ; q->name ; q++ )
  896.     if ( q->fp == p )  /* found */
  897.         return q->name ;
  898.   /* next check some special cases */
  899.   for( i = 0 ; special_cases[i].action ; i++)
  900.     if ( special_cases[i].action == p )
  901.         return  special_cases[i].name ;
  902.  
  903.   return  "unknown builtin" ;
  904. }
  905.  
  906. static struct fdump {
  907. struct fdump *link ;
  908. FBLOCK  *fbp ;
  909. }  *fdump_list ;  /* linked list of all user functions */
  910.  
  911. void add_to_fdump_list( fbp )
  912.   FBLOCK *fbp ;
  913. { struct fdump *p = (struct fdump *)zmalloc(sizeof(struct fdump)) ;
  914.   p->fbp = fbp ;
  915.   p->link = fdump_list ;  fdump_list = p ;
  916. }
  917.  
  918. void  fdump()
  919. {
  920.   register struct fdump *p, *q = fdump_list ;
  921.  
  922.   while ( p = q )
  923.   { q = p->link ;
  924.     fprintf(stderr, "function %s\n" , p->fbp->name) ;
  925.     da(p->fbp->code, stderr) ;
  926.     zfree(p, sizeof(struct fdump)) ;
  927.   }
  928. }
  929. @//E*O*F mawk0.97/da.c//
  930. chmod u=rw,g=r,o=r mawk0.97/da.c
  931.  
  932. echo x - mawk0.97/error.c
  933. sed 's/^@//' > "mawk0.97/error.c" <<'@//E*O*F mawk0.97/error.c//'
  934.  
  935. /********************************************
  936. error.c
  937. copyright 1991, Michael D. Brennan
  938.  
  939. This is a source file for mawk, an implementation of
  940. the Awk programming language as defined in
  941. Aho, Kernighan and Weinberger, The AWK Programming Language,
  942. Addison-Wesley, 1988.
  943.  
  944. See the accompaning file, LIMITATIONS, for restrictions
  945. regarding modification and redistribution of this
  946. program in source or binary form.
  947. ********************************************/
  948.  
  949.  
  950. /* $Log:    error.c,v $
  951.  * Revision 2.2  91/04/09  12:38:52  brennan
  952.  * added static to funct decls to satisfy STARDENT compiler
  953.  * 
  954.  * Revision 2.1  91/04/08  08:22:52  brennan
  955.  * VERSION 0.97
  956.  * 
  957. */
  958.  
  959.  
  960. #include  "mawk.h"
  961. #include  "scan.h"
  962. #include  "bi_vars.h"
  963.  
  964. #ifndef  EOF
  965. #define  EOF  (-1)
  966. #endif
  967.  
  968. /* statics */
  969. static void  PROTO( check_FILENAME, (void) ) ;
  970. static void  PROTO( unexpected_char, (void) ) ;
  971. static void  PROTO( missing, (int, char *, int) ) ;
  972. static char *PROTO( type_to_str, (int) ) ;
  973.  
  974.  
  975. static struct token_str  {
  976. short token ;
  977. char *str ; }  token_str[] = {
  978. EOF , "end of file" ,
  979. NL , "end of line",
  980. SEMI_COLON , ";" ,
  981. LBRACE , "{" ,
  982. RBRACE , "}" ,
  983. SC_FAKE_SEMI_COLON, "}",
  984. LPAREN , "(" ,
  985. RPAREN , ")" ,
  986. LBOX , "[",
  987. RBOX , "]",
  988. QMARK , "?",
  989. COLON , ":",
  990. OR, "||",
  991. AND, "&&",
  992. P_OR, "||",
  993. P_AND, "&&",
  994. ASSIGN , "=" ,
  995. ADD_ASG, "+=",
  996. SUB_ASG, "-=",
  997. MUL_ASG, "*=",
  998. DIV_ASG, "/=",
  999. MOD_ASG, "%=",
  1000. POW_ASG, "^=",
  1001. EQ  , "==" ,
  1002. NEQ , "!=",
  1003. LT, "<" ,
  1004. LTE, "<=" ,
  1005. GT, ">",
  1006. GTE, ">=" ,
  1007. MATCH, "~",
  1008. NOT_MATCH, "!~",
  1009. PLUS , "+" ,
  1010. MINUS, "-" ,
  1011. MUL , "*" ,
  1012. DIV, "/"  , 
  1013. MOD, "%" ,
  1014. POW, "^" ,
  1015. INC , "++" ,
  1016. DEC , "--" ,
  1017. NOT, "!" ,
  1018. COMMA, "," ,
  1019. CONSTANT , temp_buff.string_buff ,
  1020. ID , temp_buff.string_buff ,
  1021. FUNCT_ID , temp_buff.string_buff ,
  1022. BUILTIN , temp_buff.string_buff ,
  1023. IO_OUT, temp_buff.string_buff, 
  1024. IO_IN, "<" ,
  1025. PIPE, "|" ,
  1026. DOLLAR, "$" ,
  1027. FIELD, "$" ,
  1028. 0, (char *) 0 } ;
  1029.  
  1030. /* if paren_cnt >0 and we see one of these, we are missing a ')' */
  1031. static int missing_rparen[] =
  1032. { EOF, NL, SEMI_COLON, SC_FAKE_SEMI_COLON, RBRACE, 0 } ;
  1033.  
  1034. /* ditto for '}' */
  1035. static int missing_rbrace[] =
  1036. { EOF, BEGIN, END , 0 } ;
  1037.  
  1038. static void missing( c, n , ln)
  1039.   int c ;
  1040.   char *n ;
  1041.   int ln ;
  1042. { errmsg(0, "line %u: missing %c near %s" , ln, c, n) ; }
  1043.   
  1044. void  yyerror(s)
  1045.   char *s ; /* we won't use s as input 
  1046.   (yacc and bison force this).
  1047.   We will use s for storage to keep lint or the compiler
  1048.   off our back */
  1049. { struct token_str *p ;
  1050.   int *ip ;
  1051.  
  1052.   s = (char *) 0 ;
  1053.  
  1054.   for ( p = token_str ; p->token ; p++ )
  1055.       if ( current_token == p->token )
  1056.       { s = p->str ; break ; }
  1057.  
  1058.   if ( ! s )  /* search the keywords */
  1059.          s = find_kw_str(current_token) ;
  1060.  
  1061.   if ( s )
  1062.   {
  1063.     if ( paren_cnt )
  1064.         for( ip = missing_rparen ; *ip ; ip++)
  1065.           if ( *ip == current_token )
  1066.           { missing(')', s, token_lineno) ;
  1067.             paren_cnt = 0 ;
  1068.             goto done ;
  1069.           }
  1070.  
  1071.     if ( brace_cnt )
  1072.         for( ip = missing_rbrace ; *ip ; ip++)
  1073.           if ( *ip == current_token )
  1074.           { missing('}', s, token_lineno) ;
  1075.             brace_cnt = 0 ;
  1076.             goto done ;
  1077.           }
  1078.  
  1079.     compile_error("syntax error at or near %s", s) ;
  1080.  
  1081.   }
  1082.   else  /* special cases */
  1083.   switch ( current_token )
  1084.   {
  1085.     case UNEXPECTED :
  1086.             unexpected_char() ; 
  1087.             goto done ;
  1088.  
  1089.     case BAD_DECIMAL :
  1090.             compile_error(
  1091.               "syntax error in decimal constant %s",
  1092.               temp_buff.string_buff ) ;
  1093.             break ;
  1094.  
  1095.     case RE :
  1096.             compile_error(
  1097.             "syntax error at or near /%s/", 
  1098.             temp_buff.string_buff ) ;
  1099.             break ;
  1100.  
  1101.     default :
  1102.             compile_error("syntax error") ;
  1103.             break ;
  1104.   }
  1105.   return ;
  1106.  
  1107. done :
  1108.   if ( ++compile_error_count == MAX_COMPILE_ERRORS ) mawk_exit(1) ;
  1109. }
  1110.  
  1111. /* system provided errnos and messages */
  1112. extern int sys_nerr ;
  1113. extern char *sys_errlist[] ;
  1114.  
  1115. #ifdef  __STDC__
  1116. #include <stdarg.h>
  1117.  
  1118. /* generic error message with a hook into the system error 
  1119.    messages if errnum > 0 */
  1120.  
  1121. void  errmsg(int errnum, char *format, ...)
  1122. { va_list args ;
  1123.  
  1124.   fprintf(stderr, "%s: " , progname) ;
  1125.   va_start(args, format) ;
  1126.   (void) vfprintf(stderr, format, args) ;
  1127.   va_end(args) ;
  1128.   if ( errnum > 0 && errnum < sys_nerr )
  1129.     fprintf(stderr, " (%s)" , sys_errlist[errnum]) ;
  1130.   fprintf( stderr, "\n") ;
  1131. }
  1132.  
  1133. void  compile_error(char *format, ...)
  1134. { va_list args ;
  1135.  
  1136.   fprintf(stderr, "%s: line %u: " , progname, token_lineno) ;
  1137.   va_start(args, format) ;
  1138.   vfprintf(stderr, format, args) ;
  1139.   va_end(args) ;
  1140.   fprintf(stderr, "\n") ;
  1141.   if ( ++compile_error_count == MAX_COMPILE_ERRORS ) mawk_exit(1) ;
  1142. }
  1143.  
  1144. void  rt_error( char *format, ...)
  1145. { va_list args ;
  1146.  
  1147.   fprintf(stderr, "%s: run time error: " , progname ) ;
  1148.   va_start(args, format) ;
  1149.   vfprintf(stderr, format, args) ;
  1150.   va_end(args) ;
  1151.   check_FILENAME() ;
  1152.   fprintf(stderr, "\n\t(FILENAME=\"%s\" FNR=%g NR=%g)\n" ,
  1153.      string(bi_vars+FILENAME)->str, bi_vars[FNR].dval,
  1154.      bi_vars[NR].dval) ;
  1155.   mawk_exit(1) ;
  1156. }
  1157.  
  1158. #else
  1159.  
  1160. #include <varargs.h>
  1161.  
  1162. /*  void errmsg(errnum, format, ...) */
  1163.  
  1164. void  errmsg( va_alist)
  1165.   va_dcl
  1166. { va_list ap ;
  1167.   int errnum ;
  1168.   char *format ;
  1169.  
  1170.   fprintf(stderr, "%s: " , progname) ;
  1171.   va_start(ap) ;
  1172.   errnum = va_arg(ap, int) ;
  1173.   format = va_arg(ap, char *) ;
  1174.   (void) vfprintf(stderr, format, ap) ;
  1175.   if ( errnum > 0 && errnum < sys_nerr )
  1176.     fprintf(stderr, " (%s)" , sys_errlist[errnum]) ;
  1177.   fprintf( stderr, "\n") ;
  1178. }
  1179.  
  1180. void compile_error( va_alist )
  1181.   va_dcl
  1182. { va_list args ;
  1183.   char *format ;
  1184.  
  1185.   fprintf(stderr, "%s: line %u: " , progname, token_lineno) ;
  1186.   va_start(args) ;
  1187.   format = va_arg(args, char *) ;
  1188.   vfprintf(stderr, format, args) ;
  1189.   va_end(args) ;
  1190.   fprintf(stderr, "\n") ;
  1191.   if ( ++compile_error_count == MAX_COMPILE_ERRORS ) mawk_exit(1) ;
  1192. }
  1193.  
  1194. void  rt_error( va_alist )
  1195.   va_dcl
  1196. { va_list args ;
  1197.   char *format ;
  1198.  
  1199.   fprintf(stderr, "%s: run time error: " , progname ) ;
  1200.   va_start(args) ;
  1201.   format = va_arg(args, char *) ;
  1202.   vfprintf(stderr, format, args) ;
  1203.   va_end(args) ;
  1204.   check_FILENAME() ;
  1205.   fprintf(stderr, "\n\tFILENAME=\"%s\" FNR=%g NR=%g\n" ,
  1206.      string(bi_vars+FILENAME)->str, bi_vars[FNR].dval,
  1207.      bi_vars[NR].dval) ;
  1208.   mawk_exit(1) ;
  1209. }
  1210.  
  1211. #endif
  1212.  
  1213. void bozo(s)
  1214.   char *s ;
  1215. { errmsg(0, "bozo: %s" , s) ; mawk_exit(1) ; }
  1216.  
  1217. void overflow(s, size)
  1218.   char *s ; unsigned size ;
  1219. { errmsg(0 , "program limit exceeded: %s size=%u", s, size) ;
  1220.   mawk_exit(1) ; }
  1221.  
  1222. static void check_FILENAME()
  1223. {
  1224.   if ( bi_vars[FILENAME].type != C_STRING )
  1225.           cast1_to_s(bi_vars + FILENAME) ;
  1226.   if ( bi_vars[FNR].type != C_DOUBLE )
  1227.           cast1_to_d(bi_vars + FNR ) ;
  1228.   if ( bi_vars[NR].type != C_DOUBLE )
  1229.           cast1_to_d(bi_vars + NR ) ;
  1230. }
  1231.  
  1232. /* run time */
  1233. void rt_overflow(s, size)
  1234.   char *s ; unsigned size ;
  1235. { check_FILENAME() ;
  1236.   errmsg(0 , 
  1237.   "program limit exceeded: %s size=%u\n\
  1238. \t(FILENAME=\"%s\" FNR=%g NR=%g)", 
  1239.    s, size, string(bi_vars+FILENAME)->str, 
  1240.    bi_vars[FNR].dval,
  1241.    bi_vars[NR].dval) ;
  1242.    mawk_exit(1) ;
  1243. }
  1244.  
  1245. static void unexpected_char()
  1246. { int c = yylval.ival ;
  1247.  
  1248.   fprintf(stderr, "%s: %u: ", progname, token_lineno) ;
  1249.   if ( c > ' ')
  1250.       fprintf(stderr, "unexpected character '%c'\n" , c) ;
  1251.   else
  1252.       fprintf(stderr, "unexpected character 0x%02x\n" , c) ;
  1253. }
  1254.  
  1255. static char *type_to_str( type )
  1256.   int type ;
  1257. { char *retval ;
  1258.  
  1259.   switch( type )
  1260.   {
  1261.     case  ST_VAR :  retval = "variable" ; break ;
  1262.     case  ST_ARRAY :  retval = "array" ; break ;
  1263.     case  ST_FUNCT :  retval = "function" ; break ;
  1264.     case  ST_LOCAL_VAR : retval = "local variable" ; break ;
  1265.     case  ST_LOCAL_ARRAY : retval = "local array" ; break ;
  1266.     default : bozo("type_to_str") ;
  1267.   }
  1268.   return retval ;
  1269. }
  1270.  
  1271. /* emit an error message about a type clash */
  1272. void type_error(p)
  1273.   SYMTAB *p ;
  1274. { compile_error("illegal reference to %s %s", 
  1275.     type_to_str(p->type) , p->name) ;
  1276. }
  1277.  
  1278.  
  1279. @//E*O*F mawk0.97/error.c//
  1280. chmod u=rw,g=r,o=r mawk0.97/error.c
  1281.  
  1282. echo x - mawk0.97/execute.c
  1283. sed 's/^@//' > "mawk0.97/execute.c" <<'@//E*O*F mawk0.97/execute.c//'
  1284.  
  1285. /********************************************
  1286. execute.c
  1287. copyright 1991, Michael D. Brennan
  1288.  
  1289. This is a source file for mawk, an implementation of
  1290. the Awk programming language as defined in
  1291. Aho, Kernighan and Weinberger, The AWK Programming Language,
  1292. Addison-Wesley, 1988.
  1293.  
  1294. See the accompaning file, LIMITATIONS, for restrictions
  1295. regarding modification and redistribution of this
  1296. program in source or binary form.
  1297. ********************************************/
  1298.  
  1299. /* $Log:    execute.c,v $
  1300.  * Revision 2.2  91/04/09  12:38:54  brennan
  1301.  * added static to funct decls to satisfy STARDENT compiler
  1302.  * 
  1303.  * Revision 2.1  91/04/08  08:22:55  brennan
  1304.  * VERSION 0.97
  1305.  * 
  1306. */
  1307.  
  1308.  
  1309. #include "mawk.h"
  1310. #include "code.h"
  1311. #include "memory.h"
  1312. #include "symtype.h"
  1313. #include "field.h"
  1314. #include "bi_funct.h"
  1315. #include "regexp.h"
  1316. #include "repl.h"
  1317. #include <math.h>
  1318.  
  1319. /* static functions */
  1320. static int PROTO( compare, (CELL *) ) ;
  1321. static void PROTO( eval_overflow, (void) ) ;
  1322.  
  1323. #ifdef   DEBUG
  1324. #define  inc_sp()   if( ++sp == eval_stack+EVAL_STACK_SIZE )\
  1325.                          eval_overflow()
  1326. #else
  1327.  
  1328. /* If things are working, the only reason the eval stack should
  1329.    overflow is too much function recursion
  1330.    (checked for at _CALL below  */
  1331.  
  1332. #define inc_sp()    sp++
  1333. #endif
  1334.  
  1335. #define  SAFETY    3    /* if we get within 3 of stack top emit 
  1336.          overflow */
  1337.  
  1338. /*  The stack machine that executes the code */
  1339.  
  1340. CELL  eval_stack[EVAL_STACK_SIZE] ;
  1341.  
  1342. static void eval_overflow()
  1343. { overflow("eval stack" , EVAL_STACK_SIZE) ; mawk_exit(1) ; }
  1344.  
  1345. /* if this flag is on, recursive calls to execute need to
  1346.    return to the _CALL statement.  This only happens
  1347.    inside array loops */
  1348. int  returning ;  
  1349.  
  1350. INST  *execute(cdp, sp, fp)
  1351.   register INST *cdp ;  /* code ptr, start execution here */
  1352.   register CELL *sp ;   /* eval_stack pointer */
  1353.   CELL *fp ;            /* frame ptr into eval_stack for
  1354.                            user defined functions */
  1355.   /* some useful temporaries */
  1356.   CELL *cp , tc ;
  1357.   int t ;
  1358.  
  1359. #ifdef  DEBUG
  1360.   CELL *entry_sp = sp ;
  1361. #endif
  1362.  
  1363.   while ( 1 )
  1364.     switch( cdp++ -> op )
  1365.     {   case  _HALT :
  1366.         case  _STOP :  
  1367.  
  1368. #ifdef   DEBUG
  1369. /* check the stack is sane */
  1370.                 if ( sp != entry_sp ) bozo("stop") ;
  1371.                 return cdp - 1 ;
  1372.  
  1373.         case  _STOP0  : /* if debugging stops range patterns */
  1374.                 if ( sp != entry_sp+1 ) bozo("stop0") ;
  1375. #else
  1376.         case  _STOP0  :
  1377. #endif
  1378.                 return cdp -  1 ;
  1379.  
  1380.         case  _PUSHC :  
  1381.             inc_sp() ;
  1382.             (void) cellcpy(sp, cdp++ -> ptr) ;
  1383.             break ;
  1384.  
  1385.         case  F_PUSHA :
  1386.             if ( (CELL*)cdp->ptr != field && nf < 0 ) split_field0() ;
  1387.             /* fall thru */
  1388.  
  1389.         case  _PUSHA :
  1390.         case  A_PUSHA :
  1391.             inc_sp() ;
  1392.             sp -> ptr = cdp++ -> ptr ;
  1393.             break ;
  1394.  
  1395.         case _PUSHI :  /* put contents of next address on stack*/
  1396.             inc_sp() ;
  1397.             (void) cellcpy(sp, cdp++ -> ptr) ;
  1398.             break ;
  1399.             
  1400.         case L_PUSHI :  
  1401.             /* put the contents of a local var on stack,
  1402.                cdp->op holds the offset from the frame pointer */
  1403.             inc_sp() ;
  1404.             (void) cellcpy(sp, fp + cdp++->op) ;
  1405.             break ;
  1406.  
  1407.         case L_PUSHA : /* put a local address on eval stack */
  1408.             inc_sp() ;
  1409.             sp->ptr = (PTR)(fp + cdp++->op) ;
  1410.             break ;
  1411.  
  1412.  
  1413.         case F_PUSHI :
  1414.  
  1415.         /* note $0 , RS , FS and OFMT are loaded by _PUSHI */
  1416.  
  1417.             inc_sp() ;
  1418.             if ( nf < 0 )  split_field0() ;
  1419.             if ( (t = (CELL *) cdp->ptr - field) <= nf ||
  1420.                   t == NF  )
  1421.             { (void) cellcpy(sp, cdp++ -> ptr) ; }
  1422.             else  /* an unset field */
  1423.             { sp->type = C_STRING ;
  1424.               sp->ptr = (PTR) & null_str ;
  1425.               null_str.ref_cnt++ ;
  1426.               cdp++ ;
  1427.             }
  1428.             break ;
  1429.  
  1430.         case  FE_PUSHA :
  1431.             if ( sp->type != C_DOUBLE )  cast1_to_d(sp) ;
  1432.             if ( (t = (int) sp->dval) < 0 )
  1433.                 rt_error( "negative field index(%d)", t) ;
  1434.             if ( t > MAX_FIELD )
  1435.                 rt_overflow("MAX_FIELD", MAX_FIELD) ;
  1436.             if ( t && nf < 0 )  split_field0() ;
  1437.             sp->ptr = (PTR) &field[t] ;
  1438.             break ;
  1439.  
  1440.         case  FE_PUSHI :
  1441.             if ( sp->type != C_DOUBLE )  cast1_to_d(sp) ;
  1442.  
  1443.             if ( (t = (int) sp->dval) == 0 )
  1444.             { (void) cellcpy(sp, &field[0]) ; break ; }
  1445.  
  1446.             if ( t < 0 )
  1447.                   rt_error( "negative field index(%d)", t) ;
  1448.             if ( t > MAX_FIELD )
  1449.                   rt_overflow("MAX_FIELD", MAX_FIELD) ;
  1450.  
  1451.             if ( nf < 0)  split_field0() ;
  1452.             if ( t <= nf ) (void) cellcpy(sp, &field[t]) ;
  1453.             else
  1454.             { sp->type = C_STRING ;
  1455.               sp->ptr = (PTR) & null_str ;
  1456.               null_str.ref_cnt++ ;
  1457.             }
  1458.             break ; 
  1459.  
  1460.  
  1461.         case  AE_PUSHA :
  1462.         /* top of stack has an expr, cdp->ptr points at an
  1463.            array, replace the expr with the cell address inside
  1464.            the array */
  1465.             cast1_to_s(sp) ;
  1466.             cp = array_find((ARRAY)cdp++->ptr, sp->ptr, 0) ;
  1467.             free_STRING( string(sp) );
  1468.             sp->ptr = (PTR) cp ;
  1469.             break ;
  1470.  
  1471.         case  AE_PUSHI :
  1472.         /* top of stack has an expr, cdp->ptr points at an
  1473.            array, replace the expr with the contents of the
  1474.            cell inside the array */
  1475.             cast1_to_s(sp) ;
  1476.             cp = array_find((ARRAY) cdp++->ptr, sp->ptr, 0) ;
  1477.             free_STRING(string(sp)) ;
  1478.             (void) cellcpy(sp, cp) ;
  1479.             break ;
  1480.  
  1481.         case  LAE_PUSHI :
  1482.         /*  sp[0] is an expression
  1483.             cdp->op is offset from frame pointer of a CELL which
  1484.                has an ARRAY in the ptr field, replace expr
  1485.             with  array[expr]
  1486.         */
  1487.             cast1_to_s(sp) ;
  1488.             cp = array_find( (ARRAY)fp[cdp++->op].ptr, sp->ptr, 0) ;
  1489.             free_STRING(string(sp)) ;
  1490.             (void) cellcpy(sp, cp) ;
  1491.             break ;
  1492.             
  1493.         case  LAE_PUSHA :
  1494.         /*  sp[0] is an expression
  1495.             cdp->op is offset from frame pointer of a CELL which
  1496.                has an ARRAY in the ptr field, replace expr
  1497.             with  & array[expr]
  1498.         */
  1499.             cast1_to_s(sp) ;
  1500.             cp = array_find( (ARRAY)fp[cdp++->op].ptr, sp->ptr, 0) ;
  1501.             free_STRING(string(sp)) ;
  1502.             sp->ptr = (PTR) cp ;
  1503.             break ;
  1504.             
  1505.         case  LA_PUSHA  :
  1506.         /*  cdp->op is offset from frame pointer of a CELL which
  1507.                has an ARRAY in the ptr field. Push this ARRAY
  1508.                on the eval stack
  1509.         */
  1510.             inc_sp() ;
  1511.             sp->ptr = fp[cdp++->op].ptr ;
  1512.             break ;
  1513.  
  1514.         case  A_LOOP :
  1515.             cdp = array_loop(cdp,sp,fp) ;
  1516.             if ( returning ) return cdp ; /*value doesn't matter*/
  1517.             sp -= 2 ;
  1518.             break ;
  1519.  
  1520.         case  _POP : 
  1521.             cell_destroy(sp) ;
  1522.             sp-- ;
  1523.             break ;
  1524.  
  1525.         case _DUP  :
  1526.             (void) cellcpy(sp+1, sp) ;
  1527.             sp++ ; break ;
  1528.  
  1529.         case  _ASSIGN :
  1530.             /* top of stack has an expr, next down is an
  1531.                address, put the expression in *address and
  1532.                replace the address with the expression */
  1533.  
  1534.             /* don't propagate type C_MBSTRN */
  1535.             if ( sp->type == C_MBSTRN ) check_strnum(sp) ;
  1536.             sp-- ;
  1537.             cell_destroy( ((CELL *)sp->ptr) ) ;
  1538.             (void) cellcpy( sp, cellcpy(sp->ptr, sp+1) ) ;
  1539.             cell_destroy(sp+1) ;
  1540.             break ;
  1541.  
  1542.         case  F_ASSIGN : /* assign to a field  */
  1543.             if (sp->type == C_MBSTRN) check_strnum(sp) ;
  1544.             sp-- ;
  1545.             field_assign((CELL*)sp->ptr - field, sp+1) ;
  1546.             cell_destroy(sp+1) ;
  1547.             (void) cellcpy(sp, (CELL *) sp->ptr) ;
  1548.             break ;
  1549.  
  1550.         case  _ADD_ASG:
  1551.             if ( sp->type != C_DOUBLE ) cast1_to_d(sp) ;
  1552.             cp = (CELL *) (sp-1)->ptr ;
  1553.             if ( cp->type != C_DOUBLE ) cast1_to_d(cp) ;
  1554.             cp->dval += sp-- -> dval ;
  1555.             sp->type = C_DOUBLE ;
  1556.             sp->dval = cp->dval ;
  1557.             break ;
  1558.  
  1559.         case  _SUB_ASG:
  1560.             if ( sp->type != C_DOUBLE ) cast1_to_d(sp) ;
  1561.             cp = (CELL *) (sp-1)->ptr ;
  1562.             if ( cp->type != C_DOUBLE ) cast1_to_d(cp) ;
  1563.             cp->dval -= sp-- -> dval ;
  1564.             sp->type = C_DOUBLE ;
  1565.             sp->dval = cp->dval ;
  1566.             break ;
  1567.  
  1568.         case  _MUL_ASG:
  1569.             if ( sp->type != C_DOUBLE ) cast1_to_d(sp) ;
  1570.             cp = (CELL *) (sp-1)->ptr ;
  1571.             if ( cp->type != C_DOUBLE ) cast1_to_d(cp) ;
  1572.             cp->dval *= sp-- -> dval ;
  1573.             sp->type = C_DOUBLE ;
  1574.             sp->dval = cp->dval ;
  1575.             break ;
  1576.  
  1577.         case  _DIV_ASG:
  1578.             if ( sp->type != C_DOUBLE ) cast1_to_d(sp) ;
  1579.             cp = (CELL *) (sp-1)->ptr ;
  1580.             if ( cp->type != C_DOUBLE ) cast1_to_d(cp) ;
  1581.             cp->dval /= sp-- -> dval ;
  1582.             sp->type = C_DOUBLE ;
  1583.             sp->dval = cp->dval ;
  1584.             break ;
  1585.  
  1586.         case  _MOD_ASG:
  1587.             if ( sp->type != C_DOUBLE ) cast1_to_d(sp) ;
  1588.             cp = (CELL *) (sp-1)->ptr ;
  1589.             if ( cp->type != C_DOUBLE ) cast1_to_d(cp) ;
  1590.             cp->dval = fmod(cp->dval,sp-- -> dval) ;
  1591.             sp->type = C_DOUBLE ;
  1592.             sp->dval = cp->dval ;
  1593.             break ;
  1594.  
  1595.         case  _POW_ASG:
  1596.             if ( sp->type != C_DOUBLE ) cast1_to_d(sp) ;
  1597.             cp = (CELL *) (sp-1)->ptr ;
  1598.             if ( cp->type != C_DOUBLE ) cast1_to_d(cp) ;
  1599.             cp->dval = pow(cp->dval,sp-- -> dval) ;
  1600.             sp->type = C_DOUBLE ;
  1601.             sp->dval = cp->dval ;
  1602.             break ;
  1603.  
  1604.         /* will anyone ever use these ? */
  1605.  
  1606.         case F_ADD_ASG :
  1607.             if ( sp->type != C_DOUBLE ) cast1_to_d(sp) ;
  1608.             cp = (CELL *) (sp-1)->ptr ;
  1609.             cast1_to_d( cellcpy(&tc, cp) ) ;
  1610.             tc.dval += sp-- -> dval ;
  1611.             sp->type = C_DOUBLE ;
  1612.             sp->dval = tc.dval ;
  1613.             field_assign(cp-field, &tc) ;
  1614.             break ;
  1615.  
  1616.         case F_SUB_ASG :
  1617.             if ( sp->type != C_DOUBLE ) cast1_to_d(sp) ;
  1618.             cp = (CELL *) (sp-1)->ptr ;
  1619.             cast1_to_d( cellcpy(&tc, cp) ) ;
  1620.             tc.dval -= sp-- -> dval ;
  1621.             sp->type = C_DOUBLE ;
  1622.             sp->dval = tc.dval ;
  1623.             field_assign(cp-field, &tc) ;
  1624.             break ;
  1625.  
  1626.         case F_MUL_ASG :
  1627.             if ( sp->type != C_DOUBLE ) cast1_to_d(sp) ;
  1628.             cp = (CELL *) (sp-1)->ptr ;
  1629.             cast1_to_d( cellcpy(&tc, cp) ) ;
  1630.             tc.dval *= sp-- -> dval ;
  1631.             sp->type = C_DOUBLE ;
  1632.             sp->dval = tc.dval ;
  1633.             field_assign(cp-field, &tc) ;
  1634.             break ;
  1635.  
  1636.         case F_DIV_ASG :
  1637.             if ( sp->type != C_DOUBLE ) cast1_to_d(sp) ;
  1638.             cp = (CELL *) (sp-1)->ptr ;
  1639.             cast1_to_d( cellcpy(&tc, cp) ) ;
  1640.             tc.dval /= sp-- -> dval ;
  1641.             sp->type = C_DOUBLE ;
  1642.             sp->dval = tc.dval ;
  1643.             field_assign(cp-field, &tc) ;
  1644.             break ;
  1645.  
  1646.         case F_MOD_ASG :
  1647.             if ( sp->type != C_DOUBLE ) cast1_to_d(sp) ;
  1648.             cp = (CELL *) (sp-1)->ptr ;
  1649.             cast1_to_d( cellcpy(&tc, cp) ) ;
  1650.             tc.dval = fmod(tc.dval, sp-- -> dval) ;
  1651.             sp->type = C_DOUBLE ;
  1652.             sp->dval = tc.dval ;
  1653.             field_assign(cp-field, &tc) ;
  1654.             break ;
  1655.  
  1656.         case F_POW_ASG :
  1657.             if ( sp->type != C_DOUBLE ) cast1_to_d(sp) ;
  1658.             cp = (CELL *) (sp-1)->ptr ;
  1659.             cast1_to_d( cellcpy(&tc, cp) ) ;
  1660.             tc.dval = pow(tc.dval, sp-- -> dval) ;
  1661.             sp->type = C_DOUBLE ;
  1662.             sp->dval = tc.dval ;
  1663.             field_assign(cp-field, &tc) ;
  1664.             break ;
  1665.  
  1666.         case _ADD :
  1667.             sp-- ;
  1668.             if ( TEST2(sp) != TWO_DOUBLES )
  1669.                     cast2_to_d(sp) ;
  1670.             sp[0].dval += sp[1].dval ;
  1671.             break ;
  1672.  
  1673.         case _SUB :
  1674.             sp-- ;
  1675.             if ( TEST2(sp) != TWO_DOUBLES )
  1676.                     cast2_to_d(sp) ;
  1677.             sp[0].dval -= sp[1].dval ;
  1678.             break ;
  1679.  
  1680.         case _MUL :
  1681.             sp-- ;
  1682.             if ( TEST2(sp) != TWO_DOUBLES )
  1683.                     cast2_to_d(sp) ;
  1684.             sp[0].dval *= sp[1].dval ;
  1685.             break ;
  1686.  
  1687.         case _DIV :
  1688.             sp-- ;
  1689.             if ( TEST2(sp) != TWO_DOUBLES )
  1690.                     cast2_to_d(sp) ;
  1691.             sp[0].dval /= sp[1].dval ;
  1692.             break ;
  1693.  
  1694.         case _MOD :
  1695.             sp-- ;
  1696.             if ( TEST2(sp) != TWO_DOUBLES )
  1697.                     cast2_to_d(sp) ;
  1698.             sp[0].dval = fmod(sp[0].dval,sp[1].dval) ;
  1699.             break ;
  1700.  
  1701.         case _POW :
  1702.             sp-- ;
  1703.             if ( TEST2(sp) != TWO_DOUBLES )
  1704.                     cast2_to_d(sp) ;
  1705.             sp[0].dval = pow(sp[0].dval,sp[1].dval) ;
  1706.             break ;
  1707.  
  1708.         case _NOT :
  1709.         reswitch_1:
  1710.             switch( sp->type )
  1711.             { case C_NOINIT :
  1712.                     sp->dval = 1.0 ; break ;
  1713.               case C_DOUBLE :
  1714.                     sp->dval =  sp->dval ? 0.0 : 1.0 ;
  1715.                     break ;
  1716.               case C_STRING :
  1717.                     sp->dval = string(sp)->len ? 0.0 : 1.0 ;
  1718.                     free_STRING(string(sp)) ;
  1719.                     break ;
  1720.               case C_STRNUM : /* test as a number */
  1721.                     sp->dval = sp->dval ? 0.0 : 1.0 ;
  1722.                     free_STRING(string(sp)) ;
  1723.                     break ;
  1724.               case C_MBSTRN :
  1725.                     check_strnum(sp) ;
  1726.                     goto reswitch_1 ;
  1727.               default :
  1728.                     bozo("bad type on eval stack") ;
  1729.             }
  1730.             sp->type = C_DOUBLE ;
  1731.             break  ;
  1732.  
  1733.         case _TEST :
  1734.         reswitch_2:
  1735.             switch( sp->type )
  1736.             { case C_NOINIT :
  1737.                     sp->dval = 0.0 ; break ;
  1738.               case C_DOUBLE :
  1739.                     sp->dval = sp->dval ? 1.0 : 0.0 ;
  1740.                     break ;
  1741.               case C_STRING :
  1742.                     sp->dval  = string(sp)->len ? 1.0 : 0.0 ;
  1743.                     free_STRING(string(sp)) ;
  1744.                     break ;
  1745.               case C_STRNUM : /* test as a number */
  1746.                     sp->dval  = sp->dval ? 0.0 : 1.0 ;
  1747.                     free_STRING(string(sp)) ;
  1748.                     break ;
  1749.               case C_MBSTRN :
  1750.                     check_strnum(sp) ;
  1751.                     goto reswitch_2 ;
  1752.               default :
  1753.                     bozo("bad type on eval stack") ;
  1754.             }
  1755.             sp->type = C_DOUBLE ;
  1756.             break ;
  1757.  
  1758.         case _UMINUS :
  1759.             if ( sp->type != C_DOUBLE ) cast1_to_d(sp) ;
  1760.             sp->dval = - sp->dval ;
  1761.             break ;
  1762.  
  1763.         case _UPLUS :  
  1764.             if ( sp->type != C_DOUBLE ) cast1_to_d(sp) ;
  1765.             break ;
  1766.  
  1767.         case _CAT :
  1768.             { unsigned len1, len2 ;
  1769.               char *str1, *str2 ;
  1770.               STRING *b ;
  1771.               
  1772.               sp-- ;
  1773.               if ( TEST2(sp) != TWO_STRINGS )
  1774.                     cast2_to_s(sp) ;
  1775.               str1 = string(sp)->str ;
  1776.               len1 = string(sp)->len ;
  1777.               str2 = string(sp+1)->str ;
  1778.               len2 = string(sp+1)->len ;
  1779.  
  1780.               b = new_STRING((char *)0, len1+len2) ;
  1781.               (void) memcpy(b->str, str1, len1) ;
  1782.               (void) memcpy(b->str + len1, str2, len2) ;
  1783.               free_STRING(string(sp)) ;
  1784.               free_STRING( string(sp+1) ) ;
  1785.  
  1786.               sp->ptr = (PTR) b ;
  1787.               break ;
  1788.             }
  1789.  
  1790.         case _PUSHINT :
  1791.             inc_sp() ;
  1792.             sp->type = cdp++ -> op ;
  1793.             break ;
  1794.  
  1795.         case _BUILTIN :
  1796.         case _PRINT :
  1797.             sp = (* (PF_CP) cdp++ -> ptr) (sp) ;
  1798.             break ;
  1799.  
  1800.         case _POST_INC :
  1801.             (void) cellcpy(sp, cp = (CELL *)sp->ptr) ;
  1802.             if ( cp->type != C_DOUBLE ) cast1_to_d(cp) ;
  1803.             cp->dval += 1.0 ;
  1804.             break ;
  1805.  
  1806.         case _POST_DEC :
  1807.             (void) cellcpy(sp, cp = (CELL *)sp->ptr) ;
  1808.             if ( cp->type != C_DOUBLE ) cast1_to_d(cp) ;
  1809.             cp->dval -= 1.0 ;
  1810.             break ;
  1811.  
  1812.         case _PRE_INC :
  1813.             cp = (CELL *) sp->ptr ;
  1814.             if ( cp->type != C_DOUBLE ) cast1_to_d(cp) ;
  1815.             sp->dval = cp->dval += 1.0 ;
  1816.             sp->type = C_DOUBLE ;
  1817.             break ;
  1818.  
  1819.         case _PRE_DEC :
  1820.             cp = (CELL *) sp->ptr ;
  1821.             if ( cp->type != C_DOUBLE ) cast1_to_d(cp) ;
  1822.             sp->dval = cp->dval -= 1.0 ;
  1823.             sp->type = C_DOUBLE ;
  1824.             break ;
  1825.  
  1826.  
  1827.         case F_POST_INC  :
  1828.             cp = (CELL *) sp->ptr ;
  1829.             (void) cellcpy(sp, cellcpy(&tc, cp) ) ;
  1830.             cast1_to_d(&tc) ;
  1831.             tc.dval += 1.0 ;
  1832.             field_assign(cp-field, &tc) ;
  1833.             break ;
  1834.  
  1835.         case F_POST_DEC  :
  1836.             cp = (CELL *) sp->ptr ;
  1837.             (void) cellcpy(sp, cellcpy(&tc, cp) ) ;
  1838.             cast1_to_d(&tc) ;
  1839.             tc.dval -= 1.0 ;
  1840.             field_assign(cp-field, &tc) ;
  1841.             break ;
  1842.  
  1843.         case F_PRE_INC :
  1844.             cp = (CELL *) sp->ptr ;
  1845.             cast1_to_d(cellcpy(&tc, cp)) ;
  1846.             sp->dval = tc.dval += 1.0 ;
  1847.             sp->type = C_DOUBLE ;
  1848.             field_assign(cp-field, sp) ;
  1849.             break ;
  1850.  
  1851.         case F_PRE_DEC :
  1852.             cp = (CELL *) sp->ptr ;
  1853.             cast1_to_d(cellcpy(&tc, cp)) ;
  1854.             sp->dval = tc.dval -= 1.0 ;
  1855.             sp->type = C_DOUBLE ;
  1856.             field_assign(cp-field, sp) ;
  1857.             break ;
  1858.  
  1859.         case _JMP  :
  1860.             cdp += cdp->op - 1 ;
  1861.             break ;
  1862.  
  1863.         case _JNZ  :
  1864.             /* jmp if top of stack is non-zero and pop stack */
  1865.             if ( test( sp ) )
  1866.                 cdp += cdp->op - 1 ;
  1867.             else  cdp++ ;
  1868.             cell_destroy(sp) ;
  1869.             sp-- ;
  1870.             break ;
  1871.  
  1872.         case _JZ  :
  1873.             /* jmp if top of stack is zero and pop stack */
  1874.             if ( ! test( sp ) )
  1875.                 cdp += cdp->op - 1 ;
  1876.             else  cdp++ ;
  1877.             cell_destroy(sp) ;
  1878.             sp-- ;
  1879.             break ;
  1880.  
  1881.     /*  the relation operations */
  1882.     /*  compare() makes sure string ref counts are OK */
  1883.         case  _EQ :
  1884.             t = compare(--sp) ;
  1885.             sp->type = C_DOUBLE ;
  1886.             sp->dval = t == 0 ? 1.0 : 0.0 ;
  1887.             break ;
  1888.  
  1889.         case  _NEQ :
  1890.             t = compare(--sp) ;
  1891.             sp->type = C_DOUBLE ;
  1892.             sp->dval = t ? 1.0 : 0.0 ;
  1893.             break ;
  1894.  
  1895.         case  _LT :
  1896.             t = compare(--sp) ;
  1897.             sp->type = C_DOUBLE ;
  1898.             sp->dval = t < 0 ? 1.0 : 0.0 ;
  1899.             break ;
  1900.  
  1901.         case  _LTE :
  1902.             t = compare(--sp) ;
  1903.             sp->type = C_DOUBLE ;
  1904.             sp->dval = t <= 0 ? 1.0 : 0.0 ;
  1905.             break ;
  1906.  
  1907.         case  _GT :
  1908.             t = compare(--sp) ;
  1909.             sp->type = C_DOUBLE ;
  1910.             sp->dval = t > 0 ? 1.0 : 0.0 ;
  1911.             break ;
  1912.  
  1913.         case  _GTE :
  1914.             t = compare(--sp) ;
  1915.             sp->type = C_DOUBLE ;
  1916.             sp->dval = t >= 0 ? 1.0 : 0.0 ;
  1917.             break ;
  1918.  
  1919.         case  _MATCH :
  1920.             /* does sp[-1] match sp[0] as re */
  1921.             if ( sp->type != C_RE )  cast_to_RE(sp) ;
  1922.  
  1923.             if ( (--sp)->type < C_STRING )  cast1_to_s(sp) ;
  1924.             t = REtest(string(sp)->str, (sp+1)->ptr) ; 
  1925.  
  1926.             free_STRING(string(sp)) ;
  1927.             sp->type = C_DOUBLE ;
  1928.             sp->dval = t ? 1.0 : 0.0 ;
  1929.             break ;
  1930.  
  1931.         case  A_TEST :
  1932.         /* entry :  sp[0].ptr-> an array
  1933.                     sp[-1]  is an expression
  1934.  
  1935.            we compute   expression in array  */
  1936.             if ( (--sp)->type < C_STRING ) cast1_to_s(sp) ;
  1937.             t = array_test( (sp+1)->ptr, string(sp)) ;
  1938.             free_STRING(string(sp)) ;
  1939.             sp->type = C_DOUBLE ;
  1940.             sp->dval = t ? 1.0 : 0.0 ;
  1941.             break ;
  1942.  
  1943.         case  A_DEL :
  1944.         /* sp[0].ptr ->  array)
  1945.            sp[-1] is an expr
  1946.            delete  array[expr]  */
  1947.  
  1948.             cast1_to_s(--sp) ;
  1949.             array_delete( sp[1].ptr , sp->ptr) ;
  1950.             free_STRING( string(sp) ) ;
  1951.             sp-- ;
  1952.             break ;
  1953.         
  1954.         /* form a multiple array index */
  1955.         case A_CAT :
  1956.             sp = array_cat(sp, cdp++->op) ;
  1957.             break ;
  1958.  
  1959.         case  _EXIT0 :
  1960.             longjmp( exit_jump, 1) ;
  1961.  
  1962.         case  _EXIT  :
  1963.             if ( sp->type != C_DOUBLE ) cast1_to_d(sp) ;
  1964.             exit_code = (int) sp->dval ;
  1965.             longjmp( exit_jump, 1) ;
  1966.  
  1967.         case  _NEXT :
  1968.             longjmp(next_jump, 1) ;
  1969.  
  1970.         case  _RANGE :
  1971. /* test a range pattern:  pat1, pat2 { action }
  1972.    entry :
  1973.        cdp[0].op -- a flag, test pat1 if on else pat2
  1974.        cdp[1].op -- offset of pat2 code from cdp
  1975.        cdp[2].op -- offset of action code from cdp
  1976.        cdp[3].op -- offset of code after the action from cdp
  1977.        cdp[4] -- start of pat1 code
  1978. */
  1979.  
  1980. #define FLAG    cdp[0].op
  1981. #define PAT2    cdp[1].op
  1982. #define ACTION    cdp[2].op
  1983. #define FOLLOW    cdp[3].op
  1984. #define PAT1      4
  1985.  
  1986.             if ( FLAG )  /* test again pat1 */
  1987.             { 
  1988.               (void) execute(cdp + PAT1,sp, fp) ;
  1989.               t = test(sp+1) ;
  1990.               cell_destroy(sp+1) ;
  1991.               if ( t )  FLAG = 0 ;
  1992.               else
  1993.               { cdp += FOLLOW ;
  1994.                 break ;  /* break the switch */
  1995.               }
  1996.             }
  1997.  
  1998.             /* test against pat2 and then perform the action */
  1999.             (void) execute(cdp + PAT2, sp, fp) ;
  2000.             FLAG  = test(sp+1) ;
  2001.             cell_destroy(sp+1) ; 
  2002.             cdp += ACTION ;
  2003.             break ;
  2004.  
  2005. /* function calls  */
  2006.  
  2007.       case  _RET0  :
  2008.             inc_sp() ;
  2009.             sp->type = C_NOINIT ;
  2010.             /* fall thru */
  2011.  
  2012.       case  _RET   :
  2013.  
  2014. #ifdef  DEBUG
  2015.             if ( sp != entry_sp+1 ) bozo("ret") ;
  2016. #endif
  2017.             returning = 1 ;
  2018.             return  cdp-1 ;
  2019.  
  2020.       case  _CALL  :
  2021.  
  2022.             { FBLOCK *fbp = (FBLOCK*) cdp++->ptr ;
  2023.               int a_args = cdp++->op ; /* actual number of args */
  2024.               CELL *nfp = sp - a_args + 1 ; /* new fp for callee */
  2025.               CELL *local_p = sp+1; /* first local argument on stack */
  2026.               char *type_p ;  /* pts to type of an argument */
  2027.  
  2028.               if ( fbp->nargs ) type_p = fbp->typev + a_args ;
  2029.  
  2030.               /* create space for locals */
  2031.               if ( t = fbp->nargs - a_args ) /* have local args */
  2032.               {
  2033.                 if ( sp + t >= eval_stack + EVAL_STACK_SIZE - SAFETY )
  2034.                    eval_overflow() ;
  2035.  
  2036.                 while ( t-- )  
  2037.                 { (++sp)->type = C_NOINIT ;
  2038.                   if ( *type_p++ == ST_LOCAL_ARRAY )
  2039.                         sp->ptr = (PTR) new_ARRAY() ;
  2040.                 }
  2041.               }
  2042.               type_p-- ; /* *type_p is type of last arg */ 
  2043.  
  2044.               (void) execute(fbp->code, sp, nfp) ;
  2045. #ifdef  DEBUG
  2046. if ( !returning )  bozo("call") ;
  2047. #endif
  2048.               returning = 0 ;
  2049.  
  2050.               /* cleanup the callee's arguments */
  2051.               if ( sp >= nfp ) 
  2052.               {
  2053.                 cp = sp+1 ;  /* cp -> the function return */
  2054.  
  2055.                 do
  2056.                 {
  2057.                   if ( *type_p-- == ST_LOCAL_ARRAY )
  2058.                   {  if ( sp >= local_p ) array_free(sp->ptr) ; }
  2059.                   else  cell_destroy(sp) ;
  2060.  
  2061.                 } while ( --sp >= nfp ) ;
  2062.                     
  2063.                 (void) cellcpy(++sp, cp) ;
  2064.                 cell_destroy(cp) ;
  2065.               }
  2066.               else  sp++ ; /* no arguments passed */
  2067.             }
  2068.             break ;
  2069.  
  2070.         default :
  2071.             bozo("bad opcode") ;
  2072.     }
  2073. }
  2074.  
  2075. int test( cp )  /* test if a cell is null or not */
  2076.   register CELL *cp ;
  2077. reswitch :
  2078.  
  2079.   switch ( cp->type )
  2080.   {
  2081.     case C_NOINIT :  return  0 ;
  2082.     case C_STRNUM :  /* test as a number */
  2083.     case C_DOUBLE :  return  cp->dval != 0.0 ;
  2084.     case C_STRING :  return  string(cp)->len ;
  2085.     case C_MBSTRN :  check_strnum(cp) ; goto reswitch ;
  2086.  
  2087.     default :
  2088.       bozo("bad cell type in call to test") ;
  2089.   }
  2090. }
  2091.  
  2092. /* compare cells at cp and cp+1 and
  2093.    frees STRINGs at those cells
  2094. */
  2095.  
  2096. static int compare(cp)
  2097.   register CELL *cp ;
  2098. { int k ;
  2099.  
  2100. reswitch :
  2101.  
  2102.   switch( TEST2(cp) )
  2103.   { case TWO_NOINITS :  return 0 ; 
  2104.     
  2105.     case TWO_DOUBLES :
  2106.     two_d:
  2107.             return  cp->dval > (cp+1)->dval ? 1 :
  2108.                     cp->dval < (cp+1)->dval ? -1 : 0 ;
  2109.     
  2110.     case TWO_STRINGS :
  2111.     case STRING_AND_STRNUM :
  2112.     two_s:
  2113.             k = strcmp(string(cp)->str, string(cp+1)->str) ;
  2114.             free_STRING( string(cp) ) ;
  2115.             free_STRING( string(cp+1) ) ;
  2116.             return k ;
  2117.  
  2118.     case  NOINIT_AND_DOUBLE  :
  2119.     case  NOINIT_AND_STRNUM  :
  2120.     case  DOUBLE_AND_STRNUM  :
  2121.     case TWO_STRNUMS :
  2122.             cast2_to_d(cp) ; goto two_d ;
  2123.  
  2124.     case  NOINIT_AND_STRING  :
  2125.     case  DOUBLE_AND_STRING  :
  2126.             cast2_to_s(cp) ; goto two_s ;
  2127.  
  2128.     case  TWO_MBSTRNS :
  2129.             check_strnum(cp) ; check_strnum(cp+1) ;
  2130.             goto reswitch ;
  2131.  
  2132.     case  NOINIT_AND_MBSTRN :
  2133.     case  DOUBLE_AND_MBSTRN :
  2134.     case  STRING_AND_MBSTRN :
  2135.     case  STRNUM_AND_MBSTRN :
  2136.             check_strnum( cp->type == C_MBSTRN ? cp : cp+1 ) ;
  2137.             goto reswitch ;
  2138.  
  2139.     default :  /* there are no default cases */
  2140.             bozo("bad cell type passed to compare") ;
  2141.   }
  2142. }
  2143.  
  2144. /* does not assume target was a cell, if so
  2145.    then caller should have made a previous
  2146.    call to cell_destroy  */
  2147.  
  2148. CELL *cellcpy(target, source)
  2149.   register CELL *target, *source ;
  2150. { switch( target->type = source->type )
  2151.   { case C_NOINIT : 
  2152.     case C_SPACE  : 
  2153.     case C_SNULL  :
  2154.             break ;
  2155.  
  2156.     case C_DOUBLE :
  2157.             target->dval = source->dval ;
  2158.             break ;
  2159.  
  2160.     case C_STRNUM :
  2161.             target->dval = source->dval ;
  2162.             /* fall thru */
  2163.  
  2164.     case C_REPL    :
  2165.     case C_MBSTRN  :
  2166.     case C_STRING  :
  2167.             string(source)->ref_cnt++ ;
  2168.             /* fall thru */
  2169.  
  2170.     case C_RE  :
  2171.             target->ptr = source->ptr ;
  2172.             break ;
  2173.  
  2174.     case  C_REPLV :
  2175.             (void)  replv_cpy(target, source) ;
  2176.             break ;
  2177.  
  2178.     default :
  2179.             bozo("bad cell passed to cellcpy()") ;
  2180.             break ;
  2181.   }
  2182.   return  target ;
  2183. }
  2184.  
  2185. #ifdef   DEBUG
  2186.  
  2187. void  DB_cell_destroy(cp)    /* HANGOVER time */
  2188.   register CELL *cp ;
  2189. {
  2190.   switch( cp->type )
  2191.   { case C_NOINIT :
  2192.     case C_DOUBLE :  break ;
  2193.  
  2194.     case C_MBSTRN :
  2195.     case C_STRING :
  2196.     case C_STRNUM :
  2197.             if ( -- string(cp)->ref_cnt == 0 )
  2198.                 zfree(string(cp) , string(cp)->len+5) ;
  2199.             break ;
  2200.  
  2201.     case  C_RE :
  2202.             bozo("cell destroy called on RE cell") ;
  2203.     default :
  2204.             bozo("cell destroy called on bad cell type") ;
  2205.   }
  2206. }
  2207.  
  2208. #endif
  2209. @//E*O*F mawk0.97/execute.c//
  2210. chmod u=rw,g=r,o=r mawk0.97/execute.c
  2211.  
  2212. echo x - mawk0.97/fcall.c
  2213. sed 's/^@//' > "mawk0.97/fcall.c" <<'@//E*O*F mawk0.97/fcall.c//'
  2214.  
  2215. /********************************************
  2216. fcall.c
  2217. copyright 1991, Michael D. Brennan
  2218.  
  2219. This is a source file for mawk, an implementation of
  2220. the Awk programming language as defined in
  2221. Aho, Kernighan and Weinberger, The AWK Programming Language,
  2222. Addison-Wesley, 1988.
  2223.  
  2224. See the accompaning file, LIMITATIONS, for restrictions
  2225. regarding modification and redistribution of this
  2226. program in source or binary form.
  2227. ********************************************/
  2228.  
  2229.  
  2230. /*$Log:    fcall.c,v $
  2231.  * Revision 2.1  91/04/08  08:22:59  brennan
  2232.  * VERSION 0.97
  2233.  * 
  2234. */
  2235.  
  2236. #include "mawk.h"
  2237. #include "symtype.h"
  2238. #include "code.h"
  2239.  
  2240. /* This file has functions involved with type checking of
  2241.    function calls
  2242. */
  2243.  
  2244. static  FCALL_REC *PROTO(first_pass, (FCALL_REC *) ) ;
  2245. static  CA_REC    *PROTO(call_arg_check, (FBLOCK *, CA_REC *,
  2246.         INST *, unsigned) ) ;
  2247. static  int PROTO(arg_cnt_ok, (FBLOCK *,CA_REC *, unsigned) ) ;
  2248.  
  2249.  
  2250. static int check_progress ;
  2251.     /* flag that indicates call_arg_check() was able to type
  2252.        check some call arguments */
  2253.  
  2254. /* type checks a list of call arguments,
  2255.    returns a list of arguments whose type is still unknown
  2256. */
  2257. static CA_REC *call_arg_check( callee, entry_list , start,  line_no)
  2258.   FBLOCK *callee ;
  2259.   CA_REC *entry_list  ;  
  2260.   INST  *start ; /* to locate patch */
  2261.   unsigned line_no ; /* for error messages */
  2262. { register CA_REC *q ;
  2263.   CA_REC *exit_list  = (CA_REC *) 0 ;
  2264.  
  2265.   check_progress = 0 ;
  2266.  
  2267.   /* loop :
  2268.        take q off entry_list
  2269.        test it
  2270.            if OK  zfree(q)  else put on exit_list
  2271.   */
  2272.      
  2273.   while ( q = entry_list )
  2274.   {
  2275.     entry_list = q->link ;
  2276.  
  2277.     if ( q->type == ST_NONE )
  2278.     { /* try to infer the type */
  2279.       /* it might now be in symbol table */
  2280.       if ( q->sym_p->type == ST_VAR )
  2281.       { /* set type and patch */
  2282.         q->type = CA_EXPR ;
  2283.         start[q->call_offset+1].ptr  = (PTR) q->sym_p->stval.cp ;
  2284.       }
  2285.       else
  2286.       if ( q->sym_p->type == ST_ARRAY )
  2287.       { q->type = CA_ARRAY ;
  2288.         start[q->call_offset].op = A_PUSHA ;
  2289.         start[q->call_offset+1].ptr = (PTR) q->sym_p->stval.array ;
  2290.       } 
  2291.       else /* try to infer from callee */
  2292.       {
  2293.         switch( callee->typev[q->arg_num] )
  2294.         {
  2295.           case  ST_LOCAL_VAR :
  2296.                 q->type = CA_EXPR ;
  2297.                 q->sym_p->type = ST_VAR ;
  2298.                 q->sym_p->stval.cp = new_CELL() ;
  2299.                 q->sym_p->stval.cp->type = C_NOINIT ;
  2300.                 start[q->call_offset+1].ptr  = 
  2301.                          (PTR) q->sym_p->stval.cp ;
  2302.                 break ;
  2303.  
  2304.           case  ST_LOCAL_ARRAY :
  2305.                 q->type = CA_ARRAY ;
  2306.                 q->sym_p->type = ST_ARRAY ;
  2307.                 q->sym_p->stval.array = new_ARRAY() ;
  2308.                 start[q->call_offset].op = A_PUSHA ;
  2309.                 start[q->call_offset+1].ptr = 
  2310.                       (PTR) q->sym_p->stval.array ;
  2311.                 break ;
  2312.         }
  2313.       }
  2314.     }
  2315.     else
  2316.     if ( q->type == ST_LOCAL_NONE )
  2317.     { /* try to infer the type */
  2318.       if ( * q->type_p == ST_LOCAL_VAR )
  2319.       { /* set type , don't need to patch */
  2320.         q->type = CA_EXPR ;
  2321.       }
  2322.       else
  2323.       if ( * q->type_p == ST_LOCAL_ARRAY )
  2324.       { q->type = CA_ARRAY ;
  2325.         start[q->call_offset].op = LA_PUSHA ;
  2326.         /* offset+1 op is OK */
  2327.       } 
  2328.       else /* try to infer from callee */
  2329.       {
  2330.         switch( callee->typev[q->arg_num] )
  2331.         {
  2332.           case  ST_LOCAL_VAR :
  2333.                 q->type = CA_EXPR ;
  2334.                 * q->type_p = ST_LOCAL_VAR ;
  2335.                 /* do not need to patch */
  2336.                 break ;
  2337.  
  2338.           case  ST_LOCAL_ARRAY :
  2339.                 q->type = CA_ARRAY ;
  2340.                 * q->type_p = ST_LOCAL_ARRAY ;
  2341.                 start[q->call_offset].op = LA_PUSHA ;
  2342.                 break ;
  2343.         }
  2344.       }
  2345.     }
  2346.  
  2347.     /* if we still do not know the type put on the new list
  2348.        else type check */
  2349.  
  2350.     if ( q->type == ST_NONE || q->type == ST_LOCAL_NONE )
  2351.     {
  2352.       q->link = exit_list ;
  2353.       exit_list = q ;
  2354.     }
  2355.     else  /* type known */
  2356.     {
  2357.       if ( callee->typev[q->arg_num] == ST_LOCAL_NONE )
  2358.            callee->typev[q->arg_num] = q->type ;
  2359.  
  2360.       else
  2361.       if ( q->type != callee->typev[q->arg_num] )
  2362.       {
  2363.         errmsg(0, "line %u: type error in arg(%d) in call to %s",
  2364.           line_no, q->arg_num+1, callee->name) ;
  2365.         if ( ++compile_error_count == MAX_COMPILE_ERRORS )
  2366.                     mawk_exit(1) ;
  2367.       }
  2368.  
  2369.       zfree(q, sizeof(CA_REC)) ;
  2370.       check_progress = 1 ;
  2371.     }
  2372.   } /* while */
  2373.  
  2374.   return  exit_list ;
  2375. }
  2376.  
  2377.  
  2378. static  int  arg_cnt_ok( fbp, q, line_no )
  2379.   FBLOCK  *fbp ;
  2380.   CA_REC  *q ;
  2381.   unsigned line_no ;
  2382. {
  2383.   if ( q->arg_num  >= fbp->nargs )
  2384.   {
  2385.     errmsg(0, "line %u: too many arguments in call to %s" ,
  2386.        line_no, fbp->name ) ;
  2387.     if ( ++compile_error_count == MAX_COMPILE_ERRORS ) 
  2388.               mawk_exit(1) ;
  2389.  
  2390.     return  0 ;
  2391.   }
  2392.   else  return 1 ;
  2393. }
  2394.  
  2395.  
  2396. FCALL_REC  *resolve_list ;
  2397.         /* function calls whose arg types need checking 
  2398.            are stored on this list */
  2399.  
  2400.  
  2401. /* on first pass thru the resolve list
  2402.    we check :
  2403.       if forward referenced functions were really defined
  2404.       if right number of arguments
  2405.    and compute call_start which is now known
  2406. */
  2407.  
  2408. static  FCALL_REC *first_pass( p )
  2409.   register FCALL_REC *p ;
  2410. { FCALL_REC dummy ;
  2411.