perl 3.0 patch #10 patch #9, continued
[p5sagit/p5-mst-13.2.git] / cmd.c
CommitLineData
afd9f252 1/* $Header: cmd.c,v 3.0.1.5 90/02/28 16:38:31 lwall Locked $
a687059c 2 *
3 * Copyright (c) 1989, Larry Wall
4 *
5 * You may distribute under the terms of the GNU General Public License
6 * as specified in the README file that comes with the perl 3.0 kit.
8d063cd8 7 *
8 * $Log: cmd.c,v $
afd9f252 9 * Revision 3.0.1.5 90/02/28 16:38:31 lwall
10 * patch9: volatilized some more variables for super-optimizing compilers
11 * patch9: nested foreach loops didn't reset inner loop on next to outer loop
12 * patch9: returned values were read from obsolete stack
13 * patch9: added sanity check on longjmp() return value
14 * patch9: substitutions that almost always succeed can corrupt label stack
15 * patch9: subs which return by both mechanisms can clobber local return data
16 *
d8f2e4cc 17 * Revision 3.0.1.4 89/12/21 19:17:41 lwall
18 * patch7: arranged for certain registers to be restored after longjmp()
19 * patch7: made nested or recursive foreach work right
20 *
0d3e774c 21 * Revision 3.0.1.3 89/11/17 15:04:36 lwall
22 * patch5: nested foreach on same array didn't work
23 *
bf38876a 24 * Revision 3.0.1.2 89/11/11 04:08:56 lwall
25 * patch2: non-BSD machines required two ^D's for <>
26 * patch2: grow_dlevel() not inside #ifdef DEBUGGING
27 *
03a14243 28 * Revision 3.0.1.1 89/10/26 23:04:21 lwall
29 * patch1: heuristically disabled optimization could cause core dump
30 *
a687059c 31 * Revision 3.0 89/10/18 15:09:02 lwall
32 * 3.0 baseline
8d063cd8 33 *
34 */
35
8d063cd8 36#include "EXTERN.h"
8d063cd8 37#include "perl.h"
38
a687059c 39#ifdef I_VARARGS
40# include <varargs.h>
41#endif
42
8d063cd8 43static STR str_chop;
44
a687059c 45void grow_dlevel();
46
d8f2e4cc 47/* do longjmps() clobber register variables? */
48
49#if defined(cray) || defined(__STDC__)
50#define JMPCLOBBER
51#endif
52
8d063cd8 53/* This is the main command loop. We try to spend as much time in this loop
54 * as possible, so lots of optimizations do their activities in here. This
55 * means things get a little sloppy.
56 */
57
a687059c 58int
d8f2e4cc 59cmd_exec(cmdparm,gimme,sp)
60CMD *VOLATILE cmdparm;
afd9f252 61VOLATILE int gimme;
62VOLATILE int sp;
8d063cd8 63{
d8f2e4cc 64 register CMD *cmd = cmdparm;
65 SPAT *VOLATILE oldspat;
afd9f252 66 VOLATILE int firstsave = savestack->ary_fill;
d8f2e4cc 67 VOLATILE int oldsave;
68 VOLATILE int aryoptsave;
8d063cd8 69#ifdef DEBUGGING
d8f2e4cc 70 VOLATILE int olddlevel;
71 VOLATILE int entdlevel;
8d063cd8 72#endif
a687059c 73 register STR *retstr = &str_undef;
8d063cd8 74 register char *tmps;
75 register int cmdflags;
378cc40b 76 register int match;
8d063cd8 77 register char *go_to = goto_targ;
a687059c 78 register int newsp = -2;
79 register STR **st = stack->ary_array;
d8f2e4cc 80 VOLATILE FILE *fp;
81 VOLATILE ARRAY *ar;
8d063cd8 82
a687059c 83 lastsize = 0;
8d063cd8 84#ifdef DEBUGGING
85 entdlevel = dlevel;
86#endif
87tail_recursion_entry:
88#ifdef DEBUGGING
89 dlevel = entdlevel;
90#endif
a687059c 91#ifdef TAINT
92 tainted = 0; /* Each statement is presumed innocent */
93#endif
94 if (cmd == Nullcmd) {
95 if (gimme == G_ARRAY && newsp > -2)
96 return newsp;
97 else {
98 st[++sp] = retstr;
99 return sp;
100 }
101 }
8d063cd8 102 cmdflags = cmd->c_flags; /* hopefully load register */
103 if (go_to) {
104 if (cmd->c_label && strEQ(go_to,cmd->c_label))
105 goto_targ = go_to = Nullch; /* here at last */
106 else {
107 switch (cmd->c_type) {
108 case C_IF:
109 oldspat = curspat;
378cc40b 110 oldsave = savestack->ary_fill;
8d063cd8 111#ifdef DEBUGGING
112 olddlevel = dlevel;
113#endif
114 retstr = &str_yes;
a687059c 115 newsp = -2;
8d063cd8 116 if (cmd->ucmd.ccmd.cc_true) {
117#ifdef DEBUGGING
378cc40b 118 if (debug) {
119 debname[dlevel] = 't';
a687059c 120 debdelim[dlevel] = '_';
121 if (++dlevel >= dlmax)
122 grow_dlevel();
378cc40b 123 }
8d063cd8 124#endif
a687059c 125 newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme,sp);
126 st = stack->ary_array; /* possibly reallocated */
127 retstr = st[newsp];
8d063cd8 128 }
a687059c 129 if (!goto_targ)
8d063cd8 130 go_to = Nullch;
a687059c 131 curspat = oldspat;
132 if (savestack->ary_fill > oldsave)
133 restorelist(oldsave);
8d063cd8 134#ifdef DEBUGGING
a687059c 135 dlevel = olddlevel;
8d063cd8 136#endif
a687059c 137 cmd = cmd->ucmd.ccmd.cc_alt;
138 goto tail_recursion_entry;
139 case C_ELSE:
140 oldspat = curspat;
141 oldsave = savestack->ary_fill;
142#ifdef DEBUGGING
143 olddlevel = dlevel;
144#endif
145 retstr = &str_undef;
146 newsp = -2;
147 if (cmd->ucmd.ccmd.cc_true) {
148#ifdef DEBUGGING
149 if (debug) {
150 debname[dlevel] = 'e';
151 debdelim[dlevel] = '_';
152 if (++dlevel >= dlmax)
153 grow_dlevel();
8d063cd8 154 }
a687059c 155#endif
156 newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme,sp);
157 st = stack->ary_array; /* possibly reallocated */
158 retstr = st[newsp];
8d063cd8 159 }
160 if (!goto_targ)
161 go_to = Nullch;
162 curspat = oldspat;
378cc40b 163 if (savestack->ary_fill > oldsave)
164 restorelist(oldsave);
8d063cd8 165#ifdef DEBUGGING
166 dlevel = olddlevel;
167#endif
168 break;
169 case C_BLOCK:
170 case C_WHILE:
171 if (!(cmdflags & CF_ONCE)) {
172 cmdflags |= CF_ONCE;
a687059c 173 if (++loop_ptr >= loop_max) {
174 loop_max += 128;
175 Renew(loop_stack, loop_max, struct loop);
176 }
8d063cd8 177 loop_stack[loop_ptr].loop_label = cmd->c_label;
a687059c 178 loop_stack[loop_ptr].loop_sp = sp;
8d063cd8 179#ifdef DEBUGGING
180 if (debug & 4) {
181 deb("(Pushing label #%d %s)\n",
a687059c 182 loop_ptr, cmd->c_label ? cmd->c_label : "");
8d063cd8 183 }
184#endif
185 }
d8f2e4cc 186#ifdef JMPCLOBBER
187 cmdparm = cmd;
188#endif
189 if (match = setjmp(loop_stack[loop_ptr].loop_env)) {
a687059c 190 st = stack->ary_array; /* possibly reallocated */
afd9f252 191#ifdef JMPCLOBBER
d8f2e4cc 192 cmd = cmdparm;
193 cmdflags = cmd->c_flags|CF_ONCE;
194#endif
afd9f252 195 if (savestack->ary_fill > oldsave)
196 restorelist(oldsave);
d8f2e4cc 197 switch (match) {
afd9f252 198 default:
199 fatal("longjmp returned bad value (%d)",match);
d8f2e4cc 200 case O_LAST: /* not done unless go_to found */
201 go_to = Nullch;
202 if (lastretstr) {
203 retstr = lastretstr;
204 newsp = -2;
205 }
206 else {
207 newsp = sp + lastsize;
208 retstr = st[newsp];
209 }
8d063cd8 210#ifdef DEBUGGING
d8f2e4cc 211 olddlevel = dlevel;
8d063cd8 212#endif
d8f2e4cc 213 curspat = oldspat;
d8f2e4cc 214 goto next_cmd;
215 case O_NEXT: /* not done unless go_to found */
216 go_to = Nullch;
217#ifdef JMPCLOBBER
218 newsp = -2;
219 retstr = &str_undef;
220#endif
221 goto next_iter;
222 case O_REDO: /* not done unless go_to found */
223 go_to = Nullch;
224#ifdef JMPCLOBBER
225 newsp = -2;
226 retstr = &str_undef;
227#endif
228 goto doit;
229 }
8d063cd8 230 }
231 oldspat = curspat;
378cc40b 232 oldsave = savestack->ary_fill;
8d063cd8 233#ifdef DEBUGGING
234 olddlevel = dlevel;
235#endif
236 if (cmd->ucmd.ccmd.cc_true) {
237#ifdef DEBUGGING
378cc40b 238 if (debug) {
239 debname[dlevel] = 't';
a687059c 240 debdelim[dlevel] = '_';
241 if (++dlevel >= dlmax)
242 grow_dlevel();
378cc40b 243 }
8d063cd8 244#endif
a687059c 245 newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme,sp);
246 st = stack->ary_array; /* possibly reallocated */
247 retstr = st[newsp];
8d063cd8 248 }
249 if (!goto_targ) {
250 go_to = Nullch;
251 goto next_iter;
252 }
253#ifdef DEBUGGING
254 dlevel = olddlevel;
255#endif
256 if (cmd->ucmd.ccmd.cc_alt) {
257#ifdef DEBUGGING
378cc40b 258 if (debug) {
259 debname[dlevel] = 'a';
a687059c 260 debdelim[dlevel] = '_';
261 if (++dlevel >= dlmax)
262 grow_dlevel();
378cc40b 263 }
8d063cd8 264#endif
a687059c 265 newsp = cmd_exec(cmd->ucmd.ccmd.cc_alt,gimme,sp);
266 st = stack->ary_array; /* possibly reallocated */
267 retstr = st[newsp];
8d063cd8 268 }
269 if (goto_targ)
270 break;
271 go_to = Nullch;
272 goto finish_while;
273 }
274 cmd = cmd->c_next;
378cc40b 275 if (cmd && cmd->c_head == cmd)
276 /* reached end of while loop */
a687059c 277 return sp; /* targ isn't in this block */
378cc40b 278 if (cmdflags & CF_ONCE) {
279#ifdef DEBUGGING
280 if (debug & 4) {
a687059c 281 tmps = loop_stack[loop_ptr].loop_label;
378cc40b 282 deb("(Popping label #%d %s)\n",loop_ptr,
a687059c 283 tmps ? tmps : "" );
378cc40b 284 }
285#endif
286 loop_ptr--;
287 }
8d063cd8 288 goto tail_recursion_entry;
289 }
290 }
291
292until_loop:
293
378cc40b 294 /* Set line number so run-time errors can be located */
295
296 line = cmd->c_line;
297
8d063cd8 298#ifdef DEBUGGING
378cc40b 299 if (debug) {
300 if (debug & 2) {
301 deb("%s (%lx) r%lx t%lx a%lx n%lx cs%lx\n",
302 cmdname[cmd->c_type],cmd,cmd->c_expr,
303 cmd->ucmd.ccmd.cc_true,cmd->ucmd.ccmd.cc_alt,cmd->c_next,
304 curspat);
305 }
306 debname[dlevel] = cmdname[cmd->c_type][0];
a687059c 307 debdelim[dlevel] = '!';
308 if (++dlevel >= dlmax)
309 grow_dlevel();
8d063cd8 310 }
8d063cd8 311#endif
8d063cd8 312
313 /* Here is some common optimization */
314
315 if (cmdflags & CF_COND) {
316 switch (cmdflags & CF_OPTIMIZE) {
317
318 case CFT_FALSE:
378cc40b 319 retstr = cmd->c_short;
a687059c 320 newsp = -2;
8d063cd8 321 match = FALSE;
322 if (cmdflags & CF_NESURE)
323 goto maybe;
324 break;
325 case CFT_TRUE:
378cc40b 326 retstr = cmd->c_short;
a687059c 327 newsp = -2;
8d063cd8 328 match = TRUE;
329 if (cmdflags & CF_EQSURE)
330 goto flipmaybe;
331 break;
332
333 case CFT_REG:
334 retstr = STAB_STR(cmd->c_stab);
a687059c 335 newsp = -2;
8d063cd8 336 match = str_true(retstr); /* => retstr = retstr, c2 should fix */
337 if (cmdflags & (match ? CF_EQSURE : CF_NESURE))
338 goto flipmaybe;
339 break;
340
341 case CFT_ANCHOR: /* /^pat/ optimization */
342 if (multiline) {
378cc40b 343 if (*cmd->c_short->str_ptr && !(cmdflags & CF_EQSURE))
8d063cd8 344 goto scanner; /* just unanchor it */
345 else
346 break; /* must evaluate */
347 }
348 /* FALL THROUGH */
349 case CFT_STROP: /* string op optimization */
350 retstr = STAB_STR(cmd->c_stab);
a687059c 351 newsp = -2;
352#ifndef I286
378cc40b 353 if (*cmd->c_short->str_ptr == *str_get(retstr) &&
a687059c 354 bcmp(cmd->c_short->str_ptr, str_get(retstr),
355 cmd->c_slen) == 0 ) {
8d063cd8 356 if (cmdflags & CF_EQSURE) {
a687059c 357 if (sawampersand && (cmdflags & CF_OPTIMIZE) != CFT_STROP) {
358 curspat = Nullspat;
359 if (leftstab)
360 str_nset(stab_val(leftstab),"",0);
361 if (amperstab)
362 str_sset(stab_val(amperstab),cmd->c_short);
363 if (rightstab)
364 str_nset(stab_val(rightstab),
365 retstr->str_ptr + cmd->c_slen,
366 retstr->str_cur - cmd->c_slen);
367 }
8d063cd8 368 match = !(cmdflags & CF_FIRSTNEG);
369 retstr = &str_yes;
370 goto flipmaybe;
371 }
372 }
373 else if (cmdflags & CF_NESURE) {
374 match = cmdflags & CF_FIRSTNEG;
375 retstr = &str_no;
376 goto flipmaybe;
377 }
a687059c 378#else
379 {
380 char *zap1, *zap2, zap1c, zap2c;
381 int zaplen;
382
383 zap1 = cmd->c_short->str_ptr;
384 zap2 = str_get(retstr);
385 zap1c = *zap1;
386 zap2c = *zap2;
387 zaplen = cmd->c_slen;
388 if ((zap1c == zap2c) && (bcmp(zap1, zap2, zaplen) == 0)) {
389 if (cmdflags & CF_EQSURE) {
390 if (sawampersand &&
391 (cmdflags & CF_OPTIMIZE) != CFT_STROP) {
392 curspat = Nullspat;
393 if (leftstab)
394 str_nset(stab_val(leftstab),"",0);
395 if (amperstab)
396 str_sset(stab_val(amperstab),cmd->c_short);
397 if (rightstab)
398 str_nset(stab_val(rightstab),
399 retstr->str_ptr + cmd->c_slen,
400 retstr->str_cur - cmd->c_slen);
401 }
402 match = !(cmdflags & CF_FIRSTNEG);
403 retstr = &str_yes;
404 goto flipmaybe;
405 }
406 }
407 else if (cmdflags & CF_NESURE) {
408 match = cmdflags & CF_FIRSTNEG;
409 retstr = &str_no;
410 goto flipmaybe;
411 }
412 }
413#endif
8d063cd8 414 break; /* must evaluate */
415
416 case CFT_SCAN: /* non-anchored search */
417 scanner:
418 retstr = STAB_STR(cmd->c_stab);
a687059c 419 newsp = -2;
420 if (retstr->str_pok & SP_STUDIED)
378cc40b 421 if (screamfirst[cmd->c_short->str_rare] >= 0)
422 tmps = screaminstr(retstr, cmd->c_short);
423 else
424 tmps = Nullch;
425 else {
426 tmps = str_get(retstr); /* make sure it's pok */
a687059c 427#ifndef lint
428 tmps = fbminstr((unsigned char*)tmps,
429 (unsigned char*)tmps + retstr->str_cur, cmd->c_short);
430#endif
378cc40b 431 }
432 if (tmps) {
8d063cd8 433 if (cmdflags & CF_EQSURE) {
a687059c 434 ++cmd->c_short->str_u.str_useful;
435 if (sawampersand) {
436 curspat = Nullspat;
437 if (leftstab)
438 str_nset(stab_val(leftstab),retstr->str_ptr,
439 tmps - retstr->str_ptr);
440 if (amperstab)
441 str_sset(stab_val(amperstab),cmd->c_short);
442 if (rightstab)
443 str_nset(stab_val(rightstab),
444 tmps + cmd->c_short->str_cur,
445 retstr->str_cur - (tmps - retstr->str_ptr) -
446 cmd->c_short->str_cur);
447 }
8d063cd8 448 match = !(cmdflags & CF_FIRSTNEG);
449 retstr = &str_yes;
450 goto flipmaybe;
451 }
378cc40b 452 else
453 hint = tmps;
454 }
455 else {
456 if (cmdflags & CF_NESURE) {
a687059c 457 ++cmd->c_short->str_u.str_useful;
378cc40b 458 match = cmdflags & CF_FIRSTNEG;
459 retstr = &str_no;
460 goto flipmaybe;
461 }
462 }
a687059c 463 if (--cmd->c_short->str_u.str_useful < 0) {
afd9f252 464 cmdflags &= ~(CF_OPTIMIZE|CF_ONCE);
378cc40b 465 cmdflags |= CFT_EVAL; /* never try this optimization again */
466 cmd->c_flags = cmdflags;
467 }
468 break; /* must evaluate */
469
470 case CFT_NUMOP: /* numeric op optimization */
471 retstr = STAB_STR(cmd->c_stab);
a687059c 472 newsp = -2;
378cc40b 473 switch (cmd->c_slen) {
474 case O_EQ:
a687059c 475 if (dowarn) {
476 if ((!retstr->str_nok && !looks_like_number(retstr)))
477 warn("Possible use of == on string value");
478 }
479 match = (str_gnum(retstr) == cmd->c_short->str_u.str_nval);
378cc40b 480 break;
481 case O_NE:
a687059c 482 match = (str_gnum(retstr) != cmd->c_short->str_u.str_nval);
378cc40b 483 break;
484 case O_LT:
a687059c 485 match = (str_gnum(retstr) < cmd->c_short->str_u.str_nval);
378cc40b 486 break;
487 case O_LE:
a687059c 488 match = (str_gnum(retstr) <= cmd->c_short->str_u.str_nval);
378cc40b 489 break;
490 case O_GT:
a687059c 491 match = (str_gnum(retstr) > cmd->c_short->str_u.str_nval);
378cc40b 492 break;
493 case O_GE:
a687059c 494 match = (str_gnum(retstr) >= cmd->c_short->str_u.str_nval);
378cc40b 495 break;
496 }
497 if (match) {
498 if (cmdflags & CF_EQSURE) {
499 retstr = &str_yes;
500 goto flipmaybe;
501 }
8d063cd8 502 }
503 else if (cmdflags & CF_NESURE) {
8d063cd8 504 retstr = &str_no;
505 goto flipmaybe;
506 }
507 break; /* must evaluate */
508
378cc40b 509 case CFT_INDGETS: /* while (<$foo>) */
510 last_in_stab = stabent(str_get(STAB_STR(cmd->c_stab)),TRUE);
a687059c 511 if (!stab_io(last_in_stab))
512 stab_io(last_in_stab) = stio_new();
378cc40b 513 goto dogets;
8d063cd8 514 case CFT_GETS: /* really a while (<file>) */
515 last_in_stab = cmd->c_stab;
378cc40b 516 dogets:
a687059c 517 fp = stab_io(last_in_stab)->ifp;
518 retstr = stab_val(defstab);
519 newsp = -2;
bf38876a 520 keepgoing:
a687059c 521 if (fp && str_gets(retstr, fp, 0)) {
522 if (*retstr->str_ptr == '0' && retstr->str_cur == 1)
378cc40b 523 match = FALSE;
524 else
525 match = TRUE;
a687059c 526 stab_io(last_in_stab)->lines++;
8d063cd8 527 }
bf38876a 528 else if (stab_io(last_in_stab)->flags & IOF_ARGV) {
529 if (!fp)
530 goto doeval; /* first time through */
531 fp = nextargv(last_in_stab);
532 if (fp)
533 goto keepgoing;
534 (void)do_close(last_in_stab,FALSE);
535 stab_io(last_in_stab)->flags |= IOF_START;
536 retstr = &str_undef;
537 match = FALSE;
538 }
8d063cd8 539 else {
a687059c 540 retstr = &str_undef;
8d063cd8 541 match = FALSE;
542 }
543 goto flipmaybe;
544 case CFT_EVAL:
545 break;
546 case CFT_UNFLIP:
a687059c 547 while (tmps_max > tmps_base) /* clean up after last eval */
548 str_free(tmps_list[tmps_max--]);
549 newsp = eval(cmd->c_expr,gimme && (cmdflags & CF_TERM),sp);
550 st = stack->ary_array; /* possibly reallocated */
551 retstr = st[newsp];
8d063cd8 552 match = str_true(retstr);
553 if (cmd->c_expr->arg_type == O_FLIP) /* undid itself? */
554 cmdflags = copyopt(cmd,cmd->c_expr[3].arg_ptr.arg_cmd);
555 goto maybe;
556 case CFT_CHOP:
a687059c 557 retstr = stab_val(cmd->c_stab);
558 newsp = -2;
8d063cd8 559 match = (retstr->str_cur != 0);
560 tmps = str_get(retstr);
561 tmps += retstr->str_cur - match;
a687059c 562 str_nset(&str_chop,tmps,match);
8d063cd8 563 *tmps = '\0';
564 retstr->str_nok = 0;
565 retstr->str_cur = tmps - retstr->str_ptr;
566 retstr = &str_chop;
567 goto flipmaybe;
378cc40b 568 case CFT_ARRAY:
0d3e774c 569 match = cmd->c_short->str_u.str_useful; /* just to get register */
378cc40b 570
a687059c 571 if (match < 0) { /* first time through here? */
0d3e774c 572 ar = stab_array(cmd->c_expr[1].arg_ptr.arg_stab);
a687059c 573 aryoptsave = savestack->ary_fill;
574 savesptr(&stab_val(cmd->c_stab));
0d3e774c 575 savelong(&cmd->c_short->str_u.str_useful);
a687059c 576 }
afd9f252 577 else {
0d3e774c 578 ar = stab_xarray(cmd->c_expr[1].arg_ptr.arg_stab);
afd9f252 579 if (cmd->c_type != C_WHILE && savestack->ary_fill > firstsave)
580 restorelist(firstsave);
581 }
378cc40b 582
a687059c 583 if (match >= ar->ary_fill) { /* we're in LAST, probably */
584 retstr = &str_undef;
0d3e774c 585 cmd->c_short->str_u.str_useful = -1; /* actually redundant */
378cc40b 586 match = FALSE;
587 }
588 else {
589 match++;
a687059c 590 retstr = stab_val(cmd->c_stab) = ar->ary_array[match];
0d3e774c 591 cmd->c_short->str_u.str_useful = match;
378cc40b 592 match = TRUE;
593 }
a687059c 594 newsp = -2;
378cc40b 595 goto maybe;
8d063cd8 596 }
597
598 /* we have tried to make this normal case as abnormal as possible */
599
600 doeval:
a687059c 601 if (gimme == G_ARRAY) {
602 lastretstr = Nullstr;
603 lastspbase = sp;
604 lastsize = newsp - sp;
605 }
606 else
607 lastretstr = retstr;
608 while (tmps_max > tmps_base) /* clean up after last eval */
609 str_free(tmps_list[tmps_max--]);
610 newsp = eval(cmd->c_expr,gimme && (cmdflags & CF_TERM),sp);
611 st = stack->ary_array; /* possibly reallocated */
612 retstr = st[newsp];
d8f2e4cc 613 if (newsp > sp && retstr)
a687059c 614 match = str_true(retstr);
615 else
616 match = FALSE;
8d063cd8 617 goto maybe;
618
619 /* if flipflop was true, flop it */
620
621 flipmaybe:
622 if (match && cmdflags & CF_FLIP) {
a687059c 623 while (tmps_max > tmps_base) /* clean up after last eval */
624 str_free(tmps_list[tmps_max--]);
8d063cd8 625 if (cmd->c_expr->arg_type == O_FLOP) { /* currently toggled? */
a687059c 626 newsp = eval(cmd->c_expr,G_SCALAR,sp);/*let eval undo it*/
8d063cd8 627 cmdflags = copyopt(cmd,cmd->c_expr[3].arg_ptr.arg_cmd);
628 }
629 else {
a687059c 630 newsp = eval(cmd->c_expr,G_SCALAR,sp);/* let eval do it */
8d063cd8 631 if (cmd->c_expr->arg_type == O_FLOP) /* still toggled? */
632 cmdflags = copyopt(cmd,cmd->c_expr[4].arg_ptr.arg_cmd);
633 }
634 }
635 else if (cmdflags & CF_FLIP) {
636 if (cmd->c_expr->arg_type == O_FLOP) { /* currently toggled? */
637 match = TRUE; /* force on */
638 }
639 }
640
641 /* at this point, match says whether our expression was true */
642
643 maybe:
644 if (cmdflags & CF_INVERT)
645 match = !match;
a687059c 646 if (!match)
378cc40b 647 goto next_cmd;
8d063cd8 648 }
a687059c 649#ifdef TAINT
650 tainted = 0; /* modifier doesn't affect regular expression */
651#endif
8d063cd8 652
653 /* now to do the actual command, if any */
654
655 switch (cmd->c_type) {
656 case C_NULL:
378cc40b 657 fatal("panic: cmd_exec");
8d063cd8 658 case C_EXPR: /* evaluated for side effects */
659 if (cmd->ucmd.acmd.ac_expr) { /* more to do? */
a687059c 660 if (gimme == G_ARRAY) {
661 lastretstr = Nullstr;
662 lastspbase = sp;
663 lastsize = newsp - sp;
664 }
665 else
666 lastretstr = retstr;
667 while (tmps_max > tmps_base) /* clean up after last eval */
668 str_free(tmps_list[tmps_max--]);
669 newsp = eval(cmd->ucmd.acmd.ac_expr,gimme && (cmdflags&CF_TERM),sp);
670 st = stack->ary_array; /* possibly reallocated */
671 retstr = st[newsp];
8d063cd8 672 }
673 break;
a687059c 674 case C_NSWITCH:
675 match = (int)str_gnum(STAB_STR(cmd->c_stab));
676 goto doswitch;
677 case C_CSWITCH:
678 match = *(str_get(STAB_STR(cmd->c_stab))) & 255;
679 doswitch:
680 match -= cmd->ucmd.scmd.sc_offset;
681 if (match < 0)
682 match = 0;
683 else if (match > cmd->ucmd.scmd.sc_max)
684 match = cmd->c_slen;
685 cmd = cmd->ucmd.scmd.sc_next[match];
686 goto tail_recursion_entry;
687 case C_NEXT:
688 cmd = cmd->ucmd.ccmd.cc_alt;
689 goto tail_recursion_entry;
690 case C_ELSIF:
691 fatal("panic: ELSIF");
8d063cd8 692 case C_IF:
693 oldspat = curspat;
378cc40b 694 oldsave = savestack->ary_fill;
8d063cd8 695#ifdef DEBUGGING
696 olddlevel = dlevel;
697#endif
a687059c 698 retstr = &str_yes;
699 newsp = -2;
700 if (cmd->ucmd.ccmd.cc_true) {
8d063cd8 701#ifdef DEBUGGING
a687059c 702 if (debug) {
703 debname[dlevel] = 't';
704 debdelim[dlevel] = '_';
705 if (++dlevel >= dlmax)
706 grow_dlevel();
8d063cd8 707 }
a687059c 708#endif
709 newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme,sp);
710 st = stack->ary_array; /* possibly reallocated */
711 retstr = st[newsp];
8d063cd8 712 }
a687059c 713 curspat = oldspat;
714 if (savestack->ary_fill > oldsave)
715 restorelist(oldsave);
8d063cd8 716#ifdef DEBUGGING
a687059c 717 dlevel = olddlevel;
8d063cd8 718#endif
a687059c 719 cmd = cmd->ucmd.ccmd.cc_alt;
720 goto tail_recursion_entry;
721 case C_ELSE:
722 oldspat = curspat;
723 oldsave = savestack->ary_fill;
724#ifdef DEBUGGING
725 olddlevel = dlevel;
726#endif
727 retstr = &str_undef;
728 newsp = -2;
729 if (cmd->ucmd.ccmd.cc_true) {
730#ifdef DEBUGGING
731 if (debug) {
732 debname[dlevel] = 'e';
733 debdelim[dlevel] = '_';
734 if (++dlevel >= dlmax)
735 grow_dlevel();
8d063cd8 736 }
a687059c 737#endif
738 newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme,sp);
739 st = stack->ary_array; /* possibly reallocated */
740 retstr = st[newsp];
8d063cd8 741 }
742 curspat = oldspat;
378cc40b 743 if (savestack->ary_fill > oldsave)
744 restorelist(oldsave);
8d063cd8 745#ifdef DEBUGGING
746 dlevel = olddlevel;
747#endif
748 break;
749 case C_BLOCK:
750 case C_WHILE:
751 if (!(cmdflags & CF_ONCE)) { /* first time through here? */
752 cmdflags |= CF_ONCE;
a687059c 753 if (++loop_ptr >= loop_max) {
754 loop_max += 128;
755 Renew(loop_stack, loop_max, struct loop);
756 }
8d063cd8 757 loop_stack[loop_ptr].loop_label = cmd->c_label;
a687059c 758 loop_stack[loop_ptr].loop_sp = sp;
8d063cd8 759#ifdef DEBUGGING
760 if (debug & 4) {
761 deb("(Pushing label #%d %s)\n",
a687059c 762 loop_ptr, cmd->c_label ? cmd->c_label : "");
8d063cd8 763 }
764#endif
765 }
d8f2e4cc 766#ifdef JMPCLOBBER
767 cmdparm = cmd;
768#endif
769 if (match = setjmp(loop_stack[loop_ptr].loop_env)) {
a687059c 770 st = stack->ary_array; /* possibly reallocated */
afd9f252 771#ifdef JMPCLOBBER
d8f2e4cc 772 cmd = cmdparm;
773 cmdflags = cmd->c_flags|CF_ONCE;
774 go_to = goto_targ;
775#endif
afd9f252 776 if (savestack->ary_fill > oldsave)
777 restorelist(oldsave);
d8f2e4cc 778 switch (match) {
afd9f252 779 default:
780 fatal("longjmp returned bad value (%d)",match);
d8f2e4cc 781 case O_LAST:
782 if (lastretstr) {
783 retstr = lastretstr;
784 newsp = -2;
785 }
786 else {
787 newsp = sp + lastsize;
788 retstr = st[newsp];
789 }
790 curspat = oldspat;
d8f2e4cc 791 goto next_cmd;
792 case O_NEXT:
793#ifdef JMPCLOBBER
a687059c 794 newsp = -2;
d8f2e4cc 795 retstr = &str_undef;
796#endif
797 goto next_iter;
798 case O_REDO:
36ce8bec 799#ifdef DEBUGGING
d8f2e4cc 800 dlevel = olddlevel;
36ce8bec 801#endif
d8f2e4cc 802#ifdef JMPCLOBBER
803 newsp = -2;
804 retstr = &str_undef;
805#endif
806 goto doit;
807 }
8d063cd8 808 }
809 oldspat = curspat;
378cc40b 810 oldsave = savestack->ary_fill;
8d063cd8 811#ifdef DEBUGGING
812 olddlevel = dlevel;
813#endif
814 doit:
815 if (cmd->ucmd.ccmd.cc_true) {
816#ifdef DEBUGGING
378cc40b 817 if (debug) {
818 debname[dlevel] = 't';
a687059c 819 debdelim[dlevel] = '_';
820 if (++dlevel >= dlmax)
821 grow_dlevel();
378cc40b 822 }
8d063cd8 823#endif
a687059c 824 newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme,sp);
825 st = stack->ary_array; /* possibly reallocated */
826 retstr = st[newsp];
8d063cd8 827 }
378cc40b 828 /* actually, this spot is rarely reached anymore since the above
8d063cd8 829 * cmd_exec() returns through longjmp(). Hooray for structure.
830 */
831 next_iter:
832#ifdef DEBUGGING
833 dlevel = olddlevel;
834#endif
835 if (cmd->ucmd.ccmd.cc_alt) {
836#ifdef DEBUGGING
378cc40b 837 if (debug) {
838 debname[dlevel] = 'a';
a687059c 839 debdelim[dlevel] = '_';
840 if (++dlevel >= dlmax)
841 grow_dlevel();
378cc40b 842 }
8d063cd8 843#endif
a687059c 844 newsp = cmd_exec(cmd->ucmd.ccmd.cc_alt,gimme,sp);
845 st = stack->ary_array; /* possibly reallocated */
846 retstr = st[newsp];
8d063cd8 847 }
848 finish_while:
849 curspat = oldspat;
afd9f252 850 if (savestack->ary_fill > oldsave) {
851 if (cmdflags & CF_TERM) {
852 for (match = sp + 1; match <= newsp; match++)
853 st[match] = str_static(st[match]);
854 retstr = st[newsp];
855 }
378cc40b 856 restorelist(oldsave);
afd9f252 857 }
8d063cd8 858#ifdef DEBUGGING
859 dlevel = olddlevel - 1;
860#endif
861 if (cmd->c_type != C_BLOCK)
862 goto until_loop; /* go back and evaluate conditional again */
863 }
864 if (cmdflags & CF_LOOP) {
865 cmdflags |= CF_COND; /* now test the condition */
378cc40b 866#ifdef DEBUGGING
867 dlevel = entdlevel;
868#endif
8d063cd8 869 goto until_loop;
870 }
378cc40b 871 next_cmd:
872 if (cmdflags & CF_ONCE) {
873#ifdef DEBUGGING
874 if (debug & 4) {
a687059c 875 tmps = loop_stack[loop_ptr].loop_label;
876 deb("(Popping label #%d %s)\n",loop_ptr, tmps ? tmps : "");
378cc40b 877 }
878#endif
879 loop_ptr--;
afd9f252 880 if ((cmdflags & CF_OPTIMIZE) == CFT_ARRAY &&
881 savestack->ary_fill > aryoptsave)
a687059c 882 restorelist(aryoptsave);
378cc40b 883 }
8d063cd8 884 cmd = cmd->c_next;
885 goto tail_recursion_entry;
886}
887
888#ifdef DEBUGGING
a687059c 889# ifndef VARARGS
8d063cd8 890/*VARARGS1*/
891deb(pat,a1,a2,a3,a4,a5,a6,a7,a8)
892char *pat;
893{
894 register int i;
895
378cc40b 896 fprintf(stderr,"%-4ld",(long)line);
8d063cd8 897 for (i=0; i<dlevel; i++)
898 fprintf(stderr,"%c%c ",debname[i],debdelim[i]);
899 fprintf(stderr,pat,a1,a2,a3,a4,a5,a6,a7,a8);
900}
a687059c 901# else
902/*VARARGS1*/
903deb(va_alist)
904va_dcl
905{
906 va_list args;
907 char *pat;
908 register int i;
909
910 va_start(args);
911 fprintf(stderr,"%-4ld",(long)line);
912 for (i=0; i<dlevel; i++)
913 fprintf(stderr,"%c%c ",debname[i],debdelim[i]);
914
915 pat = va_arg(args, char *);
916 (void) vfprintf(stderr,pat,args);
917 va_end( args );
918}
919# endif
8d063cd8 920#endif
921
922copyopt(cmd,which)
923register CMD *cmd;
924register CMD *which;
925{
926 cmd->c_flags &= CF_ONCE|CF_COND|CF_LOOP;
927 cmd->c_flags |= which->c_flags;
378cc40b 928 cmd->c_short = which->c_short;
929 cmd->c_slen = which->c_slen;
8d063cd8 930 cmd->c_stab = which->c_stab;
931 return cmd->c_flags;
932}
378cc40b 933
a687059c 934ARRAY *
935saveary(stab)
936STAB *stab;
937{
938 register STR *str;
939
940 str = Str_new(10,0);
941 str->str_state = SS_SARY;
942 str->str_u.str_stab = stab;
943 if (str->str_ptr) {
944 Safefree(str->str_ptr);
945 str->str_len = 0;
946 }
947 str->str_ptr = (char*)stab_array(stab);
948 (void)apush(savestack,str); /* save array ptr */
949 stab_xarray(stab) = Null(ARRAY*);
950 return stab_xarray(aadd(stab));
951}
952
953HASH *
954savehash(stab)
955STAB *stab;
956{
957 register STR *str;
958
959 str = Str_new(11,0);
960 str->str_state = SS_SHASH;
961 str->str_u.str_stab = stab;
962 if (str->str_ptr) {
963 Safefree(str->str_ptr);
964 str->str_len = 0;
965 }
966 str->str_ptr = (char*)stab_hash(stab);
967 (void)apush(savestack,str); /* save hash ptr */
968 stab_xhash(stab) = Null(HASH*);
969 return stab_xhash(hadd(stab));
970}
971
972void
973saveitem(item)
974register STR *item;
975{
976 register STR *str;
977
978 (void)apush(savestack,item); /* remember the pointer */
979 str = Str_new(12,0);
980 str_sset(str,item);
981 (void)apush(savestack,str); /* remember the value */
982}
983
984void
985saveint(intp)
986int *intp;
987{
988 register STR *str;
989
990 str = Str_new(13,0);
991 str->str_state = SS_SINT;
992 str->str_u.str_useful = (long)*intp; /* remember value */
993 if (str->str_ptr) {
994 Safefree(str->str_ptr);
995 str->str_len = 0;
996 }
997 str->str_ptr = (char*)intp; /* remember pointer */
998 (void)apush(savestack,str);
999}
1000
1001void
1002savelong(longp)
1003long *longp;
1004{
1005 register STR *str;
1006
1007 str = Str_new(14,0);
1008 str->str_state = SS_SLONG;
1009 str->str_u.str_useful = *longp; /* remember value */
1010 if (str->str_ptr) {
1011 Safefree(str->str_ptr);
1012 str->str_len = 0;
1013 }
1014 str->str_ptr = (char*)longp; /* remember pointer */
1015 (void)apush(savestack,str);
1016}
1017
1018void
1019savesptr(sptr)
1020STR **sptr;
1021{
1022 register STR *str;
1023
1024 str = Str_new(15,0);
1025 str->str_state = SS_SSTRP;
1026 str->str_magic = *sptr; /* remember value */
1027 if (str->str_ptr) {
1028 Safefree(str->str_ptr);
1029 str->str_len = 0;
1030 }
1031 str->str_ptr = (char*)sptr; /* remember pointer */
1032 (void)apush(savestack,str);
1033}
1034
1035void
1036savenostab(stab)
1037STAB *stab;
1038{
1039 register STR *str;
1040
1041 str = Str_new(16,0);
1042 str->str_state = SS_SNSTAB;
1043 str->str_magic = (STR*)stab; /* remember which stab to free */
1044 (void)apush(savestack,str);
1045}
1046
1047void
1048savehptr(hptr)
1049HASH **hptr;
1050{
1051 register STR *str;
1052
1053 str = Str_new(17,0);
1054 str->str_state = SS_SHPTR;
1055 str->str_u.str_hash = *hptr; /* remember value */
1056 if (str->str_ptr) {
1057 Safefree(str->str_ptr);
1058 str->str_len = 0;
1059 }
1060 str->str_ptr = (char*)hptr; /* remember pointer */
1061 (void)apush(savestack,str);
1062}
1063
378cc40b 1064void
1065savelist(sarg,maxsarg)
1066register STR **sarg;
1067int maxsarg;
1068{
1069 register STR *str;
1070 register int i;
1071
1072 for (i = 1; i <= maxsarg; i++) {
a687059c 1073 (void)apush(savestack,sarg[i]); /* remember the pointer */
1074 str = Str_new(18,0);
378cc40b 1075 str_sset(str,sarg[i]);
a687059c 1076 (void)apush(savestack,str); /* remember the value */
d8f2e4cc 1077 sarg[i]->str_u.str_useful = -1;
378cc40b 1078 }
1079}
1080
1081void
1082restorelist(base)
1083int base;
1084{
1085 register STR *str;
1086 register STR *value;
a687059c 1087 register STAB *stab;
378cc40b 1088
a687059c 1089 if (base < -1)
1090 fatal("panic: corrupt saved stack index");
378cc40b 1091 while (savestack->ary_fill > base) {
1092 value = apop(savestack);
a687059c 1093 switch (value->str_state) {
1094 case SS_NORM: /* normal string */
1095 case SS_INCR:
1096 str = apop(savestack);
1097 str_replace(str,value);
1098 STABSET(str);
1099 break;
1100 case SS_SARY: /* array reference */
1101 stab = value->str_u.str_stab;
1102 afree(stab_xarray(stab));
1103 stab_xarray(stab) = (ARRAY*)value->str_ptr;
1104 value->str_ptr = Nullch;
1105 str_free(value);
1106 break;
1107 case SS_SHASH: /* hash reference */
1108 stab = value->str_u.str_stab;
1109 (void)hfree(stab_xhash(stab));
1110 stab_xhash(stab) = (HASH*)value->str_ptr;
1111 value->str_ptr = Nullch;
1112 str_free(value);
1113 break;
1114 case SS_SINT: /* int reference */
1115 *((int*)value->str_ptr) = (int)value->str_u.str_useful;
1116 value->str_ptr = Nullch;
1117 str_free(value);
1118 break;
1119 case SS_SLONG: /* long reference */
1120 *((long*)value->str_ptr) = value->str_u.str_useful;
1121 value->str_ptr = Nullch;
1122 str_free(value);
1123 break;
1124 case SS_SSTRP: /* STR* reference */
1125 *((STR**)value->str_ptr) = value->str_magic;
1126 value->str_magic = Nullstr;
1127 value->str_ptr = Nullch;
1128 str_free(value);
1129 break;
1130 case SS_SHPTR: /* HASH* reference */
1131 *((HASH**)value->str_ptr) = value->str_u.str_hash;
1132 value->str_ptr = Nullch;
1133 str_free(value);
1134 break;
1135 case SS_SNSTAB:
1136 stab = (STAB*)value->str_magic;
1137 value->str_magic = Nullstr;
1138 (void)stab_clear(stab);
1139 str_free(value);
1140 break;
1141 default:
1142 fatal("panic: restorelist inconsistency");
1143 }
378cc40b 1144 }
1145}
a687059c 1146
bf38876a 1147#ifdef DEBUGGING
a687059c 1148void
1149grow_dlevel()
1150{
1151 dlmax += 128;
1152 Renew(debname, dlmax, char);
1153 Renew(debdelim, dlmax, char);
1154}
bf38876a 1155#endif