4d5f1d3a5e636645bb4361485965f20bdb1353e3
[p5sagit/p5-mst-13.2.git] / x2p / walk.c
1 /* $RCSfile: walk.c,v $$Revision: 4.1 $$Date: 92/08/07 18:29:31 $
2  *
3  *    Copyright (c) 1991-2001, 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 = 0;
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 += 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         if (type == OGSUB)
827             s = "g";
828         else
829             s = "";
830         str = str_new(0);
831         tmpstr = str_new(0);
832         i = 0;
833         if (len == 3) {
834             tmpstr = walk(1,level,ops[node+3].ival,&numarg,P_MATCH+1);
835             if (strNE(tmpstr->str_ptr,"$_")) {
836                 str_cat(tmpstr, " =~ s");
837                 i++;
838             }
839             else
840                 str_set(tmpstr, "s");
841         }
842         else
843             str_set(tmpstr, "s");
844         type = ops[ops[node+2].ival].ival;
845         len = type >> 8;
846         type &= 255;
847         tmp3str = str_new(0);
848         if (type == OSTR) {
849             tmp2str=walk(1,level,ops[ops[node+2].ival+1].ival,&numarg,P_MIN);
850             for (t = tmp2str->str_ptr, d=tokenbuf; *t; d++,t++) {
851                 if (*t == '&')
852                     *d++ = '$' + 128;
853                 else if (*t == '$')
854                     *d++ = '\\' + 128;
855                 *d = *t + 128;
856             }
857             *d = '\0';
858             str_set(tmp2str,tokenbuf);
859         }
860         else {
861             tmp2str=walk(1,level,ops[node+2].ival,&numarg,P_MIN);
862             str_set(tmp3str,"($s_ = '\"'.(");
863             str_scat(tmp3str,tmp2str);
864             str_cat(tmp3str,").'\"') =~ s/&/\\$&/g, ");
865             str_set(tmp2str,"eval $s_");
866             s = (char*)(*s == 'g' ? "ge" : "e");
867             i++;
868         }
869         type = ops[ops[node+1].ival].ival;
870         len = type >> 8;
871         type &= 255;
872         fstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN);
873         if (type == OREGEX) {
874             if (useval && i)
875                 str_cat(str,"(");
876             str_scat(str,tmp3str);
877             str_scat(str,tmpstr);
878             str_scat(str,fstr);
879             str_scat(str,tmp2str);
880             str_cat(str,"/");
881             str_cat(str,s);
882         }
883         else if ((type == OFLD && !split_to_array) || (type == OVAR && len == 1)) {
884             if (useval && i)
885                 str_cat(str,"(");
886             str_scat(str,tmp3str);
887             str_scat(str,tmpstr);
888             str_cat(str,"/");
889             str_scat(str,fstr);
890             str_cat(str,"/");
891             str_scat(str,tmp2str);
892             str_cat(str,"/");
893             str_cat(str,s);
894         }
895         else {
896             i++;
897             if (useval)
898                 str_cat(str,"(");
899             str_cat(str,"$s = ");
900             str_scat(str,fstr);
901             str_cat(str,", ");
902             str_scat(str,tmp3str);
903             str_scat(str,tmpstr);
904             str_cat(str,"/$s/");
905             str_scat(str,tmp2str);
906             str_cat(str,"/");
907             str_cat(str,s);
908         }
909         if (useval && i)
910             str_cat(str,")");
911         str_free(fstr);
912         str_free(tmpstr);
913         str_free(tmp2str);
914         str_free(tmp3str);
915         numeric = 1;
916         break;
917     case ONUM:
918         str = walk(1,level,ops[node+1].ival,&numarg,P_MIN);
919         numeric = 1;
920         break;
921     case OSTR:
922         tmpstr = walk(1,level,ops[node+1].ival,&numarg,P_MIN);
923         s = "'";
924         for (t = tmpstr->str_ptr, d=tokenbuf; *t; d++,t++) {
925             if (*t == '\'')
926                 s = "\"";
927             else if (*t == '\\') {
928                 s = "\"";
929                 *d++ = *t++ + 128;
930                 switch (*t) {
931                 case '\\': case '"': case 'n': case 't': case '$':
932                     break;
933                 default:        /* hide this from perl */
934                     *d++ = '\\' + 128;
935                 }
936             }
937             *d = *t + 128;
938         }
939         *d = '\0';
940         str = str_new(0);
941         str_set(str,s);
942         str_cat(str,tokenbuf);
943         str_free(tmpstr);
944         str_cat(str,s);
945         break;
946     case ODEFINED:
947         prec = P_UNI;
948         str = str_new(0);
949         str_set(str,"defined $");
950         goto addvar;
951     case ODELETE:
952         str = str_new(0);
953         str_set(str,"delete $");
954         goto addvar;
955     case OSTAR:
956         str = str_new(0);
957         str_set(str,"*");
958         goto addvar;
959     case OVAR:
960         str = str_new(0);
961         str_set(str,"$");
962       addvar:
963         str_scat(str,tmpstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN));
964         if (len == 1) {
965             tmp2str = hfetch(symtab,tmpstr->str_ptr);
966             if (tmp2str && atoi(tmp2str->str_ptr))
967                 numeric = 2;
968             if (strEQ(str->str_ptr,"$FNR")) {
969                 numeric = 1;
970                 saw_FNR++;
971                 str_set(str,"($.-$FNRbase)");
972             }
973             else if (strEQ(str->str_ptr,"$NR")) {
974                 numeric = 1;
975                 str_set(str,"$.");
976             }
977             else if (strEQ(str->str_ptr,"$NF")) {
978                 numeric = 1;
979                 str_set(str,"$#Fld");
980             }
981             else if (strEQ(str->str_ptr,"$0"))
982                 str_set(str,"$_");
983             else if (strEQ(str->str_ptr,"$ARGC"))
984                 str_set(str,"($#ARGV+1)");
985         }
986         else {
987 #ifdef NOTDEF
988             if (curargs) {
989                 sprintf(tokenbuf,"$%s,",tmpstr->str_ptr);
990         ???     if (instr(curargs->str_ptr,tokenbuf))
991                     str_cat(str,"\377");        /* can't translate yet */
992             }
993 #endif
994             str_cat(tmpstr,"[]");
995             tmp2str = hfetch(symtab,tmpstr->str_ptr);
996             if (tmp2str && atoi(tmp2str->str_ptr))
997                 str_cat(str,"[");
998             else
999                 str_cat(str,"{");
1000             str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,P_MIN));
1001             str_free(fstr);
1002             if (strEQ(str->str_ptr,"$ARGV[0")) {
1003                 str_set(str,"$ARGV0");
1004                 saw_argv0++;
1005             }
1006             else {
1007                 if (tmp2str && atoi(tmp2str->str_ptr))
1008                     strcpy(tokenbuf,"]");
1009                 else
1010                     strcpy(tokenbuf,"}");
1011                 *tokenbuf += 128;
1012                 str_cat(str,tokenbuf);
1013             }
1014         }
1015         str_free(tmpstr);
1016         break;
1017     case OFLD:
1018         str = str_new(0);
1019         if (split_to_array) {
1020             str_set(str,"$Fld");
1021             str_cat(str,"[");
1022             str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN));
1023             str_free(fstr);
1024             str_cat(str,"]");
1025         }
1026         else {
1027             i = atoi(walk(1,level,ops[node+1].ival,&numarg,P_MIN)->str_ptr);
1028             if (i <= arymax)
1029                 sprintf(tokenbuf,"$%s",nameary[i]);
1030             else
1031                 sprintf(tokenbuf,"$Fld%d",i);
1032             str_set(str,tokenbuf);
1033         }
1034         break;
1035     case OVFLD:
1036         str = str_new(0);
1037         str_set(str,"$Fld[");
1038         i = ops[node+1].ival;
1039         if ((ops[i].ival & 255) == OPAREN)
1040             i = ops[i+1].ival;
1041         tmpstr=walk(1,level,i,&numarg,P_MIN);
1042         str_scat(str,tmpstr);
1043         str_free(tmpstr);
1044         str_cat(str,"]");
1045         break;
1046     case OJUNK:
1047         goto def;
1048     case OSNEWLINE:
1049         str = str_new(2);
1050         str_set(str,";\n");
1051         tab(str,level);
1052         break;
1053     case ONEWLINE:
1054         str = str_new(1);
1055         str_set(str,"\n");
1056         tab(str,level);
1057         break;
1058     case OSCOMMENT:
1059         str = str_new(0);
1060         str_set(str,";");
1061         tmpstr = walk(0,level,ops[node+1].ival,&numarg,P_MIN);
1062         for (s = tmpstr->str_ptr; *s && *s != '\n'; s++)
1063             *s += 128;
1064         str_scat(str,tmpstr);
1065         str_free(tmpstr);
1066         tab(str,level);
1067         break;
1068     case OCOMMENT:
1069         str = str_new(0);
1070         tmpstr = walk(0,level,ops[node+1].ival,&numarg,P_MIN);
1071         for (s = tmpstr->str_ptr; *s && *s != '\n'; s++)
1072             *s += 128;
1073         str_scat(str,tmpstr);
1074         str_free(tmpstr);
1075         tab(str,level);
1076         break;
1077     case OCOMMA:
1078         prec = P_COMMA;
1079         str = walk(1,level,ops[node+1].ival,&numarg,prec);
1080         str_cat(str,", ");
1081         str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,P_MIN));
1082         str_free(fstr);
1083         str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,prec+1));
1084         str_free(fstr);
1085         break;
1086     case OSEMICOLON:
1087         str = str_new(1);
1088         str_set(str,";\n");
1089         tab(str,level);
1090         break;
1091     case OSTATES:
1092         str = walk(0,level,ops[node+1].ival,&numarg,P_MIN);
1093         str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg,P_MIN));
1094         str_free(fstr);
1095         break;
1096     case OSTATE:
1097         str = str_new(0);
1098         if (len >= 1) {
1099             str_scat(str,fstr=walk(0,level,ops[node+1].ival,&numarg,P_MIN));
1100             str_free(fstr);
1101             if (len >= 2) {
1102                 tmpstr = walk(0,level,ops[node+2].ival,&numarg,P_MIN);
1103                 if (*tmpstr->str_ptr == ';') {
1104                     addsemi(str);
1105                     str_cat(str,tmpstr->str_ptr+1);
1106                 }
1107                 str_free(tmpstr);
1108             }
1109         }
1110         break;
1111     case OCLOSE:
1112         str = str_make("close(");
1113         tmpstr = walk(1,level,ops[node+1].ival,&numarg,P_MIN);
1114         if (!do_fancy_opens) {
1115             t = tmpstr->str_ptr;
1116             if (*t == '"' || *t == '\'')
1117                 t = cpytill(tokenbuf,t+1,*t);
1118             else
1119                 fatal("Internal error: OCLOSE %s",t);
1120             s = savestr(tokenbuf);
1121             for (t = tokenbuf; *t; t++) {
1122                 *t &= 127;
1123                 if (isLOWER(*t))
1124                     *t = toUPPER(*t);
1125                 if (!isALPHA(*t) && !isDIGIT(*t))
1126                     *t = '_';
1127             }
1128             if (!strchr(tokenbuf,'_'))
1129                 strcpy(t,"_FH");
1130             str_free(tmpstr);
1131             safefree(s);
1132             str_set(str,"close ");
1133             str_cat(str,tokenbuf);
1134         }
1135         else {
1136             sprintf(tokenbuf,"delete $opened{%s} && close(%s)",
1137                tmpstr->str_ptr, tmpstr->str_ptr);
1138             str_free(tmpstr);
1139             str_set(str,tokenbuf);
1140         }
1141         break;
1142     case OPRINTF:
1143     case OPRINT:
1144         lparen = "";    /* set to parens if necessary */
1145         rparen = "";
1146         str = str_new(0);
1147         if (len == 3) {         /* output redirection */
1148             tmpstr = walk(1,level,ops[node+3].ival,&numarg,P_MIN);
1149             tmp2str = walk(1,level,ops[node+2].ival,&numarg,P_MIN);
1150             if (!do_fancy_opens) {
1151                 t = tmpstr->str_ptr;
1152                 if (*t == '"' || *t == '\'')
1153                     t = cpytill(tokenbuf,t+1,*t);
1154                 else
1155                     fatal("Internal error: OPRINT");
1156                 d = savestr(t);
1157                 s = savestr(tokenbuf);
1158                 for (t = tokenbuf; *t; t++) {
1159                     *t &= 127;
1160                     if (isLOWER(*t))
1161                         *t = toUPPER(*t);
1162                     if (!isALPHA(*t) && !isDIGIT(*t))
1163                         *t = '_';
1164                 }
1165                 if (!strchr(tokenbuf,'_'))
1166                     strcpy(t,"_FH");
1167                 tmp3str = hfetch(symtab,tokenbuf);
1168                 if (!tmp3str) {
1169                     str_cat(opens,"open(");
1170                     str_cat(opens,tokenbuf);
1171                     str_cat(opens,", ");
1172                     d[1] = '\0';
1173                     str_cat(opens,d);
1174                     str_scat(opens,tmp2str);
1175                     str_cat(opens,tmpstr->str_ptr+1);
1176                     if (*tmp2str->str_ptr == '|')
1177                         str_cat(opens,") || die 'Cannot pipe to \"");
1178                     else
1179                         str_cat(opens,") || die 'Cannot create file \"");
1180                     if (*d == '"')
1181                         str_cat(opens,"'.\"");
1182                     str_cat(opens,s);
1183                     if (*d == '"')
1184                         str_cat(opens,"\".'");
1185                     str_cat(opens,"\".';\n");
1186                     hstore(symtab,tokenbuf,str_make("x"));
1187                 }
1188                 str_free(tmpstr);
1189                 str_free(tmp2str);
1190                 safefree(s);
1191                 safefree(d);
1192             }
1193             else {
1194                 sprintf(tokenbuf,"&Pick('%s', %s) &&\n",
1195                    tmp2str->str_ptr, tmpstr->str_ptr);
1196                 str_cat(str,tokenbuf);
1197                 tab(str,level+1);
1198                 strcpy(tokenbuf,"$fh");
1199                 str_free(tmpstr);
1200                 str_free(tmp2str);
1201                 lparen = "(";
1202                 rparen = ")";
1203             }
1204         }
1205         else
1206             strcpy(tokenbuf,"");
1207         str_cat(str,lparen);    /* may be null */
1208         if (type == OPRINTF)
1209             str_cat(str,"printf");
1210         else
1211             str_cat(str,"print");
1212         saw_fh = 0;
1213         if (len == 3 || do_fancy_opens) {
1214             if (*tokenbuf) {
1215                 str_cat(str," ");
1216                 saw_fh = 1;
1217             }
1218             str_cat(str,tokenbuf);
1219         }
1220         tmpstr = walk(1+(type==OPRINT),level,ops[node+1].ival,&numarg,P_MIN);
1221         if (!*tmpstr->str_ptr && lval_field) {
1222             t = (char*)(saw_OFS ? "$," : "' '");
1223             if (split_to_array) {
1224                 sprintf(tokenbuf,"join(%s,@Fld)",t);
1225                 str_cat(tmpstr,tokenbuf);
1226             }
1227             else {
1228                 for (i = 1; i < maxfld; i++) {
1229                     if (i <= arymax)
1230                         sprintf(tokenbuf,"$%s, ",nameary[i]);
1231                     else
1232                         sprintf(tokenbuf,"$Fld%d, ",i);
1233                     str_cat(tmpstr,tokenbuf);
1234                 }
1235                 if (maxfld <= arymax)
1236                     sprintf(tokenbuf,"$%s",nameary[maxfld]);
1237                 else
1238                     sprintf(tokenbuf,"$Fld%d",maxfld);
1239                 str_cat(tmpstr,tokenbuf);
1240             }
1241         }
1242         if (*tmpstr->str_ptr) {
1243             str_cat(str," ");
1244             if (!saw_fh && *tmpstr->str_ptr == '(') {
1245                 str_cat(str,"(");
1246                 str_scat(str,tmpstr);
1247                 str_cat(str,")");
1248             }
1249             else
1250                 str_scat(str,tmpstr);
1251         }
1252         else {
1253             str_cat(str," $_");
1254         }
1255         str_cat(str,rparen);    /* may be null */
1256         str_free(tmpstr);
1257         break;
1258     case ORAND:
1259         str = str_make("rand(1)");
1260         break;
1261     case OSRAND:
1262         str = str_make("srand(");
1263         goto maybe0;
1264     case OATAN2:
1265         str = str_make("atan2(");
1266         goto maybe0;
1267     case OSIN:
1268         str = str_make("sin(");
1269         goto maybe0;
1270     case OCOS:
1271         str = str_make("cos(");
1272         goto maybe0;
1273     case OSYSTEM:
1274         str = str_make("system(");
1275         goto maybe0;
1276     case OLENGTH:
1277         str = str_make("length(");
1278         goto maybe0;
1279     case OLOG:
1280         str = str_make("log(");
1281         goto maybe0;
1282     case OEXP:
1283         str = str_make("exp(");
1284         goto maybe0;
1285     case OSQRT:
1286         str = str_make("sqrt(");
1287         goto maybe0;
1288     case OINT:
1289         str = str_make("int(");
1290       maybe0:
1291         numeric = 1;
1292         if (len > 0)
1293             tmpstr = walk(1,level,ops[node+1].ival,&numarg,P_MIN);
1294         else
1295             tmpstr = str_new(0);
1296         if (!tmpstr->str_ptr || !*tmpstr->str_ptr) {
1297             if (lval_field) {
1298                 t = (char*)(saw_OFS ? "$," : "' '");
1299                 if (split_to_array) {
1300                     sprintf(tokenbuf,"join(%s,@Fld)",t);
1301                     str_cat(tmpstr,tokenbuf);
1302                 }
1303                 else {
1304                     sprintf(tokenbuf,"join(%s, ",t);
1305                     str_cat(tmpstr,tokenbuf);
1306                     for (i = 1; i < maxfld; i++) {
1307                         if (i <= arymax)
1308                             sprintf(tokenbuf,"$%s,",nameary[i]);
1309                         else
1310                             sprintf(tokenbuf,"$Fld%d,",i);
1311                         str_cat(tmpstr,tokenbuf);
1312                     }
1313                     if (maxfld <= arymax)
1314                         sprintf(tokenbuf,"$%s)",nameary[maxfld]);
1315                     else
1316                         sprintf(tokenbuf,"$Fld%d)",maxfld);
1317                     str_cat(tmpstr,tokenbuf);
1318                 }
1319             }
1320             else
1321                 str_cat(tmpstr,"$_");
1322         }
1323         if (strEQ(tmpstr->str_ptr,"$_")) {
1324             if (type == OLENGTH && !do_chop) {
1325                 str = str_make("(length(");
1326                 str_cat(tmpstr,") - 1");
1327             }
1328         }
1329         str_scat(str,tmpstr);
1330         str_free(tmpstr);
1331         str_cat(str,")");
1332         break;
1333     case OBREAK:
1334         str = str_new(0);
1335         str_set(str,"last");
1336         break;
1337     case ONEXT:
1338         str = str_new(0);
1339         str_set(str,"next line");
1340         break;
1341     case OEXIT:
1342         str = str_new(0);
1343         if (realexit) {
1344             prec = P_UNI;
1345             str_set(str,"exit");
1346             if (len == 1) {
1347                 str_cat(str," ");
1348                 exitval = TRUE;
1349                 str_scat(str,
1350                   fstr=walk(1,level,ops[node+1].ival,&numarg,prec+1));
1351                 str_free(fstr);
1352             }
1353         }
1354         else {
1355             if (len == 1) {
1356                 str_set(str,"$ExitValue = ");
1357                 exitval = TRUE;
1358                 str_scat(str,
1359                   fstr=walk(1,level,ops[node+1].ival,&numarg,P_ASSIGN));
1360                 str_free(fstr);
1361                 str_cat(str,"; ");
1362             }
1363             str_cat(str,"last line");
1364         }
1365         break;
1366     case OCONTINUE:
1367         str = str_new(0);
1368         str_set(str,"next");
1369         break;
1370     case OREDIR:
1371         goto def;
1372     case OIF:
1373         str = str_new(0);
1374         str_set(str,"if (");
1375         str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN));
1376         str_free(fstr);
1377         str_cat(str,") ");
1378         str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg,P_MIN));
1379         str_free(fstr);
1380         if (len == 3) {
1381             i = ops[node+3].ival;
1382             if (i) {
1383                 if ((ops[i].ival & 255) == OBLOCK) {
1384                     i = ops[i+1].ival;
1385                     if (i) {
1386                         if ((ops[i].ival & 255) != OIF)
1387                             i = 0;
1388                     }
1389                 }
1390                 else
1391                     i = 0;
1392             }
1393             if (i) {
1394                 str_cat(str,"els");
1395                 str_scat(str,fstr=walk(0,level,i,&numarg,P_MIN));
1396                 str_free(fstr);
1397             }
1398             else {
1399                 str_cat(str,"else ");
1400                 str_scat(str,fstr=walk(0,level,ops[node+3].ival,&numarg,P_MIN));
1401                 str_free(fstr);
1402             }
1403         }
1404         break;
1405     case OWHILE:
1406         str = str_new(0);
1407         str_set(str,"while (");
1408         str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN));
1409         str_free(fstr);
1410         str_cat(str,") ");
1411         str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg,P_MIN));
1412         str_free(fstr);
1413         break;
1414     case ODO:
1415         str = str_new(0);
1416         str_set(str,"do ");
1417         str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN));
1418         str_free(fstr);
1419         if (str->str_ptr[str->str_cur - 1] == '\n')
1420             --str->str_cur;
1421         str_cat(str," while (");
1422         str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg,P_MIN));
1423         str_free(fstr);
1424         str_cat(str,");");
1425         break;
1426     case OFOR:
1427         str = str_new(0);
1428         str_set(str,"for (");
1429         str_scat(str,tmpstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN));
1430         i = numarg;
1431         if (i) {
1432             t = s = tmpstr->str_ptr;
1433             while (isALPHA(*t) || isDIGIT(*t) || *t == '$' || *t == '_')
1434                 t++;
1435             i = t - s;
1436             if (i < 2)
1437                 i = 0;
1438         }
1439         str_cat(str,"; ");
1440         fstr=walk(1,level,ops[node+2].ival,&numarg,P_MIN);
1441         if (i && (t = strchr(fstr->str_ptr,0377))) {
1442             if (strnEQ(fstr->str_ptr,s,i))
1443                 *t = ' ';
1444         }
1445         str_scat(str,fstr);
1446         str_free(fstr);
1447         str_free(tmpstr);
1448         str_cat(str,"; ");
1449         str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,P_MIN));
1450         str_free(fstr);
1451         str_cat(str,") ");
1452         str_scat(str,fstr=walk(0,level,ops[node+4].ival,&numarg,P_MIN));
1453         str_free(fstr);
1454         break;
1455     case OFORIN:
1456         tmpstr = walk(0,level,ops[node+1].ival,&numarg,P_MIN);
1457         d = strchr(tmpstr->str_ptr,'$');
1458         if (!d)
1459             fatal("Illegal for loop: %s",tmpstr->str_ptr);
1460         s = strchr(d,'{');
1461         if (!s)
1462             s = strchr(d,'[');
1463         if (!s)
1464             fatal("Illegal for loop: %s",d);
1465         *s++ = '\0';
1466         for (t = s; (i = *t); t++) {
1467             i &= 127;
1468             if (i == '}' || i == ']')
1469                 break;
1470         }
1471         if (*t)
1472             *t = '\0';
1473         str = str_new(0);
1474         str_set(str,d+1);
1475         str_cat(str,"[]");
1476         tmp2str = hfetch(symtab,str->str_ptr);
1477         if (tmp2str && atoi(tmp2str->str_ptr)) {
1478             sprintf(tokenbuf,
1479               "foreach %s ($[ .. $#%s) ",
1480               s,
1481               d+1);
1482         }
1483         else {
1484             sprintf(tokenbuf,
1485               "foreach %s (keys %%%s) ",
1486               s,
1487               d+1);
1488         }
1489         str_set(str,tokenbuf);
1490         str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg,P_MIN));
1491         str_free(fstr);
1492         str_free(tmpstr);
1493         break;
1494     case OBLOCK:
1495         str = str_new(0);
1496         str_set(str,"{");
1497         if (len >= 2 && ops[node+2].ival) {
1498             str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg,P_MIN));
1499             str_free(fstr);
1500         }
1501         fixtab(str,++level);
1502         str_scat(str,fstr=walk(0,level,ops[node+1].ival,&numarg,P_MIN));
1503         str_free(fstr);
1504         addsemi(str);
1505         fixtab(str,--level);
1506         str_cat(str,"}\n");
1507         tab(str,level);
1508         if (len >= 3) {
1509             str_scat(str,fstr=walk(0,level,ops[node+3].ival,&numarg,P_MIN));
1510             str_free(fstr);
1511         }
1512         break;
1513     default:
1514       def:
1515         if (len) {
1516             if (len > 5)
1517                 fatal("Garbage length in walk");
1518             str = walk(0,level,ops[node+1].ival,&numarg,P_MIN);
1519             for (i = 2; i<= len; i++) {
1520                 str_scat(str,fstr=walk(0,level,ops[node+i].ival,&numarg,P_MIN));
1521                 str_free(fstr);
1522             }
1523         }
1524         else {
1525             str = Nullstr;
1526         }
1527         break;
1528     }
1529     if (!str)
1530         str = str_new(0);
1531
1532     if (useval && prec < minprec) {             /* need parens? */
1533         fstr = str_new(str->str_cur+2);
1534         str_nset(fstr,"(",1);
1535         str_scat(fstr,str);
1536         str_ncat(fstr,")",1);
1537         str_free(str);
1538         str = fstr;
1539     }
1540
1541     *numericptr = numeric;
1542 #ifdef DEBUGGING
1543     if (debug & 4) {
1544         printf("%3d %5d %15s %d %4d ",level,node,opname[type],len,str->str_cur);
1545         for (t = str->str_ptr; *t && t - str->str_ptr < 40; t++)
1546             if (*t == '\n')
1547                 printf("\\n");
1548             else if (*t == '\t')
1549                 printf("\\t");
1550             else
1551                 putchar(*t);
1552         putchar('\n');
1553     }
1554 #endif
1555     return str;
1556 }
1557
1558 static void
1559 tab(register STR *str, register int lvl)
1560 {
1561     while (lvl > 1) {
1562         str_cat(str,"\t");
1563         lvl -= 2;
1564     }
1565     if (lvl)
1566         str_cat(str,"    ");
1567 }
1568
1569 static void
1570 fixtab(register STR *str, register int lvl)
1571 {
1572     register char *s;
1573
1574     /* strip trailing white space */
1575
1576     s = str->str_ptr+str->str_cur - 1;
1577     while (s >= str->str_ptr && (*s == ' ' || *s == '\t' || *s == '\n'))
1578         s--;
1579     s[1] = '\0';
1580     str->str_cur = s + 1 - str->str_ptr;
1581     if (s >= str->str_ptr && *s != '\n')
1582         str_cat(str,"\n");
1583
1584     tab(str,lvl);
1585 }
1586
1587 static void
1588 addsemi(register STR *str)
1589 {
1590     register char *s;
1591
1592     s = str->str_ptr+str->str_cur - 1;
1593     while (s >= str->str_ptr && (*s == ' ' || *s == '\t' || *s == '\n'))
1594         s--;
1595     if (s >= str->str_ptr && *s != ';' && *s != '}')
1596         str_cat(str,";");
1597 }
1598
1599 static void
1600 emit_split(register STR *str, int level)
1601 {
1602     register int i;
1603
1604     if (split_to_array)
1605         str_cat(str,"@Fld");
1606     else {
1607         str_cat(str,"(");
1608         for (i = 1; i < maxfld; i++) {
1609             if (i <= arymax)
1610                 sprintf(tokenbuf,"$%s,",nameary[i]);
1611             else
1612                 sprintf(tokenbuf,"$Fld%d,",i);
1613             str_cat(str,tokenbuf);
1614         }
1615         if (maxfld <= arymax)
1616             sprintf(tokenbuf,"$%s)",nameary[maxfld]);
1617         else
1618             sprintf(tokenbuf,"$Fld%d)",maxfld);
1619         str_cat(str,tokenbuf);
1620     }
1621     if (const_FS) {
1622         sprintf(tokenbuf," = split(/[%c\\n]/, $_, 9999);\n",const_FS);
1623         str_cat(str,tokenbuf);
1624     }
1625     else if (saw_FS)
1626         str_cat(str," = split($FS, $_, 9999);\n");
1627     else
1628         str_cat(str," = split(' ', $_, 9999);\n");
1629     tab(str,level);
1630 }
1631
1632 int
1633 prewalk(int numit, int level, register int node, int *numericptr)
1634 {
1635     register int len;
1636     register int type;
1637     register int i;
1638     int numarg;
1639     int numeric = FALSE;
1640     STR *tmpstr;
1641     STR *tmp2str;
1642
1643     if (!node) {
1644         *numericptr = 0;
1645         return 0;
1646     }
1647     type = ops[node].ival;
1648     len = type >> 8;
1649     type &= 255;
1650     switch (type) {
1651     case OPROG:
1652         prewalk(0,level,ops[node+1].ival,&numarg);
1653         if (ops[node+2].ival) {
1654             prewalk(0,level,ops[node+2].ival,&numarg);
1655         }
1656         ++level;
1657         prewalk(0,level,ops[node+3].ival,&numarg);
1658         --level;
1659         if (ops[node+3].ival) {
1660             prewalk(0,level,ops[node+4].ival,&numarg);
1661         }
1662         break;
1663     case OHUNKS:
1664         prewalk(0,level,ops[node+1].ival,&numarg);
1665         prewalk(0,level,ops[node+2].ival,&numarg);
1666         if (len == 3) {
1667             prewalk(0,level,ops[node+3].ival,&numarg);
1668         }
1669         break;
1670     case ORANGE:
1671         prewalk(1,level,ops[node+1].ival,&numarg);
1672         prewalk(1,level,ops[node+2].ival,&numarg);
1673         break;
1674     case OPAT:
1675         goto def;
1676     case OREGEX:
1677         prewalk(0,level,ops[node+1].ival,&numarg);
1678         break;
1679     case OHUNK:
1680         if (len == 1) {
1681             prewalk(0,level,ops[node+1].ival,&numarg);
1682         }
1683         else {
1684             i = prewalk(0,level,ops[node+1].ival,&numarg);
1685             if (i) {
1686                 ++level;
1687                 prewalk(0,level,ops[node+2].ival,&numarg);
1688                 --level;
1689             }
1690             else {
1691                 prewalk(0,level,ops[node+2].ival,&numarg);
1692             }
1693         }
1694         break;
1695     case OPPAREN:
1696         prewalk(0,level,ops[node+1].ival,&numarg);
1697         break;
1698     case OPANDAND:
1699         prewalk(0,level,ops[node+1].ival,&numarg);
1700         prewalk(0,level,ops[node+2].ival,&numarg);
1701         break;
1702     case OPOROR:
1703         prewalk(0,level,ops[node+1].ival,&numarg);
1704         prewalk(0,level,ops[node+2].ival,&numarg);
1705         break;
1706     case OPNOT:
1707         prewalk(0,level,ops[node+1].ival,&numarg);
1708         break;
1709     case OCPAREN:
1710         prewalk(0,level,ops[node+1].ival,&numarg);
1711         numeric |= numarg;
1712         break;
1713     case OCANDAND:
1714         prewalk(0,level,ops[node+1].ival,&numarg);
1715         numeric = 1;
1716         prewalk(0,level,ops[node+2].ival,&numarg);
1717         break;
1718     case OCOROR:
1719         prewalk(0,level,ops[node+1].ival,&numarg);
1720         numeric = 1;
1721         prewalk(0,level,ops[node+2].ival,&numarg);
1722         break;
1723     case OCNOT:
1724         prewalk(0,level,ops[node+1].ival,&numarg);
1725         numeric = 1;
1726         break;
1727     case ORELOP:
1728         prewalk(0,level,ops[node+2].ival,&numarg);
1729         numeric |= numarg;
1730         prewalk(0,level,ops[node+1].ival,&numarg);
1731         prewalk(0,level,ops[node+3].ival,&numarg);
1732         numeric |= numarg;
1733         numeric = 1;
1734         break;
1735     case ORPAREN:
1736         prewalk(0,level,ops[node+1].ival,&numarg);
1737         numeric |= numarg;
1738         break;
1739     case OMATCHOP:
1740         prewalk(0,level,ops[node+2].ival,&numarg);
1741         prewalk(0,level,ops[node+1].ival,&numarg);
1742         prewalk(0,level,ops[node+3].ival,&numarg);
1743         numeric = 1;
1744         break;
1745     case OMPAREN:
1746         prewalk(0,level,ops[node+1].ival,&numarg);
1747         numeric |= numarg;
1748         break;
1749     case OCONCAT:
1750         prewalk(0,level,ops[node+1].ival,&numarg);
1751         prewalk(0,level,ops[node+2].ival,&numarg);
1752         break;
1753     case OASSIGN:
1754         prewalk(0,level,ops[node+2].ival,&numarg);
1755         prewalk(0,level,ops[node+1].ival,&numarg);
1756         prewalk(0,level,ops[node+3].ival,&numarg);
1757         if (numarg || strlen(ops[ops[node+1].ival+1].cval) > (Size_t)1) {
1758             numericize(ops[node+2].ival);
1759             if (!numarg)
1760                 numericize(ops[node+3].ival);
1761         }
1762         numeric |= numarg;
1763         break;
1764     case OADD:
1765         prewalk(1,level,ops[node+1].ival,&numarg);
1766         prewalk(1,level,ops[node+2].ival,&numarg);
1767         numeric = 1;
1768         break;
1769     case OSUBTRACT:
1770         prewalk(1,level,ops[node+1].ival,&numarg);
1771         prewalk(1,level,ops[node+2].ival,&numarg);
1772         numeric = 1;
1773         break;
1774     case OMULT:
1775         prewalk(1,level,ops[node+1].ival,&numarg);
1776         prewalk(1,level,ops[node+2].ival,&numarg);
1777         numeric = 1;
1778         break;
1779     case ODIV:
1780         prewalk(1,level,ops[node+1].ival,&numarg);
1781         prewalk(1,level,ops[node+2].ival,&numarg);
1782         numeric = 1;
1783         break;
1784     case OPOW:
1785         prewalk(1,level,ops[node+1].ival,&numarg);
1786         prewalk(1,level,ops[node+2].ival,&numarg);
1787         numeric = 1;
1788         break;
1789     case OMOD:
1790         prewalk(1,level,ops[node+1].ival,&numarg);
1791         prewalk(1,level,ops[node+2].ival,&numarg);
1792         numeric = 1;
1793         break;
1794     case OPOSTINCR:
1795         prewalk(1,level,ops[node+1].ival,&numarg);
1796         numeric = 1;
1797         break;
1798     case OPOSTDECR:
1799         prewalk(1,level,ops[node+1].ival,&numarg);
1800         numeric = 1;
1801         break;
1802     case OPREINCR:
1803         prewalk(1,level,ops[node+1].ival,&numarg);
1804         numeric = 1;
1805         break;
1806     case OPREDECR:
1807         prewalk(1,level,ops[node+1].ival,&numarg);
1808         numeric = 1;
1809         break;
1810     case OUMINUS:
1811         prewalk(1,level,ops[node+1].ival,&numarg);
1812         numeric = 1;
1813         break;
1814     case OUPLUS:
1815         prewalk(1,level,ops[node+1].ival,&numarg);
1816         numeric = 1;
1817         break;
1818     case OPAREN:
1819         prewalk(0,level,ops[node+1].ival,&numarg);
1820         numeric |= numarg;
1821         break;
1822     case OGETLINE:
1823         break;
1824     case OSPRINTF:
1825         prewalk(0,level,ops[node+1].ival,&numarg);
1826         break;
1827     case OSUBSTR:
1828         prewalk(0,level,ops[node+1].ival,&numarg);
1829         prewalk(1,level,ops[node+2].ival,&numarg);
1830         if (len == 3) {
1831             prewalk(1,level,ops[node+3].ival,&numarg);
1832         }
1833         break;
1834     case OSTRING:
1835         break;
1836     case OSPLIT:
1837         numeric = 1;
1838         prewalk(0,level,ops[node+2].ival,&numarg);
1839         if (len == 3)
1840             prewalk(0,level,ops[node+3].ival,&numarg);
1841         prewalk(0,level,ops[node+1].ival,&numarg);
1842         break;
1843     case OINDEX:
1844         prewalk(0,level,ops[node+1].ival,&numarg);
1845         prewalk(0,level,ops[node+2].ival,&numarg);
1846         numeric = 1;
1847         break;
1848     case OMATCH:
1849         prewalk(0,level,ops[node+1].ival,&numarg);
1850         prewalk(0,level,ops[node+2].ival,&numarg);
1851         numeric = 1;
1852         break;
1853     case OUSERDEF:
1854         subretnum = FALSE;
1855         --level;
1856         tmpstr = walk(0,level,ops[node+1].ival,&numarg,P_MIN);
1857         ++level;
1858         prewalk(0,level,ops[node+2].ival,&numarg);
1859         prewalk(0,level,ops[node+4].ival,&numarg);
1860         prewalk(0,level,ops[node+5].ival,&numarg);
1861         --level;
1862         str_cat(tmpstr,"(");
1863         tmp2str = str_new(0);
1864         if (subretnum || numarg)
1865             str_set(tmp2str,"1");
1866         hstore(symtab,tmpstr->str_ptr,tmp2str);
1867         str_free(tmpstr);
1868         level++;
1869         break;
1870     case ORETURN:
1871         if (len > 0) {
1872             prewalk(0,level,ops[node+1].ival,&numarg);
1873             if (numarg)
1874                 subretnum = TRUE;
1875         }
1876         break;
1877     case OUSERFUN:
1878         tmp2str = str_new(0);
1879         str_scat(tmp2str,tmpstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN));
1880         fixrargs(tmpstr->str_ptr,ops[node+2].ival,0);
1881         str_free(tmpstr);
1882         str_cat(tmp2str,"(");
1883         tmpstr = hfetch(symtab,tmp2str->str_ptr);
1884         if (tmpstr && tmpstr->str_ptr)
1885             numeric |= atoi(tmpstr->str_ptr);
1886         prewalk(0,level,ops[node+2].ival,&numarg);
1887         str_free(tmp2str);
1888         break;
1889     case OGSUB:
1890     case OSUB:
1891         if (len >= 3)
1892             prewalk(0,level,ops[node+3].ival,&numarg);
1893         prewalk(0,level,ops[ops[node+2].ival+1].ival,&numarg);
1894         prewalk(0,level,ops[node+1].ival,&numarg);
1895         numeric = 1;
1896         break;
1897     case ONUM:
1898         prewalk(0,level,ops[node+1].ival,&numarg);
1899         numeric = 1;
1900         break;
1901     case OSTR:
1902         prewalk(0,level,ops[node+1].ival,&numarg);
1903         break;
1904     case ODEFINED:
1905     case ODELETE:
1906     case OSTAR:
1907     case OVAR:
1908         prewalk(0,level,ops[node+1].ival,&numarg);
1909         if (len == 1) {
1910             if (numit)
1911                 numericize(node);
1912         }
1913         else {
1914             prewalk(0,level,ops[node+2].ival,&numarg);
1915         }
1916         break;
1917     case OFLD:
1918         prewalk(0,level,ops[node+1].ival,&numarg);
1919         break;
1920     case OVFLD:
1921         i = ops[node+1].ival;
1922         prewalk(0,level,i,&numarg);
1923         break;
1924     case OJUNK:
1925         goto def;
1926     case OSNEWLINE:
1927         break;
1928     case ONEWLINE:
1929         break;
1930     case OSCOMMENT:
1931         break;
1932     case OCOMMENT:
1933         break;
1934     case OCOMMA:
1935         prewalk(0,level,ops[node+1].ival,&numarg);
1936         prewalk(0,level,ops[node+2].ival,&numarg);
1937         prewalk(0,level,ops[node+3].ival,&numarg);
1938         break;
1939     case OSEMICOLON:
1940         break;
1941     case OSTATES:
1942         prewalk(0,level,ops[node+1].ival,&numarg);
1943         prewalk(0,level,ops[node+2].ival,&numarg);
1944         break;
1945     case OSTATE:
1946         if (len >= 1) {
1947             prewalk(0,level,ops[node+1].ival,&numarg);
1948             if (len >= 2) {
1949                 prewalk(0,level,ops[node+2].ival,&numarg);
1950             }
1951         }
1952         break;
1953     case OCLOSE:
1954         prewalk(0,level,ops[node+1].ival,&numarg);
1955         break;
1956     case OPRINTF:
1957     case OPRINT:
1958         if (len == 3) {         /* output redirection */
1959             prewalk(0,level,ops[node+3].ival,&numarg);
1960             prewalk(0,level,ops[node+2].ival,&numarg);
1961         }
1962         prewalk(0+(type==OPRINT),level,ops[node+1].ival,&numarg);
1963         break;
1964     case ORAND:
1965         break;
1966     case OSRAND:
1967         goto maybe0;
1968     case OATAN2:
1969         goto maybe0;
1970     case OSIN:
1971         goto maybe0;
1972     case OCOS:
1973         goto maybe0;
1974     case OSYSTEM:
1975         goto maybe0;
1976     case OLENGTH:
1977         goto maybe0;
1978     case OLOG:
1979         goto maybe0;
1980     case OEXP:
1981         goto maybe0;
1982     case OSQRT:
1983         goto maybe0;
1984     case OINT:
1985       maybe0:
1986         numeric = 1;
1987         if (len > 0)
1988             prewalk(type != OLENGTH && type != OSYSTEM,
1989               level,ops[node+1].ival,&numarg);
1990         break;
1991     case OBREAK:
1992         break;
1993     case ONEXT:
1994         break;
1995     case OEXIT:
1996         if (len == 1) {
1997             prewalk(1,level,ops[node+1].ival,&numarg);
1998         }
1999         break;
2000     case OCONTINUE:
2001         break;
2002     case OREDIR:
2003         goto def;
2004     case OIF:
2005         prewalk(0,level,ops[node+1].ival,&numarg);
2006         prewalk(0,level,ops[node+2].ival,&numarg);
2007         if (len == 3) {
2008             prewalk(0,level,ops[node+3].ival,&numarg);
2009         }
2010         break;
2011     case OWHILE:
2012         prewalk(0,level,ops[node+1].ival,&numarg);
2013         prewalk(0,level,ops[node+2].ival,&numarg);
2014         break;
2015     case OFOR:
2016         prewalk(0,level,ops[node+1].ival,&numarg);
2017         prewalk(0,level,ops[node+2].ival,&numarg);
2018         prewalk(0,level,ops[node+3].ival,&numarg);
2019         prewalk(0,level,ops[node+4].ival,&numarg);
2020         break;
2021     case OFORIN:
2022         prewalk(0,level,ops[node+2].ival,&numarg);
2023         prewalk(0,level,ops[node+1].ival,&numarg);
2024         break;
2025     case OBLOCK:
2026         if (len == 2) {
2027             prewalk(0,level,ops[node+2].ival,&numarg);
2028         }
2029         ++level;
2030         prewalk(0,level,ops[node+1].ival,&numarg);
2031         --level;
2032         break;
2033     default:
2034       def:
2035         if (len) {
2036             if (len > 5)
2037                 fatal("Garbage length in prewalk");
2038             prewalk(0,level,ops[node+1].ival,&numarg);
2039             for (i = 2; i<= len; i++) {
2040                 prewalk(0,level,ops[node+i].ival,&numarg);
2041             }
2042         }
2043         break;
2044     }
2045     *numericptr = numeric;
2046     return 1;
2047 }
2048
2049 static void
2050 numericize(register int node)
2051 {
2052     register int len;
2053     register int type;
2054     STR *tmpstr;
2055     STR *tmp2str;
2056     int numarg;
2057
2058     type = ops[node].ival;
2059     len = type >> 8;
2060     type &= 255;
2061     if (type == OVAR && len == 1) {
2062         tmpstr=walk(0,0,ops[node+1].ival,&numarg,P_MIN);
2063         tmp2str = str_make("1");
2064         hstore(symtab,tmpstr->str_ptr,tmp2str);
2065     }
2066 }