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