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