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

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