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