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