perl 3.0: (no announcement message available)
[p5sagit/p5-mst-13.2.git] / x2p / walk.c
1 /* $Header: walk.c,v 3.0 89/10/18 15:35:48 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:        walk.c,v $
9  * Revision 3.0  89/10/18  15:35:48  lwall
10  * 3.0 baseline
11  * 
12  */
13
14 #include "handy.h"
15 #include "EXTERN.h"
16 #include "util.h"
17 #include "a2p.h"
18
19 bool exitval = FALSE;
20 bool realexit = FALSE;
21 bool saw_getline = FALSE;
22 bool subretnum = FALSE;
23 bool saw_FNR = FALSE;
24 bool saw_argv0 = FALSE;
25 int maxtmp = 0;
26 char *lparen;
27 char *rparen;
28 STR *subs;
29 STR *curargs = Nullstr;
30
31 STR *
32 walk(useval,level,node,numericptr,minprec)
33 int useval;
34 int level;
35 register int node;
36 int *numericptr;
37 int minprec;                    /* minimum precedence without parens */
38 {
39     register int len;
40     register STR *str;
41     register int type;
42     register int i;
43     register STR *tmpstr;
44     STR *tmp2str;
45     STR *tmp3str;
46     char *t;
47     char *d, *s;
48     int numarg;
49     int numeric = FALSE;
50     STR *fstr;
51     int prec = P_MAX;           /* assume no parens needed */
52     char *index();
53
54     if (!node) {
55         *numericptr = 0;
56         return str_make("");
57     }
58     type = ops[node].ival;
59     len = type >> 8;
60     type &= 255;
61     switch (type) {
62     case OPROG:
63         opens = str_new(0);
64         subs = str_new(0);
65         str = walk(0,level,ops[node+1].ival,&numarg,P_MIN);
66         if (do_split && need_entire && !absmaxfld)
67             split_to_array = TRUE;
68         if (do_split && split_to_array)
69             set_array_base = TRUE;
70         if (set_array_base) {
71             str_cat(str,"$[ = 1;\t\t\t# set array base to 1\n");
72         }
73         if (fswitch && !const_FS)
74             const_FS = fswitch;
75         if (saw_FS > 1 || saw_RS)
76             const_FS = 0;
77         if (saw_ORS && need_entire)
78             do_chop = TRUE;
79         if (fswitch) {
80             str_cat(str,"$FS = '");
81             if (index("*+?.[]()|^$\\",fswitch))
82                 str_cat(str,"\\");
83             sprintf(tokenbuf,"%c",fswitch);
84             str_cat(str,tokenbuf);
85             str_cat(str,"';\t\t# field separator from -F switch\n");
86         }
87         else if (saw_FS && !const_FS) {
88             str_cat(str,"$FS = ' ';\t\t# set field separator\n");
89         }
90         if (saw_OFS) {
91             str_cat(str,"$, = ' ';\t\t# set output field separator\n");
92         }
93         if (saw_ORS) {
94             str_cat(str,"$\\ = \"\\n\";\t\t# set output record separator\n");
95         }
96         if (saw_argv0) {
97             str_cat(str,"$ARGV0 = $0;\t\t# remember what we ran as\n");
98         }
99         if (str->str_cur > 20)
100             str_cat(str,"\n");
101         if (ops[node+2].ival) {
102             str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg,P_MIN));
103             str_free(fstr);
104             str_cat(str,"\n\n");
105         }
106         fstr = walk(0,level+1,ops[node+3].ival,&numarg,P_MIN);
107         if (*fstr->str_ptr) {
108             if (saw_line_op)
109                 str_cat(str,"line: ");
110             str_cat(str,"while (<>) {\n");
111             tab(str,++level);
112             if (saw_FS && !const_FS)
113                 do_chop = TRUE;
114             if (do_chop) {
115                 str_cat(str,"chop;\t# strip record separator\n");
116                 tab(str,level);
117             }
118             arymax = 0;
119             if (namelist) {
120                 while (isalpha(*namelist)) {
121                     for (d = tokenbuf,s=namelist;
122                       isalpha(*s) || isdigit(*s) || *s == '_';
123                       *d++ = *s++) ;
124                     *d = '\0';
125                     while (*s && !isalpha(*s)) s++;
126                     namelist = s;
127                     nameary[++arymax] = savestr(tokenbuf);
128                 }
129             }
130             if (maxfld < arymax)
131                 maxfld = arymax;
132             if (do_split)
133                 emit_split(str,level);
134             str_scat(str,fstr);
135             str_free(fstr);
136             fixtab(str,--level);
137             str_cat(str,"}\n");
138             if (saw_FNR)
139                 str_cat(str,"continue {\n    $FNRbase = $. if eof;\n}\n");
140         }
141         else
142             str_cat(str,"# (no line actions)\n");
143         if (ops[node+4].ival) {
144             realexit = TRUE;
145             str_cat(str,"\n");
146             tab(str,level);
147             str_scat(str,fstr=walk(0,level,ops[node+4].ival,&numarg,P_MIN));
148             str_free(fstr);
149             str_cat(str,"\n");
150         }
151         if (exitval)
152             str_cat(str,"exit ExitValue;\n");
153         if (subs->str_ptr) {
154             str_cat(str,"\n");
155             str_scat(str,subs);
156         }
157         if (saw_getline) {
158             for (len = 0; len < 4; len++) {
159                 if (saw_getline & (1 << len)) {
160                     sprintf(tokenbuf,"\nsub Getline%d {\n",len);
161                     str_cat(str, tokenbuf);
162                     if (len & 2) {
163                         if (do_fancy_opens)
164                             str_cat(str,"    &Pick('',@_);\n");
165                         else
166                             str_cat(str,"    ($fh) = @_;\n");
167                     }
168                     else {
169                         if (saw_FNR)
170                             str_cat(str,"    $FNRbase = $. if eof;\n");
171                     }
172                     if (len & 1)
173                         str_cat(str,"    local($_)\n");
174                     if (len & 2)
175                         str_cat(str,
176                           "    if ($getline_ok = (($_ = <$fh>) ne ''))");
177                     else
178                         str_cat(str,
179                           "    if ($getline_ok = (($_ = <>) ne ''))");
180                     str_cat(str, " {\n");
181                     level += 2;
182                     tab(str,level);
183                     i = 0;
184                     if (do_chop) {
185                         i++;
186                         str_cat(str,"chop;\t# strip record separator\n");
187                         tab(str,level);
188                     }
189                     if (do_split && !(len & 1)) {
190                         i++;
191                         emit_split(str,level);
192                     }
193                     if (!i)
194                         str_cat(str,";\n");
195                     fixtab(str,--level);
196                     str_cat(str,"}\n    $_;\n}\n");
197                     --level;
198                 }
199             }
200         }
201         if (do_fancy_opens) {
202             str_cat(str,"\n\
203 sub Pick {\n\
204     local($mode,$name,$pipe) = @_;\n\
205     $fh = $opened{$name};\n\
206     if (!$fh) {\n\
207         $fh = $opened{$name} = 'fh_' . ($nextfh++ + 0);\n\
208         open($fh,$mode.$name.$pipe);\n\
209     }\n\
210 }\n\
211 ");
212         }
213         break;
214     case OHUNKS:
215         str = walk(0,level,ops[node+1].ival,&numarg,P_MIN);
216         str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg,P_MIN));
217         str_free(fstr);
218         if (len == 3) {
219             str_scat(str,fstr=walk(0,level,ops[node+3].ival,&numarg,P_MIN));
220             str_free(fstr);
221         }
222         else {
223         }
224         break;
225     case ORANGE:
226         prec = P_DOTDOT;
227         str = walk(1,level,ops[node+1].ival,&numarg,prec+1);
228         str_cat(str," .. ");
229         str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1));
230         str_free(fstr);
231         break;
232     case OPAT:
233         goto def;
234     case OREGEX:
235         str = str_new(0);
236         str_set(str,"/");
237         tmpstr=walk(0,level,ops[node+1].ival,&numarg,P_MIN);
238         /* translate \nnn to [\nnn] */
239         for (s = tmpstr->str_ptr, d = tokenbuf; *s; s++, d++) {
240             if (*s == '\\' && isdigit(s[1]) && isdigit(s[2]) && isdigit(s[3])){
241                 *d++ = '[';
242                 *d++ = *s++;
243                 *d++ = *s++;
244                 *d++ = *s++;
245                 *d++ = *s;
246                 *d = ']';
247             }
248             else
249                 *d = *s;
250         }
251         *d = '\0';
252         for (d=tokenbuf; *d; d++)
253             *d += 128;
254         str_cat(str,tokenbuf);
255         str_free(tmpstr);
256         str_cat(str,"/");
257         break;
258     case OHUNK:
259         if (len == 1) {
260             str = str_new(0);
261             str = walk(0,level,oper1(OPRINT,0),&numarg,P_MIN);
262             str_cat(str," if ");
263             str_scat(str,fstr=walk(0,level,ops[node+1].ival,&numarg,P_MIN));
264             str_free(fstr);
265             str_cat(str,";");
266         }
267         else {
268             tmpstr = walk(0,level,ops[node+1].ival,&numarg,P_MIN);
269             if (*tmpstr->str_ptr) {
270                 str = str_new(0);
271                 str_set(str,"if (");
272                 str_scat(str,tmpstr);
273                 str_cat(str,") {\n");
274                 tab(str,++level);
275                 str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg,P_MIN));
276                 str_free(fstr);
277                 fixtab(str,--level);
278                 str_cat(str,"}\n");
279                 tab(str,level);
280             }
281             else {
282                 str = walk(0,level,ops[node+2].ival,&numarg,P_MIN);
283             }
284         }
285         break;
286     case OPPAREN:
287         str = str_new(0);
288         str_set(str,"(");
289         str_scat(str,fstr=walk(useval != 0,level,ops[node+1].ival,&numarg,P_MIN));
290         str_free(fstr);
291         str_cat(str,")");
292         break;
293     case OPANDAND:
294         prec = P_ANDAND;
295         str = walk(1,level,ops[node+1].ival,&numarg,prec);
296         str_cat(str," && ");
297         str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1));
298         str_free(fstr);
299         str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,prec+1));
300         str_free(fstr);
301         break;
302     case OPOROR:
303         prec = P_OROR;
304         str = walk(1,level,ops[node+1].ival,&numarg,prec);
305         str_cat(str," || ");
306         str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1));
307         str_free(fstr);
308         str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,prec+1));
309         str_free(fstr);
310         break;
311     case OPNOT:
312         prec = P_UNARY;
313         str = str_new(0);
314         str_set(str,"!");
315         str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,prec));
316         str_free(fstr);
317         break;
318     case OCPAREN:
319         str = str_new(0);
320         str_set(str,"(");
321         str_scat(str,fstr=walk(useval != 0,level,ops[node+1].ival,&numarg,P_MIN));
322         str_free(fstr);
323         numeric |= numarg;
324         str_cat(str,")");
325         break;
326     case OCANDAND:
327         prec = P_ANDAND;
328         str = walk(1,level,ops[node+1].ival,&numarg,prec);
329         numeric = 1;
330         str_cat(str," && ");
331         str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1));
332         str_free(fstr);
333         str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,prec+1));
334         str_free(fstr);
335         break;
336     case OCOROR:
337         prec = P_OROR;
338         str = walk(1,level,ops[node+1].ival,&numarg,prec);
339         numeric = 1;
340         str_cat(str," || ");
341         str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1));
342         str_free(fstr);
343         str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,prec+1));
344         str_free(fstr);
345         break;
346     case OCNOT:
347         prec = P_UNARY;
348         str = str_new(0);
349         str_set(str,"!");
350         str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,prec));
351         str_free(fstr);
352         numeric = 1;
353         break;
354     case ORELOP:
355         prec = P_REL;
356         str = walk(1,level,ops[node+2].ival,&numarg,prec+1);
357         numeric |= numarg;
358         tmpstr = walk(0,level,ops[node+1].ival,&numarg,P_MIN);
359         tmp2str = walk(1,level,ops[node+3].ival,&numarg,prec+1);
360         numeric |= numarg;
361         if (!numeric ||
362          (!numarg && (*tmp2str->str_ptr == '"' || *tmp2str->str_ptr == '\''))) {
363             t = tmpstr->str_ptr;
364             if (strEQ(t,"=="))
365                 str_set(tmpstr,"eq");
366             else if (strEQ(t,"!="))
367                 str_set(tmpstr,"ne");
368             else if (strEQ(t,"<"))
369                 str_set(tmpstr,"lt");
370             else if (strEQ(t,"<="))
371                 str_set(tmpstr,"le");
372             else if (strEQ(t,">"))
373                 str_set(tmpstr,"gt");
374             else if (strEQ(t,">="))
375                 str_set(tmpstr,"ge");
376             if (!index(tmpstr->str_ptr,'\'') && !index(tmpstr->str_ptr,'"') &&
377               !index(tmp2str->str_ptr,'\'') && !index(tmp2str->str_ptr,'"') )
378                 numeric |= 2;
379         }
380         if (numeric & 2) {
381             if (numeric & 1)            /* numeric is very good guess */
382                 str_cat(str," ");
383             else
384                 str_cat(str,"\377");
385             numeric = 1;
386         }
387         else
388             str_cat(str," ");
389         str_scat(str,tmpstr);
390         str_free(tmpstr);
391         str_cat(str," ");
392         str_scat(str,tmp2str);
393         str_free(tmp2str);
394         numeric = 1;
395         break;
396     case ORPAREN:
397         str = str_new(0);
398         str_set(str,"(");
399         str_scat(str,fstr=walk(useval != 0,level,ops[node+1].ival,&numarg,P_MIN));
400         str_free(fstr);
401         numeric |= numarg;
402         str_cat(str,")");
403         break;
404     case OMATCHOP:
405         prec = P_MATCH;
406         str = walk(1,level,ops[node+2].ival,&numarg,prec+1);
407         str_cat(str," ");
408         tmpstr = walk(0,level,ops[node+1].ival,&numarg,P_MIN);
409         if (strEQ(tmpstr->str_ptr,"~"))
410             str_cat(str,"=~");
411         else {
412             str_scat(str,tmpstr);
413             str_free(tmpstr);
414         }
415         str_cat(str," ");
416         str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,prec+1));
417         str_free(fstr);
418         numeric = 1;
419         break;
420     case OMPAREN:
421         str = str_new(0);
422         str_set(str,"(");
423         str_scat(str,
424           fstr=walk(useval != 0,level,ops[node+1].ival,&numarg,P_MIN));
425         str_free(fstr);
426         numeric |= numarg;
427         str_cat(str,")");
428         break;
429     case OCONCAT:
430         prec = P_ADD;
431         type = ops[ops[node+1].ival].ival & 255;
432         str = walk(1,level,ops[node+1].ival,&numarg,prec+(type != OCONCAT));
433         str_cat(str," . ");
434         type = ops[ops[node+2].ival].ival & 255;
435         str_scat(str,
436           fstr=walk(1,level,ops[node+2].ival,&numarg,prec+(type != OCONCAT)));
437         str_free(fstr);
438         break;
439     case OASSIGN:
440         prec = P_ASSIGN;
441         str = walk(0,level,ops[node+2].ival,&numarg,prec+1);
442         str_cat(str," ");
443         tmpstr = walk(0,level,ops[node+1].ival,&numarg,P_MIN);
444         str_scat(str,tmpstr);
445         if (str_len(tmpstr) > 1)
446             numeric = 1;
447         str_free(tmpstr);
448         str_cat(str," ");
449         str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,prec));
450         str_free(fstr);
451         numeric |= numarg;
452         break;
453     case OADD:
454         prec = P_ADD;
455         str = walk(1,level,ops[node+1].ival,&numarg,prec);
456         str_cat(str," + ");
457         str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1));
458         str_free(fstr);
459         numeric = 1;
460         break;
461     case OSUBTRACT:
462         prec = P_ADD;
463         str = walk(1,level,ops[node+1].ival,&numarg,prec);
464         str_cat(str," - ");
465         str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1));
466         str_free(fstr);
467         numeric = 1;
468         break;
469     case OMULT:
470         prec = P_MUL;
471         str = walk(1,level,ops[node+1].ival,&numarg,prec);
472         str_cat(str," * ");
473         str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1));
474         str_free(fstr);
475         numeric = 1;
476         break;
477     case ODIV:
478         prec = P_MUL;
479         str = walk(1,level,ops[node+1].ival,&numarg,prec);
480         str_cat(str," / ");
481         str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1));
482         str_free(fstr);
483         numeric = 1;
484         break;
485     case OPOW:
486         prec = P_POW;
487         str = walk(1,level,ops[node+1].ival,&numarg,prec+1);
488         str_cat(str," ** ");
489         str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec));
490         str_free(fstr);
491         numeric = 1;
492         break;
493     case OMOD:
494         prec = P_MUL;
495         str = walk(1,level,ops[node+1].ival,&numarg,prec);
496         str_cat(str," % ");
497         str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1));
498         str_free(fstr);
499         numeric = 1;
500         break;
501     case OPOSTINCR:
502         prec = P_AUTO;
503         str = walk(1,level,ops[node+1].ival,&numarg,prec+1);
504         str_cat(str,"++");
505         numeric = 1;
506         break;
507     case OPOSTDECR:
508         prec = P_AUTO;
509         str = walk(1,level,ops[node+1].ival,&numarg,prec+1);
510         str_cat(str,"--");
511         numeric = 1;
512         break;
513     case OPREINCR:
514         prec = P_AUTO;
515         str = str_new(0);
516         str_set(str,"++");
517         str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,prec+1));
518         str_free(fstr);
519         numeric = 1;
520         break;
521     case OPREDECR:
522         prec = P_AUTO;
523         str = str_new(0);
524         str_set(str,"--");
525         str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,prec+1));
526         str_free(fstr);
527         numeric = 1;
528         break;
529     case OUMINUS:
530         prec = P_UNARY;
531         str = str_new(0);
532         str_set(str,"-");
533         str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,prec));
534         str_free(fstr);
535         numeric = 1;
536         break;
537     case OUPLUS:
538         numeric = 1;
539         goto def;
540     case OPAREN:
541         str = str_new(0);
542         str_set(str,"(");
543         str_scat(str,
544           fstr=walk(useval != 0,level,ops[node+1].ival,&numarg,P_MIN));
545         str_free(fstr);
546         str_cat(str,")");
547         numeric |= numarg;
548         break;
549     case OGETLINE:
550         str = str_new(0);
551         if (useval)
552             str_cat(str,"(");
553         if (len > 0) {
554             str_cat(str,"$");
555             str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN));
556             if (!*fstr->str_ptr) {
557                 str_cat(str,"_");
558                 len = 2;                /* a legal fiction */
559             }
560             str_free(fstr);
561         }
562         else
563             str_cat(str,"$_");
564         if (len > 1) {
565             tmpstr=walk(1,level,ops[node+3].ival,&numarg,P_MIN);
566             fstr=walk(1,level,ops[node+2].ival,&numarg,P_MIN);
567             if (!do_fancy_opens) {
568                 t = tmpstr->str_ptr;
569                 if (*t == '"' || *t == '\'')
570                     t = cpytill(tokenbuf,t+1,*t);
571                 else
572                     fatal("Internal error: OGETLINE %s", t);
573                 d = savestr(t);
574                 s = savestr(tokenbuf);
575                 for (t = tokenbuf; *t; t++) {
576                     *t &= 127;
577                     if (!isalpha(*t) && !isdigit(*t))
578                         *t = '_';
579                 }
580                 if (!index(tokenbuf,'_'))
581                     strcpy(t,"_fh");
582                 tmp3str = hfetch(symtab,tokenbuf);
583                 if (!tmp3str) {
584                     do_opens = TRUE;
585                     str_cat(opens,"open(");
586                     str_cat(opens,tokenbuf);
587                     str_cat(opens,", ");
588                     d[1] = '\0';
589                     str_cat(opens,d);
590                     str_cat(opens,tmpstr->str_ptr+1);
591                     opens->str_cur--;
592                     if (*fstr->str_ptr == '|')
593                         str_cat(opens,"|");
594                     str_cat(opens,d);
595                     if (*fstr->str_ptr == '|')
596                         str_cat(opens,") || die 'Cannot pipe from \"");
597                     else
598                         str_cat(opens,") || die 'Cannot open file \"");
599                     if (*d == '"')
600                         str_cat(opens,"'.\"");
601                     str_cat(opens,s);
602                     if (*d == '"')
603                         str_cat(opens,"\".'");
604                     str_cat(opens,"\".';\n");
605                     hstore(symtab,tokenbuf,str_make("x"));
606                 }
607                 safefree(s);
608                 safefree(d);
609                 str_set(tmpstr,"'");
610                 str_cat(tmpstr,tokenbuf);
611                 str_cat(tmpstr,"'");
612             }
613             if (*fstr->str_ptr == '|')
614                 str_cat(tmpstr,", '|'");
615             str_free(fstr);
616         }
617         else
618             tmpstr = str_make("");
619         sprintf(tokenbuf," = &Getline%d(%s)",len,tmpstr->str_ptr);
620         str_cat(str,tokenbuf); 
621         str_free(tmpstr);
622         if (useval)
623             str_cat(str,",$getline_ok)");
624         saw_getline |= 1 << len;
625         break;
626     case OSPRINTF:
627         str = str_new(0);
628         str_set(str,"sprintf(");
629         str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN));
630         str_free(fstr);
631         str_cat(str,")");
632         break;
633     case OSUBSTR:
634         str = str_new(0);
635         str_set(str,"substr(");
636         str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_COMMA+1));
637         str_free(fstr);
638         str_cat(str,", ");
639         str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,P_COMMA+1));
640         str_free(fstr);
641         str_cat(str,", ");
642         if (len == 3) {
643             str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,P_COMMA+1));
644             str_free(fstr);
645         }
646         else
647             str_cat(str,"999999");
648         str_cat(str,")");
649         break;
650     case OSTRING:
651         str = str_new(0);
652         str_set(str,ops[node+1].cval);
653         break;
654     case OSPLIT:
655         str = str_new(0);
656         numeric = 1;
657         tmpstr = walk(1,level,ops[node+2].ival,&numarg,P_MIN);
658         if (useval)
659             str_set(str,"(@");
660         else
661             str_set(str,"@");
662         str_scat(str,tmpstr);
663         str_cat(str," = split(");
664         if (len == 3) {
665             fstr = walk(1,level,ops[node+3].ival,&numarg,P_COMMA+1);
666             if (str_len(fstr) == 3 && *fstr->str_ptr == '\'') {
667                 i = fstr->str_ptr[1] & 127;
668                 if (index("*+?.[]()|^$\\",i))
669                     sprintf(tokenbuf,"/\\%c/",i);
670                 else
671                     sprintf(tokenbuf,"/%c/",i);
672                 str_cat(str,tokenbuf);
673             }
674             else
675                 str_scat(str,fstr);
676             str_free(fstr);
677         }
678         else if (const_FS) {
679             sprintf(tokenbuf,"/[%c\\n]/",const_FS);
680             str_cat(str,tokenbuf);
681         }
682         else if (saw_FS)
683             str_cat(str,"$FS");
684         else
685             str_cat(str,"' '");
686         str_cat(str,", ");
687         str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_COMMA+1));
688         str_free(fstr);
689         str_cat(str,", 999)");
690         if (useval) {
691             str_cat(str,")");
692         }
693         str_free(tmpstr);
694         break;
695     case OINDEX:
696         str = str_new(0);
697         str_set(str,"index(");
698         str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_COMMA+1));
699         str_free(fstr);
700         str_cat(str,", ");
701         str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,P_COMMA+1));
702         str_free(fstr);
703         str_cat(str,")");
704         numeric = 1;
705         break;
706     case OMATCH:
707         str = str_new(0);
708         prec = P_ANDAND;
709         str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_MATCH+1));
710         str_free(fstr);
711         str_cat(str," =~ ");
712         str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,P_MATCH+1));
713         str_free(fstr);
714         str_cat(str," && ($RLENGTH = length($&), $RSTART = length($`)+1)");
715         numeric = 1;
716         break;
717     case OUSERDEF:
718         str = str_new(0);
719         subretnum = FALSE;
720         fstr=walk(1,level-1,ops[node+2].ival,&numarg,P_MIN);
721         curargs = str_new(0);
722         str_sset(curargs,fstr);
723         str_cat(curargs,",");
724         tmp2str=walk(1,level,ops[node+5].ival,&numarg,P_MIN);
725         str_free(curargs);
726         curargs = Nullstr;
727         level--;
728         subretnum |= numarg;
729         s = Nullch;
730         t = tmp2str->str_ptr;
731         while (t = instr(t,"return "))
732             s = t++;
733         if (s) {
734             i = 0;
735             for (t = s+7; *t; t++) {
736                 if (*t == ';' || *t == '}')
737                     i++;
738             }
739             if (i == 1) {
740                 strcpy(s,s+7);
741                 tmp2str->str_cur -= 7;
742             }
743         }
744         str_set(str,"\n");
745         tab(str,level);
746         str_cat(str,"sub ");
747         str_scat(str,tmpstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN));
748         str_cat(str," {\n");
749         tab(str,++level);
750         if (fstr->str_cur) {
751             str_cat(str,"local(");
752             str_scat(str,fstr);
753             str_cat(str,") = @_;");
754         }
755         str_free(fstr);
756         str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,P_MIN));
757         str_free(fstr);
758         fixtab(str,level);
759         str_scat(str,fstr=walk(1,level,ops[node+4].ival,&numarg,P_MIN));
760         str_free(fstr);
761         fixtab(str,level);
762         str_scat(str,tmp2str);
763         str_free(tmp2str);
764         fixtab(str,--level);
765         str_cat(str,"}\n");
766         tab(str,level);
767         str_scat(subs,str);
768         str_set(str,"");
769         str_cat(tmpstr,"(");
770         tmp2str = str_new(0);
771         if (subretnum)
772             str_set(tmp2str,"1");
773         hstore(symtab,tmpstr->str_ptr,tmp2str);
774         str_free(tmpstr);
775         level++;
776         break;
777     case ORETURN:
778         str = str_new(0);
779         if (len > 0) {
780             str_cat(str,"return ");
781             str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_UNI+1));
782             str_free(fstr);
783             if (numarg)
784                 subretnum = TRUE;
785         }
786         else
787             str_cat(str,"return");
788         break;
789     case OUSERFUN:
790         str = str_new(0);
791         str_set(str,"&");
792         str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN));
793         str_free(fstr);
794         str_cat(str,"(");
795         tmpstr = hfetch(symtab,str->str_ptr+3);
796         if (tmpstr && tmpstr->str_ptr)
797             numeric |= atoi(tmpstr->str_ptr);
798         str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,P_MIN));
799         str_free(fstr);
800         str_cat(str,")");
801         break;
802     case OGSUB:
803     case OSUB:
804         if (type == OGSUB)
805             s = "g";
806         else
807             s = "";
808         str = str_new(0);
809         tmpstr = str_new(0);
810         i = 0;
811         if (len == 3) {
812             tmpstr = walk(1,level,ops[node+3].ival,&numarg,P_MATCH+1);
813             if (strNE(tmpstr->str_ptr,"$_")) {
814                 str_cat(tmpstr, " =~ s");
815                 i++;
816             }
817             else
818                 str_set(tmpstr, "s");
819         }
820         else
821             str_set(tmpstr, "s");
822         type = ops[ops[node+2].ival].ival;
823         len = type >> 8;
824         type &= 255;
825         tmp3str = str_new(0);
826         if (type == OSTR) {
827             tmp2str=walk(1,level,ops[ops[node+2].ival+1].ival,&numarg,P_MIN);
828             for (t = tmp2str->str_ptr, d=tokenbuf; *t; d++,t++) {
829                 if (*t == '&')
830                     *d++ = '$' + 128;
831                 else if (*t == '$')
832                     *d++ = '\\' + 128;
833                 *d = *t + 128;
834             }
835             *d = '\0';
836             str_set(tmp2str,tokenbuf);
837         }
838         else {
839             tmp2str=walk(1,level,ops[node+2].ival,&numarg,P_MIN);
840             str_set(tmp3str,"($s_ = '\"'.(");
841             str_scat(tmp3str,tmp2str);
842             str_cat(tmp3str,").'\"') =~ s/&/\\$&/g, ");
843             str_set(tmp2str,"eval $s_");
844             s = (*s == 'g' ? "ge" : "e");
845             i++;
846         }
847         type = ops[ops[node+1].ival].ival;
848         len = type >> 8;
849         type &= 255;
850         fstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN);
851         if (type == OREGEX) {
852             if (useval && i)
853                 str_cat(str,"(");
854             str_scat(str,tmp3str);
855             str_scat(str,tmpstr);
856             str_scat(str,fstr);
857             str_scat(str,tmp2str);
858             str_cat(str,"/");
859             str_cat(str,s);
860         }
861         else if ((type == OFLD && !split_to_array) || (type == OVAR && len == 1)) {
862             if (useval && i)
863                 str_cat(str,"(");
864             str_scat(str,tmp3str);
865             str_scat(str,tmpstr);
866             str_cat(str,"/");
867             str_scat(str,fstr);
868             str_cat(str,"/");
869             str_scat(str,tmp2str);
870             str_cat(str,"/");
871             str_cat(str,s);
872         }
873         else {
874             i++;
875             if (useval)
876                 str_cat(str,"(");
877             str_cat(str,"$s = ");
878             str_scat(str,fstr);
879             str_cat(str,", ");
880             str_scat(str,tmp3str);
881             str_scat(str,tmpstr);
882             str_cat(str,"/$s/");
883             str_scat(str,tmp2str);
884             str_cat(str,"/");
885             str_cat(str,s);
886         }
887         if (useval && i)
888             str_cat(str,")");
889         str_free(fstr);
890         str_free(tmpstr);
891         str_free(tmp2str);
892         str_free(tmp3str);
893         numeric = 1;
894         break;
895     case ONUM:
896         str = walk(1,level,ops[node+1].ival,&numarg,P_MIN);
897         numeric = 1;
898         break;
899     case OSTR:
900         tmpstr = walk(1,level,ops[node+1].ival,&numarg,P_MIN);
901         s = "'";
902         for (t = tmpstr->str_ptr, d=tokenbuf; *t; d++,t++) {
903             if (*t == '\'')
904                 s = "\"";
905             else if (*t == '\\') {
906                 s = "\"";
907                 *d++ = *t++ + 128;
908                 switch (*t) {
909                 case '\\': case '"': case 'n': case 't':
910                     break;
911                 default:        /* hide this from perl */
912                     *d++ = '\\' + 128;
913                 }
914             }
915             *d = *t + 128;
916         }
917         *d = '\0';
918         str = str_new(0);
919         str_set(str,s);
920         str_cat(str,tokenbuf);
921         str_free(tmpstr);
922         str_cat(str,s);
923         break;
924     case ODEFINED:
925         prec = P_UNI;
926         str = str_new(0);
927         str_set(str,"defined $");
928         goto addvar;
929     case ODELETE:
930         str = str_new(0);
931         str_set(str,"delete $");
932         goto addvar;
933     case OSTAR:
934         str = str_new(0);
935         str_set(str,"*");
936         goto addvar;
937     case OVAR:
938         str = str_new(0);
939         str_set(str,"$");
940       addvar:
941         str_scat(str,tmpstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN));
942         if (len == 1) {
943             tmp2str = hfetch(symtab,tmpstr->str_ptr);
944             if (tmp2str && atoi(tmp2str->str_ptr))
945                 numeric = 2;
946             if (strEQ(str->str_ptr,"$FNR")) {
947                 numeric = 1;
948                 saw_FNR++;
949                 str_set(str,"($.-$FNRbase)");
950             }
951             else if (strEQ(str->str_ptr,"$NR")) {
952                 numeric = 1;
953                 str_set(str,"$.");
954             }
955             else if (strEQ(str->str_ptr,"$NF")) {
956                 numeric = 1;
957                 str_set(str,"$#Fld");
958             }
959             else if (strEQ(str->str_ptr,"$0"))
960                 str_set(str,"$_");
961             else if (strEQ(str->str_ptr,"$ARGC"))
962                 str_set(str,"($#ARGV+1)");
963         }
964         else {
965 #ifdef NOTDEF
966             if (curargs) {
967                 sprintf(tokenbuf,"$%s,",tmpstr->str_ptr);
968         ???     if (instr(curargs->str_ptr,tokenbuf))
969                     str_cat(str,"\377");        /* can't translate yet */
970             }
971 #endif
972             str_cat(tmpstr,"[]");
973             tmp2str = hfetch(symtab,tmpstr->str_ptr);
974             if (tmp2str && atoi(tmp2str->str_ptr))
975                 str_cat(str,"[");
976             else
977                 str_cat(str,"{");
978             str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,P_MIN));
979             str_free(fstr);
980             if (strEQ(str->str_ptr,"$ARGV[0")) {
981                 str_set(str,"$ARGV0");
982                 saw_argv0++;
983             }
984             else {
985                 if (tmp2str && atoi(tmp2str->str_ptr))
986                     strcpy(tokenbuf,"]");
987                 else
988                     strcpy(tokenbuf,"}");
989                 *tokenbuf += 128;
990                 str_cat(str,tokenbuf);
991             }
992         }
993         str_free(tmpstr);
994         break;
995     case OFLD:
996         str = str_new(0);
997         if (split_to_array) {
998             str_set(str,"$Fld");
999             str_cat(str,"[");
1000             str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN));
1001             str_free(fstr);
1002             str_cat(str,"]");
1003         }
1004         else {
1005             i = atoi(walk(1,level,ops[node+1].ival,&numarg,P_MIN)->str_ptr);
1006             if (i <= arymax)
1007                 sprintf(tokenbuf,"$%s",nameary[i]);
1008             else
1009                 sprintf(tokenbuf,"$Fld%d",i);
1010             str_set(str,tokenbuf);
1011         }
1012         break;
1013     case OVFLD:
1014         str = str_new(0);
1015         str_set(str,"$Fld[");
1016         i = ops[node+1].ival;
1017         if ((ops[i].ival & 255) == OPAREN)
1018             i = ops[i+1].ival;
1019         tmpstr=walk(1,level,i,&numarg,P_MIN);
1020         str_scat(str,tmpstr);
1021         str_free(tmpstr);
1022         str_cat(str,"]");
1023         break;
1024     case OJUNK:
1025         goto def;
1026     case OSNEWLINE:
1027         str = str_new(2);
1028         str_set(str,";\n");
1029         tab(str,level);
1030         break;
1031     case ONEWLINE:
1032         str = str_new(1);
1033         str_set(str,"\n");
1034         tab(str,level);
1035         break;
1036     case OSCOMMENT:
1037         str = str_new(0);
1038         str_set(str,";");
1039         tmpstr = walk(0,level,ops[node+1].ival,&numarg,P_MIN);
1040         for (s = tmpstr->str_ptr; *s && *s != '\n'; s++)
1041             *s += 128;
1042         str_scat(str,tmpstr);
1043         str_free(tmpstr);
1044         tab(str,level);
1045         break;
1046     case OCOMMENT:
1047         str = str_new(0);
1048         tmpstr = walk(0,level,ops[node+1].ival,&numarg,P_MIN);
1049         for (s = tmpstr->str_ptr; *s && *s != '\n'; s++)
1050             *s += 128;
1051         str_scat(str,tmpstr);
1052         str_free(tmpstr);
1053         tab(str,level);
1054         break;
1055     case OCOMMA:
1056         prec = P_COMMA;
1057         str = walk(1,level,ops[node+1].ival,&numarg,prec);
1058         str_cat(str,", ");
1059         str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,P_MIN));
1060         str_free(fstr);
1061         str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,prec+1));
1062         str_free(fstr);
1063         break;
1064     case OSEMICOLON:
1065         str = str_new(1);
1066         str_set(str,";\n");
1067         tab(str,level);
1068         break;
1069     case OSTATES:
1070         str = walk(0,level,ops[node+1].ival,&numarg,P_MIN);
1071         str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg,P_MIN));
1072         str_free(fstr);
1073         break;
1074     case OSTATE:
1075         str = str_new(0);
1076         if (len >= 1) {
1077             str_scat(str,fstr=walk(0,level,ops[node+1].ival,&numarg,P_MIN));
1078             str_free(fstr);
1079             if (len >= 2) {
1080                 tmpstr = walk(0,level,ops[node+2].ival,&numarg,P_MIN);
1081                 if (*tmpstr->str_ptr == ';') {
1082                     addsemi(str);
1083                     str_cat(str,tmpstr->str_ptr+1);
1084                 }
1085                 str_free(tmpstr);
1086             }
1087         }
1088         break;
1089     case OCLOSE:
1090         str = str_make("close(");
1091         tmpstr = walk(1,level,ops[node+1].ival,&numarg,P_MIN);
1092         if (!do_fancy_opens) {
1093             t = tmpstr->str_ptr;
1094             if (*t == '"' || *t == '\'')
1095                 t = cpytill(tokenbuf,t+1,*t);
1096             else
1097                 fatal("Internal error: OCLOSE %s",t);
1098             s = savestr(tokenbuf);
1099             for (t = tokenbuf; *t; t++) {
1100                 *t &= 127;
1101                 if (!isalpha(*t) && !isdigit(*t))
1102                     *t = '_';
1103             }
1104             if (!index(tokenbuf,'_'))
1105                 strcpy(t,"_fh");
1106             str_free(tmpstr);
1107             safefree(s);
1108             str_set(str,"close ");
1109             str_cat(str,tokenbuf);
1110         }
1111         else {
1112             sprintf(tokenbuf,"$fh = delete $opened{%s} && close($fh)",
1113                tmpstr->str_ptr);
1114             str_free(tmpstr);
1115             str_set(str,tokenbuf);
1116         }
1117         break;
1118     case OPRINTF:
1119     case OPRINT:
1120         lparen = "";    /* set to parens if necessary */
1121         rparen = "";
1122         str = str_new(0);
1123         if (len == 3) {         /* output redirection */
1124             tmpstr = walk(1,level,ops[node+3].ival,&numarg,P_MIN);
1125             tmp2str = walk(1,level,ops[node+2].ival,&numarg,P_MIN);
1126             if (!do_fancy_opens) {
1127                 t = tmpstr->str_ptr;
1128                 if (*t == '"' || *t == '\'')
1129                     t = cpytill(tokenbuf,t+1,*t);
1130                 else
1131                     fatal("Internal error: OPRINT");
1132                 d = savestr(t);
1133                 s = savestr(tokenbuf);
1134                 for (t = tokenbuf; *t; t++) {
1135                     *t &= 127;
1136                     if (!isalpha(*t) && !isdigit(*t))
1137                         *t = '_';
1138                 }
1139                 if (!index(tokenbuf,'_'))
1140                     strcpy(t,"_fh");
1141                 tmp3str = hfetch(symtab,tokenbuf);
1142                 if (!tmp3str) {
1143                     str_cat(opens,"open(");
1144                     str_cat(opens,tokenbuf);
1145                     str_cat(opens,", ");
1146                     d[1] = '\0';
1147                     str_cat(opens,d);
1148                     str_scat(opens,tmp2str);
1149                     str_cat(opens,tmpstr->str_ptr+1);
1150                     if (*tmp2str->str_ptr == '|')
1151                         str_cat(opens,") || die 'Cannot pipe to \"");
1152                     else
1153                         str_cat(opens,") || die 'Cannot create file \"");
1154                     if (*d == '"')
1155                         str_cat(opens,"'.\"");
1156                     str_cat(opens,s);
1157                     if (*d == '"')
1158                         str_cat(opens,"\".'");
1159                     str_cat(opens,"\".';\n");
1160                     hstore(symtab,tokenbuf,str_make("x"));
1161                 }
1162                 str_free(tmpstr);
1163                 str_free(tmp2str);
1164                 safefree(s);
1165                 safefree(d);
1166             }
1167             else {
1168                 sprintf(tokenbuf,"&Pick('%s', %s) &&\n",
1169                    tmp2str->str_ptr, tmpstr->str_ptr);
1170                 str_cat(str,tokenbuf);
1171                 tab(str,level+1);
1172                 strcpy(tokenbuf,"$fh");
1173                 str_free(tmpstr);
1174                 str_free(tmp2str);
1175                 lparen = "(";
1176                 rparen = ")";
1177             }
1178         }
1179         else
1180             strcpy(tokenbuf,"");
1181         str_cat(str,lparen);    /* may be null */
1182         if (type == OPRINTF)
1183             str_cat(str,"printf");
1184         else
1185             str_cat(str,"print");
1186         if (len == 3 || do_fancy_opens) {
1187             if (*tokenbuf)
1188                 str_cat(str," ");
1189             str_cat(str,tokenbuf);
1190         }
1191         tmpstr = walk(1+(type==OPRINT),level,ops[node+1].ival,&numarg,P_MIN);
1192         if (!*tmpstr->str_ptr && lval_field) {
1193             t = saw_OFS ? "$," : "' '";
1194             if (split_to_array) {
1195                 sprintf(tokenbuf,"join(%s,@Fld)",t);
1196                 str_cat(tmpstr,tokenbuf);
1197             }
1198             else {
1199                 for (i = 1; i < maxfld; i++) {
1200                     if (i <= arymax)
1201                         sprintf(tokenbuf,"$%s, ",nameary[i]);
1202                     else
1203                         sprintf(tokenbuf,"$Fld%d, ",i);
1204                     str_cat(tmpstr,tokenbuf);
1205                 }
1206                 if (maxfld <= arymax)
1207                     sprintf(tokenbuf,"$%s",nameary[maxfld]);
1208                 else
1209                     sprintf(tokenbuf,"$Fld%d",maxfld);
1210                 str_cat(tmpstr,tokenbuf);
1211             }
1212         }
1213         if (*tmpstr->str_ptr) {
1214             str_cat(str," ");
1215             str_scat(str,tmpstr);
1216         }
1217         else {
1218             str_cat(str," $_");
1219         }
1220         str_cat(str,rparen);    /* may be null */
1221         str_free(tmpstr);
1222         break;
1223     case ORAND:
1224         str = str_make("rand(1)");
1225         break;
1226     case OSRAND:
1227         str = str_make("srand(");
1228         goto maybe0;
1229     case OATAN2:
1230         str = str_make("atan2(");
1231         goto maybe0;
1232     case OSIN:
1233         str = str_make("sin(");
1234         goto maybe0;
1235     case OCOS:
1236         str = str_make("cos(");
1237         goto maybe0;
1238     case OSYSTEM:
1239         str = str_make("system(");
1240         goto maybe0;
1241     case OLENGTH:
1242         str = str_make("length(");
1243         goto maybe0;
1244     case OLOG:
1245         str = str_make("log(");
1246         goto maybe0;
1247     case OEXP:
1248         str = str_make("exp(");
1249         goto maybe0;
1250     case OSQRT:
1251         str = str_make("sqrt(");
1252         goto maybe0;
1253     case OINT:
1254         str = str_make("int(");
1255       maybe0:
1256         numeric = 1;
1257         if (len > 0)
1258             tmpstr = walk(1,level,ops[node+1].ival,&numarg,P_MIN);
1259         else
1260             tmpstr = str_new(0);;
1261         if (!*tmpstr->str_ptr) {
1262             if (lval_field) {
1263                 t = saw_OFS ? "$," : "' '";
1264                 if (split_to_array) {
1265                     sprintf(tokenbuf,"join(%s,@Fld)",t);
1266                     str_cat(tmpstr,tokenbuf);
1267                 }
1268                 else {
1269                     sprintf(tokenbuf,"join(%s, ",t);
1270                     str_cat(tmpstr,tokenbuf);
1271                     for (i = 1; i < maxfld; i++) {
1272                         if (i <= arymax)
1273                             sprintf(tokenbuf,"$%s,",nameary[i]);
1274                         else
1275                             sprintf(tokenbuf,"$Fld%d,",i);
1276                         str_cat(tmpstr,tokenbuf);
1277                     }
1278                     if (maxfld <= arymax)
1279                         sprintf(tokenbuf,"$%s)",nameary[maxfld]);
1280                     else
1281                         sprintf(tokenbuf,"$Fld%d)",maxfld);
1282                     str_cat(tmpstr,tokenbuf);
1283                 }
1284             }
1285             else
1286                 str_cat(tmpstr,"$_");
1287         }
1288         if (strEQ(tmpstr->str_ptr,"$_")) {
1289             if (type == OLENGTH && !do_chop) {
1290                 str = str_make("(length(");
1291                 str_cat(tmpstr,") - 1");
1292             }
1293         }
1294         str_scat(str,tmpstr);
1295         str_free(tmpstr);
1296         str_cat(str,")");
1297         break;
1298     case OBREAK:
1299         str = str_new(0);
1300         str_set(str,"last");
1301         break;
1302     case ONEXT:
1303         str = str_new(0);
1304         str_set(str,"next line");
1305         break;
1306     case OEXIT:
1307         str = str_new(0);
1308         if (realexit) {
1309             prec = P_UNI;
1310             str_set(str,"exit");
1311             if (len == 1) {
1312                 str_cat(str," ");
1313                 exitval = TRUE;
1314                 str_scat(str,
1315                   fstr=walk(1,level,ops[node+1].ival,&numarg,prec+1));
1316                 str_free(fstr);
1317             }
1318         }
1319         else {
1320             if (len == 1) {
1321                 str_set(str,"ExitValue = ");
1322                 exitval = TRUE;
1323                 str_scat(str,
1324                   fstr=walk(1,level,ops[node+1].ival,&numarg,P_ASSIGN));
1325                 str_free(fstr);
1326                 str_cat(str,"; ");
1327             }
1328             str_cat(str,"last line");
1329         }
1330         break;
1331     case OCONTINUE:
1332         str = str_new(0);
1333         str_set(str,"next");
1334         break;
1335     case OREDIR:
1336         goto def;
1337     case OIF:
1338         str = str_new(0);
1339         str_set(str,"if (");
1340         str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN));
1341         str_free(fstr);
1342         str_cat(str,") ");
1343         str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg,P_MIN));
1344         str_free(fstr);
1345         if (len == 3) {
1346             i = ops[node+3].ival;
1347             if (i) {
1348                 if ((ops[i].ival & 255) == OBLOCK) {
1349                     i = ops[i+1].ival;
1350                     if (i) {
1351                         if ((ops[i].ival & 255) != OIF)
1352                             i = 0;
1353                     }
1354                 }
1355                 else
1356                     i = 0;
1357             }
1358             if (i) {
1359                 str_cat(str,"els");
1360                 str_scat(str,fstr=walk(0,level,i,&numarg,P_MIN));
1361                 str_free(fstr);
1362             }
1363             else {
1364                 str_cat(str,"else ");
1365                 str_scat(str,fstr=walk(0,level,ops[node+3].ival,&numarg,P_MIN));
1366                 str_free(fstr);
1367             }
1368         }
1369         break;
1370     case OWHILE:
1371         str = str_new(0);
1372         str_set(str,"while (");
1373         str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN));
1374         str_free(fstr);
1375         str_cat(str,") ");
1376         str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg,P_MIN));
1377         str_free(fstr);
1378         break;
1379     case OFOR:
1380         str = str_new(0);
1381         str_set(str,"for (");
1382         str_scat(str,tmpstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN));
1383         i = numarg;
1384         if (i) {
1385             t = s = tmpstr->str_ptr;
1386             while (isalpha(*t) || isdigit(*t) || *t == '$' || *t == '_')
1387                 t++;
1388             i = t - s;
1389             if (i < 2)
1390                 i = 0;
1391         }
1392         str_cat(str,"; ");
1393         fstr=walk(1,level,ops[node+2].ival,&numarg,P_MIN);
1394         if (i && (t = index(fstr->str_ptr,0377))) {
1395             if (strnEQ(fstr->str_ptr,s,i))
1396                 *t = ' ';
1397         }
1398         str_scat(str,fstr);
1399         str_free(fstr);
1400         str_free(tmpstr);
1401         str_cat(str,"; ");
1402         str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,P_MIN));
1403         str_free(fstr);
1404         str_cat(str,") ");
1405         str_scat(str,fstr=walk(0,level,ops[node+4].ival,&numarg,P_MIN));
1406         str_free(fstr);
1407         break;
1408     case OFORIN:
1409         tmpstr = walk(0,level,ops[node+1].ival,&numarg,P_MIN);
1410         d = index(tmpstr->str_ptr,'$');
1411         if (!d)
1412             fatal("Illegal for loop: %s",tmpstr->str_ptr);
1413         s = index(d,'{');
1414         if (!s)
1415             s = index(d,'[');
1416         if (!s)
1417             fatal("Illegal for loop: %s",d);
1418         *s++ = '\0';
1419         t = index(s,'}' + 128);
1420         if (!t)
1421             t = index(s,']' + 128);
1422         if (t)
1423             *t = '\0';
1424         str = str_new(0);
1425         str_set(str,d+1);
1426         str_cat(str,"[]");
1427         tmp2str = hfetch(symtab,str->str_ptr);
1428         if (tmp2str && atoi(tmp2str->str_ptr)) {
1429             sprintf(tokenbuf,
1430               "foreach %s (@%s) ",
1431               s,
1432               d+1);
1433         }
1434         else {
1435             sprintf(tokenbuf,
1436               "foreach %s (keys %%%s) ",
1437               s,
1438               d+1);
1439         }
1440         str_set(str,tokenbuf);
1441         str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg,P_MIN));
1442         str_free(fstr);
1443         str_free(tmpstr);
1444         break;
1445     case OBLOCK:
1446         str = str_new(0);
1447         str_set(str,"{");
1448         if (len >= 2 && ops[node+2].ival) {
1449             str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg,P_MIN));
1450             str_free(fstr);
1451         }
1452         fixtab(str,++level);
1453         str_scat(str,fstr=walk(0,level,ops[node+1].ival,&numarg,P_MIN));
1454         str_free(fstr);
1455         addsemi(str);
1456         fixtab(str,--level);
1457         str_cat(str,"}\n");
1458         tab(str,level);
1459         if (len >= 3) {
1460             str_scat(str,fstr=walk(0,level,ops[node+3].ival,&numarg,P_MIN));
1461             str_free(fstr);
1462         }
1463         break;
1464     default:
1465       def:
1466         if (len) {
1467             if (len > 5)
1468                 fatal("Garbage length in walk");
1469             str = walk(0,level,ops[node+1].ival,&numarg,P_MIN);
1470             for (i = 2; i<= len; i++) {
1471                 str_scat(str,fstr=walk(0,level,ops[node+i].ival,&numarg,P_MIN));
1472                 str_free(fstr);
1473             }
1474         }
1475         else {
1476             str = Nullstr;
1477         }
1478         break;
1479     }
1480     if (!str)
1481         str = str_new(0);
1482
1483     if (useval && prec < minprec) {             /* need parens? */
1484         fstr = str_new(str->str_cur+2);
1485         str_nset(fstr,"(",1);
1486         str_scat(fstr,str);
1487         str_ncat(fstr,")",1);
1488         str_free(str);
1489         str = fstr;
1490     }
1491
1492     *numericptr = numeric;
1493 #ifdef DEBUGGING
1494     if (debug & 4) {
1495         printf("%3d %5d %15s %d %4d ",level,node,opname[type],len,str->str_cur);
1496         for (t = str->str_ptr; *t && t - str->str_ptr < 40; t++)
1497             if (*t == '\n')
1498                 printf("\\n");
1499             else if (*t == '\t')
1500                 printf("\\t");
1501             else
1502                 putchar(*t);
1503         putchar('\n');
1504     }
1505 #endif
1506     return str;
1507 }
1508
1509 tab(str,lvl)
1510 register STR *str;
1511 register int lvl;
1512 {
1513     while (lvl > 1) {
1514         str_cat(str,"\t");
1515         lvl -= 2;
1516     }
1517     if (lvl)
1518         str_cat(str,"    ");
1519 }
1520
1521 fixtab(str,lvl)
1522 register STR *str;
1523 register int lvl;
1524 {
1525     register char *s;
1526
1527     /* strip trailing white space */
1528
1529     s = str->str_ptr+str->str_cur - 1;
1530     while (s >= str->str_ptr && (*s == ' ' || *s == '\t' || *s == '\n'))
1531         s--;
1532     s[1] = '\0';
1533     str->str_cur = s + 1 - str->str_ptr;
1534     if (s >= str->str_ptr && *s != '\n')
1535         str_cat(str,"\n");
1536
1537     tab(str,lvl);
1538 }
1539
1540 addsemi(str)
1541 register STR *str;
1542 {
1543     register char *s;
1544
1545     s = str->str_ptr+str->str_cur - 1;
1546     while (s >= str->str_ptr && (*s == ' ' || *s == '\t' || *s == '\n'))
1547         s--;
1548     if (s >= str->str_ptr && *s != ';' && *s != '}')
1549         str_cat(str,";");
1550 }
1551
1552 emit_split(str,level)
1553 register STR *str;
1554 int level;
1555 {
1556     register int i;
1557
1558     if (split_to_array)
1559         str_cat(str,"@Fld");
1560     else {
1561         str_cat(str,"(");
1562         for (i = 1; i < maxfld; i++) {
1563             if (i <= arymax)
1564                 sprintf(tokenbuf,"$%s,",nameary[i]);
1565             else
1566                 sprintf(tokenbuf,"$Fld%d,",i);
1567             str_cat(str,tokenbuf);
1568         }
1569         if (maxfld <= arymax)
1570             sprintf(tokenbuf,"$%s)",nameary[maxfld]);
1571         else
1572             sprintf(tokenbuf,"$Fld%d)",maxfld);
1573         str_cat(str,tokenbuf);
1574     }
1575     if (const_FS) {
1576         sprintf(tokenbuf," = split(/[%c\\n]/, $_, 999);\n",const_FS);
1577         str_cat(str,tokenbuf);
1578     }
1579     else if (saw_FS)
1580         str_cat(str," = split($FS, $_, 999);\n");
1581     else
1582         str_cat(str," = split(' ', $_, 999);\n");
1583     tab(str,level);
1584 }
1585
1586 prewalk(numit,level,node,numericptr)
1587 int numit;
1588 int level;
1589 register int node;
1590 int *numericptr;
1591 {
1592     register int len;
1593     register int type;
1594     register int i;
1595     char *t;
1596     char *d, *s;
1597     int numarg;
1598     int numeric = FALSE;
1599     STR *tmpstr;
1600     STR *tmp2str;
1601
1602     if (!node) {
1603         *numericptr = 0;
1604         return 0;
1605     }
1606     type = ops[node].ival;
1607     len = type >> 8;
1608     type &= 255;
1609     switch (type) {
1610     case OPROG:
1611         prewalk(0,level,ops[node+1].ival,&numarg);
1612         if (ops[node+2].ival) {
1613             prewalk(0,level,ops[node+2].ival,&numarg);
1614         }
1615         ++level;
1616         prewalk(0,level,ops[node+3].ival,&numarg);
1617         --level;
1618         if (ops[node+3].ival) {
1619             prewalk(0,level,ops[node+4].ival,&numarg);
1620         }
1621         break;
1622     case OHUNKS:
1623         prewalk(0,level,ops[node+1].ival,&numarg);
1624         prewalk(0,level,ops[node+2].ival,&numarg);
1625         if (len == 3) {
1626             prewalk(0,level,ops[node+3].ival,&numarg);
1627         }
1628         break;
1629     case ORANGE:
1630         prewalk(1,level,ops[node+1].ival,&numarg);
1631         prewalk(1,level,ops[node+2].ival,&numarg);
1632         break;
1633     case OPAT:
1634         goto def;
1635     case OREGEX:
1636         prewalk(0,level,ops[node+1].ival,&numarg);
1637         break;
1638     case OHUNK:
1639         if (len == 1) {
1640             prewalk(0,level,ops[node+1].ival,&numarg);
1641         }
1642         else {
1643             i = prewalk(0,level,ops[node+1].ival,&numarg);
1644             if (i) {
1645                 ++level;
1646                 prewalk(0,level,ops[node+2].ival,&numarg);
1647                 --level;
1648             }
1649             else {
1650                 prewalk(0,level,ops[node+2].ival,&numarg);
1651             }
1652         }
1653         break;
1654     case OPPAREN:
1655         prewalk(0,level,ops[node+1].ival,&numarg);
1656         break;
1657     case OPANDAND:
1658         prewalk(0,level,ops[node+1].ival,&numarg);
1659         prewalk(0,level,ops[node+2].ival,&numarg);
1660         break;
1661     case OPOROR:
1662         prewalk(0,level,ops[node+1].ival,&numarg);
1663         prewalk(0,level,ops[node+2].ival,&numarg);
1664         break;
1665     case OPNOT:
1666         prewalk(0,level,ops[node+1].ival,&numarg);
1667         break;
1668     case OCPAREN:
1669         prewalk(0,level,ops[node+1].ival,&numarg);
1670         numeric |= numarg;
1671         break;
1672     case OCANDAND:
1673         prewalk(0,level,ops[node+1].ival,&numarg);
1674         numeric = 1;
1675         prewalk(0,level,ops[node+2].ival,&numarg);
1676         break;
1677     case OCOROR:
1678         prewalk(0,level,ops[node+1].ival,&numarg);
1679         numeric = 1;
1680         prewalk(0,level,ops[node+2].ival,&numarg);
1681         break;
1682     case OCNOT:
1683         prewalk(0,level,ops[node+1].ival,&numarg);
1684         numeric = 1;
1685         break;
1686     case ORELOP:
1687         prewalk(0,level,ops[node+2].ival,&numarg);
1688         numeric |= numarg;
1689         prewalk(0,level,ops[node+1].ival,&numarg);
1690         prewalk(0,level,ops[node+3].ival,&numarg);
1691         numeric |= numarg;
1692         numeric = 1;
1693         break;
1694     case ORPAREN:
1695         prewalk(0,level,ops[node+1].ival,&numarg);
1696         numeric |= numarg;
1697         break;
1698     case OMATCHOP:
1699         prewalk(0,level,ops[node+2].ival,&numarg);
1700         prewalk(0,level,ops[node+1].ival,&numarg);
1701         prewalk(0,level,ops[node+3].ival,&numarg);
1702         numeric = 1;
1703         break;
1704     case OMPAREN:
1705         prewalk(0,level,ops[node+1].ival,&numarg);
1706         numeric |= numarg;
1707         break;
1708     case OCONCAT:
1709         prewalk(0,level,ops[node+1].ival,&numarg);
1710         prewalk(0,level,ops[node+2].ival,&numarg);
1711         break;
1712     case OASSIGN:
1713         prewalk(0,level,ops[node+2].ival,&numarg);
1714         prewalk(0,level,ops[node+1].ival,&numarg);
1715         prewalk(0,level,ops[node+3].ival,&numarg);
1716         if (numarg || strlen(ops[ops[node+1].ival+1].cval) > 1) {
1717             numericize(ops[node+2].ival);
1718             if (!numarg)
1719                 numericize(ops[node+3].ival);
1720         }
1721         numeric |= numarg;
1722         break;
1723     case OADD:
1724         prewalk(1,level,ops[node+1].ival,&numarg);
1725         prewalk(1,level,ops[node+2].ival,&numarg);
1726         numeric = 1;
1727         break;
1728     case OSUBTRACT:
1729         prewalk(1,level,ops[node+1].ival,&numarg);
1730         prewalk(1,level,ops[node+2].ival,&numarg);
1731         numeric = 1;
1732         break;
1733     case OMULT:
1734         prewalk(1,level,ops[node+1].ival,&numarg);
1735         prewalk(1,level,ops[node+2].ival,&numarg);
1736         numeric = 1;
1737         break;
1738     case ODIV:
1739         prewalk(1,level,ops[node+1].ival,&numarg);
1740         prewalk(1,level,ops[node+2].ival,&numarg);
1741         numeric = 1;
1742         break;
1743     case OPOW:
1744         prewalk(1,level,ops[node+1].ival,&numarg);
1745         prewalk(1,level,ops[node+2].ival,&numarg);
1746         numeric = 1;
1747         break;
1748     case OMOD:
1749         prewalk(1,level,ops[node+1].ival,&numarg);
1750         prewalk(1,level,ops[node+2].ival,&numarg);
1751         numeric = 1;
1752         break;
1753     case OPOSTINCR:
1754         prewalk(1,level,ops[node+1].ival,&numarg);
1755         numeric = 1;
1756         break;
1757     case OPOSTDECR:
1758         prewalk(1,level,ops[node+1].ival,&numarg);
1759         numeric = 1;
1760         break;
1761     case OPREINCR:
1762         prewalk(1,level,ops[node+1].ival,&numarg);
1763         numeric = 1;
1764         break;
1765     case OPREDECR:
1766         prewalk(1,level,ops[node+1].ival,&numarg);
1767         numeric = 1;
1768         break;
1769     case OUMINUS:
1770         prewalk(1,level,ops[node+1].ival,&numarg);
1771         numeric = 1;
1772         break;
1773     case OUPLUS:
1774         prewalk(1,level,ops[node+1].ival,&numarg);
1775         numeric = 1;
1776         break;
1777     case OPAREN:
1778         prewalk(0,level,ops[node+1].ival,&numarg);
1779         numeric |= numarg;
1780         break;
1781     case OGETLINE:
1782         break;
1783     case OSPRINTF:
1784         prewalk(0,level,ops[node+1].ival,&numarg);
1785         break;
1786     case OSUBSTR:
1787         prewalk(0,level,ops[node+1].ival,&numarg);
1788         prewalk(1,level,ops[node+2].ival,&numarg);
1789         if (len == 3) {
1790             prewalk(1,level,ops[node+3].ival,&numarg);
1791         }
1792         break;
1793     case OSTRING:
1794         break;
1795     case OSPLIT:
1796         numeric = 1;
1797         prewalk(0,level,ops[node+2].ival,&numarg);
1798         if (len == 3)
1799             prewalk(0,level,ops[node+3].ival,&numarg);
1800         prewalk(0,level,ops[node+1].ival,&numarg);
1801         break;
1802     case OINDEX:
1803         prewalk(0,level,ops[node+1].ival,&numarg);
1804         prewalk(0,level,ops[node+2].ival,&numarg);
1805         numeric = 1;
1806         break;
1807     case OMATCH:
1808         prewalk(0,level,ops[node+1].ival,&numarg);
1809         prewalk(0,level,ops[node+2].ival,&numarg);
1810         numeric = 1;
1811         break;
1812     case OUSERDEF:
1813         subretnum = FALSE;
1814         --level;
1815         tmpstr = walk(0,level,ops[node+1].ival,&numarg,P_MIN);
1816         ++level;
1817         prewalk(0,level,ops[node+2].ival,&numarg);
1818         prewalk(0,level,ops[node+4].ival,&numarg);
1819         prewalk(0,level,ops[node+5].ival,&numarg);
1820         --level;
1821         str_cat(tmpstr,"(");
1822         tmp2str = str_new(0);
1823         if (subretnum || numarg)
1824             str_set(tmp2str,"1");
1825         hstore(symtab,tmpstr->str_ptr,tmp2str);
1826         str_free(tmpstr);
1827         level++;
1828         break;
1829     case ORETURN:
1830         if (len > 0) {
1831             prewalk(0,level,ops[node+1].ival,&numarg);
1832             if (numarg)
1833                 subretnum = TRUE;
1834         }
1835         break;
1836     case OUSERFUN:
1837         tmp2str = str_new(0);
1838         str_scat(tmp2str,tmpstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN));
1839         fixrargs(tmpstr->str_ptr,ops[node+2],0);
1840         str_free(tmpstr);
1841         str_cat(tmp2str,"(");
1842         tmpstr = hfetch(symtab,tmp2str->str_ptr);
1843         if (tmpstr && tmpstr->str_ptr)
1844             numeric |= atoi(tmpstr->str_ptr);
1845         prewalk(0,level,ops[node+2].ival,&numarg);
1846         str_free(tmp2str);
1847         break;
1848     case OGSUB:
1849     case OSUB:
1850         if (len >= 3)
1851             prewalk(0,level,ops[node+3].ival,&numarg);
1852         prewalk(0,level,ops[ops[node+2].ival+1].ival,&numarg);
1853         prewalk(0,level,ops[node+1].ival,&numarg);
1854         numeric = 1;
1855         break;
1856     case ONUM:
1857         prewalk(0,level,ops[node+1].ival,&numarg);
1858         numeric = 1;
1859         break;
1860     case OSTR:
1861         prewalk(0,level,ops[node+1].ival,&numarg);
1862         break;
1863     case ODEFINED:
1864     case ODELETE:
1865     case OSTAR:
1866     case OVAR:
1867         prewalk(0,level,ops[node+1].ival,&numarg);
1868         if (len == 1) {
1869             if (numit)
1870                 numericize(node);
1871         }
1872         else {
1873             prewalk(0,level,ops[node+2].ival,&numarg);
1874         }
1875         break;
1876     case OFLD:
1877         prewalk(0,level,ops[node+1].ival,&numarg);
1878         break;
1879     case OVFLD:
1880         i = ops[node+1].ival;
1881         prewalk(0,level,i,&numarg);
1882         break;
1883     case OJUNK:
1884         goto def;
1885     case OSNEWLINE:
1886         break;
1887     case ONEWLINE:
1888         break;
1889     case OSCOMMENT:
1890         break;
1891     case OCOMMENT:
1892         break;
1893     case OCOMMA:
1894         prewalk(0,level,ops[node+1].ival,&numarg);
1895         prewalk(0,level,ops[node+2].ival,&numarg);
1896         prewalk(0,level,ops[node+3].ival,&numarg);
1897         break;
1898     case OSEMICOLON:
1899         break;
1900     case OSTATES:
1901         prewalk(0,level,ops[node+1].ival,&numarg);
1902         prewalk(0,level,ops[node+2].ival,&numarg);
1903         break;
1904     case OSTATE:
1905         if (len >= 1) {
1906             prewalk(0,level,ops[node+1].ival,&numarg);
1907             if (len >= 2) {
1908                 prewalk(0,level,ops[node+2].ival,&numarg);
1909             }
1910         }
1911         break;
1912     case OCLOSE:
1913         prewalk(0,level,ops[node+1].ival,&numarg);
1914         break;
1915     case OPRINTF:
1916     case OPRINT:
1917         if (len == 3) {         /* output redirection */
1918             prewalk(0,level,ops[node+3].ival,&numarg);
1919             prewalk(0,level,ops[node+2].ival,&numarg);
1920         }
1921         prewalk(0+(type==OPRINT),level,ops[node+1].ival,&numarg);
1922         break;
1923     case ORAND:
1924         break;
1925     case OSRAND:
1926         goto maybe0;
1927     case OATAN2:
1928         goto maybe0;
1929     case OSIN:
1930         goto maybe0;
1931     case OCOS:
1932         goto maybe0;
1933     case OSYSTEM:
1934         goto maybe0;
1935     case OLENGTH:
1936         goto maybe0;
1937     case OLOG:
1938         goto maybe0;
1939     case OEXP:
1940         goto maybe0;
1941     case OSQRT:
1942         goto maybe0;
1943     case OINT:
1944       maybe0:
1945         numeric = 1;
1946         if (len > 0)
1947             prewalk(type != OLENGTH && type != OSYSTEM,
1948               level,ops[node+1].ival,&numarg);
1949         break;
1950     case OBREAK:
1951         break;
1952     case ONEXT:
1953         break;
1954     case OEXIT:
1955         if (len == 1) {
1956             prewalk(1,level,ops[node+1].ival,&numarg);
1957         }
1958         break;
1959     case OCONTINUE:
1960         break;
1961     case OREDIR:
1962         goto def;
1963     case OIF:
1964         prewalk(0,level,ops[node+1].ival,&numarg);
1965         prewalk(0,level,ops[node+2].ival,&numarg);
1966         if (len == 3) {
1967             prewalk(0,level,ops[node+3].ival,&numarg);
1968         }
1969         break;
1970     case OWHILE:
1971         prewalk(0,level,ops[node+1].ival,&numarg);
1972         prewalk(0,level,ops[node+2].ival,&numarg);
1973         break;
1974     case OFOR:
1975         prewalk(0,level,ops[node+1].ival,&numarg);
1976         prewalk(0,level,ops[node+2].ival,&numarg);
1977         prewalk(0,level,ops[node+3].ival,&numarg);
1978         prewalk(0,level,ops[node+4].ival,&numarg);
1979         break;
1980     case OFORIN:
1981         prewalk(0,level,ops[node+2].ival,&numarg);
1982         prewalk(0,level,ops[node+1].ival,&numarg);
1983         break;
1984     case OBLOCK:
1985         if (len == 2) {
1986             prewalk(0,level,ops[node+2].ival,&numarg);
1987         }
1988         ++level;
1989         prewalk(0,level,ops[node+1].ival,&numarg);
1990         --level;
1991         break;
1992     default:
1993       def:
1994         if (len) {
1995             if (len > 5)
1996                 fatal("Garbage length in prewalk");
1997             prewalk(0,level,ops[node+1].ival,&numarg);
1998             for (i = 2; i<= len; i++) {
1999                 prewalk(0,level,ops[node+i].ival,&numarg);
2000             }
2001         }
2002         break;
2003     }
2004     *numericptr = numeric;
2005     return 1;
2006 }
2007
2008 numericize(node)
2009 register int node;
2010 {
2011     register int len;
2012     register int type;
2013     register int i;
2014     STR *tmpstr;
2015     STR *tmp2str;
2016     int numarg;
2017
2018     type = ops[node].ival;
2019     len = type >> 8;
2020     type &= 255;
2021     if (type == OVAR && len == 1) {
2022         tmpstr=walk(0,0,ops[node+1].ival,&numarg,P_MIN);
2023         tmp2str = str_make("1");
2024         hstore(symtab,tmpstr->str_ptr,tmp2str);
2025     }
2026 }