S_del_body is sufficiently small that inlining it is a space win.
[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         str_cat(str,", ");
664         if (len == 3) {
665             str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,P_COMMA+1));
666             str_free(fstr);
667         }
668         else
669             str_cat(str,"999999");
670         str_cat(str,")");
671         break;
672     case OSTRING:
673         str = str_new(0);
674         str_set(str,ops[node+1].cval);
675         break;
676     case OSPLIT:
677         str = str_new(0);
678         limit = ", 9999)";
679         numeric = 1;
680         tmpstr = walk(1,level,ops[node+2].ival,&numarg,P_MIN);
681         if (useval)
682             str_set(str,"(@");
683         else
684             str_set(str,"@");
685         str_scat(str,tmpstr);
686         str_cat(str," = split(");
687         if (len == 3) {
688             fstr = walk(1,level,ops[node+3].ival,&numarg,P_COMMA+1);
689             if (str_len(fstr) == 3 && *fstr->str_ptr == '\'') {
690                 i = fstr->str_ptr[1] & 127;
691                 if (strchr("*+?.[]()|^$\\",i))
692                     sprintf(tokenbuf,"/\\%c/",i);
693                 else if (i == ' ')
694                     sprintf(tokenbuf,"' '");
695                 else
696                     sprintf(tokenbuf,"/%c/",i);
697                 str_cat(str,tokenbuf);
698             }
699             else
700                 str_scat(str,fstr);
701             str_free(fstr);
702         }
703         else if (const_FS) {
704             sprintf(tokenbuf,"/[%c\\n]/",const_FS);
705             str_cat(str,tokenbuf);
706         }
707         else if (saw_FS)
708             str_cat(str,"$FS");
709         else {
710             str_cat(str,"' '");
711             limit = ")";
712         }
713         str_cat(str,", ");
714         str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_COMMA+1));
715         str_free(fstr);
716         str_cat(str,limit);
717         if (useval) {
718             str_cat(str,")");
719         }
720         str_free(tmpstr);
721         break;
722     case OINDEX:
723         str = str_new(0);
724         str_set(str,"index(");
725         str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_COMMA+1));
726         str_free(fstr);
727         str_cat(str,", ");
728         str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,P_COMMA+1));
729         str_free(fstr);
730         str_cat(str,")");
731         numeric = 1;
732         break;
733     case OMATCH:
734         str = str_new(0);
735         prec = P_ANDAND;
736         str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_MATCH+1));
737         str_free(fstr);
738         str_cat(str," =~ ");
739         str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,P_MATCH+1));
740         str_free(fstr);
741         str_cat(str," && ($RLENGTH = length($&), $RSTART = length($`)+1)");
742         numeric = 1;
743         break;
744     case OUSERDEF:
745         str = str_new(0);
746         subretnum = FALSE;
747         fstr=walk(1,level-1,ops[node+2].ival,&numarg,P_MIN);
748         curargs = str_new(0);
749         str_sset(curargs,fstr);
750         str_cat(curargs,",");
751         tmp2str=walk(1,level,ops[node+5].ival,&numarg,P_MIN);
752         str_free(curargs);
753         curargs = Nullstr;
754         level--;
755         subretnum |= numarg;
756         s = Nullch;
757         t = tmp2str->str_ptr;
758         while ((t = instr(t,"return ")))
759             s = t++;
760         if (s) {
761             i = 0;
762             for (t = s+7; *t; t++) {
763                 if (*t == ';' || *t == '}')
764                     i++;
765             }
766             if (i == 1) {
767                 strcpy(s,s+7);
768                 tmp2str->str_cur -= 7;
769             }
770         }
771         str_set(str,"\n");
772         tab(str,level);
773         str_cat(str,"sub ");
774         str_scat(str,tmpstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN));
775         str_cat(str," {\n");
776         tab(str,++level);
777         if (fstr->str_cur) {
778             str_cat(str,"local(");
779             str_scat(str,fstr);
780             str_cat(str,") = @_;");
781         }
782         str_free(fstr);
783         str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,P_MIN));
784         str_free(fstr);
785         fixtab(str,level);
786         str_scat(str,fstr=walk(1,level,ops[node+4].ival,&numarg,P_MIN));
787         str_free(fstr);
788         fixtab(str,level);
789         str_scat(str,tmp2str);
790         str_free(tmp2str);
791         fixtab(str,--level);
792         str_cat(str,"}\n");
793         tab(str,level);
794         str_scat(subs,str);
795         str_set(str,"");
796         str_cat(tmpstr,"(");
797         tmp2str = str_new(0);
798         if (subretnum)
799             str_set(tmp2str,"1");
800         hstore(symtab,tmpstr->str_ptr,tmp2str);
801         str_free(tmpstr);
802         level++;
803         break;
804     case ORETURN:
805         str = str_new(0);
806         if (len > 0) {
807             str_cat(str,"return ");
808             str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_UNI+1));
809             str_free(fstr);
810             if (numarg)
811                 subretnum = TRUE;
812         }
813         else
814             str_cat(str,"return");
815         break;
816     case OUSERFUN:
817         str = str_new(0);
818         str_set(str,"&");
819         str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN));
820         str_free(fstr);
821         str_cat(str,"(");
822         tmpstr = hfetch(symtab,str->str_ptr+3);
823         if (tmpstr && tmpstr->str_ptr)
824             numeric |= atoi(tmpstr->str_ptr);
825         str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,P_MIN));
826         str_free(fstr);
827         str_cat(str,")");
828         break;
829     case OGSUB:
830     case OSUB: {
831         int gsub = type == OGSUB ? 1 : 0;
832         str = str_new(0);
833         tmpstr = str_new(0);
834         i = 0;
835         if (len == 3) {
836             tmpstr = walk(1,level,ops[node+3].ival,&numarg,P_MATCH+1);
837             if (strNE(tmpstr->str_ptr,"$_")) {
838                 str_cat(tmpstr, " =~ s");
839                 i++;
840             }
841             else
842                 str_set(tmpstr, "s");
843         }
844         else
845             str_set(tmpstr, "s");
846         type = ops[ops[node+2].ival].ival;
847         len = type >> 8;
848         type &= 255;
849         tmp3str = str_new(0);
850         if (type == OSTR) {
851             tmp2str=walk(1,level,ops[ops[node+2].ival+1].ival,&numarg,P_MIN);
852             for (t = tmp2str->str_ptr, d=tokenbuf; *t; d++,t++) {
853                 if (*t == '&')
854                    *d++ = '$' + (char)128;
855                 else if (*t == '$')
856                    *d++ = '\\' + (char)128;
857                 *d = *t + 128;
858             }
859             *d = '\0';
860             str_set(tmp2str,tokenbuf);
861             s = (char *) (gsub ? "/g" : "/");
862         }
863         else {
864             tmp2str=walk(1,level,ops[node+2].ival,&numarg,P_MIN);
865             str_set(tmp3str,"($s_ = '\"'.(");
866             str_scat(tmp3str,tmp2str);
867             str_cat(tmp3str,").'\"') =~ s/&/\\$&/g, ");
868             str_set(tmp2str,"eval $s_");
869             s = (char *) (gsub ? "/ge" : "/e");
870             i++;
871         }
872         str_cat(tmp2str,s);
873         type = ops[ops[node+1].ival].ival;
874         len = type >> 8;
875         type &= 255;
876         fstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN);
877         if (type == OREGEX) {
878             if (useval && i)
879                 str_cat(str,"(");
880             str_scat(str,tmp3str);
881             str_scat(str,tmpstr);
882             str_scat(str,fstr);
883             str_scat(str,tmp2str);
884         }
885         else if ((type == OFLD && !split_to_array) || (type == OVAR && len == 1)) {
886             if (useval && i)
887                 str_cat(str,"(");
888             str_scat(str,tmp3str);
889             str_scat(str,tmpstr);
890             str_cat(str,"/");
891             str_scat(str,fstr);
892             str_cat(str,"/");
893             str_scat(str,tmp2str);
894         }
895         else {
896             i++;
897             if (useval)
898                 str_cat(str,"(");
899             str_cat(str,"$s = ");
900             str_scat(str,fstr);
901             str_cat(str,", ");
902             str_scat(str,tmp3str);
903             str_scat(str,tmpstr);
904             str_cat(str,"/$s/");
905             str_scat(str,tmp2str);
906         }
907         if (useval && i)
908             str_cat(str,")");
909         str_free(fstr);
910         str_free(tmpstr);
911         str_free(tmp2str);
912         str_free(tmp3str);
913         numeric = 1;
914         break; }
915     case ONUM:
916         str = walk(1,level,ops[node+1].ival,&numarg,P_MIN);
917         numeric = 1;
918         break;
919     case OSTR:
920         tmpstr = walk(1,level,ops[node+1].ival,&numarg,P_MIN);
921         s = "'";
922         for (t = tmpstr->str_ptr, d=tokenbuf; *t; d++,t++) {
923             if (*t == '\'')
924                 s = "\"";
925             else if (*t == '\\') {
926                 s = "\"";
927                 *d++ = *t++ + 128;
928                 switch (*t) {
929                 case '\\': case '"': case 'n': case 't': case '$':
930                     break;
931                 default:        /* hide this from perl */
932                    *d++ = '\\' + (char)128;
933                 }
934             }
935             *d = *t + 128;
936         }
937         *d = '\0';
938         str = str_new(0);
939         str_set(str,s);
940         str_cat(str,tokenbuf);
941         str_free(tmpstr);
942         str_cat(str,s);
943         break;
944     case ODEFINED:
945         prec = P_UNI;
946         str = str_new(0);
947         str_set(str,"defined $");
948         goto addvar;
949     case ODELETE:
950         str = str_new(0);
951         str_set(str,"delete $");
952         goto addvar;
953     case OSTAR:
954         str = str_new(0);
955         str_set(str,"*");
956         goto addvar;
957     case OVAR:
958         str = str_new(0);
959         str_set(str,"$");
960       addvar:
961         str_scat(str,tmpstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN));
962         if (len == 1) {
963             tmp2str = hfetch(symtab,tmpstr->str_ptr);
964             if (tmp2str && atoi(tmp2str->str_ptr))
965                 numeric = 2;
966             if (strEQ(str->str_ptr,"$FNR")) {
967                 numeric = 1;
968                 saw_FNR++;
969                 str_set(str,"($.-$FNRbase)");
970             }
971             else if (strEQ(str->str_ptr,"$NR")) {
972                 numeric = 1;
973                 str_set(str,"$.");
974             }
975             else if (strEQ(str->str_ptr,"$NF")) {
976                 numeric = 1;
977                 str_set(str,"$#Fld");
978             }
979             else if (strEQ(str->str_ptr,"$0"))
980                 str_set(str,"$_");
981             else if (strEQ(str->str_ptr,"$ARGC"))
982                 str_set(str,"($#ARGV+1)");
983         }
984         else {
985 #ifdef NOTDEF
986             if (curargs) {
987                 sprintf(tokenbuf,"$%s,",tmpstr->str_ptr);
988         ???     if (instr(curargs->str_ptr,tokenbuf))
989                     str_cat(str,"\377");        /* can't translate yet */
990             }
991 #endif
992             str_cat(tmpstr,"[]");
993             tmp2str = hfetch(symtab,tmpstr->str_ptr);
994             if (tmp2str && atoi(tmp2str->str_ptr))
995                 str_cat(str,"[");
996             else
997                 str_cat(str,"{");
998             str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,P_MIN));
999             str_free(fstr);
1000             if (strEQ(str->str_ptr,"$ARGV[0")) {
1001                 str_set(str,"$ARGV0");
1002                 saw_argv0++;
1003             }
1004             else {
1005                 if (tmp2str && atoi(tmp2str->str_ptr))
1006                     strcpy(tokenbuf,"]");
1007                 else
1008                     strcpy(tokenbuf,"}");
1009                *tokenbuf += (char)128;
1010                 str_cat(str,tokenbuf);
1011             }
1012         }
1013         str_free(tmpstr);
1014         break;
1015     case OFLD:
1016         str = str_new(0);
1017         if (split_to_array) {
1018             str_set(str,"$Fld");
1019             str_cat(str,"[");
1020             str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN));
1021             str_free(fstr);
1022             str_cat(str,"]");
1023         }
1024         else {
1025             i = atoi(walk(1,level,ops[node+1].ival,&numarg,P_MIN)->str_ptr);
1026             if (i <= arymax)
1027                 sprintf(tokenbuf,"$%s",nameary[i]);
1028             else
1029                 sprintf(tokenbuf,"$Fld%d",i);
1030             str_set(str,tokenbuf);
1031         }
1032         break;
1033     case OVFLD:
1034         str = str_new(0);
1035         str_set(str,"$Fld[");
1036         i = ops[node+1].ival;
1037         if ((ops[i].ival & 255) == OPAREN)
1038             i = ops[i+1].ival;
1039         tmpstr=walk(1,level,i,&numarg,P_MIN);
1040         str_scat(str,tmpstr);
1041         str_free(tmpstr);
1042         str_cat(str,"]");
1043         break;
1044     case OJUNK:
1045         goto def;
1046     case OSNEWLINE:
1047         str = str_new(2);
1048         str_set(str,";\n");
1049         tab(str,level);
1050         break;
1051     case ONEWLINE:
1052         str = str_new(1);
1053         str_set(str,"\n");
1054         tab(str,level);
1055         break;
1056     case OSCOMMENT:
1057         str = str_new(0);
1058         str_set(str,";");
1059         tmpstr = walk(0,level,ops[node+1].ival,&numarg,P_MIN);
1060         for (s = tmpstr->str_ptr; *s && *s != '\n'; s++)
1061            *s += (char)128;
1062         str_scat(str,tmpstr);
1063         str_free(tmpstr);
1064         tab(str,level);
1065         break;
1066     case OCOMMENT:
1067         str = str_new(0);
1068         tmpstr = walk(0,level,ops[node+1].ival,&numarg,P_MIN);
1069         for (s = tmpstr->str_ptr; *s && *s != '\n'; s++)
1070            *s += (char)128;
1071         str_scat(str,tmpstr);
1072         str_free(tmpstr);
1073         tab(str,level);
1074         break;
1075     case OCOMMA:
1076         prec = P_COMMA;
1077         str = walk(1,level,ops[node+1].ival,&numarg,prec);
1078         str_cat(str,", ");
1079         str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg,P_MIN));
1080         str_free(fstr);
1081         str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,prec+1));
1082         str_free(fstr);
1083         break;
1084     case OSEMICOLON:
1085         str = str_new(1);
1086         str_set(str,";\n");
1087         tab(str,level);
1088         break;
1089     case OSTATES:
1090         str = walk(0,level,ops[node+1].ival,&numarg,P_MIN);
1091         str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg,P_MIN));
1092         str_free(fstr);
1093         break;
1094     case OSTATE:
1095         str = str_new(0);
1096         if (len >= 1) {
1097             str_scat(str,fstr=walk(0,level,ops[node+1].ival,&numarg,P_MIN));
1098             str_free(fstr);
1099             if (len >= 2) {
1100                 tmpstr = walk(0,level,ops[node+2].ival,&numarg,P_MIN);
1101                 if (*tmpstr->str_ptr == ';') {
1102                     addsemi(str);
1103                     str_cat(str,tmpstr->str_ptr+1);
1104                 }
1105                 str_free(tmpstr);
1106             }
1107         }
1108         break;
1109     case OCLOSE:
1110         str = str_make("close(");
1111         tmpstr = walk(1,level,ops[node+1].ival,&numarg,P_MIN);
1112         if (!do_fancy_opens) {
1113             t = tmpstr->str_ptr;
1114             if (*t == '"' || *t == '\'')
1115                 t = cpytill(tokenbuf,t+1,*t);
1116             else
1117                 fatal("Internal error: OCLOSE %s",t);
1118             s = savestr(tokenbuf);
1119             for (t = tokenbuf; *t; t++) {
1120                 *t &= 127;
1121                 if (isLOWER(*t))
1122                     *t = toUPPER(*t);
1123                 if (!isALPHA(*t) && !isDIGIT(*t))
1124                     *t = '_';
1125             }
1126             if (!strchr(tokenbuf,'_'))
1127                 strcpy(t,"_FH");
1128             str_free(tmpstr);
1129             safefree(s);
1130             str_set(str,"close ");
1131             str_cat(str,tokenbuf);
1132         }
1133         else {
1134             sprintf(tokenbuf,"delete $opened{%s} && close(%s)",
1135                tmpstr->str_ptr, tmpstr->str_ptr);
1136             str_free(tmpstr);
1137             str_set(str,tokenbuf);
1138         }
1139         break;
1140     case OPRINTF:
1141     case OPRINT:
1142         lparen = "";    /* set to parens if necessary */
1143         rparen = "";
1144         str = str_new(0);
1145         if (len == 3) {         /* output redirection */
1146             tmpstr = walk(1,level,ops[node+3].ival,&numarg,P_MIN);
1147             tmp2str = walk(1,level,ops[node+2].ival,&numarg,P_MIN);
1148             if (!do_fancy_opens) {
1149                 t = tmpstr->str_ptr;
1150                 if (*t == '"' || *t == '\'')
1151                     t = cpytill(tokenbuf,t+1,*t);
1152                 else
1153                     fatal("Internal error: OPRINT");
1154                 d = savestr(t);
1155                 s = savestr(tokenbuf);
1156                 for (t = tokenbuf; *t; t++) {
1157                     *t &= 127;
1158                     if (isLOWER(*t))
1159                         *t = toUPPER(*t);
1160                     if (!isALPHA(*t) && !isDIGIT(*t))
1161                         *t = '_';
1162                 }
1163                 if (!strchr(tokenbuf,'_'))
1164                     strcpy(t,"_FH");
1165                 tmp3str = hfetch(symtab,tokenbuf);
1166                 if (!tmp3str) {
1167                     str_cat(opens,"open(");
1168                     str_cat(opens,tokenbuf);
1169                     str_cat(opens,", ");
1170                     d[1] = '\0';
1171                     str_cat(opens,d);
1172                     str_scat(opens,tmp2str);
1173                     str_cat(opens,tmpstr->str_ptr+1);
1174                     if (*tmp2str->str_ptr == '|')
1175                         str_cat(opens,") || die 'Cannot pipe to \"");
1176                     else
1177                         str_cat(opens,") || die 'Cannot create file \"");
1178                     if (*d == '"')
1179                         str_cat(opens,"'.\"");
1180                     str_cat(opens,s);
1181                     if (*d == '"')
1182                         str_cat(opens,"\".'");
1183                     str_cat(opens,"\".';\n");
1184                     hstore(symtab,tokenbuf,str_make("x"));
1185                 }
1186                 str_free(tmpstr);
1187                 str_free(tmp2str);
1188                 safefree(s);
1189                 safefree(d);
1190             }
1191             else {
1192                 sprintf(tokenbuf,"&Pick('%s', %s) &&\n",
1193                    tmp2str->str_ptr, tmpstr->str_ptr);
1194                 str_cat(str,tokenbuf);
1195                 tab(str,level+1);
1196                 strcpy(tokenbuf,"$fh");
1197                 str_free(tmpstr);
1198                 str_free(tmp2str);
1199                 lparen = "(";
1200                 rparen = ")";
1201             }
1202         }
1203         else
1204             strcpy(tokenbuf,"");
1205         str_cat(str,lparen);    /* may be null */
1206         if (type == OPRINTF)
1207             str_cat(str,"printf");
1208         else
1209             str_cat(str,"print");
1210         saw_fh = 0;
1211         if (len == 3 || do_fancy_opens) {
1212             if (*tokenbuf) {
1213                 str_cat(str," ");
1214                 saw_fh = 1;
1215             }
1216             str_cat(str,tokenbuf);
1217         }
1218         tmpstr = walk(1+(type==OPRINT),level,ops[node+1].ival,&numarg,P_MIN);
1219         if (!*tmpstr->str_ptr && lval_field) {
1220             t = (char*)(saw_OFS ? "$," : "' '");
1221             if (split_to_array) {
1222                 sprintf(tokenbuf,"join(%s,@Fld)",t);
1223                 str_cat(tmpstr,tokenbuf);
1224             }
1225             else {
1226                 for (i = 1; i < maxfld; i++) {
1227                     if (i <= arymax)
1228                         sprintf(tokenbuf,"$%s, ",nameary[i]);
1229                     else
1230                         sprintf(tokenbuf,"$Fld%d, ",i);
1231                     str_cat(tmpstr,tokenbuf);
1232                 }
1233                 if (maxfld <= arymax)
1234                     sprintf(tokenbuf,"$%s",nameary[maxfld]);
1235                 else
1236                     sprintf(tokenbuf,"$Fld%d",maxfld);
1237                 str_cat(tmpstr,tokenbuf);
1238             }
1239         }
1240         if (*tmpstr->str_ptr) {
1241             str_cat(str," ");
1242             if (!saw_fh && *tmpstr->str_ptr == '(') {
1243                 str_cat(str,"(");
1244                 str_scat(str,tmpstr);
1245                 str_cat(str,")");
1246             }
1247             else
1248                 str_scat(str,tmpstr);
1249         }
1250         else {
1251             str_cat(str," $_");
1252         }
1253         str_cat(str,rparen);    /* may be null */
1254         str_free(tmpstr);
1255         break;
1256     case ORAND:
1257         str = str_make("rand(1)");
1258         break;
1259     case OSRAND:
1260         str = str_make("srand(");
1261         goto maybe0;
1262     case OATAN2:
1263         str = str_make("atan2(");
1264         goto maybe0;
1265     case OSIN:
1266         str = str_make("sin(");
1267         goto maybe0;
1268     case OCOS:
1269         str = str_make("cos(");
1270         goto maybe0;
1271     case OSYSTEM:
1272         str = str_make("system(");
1273         goto maybe0;
1274     case OLENGTH:
1275         str = str_make("length(");
1276         goto maybe0;
1277     case OLOG:
1278         str = str_make("log(");
1279         goto maybe0;
1280     case OEXP:
1281         str = str_make("exp(");
1282         goto maybe0;
1283     case OSQRT:
1284         str = str_make("sqrt(");
1285         goto maybe0;
1286     case OINT:
1287         str = str_make("int(");
1288       maybe0:
1289         numeric = 1;
1290         if (len > 0)
1291             tmpstr = walk(1,level,ops[node+1].ival,&numarg,P_MIN);
1292         else
1293             tmpstr = str_new(0);
1294         if (!tmpstr->str_ptr || !*tmpstr->str_ptr) {
1295             if (lval_field) {
1296                 t = (char*)(saw_OFS ? "$," : "' '");
1297                 if (split_to_array) {
1298                     sprintf(tokenbuf,"join(%s,@Fld)",t);
1299                     str_cat(tmpstr,tokenbuf);
1300                 }
1301                 else {
1302                     sprintf(tokenbuf,"join(%s, ",t);
1303                     str_cat(tmpstr,tokenbuf);
1304                     for (i = 1; i < maxfld; i++) {
1305                         if (i <= arymax)
1306                             sprintf(tokenbuf,"$%s,",nameary[i]);
1307                         else
1308                             sprintf(tokenbuf,"$Fld%d,",i);
1309                         str_cat(tmpstr,tokenbuf);
1310                     }
1311                     if (maxfld <= arymax)
1312                         sprintf(tokenbuf,"$%s)",nameary[maxfld]);
1313                     else
1314                         sprintf(tokenbuf,"$Fld%d)",maxfld);
1315                     str_cat(tmpstr,tokenbuf);
1316                 }
1317             }
1318             else
1319                 str_cat(tmpstr,"$_");
1320         }
1321         if (strEQ(tmpstr->str_ptr,"$_")) {
1322             if (type == OLENGTH && !do_chop) {
1323                 str = str_make("(length(");
1324                 str_cat(tmpstr,") - 1");
1325             }
1326         }
1327         str_scat(str,tmpstr);
1328         str_free(tmpstr);
1329         str_cat(str,")");
1330         break;
1331     case OBREAK:
1332         str = str_new(0);
1333         str_set(str,"last");
1334         break;
1335     case ONEXT:
1336         str = str_new(0);
1337         str_set(str,"next line");
1338         break;
1339     case OEXIT:
1340         str = str_new(0);
1341         if (realexit) {
1342             prec = P_UNI;
1343             str_set(str,"exit");
1344             if (len == 1) {
1345                 str_cat(str," ");
1346                 exitval = TRUE;
1347                 str_scat(str,
1348                   fstr=walk(1,level,ops[node+1].ival,&numarg,prec+1));
1349                 str_free(fstr);
1350             }
1351         }
1352         else {
1353             if (len == 1) {
1354                 str_set(str,"$ExitValue = ");
1355                 exitval = TRUE;
1356                 str_scat(str,
1357                   fstr=walk(1,level,ops[node+1].ival,&numarg,P_ASSIGN));
1358                 str_free(fstr);
1359                 str_cat(str,"; ");
1360             }
1361             str_cat(str,"last line");
1362         }
1363         break;
1364     case OCONTINUE:
1365         str = str_new(0);
1366         str_set(str,"next");
1367         break;
1368     case OREDIR:
1369         goto def;
1370     case OIF:
1371         str = str_new(0);
1372         str_set(str,"if (");
1373         str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN));
1374         str_free(fstr);
1375         str_cat(str,") ");
1376         str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg,P_MIN));
1377         str_free(fstr);
1378         if (len == 3) {
1379             i = ops[node+3].ival;
1380             if (i) {
1381                 if ((ops[i].ival & 255) == OBLOCK) {
1382                     i = ops[i+1].ival;
1383                     if (i) {
1384                         if ((ops[i].ival & 255) != OIF)
1385                             i = 0;
1386                     }
1387                 }
1388                 else
1389                     i = 0;
1390             }
1391             if (i) {
1392                 str_cat(str,"els");
1393                 str_scat(str,fstr=walk(0,level,i,&numarg,P_MIN));
1394                 str_free(fstr);
1395             }
1396             else {
1397                 str_cat(str,"else ");
1398                 str_scat(str,fstr=walk(0,level,ops[node+3].ival,&numarg,P_MIN));
1399                 str_free(fstr);
1400             }
1401         }
1402         break;
1403     case OWHILE:
1404         str = str_new(0);
1405         str_set(str,"while (");
1406         str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN));
1407         str_free(fstr);
1408         str_cat(str,") ");
1409         str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg,P_MIN));
1410         str_free(fstr);
1411         break;
1412     case ODO:
1413         str = str_new(0);
1414         str_set(str,"do ");
1415         str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN));
1416         str_free(fstr);
1417         if (str->str_ptr[str->str_cur - 1] == '\n')
1418             --str->str_cur;
1419         str_cat(str," while (");
1420         str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg,P_MIN));
1421         str_free(fstr);
1422         str_cat(str,");");
1423         break;
1424     case OFOR:
1425         str = str_new(0);
1426         str_set(str,"for (");
1427         str_scat(str,tmpstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN));
1428         i = numarg;
1429         if (i) {
1430             t = s = tmpstr->str_ptr;
1431             while (isALPHA(*t) || isDIGIT(*t) || *t == '$' || *t == '_')
1432                 t++;
1433             i = t - s;
1434             if (i < 2)
1435                 i = 0;
1436         }
1437         str_cat(str,"; ");
1438         fstr=walk(1,level,ops[node+2].ival,&numarg,P_MIN);
1439         if (i && (t = strchr(fstr->str_ptr,0377))) {
1440             if (strnEQ(fstr->str_ptr,s,i))
1441                 *t = ' ';
1442         }
1443         str_scat(str,fstr);
1444         str_free(fstr);
1445         str_free(tmpstr);
1446         str_cat(str,"; ");
1447         str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg,P_MIN));
1448         str_free(fstr);
1449         str_cat(str,") ");
1450         str_scat(str,fstr=walk(0,level,ops[node+4].ival,&numarg,P_MIN));
1451         str_free(fstr);
1452         break;
1453     case OFORIN:
1454         tmpstr = walk(0,level,ops[node+1].ival,&numarg,P_MIN);
1455         d = strchr(tmpstr->str_ptr,'$');
1456         if (!d)
1457             fatal("Illegal for loop: %s",tmpstr->str_ptr);
1458         s = strchr(d,'{');
1459         if (!s)
1460             s = strchr(d,'[');
1461         if (!s)
1462             fatal("Illegal for loop: %s",d);
1463         *s++ = '\0';
1464         for (t = s; (i = *t); t++) {
1465             i &= 127;
1466             if (i == '}' || i == ']')
1467                 break;
1468         }
1469         if (*t)
1470             *t = '\0';
1471         str = str_new(0);
1472         str_set(str,d+1);
1473         str_cat(str,"[]");
1474         tmp2str = hfetch(symtab,str->str_ptr);
1475         if (tmp2str && atoi(tmp2str->str_ptr)) {
1476             sprintf(tokenbuf,
1477               "foreach %s ($[ .. $#%s) ",
1478               s,
1479               d+1);
1480         }
1481         else {
1482             sprintf(tokenbuf,
1483               "foreach %s (keys %%%s) ",
1484               s,
1485               d+1);
1486         }
1487         str_set(str,tokenbuf);
1488         str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg,P_MIN));
1489         str_free(fstr);
1490         str_free(tmpstr);
1491         break;
1492     case OBLOCK:
1493         str = str_new(0);
1494         str_set(str,"{");
1495         if (len >= 2 && ops[node+2].ival) {
1496             str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg,P_MIN));
1497             str_free(fstr);
1498         }
1499         fixtab(str,++level);
1500         str_scat(str,fstr=walk(0,level,ops[node+1].ival,&numarg,P_MIN));
1501         str_free(fstr);
1502         addsemi(str);
1503         fixtab(str,--level);
1504         str_cat(str,"}\n");
1505         tab(str,level);
1506         if (len >= 3) {
1507             str_scat(str,fstr=walk(0,level,ops[node+3].ival,&numarg,P_MIN));
1508             str_free(fstr);
1509         }
1510         break;
1511     default:
1512       def:
1513         if (len) {
1514             if (len > 5)
1515                 fatal("Garbage length in walk");
1516             str = walk(0,level,ops[node+1].ival,&numarg,P_MIN);
1517             for (i = 2; i<= len; i++) {
1518                 str_scat(str,fstr=walk(0,level,ops[node+i].ival,&numarg,P_MIN));
1519                 str_free(fstr);
1520             }
1521         }
1522         else {
1523             str = Nullstr;
1524         }
1525         break;
1526     }
1527     if (!str)
1528         str = str_new(0);
1529
1530     if (useval && prec < minprec) {             /* need parens? */
1531         fstr = str_new(str->str_cur+2);
1532         str_nset(fstr,"(",1);
1533         str_scat(fstr,str);
1534         str_ncat(fstr,")",1);
1535         str_free(str);
1536         str = fstr;
1537     }
1538
1539     *numericptr = numeric;
1540 #ifdef DEBUGGING
1541     if (debug & 4) {
1542         printf("%3d %5d %15s %d %4d ",level,node,opname[type],len,str->str_cur);
1543         for (t = str->str_ptr; *t && t - str->str_ptr < 40; t++)
1544             if (*t == '\n')
1545                 printf("\\n");
1546             else if (*t == '\t')
1547                 printf("\\t");
1548             else
1549                 putchar(*t);
1550         putchar('\n');
1551     }
1552 #endif
1553     return str;
1554 }
1555
1556 static void
1557 tab(register STR *str, register int lvl)
1558 {
1559     while (lvl > 1) {
1560         str_cat(str,"\t");
1561         lvl -= 2;
1562     }
1563     if (lvl)
1564         str_cat(str,"    ");
1565 }
1566
1567 static void
1568 fixtab(register STR *str, register int lvl)
1569 {
1570     register char *s;
1571
1572     /* strip trailing white space */
1573
1574     s = str->str_ptr+str->str_cur - 1;
1575     while (s >= str->str_ptr && (*s == ' ' || *s == '\t' || *s == '\n'))
1576         s--;
1577     s[1] = '\0';
1578     str->str_cur = s + 1 - str->str_ptr;
1579     if (s >= str->str_ptr && *s != '\n')
1580         str_cat(str,"\n");
1581
1582     tab(str,lvl);
1583 }
1584
1585 static void
1586 addsemi(register STR *str)
1587 {
1588     register char *s;
1589
1590     s = str->str_ptr+str->str_cur - 1;
1591     while (s >= str->str_ptr && (*s == ' ' || *s == '\t' || *s == '\n'))
1592         s--;
1593     if (s >= str->str_ptr && *s != ';' && *s != '}')
1594         str_cat(str,";");
1595 }
1596
1597 static void
1598 emit_split(register STR *str, int level)
1599 {
1600     register int i;
1601
1602     if (split_to_array)
1603         str_cat(str,"@Fld");
1604     else {
1605         str_cat(str,"(");
1606         for (i = 1; i < maxfld; i++) {
1607             if (i <= arymax)
1608                 sprintf(tokenbuf,"$%s,",nameary[i]);
1609             else
1610                 sprintf(tokenbuf,"$Fld%d,",i);
1611             str_cat(str,tokenbuf);
1612         }
1613         if (maxfld <= arymax)
1614             sprintf(tokenbuf,"$%s)",nameary[maxfld]);
1615         else
1616             sprintf(tokenbuf,"$Fld%d)",maxfld);
1617         str_cat(str,tokenbuf);
1618     }
1619     if (const_FS) {
1620         sprintf(tokenbuf," = split(/[%c\\n]/, $_, 9999);\n",const_FS);
1621         str_cat(str,tokenbuf);
1622     }
1623     else if (saw_FS)
1624         str_cat(str," = split($FS, $_, 9999);\n");
1625     else
1626         str_cat(str," = split(' ', $_, 9999);\n");
1627     tab(str,level);
1628 }
1629
1630 int
1631 prewalk(int numit, int level, register int node, int *numericptr)
1632 {
1633     register int len;
1634     register int type;
1635     register int i;
1636     int numarg;
1637     int numeric = FALSE;
1638     STR *tmpstr;
1639     STR *tmp2str;
1640
1641     if (!node) {
1642         *numericptr = 0;
1643         return 0;
1644     }
1645     type = ops[node].ival;
1646     len = type >> 8;
1647     type &= 255;
1648     switch (type) {
1649     case OPROG:
1650         prewalk(0,level,ops[node+1].ival,&numarg);
1651         if (ops[node+2].ival) {
1652             prewalk(0,level,ops[node+2].ival,&numarg);
1653         }
1654         ++level;
1655         prewalk(0,level,ops[node+3].ival,&numarg);
1656         --level;
1657         if (ops[node+3].ival) {
1658             prewalk(0,level,ops[node+4].ival,&numarg);
1659         }
1660         break;
1661     case OHUNKS:
1662         prewalk(0,level,ops[node+1].ival,&numarg);
1663         prewalk(0,level,ops[node+2].ival,&numarg);
1664         if (len == 3) {
1665             prewalk(0,level,ops[node+3].ival,&numarg);
1666         }
1667         break;
1668     case ORANGE:
1669         prewalk(1,level,ops[node+1].ival,&numarg);
1670         prewalk(1,level,ops[node+2].ival,&numarg);
1671         break;
1672     case OPAT:
1673         goto def;
1674     case OREGEX:
1675         prewalk(0,level,ops[node+1].ival,&numarg);
1676         break;
1677     case OHUNK:
1678         if (len == 1) {
1679             prewalk(0,level,ops[node+1].ival,&numarg);
1680         }
1681         else {
1682             i = prewalk(0,level,ops[node+1].ival,&numarg);
1683             if (i) {
1684                 ++level;
1685                 prewalk(0,level,ops[node+2].ival,&numarg);
1686                 --level;
1687             }
1688             else {
1689                 prewalk(0,level,ops[node+2].ival,&numarg);
1690             }
1691         }
1692         break;
1693     case OPPAREN:
1694         prewalk(0,level,ops[node+1].ival,&numarg);
1695         break;
1696     case OPANDAND:
1697         prewalk(0,level,ops[node+1].ival,&numarg);
1698         prewalk(0,level,ops[node+2].ival,&numarg);
1699         break;
1700     case OPOROR:
1701         prewalk(0,level,ops[node+1].ival,&numarg);
1702         prewalk(0,level,ops[node+2].ival,&numarg);
1703         break;
1704     case OPNOT:
1705         prewalk(0,level,ops[node+1].ival,&numarg);
1706         break;
1707     case OCPAREN:
1708         prewalk(0,level,ops[node+1].ival,&numarg);
1709         numeric |= numarg;
1710         break;
1711     case OCANDAND:
1712         prewalk(0,level,ops[node+1].ival,&numarg);
1713         numeric = 1;
1714         prewalk(0,level,ops[node+2].ival,&numarg);
1715         break;
1716     case OCOROR:
1717         prewalk(0,level,ops[node+1].ival,&numarg);
1718         numeric = 1;
1719         prewalk(0,level,ops[node+2].ival,&numarg);
1720         break;
1721     case OCNOT:
1722         prewalk(0,level,ops[node+1].ival,&numarg);
1723         numeric = 1;
1724         break;
1725     case ORELOP:
1726         prewalk(0,level,ops[node+2].ival,&numarg);
1727         numeric |= numarg;
1728         prewalk(0,level,ops[node+1].ival,&numarg);
1729         prewalk(0,level,ops[node+3].ival,&numarg);
1730         numeric |= numarg;
1731         numeric = 1;
1732         break;
1733     case ORPAREN:
1734         prewalk(0,level,ops[node+1].ival,&numarg);
1735         numeric |= numarg;
1736         break;
1737     case OMATCHOP:
1738         prewalk(0,level,ops[node+2].ival,&numarg);
1739         prewalk(0,level,ops[node+1].ival,&numarg);
1740         prewalk(0,level,ops[node+3].ival,&numarg);
1741         numeric = 1;
1742         break;
1743     case OMPAREN:
1744         prewalk(0,level,ops[node+1].ival,&numarg);
1745         numeric |= numarg;
1746         break;
1747     case OCONCAT:
1748         prewalk(0,level,ops[node+1].ival,&numarg);
1749         prewalk(0,level,ops[node+2].ival,&numarg);
1750         break;
1751     case OASSIGN:
1752         prewalk(0,level,ops[node+2].ival,&numarg);
1753         prewalk(0,level,ops[node+1].ival,&numarg);
1754         prewalk(0,level,ops[node+3].ival,&numarg);
1755         if (numarg || strlen(ops[ops[node+1].ival+1].cval) > (Size_t)1) {
1756             numericize(ops[node+2].ival);
1757             if (!numarg)
1758                 numericize(ops[node+3].ival);
1759         }
1760         numeric |= numarg;
1761         break;
1762     case OADD:
1763         prewalk(1,level,ops[node+1].ival,&numarg);
1764         prewalk(1,level,ops[node+2].ival,&numarg);
1765         numeric = 1;
1766         break;
1767     case OSUBTRACT:
1768         prewalk(1,level,ops[node+1].ival,&numarg);
1769         prewalk(1,level,ops[node+2].ival,&numarg);
1770         numeric = 1;
1771         break;
1772     case OMULT:
1773         prewalk(1,level,ops[node+1].ival,&numarg);
1774         prewalk(1,level,ops[node+2].ival,&numarg);
1775         numeric = 1;
1776         break;
1777     case ODIV:
1778         prewalk(1,level,ops[node+1].ival,&numarg);
1779         prewalk(1,level,ops[node+2].ival,&numarg);
1780         numeric = 1;
1781         break;
1782     case OPOW:
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 OMOD:
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 OPOSTINCR:
1793         prewalk(1,level,ops[node+1].ival,&numarg);
1794         numeric = 1;
1795         break;
1796     case OPOSTDECR:
1797         prewalk(1,level,ops[node+1].ival,&numarg);
1798         numeric = 1;
1799         break;
1800     case OPREINCR:
1801         prewalk(1,level,ops[node+1].ival,&numarg);
1802         numeric = 1;
1803         break;
1804     case OPREDECR:
1805         prewalk(1,level,ops[node+1].ival,&numarg);
1806         numeric = 1;
1807         break;
1808     case OUMINUS:
1809         prewalk(1,level,ops[node+1].ival,&numarg);
1810         numeric = 1;
1811         break;
1812     case OUPLUS:
1813         prewalk(1,level,ops[node+1].ival,&numarg);
1814         numeric = 1;
1815         break;
1816     case OPAREN:
1817         prewalk(0,level,ops[node+1].ival,&numarg);
1818         numeric |= numarg;
1819         break;
1820     case OGETLINE:
1821         break;
1822     case OSPRINTF:
1823         prewalk(0,level,ops[node+1].ival,&numarg);
1824         break;
1825     case OSUBSTR:
1826         prewalk(0,level,ops[node+1].ival,&numarg);
1827         prewalk(1,level,ops[node+2].ival,&numarg);
1828         if (len == 3) {
1829             prewalk(1,level,ops[node+3].ival,&numarg);
1830         }
1831         break;
1832     case OSTRING:
1833         break;
1834     case OSPLIT:
1835         numeric = 1;
1836         prewalk(0,level,ops[node+2].ival,&numarg);
1837         if (len == 3)
1838             prewalk(0,level,ops[node+3].ival,&numarg);
1839         prewalk(0,level,ops[node+1].ival,&numarg);
1840         break;
1841     case OINDEX:
1842         prewalk(0,level,ops[node+1].ival,&numarg);
1843         prewalk(0,level,ops[node+2].ival,&numarg);
1844         numeric = 1;
1845         break;
1846     case OMATCH:
1847         prewalk(0,level,ops[node+1].ival,&numarg);
1848         prewalk(0,level,ops[node+2].ival,&numarg);
1849         numeric = 1;
1850         break;
1851     case OUSERDEF:
1852         subretnum = FALSE;
1853         --level;
1854         tmpstr = walk(0,level,ops[node+1].ival,&numarg,P_MIN);
1855         ++level;
1856         prewalk(0,level,ops[node+2].ival,&numarg);
1857         prewalk(0,level,ops[node+4].ival,&numarg);
1858         prewalk(0,level,ops[node+5].ival,&numarg);
1859         --level;
1860         str_cat(tmpstr,"(");
1861         tmp2str = str_new(0);
1862         if (subretnum || numarg)
1863             str_set(tmp2str,"1");
1864         hstore(symtab,tmpstr->str_ptr,tmp2str);
1865         str_free(tmpstr);
1866         level++;
1867         break;
1868     case ORETURN:
1869         if (len > 0) {
1870             prewalk(0,level,ops[node+1].ival,&numarg);
1871             if (numarg)
1872                 subretnum = TRUE;
1873         }
1874         break;
1875     case OUSERFUN:
1876         tmp2str = str_new(0);
1877         str_scat(tmp2str,tmpstr=walk(1,level,ops[node+1].ival,&numarg,P_MIN));
1878         fixrargs(tmpstr->str_ptr,ops[node+2].ival,0);
1879         str_free(tmpstr);
1880         str_cat(tmp2str,"(");
1881         tmpstr = hfetch(symtab,tmp2str->str_ptr);
1882         if (tmpstr && tmpstr->str_ptr)
1883             numeric |= atoi(tmpstr->str_ptr);
1884         prewalk(0,level,ops[node+2].ival,&numarg);
1885         str_free(tmp2str);
1886         break;
1887     case OGSUB:
1888     case OSUB:
1889         if (len >= 3)
1890             prewalk(0,level,ops[node+3].ival,&numarg);
1891         prewalk(0,level,ops[ops[node+2].ival+1].ival,&numarg);
1892         prewalk(0,level,ops[node+1].ival,&numarg);
1893         numeric = 1;
1894         break;
1895     case ONUM:
1896         prewalk(0,level,ops[node+1].ival,&numarg);
1897         numeric = 1;
1898         break;
1899     case OSTR:
1900         prewalk(0,level,ops[node+1].ival,&numarg);
1901         break;
1902     case ODEFINED:
1903     case ODELETE:
1904     case OSTAR:
1905     case OVAR:
1906         prewalk(0,level,ops[node+1].ival,&numarg);
1907         if (len == 1) {
1908             if (numit)
1909                 numericize(node);
1910         }
1911         else {
1912             prewalk(0,level,ops[node+2].ival,&numarg);
1913         }
1914         break;
1915     case OFLD:
1916         prewalk(0,level,ops[node+1].ival,&numarg);
1917         break;
1918     case OVFLD:
1919         i = ops[node+1].ival;
1920         prewalk(0,level,i,&numarg);
1921         break;
1922     case OJUNK:
1923         goto def;
1924     case OSNEWLINE:
1925         break;
1926     case ONEWLINE:
1927         break;
1928     case OSCOMMENT:
1929         break;
1930     case OCOMMENT:
1931         break;
1932     case OCOMMA:
1933         prewalk(0,level,ops[node+1].ival,&numarg);
1934         prewalk(0,level,ops[node+2].ival,&numarg);
1935         prewalk(0,level,ops[node+3].ival,&numarg);
1936         break;
1937     case OSEMICOLON:
1938         break;
1939     case OSTATES:
1940         prewalk(0,level,ops[node+1].ival,&numarg);
1941         prewalk(0,level,ops[node+2].ival,&numarg);
1942         break;
1943     case OSTATE:
1944         if (len >= 1) {
1945             prewalk(0,level,ops[node+1].ival,&numarg);
1946             if (len >= 2) {
1947                 prewalk(0,level,ops[node+2].ival,&numarg);
1948             }
1949         }
1950         break;
1951     case OCLOSE:
1952         prewalk(0,level,ops[node+1].ival,&numarg);
1953         break;
1954     case OPRINTF:
1955     case OPRINT:
1956         if (len == 3) {         /* output redirection */
1957             prewalk(0,level,ops[node+3].ival,&numarg);
1958             prewalk(0,level,ops[node+2].ival,&numarg);
1959         }
1960         prewalk(0+(type==OPRINT),level,ops[node+1].ival,&numarg);
1961         break;
1962     case ORAND:
1963         break;
1964     case OSRAND:
1965         goto maybe0;
1966     case OATAN2:
1967         goto maybe0;
1968     case OSIN:
1969         goto maybe0;
1970     case OCOS:
1971         goto maybe0;
1972     case OSYSTEM:
1973         goto maybe0;
1974     case OLENGTH:
1975         goto maybe0;
1976     case OLOG:
1977         goto maybe0;
1978     case OEXP:
1979         goto maybe0;
1980     case OSQRT:
1981         goto maybe0;
1982     case OINT:
1983       maybe0:
1984         numeric = 1;
1985         if (len > 0)
1986             prewalk(type != OLENGTH && type != OSYSTEM,
1987               level,ops[node+1].ival,&numarg);
1988         break;
1989     case OBREAK:
1990         break;
1991     case ONEXT:
1992         break;
1993     case OEXIT:
1994         if (len == 1) {
1995             prewalk(1,level,ops[node+1].ival,&numarg);
1996         }
1997         break;
1998     case OCONTINUE:
1999         break;
2000     case OREDIR:
2001         goto def;
2002     case OIF:
2003         prewalk(0,level,ops[node+1].ival,&numarg);
2004         prewalk(0,level,ops[node+2].ival,&numarg);
2005         if (len == 3) {
2006             prewalk(0,level,ops[node+3].ival,&numarg);
2007         }
2008         break;
2009     case OWHILE:
2010         prewalk(0,level,ops[node+1].ival,&numarg);
2011         prewalk(0,level,ops[node+2].ival,&numarg);
2012         break;
2013     case OFOR:
2014         prewalk(0,level,ops[node+1].ival,&numarg);
2015         prewalk(0,level,ops[node+2].ival,&numarg);
2016         prewalk(0,level,ops[node+3].ival,&numarg);
2017         prewalk(0,level,ops[node+4].ival,&numarg);
2018         break;
2019     case OFORIN:
2020         prewalk(0,level,ops[node+2].ival,&numarg);
2021         prewalk(0,level,ops[node+1].ival,&numarg);
2022         break;
2023     case OBLOCK:
2024         if (len == 2) {
2025             prewalk(0,level,ops[node+2].ival,&numarg);
2026         }
2027         ++level;
2028         prewalk(0,level,ops[node+1].ival,&numarg);
2029         --level;
2030         break;
2031     default:
2032       def:
2033         if (len) {
2034             if (len > 5)
2035                 fatal("Garbage length in prewalk");
2036             prewalk(0,level,ops[node+1].ival,&numarg);
2037             for (i = 2; i<= len; i++) {
2038                 prewalk(0,level,ops[node+i].ival,&numarg);
2039             }
2040         }
2041         break;
2042     }
2043     *numericptr = numeric;
2044     return 1;
2045 }
2046
2047 static void
2048 numericize(register int node)
2049 {
2050     register int len;
2051     register int type;
2052     STR *tmpstr;
2053     STR *tmp2str;
2054     int numarg;
2055
2056     type = ops[node].ival;
2057     len = type >> 8;
2058     type &= 255;
2059     if (type == OVAR && len == 1) {
2060         tmpstr=walk(0,0,ops[node+1].ival,&numarg,P_MIN);
2061         tmp2str = str_make("1");
2062         hstore(symtab,tmpstr->str_ptr,tmp2str);
2063     }
2064 }