File Coverage

x2p/walk.c
Criterion Covered Total %
statement 0 1352 0.0
branch n/a
condition n/a
subroutine n/a
total 0 1352 0.0


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