home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 11 Util / 11-Util.zip / MAWK113.ZIP / mawk113 / execute.c < prev    next >
C/C++ Source or Header  |  1993-01-14  |  34KB  |  1,264 lines

  1.  
  2. /********************************************
  3. execute.c
  4. copyright 1991, Michael D. Brennan
  5.  
  6. This is a source file for mawk, an implementation of
  7. the AWK programming language.
  8.  
  9. Mawk is distributed without warranty under the terms of
  10. the GNU General Public License, version 2, 1991.
  11. ********************************************/
  12.  
  13. /* $Log: execute.c,v $
  14.  * Revision 5.7.1.1  1993/01/15  03:33:39  mike
  15.  * patch3: safer double to int conversion
  16.  *
  17.  * Revision 5.7  1992/12/17  02:48:01  mike
  18.  * 1.1.2d changes for DOS
  19.  *
  20.  * Revision 5.6  1992/11/29  18:57:50  mike
  21.  * field expressions convert to long so 16 bit and 32 bit
  22.  * systems behave the same
  23.  *
  24.  * Revision 5.5  1992/08/11  15:24:55  brennan
  25.  * patch2: F_PUSHA and FE_PUSHA
  26.  * If this is preparation for g?sub(r,s,$expr) or (++|--) on $expr,
  27.  * then if expr > NF, make sure $expr is set to ""
  28.  *
  29.  * Revision 5.4  1992/08/11  14:51:54  brennan
  30.  * patch2:  $expr++ is numeric even if $expr is string.
  31.  * I forgot to do this earlier when handling x++ case.
  32.  *
  33.  * Revision 5.3  1992/07/08  17:03:30  brennan
  34.  * patch 2
  35.  * revert to version 1.0 comparisons, i.e.
  36.  * page 44-45 of AWK book
  37.  *
  38.  * Revision 5.2  1992/04/20  21:40:40  brennan
  39.  * patch 2
  40.  * x++ is numeric, even if x is string
  41.  *
  42.  * Revision 5.1  1991/12/05  07:55:50  brennan
  43.  * 1.1 pre-release
  44.  *
  45. */
  46.  
  47.  
  48. #include "mawk.h"
  49. #include "code.h"
  50. #include "memory.h"
  51. #include "symtype.h"
  52. #include "field.h"
  53. #include "bi_funct.h"
  54. #include "bi_vars.h"
  55. #include "regexp.h"
  56. #include "repl.h"
  57. #include "fin.h"
  58. #include <math.h>
  59.  
  60. static int PROTO( compare, (CELL *) ) ;
  61. static int PROTO( d_to_index, (double)) ;
  62.  
  63. #if   NOINFO_SIGFPE
  64. static char dz_msg[] = "division by zero" ;
  65. #endif
  66.  
  67. #ifdef   DEBUG
  68. static void PROTO( eval_overflow, (void) ) ;
  69.  
  70. #define  inc_sp()   if( ++sp == eval_stack+EVAL_STACK_SIZE )\
  71.                          eval_overflow()
  72. #else
  73.  
  74. /* If things are working, the eval stack should not overflow */
  75.  
  76. #define inc_sp()    sp++
  77. #endif
  78.  
  79. #define  SAFETY    16
  80. #define  DANGER    (EVAL_STACK_SIZE-SAFETY)
  81.  
  82. /*  The stack machine that executes the code */
  83.  
  84. CELL  eval_stack[EVAL_STACK_SIZE] ;
  85. /* these can move for deep recursion */
  86. static CELL  *stack_base = eval_stack ;
  87. static CELL  *stack_danger = eval_stack + DANGER ;      
  88.  
  89. #ifdef  DEBUG
  90. static void eval_overflow()
  91. { overflow("eval stack" , EVAL_STACK_SIZE) ; mawk_exit(1) ; }
  92. #endif
  93.  
  94. static INST *restart_label ; /* control flow labels */
  95. INST *next_label ;
  96. static CELL tc ; /*useful temp */
  97.  
  98. void  execute(cdp, sp, fp)
  99.   register INST *cdp ;  /* code ptr, start execution here */
  100.   register CELL *sp ;   /* eval_stack pointer */
  101.   CELL *fp ;            /* frame ptr into eval_stack for
  102.                            user defined functions */
  103.   /* some useful temporaries */
  104.   CELL *cp ;
  105.   int t ;
  106.  
  107.   /* for moving the stack (deep recursion) */
  108.   CELL *old_stack_base ;
  109.   CELL *old_sp ;
  110.  
  111. #ifdef  DEBUG
  112.   CELL *entry_sp = sp ;
  113. #endif
  114.  
  115.  
  116.   if ( fp )  /* we are a function call, check for deep recursion */
  117.   {
  118.     if (sp > stack_danger)
  119.     { /* change stacks */
  120.       old_stack_base = stack_base ;
  121.       old_sp = sp ;
  122.       stack_base = (CELL *) zmalloc(sizeof(CELL)*EVAL_STACK_SIZE) ;
  123.       stack_danger = stack_base + DANGER ;
  124.       sp = stack_base ;
  125.       /* waste 1 slot for ANSI, actually LM_DOS breaks in
  126.          RET if we don't */
  127. #ifdef  DEBUG 
  128.       entry_sp = sp ;
  129. #endif
  130.     }
  131.     else old_stack_base = (CELL*) 0 ;
  132.   }
  133.  
  134.   while ( 1 )
  135.     switch( cdp++ -> op )
  136.     {   
  137.  
  138. /* HALT only used by the disassemble now ; this remains
  139.    so compilers don't offset the jump table */
  140.         case  _HALT :
  141.  
  142.         case  _STOP :  /* only for range patterns */
  143. #ifdef  DEBUG
  144.                 if ( sp != entry_sp+1 ) bozo("stop0") ;
  145. #endif
  146.                 return ;
  147.  
  148.         case  _PUSHC :  
  149.             inc_sp() ;
  150.             (void) cellcpy(sp, cdp++ -> ptr) ;
  151.             break ;
  152.  
  153.         case _PUSHD  :
  154.             inc_sp() ;
  155.             sp->type = C_DOUBLE ;
  156.             sp->dval = *(double*) cdp++->ptr ;
  157.             break ;
  158.  
  159.         case  _PUSHS :
  160.             inc_sp() ;
  161.             sp->type = C_STRING ;
  162.             sp->ptr = cdp++->ptr ;
  163.             string(sp)->ref_cnt++ ;
  164.             break ;
  165.  
  166.         case  F_PUSHA :
  167.         cp = (CELL*)cdp->ptr ;
  168.         if ( cp != field )
  169.         {
  170.         if ( nf < 0 )  split_field0() ;
  171.  
  172.         if ( ! ( 
  173. #if    LM_DOS
  174.              SAMESEG(cp,field)   &&
  175. #endif
  176.               cp >= NF && cp <= LAST_PFIELD ) )
  177.         {
  178.           /* its a real field $1, $2 ... 
  179.              If its greater than $NF, we have to
  180.              make sure its set to ""  so that
  181.              (++|--) and g?sub() work right
  182.           */
  183.           t = field_addr_to_index(cp) ;
  184.           if ( t > nf )
  185.           {
  186.             cell_destroy(cp) ;
  187.             cp->type = C_STRING ;
  188.             cp->ptr = (PTR) &null_str ;
  189.             null_str.ref_cnt++ ;
  190.           }
  191.         }
  192.         }
  193.             /* fall thru */
  194.  
  195.         case  _PUSHA :
  196.         case  A_PUSHA :
  197.             inc_sp() ;
  198.             sp -> ptr = cdp++ -> ptr ;
  199.             break ;
  200.  
  201.         case _PUSHI :  /* put contents of next address on stack*/
  202.             inc_sp() ;
  203.             (void) cellcpy(sp, cdp++ -> ptr) ;
  204.             break ;
  205.             
  206.         case L_PUSHI :  
  207.             /* put the contents of a local var on stack,
  208.                cdp->op holds the offset from the frame pointer */
  209.             inc_sp() ;
  210.             (void) cellcpy(sp, fp + cdp++->op) ;
  211.             break ;
  212.  
  213.         case L_PUSHA : /* put a local address on eval stack */
  214.             inc_sp() ;
  215.             sp->ptr = (PTR)(fp + cdp++->op) ;
  216.             break ;
  217.  
  218.  
  219.         case F_PUSHI :
  220.  
  221.         /* push contents of $i 
  222.            cdp[0] holds & $i , cdp[1] holds i */
  223.  
  224.             inc_sp() ;
  225.             if ( nf < 0 )  split_field0() ;
  226.             cp = (CELL *) cdp->ptr ;
  227.             t =  (cdp+1)->op ;
  228.             cdp += 2 ;
  229.  
  230.             if ( t <= nf ) (void) cellcpy(sp, cp) ;
  231.             else  /* an unset field */
  232.             { sp->type = C_STRING ;
  233.               sp->ptr = (PTR) & null_str ;
  234.               null_str.ref_cnt++ ;
  235.             }
  236.             break ;
  237.  
  238.         case NF_PUSHI :
  239.  
  240.             inc_sp() ;
  241.             if ( nf < 0 ) split_field0() ;
  242.             (void) cellcpy(sp, NF) ;
  243.             break ;
  244.  
  245.         case  FE_PUSHA :
  246.  
  247.             if ( sp->type != C_DOUBLE )  cast1_to_d(sp) ;
  248.  
  249.         t = d_to_index(sp->dval) ;
  250.             if ( t && nf < 0 )  split_field0() ;
  251.             sp->ptr = (PTR) field_ptr(t) ;
  252.         if ( t > nf )
  253.         {
  254.           /* make sure its set to "" */
  255.           cp = sp->ptr ;
  256.           cell_destroy(cp) ;
  257.           cp->type = C_STRING ;
  258.           cp->ptr = (PTR) &null_str ;
  259.           null_str.ref_cnt++ ;
  260.         }
  261.             break ;
  262.  
  263.         case  FE_PUSHI :
  264.  
  265.             if ( sp->type != C_DOUBLE )  cast1_to_d(sp) ;
  266.  
  267.         t = d_to_index(sp->dval) ;
  268.  
  269.             if ( nf < 0)  split_field0() ;
  270.             if ( t <= nf ) (void) cellcpy(sp, field_ptr(t)) ;
  271.             else
  272.             { sp->type = C_STRING ;
  273.               sp->ptr = (PTR) & null_str ;
  274.               null_str.ref_cnt++ ;
  275.             }
  276.             break ; 
  277.  
  278.  
  279.         case  AE_PUSHA :
  280.         /* top of stack has an expr, cdp->ptr points at an
  281.            array, replace the expr with the cell address inside
  282.            the array */
  283.  
  284.             cp = array_find((ARRAY)cdp++->ptr, sp, CREATE) ;
  285.             cell_destroy(sp) ;
  286.             sp->ptr = (PTR) cp ;
  287.             break ;
  288.  
  289.         case  AE_PUSHI :
  290.         /* top of stack has an expr, cdp->ptr points at an
  291.            array, replace the expr with the contents of the
  292.            cell inside the array */
  293.  
  294.             cp = array_find((ARRAY) cdp++->ptr, sp, CREATE) ;
  295.             cell_destroy(sp) ;
  296.             (void) cellcpy(sp, cp) ;
  297.             break ;
  298.  
  299.         case  LAE_PUSHI :
  300.         /*  sp[0] is an expression
  301.             cdp->op is offset from frame pointer of a CELL which
  302.                has an ARRAY in the ptr field, replace expr
  303.             with  array[expr]
  304.         */
  305.             cp = array_find( (ARRAY)fp[cdp++->op].ptr, sp, CREATE) ;
  306.             cell_destroy(sp) ;
  307.             (void) cellcpy(sp, cp) ;
  308.             break ;
  309.             
  310.         case  LAE_PUSHA :
  311.         /*  sp[0] is an expression
  312.             cdp->op is offset from frame pointer of a CELL which
  313.                has an ARRAY in the ptr field, replace expr
  314.             with  & array[expr]
  315.         */
  316.             cp = array_find( (ARRAY)fp[cdp++->op].ptr, sp, CREATE) ;
  317.             cell_destroy(sp) ;
  318.             sp->ptr = (PTR) cp ;
  319.             break ;
  320.             
  321.         case  LA_PUSHA  :
  322.         /*  cdp->op is offset from frame pointer of a CELL which
  323.                has an ARRAY in the ptr field. Push this ARRAY
  324.                on the eval stack
  325.         */
  326.             inc_sp() ;
  327.             sp->ptr = fp[cdp++->op].ptr ;
  328.             break ;
  329.  
  330.         case  SET_ALOOP :
  331.             { ALOOP_STATE *ap = (ALOOP_STATE *)
  332.                             (cdp + cdp->op + 2)->ptr ;
  333.  
  334.               ap->var = (CELL *) sp[-1].ptr ;
  335.               ap->A = (ARRAY) sp->ptr ;
  336.               sp -= 2 ;
  337.  
  338.           ap->index = -1 ;
  339.               if ( inc_aloop_state(ap) )  cdp++ ;
  340.           else  cdp += cdp->op + 3 ;
  341.         }
  342.         break ;
  343.  
  344.         case  ALOOP :
  345.  
  346.         if ( inc_aloop_state( (ALOOP_STATE*) cdp[1].ptr ) )
  347.             cdp += cdp->op ;
  348.         else    cdp += 2 ;
  349.         break ;
  350.  
  351.         case  _POP : 
  352.             cell_destroy(sp) ;
  353.             sp-- ;
  354.             break ;
  355.  
  356.         case _DUP  :
  357.             (void) cellcpy(sp+1, sp) ;
  358.             sp++ ; break ;
  359.  
  360.         case  _ASSIGN :
  361.             /* top of stack has an expr, next down is an
  362.                address, put the expression in *address and
  363.                replace the address with the expression */
  364.  
  365.             /* don't propagate type C_MBSTRN */
  366.             if ( sp->type == C_MBSTRN ) check_strnum(sp) ;
  367.             sp-- ;
  368.             cell_destroy( ((CELL *)sp->ptr) ) ;
  369.             (void) cellcpy( sp, cellcpy(sp->ptr, sp+1) ) ;
  370.             cell_destroy(sp+1) ;
  371.             break ;
  372.  
  373.         case  F_ASSIGN : /* assign to a field  */
  374.             if (sp->type == C_MBSTRN) check_strnum(sp) ;
  375.             sp-- ;
  376.             field_assign((CELL*)sp->ptr, sp+1) ;
  377.             cell_destroy(sp+1) ;
  378.             (void) cellcpy(sp, (CELL *) sp->ptr) ;
  379.             break ;
  380.  
  381.         case  _ADD_ASG:
  382.             if ( sp->type != C_DOUBLE ) cast1_to_d(sp) ;
  383.             cp = (CELL *) (sp-1)->ptr ;
  384.             if ( cp->type != C_DOUBLE ) cast1_to_d(cp) ;
  385.  
  386. #if SW_FP_CHECK   /* specific to V7 and XNX23A */
  387.             clrerr();
  388. #endif
  389.             cp->dval += sp-- -> dval ;
  390. #if SW_FP_CHECK
  391.             fpcheck();
  392. #endif
  393.             sp->type = C_DOUBLE ;
  394.             sp->dval = cp->dval ;
  395.             break ;
  396.  
  397.         case  _SUB_ASG:
  398.             if ( sp->type != C_DOUBLE ) cast1_to_d(sp) ;
  399.             cp = (CELL *) (sp-1)->ptr ;
  400.             if ( cp->type != C_DOUBLE ) cast1_to_d(cp) ;
  401. #if SW_FP_CHECK
  402.             clrerr();
  403. #endif
  404.             cp->dval -= sp-- -> dval ;
  405. #if SW_FP_CHECK
  406.             fpcheck();
  407. #endif
  408.             sp->type = C_DOUBLE ;
  409.             sp->dval = cp->dval ;
  410.             break ;
  411.  
  412.         case  _MUL_ASG:
  413.             if ( sp->type != C_DOUBLE ) cast1_to_d(sp) ;
  414.             cp = (CELL *) (sp-1)->ptr ;
  415.             if ( cp->type != C_DOUBLE ) cast1_to_d(cp) ;
  416. #if SW_FP_CHECK
  417.             clrerr();
  418. #endif
  419.             cp->dval *= sp-- -> dval ;
  420. #if SW_FP_CHECK
  421.             fpcheck();
  422. #endif
  423.             sp->type = C_DOUBLE ;
  424.             sp->dval = cp->dval ;
  425.             break ;
  426.  
  427.         case  _DIV_ASG:
  428.             if ( sp->type != C_DOUBLE ) cast1_to_d(sp) ;
  429.             cp = (CELL *) (sp-1)->ptr ;
  430.             if ( cp->type != C_DOUBLE ) cast1_to_d(cp) ;
  431.  
  432. #if  NOINFO_SIGFPE
  433.         CHECK_DIVZERO(sp->dval) ;
  434. #endif
  435.  
  436. #if SW_FP_CHECK
  437.             clrerr();
  438. #endif
  439.             cp->dval /= sp-- -> dval ;
  440. #if SW_FP_CHECK
  441.             fpcheck();
  442. #endif
  443.             sp->type = C_DOUBLE ;
  444.             sp->dval = cp->dval ;
  445.             break ;
  446.  
  447.         case  _MOD_ASG:
  448.             if ( sp->type != C_DOUBLE ) cast1_to_d(sp) ;
  449.             cp = (CELL *) (sp-1)->ptr ;
  450.             if ( cp->type != C_DOUBLE ) cast1_to_d(cp) ;
  451.  
  452. #if  NOINFO_SIGFPE
  453.         CHECK_DIVZERO(sp->dval) ;
  454. #endif
  455.  
  456.             cp->dval = fmod(cp->dval,sp-- -> dval) ;
  457.             sp->type = C_DOUBLE ;
  458.             sp->dval = cp->dval ;
  459.             break ;
  460.  
  461.         case  _POW_ASG:
  462.             if ( sp->type != C_DOUBLE ) cast1_to_d(sp) ;
  463.             cp = (CELL *) (sp-1)->ptr ;
  464.             if ( cp->type != C_DOUBLE ) cast1_to_d(cp) ;
  465.             cp->dval = pow(cp->dval,sp-- -> dval) ;
  466.             sp->type = C_DOUBLE ;
  467.             sp->dval = cp->dval ;
  468.             break ;
  469.  
  470.         /* will anyone ever use these ? */
  471.  
  472.         case F_ADD_ASG :
  473.             if ( sp->type != C_DOUBLE ) cast1_to_d(sp) ;
  474.             cp = (CELL *) (sp-1)->ptr ;
  475.             cast1_to_d( cellcpy(&tc, cp) ) ;
  476. #if SW_FP_CHECK
  477.             clrerr();
  478. #endif
  479.             tc.dval += sp-- -> dval ;
  480. #if SW_FP_CHECK
  481.             fpcheck();
  482. #endif
  483.             sp->type = C_DOUBLE ;
  484.             sp->dval = tc.dval ;
  485.             field_assign(cp, &tc) ;
  486.             break ;
  487.  
  488.         case F_SUB_ASG :
  489.             if ( sp->type != C_DOUBLE ) cast1_to_d(sp) ;
  490.             cp = (CELL *) (sp-1)->ptr ;
  491.             cast1_to_d( cellcpy(&tc, cp) ) ;
  492. #if SW_FP_CHECK
  493.             clrerr();
  494. #endif
  495.             tc.dval -= sp-- -> dval ;
  496. #if SW_FP_CHECK
  497.             fpcheck();
  498. #endif
  499.             sp->type = C_DOUBLE ;
  500.             sp->dval = tc.dval ;
  501.             field_assign(cp, &tc) ;
  502.             break ;
  503.  
  504.         case F_MUL_ASG :
  505.             if ( sp->type != C_DOUBLE ) cast1_to_d(sp) ;
  506.             cp = (CELL *) (sp-1)->ptr ;
  507.             cast1_to_d( cellcpy(&tc, cp) ) ;
  508. #if SW_FP_CHECK
  509.             clrerr();
  510. #endif
  511.             tc.dval *= sp-- -> dval ;
  512. #if SW_FP_CHECK
  513.             fpcheck();
  514. #endif
  515.             sp->type = C_DOUBLE ;
  516.             sp->dval = tc.dval ;
  517.             field_assign(cp, &tc) ;
  518.             break ;
  519.  
  520.         case F_DIV_ASG :
  521.             if ( sp->type != C_DOUBLE ) cast1_to_d(sp) ;
  522.             cp = (CELL *) (sp-1)->ptr ;
  523.             cast1_to_d( cellcpy(&tc, cp) ) ;
  524.  
  525. #if  NOINFO_SIGFPE
  526.         CHECK_DIVZERO(sp->dval) ;
  527. #endif
  528.  
  529. #if SW_FP_CHECK
  530.             clrerr();
  531. #endif
  532.             tc.dval /= sp-- -> dval ;
  533. #if SW_FP_CHECK
  534.             fpcheck();
  535. #endif
  536.             sp->type = C_DOUBLE ;
  537.             sp->dval = tc.dval ;
  538.             field_assign(cp, &tc) ;
  539.             break ;
  540.  
  541.         case F_MOD_ASG :
  542.             if ( sp->type != C_DOUBLE ) cast1_to_d(sp) ;
  543.             cp = (CELL *) (sp-1)->ptr ;
  544.             cast1_to_d( cellcpy(&tc, cp) ) ;
  545.  
  546. #if  NOINFO_SIGFPE
  547.         CHECK_DIVZERO(sp->dval) ;
  548. #endif
  549.  
  550.             tc.dval = fmod(tc.dval, sp-- -> dval) ;
  551.             sp->type = C_DOUBLE ;
  552.             sp->dval = tc.dval ;
  553.             field_assign(cp, &tc) ;
  554.             break ;
  555.  
  556.         case F_POW_ASG :
  557.             if ( sp->type != C_DOUBLE ) cast1_to_d(sp) ;
  558.             cp = (CELL *) (sp-1)->ptr ;
  559.             cast1_to_d( cellcpy(&tc, cp) ) ;
  560.             tc.dval = pow(tc.dval, sp-- -> dval) ;
  561.             sp->type = C_DOUBLE ;
  562.             sp->dval = tc.dval ;
  563.             field_assign(cp, &tc) ;
  564.             break ;
  565.  
  566.         case _ADD :
  567.             sp-- ;
  568.             if ( TEST2(sp) != TWO_DOUBLES )
  569.                     cast2_to_d(sp) ;
  570. #if SW_FP_CHECK
  571.             clrerr();
  572. #endif
  573.             sp[0].dval += sp[1].dval ;
  574. #if SW_FP_CHECK
  575.             fpcheck();
  576. #endif
  577.             break ;
  578.  
  579.         case _SUB :
  580.             sp-- ;
  581.             if ( TEST2(sp) != TWO_DOUBLES )
  582.                     cast2_to_d(sp) ;
  583. #if SW_FP_CHECK
  584.             clrerr();
  585. #endif
  586.             sp[0].dval -= sp[1].dval ;
  587. #if SW_FP_CHECK
  588.             fpcheck();
  589. #endif
  590.             break ;
  591.  
  592.         case _MUL :
  593.             sp-- ;
  594.             if ( TEST2(sp) != TWO_DOUBLES )
  595.                     cast2_to_d(sp) ;
  596. #if SW_FP_CHECK
  597.             clrerr();
  598. #endif
  599.             sp[0].dval *= sp[1].dval ;
  600. #if SW_FP_CHECK
  601.             fpcheck();
  602. #endif
  603.             break ;
  604.  
  605.         case _DIV :
  606.             sp-- ;
  607.             if ( TEST2(sp) != TWO_DOUBLES )
  608.                     cast2_to_d(sp) ;
  609.  
  610. #if  NOINFO_SIGFPE
  611.         CHECK_DIVZERO(sp[1].dval) ;
  612. #endif
  613.  
  614. #if SW_FP_CHECK
  615.             clrerr();
  616. #endif
  617.             sp[0].dval /= sp[1].dval ;
  618. #if SW_FP_CHECK
  619.             fpcheck();
  620. #endif
  621.             break ;
  622.  
  623.         case _MOD :
  624.             sp-- ;
  625.             if ( TEST2(sp) != TWO_DOUBLES )
  626.                     cast2_to_d(sp) ;
  627.  
  628. #if  NOINFO_SIGFPE
  629.         CHECK_DIVZERO(sp[1].dval) ;
  630. #endif
  631.  
  632.             sp[0].dval = fmod(sp[0].dval,sp[1].dval) ;
  633.             break ;
  634.  
  635.         case _POW :
  636.             sp-- ;
  637.             if ( TEST2(sp) != TWO_DOUBLES )
  638.                     cast2_to_d(sp) ;
  639.             sp[0].dval = pow(sp[0].dval,sp[1].dval) ;
  640.             break ;
  641.  
  642.         case _NOT :
  643.         reswitch_1:
  644.             switch( sp->type )
  645.             { case C_NOINIT :
  646.                     sp->dval = 1.0 ; break ;
  647.               case C_DOUBLE :
  648.                     sp->dval = D2BOOL(sp->dval) ? 0.0 : 1.0 ;
  649.                     break ;
  650.               case C_STRING :
  651.                     sp->dval = string(sp)->len ? 0.0 : 1.0 ;
  652.                     free_STRING(string(sp)) ;
  653.                     break ;
  654.               case C_STRNUM : /* test as a number */
  655.                     sp->dval = D2BOOL(sp->dval) ? 0.0 : 1.0 ;
  656.                     free_STRING(string(sp)) ;
  657.                     break ;
  658.               case C_MBSTRN :
  659.                     check_strnum(sp) ;
  660.                     goto reswitch_1 ;
  661.               default :
  662.                     bozo("bad type on eval stack") ;
  663.             }
  664.             sp->type = C_DOUBLE ;
  665.             break  ;
  666.  
  667.         case _TEST :
  668.         reswitch_2:
  669.             switch( sp->type )
  670.             { case C_NOINIT :
  671.                     sp->dval = 0.0 ; break ;
  672.               case C_DOUBLE :
  673.                     sp->dval = D2BOOL(sp->dval) ? 1.0 : 0.0 ;
  674.                     break ;
  675.               case C_STRING :
  676.                     sp->dval  = string(sp)->len ? 1.0 : 0.0 ;
  677.                     free_STRING(string(sp)) ;
  678.                     break ;
  679.               case C_STRNUM : /* test as a number */
  680.                     sp->dval = D2BOOL(sp->dval) ? 1.0 : 0.0 ;
  681.                     free_STRING(string(sp)) ;
  682.                     break ;
  683.               case C_MBSTRN :
  684.                     check_strnum(sp) ;
  685.                     goto reswitch_2 ;
  686.               default :
  687.                     bozo("bad type on eval stack") ;
  688.             }
  689.             sp->type = C_DOUBLE ;
  690.             break ;
  691.  
  692.         case _UMINUS :
  693.             if ( sp->type != C_DOUBLE ) cast1_to_d(sp) ;
  694.             sp->dval = - sp->dval ;
  695.             break ;
  696.  
  697.         case _UPLUS :  
  698.             if ( sp->type != C_DOUBLE ) cast1_to_d(sp) ;
  699.             break ;
  700.  
  701.         case _CAT :
  702.             { unsigned len1, len2 ;
  703.               char *str1, *str2 ;
  704.               STRING *b ;
  705.               
  706.               sp-- ;
  707.               if ( TEST2(sp) != TWO_STRINGS )
  708.                     cast2_to_s(sp) ;
  709.               str1 = string(sp)->str ;
  710.               len1 = string(sp)->len ;
  711.               str2 = string(sp+1)->str ;
  712.               len2 = string(sp+1)->len ;
  713.  
  714.               b = new_STRING((char *)0, len1+len2) ;
  715.               (void) memcpy(b->str, str1, SIZE_T(len1)) ;
  716.               (void) memcpy(b->str + len1, str2, SIZE_T(len2)) ;
  717.               free_STRING(string(sp)) ;
  718.               free_STRING( string(sp+1) ) ;
  719.  
  720.               sp->ptr = (PTR) b ;
  721.               break ;
  722.             }
  723.  
  724.         case _PUSHINT :
  725.             inc_sp() ;
  726.             sp->type = cdp++ -> op ;
  727.             break ;
  728.  
  729.         case _BUILTIN :
  730.         case _PRINT :
  731.             sp = (* (PF_CP) cdp++ -> ptr) (sp) ;
  732.             break ;
  733.  
  734.         case _POST_INC :
  735.         cp = (CELL *)sp->ptr ;
  736.             if ( cp->type != C_DOUBLE ) cast1_to_d(cp) ;
  737.         sp->type = C_DOUBLE ;
  738.         sp->dval = cp->dval ;
  739.             cp->dval += 1.0 ;
  740.             break ;
  741.  
  742.         case _POST_DEC :
  743.         cp = (CELL *)sp->ptr ;
  744.             if ( cp->type != C_DOUBLE ) cast1_to_d(cp) ;
  745.         sp->type = C_DOUBLE ;
  746.         sp->dval = cp->dval ;
  747.             cp->dval -= 1.0 ;
  748.             break ;
  749.  
  750.         case _PRE_INC :
  751.             cp = (CELL *) sp->ptr ;
  752.             if ( cp->type != C_DOUBLE ) cast1_to_d(cp) ;
  753.             sp->dval = cp->dval += 1.0 ;
  754.             sp->type = C_DOUBLE ;
  755.             break ;
  756.  
  757.         case _PRE_DEC :
  758.             cp = (CELL *) sp->ptr ;
  759.             if ( cp->type != C_DOUBLE ) cast1_to_d(cp) ;
  760.             sp->dval = cp->dval -= 1.0 ;
  761.             sp->type = C_DOUBLE ;
  762.             break ;
  763.  
  764.  
  765.         case F_POST_INC  :
  766.             cp = (CELL *) sp->ptr ;
  767.         (void) cellcpy(&tc, cp) ;
  768.         cast1_to_d(&tc) ;
  769.         sp->type = C_DOUBLE ;
  770.         sp->dval = tc.dval ;
  771.         tc.dval += 1.0 ;
  772.             field_assign(cp, &tc) ;
  773.             break ;
  774.  
  775.         case F_POST_DEC  :
  776.             cp = (CELL *) sp->ptr ;
  777.         (void) cellcpy(&tc, cp) ;
  778.         cast1_to_d(&tc) ;
  779.         sp->type = C_DOUBLE ;
  780.         sp->dval = tc.dval ;
  781.         tc.dval -= 1.0 ;
  782.             field_assign(cp, &tc) ;
  783.             break ;
  784.  
  785.         case F_PRE_INC :
  786.             cp = (CELL *) sp->ptr ;
  787.             cast1_to_d(cellcpy(sp, cp)) ;
  788.             sp->dval += 1.0 ;
  789.             field_assign(cp, sp) ;
  790.             break ;
  791.  
  792.         case F_PRE_DEC :
  793.             cp = (CELL *) sp->ptr ;
  794.             cast1_to_d(cellcpy(sp, cp)) ;
  795.             sp->dval -= 1.0 ;
  796.             field_assign(cp, sp) ;
  797.             break ;
  798.  
  799.         case _JMP  :
  800.             cdp += cdp->op  ;
  801.             break ;
  802.  
  803.         case _JNZ  :
  804.             /* jmp if top of stack is non-zero and pop stack */
  805.             if ( test( sp ) )
  806.                 cdp += cdp->op  ;
  807.             else  cdp++ ;
  808.             cell_destroy(sp) ;
  809.             sp-- ;
  810.             break ;
  811.  
  812.         case _JZ  :
  813.             /* jmp if top of stack is zero and pop stack */
  814.             if ( ! test( sp ) )
  815.                 cdp += cdp->op  ;
  816.             else  cdp++ ;
  817.             cell_destroy(sp) ;
  818.             sp-- ;
  819.             break ;
  820.  
  821.     /*  the relation operations */
  822.     /*  compare() makes sure string ref counts are OK */
  823.         case  _EQ :
  824.             t = compare(--sp) ;
  825.             sp->type = C_DOUBLE ;
  826.             sp->dval = t == 0 ? 1.0 : 0.0 ;
  827.             break ;
  828.  
  829.         case  _NEQ :
  830.             t = compare(--sp) ;
  831.             sp->type = C_DOUBLE ;
  832.             sp->dval = t ? 1.0 : 0.0 ;
  833.             break ;
  834.  
  835.         case  _LT :
  836.             t = compare(--sp) ;
  837.             sp->type = C_DOUBLE ;
  838.             sp->dval = t < 0 ? 1.0 : 0.0 ;
  839.             break ;
  840.  
  841.         case  _LTE :
  842.             t = compare(--sp) ;
  843.             sp->type = C_DOUBLE ;
  844.             sp->dval = t <= 0 ? 1.0 : 0.0 ;
  845.             break ;
  846.  
  847.         case  _GT :
  848.             t = compare(--sp) ;
  849.             sp->type = C_DOUBLE ;
  850.             sp->dval = t > 0 ? 1.0 : 0.0 ;
  851.             break ;
  852.  
  853.         case  _GTE :
  854.             t = compare(--sp) ;
  855.             sp->type = C_DOUBLE ;
  856.             sp->dval = t >= 0 ? 1.0 : 0.0 ;
  857.             break ;
  858.  
  859.         case _MATCH0 : 
  860.             /* does $0 match, the RE at cdp */
  861.  
  862.             inc_sp() ;
  863.             if ( field->type >= C_STRING )
  864.             { sp->type = C_DOUBLE ;
  865.               sp->dval = REtest(string(field)->str, cdp++->ptr)
  866.                          ? 1.0 : 0.0 ;
  867.  
  868.               break /* the case */ ;
  869.             }
  870.             else
  871.             {
  872.               cellcpy(sp, field) ;
  873.               /* and FALL THRU */
  874.             }
  875.  
  876.         case _MATCH1 :
  877.             /* does expr at sp[0] match RE at cdp */
  878.             if ( sp->type < C_STRING ) cast1_to_s(sp) ;
  879.             t = REtest(string(sp)->str, cdp++->ptr) ;
  880.             free_STRING(string(sp)) ;
  881.             sp->type = C_DOUBLE ;
  882.             sp->dval = t ? 1.0 : 0.0 ;
  883.             break ;
  884.  
  885.  
  886.         case  _MATCH2 :
  887.             /* does sp[-1] match sp[0] as re */
  888.              cast_to_RE(sp) ;
  889.  
  890.             if ( (--sp)->type < C_STRING )  cast1_to_s(sp) ;
  891.             t = REtest(string(sp)->str, (sp+1)->ptr) ; 
  892.  
  893.             free_STRING(string(sp)) ;
  894.             sp->type = C_DOUBLE ;
  895.             sp->dval = t ? 1.0 : 0.0 ;
  896.             break ;
  897.  
  898.         case  A_TEST :
  899.         /* entry :  sp[0].ptr-> an array
  900.                     sp[-1]  is an expression
  901.  
  902.            we compute   expression in array  */
  903.             sp-- ;
  904.             cp = array_find( (sp+1)->ptr, sp, NO_CREATE) ;
  905.             cell_destroy(sp) ;
  906.             sp->type = C_DOUBLE ;
  907.             sp->dval = (cp!=(CELL*)0)  ? 1.0 : 0.0 ;
  908.             break ;
  909.  
  910.         case  A_DEL :
  911.         /* sp[0].ptr ->  array
  912.            sp[-1] is an expr
  913.            delete  array[expr]  */
  914.  
  915.             array_delete(sp->ptr, sp-1) ;
  916.             cell_destroy(sp-1) ;
  917.             sp -= 2 ;
  918.             break ;
  919.         
  920.         /* form a multiple array index */
  921.         case A_CAT :
  922.             sp = array_cat(sp, cdp++->op) ;
  923.             break ;
  924.  
  925.         case  _EXIT  :
  926.             if ( sp->type != C_DOUBLE ) cast1_to_d(sp) ;
  927.             exit_code = d_to_i(sp->dval) ;
  928.         sp-- ;
  929.             /* fall thru */
  930.  
  931.         case  _EXIT0 :
  932.             if ( !(cdp = end_code.start) ) mawk_exit(exit_code) ;
  933.  
  934.             end_code.start = (INST *) 0 ; /* makes sure next exit exits */
  935.             if ( begin_code.start )
  936.          zfree(begin_code.start, begin_code.size) ;
  937.             if ( main_start )  zfree(main_start, main_size);
  938.             sp = eval_stack - 1 ; /* might be in user function */
  939.             break ;
  940.  
  941.         case  _JMAIN : /* go from BEGIN code to MAIN code */
  942.             zfree(begin_code.start, begin_code.size) ;
  943.             begin_code.start = (INST *) 0 ;
  944.             cdp = main_start ;
  945.             break ;
  946.  
  947.         case  _OMAIN :
  948.             if ( !main_fin )  open_main() ;
  949.             restart_label = cdp ;
  950.             cdp = next_label ;
  951.             break ;
  952.  
  953.         case  _NEXT :
  954.             cdp = next_label ;
  955.             break ;
  956.  
  957.         case  OL_GL :
  958.             {
  959.               char *p ;
  960.               unsigned len ;
  961.  
  962.               if ( !(p = FINgets(main_fin, &len)) )
  963.               {
  964.                 if ( !end_code.start )  mawk_exit(0) ;
  965.  
  966.                 cdp = end_code.start ;
  967.                 zfree(main_start, main_size) ;
  968.                 main_start = end_code.start = (INST*) 0 ;
  969.               }
  970.               else
  971.               { set_field0(p, len) ; cdp = restart_label ; }
  972.             }
  973.             break ;
  974.  
  975.         case  OL_GL_NR :
  976.             {
  977.               char *p ;
  978.               unsigned len ;
  979.  
  980.               if ( !(p = FINgets(main_fin, &len)) )
  981.               {
  982.                 if ( !end_code.start )  mawk_exit(0) ;
  983.  
  984.                 cdp = end_code.start ;
  985.                 zfree(main_start, main_size) ;
  986.                 main_start = end_code.start = (INST*) 0 ;
  987.               }
  988.               else
  989.               {
  990.                 set_field0(p, len) ; 
  991.                 cdp = restart_label ;
  992.  
  993.                 if ( TEST2(NR) != TWO_DOUBLES ) cast2_to_d(NR) ;
  994.  
  995.                 NR->dval += 1.0 ;
  996.                 FNR->dval += 1.0 ;
  997.               }
  998.             }
  999.             break ;
  1000.  
  1001.  
  1002.         case  _RANGE :
  1003. /* test a range pattern:  pat1, pat2 { action }
  1004.    entry :
  1005.        cdp[0].op -- a flag, test pat1 if on else pat2
  1006.        cdp[1].op -- offset of pat2 code from cdp
  1007.        cdp[2].op -- offset of action code from cdp
  1008.        cdp[3].op -- offset of code after the action from cdp
  1009.        cdp[4] -- start of pat1 code
  1010. */
  1011.  
  1012. #define FLAG    cdp[0].op
  1013. #define PAT2    cdp[1].op
  1014. #define ACTION    cdp[2].op
  1015. #define FOLLOW    cdp[3].op
  1016. #define PAT1      4
  1017.  
  1018.             if ( FLAG )  /* test again pat1 */
  1019.             { 
  1020.               execute(cdp + PAT1,sp, fp) ;
  1021.               t = test(sp+1) ;
  1022.               cell_destroy(sp+1) ;
  1023.               if ( t )  FLAG = 0 ;
  1024.               else
  1025.               { cdp += FOLLOW ;
  1026.                 break ;  /* break the switch */
  1027.               }
  1028.             }
  1029.  
  1030.             /* test against pat2 and then perform the action */
  1031.             execute(cdp + PAT2, sp, fp) ;
  1032.             FLAG  = test(sp+1) ;
  1033.             cell_destroy(sp+1) ; 
  1034.             cdp += ACTION ;
  1035.             break ;
  1036.  
  1037. /* function calls  */
  1038.  
  1039.       case  _RET0  :
  1040.             inc_sp() ;
  1041.             sp->type = C_NOINIT ;
  1042.             /* fall thru */
  1043.  
  1044.       case  _RET   :
  1045.  
  1046. #ifdef  DEBUG 
  1047.             if ( sp != entry_sp+1 ) bozo("ret") ;
  1048. #endif
  1049.             if ( old_stack_base ) /* reset stack */
  1050.             {
  1051.               /* move the return value */
  1052.               (void) cellcpy(old_sp+1, sp) ;
  1053.               cell_destroy(sp) ;
  1054.               zfree(stack_base, sizeof(CELL)*EVAL_STACK_SIZE) ;
  1055.               stack_base = old_stack_base ;
  1056.               stack_danger = old_stack_base + DANGER ;
  1057.             }
  1058.               
  1059.             return  ;
  1060.  
  1061.       case  _CALL  :
  1062.  
  1063.             { FBLOCK *fbp = (FBLOCK*) cdp++->ptr ;
  1064.               int a_args = cdp++->op ; /* actual number of args */
  1065.               CELL *nfp = sp - a_args + 1 ; /* new fp for callee */
  1066.               CELL *local_p = sp+1; /* first local argument on stack */
  1067.               char *type_p ;  /* pts to type of an argument */
  1068.  
  1069.               if ( fbp->nargs ) type_p = fbp->typev + a_args ;
  1070.  
  1071.               /* create space for locals */
  1072.               if ( t = fbp->nargs - a_args ) /* have local args */
  1073.               {
  1074.                 while ( t-- )  
  1075.                 { (++sp)->type = C_NOINIT ;
  1076.                   if ( *type_p++ == ST_LOCAL_ARRAY )
  1077.                         sp->ptr = (PTR) new_ARRAY() ;
  1078.                 }
  1079.               }
  1080.               type_p-- ; /* *type_p is type of last arg */ 
  1081.  
  1082.               execute(fbp->code, sp, nfp) ;
  1083.  
  1084.               /* cleanup the callee's arguments */
  1085.               if ( sp >= nfp ) 
  1086.               {
  1087.                 cp = sp+1 ;  /* cp -> the function return */
  1088.  
  1089.                 do
  1090.                 {
  1091.                   if ( *type_p-- == ST_LOCAL_ARRAY )
  1092.                   {  if ( sp >= local_p ) array_free(sp->ptr) ; }
  1093.                   else  cell_destroy(sp) ;
  1094.  
  1095.                 } while ( --sp >= nfp ) ;
  1096.                     
  1097.                 (void) cellcpy(++sp, cp) ;
  1098.                 cell_destroy(cp) ;
  1099.               }
  1100.               else  sp++ ; /* no arguments passed */
  1101.             }
  1102.             break ;
  1103.  
  1104.         default :
  1105.             bozo("bad opcode") ;
  1106.     }
  1107. }
  1108.  
  1109. int test( cp )  /* test if a cell is null or not */
  1110.   register CELL *cp ;
  1111. reswitch :
  1112.  
  1113.   switch ( cp->type )
  1114.   {
  1115.     case C_NOINIT :  return  0 ;
  1116.     case C_STRNUM :  /* test as a number */
  1117.     case C_DOUBLE :  return  cp->dval != 0.0 ;
  1118.     case C_STRING :  return  string(cp)->len ;
  1119.     case C_MBSTRN :  check_strnum(cp) ; goto reswitch ;
  1120.  
  1121.     default :
  1122.       bozo("bad cell type in call to test") ;
  1123.   }
  1124.   return 0 ; /*can't get here: shutup */
  1125. }
  1126.  
  1127. /* compare cells at cp and cp+1 and
  1128.    frees STRINGs at those cells
  1129. */
  1130. static int compare(cp)
  1131.   register CELL *cp ;
  1132. { int k ;
  1133.  
  1134. reswitch :
  1135.  
  1136.   switch( TEST2(cp) )
  1137.   { case TWO_NOINITS :  return 0 ; 
  1138.     
  1139.     case TWO_DOUBLES :
  1140.     two_d:
  1141.             return  cp->dval > (cp+1)->dval ? 1 :
  1142.                     cp->dval < (cp+1)->dval ? -1 : 0 ;
  1143.     
  1144.     case TWO_STRINGS :
  1145.     case STRING_AND_STRNUM :
  1146.     two_s:
  1147.             k = strcmp(string(cp)->str, string(cp+1)->str) ;
  1148.             free_STRING( string(cp) ) ;
  1149.             free_STRING( string(cp+1) ) ;
  1150.             return k ;
  1151.  
  1152.     case  NOINIT_AND_DOUBLE  :
  1153.     case  NOINIT_AND_STRNUM  :
  1154.     case  DOUBLE_AND_STRNUM  :
  1155.     case TWO_STRNUMS :
  1156.             cast2_to_d(cp) ; goto two_d ;
  1157.  
  1158.     case  NOINIT_AND_STRING  :
  1159.     case  DOUBLE_AND_STRING  :
  1160.             cast2_to_s(cp) ; goto two_s ;
  1161.  
  1162.     case  TWO_MBSTRNS :
  1163.             check_strnum(cp) ; check_strnum(cp+1) ;
  1164.             goto reswitch ;
  1165.  
  1166.     case  NOINIT_AND_MBSTRN :
  1167.     case  DOUBLE_AND_MBSTRN :
  1168.     case  STRING_AND_MBSTRN :
  1169.     case  STRNUM_AND_MBSTRN :
  1170.             check_strnum( cp->type == C_MBSTRN ? cp : cp+1 ) ;
  1171.             goto reswitch ;
  1172.  
  1173.     default :  /* there are no default cases */
  1174.             bozo("bad cell type passed to compare") ;
  1175.   }
  1176.   return 0 ; /* shut up */
  1177. }
  1178.  
  1179. /* does not assume target was a cell, if so
  1180.    then caller should have made a previous
  1181.    call to cell_destroy  */
  1182.  
  1183. CELL *cellcpy(target, source)
  1184.   register CELL *target, *source ;
  1185. { switch( target->type = source->type )
  1186.   { case C_NOINIT : 
  1187.     case C_SPACE  : 
  1188.     case C_SNULL  :
  1189.             break ;
  1190.  
  1191.     case C_DOUBLE :
  1192.             target->dval = source->dval ;
  1193.             break ;
  1194.  
  1195.     case C_STRNUM :
  1196.             target->dval = source->dval ;
  1197.             /* fall thru */
  1198.  
  1199.     case C_REPL    :
  1200.     case C_MBSTRN  :
  1201.     case C_STRING  :
  1202.             string(source)->ref_cnt++ ;
  1203.             /* fall thru */
  1204.  
  1205.     case C_RE  :
  1206.             target->ptr = source->ptr ;
  1207.             break ;
  1208.  
  1209.     case  C_REPLV :
  1210.             (void)  replv_cpy(target, source) ;
  1211.             break ;
  1212.  
  1213.     default :
  1214.             bozo("bad cell passed to cellcpy()") ;
  1215.             break ;
  1216.   }
  1217.   return  target ;
  1218. }
  1219.  
  1220. #ifdef   DEBUG
  1221.  
  1222. void  DB_cell_destroy(cp)    /* HANGOVER time */
  1223.   register CELL *cp ;
  1224. {
  1225.   switch( cp->type )
  1226.   { case C_NOINIT :
  1227.     case C_DOUBLE :  break ;
  1228.  
  1229.     case C_MBSTRN :
  1230.     case C_STRING :
  1231.     case C_STRNUM :
  1232.             if ( -- string(cp)->ref_cnt == 0 )
  1233.                 zfree(string(cp) , string(cp)->len+STRING_OH) ;
  1234.             break ;
  1235.  
  1236.     case  C_RE :
  1237.             bozo("cell destroy called on RE cell") ;
  1238.     default :
  1239.             bozo("cell destroy called on bad cell type") ;
  1240.   }
  1241. }
  1242.  
  1243. #endif
  1244.  
  1245.  
  1246.  
  1247. /* convert a double d to a field index  $d -> $i */
  1248. static int
  1249. d_to_index( d ) 
  1250.   double d ;
  1251. {
  1252.  
  1253.   if ( d > MAX_FIELD ) 
  1254.         rt_overflow("maximum number of fields", MAX_FIELD) ;
  1255.   
  1256.   if ( d >= 0.0 )  return (int) d ;
  1257.   
  1258.   /* might include nan */
  1259.   rt_error("negative field index $%.6g", d) ;
  1260.   return 0 ; /* shutup */
  1261. }
  1262.