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