This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
perl 2.0 (no announcement message available)
[perl5.git] / perly.c
CommitLineData
378cc40b 1char 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
13extern char *tokename[];
14extern int yychar;
15
16static int cmd_tosave();
17static int arg_tosave();
18static int spat_tosave();
8d063cd8
LW
19
20main(argc,argv,env)
21register int argc;
22register char **argv;
23register 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
294magicalize(list)
295register 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
309ARG *
310make_split(stab,arg)
311register STAB *stab;
312register 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
338SUBR *
339make_sub(name,cmd)
340char *name;
341CMD *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
369CMD *
370block_head(tail)
371register CMD *tail;
372{
373 if (tail == Nullcmd) {
374 return tail;
375 }
376 return tail->c_head;
377}
378
379CMD *
380append_line(head,tail)
381register CMD *head;
382register 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
406CMD *
407make_acmd(type,stab,cond,arg)
408int type;
409STAB *stab;
410ARG *cond;
411ARG *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
432CMD *
433make_ccmd(type,arg,cblock)
434int type;
435register ARG *arg;
436struct 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
456void
378cc40b 457opt_arg(cmd,fliporflop,acmd)
8d063cd8
LW
458register CMD *cmd;
459int fliporflop;
378cc40b 460int 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
695ARG *
696mod_match(type,left,pat)
697register ARG *left;
698register 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
760CMD *
761add_label(lbl,cmd)
762char *lbl;
763register CMD *cmd;
764{
765 if (cmd)
766 cmd->c_label = lbl;
767 return cmd;
768}
769
770CMD *
771addcond(cmd, arg)
772register CMD *cmd;
773register 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
781CMD *
782addloop(cmd, arg)
783register CMD *cmd;
784register 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
801CMD *
802invert(cmd)
803register CMD *cmd;
804{
805 cmd->c_flags ^= CF_INVERT;
806 return cmd;
807}
808
809yyerror(s)
810char *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
840ARG *
841make_op(type,newlen,arg1,arg2,arg3,dolist)
842int type;
843int newlen;
844ARG *arg1;
845ARG *arg2;
846ARG *arg3;
847int 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
975ARG *
976flipflip(arg)
977register 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
990void
991evalstatic(arg)
992register 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
1219ARG *
1220l(arg)
1221register 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
1308dehoist(arg,i)
1309ARG *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
1321ARG *
1322addflags(i,flags,arg)
1323register ARG *arg;
1324{
1325 arg[i].arg_flags |= flags;
1326 return arg;
1327}
1328
1329ARG *
1330hide_ary(arg)
1331ARG *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
1338ARG *
1339make_list(arg)
1340register 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
1391ARG *
1392listish(arg)
1393ARG *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
1404ARG *
1405localize(arg)
1406ARG *arg;
1407{
1408 arg->arg_flags |= AF_LOCAL;
8d063cd8
LW
1409 return arg;
1410}
1411
1412ARG *
378cc40b 1413stab2arg(atype,stab)
8d063cd8
LW
1414int atype;
1415register 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
1426ARG *
1427cval_to_arg(cval)
1428register 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
1440ARG *
1441op_new(numargs)
1442int 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
1453void
1454free_arg(arg)
1455ARG *arg;
1456{
1457 str_free(arg->arg_ptr.arg_str);
1458 safefree((char*)arg);
1459}
1460
1461ARG *
1462make_match(type,expr,spat)
1463int type;
1464ARG *expr;
1465SPAT *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
1486ARG *
1487cmd_to_arg(cmd)
1488CMD *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
1499CMD *
1500wopt(cmd)
1501register 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
1572CMD *
1573over(eachstab,cmd)
1574STAB *eachstab;
1575register 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
1586static int gensym = 0;
1587
1588STAB *
1589genstab()
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 1597STR *
378cc40b 1598do_eval(str,optype)
a559c259 1599STR *str;
378cc40b 1600int 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
1664cmd_free(cmd)
1665register 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
1703arg_free(arg)
1704register 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
1741spat_free(spat)
1742register 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
1773static int
1774cmd_tosave(cmd)
1775register 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
1804static int
1805arg_tosave(arg)
1806register 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
1850static int
1851spat_tosave(spat)
1852register 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}