home *** CD-ROM | disk | FTP | other *** search
/ ftp.muug.mb.ca / 2014.06.ftp.muug.mb.ca.tar / ftp.muug.mb.ca / pub / src / perl / cmd.c < prev    next >
C/C++ Source or Header  |  1992-04-11  |  30KB  |  1,248 lines

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