Commit | Line | Data |
---|---|---|
378cc40b | 1 | char rcsid[] = "$Header: perly.c,v 2.0 88/06/05 00:09:56 root Exp $"; |
8d063cd8 LW |
2 | /* |
3 | * $Log: perly.c,v $ | |
378cc40b LW |
4 | * Revision 2.0 88/06/05 00:09:56 root |
5 | * Baseline version 2.0. | |
8d063cd8 LW |
6 | * |
7 | */ | |
8 | ||
378cc40b LW |
9 | #include "EXTERN.h" |
10 | #include "perl.h" | |
11 | #include "perly.h" | |
12 | ||
13 | extern char *tokename[]; | |
14 | extern int yychar; | |
15 | ||
16 | static int cmd_tosave(); | |
17 | static int arg_tosave(); | |
18 | static int spat_tosave(); | |
8d063cd8 LW |
19 | |
20 | main(argc,argv,env) | |
21 | register int argc; | |
22 | register char **argv; | |
23 | register char **env; | |
24 | { | |
25 | register STR *str; | |
26 | register char *s; | |
378cc40b LW |
27 | char *index(), *strcpy(), *getenv(); |
28 | bool dosearch = FALSE; | |
8d063cd8 | 29 | |
378cc40b LW |
30 | uid = (int)getuid(); |
31 | euid = (int)geteuid(); | |
8d063cd8 | 32 | linestr = str_new(80); |
378cc40b LW |
33 | str_nset(linestr,"",0); |
34 | str = str_make(""); /* first used for -I flags */ | |
35 | incstab = aadd(stabent("INC",TRUE)); | |
8d063cd8 LW |
36 | for (argc--,argv++; argc; argc--,argv++) { |
37 | if (argv[0][0] != '-' || !argv[0][1]) | |
38 | break; | |
39 | reswitch: | |
40 | switch (argv[0][1]) { | |
378cc40b LW |
41 | case 'a': |
42 | minus_a = TRUE; | |
43 | strcpy(argv[0], argv[0]+1); | |
44 | goto reswitch; | |
8d063cd8 LW |
45 | #ifdef DEBUGGING |
46 | case 'D': | |
47 | debug = atoi(argv[0]+2); | |
48 | #ifdef YYDEBUG | |
49 | yydebug = (debug & 1); | |
50 | #endif | |
51 | break; | |
52 | #endif | |
53 | case 'e': | |
54 | if (!e_fp) { | |
378cc40b | 55 | e_tmpname = strcpy(safemalloc(sizeof(TMPPATH)),TMPPATH); |
8d063cd8 LW |
56 | mktemp(e_tmpname); |
57 | e_fp = fopen(e_tmpname,"w"); | |
58 | } | |
59 | if (argv[1]) | |
60 | fputs(argv[1],e_fp); | |
61 | putc('\n', e_fp); | |
62 | argc--,argv++; | |
63 | break; | |
64 | case 'i': | |
65 | inplace = savestr(argv[0]+2); | |
66 | argvoutstab = stabent("ARGVOUT",TRUE); | |
67 | break; | |
68 | case 'I': | |
69 | str_cat(str,argv[0]); | |
70 | str_cat(str," "); | |
378cc40b LW |
71 | if (argv[0][2]) { |
72 | apush(incstab->stab_array,str_make(argv[0]+2)); | |
73 | } | |
74 | else { | |
75 | apush(incstab->stab_array,str_make(argv[1])); | |
8d063cd8 LW |
76 | str_cat(str,argv[1]); |
77 | argc--,argv++; | |
78 | str_cat(str," "); | |
79 | } | |
80 | break; | |
81 | case 'n': | |
378cc40b | 82 | minus_n = TRUE; |
8d063cd8 LW |
83 | strcpy(argv[0], argv[0]+1); |
84 | goto reswitch; | |
85 | case 'p': | |
378cc40b | 86 | minus_p = TRUE; |
8d063cd8 LW |
87 | strcpy(argv[0], argv[0]+1); |
88 | goto reswitch; | |
89 | case 'P': | |
90 | preprocess = TRUE; | |
91 | strcpy(argv[0], argv[0]+1); | |
92 | goto reswitch; | |
93 | case 's': | |
94 | doswitches = TRUE; | |
95 | strcpy(argv[0], argv[0]+1); | |
96 | goto reswitch; | |
378cc40b LW |
97 | case 'S': |
98 | dosearch = TRUE; | |
99 | strcpy(argv[0], argv[0]+1); | |
100 | goto reswitch; | |
101 | case 'U': | |
102 | unsafe = TRUE; | |
103 | strcpy(argv[0], argv[0]+1); | |
104 | goto reswitch; | |
8d063cd8 LW |
105 | case 'v': |
106 | version(); | |
107 | exit(0); | |
378cc40b LW |
108 | case 'w': |
109 | dowarn = TRUE; | |
110 | strcpy(argv[0], argv[0]+1); | |
111 | goto reswitch; | |
8d063cd8 LW |
112 | case '-': |
113 | argc--,argv++; | |
114 | goto switch_end; | |
115 | case 0: | |
116 | break; | |
117 | default: | |
378cc40b | 118 | fatal("Unrecognized switch: %s",argv[0]); |
8d063cd8 LW |
119 | } |
120 | } | |
121 | switch_end: | |
122 | if (e_fp) { | |
123 | fclose(e_fp); | |
124 | argc++,argv--; | |
125 | argv[0] = e_tmpname; | |
126 | } | |
378cc40b LW |
127 | #ifndef PRIVLIB |
128 | #define PRIVLIB "/usr/local/lib/perl" | |
129 | #endif | |
130 | apush(incstab->stab_array,str_make(PRIVLIB)); | |
8d063cd8 LW |
131 | |
132 | str_set(&str_no,No); | |
133 | str_set(&str_yes,Yes); | |
134 | init_eval(); | |
135 | ||
136 | /* open script */ | |
137 | ||
138 | if (argv[0] == Nullch) | |
139 | argv[0] = "-"; | |
378cc40b LW |
140 | if (dosearch && argv[0][0] != '/' && (s = getenv("PATH"))) { |
141 | char *xfound = Nullch, *xfailed = Nullch; | |
142 | ||
143 | while (*s) { | |
144 | s = cpytill(tokenbuf,s,':'); | |
145 | if (*s) | |
146 | s++; | |
147 | if (tokenbuf[0]) | |
148 | strcat(tokenbuf,"/"); | |
149 | strcat(tokenbuf,argv[0]); | |
150 | #ifdef DEBUGGING | |
151 | if (debug & 1) | |
152 | fprintf(stderr,"Looking for %s\n",tokenbuf); | |
153 | #endif | |
154 | if (stat(tokenbuf,&statbuf) < 0) /* not there? */ | |
155 | continue; | |
156 | if ((statbuf.st_mode & S_IFMT) == S_IFREG | |
157 | && cando(S_IREAD,TRUE) && cando(S_IEXEC,TRUE)) { | |
158 | xfound = tokenbuf; /* bingo! */ | |
159 | break; | |
160 | } | |
161 | if (!xfailed) | |
162 | xfailed = savestr(tokenbuf); | |
163 | } | |
164 | if (!xfound) | |
165 | fatal("Can't execute %s", xfailed); | |
166 | if (xfailed) | |
167 | safefree(xfailed); | |
168 | argv[0] = savestr(xfound); | |
169 | } | |
8d063cd8 | 170 | filename = savestr(argv[0]); |
378cc40b | 171 | origfilename = savestr(filename); |
8d063cd8 LW |
172 | if (strEQ(filename,"-")) |
173 | argv[0] = ""; | |
174 | if (preprocess) { | |
378cc40b LW |
175 | str_cat(str,"-I"); |
176 | str_cat(str,PRIVLIB); | |
8d063cd8 LW |
177 | sprintf(buf, "\ |
178 | /bin/sed -e '/^[^#]/b' \ | |
179 | -e '/^#[ ]*include[ ]/b' \ | |
180 | -e '/^#[ ]*define[ ]/b' \ | |
181 | -e '/^#[ ]*if[ ]/b' \ | |
182 | -e '/^#[ ]*ifdef[ ]/b' \ | |
378cc40b | 183 | -e '/^#[ ]*ifndef[ ]/b' \ |
8d063cd8 LW |
184 | -e '/^#[ ]*else/b' \ |
185 | -e '/^#[ ]*endif/b' \ | |
186 | -e 's/^#.*//' \ | |
378cc40b LW |
187 | %s | %s -C %s %s", |
188 | argv[0], CPPSTDIN, str_get(str), CPPMINUS); | |
8d063cd8 LW |
189 | rsfp = popen(buf,"r"); |
190 | } | |
191 | else if (!*argv[0]) | |
192 | rsfp = stdin; | |
193 | else | |
194 | rsfp = fopen(argv[0],"r"); | |
195 | if (rsfp == Nullfp) | |
378cc40b | 196 | fatal("Perl script \"%s\" doesn't seem to exist",filename); |
8d063cd8 LW |
197 | str_free(str); /* free -I directories */ |
198 | ||
199 | defstab = stabent("_",TRUE); | |
200 | ||
201 | /* init tokener */ | |
202 | ||
203 | bufptr = str_get(linestr); | |
204 | ||
205 | /* now parse the report spec */ | |
206 | ||
207 | if (yyparse()) | |
208 | fatal("Execution aborted due to compilation errors.\n"); | |
209 | ||
378cc40b LW |
210 | if (dowarn) { |
211 | stab_check('A','Z'); | |
212 | stab_check('a','z'); | |
213 | } | |
214 | ||
215 | preprocess = FALSE; | |
8d063cd8 LW |
216 | if (e_fp) { |
217 | e_fp = Nullfp; | |
218 | UNLINK(e_tmpname); | |
219 | } | |
220 | argc--,argv++; /* skip name of script */ | |
221 | if (doswitches) { | |
222 | for (; argc > 0 && **argv == '-'; argc--,argv++) { | |
223 | if (argv[0][1] == '-') { | |
224 | argc--,argv++; | |
225 | break; | |
226 | } | |
227 | str_numset(stabent(argv[0]+1,TRUE)->stab_val,(double)1.0); | |
228 | } | |
229 | } | |
a559c259 | 230 | if (argvstab = stabent("ARGV",allstabs)) { |
378cc40b | 231 | aadd(argvstab); |
8d063cd8 LW |
232 | for (; argc > 0; argc--,argv++) { |
233 | apush(argvstab->stab_array,str_make(argv[0])); | |
234 | } | |
235 | } | |
a559c259 | 236 | if (envstab = stabent("ENV",allstabs)) { |
378cc40b | 237 | hadd(envstab); |
8d063cd8 LW |
238 | for (; *env; env++) { |
239 | if (!(s = index(*env,'='))) | |
240 | continue; | |
241 | *s++ = '\0'; | |
242 | str = str_make(s); | |
243 | str->str_link.str_magic = envstab; | |
244 | hstore(envstab->stab_hash,*env,str); | |
245 | *--s = '='; | |
246 | } | |
247 | } | |
378cc40b LW |
248 | if (sigstab = stabent("SIG",allstabs)) |
249 | hadd(sigstab); | |
8d063cd8 | 250 | |
378cc40b | 251 | magicalize("!#?^~=-%0123456789.+&*()<>,\\/[|"); |
8d063cd8 | 252 | |
378cc40b LW |
253 | sawampersand = (stabent("&",FALSE) != Nullstab); |
254 | if (tmpstab = stabent("0",allstabs)) | |
255 | str_set(STAB_STR(tmpstab),origfilename); | |
256 | if (tmpstab = stabent("$",allstabs)) | |
8d063cd8 LW |
257 | str_numset(STAB_STR(tmpstab),(double)getpid()); |
258 | ||
259 | tmpstab = stabent("stdin",TRUE); | |
260 | tmpstab->stab_io = stio_new(); | |
261 | tmpstab->stab_io->fp = stdin; | |
262 | ||
263 | tmpstab = stabent("stdout",TRUE); | |
264 | tmpstab->stab_io = stio_new(); | |
265 | tmpstab->stab_io->fp = stdout; | |
266 | defoutstab = tmpstab; | |
267 | curoutstab = tmpstab; | |
268 | ||
269 | tmpstab = stabent("stderr",TRUE); | |
270 | tmpstab->stab_io = stio_new(); | |
271 | tmpstab->stab_io->fp = stderr; | |
378cc40b LW |
272 | |
273 | savestack = anew(Nullstab); /* for saving non-local values */ | |
8d063cd8 LW |
274 | |
275 | setjmp(top_env); /* sets goto_targ on longjump */ | |
276 | ||
277 | #ifdef DEBUGGING | |
278 | if (debug & 1024) | |
279 | dump_cmd(main_root,Nullcmd); | |
280 | if (debug) | |
281 | fprintf(stderr,"\nEXECUTING...\n\n"); | |
282 | #endif | |
283 | ||
284 | /* do it */ | |
285 | ||
286 | (void) cmd_exec(main_root); | |
287 | ||
288 | if (goto_targ) | |
378cc40b | 289 | fatal("Can't find label \"%s\"--aborting",goto_targ); |
8d063cd8 | 290 | exit(0); |
378cc40b | 291 | /* NOTREACHED */ |
8d063cd8 LW |
292 | } |
293 | ||
294 | magicalize(list) | |
295 | register char *list; | |
296 | { | |
297 | register STAB *stab; | |
298 | char sym[2]; | |
299 | ||
300 | sym[1] = '\0'; | |
301 | while (*sym = *list++) { | |
a559c259 | 302 | if (stab = stabent(sym,allstabs)) { |
8d063cd8 LW |
303 | stab->stab_flags = SF_VMAGIC; |
304 | stab->stab_val->str_link.str_magic = stab; | |
305 | } | |
306 | } | |
307 | } | |
308 | ||
8d063cd8 LW |
309 | ARG * |
310 | make_split(stab,arg) | |
311 | register STAB *stab; | |
312 | register ARG *arg; | |
313 | { | |
378cc40b | 314 | register SPAT *spat = (SPAT *) safemalloc(sizeof (SPAT)); |
8d063cd8 | 315 | |
378cc40b LW |
316 | if (arg->arg_type != O_MATCH) { |
317 | spat = (SPAT *) safemalloc(sizeof (SPAT)); | |
8d063cd8 LW |
318 | bzero((char *)spat, sizeof(SPAT)); |
319 | spat->spat_next = spat_root; /* link into spat list */ | |
320 | spat_root = spat; | |
8d063cd8 LW |
321 | |
322 | spat->spat_runtime = arg; | |
378cc40b | 323 | arg = make_match(O_MATCH,stab2arg(A_STAB,defstab),spat); |
8d063cd8 LW |
324 | } |
325 | arg->arg_type = O_SPLIT; | |
378cc40b LW |
326 | spat = arg[2].arg_ptr.arg_spat; |
327 | spat->spat_repl = stab2arg(A_STAB,aadd(stab)); | |
328 | if (spat->spat_short) { /* exact match can bypass regexec() */ | |
329 | if (!((spat->spat_flags & SPAT_SCANFIRST) && | |
330 | (spat->spat_flags & SPAT_ALL) )) { | |
331 | str_free(spat->spat_short); | |
332 | spat->spat_short = Nullstr; | |
8d063cd8 | 333 | } |
8d063cd8 | 334 | } |
378cc40b | 335 | return arg; |
8d063cd8 LW |
336 | } |
337 | ||
378cc40b LW |
338 | SUBR * |
339 | make_sub(name,cmd) | |
340 | char *name; | |
341 | CMD *cmd; | |
8d063cd8 | 342 | { |
378cc40b LW |
343 | register SUBR *sub = (SUBR *) safemalloc(sizeof (SUBR)); |
344 | STAB *stab = stabent(name,TRUE); | |
345 | ||
346 | if (stab->stab_sub) { | |
347 | if (dowarn) { | |
348 | line_t oldline = line; | |
349 | ||
350 | if (cmd) | |
351 | line = cmd->c_line; | |
352 | warn("Subroutine %s redefined",name); | |
353 | line = oldline; | |
354 | } | |
355 | cmd_free(stab->stab_sub->cmd); | |
356 | afree(stab->stab_sub->tosave); | |
357 | safefree((char*)stab->stab_sub); | |
358 | } | |
359 | bzero((char *)sub, sizeof(SUBR)); | |
360 | sub->cmd = cmd; | |
361 | sub->filename = filename; | |
362 | tosave = anew(Nullstab); | |
363 | tosave->ary_fill = 0; /* make 1 based */ | |
364 | cmd_tosave(cmd); /* this builds the tosave array */ | |
365 | sub->tosave = tosave; | |
366 | stab->stab_sub = sub; | |
8d063cd8 LW |
367 | } |
368 | ||
369 | CMD * | |
370 | block_head(tail) | |
371 | register CMD *tail; | |
372 | { | |
373 | if (tail == Nullcmd) { | |
374 | return tail; | |
375 | } | |
376 | return tail->c_head; | |
377 | } | |
378 | ||
379 | CMD * | |
380 | append_line(head,tail) | |
381 | register CMD *head; | |
382 | register CMD *tail; | |
383 | { | |
384 | if (tail == Nullcmd) | |
385 | return head; | |
386 | if (!tail->c_head) /* make sure tail is well formed */ | |
387 | tail->c_head = tail; | |
388 | if (head != Nullcmd) { | |
389 | tail = tail->c_head; /* get to start of tail list */ | |
390 | if (!head->c_head) | |
391 | head->c_head = head; /* start a new head list */ | |
392 | while (head->c_next) { | |
393 | head->c_next->c_head = head->c_head; | |
394 | head = head->c_next; /* get to end of head list */ | |
395 | } | |
396 | head->c_next = tail; /* link to end of old list */ | |
397 | tail->c_head = head->c_head; /* propagate head pointer */ | |
398 | } | |
399 | while (tail->c_next) { | |
400 | tail->c_next->c_head = tail->c_head; | |
401 | tail = tail->c_next; | |
402 | } | |
403 | return tail; | |
404 | } | |
405 | ||
406 | CMD * | |
407 | make_acmd(type,stab,cond,arg) | |
408 | int type; | |
409 | STAB *stab; | |
410 | ARG *cond; | |
411 | ARG *arg; | |
412 | { | |
413 | register CMD *cmd = (CMD *) safemalloc(sizeof (CMD)); | |
414 | ||
415 | bzero((char *)cmd, sizeof(CMD)); | |
416 | cmd->c_type = type; | |
417 | cmd->ucmd.acmd.ac_stab = stab; | |
418 | cmd->ucmd.acmd.ac_expr = arg; | |
419 | cmd->c_expr = cond; | |
420 | if (cond) { | |
378cc40b | 421 | opt_arg(cmd,1,1); |
8d063cd8 LW |
422 | cmd->c_flags |= CF_COND; |
423 | } | |
378cc40b LW |
424 | if (cmdline != NOLINE) { |
425 | cmd->c_line = cmdline; | |
426 | cmdline = NOLINE; | |
427 | } | |
428 | cmd->c_file = filename; | |
8d063cd8 LW |
429 | return cmd; |
430 | } | |
431 | ||
432 | CMD * | |
433 | make_ccmd(type,arg,cblock) | |
434 | int type; | |
435 | register ARG *arg; | |
436 | struct compcmd cblock; | |
437 | { | |
438 | register CMD *cmd = (CMD *) safemalloc(sizeof (CMD)); | |
439 | ||
440 | bzero((char *)cmd, sizeof(CMD)); | |
441 | cmd->c_type = type; | |
442 | cmd->c_expr = arg; | |
443 | cmd->ucmd.ccmd.cc_true = cblock.comp_true; | |
444 | cmd->ucmd.ccmd.cc_alt = cblock.comp_alt; | |
445 | if (arg) { | |
378cc40b | 446 | opt_arg(cmd,1,0); |
8d063cd8 LW |
447 | cmd->c_flags |= CF_COND; |
448 | } | |
378cc40b LW |
449 | if (cmdline != NOLINE) { |
450 | cmd->c_line = cmdline; | |
451 | cmdline = NOLINE; | |
452 | } | |
8d063cd8 LW |
453 | return cmd; |
454 | } | |
455 | ||
456 | void | |
378cc40b | 457 | opt_arg(cmd,fliporflop,acmd) |
8d063cd8 LW |
458 | register CMD *cmd; |
459 | int fliporflop; | |
378cc40b | 460 | int acmd; |
8d063cd8 LW |
461 | { |
462 | register ARG *arg; | |
463 | int opt = CFT_EVAL; | |
464 | int sure = 0; | |
465 | ARG *arg2; | |
466 | char *tmps; /* for True macro */ | |
467 | int context = 0; /* 0 = normal, 1 = before &&, 2 = before || */ | |
468 | int flp = fliporflop; | |
469 | ||
470 | if (!cmd) | |
471 | return; | |
472 | arg = cmd->c_expr; | |
473 | ||
378cc40b LW |
474 | /* Can we turn && and || into if and unless? */ |
475 | ||
476 | if (acmd && !cmd->ucmd.acmd.ac_expr && | |
477 | (arg->arg_type == O_AND || arg->arg_type == O_OR) ) { | |
478 | dehoist(arg,1); | |
479 | dehoist(arg,2); | |
480 | cmd->ucmd.acmd.ac_expr = arg[2].arg_ptr.arg_arg; | |
481 | cmd->c_expr = arg[1].arg_ptr.arg_arg; | |
482 | if (arg->arg_type == O_OR) | |
483 | cmd->c_flags ^= CF_INVERT; /* || is like unless */ | |
484 | arg->arg_len = 0; | |
485 | arg_free(arg); | |
486 | arg = cmd->c_expr; | |
487 | } | |
488 | ||
8d063cd8 LW |
489 | /* Turn "if (!expr)" into "unless (expr)" */ |
490 | ||
378cc40b LW |
491 | while (arg->arg_type == O_NOT) { |
492 | dehoist(arg,1); | |
8d063cd8 LW |
493 | cmd->c_flags ^= CF_INVERT; /* flip sense of cmd */ |
494 | cmd->c_expr = arg[1].arg_ptr.arg_arg; /* hoist the rest of expr */ | |
495 | free_arg(arg); | |
496 | arg = cmd->c_expr; /* here we go again */ | |
497 | } | |
498 | ||
499 | if (!arg->arg_len) { /* sanity check */ | |
500 | cmd->c_flags |= opt; | |
501 | return; | |
502 | } | |
503 | ||
504 | /* for "cond .. cond" we set up for the initial check */ | |
505 | ||
506 | if (arg->arg_type == O_FLIP) | |
507 | context |= 4; | |
508 | ||
509 | /* for "cond && expr" and "cond || expr" we can ignore expr, sort of */ | |
510 | ||
511 | if (arg->arg_type == O_AND) | |
512 | context |= 1; | |
513 | else if (arg->arg_type == O_OR) | |
514 | context |= 2; | |
515 | if (context && arg[flp].arg_type == A_EXPR) { | |
516 | arg = arg[flp].arg_ptr.arg_arg; | |
517 | flp = 1; | |
518 | } | |
519 | ||
520 | if (arg[flp].arg_flags & (AF_PRE|AF_POST)) { | |
521 | cmd->c_flags |= opt; | |
522 | return; /* side effect, can't optimize */ | |
523 | } | |
524 | ||
525 | if (arg->arg_type == O_ITEM || arg->arg_type == O_FLIP || | |
526 | arg->arg_type == O_AND || arg->arg_type == O_OR) { | |
527 | if (arg[flp].arg_type == A_SINGLE) { | |
528 | opt = (str_true(arg[flp].arg_ptr.arg_str) ? CFT_TRUE : CFT_FALSE); | |
378cc40b | 529 | cmd->c_short = arg[flp].arg_ptr.arg_str; |
8d063cd8 LW |
530 | goto literal; |
531 | } | |
532 | else if (arg[flp].arg_type == A_STAB || arg[flp].arg_type == A_LVAL) { | |
533 | cmd->c_stab = arg[flp].arg_ptr.arg_stab; | |
534 | opt = CFT_REG; | |
535 | literal: | |
536 | if (!context) { /* no && or ||? */ | |
537 | free_arg(arg); | |
538 | cmd->c_expr = Nullarg; | |
539 | } | |
540 | if (!(context & 1)) | |
541 | cmd->c_flags |= CF_EQSURE; | |
542 | if (!(context & 2)) | |
543 | cmd->c_flags |= CF_NESURE; | |
544 | } | |
545 | } | |
546 | else if (arg->arg_type == O_MATCH || arg->arg_type == O_SUBST || | |
378cc40b | 547 | arg->arg_type == O_NMATCH || arg->arg_type == O_NSUBST) { |
8d063cd8 LW |
548 | if ((arg[1].arg_type == A_STAB || arg[1].arg_type == A_LVAL) && |
549 | arg[2].arg_type == A_SPAT && | |
378cc40b | 550 | arg[2].arg_ptr.arg_spat->spat_short ) { |
8d063cd8 | 551 | cmd->c_stab = arg[1].arg_ptr.arg_stab; |
378cc40b LW |
552 | cmd->c_short = arg[2].arg_ptr.arg_spat->spat_short; |
553 | cmd->c_slen = arg[2].arg_ptr.arg_spat->spat_slen; | |
554 | if (arg[2].arg_ptr.arg_spat->spat_flags & SPAT_ALL && | |
555 | !(arg[2].arg_ptr.arg_spat->spat_flags & SPAT_ONCE) && | |
8d063cd8 LW |
556 | (arg->arg_type == O_MATCH || arg->arg_type == O_NMATCH) ) |
557 | sure |= CF_EQSURE; /* (SUBST must be forced even */ | |
558 | /* if we know it will work.) */ | |
378cc40b LW |
559 | arg[2].arg_ptr.arg_spat->spat_short = Nullstr; |
560 | arg[2].arg_ptr.arg_spat->spat_slen = 0; /* only one chk */ | |
8d063cd8 LW |
561 | sure |= CF_NESURE; /* normally only sure if it fails */ |
562 | if (arg->arg_type == O_NMATCH || arg->arg_type == O_NSUBST) | |
563 | cmd->c_flags |= CF_FIRSTNEG; | |
564 | if (context & 1) { /* only sure if thing is false */ | |
565 | if (cmd->c_flags & CF_FIRSTNEG) | |
566 | sure &= ~CF_NESURE; | |
567 | else | |
568 | sure &= ~CF_EQSURE; | |
569 | } | |
570 | else if (context & 2) { /* only sure if thing is true */ | |
571 | if (cmd->c_flags & CF_FIRSTNEG) | |
572 | sure &= ~CF_EQSURE; | |
573 | else | |
574 | sure &= ~CF_NESURE; | |
575 | } | |
576 | if (sure & (CF_EQSURE|CF_NESURE)) { /* if we know anything*/ | |
577 | if (arg[2].arg_ptr.arg_spat->spat_flags & SPAT_SCANFIRST) | |
578 | opt = CFT_SCAN; | |
579 | else | |
580 | opt = CFT_ANCHOR; | |
581 | if (sure == (CF_EQSURE|CF_NESURE) /* really sure? */ | |
582 | && arg->arg_type == O_MATCH | |
583 | && context & 4 | |
584 | && fliporflop == 1) { | |
378cc40b LW |
585 | spat_free(arg[2].arg_ptr.arg_spat); |
586 | arg[2].arg_ptr.arg_spat = Nullspat; /* don't do twice */ | |
8d063cd8 LW |
587 | } |
588 | cmd->c_flags |= sure; | |
589 | } | |
590 | } | |
591 | } | |
592 | else if (arg->arg_type == O_SEQ || arg->arg_type == O_SNE || | |
593 | arg->arg_type == O_SLT || arg->arg_type == O_SGT) { | |
594 | if (arg[1].arg_type == A_STAB || arg[1].arg_type == A_LVAL) { | |
595 | if (arg[2].arg_type == A_SINGLE) { | |
596 | cmd->c_stab = arg[1].arg_ptr.arg_stab; | |
378cc40b LW |
597 | cmd->c_short = arg[2].arg_ptr.arg_str; |
598 | cmd->c_slen = 30000; | |
8d063cd8 LW |
599 | switch (arg->arg_type) { |
600 | case O_SLT: case O_SGT: | |
601 | sure |= CF_EQSURE; | |
602 | cmd->c_flags |= CF_FIRSTNEG; | |
603 | break; | |
604 | case O_SNE: | |
605 | cmd->c_flags |= CF_FIRSTNEG; | |
606 | /* FALL THROUGH */ | |
607 | case O_SEQ: | |
608 | sure |= CF_NESURE|CF_EQSURE; | |
609 | break; | |
610 | } | |
611 | if (context & 1) { /* only sure if thing is false */ | |
612 | if (cmd->c_flags & CF_FIRSTNEG) | |
613 | sure &= ~CF_NESURE; | |
614 | else | |
615 | sure &= ~CF_EQSURE; | |
616 | } | |
617 | else if (context & 2) { /* only sure if thing is true */ | |
618 | if (cmd->c_flags & CF_FIRSTNEG) | |
619 | sure &= ~CF_EQSURE; | |
620 | else | |
621 | sure &= ~CF_NESURE; | |
622 | } | |
623 | if (sure & (CF_EQSURE|CF_NESURE)) { | |
624 | opt = CFT_STROP; | |
625 | cmd->c_flags |= sure; | |
626 | } | |
627 | } | |
628 | } | |
629 | } | |
378cc40b LW |
630 | else if (arg->arg_type == O_EQ || arg->arg_type == O_NE || |
631 | arg->arg_type == O_LE || arg->arg_type == O_GE || | |
632 | arg->arg_type == O_LT || arg->arg_type == O_GT) { | |
633 | if (arg[1].arg_type == A_STAB || arg[1].arg_type == A_LVAL) { | |
634 | if (arg[2].arg_type == A_SINGLE) { | |
635 | cmd->c_stab = arg[1].arg_ptr.arg_stab; | |
636 | cmd->c_short = str_nmake(str_gnum(arg[2].arg_ptr.arg_str)); | |
637 | cmd->c_slen = arg->arg_type; | |
638 | sure |= CF_NESURE|CF_EQSURE; | |
639 | if (context & 1) { /* only sure if thing is false */ | |
640 | sure &= ~CF_EQSURE; | |
641 | } | |
642 | else if (context & 2) { /* only sure if thing is true */ | |
643 | sure &= ~CF_NESURE; | |
644 | } | |
645 | if (sure & (CF_EQSURE|CF_NESURE)) { | |
646 | opt = CFT_NUMOP; | |
647 | cmd->c_flags |= sure; | |
648 | } | |
649 | } | |
650 | } | |
651 | } | |
8d063cd8 LW |
652 | else if (arg->arg_type == O_ASSIGN && |
653 | (arg[1].arg_type == A_STAB || arg[1].arg_type == A_LVAL) && | |
654 | arg[1].arg_ptr.arg_stab == defstab && | |
655 | arg[2].arg_type == A_EXPR ) { | |
656 | arg2 = arg[2].arg_ptr.arg_arg; | |
657 | if (arg2->arg_type == O_ITEM && arg2[1].arg_type == A_READ) { | |
658 | opt = CFT_GETS; | |
659 | cmd->c_stab = arg2[1].arg_ptr.arg_stab; | |
660 | if (!(arg2[1].arg_ptr.arg_stab->stab_io->flags & IOF_ARGV)) { | |
661 | free_arg(arg2); | |
662 | free_arg(arg); | |
663 | cmd->c_expr = Nullarg; | |
664 | } | |
665 | } | |
666 | } | |
667 | else if (arg->arg_type == O_CHOP && | |
668 | (arg[1].arg_type == A_STAB || arg[1].arg_type == A_LVAL) ) { | |
669 | opt = CFT_CHOP; | |
670 | cmd->c_stab = arg[1].arg_ptr.arg_stab; | |
671 | free_arg(arg); | |
672 | cmd->c_expr = Nullarg; | |
673 | } | |
674 | if (context & 4) | |
675 | opt |= CF_FLIP; | |
676 | cmd->c_flags |= opt; | |
677 | ||
678 | if (cmd->c_flags & CF_FLIP) { | |
679 | if (fliporflop == 1) { | |
680 | arg = cmd->c_expr; /* get back to O_FLIP arg */ | |
681 | arg[3].arg_ptr.arg_cmd = (CMD*)safemalloc(sizeof(CMD)); | |
682 | bcopy((char *)cmd, (char *)arg[3].arg_ptr.arg_cmd, sizeof(CMD)); | |
683 | arg[4].arg_ptr.arg_cmd = (CMD*)safemalloc(sizeof(CMD)); | |
684 | bcopy((char *)cmd, (char *)arg[4].arg_ptr.arg_cmd, sizeof(CMD)); | |
378cc40b | 685 | opt_arg(arg[4].arg_ptr.arg_cmd,2,acmd); |
8d063cd8 LW |
686 | arg->arg_len = 2; /* this is a lie */ |
687 | } | |
688 | else { | |
689 | if ((opt & CF_OPTIMIZE) == CFT_EVAL) | |
690 | cmd->c_flags = (cmd->c_flags & ~CF_OPTIMIZE) | CFT_UNFLIP; | |
691 | } | |
692 | } | |
693 | } | |
694 | ||
695 | ARG * | |
696 | mod_match(type,left,pat) | |
697 | register ARG *left; | |
698 | register ARG *pat; | |
699 | { | |
700 | ||
701 | register SPAT *spat; | |
702 | register ARG *newarg; | |
703 | ||
704 | if ((pat->arg_type == O_MATCH || | |
705 | pat->arg_type == O_SUBST || | |
706 | pat->arg_type == O_TRANS || | |
707 | pat->arg_type == O_SPLIT | |
708 | ) && | |
709 | pat[1].arg_ptr.arg_stab == defstab ) { | |
710 | switch (pat->arg_type) { | |
711 | case O_MATCH: | |
712 | newarg = make_op(type == O_MATCH ? O_MATCH : O_NMATCH, | |
713 | pat->arg_len, | |
714 | left,Nullarg,Nullarg,0); | |
715 | break; | |
716 | case O_SUBST: | |
717 | newarg = l(make_op(type == O_MATCH ? O_SUBST : O_NSUBST, | |
718 | pat->arg_len, | |
719 | left,Nullarg,Nullarg,0)); | |
720 | break; | |
721 | case O_TRANS: | |
722 | newarg = l(make_op(type == O_MATCH ? O_TRANS : O_NTRANS, | |
723 | pat->arg_len, | |
724 | left,Nullarg,Nullarg,0)); | |
725 | break; | |
726 | case O_SPLIT: | |
727 | newarg = make_op(type == O_MATCH ? O_SPLIT : O_SPLIT, | |
728 | pat->arg_len, | |
729 | left,Nullarg,Nullarg,0); | |
730 | break; | |
731 | } | |
732 | if (pat->arg_len >= 2) { | |
733 | newarg[2].arg_type = pat[2].arg_type; | |
734 | newarg[2].arg_ptr = pat[2].arg_ptr; | |
735 | newarg[2].arg_flags = pat[2].arg_flags; | |
736 | if (pat->arg_len >= 3) { | |
737 | newarg[3].arg_type = pat[3].arg_type; | |
738 | newarg[3].arg_ptr = pat[3].arg_ptr; | |
739 | newarg[3].arg_flags = pat[3].arg_flags; | |
740 | } | |
741 | } | |
742 | safefree((char*)pat); | |
743 | } | |
744 | else { | |
745 | spat = (SPAT *) safemalloc(sizeof (SPAT)); | |
746 | bzero((char *)spat, sizeof(SPAT)); | |
747 | spat->spat_next = spat_root; /* link into spat list */ | |
748 | spat_root = spat; | |
8d063cd8 LW |
749 | |
750 | spat->spat_runtime = pat; | |
751 | newarg = make_op(type,2,left,Nullarg,Nullarg,0); | |
752 | newarg[2].arg_type = A_SPAT; | |
753 | newarg[2].arg_ptr.arg_spat = spat; | |
754 | newarg[2].arg_flags = AF_SPECIAL; | |
755 | } | |
756 | ||
757 | return newarg; | |
758 | } | |
759 | ||
760 | CMD * | |
761 | add_label(lbl,cmd) | |
762 | char *lbl; | |
763 | register CMD *cmd; | |
764 | { | |
765 | if (cmd) | |
766 | cmd->c_label = lbl; | |
767 | return cmd; | |
768 | } | |
769 | ||
770 | CMD * | |
771 | addcond(cmd, arg) | |
772 | register CMD *cmd; | |
773 | register ARG *arg; | |
774 | { | |
775 | cmd->c_expr = arg; | |
378cc40b | 776 | opt_arg(cmd,1,0); |
8d063cd8 LW |
777 | cmd->c_flags |= CF_COND; |
778 | return cmd; | |
779 | } | |
780 | ||
781 | CMD * | |
782 | addloop(cmd, arg) | |
783 | register CMD *cmd; | |
784 | register ARG *arg; | |
785 | { | |
786 | cmd->c_expr = arg; | |
378cc40b | 787 | opt_arg(cmd,1,0); |
8d063cd8 LW |
788 | cmd->c_flags |= CF_COND|CF_LOOP; |
789 | if (cmd->c_type == C_BLOCK) | |
790 | cmd->c_flags &= ~CF_COND; | |
791 | else { | |
792 | arg = cmd->ucmd.acmd.ac_expr; | |
793 | if (arg && arg->arg_type == O_ITEM && arg[1].arg_type == A_CMD) | |
794 | cmd->c_flags &= ~CF_COND; /* "do {} while" happens at least once */ | |
795 | if (arg && arg->arg_type == O_SUBR) | |
796 | cmd->c_flags &= ~CF_COND; /* likewise for "do subr() while" */ | |
797 | } | |
798 | return cmd; | |
799 | } | |
800 | ||
801 | CMD * | |
802 | invert(cmd) | |
803 | register CMD *cmd; | |
804 | { | |
805 | cmd->c_flags ^= CF_INVERT; | |
806 | return cmd; | |
807 | } | |
808 | ||
809 | yyerror(s) | |
810 | char *s; | |
811 | { | |
812 | char tmpbuf[128]; | |
813 | char *tname = tmpbuf; | |
814 | ||
815 | if (yychar > 256) { | |
816 | tname = tokename[yychar-256]; | |
817 | if (strEQ(tname,"word")) | |
818 | strcpy(tname,tokenbuf); | |
819 | else if (strEQ(tname,"register")) | |
820 | sprintf(tname,"$%s",tokenbuf); | |
821 | else if (strEQ(tname,"array_length")) | |
822 | sprintf(tname,"$#%s",tokenbuf); | |
823 | } | |
824 | else if (!yychar) | |
825 | strcpy(tname,"EOF"); | |
826 | else if (yychar < 32) | |
827 | sprintf(tname,"^%c",yychar+64); | |
828 | else if (yychar == 127) | |
829 | strcpy(tname,"^?"); | |
830 | else | |
831 | sprintf(tname,"%c",yychar); | |
a559c259 | 832 | sprintf(tokenbuf, "%s in file %s at line %d, next token \"%s\"\n", |
8d063cd8 | 833 | s,filename,line,tname); |
a559c259 LW |
834 | if (in_eval) |
835 | str_set(stabent("@",TRUE)->stab_val,tokenbuf); | |
836 | else | |
837 | fputs(tokenbuf,stderr); | |
8d063cd8 LW |
838 | } |
839 | ||
8d063cd8 LW |
840 | ARG * |
841 | make_op(type,newlen,arg1,arg2,arg3,dolist) | |
842 | int type; | |
843 | int newlen; | |
844 | ARG *arg1; | |
845 | ARG *arg2; | |
846 | ARG *arg3; | |
847 | int dolist; | |
848 | { | |
849 | register ARG *arg; | |
850 | register ARG *chld; | |
851 | register int doarg; | |
852 | ||
853 | arg = op_new(newlen); | |
854 | arg->arg_type = type; | |
855 | doarg = opargs[type]; | |
856 | if (chld = arg1) { | |
857 | if (!(doarg & 1)) | |
858 | arg[1].arg_flags |= AF_SPECIAL; | |
859 | if (doarg & 16) | |
860 | arg[1].arg_flags |= AF_NUMERIC; | |
861 | if (chld->arg_type == O_ITEM && | |
862 | (hoistable[chld[1].arg_type] || chld[1].arg_type == A_LVAL) ) { | |
863 | arg[1].arg_type = chld[1].arg_type; | |
864 | arg[1].arg_ptr = chld[1].arg_ptr; | |
865 | arg[1].arg_flags |= chld[1].arg_flags; | |
866 | free_arg(chld); | |
867 | } | |
868 | else { | |
869 | arg[1].arg_type = A_EXPR; | |
870 | arg[1].arg_ptr.arg_arg = chld; | |
871 | if (dolist & 1) { | |
872 | if (chld->arg_type == O_LIST) { | |
873 | if (newlen == 1) { /* we can hoist entire list */ | |
874 | chld->arg_type = type; | |
875 | free_arg(arg); | |
876 | arg = chld; | |
877 | } | |
878 | else { | |
879 | arg[1].arg_flags |= AF_SPECIAL; | |
880 | } | |
881 | } | |
378cc40b LW |
882 | else { |
883 | switch (chld->arg_type) { | |
884 | case O_ARRAY: | |
885 | if (chld->arg_len == 1) | |
886 | arg[1].arg_flags |= AF_SPECIAL; | |
887 | break; | |
888 | case O_ITEM: | |
889 | if (chld[1].arg_type == A_READ || | |
890 | chld[1].arg_type == A_INDREAD || | |
891 | chld[1].arg_type == A_GLOB) | |
892 | arg[1].arg_flags |= AF_SPECIAL; | |
893 | break; | |
894 | case O_SPLIT: | |
895 | case O_TMS: | |
896 | case O_EACH: | |
897 | case O_VALUES: | |
898 | case O_KEYS: | |
899 | case O_SORT: | |
900 | arg[1].arg_flags |= AF_SPECIAL; | |
901 | break; | |
902 | } | |
903 | } | |
8d063cd8 LW |
904 | } |
905 | } | |
906 | } | |
907 | if (chld = arg2) { | |
908 | if (!(doarg & 2)) | |
909 | arg[2].arg_flags |= AF_SPECIAL; | |
910 | if (doarg & 32) | |
911 | arg[2].arg_flags |= AF_NUMERIC; | |
912 | if (chld->arg_type == O_ITEM && | |
913 | (hoistable[chld[1].arg_type] || | |
914 | (type == O_ASSIGN && | |
378cc40b LW |
915 | ((chld[1].arg_type == A_READ && !(arg[1].arg_flags & AF_SPECIAL)) |
916 | || | |
917 | (chld[1].arg_type == A_INDREAD && !(arg[1].arg_flags & AF_SPECIAL)) | |
918 | || | |
919 | (chld[1].arg_type == A_GLOB && !(arg[1].arg_flags & AF_SPECIAL)) | |
920 | || | |
8d063cd8 LW |
921 | chld[1].arg_type == A_BACKTICK ) ) ) ) { |
922 | arg[2].arg_type = chld[1].arg_type; | |
923 | arg[2].arg_ptr = chld[1].arg_ptr; | |
924 | free_arg(chld); | |
925 | } | |
926 | else { | |
927 | arg[2].arg_type = A_EXPR; | |
928 | arg[2].arg_ptr.arg_arg = chld; | |
929 | if ((dolist & 2) && | |
930 | (chld->arg_type == O_LIST || | |
931 | (chld->arg_type == O_ARRAY && chld->arg_len == 1) )) | |
932 | arg[2].arg_flags |= AF_SPECIAL; | |
933 | } | |
934 | } | |
935 | if (chld = arg3) { | |
936 | if (!(doarg & 4)) | |
937 | arg[3].arg_flags |= AF_SPECIAL; | |
938 | if (doarg & 64) | |
939 | arg[3].arg_flags |= AF_NUMERIC; | |
940 | if (chld->arg_type == O_ITEM && hoistable[chld[1].arg_type]) { | |
941 | arg[3].arg_type = chld[1].arg_type; | |
942 | arg[3].arg_ptr = chld[1].arg_ptr; | |
943 | free_arg(chld); | |
944 | } | |
945 | else { | |
946 | arg[3].arg_type = A_EXPR; | |
947 | arg[3].arg_ptr.arg_arg = chld; | |
948 | if ((dolist & 4) && | |
949 | (chld->arg_type == O_LIST || | |
950 | (chld->arg_type == O_ARRAY && chld->arg_len == 1) )) | |
951 | arg[3].arg_flags |= AF_SPECIAL; | |
952 | } | |
953 | } | |
954 | #ifdef DEBUGGING | |
955 | if (debug & 16) { | |
956 | fprintf(stderr,"%lx <= make_op(%s",arg,opname[arg->arg_type]); | |
957 | if (arg1) | |
958 | fprintf(stderr,",%s=%lx", | |
959 | argname[arg[1].arg_type],arg[1].arg_ptr.arg_arg); | |
960 | if (arg2) | |
961 | fprintf(stderr,",%s=%lx", | |
962 | argname[arg[2].arg_type],arg[2].arg_ptr.arg_arg); | |
963 | if (arg3) | |
964 | fprintf(stderr,",%s=%lx", | |
965 | argname[arg[3].arg_type],arg[3].arg_ptr.arg_arg); | |
966 | fprintf(stderr,")\n"); | |
967 | } | |
968 | #endif | |
969 | evalstatic(arg); /* see if we can consolidate anything */ | |
970 | return arg; | |
971 | } | |
972 | ||
973 | /* turn 123 into 123 == $. */ | |
974 | ||
975 | ARG * | |
976 | flipflip(arg) | |
977 | register ARG *arg; | |
978 | { | |
979 | if (arg && arg->arg_type == O_ITEM && arg[1].arg_type == A_SINGLE) { | |
980 | arg = (ARG*)saferealloc((char*)arg,3*sizeof(ARG)); | |
981 | arg->arg_type = O_EQ; | |
982 | arg->arg_len = 2; | |
983 | arg[2].arg_type = A_STAB; | |
984 | arg[2].arg_flags = 0; | |
985 | arg[2].arg_ptr.arg_stab = stabent(".",TRUE); | |
986 | } | |
987 | return arg; | |
988 | } | |
989 | ||
990 | void | |
991 | evalstatic(arg) | |
992 | register ARG *arg; | |
993 | { | |
994 | register STR *str; | |
995 | register STR *s1; | |
996 | register STR *s2; | |
997 | double value; /* must not be register */ | |
998 | register char *tmps; | |
999 | int i; | |
378cc40b | 1000 | unsigned long tmplong; |
8d063cd8 LW |
1001 | double exp(), log(), sqrt(), modf(); |
1002 | char *crypt(); | |
1003 | ||
1004 | if (!arg || !arg->arg_len) | |
1005 | return; | |
1006 | ||
1007 | if (arg[1].arg_type == A_SINGLE && | |
1008 | (arg->arg_len == 1 || arg[2].arg_type == A_SINGLE) ) { | |
1009 | str = str_new(0); | |
1010 | s1 = arg[1].arg_ptr.arg_str; | |
1011 | if (arg->arg_len > 1) | |
1012 | s2 = arg[2].arg_ptr.arg_str; | |
1013 | else | |
1014 | s2 = Nullstr; | |
1015 | switch (arg->arg_type) { | |
1016 | default: | |
1017 | str_free(str); | |
1018 | str = Nullstr; /* can't be evaluated yet */ | |
1019 | break; | |
1020 | case O_CONCAT: | |
1021 | str_sset(str,s1); | |
1022 | str_scat(str,s2); | |
1023 | break; | |
1024 | case O_REPEAT: | |
1025 | i = (int)str_gnum(s2); | |
378cc40b | 1026 | while (i-- > 0) |
8d063cd8 LW |
1027 | str_scat(str,s1); |
1028 | break; | |
1029 | case O_MULTIPLY: | |
1030 | value = str_gnum(s1); | |
1031 | str_numset(str,value * str_gnum(s2)); | |
1032 | break; | |
1033 | case O_DIVIDE: | |
378cc40b LW |
1034 | value = str_gnum(s2); |
1035 | if (value == 0.0) | |
1036 | fatal("Illegal division by constant zero"); | |
1037 | str_numset(str,str_gnum(s1) / value); | |
8d063cd8 LW |
1038 | break; |
1039 | case O_MODULO: | |
378cc40b LW |
1040 | tmplong = (unsigned long)str_gnum(s2); |
1041 | if (tmplong == 0L) | |
1042 | fatal("Illegal modulus of constant zero"); | |
1043 | str_numset(str,(double)(((unsigned long)str_gnum(s1)) % tmplong)); | |
8d063cd8 LW |
1044 | break; |
1045 | case O_ADD: | |
1046 | value = str_gnum(s1); | |
1047 | str_numset(str,value + str_gnum(s2)); | |
1048 | break; | |
1049 | case O_SUBTRACT: | |
1050 | value = str_gnum(s1); | |
1051 | str_numset(str,value - str_gnum(s2)); | |
1052 | break; | |
1053 | case O_LEFT_SHIFT: | |
1054 | value = str_gnum(s1); | |
378cc40b LW |
1055 | i = (int)str_gnum(s2); |
1056 | str_numset(str,(double)(((unsigned long)value) << i)); | |
8d063cd8 LW |
1057 | break; |
1058 | case O_RIGHT_SHIFT: | |
1059 | value = str_gnum(s1); | |
378cc40b LW |
1060 | i = (int)str_gnum(s2); |
1061 | str_numset(str,(double)(((unsigned long)value) >> i)); | |
8d063cd8 LW |
1062 | break; |
1063 | case O_LT: | |
1064 | value = str_gnum(s1); | |
1065 | str_numset(str,(double)(value < str_gnum(s2))); | |
1066 | break; | |
1067 | case O_GT: | |
1068 | value = str_gnum(s1); | |
1069 | str_numset(str,(double)(value > str_gnum(s2))); | |
1070 | break; | |
1071 | case O_LE: | |
1072 | value = str_gnum(s1); | |
1073 | str_numset(str,(double)(value <= str_gnum(s2))); | |
1074 | break; | |
1075 | case O_GE: | |
1076 | value = str_gnum(s1); | |
1077 | str_numset(str,(double)(value >= str_gnum(s2))); | |
1078 | break; | |
1079 | case O_EQ: | |
1080 | value = str_gnum(s1); | |
1081 | str_numset(str,(double)(value == str_gnum(s2))); | |
1082 | break; | |
1083 | case O_NE: | |
1084 | value = str_gnum(s1); | |
1085 | str_numset(str,(double)(value != str_gnum(s2))); | |
1086 | break; | |
1087 | case O_BIT_AND: | |
1088 | value = str_gnum(s1); | |
378cc40b LW |
1089 | str_numset(str,(double)(((unsigned long)value) & |
1090 | ((unsigned long)str_gnum(s2)))); | |
8d063cd8 LW |
1091 | break; |
1092 | case O_XOR: | |
1093 | value = str_gnum(s1); | |
378cc40b LW |
1094 | str_numset(str,(double)(((unsigned long)value) ^ |
1095 | ((unsigned long)str_gnum(s2)))); | |
8d063cd8 LW |
1096 | break; |
1097 | case O_BIT_OR: | |
1098 | value = str_gnum(s1); | |
378cc40b LW |
1099 | str_numset(str,(double)(((unsigned long)value) | |
1100 | ((unsigned long)str_gnum(s2)))); | |
8d063cd8 LW |
1101 | break; |
1102 | case O_AND: | |
1103 | if (str_true(s1)) | |
1104 | str = str_make(str_get(s2)); | |
1105 | else | |
1106 | str = str_make(str_get(s1)); | |
1107 | break; | |
1108 | case O_OR: | |
1109 | if (str_true(s1)) | |
1110 | str = str_make(str_get(s1)); | |
1111 | else | |
1112 | str = str_make(str_get(s2)); | |
1113 | break; | |
1114 | case O_COND_EXPR: | |
1115 | if (arg[3].arg_type != A_SINGLE) { | |
1116 | str_free(str); | |
1117 | str = Nullstr; | |
1118 | } | |
1119 | else { | |
1120 | str = str_make(str_get(str_true(s1) ? s2 : arg[3].arg_ptr.arg_str)); | |
1121 | str_free(arg[3].arg_ptr.arg_str); | |
1122 | } | |
1123 | break; | |
1124 | case O_NEGATE: | |
1125 | str_numset(str,(double)(-str_gnum(s1))); | |
1126 | break; | |
1127 | case O_NOT: | |
1128 | str_numset(str,(double)(!str_true(s1))); | |
1129 | break; | |
1130 | case O_COMPLEMENT: | |
1131 | str_numset(str,(double)(~(long)str_gnum(s1))); | |
1132 | break; | |
1133 | case O_LENGTH: | |
1134 | str_numset(str, (double)str_len(s1)); | |
1135 | break; | |
1136 | case O_SUBSTR: | |
a559c259 | 1137 | if (arg[3].arg_type != A_SINGLE || stabent("[",allstabs)) { |
8d063cd8 LW |
1138 | str_free(str); /* making the fallacious assumption */ |
1139 | str = Nullstr; /* that any $[ occurs before substr()*/ | |
1140 | } | |
1141 | else { | |
1142 | char *beg; | |
1143 | int len = (int)str_gnum(s2); | |
1144 | int tmp; | |
1145 | ||
1146 | for (beg = str_get(s1); *beg && len > 0; beg++,len--) ; | |
1147 | len = (int)str_gnum(arg[3].arg_ptr.arg_str); | |
1148 | str_free(arg[3].arg_ptr.arg_str); | |
1149 | if (len > (tmp = strlen(beg))) | |
1150 | len = tmp; | |
1151 | str_nset(str,beg,len); | |
1152 | } | |
1153 | break; | |
1154 | case O_SLT: | |
1155 | tmps = str_get(s1); | |
1156 | str_numset(str,(double)(strLT(tmps,str_get(s2)))); | |
1157 | break; | |
1158 | case O_SGT: | |
1159 | tmps = str_get(s1); | |
1160 | str_numset(str,(double)(strGT(tmps,str_get(s2)))); | |
1161 | break; | |
1162 | case O_SLE: | |
1163 | tmps = str_get(s1); | |
1164 | str_numset(str,(double)(strLE(tmps,str_get(s2)))); | |
1165 | break; | |
1166 | case O_SGE: | |
1167 | tmps = str_get(s1); | |
1168 | str_numset(str,(double)(strGE(tmps,str_get(s2)))); | |
1169 | break; | |
1170 | case O_SEQ: | |
1171 | tmps = str_get(s1); | |
1172 | str_numset(str,(double)(strEQ(tmps,str_get(s2)))); | |
1173 | break; | |
1174 | case O_SNE: | |
1175 | tmps = str_get(s1); | |
1176 | str_numset(str,(double)(strNE(tmps,str_get(s2)))); | |
1177 | break; | |
1178 | case O_CRYPT: | |
378cc40b | 1179 | #ifdef CRYPT |
8d063cd8 LW |
1180 | tmps = str_get(s1); |
1181 | str_set(str,crypt(tmps,str_get(s2))); | |
378cc40b LW |
1182 | #else |
1183 | fatal( | |
1184 | "The crypt() function is unimplemented due to excessive paranoia."); | |
1185 | #endif | |
8d063cd8 LW |
1186 | break; |
1187 | case O_EXP: | |
1188 | str_numset(str,exp(str_gnum(s1))); | |
1189 | break; | |
1190 | case O_LOG: | |
1191 | str_numset(str,log(str_gnum(s1))); | |
1192 | break; | |
1193 | case O_SQRT: | |
1194 | str_numset(str,sqrt(str_gnum(s1))); | |
1195 | break; | |
1196 | case O_INT: | |
378cc40b LW |
1197 | value = str_gnum(s1); |
1198 | if (value >= 0.0) | |
1199 | modf(value,&value); | |
1200 | else { | |
1201 | modf(-value,&value); | |
1202 | value = -value; | |
1203 | } | |
8d063cd8 LW |
1204 | str_numset(str,value); |
1205 | break; | |
1206 | case O_ORD: | |
1207 | str_numset(str,(double)(*str_get(s1))); | |
1208 | break; | |
1209 | } | |
1210 | if (str) { | |
1211 | arg->arg_type = O_ITEM; /* note arg1 type is already SINGLE */ | |
1212 | str_free(s1); | |
1213 | str_free(s2); | |
1214 | arg[1].arg_ptr.arg_str = str; | |
1215 | } | |
1216 | } | |
1217 | } | |
1218 | ||
1219 | ARG * | |
1220 | l(arg) | |
1221 | register ARG *arg; | |
1222 | { | |
1223 | register int i; | |
1224 | register ARG *arg1; | |
378cc40b | 1225 | ARG *tmparg; |
8d063cd8 LW |
1226 | |
1227 | arg->arg_flags |= AF_COMMON; /* XXX should cross-match */ | |
378cc40b LW |
1228 | /* this does unnecessary copying */ |
1229 | ||
1230 | if (arg[1].arg_type == A_ARYLEN) { | |
1231 | arg[1].arg_type = A_LARYLEN; | |
1232 | return arg; | |
1233 | } | |
8d063cd8 LW |
1234 | |
1235 | /* see if it's an array reference */ | |
1236 | ||
1237 | if (arg[1].arg_type == A_EXPR) { | |
1238 | arg1 = arg[1].arg_ptr.arg_arg; | |
1239 | ||
1240 | if (arg1->arg_type == O_LIST && arg->arg_type != O_ITEM) { | |
1241 | /* assign to list */ | |
1242 | arg[1].arg_flags |= AF_SPECIAL; | |
378cc40b | 1243 | dehoist(arg,2); |
8d063cd8 LW |
1244 | arg[2].arg_flags |= AF_SPECIAL; |
1245 | for (i = arg1->arg_len; i >= 1; i--) { | |
1246 | switch (arg1[i].arg_type) { | |
1247 | case A_STAB: case A_LVAL: | |
1248 | arg1[i].arg_type = A_LVAL; | |
1249 | break; | |
1250 | case A_EXPR: case A_LEXPR: | |
1251 | arg1[i].arg_type = A_LEXPR; | |
1252 | if (arg1[i].arg_ptr.arg_arg->arg_type == O_ARRAY) | |
1253 | arg1[i].arg_ptr.arg_arg->arg_type = O_LARRAY; | |
1254 | else if (arg1[i].arg_ptr.arg_arg->arg_type == O_HASH) | |
1255 | arg1[i].arg_ptr.arg_arg->arg_type = O_LHASH; | |
1256 | if (arg1[i].arg_ptr.arg_arg->arg_type == O_LARRAY) | |
1257 | break; | |
1258 | if (arg1[i].arg_ptr.arg_arg->arg_type == O_LHASH) | |
1259 | break; | |
1260 | /* FALL THROUGH */ | |
1261 | default: | |
1262 | sprintf(tokenbuf, | |
1263 | "Illegal item (%s) as lvalue",argname[arg1[i].arg_type]); | |
1264 | yyerror(tokenbuf); | |
1265 | } | |
1266 | } | |
1267 | } | |
1268 | else if (arg1->arg_type == O_ARRAY) { | |
1269 | if (arg1->arg_len == 1 && arg->arg_type != O_ITEM) { | |
1270 | /* assign to array */ | |
1271 | arg[1].arg_flags |= AF_SPECIAL; | |
378cc40b | 1272 | dehoist(arg,2); |
8d063cd8 LW |
1273 | arg[2].arg_flags |= AF_SPECIAL; |
1274 | } | |
1275 | else | |
1276 | arg1->arg_type = O_LARRAY; /* assign to array elem */ | |
1277 | } | |
1278 | else if (arg1->arg_type == O_HASH) | |
1279 | arg1->arg_type = O_LHASH; | |
378cc40b | 1280 | else if (arg1->arg_type != O_ASSIGN) { |
8d063cd8 LW |
1281 | sprintf(tokenbuf, |
1282 | "Illegal expression (%s) as lvalue",opname[arg1->arg_type]); | |
1283 | yyerror(tokenbuf); | |
1284 | } | |
1285 | arg[1].arg_type = A_LEXPR; | |
1286 | #ifdef DEBUGGING | |
1287 | if (debug & 16) | |
1288 | fprintf(stderr,"lval LEXPR\n"); | |
1289 | #endif | |
1290 | return arg; | |
1291 | } | |
1292 | ||
1293 | /* not an array reference, should be a register name */ | |
1294 | ||
1295 | if (arg[1].arg_type != A_STAB && arg[1].arg_type != A_LVAL) { | |
1296 | sprintf(tokenbuf, | |
1297 | "Illegal item (%s) as lvalue",argname[arg[1].arg_type]); | |
1298 | yyerror(tokenbuf); | |
1299 | } | |
1300 | arg[1].arg_type = A_LVAL; | |
1301 | #ifdef DEBUGGING | |
1302 | if (debug & 16) | |
1303 | fprintf(stderr,"lval LVAL\n"); | |
1304 | #endif | |
1305 | return arg; | |
1306 | } | |
1307 | ||
378cc40b LW |
1308 | dehoist(arg,i) |
1309 | ARG *arg; | |
1310 | { | |
1311 | ARG *tmparg; | |
1312 | ||
1313 | if (arg[i].arg_type != A_EXPR) { /* dehoist */ | |
1314 | tmparg = make_op(O_ITEM,1,Nullarg,Nullarg,Nullarg,0); | |
1315 | tmparg[1] = arg[i]; | |
1316 | arg[i].arg_ptr.arg_arg = tmparg; | |
1317 | arg[i].arg_type = A_EXPR; | |
1318 | } | |
1319 | } | |
1320 | ||
8d063cd8 LW |
1321 | ARG * |
1322 | addflags(i,flags,arg) | |
1323 | register ARG *arg; | |
1324 | { | |
1325 | arg[i].arg_flags |= flags; | |
1326 | return arg; | |
1327 | } | |
1328 | ||
1329 | ARG * | |
1330 | hide_ary(arg) | |
1331 | ARG *arg; | |
1332 | { | |
1333 | if (arg->arg_type == O_ARRAY) | |
1334 | return make_op(O_ITEM,1,arg,Nullarg,Nullarg,0); | |
1335 | return arg; | |
1336 | } | |
1337 | ||
1338 | ARG * | |
1339 | make_list(arg) | |
1340 | register ARG *arg; | |
1341 | { | |
1342 | register int i; | |
1343 | register ARG *node; | |
1344 | register ARG *nxtnode; | |
1345 | register int j; | |
1346 | STR *tmpstr; | |
1347 | ||
1348 | if (!arg) { | |
1349 | arg = op_new(0); | |
1350 | arg->arg_type = O_LIST; | |
1351 | } | |
1352 | if (arg->arg_type != O_COMMA) { | |
1353 | arg->arg_flags |= AF_LISTISH; /* see listish() below */ | |
1354 | return arg; | |
1355 | } | |
1356 | for (i = 2, node = arg; ; i++) { | |
1357 | if (node->arg_len < 2) | |
1358 | break; | |
1359 | if (node[2].arg_type != A_EXPR) | |
1360 | break; | |
1361 | node = node[2].arg_ptr.arg_arg; | |
1362 | if (node->arg_type != O_COMMA) | |
1363 | break; | |
1364 | } | |
1365 | if (i > 2) { | |
1366 | node = arg; | |
1367 | arg = op_new(i); | |
1368 | tmpstr = arg->arg_ptr.arg_str; | |
1369 | *arg = *node; /* copy everything except the STR */ | |
1370 | arg->arg_ptr.arg_str = tmpstr; | |
1371 | for (j = 1; ; ) { | |
378cc40b LW |
1372 | arg[j] = node[1]; |
1373 | ++j; /* Bug in Xenix compiler */ | |
8d063cd8 LW |
1374 | if (j >= i) { |
1375 | arg[j] = node[2]; | |
1376 | free_arg(node); | |
1377 | break; | |
1378 | } | |
1379 | nxtnode = node[2].arg_ptr.arg_arg; | |
1380 | free_arg(node); | |
1381 | node = nxtnode; | |
1382 | } | |
1383 | } | |
1384 | arg->arg_type = O_LIST; | |
1385 | arg->arg_len = i; | |
1386 | return arg; | |
1387 | } | |
1388 | ||
1389 | /* turn a single item into a list */ | |
1390 | ||
1391 | ARG * | |
1392 | listish(arg) | |
1393 | ARG *arg; | |
1394 | { | |
378cc40b | 1395 | if (arg->arg_flags & AF_LISTISH) { |
8d063cd8 | 1396 | arg = make_op(O_LIST,1,arg,Nullarg,Nullarg,0); |
378cc40b LW |
1397 | arg[1].arg_flags &= ~AF_SPECIAL; |
1398 | } | |
1399 | return arg; | |
1400 | } | |
1401 | ||
1402 | /* mark list of local variables */ | |
1403 | ||
1404 | ARG * | |
1405 | localize(arg) | |
1406 | ARG *arg; | |
1407 | { | |
1408 | arg->arg_flags |= AF_LOCAL; | |
8d063cd8 LW |
1409 | return arg; |
1410 | } | |
1411 | ||
1412 | ARG * | |
378cc40b | 1413 | stab2arg(atype,stab) |
8d063cd8 LW |
1414 | int atype; |
1415 | register STAB *stab; | |
1416 | { | |
1417 | register ARG *arg; | |
1418 | ||
1419 | arg = op_new(1); | |
1420 | arg->arg_type = O_ITEM; | |
1421 | arg[1].arg_type = atype; | |
1422 | arg[1].arg_ptr.arg_stab = stab; | |
1423 | return arg; | |
1424 | } | |
1425 | ||
1426 | ARG * | |
1427 | cval_to_arg(cval) | |
1428 | register char *cval; | |
1429 | { | |
1430 | register ARG *arg; | |
1431 | ||
1432 | arg = op_new(1); | |
1433 | arg->arg_type = O_ITEM; | |
1434 | arg[1].arg_type = A_SINGLE; | |
1435 | arg[1].arg_ptr.arg_str = str_make(cval); | |
1436 | safefree(cval); | |
1437 | return arg; | |
1438 | } | |
1439 | ||
1440 | ARG * | |
1441 | op_new(numargs) | |
1442 | int numargs; | |
1443 | { | |
1444 | register ARG *arg; | |
1445 | ||
1446 | arg = (ARG*)safemalloc((numargs + 1) * sizeof (ARG)); | |
1447 | bzero((char *)arg, (numargs + 1) * sizeof (ARG)); | |
1448 | arg->arg_ptr.arg_str = str_new(0); | |
1449 | arg->arg_len = numargs; | |
1450 | return arg; | |
1451 | } | |
1452 | ||
1453 | void | |
1454 | free_arg(arg) | |
1455 | ARG *arg; | |
1456 | { | |
1457 | str_free(arg->arg_ptr.arg_str); | |
1458 | safefree((char*)arg); | |
1459 | } | |
1460 | ||
1461 | ARG * | |
1462 | make_match(type,expr,spat) | |
1463 | int type; | |
1464 | ARG *expr; | |
1465 | SPAT *spat; | |
1466 | { | |
1467 | register ARG *arg; | |
1468 | ||
1469 | arg = make_op(type,2,expr,Nullarg,Nullarg,0); | |
1470 | ||
1471 | arg[2].arg_type = A_SPAT; | |
1472 | arg[2].arg_ptr.arg_spat = spat; | |
1473 | #ifdef DEBUGGING | |
1474 | if (debug & 16) | |
378cc40b | 1475 | fprintf(stderr,"make_match SPAT=%lx\n",(long)spat); |
8d063cd8 LW |
1476 | #endif |
1477 | ||
1478 | if (type == O_SUBST || type == O_NSUBST) { | |
1479 | if (arg[1].arg_type != A_STAB) | |
1480 | yyerror("Illegal lvalue"); | |
1481 | arg[1].arg_type = A_LVAL; | |
1482 | } | |
1483 | return arg; | |
1484 | } | |
1485 | ||
1486 | ARG * | |
1487 | cmd_to_arg(cmd) | |
1488 | CMD *cmd; | |
1489 | { | |
1490 | register ARG *arg; | |
1491 | ||
1492 | arg = op_new(1); | |
1493 | arg->arg_type = O_ITEM; | |
1494 | arg[1].arg_type = A_CMD; | |
1495 | arg[1].arg_ptr.arg_cmd = cmd; | |
1496 | return arg; | |
1497 | } | |
1498 | ||
1499 | CMD * | |
1500 | wopt(cmd) | |
1501 | register CMD *cmd; | |
1502 | { | |
1503 | register CMD *tail; | |
1504 | register ARG *arg = cmd->c_expr; | |
378cc40b | 1505 | STAB *asgnstab; |
8d063cd8 LW |
1506 | |
1507 | /* hoist "while (<channel>)" up into command block */ | |
1508 | ||
1509 | if (arg && arg->arg_type == O_ITEM && arg[1].arg_type == A_READ) { | |
1510 | cmd->c_flags &= ~CF_OPTIMIZE; /* clear optimization type */ | |
1511 | cmd->c_flags |= CFT_GETS; /* and set it to do the input */ | |
1512 | cmd->c_stab = arg[1].arg_ptr.arg_stab; | |
1513 | if (arg[1].arg_ptr.arg_stab->stab_io->flags & IOF_ARGV) { | |
1514 | cmd->c_expr = l(make_op(O_ASSIGN, 2, /* fake up "$_ =" */ | |
378cc40b | 1515 | stab2arg(A_LVAL,defstab), arg, Nullarg,1 )); |
8d063cd8 LW |
1516 | } |
1517 | else { | |
1518 | free_arg(arg); | |
1519 | cmd->c_expr = Nullarg; | |
1520 | } | |
1521 | } | |
378cc40b LW |
1522 | else if (arg && arg->arg_type == O_ITEM && arg[1].arg_type == A_INDREAD) { |
1523 | cmd->c_flags &= ~CF_OPTIMIZE; /* clear optimization type */ | |
1524 | cmd->c_flags |= CFT_INDGETS; /* and set it to do the input */ | |
1525 | cmd->c_stab = arg[1].arg_ptr.arg_stab; | |
1526 | free_arg(arg); | |
1527 | cmd->c_expr = Nullarg; | |
1528 | } | |
1529 | else if (arg && arg->arg_type == O_ITEM && arg[1].arg_type == A_GLOB) { | |
1530 | if ((cmd->c_flags & CF_OPTIMIZE) == CFT_ARRAY) | |
1531 | asgnstab = cmd->c_stab; | |
1532 | else | |
1533 | asgnstab = defstab; | |
1534 | cmd->c_expr = l(make_op(O_ASSIGN, 2, /* fake up "$foo =" */ | |
1535 | stab2arg(A_LVAL,asgnstab), arg, Nullarg,1 )); | |
1536 | cmd->c_flags &= ~CF_OPTIMIZE; /* clear optimization type */ | |
1537 | } | |
8d063cd8 LW |
1538 | |
1539 | /* First find the end of the true list */ | |
1540 | ||
1541 | if (cmd->ucmd.ccmd.cc_true == Nullcmd) | |
1542 | return cmd; | |
1543 | for (tail = cmd->ucmd.ccmd.cc_true; tail->c_next; tail = tail->c_next) ; | |
1544 | ||
1545 | /* if there's a continue block, link it to true block and find end */ | |
1546 | ||
1547 | if (cmd->ucmd.ccmd.cc_alt != Nullcmd) { | |
1548 | tail->c_next = cmd->ucmd.ccmd.cc_alt; | |
1549 | for ( ; tail->c_next; tail = tail->c_next) ; | |
1550 | } | |
1551 | ||
1552 | /* Here's the real trick: link the end of the list back to the beginning, | |
1553 | * inserting a "last" block to break out of the loop. This saves one or | |
1554 | * two procedure calls every time through the loop, because of how cmd_exec | |
1555 | * does tail recursion. | |
1556 | */ | |
1557 | ||
1558 | tail->c_next = (CMD *) safemalloc(sizeof (CMD)); | |
1559 | tail = tail->c_next; | |
1560 | if (!cmd->ucmd.ccmd.cc_alt) | |
1561 | cmd->ucmd.ccmd.cc_alt = tail; /* every loop has a continue now */ | |
1562 | ||
1563 | bcopy((char *)cmd, (char *)tail, sizeof(CMD)); | |
1564 | tail->c_type = C_EXPR; | |
1565 | tail->c_flags ^= CF_INVERT; /* turn into "last unless" */ | |
1566 | tail->c_next = tail->ucmd.ccmd.cc_true; /* loop directly back to top */ | |
1567 | tail->ucmd.acmd.ac_expr = make_op(O_LAST,0,Nullarg,Nullarg,Nullarg,0); | |
1568 | tail->ucmd.acmd.ac_stab = Nullstab; | |
1569 | return cmd; | |
1570 | } | |
1571 | ||
378cc40b LW |
1572 | CMD * |
1573 | over(eachstab,cmd) | |
1574 | STAB *eachstab; | |
1575 | register CMD *cmd; | |
8d063cd8 | 1576 | { |
378cc40b LW |
1577 | /* hoist "for $foo (@bar)" up into command block */ |
1578 | ||
1579 | cmd->c_flags &= ~CF_OPTIMIZE; /* clear optimization type */ | |
1580 | cmd->c_flags |= CFT_ARRAY; /* and set it to do the iteration */ | |
1581 | cmd->c_stab = eachstab; | |
1582 | ||
1583 | return cmd; | |
1584 | } | |
1585 | ||
1586 | static int gensym = 0; | |
1587 | ||
1588 | STAB * | |
1589 | genstab() | |
1590 | { | |
1591 | sprintf(tokenbuf,"_GEN_%d",gensym++); | |
1592 | return stabent(tokenbuf,TRUE); | |
8d063cd8 | 1593 | } |
a559c259 | 1594 | |
378cc40b LW |
1595 | /* this routine is in perly.c by virtue of being sort of an alternate main() */ |
1596 | ||
a559c259 | 1597 | STR * |
378cc40b | 1598 | do_eval(str,optype) |
a559c259 | 1599 | STR *str; |
378cc40b | 1600 | int optype; |
a559c259 LW |
1601 | { |
1602 | int retval; | |
1603 | CMD *myroot; | |
378cc40b LW |
1604 | ARRAY *ar; |
1605 | int i; | |
1606 | char *oldfile = filename; | |
1607 | line_t oldline = line; | |
1608 | int oldtmps_base = tmps_base; | |
1609 | int oldsave = savestack->ary_fill; | |
a559c259 | 1610 | |
378cc40b | 1611 | tmps_base = tmps_max; |
a559c259 | 1612 | str_set(stabent("@",TRUE)->stab_val,""); |
378cc40b LW |
1613 | if (optype != O_DOFILE) { /* normal eval */ |
1614 | filename = "(eval)"; | |
1615 | line = 1; | |
1616 | str_sset(linestr,str); | |
1617 | } | |
1618 | else { | |
1619 | filename = savestr(str_get(str)); /* can't free this easily */ | |
1620 | str_set(linestr,""); | |
1621 | rsfp = fopen(filename,"r"); | |
1622 | ar = incstab->stab_array; | |
1623 | if (!rsfp && *filename != '/') { | |
1624 | for (i = 0; i <= ar->ary_fill; i++) { | |
1625 | sprintf(tokenbuf,"%s/%s",str_get(afetch(ar,i)),filename); | |
1626 | rsfp = fopen(tokenbuf,"r"); | |
1627 | if (rsfp) { | |
1628 | free(filename); | |
1629 | filename = savestr(tokenbuf); | |
1630 | break; | |
1631 | } | |
1632 | } | |
1633 | } | |
1634 | if (!rsfp) { | |
1635 | filename = oldfile; | |
1636 | tmps_base = oldtmps_base; | |
1637 | return &str_no; | |
1638 | } | |
1639 | line = 0; | |
1640 | } | |
1641 | in_eval++; | |
a559c259 LW |
1642 | bufptr = str_get(linestr); |
1643 | if (setjmp(eval_env)) | |
1644 | retval = 1; | |
1645 | else | |
1646 | retval = yyparse(); | |
1647 | myroot = eval_root; /* in case cmd_exec does another eval! */ | |
1648 | if (retval) | |
1649 | str = &str_no; | |
1650 | else { | |
378cc40b LW |
1651 | str = str_static(cmd_exec(eval_root)); |
1652 | /* if we don't save str, free zaps it */ | |
a559c259 LW |
1653 | cmd_free(myroot); /* can't free on error, for some reason */ |
1654 | } | |
1655 | in_eval--; | |
378cc40b LW |
1656 | filename = oldfile; |
1657 | line = oldline; | |
1658 | tmps_base = oldtmps_base; | |
1659 | if (savestack->ary_fill > oldsave) /* let them use local() */ | |
1660 | restorelist(oldsave); | |
a559c259 LW |
1661 | return str; |
1662 | } | |
1663 | ||
1664 | cmd_free(cmd) | |
1665 | register CMD *cmd; | |
1666 | { | |
1667 | register CMD *tofree; | |
1668 | register CMD *head = cmd; | |
1669 | ||
1670 | while (cmd) { | |
378cc40b LW |
1671 | if (cmd->c_type != C_WHILE) { /* WHILE block is duplicated */ |
1672 | if (cmd->c_label) | |
1673 | safefree(cmd->c_label); | |
1674 | if (cmd->c_short) | |
1675 | str_free(cmd->c_short); | |
1676 | if (cmd->c_spat) | |
1677 | spat_free(cmd->c_spat); | |
1678 | if (cmd->c_expr) | |
1679 | arg_free(cmd->c_expr); | |
1680 | } | |
a559c259 LW |
1681 | switch (cmd->c_type) { |
1682 | case C_WHILE: | |
1683 | case C_BLOCK: | |
1684 | case C_IF: | |
1685 | if (cmd->ucmd.ccmd.cc_true) | |
1686 | cmd_free(cmd->ucmd.ccmd.cc_true); | |
1687 | if (cmd->c_type == C_IF && cmd->ucmd.ccmd.cc_alt) | |
378cc40b | 1688 | cmd_free(cmd->ucmd.ccmd.cc_alt); |
a559c259 LW |
1689 | break; |
1690 | case C_EXPR: | |
a559c259 LW |
1691 | if (cmd->ucmd.acmd.ac_expr) |
1692 | arg_free(cmd->ucmd.acmd.ac_expr); | |
1693 | break; | |
1694 | } | |
1695 | tofree = cmd; | |
1696 | cmd = cmd->c_next; | |
1697 | safefree((char*)tofree); | |
1698 | if (cmd && cmd == head) /* reached end of while loop */ | |
1699 | break; | |
1700 | } | |
1701 | } | |
1702 | ||
1703 | arg_free(arg) | |
1704 | register ARG *arg; | |
1705 | { | |
1706 | register int i; | |
1707 | ||
1708 | for (i = 1; i <= arg->arg_len; i++) { | |
1709 | switch (arg[i].arg_type) { | |
1710 | case A_NULL: | |
1711 | break; | |
1712 | case A_LEXPR: | |
1713 | case A_EXPR: | |
1714 | arg_free(arg[i].arg_ptr.arg_arg); | |
1715 | break; | |
1716 | case A_CMD: | |
1717 | cmd_free(arg[i].arg_ptr.arg_cmd); | |
1718 | break; | |
378cc40b | 1719 | case A_WORD: |
a559c259 LW |
1720 | case A_STAB: |
1721 | case A_LVAL: | |
1722 | case A_READ: | |
378cc40b | 1723 | case A_GLOB: |
a559c259 LW |
1724 | case A_ARYLEN: |
1725 | break; | |
1726 | case A_SINGLE: | |
1727 | case A_DOUBLE: | |
1728 | case A_BACKTICK: | |
1729 | str_free(arg[i].arg_ptr.arg_str); | |
1730 | break; | |
1731 | case A_SPAT: | |
1732 | spat_free(arg[i].arg_ptr.arg_spat); | |
1733 | break; | |
1734 | case A_NUMBER: | |
1735 | break; | |
1736 | } | |
1737 | } | |
1738 | free_arg(arg); | |
1739 | } | |
1740 | ||
1741 | spat_free(spat) | |
1742 | register SPAT *spat; | |
1743 | { | |
1744 | register SPAT *sp; | |
1745 | ||
1746 | if (spat->spat_runtime) | |
1747 | arg_free(spat->spat_runtime); | |
1748 | if (spat->spat_repl) { | |
1749 | arg_free(spat->spat_repl); | |
1750 | } | |
378cc40b LW |
1751 | if (spat->spat_short) { |
1752 | str_free(spat->spat_short); | |
1753 | } | |
1754 | if (spat->spat_regexp) { | |
1755 | regfree(spat->spat_regexp); | |
1756 | } | |
a559c259 LW |
1757 | |
1758 | /* now unlink from spat list */ | |
1759 | if (spat_root == spat) | |
1760 | spat_root = spat->spat_next; | |
1761 | else { | |
1762 | for (sp = spat_root; sp->spat_next != spat; sp = sp->spat_next) ; | |
1763 | sp->spat_next = spat->spat_next; | |
1764 | } | |
1765 | ||
1766 | safefree((char*)spat); | |
1767 | } | |
378cc40b LW |
1768 | |
1769 | /* Recursively descend a command sequence and push the address of any string | |
1770 | * that needs saving on recursion onto the tosave array. | |
1771 | */ | |
1772 | ||
1773 | static int | |
1774 | cmd_tosave(cmd) | |
1775 | register CMD *cmd; | |
1776 | { | |
1777 | register CMD *head = cmd; | |
1778 | ||
1779 | while (cmd) { | |
1780 | if (cmd->c_spat) | |
1781 | spat_tosave(cmd->c_spat); | |
1782 | if (cmd->c_expr) | |
1783 | arg_tosave(cmd->c_expr); | |
1784 | switch (cmd->c_type) { | |
1785 | case C_WHILE: | |
1786 | case C_BLOCK: | |
1787 | case C_IF: | |
1788 | if (cmd->ucmd.ccmd.cc_true) | |
1789 | cmd_tosave(cmd->ucmd.ccmd.cc_true); | |
1790 | if (cmd->c_type == C_IF && cmd->ucmd.ccmd.cc_alt) | |
1791 | cmd_tosave(cmd->ucmd.ccmd.cc_alt); | |
1792 | break; | |
1793 | case C_EXPR: | |
1794 | if (cmd->ucmd.acmd.ac_expr) | |
1795 | arg_tosave(cmd->ucmd.acmd.ac_expr); | |
1796 | break; | |
1797 | } | |
1798 | cmd = cmd->c_next; | |
1799 | if (cmd && cmd == head) /* reached end of while loop */ | |
1800 | break; | |
1801 | } | |
1802 | } | |
1803 | ||
1804 | static int | |
1805 | arg_tosave(arg) | |
1806 | register ARG *arg; | |
1807 | { | |
1808 | register int i; | |
1809 | int saving = FALSE; | |
1810 | ||
1811 | for (i = 1; i <= arg->arg_len; i++) { | |
1812 | switch (arg[i].arg_type) { | |
1813 | case A_NULL: | |
1814 | break; | |
1815 | case A_LEXPR: | |
1816 | case A_EXPR: | |
1817 | saving |= arg_tosave(arg[i].arg_ptr.arg_arg); | |
1818 | break; | |
1819 | case A_CMD: | |
1820 | cmd_tosave(arg[i].arg_ptr.arg_cmd); | |
1821 | saving = TRUE; /* assume hanky panky */ | |
1822 | break; | |
1823 | case A_WORD: | |
1824 | case A_STAB: | |
1825 | case A_LVAL: | |
1826 | case A_READ: | |
1827 | case A_GLOB: | |
1828 | case A_ARYLEN: | |
1829 | case A_SINGLE: | |
1830 | case A_DOUBLE: | |
1831 | case A_BACKTICK: | |
1832 | break; | |
1833 | case A_SPAT: | |
1834 | saving |= spat_tosave(arg[i].arg_ptr.arg_spat); | |
1835 | break; | |
1836 | case A_NUMBER: | |
1837 | break; | |
1838 | } | |
1839 | } | |
1840 | switch (arg->arg_type) { | |
1841 | case O_EVAL: | |
1842 | case O_SUBR: | |
1843 | saving = TRUE; | |
1844 | } | |
1845 | if (saving) | |
1846 | apush(tosave,arg->arg_ptr.arg_str); | |
1847 | return saving; | |
1848 | } | |
1849 | ||
1850 | static int | |
1851 | spat_tosave(spat) | |
1852 | register SPAT *spat; | |
1853 | { | |
1854 | int saving = FALSE; | |
1855 | ||
1856 | if (spat->spat_runtime) | |
1857 | saving |= arg_tosave(spat->spat_runtime); | |
1858 | if (spat->spat_repl) { | |
1859 | saving |= arg_tosave(spat->spat_repl); | |
1860 | } | |
1861 | ||
1862 | return saving; | |
1863 | } |