diff options
Diffstat (limited to 'cons.c')
-rw-r--r-- | cons.c | 1444 |
1 files changed, 0 insertions, 1444 deletions
diff --git a/cons.c b/cons.c deleted file mode 100644 index 8b1210d464..0000000000 --- a/cons.c +++ /dev/null @@ -1,1444 +0,0 @@ -/* $RCSfile: cons.c,v $$Revision: 4.0.1.3 $$Date: 92/06/08 12:18:35 $ - * - * Copyright (c) 1991, Larry Wall - * - * You may distribute under the terms of either the GNU General Public - * License or the Artistic License, as specified in the README file. - * - * $Log: cons.c,v $ - * Revision 4.0.1.3 92/06/08 12:18:35 lwall - * patch20: removed implicit int declarations on funcions - * patch20: deleted some minor memory leaks - * patch20: fixed double debug break in foreach with implicit array assignment - * patch20: fixed confusion between a *var's real name and its effective name - * patch20: Perl now distinguishes overlapped copies from non-overlapped - * patch20: debugger sometimes displayed wrong source line - * patch20: various error messages have been clarified - * patch20: an eval block containing a null block or statement could dump core - * - * Revision 4.0.1.2 91/11/05 16:15:13 lwall - * patch11: debugger got confused over nested subroutine definitions - * patch11: prepared for ctype implementations that don't define isascii() - * - * Revision 4.0.1.1 91/06/07 10:31:15 lwall - * patch4: new copyright notice - * patch4: added global modifier for pattern matches - * - * Revision 4.0 91/03/20 01:05:51 lwall - * 4.0 baseline. - * - */ - -#include "EXTERN.h" -#include "perl.h" -#include "perly.h" - -extern char *tokename[]; -extern int yychar; - -static int cmd_tosave(); -static int arg_tosave(); -static int spat_tosave(); -static void make_cswitch(); -static void make_nswitch(); - -static bool saw_return; - -SUBR * -make_sub(name,cmd) -char *name; -CMD *cmd; -{ - register SUBR *sub; - STAB *stab = stabent(name,TRUE); - - if (sub = stab_sub(stab)) { - if (dowarn) { - CMD *oldcurcmd = curcmd; - - if (cmd) - curcmd = cmd; - warn("Subroutine %s redefined",name); - curcmd = oldcurcmd; - } - if (!sub->usersub && sub->cmd) { - cmd_free(sub->cmd); - sub->cmd = Nullcmd; - afree(sub->tosave); - } - Safefree(sub); - } - Newz(101,sub,1,SUBR); - stab_sub(stab) = sub; - sub->filestab = curcmd->c_filestab; - saw_return = FALSE; - tosave = anew(Nullstab); - tosave->ary_fill = 0; /* make 1 based */ - (void)cmd_tosave(cmd,FALSE); /* this builds the tosave array */ - sub->tosave = tosave; - if (saw_return) { - struct compcmd mycompblock; - - mycompblock.comp_true = cmd; - mycompblock.comp_alt = Nullcmd; - cmd = add_label(savestr("_SUB_"),make_ccmd(C_BLOCK,0, - Nullarg,mycompblock)); - saw_return = FALSE; - cmd->c_flags |= CF_TERM; - cmd->c_head = cmd; - } - sub->cmd = cmd; - if (perldb) { - STR *str; - STR *tmpstr = str_mortal(&str_undef); - - sprintf(buf,"%s:%ld",stab_val(curcmd->c_filestab)->str_ptr, subline); - str = str_make(buf,0); - str_cat(str,"-"); - sprintf(buf,"%ld",(long)curcmd->c_line); - str_cat(str,buf); - stab_efullname(tmpstr,stab); - hstore(stab_xhash(DBsub), tmpstr->str_ptr, tmpstr->str_cur, str, 0); - } - Safefree(name); - return sub; -} - -SUBR * -make_usub(name, ix, subaddr, filename) -char *name; -int ix; -int (*subaddr)(); -char *filename; -{ - register SUBR *sub; - STAB *stab = stabent(name,allstabs); - - if (!stab) /* unused function */ - return Null(SUBR*); - if (sub = stab_sub(stab)) { - if (dowarn) - warn("Subroutine %s redefined",name); - if (!sub->usersub && sub->cmd) { - cmd_free(sub->cmd); - sub->cmd = Nullcmd; - afree(sub->tosave); - } - Safefree(sub); - } - Newz(101,sub,1,SUBR); - stab_sub(stab) = sub; - sub->filestab = fstab(filename); - sub->usersub = subaddr; - sub->userindex = ix; - return sub; -} - -void -make_form(stab,fcmd) -STAB *stab; -FCMD *fcmd; -{ - if (stab_form(stab)) { - FCMD *tmpfcmd; - FCMD *nextfcmd; - - for (tmpfcmd = stab_form(stab); tmpfcmd; tmpfcmd = nextfcmd) { - nextfcmd = tmpfcmd->f_next; - if (tmpfcmd->f_expr) - arg_free(tmpfcmd->f_expr); - if (tmpfcmd->f_unparsed) - str_free(tmpfcmd->f_unparsed); - if (tmpfcmd->f_pre) - Safefree(tmpfcmd->f_pre); - Safefree(tmpfcmd); - } - } - stab_form(stab) = fcmd; -} - -CMD * -block_head(tail) -register CMD *tail; -{ - CMD *head; - register int opt; - register int last_opt = 0; - register STAB *last_stab = Nullstab; - register int count = 0; - register CMD *switchbeg = Nullcmd; - - if (tail == Nullcmd) { - return tail; - } - head = tail->c_head; - - for (tail = head; tail; tail = tail->c_next) { - - /* save one measly dereference at runtime */ - if (tail->c_type == C_IF) { - if (!(tail->ucmd.ccmd.cc_alt = tail->ucmd.ccmd.cc_alt->c_next)) - tail->c_flags |= CF_TERM; - } - else if (tail->c_type == C_EXPR) { - ARG *arg; - - if (tail->ucmd.acmd.ac_expr) - arg = tail->ucmd.acmd.ac_expr; - else - arg = tail->c_expr; - if (arg) { - if (arg->arg_type == O_RETURN) - tail->c_flags |= CF_TERM; - else if (arg->arg_type == O_ITEM && arg[1].arg_type == A_CMD) - tail->c_flags |= CF_TERM; - } - } - if (!tail->c_next) - tail->c_flags |= CF_TERM; - - if (tail->c_expr && (tail->c_flags & CF_OPTIMIZE) == CFT_FALSE) - opt_arg(tail,1, tail->c_type == C_EXPR); - - /* now do a little optimization on case-ish structures */ - switch(tail->c_flags & (CF_OPTIMIZE|CF_FIRSTNEG|CF_INVERT)) { - case CFT_ANCHOR: - case CFT_STROP: - opt = (tail->c_flags & CF_NESURE) ? CFT_STROP : 0; - break; - case CFT_CCLASS: - opt = CFT_STROP; - break; - case CFT_NUMOP: - opt = (tail->c_slen == O_NE ? 0 : CFT_NUMOP); - if ((tail->c_flags&(CF_NESURE|CF_EQSURE)) != (CF_NESURE|CF_EQSURE)) - opt = 0; - break; - default: - opt = 0; - } - if (opt && opt == last_opt && tail->c_stab == last_stab) - count++; - else { - if (count >= 3) { /* is this the breakeven point? */ - if (last_opt == CFT_NUMOP) - make_nswitch(switchbeg,count); - else - make_cswitch(switchbeg,count); - } - if (opt) { - count = 1; - switchbeg = tail; - } - else - count = 0; - } - last_opt = opt; - last_stab = tail->c_stab; - } - if (count >= 3) { /* is this the breakeven point? */ - if (last_opt == CFT_NUMOP) - make_nswitch(switchbeg,count); - else - make_cswitch(switchbeg,count); - } - return head; -} - -/* We've spotted a sequence of CMDs that all test the value of the same - * spat. Thus we can insert a SWITCH in front and jump directly - * to the correct one. - */ -static void -make_cswitch(head,count) -register CMD *head; -int count; -{ - register CMD *cur; - register CMD **loc; - register int i; - register int min = 255; - register int max = 0; - - /* make a new head in the exact same spot */ - New(102,cur, 1, CMD); - StructCopy(head,cur,CMD); - Zero(head,1,CMD); - head->c_head = cur->c_head; - head->c_type = C_CSWITCH; - head->c_next = cur; /* insert new cmd at front of list */ - head->c_stab = cur->c_stab; - - Newz(103,loc,258,CMD*); - loc++; /* lie a little */ - while (count--) { - if ((cur->c_flags & CF_OPTIMIZE) == CFT_CCLASS) { - for (i = 0; i <= 255; i++) { - if (!loc[i] && cur->c_short->str_ptr[i>>3] & (1 << (i&7))) { - loc[i] = cur; - if (i < min) - min = i; - if (i > max) - max = i; - } - } - } - else { - i = *cur->c_short->str_ptr & 255; - if (!loc[i]) { - loc[i] = cur; - if (i < min) - min = i; - if (i > max) - max = i; - } - } - cur = cur->c_next; - } - max++; - if (min > 0) - Move(&loc[min],&loc[0], max - min, CMD*); - loc--; - min--; - max -= min; - for (i = 0; i <= max; i++) - if (!loc[i]) - loc[i] = cur; - Renew(loc,max+1,CMD*); /* chop it down to size */ - head->ucmd.scmd.sc_offset = min; - head->ucmd.scmd.sc_max = max; - head->ucmd.scmd.sc_next = loc; -} - -static void -make_nswitch(head,count) -register CMD *head; -int count; -{ - register CMD *cur = head; - register CMD **loc; - register int i; - register int min = 32767; - register int max = -32768; - int origcount = count; - double value; /* or your money back! */ - short changed; /* so triple your money back! */ - - while (count--) { - i = (int)str_gnum(cur->c_short); - value = (double)i; - if (value != cur->c_short->str_u.str_nval) - return; /* fractional values--just forget it */ - changed = i; - if (changed != i) - return; /* too big for a short */ - if (cur->c_slen == O_LE) - i++; - else if (cur->c_slen == O_GE) /* we only do < or > here */ - i--; - if (i < min) - min = i; - if (i > max) - max = i; - cur = cur->c_next; - } - count = origcount; - if (max - min > count * 2 + 10) /* too sparse? */ - return; - - /* now make a new head in the exact same spot */ - New(104,cur, 1, CMD); - StructCopy(head,cur,CMD); - Zero(head,1,CMD); - head->c_head = cur->c_head; - head->c_type = C_NSWITCH; - head->c_next = cur; /* insert new cmd at front of list */ - head->c_stab = cur->c_stab; - - Newz(105,loc, max - min + 3, CMD*); - loc++; - max -= min; - max++; - while (count--) { - i = (int)str_gnum(cur->c_short); - i -= min; - switch(cur->c_slen) { - case O_LE: - i++; - case O_LT: - for (i--; i >= -1; i--) - if (!loc[i]) - loc[i] = cur; - break; - case O_GE: - i--; - case O_GT: - for (i++; i <= max; i++) - if (!loc[i]) - loc[i] = cur; - break; - case O_EQ: - if (!loc[i]) - loc[i] = cur; - break; - } - cur = cur->c_next; - } - loc--; - min--; - max++; - for (i = 0; i <= max; i++) - if (!loc[i]) - loc[i] = cur; - head->ucmd.scmd.sc_offset = min; - head->ucmd.scmd.sc_max = max; - head->ucmd.scmd.sc_next = loc; -} - -CMD * -append_line(head,tail) -register CMD *head; -register CMD *tail; -{ - if (tail == Nullcmd) - return head; - if (!tail->c_head) /* make sure tail is well formed */ - tail->c_head = tail; - if (head != Nullcmd) { - tail = tail->c_head; /* get to start of tail list */ - if (!head->c_head) - head->c_head = head; /* start a new head list */ - while (head->c_next) { - head->c_next->c_head = head->c_head; - head = head->c_next; /* get to end of head list */ - } - head->c_next = tail; /* link to end of old list */ - tail->c_head = head->c_head; /* propagate head pointer */ - } - while (tail->c_next) { - tail->c_next->c_head = tail->c_head; - tail = tail->c_next; - } - return tail; -} - -CMD * -dodb(cur) -CMD *cur; -{ - register CMD *cmd; - register CMD *head = cur->c_head; - STR *str; - - if (!head) - head = cur; - if (!head->c_line) - return cur; - str = afetch(stab_xarray(curcmd->c_filestab),(int)head->c_line,FALSE); - if (str == &str_undef || str->str_nok) - return cur; - str->str_u.str_nval = (double)head->c_line; - str->str_nok = 1; - Newz(106,cmd,1,CMD); - str_magic(str, curcmd->c_filestab, 0, Nullch, 0); - str->str_magic->str_u.str_cmd = cmd; - cmd->c_type = C_EXPR; - cmd->ucmd.acmd.ac_stab = Nullstab; - cmd->ucmd.acmd.ac_expr = Nullarg; - cmd->c_expr = make_op(O_SUBR, 2, - stab2arg(A_WORD,DBstab), - Nullarg, - Nullarg); - /*SUPPRESS 53*/ - cmd->c_flags |= CF_COND|CF_DBSUB|CFT_D0; - cmd->c_line = head->c_line; - cmd->c_label = head->c_label; - cmd->c_filestab = curcmd->c_filestab; - cmd->c_stash = curstash; - return append_line(cmd, cur); -} - -CMD * -make_acmd(type,stab,cond,arg) -int type; -STAB *stab; -ARG *cond; -ARG *arg; -{ - register CMD *cmd; - - Newz(107,cmd,1,CMD); - cmd->c_type = type; - cmd->ucmd.acmd.ac_stab = stab; - cmd->ucmd.acmd.ac_expr = arg; - cmd->c_expr = cond; - if (cond) - cmd->c_flags |= CF_COND; - if (cmdline == NOLINE) - cmd->c_line = curcmd->c_line; - else { - cmd->c_line = cmdline; - cmdline = NOLINE; - } - cmd->c_filestab = curcmd->c_filestab; - cmd->c_stash = curstash; - if (perldb) - cmd = dodb(cmd); - return cmd; -} - -CMD * -make_ccmd(type,debuggable,arg,cblock) -int type; -int debuggable; -ARG *arg; -struct compcmd cblock; -{ - register CMD *cmd; - - Newz(108,cmd, 1, CMD); - cmd->c_type = type; - cmd->c_expr = arg; - cmd->ucmd.ccmd.cc_true = cblock.comp_true; - cmd->ucmd.ccmd.cc_alt = cblock.comp_alt; - if (arg) - cmd->c_flags |= CF_COND; - if (cmdline == NOLINE) - cmd->c_line = curcmd->c_line; - else { - cmd->c_line = cmdline; - cmdline = NOLINE; - } - cmd->c_filestab = curcmd->c_filestab; - cmd->c_stash = curstash; - if (perldb && debuggable) - cmd = dodb(cmd); - return cmd; -} - -CMD * -make_icmd(type,arg,cblock) -int type; -ARG *arg; -struct compcmd cblock; -{ - register CMD *cmd; - register CMD *alt; - register CMD *cur; - register CMD *head; - struct compcmd ncblock; - - Newz(109,cmd, 1, CMD); - head = cmd; - cmd->c_type = type; - cmd->c_expr = arg; - cmd->ucmd.ccmd.cc_true = cblock.comp_true; - cmd->ucmd.ccmd.cc_alt = cblock.comp_alt; - if (arg) - cmd->c_flags |= CF_COND; - if (cmdline == NOLINE) - cmd->c_line = curcmd->c_line; - else { - cmd->c_line = cmdline; - cmdline = NOLINE; - } - cmd->c_filestab = curcmd->c_filestab; - cmd->c_stash = curstash; - cur = cmd; - alt = cblock.comp_alt; - while (alt && alt->c_type == C_ELSIF) { - cur = alt; - alt = alt->ucmd.ccmd.cc_alt; - } - if (alt) { /* a real life ELSE at the end? */ - ncblock.comp_true = alt; - ncblock.comp_alt = Nullcmd; - alt = append_line(cur,make_ccmd(C_ELSE,1,Nullarg,ncblock)); - cur->ucmd.ccmd.cc_alt = alt; - } - else - alt = cur; /* no ELSE, so cur is proxy ELSE */ - - cur = cmd; - while (cmd) { /* now point everyone at the ELSE */ - cur = cmd; - cmd = cur->ucmd.ccmd.cc_alt; - cur->c_head = head; - if (cur->c_type == C_ELSIF) - cur->c_type = C_IF; - if (cur->c_type == C_IF) - cur->ucmd.ccmd.cc_alt = alt; - if (cur == alt) - break; - cur->c_next = cmd; - } - if (perldb) - cur = dodb(cur); - return cur; -} - -void -opt_arg(cmd,fliporflop,acmd) -register CMD *cmd; -int fliporflop; -int acmd; -{ - register ARG *arg; - int opt = CFT_EVAL; - int sure = 0; - ARG *arg2; - int context = 0; /* 0 = normal, 1 = before &&, 2 = before || */ - int flp = fliporflop; - - if (!cmd) - return; - if (!(arg = cmd->c_expr)) { - cmd->c_flags &= ~CF_COND; - return; - } - - /* Can we turn && and || into if and unless? */ - - if (acmd && !cmd->ucmd.acmd.ac_expr && !(cmd->c_flags & CF_TERM) && - (arg->arg_type == O_AND || arg->arg_type == O_OR) ) { - dehoist(arg,1); - arg[2].arg_type &= A_MASK; /* don't suppress eval */ - dehoist(arg,2); - cmd->ucmd.acmd.ac_expr = arg[2].arg_ptr.arg_arg; - cmd->c_expr = arg[1].arg_ptr.arg_arg; - if (arg->arg_type == O_OR) - cmd->c_flags ^= CF_INVERT; /* || is like unless */ - arg->arg_len = 0; - free_arg(arg); - arg = cmd->c_expr; - } - - /* Turn "if (!expr)" into "unless (expr)" */ - - if (!(cmd->c_flags & CF_TERM)) { /* unless return value wanted */ - while (arg->arg_type == O_NOT) { - dehoist(arg,1); - cmd->c_flags ^= CF_INVERT; /* flip sense of cmd */ - cmd->c_expr = arg[1].arg_ptr.arg_arg; /* hoist the rest of expr */ - free_arg(arg); - arg = cmd->c_expr; /* here we go again */ - } - } - - if (!arg->arg_len) { /* sanity check */ - cmd->c_flags |= opt; - return; - } - - /* for "cond .. cond" we set up for the initial check */ - - if (arg->arg_type == O_FLIP) - context |= 4; - - /* for "cond && expr" and "cond || expr" we can ignore expr, sort of */ - - morecontext: - if (arg->arg_type == O_AND) - context |= 1; - else if (arg->arg_type == O_OR) - context |= 2; - if (context && (arg[flp].arg_type & A_MASK) == A_EXPR) { - arg = arg[flp].arg_ptr.arg_arg; - flp = 1; - if (arg->arg_type == O_AND || arg->arg_type == O_OR) - goto morecontext; - } - if ((context & 3) == 3) - return; - - if (arg[flp].arg_flags & (AF_PRE|AF_POST)) { - cmd->c_flags |= opt; - if (acmd && !cmd->ucmd.acmd.ac_expr && !(cmd->c_flags & CF_TERM) - && cmd->c_expr->arg_type == O_ITEM) { - arg[flp].arg_flags &= ~AF_POST; /* prefer ++$foo to $foo++ */ - arg[flp].arg_flags |= AF_PRE; /* if value not wanted */ - } - return; /* side effect, can't optimize */ - } - - if (arg->arg_type == O_ITEM || arg->arg_type == O_FLIP || - arg->arg_type == O_AND || arg->arg_type == O_OR) { - if ((arg[flp].arg_type & A_MASK) == A_SINGLE) { - opt = (str_true(arg[flp].arg_ptr.arg_str) ? CFT_TRUE : CFT_FALSE); - cmd->c_short = str_smake(arg[flp].arg_ptr.arg_str); - goto literal; - } - else if ((arg[flp].arg_type & A_MASK) == A_STAB || - (arg[flp].arg_type & A_MASK) == A_LVAL) { - cmd->c_stab = arg[flp].arg_ptr.arg_stab; - if (!context) - arg[flp].arg_ptr.arg_stab = Nullstab; - opt = CFT_REG; - literal: - if (!context) { /* no && or ||? */ - arg_free(arg); - cmd->c_expr = Nullarg; - } - if (!(context & 1)) - cmd->c_flags |= CF_EQSURE; - if (!(context & 2)) - cmd->c_flags |= CF_NESURE; - } - } - else if (arg->arg_type == O_MATCH || arg->arg_type == O_SUBST || - arg->arg_type == O_NMATCH || arg->arg_type == O_NSUBST) { - if ((arg[1].arg_type == A_STAB || arg[1].arg_type == A_LVAL) && - (arg[2].arg_type & A_MASK) == A_SPAT && - arg[2].arg_ptr.arg_spat->spat_short && - (arg->arg_type == O_SUBST || arg->arg_type == O_NSUBST || - (arg[2].arg_ptr.arg_spat->spat_flags & SPAT_GLOBAL) == 0 )) { - cmd->c_stab = arg[1].arg_ptr.arg_stab; - cmd->c_short = str_smake(arg[2].arg_ptr.arg_spat->spat_short); - cmd->c_slen = arg[2].arg_ptr.arg_spat->spat_slen; - if (arg[2].arg_ptr.arg_spat->spat_flags & SPAT_ALL && - !(arg[2].arg_ptr.arg_spat->spat_flags & SPAT_ONCE) && - (arg->arg_type == O_MATCH || arg->arg_type == O_NMATCH) ) - sure |= CF_EQSURE; /* (SUBST must be forced even */ - /* if we know it will work.) */ - if (arg->arg_type != O_SUBST) { - str_free(arg[2].arg_ptr.arg_spat->spat_short); - arg[2].arg_ptr.arg_spat->spat_short = Nullstr; - arg[2].arg_ptr.arg_spat->spat_slen = 0; /* only one chk */ - } - sure |= CF_NESURE; /* normally only sure if it fails */ - if (arg->arg_type == O_NMATCH || arg->arg_type == O_NSUBST) - cmd->c_flags |= CF_FIRSTNEG; - if (context & 1) { /* only sure if thing is false */ - if (cmd->c_flags & CF_FIRSTNEG) - sure &= ~CF_NESURE; - else - sure &= ~CF_EQSURE; - } - else if (context & 2) { /* only sure if thing is true */ - if (cmd->c_flags & CF_FIRSTNEG) - sure &= ~CF_EQSURE; - else - sure &= ~CF_NESURE; - } - if (sure & (CF_EQSURE|CF_NESURE)) { /* if we know anything*/ - if (arg[2].arg_ptr.arg_spat->spat_flags & SPAT_SCANFIRST) - opt = CFT_SCAN; - else - opt = CFT_ANCHOR; - if (sure == (CF_EQSURE|CF_NESURE) /* really sure? */ - && arg->arg_type == O_MATCH - && context & 4 - && fliporflop == 1) { - spat_free(arg[2].arg_ptr.arg_spat); - arg[2].arg_ptr.arg_spat = Nullspat; /* don't do twice */ - } - else - cmd->c_spat = arg[2].arg_ptr.arg_spat; - cmd->c_flags |= sure; - } - } - } - else if (arg->arg_type == O_SEQ || arg->arg_type == O_SNE || - arg->arg_type == O_SLT || arg->arg_type == O_SGT) { - if (arg[1].arg_type == A_STAB || arg[1].arg_type == A_LVAL) { - if (arg[2].arg_type == A_SINGLE) { - /*SUPPRESS 594*/ - char *junk = str_get(arg[2].arg_ptr.arg_str); - - cmd->c_stab = arg[1].arg_ptr.arg_stab; - cmd->c_short = str_smake(arg[2].arg_ptr.arg_str); - cmd->c_slen = cmd->c_short->str_cur+1; - switch (arg->arg_type) { - case O_SLT: case O_SGT: - sure |= CF_EQSURE; - cmd->c_flags |= CF_FIRSTNEG; - break; - case O_SNE: - cmd->c_flags |= CF_FIRSTNEG; - /* FALL THROUGH */ - case O_SEQ: - sure |= CF_NESURE|CF_EQSURE; - break; - } - if (context & 1) { /* only sure if thing is false */ - if (cmd->c_flags & CF_FIRSTNEG) - sure &= ~CF_NESURE; - else - sure &= ~CF_EQSURE; - } - else if (context & 2) { /* only sure if thing is true */ - if (cmd->c_flags & CF_FIRSTNEG) - sure &= ~CF_EQSURE; - else - sure &= ~CF_NESURE; - } - if (sure & (CF_EQSURE|CF_NESURE)) { - opt = CFT_STROP; - cmd->c_flags |= sure; - } - } - } - } - else if (arg->arg_type == O_EQ || arg->arg_type == O_NE || - arg->arg_type == O_LE || arg->arg_type == O_GE || - arg->arg_type == O_LT || arg->arg_type == O_GT) { - if (arg[1].arg_type == A_STAB || arg[1].arg_type == A_LVAL) { - if (arg[2].arg_type == A_SINGLE) { - cmd->c_stab = arg[1].arg_ptr.arg_stab; - if (dowarn) { - STR *str = arg[2].arg_ptr.arg_str; - - if ((!str->str_nok && !looks_like_number(str))) - warn("Possible use of == on string value"); - } - cmd->c_short = str_nmake(str_gnum(arg[2].arg_ptr.arg_str)); - cmd->c_slen = arg->arg_type; - sure |= CF_NESURE|CF_EQSURE; - if (context & 1) { /* only sure if thing is false */ - sure &= ~CF_EQSURE; - } - else if (context & 2) { /* only sure if thing is true */ - sure &= ~CF_NESURE; - } - if (sure & (CF_EQSURE|CF_NESURE)) { - opt = CFT_NUMOP; - cmd->c_flags |= sure; - } - } - } - } - else if (arg->arg_type == O_ASSIGN && - (arg[1].arg_type == A_STAB || arg[1].arg_type == A_LVAL) && - arg[1].arg_ptr.arg_stab == defstab && - arg[2].arg_type == A_EXPR ) { - arg2 = arg[2].arg_ptr.arg_arg; - if (arg2->arg_type == O_ITEM && arg2[1].arg_type == A_READ) { - opt = CFT_GETS; - cmd->c_stab = arg2[1].arg_ptr.arg_stab; - if (!(stab_io(arg2[1].arg_ptr.arg_stab)->flags & IOF_ARGV)) { - free_arg(arg2); - arg[2].arg_ptr.arg_arg = Nullarg; - free_arg(arg); - cmd->c_expr = Nullarg; - } - } - } - else if (arg->arg_type == O_CHOP && - (arg[1].arg_type == A_STAB || arg[1].arg_type == A_LVAL) ) { - opt = CFT_CHOP; - cmd->c_stab = arg[1].arg_ptr.arg_stab; - free_arg(arg); - cmd->c_expr = Nullarg; - } - if (context & 4) - opt |= CF_FLIP; - cmd->c_flags |= opt; - - if (cmd->c_flags & CF_FLIP) { - if (fliporflop == 1) { - arg = cmd->c_expr; /* get back to O_FLIP arg */ - New(110,arg[3].arg_ptr.arg_cmd, 1, CMD); - Copy(cmd, arg[3].arg_ptr.arg_cmd, 1, CMD); - New(111,arg[4].arg_ptr.arg_cmd,1,CMD); - Copy(cmd, arg[4].arg_ptr.arg_cmd, 1, CMD); - opt_arg(arg[4].arg_ptr.arg_cmd,2,acmd); - arg->arg_len = 2; /* this is a lie */ - } - else { - if ((opt & CF_OPTIMIZE) == CFT_EVAL) - cmd->c_flags = (cmd->c_flags & ~CF_OPTIMIZE) | CFT_UNFLIP; - } - } -} - -CMD * -add_label(lbl,cmd) -char *lbl; -register CMD *cmd; -{ - if (cmd) - cmd->c_label = lbl; - return cmd; -} - -CMD * -addcond(cmd, arg) -register CMD *cmd; -register ARG *arg; -{ - cmd->c_expr = arg; - cmd->c_flags |= CF_COND; - return cmd; -} - -CMD * -addloop(cmd, arg) -register CMD *cmd; -register ARG *arg; -{ - void while_io(); - - cmd->c_expr = arg; - cmd->c_flags |= CF_COND|CF_LOOP; - - if (!(cmd->c_flags & CF_INVERT)) - while_io(cmd); /* add $_ =, if necessary */ - - if (cmd->c_type == C_BLOCK) - cmd->c_flags &= ~CF_COND; - else { - arg = cmd->ucmd.acmd.ac_expr; - if (arg && arg->arg_type == O_ITEM && arg[1].arg_type == A_CMD) - cmd->c_flags &= ~CF_COND; /* "do {} while" happens at least once */ - if (arg && (arg->arg_flags & AF_DEPR) && - (arg->arg_type == O_SUBR || arg->arg_type == O_DBSUBR) ) - cmd->c_flags &= ~CF_COND; /* likewise for "do subr() while" */ - } - return cmd; -} - -CMD * -invert(cmd) -CMD *cmd; -{ - register CMD *targ = cmd; - if (targ->c_head) - targ = targ->c_head; - if (targ->c_flags & CF_DBSUB) - targ = targ->c_next; - targ->c_flags ^= CF_INVERT; - return cmd; -} - -void -cpy7bit(d,s,l) -register char *d; -register char *s; -register int l; -{ - while (l--) - *d++ = *s++ & 127; - *d = '\0'; -} - -int -yyerror(s) -char *s; -{ - char tmpbuf[258]; - char tmp2buf[258]; - char *tname = tmpbuf; - - if (bufptr > oldoldbufptr && bufptr - oldoldbufptr < 200 && - oldoldbufptr != oldbufptr && oldbufptr != bufptr) { - while (isSPACE(*oldoldbufptr)) - oldoldbufptr++; - cpy7bit(tmp2buf, oldoldbufptr, bufptr - oldoldbufptr); - sprintf(tname,"next 2 tokens \"%s\"",tmp2buf); - } - else if (bufptr > oldbufptr && bufptr - oldbufptr < 200 && - oldbufptr != bufptr) { - while (isSPACE(*oldbufptr)) - oldbufptr++; - cpy7bit(tmp2buf, oldbufptr, bufptr - oldbufptr); - sprintf(tname,"next token \"%s\"",tmp2buf); - } - else if (yychar > 256) - tname = "next token ???"; - else if (!yychar) - (void)strcpy(tname,"at EOF"); - else if (yychar < 32) - (void)sprintf(tname,"next char ^%c",yychar+64); - else if (yychar == 127) - (void)strcpy(tname,"at EOF"); - else - (void)sprintf(tname,"next char %c",yychar); - (void)sprintf(buf, "%s in file %s at line %d, %s\n", - s,stab_val(curcmd->c_filestab)->str_ptr,curcmd->c_line,tname); - if (curcmd->c_line == multi_end && multi_start < multi_end) - sprintf(buf+strlen(buf), - " (Might be a runaway multi-line %c%c string starting on line %d)\n", - multi_open,multi_close,multi_start); - if (in_eval) - str_cat(stab_val(stabent("@",TRUE)),buf); - else - fputs(buf,stderr); - if (++error_count >= 10) - fatal("%s has too many errors.\n", - stab_val(curcmd->c_filestab)->str_ptr); -} - -void -while_io(cmd) -register CMD *cmd; -{ - register ARG *arg = cmd->c_expr; - STAB *asgnstab; - - /* hoist "while (<channel>)" up into command block */ - - if (arg && arg->arg_type == O_ITEM && arg[1].arg_type == A_READ) { - cmd->c_flags &= ~CF_OPTIMIZE; /* clear optimization type */ - cmd->c_flags |= CFT_GETS; /* and set it to do the input */ - cmd->c_stab = arg[1].arg_ptr.arg_stab; - if (stab_io(arg[1].arg_ptr.arg_stab)->flags & IOF_ARGV) { - cmd->c_expr = l(make_op(O_ASSIGN, 2, /* fake up "$_ =" */ - stab2arg(A_LVAL,defstab), arg, Nullarg)); - } - else { - free_arg(arg); - cmd->c_expr = Nullarg; - } - } - else if (arg && arg->arg_type == O_ITEM && arg[1].arg_type == A_INDREAD) { - cmd->c_flags &= ~CF_OPTIMIZE; /* clear optimization type */ - cmd->c_flags |= CFT_INDGETS; /* and set it to do the input */ - cmd->c_stab = arg[1].arg_ptr.arg_stab; - free_arg(arg); - cmd->c_expr = Nullarg; - } - else if (arg && arg->arg_type == O_ITEM && arg[1].arg_type == A_GLOB) { - if ((cmd->c_flags & CF_OPTIMIZE) == CFT_ARRAY) - asgnstab = cmd->c_stab; - else - asgnstab = defstab; - cmd->c_expr = l(make_op(O_ASSIGN, 2, /* fake up "$foo =" */ - stab2arg(A_LVAL,asgnstab), arg, Nullarg)); - cmd->c_flags &= ~CF_OPTIMIZE; /* clear optimization type */ - } -} - -CMD * -wopt(cmd) -register CMD *cmd; -{ - register CMD *tail; - CMD *newtail; - register int i; - - if (cmd->c_expr && (cmd->c_flags & CF_OPTIMIZE) == CFT_FALSE) - opt_arg(cmd,1, cmd->c_type == C_EXPR); - - while_io(cmd); /* add $_ =, if necessary */ - - /* First find the end of the true list */ - - tail = cmd->ucmd.ccmd.cc_true; - if (tail == Nullcmd) - return cmd; - New(112,newtail, 1, CMD); /* guaranteed continue */ - for (;;) { - /* optimize "next" to point directly to continue block */ - if (tail->c_type == C_EXPR && - tail->ucmd.acmd.ac_expr && - tail->ucmd.acmd.ac_expr->arg_type == O_NEXT && - (tail->ucmd.acmd.ac_expr->arg_len == 0 || - (cmd->c_label && - strEQ(cmd->c_label, - tail->ucmd.acmd.ac_expr[1].arg_ptr.arg_str->str_ptr) ))) - { - arg_free(tail->ucmd.acmd.ac_expr); - tail->ucmd.acmd.ac_expr = Nullarg; - tail->c_type = C_NEXT; - if (cmd->ucmd.ccmd.cc_alt != Nullcmd) - tail->ucmd.ccmd.cc_alt = cmd->ucmd.ccmd.cc_alt; - else - tail->ucmd.ccmd.cc_alt = newtail; - tail->ucmd.ccmd.cc_true = Nullcmd; - } - else if (tail->c_type == C_IF && !tail->ucmd.ccmd.cc_alt) { - if (cmd->ucmd.ccmd.cc_alt != Nullcmd) - tail->ucmd.ccmd.cc_alt = cmd->ucmd.ccmd.cc_alt; - else - tail->ucmd.ccmd.cc_alt = newtail; - } - else if (tail->c_type == C_CSWITCH || tail->c_type == C_NSWITCH) { - if (cmd->ucmd.ccmd.cc_alt != Nullcmd) { - for (i = tail->ucmd.scmd.sc_max; i >= 0; i--) - if (!tail->ucmd.scmd.sc_next[i]) - tail->ucmd.scmd.sc_next[i] = cmd->ucmd.ccmd.cc_alt; - } - else { - for (i = tail->ucmd.scmd.sc_max; i >= 0; i--) - if (!tail->ucmd.scmd.sc_next[i]) - tail->ucmd.scmd.sc_next[i] = newtail; - } - } - - if (!tail->c_next) - break; - tail = tail->c_next; - } - - /* if there's a continue block, link it to true block and find end */ - - if (cmd->ucmd.ccmd.cc_alt != Nullcmd) { - tail->c_next = cmd->ucmd.ccmd.cc_alt; - tail = tail->c_next; - for (;;) { - /* optimize "next" to point directly to continue block */ - if (tail->c_type == C_EXPR && - tail->ucmd.acmd.ac_expr && - tail->ucmd.acmd.ac_expr->arg_type == O_NEXT && - (tail->ucmd.acmd.ac_expr->arg_len == 0 || - (cmd->c_label && - strEQ(cmd->c_label, - tail->ucmd.acmd.ac_expr[1].arg_ptr.arg_str->str_ptr) ))) - { - arg_free(tail->ucmd.acmd.ac_expr); - tail->ucmd.acmd.ac_expr = Nullarg; - tail->c_type = C_NEXT; - tail->ucmd.ccmd.cc_alt = newtail; - tail->ucmd.ccmd.cc_true = Nullcmd; - } - else if (tail->c_type == C_IF && !tail->ucmd.ccmd.cc_alt) { - tail->ucmd.ccmd.cc_alt = newtail; - } - else if (tail->c_type == C_CSWITCH || tail->c_type == C_NSWITCH) { - for (i = tail->ucmd.scmd.sc_max; i >= 0; i--) - if (!tail->ucmd.scmd.sc_next[i]) - tail->ucmd.scmd.sc_next[i] = newtail; - } - - if (!tail->c_next) - break; - tail = tail->c_next; - } - /*SUPPRESS 530*/ - for ( ; tail->c_next; tail = tail->c_next) ; - } - - /* Here's the real trick: link the end of the list back to the beginning, - * inserting a "last" block to break out of the loop. This saves one or - * two procedure calls every time through the loop, because of how cmd_exec - * does tail recursion. - */ - - tail->c_next = newtail; - tail = newtail; - if (!cmd->ucmd.ccmd.cc_alt) - cmd->ucmd.ccmd.cc_alt = tail; /* every loop has a continue now */ - -#ifndef lint - Copy((char *)cmd, (char *)tail, 1, CMD); -#endif - tail->c_type = C_EXPR; - tail->c_flags ^= CF_INVERT; /* turn into "last unless" */ - tail->c_next = tail->ucmd.ccmd.cc_true; /* loop directly back to top */ - tail->ucmd.acmd.ac_expr = make_op(O_LAST,0,Nullarg,Nullarg,Nullarg); - tail->ucmd.acmd.ac_stab = Nullstab; - return cmd; -} - -CMD * -over(eachstab,cmd) -STAB *eachstab; -register CMD *cmd; -{ - /* hoist "for $foo (@bar)" up into command block */ - - cmd->c_flags &= ~CF_OPTIMIZE; /* clear optimization type */ - cmd->c_flags |= CFT_ARRAY; /* and set it to do the iteration */ - cmd->c_stab = eachstab; - cmd->c_short = Str_new(23,0); /* just to save a field in struct cmd */ - cmd->c_short->str_u.str_useful = -1; - - return cmd; -} - -void -cmd_free(cmd) -register CMD *cmd; -{ - register CMD *tofree; - register CMD *head = cmd; - - if (!cmd) - return; - if (cmd->c_head != cmd) - warn("Malformed cmd links\n"); - while (cmd) { - if (cmd->c_type != C_WHILE) { /* WHILE block is duplicated */ - if (cmd->c_label) { - Safefree(cmd->c_label); - cmd->c_label = Nullch; - } - if (cmd->c_short) { - str_free(cmd->c_short); - cmd->c_short = Nullstr; - } - if (cmd->c_expr) { - arg_free(cmd->c_expr); - cmd->c_expr = Nullarg; - } - } - switch (cmd->c_type) { - case C_WHILE: - case C_BLOCK: - case C_ELSE: - case C_IF: - if (cmd->ucmd.ccmd.cc_true) { - cmd_free(cmd->ucmd.ccmd.cc_true); - cmd->ucmd.ccmd.cc_true = Nullcmd; - } - break; - case C_EXPR: - if (cmd->ucmd.acmd.ac_expr) { - arg_free(cmd->ucmd.acmd.ac_expr); - cmd->ucmd.acmd.ac_expr = Nullarg; - } - break; - } - tofree = cmd; - cmd = cmd->c_next; - if (tofree != head) /* to get Saber to shut up */ - Safefree(tofree); - if (cmd && cmd == head) /* reached end of while loop */ - break; - } - Safefree(head); -} - -void -arg_free(arg) -register ARG *arg; -{ - register int i; - - if (!arg) - return; - for (i = 1; i <= arg->arg_len; i++) { - switch (arg[i].arg_type & A_MASK) { - case A_NULL: - if (arg->arg_type == O_TRANS) { - Safefree(arg[i].arg_ptr.arg_cval); - arg[i].arg_ptr.arg_cval = Nullch; - } - break; - case A_LEXPR: - if (arg->arg_type == O_AASSIGN && - arg[i].arg_ptr.arg_arg->arg_type == O_LARRAY) { - char *name = - stab_name(arg[i].arg_ptr.arg_arg[1].arg_ptr.arg_stab); - - if (strnEQ("_GEN_",name, 5)) /* array for foreach */ - hdelete(defstash,name,strlen(name)); - } - /* FALL THROUGH */ - case A_EXPR: - arg_free(arg[i].arg_ptr.arg_arg); - arg[i].arg_ptr.arg_arg = Nullarg; - break; - case A_CMD: - cmd_free(arg[i].arg_ptr.arg_cmd); - arg[i].arg_ptr.arg_cmd = Nullcmd; - break; - case A_WORD: - case A_STAB: - case A_LVAL: - case A_READ: - case A_GLOB: - case A_ARYLEN: - case A_LARYLEN: - case A_ARYSTAB: - case A_LARYSTAB: - break; - case A_SINGLE: - case A_DOUBLE: - case A_BACKTICK: - str_free(arg[i].arg_ptr.arg_str); - arg[i].arg_ptr.arg_str = Nullstr; - break; - case A_SPAT: - spat_free(arg[i].arg_ptr.arg_spat); - arg[i].arg_ptr.arg_spat = Nullspat; - break; - } - } - free_arg(arg); -} - -void -spat_free(spat) -register SPAT *spat; -{ - register SPAT *sp; - HENT *entry; - - if (!spat) - return; - if (spat->spat_runtime) { - arg_free(spat->spat_runtime); - spat->spat_runtime = Nullarg; - } - if (spat->spat_repl) { - arg_free(spat->spat_repl); - spat->spat_repl = Nullarg; - } - if (spat->spat_short) { - str_free(spat->spat_short); - spat->spat_short = Nullstr; - } - if (spat->spat_regexp) { - regfree(spat->spat_regexp); - spat->spat_regexp = Null(REGEXP*); - } - - /* now unlink from spat list */ - - for (entry = defstash->tbl_array['_']; entry; entry = entry->hent_next) { - register HASH *stash; - STAB *stab = (STAB*)entry->hent_val; - - if (!stab) - continue; - stash = stab_hash(stab); - if (!stash || stash->tbl_spatroot == Null(SPAT*)) - continue; - if (stash->tbl_spatroot == spat) - stash->tbl_spatroot = spat->spat_next; - else { - for (sp = stash->tbl_spatroot; - sp && sp->spat_next != spat; - sp = sp->spat_next) - /*SUPPRESS 530*/ - ; - if (sp) - sp->spat_next = spat->spat_next; - } - } - Safefree(spat); -} - -/* Recursively descend a command sequence and push the address of any string - * that needs saving on recursion onto the tosave array. - */ - -static int -cmd_tosave(cmd,willsave) -register CMD *cmd; -int willsave; /* willsave passes down the tree */ -{ - register CMD *head = cmd; - int shouldsave = FALSE; /* shouldsave passes up the tree */ - int tmpsave; - register CMD *lastcmd = Nullcmd; - - while (cmd) { - if (cmd->c_expr) - shouldsave |= arg_tosave(cmd->c_expr,willsave); - switch (cmd->c_type) { - case C_WHILE: - if (cmd->ucmd.ccmd.cc_true) { - tmpsave = cmd_tosave(cmd->ucmd.ccmd.cc_true,willsave); - - /* Here we check to see if the temporary array generated for - * a foreach needs to be localized because of recursion. - */ - if (tmpsave && (cmd->c_flags & CF_OPTIMIZE) == CFT_ARRAY) { - if (lastcmd && - lastcmd->c_type == C_EXPR && - lastcmd->c_expr) { - ARG *arg = lastcmd->c_expr; - - if (arg->arg_type == O_ASSIGN && - arg[1].arg_type == A_LEXPR && - arg[1].arg_ptr.arg_arg->arg_type == O_LARRAY && - strnEQ("_GEN_", - stab_name( - arg[1].arg_ptr.arg_arg[1].arg_ptr.arg_stab), - 5)) { /* array generated for foreach */ - (void)localize(arg); - } - } - - /* in any event, save the iterator */ - - if (cmd->c_short) /* Better safe than sorry */ - (void)apush(tosave,cmd->c_short); - } - shouldsave |= tmpsave; - } - break; - case C_BLOCK: - case C_ELSE: - case C_IF: - if (cmd->ucmd.ccmd.cc_true) - shouldsave |= cmd_tosave(cmd->ucmd.ccmd.cc_true,willsave); - break; - case C_EXPR: - if (cmd->ucmd.acmd.ac_expr) - shouldsave |= arg_tosave(cmd->ucmd.acmd.ac_expr,willsave); - break; - } - lastcmd = cmd; - cmd = cmd->c_next; - if (cmd && cmd == head) /* reached end of while loop */ - break; - } - return shouldsave; -} - -static int -arg_tosave(arg,willsave) -register ARG *arg; -int willsave; -{ - register int i; - int shouldsave = FALSE; - - for (i = arg->arg_len; i >= 1; i--) { - switch (arg[i].arg_type & A_MASK) { - case A_NULL: - break; - case A_LEXPR: - case A_EXPR: - shouldsave |= arg_tosave(arg[i].arg_ptr.arg_arg,shouldsave); - break; - case A_CMD: - shouldsave |= cmd_tosave(arg[i].arg_ptr.arg_cmd,shouldsave); - break; - case A_WORD: - case A_STAB: - case A_LVAL: - case A_READ: - case A_GLOB: - case A_ARYLEN: - case A_SINGLE: - case A_DOUBLE: - case A_BACKTICK: - break; - case A_SPAT: - shouldsave |= spat_tosave(arg[i].arg_ptr.arg_spat); - break; - } - } - switch (arg->arg_type) { - case O_RETURN: - saw_return = TRUE; - break; - case O_EVAL: - case O_SUBR: - shouldsave = TRUE; - break; - } - if (willsave && arg->arg_ptr.arg_str) - (void)apush(tosave,arg->arg_ptr.arg_str); - return shouldsave; -} - -static int -spat_tosave(spat) -register SPAT *spat; -{ - int shouldsave = FALSE; - - if (spat->spat_runtime) - shouldsave |= arg_tosave(spat->spat_runtime,FALSE); - if (spat->spat_repl) { - shouldsave |= arg_tosave(spat->spat_repl,FALSE); - } - - return shouldsave; -} - |