1 /* $Header: cmd.c,v 1.0.1.1 88/01/21 21:24:16 root Exp $
4 * Revision 1.0.1.1 88/01/21 21:24:16 root
5 * The redo cmd got a segmentation fault because trace context stack overflowed.
7 * Revision 1.0 87/12/18 13:04:51 root
20 /* This is the main command loop. We try to spend as much time in this loop
21 * as possible, so lots of optimizations do their activities in here. This
22 * means things get a little sloppy.
36 register int cmdflags;
38 register char *go_to = goto_targ;
52 cmdflags = cmd->c_flags; /* hopefully load register */
54 if (cmd->c_label && strEQ(go_to,cmd->c_label))
55 goto_targ = go_to = Nullch; /* here at last */
57 switch (cmd->c_type) {
64 if (cmd->ucmd.ccmd.cc_true) {
66 debname[dlevel] = 't';
67 debdelim[dlevel++] = '_';
69 retstr = cmd_exec(cmd->ucmd.ccmd.cc_true);
75 if (cmd->ucmd.ccmd.cc_alt) {
77 debname[dlevel] = 'e';
78 debdelim[dlevel++] = '_';
80 retstr = cmd_exec(cmd->ucmd.ccmd.cc_alt);
92 if (!(cmdflags & CF_ONCE)) {
95 loop_stack[loop_ptr].loop_label = cmd->c_label;
98 deb("(Pushing label #%d %s)\n",
99 loop_ptr,cmd->c_label);
103 switch (setjmp(loop_stack[loop_ptr].loop_env)) {
104 case O_LAST: /* not done unless go_to found */
113 deb("(Popping label #%d %s)\n",loop_ptr,
114 loop_stack[loop_ptr].loop_label);
119 goto tail_recursion_entry;
120 case O_NEXT: /* not done unless go_to found */
123 case O_REDO: /* not done unless go_to found */
131 if (cmd->ucmd.ccmd.cc_true) {
133 debname[dlevel] = 't';
134 debdelim[dlevel++] = '_';
136 cmd_exec(cmd->ucmd.ccmd.cc_true);
145 if (cmd->ucmd.ccmd.cc_alt) {
147 debname[dlevel] = 'a';
148 debdelim[dlevel++] = '_';
150 cmd_exec(cmd->ucmd.ccmd.cc_alt);
158 if (cmd && cmd->c_head == cmd) /* reached end of while loop */
159 return retstr; /* targ isn't in this block */
160 goto tail_recursion_entry;
168 deb("%s (%lx) r%lx t%lx a%lx n%lx cs%lx\n",
169 cmdname[cmd->c_type],cmd,cmd->c_expr,
170 cmd->ucmd.ccmd.cc_true,cmd->ucmd.ccmd.cc_alt,cmd->c_next,curspat);
172 debname[dlevel] = cmdname[cmd->c_type][0];
173 debdelim[dlevel++] = '!';
175 while (tmps_max >= 0) /* clean up after last eval */
176 str_free(tmps_list[tmps_max--]);
178 /* Here is some common optimization */
180 if (cmdflags & CF_COND) {
181 switch (cmdflags & CF_OPTIMIZE) {
184 retstr = cmd->c_first;
186 if (cmdflags & CF_NESURE)
190 retstr = cmd->c_first;
192 if (cmdflags & CF_EQSURE)
197 retstr = STAB_STR(cmd->c_stab);
198 match = str_true(retstr); /* => retstr = retstr, c2 should fix */
199 if (cmdflags & (match ? CF_EQSURE : CF_NESURE))
203 case CFT_ANCHOR: /* /^pat/ optimization */
205 if (*cmd->c_first->str_ptr && !(cmdflags & CF_EQSURE))
206 goto scanner; /* just unanchor it */
208 break; /* must evaluate */
211 case CFT_STROP: /* string op optimization */
212 retstr = STAB_STR(cmd->c_stab);
213 if (*cmd->c_first->str_ptr == *str_get(retstr) &&
214 strnEQ(cmd->c_first->str_ptr, str_get(retstr),
216 if (cmdflags & CF_EQSURE) {
217 match = !(cmdflags & CF_FIRSTNEG);
222 else if (cmdflags & CF_NESURE) {
223 match = cmdflags & CF_FIRSTNEG;
227 break; /* must evaluate */
229 case CFT_SCAN: /* non-anchored search */
231 retstr = STAB_STR(cmd->c_stab);
232 if (instr(str_get(retstr),cmd->c_first->str_ptr)) {
233 if (cmdflags & CF_EQSURE) {
234 match = !(cmdflags & CF_FIRSTNEG);
239 else if (cmdflags & CF_NESURE) {
240 match = cmdflags & CF_FIRSTNEG;
244 break; /* must evaluate */
246 case CFT_GETS: /* really a while (<file>) */
247 last_in_stab = cmd->c_stab;
248 fp = last_in_stab->stab_io->fp;
249 retstr = defstab->stab_val;
250 if (fp && str_gets(retstr, fp)) {
251 last_in_stab->stab_io->lines++;
254 else if (last_in_stab->stab_io->flags & IOF_ARGV)
255 goto doeval; /* doesn't necessarily count as EOF yet */
264 retstr = eval(cmd->c_expr,Null(char***));
265 match = str_true(retstr);
266 if (cmd->c_expr->arg_type == O_FLIP) /* undid itself? */
267 cmdflags = copyopt(cmd,cmd->c_expr[3].arg_ptr.arg_cmd);
270 retstr = cmd->c_stab->stab_val;
271 match = (retstr->str_cur != 0);
272 tmps = str_get(retstr);
273 tmps += retstr->str_cur - match;
274 str_set(&str_chop,tmps);
277 retstr->str_cur = tmps - retstr->str_ptr;
282 /* we have tried to make this normal case as abnormal as possible */
285 retstr = eval(cmd->c_expr,Null(char***));
286 match = str_true(retstr);
289 /* if flipflop was true, flop it */
292 if (match && cmdflags & CF_FLIP) {
293 if (cmd->c_expr->arg_type == O_FLOP) { /* currently toggled? */
294 retstr = eval(cmd->c_expr,Null(char***)); /* let eval undo it */
295 cmdflags = copyopt(cmd,cmd->c_expr[3].arg_ptr.arg_cmd);
298 retstr = eval(cmd->c_expr,Null(char***)); /* let eval do it */
299 if (cmd->c_expr->arg_type == O_FLOP) /* still toggled? */
300 cmdflags = copyopt(cmd,cmd->c_expr[4].arg_ptr.arg_cmd);
303 else if (cmdflags & CF_FLIP) {
304 if (cmd->c_expr->arg_type == O_FLOP) { /* currently toggled? */
305 match = TRUE; /* force on */
309 /* at this point, match says whether our expression was true */
312 if (cmdflags & CF_INVERT)
314 if (!match && cmd->c_type != C_IF) {
316 goto tail_recursion_entry;
320 /* now to do the actual command, if any */
322 switch (cmd->c_type) {
324 fatal("panic: cmd_exec\n");
325 case C_EXPR: /* evaluated for side effects */
326 if (cmd->ucmd.acmd.ac_expr) { /* more to do? */
327 retstr = eval(cmd->ucmd.acmd.ac_expr,Null(char***));
337 if (cmd->ucmd.ccmd.cc_true) {
339 debname[dlevel] = 't';
340 debdelim[dlevel++] = '_';
342 retstr = cmd_exec(cmd->ucmd.ccmd.cc_true);
347 if (cmd->ucmd.ccmd.cc_alt) {
349 debname[dlevel] = 'e';
350 debdelim[dlevel++] = '_';
352 retstr = cmd_exec(cmd->ucmd.ccmd.cc_alt);
362 if (!(cmdflags & CF_ONCE)) { /* first time through here? */
365 loop_stack[loop_ptr].loop_label = cmd->c_label;
368 deb("(Pushing label #%d %s)\n",
369 loop_ptr,cmd->c_label);
373 switch (setjmp(loop_stack[loop_ptr].loop_env)) {
379 deb("(Popping label #%d %s)\n",loop_ptr,
380 loop_stack[loop_ptr].loop_label);
385 goto tail_recursion_entry;
399 if (cmd->ucmd.ccmd.cc_true) {
401 debname[dlevel] = 't';
402 debdelim[dlevel++] = '_';
404 cmd_exec(cmd->ucmd.ccmd.cc_true);
406 /* actually, this spot is never reached anymore since the above
407 * cmd_exec() returns through longjmp(). Hooray for structure.
413 if (cmd->ucmd.ccmd.cc_alt) {
415 debname[dlevel] = 'a';
416 debdelim[dlevel++] = '_';
418 cmd_exec(cmd->ucmd.ccmd.cc_alt);
423 dlevel = olddlevel - 1;
425 if (cmd->c_type != C_BLOCK)
426 goto until_loop; /* go back and evaluate conditional again */
428 if (cmdflags & CF_LOOP) {
429 cmdflags |= CF_COND; /* now test the condition */
433 goto tail_recursion_entry;
438 deb(pat,a1,a2,a3,a4,a5,a6,a7,a8)
443 for (i=0; i<dlevel; i++)
444 fprintf(stderr,"%c%c ",debname[i],debdelim[i]);
445 fprintf(stderr,pat,a1,a2,a3,a4,a5,a6,a7,a8);
453 cmd->c_flags &= CF_ONCE|CF_COND|CF_LOOP;
454 cmd->c_flags |= which->c_flags;
455 cmd->c_first = which->c_first;
456 cmd->c_flen = which->c_flen;
457 cmd->c_stab = which->c_stab;