home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / PERL4036.ZIP / cons.c < prev    next >
C/C++ Source or Header  |  1993-02-08  |  36KB  |  1,448 lines

  1. /* $RCSfile: cons.c,v $$Revision: 4.0.1.4 $$Date: 1993/02/05 19:30:15 $
  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: cons.c,v $
  9.  * Revision 4.0.1.4  1993/02/05  19:30:15  lwall
  10.  * patch36: fixed various little coredump bugs
  11.  *
  12.  * Revision 4.0.1.3  92/06/08  12:18:35  lwall
  13.  * patch20: removed implicit int declarations on funcions
  14.  * patch20: deleted some minor memory leaks
  15.  * patch20: fixed double debug break in foreach with implicit array assignment
  16.  * patch20: fixed confusion between a *var's real name and its effective name
  17.  * patch20: Perl now distinguishes overlapped copies from non-overlapped
  18.  * patch20: debugger sometimes displayed wrong source line
  19.  * patch20: various error messages have been clarified
  20.  * patch20: an eval block containing a null block or statement could dump core
  21.  * 
  22.  * Revision 4.0.1.2  91/11/05  16:15:13  lwall
  23.  * patch11: debugger got confused over nested subroutine definitions
  24.  * patch11: prepared for ctype implementations that don't define isascii()
  25.  * 
  26.  * Revision 4.0.1.1  91/06/07  10:31:15  lwall
  27.  * patch4: new copyright notice
  28.  * patch4: added global modifier for pattern matches
  29.  * 
  30.  * Revision 4.0  91/03/20  01:05:51  lwall
  31.  * 4.0 baseline.
  32.  * 
  33.  */
  34.  
  35. #include "EXTERN.h"
  36. #include "perl.h"
  37. #include "perly.h"
  38.  
  39. extern char *tokename[];
  40. extern int yychar;
  41.  
  42. static int cmd_tosave();
  43. static int arg_tosave();
  44. static int spat_tosave();
  45. static void make_cswitch();
  46. static void make_nswitch();
  47.  
  48. static bool saw_return;
  49.  
  50. SUBR *
  51. make_sub(name,cmd)
  52. char *name;
  53. CMD *cmd;
  54. {
  55.     register SUBR *sub;
  56.     STAB *stab = stabent(name,TRUE);
  57.  
  58.     if (sub = stab_sub(stab)) {
  59.     if (dowarn) {
  60.         CMD *oldcurcmd = curcmd;
  61.  
  62.         if (cmd)
  63.         curcmd = cmd;
  64.         warn("Subroutine %s redefined",name);
  65.         curcmd = oldcurcmd;
  66.     }
  67.     if (!sub->usersub && sub->cmd) {
  68.         cmd_free(sub->cmd);
  69.         sub->cmd = Nullcmd;
  70.         afree(sub->tosave);
  71.     }
  72.     Safefree(sub);
  73.     }
  74.     Newz(101,sub,1,SUBR);
  75.     stab_sub(stab) = sub;
  76.     sub->filestab = curcmd->c_filestab;
  77.     saw_return = FALSE;
  78.     tosave = anew(Nullstab);
  79.     tosave->ary_fill = 0;    /* make 1 based */
  80.     (void)cmd_tosave(cmd,FALSE);    /* this builds the tosave array */
  81.     sub->tosave = tosave;
  82.     if (saw_return) {
  83.     struct compcmd mycompblock;
  84.  
  85.     mycompblock.comp_true = cmd;
  86.     mycompblock.comp_alt = Nullcmd;
  87.     cmd = add_label(savestr("_SUB_"),make_ccmd(C_BLOCK,0,
  88.         Nullarg,mycompblock));
  89.     saw_return = FALSE;
  90.     cmd->c_flags |= CF_TERM;
  91.     cmd->c_head = cmd;
  92.     }
  93.     sub->cmd = cmd;
  94.     if (perldb) {
  95.     STR *str;
  96.     STR *tmpstr = str_mortal(&str_undef);
  97.  
  98.     sprintf(buf,"%s:%ld",stab_val(curcmd->c_filestab)->str_ptr, subline);
  99.     str = str_make(buf,0);
  100.     str_cat(str,"-");
  101.     sprintf(buf,"%ld",(long)curcmd->c_line);
  102.     str_cat(str,buf);
  103.     stab_efullname(tmpstr,stab);
  104.     hstore(stab_xhash(DBsub), tmpstr->str_ptr, tmpstr->str_cur, str, 0);
  105.     }
  106.     Safefree(name);
  107.     return sub;
  108. }
  109.  
  110. SUBR *
  111. make_usub(name, ix, subaddr, filename)
  112. char *name;
  113. int ix;
  114. int (*subaddr)();
  115. char *filename;
  116. {
  117.     register SUBR *sub;
  118.     STAB *stab = stabent(name,allstabs);
  119.  
  120.     if (!stab)                /* unused function */
  121.     return Null(SUBR*);
  122.     if (sub = stab_sub(stab)) {
  123.     if (dowarn)
  124.         warn("Subroutine %s redefined",name);
  125.     if (!sub->usersub && sub->cmd) {
  126.         cmd_free(sub->cmd);
  127.         sub->cmd = Nullcmd;
  128.         afree(sub->tosave);
  129.     }
  130.     Safefree(sub);
  131.     }
  132.     Newz(101,sub,1,SUBR);
  133.     stab_sub(stab) = sub;
  134.     sub->filestab = fstab(filename);
  135.     sub->usersub = subaddr;
  136.     sub->userindex = ix;
  137.     return sub;
  138. }
  139.  
  140. void
  141. make_form(stab,fcmd)
  142. STAB *stab;
  143. FCMD *fcmd;
  144. {
  145.     if (stab_form(stab)) {
  146.     FCMD *tmpfcmd;
  147.     FCMD *nextfcmd;
  148.  
  149.     for (tmpfcmd = stab_form(stab); tmpfcmd; tmpfcmd = nextfcmd) {
  150.         nextfcmd = tmpfcmd->f_next;
  151.         if (tmpfcmd->f_expr)
  152.         arg_free(tmpfcmd->f_expr);
  153.         if (tmpfcmd->f_unparsed)
  154.         str_free(tmpfcmd->f_unparsed);
  155.         if (tmpfcmd->f_pre)
  156.         Safefree(tmpfcmd->f_pre);
  157.         Safefree(tmpfcmd);
  158.     }
  159.     }
  160.     stab_form(stab) = fcmd;
  161. }
  162.  
  163. CMD *
  164. block_head(tail)
  165. register CMD *tail;
  166. {
  167.     CMD *head;
  168.     register int opt;
  169.     register int last_opt = 0;
  170.     register STAB *last_stab = Nullstab;
  171.     register int count = 0;
  172.     register CMD *switchbeg = Nullcmd;
  173.  
  174.     if (tail == Nullcmd) {
  175.     return tail;
  176.     }
  177.     head = tail->c_head;
  178.  
  179.     for (tail = head; tail; tail = tail->c_next) {
  180.  
  181.     /* save one measly dereference at runtime */
  182.     if (tail->c_type == C_IF) {
  183.         if (!(tail->ucmd.ccmd.cc_alt = tail->ucmd.ccmd.cc_alt->c_next))
  184.         tail->c_flags |= CF_TERM;
  185.     }
  186.     else if (tail->c_type == C_EXPR) {
  187.         ARG *arg;
  188.  
  189.         if (tail->ucmd.acmd.ac_expr)
  190.         arg = tail->ucmd.acmd.ac_expr;
  191.         else
  192.         arg = tail->c_expr;
  193.         if (arg) {
  194.         if (arg->arg_type == O_RETURN)
  195.             tail->c_flags |= CF_TERM;
  196.         else if (arg->arg_type == O_ITEM && arg[1].arg_type == A_CMD)
  197.             tail->c_flags |= CF_TERM;
  198.         }
  199.     }
  200.     if (!tail->c_next)
  201.         tail->c_flags |= CF_TERM;
  202.  
  203.     if (tail->c_expr && (tail->c_flags & CF_OPTIMIZE) == CFT_FALSE)
  204.         opt_arg(tail,1, tail->c_type == C_EXPR);
  205.  
  206.     /* now do a little optimization on case-ish structures */
  207.     switch(tail->c_flags & (CF_OPTIMIZE|CF_FIRSTNEG|CF_INVERT)) {
  208.     case CFT_ANCHOR:
  209.     case CFT_STROP:
  210.         opt = (tail->c_flags & CF_NESURE) ? CFT_STROP : 0;
  211.         break;
  212.     case CFT_CCLASS:
  213.         opt = CFT_STROP;
  214.         break;
  215.     case CFT_NUMOP:
  216.         opt = (tail->c_slen == O_NE ? 0 : CFT_NUMOP);
  217.         if ((tail->c_flags&(CF_NESURE|CF_EQSURE)) != (CF_NESURE|CF_EQSURE))
  218.         opt = 0;
  219.         break;
  220.     default:
  221.         opt = 0;
  222.     }
  223.     if (opt && opt == last_opt && tail->c_stab == last_stab)
  224.         count++;
  225.     else {
  226.         if (count >= 3) {        /* is this the breakeven point? */
  227.         if (last_opt == CFT_NUMOP)
  228.             make_nswitch(switchbeg,count);
  229.         else
  230.             make_cswitch(switchbeg,count);
  231.         }
  232.         if (opt) {
  233.         count = 1;
  234.         switchbeg = tail;
  235.         }
  236.         else
  237.         count = 0;
  238.     }
  239.     last_opt = opt;
  240.     last_stab = tail->c_stab;
  241.     }
  242.     if (count >= 3) {        /* is this the breakeven point? */
  243.     if (last_opt == CFT_NUMOP)
  244.         make_nswitch(switchbeg,count);
  245.     else
  246.         make_cswitch(switchbeg,count);
  247.     }
  248.     return head;
  249. }
  250.  
  251. /* We've spotted a sequence of CMDs that all test the value of the same
  252.  * spat.  Thus we can insert a SWITCH in front and jump directly
  253.  * to the correct one.
  254.  */
  255. static void
  256. make_cswitch(head,count)
  257. register CMD *head;
  258. int count;
  259. {
  260.     register CMD *cur;
  261.     register CMD **loc;
  262.     register int i;
  263.     register int min = 255;
  264.     register int max = 0;
  265.  
  266.     /* make a new head in the exact same spot */
  267.     New(102,cur, 1, CMD);
  268.     StructCopy(head,cur,CMD);
  269.     Zero(head,1,CMD);
  270.     head->c_head = cur->c_head;
  271.     head->c_type = C_CSWITCH;
  272.     head->c_next = cur;        /* insert new cmd at front of list */
  273.     head->c_stab = cur->c_stab;
  274.  
  275.     Newz(103,loc,258,CMD*);
  276.     loc++;                /* lie a little */
  277.     while (count--) {
  278.     if ((cur->c_flags & CF_OPTIMIZE) == CFT_CCLASS) {
  279.         for (i = 0; i <= 255; i++) {
  280.         if (!loc[i] && cur->c_short->str_ptr[i>>3] & (1 << (i&7))) {
  281.             loc[i] = cur;
  282.             if (i < min)
  283.             min = i;
  284.             if (i > max)
  285.             max = i;
  286.         }
  287.         }
  288.     }
  289.     else {
  290.         i = *cur->c_short->str_ptr & 255;
  291.         if (!loc[i]) {
  292.         loc[i] = cur;
  293.         if (i < min)
  294.             min = i;
  295.         if (i > max)
  296.             max = i;
  297.         }
  298.     }
  299.     cur = cur->c_next;
  300.     }
  301.     max++;
  302.     if (min > 0)
  303.     Move(&loc[min],&loc[0], max - min, CMD*);
  304.     loc--;
  305.     min--;
  306.     max -= min;
  307.     for (i = 0; i <= max; i++)
  308.     if (!loc[i])
  309.         loc[i] = cur;
  310.     Renew(loc,max+1,CMD*);    /* chop it down to size */
  311.     head->ucmd.scmd.sc_offset = min;
  312.     head->ucmd.scmd.sc_max = max;
  313.     head->ucmd.scmd.sc_next = loc;
  314. }
  315.  
  316. static void
  317. make_nswitch(head,count)
  318. register CMD *head;
  319. int count;
  320. {
  321.     register CMD *cur = head;
  322.     register CMD **loc;
  323.     register int i;
  324.     register int min = 32767;
  325.     register int max = -32768;
  326.     int origcount = count;
  327.     double value;        /* or your money back! */
  328.     short changed;        /* so triple your money back! */
  329.  
  330.     while (count--) {
  331.     i = (int)str_gnum(cur->c_short);
  332.     value = (double)i;
  333.     if (value != cur->c_short->str_u.str_nval)
  334.         return;        /* fractional values--just forget it */
  335.     changed = i;
  336.     if (changed != i)
  337.         return;        /* too big for a short */
  338.     if (cur->c_slen == O_LE)
  339.         i++;
  340.     else if (cur->c_slen == O_GE)    /* we only do < or > here */
  341.         i--;
  342.     if (i < min)
  343.         min = i;
  344.     if (i > max)
  345.         max = i;
  346.     cur = cur->c_next;
  347.     }
  348.     count = origcount;
  349.     if (max - min > count * 2 + 10)        /* too sparse? */
  350.     return;
  351.  
  352.     /* now make a new head in the exact same spot */
  353.     New(104,cur, 1, CMD);
  354.     StructCopy(head,cur,CMD);
  355.     Zero(head,1,CMD);
  356.     head->c_head = cur->c_head;
  357.     head->c_type = C_NSWITCH;
  358.     head->c_next = cur;        /* insert new cmd at front of list */
  359.     head->c_stab = cur->c_stab;
  360.  
  361.     Newz(105,loc, max - min + 3, CMD*);
  362.     loc++;
  363.     max -= min;
  364.     max++;
  365.     while (count--) {
  366.     i = (int)str_gnum(cur->c_short);
  367.     i -= min;
  368.     switch(cur->c_slen) {
  369.     case O_LE:
  370.         i++;
  371.     case O_LT:
  372.         for (i--; i >= -1; i--)
  373.         if (!loc[i])
  374.             loc[i] = cur;
  375.         break;
  376.     case O_GE:
  377.         i--;
  378.     case O_GT:
  379.         for (i++; i <= max; i++)
  380.         if (!loc[i])
  381.             loc[i] = cur;
  382.         break;
  383.     case O_EQ:
  384.         if (!loc[i])
  385.         loc[i] = cur;
  386.         break;
  387.     }
  388.     cur = cur->c_next;
  389.     }
  390.     loc--;
  391.     min--;
  392.     max++;
  393.     for (i = 0; i <= max; i++)
  394.     if (!loc[i])
  395.         loc[i] = cur;
  396.     head->ucmd.scmd.sc_offset = min;
  397.     head->ucmd.scmd.sc_max = max;
  398.     head->ucmd.scmd.sc_next = loc;
  399. }
  400.  
  401. CMD *
  402. append_line(head,tail)
  403. register CMD *head;
  404. register CMD *tail;
  405. {
  406.     if (tail == Nullcmd)
  407.     return head;
  408.     if (!tail->c_head)            /* make sure tail is well formed */
  409.     tail->c_head = tail;
  410.     if (head != Nullcmd) {
  411.     tail = tail->c_head;        /* get to start of tail list */
  412.     if (!head->c_head)
  413.         head->c_head = head;    /* start a new head list */
  414.     while (head->c_next) {
  415.         head->c_next->c_head = head->c_head;
  416.         head = head->c_next;    /* get to end of head list */
  417.     }
  418.     head->c_next = tail;        /* link to end of old list */
  419.     tail->c_head = head->c_head;    /* propagate head pointer */
  420.     }
  421.     while (tail->c_next) {
  422.     tail->c_next->c_head = tail->c_head;
  423.     tail = tail->c_next;
  424.     }
  425.     return tail;
  426. }
  427.  
  428. CMD *
  429. dodb(cur)
  430. CMD *cur;
  431. {
  432.     register CMD *cmd;
  433.     register CMD *head = cur->c_head;
  434.     STR *str;
  435.  
  436.     if (!head)
  437.     head = cur;
  438.     if (!head->c_line)
  439.     return cur;
  440.     str = afetch(stab_xarray(curcmd->c_filestab),(int)head->c_line,FALSE);
  441.     if (str == &str_undef || str->str_nok)
  442.     return cur;
  443.     str->str_u.str_nval = (double)head->c_line;
  444.     str->str_nok = 1;
  445.     Newz(106,cmd,1,CMD);
  446.     str_magic(str, curcmd->c_filestab, 0, Nullch, 0);
  447.     str->str_magic->str_u.str_cmd = cmd;
  448.     cmd->c_type = C_EXPR;
  449.     cmd->ucmd.acmd.ac_stab = Nullstab;
  450.     cmd->ucmd.acmd.ac_expr = Nullarg;
  451.     cmd->c_expr = make_op(O_SUBR, 2,
  452.     stab2arg(A_WORD,DBstab),
  453.     Nullarg,
  454.     Nullarg);
  455.     /*SUPPRESS 53*/
  456.     cmd->c_flags |= CF_COND|CF_DBSUB|CFT_D0;
  457.     cmd->c_line = head->c_line;
  458.     cmd->c_label = head->c_label;
  459.     cmd->c_filestab = curcmd->c_filestab;
  460.     cmd->c_stash = curstash;
  461.     return append_line(cmd, cur);
  462. }
  463.  
  464. CMD *
  465. make_acmd(type,stab,cond,arg)
  466. int type;
  467. STAB *stab;
  468. ARG *cond;
  469. ARG *arg;
  470. {
  471.     register CMD *cmd;
  472.  
  473.     Newz(107,cmd,1,CMD);
  474.     cmd->c_type = type;
  475.     cmd->ucmd.acmd.ac_stab = stab;
  476.     cmd->ucmd.acmd.ac_expr = arg;
  477.     cmd->c_expr = cond;
  478.     if (cond)
  479.     cmd->c_flags |= CF_COND;
  480.     if (cmdline == NOLINE)
  481.     cmd->c_line = curcmd->c_line;
  482.     else {
  483.     cmd->c_line = cmdline;
  484.     cmdline = NOLINE;
  485.     }
  486.     cmd->c_filestab = curcmd->c_filestab;
  487.     cmd->c_stash = curstash;
  488.     if (perldb)
  489.     cmd = dodb(cmd);
  490.     return cmd;
  491. }
  492.  
  493. CMD *
  494. make_ccmd(type,debuggable,arg,cblock)
  495. int type;
  496. int debuggable;
  497. ARG *arg;
  498. struct compcmd cblock;
  499. {
  500.     register CMD *cmd;
  501.  
  502.     Newz(108,cmd, 1, CMD);
  503.     cmd->c_type = type;
  504.     cmd->c_expr = arg;
  505.     cmd->ucmd.ccmd.cc_true = cblock.comp_true;
  506.     cmd->ucmd.ccmd.cc_alt = cblock.comp_alt;
  507.     if (arg)
  508.     cmd->c_flags |= CF_COND;
  509.     if (cmdline == NOLINE)
  510.     cmd->c_line = curcmd->c_line;
  511.     else {
  512.     cmd->c_line = cmdline;
  513.     cmdline = NOLINE;
  514.     }
  515.     cmd->c_filestab = curcmd->c_filestab;
  516.     cmd->c_stash = curstash;
  517.     if (perldb && debuggable)
  518.     cmd = dodb(cmd);
  519.     return cmd;
  520. }
  521.  
  522. CMD *
  523. make_icmd(type,arg,cblock)
  524. int type;
  525. ARG *arg;
  526. struct compcmd cblock;
  527. {
  528.     register CMD *cmd;
  529.     register CMD *alt;
  530.     register CMD *cur;
  531.     register CMD *head;
  532.     struct compcmd ncblock;
  533.  
  534.     Newz(109,cmd, 1, CMD);
  535.     head = cmd;
  536.     cmd->c_type = type;
  537.     cmd->c_expr = arg;
  538.     cmd->ucmd.ccmd.cc_true = cblock.comp_true;
  539.     cmd->ucmd.ccmd.cc_alt = cblock.comp_alt;
  540.     if (arg)
  541.     cmd->c_flags |= CF_COND;
  542.     if (cmdline == NOLINE)
  543.     cmd->c_line = curcmd->c_line;
  544.     else {
  545.     cmd->c_line = cmdline;
  546.     cmdline = NOLINE;
  547.     }
  548.     cmd->c_filestab = curcmd->c_filestab;
  549.     cmd->c_stash = curstash;
  550.     cur = cmd;
  551.     alt = cblock.comp_alt;
  552.     while (alt && alt->c_type == C_ELSIF) {
  553.     cur = alt;
  554.     alt = alt->ucmd.ccmd.cc_alt;
  555.     }
  556.     if (alt) {            /* a real life ELSE at the end? */
  557.     ncblock.comp_true = alt;
  558.     ncblock.comp_alt = Nullcmd;
  559.     alt = append_line(cur,make_ccmd(C_ELSE,1,Nullarg,ncblock));
  560.     cur->ucmd.ccmd.cc_alt = alt;
  561.     }
  562.     else
  563.     alt = cur;        /* no ELSE, so cur is proxy ELSE */
  564.  
  565.     cur = cmd;
  566.     while (cmd) {        /* now point everyone at the ELSE */
  567.     cur = cmd;
  568.     cmd = cur->ucmd.ccmd.cc_alt;
  569.     cur->c_head = head;
  570.     if (cur->c_type == C_ELSIF)
  571.         cur->c_type = C_IF;
  572.     if (cur->c_type == C_IF)
  573.         cur->ucmd.ccmd.cc_alt = alt;
  574.     if (cur == alt)
  575.         break;
  576.     cur->c_next = cmd;
  577.     }
  578.     if (perldb)
  579.     cur = dodb(cur);
  580.     return cur;
  581. }
  582.  
  583. void
  584. opt_arg(cmd,fliporflop,acmd)
  585. register CMD *cmd;
  586. int fliporflop;
  587. int acmd;
  588. {
  589.     register ARG *arg;
  590.     int opt = CFT_EVAL;
  591.     int sure = 0;
  592.     ARG *arg2;
  593.     int context = 0;    /* 0 = normal, 1 = before &&, 2 = before || */
  594.     int flp = fliporflop;
  595.  
  596.     if (!cmd)
  597.     return;
  598.     if (!(arg = cmd->c_expr)) {
  599.     cmd->c_flags &= ~CF_COND;
  600.     return;
  601.     }
  602.  
  603.     /* Can we turn && and || into if and unless? */
  604.  
  605.     if (acmd && !cmd->ucmd.acmd.ac_expr && !(cmd->c_flags & CF_TERM) &&
  606.       (arg->arg_type == O_AND || arg->arg_type == O_OR) ) {
  607.     dehoist(arg,1);
  608.     arg[2].arg_type &= A_MASK;    /* don't suppress eval */
  609.     dehoist(arg,2);
  610.     cmd->ucmd.acmd.ac_expr = arg[2].arg_ptr.arg_arg;
  611.     cmd->c_expr = arg[1].arg_ptr.arg_arg;
  612.     if (arg->arg_type == O_OR)
  613.         cmd->c_flags ^= CF_INVERT;        /* || is like unless */
  614.     arg->arg_len = 0;
  615.     free_arg(arg);
  616.     arg = cmd->c_expr;
  617.     }
  618.  
  619.     /* Turn "if (!expr)" into "unless (expr)" */
  620.  
  621.     if (!(cmd->c_flags & CF_TERM)) {        /* unless return value wanted */
  622.     while (arg->arg_type == O_NOT) {
  623.         dehoist(arg,1);
  624.         cmd->c_flags ^= CF_INVERT;        /* flip sense of cmd */
  625.         cmd->c_expr = arg[1].arg_ptr.arg_arg; /* hoist the rest of expr */
  626.         free_arg(arg);
  627.         arg = cmd->c_expr;            /* here we go again */
  628.     }
  629.     }
  630.  
  631.     if (!arg->arg_len) {        /* sanity check */
  632.     cmd->c_flags |= opt;
  633.     return;
  634.     }
  635.  
  636.     /* for "cond .. cond" we set up for the initial check */
  637.  
  638.     if (arg->arg_type == O_FLIP)
  639.     context |= 4;
  640.  
  641.     /* for "cond && expr" and "cond || expr" we can ignore expr, sort of */
  642.  
  643.   morecontext:
  644.     if (arg->arg_type == O_AND)
  645.     context |= 1;
  646.     else if (arg->arg_type == O_OR)
  647.     context |= 2;
  648.     if (context && (arg[flp].arg_type & A_MASK) == A_EXPR) {
  649.     arg = arg[flp].arg_ptr.arg_arg;
  650.     flp = 1;
  651.     if (arg->arg_type == O_AND || arg->arg_type == O_OR)
  652.         goto morecontext;
  653.     }
  654.     if ((context & 3) == 3)
  655.     return;
  656.  
  657.     if (arg[flp].arg_flags & (AF_PRE|AF_POST)) {
  658.     cmd->c_flags |= opt;
  659.     if (acmd && !cmd->ucmd.acmd.ac_expr && !(cmd->c_flags & CF_TERM)
  660.       && cmd->c_expr->arg_type == O_ITEM) {
  661.         arg[flp].arg_flags &= ~AF_POST;    /* prefer ++$foo to $foo++ */
  662.         arg[flp].arg_flags |= AF_PRE;    /*  if value not wanted */
  663.     }
  664.     return;                /* side effect, can't optimize */
  665.     }
  666.  
  667.     if (arg->arg_type == O_ITEM || arg->arg_type == O_FLIP ||
  668.       arg->arg_type == O_AND || arg->arg_type == O_OR) {
  669.     if ((arg[flp].arg_type & A_MASK) == A_SINGLE) {
  670.         opt = (str_true(arg[flp].arg_ptr.arg_str) ? CFT_TRUE : CFT_FALSE);
  671.         cmd->c_short = str_smake(arg[flp].arg_ptr.arg_str);
  672.         goto literal;
  673.     }
  674.     else if ((arg[flp].arg_type & A_MASK) == A_STAB ||
  675.       (arg[flp].arg_type & A_MASK) == A_LVAL) {
  676.         cmd->c_stab  = arg[flp].arg_ptr.arg_stab;
  677.         if (!context)
  678.         arg[flp].arg_ptr.arg_stab = Nullstab;
  679.         opt = CFT_REG;
  680.       literal:
  681.         if (!context) {    /* no && or ||? */
  682.         arg_free(arg);
  683.         cmd->c_expr = Nullarg;
  684.         }
  685.         if (!(context & 1))
  686.         cmd->c_flags |= CF_EQSURE;
  687.         if (!(context & 2))
  688.         cmd->c_flags |= CF_NESURE;
  689.     }
  690.     }
  691.     else if (arg->arg_type == O_MATCH || arg->arg_type == O_SUBST ||
  692.          arg->arg_type == O_NMATCH || arg->arg_type == O_NSUBST) {
  693.     if ((arg[1].arg_type == A_STAB || arg[1].arg_type == A_LVAL) &&
  694.         (arg[2].arg_type & A_MASK) == A_SPAT &&
  695.         arg[2].arg_ptr.arg_spat->spat_short &&
  696.         (arg->arg_type == O_SUBST || arg->arg_type == O_NSUBST ||
  697.          (arg[2].arg_ptr.arg_spat->spat_flags & SPAT_GLOBAL) == 0 )) {
  698.         cmd->c_stab  = arg[1].arg_ptr.arg_stab;
  699.         cmd->c_short = str_smake(arg[2].arg_ptr.arg_spat->spat_short);
  700.         cmd->c_slen  = arg[2].arg_ptr.arg_spat->spat_slen;
  701.         if (arg[2].arg_ptr.arg_spat->spat_flags & SPAT_ALL &&
  702.         !(arg[2].arg_ptr.arg_spat->spat_flags & SPAT_ONCE) &&
  703.         (arg->arg_type == O_MATCH || arg->arg_type == O_NMATCH) )
  704.         sure |= CF_EQSURE;        /* (SUBST must be forced even */
  705.                         /* if we know it will work.) */
  706.         if (arg->arg_type != O_SUBST) {
  707.         str_free(arg[2].arg_ptr.arg_spat->spat_short);
  708.         arg[2].arg_ptr.arg_spat->spat_short = Nullstr;
  709.         arg[2].arg_ptr.arg_spat->spat_slen = 0; /* only one chk */
  710.         }
  711.         sure |= CF_NESURE;        /* normally only sure if it fails */
  712.         if (arg->arg_type == O_NMATCH || arg->arg_type == O_NSUBST)
  713.         cmd->c_flags |= CF_FIRSTNEG;
  714.         if (context & 1) {        /* only sure if thing is false */
  715.         if (cmd->c_flags & CF_FIRSTNEG)
  716.             sure &= ~CF_NESURE;
  717.         else
  718.             sure &= ~CF_EQSURE;
  719.         }
  720.         else if (context & 2) {    /* only sure if thing is true */
  721.         if (cmd->c_flags & CF_FIRSTNEG)
  722.             sure &= ~CF_EQSURE;
  723.         else
  724.             sure &= ~CF_NESURE;
  725.         }
  726.         if (sure & (CF_EQSURE|CF_NESURE)) {    /* if we know anything*/
  727.         if (arg[2].arg_ptr.arg_spat->spat_flags & SPAT_SCANFIRST)
  728.             opt = CFT_SCAN;
  729.         else
  730.             opt = CFT_ANCHOR;
  731.         if (sure == (CF_EQSURE|CF_NESURE)    /* really sure? */
  732.             && arg->arg_type == O_MATCH
  733.             && context & 4
  734.             && fliporflop == 1) {
  735.             spat_free(arg[2].arg_ptr.arg_spat);
  736.             arg[2].arg_ptr.arg_spat = Nullspat;    /* don't do twice */
  737.         }
  738.         else
  739.             cmd->c_spat = arg[2].arg_ptr.arg_spat;
  740.         cmd->c_flags |= sure;
  741.         }
  742.     }
  743.     }
  744.     else if (arg->arg_type == O_SEQ || arg->arg_type == O_SNE ||
  745.          arg->arg_type == O_SLT || arg->arg_type == O_SGT) {
  746.     if (arg[1].arg_type == A_STAB || arg[1].arg_type == A_LVAL) {
  747.         if (arg[2].arg_type == A_SINGLE) {
  748.         /*SUPPRESS 594*/
  749.         char *junk = str_get(arg[2].arg_ptr.arg_str);
  750.  
  751.         cmd->c_stab  = arg[1].arg_ptr.arg_stab;
  752.         cmd->c_short = str_smake(arg[2].arg_ptr.arg_str);
  753.         cmd->c_slen  = cmd->c_short->str_cur+1;
  754.         switch (arg->arg_type) {
  755.         case O_SLT: case O_SGT:
  756.             sure |= CF_EQSURE;
  757.             cmd->c_flags |= CF_FIRSTNEG;
  758.             break;
  759.         case O_SNE:
  760.             cmd->c_flags |= CF_FIRSTNEG;
  761.             /* FALL THROUGH */
  762.         case O_SEQ:
  763.             sure |= CF_NESURE|CF_EQSURE;
  764.             break;
  765.         }
  766.         if (context & 1) {    /* only sure if thing is false */
  767.             if (cmd->c_flags & CF_FIRSTNEG)
  768.             sure &= ~CF_NESURE;
  769.             else
  770.             sure &= ~CF_EQSURE;
  771.         }
  772.         else if (context & 2) { /* only sure if thing is true */
  773.             if (cmd->c_flags & CF_FIRSTNEG)
  774.             sure &= ~CF_EQSURE;
  775.             else
  776.             sure &= ~CF_NESURE;
  777.         }
  778.         if (sure & (CF_EQSURE|CF_NESURE)) {
  779.             opt = CFT_STROP;
  780.             cmd->c_flags |= sure;
  781.         }
  782.         }
  783.     }
  784.     }
  785.     else if (arg->arg_type == O_EQ || arg->arg_type == O_NE ||
  786.          arg->arg_type == O_LE || arg->arg_type == O_GE ||
  787.          arg->arg_type == O_LT || arg->arg_type == O_GT) {
  788.     if (arg[1].arg_type == A_STAB || arg[1].arg_type == A_LVAL) {
  789.         if (arg[2].arg_type == A_SINGLE) {
  790.         cmd->c_stab  = arg[1].arg_ptr.arg_stab;
  791.         if (dowarn) {
  792.             STR *str = arg[2].arg_ptr.arg_str;
  793.  
  794.             if ((!str->str_nok && !looks_like_number(str)))
  795.             warn("Possible use of == on string value");
  796.         }
  797.         cmd->c_short = str_nmake(str_gnum(arg[2].arg_ptr.arg_str));
  798.         cmd->c_slen = arg->arg_type;
  799.         sure |= CF_NESURE|CF_EQSURE;
  800.         if (context & 1) {    /* only sure if thing is false */
  801.             sure &= ~CF_EQSURE;
  802.         }
  803.         else if (context & 2) { /* only sure if thing is true */
  804.             sure &= ~CF_NESURE;
  805.         }
  806.         if (sure & (CF_EQSURE|CF_NESURE)) {
  807.             opt = CFT_NUMOP;
  808.             cmd->c_flags |= sure;
  809.         }
  810.         }
  811.     }
  812.     }
  813.     else if (arg->arg_type == O_ASSIGN &&
  814.          (arg[1].arg_type == A_STAB || arg[1].arg_type == A_LVAL) &&
  815.          arg[1].arg_ptr.arg_stab == defstab &&
  816.          arg[2].arg_type == A_EXPR ) {
  817.     arg2 = arg[2].arg_ptr.arg_arg;
  818.     if (arg2->arg_type == O_ITEM && arg2[1].arg_type == A_READ) {
  819.         opt = CFT_GETS;
  820.         cmd->c_stab = arg2[1].arg_ptr.arg_stab;
  821.         if (!(stab_io(arg2[1].arg_ptr.arg_stab)->flags & IOF_ARGV)) {
  822.         free_arg(arg2);
  823.         arg[2].arg_ptr.arg_arg = Nullarg;
  824.         free_arg(arg);
  825.         cmd->c_expr = Nullarg;
  826.         }
  827.     }
  828.     }
  829.     else if (arg->arg_type == O_CHOP &&
  830.          (arg[1].arg_type == A_STAB || arg[1].arg_type == A_LVAL) ) {
  831.     opt = CFT_CHOP;
  832.     cmd->c_stab = arg[1].arg_ptr.arg_stab;
  833.     free_arg(arg);
  834.     cmd->c_expr = Nullarg;
  835.     }
  836.     if (context & 4)
  837.     opt |= CF_FLIP;
  838.     cmd->c_flags |= opt;
  839.  
  840.     if (cmd->c_flags & CF_FLIP) {
  841.     if (fliporflop == 1) {
  842.         arg = cmd->c_expr;    /* get back to O_FLIP arg */
  843.         New(110,arg[3].arg_ptr.arg_cmd, 1, CMD);
  844.         Copy(cmd, arg[3].arg_ptr.arg_cmd, 1, CMD);
  845.         New(111,arg[4].arg_ptr.arg_cmd,1,CMD);
  846.         Copy(cmd, arg[4].arg_ptr.arg_cmd, 1, CMD);
  847.         opt_arg(arg[4].arg_ptr.arg_cmd,2,acmd);
  848.         arg->arg_len = 2;        /* this is a lie */
  849.     }
  850.     else {
  851.         if ((opt & CF_OPTIMIZE) == CFT_EVAL)
  852.         cmd->c_flags = (cmd->c_flags & ~CF_OPTIMIZE) | CFT_UNFLIP;
  853.     }
  854.     }
  855. }
  856.  
  857. CMD *
  858. add_label(lbl,cmd)
  859. char *lbl;
  860. register CMD *cmd;
  861. {
  862.     if (cmd)
  863.     cmd->c_label = lbl;
  864.     return cmd;
  865. }
  866.  
  867. CMD *
  868. addcond(cmd, arg)
  869. register CMD *cmd;
  870. register ARG *arg;
  871. {
  872.     cmd->c_expr = arg;
  873.     cmd->c_flags |= CF_COND;
  874.     return cmd;
  875. }
  876.  
  877. CMD *
  878. addloop(cmd, arg)
  879. register CMD *cmd;
  880. register ARG *arg;
  881. {
  882.     void while_io();
  883.  
  884.     cmd->c_expr = arg;
  885.     cmd->c_flags |= CF_COND|CF_LOOP;
  886.  
  887.     if (!(cmd->c_flags & CF_INVERT))
  888.     while_io(cmd);        /* add $_ =, if necessary */
  889.  
  890.     if (cmd->c_type == C_BLOCK)
  891.     cmd->c_flags &= ~CF_COND;
  892.     else {
  893.     arg = cmd->ucmd.acmd.ac_expr;
  894.     if (arg && arg->arg_type == O_ITEM && arg[1].arg_type == A_CMD)
  895.         cmd->c_flags &= ~CF_COND;  /* "do {} while" happens at least once */
  896.     if (arg && (arg->arg_flags & AF_DEPR) &&
  897.       (arg->arg_type == O_SUBR || arg->arg_type == O_DBSUBR) )
  898.         cmd->c_flags &= ~CF_COND;  /* likewise for "do subr() while" */
  899.     }
  900.     return cmd;
  901. }
  902.  
  903. CMD *
  904. invert(cmd)
  905. CMD *cmd;
  906. {
  907.     register CMD *targ = cmd;
  908.     if (targ->c_head)
  909.     targ = targ->c_head;
  910.     if (targ->c_flags & CF_DBSUB)
  911.     targ = targ->c_next;
  912.     targ->c_flags ^= CF_INVERT;
  913.     return cmd;
  914. }
  915.  
  916. void
  917. cpy7bit(d,s,l)
  918. register char *d;
  919. register char *s;
  920. register int l;
  921. {
  922.     while (l--)
  923.     *d++ = *s++ & 127;
  924.     *d = '\0';
  925. }
  926.  
  927. int
  928. yyerror(s)
  929. char *s;
  930. {
  931.     char tmpbuf[258];
  932.     char tmp2buf[258];
  933.     char *tname = tmpbuf;
  934.  
  935.     if (bufptr > oldoldbufptr && bufptr - oldoldbufptr < 200 &&
  936.       oldoldbufptr != oldbufptr && oldbufptr != bufptr) {
  937.     while (isSPACE(*oldoldbufptr))
  938.         oldoldbufptr++;
  939.     cpy7bit(tmp2buf, oldoldbufptr, bufptr - oldoldbufptr);
  940.     sprintf(tname,"next 2 tokens \"%s\"",tmp2buf);
  941.     }
  942.     else if (bufptr > oldbufptr && bufptr - oldbufptr < 200 &&
  943.       oldbufptr != bufptr) {
  944.     while (isSPACE(*oldbufptr))
  945.         oldbufptr++;
  946.     cpy7bit(tmp2buf, oldbufptr, bufptr - oldbufptr);
  947.     sprintf(tname,"next token \"%s\"",tmp2buf);
  948.     }
  949.     else if (yychar > 256)
  950.     tname = "next token ???";
  951.     else if (!yychar)
  952.     (void)strcpy(tname,"at EOF");
  953.     else if (yychar < 32)
  954.     (void)sprintf(tname,"next char ^%c",yychar+64);
  955.     else if (yychar == 127)
  956.     (void)strcpy(tname,"at EOF");
  957.     else
  958.     (void)sprintf(tname,"next char %c",yychar);
  959.     (void)sprintf(buf, "%s in file %s at line %d, %s\n",
  960.       s,stab_val(curcmd->c_filestab)->str_ptr,curcmd->c_line,tname);
  961.     if (curcmd->c_line == multi_end && multi_start < multi_end)
  962.     sprintf(buf+strlen(buf),
  963.       "  (Might be a runaway multi-line %c%c string starting on line %d)\n",
  964.       multi_open,multi_close,multi_start);
  965.     if (in_eval)
  966.     str_cat(stab_val(stabent("@",TRUE)),buf);
  967.     else
  968.     fputs(buf,stderr);
  969.     if (++error_count >= 10)
  970.     fatal("%s has too many errors.\n",
  971.     stab_val(curcmd->c_filestab)->str_ptr);
  972. }
  973.  
  974. void
  975. while_io(cmd)
  976. register CMD *cmd;
  977. {
  978.     register ARG *arg = cmd->c_expr;
  979.     STAB *asgnstab;
  980.  
  981.     /* hoist "while (<channel>)" up into command block */
  982.  
  983.     if (arg && arg->arg_type == O_ITEM && arg[1].arg_type == A_READ) {
  984.     cmd->c_flags &= ~CF_OPTIMIZE;    /* clear optimization type */
  985.     cmd->c_flags |= CFT_GETS;    /* and set it to do the input */
  986.     cmd->c_stab = arg[1].arg_ptr.arg_stab;
  987.     if (stab_io(arg[1].arg_ptr.arg_stab)->flags & IOF_ARGV) {
  988.         cmd->c_expr = l(make_op(O_ASSIGN, 2,    /* fake up "$_ =" */
  989.            stab2arg(A_LVAL,defstab), arg, Nullarg));
  990.     }
  991.     else {
  992.         free_arg(arg);
  993.         cmd->c_expr = Nullarg;
  994.     }
  995.     }
  996.     else if (arg && arg->arg_type == O_ITEM && arg[1].arg_type == A_INDREAD) {
  997.     cmd->c_flags &= ~CF_OPTIMIZE;    /* clear optimization type */
  998.     cmd->c_flags |= CFT_INDGETS;    /* and set it to do the input */
  999.     cmd->c_stab = arg[1].arg_ptr.arg_stab;
  1000.     free_arg(arg);
  1001.     cmd->c_expr = Nullarg;
  1002.     }
  1003.     else if (arg && arg->arg_type == O_ITEM && arg[1].arg_type == A_GLOB) {
  1004.     if ((cmd->c_flags & CF_OPTIMIZE) == CFT_ARRAY)
  1005.         asgnstab = cmd->c_stab;
  1006.     else
  1007.         asgnstab = defstab;
  1008.     cmd->c_expr = l(make_op(O_ASSIGN, 2,    /* fake up "$foo =" */
  1009.        stab2arg(A_LVAL,asgnstab), arg, Nullarg));
  1010.     cmd->c_flags &= ~CF_OPTIMIZE;    /* clear optimization type */
  1011.     }
  1012. }
  1013.  
  1014. CMD *
  1015. wopt(cmd)
  1016. register CMD *cmd;
  1017. {
  1018.     register CMD *tail;
  1019.     CMD *newtail;
  1020.     register int i;
  1021.  
  1022.     if (cmd->c_expr && (cmd->c_flags & CF_OPTIMIZE) == CFT_FALSE)
  1023.     opt_arg(cmd,1, cmd->c_type == C_EXPR);
  1024.  
  1025.     while_io(cmd);        /* add $_ =, if necessary */
  1026.  
  1027.     /* First find the end of the true list */
  1028.  
  1029.     tail = cmd->ucmd.ccmd.cc_true;
  1030.     if (tail == Nullcmd)
  1031.     return cmd;
  1032.     New(112,newtail, 1, CMD);    /* guaranteed continue */
  1033.     for (;;) {
  1034.     /* optimize "next" to point directly to continue block */
  1035.     if (tail->c_type == C_EXPR &&
  1036.         tail->ucmd.acmd.ac_expr &&
  1037.         tail->ucmd.acmd.ac_expr->arg_type == O_NEXT &&
  1038.         (tail->ucmd.acmd.ac_expr->arg_len == 0 ||
  1039.          (cmd->c_label &&
  1040.           strEQ(cmd->c_label,
  1041.             tail->ucmd.acmd.ac_expr[1].arg_ptr.arg_str->str_ptr) )))
  1042.     {
  1043.         arg_free(tail->ucmd.acmd.ac_expr);
  1044.         tail->ucmd.acmd.ac_expr = Nullarg;
  1045.         tail->c_type = C_NEXT;
  1046.         if (cmd->ucmd.ccmd.cc_alt != Nullcmd)
  1047.         tail->ucmd.ccmd.cc_alt = cmd->ucmd.ccmd.cc_alt;
  1048.         else
  1049.         tail->ucmd.ccmd.cc_alt = newtail;
  1050.         tail->ucmd.ccmd.cc_true = Nullcmd;
  1051.     }
  1052.     else if (tail->c_type == C_IF && !tail->ucmd.ccmd.cc_alt) {
  1053.         if (cmd->ucmd.ccmd.cc_alt != Nullcmd)
  1054.         tail->ucmd.ccmd.cc_alt = cmd->ucmd.ccmd.cc_alt;
  1055.         else
  1056.         tail->ucmd.ccmd.cc_alt = newtail;
  1057.     }
  1058.     else if (tail->c_type == C_CSWITCH || tail->c_type == C_NSWITCH) {
  1059.         if (cmd->ucmd.ccmd.cc_alt != Nullcmd) {
  1060.         for (i = tail->ucmd.scmd.sc_max; i >= 0; i--)
  1061.             if (!tail->ucmd.scmd.sc_next[i])
  1062.             tail->ucmd.scmd.sc_next[i] = cmd->ucmd.ccmd.cc_alt;
  1063.         }
  1064.         else {
  1065.         for (i = tail->ucmd.scmd.sc_max; i >= 0; i--)
  1066.             if (!tail->ucmd.scmd.sc_next[i])
  1067.             tail->ucmd.scmd.sc_next[i] = newtail;
  1068.         }
  1069.     }
  1070.  
  1071.     if (!tail->c_next)
  1072.         break;
  1073.     tail = tail->c_next;
  1074.     }
  1075.  
  1076.     /* if there's a continue block, link it to true block and find end */
  1077.  
  1078.     if (cmd->ucmd.ccmd.cc_alt != Nullcmd) {
  1079.     tail->c_next = cmd->ucmd.ccmd.cc_alt;
  1080.     tail = tail->c_next;
  1081.     for (;;) {
  1082.         /* optimize "next" to point directly to continue block */
  1083.         if (tail->c_type == C_EXPR &&
  1084.         tail->ucmd.acmd.ac_expr &&
  1085.         tail->ucmd.acmd.ac_expr->arg_type == O_NEXT &&
  1086.         (tail->ucmd.acmd.ac_expr->arg_len == 0 ||
  1087.          (cmd->c_label &&
  1088.           strEQ(cmd->c_label,
  1089.             tail->ucmd.acmd.ac_expr[1].arg_ptr.arg_str->str_ptr) )))
  1090.         {
  1091.         arg_free(tail->ucmd.acmd.ac_expr);
  1092.         tail->ucmd.acmd.ac_expr = Nullarg;
  1093.         tail->c_type = C_NEXT;
  1094.         tail->ucmd.ccmd.cc_alt = newtail;
  1095.         tail->ucmd.ccmd.cc_true = Nullcmd;
  1096.         }
  1097.         else if (tail->c_type == C_IF && !tail->ucmd.ccmd.cc_alt) {
  1098.         tail->ucmd.ccmd.cc_alt = newtail;
  1099.         }
  1100.         else if (tail->c_type == C_CSWITCH || tail->c_type == C_NSWITCH) {
  1101.         for (i = tail->ucmd.scmd.sc_max; i >= 0; i--)
  1102.             if (!tail->ucmd.scmd.sc_next[i])
  1103.             tail->ucmd.scmd.sc_next[i] = newtail;
  1104.         }
  1105.  
  1106.         if (!tail->c_next)
  1107.         break;
  1108.         tail = tail->c_next;
  1109.     }
  1110.     /*SUPPRESS 530*/
  1111.     for ( ; tail->c_next; tail = tail->c_next) ;
  1112.     }
  1113.  
  1114.     /* Here's the real trick: link the end of the list back to the beginning,
  1115.      * inserting a "last" block to break out of the loop.  This saves one or
  1116.      * two procedure calls every time through the loop, because of how cmd_exec
  1117.      * does tail recursion.
  1118.      */
  1119.  
  1120.     tail->c_next = newtail;
  1121.     tail = newtail;
  1122.     if (!cmd->ucmd.ccmd.cc_alt)
  1123.     cmd->ucmd.ccmd.cc_alt = tail;    /* every loop has a continue now */
  1124.  
  1125. #ifndef lint
  1126.     Copy((char *)cmd, (char *)tail, 1, CMD);
  1127. #endif
  1128.     tail->c_type = C_EXPR;
  1129.     tail->c_flags ^= CF_INVERT;        /* turn into "last unless" */
  1130.     tail->c_next = tail->ucmd.ccmd.cc_true;    /* loop directly back to top */
  1131.     tail->ucmd.acmd.ac_expr = make_op(O_LAST,0,Nullarg,Nullarg,Nullarg);
  1132.     tail->ucmd.acmd.ac_stab = Nullstab;
  1133.     return cmd;
  1134. }
  1135.  
  1136. CMD *
  1137. over(eachstab,cmd)
  1138. STAB *eachstab;
  1139. register CMD *cmd;
  1140. {
  1141.     /* hoist "for $foo (@bar)" up into command block */
  1142.  
  1143.     cmd->c_flags &= ~CF_OPTIMIZE;    /* clear optimization type */
  1144.     cmd->c_flags |= CFT_ARRAY;        /* and set it to do the iteration */
  1145.     cmd->c_stab = eachstab;
  1146.     cmd->c_short = Str_new(23,0);    /* just to save a field in struct cmd */
  1147.     cmd->c_short->str_u.str_useful = -1;
  1148.  
  1149.     return cmd;
  1150. }
  1151.  
  1152. void
  1153. cmd_free(cmd)
  1154. register CMD *cmd;
  1155. {
  1156.     register CMD *tofree;
  1157.     register CMD *head = cmd;
  1158.  
  1159.     if (!cmd)
  1160.     return;
  1161.     if (cmd->c_head != cmd)
  1162.     warn("Malformed cmd links\n");
  1163.     while (cmd) {
  1164.     if (cmd->c_type != C_WHILE) {    /* WHILE block is duplicated */
  1165.         if (cmd->c_label) {
  1166.         Safefree(cmd->c_label);
  1167.         cmd->c_label = Nullch;
  1168.         }
  1169.         if (cmd->c_short) {
  1170.         str_free(cmd->c_short);
  1171.         cmd->c_short = Nullstr;
  1172.         }
  1173.         if (cmd->c_expr) {
  1174.         arg_free(cmd->c_expr);
  1175.         cmd->c_expr = Nullarg;
  1176.         }
  1177.     }
  1178.     switch (cmd->c_type) {
  1179.     case C_WHILE:
  1180.     case C_BLOCK:
  1181.     case C_ELSE:
  1182.     case C_IF:
  1183.         if (cmd->ucmd.ccmd.cc_true) {
  1184.         cmd_free(cmd->ucmd.ccmd.cc_true);
  1185.         cmd->ucmd.ccmd.cc_true = Nullcmd;
  1186.         }
  1187.         break;
  1188.     case C_EXPR:
  1189.         if (cmd->ucmd.acmd.ac_expr) {
  1190.         arg_free(cmd->ucmd.acmd.ac_expr);
  1191.         cmd->ucmd.acmd.ac_expr = Nullarg;
  1192.         }
  1193.         break;
  1194.     }
  1195.     tofree = cmd;
  1196.     cmd = cmd->c_next;
  1197.     if (tofree != head)        /* to get Saber to shut up */
  1198.         Safefree(tofree);
  1199.     if (cmd && cmd == head)        /* reached end of while loop */
  1200.         break;
  1201.     }
  1202.     Safefree(head);
  1203. }
  1204.  
  1205. void
  1206. arg_free(arg)
  1207. register ARG *arg;
  1208. {
  1209.     register int i;
  1210.  
  1211.     if (!arg)
  1212.     return;
  1213.     for (i = 1; i <= arg->arg_len; i++) {
  1214.     switch (arg[i].arg_type & A_MASK) {
  1215.     case A_NULL:
  1216.         if (arg->arg_type == O_TRANS) {
  1217.         Safefree(arg[i].arg_ptr.arg_cval);
  1218.         arg[i].arg_ptr.arg_cval = Nullch;
  1219.         }
  1220.         break;
  1221.     case A_LEXPR:
  1222.         if (arg->arg_type == O_AASSIGN &&
  1223.           arg[i].arg_ptr.arg_arg->arg_type == O_LARRAY) {
  1224.         char *name = 
  1225.           stab_name(arg[i].arg_ptr.arg_arg[1].arg_ptr.arg_stab);
  1226.  
  1227.         if (strnEQ("_GEN_",name, 5))    /* array for foreach */
  1228.             hdelete(defstash,name,strlen(name));
  1229.         }
  1230.         /* FALL THROUGH */
  1231.     case A_EXPR:
  1232.         arg_free(arg[i].arg_ptr.arg_arg);
  1233.         arg[i].arg_ptr.arg_arg = Nullarg;
  1234.         break;
  1235.     case A_CMD:
  1236.         cmd_free(arg[i].arg_ptr.arg_cmd);
  1237.         arg[i].arg_ptr.arg_cmd = Nullcmd;
  1238.         break;
  1239.     case A_WORD:
  1240.     case A_STAB:
  1241.     case A_LVAL:
  1242.     case A_READ:
  1243.     case A_GLOB:
  1244.     case A_ARYLEN:
  1245.     case A_LARYLEN:
  1246.     case A_ARYSTAB:
  1247.     case A_LARYSTAB:
  1248.         break;
  1249.     case A_SINGLE:
  1250.     case A_DOUBLE:
  1251.     case A_BACKTICK:
  1252.         str_free(arg[i].arg_ptr.arg_str);
  1253.         arg[i].arg_ptr.arg_str = Nullstr;
  1254.         break;
  1255.     case A_SPAT:
  1256.         spat_free(arg[i].arg_ptr.arg_spat);
  1257.         arg[i].arg_ptr.arg_spat = Nullspat;
  1258.         break;
  1259.     }
  1260.     }
  1261.     free_arg(arg);
  1262. }
  1263.  
  1264. void
  1265. spat_free(spat)
  1266. register SPAT *spat;
  1267. {
  1268.     register SPAT *sp;
  1269.     HENT *entry;
  1270.  
  1271.     if (!spat)
  1272.     return;
  1273.     if (spat->spat_runtime) {
  1274.     arg_free(spat->spat_runtime);
  1275.     spat->spat_runtime = Nullarg;
  1276.     }
  1277.     if (spat->spat_repl) {
  1278.     arg_free(spat->spat_repl);
  1279.     spat->spat_repl = Nullarg;
  1280.     }
  1281.     if (spat->spat_short) {
  1282.     str_free(spat->spat_short);
  1283.     spat->spat_short = Nullstr;
  1284.     }
  1285.     if (spat->spat_regexp) {
  1286.     regfree(spat->spat_regexp);
  1287.     spat->spat_regexp = Null(REGEXP*);
  1288.     }
  1289.  
  1290.     /* now unlink from spat list */
  1291.  
  1292.     for (entry = defstash->tbl_array['_']; entry; entry = entry->hent_next) {
  1293.     register HASH *stash;
  1294.     STAB *stab = (STAB*)entry->hent_val;
  1295.  
  1296.     if (!stab)
  1297.         continue;
  1298.     stash = stab_hash(stab);
  1299.     if (!stash || stash->tbl_spatroot == Null(SPAT*))
  1300.         continue;
  1301.     if (stash->tbl_spatroot == spat)
  1302.         stash->tbl_spatroot = spat->spat_next;
  1303.     else {
  1304.         for (sp = stash->tbl_spatroot;
  1305.           sp && sp->spat_next != spat;
  1306.           sp = sp->spat_next)
  1307.         /*SUPPRESS 530*/
  1308.         ;
  1309.         if (sp)
  1310.         sp->spat_next = spat->spat_next;
  1311.     }
  1312.     }
  1313.     Safefree(spat);
  1314. }
  1315.  
  1316. /* Recursively descend a command sequence and push the address of any string
  1317.  * that needs saving on recursion onto the tosave array.
  1318.  */
  1319.  
  1320. static int
  1321. cmd_tosave(cmd,willsave)
  1322. register CMD *cmd;
  1323. int willsave;                /* willsave passes down the tree */
  1324. {
  1325.     register CMD *head = cmd;
  1326.     int shouldsave = FALSE;        /* shouldsave passes up the tree */
  1327.     int tmpsave;
  1328.     register CMD *lastcmd = Nullcmd;
  1329.  
  1330.     while (cmd) {
  1331.     if (cmd->c_expr)
  1332.         shouldsave |= arg_tosave(cmd->c_expr,willsave);
  1333.     switch (cmd->c_type) {
  1334.     case C_WHILE:
  1335.         if (cmd->ucmd.ccmd.cc_true) {
  1336.         tmpsave = cmd_tosave(cmd->ucmd.ccmd.cc_true,willsave);
  1337.  
  1338.         /* Here we check to see if the temporary array generated for
  1339.          * a foreach needs to be localized because of recursion.
  1340.          */
  1341.         if (tmpsave && (cmd->c_flags & CF_OPTIMIZE) == CFT_ARRAY) {
  1342.             if (lastcmd &&
  1343.               lastcmd->c_type == C_EXPR &&
  1344.               lastcmd->c_expr) {
  1345.             ARG *arg = lastcmd->c_expr;
  1346.  
  1347.             if (arg->arg_type == O_ASSIGN &&
  1348.                 arg[1].arg_type == A_LEXPR &&
  1349.                 arg[1].arg_ptr.arg_arg->arg_type == O_LARRAY &&
  1350.                 strnEQ("_GEN_",
  1351.                   stab_name(
  1352.                 arg[1].arg_ptr.arg_arg[1].arg_ptr.arg_stab),
  1353.                   5)) {    /* array generated for foreach */
  1354.                 (void)localize(arg);
  1355.             }
  1356.             }
  1357.  
  1358.             /* in any event, save the iterator */
  1359.  
  1360.             if (cmd->c_short)  /* Better safe than sorry */
  1361.             (void)apush(tosave,cmd->c_short);
  1362.         }
  1363.         shouldsave |= tmpsave;
  1364.         }
  1365.         break;
  1366.     case C_BLOCK:
  1367.     case C_ELSE:
  1368.     case C_IF:
  1369.         if (cmd->ucmd.ccmd.cc_true)
  1370.         shouldsave |= cmd_tosave(cmd->ucmd.ccmd.cc_true,willsave);
  1371.         break;
  1372.     case C_EXPR:
  1373.         if (cmd->ucmd.acmd.ac_expr)
  1374.         shouldsave |= arg_tosave(cmd->ucmd.acmd.ac_expr,willsave);
  1375.         break;
  1376.     }
  1377.     lastcmd = cmd;
  1378.     cmd = cmd->c_next;
  1379.     if (cmd && cmd == head)        /* reached end of while loop */
  1380.         break;
  1381.     }
  1382.     return shouldsave;
  1383. }
  1384.  
  1385. static int
  1386. arg_tosave(arg,willsave)
  1387. register ARG *arg;
  1388. int willsave;
  1389. {
  1390.     register int i;
  1391.     int shouldsave = FALSE;
  1392.  
  1393.     for (i = arg->arg_len; i >= 1; i--) {
  1394.     switch (arg[i].arg_type & A_MASK) {
  1395.     case A_NULL:
  1396.         break;
  1397.     case A_LEXPR:
  1398.     case A_EXPR:
  1399.         shouldsave |= arg_tosave(arg[i].arg_ptr.arg_arg,shouldsave);
  1400.         break;
  1401.     case A_CMD:
  1402.         shouldsave |= cmd_tosave(arg[i].arg_ptr.arg_cmd,shouldsave);
  1403.         break;
  1404.     case A_WORD:
  1405.     case A_STAB:
  1406.     case A_LVAL:
  1407.     case A_READ:
  1408.     case A_GLOB:
  1409.     case A_ARYLEN:
  1410.     case A_SINGLE:
  1411.     case A_DOUBLE:
  1412.     case A_BACKTICK:
  1413.         break;
  1414.     case A_SPAT:
  1415.         shouldsave |= spat_tosave(arg[i].arg_ptr.arg_spat);
  1416.         break;
  1417.     }
  1418.     }
  1419.     switch (arg->arg_type) {
  1420.     case O_RETURN:
  1421.     saw_return = TRUE;
  1422.     break;
  1423.     case O_EVAL:
  1424.     case O_SUBR:
  1425.     shouldsave = TRUE;
  1426.     break;
  1427.     }
  1428.     if (willsave && arg->arg_ptr.arg_str)
  1429.     (void)apush(tosave,arg->arg_ptr.arg_str);
  1430.     return shouldsave;
  1431. }
  1432.  
  1433. static int
  1434. spat_tosave(spat)
  1435. register SPAT *spat;
  1436. {
  1437.     int shouldsave = FALSE;
  1438.  
  1439.     if (spat->spat_runtime)
  1440.     shouldsave |= arg_tosave(spat->spat_runtime,FALSE);
  1441.     if (spat->spat_repl) {
  1442.     shouldsave |= arg_tosave(spat->spat_repl,FALSE);
  1443.     }
  1444.  
  1445.     return shouldsave;
  1446. }
  1447.  
  1448.