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