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