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