home *** CD-ROM | disk | FTP | other *** search
/ BBS in a Box 15 / BBS in a box XV-2.iso / Files II / Prog / M / MacPerl 4.13 source.sit / Perl Source ƒ / Perl / cmd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-05-04  |  30.9 KB  |  1,331 lines  |  [TEXT/MPS ]

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