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