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