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