diff options
Diffstat (limited to 'cmd.c')
-rw-r--r-- | cmd.c | 315 |
1 files changed, 239 insertions, 76 deletions
@@ -1,18 +1,12 @@ -/* $Header: cmd.c,v 1.0.1.1 88/01/21 21:24:16 root Exp $ +/* $Header: cmd.c,v 2.0 88/06/05 00:08:24 root Exp $ * * $Log: cmd.c,v $ - * Revision 1.0.1.1 88/01/21 21:24:16 root - * The redo cmd got a segmentation fault because trace context stack overflowed. - * - * Revision 1.0 87/12/18 13:04:51 root - * Initial revision + * Revision 2.0 88/06/05 00:08:24 root + * Baseline version 2.0. * */ -#include "handy.h" #include "EXTERN.h" -#include "search.h" -#include "util.h" #include "perl.h" static STR str_chop; @@ -24,9 +18,14 @@ static STR str_chop; STR * cmd_exec(cmd) +#ifdef cray /* nobody else has complained yet */ +CMD *cmd; +#else register CMD *cmd; +#endif { SPAT *oldspat; + int oldsave; #ifdef DEBUGGING int olddlevel; int entdlevel; @@ -34,10 +33,10 @@ register CMD *cmd; register STR *retstr; register char *tmps; register int cmdflags; - register bool match; + register int match; register char *go_to = goto_targ; - ARG *arg; FILE *fp; + ARRAY *ar; retstr = &str_no; #ifdef DEBUGGING @@ -57,14 +56,17 @@ tail_recursion_entry: switch (cmd->c_type) { case C_IF: oldspat = curspat; + oldsave = savestack->ary_fill; #ifdef DEBUGGING olddlevel = dlevel; #endif retstr = &str_yes; if (cmd->ucmd.ccmd.cc_true) { #ifdef DEBUGGING - debname[dlevel] = 't'; - debdelim[dlevel++] = '_'; + if (debug) { + debname[dlevel] = 't'; + debdelim[dlevel++] = '_'; + } #endif retstr = cmd_exec(cmd->ucmd.ccmd.cc_true); } @@ -74,8 +76,10 @@ tail_recursion_entry: retstr = &str_no; if (cmd->ucmd.ccmd.cc_alt) { #ifdef DEBUGGING - debname[dlevel] = 'e'; - debdelim[dlevel++] = '_'; + if (debug) { + debname[dlevel] = 'e'; + debdelim[dlevel++] = '_'; + } #endif retstr = cmd_exec(cmd->ucmd.ccmd.cc_alt); } @@ -83,6 +87,8 @@ tail_recursion_entry: if (!goto_targ) go_to = Nullch; curspat = oldspat; + if (savestack->ary_fill > oldsave) + restorelist(oldsave); #ifdef DEBUGGING dlevel = olddlevel; #endif @@ -108,15 +114,9 @@ tail_recursion_entry: olddlevel = dlevel; #endif curspat = oldspat; -#ifdef DEBUGGING - if (debug & 4) { - deb("(Popping label #%d %s)\n",loop_ptr, - loop_stack[loop_ptr].loop_label); - } -#endif - loop_ptr--; - cmd = cmd->c_next; - goto tail_recursion_entry; + if (savestack->ary_fill > oldsave) + restorelist(oldsave); + goto next_cmd; case O_NEXT: /* not done unless go_to found */ go_to = Nullch; goto next_iter; @@ -125,13 +125,16 @@ tail_recursion_entry: goto doit; } oldspat = curspat; + oldsave = savestack->ary_fill; #ifdef DEBUGGING olddlevel = dlevel; #endif if (cmd->ucmd.ccmd.cc_true) { #ifdef DEBUGGING - debname[dlevel] = 't'; - debdelim[dlevel++] = '_'; + if (debug) { + debname[dlevel] = 't'; + debdelim[dlevel++] = '_'; + } #endif cmd_exec(cmd->ucmd.ccmd.cc_true); } @@ -144,8 +147,10 @@ tail_recursion_entry: #endif if (cmd->ucmd.ccmd.cc_alt) { #ifdef DEBUGGING - debname[dlevel] = 'a'; - debdelim[dlevel++] = '_'; + if (debug) { + debname[dlevel] = 'a'; + debdelim[dlevel++] = '_'; + } #endif cmd_exec(cmd->ucmd.ccmd.cc_alt); } @@ -155,24 +160,41 @@ tail_recursion_entry: goto finish_while; } cmd = cmd->c_next; - if (cmd && cmd->c_head == cmd) /* reached end of while loop */ + if (cmd && cmd->c_head == cmd) + /* reached end of while loop */ return retstr; /* targ isn't in this block */ + if (cmdflags & CF_ONCE) { +#ifdef DEBUGGING + if (debug & 4) { + deb("(Popping label #%d %s)\n",loop_ptr, + loop_stack[loop_ptr].loop_label); + } +#endif + loop_ptr--; + } goto tail_recursion_entry; } } until_loop: + /* Set line number so run-time errors can be located */ + + line = cmd->c_line; + #ifdef DEBUGGING - 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); + 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++] = '!'; } - debname[dlevel] = cmdname[cmd->c_type][0]; - debdelim[dlevel++] = '!'; #endif - while (tmps_max >= 0) /* clean up after last eval */ + while (tmps_max > tmps_base) /* clean up after last eval */ str_free(tmps_list[tmps_max--]); /* Here is some common optimization */ @@ -181,13 +203,13 @@ until_loop: switch (cmdflags & CF_OPTIMIZE) { case CFT_FALSE: - retstr = cmd->c_first; + retstr = cmd->c_short; match = FALSE; if (cmdflags & CF_NESURE) goto maybe; break; case CFT_TRUE: - retstr = cmd->c_first; + retstr = cmd->c_short; match = TRUE; if (cmdflags & CF_EQSURE) goto flipmaybe; @@ -202,7 +224,7 @@ until_loop: case CFT_ANCHOR: /* /^pat/ optimization */ if (multiline) { - if (*cmd->c_first->str_ptr && !(cmdflags & CF_EQSURE)) + if (*cmd->c_short->str_ptr && !(cmdflags & CF_EQSURE)) goto scanner; /* just unanchor it */ else break; /* must evaluate */ @@ -210,9 +232,9 @@ until_loop: /* FALL THROUGH */ case CFT_STROP: /* string op optimization */ retstr = STAB_STR(cmd->c_stab); - if (*cmd->c_first->str_ptr == *str_get(retstr) && - strnEQ(cmd->c_first->str_ptr, str_get(retstr), - cmd->c_flen) ) { + if (*cmd->c_short->str_ptr == *str_get(retstr) && + strnEQ(cmd->c_short->str_ptr, str_get(retstr), + cmd->c_slen) ) { if (cmdflags & CF_EQSURE) { match = !(cmdflags & CF_FIRSTNEG); retstr = &str_yes; @@ -229,27 +251,92 @@ until_loop: case CFT_SCAN: /* non-anchored search */ scanner: retstr = STAB_STR(cmd->c_stab); - if (instr(str_get(retstr),cmd->c_first->str_ptr)) { + if (retstr->str_pok == 5) + 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 */ + tmps = fbminstr(tmps, tmps + retstr->str_cur, cmd->c_short); + } + if (tmps) { if (cmdflags & CF_EQSURE) { + ++*(long*)&cmd->c_short->str_nval; match = !(cmdflags & CF_FIRSTNEG); retstr = &str_yes; goto flipmaybe; } + else + hint = tmps; + } + else { + if (cmdflags & CF_NESURE) { + ++*(long*)&cmd->c_short->str_nval; + match = cmdflags & CF_FIRSTNEG; + retstr = &str_no; + goto flipmaybe; + } + } + if (--*(long*)&cmd->c_short->str_nval < 0) { + str_free(cmd->c_short); + cmd->c_short = Nullstr; + cmdflags &= ~CF_OPTIMIZE; + cmdflags |= CFT_EVAL; /* never try this optimization again */ + cmd->c_flags = cmdflags; + } + break; /* must evaluate */ + + case CFT_NUMOP: /* numeric op optimization */ + retstr = STAB_STR(cmd->c_stab); + switch (cmd->c_slen) { + case O_EQ: + match = (str_gnum(retstr) == cmd->c_short->str_nval); + break; + case O_NE: + match = (str_gnum(retstr) != cmd->c_short->str_nval); + break; + case O_LT: + match = (str_gnum(retstr) < cmd->c_short->str_nval); + break; + case O_LE: + match = (str_gnum(retstr) <= cmd->c_short->str_nval); + break; + case O_GT: + match = (str_gnum(retstr) > cmd->c_short->str_nval); + break; + case O_GE: + match = (str_gnum(retstr) >= cmd->c_short->str_nval); + break; + } + if (match) { + if (cmdflags & CF_EQSURE) { + retstr = &str_yes; + goto flipmaybe; + } } else if (cmdflags & CF_NESURE) { - match = cmdflags & CF_FIRSTNEG; 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 (!last_in_stab->stab_io) + last_in_stab->stab_io = stio_new(); + goto dogets; case CFT_GETS: /* really a while (<file>) */ last_in_stab = cmd->c_stab; + dogets: fp = last_in_stab->stab_io->fp; retstr = defstab->stab_val; if (fp && str_gets(retstr, fp)) { + if (*retstr->str_ptr == '0' && !retstr->str_ptr[1]) + match = FALSE; + else + match = TRUE; last_in_stab->stab_io->lines++; - match = TRUE; } else if (last_in_stab->stab_io->flags & IOF_ARGV) goto doeval; /* doesn't necessarily count as EOF yet */ @@ -261,7 +348,7 @@ until_loop: case CFT_EVAL: break; case CFT_UNFLIP: - retstr = eval(cmd->c_expr,Null(char***)); + retstr = eval(cmd->c_expr,Null(STR***),-1); 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); @@ -277,12 +364,32 @@ until_loop: retstr->str_cur = tmps - retstr->str_ptr; retstr = &str_chop; goto flipmaybe; + case CFT_ARRAY: + ar = cmd->c_expr[1].arg_ptr.arg_stab->stab_array; + match = ar->ary_index; /* just to get register */ + + if (match < 0) /* first time through here? */ + cmd->c_short = cmd->c_stab->stab_val; + + if (match >= ar->ary_fill) { + ar->ary_index = -1; +/* cmd->c_stab->stab_val = cmd->c_short; - Can't be done in LAST */ + match = FALSE; + } + else { + match++; + retstr = cmd->c_stab->stab_val = ar->ary_array[match]; + ar->ary_index = match; + match = TRUE; + } + goto maybe; } /* we have tried to make this normal case as abnormal as possible */ doeval: - retstr = eval(cmd->c_expr,Null(char***)); + lastretstr = retstr; + retstr = eval(cmd->c_expr,Null(STR***),-1); match = str_true(retstr); goto maybe; @@ -291,11 +398,11 @@ until_loop: flipmaybe: if (match && cmdflags & CF_FLIP) { if (cmd->c_expr->arg_type == O_FLOP) { /* currently toggled? */ - retstr = eval(cmd->c_expr,Null(char***)); /* let eval undo it */ + retstr = eval(cmd->c_expr,Null(STR***),-1);/*let eval undo it*/ cmdflags = copyopt(cmd,cmd->c_expr[3].arg_ptr.arg_cmd); } else { - retstr = eval(cmd->c_expr,Null(char***)); /* let eval do it */ + retstr = eval(cmd->c_expr,Null(STR***),-1);/* 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); } @@ -311,24 +418,24 @@ until_loop: maybe: if (cmdflags & CF_INVERT) match = !match; - if (!match && cmd->c_type != C_IF) { - cmd = cmd->c_next; - goto tail_recursion_entry; - } + if (!match && cmd->c_type != C_IF) + goto next_cmd; } /* now to do the actual command, if any */ switch (cmd->c_type) { case C_NULL: - fatal("panic: cmd_exec\n"); + fatal("panic: cmd_exec"); case C_EXPR: /* evaluated for side effects */ if (cmd->ucmd.acmd.ac_expr) { /* more to do? */ - retstr = eval(cmd->ucmd.acmd.ac_expr,Null(char***)); + lastretstr = retstr; + retstr = eval(cmd->ucmd.acmd.ac_expr,Null(STR***),-1); } break; case C_IF: oldspat = curspat; + oldsave = savestack->ary_fill; #ifdef DEBUGGING olddlevel = dlevel; #endif @@ -336,8 +443,10 @@ until_loop: retstr = &str_yes; if (cmd->ucmd.ccmd.cc_true) { #ifdef DEBUGGING - debname[dlevel] = 't'; - debdelim[dlevel++] = '_'; + if (debug) { + debname[dlevel] = 't'; + debdelim[dlevel++] = '_'; + } #endif retstr = cmd_exec(cmd->ucmd.ccmd.cc_true); } @@ -346,13 +455,17 @@ until_loop: retstr = &str_no; if (cmd->ucmd.ccmd.cc_alt) { #ifdef DEBUGGING - debname[dlevel] = 'e'; - debdelim[dlevel++] = '_'; + if (debug) { + debname[dlevel] = 'e'; + debdelim[dlevel++] = '_'; + } #endif retstr = cmd_exec(cmd->ucmd.ccmd.cc_alt); } } curspat = oldspat; + if (savestack->ary_fill > oldsave) + restorelist(oldsave); #ifdef DEBUGGING dlevel = olddlevel; #endif @@ -372,17 +485,11 @@ until_loop: } switch (setjmp(loop_stack[loop_ptr].loop_env)) { case O_LAST: - retstr = &str_no; + retstr = lastretstr; curspat = oldspat; -#ifdef DEBUGGING - if (debug & 4) { - deb("(Popping label #%d %s)\n",loop_ptr, - loop_stack[loop_ptr].loop_label); - } -#endif - loop_ptr--; - cmd = cmd->c_next; - goto tail_recursion_entry; + if (savestack->ary_fill > oldsave) + restorelist(oldsave); + goto next_cmd; case O_NEXT: goto next_iter; case O_REDO: @@ -392,18 +499,21 @@ until_loop: goto doit; } oldspat = curspat; + oldsave = savestack->ary_fill; #ifdef DEBUGGING olddlevel = dlevel; #endif doit: if (cmd->ucmd.ccmd.cc_true) { #ifdef DEBUGGING - debname[dlevel] = 't'; - debdelim[dlevel++] = '_'; + if (debug) { + debname[dlevel] = 't'; + debdelim[dlevel++] = '_'; + } #endif cmd_exec(cmd->ucmd.ccmd.cc_true); } - /* actually, this spot is never reached anymore since the above + /* actually, this spot is rarely reached anymore since the above * cmd_exec() returns through longjmp(). Hooray for structure. */ next_iter: @@ -412,13 +522,17 @@ until_loop: #endif if (cmd->ucmd.ccmd.cc_alt) { #ifdef DEBUGGING - debname[dlevel] = 'a'; - debdelim[dlevel++] = '_'; + if (debug) { + debname[dlevel] = 'a'; + debdelim[dlevel++] = '_'; + } #endif cmd_exec(cmd->ucmd.ccmd.cc_alt); } finish_while: curspat = oldspat; + if (savestack->ary_fill > oldsave) + restorelist(oldsave); #ifdef DEBUGGING dlevel = olddlevel - 1; #endif @@ -427,8 +541,24 @@ until_loop: } 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) { + deb("(Popping label #%d %s)\n",loop_ptr, + loop_stack[loop_ptr].loop_label); + } +#endif + loop_ptr--; + if ((cmdflags & CF_OPTIMIZE) == CFT_ARRAY) { + cmd->c_stab->stab_val = cmd->c_short; + } + } cmd = cmd->c_next; goto tail_recursion_entry; } @@ -440,6 +570,7 @@ char *pat; { register int i; + fprintf(stderr,"%-4ld",(long)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); @@ -452,8 +583,40 @@ register CMD *which; { cmd->c_flags &= CF_ONCE|CF_COND|CF_LOOP; cmd->c_flags |= which->c_flags; - cmd->c_first = which->c_first; - cmd->c_flen = which->c_flen; + cmd->c_short = which->c_short; + cmd->c_slen = which->c_slen; cmd->c_stab = which->c_stab; return cmd->c_flags; } + +void +savelist(sarg,maxsarg) +register STR **sarg; +int maxsarg; +{ + register STR *str; + register int i; + + for (i = 1; i <= maxsarg; i++) { + apush(savestack,sarg[i]); /* remember the pointer */ + str = str_new(0); + str_sset(str,sarg[i]); + apush(savestack,str); /* remember the value */ + } +} + +void +restorelist(base) +int base; +{ + register STR *str; + register STR *value; + + while (savestack->ary_fill > base) { + value = apop(savestack); + str = apop(savestack); + str_sset(str,value); + STABSET(str); + str_free(value); + } +} |