home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-387-Vol-3of3.iso / p / perl4036.zip / cmd.c < prev    next >
C/C++ Source or Header  |  1993-02-08  |  31KB  |  1,261 lines

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