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