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