1 /* $Header: cmd.c,v 3.0.1.10 90/10/20 02:01:56 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.10 90/10/20 02:01:56 lwall
10 * patch37: cray has weird restrictions on setjmp locations
12 * Revision 3.0.1.9 90/10/15 15:32:39 lwall
13 * patch29: non-existent array values no longer cause core dumps
14 * patch29: scripts now run at almost full speed under the debugger
15 * patch29: @ENV = () now works
16 * patch29: added caller
18 * Revision 3.0.1.8 90/08/09 02:28:49 lwall
19 * patch19: did preliminary work toward debugging packages and evals
20 * patch19: conditionals now always supply a scalar context to expression
21 * patch19: switch optimizer was confused by negative fractional values
23 * Revision 3.0.1.7 90/03/27 15:32:37 lwall
24 * patch16: non-terminal blocks should never have arrays requested of them
26 * Revision 3.0.1.6 90/03/12 16:21:09 lwall
27 * patch13: fixed some backwards VOLATILE declarations
28 * patch13: while (s/x//) {} still caused some anomolies
29 * patch13: greater-than test of numeric switch structures did less-than action
31 * Revision 3.0.1.5 90/02/28 16:38:31 lwall
32 * patch9: volatilized some more variables for super-optimizing compilers
33 * patch9: nested foreach loops didn't reset inner loop on next to outer loop
34 * patch9: returned values were read from obsolete stack
35 * patch9: added sanity check on longjmp() return value
36 * patch9: substitutions that almost always succeed can corrupt label stack
37 * patch9: subs which return by both mechanisms can clobber local return data
39 * Revision 3.0.1.4 89/12/21 19:17:41 lwall
40 * patch7: arranged for certain registers to be restored after longjmp()
41 * patch7: made nested or recursive foreach work right
43 * Revision 3.0.1.3 89/11/17 15:04:36 lwall
44 * patch5: nested foreach on same array didn't work
46 * Revision 3.0.1.2 89/11/11 04:08:56 lwall
47 * patch2: non-BSD machines required two ^D's for <>
48 * patch2: grow_dlevel() not inside #ifdef DEBUGGING
50 * Revision 3.0.1.1 89/10/26 23:04:21 lwall
51 * patch1: heuristically disabled optimization could cause core dump
53 * Revision 3.0 89/10/18 15:09:02 lwall
69 /* do longjmps() clobber register variables? */
71 #if defined(cray) || defined(__STDC__)
75 /* This is the main command loop. We try to spend as much time in this loop
76 * as possible, so lots of optimizations do their activities in here. This
77 * means things get a little sloppy.
81 cmd_exec(cmdparm,gimme,sp)
82 CMD *VOLATILE cmdparm;
86 register CMD *cmd = cmdparm;
87 SPAT *VOLATILE oldspat;
88 VOLATILE int firstsave = savestack->ary_fill;
90 VOLATILE int aryoptsave;
92 VOLATILE int olddlevel;
93 VOLATILE int entdlevel;
95 register STR *retstr = &str_undef;
97 register int cmdflags;
99 register char *go_to = goto_targ;
100 register int newsp = -2;
101 register STR **st = stack->ary_array;
109 tail_recursion_entry:
114 tainted = 0; /* Each statement is presumed innocent */
116 if (cmd == Nullcmd) {
117 if (gimme == G_ARRAY && newsp > -2)
124 cmdflags = cmd->c_flags; /* hopefully load register */
126 if (cmd->c_label && strEQ(go_to,cmd->c_label))
127 goto_targ = go_to = Nullch; /* here at last */
129 switch (cmd->c_type) {
132 oldsave = savestack->ary_fill;
138 if (cmd->ucmd.ccmd.cc_true) {
141 debname[dlevel] = 't';
142 debdelim[dlevel] = '_';
143 if (++dlevel >= dlmax)
147 newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme && (cmdflags & CF_TERM),sp);
148 st = stack->ary_array; /* possibly reallocated */
154 if (savestack->ary_fill > oldsave)
155 restorelist(oldsave);
159 cmd = cmd->ucmd.ccmd.cc_alt;
160 goto tail_recursion_entry;
163 oldsave = savestack->ary_fill;
169 if (cmd->ucmd.ccmd.cc_true) {
172 debname[dlevel] = 'e';
173 debdelim[dlevel] = '_';
174 if (++dlevel >= dlmax)
178 newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme && (cmdflags & CF_TERM),sp);
179 st = stack->ary_array; /* possibly reallocated */
185 if (savestack->ary_fill > oldsave)
186 restorelist(oldsave);
193 if (!(cmdflags & CF_ONCE)) {
195 if (++loop_ptr >= loop_max) {
197 Renew(loop_stack, loop_max, struct loop);
199 loop_stack[loop_ptr].loop_label = cmd->c_label;
200 loop_stack[loop_ptr].loop_sp = sp;
203 deb("(Pushing label #%d %s)\n",
204 loop_ptr, cmd->c_label ? cmd->c_label : "");
211 match = setjmp(loop_stack[loop_ptr].loop_env);
213 st = stack->ary_array; /* possibly reallocated */
216 cmdflags = cmd->c_flags|CF_ONCE;
218 if (savestack->ary_fill > oldsave)
219 restorelist(oldsave);
222 fatal("longjmp returned bad value (%d)",match);
223 case O_LAST: /* not done unless go_to found */
230 newsp = sp + lastsize;
238 case O_NEXT: /* not done unless go_to found */
245 case O_REDO: /* not done unless go_to found */
255 oldsave = savestack->ary_fill;
259 if (cmd->ucmd.ccmd.cc_true) {
262 debname[dlevel] = 't';
263 debdelim[dlevel] = '_';
264 if (++dlevel >= dlmax)
268 newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme && (cmdflags & CF_TERM),sp);
269 st = stack->ary_array; /* possibly reallocated */
279 if (cmd->ucmd.ccmd.cc_alt) {
282 debname[dlevel] = 'a';
283 debdelim[dlevel] = '_';
284 if (++dlevel >= dlmax)
288 newsp = cmd_exec(cmd->ucmd.ccmd.cc_alt,gimme && (cmdflags & CF_TERM),sp);
289 st = stack->ary_array; /* possibly reallocated */
298 if (cmd && cmd->c_head == cmd)
299 /* reached end of while loop */
300 return sp; /* targ isn't in this block */
301 if (cmdflags & CF_ONCE) {
304 tmps = loop_stack[loop_ptr].loop_label;
305 deb("(Popping label #%d %s)\n",loop_ptr,
311 goto tail_recursion_entry;
317 /* Set line number so run-time errors can be located */
324 deb("%s (%lx) r%lx t%lx a%lx n%lx cs%lx\n",
325 cmdname[cmd->c_type],cmd,cmd->c_expr,
326 cmd->ucmd.ccmd.cc_true,cmd->ucmd.ccmd.cc_alt,cmd->c_next,
329 debname[dlevel] = cmdname[cmd->c_type][0];
330 debdelim[dlevel] = '!';
331 if (++dlevel >= dlmax)
336 /* Here is some common optimization */
338 if (cmdflags & CF_COND) {
339 switch (cmdflags & CF_OPTIMIZE) {
342 retstr = cmd->c_short;
345 if (cmdflags & CF_NESURE)
349 retstr = cmd->c_short;
352 if (cmdflags & CF_EQSURE)
357 retstr = STAB_STR(cmd->c_stab);
359 match = str_true(retstr); /* => retstr = retstr, c2 should fix */
360 if (cmdflags & (match ? CF_EQSURE : CF_NESURE))
364 case CFT_ANCHOR: /* /^pat/ optimization */
366 if (*cmd->c_short->str_ptr && !(cmdflags & CF_EQSURE))
367 goto scanner; /* just unanchor it */
369 break; /* must evaluate */
372 case CFT_STROP: /* string op optimization */
373 retstr = STAB_STR(cmd->c_stab);
376 if (*cmd->c_short->str_ptr == *str_get(retstr) &&
377 bcmp(cmd->c_short->str_ptr, str_get(retstr),
378 cmd->c_slen) == 0 ) {
379 if (cmdflags & CF_EQSURE) {
380 if (sawampersand && (cmdflags & CF_OPTIMIZE) != CFT_STROP) {
383 str_nset(stab_val(leftstab),"",0);
385 str_sset(stab_val(amperstab),cmd->c_short);
387 str_nset(stab_val(rightstab),
388 retstr->str_ptr + cmd->c_slen,
389 retstr->str_cur - cmd->c_slen);
391 match = !(cmdflags & CF_FIRSTNEG);
396 else if (cmdflags & CF_NESURE) {
397 match = cmdflags & CF_FIRSTNEG;
403 char *zap1, *zap2, zap1c, zap2c;
406 zap1 = cmd->c_short->str_ptr;
407 zap2 = str_get(retstr);
410 zaplen = cmd->c_slen;
411 if ((zap1c == zap2c) && (bcmp(zap1, zap2, zaplen) == 0)) {
412 if (cmdflags & CF_EQSURE) {
414 (cmdflags & CF_OPTIMIZE) != CFT_STROP) {
417 str_nset(stab_val(leftstab),"",0);
419 str_sset(stab_val(amperstab),cmd->c_short);
421 str_nset(stab_val(rightstab),
422 retstr->str_ptr + cmd->c_slen,
423 retstr->str_cur - cmd->c_slen);
425 match = !(cmdflags & CF_FIRSTNEG);
430 else if (cmdflags & CF_NESURE) {
431 match = cmdflags & CF_FIRSTNEG;
437 break; /* must evaluate */
439 case CFT_SCAN: /* non-anchored search */
441 retstr = STAB_STR(cmd->c_stab);
443 if (retstr->str_pok & SP_STUDIED)
444 if (screamfirst[cmd->c_short->str_rare] >= 0)
445 tmps = screaminstr(retstr, cmd->c_short);
449 tmps = str_get(retstr); /* make sure it's pok */
451 tmps = fbminstr((unsigned char*)tmps,
452 (unsigned char*)tmps + retstr->str_cur, cmd->c_short);
456 if (cmdflags & CF_EQSURE) {
457 ++cmd->c_short->str_u.str_useful;
461 str_nset(stab_val(leftstab),retstr->str_ptr,
462 tmps - retstr->str_ptr);
464 str_sset(stab_val(amperstab),cmd->c_short);
466 str_nset(stab_val(rightstab),
467 tmps + cmd->c_short->str_cur,
468 retstr->str_cur - (tmps - retstr->str_ptr) -
469 cmd->c_short->str_cur);
471 match = !(cmdflags & CF_FIRSTNEG);
479 if (cmdflags & CF_NESURE) {
480 ++cmd->c_short->str_u.str_useful;
481 match = cmdflags & CF_FIRSTNEG;
486 if (--cmd->c_short->str_u.str_useful < 0) {
487 cmdflags &= ~CF_OPTIMIZE;
488 cmdflags |= CFT_EVAL; /* never try this optimization again */
489 cmd->c_flags = (cmdflags & ~CF_ONCE);
491 break; /* must evaluate */
493 case CFT_NUMOP: /* numeric op optimization */
494 retstr = STAB_STR(cmd->c_stab);
496 switch (cmd->c_slen) {
499 if ((!retstr->str_nok && !looks_like_number(retstr)))
500 warn("Possible use of == on string value");
502 match = (str_gnum(retstr) == cmd->c_short->str_u.str_nval);
505 match = (str_gnum(retstr) != cmd->c_short->str_u.str_nval);
508 match = (str_gnum(retstr) < cmd->c_short->str_u.str_nval);
511 match = (str_gnum(retstr) <= cmd->c_short->str_u.str_nval);
514 match = (str_gnum(retstr) > cmd->c_short->str_u.str_nval);
517 match = (str_gnum(retstr) >= cmd->c_short->str_u.str_nval);
521 if (cmdflags & CF_EQSURE) {
526 else if (cmdflags & CF_NESURE) {
530 break; /* must evaluate */
532 case CFT_INDGETS: /* while (<$foo>) */
533 last_in_stab = stabent(str_get(STAB_STR(cmd->c_stab)),TRUE);
534 if (!stab_io(last_in_stab))
535 stab_io(last_in_stab) = stio_new();
537 case CFT_GETS: /* really a while (<file>) */
538 last_in_stab = cmd->c_stab;
540 fp = stab_io(last_in_stab)->ifp;
541 retstr = stab_val(defstab);
544 if (fp && str_gets(retstr, fp, 0)) {
545 if (*retstr->str_ptr == '0' && retstr->str_cur == 1)
549 stab_io(last_in_stab)->lines++;
551 else if (stab_io(last_in_stab)->flags & IOF_ARGV) {
553 goto doeval; /* first time through */
554 fp = nextargv(last_in_stab);
557 (void)do_close(last_in_stab,FALSE);
558 stab_io(last_in_stab)->flags |= IOF_START;
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 */
575 match = str_true(retstr);
576 if (cmd->c_expr->arg_type == O_FLIP) /* undid itself? */
577 cmdflags = copyopt(cmd,cmd->c_expr[3].arg_ptr.arg_cmd);
580 retstr = stab_val(cmd->c_stab);
582 match = (retstr->str_cur != 0);
583 tmps = str_get(retstr);
584 tmps += retstr->str_cur - match;
585 str_nset(&str_chop,tmps,match);
588 retstr->str_cur = tmps - retstr->str_ptr;
592 match = cmd->c_short->str_u.str_useful; /* just to get register */
594 if (match < 0) { /* first time through here? */
595 ar = stab_array(cmd->c_expr[1].arg_ptr.arg_stab);
596 aryoptsave = savestack->ary_fill;
597 savesptr(&stab_val(cmd->c_stab));
598 savelong(&cmd->c_short->str_u.str_useful);
601 ar = stab_xarray(cmd->c_expr[1].arg_ptr.arg_stab);
602 if (cmd->c_type != C_WHILE && savestack->ary_fill > firstsave)
603 restorelist(firstsave);
606 if (match >= ar->ary_fill) { /* we're in LAST, probably */
608 cmd->c_short->str_u.str_useful = -1; /* actually redundant */
613 if (!(retstr = ar->ary_array[match]))
614 retstr = afetch(ar,match,TRUE);
615 stab_val(cmd->c_stab) = retstr;
616 cmd->c_short->str_u.str_useful = match;
624 if (DBsingle->str_u.str_nval != 0)
626 if (DBsignal->str_u.str_nval != 0)
628 if (DBtrace->str_u.str_nval != 0)
633 /* we have tried to make this normal case as abnormal as possible */
636 if (gimme == G_ARRAY) {
637 lastretstr = Nullstr;
639 lastsize = newsp - sp;
643 while (tmps_max > tmps_base) /* clean up after last eval */
644 str_free(tmps_list[tmps_max--]);
645 newsp = eval(cmd->c_expr,
646 gimme && (cmdflags & CF_TERM) && cmd->c_type == C_EXPR &&
647 !cmd->ucmd.acmd.ac_expr,
649 st = stack->ary_array; /* possibly reallocated */
651 if (newsp > sp && retstr)
652 match = str_true(retstr);
657 /* if flipflop was true, flop it */
660 if (match && cmdflags & CF_FLIP) {
661 while (tmps_max > tmps_base) /* clean up after last eval */
662 str_free(tmps_list[tmps_max--]);
663 if (cmd->c_expr->arg_type == O_FLOP) { /* currently toggled? */
664 newsp = eval(cmd->c_expr,G_SCALAR,sp);/*let eval undo it*/
665 cmdflags = copyopt(cmd,cmd->c_expr[3].arg_ptr.arg_cmd);
668 newsp = eval(cmd->c_expr,G_SCALAR,sp);/* let eval do it */
669 if (cmd->c_expr->arg_type == O_FLOP) /* still toggled? */
670 cmdflags = copyopt(cmd,cmd->c_expr[4].arg_ptr.arg_cmd);
673 else if (cmdflags & CF_FLIP) {
674 if (cmd->c_expr->arg_type == O_FLOP) { /* currently toggled? */
675 match = TRUE; /* force on */
679 /* at this point, match says whether our expression was true */
682 if (cmdflags & CF_INVERT)
688 tainted = 0; /* modifier doesn't affect regular expression */
691 /* now to do the actual command, if any */
693 switch (cmd->c_type) {
695 fatal("panic: cmd_exec");
696 case C_EXPR: /* evaluated for side effects */
697 if (cmd->ucmd.acmd.ac_expr) { /* more to do? */
698 if (gimme == G_ARRAY) {
699 lastretstr = Nullstr;
701 lastsize = newsp - sp;
705 while (tmps_max > tmps_base) /* clean up after last eval */
706 str_free(tmps_list[tmps_max--]);
707 newsp = eval(cmd->ucmd.acmd.ac_expr,gimme && (cmdflags&CF_TERM),sp);
708 st = stack->ary_array; /* possibly reallocated */
714 double value = str_gnum(STAB_STR(cmd->c_stab));
718 if (((double)match) > value)
719 --match; /* was fractional--truncate other way */
724 match = *(str_get(STAB_STR(cmd->c_stab))) & 255;
726 match -= cmd->ucmd.scmd.sc_offset;
729 else if (match > cmd->ucmd.scmd.sc_max)
730 match = cmd->ucmd.scmd.sc_max;
731 cmd = cmd->ucmd.scmd.sc_next[match];
732 goto tail_recursion_entry;
734 cmd = cmd->ucmd.ccmd.cc_alt;
735 goto tail_recursion_entry;
737 fatal("panic: ELSIF");
740 oldsave = savestack->ary_fill;
746 if (cmd->ucmd.ccmd.cc_true) {
749 debname[dlevel] = 't';
750 debdelim[dlevel] = '_';
751 if (++dlevel >= dlmax)
755 newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme && (cmdflags & CF_TERM),sp);
756 st = stack->ary_array; /* possibly reallocated */
760 if (savestack->ary_fill > oldsave)
761 restorelist(oldsave);
765 cmd = cmd->ucmd.ccmd.cc_alt;
766 goto tail_recursion_entry;
769 oldsave = savestack->ary_fill;
775 if (cmd->ucmd.ccmd.cc_true) {
778 debname[dlevel] = 'e';
779 debdelim[dlevel] = '_';
780 if (++dlevel >= dlmax)
784 newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme && (cmdflags & CF_TERM),sp);
785 st = stack->ary_array; /* possibly reallocated */
789 if (savestack->ary_fill > oldsave)
790 restorelist(oldsave);
797 if (!(cmdflags & CF_ONCE)) { /* first time through here? */
799 if (++loop_ptr >= loop_max) {
801 Renew(loop_stack, loop_max, struct loop);
803 loop_stack[loop_ptr].loop_label = cmd->c_label;
804 loop_stack[loop_ptr].loop_sp = sp;
807 deb("(Pushing label #%d %s)\n",
808 loop_ptr, cmd->c_label ? cmd->c_label : "");
815 match = setjmp(loop_stack[loop_ptr].loop_env);
817 st = stack->ary_array; /* possibly reallocated */
820 cmdflags = cmd->c_flags|CF_ONCE;
823 if (savestack->ary_fill > oldsave)
824 restorelist(oldsave);
827 fatal("longjmp returned bad value (%d)",match);
834 newsp = sp + lastsize;
857 oldsave = savestack->ary_fill;
862 if (cmd->ucmd.ccmd.cc_true) {
865 debname[dlevel] = 't';
866 debdelim[dlevel] = '_';
867 if (++dlevel >= dlmax)
871 newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme && (cmdflags & CF_TERM),sp);
872 st = stack->ary_array; /* possibly reallocated */
875 /* actually, this spot is rarely reached anymore since the above
876 * cmd_exec() returns through longjmp(). Hooray for structure.
882 if (cmd->ucmd.ccmd.cc_alt) {
885 debname[dlevel] = 'a';
886 debdelim[dlevel] = '_';
887 if (++dlevel >= dlmax)
891 newsp = cmd_exec(cmd->ucmd.ccmd.cc_alt,gimme && (cmdflags & CF_TERM),sp);
892 st = stack->ary_array; /* possibly reallocated */
897 if (savestack->ary_fill > oldsave) {
898 if (cmdflags & CF_TERM) {
899 for (match = sp + 1; match <= newsp; match++)
900 st[match] = str_static(st[match]);
903 restorelist(oldsave);
906 dlevel = olddlevel - 1;
908 if (cmd->c_type != C_BLOCK)
909 goto until_loop; /* go back and evaluate conditional again */
911 if (cmdflags & CF_LOOP) {
912 cmdflags |= CF_COND; /* now test the condition */
919 if (cmdflags & CF_ONCE) {
922 tmps = loop_stack[loop_ptr].loop_label;
923 deb("(Popping label #%d %s)\n",loop_ptr, tmps ? tmps : "");
927 if ((cmdflags & CF_OPTIMIZE) == CFT_ARRAY &&
928 savestack->ary_fill > aryoptsave)
929 restorelist(aryoptsave);
932 goto tail_recursion_entry;
938 deb(pat,a1,a2,a3,a4,a5,a6,a7,a8)
943 fprintf(stderr,"%-4ld",(long)curcmd->c_line);
944 for (i=0; i<dlevel; i++)
945 fprintf(stderr,"%c%c ",debname[i],debdelim[i]);
946 fprintf(stderr,pat,a1,a2,a3,a4,a5,a6,a7,a8);
958 fprintf(stderr,"%-4ld",(long)curcmd->c_line);
959 for (i=0; i<dlevel; i++)
960 fprintf(stderr,"%c%c ",debname[i],debdelim[i]);
962 pat = va_arg(args, char *);
963 (void) vfprintf(stderr,pat,args);
973 cmd->c_flags &= CF_ONCE|CF_COND|CF_LOOP;
974 cmd->c_flags |= which->c_flags;
975 cmd->c_short = which->c_short;
976 cmd->c_slen = which->c_slen;
977 cmd->c_stab = which->c_stab;
988 str->str_state = SS_SARY;
989 str->str_u.str_stab = stab;
991 Safefree(str->str_ptr);
994 str->str_ptr = (char*)stab_array(stab);
995 (void)apush(savestack,str); /* save array ptr */
996 stab_xarray(stab) = Null(ARRAY*);
997 return stab_xarray(aadd(stab));
1006 str = Str_new(11,0);
1007 str->str_state = SS_SHASH;
1008 str->str_u.str_stab = stab;
1010 Safefree(str->str_ptr);
1013 str->str_ptr = (char*)stab_hash(stab);
1014 (void)apush(savestack,str); /* save hash ptr */
1015 stab_xhash(stab) = Null(HASH*);
1016 return stab_xhash(hadd(stab));
1025 (void)apush(savestack,item); /* remember the pointer */
1026 str = Str_new(12,0);
1028 (void)apush(savestack,str); /* remember the value */
1037 str = Str_new(13,0);
1038 str->str_state = SS_SINT;
1039 str->str_u.str_useful = (long)*intp; /* remember value */
1041 Safefree(str->str_ptr);
1044 str->str_ptr = (char*)intp; /* remember pointer */
1045 (void)apush(savestack,str);
1054 str = Str_new(14,0);
1055 str->str_state = SS_SLONG;
1056 str->str_u.str_useful = *longp; /* remember value */
1058 Safefree(str->str_ptr);
1061 str->str_ptr = (char*)longp; /* remember pointer */
1062 (void)apush(savestack,str);
1071 str = Str_new(15,0);
1072 str->str_state = SS_SSTRP;
1073 str->str_magic = *sptr; /* remember value */
1075 Safefree(str->str_ptr);
1078 str->str_ptr = (char*)sptr; /* remember pointer */
1079 (void)apush(savestack,str);
1088 str = Str_new(16,0);
1089 str->str_state = SS_SNSTAB;
1090 str->str_magic = (STR*)stab; /* remember which stab to free */
1091 (void)apush(savestack,str);
1100 str = Str_new(17,0);
1101 str->str_state = SS_SHPTR;
1102 str->str_u.str_hash = *hptr; /* remember value */
1104 Safefree(str->str_ptr);
1107 str->str_ptr = (char*)hptr; /* remember pointer */
1108 (void)apush(savestack,str);
1112 savelist(sarg,maxsarg)
1113 register STR **sarg;
1119 for (i = 1; i <= maxsarg; i++) {
1120 (void)apush(savestack,sarg[i]); /* remember the pointer */
1121 str = Str_new(18,0);
1122 str_sset(str,sarg[i]);
1123 (void)apush(savestack,str); /* remember the value */
1124 sarg[i]->str_u.str_useful = -1;
1133 register STR *value;
1134 register STAB *stab;
1137 fatal("panic: corrupt saved stack index");
1138 while (savestack->ary_fill > base) {
1139 value = apop(savestack);
1140 switch (value->str_state) {
1141 case SS_NORM: /* normal string */
1143 str = apop(savestack);
1144 str_replace(str,value);
1147 case SS_SARY: /* array reference */
1148 stab = value->str_u.str_stab;
1149 afree(stab_xarray(stab));
1150 stab_xarray(stab) = (ARRAY*)value->str_ptr;
1151 value->str_ptr = Nullch;
1154 case SS_SHASH: /* hash reference */
1155 stab = value->str_u.str_stab;
1156 (void)hfree(stab_xhash(stab), FALSE);
1157 stab_xhash(stab) = (HASH*)value->str_ptr;
1158 value->str_ptr = Nullch;
1161 case SS_SINT: /* int reference */
1162 *((int*)value->str_ptr) = (int)value->str_u.str_useful;
1163 value->str_ptr = Nullch;
1166 case SS_SLONG: /* long reference */
1167 *((long*)value->str_ptr) = value->str_u.str_useful;
1168 value->str_ptr = Nullch;
1171 case SS_SSTRP: /* STR* reference */
1172 *((STR**)value->str_ptr) = value->str_magic;
1173 value->str_magic = Nullstr;
1174 value->str_ptr = Nullch;
1177 case SS_SHPTR: /* HASH* reference */
1178 *((HASH**)value->str_ptr) = value->str_u.str_hash;
1179 value->str_ptr = Nullch;
1183 stab = (STAB*)value->str_magic;
1184 value->str_magic = Nullstr;
1185 (void)stab_clear(stab);
1188 case SS_SCSV: /* callsave structure */
1190 CSV *csv = (CSV*) value->str_ptr;
1192 curcmd = csv->curcmd;
1193 curcsv = csv->curcsv;
1194 csv->sub->depth = csv->depth;
1195 if (csv->hasargs) { /* put back old @_ */
1196 afree(csv->argarray);
1197 stab_xarray(defstab) = csv->savearray;
1203 fatal("panic: restorelist inconsistency");
1213 Renew(debname, dlmax, char);
1214 Renew(debdelim, dlmax, char);