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