diff options
Diffstat (limited to 'cmd.c')
-rw-r--r-- | cmd.c | 1260 |
1 files changed, 0 insertions, 1260 deletions
diff --git a/cmd.c b/cmd.c deleted file mode 100644 index a4f310a110..0000000000 --- a/cmd.c +++ /dev/null @@ -1,1260 +0,0 @@ -/* $RCSfile: cmd.c,v $$Revision: 4.0.1.5 $$Date: 92/06/08 12:00:39 $ - * - * 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: cmd.c,v $ - * Revision 4.0.1.5 92/06/08 12:00:39 lwall - * patch20: the switch optimizer didn't do anything in subroutines - * patch20: removed implicit int declarations on funcions - * - * Revision 4.0.1.4 91/11/11 16:29:33 lwall - * patch19: do {$foo ne "bar";} returned wrong value - * patch19: some earlier patches weren't propagated to alternate 286 code - * - * Revision 4.0.1.3 91/11/05 16:07:43 lwall - * patch11: random cleanup - * patch11: "foo\0" eq "foo" was sometimes optimized to true - * patch11: foreach on null list could spring memory leak - * - * Revision 4.0.1.2 91/06/07 10:26:45 lwall - * patch4: new copyright notice - * patch4: made some allowances for "semi-standard" C - * - * Revision 4.0.1.1 91/04/11 17:36:16 lwall - * patch1: you may now use "die" and "caller" in a signal handler - * - * Revision 4.0 91/03/20 01:04:18 lwall - * 4.0 baseline. - * - */ - -#include "EXTERN.h" -#include "perl.h" - -#ifdef I_VARARGS -# include <varargs.h> -#endif - -static STR strchop; - -void grow_dlevel(); - -/* do longjmps() clobber register variables? */ - -#if defined(cray) || defined(STANDARD_C) -#define JMPCLOBBER -#endif - -/* This is the main command loop. We try to spend as much time in this loop - * as possible, so lots of optimizations do their activities in here. This - * means things get a little sloppy. - */ - -int -cmd_exec(cmdparm,gimme,sp) -CMD *VOLATILE cmdparm; -VOLATILE int gimme; -VOLATILE int sp; -{ - register CMD *cmd = cmdparm; - SPAT *VOLATILE oldspat; - VOLATILE int firstsave = savestack->ary_fill; - VOLATILE int oldsave; - VOLATILE int aryoptsave; -#ifdef DEBUGGING - VOLATILE int olddlevel; - VOLATILE int entdlevel; -#endif - register STR *retstr = &str_undef; - register char *tmps; - register int cmdflags; - register int match; - register char *go_to = goto_targ; - register int newsp = -2; - register STR **st = stack->ary_array; - FILE *VOLATILE fp; - ARRAY *VOLATILE ar; - - lastsize = 0; -#ifdef DEBUGGING - entdlevel = dlevel; -#endif -tail_recursion_entry: -#ifdef DEBUGGING - dlevel = entdlevel; - if (debug & 4) - deb("mortals = (%d/%d) stack, = (%d/%d)\n", - tmps_max, tmps_base, - savestack->ary_fill, firstsave); -#endif -#ifdef TAINT - tainted = 0; /* Each statement is presumed innocent */ -#endif - if (cmd == Nullcmd) { - if (gimme == G_ARRAY && newsp > -2) - return newsp; - else { - st[++sp] = retstr; - return sp; - } - } - cmdflags = cmd->c_flags; /* hopefully load register */ - if (go_to) { - if (cmd->c_label && strEQ(go_to,cmd->c_label)) - goto_targ = go_to = Nullch; /* here at last */ - else { - switch (cmd->c_type) { - case C_IF: - oldspat = curspat; - oldsave = savestack->ary_fill; -#ifdef DEBUGGING - olddlevel = dlevel; -#endif - retstr = &str_yes; - newsp = -2; - if (cmd->ucmd.ccmd.cc_true) { -#ifdef DEBUGGING - if (debug) { - debname[dlevel] = 't'; - debdelim[dlevel] = '_'; - if (++dlevel >= dlmax) - grow_dlevel(); - } -#endif - newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme && (cmdflags & CF_TERM),sp); - st = stack->ary_array; /* possibly reallocated */ - retstr = st[newsp]; - } - if (!goto_targ) - go_to = Nullch; - curspat = oldspat; - if (savestack->ary_fill > oldsave) - restorelist(oldsave); -#ifdef DEBUGGING - dlevel = olddlevel; -#endif - cmd = cmd->ucmd.ccmd.cc_alt; - goto tail_recursion_entry; - case C_ELSE: - oldspat = curspat; - oldsave = savestack->ary_fill; -#ifdef DEBUGGING - olddlevel = dlevel; -#endif - retstr = &str_undef; - newsp = -2; - if (cmd->ucmd.ccmd.cc_true) { -#ifdef DEBUGGING - if (debug) { - debname[dlevel] = 'e'; - debdelim[dlevel] = '_'; - if (++dlevel >= dlmax) - grow_dlevel(); - } -#endif - newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme && (cmdflags & CF_TERM),sp); - st = stack->ary_array; /* possibly reallocated */ - retstr = st[newsp]; - } - if (!goto_targ) - go_to = Nullch; - curspat = oldspat; - if (savestack->ary_fill > oldsave) - restorelist(oldsave); -#ifdef DEBUGGING - dlevel = olddlevel; -#endif - break; - case C_BLOCK: - case C_WHILE: - if (!(cmdflags & CF_ONCE)) { - cmdflags |= CF_ONCE; - if (++loop_ptr >= loop_max) { - loop_max += 128; - Renew(loop_stack, loop_max, struct loop); - } - loop_stack[loop_ptr].loop_label = cmd->c_label; - loop_stack[loop_ptr].loop_sp = sp; -#ifdef DEBUGGING - if (debug & 4) { - deb("(Pushing label #%d %s)\n", - loop_ptr, cmd->c_label ? cmd->c_label : ""); - } -#endif - } -#ifdef JMPCLOBBER - cmdparm = cmd; -#endif - match = setjmp(loop_stack[loop_ptr].loop_env); - if (match) { - st = stack->ary_array; /* possibly reallocated */ -#ifdef JMPCLOBBER - cmd = cmdparm; - cmdflags = cmd->c_flags|CF_ONCE; -#endif - if (savestack->ary_fill > oldsave) - restorelist(oldsave); - switch (match) { - default: - fatal("longjmp returned bad value (%d)",match); - case O_LAST: /* not done unless go_to found */ - go_to = Nullch; - if (lastretstr) { - retstr = lastretstr; - newsp = -2; - } - else { - newsp = sp + lastsize; - retstr = st[newsp]; - } -#ifdef DEBUGGING - olddlevel = dlevel; -#endif - curspat = oldspat; - goto next_cmd; - case O_NEXT: /* not done unless go_to found */ - go_to = Nullch; -#ifdef JMPCLOBBER - newsp = -2; - retstr = &str_undef; -#endif - goto next_iter; - case O_REDO: /* not done unless go_to found */ - go_to = Nullch; -#ifdef JMPCLOBBER - newsp = -2; - retstr = &str_undef; -#endif - goto doit; - } - } - oldspat = curspat; - oldsave = savestack->ary_fill; -#ifdef DEBUGGING - olddlevel = dlevel; -#endif - if (cmd->ucmd.ccmd.cc_true) { -#ifdef DEBUGGING - if (debug) { - debname[dlevel] = 't'; - debdelim[dlevel] = '_'; - if (++dlevel >= dlmax) - grow_dlevel(); - } -#endif - newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme && (cmdflags & CF_TERM),sp); - st = stack->ary_array; /* possibly reallocated */ - if (newsp >= 0) - retstr = st[newsp]; - } - if (!goto_targ) { - go_to = Nullch; - goto next_iter; - } -#ifdef DEBUGGING - dlevel = olddlevel; -#endif - if (cmd->ucmd.ccmd.cc_alt) { -#ifdef DEBUGGING - if (debug) { - debname[dlevel] = 'a'; - debdelim[dlevel] = '_'; - if (++dlevel >= dlmax) - grow_dlevel(); - } -#endif - newsp = cmd_exec(cmd->ucmd.ccmd.cc_alt,gimme && (cmdflags & CF_TERM),sp); - st = stack->ary_array; /* possibly reallocated */ - if (newsp >= 0) - retstr = st[newsp]; - } - if (goto_targ) - break; - go_to = Nullch; - goto finish_while; - } - cmd = cmd->c_next; - if (cmd && cmd->c_head == cmd) - /* reached end of while loop */ - return sp; /* targ isn't in this block */ - if (cmdflags & CF_ONCE) { -#ifdef DEBUGGING - if (debug & 4) { - tmps = loop_stack[loop_ptr].loop_label; - deb("(Popping label #%d %s)\n",loop_ptr, - tmps ? tmps : "" ); - } -#endif - loop_ptr--; - } - goto tail_recursion_entry; - } - } - -until_loop: - - /* Set line number so run-time errors can be located */ - - curcmd = cmd; - -#ifdef DEBUGGING - if (debug) { - if (debug & 2) { - deb("%s (%lx) r%lx t%lx a%lx n%lx cs%lx\n", - cmdname[cmd->c_type],cmd,cmd->c_expr, - cmd->ucmd.ccmd.cc_true,cmd->ucmd.ccmd.cc_alt,cmd->c_next, - curspat); - } - debname[dlevel] = cmdname[cmd->c_type][0]; - debdelim[dlevel] = '!'; - if (++dlevel >= dlmax) - grow_dlevel(); - } -#endif - - /* Here is some common optimization */ - - if (cmdflags & CF_COND) { - switch (cmdflags & CF_OPTIMIZE) { - - case CFT_FALSE: - retstr = cmd->c_short; - newsp = -2; - match = FALSE; - if (cmdflags & CF_NESURE) - goto maybe; - break; - case CFT_TRUE: - retstr = cmd->c_short; - newsp = -2; - match = TRUE; - if (cmdflags & CF_EQSURE) - goto flipmaybe; - break; - - case CFT_REG: - retstr = STAB_STR(cmd->c_stab); - newsp = -2; - match = str_true(retstr); /* => retstr = retstr, c2 should fix */ - if (cmdflags & (match ? CF_EQSURE : CF_NESURE)) - goto flipmaybe; - break; - - case CFT_ANCHOR: /* /^pat/ optimization */ - if (multiline) { - if (*cmd->c_short->str_ptr && !(cmdflags & CF_EQSURE)) - goto scanner; /* just unanchor it */ - else - break; /* must evaluate */ - } - match = 0; - goto strop; - - case CFT_STROP: /* string op optimization */ - match = 1; - strop: - retstr = STAB_STR(cmd->c_stab); - newsp = -2; -#ifndef I286 - if (*cmd->c_short->str_ptr == *str_get(retstr) && - (match ? retstr->str_cur == cmd->c_slen - 1 : - retstr->str_cur >= cmd->c_slen) && - bcmp(cmd->c_short->str_ptr, str_get(retstr), - cmd->c_slen) == 0 ) { - if (cmdflags & CF_EQSURE) { - if (sawampersand && (cmdflags & CF_OPTIMIZE) != CFT_STROP) { - curspat = Nullspat; - if (leftstab) - str_nset(stab_val(leftstab),"",0); - if (amperstab) - str_sset(stab_val(amperstab),cmd->c_short); - if (rightstab) - str_nset(stab_val(rightstab), - retstr->str_ptr + cmd->c_slen, - retstr->str_cur - cmd->c_slen); - } - if (cmd->c_spat) - lastspat = cmd->c_spat; - match = !(cmdflags & CF_FIRSTNEG); - retstr = match ? &str_yes : &str_no; - goto flipmaybe; - } - } - else if (cmdflags & CF_NESURE) { - match = cmdflags & CF_FIRSTNEG; - retstr = match ? &str_yes : &str_no; - goto flipmaybe; - } -#else - { - char *zap1, *zap2, zap1c, zap2c; - int zaplen; - int lenok; - - zap1 = cmd->c_short->str_ptr; - zap2 = str_get(retstr); - zap1c = *zap1; - zap2c = *zap2; - zaplen = cmd->c_slen; - if (match) - lenok = (retstr->str_cur == cmd->c_slen - 1); - else - lenok = (retstr->str_cur >= cmd->c_slen); - if ((zap1c == zap2c) && lenok && (bcmp(zap1, zap2, zaplen) == 0)) { - if (cmdflags & CF_EQSURE) { - if (sawampersand && - (cmdflags & CF_OPTIMIZE) != CFT_STROP) { - curspat = Nullspat; - if (leftstab) - str_nset(stab_val(leftstab),"",0); - if (amperstab) - str_sset(stab_val(amperstab),cmd->c_short); - if (rightstab) - str_nset(stab_val(rightstab), - retstr->str_ptr + cmd->c_slen, - retstr->str_cur - cmd->c_slen); - } - if (cmd->c_spat) - lastspat = cmd->c_spat; - match = !(cmdflags & CF_FIRSTNEG); - retstr = match ? &str_yes : &str_no; - goto flipmaybe; - } - } - else if (cmdflags & CF_NESURE) { - match = cmdflags & CF_FIRSTNEG; - retstr = match ? &str_yes : &str_no; - goto flipmaybe; - } - } -#endif - break; /* must evaluate */ - - case CFT_SCAN: /* non-anchored search */ - scanner: - retstr = STAB_STR(cmd->c_stab); - newsp = -2; - if (retstr->str_pok & SP_STUDIED) - if (screamfirst[cmd->c_short->str_rare] >= 0) - tmps = screaminstr(retstr, cmd->c_short); - else - tmps = Nullch; - else { - tmps = str_get(retstr); /* make sure it's pok */ -#ifndef lint - tmps = fbminstr((unsigned char*)tmps, - (unsigned char*)tmps + retstr->str_cur, cmd->c_short); -#endif - } - if (tmps) { - if (cmdflags & CF_EQSURE) { - ++cmd->c_short->str_u.str_useful; - if (sawampersand) { - curspat = Nullspat; - if (leftstab) - str_nset(stab_val(leftstab),retstr->str_ptr, - tmps - retstr->str_ptr); - if (amperstab) - str_nset(stab_val(amperstab), - tmps, cmd->c_short->str_cur); - if (rightstab) - str_nset(stab_val(rightstab), - tmps + cmd->c_short->str_cur, - retstr->str_cur - (tmps - retstr->str_ptr) - - cmd->c_short->str_cur); - } - lastspat = cmd->c_spat; - match = !(cmdflags & CF_FIRSTNEG); - retstr = match ? &str_yes : &str_no; - goto flipmaybe; - } - else - hint = tmps; - } - else { - if (cmdflags & CF_NESURE) { - ++cmd->c_short->str_u.str_useful; - match = cmdflags & CF_FIRSTNEG; - retstr = match ? &str_yes : &str_no; - goto flipmaybe; - } - } - if (--cmd->c_short->str_u.str_useful < 0) { - cmdflags &= ~CF_OPTIMIZE; - cmdflags |= CFT_EVAL; /* never try this optimization again */ - cmd->c_flags = (cmdflags & ~CF_ONCE); - } - break; /* must evaluate */ - - case CFT_NUMOP: /* numeric op optimization */ - retstr = STAB_STR(cmd->c_stab); - newsp = -2; - switch (cmd->c_slen) { - case O_EQ: - if (dowarn) { - if ((!retstr->str_nok && !looks_like_number(retstr))) - warn("Possible use of == on string value"); - } - match = (str_gnum(retstr) == cmd->c_short->str_u.str_nval); - break; - case O_NE: - match = (str_gnum(retstr) != cmd->c_short->str_u.str_nval); - break; - case O_LT: - match = (str_gnum(retstr) < cmd->c_short->str_u.str_nval); - break; - case O_LE: - match = (str_gnum(retstr) <= cmd->c_short->str_u.str_nval); - break; - case O_GT: - match = (str_gnum(retstr) > cmd->c_short->str_u.str_nval); - break; - case O_GE: - match = (str_gnum(retstr) >= cmd->c_short->str_u.str_nval); - break; - } - if (match) { - if (cmdflags & CF_EQSURE) { - retstr = &str_yes; - goto flipmaybe; - } - } - else if (cmdflags & CF_NESURE) { - retstr = &str_no; - goto flipmaybe; - } - break; /* must evaluate */ - - case CFT_INDGETS: /* while (<$foo>) */ - last_in_stab = stabent(str_get(STAB_STR(cmd->c_stab)),TRUE); - if (!stab_io(last_in_stab)) - stab_io(last_in_stab) = stio_new(); - goto dogets; - case CFT_GETS: /* really a while (<file>) */ - last_in_stab = cmd->c_stab; - dogets: - fp = stab_io(last_in_stab)->ifp; - retstr = stab_val(defstab); - newsp = -2; - keepgoing: - if (fp && str_gets(retstr, fp, 0)) { - if (*retstr->str_ptr == '0' && retstr->str_cur == 1) - match = FALSE; - else - match = TRUE; - stab_io(last_in_stab)->lines++; - } - else if (stab_io(last_in_stab)->flags & IOF_ARGV) { - if (!fp) - goto doeval; /* first time through */ - fp = nextargv(last_in_stab); - if (fp) - goto keepgoing; - (void)do_close(last_in_stab,FALSE); - stab_io(last_in_stab)->flags |= IOF_START; - retstr = &str_undef; - match = FALSE; - } - else { - retstr = &str_undef; - match = FALSE; - } - goto flipmaybe; - case CFT_EVAL: - break; - case CFT_UNFLIP: - while (tmps_max > tmps_base) { /* clean up after last eval */ - str_free(tmps_list[tmps_max]); - tmps_list[tmps_max--] = Nullstr; - } - newsp = eval(cmd->c_expr,gimme && (cmdflags & CF_TERM),sp); - st = stack->ary_array; /* possibly reallocated */ - retstr = st[newsp]; - match = str_true(retstr); - if (cmd->c_expr->arg_type == O_FLIP) /* undid itself? */ - cmdflags = copyopt(cmd,cmd->c_expr[3].arg_ptr.arg_cmd); - goto maybe; - case CFT_CHOP: - retstr = stab_val(cmd->c_stab); - newsp = -2; - match = (retstr->str_cur != 0); - tmps = str_get(retstr); - tmps += retstr->str_cur - match; - str_nset(&strchop,tmps,match); - *tmps = '\0'; - retstr->str_nok = 0; - retstr->str_cur = tmps - retstr->str_ptr; - STABSET(retstr); - retstr = &strchop; - goto flipmaybe; - case CFT_ARRAY: - match = cmd->c_short->str_u.str_useful; /* just to get register */ - - if (match < 0) { /* first time through here? */ - ar = stab_array(cmd->c_expr[1].arg_ptr.arg_stab); - aryoptsave = savestack->ary_fill; - savesptr(&stab_val(cmd->c_stab)); - savelong(&cmd->c_short->str_u.str_useful); - } - else { - ar = stab_xarray(cmd->c_expr[1].arg_ptr.arg_stab); - if (cmd->c_type != C_WHILE && savestack->ary_fill > firstsave) - restorelist(firstsave); - } - - if (match >= ar->ary_fill) { /* we're in LAST, probably */ - if (match < 0 && /* er, probably not... */ - savestack->ary_fill > aryoptsave) - restorelist(aryoptsave); - retstr = &str_undef; - cmd->c_short->str_u.str_useful = -1; /* actually redundant */ - match = FALSE; - } - else { - match++; - if (!(retstr = ar->ary_array[match])) - retstr = afetch(ar,match,TRUE); - stab_val(cmd->c_stab) = retstr; - cmd->c_short->str_u.str_useful = match; - match = TRUE; - } - newsp = -2; - goto maybe; - case CFT_D1: - break; - case CFT_D0: - if (DBsingle->str_u.str_nval != 0) - break; - if (DBsignal->str_u.str_nval != 0) - break; - if (DBtrace->str_u.str_nval != 0) - break; - goto next_cmd; - } - - /* we have tried to make this normal case as abnormal as possible */ - - doeval: - if (gimme == G_ARRAY) { - lastretstr = Nullstr; - lastspbase = sp; - lastsize = newsp - sp; - if (lastsize < 0) - lastsize = 0; - } - else - lastretstr = retstr; - while (tmps_max > tmps_base) { /* clean up after last eval */ - str_free(tmps_list[tmps_max]); - tmps_list[tmps_max--] = Nullstr; - } - newsp = eval(cmd->c_expr, - gimme && (cmdflags & CF_TERM) && cmd->c_type == C_EXPR && - !cmd->ucmd.acmd.ac_expr, - sp); - st = stack->ary_array; /* possibly reallocated */ - retstr = st[newsp]; - if (newsp > sp && retstr) - match = str_true(retstr); - else - match = FALSE; - goto maybe; - - /* if flipflop was true, flop it */ - - flipmaybe: - if (match && cmdflags & CF_FLIP) { - while (tmps_max > tmps_base) { /* clean up after last eval */ - str_free(tmps_list[tmps_max]); - tmps_list[tmps_max--] = Nullstr; - } - if (cmd->c_expr->arg_type == O_FLOP) { /* currently toggled? */ - newsp = eval(cmd->c_expr,G_SCALAR,sp);/*let eval undo it*/ - cmdflags = copyopt(cmd,cmd->c_expr[3].arg_ptr.arg_cmd); - } - else { - newsp = eval(cmd->c_expr,G_SCALAR,sp);/* let eval do it */ - if (cmd->c_expr->arg_type == O_FLOP) /* still toggled? */ - cmdflags = copyopt(cmd,cmd->c_expr[4].arg_ptr.arg_cmd); - } - } - else if (cmdflags & CF_FLIP) { - if (cmd->c_expr->arg_type == O_FLOP) { /* currently toggled? */ - match = TRUE; /* force on */ - } - } - - /* at this point, match says whether our expression was true */ - - maybe: - if (cmdflags & CF_INVERT) - match = !match; - if (!match) - goto next_cmd; - } -#ifdef TAINT - tainted = 0; /* modifier doesn't affect regular expression */ -#endif - - /* now to do the actual command, if any */ - - switch (cmd->c_type) { - case C_NULL: - fatal("panic: cmd_exec"); - case C_EXPR: /* evaluated for side effects */ - if (cmd->ucmd.acmd.ac_expr) { /* more to do? */ - if (gimme == G_ARRAY) { - lastretstr = Nullstr; - lastspbase = sp; - lastsize = newsp - sp; - if (lastsize < 0) - lastsize = 0; - } - else - lastretstr = retstr; - while (tmps_max > tmps_base) { /* clean up after last eval */ - str_free(tmps_list[tmps_max]); - tmps_list[tmps_max--] = Nullstr; - } - newsp = eval(cmd->ucmd.acmd.ac_expr,gimme && (cmdflags&CF_TERM),sp); - st = stack->ary_array; /* possibly reallocated */ - retstr = st[newsp]; - } - break; - case C_NSWITCH: - { - double value = str_gnum(STAB_STR(cmd->c_stab)); - - match = (int)value; - if (value < 0.0) { - if (((double)match) > value) - --match; /* was fractional--truncate other way */ - } - } - goto doswitch; - case C_CSWITCH: - if (multiline) { - cmd = cmd->c_next; /* can't assume anything */ - goto tail_recursion_entry; - } - match = *(str_get(STAB_STR(cmd->c_stab))) & 255; - doswitch: - match -= cmd->ucmd.scmd.sc_offset; - if (match < 0) - match = 0; - else if (match > cmd->ucmd.scmd.sc_max) - match = cmd->ucmd.scmd.sc_max; - cmd = cmd->ucmd.scmd.sc_next[match]; - goto tail_recursion_entry; - case C_NEXT: - cmd = cmd->ucmd.ccmd.cc_alt; - goto tail_recursion_entry; - case C_ELSIF: - fatal("panic: ELSIF"); - case C_IF: - oldspat = curspat; - oldsave = savestack->ary_fill; -#ifdef DEBUGGING - olddlevel = dlevel; -#endif - retstr = &str_yes; - newsp = -2; - if (cmd->ucmd.ccmd.cc_true) { -#ifdef DEBUGGING - if (debug) { - debname[dlevel] = 't'; - debdelim[dlevel] = '_'; - if (++dlevel >= dlmax) - grow_dlevel(); - } -#endif - newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme && (cmdflags & CF_TERM),sp); - st = stack->ary_array; /* possibly reallocated */ - retstr = st[newsp]; - } - curspat = oldspat; - if (savestack->ary_fill > oldsave) - restorelist(oldsave); -#ifdef DEBUGGING - dlevel = olddlevel; -#endif - cmd = cmd->ucmd.ccmd.cc_alt; - goto tail_recursion_entry; - case C_ELSE: - oldspat = curspat; - oldsave = savestack->ary_fill; -#ifdef DEBUGGING - olddlevel = dlevel; -#endif - retstr = &str_undef; - newsp = -2; - if (cmd->ucmd.ccmd.cc_true) { -#ifdef DEBUGGING - if (debug) { - debname[dlevel] = 'e'; - debdelim[dlevel] = '_'; - if (++dlevel >= dlmax) - grow_dlevel(); - } -#endif - newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme && (cmdflags & CF_TERM),sp); - st = stack->ary_array; /* possibly reallocated */ - retstr = st[newsp]; - } - curspat = oldspat; - if (savestack->ary_fill > oldsave) - restorelist(oldsave); -#ifdef DEBUGGING - dlevel = olddlevel; -#endif - break; - case C_BLOCK: - case C_WHILE: - if (!(cmdflags & CF_ONCE)) { /* first time through here? */ - cmdflags |= CF_ONCE; - if (++loop_ptr >= loop_max) { - loop_max += 128; - Renew(loop_stack, loop_max, struct loop); - } - loop_stack[loop_ptr].loop_label = cmd->c_label; - loop_stack[loop_ptr].loop_sp = sp; -#ifdef DEBUGGING - if (debug & 4) { - deb("(Pushing label #%d %s)\n", - loop_ptr, cmd->c_label ? cmd->c_label : ""); - } -#endif - } -#ifdef JMPCLOBBER - cmdparm = cmd; -#endif - match = setjmp(loop_stack[loop_ptr].loop_env); - if (match) { - st = stack->ary_array; /* possibly reallocated */ -#ifdef JMPCLOBBER - cmd = cmdparm; - cmdflags = cmd->c_flags|CF_ONCE; - go_to = goto_targ; -#endif - if (savestack->ary_fill > oldsave) - restorelist(oldsave); - switch (match) { - default: - fatal("longjmp returned bad value (%d)",match); - case O_LAST: - if (lastretstr) { - retstr = lastretstr; - newsp = -2; - } - else { - newsp = sp + lastsize; - retstr = st[newsp]; - } - curspat = oldspat; - goto next_cmd; - case O_NEXT: -#ifdef JMPCLOBBER - newsp = -2; - retstr = &str_undef; -#endif - goto next_iter; - case O_REDO: -#ifdef DEBUGGING - dlevel = olddlevel; -#endif -#ifdef JMPCLOBBER - newsp = -2; - retstr = &str_undef; -#endif - goto doit; - } - } - oldspat = curspat; - oldsave = savestack->ary_fill; -#ifdef DEBUGGING - olddlevel = dlevel; -#endif - doit: - if (cmd->ucmd.ccmd.cc_true) { -#ifdef DEBUGGING - if (debug) { - debname[dlevel] = 't'; - debdelim[dlevel] = '_'; - if (++dlevel >= dlmax) - grow_dlevel(); - } -#endif - newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme && (cmdflags & CF_TERM),sp); - st = stack->ary_array; /* possibly reallocated */ - retstr = st[newsp]; - } - /* actually, this spot is rarely reached anymore since the above - * cmd_exec() returns through longjmp(). Hooray for structure. - */ - next_iter: -#ifdef DEBUGGING - dlevel = olddlevel; -#endif - if (cmd->ucmd.ccmd.cc_alt) { -#ifdef DEBUGGING - if (debug) { - debname[dlevel] = 'a'; - debdelim[dlevel] = '_'; - if (++dlevel >= dlmax) - grow_dlevel(); - } -#endif - newsp = cmd_exec(cmd->ucmd.ccmd.cc_alt,gimme && (cmdflags & CF_TERM),sp); - st = stack->ary_array; /* possibly reallocated */ - retstr = st[newsp]; - } - finish_while: - curspat = oldspat; - if (savestack->ary_fill > oldsave) { - if (cmdflags & CF_TERM) { - for (match = sp + 1; match <= newsp; match++) - st[match] = str_mortal(st[match]); - retstr = st[newsp]; - } - restorelist(oldsave); - } -#ifdef DEBUGGING - dlevel = olddlevel - 1; -#endif - if (cmd->c_type != C_BLOCK) - goto until_loop; /* go back and evaluate conditional again */ - } - if (cmdflags & CF_LOOP) { - cmdflags |= CF_COND; /* now test the condition */ -#ifdef DEBUGGING - dlevel = entdlevel; -#endif - goto until_loop; - } - next_cmd: - if (cmdflags & CF_ONCE) { -#ifdef DEBUGGING - if (debug & 4) { - tmps = loop_stack[loop_ptr].loop_label; - deb("(Popping label #%d %s)\n",loop_ptr, tmps ? tmps : ""); - } -#endif - loop_ptr--; - if ((cmdflags & CF_OPTIMIZE) == CFT_ARRAY && - savestack->ary_fill > aryoptsave) - restorelist(aryoptsave); - } - cmd = cmd->c_next; - goto tail_recursion_entry; -} - -#ifdef DEBUGGING -# ifndef I_VARARGS -/*VARARGS1*/ -void deb(pat,a1,a2,a3,a4,a5,a6,a7,a8) -char *pat; -{ - register int i; - - fprintf(stderr,"%-4ld",(long)curcmd->c_line); - for (i=0; i<dlevel; i++) - fprintf(stderr,"%c%c ",debname[i],debdelim[i]); - fprintf(stderr,pat,a1,a2,a3,a4,a5,a6,a7,a8); -} -# else -/*VARARGS1*/ -void deb(va_alist) -va_dcl -{ - va_list args; - char *pat; - register int i; - - va_start(args); - fprintf(stderr,"%-4ld",(long)curcmd->c_line); - for (i=0; i<dlevel; i++) - fprintf(stderr,"%c%c ",debname[i],debdelim[i]); - - pat = va_arg(args, char *); - (void) vfprintf(stderr,pat,args); - va_end( args ); -} -# endif -#endif - -int -copyopt(cmd,which) -register CMD *cmd; -register CMD *which; -{ - cmd->c_flags &= CF_ONCE|CF_COND|CF_LOOP; - cmd->c_flags |= which->c_flags; - cmd->c_short = which->c_short; - cmd->c_slen = which->c_slen; - cmd->c_stab = which->c_stab; - return cmd->c_flags; -} - -ARRAY * -saveary(stab) -STAB *stab; -{ - register STR *str; - - str = Str_new(10,0); - str->str_state = SS_SARY; - str->str_u.str_stab = stab; - if (str->str_ptr) { - Safefree(str->str_ptr); - str->str_ptr = Nullch; - str->str_len = 0; - } - str->str_ptr = (char*)stab_array(stab); - (void)apush(savestack,str); /* save array ptr */ - stab_xarray(stab) = Null(ARRAY*); - return stab_xarray(aadd(stab)); -} - -HASH * -savehash(stab) -STAB *stab; -{ - register STR *str; - - str = Str_new(11,0); - str->str_state = SS_SHASH; - str->str_u.str_stab = stab; - if (str->str_ptr) { - Safefree(str->str_ptr); - str->str_ptr = Nullch; - str->str_len = 0; - } - str->str_ptr = (char*)stab_hash(stab); - (void)apush(savestack,str); /* save hash ptr */ - stab_xhash(stab) = Null(HASH*); - return stab_xhash(hadd(stab)); -} - -void -saveitem(item) -register STR *item; -{ - register STR *str; - - (void)apush(savestack,item); /* remember the pointer */ - str = Str_new(12,0); - str_sset(str,item); - (void)apush(savestack,str); /* remember the value */ -} - -void -saveint(intp) -int *intp; -{ - register STR *str; - - str = Str_new(13,0); - str->str_state = SS_SINT; - str->str_u.str_useful = (long)*intp; /* remember value */ - if (str->str_ptr) { - Safefree(str->str_ptr); - str->str_len = 0; - } - str->str_ptr = (char*)intp; /* remember pointer */ - (void)apush(savestack,str); -} - -void -savelong(longp) -long *longp; -{ - register STR *str; - - str = Str_new(14,0); - str->str_state = SS_SLONG; - str->str_u.str_useful = *longp; /* remember value */ - if (str->str_ptr) { - Safefree(str->str_ptr); - str->str_len = 0; - } - str->str_ptr = (char*)longp; /* remember pointer */ - (void)apush(savestack,str); -} - -void -savesptr(sptr) -STR **sptr; -{ - register STR *str; - - str = Str_new(15,0); - str->str_state = SS_SSTRP; - str->str_magic = *sptr; /* remember value */ - if (str->str_ptr) { - Safefree(str->str_ptr); - str->str_len = 0; - } - str->str_ptr = (char*)sptr; /* remember pointer */ - (void)apush(savestack,str); -} - -void -savenostab(stab) -STAB *stab; -{ - register STR *str; - - str = Str_new(16,0); - str->str_state = SS_SNSTAB; - str->str_magic = (STR*)stab; /* remember which stab to free */ - (void)apush(savestack,str); -} - -void -savehptr(hptr) -HASH **hptr; -{ - register STR *str; - - str = Str_new(17,0); - str->str_state = SS_SHPTR; - str->str_u.str_hash = *hptr; /* remember value */ - if (str->str_ptr) { - Safefree(str->str_ptr); - str->str_len = 0; - } - str->str_ptr = (char*)hptr; /* remember pointer */ - (void)apush(savestack,str); -} - -void -saveaptr(aptr) -ARRAY **aptr; -{ - register STR *str; - - str = Str_new(17,0); - str->str_state = SS_SAPTR; - str->str_u.str_array = *aptr; /* remember value */ - if (str->str_ptr) { - Safefree(str->str_ptr); - str->str_len = 0; - } - str->str_ptr = (char*)aptr; /* remember pointer */ - (void)apush(savestack,str); -} - -void -savelist(sarg,maxsarg) -register STR **sarg; -int maxsarg; -{ - register STR *str; - register int i; - - for (i = 1; i <= maxsarg; i++) { - (void)apush(savestack,sarg[i]); /* remember the pointer */ - str = Str_new(18,0); - str_sset(str,sarg[i]); - (void)apush(savestack,str); /* remember the value */ - sarg[i]->str_u.str_useful = -1; - } -} - -void -restorelist(base) -int base; -{ - register STR *str; - register STR *value; - register STAB *stab; - - if (base < -1) - fatal("panic: corrupt saved stack index"); - while (savestack->ary_fill > base) { - value = apop(savestack); - switch (value->str_state) { - case SS_NORM: /* normal string */ - case SS_INCR: - str = apop(savestack); - str_replace(str,value); - STABSET(str); - break; - case SS_SARY: /* array reference */ - stab = value->str_u.str_stab; - afree(stab_xarray(stab)); - stab_xarray(stab) = (ARRAY*)value->str_ptr; - value->str_ptr = Nullch; - str_free(value); - break; - case SS_SHASH: /* hash reference */ - stab = value->str_u.str_stab; - (void)hfree(stab_xhash(stab), FALSE); - stab_xhash(stab) = (HASH*)value->str_ptr; - value->str_ptr = Nullch; - str_free(value); - break; - case SS_SINT: /* int reference */ - *((int*)value->str_ptr) = (int)value->str_u.str_useful; - value->str_ptr = Nullch; - str_free(value); - break; - case SS_SLONG: /* long reference */ - *((long*)value->str_ptr) = value->str_u.str_useful; - value->str_ptr = Nullch; - str_free(value); - break; - case SS_SSTRP: /* STR* reference */ - *((STR**)value->str_ptr) = value->str_magic; - value->str_magic = Nullstr; - value->str_ptr = Nullch; - str_free(value); - break; - case SS_SHPTR: /* HASH* reference */ - *((HASH**)value->str_ptr) = value->str_u.str_hash; - value->str_ptr = Nullch; - str_free(value); - break; - case SS_SAPTR: /* ARRAY* reference */ - *((ARRAY**)value->str_ptr) = value->str_u.str_array; - value->str_ptr = Nullch; - str_free(value); - break; - case SS_SNSTAB: - stab = (STAB*)value->str_magic; - value->str_magic = Nullstr; - (void)stab_clear(stab); - str_free(value); - break; - case SS_SCSV: /* callsave structure */ - { - CSV *csv = (CSV*) value->str_ptr; - - curcmd = csv->curcmd; - curcsv = csv->curcsv; - csv->sub->depth = csv->depth; - if (csv->hasargs) { /* put back old @_ */ - afree(csv->argarray); - stab_xarray(defstab) = csv->savearray; - } - str_free(value); - } - break; - default: - fatal("panic: restorelist inconsistency"); - } - } -} - -#ifdef DEBUGGING -void -grow_dlevel() -{ - dlmax += 128; - Renew(debname, dlmax, char); - Renew(debdelim, dlmax, char); -} -#endif |