1 /* $Header: cmd.c,v 2.0 88/06/05 00:08:24 root Exp $
4 * Revision 2.0 88/06/05 00:08:24 root
5 * Baseline version 2.0.
14 /* This is the main command loop. We try to spend as much time in this loop
15 * as possible, so lots of optimizations do their activities in here. This
16 * means things get a little sloppy.
21 #ifdef cray /* nobody else has complained yet */
35 register int cmdflags;
37 register char *go_to = goto_targ;
51 cmdflags = cmd->c_flags; /* hopefully load register */
53 if (cmd->c_label && strEQ(go_to,cmd->c_label))
54 goto_targ = go_to = Nullch; /* here at last */
56 switch (cmd->c_type) {
59 oldsave = savestack->ary_fill;
64 if (cmd->ucmd.ccmd.cc_true) {
67 debname[dlevel] = 't';
68 debdelim[dlevel++] = '_';
71 retstr = cmd_exec(cmd->ucmd.ccmd.cc_true);
77 if (cmd->ucmd.ccmd.cc_alt) {
80 debname[dlevel] = 'e';
81 debdelim[dlevel++] = '_';
84 retstr = cmd_exec(cmd->ucmd.ccmd.cc_alt);
90 if (savestack->ary_fill > oldsave)
98 if (!(cmdflags & CF_ONCE)) {
101 loop_stack[loop_ptr].loop_label = cmd->c_label;
104 deb("(Pushing label #%d %s)\n",
105 loop_ptr,cmd->c_label);
109 switch (setjmp(loop_stack[loop_ptr].loop_env)) {
110 case O_LAST: /* not done unless go_to found */
117 if (savestack->ary_fill > oldsave)
118 restorelist(oldsave);
120 case O_NEXT: /* not done unless go_to found */
123 case O_REDO: /* not done unless go_to found */
128 oldsave = savestack->ary_fill;
132 if (cmd->ucmd.ccmd.cc_true) {
135 debname[dlevel] = 't';
136 debdelim[dlevel++] = '_';
139 cmd_exec(cmd->ucmd.ccmd.cc_true);
148 if (cmd->ucmd.ccmd.cc_alt) {
151 debname[dlevel] = 'a';
152 debdelim[dlevel++] = '_';
155 cmd_exec(cmd->ucmd.ccmd.cc_alt);
163 if (cmd && cmd->c_head == cmd)
164 /* reached end of while loop */
165 return retstr; /* targ isn't in this block */
166 if (cmdflags & CF_ONCE) {
169 deb("(Popping label #%d %s)\n",loop_ptr,
170 loop_stack[loop_ptr].loop_label);
175 goto tail_recursion_entry;
181 /* Set line number so run-time errors can be located */
188 deb("%s (%lx) r%lx t%lx a%lx n%lx cs%lx\n",
189 cmdname[cmd->c_type],cmd,cmd->c_expr,
190 cmd->ucmd.ccmd.cc_true,cmd->ucmd.ccmd.cc_alt,cmd->c_next,
193 debname[dlevel] = cmdname[cmd->c_type][0];
194 debdelim[dlevel++] = '!';
197 while (tmps_max > tmps_base) /* clean up after last eval */
198 str_free(tmps_list[tmps_max--]);
200 /* Here is some common optimization */
202 if (cmdflags & CF_COND) {
203 switch (cmdflags & CF_OPTIMIZE) {
206 retstr = cmd->c_short;
208 if (cmdflags & CF_NESURE)
212 retstr = cmd->c_short;
214 if (cmdflags & CF_EQSURE)
219 retstr = STAB_STR(cmd->c_stab);
220 match = str_true(retstr); /* => retstr = retstr, c2 should fix */
221 if (cmdflags & (match ? CF_EQSURE : CF_NESURE))
225 case CFT_ANCHOR: /* /^pat/ optimization */
227 if (*cmd->c_short->str_ptr && !(cmdflags & CF_EQSURE))
228 goto scanner; /* just unanchor it */
230 break; /* must evaluate */
233 case CFT_STROP: /* string op optimization */
234 retstr = STAB_STR(cmd->c_stab);
235 if (*cmd->c_short->str_ptr == *str_get(retstr) &&
236 strnEQ(cmd->c_short->str_ptr, str_get(retstr),
238 if (cmdflags & CF_EQSURE) {
239 match = !(cmdflags & CF_FIRSTNEG);
244 else if (cmdflags & CF_NESURE) {
245 match = cmdflags & CF_FIRSTNEG;
249 break; /* must evaluate */
251 case CFT_SCAN: /* non-anchored search */
253 retstr = STAB_STR(cmd->c_stab);
254 if (retstr->str_pok == 5)
255 if (screamfirst[cmd->c_short->str_rare] >= 0)
256 tmps = screaminstr(retstr, cmd->c_short);
260 tmps = str_get(retstr); /* make sure it's pok */
261 tmps = fbminstr(tmps, tmps + retstr->str_cur, cmd->c_short);
264 if (cmdflags & CF_EQSURE) {
265 ++*(long*)&cmd->c_short->str_nval;
266 match = !(cmdflags & CF_FIRSTNEG);
274 if (cmdflags & CF_NESURE) {
275 ++*(long*)&cmd->c_short->str_nval;
276 match = cmdflags & CF_FIRSTNEG;
281 if (--*(long*)&cmd->c_short->str_nval < 0) {
282 str_free(cmd->c_short);
283 cmd->c_short = Nullstr;
284 cmdflags &= ~CF_OPTIMIZE;
285 cmdflags |= CFT_EVAL; /* never try this optimization again */
286 cmd->c_flags = cmdflags;
288 break; /* must evaluate */
290 case CFT_NUMOP: /* numeric op optimization */
291 retstr = STAB_STR(cmd->c_stab);
292 switch (cmd->c_slen) {
294 match = (str_gnum(retstr) == cmd->c_short->str_nval);
297 match = (str_gnum(retstr) != cmd->c_short->str_nval);
300 match = (str_gnum(retstr) < cmd->c_short->str_nval);
303 match = (str_gnum(retstr) <= cmd->c_short->str_nval);
306 match = (str_gnum(retstr) > cmd->c_short->str_nval);
309 match = (str_gnum(retstr) >= cmd->c_short->str_nval);
313 if (cmdflags & CF_EQSURE) {
318 else if (cmdflags & CF_NESURE) {
322 break; /* must evaluate */
324 case CFT_INDGETS: /* while (<$foo>) */
325 last_in_stab = stabent(str_get(STAB_STR(cmd->c_stab)),TRUE);
326 if (!last_in_stab->stab_io)
327 last_in_stab->stab_io = stio_new();
329 case CFT_GETS: /* really a while (<file>) */
330 last_in_stab = cmd->c_stab;
332 fp = last_in_stab->stab_io->fp;
333 retstr = defstab->stab_val;
334 if (fp && str_gets(retstr, fp)) {
335 if (*retstr->str_ptr == '0' && !retstr->str_ptr[1])
339 last_in_stab->stab_io->lines++;
341 else if (last_in_stab->stab_io->flags & IOF_ARGV)
342 goto doeval; /* doesn't necessarily count as EOF yet */
351 retstr = eval(cmd->c_expr,Null(STR***),-1);
352 match = str_true(retstr);
353 if (cmd->c_expr->arg_type == O_FLIP) /* undid itself? */
354 cmdflags = copyopt(cmd,cmd->c_expr[3].arg_ptr.arg_cmd);
357 retstr = cmd->c_stab->stab_val;
358 match = (retstr->str_cur != 0);
359 tmps = str_get(retstr);
360 tmps += retstr->str_cur - match;
361 str_set(&str_chop,tmps);
364 retstr->str_cur = tmps - retstr->str_ptr;
368 ar = cmd->c_expr[1].arg_ptr.arg_stab->stab_array;
369 match = ar->ary_index; /* just to get register */
371 if (match < 0) /* first time through here? */
372 cmd->c_short = cmd->c_stab->stab_val;
374 if (match >= ar->ary_fill) {
376 /* cmd->c_stab->stab_val = cmd->c_short; - Can't be done in LAST */
381 retstr = cmd->c_stab->stab_val = ar->ary_array[match];
382 ar->ary_index = match;
388 /* we have tried to make this normal case as abnormal as possible */
392 retstr = eval(cmd->c_expr,Null(STR***),-1);
393 match = str_true(retstr);
396 /* if flipflop was true, flop it */
399 if (match && cmdflags & CF_FLIP) {
400 if (cmd->c_expr->arg_type == O_FLOP) { /* currently toggled? */
401 retstr = eval(cmd->c_expr,Null(STR***),-1);/*let eval undo it*/
402 cmdflags = copyopt(cmd,cmd->c_expr[3].arg_ptr.arg_cmd);
405 retstr = eval(cmd->c_expr,Null(STR***),-1);/* let eval do it */
406 if (cmd->c_expr->arg_type == O_FLOP) /* still toggled? */
407 cmdflags = copyopt(cmd,cmd->c_expr[4].arg_ptr.arg_cmd);
410 else if (cmdflags & CF_FLIP) {
411 if (cmd->c_expr->arg_type == O_FLOP) { /* currently toggled? */
412 match = TRUE; /* force on */
416 /* at this point, match says whether our expression was true */
419 if (cmdflags & CF_INVERT)
421 if (!match && cmd->c_type != C_IF)
425 /* now to do the actual command, if any */
427 switch (cmd->c_type) {
429 fatal("panic: cmd_exec");
430 case C_EXPR: /* evaluated for side effects */
431 if (cmd->ucmd.acmd.ac_expr) { /* more to do? */
433 retstr = eval(cmd->ucmd.acmd.ac_expr,Null(STR***),-1);
438 oldsave = savestack->ary_fill;
444 if (cmd->ucmd.ccmd.cc_true) {
447 debname[dlevel] = 't';
448 debdelim[dlevel++] = '_';
451 retstr = cmd_exec(cmd->ucmd.ccmd.cc_true);
456 if (cmd->ucmd.ccmd.cc_alt) {
459 debname[dlevel] = 'e';
460 debdelim[dlevel++] = '_';
463 retstr = cmd_exec(cmd->ucmd.ccmd.cc_alt);
467 if (savestack->ary_fill > oldsave)
468 restorelist(oldsave);
475 if (!(cmdflags & CF_ONCE)) { /* first time through here? */
478 loop_stack[loop_ptr].loop_label = cmd->c_label;
481 deb("(Pushing label #%d %s)\n",
482 loop_ptr,cmd->c_label);
486 switch (setjmp(loop_stack[loop_ptr].loop_env)) {
490 if (savestack->ary_fill > oldsave)
491 restorelist(oldsave);
502 oldsave = savestack->ary_fill;
507 if (cmd->ucmd.ccmd.cc_true) {
510 debname[dlevel] = 't';
511 debdelim[dlevel++] = '_';
514 cmd_exec(cmd->ucmd.ccmd.cc_true);
516 /* actually, this spot is rarely reached anymore since the above
517 * cmd_exec() returns through longjmp(). Hooray for structure.
523 if (cmd->ucmd.ccmd.cc_alt) {
526 debname[dlevel] = 'a';
527 debdelim[dlevel++] = '_';
530 cmd_exec(cmd->ucmd.ccmd.cc_alt);
534 if (savestack->ary_fill > oldsave)
535 restorelist(oldsave);
537 dlevel = olddlevel - 1;
539 if (cmd->c_type != C_BLOCK)
540 goto until_loop; /* go back and evaluate conditional again */
542 if (cmdflags & CF_LOOP) {
543 cmdflags |= CF_COND; /* now test the condition */
550 if (cmdflags & CF_ONCE) {
553 deb("(Popping label #%d %s)\n",loop_ptr,
554 loop_stack[loop_ptr].loop_label);
558 if ((cmdflags & CF_OPTIMIZE) == CFT_ARRAY) {
559 cmd->c_stab->stab_val = cmd->c_short;
563 goto tail_recursion_entry;
568 deb(pat,a1,a2,a3,a4,a5,a6,a7,a8)
573 fprintf(stderr,"%-4ld",(long)line);
574 for (i=0; i<dlevel; i++)
575 fprintf(stderr,"%c%c ",debname[i],debdelim[i]);
576 fprintf(stderr,pat,a1,a2,a3,a4,a5,a6,a7,a8);
584 cmd->c_flags &= CF_ONCE|CF_COND|CF_LOOP;
585 cmd->c_flags |= which->c_flags;
586 cmd->c_short = which->c_short;
587 cmd->c_slen = which->c_slen;
588 cmd->c_stab = which->c_stab;
593 savelist(sarg,maxsarg)
600 for (i = 1; i <= maxsarg; i++) {
601 apush(savestack,sarg[i]); /* remember the pointer */
603 str_sset(str,sarg[i]);
604 apush(savestack,str); /* remember the value */
615 while (savestack->ary_fill > base) {
616 value = apop(savestack);
617 str = apop(savestack);