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