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