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