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