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