home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / perl / os2perl / cmd.c < prev    next >
C/C++ Source or Header  |  1991-06-11  |  31KB  |  1,223 lines

  1. /* $RCSfile: cmd.c,v $$Revision: 4.0.1.2 $$Date: 91/06/07 10:26:45 $
  2.  *
  3.  *    Copyright (c) 1991, Larry Wall
  4.  *
  5.  *    You may distribute under the terms of either the GNU General Public
  6.  *    License or the Artistic License, as specified in the README file.
  7.  *
  8.  * $Log:    cmd.c,v $
  9.  * Revision 4.0.1.2  91/06/07  10:26:45  lwall
  10.  * patch4: new copyright notice
  11.  * patch4: made some allowances for "semi-standard" C
  12.  *
  13.  * Revision 4.0.1.1  91/04/11  17:36:16  lwall
  14.  * patch1: you may now use "die" and "caller" in a signal handler
  15.  *
  16.  * Revision 4.0  91/03/20  01:04:18  lwall
  17.  * 4.0 baseline.
  18.  *
  19.  */
  20.  
  21. #include "EXTERN.h"
  22. #include "perl.h"
  23.  
  24. #ifdef I_VARARGS
  25. #  include <varargs.h>
  26. #endif
  27.  
  28. static STR str_chop;
  29.  
  30. void grow_dlevel();
  31.  
  32. /* do longjmps() clobber register variables? */
  33.  
  34. #if defined(cray) || defined(STANDARD_C)
  35. #define JMPCLOBBER
  36. #endif
  37.  
  38. /* This is the main command loop.  We try to spend as much time in this loop
  39.  * as possible, so lots of optimizations do their activities in here.  This
  40.  * means things get a little sloppy.
  41.  */
  42.  
  43. int
  44. cmd_exec(cmdparm,gimme,sp)
  45. CMD *VOLATILE cmdparm;
  46. VOLATILE int gimme;
  47. VOLATILE int sp;
  48. {
  49.     register CMD *cmd = cmdparm;
  50.     SPAT *VOLATILE oldspat;
  51.     VOLATILE int firstsave = savestack->ary_fill;
  52.     VOLATILE int oldsave;
  53.     VOLATILE int aryoptsave;
  54. #ifdef DEBUGGING
  55.     VOLATILE int olddlevel;
  56.     VOLATILE int entdlevel;
  57. #endif
  58.     register STR *retstr = &str_undef;
  59.     register char *tmps;
  60.     register int cmdflags;
  61.     register int match;
  62.     register char *go_to = goto_targ;
  63.     register int newsp = -2;
  64.     register STR **st = stack->ary_array;
  65.     FILE *VOLATILE fp;
  66.     ARRAY *VOLATILE ar;
  67.  
  68.     lastsize = 0;
  69. #ifdef DEBUGGING
  70.     entdlevel = dlevel;
  71. #endif
  72. tail_recursion_entry:
  73. #ifdef DEBUGGING
  74.     dlevel = entdlevel;
  75. #endif
  76. #ifdef TAINT
  77.     tainted = 0;    /* Each statement is presumed innocent */
  78. #endif
  79.     if (cmd == Nullcmd) {
  80.     if (gimme == G_ARRAY && newsp > -2)
  81.         return newsp;
  82.     else {
  83.         st[++sp] = retstr;
  84.         return sp;
  85.     }
  86.     }
  87.     cmdflags = cmd->c_flags;    /* hopefully load register */
  88.     if (go_to) {
  89.     if (cmd->c_label && strEQ(go_to,cmd->c_label))
  90.         goto_targ = go_to = Nullch;        /* here at last */
  91.     else {
  92.         switch (cmd->c_type) {
  93.         case C_IF:
  94.         oldspat = curspat;
  95.         oldsave = savestack->ary_fill;
  96. #ifdef DEBUGGING
  97.         olddlevel = dlevel;
  98. #endif
  99.         retstr = &str_yes;
  100.         newsp = -2;
  101.         if (cmd->ucmd.ccmd.cc_true) {
  102. #ifdef DEBUGGING
  103.             if (debug) {
  104.             debname[dlevel] = 't';
  105.             debdelim[dlevel] = '_';
  106.             if (++dlevel >= dlmax)
  107.                 grow_dlevel();
  108.             }
  109. #endif
  110.             newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme && (cmdflags & CF_TERM),sp);
  111.             st = stack->ary_array;    /* possibly reallocated */
  112.             retstr = st[newsp];
  113.         }
  114.         if (!goto_targ)
  115.             go_to = Nullch;
  116.         curspat = oldspat;
  117.         if (savestack->ary_fill > oldsave)
  118.             restorelist(oldsave);
  119. #ifdef DEBUGGING
  120.         dlevel = olddlevel;
  121. #endif
  122.         cmd = cmd->ucmd.ccmd.cc_alt;
  123.         goto tail_recursion_entry;
  124.         case C_ELSE:
  125.         oldspat = curspat;
  126.         oldsave = savestack->ary_fill;
  127. #ifdef DEBUGGING
  128.         olddlevel = dlevel;
  129. #endif
  130.         retstr = &str_undef;
  131.         newsp = -2;
  132.         if (cmd->ucmd.ccmd.cc_true) {
  133. #ifdef DEBUGGING
  134.             if (debug) {
  135.             debname[dlevel] = 'e';
  136.             debdelim[dlevel] = '_';
  137.             if (++dlevel >= dlmax)
  138.                 grow_dlevel();
  139.             }
  140. #endif
  141.             newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme && (cmdflags & CF_TERM),sp);
  142.             st = stack->ary_array;    /* possibly reallocated */
  143.             retstr = st[newsp];
  144.         }
  145.         if (!goto_targ)
  146.             go_to = Nullch;
  147.         curspat = oldspat;
  148.         if (savestack->ary_fill > oldsave)
  149.             restorelist(oldsave);
  150. #ifdef DEBUGGING
  151.         dlevel = olddlevel;
  152. #endif
  153.         break;
  154.         case C_BLOCK:
  155.         case C_WHILE:
  156.         if (!(cmdflags & CF_ONCE)) {
  157.             cmdflags |= CF_ONCE;
  158.             if (++loop_ptr >= loop_max) {
  159.             loop_max += 128;
  160.             Renew(loop_stack, loop_max, struct loop);
  161.             }
  162.             loop_stack[loop_ptr].loop_label = cmd->c_label;
  163.             loop_stack[loop_ptr].loop_sp = sp;
  164. #ifdef DEBUGGING
  165.             if (debug & 4) {
  166.             deb("(Pushing label #%d %s)\n",
  167.               loop_ptr, cmd->c_label ? cmd->c_label : "");
  168.             }
  169. #endif
  170.         }
  171. #ifdef JMPCLOBBER
  172.         cmdparm = cmd;
  173. #endif
  174.         match = setjmp(loop_stack[loop_ptr].loop_env);
  175.         if (match) {
  176.             st = stack->ary_array;    /* possibly reallocated */
  177. #ifdef JMPCLOBBER
  178.             cmd = cmdparm;
  179.             cmdflags = cmd->c_flags|CF_ONCE;
  180. #endif
  181.             if (savestack->ary_fill > oldsave)
  182.             restorelist(oldsave);
  183.             switch (match) {
  184.             default:
  185.             fatal("longjmp returned bad value (%d)",match);
  186.             case O_LAST:    /* not done unless go_to found */
  187.             go_to = Nullch;
  188.             if (lastretstr) {
  189.                 retstr = lastretstr;
  190.                 newsp = -2;
  191.             }
  192.             else {
  193.                 newsp = sp + lastsize;
  194.                 retstr = st[newsp];
  195.             }
  196. #ifdef DEBUGGING
  197.             olddlevel = dlevel;
  198. #endif
  199.             curspat = oldspat;
  200.             goto next_cmd;
  201.             case O_NEXT:    /* not done unless go_to found */
  202.             go_to = Nullch;
  203. #ifdef JMPCLOBBER
  204.             newsp = -2;
  205.             retstr = &str_undef;
  206. #endif
  207.             goto next_iter;
  208.             case O_REDO:    /* not done unless go_to found */
  209.             go_to = Nullch;
  210. #ifdef JMPCLOBBER
  211.             newsp = -2;
  212.             retstr = &str_undef;
  213. #endif
  214.             goto doit;
  215.             }
  216.         }
  217.         oldspat = curspat;
  218.         oldsave = savestack->ary_fill;
  219. #ifdef DEBUGGING
  220.         olddlevel = dlevel;
  221. #endif
  222.         if (cmd->ucmd.ccmd.cc_true) {
  223. #ifdef DEBUGGING
  224.             if (debug) {
  225.             debname[dlevel] = 't';
  226.             debdelim[dlevel] = '_';
  227.             if (++dlevel >= dlmax)
  228.                 grow_dlevel();
  229.             }
  230. #endif
  231.             newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme && (cmdflags & CF_TERM),sp);
  232.             st = stack->ary_array;    /* possibly reallocated */
  233.             retstr = st[newsp];
  234.         }
  235.         if (!goto_targ) {
  236.             go_to = Nullch;
  237.             goto next_iter;
  238.         }
  239. #ifdef DEBUGGING
  240.         dlevel = olddlevel;
  241. #endif
  242.         if (cmd->ucmd.ccmd.cc_alt) {
  243. #ifdef DEBUGGING
  244.             if (debug) {
  245.             debname[dlevel] = 'a';
  246.             debdelim[dlevel] = '_';
  247.             if (++dlevel >= dlmax)
  248.                 grow_dlevel();
  249.             }
  250. #endif
  251.             newsp = cmd_exec(cmd->ucmd.ccmd.cc_alt,gimme && (cmdflags & CF_TERM),sp);
  252.             st = stack->ary_array;    /* possibly reallocated */
  253.             retstr = st[newsp];
  254.         }
  255.         if (goto_targ)
  256.             break;
  257.         go_to = Nullch;
  258.         goto finish_while;
  259.         }
  260.         cmd = cmd->c_next;
  261.         if (cmd && cmd->c_head == cmd)
  262.                     /* reached end of while loop */
  263.         return sp;        /* targ isn't in this block */
  264.         if (cmdflags & CF_ONCE) {
  265. #ifdef DEBUGGING
  266.         if (debug & 4) {
  267.             tmps = loop_stack[loop_ptr].loop_label;
  268.             deb("(Popping label #%d %s)\n",loop_ptr,
  269.             tmps ? tmps : "" );
  270.         }
  271. #endif
  272.         loop_ptr--;
  273.         }
  274.         goto tail_recursion_entry;
  275.     }
  276.     }
  277.  
  278. until_loop:
  279.  
  280.     /* Set line number so run-time errors can be located */
  281.  
  282.     curcmd = cmd;
  283.  
  284. #ifdef DEBUGGING
  285.     if (debug) {
  286.     if (debug & 2) {
  287.         deb("%s    (%lx)    r%lx    t%lx    a%lx    n%lx    cs%lx\n",
  288.         cmdname[cmd->c_type],cmd,cmd->c_expr,
  289.         cmd->ucmd.ccmd.cc_true,cmd->ucmd.ccmd.cc_alt,cmd->c_next,
  290.         curspat);
  291.     }
  292.     debname[dlevel] = cmdname[cmd->c_type][0];
  293.     debdelim[dlevel] = '!';
  294.     if (++dlevel >= dlmax)
  295.         grow_dlevel();
  296.     }
  297. #endif
  298.  
  299.     /* Here is some common optimization */
  300.  
  301.     if (cmdflags & CF_COND) {
  302.     switch (cmdflags & CF_OPTIMIZE) {
  303.  
  304.     case CFT_FALSE:
  305.         retstr = cmd->c_short;
  306.         newsp = -2;
  307.         match = FALSE;
  308.         if (cmdflags & CF_NESURE)
  309.         goto maybe;
  310.         break;
  311.     case CFT_TRUE:
  312.         retstr = cmd->c_short;
  313.         newsp = -2;
  314.         match = TRUE;
  315.         if (cmdflags & CF_EQSURE)
  316.         goto flipmaybe;
  317.         break;
  318.  
  319.     case CFT_REG:
  320.         retstr = STAB_STR(cmd->c_stab);
  321.         newsp = -2;
  322.         match = str_true(retstr);    /* => retstr = retstr, c2 should fix */
  323.         if (cmdflags & (match ? CF_EQSURE : CF_NESURE))
  324.         goto flipmaybe;
  325.         break;
  326.  
  327.     case CFT_ANCHOR:    /* /^pat/ optimization */
  328.         if (multiline) {
  329.         if (*cmd->c_short->str_ptr && !(cmdflags & CF_EQSURE))
  330.             goto scanner;    /* just unanchor it */
  331.         else
  332.             break;        /* must evaluate */
  333.         }
  334.         /* FALL THROUGH */
  335.     case CFT_STROP:        /* string op optimization */
  336.         retstr = STAB_STR(cmd->c_stab);
  337.         newsp = -2;
  338. #ifndef I286
  339.         if (*cmd->c_short->str_ptr == *str_get(retstr) &&
  340.             bcmp(cmd->c_short->str_ptr, str_get(retstr),
  341.               cmd->c_slen) == 0 ) {
  342.         if (cmdflags & CF_EQSURE) {
  343.             if (sawampersand && (cmdflags & CF_OPTIMIZE) != CFT_STROP) {
  344.             curspat = Nullspat;
  345.             if (leftstab)
  346.                 str_nset(stab_val(leftstab),"",0);
  347.             if (amperstab)
  348.                 str_sset(stab_val(amperstab),cmd->c_short);
  349.             if (rightstab)
  350.                 str_nset(stab_val(rightstab),
  351.                   retstr->str_ptr + cmd->c_slen,
  352.                   retstr->str_cur - cmd->c_slen);
  353.             }
  354.             if (cmd->c_spat)
  355.             lastspat = cmd->c_spat;
  356.             match = !(cmdflags & CF_FIRSTNEG);
  357.             retstr = &str_yes;
  358.             goto flipmaybe;
  359.         }
  360.         }
  361.         else if (cmdflags & CF_NESURE) {
  362.         match = cmdflags & CF_FIRSTNEG;
  363.         retstr = &str_no;
  364.         goto flipmaybe;
  365.         }
  366. #else
  367.         {
  368.         char *zap1, *zap2, zap1c, zap2c;
  369.         int  zaplen;
  370.  
  371.         zap1 = cmd->c_short->str_ptr;
  372.         zap2 = str_get(retstr);
  373.         zap1c = *zap1;
  374.         zap2c = *zap2;
  375.         zaplen = cmd->c_slen;
  376.         if ((zap1c == zap2c) && (bcmp(zap1, zap2, zaplen) == 0)) {
  377.             if (cmdflags & CF_EQSURE) {
  378.             if (sawampersand &&
  379.               (cmdflags & CF_OPTIMIZE) != CFT_STROP) {
  380.                 curspat = Nullspat;
  381.                 if (leftstab)
  382.                 str_nset(stab_val(leftstab),"",0);
  383.                 if (amperstab)
  384.                 str_sset(stab_val(amperstab),cmd->c_short);
  385.                 if (rightstab)
  386.                 str_nset(stab_val(rightstab),
  387.                      retstr->str_ptr + cmd->c_slen,
  388.                      retstr->str_cur - cmd->c_slen);
  389.             }
  390.             if (cmd->c_spat)
  391.                 lastspat = cmd->c_spat;
  392.              match = !(cmdflags & CF_FIRSTNEG);
  393.              retstr = &str_yes;
  394.              goto flipmaybe;
  395.             }
  396.         }
  397.         else if (cmdflags & CF_NESURE) {
  398.             match = cmdflags & CF_FIRSTNEG;
  399.             retstr = &str_no;
  400.             goto flipmaybe;
  401.         }
  402.         }
  403. #endif
  404.         break;            /* must evaluate */
  405.  
  406.     case CFT_SCAN:            /* non-anchored search */
  407.       scanner:
  408.         retstr = STAB_STR(cmd->c_stab);
  409.         newsp = -2;
  410.         if (retstr->str_pok & SP_STUDIED)
  411.         if (screamfirst[cmd->c_short->str_rare] >= 0)
  412.             tmps = screaminstr(retstr, cmd->c_short);
  413.         else
  414.             tmps = Nullch;
  415.         else {
  416.         tmps = str_get(retstr);        /* make sure it's pok */
  417. #ifndef lint
  418.         tmps = fbminstr((unsigned char*)tmps,
  419.             (unsigned char*)tmps + retstr->str_cur, cmd->c_short);
  420. #endif
  421.         }
  422.         if (tmps) {
  423.         if (cmdflags & CF_EQSURE) {
  424.             ++cmd->c_short->str_u.str_useful;
  425.             if (sawampersand) {
  426.             curspat = Nullspat;
  427.             if (leftstab)
  428.                 str_nset(stab_val(leftstab),retstr->str_ptr,
  429.                   tmps - retstr->str_ptr);
  430.             if (amperstab)
  431.                 str_nset(stab_val(amperstab),
  432.                   tmps, cmd->c_short->str_cur);
  433.             if (rightstab)
  434.                 str_nset(stab_val(rightstab),
  435.                   tmps + cmd->c_short->str_cur,
  436.                   retstr->str_cur - (tmps - retstr->str_ptr) -
  437.                 cmd->c_short->str_cur);
  438.             }
  439.             lastspat = cmd->c_spat;
  440.             match = !(cmdflags & CF_FIRSTNEG);
  441.             retstr = &str_yes;
  442.             goto flipmaybe;
  443.         }
  444.         else
  445.             hint = tmps;
  446.         }
  447.         else {
  448.         if (cmdflags & CF_NESURE) {
  449.             ++cmd->c_short->str_u.str_useful;
  450.             match = cmdflags & CF_FIRSTNEG;
  451.             retstr = &str_no;
  452.             goto flipmaybe;
  453.         }
  454.         }
  455.         if (--cmd->c_short->str_u.str_useful < 0) {
  456.         cmdflags &= ~CF_OPTIMIZE;
  457.         cmdflags |= CFT_EVAL;    /* never try this optimization again */
  458.         cmd->c_flags = (cmdflags & ~CF_ONCE);
  459.         }
  460.         break;            /* must evaluate */
  461.  
  462.     case CFT_NUMOP:        /* numeric op optimization */
  463.         retstr = STAB_STR(cmd->c_stab);
  464.         newsp = -2;
  465.         switch (cmd->c_slen) {
  466.         case O_EQ:
  467.         if (dowarn) {
  468.             if ((!retstr->str_nok && !looks_like_number(retstr)))
  469.             warn("Possible use of == on string value");
  470.         }
  471.         match = (str_gnum(retstr) == cmd->c_short->str_u.str_nval);
  472.         break;
  473.         case O_NE:
  474.         match = (str_gnum(retstr) != cmd->c_short->str_u.str_nval);
  475.         break;
  476.         case O_LT:
  477.         match = (str_gnum(retstr) <  cmd->c_short->str_u.str_nval);
  478.         break;
  479.         case O_LE:
  480.         match = (str_gnum(retstr) <= cmd->c_short->str_u.str_nval);
  481.         break;
  482.         case O_GT:
  483.         match = (str_gnum(retstr) >  cmd->c_short->str_u.str_nval);
  484.         break;
  485.         case O_GE:
  486.         match = (str_gnum(retstr) >= cmd->c_short->str_u.str_nval);
  487.         break;
  488.         }
  489.         if (match) {
  490.         if (cmdflags & CF_EQSURE) {
  491.             retstr = &str_yes;
  492.             goto flipmaybe;
  493.         }
  494.         }
  495.         else if (cmdflags & CF_NESURE) {
  496.         retstr = &str_no;
  497.         goto flipmaybe;
  498.         }
  499.         break;            /* must evaluate */
  500.  
  501.     case CFT_INDGETS:        /* while (<$foo>) */
  502.         last_in_stab = stabent(str_get(STAB_STR(cmd->c_stab)),TRUE);
  503.         if (!stab_io(last_in_stab))
  504.         stab_io(last_in_stab) = stio_new();
  505.         goto dogets;
  506.     case CFT_GETS:            /* really a while (<file>) */
  507.         last_in_stab = cmd->c_stab;
  508.       dogets:
  509.         fp = stab_io(last_in_stab)->ifp;
  510.         retstr = stab_val(defstab);
  511.         newsp = -2;
  512.       keepgoing:
  513.         if (fp && str_gets(retstr, fp, 0)) {
  514.         if (*retstr->str_ptr == '0' && retstr->str_cur == 1)
  515.             match = FALSE;
  516.         else
  517.             match = TRUE;
  518.         stab_io(last_in_stab)->lines++;
  519.         }
  520.         else if (stab_io(last_in_stab)->flags & IOF_ARGV) {
  521.         if (!fp)
  522.             goto doeval;    /* first time through */
  523.         fp = nextargv(last_in_stab);
  524.         if (fp)
  525.             goto keepgoing;
  526.         (void)do_close(last_in_stab,FALSE);
  527.         stab_io(last_in_stab)->flags |= IOF_START;
  528.         retstr = &str_undef;
  529.         match = FALSE;
  530.         }
  531.         else {
  532.         retstr = &str_undef;
  533.         match = FALSE;
  534.         }
  535.         goto flipmaybe;
  536.     case CFT_EVAL:
  537.         break;
  538.     case CFT_UNFLIP:
  539.         while (tmps_max > tmps_base) {    /* clean up after last eval */
  540.         str_free(tmps_list[tmps_max]);
  541.         tmps_list[tmps_max--] = Nullstr;
  542.         }
  543.         newsp = eval(cmd->c_expr,gimme && (cmdflags & CF_TERM),sp);
  544.         st = stack->ary_array;    /* possibly reallocated */
  545.         retstr = st[newsp];
  546.         match = str_true(retstr);
  547.         if (cmd->c_expr->arg_type == O_FLIP)    /* undid itself? */
  548.         cmdflags = copyopt(cmd,cmd->c_expr[3].arg_ptr.arg_cmd);
  549.         goto maybe;
  550.     case CFT_CHOP:
  551.         retstr = stab_val(cmd->c_stab);
  552.         newsp = -2;
  553.         match = (retstr->str_cur != 0);
  554.         tmps = str_get(retstr);
  555.         tmps += retstr->str_cur - match;
  556.         str_nset(&str_chop,tmps,match);
  557.         *tmps = '\0';
  558.         retstr->str_nok = 0;
  559.         retstr->str_cur = tmps - retstr->str_ptr;
  560.         STABSET(retstr);
  561.         retstr = &str_chop;
  562.         goto flipmaybe;
  563.     case CFT_ARRAY:
  564.         match = cmd->c_short->str_u.str_useful; /* just to get register */
  565.  
  566.         if (match < 0) {        /* first time through here? */
  567.         ar = stab_array(cmd->c_expr[1].arg_ptr.arg_stab);
  568.         aryoptsave = savestack->ary_fill;
  569.         savesptr(&stab_val(cmd->c_stab));
  570.         savelong(&cmd->c_short->str_u.str_useful);
  571.         }
  572.         else {
  573.         ar = stab_xarray(cmd->c_expr[1].arg_ptr.arg_stab);
  574.         if (cmd->c_type != C_WHILE && savestack->ary_fill > firstsave)
  575.             restorelist(firstsave);
  576.         }
  577.  
  578.         if (match >= ar->ary_fill) {    /* we're in LAST, probably */
  579.         retstr = &str_undef;
  580.         cmd->c_short->str_u.str_useful = -1;    /* actually redundant */
  581.         match = FALSE;
  582.         }
  583.         else {
  584.         match++;
  585.         if (!(retstr = ar->ary_array[match]))
  586.             retstr = afetch(ar,match,TRUE);
  587.         stab_val(cmd->c_stab) = retstr;
  588.         cmd->c_short->str_u.str_useful = match;
  589.         match = TRUE;
  590.         }
  591.         newsp = -2;
  592.         goto maybe;
  593.     case CFT_D1:
  594.         break;
  595.     case CFT_D0:
  596.         if (DBsingle->str_u.str_nval != 0)
  597.         break;
  598.         if (DBsignal->str_u.str_nval != 0)
  599.         break;
  600.         if (DBtrace->str_u.str_nval != 0)
  601.         break;
  602.         goto next_cmd;
  603.     }
  604.  
  605.     /* we have tried to make this normal case as abnormal as possible */
  606.  
  607.     doeval:
  608.     if (gimme == G_ARRAY) {
  609.         lastretstr = Nullstr;
  610.         lastspbase = sp;
  611.         lastsize = newsp - sp;
  612.         if (lastsize < 0)
  613.         lastsize = 0;
  614.     }
  615.     else
  616.         lastretstr = retstr;
  617.     while (tmps_max > tmps_base) {    /* clean up after last eval */
  618.         str_free(tmps_list[tmps_max]);
  619.         tmps_list[tmps_max--] = Nullstr;
  620.     }
  621.     newsp = eval(cmd->c_expr,
  622.       gimme && (cmdflags & CF_TERM) && cmd->c_type == C_EXPR &&
  623.         !cmd->ucmd.acmd.ac_expr,
  624.       sp);
  625.     st = stack->ary_array;    /* possibly reallocated */
  626.     retstr = st[newsp];
  627.     if (newsp > sp && retstr)
  628.         match = str_true(retstr);
  629.     else
  630.         match = FALSE;
  631.     goto maybe;
  632.  
  633.     /* if flipflop was true, flop it */
  634.  
  635.     flipmaybe:
  636.     if (match && cmdflags & CF_FLIP) {
  637.         while (tmps_max > tmps_base) {    /* clean up after last eval */
  638.         str_free(tmps_list[tmps_max]);
  639.         tmps_list[tmps_max--] = Nullstr;
  640.         }
  641.         if (cmd->c_expr->arg_type == O_FLOP) {    /* currently toggled? */
  642.         newsp = eval(cmd->c_expr,G_SCALAR,sp);/*let eval undo it*/
  643.         cmdflags = copyopt(cmd,cmd->c_expr[3].arg_ptr.arg_cmd);
  644.         }
  645.         else {
  646.         newsp = eval(cmd->c_expr,G_SCALAR,sp);/* let eval do it */
  647.         if (cmd->c_expr->arg_type == O_FLOP)    /* still toggled? */
  648.             cmdflags = copyopt(cmd,cmd->c_expr[4].arg_ptr.arg_cmd);
  649.         }
  650.     }
  651.     else if (cmdflags & CF_FLIP) {
  652.         if (cmd->c_expr->arg_type == O_FLOP) {    /* currently toggled? */
  653.         match = TRUE;                /* force on */
  654.         }
  655.     }
  656.  
  657.     /* at this point, match says whether our expression was true */
  658.  
  659.     maybe:
  660.     if (cmdflags & CF_INVERT)
  661.         match = !match;
  662.     if (!match)
  663.         goto next_cmd;
  664.     }
  665. #ifdef TAINT
  666.     tainted = 0;    /* modifier doesn't affect regular expression */
  667. #endif
  668.  
  669.     /* now to do the actual command, if any */
  670.  
  671.     switch (cmd->c_type) {
  672.     case C_NULL:
  673.     fatal("panic: cmd_exec");
  674.     case C_EXPR:            /* evaluated for side effects */
  675.     if (cmd->ucmd.acmd.ac_expr) {    /* more to do? */
  676.         if (gimme == G_ARRAY) {
  677.         lastretstr = Nullstr;
  678.         lastspbase = sp;
  679.         lastsize = newsp - sp;
  680.         if (lastsize < 0)
  681.             lastsize = 0;
  682.         }
  683.         else
  684.         lastretstr = retstr;
  685.         while (tmps_max > tmps_base) {    /* clean up after last eval */
  686.         str_free(tmps_list[tmps_max]);
  687.         tmps_list[tmps_max--] = Nullstr;
  688.         }
  689.         newsp = eval(cmd->ucmd.acmd.ac_expr,gimme && (cmdflags&CF_TERM),sp);
  690.         st = stack->ary_array;    /* possibly reallocated */
  691.         retstr = st[newsp];
  692.     }
  693.     break;
  694.     case C_NSWITCH:
  695.     {
  696.         double value = str_gnum(STAB_STR(cmd->c_stab));
  697.  
  698.         match = (int)value;
  699.         if (value < 0.0) {
  700.         if (((double)match) > value)
  701.             --match;        /* was fractional--truncate other way */
  702.         }
  703.     }
  704.     goto doswitch;
  705.     case C_CSWITCH:
  706.     match = *(str_get(STAB_STR(cmd->c_stab))) & 255;
  707.       doswitch:
  708.     match -= cmd->ucmd.scmd.sc_offset;
  709.     if (match < 0)
  710.         match = 0;
  711.     else if (match > cmd->ucmd.scmd.sc_max)
  712.         match = cmd->ucmd.scmd.sc_max;
  713.     cmd = cmd->ucmd.scmd.sc_next[match];
  714.     goto tail_recursion_entry;
  715.     case C_NEXT:
  716.     cmd = cmd->ucmd.ccmd.cc_alt;
  717.     goto tail_recursion_entry;
  718.     case C_ELSIF:
  719.     fatal("panic: ELSIF");
  720.     case C_IF:
  721.     oldspat = curspat;
  722.     oldsave = savestack->ary_fill;
  723. #ifdef DEBUGGING
  724.     olddlevel = dlevel;
  725. #endif
  726.     retstr = &str_yes;
  727.     newsp = -2;
  728.     if (cmd->ucmd.ccmd.cc_true) {
  729. #ifdef DEBUGGING
  730.         if (debug) {
  731.         debname[dlevel] = 't';
  732.         debdelim[dlevel] = '_';
  733.         if (++dlevel >= dlmax)
  734.             grow_dlevel();
  735.         }
  736. #endif
  737.         newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme && (cmdflags & CF_TERM),sp);
  738.         st = stack->ary_array;    /* possibly reallocated */
  739.         retstr = st[newsp];
  740.     }
  741.     curspat = oldspat;
  742.     if (savestack->ary_fill > oldsave)
  743.         restorelist(oldsave);
  744. #ifdef DEBUGGING
  745.     dlevel = olddlevel;
  746. #endif
  747.     cmd = cmd->ucmd.ccmd.cc_alt;
  748.     goto tail_recursion_entry;
  749.     case C_ELSE:
  750.     oldspat = curspat;
  751.     oldsave = savestack->ary_fill;
  752. #ifdef DEBUGGING
  753.     olddlevel = dlevel;
  754. #endif
  755.     retstr = &str_undef;
  756.     newsp = -2;
  757.     if (cmd->ucmd.ccmd.cc_true) {
  758. #ifdef DEBUGGING
  759.         if (debug) {
  760.         debname[dlevel] = 'e';
  761.         debdelim[dlevel] = '_';
  762.         if (++dlevel >= dlmax)
  763.             grow_dlevel();
  764.         }
  765. #endif
  766.         newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme && (cmdflags & CF_TERM),sp);
  767.         st = stack->ary_array;    /* possibly reallocated */
  768.         retstr = st[newsp];
  769.     }
  770.     curspat = oldspat;
  771.     if (savestack->ary_fill > oldsave)
  772.         restorelist(oldsave);
  773. #ifdef DEBUGGING
  774.     dlevel = olddlevel;
  775. #endif
  776.     break;
  777.     case C_BLOCK:
  778.     case C_WHILE:
  779.     if (!(cmdflags & CF_ONCE)) {    /* first time through here? */
  780.         cmdflags |= CF_ONCE;
  781.         if (++loop_ptr >= loop_max) {
  782.         loop_max += 128;
  783.         Renew(loop_stack, loop_max, struct loop);
  784.         }
  785.         loop_stack[loop_ptr].loop_label = cmd->c_label;
  786.         loop_stack[loop_ptr].loop_sp = sp;
  787. #ifdef DEBUGGING
  788.         if (debug & 4) {
  789.         deb("(Pushing label #%d %s)\n",
  790.           loop_ptr, cmd->c_label ? cmd->c_label : "");
  791.         }
  792. #endif
  793.     }
  794. #ifdef JMPCLOBBER
  795.     cmdparm = cmd;
  796. #endif
  797.     match = setjmp(loop_stack[loop_ptr].loop_env);
  798.     if (match) {
  799.         st = stack->ary_array;    /* possibly reallocated */
  800. #ifdef JMPCLOBBER
  801.         cmd = cmdparm;
  802.         cmdflags = cmd->c_flags|CF_ONCE;
  803.         go_to = goto_targ;
  804. #endif
  805.         if (savestack->ary_fill > oldsave)
  806.         restorelist(oldsave);
  807.         switch (match) {
  808.         default:
  809.         fatal("longjmp returned bad value (%d)",match);
  810.         case O_LAST:
  811.         if (lastretstr) {
  812.             retstr = lastretstr;
  813.             newsp = -2;
  814.         }
  815.         else {
  816.             newsp = sp + lastsize;
  817.             retstr = st[newsp];
  818.         }
  819.         curspat = oldspat;
  820.         goto next_cmd;
  821.         case O_NEXT:
  822. #ifdef JMPCLOBBER
  823.         newsp = -2;
  824.         retstr = &str_undef;
  825. #endif
  826.         goto next_iter;
  827.         case O_REDO:
  828. #ifdef DEBUGGING
  829.         dlevel = olddlevel;
  830. #endif
  831. #ifdef JMPCLOBBER
  832.         newsp = -2;
  833.         retstr = &str_undef;
  834. #endif
  835.         goto doit;
  836.         }
  837.     }
  838.     oldspat = curspat;
  839.     oldsave = savestack->ary_fill;
  840. #ifdef DEBUGGING
  841.     olddlevel = dlevel;
  842. #endif
  843.     doit:
  844.     if (cmd->ucmd.ccmd.cc_true) {
  845. #ifdef DEBUGGING
  846.         if (debug) {
  847.         debname[dlevel] = 't';
  848.         debdelim[dlevel] = '_';
  849.         if (++dlevel >= dlmax)
  850.             grow_dlevel();
  851.         }
  852. #endif
  853.         newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme && (cmdflags & CF_TERM),sp);
  854.         st = stack->ary_array;    /* possibly reallocated */
  855.         retstr = st[newsp];
  856.     }
  857.     /* actually, this spot is rarely reached anymore since the above
  858.      * cmd_exec() returns through longjmp().  Hooray for structure.
  859.      */
  860.       next_iter:
  861. #ifdef DEBUGGING
  862.     dlevel = olddlevel;
  863. #endif
  864.     if (cmd->ucmd.ccmd.cc_alt) {
  865. #ifdef DEBUGGING
  866.         if (debug) {
  867.         debname[dlevel] = 'a';
  868.         debdelim[dlevel] = '_';
  869.         if (++dlevel >= dlmax)
  870.             grow_dlevel();
  871.         }
  872. #endif
  873.         newsp = cmd_exec(cmd->ucmd.ccmd.cc_alt,gimme && (cmdflags & CF_TERM),sp);
  874.         st = stack->ary_array;    /* possibly reallocated */
  875.         retstr = st[newsp];
  876.     }
  877.       finish_while:
  878.     curspat = oldspat;
  879.     if (savestack->ary_fill > oldsave) {
  880.         if (cmdflags & CF_TERM) {
  881.         for (match = sp + 1; match <= newsp; match++)
  882.             st[match] = str_mortal(st[match]);
  883.         retstr = st[newsp];
  884.         }
  885.         restorelist(oldsave);
  886.     }
  887. #ifdef DEBUGGING
  888.     dlevel = olddlevel - 1;
  889. #endif
  890.     if (cmd->c_type != C_BLOCK)
  891.         goto until_loop;    /* go back and evaluate conditional again */
  892.     }
  893.     if (cmdflags & CF_LOOP) {
  894.     cmdflags |= CF_COND;        /* now test the condition */
  895. #ifdef DEBUGGING
  896.     dlevel = entdlevel;
  897. #endif
  898.     goto until_loop;
  899.     }
  900.   next_cmd:
  901.     if (cmdflags & CF_ONCE) {
  902. #ifdef DEBUGGING
  903.     if (debug & 4) {
  904.         tmps = loop_stack[loop_ptr].loop_label;
  905.         deb("(Popping label #%d %s)\n",loop_ptr, tmps ? tmps : "");
  906.     }
  907. #endif
  908.     loop_ptr--;
  909.     if ((cmdflags & CF_OPTIMIZE) == CFT_ARRAY &&
  910.       savestack->ary_fill > aryoptsave)
  911.         restorelist(aryoptsave);
  912.     }
  913.     cmd = cmd->c_next;
  914.     goto tail_recursion_entry;
  915. }
  916.  
  917. #ifdef DEBUGGING
  918. #  ifndef I_VARARGS
  919. /*VARARGS1*/
  920. deb(pat,a1,a2,a3,a4,a5,a6,a7,a8)
  921. char *pat;
  922. {
  923.     register int i;
  924.  
  925.     fprintf(stderr,"%-4ld",(long)curcmd->c_line);
  926.     for (i=0; i<dlevel; i++)
  927.     fprintf(stderr,"%c%c ",debname[i],debdelim[i]);
  928.     fprintf(stderr,pat,a1,a2,a3,a4,a5,a6,a7,a8);
  929. }
  930. #  else
  931. /*VARARGS1*/
  932. deb(va_alist)
  933. va_dcl
  934. {
  935.     va_list args;
  936.     char *pat;
  937.     register int i;
  938.  
  939.     va_start(args);
  940.     fprintf(stderr,"%-4ld",(long)curcmd->c_line);
  941.     for (i=0; i<dlevel; i++)
  942.     fprintf(stderr,"%c%c ",debname[i],debdelim[i]);
  943.  
  944.     pat = va_arg(args, char *);
  945.     (void) vfprintf(stderr,pat,args);
  946.     va_end( args );
  947. }
  948. #  endif
  949. #endif
  950.  
  951. copyopt(cmd,which)
  952. register CMD *cmd;
  953. register CMD *which;
  954. {
  955.     cmd->c_flags &= CF_ONCE|CF_COND|CF_LOOP;
  956.     cmd->c_flags |= which->c_flags;
  957.     cmd->c_short = which->c_short;
  958.     cmd->c_slen = which->c_slen;
  959.     cmd->c_stab = which->c_stab;
  960.     return cmd->c_flags;
  961. }
  962.  
  963. ARRAY *
  964. saveary(stab)
  965. STAB *stab;
  966. {
  967.     register STR *str;
  968.  
  969.     str = Str_new(10,0);
  970.     str->str_state = SS_SARY;
  971.     str->str_u.str_stab = stab;
  972.     if (str->str_ptr) {
  973.     Safefree(str->str_ptr);
  974.     str->str_ptr = Nullch;
  975.     str->str_len = 0;
  976.     }
  977.     str->str_ptr = (char*)stab_array(stab);
  978.     (void)apush(savestack,str); /* save array ptr */
  979.     stab_xarray(stab) = Null(ARRAY*);
  980.     return stab_xarray(aadd(stab));
  981. }
  982.  
  983. HASH *
  984. savehash(stab)
  985. STAB *stab;
  986. {
  987.     register STR *str;
  988.  
  989.     str = Str_new(11,0);
  990.     str->str_state = SS_SHASH;
  991.     str->str_u.str_stab = stab;
  992.     if (str->str_ptr) {
  993.     Safefree(str->str_ptr);
  994.     str->str_ptr = Nullch;
  995.     str->str_len = 0;
  996.     }
  997.     str->str_ptr = (char*)stab_hash(stab);
  998.     (void)apush(savestack,str); /* save hash ptr */
  999.     stab_xhash(stab) = Null(HASH*);
  1000.     return stab_xhash(hadd(stab));
  1001. }
  1002.  
  1003. void
  1004. saveitem(item)
  1005. register STR *item;
  1006. {
  1007.     register STR *str;
  1008.  
  1009.     (void)apush(savestack,item);        /* remember the pointer */
  1010.     str = Str_new(12,0);
  1011.     str_sset(str,item);
  1012.     (void)apush(savestack,str);            /* remember the value */
  1013. }
  1014.  
  1015. void
  1016. saveint(intp)
  1017. int *intp;
  1018. {
  1019.     register STR *str;
  1020.  
  1021.     str = Str_new(13,0);
  1022.     str->str_state = SS_SINT;
  1023.     str->str_u.str_useful = (long)*intp;    /* remember value */
  1024.     if (str->str_ptr) {
  1025.     Safefree(str->str_ptr);
  1026.     str->str_len = 0;
  1027.     }
  1028.     str->str_ptr = (char*)intp;        /* remember pointer */
  1029.     (void)apush(savestack,str);
  1030. }
  1031.  
  1032. void
  1033. savelong(longp)
  1034. long *longp;
  1035. {
  1036.     register STR *str;
  1037.  
  1038.     str = Str_new(14,0);
  1039.     str->str_state = SS_SLONG;
  1040.     str->str_u.str_useful = *longp;        /* remember value */
  1041.     if (str->str_ptr) {
  1042.     Safefree(str->str_ptr);
  1043.     str->str_len = 0;
  1044.     }
  1045.     str->str_ptr = (char*)longp;        /* remember pointer */
  1046.     (void)apush(savestack,str);
  1047. }
  1048.  
  1049. void
  1050. savesptr(sptr)
  1051. STR **sptr;
  1052. {
  1053.     register STR *str;
  1054.  
  1055.     str = Str_new(15,0);
  1056.     str->str_state = SS_SSTRP;
  1057.     str->str_magic = *sptr;        /* remember value */
  1058.     if (str->str_ptr) {
  1059.     Safefree(str->str_ptr);
  1060.     str->str_len = 0;
  1061.     }
  1062.     str->str_ptr = (char*)sptr;        /* remember pointer */
  1063.     (void)apush(savestack,str);
  1064. }
  1065.  
  1066. void
  1067. savenostab(stab)
  1068. STAB *stab;
  1069. {
  1070.     register STR *str;
  1071.  
  1072.     str = Str_new(16,0);
  1073.     str->str_state = SS_SNSTAB;
  1074.     str->str_magic = (STR*)stab;    /* remember which stab to free */
  1075.     (void)apush(savestack,str);
  1076. }
  1077.  
  1078. void
  1079. savehptr(hptr)
  1080. HASH **hptr;
  1081. {
  1082.     register STR *str;
  1083.  
  1084.     str = Str_new(17,0);
  1085.     str->str_state = SS_SHPTR;
  1086.     str->str_u.str_hash = *hptr;    /* remember value */
  1087.     if (str->str_ptr) {
  1088.     Safefree(str->str_ptr);
  1089.     str->str_len = 0;
  1090.     }
  1091.     str->str_ptr = (char*)hptr;        /* remember pointer */
  1092.     (void)apush(savestack,str);
  1093. }
  1094.  
  1095. void
  1096. saveaptr(aptr)
  1097. ARRAY **aptr;
  1098. {
  1099.     register STR *str;
  1100.  
  1101.     str = Str_new(17,0);
  1102.     str->str_state = SS_SAPTR;
  1103.     str->str_u.str_array = *aptr;    /* remember value */
  1104.     if (str->str_ptr) {
  1105.     Safefree(str->str_ptr);
  1106.     str->str_len = 0;
  1107.     }
  1108.     str->str_ptr = (char*)aptr;        /* remember pointer */
  1109.     (void)apush(savestack,str);
  1110. }
  1111.  
  1112. void
  1113. savelist(sarg,maxsarg)
  1114. register STR **sarg;
  1115. int maxsarg;
  1116. {
  1117.     register STR *str;
  1118.     register int i;
  1119.  
  1120.     for (i = 1; i <= maxsarg; i++) {
  1121.     (void)apush(savestack,sarg[i]);        /* remember the pointer */
  1122.     str = Str_new(18,0);
  1123.     str_sset(str,sarg[i]);
  1124.     (void)apush(savestack,str);            /* remember the value */
  1125.     sarg[i]->str_u.str_useful = -1;
  1126.     }
  1127. }
  1128.  
  1129. void
  1130. restorelist(base)
  1131. int base;
  1132. {
  1133.     register STR *str;
  1134.     register STR *value;
  1135.     register STAB *stab;
  1136.  
  1137.     if (base < -1)
  1138.     fatal("panic: corrupt saved stack index");
  1139.     while (savestack->ary_fill > base) {
  1140.     value = apop(savestack);
  1141.     switch (value->str_state) {
  1142.     case SS_NORM:                /* normal string */
  1143.     case SS_INCR:
  1144.         str = apop(savestack);
  1145.         str_replace(str,value);
  1146.         STABSET(str);
  1147.         break;
  1148.     case SS_SARY:                /* array reference */
  1149.         stab = value->str_u.str_stab;
  1150.         afree(stab_xarray(stab));
  1151.         stab_xarray(stab) = (ARRAY*)value->str_ptr;
  1152.         value->str_ptr = Nullch;
  1153.         str_free(value);
  1154.         break;
  1155.     case SS_SHASH:                /* hash reference */
  1156.         stab = value->str_u.str_stab;
  1157.         (void)hfree(stab_xhash(stab), FALSE);
  1158.         stab_xhash(stab) = (HASH*)value->str_ptr;
  1159.         value->str_ptr = Nullch;
  1160.         str_free(value);
  1161.         break;
  1162.     case SS_SINT:                /* int reference */
  1163.         *((int*)value->str_ptr) = (int)value->str_u.str_useful;
  1164.         value->str_ptr = Nullch;
  1165.         str_free(value);
  1166.         break;
  1167.     case SS_SLONG:                /* long reference */
  1168.         *((long*)value->str_ptr) = value->str_u.str_useful;
  1169.         value->str_ptr = Nullch;
  1170.         str_free(value);
  1171.         break;
  1172.     case SS_SSTRP:                /* STR* reference */
  1173.         *((STR**)value->str_ptr) = value->str_magic;
  1174.         value->str_magic = Nullstr;
  1175.         value->str_ptr = Nullch;
  1176.         str_free(value);
  1177.         break;
  1178.     case SS_SHPTR:                /* HASH* reference */
  1179.         *((HASH**)value->str_ptr) = value->str_u.str_hash;
  1180.         value->str_ptr = Nullch;
  1181.         str_free(value);
  1182.         break;
  1183.     case SS_SAPTR:                /* ARRAY* reference */
  1184.         *((ARRAY**)value->str_ptr) = value->str_u.str_array;
  1185.         value->str_ptr = Nullch;
  1186.         str_free(value);
  1187.         break;
  1188.     case SS_SNSTAB:
  1189.         stab = (STAB*)value->str_magic;
  1190.         value->str_magic = Nullstr;
  1191.         (void)stab_clear(stab);
  1192.         str_free(value);
  1193.         break;
  1194.     case SS_SCSV:                /* callsave structure */
  1195.         {
  1196.         CSV *csv = (CSV*) value->str_ptr;
  1197.  
  1198.         curcmd = csv->curcmd;
  1199.         curcsv = csv->curcsv;
  1200.         csv->sub->depth = csv->depth;
  1201.         if (csv->hasargs) {        /* put back old @_ */
  1202.             afree(csv->argarray);
  1203.             stab_xarray(defstab) = csv->savearray;
  1204.         }
  1205.         str_free(value);
  1206.         }
  1207.         break;
  1208.     default:
  1209.         fatal("panic: restorelist inconsistency");
  1210.     }
  1211.     }
  1212. }
  1213.  
  1214. #ifdef DEBUGGING
  1215. void
  1216. grow_dlevel()
  1217. {
  1218.     dlmax += 128;
  1219.     Renew(debname, dlmax, char);
  1220.     Renew(debdelim, dlmax, char);
  1221. }
  1222. #endif
  1223.