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