e745510b1d3df2b55ecc572279a06edcf00e4b27
[p5sagit/p5-mst-13.2.git] / x2p / walk.c
1 /* $Header: walk.c,v 1.0.1.1 88/01/28 11:07:56 root Exp $
2  *
3  * $Log:        walk.c,v $
4  * Revision 1.0.1.1  88/01/28  11:07:56  root
5  * patch8: changed some misleading comments.
6  * 
7  * Revision 1.0  87/12/18  13:07:40  root
8  * Initial revision
9  * 
10  */
11
12 #include "handy.h"
13 #include "EXTERN.h"
14 #include "util.h"
15 #include "a2p.h"
16
17 bool exitval = FALSE;
18 bool realexit = FALSE;
19 int maxtmp = 0;
20
21 STR *
22 walk(useval,level,node,numericptr)
23 int useval;
24 int level;
25 register int node;
26 int *numericptr;
27 {
28     register int len;
29     register STR *str;
30     register int type;
31     register int i;
32     register STR *tmpstr;
33     STR *tmp2str;
34     char *t;
35     char *d, *s;
36     int numarg;
37     int numeric = FALSE;
38     STR *fstr;
39     char *index();
40
41     if (!node) {
42         *numericptr = 0;
43         return str_make("");
44     }
45     type = ops[node].ival;
46     len = type >> 8;
47     type &= 255;
48     switch (type) {
49     case OPROG:
50         str = walk(0,level,ops[node+1].ival,&numarg);
51         opens = str_new(0);
52         if (do_split && need_entire && !absmaxfld)
53             split_to_array = TRUE;
54         if (do_split && split_to_array)
55             set_array_base = TRUE;
56         if (set_array_base) {
57             str_cat(str,"$[ = 1;\t\t\t# set array base to 1\n");
58         }
59         if (fswitch && !const_FS)
60             const_FS = fswitch;
61         if (saw_FS > 1 || saw_RS)
62             const_FS = 0;
63         if (saw_ORS && need_entire)
64             do_chop = TRUE;
65         if (fswitch) {
66             str_cat(str,"$FS = '");
67             if (index("*+?.[]()|^$\\",fswitch))
68                 str_cat(str,"\\");
69             sprintf(tokenbuf,"%c",fswitch);
70             str_cat(str,tokenbuf);
71             str_cat(str,"';\t\t# field separator from -F switch\n");
72         }
73         else if (saw_FS && !const_FS) {
74             str_cat(str,"$FS = '[ \\t\\n]+';\t\t# set field separator\n");
75         }
76         if (saw_OFS) {
77             str_cat(str,"$, = ' ';\t\t# set output field separator\n");
78         }
79         if (saw_ORS) {
80             str_cat(str,"$\\ = \"\\n\";\t\t# set output record separator\n");
81         }
82         if (str->str_cur > 20)
83             str_cat(str,"\n");
84         if (ops[node+2].ival) {
85             str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg));
86             str_free(fstr);
87             str_cat(str,"\n\n");
88         }
89         if (saw_line_op)
90             str_cat(str,"line: ");
91         str_cat(str,"while (<>) {\n");
92         tab(str,++level);
93         if (saw_FS && !const_FS)
94             do_chop = TRUE;
95         if (do_chop) {
96             str_cat(str,"chop;\t# strip record separator\n");
97             tab(str,level);
98         }
99         arymax = 0;
100         if (namelist) {
101             while (isalpha(*namelist)) {
102                 for (d = tokenbuf,s=namelist;
103                   isalpha(*s) || isdigit(*s) || *s == '_';
104                   *d++ = *s++) ;
105                 *d = '\0';
106                 while (*s && !isalpha(*s)) s++;
107                 namelist = s;
108                 nameary[++arymax] = savestr(tokenbuf);
109             }
110         }
111         if (maxfld < arymax)
112             maxfld = arymax;
113         if (do_split)
114             emit_split(str,level);
115         str_scat(str,fstr=walk(0,level,ops[node+3].ival,&numarg));
116         str_free(fstr);
117         fixtab(str,--level);
118         str_cat(str,"}\n");
119         if (ops[node+4].ival) {
120             realexit = TRUE;
121             str_cat(str,"\n");
122             tab(str,level);
123             str_scat(str,fstr=walk(0,level,ops[node+4].ival,&numarg));
124             str_free(fstr);
125             str_cat(str,"\n");
126         }
127         if (exitval)
128             str_cat(str,"exit ExitValue;\n");
129         if (do_fancy_opens) {
130             str_cat(str,"\n\
131 sub Pick {\n\
132     ($name) = @_;\n\
133     $fh = $opened{$name};\n\
134     if (!$fh) {\n\
135         $nextfh == 0 && open(fh_0,$name);\n\
136         $nextfh == 1 && open(fh_1,$name);\n\
137         $nextfh == 2 && open(fh_2,$name);\n\
138         $nextfh == 3 && open(fh_3,$name);\n\
139         $nextfh == 4 && open(fh_4,$name);\n\
140         $nextfh == 5 && open(fh_5,$name);\n\
141         $nextfh == 6 && open(fh_6,$name);\n\
142         $nextfh == 7 && open(fh_7,$name);\n\
143         $nextfh == 8 && open(fh_8,$name);\n\
144         $nextfh == 9 && open(fh_9,$name);\n\
145         $fh = $opened{$name} = 'fh_' . $nextfh++;\n\
146     }\n\
147     select($fh);\n\
148 }\n\
149 ");
150         }
151         break;
152     case OHUNKS:
153         str = walk(0,level,ops[node+1].ival,&numarg);
154         str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg));
155         str_free(fstr);
156         if (len == 3) {
157             str_scat(str,fstr=walk(0,level,ops[node+3].ival,&numarg));
158             str_free(fstr);
159         }
160         else {
161         }
162         break;
163     case ORANGE:
164         str = walk(1,level,ops[node+1].ival,&numarg);
165         str_cat(str," .. ");
166         str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg));
167         str_free(fstr);
168         break;
169     case OPAT:
170         goto def;
171     case OREGEX:
172         str = str_new(0);
173         str_set(str,"/");
174         tmpstr=walk(0,level,ops[node+1].ival,&numarg);
175         /* translate \nnn to [\nnn] */
176         for (s = tmpstr->str_ptr, d = tokenbuf; *s; s++, d++) {
177             if (*s == '\\' && isdigit(s[1]) && isdigit(s[2]) && isdigit(s[3])) {
178                 *d++ = '[';
179                 *d++ = *s++;
180                 *d++ = *s++;
181                 *d++ = *s++;
182                 *d++ = *s;
183                 *d = ']';
184             }
185             else
186                 *d = *s;
187         }
188         *d = '\0';
189         str_cat(str,tokenbuf);
190         str_free(tmpstr);
191         str_cat(str,"/");
192         break;
193     case OHUNK:
194         if (len == 1) {
195             str = str_new(0);
196             str = walk(0,level,oper1(OPRINT,0),&numarg);
197             str_cat(str," if ");
198             str_scat(str,fstr=walk(0,level,ops[node+1].ival,&numarg));
199             str_free(fstr);
200             str_cat(str,";");
201         }
202         else {
203             tmpstr = walk(0,level,ops[node+1].ival,&numarg);
204             if (*tmpstr->str_ptr) {
205                 str = str_new(0);
206                 str_set(str,"if (");
207                 str_scat(str,tmpstr);
208                 str_cat(str,") {\n");
209                 tab(str,++level);
210                 str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg));
211                 str_free(fstr);
212                 fixtab(str,--level);
213                 str_cat(str,"}\n");
214                 tab(str,level);
215             }
216             else {
217                 str = walk(0,level,ops[node+2].ival,&numarg);
218             }
219         }
220         break;
221     case OPPAREN:
222         str = str_new(0);
223         str_set(str,"(");
224         str_scat(str,fstr=walk(useval != 0,level,ops[node+1].ival,&numarg));
225         str_free(fstr);
226         str_cat(str,")");
227         break;
228     case OPANDAND:
229         str = walk(1,level,ops[node+1].ival,&numarg);
230         str_cat(str," && ");
231         str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg));
232         str_free(fstr);
233         break;
234     case OPOROR:
235         str = walk(1,level,ops[node+1].ival,&numarg);
236         str_cat(str," || ");
237         str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg));
238         str_free(fstr);
239         break;
240     case OPNOT:
241         str = str_new(0);
242         str_set(str,"!");
243         str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg));
244         str_free(fstr);
245         break;
246     case OCPAREN:
247         str = str_new(0);
248         str_set(str,"(");
249         str_scat(str,fstr=walk(useval != 0,level,ops[node+1].ival,&numarg));
250         str_free(fstr);
251         numeric |= numarg;
252         str_cat(str,")");
253         break;
254     case OCANDAND:
255         str = walk(1,level,ops[node+1].ival,&numarg);
256         numeric = 1;
257         str_cat(str," && ");
258         str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg));
259         str_free(fstr);
260         break;
261     case OCOROR:
262         str = walk(1,level,ops[node+1].ival,&numarg);
263         numeric = 1;
264         str_cat(str," || ");
265         str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg));
266         str_free(fstr);
267         break;
268     case OCNOT:
269         str = str_new(0);
270         str_set(str,"!");
271         str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg));
272         str_free(fstr);
273         numeric = 1;
274         break;
275     case ORELOP:
276         str = walk(1,level,ops[node+2].ival,&numarg);
277         numeric |= numarg;
278         tmpstr = walk(0,level,ops[node+1].ival,&numarg);
279         tmp2str = walk(1,level,ops[node+3].ival,&numarg);
280         numeric |= numarg;
281         if (!numeric) {
282             t = tmpstr->str_ptr;
283             if (strEQ(t,"=="))
284                 str_set(tmpstr,"eq");
285             else if (strEQ(t,"!="))
286                 str_set(tmpstr,"ne");
287             else if (strEQ(t,"<"))
288                 str_set(tmpstr,"lt");
289             else if (strEQ(t,"<="))
290                 str_set(tmpstr,"le");
291             else if (strEQ(t,">"))
292                 str_set(tmpstr,"gt");
293             else if (strEQ(t,">="))
294                 str_set(tmpstr,"ge");
295             if (!index(tmpstr->str_ptr,'\'') && !index(tmpstr->str_ptr,'"') &&
296               !index(tmp2str->str_ptr,'\'') && !index(tmp2str->str_ptr,'"') )
297                 numeric |= 2;
298         }
299         if (numeric & 2) {
300             if (numeric & 1)            /* numeric is very good guess */
301                 str_cat(str," ");
302             else
303                 str_cat(str,"\377");
304             numeric = 1;
305         }
306         else
307             str_cat(str," ");
308         str_scat(str,tmpstr);
309         str_free(tmpstr);
310         str_cat(str," ");
311         str_scat(str,tmp2str);
312         str_free(tmp2str);
313         numeric = 1;
314         break;
315     case ORPAREN:
316         str = str_new(0);
317         str_set(str,"(");
318         str_scat(str,fstr=walk(useval != 0,level,ops[node+1].ival,&numarg));
319         str_free(fstr);
320         numeric |= numarg;
321         str_cat(str,")");
322         break;
323     case OMATCHOP:
324         str = walk(1,level,ops[node+2].ival,&numarg);
325         str_cat(str," ");
326         tmpstr = walk(0,level,ops[node+1].ival,&numarg);
327         if (strEQ(tmpstr->str_ptr,"~"))
328             str_cat(str,"=~");
329         else {
330             str_scat(str,tmpstr);
331             str_free(tmpstr);
332         }
333         str_cat(str," ");
334         str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg));
335         str_free(fstr);
336         numeric = 1;
337         break;
338     case OMPAREN:
339         str = str_new(0);
340         str_set(str,"(");
341         str_scat(str,fstr=walk(useval != 0,level,ops[node+1].ival,&numarg));
342         str_free(fstr);
343         numeric |= numarg;
344         str_cat(str,")");
345         break;
346     case OCONCAT:
347         str = walk(1,level,ops[node+1].ival,&numarg);
348         str_cat(str," . ");
349         str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg));
350         str_free(fstr);
351         break;
352     case OASSIGN:
353         str = walk(0,level,ops[node+2].ival,&numarg);
354         str_cat(str," ");
355         tmpstr = walk(0,level,ops[node+1].ival,&numarg);
356         str_scat(str,tmpstr);
357         if (str_len(tmpstr) > 1)
358             numeric = 1;
359         str_free(tmpstr);
360         str_cat(str," ");
361         str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg));
362         str_free(fstr);
363         numeric |= numarg;
364         if (strEQ(str->str_ptr,"$FS = '\240'"))
365             str_set(str,"$FS = '[\240\\n\\t]+'");
366         break;
367     case OADD:
368         str = walk(1,level,ops[node+1].ival,&numarg);
369         str_cat(str," + ");
370         str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg));
371         str_free(fstr);
372         numeric = 1;
373         break;
374     case OSUB:
375         str = walk(1,level,ops[node+1].ival,&numarg);
376         str_cat(str," - ");
377         str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg));
378         str_free(fstr);
379         numeric = 1;
380         break;
381     case OMULT:
382         str = walk(1,level,ops[node+1].ival,&numarg);
383         str_cat(str," * ");
384         str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg));
385         str_free(fstr);
386         numeric = 1;
387         break;
388     case ODIV:
389         str = walk(1,level,ops[node+1].ival,&numarg);
390         str_cat(str," / ");
391         str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg));
392         str_free(fstr);
393         numeric = 1;
394         break;
395     case OMOD:
396         str = walk(1,level,ops[node+1].ival,&numarg);
397         str_cat(str," % ");
398         str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg));
399         str_free(fstr);
400         numeric = 1;
401         break;
402     case OPOSTINCR:
403         str = walk(1,level,ops[node+1].ival,&numarg);
404         str_cat(str,"++");
405         numeric = 1;
406         break;
407     case OPOSTDECR:
408         str = walk(1,level,ops[node+1].ival,&numarg);
409         str_cat(str,"--");
410         numeric = 1;
411         break;
412     case OPREINCR:
413         str = str_new(0);
414         str_set(str,"++");
415         str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg));
416         str_free(fstr);
417         numeric = 1;
418         break;
419     case OPREDECR:
420         str = str_new(0);
421         str_set(str,"--");
422         str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg));
423         str_free(fstr);
424         numeric = 1;
425         break;
426     case OUMINUS:
427         str = str_new(0);
428         str_set(str,"-");
429         str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg));
430         str_free(fstr);
431         numeric = 1;
432         break;
433     case OUPLUS:
434         numeric = 1;
435         goto def;
436     case OPAREN:
437         str = str_new(0);
438         str_set(str,"(");
439         str_scat(str,fstr=walk(useval != 0,level,ops[node+1].ival,&numarg));
440         str_free(fstr);
441         str_cat(str,")");
442         numeric |= numarg;
443         break;
444     case OGETLINE:
445         str = str_new(0);
446         str_set(str,"$_ = <>;\n");
447         tab(str,level);
448         if (do_chop) {
449             str_cat(str,"chop;\t# strip record separator\n");
450             tab(str,level);
451         }
452         if (do_split)
453             emit_split(str,level);
454         break;
455     case OSPRINTF:
456         str = str_new(0);
457         str_set(str,"sprintf(");
458         str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg));
459         str_free(fstr);
460         str_cat(str,")");
461         break;
462     case OSUBSTR:
463         str = str_new(0);
464         str_set(str,"substr(");
465         str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg));
466         str_free(fstr);
467         str_cat(str,", ");
468         str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg));
469         str_free(fstr);
470         str_cat(str,", ");
471         if (len == 3) {
472             str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg));
473             str_free(fstr);
474         }
475         else
476             str_cat(str,"999999");
477         str_cat(str,")");
478         break;
479     case OSTRING:
480         str = str_new(0);
481         str_set(str,ops[node+1].cval);
482         break;
483     case OSPLIT:
484         str = str_new(0);
485         numeric = 1;
486         tmpstr = walk(1,level,ops[node+2].ival,&numarg);
487         if (useval)
488             str_set(str,"(@");
489         else
490             str_set(str,"@");
491         str_scat(str,tmpstr);
492         str_cat(str," = split(");
493         if (len == 3) {
494             fstr = walk(1,level,ops[node+3].ival,&numarg);
495             if (str_len(fstr) == 3 && *fstr->str_ptr == '\'') {
496                 i = fstr->str_ptr[1] & 127;
497                 if (index("*+?.[]()|^$\\",i))
498                     sprintf(tokenbuf,"/\\%c/",i);
499                 else
500                     sprintf(tokenbuf,"/%c/",i);
501                 str_cat(str,tokenbuf);
502             }
503             else
504                 str_scat(str,fstr);
505             str_free(fstr);
506         }
507         else if (const_FS) {
508             sprintf(tokenbuf,"/[%c\\n]/",const_FS);
509             str_cat(str,tokenbuf);
510         }
511         else if (saw_FS)
512             str_cat(str,"$FS");
513         else
514             str_cat(str,"/[ \\t\\n]+/");
515         str_cat(str,", ");
516         str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg));
517         str_free(fstr);
518         str_cat(str,")");
519         if (useval) {
520             str_cat(str,")");
521         }
522         str_free(tmpstr);
523         break;
524     case OINDEX:
525         str = str_new(0);
526         str_set(str,"index(");
527         str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg));
528         str_free(fstr);
529         str_cat(str,", ");
530         str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg));
531         str_free(fstr);
532         str_cat(str,")");
533         numeric = 1;
534         break;
535     case ONUM:
536         str = walk(1,level,ops[node+1].ival,&numarg);
537         numeric = 1;
538         break;
539     case OSTR:
540         tmpstr = walk(1,level,ops[node+1].ival,&numarg);
541         s = "'";
542         for (t = tmpstr->str_ptr; *t; t++) {
543             if (*t == '\\' || *t == '\'')
544                 s = "\"";
545             *t += 128;
546         }
547         str = str_new(0);
548         str_set(str,s);
549         str_scat(str,tmpstr);
550         str_free(tmpstr);
551         str_cat(str,s);
552         break;
553     case OVAR:
554         str = str_new(0);
555         str_set(str,"$");
556         str_scat(str,tmpstr=walk(1,level,ops[node+1].ival,&numarg));
557         if (len == 1) {
558             tmp2str = hfetch(symtab,tmpstr->str_ptr);
559             if (tmp2str && atoi(tmp2str->str_ptr))
560                 numeric = 2;
561             if (strEQ(str->str_ptr,"$NR")) {
562                 numeric = 1;
563                 str_set(str,"$.");
564             }
565             else if (strEQ(str->str_ptr,"$NF")) {
566                 numeric = 1;
567                 str_set(str,"$#Fld");
568             }
569             else if (strEQ(str->str_ptr,"$0"))
570                 str_set(str,"$_");
571         }
572         else {
573             str_cat(tmpstr,"[]");
574             tmp2str = hfetch(symtab,tmpstr->str_ptr);
575             if (tmp2str && atoi(tmp2str->str_ptr))
576                 str_cat(str,"[");
577             else
578                 str_cat(str,"{");
579             str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg));
580             str_free(fstr);
581             if (tmp2str && atoi(tmp2str->str_ptr))
582                 strcpy(tokenbuf,"]");
583             else
584                 strcpy(tokenbuf,"}");
585             *tokenbuf += 128;
586             str_cat(str,tokenbuf);
587         }
588         str_free(tmpstr);
589         break;
590     case OFLD:
591         str = str_new(0);
592         if (split_to_array) {
593             str_set(str,"$Fld");
594             str_cat(str,"[");
595             str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg));
596             str_free(fstr);
597             str_cat(str,"]");
598         }
599         else {
600             i = atoi(walk(1,level,ops[node+1].ival,&numarg)->str_ptr);
601             if (i <= arymax)
602                 sprintf(tokenbuf,"$%s",nameary[i]);
603             else
604                 sprintf(tokenbuf,"$Fld%d",i);
605             str_set(str,tokenbuf);
606         }
607         break;
608     case OVFLD:
609         str = str_new(0);
610         str_set(str,"$Fld[");
611         i = ops[node+1].ival;
612         if ((ops[i].ival & 255) == OPAREN)
613             i = ops[i+1].ival;
614         tmpstr=walk(1,level,i,&numarg);
615         str_scat(str,tmpstr);
616         str_free(tmpstr);
617         str_cat(str,"]");
618         break;
619     case OJUNK:
620         goto def;
621     case OSNEWLINE:
622         str = str_new(2);
623         str_set(str,";\n");
624         tab(str,level);
625         break;
626     case ONEWLINE:
627         str = str_new(1);
628         str_set(str,"\n");
629         tab(str,level);
630         break;
631     case OSCOMMENT:
632         str = str_new(0);
633         str_set(str,";");
634         tmpstr = walk(0,level,ops[node+1].ival,&numarg);
635         for (s = tmpstr->str_ptr; *s && *s != '\n'; s++)
636             *s += 128;
637         str_scat(str,tmpstr);
638         str_free(tmpstr);
639         tab(str,level);
640         break;
641     case OCOMMENT:
642         str = str_new(0);
643         tmpstr = walk(0,level,ops[node+1].ival,&numarg);
644         for (s = tmpstr->str_ptr; *s && *s != '\n'; s++)
645             *s += 128;
646         str_scat(str,tmpstr);
647         str_free(tmpstr);
648         tab(str,level);
649         break;
650     case OCOMMA:
651         str = walk(1,level,ops[node+1].ival,&numarg);
652         str_cat(str,", ");
653         str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg));
654         str_free(fstr);
655         break;
656     case OSEMICOLON:
657         str = str_new(1);
658         str_set(str,"; ");
659         break;
660     case OSTATES:
661         str = walk(0,level,ops[node+1].ival,&numarg);
662         str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg));
663         str_free(fstr);
664         break;
665     case OSTATE:
666         str = str_new(0);
667         if (len >= 1) {
668             str_scat(str,fstr=walk(0,level,ops[node+1].ival,&numarg));
669             str_free(fstr);
670             if (len >= 2) {
671                 tmpstr = walk(0,level,ops[node+2].ival,&numarg);
672                 if (*tmpstr->str_ptr == ';') {
673                     addsemi(str);
674                     str_cat(str,tmpstr->str_ptr+1);
675                 }
676                 str_free(tmpstr);
677             }
678         }
679         break;
680     case OPRINTF:
681     case OPRINT:
682         str = str_new(0);
683         if (len == 3) {         /* output redirection */
684             tmpstr = walk(1,level,ops[node+3].ival,&numarg);
685             tmp2str = walk(1,level,ops[node+2].ival,&numarg);
686             if (!do_fancy_opens) {
687                 t = tmpstr->str_ptr;
688                 if (*t == '"' || *t == '\'')
689                     t = cpytill(tokenbuf,t+1,*t);
690                 else
691                     fatal("Internal error: OPRINT");
692                 d = savestr(t);
693                 s = savestr(tokenbuf);
694                 for (t = tokenbuf; *t; t++) {
695                     *t &= 127;
696                     if (!isalpha(*t) && !isdigit(*t))
697                         *t = '_';
698                 }
699                 if (!index(tokenbuf,'_'))
700                     strcpy(t,"_fh");
701                 str_cat(opens,"open(");
702                 str_cat(opens,tokenbuf);
703                 str_cat(opens,", ");
704                 d[1] = '\0';
705                 str_cat(opens,d);
706                 str_scat(opens,tmp2str);
707                 str_cat(opens,tmpstr->str_ptr+1);
708                 if (*tmp2str->str_ptr == '|')
709                     str_cat(opens,") || die 'Cannot pipe to \"");
710                 else
711                     str_cat(opens,") || die 'Cannot create file \"");
712                 if (*d == '"')
713                     str_cat(opens,"'.\"");
714                 str_cat(opens,s);
715                 if (*d == '"')
716                     str_cat(opens,"\".'");
717                 str_cat(opens,"\".';\n");
718                 str_free(tmpstr);
719                 str_free(tmp2str);
720                 safefree(s);
721                 safefree(d);
722             }
723             else {
724                 sprintf(tokenbuf,"do Pick('%s' . (%s)) &&\n",
725                    tmp2str->str_ptr, tmpstr->str_ptr);
726                 str_cat(str,tokenbuf);
727                 tab(str,level+1);
728                 *tokenbuf = '\0';
729                 str_free(tmpstr);
730                 str_free(tmp2str);
731             }
732         }
733         else
734             strcpy(tokenbuf,"stdout");
735         if (type == OPRINTF)
736             str_cat(str,"printf");
737         else
738             str_cat(str,"print");
739         if (len == 3 || do_fancy_opens) {
740             if (*tokenbuf)
741                 str_cat(str," ");
742             str_cat(str,tokenbuf);
743         }
744         tmpstr = walk(1+(type==OPRINT),level,ops[node+1].ival,&numarg);
745         if (!*tmpstr->str_ptr && lval_field) {
746             t = saw_OFS ? "$," : "' '";
747             if (split_to_array) {
748                 sprintf(tokenbuf,"join(%s,@Fld)",t);
749                 str_cat(tmpstr,tokenbuf);
750             }
751             else {
752                 for (i = 1; i < maxfld; i++) {
753                     if (i <= arymax)
754                         sprintf(tokenbuf,"$%s, ",nameary[i]);
755                     else
756                         sprintf(tokenbuf,"$Fld%d, ",i);
757                     str_cat(tmpstr,tokenbuf);
758                 }
759                 if (maxfld <= arymax)
760                     sprintf(tokenbuf,"$%s",nameary[maxfld]);
761                 else
762                     sprintf(tokenbuf,"$Fld%d",maxfld);
763                 str_cat(tmpstr,tokenbuf);
764             }
765         }
766         if (*tmpstr->str_ptr) {
767             str_cat(str," ");
768             str_scat(str,tmpstr);
769         }
770         else {
771             str_cat(str," $_");
772         }
773         str_free(tmpstr);
774         break;
775     case OLENGTH:
776         str = str_make("length(");
777         goto maybe0;
778     case OLOG:
779         str = str_make("log(");
780         goto maybe0;
781     case OEXP:
782         str = str_make("exp(");
783         goto maybe0;
784     case OSQRT:
785         str = str_make("sqrt(");
786         goto maybe0;
787     case OINT:
788         str = str_make("int(");
789       maybe0:
790         numeric = 1;
791         if (len > 0)
792             tmpstr = walk(1,level,ops[node+1].ival,&numarg);
793         else
794             tmpstr = str_new(0);;
795         if (!*tmpstr->str_ptr) {
796             if (lval_field) {
797                 t = saw_OFS ? "$," : "' '";
798                 if (split_to_array) {
799                     sprintf(tokenbuf,"join(%s,@Fld)",t);
800                     str_cat(tmpstr,tokenbuf);
801                 }
802                 else {
803                     sprintf(tokenbuf,"join(%s, ",t);
804                     str_cat(tmpstr,tokenbuf);
805                     for (i = 1; i < maxfld; i++) {
806                         if (i <= arymax)
807                             sprintf(tokenbuf,"$%s,",nameary[i]);
808                         else
809                             sprintf(tokenbuf,"$Fld%d,",i);
810                         str_cat(tmpstr,tokenbuf);
811                     }
812                     if (maxfld <= arymax)
813                         sprintf(tokenbuf,"$%s)",nameary[maxfld]);
814                     else
815                         sprintf(tokenbuf,"$Fld%d)",maxfld);
816                     str_cat(tmpstr,tokenbuf);
817                 }
818             }
819             else
820                 str_cat(tmpstr,"$_");
821         }
822         if (strEQ(tmpstr->str_ptr,"$_")) {
823             if (type == OLENGTH && !do_chop) {
824                 str = str_make("(length(");
825                 str_cat(tmpstr,") - 1");
826             }
827         }
828         str_scat(str,tmpstr);
829         str_free(tmpstr);
830         str_cat(str,")");
831         break;
832     case OBREAK:
833         str = str_new(0);
834         str_set(str,"last");
835         break;
836     case ONEXT:
837         str = str_new(0);
838         str_set(str,"next line");
839         break;
840     case OEXIT:
841         str = str_new(0);
842         if (realexit) {
843             str_set(str,"exit");
844             if (len == 1) {
845                 str_cat(str," ");
846                 exitval = TRUE;
847                 str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg));
848                 str_free(fstr);
849             }
850         }
851         else {
852             if (len == 1) {
853                 str_set(str,"ExitValue = ");
854                 exitval = TRUE;
855                 str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg));
856                 str_free(fstr);
857                 str_cat(str,"; ");
858             }
859             str_cat(str,"last line");
860         }
861         break;
862     case OCONTINUE:
863         str = str_new(0);
864         str_set(str,"next");
865         break;
866     case OREDIR:
867         goto def;
868     case OIF:
869         str = str_new(0);
870         str_set(str,"if (");
871         str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg));
872         str_free(fstr);
873         str_cat(str,") ");
874         str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg));
875         str_free(fstr);
876         if (len == 3) {
877             i = ops[node+3].ival;
878             if (i) {
879                 if ((ops[i].ival & 255) == OBLOCK) {
880                     i = ops[i+1].ival;
881                     if (i) {
882                         if ((ops[i].ival & 255) != OIF)
883                             i = 0;
884                     }
885                 }
886                 else
887                     i = 0;
888             }
889             if (i) {
890                 str_cat(str,"els");
891                 str_scat(str,fstr=walk(0,level,i,&numarg));
892                 str_free(fstr);
893             }
894             else {
895                 str_cat(str,"else ");
896                 str_scat(str,fstr=walk(0,level,ops[node+3].ival,&numarg));
897                 str_free(fstr);
898             }
899         }
900         break;
901     case OWHILE:
902         str = str_new(0);
903         str_set(str,"while (");
904         str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg));
905         str_free(fstr);
906         str_cat(str,") ");
907         str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg));
908         str_free(fstr);
909         break;
910     case OFOR:
911         str = str_new(0);
912         str_set(str,"for (");
913         str_scat(str,tmpstr=walk(1,level,ops[node+1].ival,&numarg));
914         i = numarg;
915         if (i) {
916             t = s = tmpstr->str_ptr;
917             while (isalpha(*t) || isdigit(*t) || *t == '$' || *t == '_')
918                 t++;
919             i = t - s;
920             if (i < 2)
921                 i = 0;
922         }
923         str_cat(str,"; ");
924         fstr=walk(1,level,ops[node+2].ival,&numarg);
925         if (i && (t = index(fstr->str_ptr,0377))) {
926             if (strnEQ(fstr->str_ptr,s,i))
927                 *t = ' ';
928         }
929         str_scat(str,fstr);
930         str_free(fstr);
931         str_free(tmpstr);
932         str_cat(str,"; ");
933         str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg));
934         str_free(fstr);
935         str_cat(str,") ");
936         str_scat(str,fstr=walk(0,level,ops[node+4].ival,&numarg));
937         str_free(fstr);
938         break;
939     case OFORIN:
940         tmpstr=walk(0,level,ops[node+2].ival,&numarg);
941         str = str_new(0);
942         str_sset(str,tmpstr);
943         str_cat(str,"[]");
944         tmp2str = hfetch(symtab,str->str_ptr);
945         if (tmp2str && atoi(tmp2str->str_ptr)) {
946             maxtmp++;
947             fstr=walk(1,level,ops[node+1].ival,&numarg);
948             sprintf(tokenbuf,
949               "for ($T_%d = 1; ($%s = $%s[$T_%d]) || $T_%d <= $#%s; $T_%d++)%c",
950               maxtmp,
951               fstr->str_ptr,
952               tmpstr->str_ptr,
953               maxtmp,
954               maxtmp,
955               tmpstr->str_ptr,
956               maxtmp,
957               0377);
958             str_set(str,tokenbuf);
959             str_free(fstr);
960             str_scat(str,fstr=walk(0,level,ops[node+3].ival,&numarg));
961             str_free(fstr);
962         }
963         else {
964             str_set(str,"while (($junkkey,$");
965             str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg));
966             str_free(fstr);
967             str_cat(str,") = each(");
968             str_scat(str,tmpstr);
969             str_cat(str,")) ");
970             str_scat(str,fstr=walk(0,level,ops[node+3].ival,&numarg));
971             str_free(fstr);
972         }
973         str_free(tmpstr);
974         break;
975     case OBLOCK:
976         str = str_new(0);
977         str_set(str,"{");
978         if (len == 2) {
979             str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg));
980             str_free(fstr);
981         }
982         fixtab(str,++level);
983         str_scat(str,fstr=walk(0,level,ops[node+1].ival,&numarg));
984         str_free(fstr);
985         addsemi(str);
986         fixtab(str,--level);
987         str_cat(str,"}\n");
988         tab(str,level);
989         break;
990     default:
991       def:
992         if (len) {
993             if (len > 5)
994                 fatal("Garbage length in walk");
995             str = walk(0,level,ops[node+1].ival,&numarg);
996             for (i = 2; i<= len; i++) {
997                 str_scat(str,fstr=walk(0,level,ops[node+i].ival,&numarg));
998                 str_free(fstr);
999             }
1000         }
1001         else {
1002             str = Nullstr;
1003         }
1004         break;
1005     }
1006     if (!str)
1007         str = str_new(0);
1008     *numericptr = numeric;
1009 #ifdef DEBUGGING
1010     if (debug & 4) {
1011         printf("%3d %5d %15s %d %4d ",level,node,opname[type],len,str->str_cur);
1012         for (t = str->str_ptr; *t && t - str->str_ptr < 40; t++)
1013             if (*t == '\n')
1014                 printf("\\n");
1015             else if (*t == '\t')
1016                 printf("\\t");
1017             else
1018                 putchar(*t);
1019         putchar('\n');
1020     }
1021 #endif
1022     return str;
1023 }
1024
1025 tab(str,lvl)
1026 register STR *str;
1027 register int lvl;
1028 {
1029     while (lvl > 1) {
1030         str_cat(str,"\t");
1031         lvl -= 2;
1032     }
1033     if (lvl)
1034         str_cat(str,"    ");
1035 }
1036
1037 fixtab(str,lvl)
1038 register STR *str;
1039 register int lvl;
1040 {
1041     register char *s;
1042
1043     /* strip trailing white space */
1044
1045     s = str->str_ptr+str->str_cur - 1;
1046     while (s >= str->str_ptr && (*s == ' ' || *s == '\t'))
1047         s--;
1048     s[1] = '\0';
1049     str->str_cur = s + 1 - str->str_ptr;
1050     if (s >= str->str_ptr && *s != '\n')
1051         str_cat(str,"\n");
1052
1053     tab(str,lvl);
1054 }
1055
1056 addsemi(str)
1057 register STR *str;
1058 {
1059     register char *s;
1060
1061     s = str->str_ptr+str->str_cur - 1;
1062     while (s >= str->str_ptr && (*s == ' ' || *s == '\t' || *s == '\n'))
1063         s--;
1064     if (s >= str->str_ptr && *s != ';' && *s != '}')
1065         str_cat(str,";");
1066 }
1067
1068 emit_split(str,level)
1069 register STR *str;
1070 int level;
1071 {
1072     register int i;
1073
1074     if (split_to_array)
1075         str_cat(str,"@Fld");
1076     else {
1077         str_cat(str,"(");
1078         for (i = 1; i < maxfld; i++) {
1079             if (i <= arymax)
1080                 sprintf(tokenbuf,"$%s,",nameary[i]);
1081             else
1082                 sprintf(tokenbuf,"$Fld%d,",i);
1083             str_cat(str,tokenbuf);
1084         }
1085         if (maxfld <= arymax)
1086             sprintf(tokenbuf,"$%s)",nameary[maxfld]);
1087         else
1088             sprintf(tokenbuf,"$Fld%d)",maxfld);
1089         str_cat(str,tokenbuf);
1090     }
1091     if (const_FS) {
1092         sprintf(tokenbuf," = split(/[%c\\n]/);\n",const_FS);
1093         str_cat(str,tokenbuf);
1094     }
1095     else if (saw_FS)
1096         str_cat(str," = split($FS);\n");
1097     else
1098         str_cat(str," = split;\n");
1099     tab(str,level);
1100 }
1101
1102 prewalk(numit,level,node,numericptr)
1103 int numit;
1104 int level;
1105 register int node;
1106 int *numericptr;
1107 {
1108     register int len;
1109     register int type;
1110     register int i;
1111     char *t;
1112     char *d, *s;
1113     int numarg;
1114     int numeric = FALSE;
1115
1116     if (!node) {
1117         *numericptr = 0;
1118         return 0;
1119     }
1120     type = ops[node].ival;
1121     len = type >> 8;
1122     type &= 255;
1123     switch (type) {
1124     case OPROG:
1125         prewalk(0,level,ops[node+1].ival,&numarg);
1126         if (ops[node+2].ival) {
1127             prewalk(0,level,ops[node+2].ival,&numarg);
1128         }
1129         ++level;
1130         prewalk(0,level,ops[node+3].ival,&numarg);
1131         --level;
1132         if (ops[node+3].ival) {
1133             prewalk(0,level,ops[node+4].ival,&numarg);
1134         }
1135         break;
1136     case OHUNKS:
1137         prewalk(0,level,ops[node+1].ival,&numarg);
1138         prewalk(0,level,ops[node+2].ival,&numarg);
1139         if (len == 3) {
1140             prewalk(0,level,ops[node+3].ival,&numarg);
1141         }
1142         break;
1143     case ORANGE:
1144         prewalk(1,level,ops[node+1].ival,&numarg);
1145         prewalk(1,level,ops[node+2].ival,&numarg);
1146         break;
1147     case OPAT:
1148         goto def;
1149     case OREGEX:
1150         prewalk(0,level,ops[node+1].ival,&numarg);
1151         break;
1152     case OHUNK:
1153         if (len == 1) {
1154             prewalk(0,level,ops[node+1].ival,&numarg);
1155         }
1156         else {
1157             i = prewalk(0,level,ops[node+1].ival,&numarg);
1158             if (i) {
1159                 ++level;
1160                 prewalk(0,level,ops[node+2].ival,&numarg);
1161                 --level;
1162             }
1163             else {
1164                 prewalk(0,level,ops[node+2].ival,&numarg);
1165             }
1166         }
1167         break;
1168     case OPPAREN:
1169         prewalk(0,level,ops[node+1].ival,&numarg);
1170         break;
1171     case OPANDAND:
1172         prewalk(0,level,ops[node+1].ival,&numarg);
1173         prewalk(0,level,ops[node+2].ival,&numarg);
1174         break;
1175     case OPOROR:
1176         prewalk(0,level,ops[node+1].ival,&numarg);
1177         prewalk(0,level,ops[node+2].ival,&numarg);
1178         break;
1179     case OPNOT:
1180         prewalk(0,level,ops[node+1].ival,&numarg);
1181         break;
1182     case OCPAREN:
1183         prewalk(0,level,ops[node+1].ival,&numarg);
1184         numeric |= numarg;
1185         break;
1186     case OCANDAND:
1187         prewalk(0,level,ops[node+1].ival,&numarg);
1188         numeric = 1;
1189         prewalk(0,level,ops[node+2].ival,&numarg);
1190         break;
1191     case OCOROR:
1192         prewalk(0,level,ops[node+1].ival,&numarg);
1193         numeric = 1;
1194         prewalk(0,level,ops[node+2].ival,&numarg);
1195         break;
1196     case OCNOT:
1197         prewalk(0,level,ops[node+1].ival,&numarg);
1198         numeric = 1;
1199         break;
1200     case ORELOP:
1201         prewalk(0,level,ops[node+2].ival,&numarg);
1202         numeric |= numarg;
1203         prewalk(0,level,ops[node+1].ival,&numarg);
1204         prewalk(0,level,ops[node+3].ival,&numarg);
1205         numeric |= numarg;
1206         numeric = 1;
1207         break;
1208     case ORPAREN:
1209         prewalk(0,level,ops[node+1].ival,&numarg);
1210         numeric |= numarg;
1211         break;
1212     case OMATCHOP:
1213         prewalk(0,level,ops[node+2].ival,&numarg);
1214         prewalk(0,level,ops[node+1].ival,&numarg);
1215         prewalk(0,level,ops[node+3].ival,&numarg);
1216         numeric = 1;
1217         break;
1218     case OMPAREN:
1219         prewalk(0,level,ops[node+1].ival,&numarg);
1220         numeric |= numarg;
1221         break;
1222     case OCONCAT:
1223         prewalk(0,level,ops[node+1].ival,&numarg);
1224         prewalk(0,level,ops[node+2].ival,&numarg);
1225         break;
1226     case OASSIGN:
1227         prewalk(0,level,ops[node+2].ival,&numarg);
1228         prewalk(0,level,ops[node+1].ival,&numarg);
1229         prewalk(0,level,ops[node+3].ival,&numarg);
1230         if (numarg || strlen(ops[ops[node+1].ival+1].cval) > 1) {
1231             numericize(ops[node+2].ival);
1232             if (!numarg)
1233                 numericize(ops[node+3].ival);
1234         }
1235         numeric |= numarg;
1236         break;
1237     case OADD:
1238         prewalk(1,level,ops[node+1].ival,&numarg);
1239         prewalk(1,level,ops[node+2].ival,&numarg);
1240         numeric = 1;
1241         break;
1242     case OSUB:
1243         prewalk(1,level,ops[node+1].ival,&numarg);
1244         prewalk(1,level,ops[node+2].ival,&numarg);
1245         numeric = 1;
1246         break;
1247     case OMULT:
1248         prewalk(1,level,ops[node+1].ival,&numarg);
1249         prewalk(1,level,ops[node+2].ival,&numarg);
1250         numeric = 1;
1251         break;
1252     case ODIV:
1253         prewalk(1,level,ops[node+1].ival,&numarg);
1254         prewalk(1,level,ops[node+2].ival,&numarg);
1255         numeric = 1;
1256         break;
1257     case OMOD:
1258         prewalk(1,level,ops[node+1].ival,&numarg);
1259         prewalk(1,level,ops[node+2].ival,&numarg);
1260         numeric = 1;
1261         break;
1262     case OPOSTINCR:
1263         prewalk(1,level,ops[node+1].ival,&numarg);
1264         numeric = 1;
1265         break;
1266     case OPOSTDECR:
1267         prewalk(1,level,ops[node+1].ival,&numarg);
1268         numeric = 1;
1269         break;
1270     case OPREINCR:
1271         prewalk(1,level,ops[node+1].ival,&numarg);
1272         numeric = 1;
1273         break;
1274     case OPREDECR:
1275         prewalk(1,level,ops[node+1].ival,&numarg);
1276         numeric = 1;
1277         break;
1278     case OUMINUS:
1279         prewalk(1,level,ops[node+1].ival,&numarg);
1280         numeric = 1;
1281         break;
1282     case OUPLUS:
1283         prewalk(1,level,ops[node+1].ival,&numarg);
1284         numeric = 1;
1285         break;
1286     case OPAREN:
1287         prewalk(0,level,ops[node+1].ival,&numarg);
1288         numeric |= numarg;
1289         break;
1290     case OGETLINE:
1291         break;
1292     case OSPRINTF:
1293         prewalk(0,level,ops[node+1].ival,&numarg);
1294         break;
1295     case OSUBSTR:
1296         prewalk(0,level,ops[node+1].ival,&numarg);
1297         prewalk(1,level,ops[node+2].ival,&numarg);
1298         if (len == 3) {
1299             prewalk(1,level,ops[node+3].ival,&numarg);
1300         }
1301         break;
1302     case OSTRING:
1303         break;
1304     case OSPLIT:
1305         numeric = 1;
1306         prewalk(0,level,ops[node+2].ival,&numarg);
1307         if (len == 3)
1308             prewalk(0,level,ops[node+3].ival,&numarg);
1309         prewalk(0,level,ops[node+1].ival,&numarg);
1310         break;
1311     case OINDEX:
1312         prewalk(0,level,ops[node+1].ival,&numarg);
1313         prewalk(0,level,ops[node+2].ival,&numarg);
1314         numeric = 1;
1315         break;
1316     case ONUM:
1317         prewalk(0,level,ops[node+1].ival,&numarg);
1318         numeric = 1;
1319         break;
1320     case OSTR:
1321         prewalk(0,level,ops[node+1].ival,&numarg);
1322         break;
1323     case OVAR:
1324         prewalk(0,level,ops[node+1].ival,&numarg);
1325         if (len == 1) {
1326             if (numit)
1327                 numericize(node);
1328         }
1329         else {
1330             prewalk(0,level,ops[node+2].ival,&numarg);
1331         }
1332         break;
1333     case OFLD:
1334         prewalk(0,level,ops[node+1].ival,&numarg);
1335         break;
1336     case OVFLD:
1337         i = ops[node+1].ival;
1338         prewalk(0,level,i,&numarg);
1339         break;
1340     case OJUNK:
1341         goto def;
1342     case OSNEWLINE:
1343         break;
1344     case ONEWLINE:
1345         break;
1346     case OSCOMMENT:
1347         break;
1348     case OCOMMENT:
1349         break;
1350     case OCOMMA:
1351         prewalk(0,level,ops[node+1].ival,&numarg);
1352         prewalk(0,level,ops[node+2].ival,&numarg);
1353         break;
1354     case OSEMICOLON:
1355         break;
1356     case OSTATES:
1357         prewalk(0,level,ops[node+1].ival,&numarg);
1358         prewalk(0,level,ops[node+2].ival,&numarg);
1359         break;
1360     case OSTATE:
1361         if (len >= 1) {
1362             prewalk(0,level,ops[node+1].ival,&numarg);
1363             if (len >= 2) {
1364                 prewalk(0,level,ops[node+2].ival,&numarg);
1365             }
1366         }
1367         break;
1368     case OPRINTF:
1369     case OPRINT:
1370         if (len == 3) {         /* output redirection */
1371             prewalk(0,level,ops[node+3].ival,&numarg);
1372             prewalk(0,level,ops[node+2].ival,&numarg);
1373         }
1374         prewalk(0+(type==OPRINT),level,ops[node+1].ival,&numarg);
1375         break;
1376     case OLENGTH:
1377         goto maybe0;
1378     case OLOG:
1379         goto maybe0;
1380     case OEXP:
1381         goto maybe0;
1382     case OSQRT:
1383         goto maybe0;
1384     case OINT:
1385       maybe0:
1386         numeric = 1;
1387         if (len > 0)
1388             prewalk(type != OLENGTH,level,ops[node+1].ival,&numarg);
1389         break;
1390     case OBREAK:
1391         break;
1392     case ONEXT:
1393         break;
1394     case OEXIT:
1395         if (len == 1) {
1396             prewalk(1,level,ops[node+1].ival,&numarg);
1397         }
1398         break;
1399     case OCONTINUE:
1400         break;
1401     case OREDIR:
1402         goto def;
1403     case OIF:
1404         prewalk(0,level,ops[node+1].ival,&numarg);
1405         prewalk(0,level,ops[node+2].ival,&numarg);
1406         if (len == 3) {
1407             prewalk(0,level,ops[node+3].ival,&numarg);
1408         }
1409         break;
1410     case OWHILE:
1411         prewalk(0,level,ops[node+1].ival,&numarg);
1412         prewalk(0,level,ops[node+2].ival,&numarg);
1413         break;
1414     case OFOR:
1415         prewalk(0,level,ops[node+1].ival,&numarg);
1416         prewalk(0,level,ops[node+2].ival,&numarg);
1417         prewalk(0,level,ops[node+3].ival,&numarg);
1418         prewalk(0,level,ops[node+4].ival,&numarg);
1419         break;
1420     case OFORIN:
1421         prewalk(0,level,ops[node+2].ival,&numarg);
1422         prewalk(0,level,ops[node+1].ival,&numarg);
1423         prewalk(0,level,ops[node+3].ival,&numarg);
1424         break;
1425     case OBLOCK:
1426         if (len == 2) {
1427             prewalk(0,level,ops[node+2].ival,&numarg);
1428         }
1429         ++level;
1430         prewalk(0,level,ops[node+1].ival,&numarg);
1431         --level;
1432         break;
1433     default:
1434       def:
1435         if (len) {
1436             if (len > 5)
1437                 fatal("Garbage length in prewalk");
1438             prewalk(0,level,ops[node+1].ival,&numarg);
1439             for (i = 2; i<= len; i++) {
1440                 prewalk(0,level,ops[node+i].ival,&numarg);
1441             }
1442         }
1443         break;
1444     }
1445     *numericptr = numeric;
1446     return 1;
1447 }
1448
1449 numericize(node)
1450 register int node;
1451 {
1452     register int len;
1453     register int type;
1454     register int i;
1455     STR *tmpstr;
1456     STR *tmp2str;
1457     int numarg;
1458
1459     type = ops[node].ival;
1460     len = type >> 8;
1461     type &= 255;
1462     if (type == OVAR && len == 1) {
1463         tmpstr=walk(0,0,ops[node+1].ival,&numarg);
1464         tmp2str = str_make("1");
1465         hstore(symtab,tmpstr->str_ptr,tmp2str);
1466     }
1467 }