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