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