perl 3.0 patch #41 (combined patch)
[p5sagit/p5-mst-13.2.git] / cons.c
CommitLineData
5303340c 1/* $Header: cons.c,v 3.0.1.9 90/11/10 01:10:50 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.
7 *
8 * $Log: cons.c,v $
5303340c 9 * Revision 3.0.1.9 90/11/10 01:10:50 lwall
10 * patch38: random cleanup
11 *
39c3038c 12 * Revision 3.0.1.8 90/10/15 15:41:09 lwall
13 * patch29: added caller
14 * patch29: scripts now run at almost full speed under the debugger
15 * patch29: the debugger now understands packages and evals
16 * patch29: package behavior is now more consistent
17 *
ff8e2863 18 * Revision 3.0.1.7 90/08/09 02:35:52 lwall
19 * patch19: did preliminary work toward debugging packages and evals
20 * patch19: Added support for linked-in C subroutines
21 * patch19: Numeric literals are now stored only in floating point
22 * patch19: Added -c switch to do compilation only
23 *
0f85fab0 24 * Revision 3.0.1.6 90/03/27 15:35:21 lwall
25 * patch16: formats didn't work inside eval
26 * patch16: $foo++ now optimized to ++$foo where value not required
27 *
ff2452de 28 * Revision 3.0.1.5 90/03/12 16:23:10 lwall
29 * patch13: perl -d coredumped on scripts with subs that did explicit return
30 *
afd9f252 31 * Revision 3.0.1.4 90/02/28 16:44:00 lwall
32 * patch9: subs which return by both mechanisms can clobber local return data
33 * patch9: changed internal SUB label to _SUB_
34 * patch9: line numbers were bogus during certain portions of foreach evaluation
35 *
663a0e37 36 * Revision 3.0.1.3 89/12/21 19:20:25 lwall
37 * patch7: made nested or recursive foreach work right
38 *
0d3e774c 39 * Revision 3.0.1.2 89/11/17 15:08:53 lwall
40 * patch5: nested foreach on same array didn't work
41 *
03a14243 42 * Revision 3.0.1.1 89/10/26 23:09:01 lwall
43 * patch1: numeric switch optimization was broken
44 * patch1: unless was broken when run under the debugger
45 *
a687059c 46 * Revision 3.0 89/10/18 15:10:23 lwall
47 * 3.0 baseline
48 *
49 */
50
51#include "EXTERN.h"
52#include "perl.h"
53#include "perly.h"
54
55extern char *tokename[];
56extern int yychar;
57
58static int cmd_tosave();
59static int arg_tosave();
60static int spat_tosave();
61
62static bool saw_return;
63
64SUBR *
65make_sub(name,cmd)
66char *name;
67CMD *cmd;
68{
69 register SUBR *sub;
70 STAB *stab = stabent(name,TRUE);
71
72 Newz(101,sub,1,SUBR);
73 if (stab_sub(stab)) {
74 if (dowarn) {
ff8e2863 75 CMD *oldcurcmd = curcmd;
a687059c 76
77 if (cmd)
ff8e2863 78 curcmd = cmd;
a687059c 79 warn("Subroutine %s redefined",name);
ff8e2863 80 curcmd = oldcurcmd;
81 }
82 if (stab_sub(stab)->cmd) {
83 cmd_free(stab_sub(stab)->cmd);
84 afree(stab_sub(stab)->tosave);
a687059c 85 }
a687059c 86 Safefree(stab_sub(stab));
87 }
39c3038c 88 sub->filestab = curcmd->c_filestab;
a687059c 89 saw_return = FALSE;
90 tosave = anew(Nullstab);
91 tosave->ary_fill = 0; /* make 1 based */
92 (void)cmd_tosave(cmd,FALSE); /* this builds the tosave array */
93 sub->tosave = tosave;
94 if (saw_return) {
95 struct compcmd mycompblock;
96
97 mycompblock.comp_true = cmd;
98 mycompblock.comp_alt = Nullcmd;
afd9f252 99 cmd = add_label(savestr("_SUB_"),make_ccmd(C_BLOCK,Nullarg,mycompblock));
a687059c 100 saw_return = FALSE;
ff2452de 101 cmd->c_flags |= CF_TERM;
a687059c 102 }
103 sub->cmd = cmd;
104 stab_sub(stab) = sub;
105 if (perldb) {
39c3038c 106 STR *str;
107 STR *tmpstr = str_static(&str_undef);
a687059c 108
39c3038c 109 sprintf(buf,"%s:%ld",stab_val(curcmd->c_filestab)->str_ptr,
110 (long)subline);
111 str = str_make(buf,0);
a687059c 112 str_cat(str,"-");
ff8e2863 113 sprintf(buf,"%ld",(long)curcmd->c_line);
a687059c 114 str_cat(str,buf);
115 name = str_get(subname);
39c3038c 116 stab_fullname(tmpstr,stab);
117 hstore(stab_xhash(DBsub), tmpstr->str_ptr, tmpstr->str_cur, str, 0);
a687059c 118 str_set(subname,"main");
119 }
120 subline = 0;
121 return sub;
122}
123
ff8e2863 124SUBR *
125make_usub(name, ix, subaddr, filename)
126char *name;
127int ix;
128int (*subaddr)();
129char *filename;
130{
131 register SUBR *sub;
132 STAB *stab = stabent(name,allstabs);
133
134 if (!stab) /* unused function */
135 return;
136 Newz(101,sub,1,SUBR);
137 if (stab_sub(stab)) {
138 if (dowarn)
139 warn("Subroutine %s redefined",name);
140 if (stab_sub(stab)->cmd) {
141 cmd_free(stab_sub(stab)->cmd);
142 afree(stab_sub(stab)->tosave);
143 }
144 Safefree(stab_sub(stab));
145 }
39c3038c 146 sub->filestab = fstab(filename);
ff8e2863 147 sub->usersub = subaddr;
148 sub->userindex = ix;
149 stab_sub(stab) = sub;
150 return sub;
151}
152
0f85fab0 153make_form(stab,fcmd)
154STAB *stab;
155FCMD *fcmd;
156{
157 if (stab_form(stab)) {
158 FCMD *tmpfcmd;
159 FCMD *nextfcmd;
160
161 for (tmpfcmd = stab_form(stab); tmpfcmd; tmpfcmd = nextfcmd) {
162 nextfcmd = tmpfcmd->f_next;
163 if (tmpfcmd->f_expr)
164 arg_free(tmpfcmd->f_expr);
165 if (tmpfcmd->f_unparsed)
166 str_free(tmpfcmd->f_unparsed);
167 if (tmpfcmd->f_pre)
168 Safefree(tmpfcmd->f_pre);
169 Safefree(tmpfcmd);
170 }
171 }
172 stab_form(stab) = fcmd;
173}
174
a687059c 175CMD *
176block_head(tail)
177register CMD *tail;
178{
179 CMD *head;
180 register int opt;
181 register int last_opt = 0;
182 register STAB *last_stab = Nullstab;
183 register int count = 0;
184 register CMD *switchbeg = Nullcmd;
185
186 if (tail == Nullcmd) {
187 return tail;
188 }
189 head = tail->c_head;
190
191 for (tail = head; tail; tail = tail->c_next) {
192
193 /* save one measly dereference at runtime */
194 if (tail->c_type == C_IF) {
195 if (!(tail->ucmd.ccmd.cc_alt = tail->ucmd.ccmd.cc_alt->c_next))
196 tail->c_flags |= CF_TERM;
197 }
198 else if (tail->c_type == C_EXPR) {
199 ARG *arg;
200
201 if (tail->ucmd.acmd.ac_expr)
202 arg = tail->ucmd.acmd.ac_expr;
203 else
204 arg = tail->c_expr;
205 if (arg) {
206 if (arg->arg_type == O_RETURN)
207 tail->c_flags |= CF_TERM;
208 else if (arg->arg_type == O_ITEM && arg[1].arg_type == A_CMD)
209 tail->c_flags |= CF_TERM;
210 }
211 }
212 if (!tail->c_next)
213 tail->c_flags |= CF_TERM;
214
215 if (tail->c_expr && (tail->c_flags & CF_OPTIMIZE) == CFT_FALSE)
216 opt_arg(tail,1, tail->c_type == C_EXPR);
217
218 /* now do a little optimization on case-ish structures */
219 switch(tail->c_flags & (CF_OPTIMIZE|CF_FIRSTNEG|CF_INVERT)) {
220 case CFT_ANCHOR:
221 if (stabent("*",FALSE)) { /* bad assumption here!!! */
222 opt = 0;
223 break;
224 }
225 /* FALL THROUGH */
226 case CFT_STROP:
227 opt = (tail->c_flags & CF_NESURE) ? CFT_STROP : 0;
228 break;
229 case CFT_CCLASS:
230 opt = CFT_STROP;
231 break;
232 case CFT_NUMOP:
233 opt = (tail->c_slen == O_NE ? 0 : CFT_NUMOP);
234 if ((tail->c_flags&(CF_NESURE|CF_EQSURE)) != (CF_NESURE|CF_EQSURE))
235 opt = 0;
236 break;
237 default:
238 opt = 0;
239 }
240 if (opt && opt == last_opt && tail->c_stab == last_stab)
241 count++;
242 else {
243 if (count >= 3) { /* is this the breakeven point? */
244 if (last_opt == CFT_NUMOP)
245 make_nswitch(switchbeg,count);
246 else
247 make_cswitch(switchbeg,count);
248 }
249 if (opt) {
250 count = 1;
251 switchbeg = tail;
252 }
253 else
254 count = 0;
255 }
256 last_opt = opt;
257 last_stab = tail->c_stab;
258 }
259 if (count >= 3) { /* is this the breakeven point? */
260 if (last_opt == CFT_NUMOP)
261 make_nswitch(switchbeg,count);
262 else
263 make_cswitch(switchbeg,count);
264 }
265 return head;
266}
267
268/* We've spotted a sequence of CMDs that all test the value of the same
269 * spat. Thus we can insert a SWITCH in front and jump directly
270 * to the correct one.
271 */
272make_cswitch(head,count)
273register CMD *head;
274int count;
275{
276 register CMD *cur;
277 register CMD **loc;
278 register int i;
279 register int min = 255;
280 register int max = 0;
281
282 /* make a new head in the exact same spot */
283 New(102,cur, 1, CMD);
284#ifdef STRUCTCOPY
285 *cur = *head;
286#else
287 Copy(head,cur,1,CMD);
288#endif
289 Zero(head,1,CMD);
290 head->c_type = C_CSWITCH;
291 head->c_next = cur; /* insert new cmd at front of list */
292 head->c_stab = cur->c_stab;
293
294 Newz(103,loc,258,CMD*);
295 loc++; /* lie a little */
296 while (count--) {
297 if ((cur->c_flags & CF_OPTIMIZE) == CFT_CCLASS) {
298 for (i = 0; i <= 255; i++) {
299 if (!loc[i] && cur->c_short->str_ptr[i>>3] & (1 << (i&7))) {
300 loc[i] = cur;
301 if (i < min)
302 min = i;
303 if (i > max)
304 max = i;
305 }
306 }
307 }
308 else {
309 i = *cur->c_short->str_ptr & 255;
310 if (!loc[i]) {
311 loc[i] = cur;
312 if (i < min)
313 min = i;
314 if (i > max)
315 max = i;
316 }
317 }
318 cur = cur->c_next;
319 }
320 max++;
321 if (min > 0)
322 Copy(&loc[min],&loc[0], max - min, CMD*);
323 loc--;
324 min--;
325 max -= min;
326 for (i = 0; i <= max; i++)
327 if (!loc[i])
328 loc[i] = cur;
329 Renew(loc,max+1,CMD*); /* chop it down to size */
330 head->ucmd.scmd.sc_offset = min;
331 head->ucmd.scmd.sc_max = max;
332 head->ucmd.scmd.sc_next = loc;
333}
334
335make_nswitch(head,count)
336register CMD *head;
337int count;
338{
339 register CMD *cur = head;
340 register CMD **loc;
341 register int i;
342 register int min = 32767;
343 register int max = -32768;
344 int origcount = count;
345 double value; /* or your money back! */
346 short changed; /* so triple your money back! */
347
348 while (count--) {
349 i = (int)str_gnum(cur->c_short);
350 value = (double)i;
351 if (value != cur->c_short->str_u.str_nval)
352 return; /* fractional values--just forget it */
353 changed = i;
354 if (changed != i)
355 return; /* too big for a short */
356 if (cur->c_slen == O_LE)
357 i++;
358 else if (cur->c_slen == O_GE) /* we only do < or > here */
359 i--;
360 if (i < min)
361 min = i;
362 if (i > max)
363 max = i;
364 cur = cur->c_next;
365 }
366 count = origcount;
367 if (max - min > count * 2 + 10) /* too sparse? */
368 return;
369
370 /* now make a new head in the exact same spot */
371 New(104,cur, 1, CMD);
372#ifdef STRUCTCOPY
373 *cur = *head;
374#else
375 Copy(head,cur,1,CMD);
376#endif
377 Zero(head,1,CMD);
378 head->c_type = C_NSWITCH;
379 head->c_next = cur; /* insert new cmd at front of list */
380 head->c_stab = cur->c_stab;
381
382 Newz(105,loc, max - min + 3, CMD*);
383 loc++;
03a14243 384 max -= min;
385 max++;
a687059c 386 while (count--) {
387 i = (int)str_gnum(cur->c_short);
388 i -= min;
a687059c 389 switch(cur->c_slen) {
390 case O_LE:
391 i++;
392 case O_LT:
393 for (i--; i >= -1; i--)
394 if (!loc[i])
395 loc[i] = cur;
396 break;
397 case O_GE:
398 i--;
399 case O_GT:
400 for (i++; i <= max; i++)
401 if (!loc[i])
402 loc[i] = cur;
403 break;
404 case O_EQ:
405 if (!loc[i])
406 loc[i] = cur;
407 break;
408 }
409 cur = cur->c_next;
410 }
411 loc--;
412 min--;
03a14243 413 max++;
a687059c 414 for (i = 0; i <= max; i++)
415 if (!loc[i])
416 loc[i] = cur;
417 head->ucmd.scmd.sc_offset = min;
418 head->ucmd.scmd.sc_max = max;
419 head->ucmd.scmd.sc_next = loc;
420}
421
422CMD *
423append_line(head,tail)
424register CMD *head;
425register CMD *tail;
426{
427 if (tail == Nullcmd)
428 return head;
429 if (!tail->c_head) /* make sure tail is well formed */
430 tail->c_head = tail;
431 if (head != Nullcmd) {
432 tail = tail->c_head; /* get to start of tail list */
433 if (!head->c_head)
434 head->c_head = head; /* start a new head list */
435 while (head->c_next) {
436 head->c_next->c_head = head->c_head;
437 head = head->c_next; /* get to end of head list */
438 }
439 head->c_next = tail; /* link to end of old list */
440 tail->c_head = head->c_head; /* propagate head pointer */
441 }
442 while (tail->c_next) {
443 tail->c_next->c_head = tail->c_head;
444 tail = tail->c_next;
445 }
446 return tail;
447}
448
449CMD *
450dodb(cur)
451CMD *cur;
452{
453 register CMD *cmd;
454 register CMD *head = cur->c_head;
a687059c 455 STR *str;
456
457 if (!head)
458 head = cur;
459 if (!head->c_line)
460 return cur;
39c3038c 461 str = afetch(stab_xarray(curcmd->c_filestab),(int)head->c_line,FALSE);
462 if (str == &str_undef || str->str_nok)
a687059c 463 return cur;
464 str->str_u.str_nval = (double)head->c_line;
465 str->str_nok = 1;
466 Newz(106,cmd,1,CMD);
39c3038c 467 str_magic(str, curcmd->c_filestab, 0, Nullch, 0);
468 str->str_magic->str_u.str_cmd = cmd;
a687059c 469 cmd->c_type = C_EXPR;
470 cmd->ucmd.acmd.ac_stab = Nullstab;
471 cmd->ucmd.acmd.ac_expr = Nullarg;
39c3038c 472 cmd->c_expr = make_op(O_SUBR, 1,
a687059c 473 stab2arg(A_WORD,DBstab),
39c3038c 474 Nullarg,
a687059c 475 Nullarg);
39c3038c 476 cmd->c_flags |= CF_COND|CF_DBSUB|CFT_D0;
a687059c 477 cmd->c_line = head->c_line;
478 cmd->c_label = head->c_label;
39c3038c 479 cmd->c_filestab = curcmd->c_filestab;
480 cmd->c_stash = curstash;
a687059c 481 return append_line(cmd, cur);
482}
483
484CMD *
485make_acmd(type,stab,cond,arg)
486int type;
487STAB *stab;
488ARG *cond;
489ARG *arg;
490{
491 register CMD *cmd;
492
493 Newz(107,cmd,1,CMD);
494 cmd->c_type = type;
495 cmd->ucmd.acmd.ac_stab = stab;
496 cmd->ucmd.acmd.ac_expr = arg;
497 cmd->c_expr = cond;
498 if (cond)
499 cmd->c_flags |= CF_COND;
afd9f252 500 if (cmdline == NOLINE)
ff8e2863 501 cmd->c_line = curcmd->c_line;
afd9f252 502 else {
a687059c 503 cmd->c_line = cmdline;
504 cmdline = NOLINE;
505 }
39c3038c 506 cmd->c_filestab = curcmd->c_filestab;
507 cmd->c_stash = curstash;
a687059c 508 if (perldb)
509 cmd = dodb(cmd);
510 return cmd;
511}
512
513CMD *
514make_ccmd(type,arg,cblock)
515int type;
516ARG *arg;
517struct compcmd cblock;
518{
519 register CMD *cmd;
520
521 Newz(108,cmd, 1, CMD);
522 cmd->c_type = type;
523 cmd->c_expr = arg;
524 cmd->ucmd.ccmd.cc_true = cblock.comp_true;
525 cmd->ucmd.ccmd.cc_alt = cblock.comp_alt;
526 if (arg)
527 cmd->c_flags |= CF_COND;
afd9f252 528 if (cmdline == NOLINE)
ff8e2863 529 cmd->c_line = curcmd->c_line;
afd9f252 530 else {
a687059c 531 cmd->c_line = cmdline;
532 cmdline = NOLINE;
533 }
39c3038c 534 cmd->c_filestab = curcmd->c_filestab;
535 cmd->c_stash = curstash;
a687059c 536 if (perldb)
537 cmd = dodb(cmd);
538 return cmd;
539}
540
541CMD *
542make_icmd(type,arg,cblock)
543int type;
544ARG *arg;
545struct compcmd cblock;
546{
547 register CMD *cmd;
548 register CMD *alt;
549 register CMD *cur;
550 register CMD *head;
551 struct compcmd ncblock;
552
553 Newz(109,cmd, 1, CMD);
554 head = cmd;
555 cmd->c_type = type;
556 cmd->c_expr = arg;
557 cmd->ucmd.ccmd.cc_true = cblock.comp_true;
558 cmd->ucmd.ccmd.cc_alt = cblock.comp_alt;
559 if (arg)
560 cmd->c_flags |= CF_COND;
afd9f252 561 if (cmdline == NOLINE)
ff8e2863 562 cmd->c_line = curcmd->c_line;
afd9f252 563 else {
a687059c 564 cmd->c_line = cmdline;
565 cmdline = NOLINE;
566 }
39c3038c 567 cmd->c_filestab = curcmd->c_filestab;
568 cmd->c_stash = curstash;
a687059c 569 cur = cmd;
570 alt = cblock.comp_alt;
571 while (alt && alt->c_type == C_ELSIF) {
572 cur = alt;
573 alt = alt->ucmd.ccmd.cc_alt;
574 }
575 if (alt) { /* a real life ELSE at the end? */
576 ncblock.comp_true = alt;
577 ncblock.comp_alt = Nullcmd;
578 alt = append_line(cur,make_ccmd(C_ELSE,Nullarg,ncblock));
579 cur->ucmd.ccmd.cc_alt = alt;
580 }
581 else
582 alt = cur; /* no ELSE, so cur is proxy ELSE */
583
584 cur = cmd;
585 while (cmd) { /* now point everyone at the ELSE */
586 cur = cmd;
587 cmd = cur->ucmd.ccmd.cc_alt;
588 cur->c_head = head;
589 if (cur->c_type == C_ELSIF)
590 cur->c_type = C_IF;
591 if (cur->c_type == C_IF)
592 cur->ucmd.ccmd.cc_alt = alt;
593 if (cur == alt)
594 break;
595 cur->c_next = cmd;
596 }
597 if (perldb)
598 cur = dodb(cur);
599 return cur;
600}
601
602void
603opt_arg(cmd,fliporflop,acmd)
604register CMD *cmd;
605int fliporflop;
606int acmd;
607{
608 register ARG *arg;
609 int opt = CFT_EVAL;
610 int sure = 0;
611 ARG *arg2;
612 int context = 0; /* 0 = normal, 1 = before &&, 2 = before || */
613 int flp = fliporflop;
614
615 if (!cmd)
616 return;
617 if (!(arg = cmd->c_expr)) {
618 cmd->c_flags &= ~CF_COND;
619 return;
620 }
621
622 /* Can we turn && and || into if and unless? */
623
624 if (acmd && !cmd->ucmd.acmd.ac_expr && !(cmd->c_flags & CF_TERM) &&
625 (arg->arg_type == O_AND || arg->arg_type == O_OR) ) {
626 dehoist(arg,1);
627 arg[2].arg_type &= A_MASK; /* don't suppress eval */
628 dehoist(arg,2);
629 cmd->ucmd.acmd.ac_expr = arg[2].arg_ptr.arg_arg;
630 cmd->c_expr = arg[1].arg_ptr.arg_arg;
631 if (arg->arg_type == O_OR)
632 cmd->c_flags ^= CF_INVERT; /* || is like unless */
633 arg->arg_len = 0;
634 free_arg(arg);
635 arg = cmd->c_expr;
636 }
637
638 /* Turn "if (!expr)" into "unless (expr)" */
639
640 if (!(cmd->c_flags & CF_TERM)) { /* unless return value wanted */
641 while (arg->arg_type == O_NOT) {
642 dehoist(arg,1);
643 cmd->c_flags ^= CF_INVERT; /* flip sense of cmd */
644 cmd->c_expr = arg[1].arg_ptr.arg_arg; /* hoist the rest of expr */
645 free_arg(arg);
646 arg = cmd->c_expr; /* here we go again */
647 }
648 }
649
650 if (!arg->arg_len) { /* sanity check */
651 cmd->c_flags |= opt;
652 return;
653 }
654
655 /* for "cond .. cond" we set up for the initial check */
656
657 if (arg->arg_type == O_FLIP)
658 context |= 4;
659
660 /* for "cond && expr" and "cond || expr" we can ignore expr, sort of */
661
662 morecontext:
663 if (arg->arg_type == O_AND)
664 context |= 1;
665 else if (arg->arg_type == O_OR)
666 context |= 2;
667 if (context && (arg[flp].arg_type & A_MASK) == A_EXPR) {
668 arg = arg[flp].arg_ptr.arg_arg;
669 flp = 1;
670 if (arg->arg_type == O_AND || arg->arg_type == O_OR)
671 goto morecontext;
672 }
673 if ((context & 3) == 3)
674 return;
675
676 if (arg[flp].arg_flags & (AF_PRE|AF_POST)) {
677 cmd->c_flags |= opt;
0f85fab0 678 if (acmd && !cmd->ucmd.acmd.ac_expr && !(cmd->c_flags & CF_TERM)) {
679 arg[flp].arg_flags &= ~AF_POST; /* prefer ++$foo to $foo++ */
680 arg[flp].arg_flags |= AF_PRE; /* if value not wanted */
681 }
a687059c 682 return; /* side effect, can't optimize */
683 }
684
685 if (arg->arg_type == O_ITEM || arg->arg_type == O_FLIP ||
686 arg->arg_type == O_AND || arg->arg_type == O_OR) {
687 if ((arg[flp].arg_type & A_MASK) == A_SINGLE) {
688 opt = (str_true(arg[flp].arg_ptr.arg_str) ? CFT_TRUE : CFT_FALSE);
689 cmd->c_short = str_smake(arg[flp].arg_ptr.arg_str);
690 goto literal;
691 }
692 else if ((arg[flp].arg_type & A_MASK) == A_STAB ||
693 (arg[flp].arg_type & A_MASK) == A_LVAL) {
694 cmd->c_stab = arg[flp].arg_ptr.arg_stab;
695 opt = CFT_REG;
696 literal:
697 if (!context) { /* no && or ||? */
698 free_arg(arg);
699 cmd->c_expr = Nullarg;
700 }
701 if (!(context & 1))
702 cmd->c_flags |= CF_EQSURE;
703 if (!(context & 2))
704 cmd->c_flags |= CF_NESURE;
705 }
706 }
707 else if (arg->arg_type == O_MATCH || arg->arg_type == O_SUBST ||
708 arg->arg_type == O_NMATCH || arg->arg_type == O_NSUBST) {
709 if ((arg[1].arg_type == A_STAB || arg[1].arg_type == A_LVAL) &&
710 (arg[2].arg_type & A_MASK) == A_SPAT &&
711 arg[2].arg_ptr.arg_spat->spat_short ) {
712 cmd->c_stab = arg[1].arg_ptr.arg_stab;
713 cmd->c_short = str_smake(arg[2].arg_ptr.arg_spat->spat_short);
714 cmd->c_slen = arg[2].arg_ptr.arg_spat->spat_slen;
715 if (arg[2].arg_ptr.arg_spat->spat_flags & SPAT_ALL &&
716 !(arg[2].arg_ptr.arg_spat->spat_flags & SPAT_ONCE) &&
717 (arg->arg_type == O_MATCH || arg->arg_type == O_NMATCH) )
718 sure |= CF_EQSURE; /* (SUBST must be forced even */
719 /* if we know it will work.) */
720 if (arg->arg_type != O_SUBST) {
721 arg[2].arg_ptr.arg_spat->spat_short = Nullstr;
722 arg[2].arg_ptr.arg_spat->spat_slen = 0; /* only one chk */
723 }
724 sure |= CF_NESURE; /* normally only sure if it fails */
725 if (arg->arg_type == O_NMATCH || arg->arg_type == O_NSUBST)
726 cmd->c_flags |= CF_FIRSTNEG;
727 if (context & 1) { /* only sure if thing is false */
728 if (cmd->c_flags & CF_FIRSTNEG)
729 sure &= ~CF_NESURE;
730 else
731 sure &= ~CF_EQSURE;
732 }
733 else if (context & 2) { /* only sure if thing is true */
734 if (cmd->c_flags & CF_FIRSTNEG)
735 sure &= ~CF_EQSURE;
736 else
737 sure &= ~CF_NESURE;
738 }
739 if (sure & (CF_EQSURE|CF_NESURE)) { /* if we know anything*/
740 if (arg[2].arg_ptr.arg_spat->spat_flags & SPAT_SCANFIRST)
741 opt = CFT_SCAN;
742 else
743 opt = CFT_ANCHOR;
744 if (sure == (CF_EQSURE|CF_NESURE) /* really sure? */
745 && arg->arg_type == O_MATCH
746 && context & 4
747 && fliporflop == 1) {
748 spat_free(arg[2].arg_ptr.arg_spat);
749 arg[2].arg_ptr.arg_spat = Nullspat; /* don't do twice */
750 }
751 cmd->c_flags |= sure;
752 }
753 }
754 }
755 else if (arg->arg_type == O_SEQ || arg->arg_type == O_SNE ||
756 arg->arg_type == O_SLT || arg->arg_type == O_SGT) {
757 if (arg[1].arg_type == A_STAB || arg[1].arg_type == A_LVAL) {
758 if (arg[2].arg_type == A_SINGLE) {
ff8e2863 759 char *junk = str_get(arg[2].arg_ptr.arg_str);
760
a687059c 761 cmd->c_stab = arg[1].arg_ptr.arg_stab;
762 cmd->c_short = str_smake(arg[2].arg_ptr.arg_str);
763 cmd->c_slen = cmd->c_short->str_cur+1;
764 switch (arg->arg_type) {
765 case O_SLT: case O_SGT:
766 sure |= CF_EQSURE;
767 cmd->c_flags |= CF_FIRSTNEG;
768 break;
769 case O_SNE:
770 cmd->c_flags |= CF_FIRSTNEG;
771 /* FALL THROUGH */
772 case O_SEQ:
773 sure |= CF_NESURE|CF_EQSURE;
774 break;
775 }
776 if (context & 1) { /* only sure if thing is false */
777 if (cmd->c_flags & CF_FIRSTNEG)
778 sure &= ~CF_NESURE;
779 else
780 sure &= ~CF_EQSURE;
781 }
782 else if (context & 2) { /* only sure if thing is true */
783 if (cmd->c_flags & CF_FIRSTNEG)
784 sure &= ~CF_EQSURE;
785 else
786 sure &= ~CF_NESURE;
787 }
788 if (sure & (CF_EQSURE|CF_NESURE)) {
789 opt = CFT_STROP;
790 cmd->c_flags |= sure;
791 }
792 }
793 }
794 }
795 else if (arg->arg_type == O_EQ || arg->arg_type == O_NE ||
796 arg->arg_type == O_LE || arg->arg_type == O_GE ||
797 arg->arg_type == O_LT || arg->arg_type == O_GT) {
798 if (arg[1].arg_type == A_STAB || arg[1].arg_type == A_LVAL) {
799 if (arg[2].arg_type == A_SINGLE) {
800 cmd->c_stab = arg[1].arg_ptr.arg_stab;
801 if (dowarn) {
802 STR *str = arg[2].arg_ptr.arg_str;
803
804 if ((!str->str_nok && !looks_like_number(str)))
805 warn("Possible use of == on string value");
806 }
807 cmd->c_short = str_nmake(str_gnum(arg[2].arg_ptr.arg_str));
808 cmd->c_slen = arg->arg_type;
809 sure |= CF_NESURE|CF_EQSURE;
810 if (context & 1) { /* only sure if thing is false */
811 sure &= ~CF_EQSURE;
812 }
813 else if (context & 2) { /* only sure if thing is true */
814 sure &= ~CF_NESURE;
815 }
816 if (sure & (CF_EQSURE|CF_NESURE)) {
817 opt = CFT_NUMOP;
818 cmd->c_flags |= sure;
819 }
820 }
821 }
822 }
823 else if (arg->arg_type == O_ASSIGN &&
824 (arg[1].arg_type == A_STAB || arg[1].arg_type == A_LVAL) &&
825 arg[1].arg_ptr.arg_stab == defstab &&
826 arg[2].arg_type == A_EXPR ) {
827 arg2 = arg[2].arg_ptr.arg_arg;
828 if (arg2->arg_type == O_ITEM && arg2[1].arg_type == A_READ) {
829 opt = CFT_GETS;
830 cmd->c_stab = arg2[1].arg_ptr.arg_stab;
831 if (!(stab_io(arg2[1].arg_ptr.arg_stab)->flags & IOF_ARGV)) {
832 free_arg(arg2);
833 free_arg(arg);
834 cmd->c_expr = Nullarg;
835 }
836 }
837 }
838 else if (arg->arg_type == O_CHOP &&
839 (arg[1].arg_type == A_STAB || arg[1].arg_type == A_LVAL) ) {
840 opt = CFT_CHOP;
841 cmd->c_stab = arg[1].arg_ptr.arg_stab;
842 free_arg(arg);
843 cmd->c_expr = Nullarg;
844 }
845 if (context & 4)
846 opt |= CF_FLIP;
847 cmd->c_flags |= opt;
848
849 if (cmd->c_flags & CF_FLIP) {
850 if (fliporflop == 1) {
851 arg = cmd->c_expr; /* get back to O_FLIP arg */
852 New(110,arg[3].arg_ptr.arg_cmd, 1, CMD);
853 Copy(cmd, arg[3].arg_ptr.arg_cmd, 1, CMD);
854 New(111,arg[4].arg_ptr.arg_cmd,1,CMD);
855 Copy(cmd, arg[4].arg_ptr.arg_cmd, 1, CMD);
856 opt_arg(arg[4].arg_ptr.arg_cmd,2,acmd);
857 arg->arg_len = 2; /* this is a lie */
858 }
859 else {
860 if ((opt & CF_OPTIMIZE) == CFT_EVAL)
861 cmd->c_flags = (cmd->c_flags & ~CF_OPTIMIZE) | CFT_UNFLIP;
862 }
863 }
864}
865
866CMD *
867add_label(lbl,cmd)
868char *lbl;
869register CMD *cmd;
870{
871 if (cmd)
872 cmd->c_label = lbl;
873 return cmd;
874}
875
876CMD *
877addcond(cmd, arg)
878register CMD *cmd;
879register ARG *arg;
880{
881 cmd->c_expr = arg;
882 cmd->c_flags |= CF_COND;
883 return cmd;
884}
885
886CMD *
887addloop(cmd, arg)
888register CMD *cmd;
889register ARG *arg;
890{
891 void while_io();
892
893 cmd->c_expr = arg;
894 cmd->c_flags |= CF_COND|CF_LOOP;
895
896 if (!(cmd->c_flags & CF_INVERT))
897 while_io(cmd); /* add $_ =, if necessary */
898
899 if (cmd->c_type == C_BLOCK)
900 cmd->c_flags &= ~CF_COND;
901 else {
902 arg = cmd->ucmd.acmd.ac_expr;
903 if (arg && arg->arg_type == O_ITEM && arg[1].arg_type == A_CMD)
904 cmd->c_flags &= ~CF_COND; /* "do {} while" happens at least once */
905 if (arg && arg->arg_type == O_SUBR)
906 cmd->c_flags &= ~CF_COND; /* likewise for "do subr() while" */
907 }
908 return cmd;
909}
910
911CMD *
912invert(cmd)
03a14243 913CMD *cmd;
a687059c 914{
03a14243 915 register CMD *targ = cmd;
916 if (targ->c_head)
917 targ = targ->c_head;
918 if (targ->c_flags & CF_DBSUB)
919 targ = targ->c_next;
920 targ->c_flags ^= CF_INVERT;
a687059c 921 return cmd;
922}
923
924yyerror(s)
925char *s;
926{
927 char tmpbuf[258];
928 char tmp2buf[258];
929 char *tname = tmpbuf;
930
931 if (bufptr > oldoldbufptr && bufptr - oldoldbufptr < 200 &&
932 oldoldbufptr != oldbufptr && oldbufptr != bufptr) {
933 while (isspace(*oldoldbufptr))
934 oldoldbufptr++;
935 strncpy(tmp2buf, oldoldbufptr, bufptr - oldoldbufptr);
936 tmp2buf[bufptr - oldoldbufptr] = '\0';
937 sprintf(tname,"next 2 tokens \"%s\"",tmp2buf);
938 }
939 else if (bufptr > oldbufptr && bufptr - oldbufptr < 200 &&
940 oldbufptr != bufptr) {
941 while (isspace(*oldbufptr))
942 oldbufptr++;
943 strncpy(tmp2buf, oldbufptr, bufptr - oldbufptr);
944 tmp2buf[bufptr - oldbufptr] = '\0';
945 sprintf(tname,"next token \"%s\"",tmp2buf);
946 }
947 else if (yychar > 256)
948 tname = "next token ???";
949 else if (!yychar)
950 (void)strcpy(tname,"at EOF");
951 else if (yychar < 32)
952 (void)sprintf(tname,"next char ^%c",yychar+64);
953 else if (yychar == 127)
954 (void)strcpy(tname,"at EOF");
955 else
956 (void)sprintf(tname,"next char %c",yychar);
957 (void)sprintf(buf, "%s in file %s at line %d, %s\n",
39c3038c 958 s,stab_val(curcmd->c_filestab)->str_ptr,curcmd->c_line,tname);
ff8e2863 959 if (curcmd->c_line == multi_end && multi_start < multi_end)
a687059c 960 sprintf(buf+strlen(buf),
961 " (Might be a runaway multi-line %c%c string starting on line %d)\n",
962 multi_open,multi_close,multi_start);
963 if (in_eval)
964 str_cat(stab_val(stabent("@",TRUE)),buf);
965 else
966 fputs(buf,stderr);
967 if (++error_count >= 10)
39c3038c 968 fatal("%s has too many errors.\n",
969 stab_val(curcmd->c_filestab)->str_ptr);
a687059c 970}
971
972void
973while_io(cmd)
974register CMD *cmd;
975{
976 register ARG *arg = cmd->c_expr;
977 STAB *asgnstab;
978
979 /* hoist "while (<channel>)" up into command block */
980
981 if (arg && arg->arg_type == O_ITEM && arg[1].arg_type == A_READ) {
982 cmd->c_flags &= ~CF_OPTIMIZE; /* clear optimization type */
983 cmd->c_flags |= CFT_GETS; /* and set it to do the input */
984 cmd->c_stab = arg[1].arg_ptr.arg_stab;
985 if (stab_io(arg[1].arg_ptr.arg_stab)->flags & IOF_ARGV) {
986 cmd->c_expr = l(make_op(O_ASSIGN, 2, /* fake up "$_ =" */
987 stab2arg(A_LVAL,defstab), arg, Nullarg));
988 }
989 else {
990 free_arg(arg);
991 cmd->c_expr = Nullarg;
992 }
993 }
994 else if (arg && arg->arg_type == O_ITEM && arg[1].arg_type == A_INDREAD) {
995 cmd->c_flags &= ~CF_OPTIMIZE; /* clear optimization type */
996 cmd->c_flags |= CFT_INDGETS; /* and set it to do the input */
997 cmd->c_stab = arg[1].arg_ptr.arg_stab;
998 free_arg(arg);
999 cmd->c_expr = Nullarg;
1000 }
1001 else if (arg && arg->arg_type == O_ITEM && arg[1].arg_type == A_GLOB) {
1002 if ((cmd->c_flags & CF_OPTIMIZE) == CFT_ARRAY)
1003 asgnstab = cmd->c_stab;
1004 else
1005 asgnstab = defstab;
1006 cmd->c_expr = l(make_op(O_ASSIGN, 2, /* fake up "$foo =" */
1007 stab2arg(A_LVAL,asgnstab), arg, Nullarg));
1008 cmd->c_flags &= ~CF_OPTIMIZE; /* clear optimization type */
1009 }
1010}
1011
1012CMD *
1013wopt(cmd)
1014register CMD *cmd;
1015{
1016 register CMD *tail;
1017 CMD *newtail;
1018 register int i;
1019
1020 if (cmd->c_expr && (cmd->c_flags & CF_OPTIMIZE) == CFT_FALSE)
1021 opt_arg(cmd,1, cmd->c_type == C_EXPR);
1022
1023 while_io(cmd); /* add $_ =, if necessary */
1024
1025 /* First find the end of the true list */
1026
1027 tail = cmd->ucmd.ccmd.cc_true;
1028 if (tail == Nullcmd)
1029 return cmd;
1030 New(112,newtail, 1, CMD); /* guaranteed continue */
1031 for (;;) {
1032 /* optimize "next" to point directly to continue block */
1033 if (tail->c_type == C_EXPR &&
1034 tail->ucmd.acmd.ac_expr &&
1035 tail->ucmd.acmd.ac_expr->arg_type == O_NEXT &&
1036 (tail->ucmd.acmd.ac_expr->arg_len == 0 ||
1037 (cmd->c_label &&
1038 strEQ(cmd->c_label,
1039 tail->ucmd.acmd.ac_expr[1].arg_ptr.arg_str->str_ptr) )))
1040 {
1041 arg_free(tail->ucmd.acmd.ac_expr);
1042 tail->c_type = C_NEXT;
1043 if (cmd->ucmd.ccmd.cc_alt != Nullcmd)
1044 tail->ucmd.ccmd.cc_alt = cmd->ucmd.ccmd.cc_alt;
1045 else
1046 tail->ucmd.ccmd.cc_alt = newtail;
1047 tail->ucmd.ccmd.cc_true = Nullcmd;
1048 }
1049 else if (tail->c_type == C_IF && !tail->ucmd.ccmd.cc_alt) {
1050 if (cmd->ucmd.ccmd.cc_alt != Nullcmd)
1051 tail->ucmd.ccmd.cc_alt = cmd->ucmd.ccmd.cc_alt;
1052 else
1053 tail->ucmd.ccmd.cc_alt = newtail;
1054 }
1055 else if (tail->c_type == C_CSWITCH || tail->c_type == C_NSWITCH) {
1056 if (cmd->ucmd.ccmd.cc_alt != Nullcmd) {
1057 for (i = tail->ucmd.scmd.sc_max; i >= 0; i--)
1058 if (!tail->ucmd.scmd.sc_next[i])
1059 tail->ucmd.scmd.sc_next[i] = cmd->ucmd.ccmd.cc_alt;
1060 }
1061 else {
1062 for (i = tail->ucmd.scmd.sc_max; i >= 0; i--)
1063 if (!tail->ucmd.scmd.sc_next[i])
1064 tail->ucmd.scmd.sc_next[i] = newtail;
1065 }
1066 }
1067
1068 if (!tail->c_next)
1069 break;
1070 tail = tail->c_next;
1071 }
1072
1073 /* if there's a continue block, link it to true block and find end */
1074
1075 if (cmd->ucmd.ccmd.cc_alt != Nullcmd) {
1076 tail->c_next = cmd->ucmd.ccmd.cc_alt;
1077 tail = tail->c_next;
1078 for (;;) {
1079 /* optimize "next" to point directly to continue block */
1080 if (tail->c_type == C_EXPR &&
1081 tail->ucmd.acmd.ac_expr &&
1082 tail->ucmd.acmd.ac_expr->arg_type == O_NEXT &&
1083 (tail->ucmd.acmd.ac_expr->arg_len == 0 ||
1084 (cmd->c_label &&
1085 strEQ(cmd->c_label,
1086 tail->ucmd.acmd.ac_expr[1].arg_ptr.arg_str->str_ptr) )))
1087 {
1088 arg_free(tail->ucmd.acmd.ac_expr);
1089 tail->c_type = C_NEXT;
1090 tail->ucmd.ccmd.cc_alt = newtail;
1091 tail->ucmd.ccmd.cc_true = Nullcmd;
1092 }
1093 else if (tail->c_type == C_IF && !tail->ucmd.ccmd.cc_alt) {
1094 tail->ucmd.ccmd.cc_alt = newtail;
1095 }
1096 else if (tail->c_type == C_CSWITCH || tail->c_type == C_NSWITCH) {
1097 for (i = tail->ucmd.scmd.sc_max; i >= 0; i--)
1098 if (!tail->ucmd.scmd.sc_next[i])
1099 tail->ucmd.scmd.sc_next[i] = newtail;
1100 }
1101
1102 if (!tail->c_next)
1103 break;
1104 tail = tail->c_next;
1105 }
1106 for ( ; tail->c_next; tail = tail->c_next) ;
1107 }
1108
1109 /* Here's the real trick: link the end of the list back to the beginning,
1110 * inserting a "last" block to break out of the loop. This saves one or
1111 * two procedure calls every time through the loop, because of how cmd_exec
1112 * does tail recursion.
1113 */
1114
1115 tail->c_next = newtail;
1116 tail = newtail;
1117 if (!cmd->ucmd.ccmd.cc_alt)
1118 cmd->ucmd.ccmd.cc_alt = tail; /* every loop has a continue now */
1119
1120#ifndef lint
1121 (void)bcopy((char *)cmd, (char *)tail, sizeof(CMD));
1122#endif
1123 tail->c_type = C_EXPR;
1124 tail->c_flags ^= CF_INVERT; /* turn into "last unless" */
1125 tail->c_next = tail->ucmd.ccmd.cc_true; /* loop directly back to top */
1126 tail->ucmd.acmd.ac_expr = make_op(O_LAST,0,Nullarg,Nullarg,Nullarg);
1127 tail->ucmd.acmd.ac_stab = Nullstab;
1128 return cmd;
1129}
1130
1131CMD *
1132over(eachstab,cmd)
1133STAB *eachstab;
1134register CMD *cmd;
1135{
1136 /* hoist "for $foo (@bar)" up into command block */
1137
1138 cmd->c_flags &= ~CF_OPTIMIZE; /* clear optimization type */
1139 cmd->c_flags |= CFT_ARRAY; /* and set it to do the iteration */
1140 cmd->c_stab = eachstab;
0d3e774c 1141 cmd->c_short = str_new(0); /* just to save a field in struct cmd */
1142 cmd->c_short->str_u.str_useful = -1;
a687059c 1143
1144 return cmd;
1145}
1146
1147cmd_free(cmd)
1148register CMD *cmd;
1149{
1150 register CMD *tofree;
1151 register CMD *head = cmd;
1152
1153 while (cmd) {
1154 if (cmd->c_type != C_WHILE) { /* WHILE block is duplicated */
1155 if (cmd->c_label)
1156 Safefree(cmd->c_label);
1157 if (cmd->c_short)
1158 str_free(cmd->c_short);
1159 if (cmd->c_spat)
1160 spat_free(cmd->c_spat);
1161 if (cmd->c_expr)
1162 arg_free(cmd->c_expr);
1163 }
1164 switch (cmd->c_type) {
1165 case C_WHILE:
1166 case C_BLOCK:
1167 case C_ELSE:
1168 case C_IF:
1169 if (cmd->ucmd.ccmd.cc_true)
1170 cmd_free(cmd->ucmd.ccmd.cc_true);
1171 break;
1172 case C_EXPR:
1173 if (cmd->ucmd.acmd.ac_expr)
1174 arg_free(cmd->ucmd.acmd.ac_expr);
1175 break;
1176 }
1177 tofree = cmd;
1178 cmd = cmd->c_next;
ff8e2863 1179 if (tofree != head) /* to get Saber to shut up */
1180 Safefree(tofree);
a687059c 1181 if (cmd && cmd == head) /* reached end of while loop */
1182 break;
1183 }
ff8e2863 1184 Safefree(head);
a687059c 1185}
1186
1187arg_free(arg)
1188register ARG *arg;
1189{
1190 register int i;
1191
1192 for (i = 1; i <= arg->arg_len; i++) {
1193 switch (arg[i].arg_type & A_MASK) {
1194 case A_NULL:
1195 break;
1196 case A_LEXPR:
1197 if (arg->arg_type == O_AASSIGN &&
1198 arg[i].arg_ptr.arg_arg->arg_type == O_LARRAY) {
1199 char *name =
1200 stab_name(arg[i].arg_ptr.arg_arg[1].arg_ptr.arg_stab);
1201
1202 if (strnEQ("_GEN_",name, 5)) /* array for foreach */
1203 hdelete(defstash,name,strlen(name));
1204 }
1205 /* FALL THROUGH */
1206 case A_EXPR:
1207 arg_free(arg[i].arg_ptr.arg_arg);
1208 break;
1209 case A_CMD:
1210 cmd_free(arg[i].arg_ptr.arg_cmd);
1211 break;
1212 case A_WORD:
1213 case A_STAB:
1214 case A_LVAL:
1215 case A_READ:
1216 case A_GLOB:
1217 case A_ARYLEN:
1218 case A_LARYLEN:
1219 case A_ARYSTAB:
1220 case A_LARYSTAB:
1221 break;
1222 case A_SINGLE:
1223 case A_DOUBLE:
1224 case A_BACKTICK:
1225 str_free(arg[i].arg_ptr.arg_str);
1226 break;
1227 case A_SPAT:
1228 spat_free(arg[i].arg_ptr.arg_spat);
1229 break;
1230 }
1231 }
1232 free_arg(arg);
1233}
1234
1235spat_free(spat)
1236register SPAT *spat;
1237{
1238 register SPAT *sp;
1239 HENT *entry;
1240
1241 if (spat->spat_runtime)
1242 arg_free(spat->spat_runtime);
1243 if (spat->spat_repl) {
1244 arg_free(spat->spat_repl);
1245 }
1246 if (spat->spat_short) {
1247 str_free(spat->spat_short);
1248 }
1249 if (spat->spat_regexp) {
1250 regfree(spat->spat_regexp);
1251 }
1252
1253 /* now unlink from spat list */
1254
1255 for (entry = defstash->tbl_array['_']; entry; entry = entry->hent_next) {
1256 register HASH *stash;
1257 STAB *stab = (STAB*)entry->hent_val;
1258
1259 if (!stab)
1260 continue;
1261 stash = stab_hash(stab);
1262 if (!stash || stash->tbl_spatroot == Null(SPAT*))
1263 continue;
1264 if (stash->tbl_spatroot == spat)
1265 stash->tbl_spatroot = spat->spat_next;
1266 else {
1267 for (sp = stash->tbl_spatroot;
1268 sp && sp->spat_next != spat;
1269 sp = sp->spat_next)
1270 ;
1271 if (sp)
1272 sp->spat_next = spat->spat_next;
1273 }
1274 }
1275 Safefree(spat);
1276}
1277
1278/* Recursively descend a command sequence and push the address of any string
1279 * that needs saving on recursion onto the tosave array.
1280 */
1281
1282static int
1283cmd_tosave(cmd,willsave)
1284register CMD *cmd;
1285int willsave; /* willsave passes down the tree */
1286{
1287 register CMD *head = cmd;
1288 int shouldsave = FALSE; /* shouldsave passes up the tree */
1289 int tmpsave;
1290 register CMD *lastcmd = Nullcmd;
1291
1292 while (cmd) {
1293 if (cmd->c_spat)
1294 shouldsave |= spat_tosave(cmd->c_spat);
1295 if (cmd->c_expr)
1296 shouldsave |= arg_tosave(cmd->c_expr,willsave);
1297 switch (cmd->c_type) {
1298 case C_WHILE:
1299 if (cmd->ucmd.ccmd.cc_true) {
1300 tmpsave = cmd_tosave(cmd->ucmd.ccmd.cc_true,willsave);
1301
1302 /* Here we check to see if the temporary array generated for
1303 * a foreach needs to be localized because of recursion.
1304 */
663a0e37 1305 if (tmpsave && (cmd->c_flags & CF_OPTIMIZE) == CFT_ARRAY) {
1306 if (lastcmd &&
1307 lastcmd->c_type == C_EXPR &&
1308 lastcmd->ucmd.acmd.ac_expr) {
1309 ARG *arg = lastcmd->ucmd.acmd.ac_expr;
1310
1311 if (arg->arg_type == O_ASSIGN &&
1312 arg[1].arg_type == A_LEXPR &&
1313 arg[1].arg_ptr.arg_arg->arg_type == O_LARRAY &&
1314 strnEQ("_GEN_",
1315 stab_name(
1316 arg[1].arg_ptr.arg_arg[1].arg_ptr.arg_stab),
1317 5)) { /* array generated for foreach */
1318 (void)localize(arg[1].arg_ptr.arg_arg);
1319 }
a687059c 1320 }
663a0e37 1321
1322 /* in any event, save the iterator */
1323
1324 (void)apush(tosave,cmd->c_short);
a687059c 1325 }
1326 shouldsave |= tmpsave;
1327 }
1328 break;
1329 case C_BLOCK:
1330 case C_ELSE:
1331 case C_IF:
1332 if (cmd->ucmd.ccmd.cc_true)
1333 shouldsave |= cmd_tosave(cmd->ucmd.ccmd.cc_true,willsave);
1334 break;
1335 case C_EXPR:
1336 if (cmd->ucmd.acmd.ac_expr)
1337 shouldsave |= arg_tosave(cmd->ucmd.acmd.ac_expr,willsave);
1338 break;
1339 }
1340 lastcmd = cmd;
1341 cmd = cmd->c_next;
1342 if (cmd && cmd == head) /* reached end of while loop */
1343 break;
1344 }
1345 return shouldsave;
1346}
1347
1348static int
1349arg_tosave(arg,willsave)
1350register ARG *arg;
1351int willsave;
1352{
1353 register int i;
1354 int shouldsave = FALSE;
1355
1356 for (i = arg->arg_len; i >= 1; i--) {
1357 switch (arg[i].arg_type & A_MASK) {
1358 case A_NULL:
1359 break;
1360 case A_LEXPR:
1361 case A_EXPR:
1362 shouldsave |= arg_tosave(arg[i].arg_ptr.arg_arg,shouldsave);
1363 break;
1364 case A_CMD:
1365 shouldsave |= cmd_tosave(arg[i].arg_ptr.arg_cmd,shouldsave);
1366 break;
1367 case A_WORD:
1368 case A_STAB:
1369 case A_LVAL:
1370 case A_READ:
1371 case A_GLOB:
1372 case A_ARYLEN:
1373 case A_SINGLE:
1374 case A_DOUBLE:
1375 case A_BACKTICK:
1376 break;
1377 case A_SPAT:
1378 shouldsave |= spat_tosave(arg[i].arg_ptr.arg_spat);
1379 break;
1380 }
1381 }
1382 switch (arg->arg_type) {
1383 case O_RETURN:
1384 saw_return = TRUE;
1385 break;
1386 case O_EVAL:
1387 case O_SUBR:
1388 shouldsave = TRUE;
1389 break;
1390 }
1391 if (willsave)
1392 (void)apush(tosave,arg->arg_ptr.arg_str);
1393 return shouldsave;
1394}
1395
1396static int
1397spat_tosave(spat)
1398register SPAT *spat;
1399{
1400 int shouldsave = FALSE;
1401
1402 if (spat->spat_runtime)
1403 shouldsave |= arg_tosave(spat->spat_runtime,FALSE);
1404 if (spat->spat_repl) {
1405 shouldsave |= arg_tosave(spat->spat_repl,FALSE);
1406 }
1407
1408 return shouldsave;
1409}
1410