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