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