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