1 /* $Header: cmd.c,v 3.0.1.3 89/11/17 15:04:36 lwall Locked $
3 * Copyright (c) 1989, Larry Wall
5 * You may distribute under the terms of the GNU General Public License
6 * as specified in the README file that comes with the perl 3.0 kit.
9 * Revision 3.0.1.3 89/11/17 15:04:36 lwall
10 * patch5: nested foreach on same array didn't work
12 * Revision 3.0.1.2 89/11/11 04:08:56 lwall
13 * patch2: non-BSD machines required two ^D's for <>
14 * patch2: grow_dlevel() not inside #ifdef DEBUGGING
16 * Revision 3.0.1.1 89/10/26 23:04:21 lwall
17 * patch1: heuristically disabled optimization could cause core dump
19 * Revision 3.0 89/10/18 15:09:02 lwall
35 /* This is the main command loop. We try to spend as much time in this loop
36 * as possible, so lots of optimizations do their activities in here. This
37 * means things get a little sloppy.
41 cmd_exec(cmd,gimme,sp)
42 #ifdef cray /* nobody else has complained yet */
57 register STR *retstr = &str_undef;
59 register int cmdflags;
61 register char *go_to = goto_targ;
62 register int newsp = -2;
63 register STR **st = stack->ary_array;
76 tainted = 0; /* Each statement is presumed innocent */
79 if (gimme == G_ARRAY && newsp > -2)
86 cmdflags = cmd->c_flags; /* hopefully load register */
88 if (cmd->c_label && strEQ(go_to,cmd->c_label))
89 goto_targ = go_to = Nullch; /* here at last */
91 switch (cmd->c_type) {
94 oldsave = savestack->ary_fill;
100 if (cmd->ucmd.ccmd.cc_true) {
103 debname[dlevel] = 't';
104 debdelim[dlevel] = '_';
105 if (++dlevel >= dlmax)
109 newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme,sp);
110 st = stack->ary_array; /* possibly reallocated */
116 if (savestack->ary_fill > oldsave)
117 restorelist(oldsave);
121 cmd = cmd->ucmd.ccmd.cc_alt;
122 goto tail_recursion_entry;
125 oldsave = savestack->ary_fill;
131 if (cmd->ucmd.ccmd.cc_true) {
134 debname[dlevel] = 'e';
135 debdelim[dlevel] = '_';
136 if (++dlevel >= dlmax)
140 newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme,sp);
141 st = stack->ary_array; /* possibly reallocated */
147 if (savestack->ary_fill > oldsave)
148 restorelist(oldsave);
155 if (!(cmdflags & CF_ONCE)) {
157 if (++loop_ptr >= loop_max) {
159 Renew(loop_stack, loop_max, struct loop);
161 loop_stack[loop_ptr].loop_label = cmd->c_label;
162 loop_stack[loop_ptr].loop_sp = sp;
165 deb("(Pushing label #%d %s)\n",
166 loop_ptr, cmd->c_label ? cmd->c_label : "");
170 switch (setjmp(loop_stack[loop_ptr].loop_env)) {
171 case O_LAST: /* not done unless go_to found */
173 st = stack->ary_array; /* possibly reallocated */
179 newsp = sp + lastsize;
186 if (savestack->ary_fill > oldsave)
187 restorelist(oldsave);
189 case O_NEXT: /* not done unless go_to found */
192 case O_REDO: /* not done unless go_to found */
197 oldsave = savestack->ary_fill;
201 if (cmd->ucmd.ccmd.cc_true) {
204 debname[dlevel] = 't';
205 debdelim[dlevel] = '_';
206 if (++dlevel >= dlmax)
210 newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme,sp);
211 st = stack->ary_array; /* possibly reallocated */
221 if (cmd->ucmd.ccmd.cc_alt) {
224 debname[dlevel] = 'a';
225 debdelim[dlevel] = '_';
226 if (++dlevel >= dlmax)
230 newsp = cmd_exec(cmd->ucmd.ccmd.cc_alt,gimme,sp);
231 st = stack->ary_array; /* possibly reallocated */
240 if (cmd && cmd->c_head == cmd)
241 /* reached end of while loop */
242 return sp; /* targ isn't in this block */
243 if (cmdflags & CF_ONCE) {
246 tmps = loop_stack[loop_ptr].loop_label;
247 deb("(Popping label #%d %s)\n",loop_ptr,
253 goto tail_recursion_entry;
259 /* Set line number so run-time errors can be located */
266 deb("%s (%lx) r%lx t%lx a%lx n%lx cs%lx\n",
267 cmdname[cmd->c_type],cmd,cmd->c_expr,
268 cmd->ucmd.ccmd.cc_true,cmd->ucmd.ccmd.cc_alt,cmd->c_next,
271 debname[dlevel] = cmdname[cmd->c_type][0];
272 debdelim[dlevel] = '!';
273 if (++dlevel >= dlmax)
278 /* Here is some common optimization */
280 if (cmdflags & CF_COND) {
281 switch (cmdflags & CF_OPTIMIZE) {
284 retstr = cmd->c_short;
287 if (cmdflags & CF_NESURE)
291 retstr = cmd->c_short;
294 if (cmdflags & CF_EQSURE)
299 retstr = STAB_STR(cmd->c_stab);
301 match = str_true(retstr); /* => retstr = retstr, c2 should fix */
302 if (cmdflags & (match ? CF_EQSURE : CF_NESURE))
306 case CFT_ANCHOR: /* /^pat/ optimization */
308 if (*cmd->c_short->str_ptr && !(cmdflags & CF_EQSURE))
309 goto scanner; /* just unanchor it */
311 break; /* must evaluate */
314 case CFT_STROP: /* string op optimization */
315 retstr = STAB_STR(cmd->c_stab);
318 if (*cmd->c_short->str_ptr == *str_get(retstr) &&
319 bcmp(cmd->c_short->str_ptr, str_get(retstr),
320 cmd->c_slen) == 0 ) {
321 if (cmdflags & CF_EQSURE) {
322 if (sawampersand && (cmdflags & CF_OPTIMIZE) != CFT_STROP) {
325 str_nset(stab_val(leftstab),"",0);
327 str_sset(stab_val(amperstab),cmd->c_short);
329 str_nset(stab_val(rightstab),
330 retstr->str_ptr + cmd->c_slen,
331 retstr->str_cur - cmd->c_slen);
333 match = !(cmdflags & CF_FIRSTNEG);
338 else if (cmdflags & CF_NESURE) {
339 match = cmdflags & CF_FIRSTNEG;
345 char *zap1, *zap2, zap1c, zap2c;
348 zap1 = cmd->c_short->str_ptr;
349 zap2 = str_get(retstr);
352 zaplen = cmd->c_slen;
353 if ((zap1c == zap2c) && (bcmp(zap1, zap2, zaplen) == 0)) {
354 if (cmdflags & CF_EQSURE) {
356 (cmdflags & CF_OPTIMIZE) != CFT_STROP) {
359 str_nset(stab_val(leftstab),"",0);
361 str_sset(stab_val(amperstab),cmd->c_short);
363 str_nset(stab_val(rightstab),
364 retstr->str_ptr + cmd->c_slen,
365 retstr->str_cur - cmd->c_slen);
367 match = !(cmdflags & CF_FIRSTNEG);
372 else if (cmdflags & CF_NESURE) {
373 match = cmdflags & CF_FIRSTNEG;
379 break; /* must evaluate */
381 case CFT_SCAN: /* non-anchored search */
383 retstr = STAB_STR(cmd->c_stab);
385 if (retstr->str_pok & SP_STUDIED)
386 if (screamfirst[cmd->c_short->str_rare] >= 0)
387 tmps = screaminstr(retstr, cmd->c_short);
391 tmps = str_get(retstr); /* make sure it's pok */
393 tmps = fbminstr((unsigned char*)tmps,
394 (unsigned char*)tmps + retstr->str_cur, cmd->c_short);
398 if (cmdflags & CF_EQSURE) {
399 ++cmd->c_short->str_u.str_useful;
403 str_nset(stab_val(leftstab),retstr->str_ptr,
404 tmps - retstr->str_ptr);
406 str_sset(stab_val(amperstab),cmd->c_short);
408 str_nset(stab_val(rightstab),
409 tmps + cmd->c_short->str_cur,
410 retstr->str_cur - (tmps - retstr->str_ptr) -
411 cmd->c_short->str_cur);
413 match = !(cmdflags & CF_FIRSTNEG);
421 if (cmdflags & CF_NESURE) {
422 ++cmd->c_short->str_u.str_useful;
423 match = cmdflags & CF_FIRSTNEG;
428 if (--cmd->c_short->str_u.str_useful < 0) {
429 cmdflags &= ~CF_OPTIMIZE;
430 cmdflags |= CFT_EVAL; /* never try this optimization again */
431 cmd->c_flags = cmdflags;
433 break; /* must evaluate */
435 case CFT_NUMOP: /* numeric op optimization */
436 retstr = STAB_STR(cmd->c_stab);
438 switch (cmd->c_slen) {
441 if ((!retstr->str_nok && !looks_like_number(retstr)))
442 warn("Possible use of == on string value");
444 match = (str_gnum(retstr) == cmd->c_short->str_u.str_nval);
447 match = (str_gnum(retstr) != cmd->c_short->str_u.str_nval);
450 match = (str_gnum(retstr) < cmd->c_short->str_u.str_nval);
453 match = (str_gnum(retstr) <= cmd->c_short->str_u.str_nval);
456 match = (str_gnum(retstr) > cmd->c_short->str_u.str_nval);
459 match = (str_gnum(retstr) >= cmd->c_short->str_u.str_nval);
463 if (cmdflags & CF_EQSURE) {
468 else if (cmdflags & CF_NESURE) {
472 break; /* must evaluate */
474 case CFT_INDGETS: /* while (<$foo>) */
475 last_in_stab = stabent(str_get(STAB_STR(cmd->c_stab)),TRUE);
476 if (!stab_io(last_in_stab))
477 stab_io(last_in_stab) = stio_new();
479 case CFT_GETS: /* really a while (<file>) */
480 last_in_stab = cmd->c_stab;
482 fp = stab_io(last_in_stab)->ifp;
483 retstr = stab_val(defstab);
486 if (fp && str_gets(retstr, fp, 0)) {
487 if (*retstr->str_ptr == '0' && retstr->str_cur == 1)
491 stab_io(last_in_stab)->lines++;
493 else if (stab_io(last_in_stab)->flags & IOF_ARGV) {
495 goto doeval; /* first time through */
496 fp = nextargv(last_in_stab);
499 (void)do_close(last_in_stab,FALSE);
500 stab_io(last_in_stab)->flags |= IOF_START;
512 while (tmps_max > tmps_base) /* clean up after last eval */
513 str_free(tmps_list[tmps_max--]);
514 newsp = eval(cmd->c_expr,gimme && (cmdflags & CF_TERM),sp);
515 st = stack->ary_array; /* possibly reallocated */
517 match = str_true(retstr);
518 if (cmd->c_expr->arg_type == O_FLIP) /* undid itself? */
519 cmdflags = copyopt(cmd,cmd->c_expr[3].arg_ptr.arg_cmd);
522 retstr = stab_val(cmd->c_stab);
524 match = (retstr->str_cur != 0);
525 tmps = str_get(retstr);
526 tmps += retstr->str_cur - match;
527 str_nset(&str_chop,tmps,match);
530 retstr->str_cur = tmps - retstr->str_ptr;
534 match = cmd->c_short->str_u.str_useful; /* just to get register */
536 if (match < 0) { /* first time through here? */
537 ar = stab_array(cmd->c_expr[1].arg_ptr.arg_stab);
538 aryoptsave = savestack->ary_fill;
539 savesptr(&stab_val(cmd->c_stab));
540 savelong(&cmd->c_short->str_u.str_useful);
543 ar = stab_xarray(cmd->c_expr[1].arg_ptr.arg_stab);
545 if (match >= ar->ary_fill) { /* we're in LAST, probably */
547 cmd->c_short->str_u.str_useful = -1; /* actually redundant */
552 retstr = stab_val(cmd->c_stab) = ar->ary_array[match];
553 cmd->c_short->str_u.str_useful = match;
560 /* we have tried to make this normal case as abnormal as possible */
563 if (gimme == G_ARRAY) {
564 lastretstr = Nullstr;
566 lastsize = newsp - sp;
570 while (tmps_max > tmps_base) /* clean up after last eval */
571 str_free(tmps_list[tmps_max--]);
572 newsp = eval(cmd->c_expr,gimme && (cmdflags & CF_TERM),sp);
573 st = stack->ary_array; /* possibly reallocated */
576 match = str_true(retstr);
581 /* if flipflop was true, flop it */
584 if (match && cmdflags & CF_FLIP) {
585 while (tmps_max > tmps_base) /* clean up after last eval */
586 str_free(tmps_list[tmps_max--]);
587 if (cmd->c_expr->arg_type == O_FLOP) { /* currently toggled? */
588 newsp = eval(cmd->c_expr,G_SCALAR,sp);/*let eval undo it*/
589 cmdflags = copyopt(cmd,cmd->c_expr[3].arg_ptr.arg_cmd);
592 newsp = eval(cmd->c_expr,G_SCALAR,sp);/* let eval do it */
593 if (cmd->c_expr->arg_type == O_FLOP) /* still toggled? */
594 cmdflags = copyopt(cmd,cmd->c_expr[4].arg_ptr.arg_cmd);
597 else if (cmdflags & CF_FLIP) {
598 if (cmd->c_expr->arg_type == O_FLOP) { /* currently toggled? */
599 match = TRUE; /* force on */
603 /* at this point, match says whether our expression was true */
606 if (cmdflags & CF_INVERT)
612 tainted = 0; /* modifier doesn't affect regular expression */
615 /* now to do the actual command, if any */
617 switch (cmd->c_type) {
619 fatal("panic: cmd_exec");
620 case C_EXPR: /* evaluated for side effects */
621 if (cmd->ucmd.acmd.ac_expr) { /* more to do? */
622 if (gimme == G_ARRAY) {
623 lastretstr = Nullstr;
625 lastsize = newsp - sp;
629 while (tmps_max > tmps_base) /* clean up after last eval */
630 str_free(tmps_list[tmps_max--]);
631 newsp = eval(cmd->ucmd.acmd.ac_expr,gimme && (cmdflags&CF_TERM),sp);
632 st = stack->ary_array; /* possibly reallocated */
637 match = (int)str_gnum(STAB_STR(cmd->c_stab));
640 match = *(str_get(STAB_STR(cmd->c_stab))) & 255;
642 match -= cmd->ucmd.scmd.sc_offset;
645 else if (match > cmd->ucmd.scmd.sc_max)
647 cmd = cmd->ucmd.scmd.sc_next[match];
648 goto tail_recursion_entry;
650 cmd = cmd->ucmd.ccmd.cc_alt;
651 goto tail_recursion_entry;
653 fatal("panic: ELSIF");
656 oldsave = savestack->ary_fill;
662 if (cmd->ucmd.ccmd.cc_true) {
665 debname[dlevel] = 't';
666 debdelim[dlevel] = '_';
667 if (++dlevel >= dlmax)
671 newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme,sp);
672 st = stack->ary_array; /* possibly reallocated */
676 if (savestack->ary_fill > oldsave)
677 restorelist(oldsave);
681 cmd = cmd->ucmd.ccmd.cc_alt;
682 goto tail_recursion_entry;
685 oldsave = savestack->ary_fill;
691 if (cmd->ucmd.ccmd.cc_true) {
694 debname[dlevel] = 'e';
695 debdelim[dlevel] = '_';
696 if (++dlevel >= dlmax)
700 newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme,sp);
701 st = stack->ary_array; /* possibly reallocated */
705 if (savestack->ary_fill > oldsave)
706 restorelist(oldsave);
713 if (!(cmdflags & CF_ONCE)) { /* first time through here? */
715 if (++loop_ptr >= loop_max) {
717 Renew(loop_stack, loop_max, struct loop);
719 loop_stack[loop_ptr].loop_label = cmd->c_label;
720 loop_stack[loop_ptr].loop_sp = sp;
723 deb("(Pushing label #%d %s)\n",
724 loop_ptr, cmd->c_label ? cmd->c_label : "");
728 switch (setjmp(loop_stack[loop_ptr].loop_env)) {
730 /* retstr = lastretstr; */
731 st = stack->ary_array; /* possibly reallocated */
737 newsp = sp + lastsize;
741 if (savestack->ary_fill > oldsave)
742 restorelist(oldsave);
753 oldsave = savestack->ary_fill;
758 if (cmd->ucmd.ccmd.cc_true) {
761 debname[dlevel] = 't';
762 debdelim[dlevel] = '_';
763 if (++dlevel >= dlmax)
767 newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme,sp);
768 st = stack->ary_array; /* possibly reallocated */
771 /* actually, this spot is rarely reached anymore since the above
772 * cmd_exec() returns through longjmp(). Hooray for structure.
778 if (cmd->ucmd.ccmd.cc_alt) {
781 debname[dlevel] = 'a';
782 debdelim[dlevel] = '_';
783 if (++dlevel >= dlmax)
787 newsp = cmd_exec(cmd->ucmd.ccmd.cc_alt,gimme,sp);
788 st = stack->ary_array; /* possibly reallocated */
793 if (savestack->ary_fill > oldsave)
794 restorelist(oldsave);
796 dlevel = olddlevel - 1;
798 if (cmd->c_type != C_BLOCK)
799 goto until_loop; /* go back and evaluate conditional again */
801 if (cmdflags & CF_LOOP) {
802 cmdflags |= CF_COND; /* now test the condition */
809 if (cmdflags & CF_ONCE) {
812 tmps = loop_stack[loop_ptr].loop_label;
813 deb("(Popping label #%d %s)\n",loop_ptr, tmps ? tmps : "");
817 if ((cmdflags & CF_OPTIMIZE) == CFT_ARRAY)
818 restorelist(aryoptsave);
821 goto tail_recursion_entry;
827 deb(pat,a1,a2,a3,a4,a5,a6,a7,a8)
832 fprintf(stderr,"%-4ld",(long)line);
833 for (i=0; i<dlevel; i++)
834 fprintf(stderr,"%c%c ",debname[i],debdelim[i]);
835 fprintf(stderr,pat,a1,a2,a3,a4,a5,a6,a7,a8);
847 fprintf(stderr,"%-4ld",(long)line);
848 for (i=0; i<dlevel; i++)
849 fprintf(stderr,"%c%c ",debname[i],debdelim[i]);
851 pat = va_arg(args, char *);
852 (void) vfprintf(stderr,pat,args);
862 cmd->c_flags &= CF_ONCE|CF_COND|CF_LOOP;
863 cmd->c_flags |= which->c_flags;
864 cmd->c_short = which->c_short;
865 cmd->c_slen = which->c_slen;
866 cmd->c_stab = which->c_stab;
877 str->str_state = SS_SARY;
878 str->str_u.str_stab = stab;
880 Safefree(str->str_ptr);
883 str->str_ptr = (char*)stab_array(stab);
884 (void)apush(savestack,str); /* save array ptr */
885 stab_xarray(stab) = Null(ARRAY*);
886 return stab_xarray(aadd(stab));
896 str->str_state = SS_SHASH;
897 str->str_u.str_stab = stab;
899 Safefree(str->str_ptr);
902 str->str_ptr = (char*)stab_hash(stab);
903 (void)apush(savestack,str); /* save hash ptr */
904 stab_xhash(stab) = Null(HASH*);
905 return stab_xhash(hadd(stab));
914 (void)apush(savestack,item); /* remember the pointer */
917 (void)apush(savestack,str); /* remember the value */
927 str->str_state = SS_SINT;
928 str->str_u.str_useful = (long)*intp; /* remember value */
930 Safefree(str->str_ptr);
933 str->str_ptr = (char*)intp; /* remember pointer */
934 (void)apush(savestack,str);
944 str->str_state = SS_SLONG;
945 str->str_u.str_useful = *longp; /* remember value */
947 Safefree(str->str_ptr);
950 str->str_ptr = (char*)longp; /* remember pointer */
951 (void)apush(savestack,str);
961 str->str_state = SS_SSTRP;
962 str->str_magic = *sptr; /* remember value */
964 Safefree(str->str_ptr);
967 str->str_ptr = (char*)sptr; /* remember pointer */
968 (void)apush(savestack,str);
978 str->str_state = SS_SNSTAB;
979 str->str_magic = (STR*)stab; /* remember which stab to free */
980 (void)apush(savestack,str);
990 str->str_state = SS_SHPTR;
991 str->str_u.str_hash = *hptr; /* remember value */
993 Safefree(str->str_ptr);
996 str->str_ptr = (char*)hptr; /* remember pointer */
997 (void)apush(savestack,str);
1001 savelist(sarg,maxsarg)
1002 register STR **sarg;
1008 for (i = 1; i <= maxsarg; i++) {
1009 (void)apush(savestack,sarg[i]); /* remember the pointer */
1010 str = Str_new(18,0);
1011 str_sset(str,sarg[i]);
1012 (void)apush(savestack,str); /* remember the value */
1021 register STR *value;
1022 register STAB *stab;
1025 fatal("panic: corrupt saved stack index");
1026 while (savestack->ary_fill > base) {
1027 value = apop(savestack);
1028 switch (value->str_state) {
1029 case SS_NORM: /* normal string */
1031 str = apop(savestack);
1032 str_replace(str,value);
1035 case SS_SARY: /* array reference */
1036 stab = value->str_u.str_stab;
1037 afree(stab_xarray(stab));
1038 stab_xarray(stab) = (ARRAY*)value->str_ptr;
1039 value->str_ptr = Nullch;
1042 case SS_SHASH: /* hash reference */
1043 stab = value->str_u.str_stab;
1044 (void)hfree(stab_xhash(stab));
1045 stab_xhash(stab) = (HASH*)value->str_ptr;
1046 value->str_ptr = Nullch;
1049 case SS_SINT: /* int reference */
1050 *((int*)value->str_ptr) = (int)value->str_u.str_useful;
1051 value->str_ptr = Nullch;
1054 case SS_SLONG: /* long reference */
1055 *((long*)value->str_ptr) = value->str_u.str_useful;
1056 value->str_ptr = Nullch;
1059 case SS_SSTRP: /* STR* reference */
1060 *((STR**)value->str_ptr) = value->str_magic;
1061 value->str_magic = Nullstr;
1062 value->str_ptr = Nullch;
1065 case SS_SHPTR: /* HASH* reference */
1066 *((HASH**)value->str_ptr) = value->str_u.str_hash;
1067 value->str_ptr = Nullch;
1071 stab = (STAB*)value->str_magic;
1072 value->str_magic = Nullstr;
1073 (void)stab_clear(stab);
1077 fatal("panic: restorelist inconsistency");
1087 Renew(debname, dlmax, char);
1088 Renew(debdelim, dlmax, char);