perl 4.0 patch 32: patch #20, continued
[p5sagit/p5-mst-13.2.git] / x2p / walk.c
1 /* $RCSfile: walk.c,v $$Revision: 4.0.1.3 $$Date: 92/06/08 17:33:46 $
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  * Revision 4.0.1.3  92/06/08  17:33:46  lwall
10  * patch20: in a2p, simplified the filehandle model
11  * patch20: in a2p, made RS="" translate to $/ = "\n\n"
12  * patch20: in a2p, do {...} while ... was missing some reconstruction code
13  * patch20: in a2p, getline should allow variable to be array element
14  * 
15  * Revision 4.0.1.2  91/11/05  19:25:09  lwall
16  * patch11: in a2p, split on whitespace produced extra null field
17  * 
18  * Revision 4.0.1.1  91/06/07  12:22:04  lwall
19  * patch4: new copyright notice
20  * patch4: a2p didn't correctly implement -n switch
21  * 
22  * Revision 4.0  91/03/20  01:58:36  lwall
23  * 4.0 baseline.
24  * 
25  */
26
27 #include "handy.h"
28 #include "EXTERN.h"
29 #include "util.h"
30 #include "a2p.h"
31
32 bool exitval = FALSE;
33 bool realexit = FALSE;
34 bool saw_getline = FALSE;
35 bool subretnum = FALSE;
36 bool saw_FNR = FALSE;
37 bool saw_argv0 = FALSE;
38 bool saw_fh = FALSE;
39 int maxtmp = 0;
40 char *lparen;
41 char *rparen;
42 char *limit;
43 STR *subs;
44 STR *curargs = Nullstr;
45
46 STR *
47 walk(useval,level,node,numericptr,minprec)
48 int useval;
49 int level;
50 register int node;
51 int *numericptr;
52 int minprec;                    /* minimum precedence without parens */
53 {
54     register int len;
55     register STR *str;
56     register int type;
57     register int i;
58     register STR *tmpstr;
59     STR *tmp2str;
60     STR *tmp3str;
61     char *t;
62     char *d, *s;
63     int numarg;
64     int numeric = FALSE;
65     STR *fstr;
66     int prec = P_MAX;           /* assume no parens needed */
67     char *index();
68
69     if (!node) {
70         *numericptr = 0;
71         return str_make("");
72     }
73     type = ops[node].ival;
74     len = type >> 8;
75     type &= 255;
76     switch (type) {
77     case OPROG:
78         arymax = 0;
79         if (namelist) {
80             while (isalpha(*namelist)) {
81                 for (d = tokenbuf,s=namelist;
82                   isalpha(*s) || isdigit(*s) || *s == '_';
83                   *d++ = *s++) ;
84                 *d = '\0';
85                 while (*s && !isalpha(*s)) s++;
86                 namelist = s;
87                 nameary[++arymax] = savestr(tokenbuf);
88             }
89         }
90         if (maxfld < arymax)
91             maxfld = arymax;
92         opens = str_new(0);
93         subs = str_new(0);
94         str = walk(0,level,ops[node+1].ival,&numarg,P_MIN);
95         if (do_split && need_entire && !absmaxfld)
96             split_to_array = TRUE;
97         if (do_split && split_to_array)
98             set_array_base = TRUE;
99         if (set_array_base) {
100             str_cat(str,"$[ = 1;\t\t\t# set array base to 1\n");
101         }
102         if (fswitch && !const_FS)
103             const_FS = fswitch;
104         if (saw_FS > 1 || saw_RS)
105             const_FS = 0;
106         if (saw_ORS && need_entire)
107             do_chop = TRUE;
108         if (fswitch) {
109             str_cat(str,"$FS = '");
110             if (index("*+?.[]()|^$\\",fswitch))
111                 str_cat(str,"\\");
112             sprintf(tokenbuf,"%c",fswitch);
113             str_cat(str,tokenbuf);
114             str_cat(str,"';\t\t# field separator from -F switch\n");
115         }
116         else if (saw_FS && !const_FS) {
117             str_cat(str,"$FS = ' ';\t\t# set field separator\n");
118         }
119         if (saw_OFS) {
120             str_cat(str,"$, = ' ';\t\t# set output field separator\n");
121         }
122         if (saw_ORS) {
123             str_cat(str,"$\\ = \"\\n\";\t\t# set output record separator\n");
124         }
125         if (saw_argv0) {
126             str_cat(str,"$ARGV0 = $0;\t\t# remember what we ran as\n");
127         }
128         if (str->str_cur > 20)
129             str_cat(str,"\n");
130         if (ops[node+2].ival) {
131             str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg,P_MIN));
132             str_free(fstr);
133             str_cat(str,"\n\n");
134         }
135         fstr = walk(0,level+1,ops[node+3].ival,&numarg,P_MIN);
136         if (*fstr->str_ptr) {
137             if (saw_line_op)
138                 str_cat(str,"line: ");
139             str_cat(str,"while (<>) {\n");
140             tab(str,++level);
141             if (saw_FS && !const_FS)
142                 do_chop = TRUE;
143             if (do_chop) {
144                 str_cat(str,"chop;\t# strip record separator\n");
145                 tab(str,level);
146             }
147             if (do_split)
148                 emit_split(str,level);
149             str_scat(str,fstr);
150             str_free(fstr);
151             fixtab(str,--level);
152             str_cat(str,"}\n");
153             if (saw_FNR)
154                 str_cat(str,"continue {\n    $FNRbase = $. if eof;\n}\n");
155         }
156         else
157             str_cat(str,"while (<>) { }         # (no line actions)\n");
158         if (ops[node+4].ival) {
159             realexit = TRUE;
160             str_cat(str,"\n");
161             tab(str,level);
162             str_scat(str,fstr=walk(0,level,ops[node+4].ival,&numarg,P_MIN));
163             str_free(fstr);
164             str_cat(str,"\n");
165         }
166         if (exitval)
167             str_cat(str,"exit $ExitValue;\n");
168         if (subs->str_ptr) {
169             str_cat(str,"\n");
170             str_scat(str,subs);
171         }
172         if (saw_getline) {
173             for (len = 0; len < 4; len++) {
174                 if (saw_getline & (1 << len)) {
175                     sprintf(tokenbuf,"\nsub Getline%d {\n",len);
176                     str_cat(str, tokenbuf);
177                     if (len & 2) {
178                         if (do_fancy_opens)
179                             str_cat(str,"    &Pick('',@_);\n");
180                         else
181                             str_cat(str,"    ($fh) = @_;\n");
182                     }
183                     else {
184                         if (saw_FNR)
185                             str_cat(str,"    $FNRbase = $. if eof;\n");
186                     }
187                     if (len & 1)
188                         str_cat(str,"    local($_);\n");
189                     if (len & 2)
190                         str_cat(str,
191                           "    if ($getline_ok = (($_ = <$fh>) ne ''))");
192                     else
193                         str_cat(str,
194                           "    if ($getline_ok = (($_ = <>) ne ''))");
195                     str_cat(str, " {\n");
196                     level += 2;
197                     tab(str,level);
198                     i = 0;
199                     if (do_chop) {
200                         i++;
201                         str_cat(str,"chop;\t# strip record separator\n");
202                         tab(str,level);
203                     }
204                     if (do_split && !(len & 1)) {
205                         i++;
206                         emit_split(str,level);
207                     }
208                     if (!i)
209                         str_cat(str,";\n");
210                     fixtab(str,--level);
211                     str_cat(str,"}\n    $_;\n}\n");
212                     --level;
213                 }
214             }
215         }
216         if (do_fancy_opens) {
217             str_cat(str,"\n\
218 sub Pick {\n\
219     local($mode,$name,$pipe) = @_;\n\
220     $fh = $name;\n\
221     open($name,$mode.$name.$pipe) unless $opened{$name}++;\n\
222 }\n\
223 ");
224         }
225         break;
226     case OHUNKS:
227         str = walk(0,level,ops[node+1].ival,&numarg,P_MIN);
228         str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg,P_MIN));
229         str_free(fstr);
230         if (len == 3) {
231             str_scat(str,fstr=walk(0,level,ops[node+3].ival,&numarg,P_MIN));
232             str_free(fstr);
233         }
234         else {
235         }
236         break;
237     case ORANGE:
238         prec = P_DOTDOT;
239         str = walk(1,level,ops[node+1].ival,&numarg,prec+1);
240         str_cat(str," .. ");
241         str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1));
242         str_free(fstr);
243         break;
244     case OPAT:
245         goto def;
246     case OREGEX:
247         str = str_new(0);
248         str_set(str,"/");
249         tmpstr=walk(0,level,ops[node+1].ival,&numarg,P_MIN);
250         /* translate \nnn to [\nnn] */
251         for (s = tmpstr->str_ptr, d = tokenbuf; *s; s++, d++) {
252             if (*s == '\\' && isdigit(s[1]) && isdigit(s[2]) && isdigit(s[3])){
253                 *d++ = '[';
254                 *d++ = *s++;
255                 *d++ = *s++;
256                 *d++ = *s++;
257                 *d++ = *s;
258                 *d = ']';
259             }
260             else
261                 *d = *s;
262         }
263         *d = '\0';
264         for (d=tokenbuf; *d; d++)
265             *d += 128;
266         str_cat(str,tokenbuf);
267         str_free(tmpstr);
268         str_cat(str,"/");
269         break;
270     case OHUNK:
271         if (len == 1) {
272             str = str_new(0);
273             str = walk(0,level,oper1(OPRINT,0),&numarg,P_MIN);
274             str_cat(str," if ");
275             str_scat(str,fstr=walk(0,level,ops[node+1].ival,&numarg,P_MIN));
276             str_free(fstr);
277             str_cat(str,";");
278         }
279         else {
280             tmpstr = walk(0,level,ops[node+1].ival,&numarg,P_MIN);
281             if (*tmpstr->str_ptr) {
282                 str = str_new(0);
283                 str_set(str,"if (");
284                 str_scat(str,tmpstr);
285                 str_cat(str,") {\n");
286                 tab(str,++level);
287                 str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg,P_MIN));
288                 str_free(fstr);
289                 fixtab(str,--level);
290                 str_cat(str,"}\n");
291                 tab(str,level);
292             }
293             else {
294                 str = walk(0,level,ops[node+2].ival,&numarg,P_MIN);
295             }
296         }
297         break;
298     case OPPAREN:
299         str = str_new(0);
300         str_set(str,"(");
301         str_scat(str,fstr=walk(useval != 0,level,ops[node+1].ival,&numarg,P_MIN));
302         str_free(fstr);
303         str_cat(str,")");
304         break;
305     case OPANDAND:
306         prec = P_ANDAND;
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 OPOROR:
315         prec = P_OROR;
316         str = walk(1,level,ops[node+1].ival,&numarg,prec);
317         str_cat(str," || ");
318         str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1));
319         str_free(fstr);
320         str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,prec+1));
321         str_free(fstr);
322         break;
323     case OPNOT:
324         prec = P_UNARY;
325         str = str_new(0);
326         str_set(str,"!");
327         str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,prec));
328         str_free(fstr);
329         break;
330     case OCOND:
331         prec = P_COND;
332         str = walk(1,level,ops[node+1].ival,&numarg,prec);
333         str_cat(str," ? ");
334         str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1));
335         str_free(fstr);
336         str_cat(str," : ");
337         str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,prec+1));
338         str_free(fstr);
339         break;
340     case OCPAREN:
341         str = str_new(0);
342         str_set(str,"(");
343         str_scat(str,fstr=walk(useval != 0,level,ops[node+1].ival,&numarg,P_MIN));
344         str_free(fstr);
345         numeric |= numarg;
346         str_cat(str,")");
347         break;
348     case OCANDAND:
349         prec = P_ANDAND;
350         str = walk(1,level,ops[node+1].ival,&numarg,prec);
351         numeric = 1;
352         str_cat(str," && ");
353         str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1));
354         str_free(fstr);
355         str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,prec+1));
356         str_free(fstr);
357         break;
358     case OCOROR:
359         prec = P_OROR;
360         str = walk(1,level,ops[node+1].ival,&numarg,prec);
361         numeric = 1;
362         str_cat(str," || ");
363         str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1));
364         str_free(fstr);
365         str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,prec+1));
366         str_free(fstr);
367         break;
368     case OCNOT:
369         prec = P_UNARY;
370         str = str_new(0);
371         str_set(str,"!");
372         str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,prec));
373         str_free(fstr);
374         numeric = 1;
375         break;
376     case ORELOP:
377         prec = P_REL;
378         str = walk(1,level,ops[node+2].ival,&numarg,prec+1);
379         numeric |= numarg;
380         tmpstr = walk(0,level,ops[node+1].ival,&numarg,P_MIN);
381         tmp2str = walk(1,level,ops[node+3].ival,&numarg,prec+1);
382         numeric |= numarg;
383         if (!numeric ||
384          (!numarg && (*tmp2str->str_ptr == '"' || *tmp2str->str_ptr == '\''))) {
385             t = tmpstr->str_ptr;
386             if (strEQ(t,"=="))
387                 str_set(tmpstr,"eq");
388             else if (strEQ(t,"!="))
389                 str_set(tmpstr,"ne");
390             else if (strEQ(t,"<"))
391                 str_set(tmpstr,"lt");
392             else if (strEQ(t,"<="))
393                 str_set(tmpstr,"le");
394             else if (strEQ(t,">"))
395                 str_set(tmpstr,"gt");
396             else if (strEQ(t,">="))
397                 str_set(tmpstr,"ge");
398             if (!index(tmpstr->str_ptr,'\'') && !index(tmpstr->str_ptr,'"') &&
399               !index(tmp2str->str_ptr,'\'') && !index(tmp2str->str_ptr,'"') )
400                 numeric |= 2;
401         }
402         if (numeric & 2) {
403             if (numeric & 1)            /* numeric is very good guess */
404                 str_cat(str," ");
405             else
406                 str_cat(str,"\377");
407             numeric = 1;
408         }
409         else
410             str_cat(str," ");
411         str_scat(str,tmpstr);
412         str_free(tmpstr);
413         str_cat(str," ");
414         str_scat(str,tmp2str);
415         str_free(tmp2str);
416         numeric = 1;
417         break;
418     case ORPAREN:
419         str = str_new(0);
420         str_set(str,"(");
421         str_scat(str,fstr=walk(useval != 0,level,ops[node+1].ival,&numarg,P_MIN));
422         str_free(fstr);
423         numeric |= numarg;
424         str_cat(str,")");
425         break;
426     case OMATCHOP:
427         prec = P_MATCH;
428         str = walk(1,level,ops[node+2].ival,&numarg,prec+1);
429         str_cat(str," ");
430         tmpstr = walk(0,level,ops[node+1].ival,&numarg,P_MIN);
431         if (strEQ(tmpstr->str_ptr,"~"))
432             str_cat(str,"=~");
433         else {
434             str_scat(str,tmpstr);
435             str_free(tmpstr);
436         }
437         str_cat(str," ");
438         str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,prec+1));
439         str_free(fstr);
440         numeric = 1;
441         break;
442     case OMPAREN:
443         str = str_new(0);
444         str_set(str,"(");
445         str_scat(str,
446           fstr=walk(useval != 0,level,ops[node+1].ival,&numarg,P_MIN));
447         str_free(fstr);
448         numeric |= numarg;
449         str_cat(str,")");
450         break;
451     case OCONCAT:
452         prec = P_ADD;
453         type = ops[ops[node+1].ival].ival & 255;
454         str = walk(1,level,ops[node+1].ival,&numarg,prec+(type != OCONCAT));
455         str_cat(str," . ");
456         type = ops[ops[node+2].ival].ival & 255;
457         str_scat(str,
458           fstr=walk(1,level,ops[node+2].ival,&numarg,prec+(type != OCONCAT)));
459         str_free(fstr);
460         break;
461     case OASSIGN:
462         prec = P_ASSIGN;
463         str = walk(0,level,ops[node+2].ival,&numarg,prec+1);
464         str_cat(str," ");
465         tmpstr = walk(0,level,ops[node+1].ival,&numarg,P_MIN);
466         str_scat(str,tmpstr);
467         if (str_len(tmpstr) > 1)
468             numeric = 1;
469         str_free(tmpstr);
470         str_cat(str," ");
471         str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,prec));
472         str_free(fstr);
473         numeric |= numarg;
474         if (strEQ(str->str_ptr,"$/ = ''"))
475             str_set(str, "$/ = \"\\n\\n\"");
476         break;
477     case OADD:
478         prec = P_ADD;
479         str = walk(1,level,ops[node+1].ival,&numarg,prec);
480         str_cat(str," + ");
481         str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1));
482         str_free(fstr);
483         numeric = 1;
484         break;
485     case OSUBTRACT:
486         prec = P_ADD;
487         str = walk(1,level,ops[node+1].ival,&numarg,prec);
488         str_cat(str," - ");
489         str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1));
490         str_free(fstr);
491         numeric = 1;
492         break;
493     case OMULT:
494         prec = P_MUL;
495         str = walk(1,level,ops[node+1].ival,&numarg,prec);
496         str_cat(str," * ");
497         str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1));
498         str_free(fstr);
499         numeric = 1;
500         break;
501     case ODIV:
502         prec = P_MUL;
503         str = walk(1,level,ops[node+1].ival,&numarg,prec);
504         str_cat(str," / ");
505         str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1));
506         str_free(fstr);
507         numeric = 1;
508         break;
509     case OPOW:
510         prec = P_POW;
511         str = walk(1,level,ops[node+1].ival,&numarg,prec+1);
512         str_cat(str," ** ");
513         str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec));
514         str_free(fstr);
515         numeric = 1;
516         break;
517     case OMOD:
518         prec = P_MUL;
519         str = walk(1,level,ops[node+1].ival,&numarg,prec);
520         str_cat(str," % ");
521         str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,prec+1));
522         str_free(fstr);
523         numeric = 1;
524         break;
525     case OPOSTINCR:
526         prec = P_AUTO;
527         str = walk(1,level,ops[node+1].ival,&numarg,prec+1);
528         str_cat(str,"++");
529         numeric = 1;
530         break;
531     case OPOSTDECR:
532         prec = P_AUTO;
533         str = walk(1,level,ops[node+1].ival,&numarg,prec+1);
534         str_cat(str,"--");
535         numeric = 1;
536         break;
537     case OPREINCR:
538         prec = P_AUTO;
539         str = str_new(0);
540         str_set(str,"++");
541         str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,prec+1));
542         str_free(fstr);
543         numeric = 1;
544         break;
545     case OPREDECR:
546         prec = P_AUTO;
547         str = str_new(0);
548         str_set(str,"--");
549         str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,prec+1));
550         str_free(fstr);
551         numeric = 1;
552         break;
553     case OUMINUS:
554         prec = P_UNARY;
555         str = str_new(0);
556         str_set(str,"-");
557         str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,prec));
558         str_free(fstr);
559         numeric = 1;
560         break;
561     case OUPLUS:
562         numeric = 1;
563         goto def;
564     case OPAREN:
565         str = str_new(0);
566         str_set(str,"(");
567         str_scat(str,
568           fstr=walk(useval != 0,level,ops[node+1].ival,&numarg,P_MIN));
569         str_free(fstr);
570         str_cat(str,")");
571         numeric |= numarg;
572         break;
573     case OGETLINE:
574         str = str_new(0);
575         if (useval)
576             str_cat(str,"(");
577         if (len > 0) {
578             str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN));
579             if (!*fstr->str_ptr) {
580                 str_cat(str,"$_");
581                 len = 2;                /* a legal fiction */
582             }
583             str_free(fstr);
584         }
585         else
586             str_cat(str,"$_");
587         if (len > 1) {
588             tmpstr=walk(1,level,ops[node+3].ival,&numarg,P_MIN);
589             fstr=walk(1,level,ops[node+2].ival,&numarg,P_MIN);
590             if (!do_fancy_opens) {
591                 t = tmpstr->str_ptr;
592                 if (*t == '"' || *t == '\'')
593                     t = cpytill(tokenbuf,t+1,*t);
594                 else
595                     fatal("Internal error: OGETLINE %s", t);
596                 d = savestr(t);
597                 s = savestr(tokenbuf);
598                 for (t = tokenbuf; *t; t++) {
599                     *t &= 127;
600                     if (islower(*t))
601                         *t = toupper(*t);
602                     if (!isalpha(*t) && !isdigit(*t))
603                         *t = '_';
604                 }
605                 if (!index(tokenbuf,'_'))
606                     strcpy(t,"_FH");
607                 tmp3str = hfetch(symtab,tokenbuf);
608                 if (!tmp3str) {
609                     do_opens = TRUE;
610                     str_cat(opens,"open(");
611                     str_cat(opens,tokenbuf);
612                     str_cat(opens,", ");
613                     d[1] = '\0';
614                     str_cat(opens,d);
615                     str_cat(opens,tmpstr->str_ptr+1);
616                     opens->str_cur--;
617                     if (*fstr->str_ptr == '|')
618                         str_cat(opens,"|");
619                     str_cat(opens,d);
620                     if (*fstr->str_ptr == '|')
621                         str_cat(opens,") || die 'Cannot pipe from \"");
622                     else
623                         str_cat(opens,") || die 'Cannot open file \"");
624                     if (*d == '"')
625                         str_cat(opens,"'.\"");
626                     str_cat(opens,s);
627                     if (*d == '"')
628                         str_cat(opens,"\".'");
629                     str_cat(opens,"\".';\n");
630                     hstore(symtab,tokenbuf,str_make("x"));
631                 }
632                 safefree(s);
633                 safefree(d);
634                 str_set(tmpstr,"'");
635                 str_cat(tmpstr,tokenbuf);
636                 str_cat(tmpstr,"'");
637             }
638             if (*fstr->str_ptr == '|')
639                 str_cat(tmpstr,", '|'");
640             str_free(fstr);
641         }
642         else
643             tmpstr = str_make("");
644         sprintf(tokenbuf," = &Getline%d(%s)",len,tmpstr->str_ptr);
645         str_cat(str,tokenbuf); 
646         str_free(tmpstr);
647         if (useval)
648             str_cat(str,",$getline_ok)");
649         saw_getline |= 1 << len;
650         break;
651     case OSPRINTF:
652         str = str_new(0);
653         str_set(str,"sprintf(");
654         str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN));
655         str_free(fstr);
656         str_cat(str,")");
657         break;
658     case OSUBSTR:
659         str = str_new(0);
660         str_set(str,"substr(");
661         str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_COMMA+1));
662         str_free(fstr);
663         str_cat(str,", ");
664         str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,P_COMMA+1));
665         str_free(fstr);
666         str_cat(str,", ");
667         if (len == 3) {
668             str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,P_COMMA+1));
669             str_free(fstr);
670         }
671         else
672             str_cat(str,"999999");
673         str_cat(str,")");
674         break;
675     case OSTRING:
676         str = str_new(0);
677         str_set(str,ops[node+1].cval);
678         break;
679     case OSPLIT:
680         str = str_new(0);
681         limit = ", 9999)";
682         numeric = 1;
683         tmpstr = walk(1,level,ops[node+2].ival,&numarg,P_MIN);
684         if (useval)
685             str_set(str,"(@");
686         else
687             str_set(str,"@");
688         str_scat(str,tmpstr);
689         str_cat(str," = split(");
690         if (len == 3) {
691             fstr = walk(1,level,ops[node+3].ival,&numarg,P_COMMA+1);
692             if (str_len(fstr) == 3 && *fstr->str_ptr == '\'') {
693                 i = fstr->str_ptr[1] & 127;
694                 if (index("*+?.[]()|^$\\",i))
695                     sprintf(tokenbuf,"/\\%c/",i);
696                 else if (i == ' ')
697                     sprintf(tokenbuf,"' '");
698                 else
699                     sprintf(tokenbuf,"/%c/",i);
700                 str_cat(str,tokenbuf);
701             }
702             else
703                 str_scat(str,fstr);
704             str_free(fstr);
705         }
706         else if (const_FS) {
707             sprintf(tokenbuf,"/[%c\\n]/",const_FS);
708             str_cat(str,tokenbuf);
709         }
710         else if (saw_FS)
711             str_cat(str,"$FS");
712         else {
713             str_cat(str,"' '");
714             limit = ")";
715         }
716         str_cat(str,", ");
717         str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_COMMA+1));
718         str_free(fstr);
719         str_cat(str,limit);
720         if (useval) {
721             str_cat(str,")");
722         }
723         str_free(tmpstr);
724         break;
725     case OINDEX:
726         str = str_new(0);
727         str_set(str,"index(");
728         str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_COMMA+1));
729         str_free(fstr);
730         str_cat(str,", ");
731         str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,P_COMMA+1));
732         str_free(fstr);
733         str_cat(str,")");
734         numeric = 1;
735         break;
736     case OMATCH:
737         str = str_new(0);
738         prec = P_ANDAND;
739         str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_MATCH+1));
740         str_free(fstr);
741         str_cat(str," =~ ");
742         str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,P_MATCH+1));
743         str_free(fstr);
744         str_cat(str," && ($RLENGTH = length($&), $RSTART = length($`)+1)");
745         numeric = 1;
746         break;
747     case OUSERDEF:
748         str = str_new(0);
749         subretnum = FALSE;
750         fstr=walk(1,level-1,ops[node+2].ival,&numarg,P_MIN);
751         curargs = str_new(0);
752         str_sset(curargs,fstr);
753         str_cat(curargs,",");
754         tmp2str=walk(1,level,ops[node+5].ival,&numarg,P_MIN);
755         str_free(curargs);
756         curargs = Nullstr;
757         level--;
758         subretnum |= numarg;
759         s = Nullch;
760         t = tmp2str->str_ptr;
761         while (t = instr(t,"return "))
762             s = t++;
763         if (s) {
764             i = 0;
765             for (t = s+7; *t; t++) {
766                 if (*t == ';' || *t == '}')
767                     i++;
768             }
769             if (i == 1) {
770                 strcpy(s,s+7);
771                 tmp2str->str_cur -= 7;
772             }
773         }
774         str_set(str,"\n");
775         tab(str,level);
776         str_cat(str,"sub ");
777         str_scat(str,tmpstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN));
778         str_cat(str," {\n");
779         tab(str,++level);
780         if (fstr->str_cur) {
781             str_cat(str,"local(");
782             str_scat(str,fstr);
783             str_cat(str,") = @_;");
784         }
785         str_free(fstr);
786         str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,P_MIN));
787         str_free(fstr);
788         fixtab(str,level);
789         str_scat(str,fstr=walk(1,level,ops[node+4].ival,&numarg,P_MIN));
790         str_free(fstr);
791         fixtab(str,level);
792         str_scat(str,tmp2str);
793         str_free(tmp2str);
794         fixtab(str,--level);
795         str_cat(str,"}\n");
796         tab(str,level);
797         str_scat(subs,str);
798         str_set(str,"");
799         str_cat(tmpstr,"(");
800         tmp2str = str_new(0);
801         if (subretnum)
802             str_set(tmp2str,"1");
803         hstore(symtab,tmpstr->str_ptr,tmp2str);
804         str_free(tmpstr);
805         level++;
806         break;
807     case ORETURN:
808         str = str_new(0);
809         if (len > 0) {
810             str_cat(str,"return ");
811             str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_UNI+1));
812             str_free(fstr);
813             if (numarg)
814                 subretnum = TRUE;
815         }
816         else
817             str_cat(str,"return");
818         break;
819     case OUSERFUN:
820         str = str_new(0);
821         str_set(str,"&");
822         str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN));
823         str_free(fstr);
824         str_cat(str,"(");
825         tmpstr = hfetch(symtab,str->str_ptr+3);
826         if (tmpstr && tmpstr->str_ptr)
827             numeric |= atoi(tmpstr->str_ptr);
828         str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,P_MIN));
829         str_free(fstr);
830         str_cat(str,")");
831         break;
832     case OGSUB:
833     case OSUB:
834         if (type == OGSUB)
835             s = "g";
836         else
837             s = "";
838         str = str_new(0);
839         tmpstr = str_new(0);
840         i = 0;
841         if (len == 3) {
842             tmpstr = walk(1,level,ops[node+3].ival,&numarg,P_MATCH+1);
843             if (strNE(tmpstr->str_ptr,"$_")) {
844                 str_cat(tmpstr, " =~ s");
845                 i++;
846             }
847             else
848                 str_set(tmpstr, "s");
849         }
850         else
851             str_set(tmpstr, "s");
852         type = ops[ops[node+2].ival].ival;
853         len = type >> 8;
854         type &= 255;
855         tmp3str = str_new(0);
856         if (type == OSTR) {
857             tmp2str=walk(1,level,ops[ops[node+2].ival+1].ival,&numarg,P_MIN);
858             for (t = tmp2str->str_ptr, d=tokenbuf; *t; d++,t++) {
859                 if (*t == '&')
860                     *d++ = '$' + 128;
861                 else if (*t == '$')
862                     *d++ = '\\' + 128;
863                 *d = *t + 128;
864             }
865             *d = '\0';
866             str_set(tmp2str,tokenbuf);
867         }
868         else {
869             tmp2str=walk(1,level,ops[node+2].ival,&numarg,P_MIN);
870             str_set(tmp3str,"($s_ = '\"'.(");
871             str_scat(tmp3str,tmp2str);
872             str_cat(tmp3str,").'\"') =~ s/&/\\$&/g, ");
873             str_set(tmp2str,"eval $s_");
874             s = (*s == 'g' ? "ge" : "e");
875             i++;
876         }
877         type = ops[ops[node+1].ival].ival;
878         len = type >> 8;
879         type &= 255;
880         fstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN);
881         if (type == OREGEX) {
882             if (useval && i)
883                 str_cat(str,"(");
884             str_scat(str,tmp3str);
885             str_scat(str,tmpstr);
886             str_scat(str,fstr);
887             str_scat(str,tmp2str);
888             str_cat(str,"/");
889             str_cat(str,s);
890         }
891         else if ((type == OFLD && !split_to_array) || (type == OVAR && len == 1)) {
892             if (useval && i)
893                 str_cat(str,"(");
894             str_scat(str,tmp3str);
895             str_scat(str,tmpstr);
896             str_cat(str,"/");
897             str_scat(str,fstr);
898             str_cat(str,"/");
899             str_scat(str,tmp2str);
900             str_cat(str,"/");
901             str_cat(str,s);
902         }
903         else {
904             i++;
905             if (useval)
906                 str_cat(str,"(");
907             str_cat(str,"$s = ");
908             str_scat(str,fstr);
909             str_cat(str,", ");
910             str_scat(str,tmp3str);
911             str_scat(str,tmpstr);
912             str_cat(str,"/$s/");
913             str_scat(str,tmp2str);
914             str_cat(str,"/");
915             str_cat(str,s);
916         }
917         if (useval && i)
918             str_cat(str,")");
919         str_free(fstr);
920         str_free(tmpstr);
921         str_free(tmp2str);
922         str_free(tmp3str);
923         numeric = 1;
924         break;
925     case ONUM:
926         str = walk(1,level,ops[node+1].ival,&numarg,P_MIN);
927         numeric = 1;
928         break;
929     case OSTR:
930         tmpstr = walk(1,level,ops[node+1].ival,&numarg,P_MIN);
931         s = "'";
932         for (t = tmpstr->str_ptr, d=tokenbuf; *t; d++,t++) {
933             if (*t == '\'')
934                 s = "\"";
935             else if (*t == '\\') {
936                 s = "\"";
937                 *d++ = *t++ + 128;
938                 switch (*t) {
939                 case '\\': case '"': case 'n': case 't': case '$':
940                     break;
941                 default:        /* hide this from perl */
942                     *d++ = '\\' + 128;
943                 }
944             }
945             *d = *t + 128;
946         }
947         *d = '\0';
948         str = str_new(0);
949         str_set(str,s);
950         str_cat(str,tokenbuf);
951         str_free(tmpstr);
952         str_cat(str,s);
953         break;
954     case ODEFINED:
955         prec = P_UNI;
956         str = str_new(0);
957         str_set(str,"defined $");
958         goto addvar;
959     case ODELETE:
960         str = str_new(0);
961         str_set(str,"delete $");
962         goto addvar;
963     case OSTAR:
964         str = str_new(0);
965         str_set(str,"*");
966         goto addvar;
967     case OVAR:
968         str = str_new(0);
969         str_set(str,"$");
970       addvar:
971         str_scat(str,tmpstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN));
972         if (len == 1) {
973             tmp2str = hfetch(symtab,tmpstr->str_ptr);
974             if (tmp2str && atoi(tmp2str->str_ptr))
975                 numeric = 2;
976             if (strEQ(str->str_ptr,"$FNR")) {
977                 numeric = 1;
978                 saw_FNR++;
979                 str_set(str,"($.-$FNRbase)");
980             }
981             else if (strEQ(str->str_ptr,"$NR")) {
982                 numeric = 1;
983                 str_set(str,"$.");
984             }
985             else if (strEQ(str->str_ptr,"$NF")) {
986                 numeric = 1;
987                 str_set(str,"$#Fld");
988             }
989             else if (strEQ(str->str_ptr,"$0"))
990                 str_set(str,"$_");
991             else if (strEQ(str->str_ptr,"$ARGC"))
992                 str_set(str,"($#ARGV+1)");
993         }
994         else {
995 #ifdef NOTDEF
996             if (curargs) {
997                 sprintf(tokenbuf,"$%s,",tmpstr->str_ptr);
998         ???     if (instr(curargs->str_ptr,tokenbuf))
999                     str_cat(str,"\377");        /* can't translate yet */
1000             }
1001 #endif
1002             str_cat(tmpstr,"[]");
1003             tmp2str = hfetch(symtab,tmpstr->str_ptr);
1004             if (tmp2str && atoi(tmp2str->str_ptr))
1005                 str_cat(str,"[");
1006             else
1007                 str_cat(str,"{");
1008             str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,P_MIN));
1009             str_free(fstr);
1010             if (strEQ(str->str_ptr,"$ARGV[0")) {
1011                 str_set(str,"$ARGV0");
1012                 saw_argv0++;
1013             }
1014             else {
1015                 if (tmp2str && atoi(tmp2str->str_ptr))
1016                     strcpy(tokenbuf,"]");
1017                 else
1018                     strcpy(tokenbuf,"}");
1019                 *tokenbuf += 128;
1020                 str_cat(str,tokenbuf);
1021             }
1022         }
1023         str_free(tmpstr);
1024         break;
1025     case OFLD:
1026         str = str_new(0);
1027         if (split_to_array) {
1028             str_set(str,"$Fld");
1029             str_cat(str,"[");
1030             str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN));
1031             str_free(fstr);
1032             str_cat(str,"]");
1033         }
1034         else {
1035             i = atoi(walk(1,level,ops[node+1].ival,&numarg,P_MIN)->str_ptr);
1036             if (i <= arymax)
1037                 sprintf(tokenbuf,"$%s",nameary[i]);
1038             else
1039                 sprintf(tokenbuf,"$Fld%d",i);
1040             str_set(str,tokenbuf);
1041         }
1042         break;
1043     case OVFLD:
1044         str = str_new(0);
1045         str_set(str,"$Fld[");
1046         i = ops[node+1].ival;
1047         if ((ops[i].ival & 255) == OPAREN)
1048             i = ops[i+1].ival;
1049         tmpstr=walk(1,level,i,&numarg,P_MIN);
1050         str_scat(str,tmpstr);
1051         str_free(tmpstr);
1052         str_cat(str,"]");
1053         break;
1054     case OJUNK:
1055         goto def;
1056     case OSNEWLINE:
1057         str = str_new(2);
1058         str_set(str,";\n");
1059         tab(str,level);
1060         break;
1061     case ONEWLINE:
1062         str = str_new(1);
1063         str_set(str,"\n");
1064         tab(str,level);
1065         break;
1066     case OSCOMMENT:
1067         str = str_new(0);
1068         str_set(str,";");
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 OCOMMENT:
1077         str = str_new(0);
1078         tmpstr = walk(0,level,ops[node+1].ival,&numarg,P_MIN);
1079         for (s = tmpstr->str_ptr; *s && *s != '\n'; s++)
1080             *s += 128;
1081         str_scat(str,tmpstr);
1082         str_free(tmpstr);
1083         tab(str,level);
1084         break;
1085     case OCOMMA:
1086         prec = P_COMMA;
1087         str = walk(1,level,ops[node+1].ival,&numarg,prec);
1088         str_cat(str,", ");
1089         str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,P_MIN));
1090         str_free(fstr);
1091         str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,prec+1));
1092         str_free(fstr);
1093         break;
1094     case OSEMICOLON:
1095         str = str_new(1);
1096         str_set(str,";\n");
1097         tab(str,level);
1098         break;
1099     case OSTATES:
1100         str = walk(0,level,ops[node+1].ival,&numarg,P_MIN);
1101         str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg,P_MIN));
1102         str_free(fstr);
1103         break;
1104     case OSTATE:
1105         str = str_new(0);
1106         if (len >= 1) {
1107             str_scat(str,fstr=walk(0,level,ops[node+1].ival,&numarg,P_MIN));
1108             str_free(fstr);
1109             if (len >= 2) {
1110                 tmpstr = walk(0,level,ops[node+2].ival,&numarg,P_MIN);
1111                 if (*tmpstr->str_ptr == ';') {
1112                     addsemi(str);
1113                     str_cat(str,tmpstr->str_ptr+1);
1114                 }
1115                 str_free(tmpstr);
1116             }
1117         }
1118         break;
1119     case OCLOSE:
1120         str = str_make("close(");
1121         tmpstr = walk(1,level,ops[node+1].ival,&numarg,P_MIN);
1122         if (!do_fancy_opens) {
1123             t = tmpstr->str_ptr;
1124             if (*t == '"' || *t == '\'')
1125                 t = cpytill(tokenbuf,t+1,*t);
1126             else
1127                 fatal("Internal error: OCLOSE %s",t);
1128             s = savestr(tokenbuf);
1129             for (t = tokenbuf; *t; t++) {
1130                 *t &= 127;
1131                 if (islower(*t))
1132                     *t = toupper(*t);
1133                 if (!isalpha(*t) && !isdigit(*t))
1134                     *t = '_';
1135             }
1136             if (!index(tokenbuf,'_'))
1137                 strcpy(t,"_FH");
1138             str_free(tmpstr);
1139             safefree(s);
1140             str_set(str,"close ");
1141             str_cat(str,tokenbuf);
1142         }
1143         else {
1144             sprintf(tokenbuf,"delete $opened{%s} && close(%s)",
1145                tmpstr->str_ptr, tmpstr->str_ptr);
1146             str_free(tmpstr);
1147             str_set(str,tokenbuf);
1148         }
1149         break;
1150     case OPRINTF:
1151     case OPRINT:
1152         lparen = "";    /* set to parens if necessary */
1153         rparen = "";
1154         str = str_new(0);
1155         if (len == 3) {         /* output redirection */
1156             tmpstr = walk(1,level,ops[node+3].ival,&numarg,P_MIN);
1157             tmp2str = walk(1,level,ops[node+2].ival,&numarg,P_MIN);
1158             if (!do_fancy_opens) {
1159                 t = tmpstr->str_ptr;
1160                 if (*t == '"' || *t == '\'')
1161                     t = cpytill(tokenbuf,t+1,*t);
1162                 else
1163                     fatal("Internal error: OPRINT");
1164                 d = savestr(t);
1165                 s = savestr(tokenbuf);
1166                 for (t = tokenbuf; *t; t++) {
1167                     *t &= 127;
1168                     if (islower(*t))
1169                         *t = toupper(*t);
1170                     if (!isalpha(*t) && !isdigit(*t))
1171                         *t = '_';
1172                 }
1173                 if (!index(tokenbuf,'_'))
1174                     strcpy(t,"_FH");
1175                 tmp3str = hfetch(symtab,tokenbuf);
1176                 if (!tmp3str) {
1177                     str_cat(opens,"open(");
1178                     str_cat(opens,tokenbuf);
1179                     str_cat(opens,", ");
1180                     d[1] = '\0';
1181                     str_cat(opens,d);
1182                     str_scat(opens,tmp2str);
1183                     str_cat(opens,tmpstr->str_ptr+1);
1184                     if (*tmp2str->str_ptr == '|')
1185                         str_cat(opens,") || die 'Cannot pipe to \"");
1186                     else
1187                         str_cat(opens,") || die 'Cannot create file \"");
1188                     if (*d == '"')
1189                         str_cat(opens,"'.\"");
1190                     str_cat(opens,s);
1191                     if (*d == '"')
1192                         str_cat(opens,"\".'");
1193                     str_cat(opens,"\".';\n");
1194                     hstore(symtab,tokenbuf,str_make("x"));
1195                 }
1196                 str_free(tmpstr);
1197                 str_free(tmp2str);
1198                 safefree(s);
1199                 safefree(d);
1200             }
1201             else {
1202                 sprintf(tokenbuf,"&Pick('%s', %s) &&\n",
1203                    tmp2str->str_ptr, tmpstr->str_ptr);
1204                 str_cat(str,tokenbuf);
1205                 tab(str,level+1);
1206                 strcpy(tokenbuf,"$fh");
1207                 str_free(tmpstr);
1208                 str_free(tmp2str);
1209                 lparen = "(";
1210                 rparen = ")";
1211             }
1212         }
1213         else
1214             strcpy(tokenbuf,"");
1215         str_cat(str,lparen);    /* may be null */
1216         if (type == OPRINTF)
1217             str_cat(str,"printf");
1218         else
1219             str_cat(str,"print");
1220         saw_fh = 0;
1221         if (len == 3 || do_fancy_opens) {
1222             if (*tokenbuf) {
1223                 str_cat(str," ");
1224                 saw_fh = 1;
1225             }
1226             str_cat(str,tokenbuf);
1227         }
1228         tmpstr = walk(1+(type==OPRINT),level,ops[node+1].ival,&numarg,P_MIN);
1229         if (!*tmpstr->str_ptr && lval_field) {
1230             t = saw_OFS ? "$," : "' '";
1231             if (split_to_array) {
1232                 sprintf(tokenbuf,"join(%s,@Fld)",t);
1233                 str_cat(tmpstr,tokenbuf);
1234             }
1235             else {
1236                 for (i = 1; i < maxfld; i++) {
1237                     if (i <= arymax)
1238                         sprintf(tokenbuf,"$%s, ",nameary[i]);
1239                     else
1240                         sprintf(tokenbuf,"$Fld%d, ",i);
1241                     str_cat(tmpstr,tokenbuf);
1242                 }
1243                 if (maxfld <= arymax)
1244                     sprintf(tokenbuf,"$%s",nameary[maxfld]);
1245                 else
1246                     sprintf(tokenbuf,"$Fld%d",maxfld);
1247                 str_cat(tmpstr,tokenbuf);
1248             }
1249         }
1250         if (*tmpstr->str_ptr) {
1251             str_cat(str," ");
1252             if (!saw_fh && *tmpstr->str_ptr == '(') {
1253                 str_cat(str,"(");
1254                 str_scat(str,tmpstr);
1255                 str_cat(str,")");
1256             }
1257             else
1258                 str_scat(str,tmpstr);
1259         }
1260         else {
1261             str_cat(str," $_");
1262         }
1263         str_cat(str,rparen);    /* may be null */
1264         str_free(tmpstr);
1265         break;
1266     case ORAND:
1267         str = str_make("rand(1)");
1268         break;
1269     case OSRAND:
1270         str = str_make("srand(");
1271         goto maybe0;
1272     case OATAN2:
1273         str = str_make("atan2(");
1274         goto maybe0;
1275     case OSIN:
1276         str = str_make("sin(");
1277         goto maybe0;
1278     case OCOS:
1279         str = str_make("cos(");
1280         goto maybe0;
1281     case OSYSTEM:
1282         str = str_make("system(");
1283         goto maybe0;
1284     case OLENGTH:
1285         str = str_make("length(");
1286         goto maybe0;
1287     case OLOG:
1288         str = str_make("log(");
1289         goto maybe0;
1290     case OEXP:
1291         str = str_make("exp(");
1292         goto maybe0;
1293     case OSQRT:
1294         str = str_make("sqrt(");
1295         goto maybe0;
1296     case OINT:
1297         str = str_make("int(");
1298       maybe0:
1299         numeric = 1;
1300         if (len > 0)
1301             tmpstr = walk(1,level,ops[node+1].ival,&numarg,P_MIN);
1302         else
1303             tmpstr = str_new(0);;
1304         if (!tmpstr->str_ptr || !*tmpstr->str_ptr) {
1305             if (lval_field) {
1306                 t = saw_OFS ? "$," : "' '";
1307                 if (split_to_array) {
1308                     sprintf(tokenbuf,"join(%s,@Fld)",t);
1309                     str_cat(tmpstr,tokenbuf);
1310                 }
1311                 else {
1312                     sprintf(tokenbuf,"join(%s, ",t);
1313                     str_cat(tmpstr,tokenbuf);
1314                     for (i = 1; i < maxfld; i++) {
1315                         if (i <= arymax)
1316                             sprintf(tokenbuf,"$%s,",nameary[i]);
1317                         else
1318                             sprintf(tokenbuf,"$Fld%d,",i);
1319                         str_cat(tmpstr,tokenbuf);
1320                     }
1321                     if (maxfld <= arymax)
1322                         sprintf(tokenbuf,"$%s)",nameary[maxfld]);
1323                     else
1324                         sprintf(tokenbuf,"$Fld%d)",maxfld);
1325                     str_cat(tmpstr,tokenbuf);
1326                 }
1327             }
1328             else
1329                 str_cat(tmpstr,"$_");
1330         }
1331         if (strEQ(tmpstr->str_ptr,"$_")) {
1332             if (type == OLENGTH && !do_chop) {
1333                 str = str_make("(length(");
1334                 str_cat(tmpstr,") - 1");
1335             }
1336         }
1337         str_scat(str,tmpstr);
1338         str_free(tmpstr);
1339         str_cat(str,")");
1340         break;
1341     case OBREAK:
1342         str = str_new(0);
1343         str_set(str,"last");
1344         break;
1345     case ONEXT:
1346         str = str_new(0);
1347         str_set(str,"next line");
1348         break;
1349     case OEXIT:
1350         str = str_new(0);
1351         if (realexit) {
1352             prec = P_UNI;
1353             str_set(str,"exit");
1354             if (len == 1) {
1355                 str_cat(str," ");
1356                 exitval = TRUE;
1357                 str_scat(str,
1358                   fstr=walk(1,level,ops[node+1].ival,&numarg,prec+1));
1359                 str_free(fstr);
1360             }
1361         }
1362         else {
1363             if (len == 1) {
1364                 str_set(str,"$ExitValue = ");
1365                 exitval = TRUE;
1366                 str_scat(str,
1367                   fstr=walk(1,level,ops[node+1].ival,&numarg,P_ASSIGN));
1368                 str_free(fstr);
1369                 str_cat(str,"; ");
1370             }
1371             str_cat(str,"last line");
1372         }
1373         break;
1374     case OCONTINUE:
1375         str = str_new(0);
1376         str_set(str,"next");
1377         break;
1378     case OREDIR:
1379         goto def;
1380     case OIF:
1381         str = str_new(0);
1382         str_set(str,"if (");
1383         str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN));
1384         str_free(fstr);
1385         str_cat(str,") ");
1386         str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg,P_MIN));
1387         str_free(fstr);
1388         if (len == 3) {
1389             i = ops[node+3].ival;
1390             if (i) {
1391                 if ((ops[i].ival & 255) == OBLOCK) {
1392                     i = ops[i+1].ival;
1393                     if (i) {
1394                         if ((ops[i].ival & 255) != OIF)
1395                             i = 0;
1396                     }
1397                 }
1398                 else
1399                     i = 0;
1400             }
1401             if (i) {
1402                 str_cat(str,"els");
1403                 str_scat(str,fstr=walk(0,level,i,&numarg,P_MIN));
1404                 str_free(fstr);
1405             }
1406             else {
1407                 str_cat(str,"else ");
1408                 str_scat(str,fstr=walk(0,level,ops[node+3].ival,&numarg,P_MIN));
1409                 str_free(fstr);
1410             }
1411         }
1412         break;
1413     case OWHILE:
1414         str = str_new(0);
1415         str_set(str,"while (");
1416         str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN));
1417         str_free(fstr);
1418         str_cat(str,") ");
1419         str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg,P_MIN));
1420         str_free(fstr);
1421         break;
1422     case ODO:
1423         str = str_new(0);
1424         str_set(str,"do ");
1425         str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN));
1426         str_free(fstr);
1427         if (str->str_ptr[str->str_cur - 1] == '\n')
1428             --str->str_cur;;
1429         str_cat(str," while (");
1430         str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg,P_MIN));
1431         str_free(fstr);
1432         str_cat(str,");");
1433         break;
1434     case OFOR:
1435         str = str_new(0);
1436         str_set(str,"for (");
1437         str_scat(str,tmpstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN));
1438         i = numarg;
1439         if (i) {
1440             t = s = tmpstr->str_ptr;
1441             while (isalpha(*t) || isdigit(*t) || *t == '$' || *t == '_')
1442                 t++;
1443             i = t - s;
1444             if (i < 2)
1445                 i = 0;
1446         }
1447         str_cat(str,"; ");
1448         fstr=walk(1,level,ops[node+2].ival,&numarg,P_MIN);
1449         if (i && (t = index(fstr->str_ptr,0377))) {
1450             if (strnEQ(fstr->str_ptr,s,i))
1451                 *t = ' ';
1452         }
1453         str_scat(str,fstr);
1454         str_free(fstr);
1455         str_free(tmpstr);
1456         str_cat(str,"; ");
1457         str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,P_MIN));
1458         str_free(fstr);
1459         str_cat(str,") ");
1460         str_scat(str,fstr=walk(0,level,ops[node+4].ival,&numarg,P_MIN));
1461         str_free(fstr);
1462         break;
1463     case OFORIN:
1464         tmpstr = walk(0,level,ops[node+1].ival,&numarg,P_MIN);
1465         d = index(tmpstr->str_ptr,'$');
1466         if (!d)
1467             fatal("Illegal for loop: %s",tmpstr->str_ptr);
1468         s = index(d,'{');
1469         if (!s)
1470             s = index(d,'[');
1471         if (!s)
1472             fatal("Illegal for loop: %s",d);
1473         *s++ = '\0';
1474         for (t = s; i = *t; t++) {
1475             i &= 127;
1476             if (i == '}' || i == ']')
1477                 break;
1478         }
1479         if (*t)
1480             *t = '\0';
1481         str = str_new(0);
1482         str_set(str,d+1);
1483         str_cat(str,"[]");
1484         tmp2str = hfetch(symtab,str->str_ptr);
1485         if (tmp2str && atoi(tmp2str->str_ptr)) {
1486             sprintf(tokenbuf,
1487               "foreach %s ($[ .. $#%s) ",
1488               s,
1489               d+1);
1490         }
1491         else {
1492             sprintf(tokenbuf,
1493               "foreach %s (keys %%%s) ",
1494               s,
1495               d+1);
1496         }
1497         str_set(str,tokenbuf);
1498         str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg,P_MIN));
1499         str_free(fstr);
1500         str_free(tmpstr);
1501         break;
1502     case OBLOCK:
1503         str = str_new(0);
1504         str_set(str,"{");
1505         if (len >= 2 && ops[node+2].ival) {
1506             str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg,P_MIN));
1507             str_free(fstr);
1508         }
1509         fixtab(str,++level);
1510         str_scat(str,fstr=walk(0,level,ops[node+1].ival,&numarg,P_MIN));
1511         str_free(fstr);
1512         addsemi(str);
1513         fixtab(str,--level);
1514         str_cat(str,"}\n");
1515         tab(str,level);
1516         if (len >= 3) {
1517             str_scat(str,fstr=walk(0,level,ops[node+3].ival,&numarg,P_MIN));
1518             str_free(fstr);
1519         }
1520         break;
1521     default:
1522       def:
1523         if (len) {
1524             if (len > 5)
1525                 fatal("Garbage length in walk");
1526             str = walk(0,level,ops[node+1].ival,&numarg,P_MIN);
1527             for (i = 2; i<= len; i++) {
1528                 str_scat(str,fstr=walk(0,level,ops[node+i].ival,&numarg,P_MIN));
1529                 str_free(fstr);
1530             }
1531         }
1532         else {
1533             str = Nullstr;
1534         }
1535         break;
1536     }
1537     if (!str)
1538         str = str_new(0);
1539
1540     if (useval && prec < minprec) {             /* need parens? */
1541         fstr = str_new(str->str_cur+2);
1542         str_nset(fstr,"(",1);
1543         str_scat(fstr,str);
1544         str_ncat(fstr,")",1);
1545         str_free(str);
1546         str = fstr;
1547     }
1548
1549     *numericptr = numeric;
1550 #ifdef DEBUGGING
1551     if (debug & 4) {
1552         printf("%3d %5d %15s %d %4d ",level,node,opname[type],len,str->str_cur);
1553         for (t = str->str_ptr; *t && t - str->str_ptr < 40; t++)
1554             if (*t == '\n')
1555                 printf("\\n");
1556             else if (*t == '\t')
1557                 printf("\\t");
1558             else
1559                 putchar(*t);
1560         putchar('\n');
1561     }
1562 #endif
1563     return str;
1564 }
1565
1566 tab(str,lvl)
1567 register STR *str;
1568 register int lvl;
1569 {
1570     while (lvl > 1) {
1571         str_cat(str,"\t");
1572         lvl -= 2;
1573     }
1574     if (lvl)
1575         str_cat(str,"    ");
1576 }
1577
1578 fixtab(str,lvl)
1579 register STR *str;
1580 register int lvl;
1581 {
1582     register char *s;
1583
1584     /* strip trailing white space */
1585
1586     s = str->str_ptr+str->str_cur - 1;
1587     while (s >= str->str_ptr && (*s == ' ' || *s == '\t' || *s == '\n'))
1588         s--;
1589     s[1] = '\0';
1590     str->str_cur = s + 1 - str->str_ptr;
1591     if (s >= str->str_ptr && *s != '\n')
1592         str_cat(str,"\n");
1593
1594     tab(str,lvl);
1595 }
1596
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 emit_split(str,level)
1610 register STR *str;
1611 int level;
1612 {
1613     register int i;
1614
1615     if (split_to_array)
1616         str_cat(str,"@Fld");
1617     else {
1618         str_cat(str,"(");
1619         for (i = 1; i < maxfld; i++) {
1620             if (i <= arymax)
1621                 sprintf(tokenbuf,"$%s,",nameary[i]);
1622             else
1623                 sprintf(tokenbuf,"$Fld%d,",i);
1624             str_cat(str,tokenbuf);
1625         }
1626         if (maxfld <= arymax)
1627             sprintf(tokenbuf,"$%s)",nameary[maxfld]);
1628         else
1629             sprintf(tokenbuf,"$Fld%d)",maxfld);
1630         str_cat(str,tokenbuf);
1631     }
1632     if (const_FS) {
1633         sprintf(tokenbuf," = split(/[%c\\n]/, $_, 9999);\n",const_FS);
1634         str_cat(str,tokenbuf);
1635     }
1636     else if (saw_FS)
1637         str_cat(str," = split($FS, $_, 9999);\n");
1638     else
1639         str_cat(str," = split(' ', $_, 9999);\n");
1640     tab(str,level);
1641 }
1642
1643 prewalk(numit,level,node,numericptr)
1644 int numit;
1645 int level;
1646 register int node;
1647 int *numericptr;
1648 {
1649     register int len;
1650     register int type;
1651     register int i;
1652     char *t;
1653     char *d, *s;
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) > 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 numericize(node)
2066 register int node;
2067 {
2068     register int len;
2069     register int type;
2070     register int i;
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 }