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