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