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