1 /* $RCSfile: cmd.c,v $$Revision: 4.0.1.5 $$Date: 92/06/08 12:00:39 $
3 * Copyright (c) 1991, Larry Wall
5 * You may distribute under the terms of either the GNU General Public
6 * License or the Artistic License, as specified in the README file.
9 * Revision 4.0.1.5 92/06/08 12:00:39 lwall
10 * patch20: the switch optimizer didn't do anything in subroutines
11 * patch20: removed implicit int declarations on funcions
13 * Revision 4.0.1.4 91/11/11 16:29:33 lwall
14 * patch19: do {$foo ne "bar";} returned wrong value
15 * patch19: some earlier patches weren't propagated to alternate 286 code
17 * Revision 4.0.1.3 91/11/05 16:07:43 lwall
18 * patch11: random cleanup
19 * patch11: "foo\0" eq "foo" was sometimes optimized to true
20 * patch11: foreach on null list could spring memory leak
22 * Revision 4.0.1.2 91/06/07 10:26:45 lwall
23 * patch4: new copyright notice
24 * patch4: made some allowances for "semi-standard" C
26 * Revision 4.0.1.1 91/04/11 17:36:16 lwall
27 * patch1: you may now use "die" and "caller" in a signal handler
29 * Revision 4.0 91/03/20 01:04:18 lwall
45 /* do longjmps() clobber register variables? */
47 #if defined(cray) || defined(STANDARD_C)
51 /* This is the main command loop. We try to spend as much time in this loop
52 * as possible, so lots of optimizations do their activities in here. This
53 * means things get a little sloppy.
57 cmd_exec(cmdparm,gimme,sp)
58 CMD *VOLATILE cmdparm;
62 register CMD *cmd = cmdparm;
63 SPAT *VOLATILE oldspat;
64 VOLATILE int firstsave = savestack->ary_fill;
66 VOLATILE int aryoptsave;
68 VOLATILE int olddlevel;
69 VOLATILE int entdlevel;
71 register STR *retstr = &str_undef;
73 register int cmdflags;
75 register char *go_to = goto_targ;
76 register int newsp = -2;
77 register STR **st = stack->ary_array;
89 deb("mortals = (%d/%d) stack, = (%d/%d)\n",
91 savestack->ary_fill, firstsave);
94 tainted = 0; /* Each statement is presumed innocent */
97 if (gimme == G_ARRAY && newsp > -2)
104 cmdflags = cmd->c_flags; /* hopefully load register */
106 if (cmd->c_label && strEQ(go_to,cmd->c_label))
107 goto_targ = go_to = Nullch; /* here at last */
109 switch (cmd->c_type) {
112 oldsave = savestack->ary_fill;
118 if (cmd->ucmd.ccmd.cc_true) {
121 debname[dlevel] = 't';
122 debdelim[dlevel] = '_';
123 if (++dlevel >= dlmax)
127 newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme && (cmdflags & CF_TERM),sp);
128 st = stack->ary_array; /* possibly reallocated */
134 if (savestack->ary_fill > oldsave)
135 restorelist(oldsave);
139 cmd = cmd->ucmd.ccmd.cc_alt;
140 goto tail_recursion_entry;
143 oldsave = savestack->ary_fill;
149 if (cmd->ucmd.ccmd.cc_true) {
152 debname[dlevel] = 'e';
153 debdelim[dlevel] = '_';
154 if (++dlevel >= dlmax)
158 newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme && (cmdflags & CF_TERM),sp);
159 st = stack->ary_array; /* possibly reallocated */
165 if (savestack->ary_fill > oldsave)
166 restorelist(oldsave);
173 if (!(cmdflags & CF_ONCE)) {
175 if (++loop_ptr >= loop_max) {
177 Renew(loop_stack, loop_max, struct loop);
179 loop_stack[loop_ptr].loop_label = cmd->c_label;
180 loop_stack[loop_ptr].loop_sp = sp;
183 deb("(Pushing label #%d %s)\n",
184 loop_ptr, cmd->c_label ? cmd->c_label : "");
191 match = setjmp(loop_stack[loop_ptr].loop_env);
193 st = stack->ary_array; /* possibly reallocated */
196 cmdflags = cmd->c_flags|CF_ONCE;
198 if (savestack->ary_fill > oldsave)
199 restorelist(oldsave);
202 fatal("longjmp returned bad value (%d)",match);
203 case O_LAST: /* not done unless go_to found */
210 newsp = sp + lastsize;
218 case O_NEXT: /* not done unless go_to found */
225 case O_REDO: /* not done unless go_to found */
235 oldsave = savestack->ary_fill;
239 if (cmd->ucmd.ccmd.cc_true) {
242 debname[dlevel] = 't';
243 debdelim[dlevel] = '_';
244 if (++dlevel >= dlmax)
248 newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme && (cmdflags & CF_TERM),sp);
249 st = stack->ary_array; /* possibly reallocated */
260 if (cmd->ucmd.ccmd.cc_alt) {
263 debname[dlevel] = 'a';
264 debdelim[dlevel] = '_';
265 if (++dlevel >= dlmax)
269 newsp = cmd_exec(cmd->ucmd.ccmd.cc_alt,gimme && (cmdflags & CF_TERM),sp);
270 st = stack->ary_array; /* possibly reallocated */
280 if (cmd && cmd->c_head == cmd)
281 /* reached end of while loop */
282 return sp; /* targ isn't in this block */
283 if (cmdflags & CF_ONCE) {
286 tmps = loop_stack[loop_ptr].loop_label;
287 deb("(Popping label #%d %s)\n",loop_ptr,
293 goto tail_recursion_entry;
299 /* Set line number so run-time errors can be located */
306 deb("%s (%lx) r%lx t%lx a%lx n%lx cs%lx\n",
307 cmdname[cmd->c_type],cmd,cmd->c_expr,
308 cmd->ucmd.ccmd.cc_true,cmd->ucmd.ccmd.cc_alt,cmd->c_next,
311 debname[dlevel] = cmdname[cmd->c_type][0];
312 debdelim[dlevel] = '!';
313 if (++dlevel >= dlmax)
318 /* Here is some common optimization */
320 if (cmdflags & CF_COND) {
321 switch (cmdflags & CF_OPTIMIZE) {
324 retstr = cmd->c_short;
327 if (cmdflags & CF_NESURE)
331 retstr = cmd->c_short;
334 if (cmdflags & CF_EQSURE)
339 retstr = STAB_STR(cmd->c_stab);
341 match = str_true(retstr); /* => retstr = retstr, c2 should fix */
342 if (cmdflags & (match ? CF_EQSURE : CF_NESURE))
346 case CFT_ANCHOR: /* /^pat/ optimization */
348 if (*cmd->c_short->str_ptr && !(cmdflags & CF_EQSURE))
349 goto scanner; /* just unanchor it */
351 break; /* must evaluate */
356 case CFT_STROP: /* string op optimization */
359 retstr = STAB_STR(cmd->c_stab);
362 if (*cmd->c_short->str_ptr == *str_get(retstr) &&
363 (match ? retstr->str_cur == cmd->c_slen - 1 :
364 retstr->str_cur >= cmd->c_slen) &&
365 bcmp(cmd->c_short->str_ptr, str_get(retstr),
366 cmd->c_slen) == 0 ) {
367 if (cmdflags & CF_EQSURE) {
368 if (sawampersand && (cmdflags & CF_OPTIMIZE) != CFT_STROP) {
371 str_nset(stab_val(leftstab),"",0);
373 str_sset(stab_val(amperstab),cmd->c_short);
375 str_nset(stab_val(rightstab),
376 retstr->str_ptr + cmd->c_slen,
377 retstr->str_cur - cmd->c_slen);
380 lastspat = cmd->c_spat;
381 match = !(cmdflags & CF_FIRSTNEG);
382 retstr = match ? &str_yes : &str_no;
386 else if (cmdflags & CF_NESURE) {
387 match = cmdflags & CF_FIRSTNEG;
388 retstr = match ? &str_yes : &str_no;
393 char *zap1, *zap2, zap1c, zap2c;
397 zap1 = cmd->c_short->str_ptr;
398 zap2 = str_get(retstr);
401 zaplen = cmd->c_slen;
403 lenok = (retstr->str_cur == cmd->c_slen - 1);
405 lenok = (retstr->str_cur >= cmd->c_slen);
406 if ((zap1c == zap2c) && lenok && (bcmp(zap1, zap2, zaplen) == 0)) {
407 if (cmdflags & CF_EQSURE) {
409 (cmdflags & CF_OPTIMIZE) != CFT_STROP) {
412 str_nset(stab_val(leftstab),"",0);
414 str_sset(stab_val(amperstab),cmd->c_short);
416 str_nset(stab_val(rightstab),
417 retstr->str_ptr + cmd->c_slen,
418 retstr->str_cur - cmd->c_slen);
421 lastspat = cmd->c_spat;
422 match = !(cmdflags & CF_FIRSTNEG);
423 retstr = match ? &str_yes : &str_no;
427 else if (cmdflags & CF_NESURE) {
428 match = cmdflags & CF_FIRSTNEG;
429 retstr = match ? &str_yes : &str_no;
434 break; /* must evaluate */
436 case CFT_SCAN: /* non-anchored search */
438 retstr = STAB_STR(cmd->c_stab);
440 if (retstr->str_pok & SP_STUDIED)
441 if (screamfirst[cmd->c_short->str_rare] >= 0)
442 tmps = screaminstr(retstr, cmd->c_short);
446 tmps = str_get(retstr); /* make sure it's pok */
448 tmps = fbminstr((unsigned char*)tmps,
449 (unsigned char*)tmps + retstr->str_cur, cmd->c_short);
453 if (cmdflags & CF_EQSURE) {
454 ++cmd->c_short->str_u.str_useful;
458 str_nset(stab_val(leftstab),retstr->str_ptr,
459 tmps - retstr->str_ptr);
461 str_nset(stab_val(amperstab),
462 tmps, cmd->c_short->str_cur);
464 str_nset(stab_val(rightstab),
465 tmps + cmd->c_short->str_cur,
466 retstr->str_cur - (tmps - retstr->str_ptr) -
467 cmd->c_short->str_cur);
469 lastspat = cmd->c_spat;
470 match = !(cmdflags & CF_FIRSTNEG);
471 retstr = match ? &str_yes : &str_no;
478 if (cmdflags & CF_NESURE) {
479 ++cmd->c_short->str_u.str_useful;
480 match = cmdflags & CF_FIRSTNEG;
481 retstr = match ? &str_yes : &str_no;
485 if (--cmd->c_short->str_u.str_useful < 0) {
486 cmdflags &= ~CF_OPTIMIZE;
487 cmdflags |= CFT_EVAL; /* never try this optimization again */
488 cmd->c_flags = (cmdflags & ~CF_ONCE);
490 break; /* must evaluate */
492 case CFT_NUMOP: /* numeric op optimization */
493 retstr = STAB_STR(cmd->c_stab);
495 switch (cmd->c_slen) {
498 if ((!retstr->str_nok && !looks_like_number(retstr)))
499 warn("Possible use of == on string value");
501 match = (str_gnum(retstr) == cmd->c_short->str_u.str_nval);
504 match = (str_gnum(retstr) != cmd->c_short->str_u.str_nval);
507 match = (str_gnum(retstr) < cmd->c_short->str_u.str_nval);
510 match = (str_gnum(retstr) <= cmd->c_short->str_u.str_nval);
513 match = (str_gnum(retstr) > cmd->c_short->str_u.str_nval);
516 match = (str_gnum(retstr) >= cmd->c_short->str_u.str_nval);
520 if (cmdflags & CF_EQSURE) {
525 else if (cmdflags & CF_NESURE) {
529 break; /* must evaluate */
531 case CFT_INDGETS: /* while (<$foo>) */
532 last_in_stab = stabent(str_get(STAB_STR(cmd->c_stab)),TRUE);
533 if (!stab_io(last_in_stab))
534 stab_io(last_in_stab) = stio_new();
536 case CFT_GETS: /* really a while (<file>) */
537 last_in_stab = cmd->c_stab;
539 fp = stab_io(last_in_stab)->ifp;
540 retstr = stab_val(defstab);
543 if (fp && str_gets(retstr, fp, 0)) {
544 if (*retstr->str_ptr == '0' && retstr->str_cur == 1)
548 stab_io(last_in_stab)->lines++;
550 else if (stab_io(last_in_stab)->flags & IOF_ARGV) {
552 goto doeval; /* first time through */
553 fp = nextargv(last_in_stab);
556 (void)do_close(last_in_stab,FALSE);
557 stab_io(last_in_stab)->flags |= IOF_START;
569 while (tmps_max > tmps_base) { /* clean up after last eval */
570 str_free(tmps_list[tmps_max]);
571 tmps_list[tmps_max--] = Nullstr;
573 newsp = eval(cmd->c_expr,gimme && (cmdflags & CF_TERM),sp);
574 st = stack->ary_array; /* possibly reallocated */
576 match = str_true(retstr);
577 if (cmd->c_expr->arg_type == O_FLIP) /* undid itself? */
578 cmdflags = copyopt(cmd,cmd->c_expr[3].arg_ptr.arg_cmd);
581 retstr = stab_val(cmd->c_stab);
583 match = (retstr->str_cur != 0);
584 tmps = str_get(retstr);
585 tmps += retstr->str_cur - match;
586 str_nset(&strchop,tmps,match);
589 retstr->str_cur = tmps - retstr->str_ptr;
594 match = cmd->c_short->str_u.str_useful; /* just to get register */
596 if (match < 0) { /* first time through here? */
597 ar = stab_array(cmd->c_expr[1].arg_ptr.arg_stab);
598 aryoptsave = savestack->ary_fill;
599 savesptr(&stab_val(cmd->c_stab));
600 savelong(&cmd->c_short->str_u.str_useful);
603 ar = stab_xarray(cmd->c_expr[1].arg_ptr.arg_stab);
604 if (cmd->c_type != C_WHILE && savestack->ary_fill > firstsave)
605 restorelist(firstsave);
608 if (match >= ar->ary_fill) { /* we're in LAST, probably */
609 if (match < 0 && /* er, probably not... */
610 savestack->ary_fill > aryoptsave)
611 restorelist(aryoptsave);
613 cmd->c_short->str_u.str_useful = -1; /* actually redundant */
618 if (!(retstr = ar->ary_array[match]))
619 retstr = afetch(ar,match,TRUE);
620 stab_val(cmd->c_stab) = retstr;
621 cmd->c_short->str_u.str_useful = match;
629 if (DBsingle->str_u.str_nval != 0)
631 if (DBsignal->str_u.str_nval != 0)
633 if (DBtrace->str_u.str_nval != 0)
638 /* we have tried to make this normal case as abnormal as possible */
641 if (gimme == G_ARRAY) {
642 lastretstr = Nullstr;
644 lastsize = newsp - sp;
650 while (tmps_max > tmps_base) { /* clean up after last eval */
651 str_free(tmps_list[tmps_max]);
652 tmps_list[tmps_max--] = Nullstr;
654 newsp = eval(cmd->c_expr,
655 gimme && (cmdflags & CF_TERM) && cmd->c_type == C_EXPR &&
656 !cmd->ucmd.acmd.ac_expr,
658 st = stack->ary_array; /* possibly reallocated */
660 if (newsp > sp && retstr)
661 match = str_true(retstr);
666 /* if flipflop was true, flop it */
669 if (match && cmdflags & CF_FLIP) {
670 while (tmps_max > tmps_base) { /* clean up after last eval */
671 str_free(tmps_list[tmps_max]);
672 tmps_list[tmps_max--] = Nullstr;
674 if (cmd->c_expr->arg_type == O_FLOP) { /* currently toggled? */
675 newsp = eval(cmd->c_expr,G_SCALAR,sp);/*let eval undo it*/
676 cmdflags = copyopt(cmd,cmd->c_expr[3].arg_ptr.arg_cmd);
679 newsp = eval(cmd->c_expr,G_SCALAR,sp);/* let eval do it */
680 if (cmd->c_expr->arg_type == O_FLOP) /* still toggled? */
681 cmdflags = copyopt(cmd,cmd->c_expr[4].arg_ptr.arg_cmd);
684 else if (cmdflags & CF_FLIP) {
685 if (cmd->c_expr->arg_type == O_FLOP) { /* currently toggled? */
686 match = TRUE; /* force on */
690 /* at this point, match says whether our expression was true */
693 if (cmdflags & CF_INVERT)
699 tainted = 0; /* modifier doesn't affect regular expression */
702 /* now to do the actual command, if any */
704 switch (cmd->c_type) {
706 fatal("panic: cmd_exec");
707 case C_EXPR: /* evaluated for side effects */
708 if (cmd->ucmd.acmd.ac_expr) { /* more to do? */
709 if (gimme == G_ARRAY) {
710 lastretstr = Nullstr;
712 lastsize = newsp - sp;
718 while (tmps_max > tmps_base) { /* clean up after last eval */
719 str_free(tmps_list[tmps_max]);
720 tmps_list[tmps_max--] = Nullstr;
722 newsp = eval(cmd->ucmd.acmd.ac_expr,gimme && (cmdflags&CF_TERM),sp);
723 st = stack->ary_array; /* possibly reallocated */
729 double value = str_gnum(STAB_STR(cmd->c_stab));
733 if (((double)match) > value)
734 --match; /* was fractional--truncate other way */
740 cmd = cmd->c_next; /* can't assume anything */
741 goto tail_recursion_entry;
743 match = *(str_get(STAB_STR(cmd->c_stab))) & 255;
745 match -= cmd->ucmd.scmd.sc_offset;
748 else if (match > cmd->ucmd.scmd.sc_max)
749 match = cmd->ucmd.scmd.sc_max;
750 cmd = cmd->ucmd.scmd.sc_next[match];
751 goto tail_recursion_entry;
753 cmd = cmd->ucmd.ccmd.cc_alt;
754 goto tail_recursion_entry;
756 fatal("panic: ELSIF");
759 oldsave = savestack->ary_fill;
765 if (cmd->ucmd.ccmd.cc_true) {
768 debname[dlevel] = 't';
769 debdelim[dlevel] = '_';
770 if (++dlevel >= dlmax)
774 newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme && (cmdflags & CF_TERM),sp);
775 st = stack->ary_array; /* possibly reallocated */
779 if (savestack->ary_fill > oldsave)
780 restorelist(oldsave);
784 cmd = cmd->ucmd.ccmd.cc_alt;
785 goto tail_recursion_entry;
788 oldsave = savestack->ary_fill;
794 if (cmd->ucmd.ccmd.cc_true) {
797 debname[dlevel] = 'e';
798 debdelim[dlevel] = '_';
799 if (++dlevel >= dlmax)
803 newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme && (cmdflags & CF_TERM),sp);
804 st = stack->ary_array; /* possibly reallocated */
808 if (savestack->ary_fill > oldsave)
809 restorelist(oldsave);
816 if (!(cmdflags & CF_ONCE)) { /* first time through here? */
818 if (++loop_ptr >= loop_max) {
820 Renew(loop_stack, loop_max, struct loop);
822 loop_stack[loop_ptr].loop_label = cmd->c_label;
823 loop_stack[loop_ptr].loop_sp = sp;
826 deb("(Pushing label #%d %s)\n",
827 loop_ptr, cmd->c_label ? cmd->c_label : "");
834 match = setjmp(loop_stack[loop_ptr].loop_env);
836 st = stack->ary_array; /* possibly reallocated */
839 cmdflags = cmd->c_flags|CF_ONCE;
842 if (savestack->ary_fill > oldsave)
843 restorelist(oldsave);
846 fatal("longjmp returned bad value (%d)",match);
853 newsp = sp + lastsize;
876 oldsave = savestack->ary_fill;
881 if (cmd->ucmd.ccmd.cc_true) {
884 debname[dlevel] = 't';
885 debdelim[dlevel] = '_';
886 if (++dlevel >= dlmax)
890 newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme && (cmdflags & CF_TERM),sp);
891 st = stack->ary_array; /* possibly reallocated */
894 /* actually, this spot is rarely reached anymore since the above
895 * cmd_exec() returns through longjmp(). Hooray for structure.
901 if (cmd->ucmd.ccmd.cc_alt) {
904 debname[dlevel] = 'a';
905 debdelim[dlevel] = '_';
906 if (++dlevel >= dlmax)
910 newsp = cmd_exec(cmd->ucmd.ccmd.cc_alt,gimme && (cmdflags & CF_TERM),sp);
911 st = stack->ary_array; /* possibly reallocated */
916 if (savestack->ary_fill > oldsave) {
917 if (cmdflags & CF_TERM) {
918 for (match = sp + 1; match <= newsp; match++)
919 st[match] = str_mortal(st[match]);
922 restorelist(oldsave);
925 dlevel = olddlevel - 1;
927 if (cmd->c_type != C_BLOCK)
928 goto until_loop; /* go back and evaluate conditional again */
930 if (cmdflags & CF_LOOP) {
931 cmdflags |= CF_COND; /* now test the condition */
938 if (cmdflags & CF_ONCE) {
941 tmps = loop_stack[loop_ptr].loop_label;
942 deb("(Popping label #%d %s)\n",loop_ptr, tmps ? tmps : "");
946 if ((cmdflags & CF_OPTIMIZE) == CFT_ARRAY &&
947 savestack->ary_fill > aryoptsave)
948 restorelist(aryoptsave);
951 goto tail_recursion_entry;
957 void deb(pat,a1,a2,a3,a4,a5,a6,a7,a8)
962 fprintf(stderr,"%-4ld",(long)curcmd->c_line);
963 for (i=0; i<dlevel; i++)
964 fprintf(stderr,"%c%c ",debname[i],debdelim[i]);
965 fprintf(stderr,pat,a1,a2,a3,a4,a5,a6,a7,a8);
977 fprintf(stderr,"%-4ld",(long)curcmd->c_line);
978 for (i=0; i<dlevel; i++)
979 fprintf(stderr,"%c%c ",debname[i],debdelim[i]);
981 pat = va_arg(args, char *);
982 (void) vfprintf(stderr,pat,args);
993 cmd->c_flags &= CF_ONCE|CF_COND|CF_LOOP;
994 cmd->c_flags |= which->c_flags;
995 cmd->c_short = which->c_short;
996 cmd->c_slen = which->c_slen;
997 cmd->c_stab = which->c_stab;
1007 str = Str_new(10,0);
1008 str->str_state = SS_SARY;
1009 str->str_u.str_stab = stab;
1011 Safefree(str->str_ptr);
1012 str->str_ptr = Nullch;
1015 str->str_ptr = (char*)stab_array(stab);
1016 (void)apush(savestack,str); /* save array ptr */
1017 stab_xarray(stab) = Null(ARRAY*);
1018 return stab_xarray(aadd(stab));
1027 str = Str_new(11,0);
1028 str->str_state = SS_SHASH;
1029 str->str_u.str_stab = stab;
1031 Safefree(str->str_ptr);
1032 str->str_ptr = Nullch;
1035 str->str_ptr = (char*)stab_hash(stab);
1036 (void)apush(savestack,str); /* save hash ptr */
1037 stab_xhash(stab) = Null(HASH*);
1038 return stab_xhash(hadd(stab));
1047 (void)apush(savestack,item); /* remember the pointer */
1048 str = Str_new(12,0);
1050 (void)apush(savestack,str); /* remember the value */
1059 str = Str_new(13,0);
1060 str->str_state = SS_SINT;
1061 str->str_u.str_useful = (long)*intp; /* remember value */
1063 Safefree(str->str_ptr);
1066 str->str_ptr = (char*)intp; /* remember pointer */
1067 (void)apush(savestack,str);
1076 str = Str_new(14,0);
1077 str->str_state = SS_SLONG;
1078 str->str_u.str_useful = *longp; /* remember value */
1080 Safefree(str->str_ptr);
1083 str->str_ptr = (char*)longp; /* remember pointer */
1084 (void)apush(savestack,str);
1093 str = Str_new(15,0);
1094 str->str_state = SS_SSTRP;
1095 str->str_magic = *sptr; /* remember value */
1097 Safefree(str->str_ptr);
1100 str->str_ptr = (char*)sptr; /* remember pointer */
1101 (void)apush(savestack,str);
1110 str = Str_new(16,0);
1111 str->str_state = SS_SNSTAB;
1112 str->str_magic = (STR*)stab; /* remember which stab to free */
1113 (void)apush(savestack,str);
1122 str = Str_new(17,0);
1123 str->str_state = SS_SHPTR;
1124 str->str_u.str_hash = *hptr; /* remember value */
1126 Safefree(str->str_ptr);
1129 str->str_ptr = (char*)hptr; /* remember pointer */
1130 (void)apush(savestack,str);
1139 str = Str_new(17,0);
1140 str->str_state = SS_SAPTR;
1141 str->str_u.str_array = *aptr; /* remember value */
1143 Safefree(str->str_ptr);
1146 str->str_ptr = (char*)aptr; /* remember pointer */
1147 (void)apush(savestack,str);
1151 savelist(sarg,maxsarg)
1152 register STR **sarg;
1158 for (i = 1; i <= maxsarg; i++) {
1159 (void)apush(savestack,sarg[i]); /* remember the pointer */
1160 str = Str_new(18,0);
1161 str_sset(str,sarg[i]);
1162 (void)apush(savestack,str); /* remember the value */
1163 sarg[i]->str_u.str_useful = -1;
1172 register STR *value;
1173 register STAB *stab;
1176 fatal("panic: corrupt saved stack index");
1177 while (savestack->ary_fill > base) {
1178 value = apop(savestack);
1179 switch (value->str_state) {
1180 case SS_NORM: /* normal string */
1182 str = apop(savestack);
1183 str_replace(str,value);
1186 case SS_SARY: /* array reference */
1187 stab = value->str_u.str_stab;
1188 afree(stab_xarray(stab));
1189 stab_xarray(stab) = (ARRAY*)value->str_ptr;
1190 value->str_ptr = Nullch;
1193 case SS_SHASH: /* hash reference */
1194 stab = value->str_u.str_stab;
1195 (void)hfree(stab_xhash(stab), FALSE);
1196 stab_xhash(stab) = (HASH*)value->str_ptr;
1197 value->str_ptr = Nullch;
1200 case SS_SINT: /* int reference */
1201 *((int*)value->str_ptr) = (int)value->str_u.str_useful;
1202 value->str_ptr = Nullch;
1205 case SS_SLONG: /* long reference */
1206 *((long*)value->str_ptr) = value->str_u.str_useful;
1207 value->str_ptr = Nullch;
1210 case SS_SSTRP: /* STR* reference */
1211 *((STR**)value->str_ptr) = value->str_magic;
1212 value->str_magic = Nullstr;
1213 value->str_ptr = Nullch;
1216 case SS_SHPTR: /* HASH* reference */
1217 *((HASH**)value->str_ptr) = value->str_u.str_hash;
1218 value->str_ptr = Nullch;
1221 case SS_SAPTR: /* ARRAY* reference */
1222 *((ARRAY**)value->str_ptr) = value->str_u.str_array;
1223 value->str_ptr = Nullch;
1227 stab = (STAB*)value->str_magic;
1228 value->str_magic = Nullstr;
1229 (void)stab_clear(stab);
1232 case SS_SCSV: /* callsave structure */
1234 CSV *csv = (CSV*) value->str_ptr;
1236 curcmd = csv->curcmd;
1237 curcsv = csv->curcsv;
1238 csv->sub->depth = csv->depth;
1239 if (csv->hasargs) { /* put back old @_ */
1240 afree(csv->argarray);
1241 stab_xarray(defstab) = csv->savearray;
1247 fatal("panic: restorelist inconsistency");
1257 Renew(debname, dlmax, char);
1258 Renew(debdelim, dlmax, char);