1 /* $RCSfile: cmd.c,v $$Revision: 4.0.1.4 $$Date: 91/11/11 16:29:33 $
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.4 91/11/11 16:29:33 lwall
10 * patch19: do {$foo ne "bar";} returned wrong value
11 * patch19: some earlier patches weren't propagated to alternate 286 code
13 * Revision 4.0.1.3 91/11/05 16:07:43 lwall
14 * patch11: random cleanup
15 * patch11: "foo\0" eq "foo" was sometimes optimized to true
16 * patch11: foreach on null list could spring memory leak
18 * Revision 4.0.1.2 91/06/07 10:26:45 lwall
19 * patch4: new copyright notice
20 * patch4: made some allowances for "semi-standard" C
22 * Revision 4.0.1.1 91/04/11 17:36:16 lwall
23 * patch1: you may now use "die" and "caller" in a signal handler
25 * Revision 4.0 91/03/20 01:04:18 lwall
41 /* do longjmps() clobber register variables? */
43 #if defined(cray) || defined(STANDARD_C)
47 /* This is the main command loop. We try to spend as much time in this loop
48 * as possible, so lots of optimizations do their activities in here. This
49 * means things get a little sloppy.
53 cmd_exec(cmdparm,gimme,sp)
54 CMD *VOLATILE cmdparm;
58 register CMD *cmd = cmdparm;
59 SPAT *VOLATILE oldspat;
60 VOLATILE int firstsave = savestack->ary_fill;
62 VOLATILE int aryoptsave;
64 VOLATILE int olddlevel;
65 VOLATILE int entdlevel;
67 register STR *retstr = &str_undef;
69 register int cmdflags;
71 register char *go_to = goto_targ;
72 register int newsp = -2;
73 register STR **st = stack->ary_array;
86 tainted = 0; /* Each statement is presumed innocent */
89 if (gimme == G_ARRAY && newsp > -2)
96 cmdflags = cmd->c_flags; /* hopefully load register */
98 if (cmd->c_label && strEQ(go_to,cmd->c_label))
99 goto_targ = go_to = Nullch; /* here at last */
101 switch (cmd->c_type) {
104 oldsave = savestack->ary_fill;
110 if (cmd->ucmd.ccmd.cc_true) {
113 debname[dlevel] = 't';
114 debdelim[dlevel] = '_';
115 if (++dlevel >= dlmax)
119 newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme && (cmdflags & CF_TERM),sp);
120 st = stack->ary_array; /* possibly reallocated */
126 if (savestack->ary_fill > oldsave)
127 restorelist(oldsave);
131 cmd = cmd->ucmd.ccmd.cc_alt;
132 goto tail_recursion_entry;
135 oldsave = savestack->ary_fill;
141 if (cmd->ucmd.ccmd.cc_true) {
144 debname[dlevel] = 'e';
145 debdelim[dlevel] = '_';
146 if (++dlevel >= dlmax)
150 newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme && (cmdflags & CF_TERM),sp);
151 st = stack->ary_array; /* possibly reallocated */
157 if (savestack->ary_fill > oldsave)
158 restorelist(oldsave);
165 if (!(cmdflags & CF_ONCE)) {
167 if (++loop_ptr >= loop_max) {
169 Renew(loop_stack, loop_max, struct loop);
171 loop_stack[loop_ptr].loop_label = cmd->c_label;
172 loop_stack[loop_ptr].loop_sp = sp;
175 deb("(Pushing label #%d %s)\n",
176 loop_ptr, cmd->c_label ? cmd->c_label : "");
183 match = setjmp(loop_stack[loop_ptr].loop_env);
185 st = stack->ary_array; /* possibly reallocated */
188 cmdflags = cmd->c_flags|CF_ONCE;
190 if (savestack->ary_fill > oldsave)
191 restorelist(oldsave);
194 fatal("longjmp returned bad value (%d)",match);
195 case O_LAST: /* not done unless go_to found */
202 newsp = sp + lastsize;
210 case O_NEXT: /* not done unless go_to found */
217 case O_REDO: /* not done unless go_to found */
227 oldsave = savestack->ary_fill;
231 if (cmd->ucmd.ccmd.cc_true) {
234 debname[dlevel] = 't';
235 debdelim[dlevel] = '_';
236 if (++dlevel >= dlmax)
240 newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme && (cmdflags & CF_TERM),sp);
241 st = stack->ary_array; /* possibly reallocated */
252 if (cmd->ucmd.ccmd.cc_alt) {
255 debname[dlevel] = 'a';
256 debdelim[dlevel] = '_';
257 if (++dlevel >= dlmax)
261 newsp = cmd_exec(cmd->ucmd.ccmd.cc_alt,gimme && (cmdflags & CF_TERM),sp);
262 st = stack->ary_array; /* possibly reallocated */
272 if (cmd && cmd->c_head == cmd)
273 /* reached end of while loop */
274 return sp; /* targ isn't in this block */
275 if (cmdflags & CF_ONCE) {
278 tmps = loop_stack[loop_ptr].loop_label;
279 deb("(Popping label #%d %s)\n",loop_ptr,
285 goto tail_recursion_entry;
291 /* Set line number so run-time errors can be located */
298 deb("%s (%lx) r%lx t%lx a%lx n%lx cs%lx\n",
299 cmdname[cmd->c_type],cmd,cmd->c_expr,
300 cmd->ucmd.ccmd.cc_true,cmd->ucmd.ccmd.cc_alt,cmd->c_next,
303 debname[dlevel] = cmdname[cmd->c_type][0];
304 debdelim[dlevel] = '!';
305 if (++dlevel >= dlmax)
310 /* Here is some common optimization */
312 if (cmdflags & CF_COND) {
313 switch (cmdflags & CF_OPTIMIZE) {
316 retstr = cmd->c_short;
319 if (cmdflags & CF_NESURE)
323 retstr = cmd->c_short;
326 if (cmdflags & CF_EQSURE)
331 retstr = STAB_STR(cmd->c_stab);
333 match = str_true(retstr); /* => retstr = retstr, c2 should fix */
334 if (cmdflags & (match ? CF_EQSURE : CF_NESURE))
338 case CFT_ANCHOR: /* /^pat/ optimization */
340 if (*cmd->c_short->str_ptr && !(cmdflags & CF_EQSURE))
341 goto scanner; /* just unanchor it */
343 break; /* must evaluate */
348 case CFT_STROP: /* string op optimization */
351 retstr = STAB_STR(cmd->c_stab);
354 if (*cmd->c_short->str_ptr == *str_get(retstr) &&
355 (match ? retstr->str_cur == cmd->c_slen - 1 :
356 retstr->str_cur >= cmd->c_slen) &&
357 bcmp(cmd->c_short->str_ptr, str_get(retstr),
358 cmd->c_slen) == 0 ) {
359 if (cmdflags & CF_EQSURE) {
360 if (sawampersand && (cmdflags & CF_OPTIMIZE) != CFT_STROP) {
363 str_nset(stab_val(leftstab),"",0);
365 str_sset(stab_val(amperstab),cmd->c_short);
367 str_nset(stab_val(rightstab),
368 retstr->str_ptr + cmd->c_slen,
369 retstr->str_cur - cmd->c_slen);
372 lastspat = cmd->c_spat;
373 match = !(cmdflags & CF_FIRSTNEG);
374 retstr = match ? &str_yes : &str_no;
378 else if (cmdflags & CF_NESURE) {
379 match = cmdflags & CF_FIRSTNEG;
380 retstr = match ? &str_yes : &str_no;
385 char *zap1, *zap2, zap1c, zap2c;
389 zap1 = cmd->c_short->str_ptr;
390 zap2 = str_get(retstr);
393 zaplen = cmd->c_slen;
395 lenok = (retstr->str_cur == cmd->c_slen - 1);
397 lenok = (retstr->str_cur >= cmd->c_slen);
398 if ((zap1c == zap2c) && lenok && (bcmp(zap1, zap2, zaplen) == 0)) {
399 if (cmdflags & CF_EQSURE) {
401 (cmdflags & CF_OPTIMIZE) != CFT_STROP) {
404 str_nset(stab_val(leftstab),"",0);
406 str_sset(stab_val(amperstab),cmd->c_short);
408 str_nset(stab_val(rightstab),
409 retstr->str_ptr + cmd->c_slen,
410 retstr->str_cur - cmd->c_slen);
413 lastspat = cmd->c_spat;
414 match = !(cmdflags & CF_FIRSTNEG);
415 retstr = match ? &str_yes : &str_no;
419 else if (cmdflags & CF_NESURE) {
420 match = cmdflags & CF_FIRSTNEG;
421 retstr = match ? &str_yes : &str_no;
426 break; /* must evaluate */
428 case CFT_SCAN: /* non-anchored search */
430 retstr = STAB_STR(cmd->c_stab);
432 if (retstr->str_pok & SP_STUDIED)
433 if (screamfirst[cmd->c_short->str_rare] >= 0)
434 tmps = screaminstr(retstr, cmd->c_short);
438 tmps = str_get(retstr); /* make sure it's pok */
440 tmps = fbminstr((unsigned char*)tmps,
441 (unsigned char*)tmps + retstr->str_cur, cmd->c_short);
445 if (cmdflags & CF_EQSURE) {
446 ++cmd->c_short->str_u.str_useful;
450 str_nset(stab_val(leftstab),retstr->str_ptr,
451 tmps - retstr->str_ptr);
453 str_nset(stab_val(amperstab),
454 tmps, cmd->c_short->str_cur);
456 str_nset(stab_val(rightstab),
457 tmps + cmd->c_short->str_cur,
458 retstr->str_cur - (tmps - retstr->str_ptr) -
459 cmd->c_short->str_cur);
461 lastspat = cmd->c_spat;
462 match = !(cmdflags & CF_FIRSTNEG);
463 retstr = match ? &str_yes : &str_no;
470 if (cmdflags & CF_NESURE) {
471 ++cmd->c_short->str_u.str_useful;
472 match = cmdflags & CF_FIRSTNEG;
473 retstr = match ? &str_yes : &str_no;
477 if (--cmd->c_short->str_u.str_useful < 0) {
478 cmdflags &= ~CF_OPTIMIZE;
479 cmdflags |= CFT_EVAL; /* never try this optimization again */
480 cmd->c_flags = (cmdflags & ~CF_ONCE);
482 break; /* must evaluate */
484 case CFT_NUMOP: /* numeric op optimization */
485 retstr = STAB_STR(cmd->c_stab);
487 switch (cmd->c_slen) {
490 if ((!retstr->str_nok && !looks_like_number(retstr)))
491 warn("Possible use of == on string value");
493 match = (str_gnum(retstr) == cmd->c_short->str_u.str_nval);
496 match = (str_gnum(retstr) != cmd->c_short->str_u.str_nval);
499 match = (str_gnum(retstr) < cmd->c_short->str_u.str_nval);
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);
512 if (cmdflags & CF_EQSURE) {
517 else if (cmdflags & CF_NESURE) {
521 break; /* must evaluate */
523 case CFT_INDGETS: /* while (<$foo>) */
524 last_in_stab = stabent(str_get(STAB_STR(cmd->c_stab)),TRUE);
525 if (!stab_io(last_in_stab))
526 stab_io(last_in_stab) = stio_new();
528 case CFT_GETS: /* really a while (<file>) */
529 last_in_stab = cmd->c_stab;
531 fp = stab_io(last_in_stab)->ifp;
532 retstr = stab_val(defstab);
535 if (fp && str_gets(retstr, fp, 0)) {
536 if (*retstr->str_ptr == '0' && retstr->str_cur == 1)
540 stab_io(last_in_stab)->lines++;
542 else if (stab_io(last_in_stab)->flags & IOF_ARGV) {
544 goto doeval; /* first time through */
545 fp = nextargv(last_in_stab);
548 (void)do_close(last_in_stab,FALSE);
549 stab_io(last_in_stab)->flags |= IOF_START;
561 while (tmps_max > tmps_base) { /* clean up after last eval */
562 str_free(tmps_list[tmps_max]);
563 tmps_list[tmps_max--] = Nullstr;
565 newsp = eval(cmd->c_expr,gimme && (cmdflags & CF_TERM),sp);
566 st = stack->ary_array; /* possibly reallocated */
568 match = str_true(retstr);
569 if (cmd->c_expr->arg_type == O_FLIP) /* undid itself? */
570 cmdflags = copyopt(cmd,cmd->c_expr[3].arg_ptr.arg_cmd);
573 retstr = stab_val(cmd->c_stab);
575 match = (retstr->str_cur != 0);
576 tmps = str_get(retstr);
577 tmps += retstr->str_cur - match;
578 str_nset(&str_chop,tmps,match);
581 retstr->str_cur = tmps - retstr->str_ptr;
586 match = cmd->c_short->str_u.str_useful; /* just to get register */
588 if (match < 0) { /* first time through here? */
589 ar = stab_array(cmd->c_expr[1].arg_ptr.arg_stab);
590 aryoptsave = savestack->ary_fill;
591 savesptr(&stab_val(cmd->c_stab));
592 savelong(&cmd->c_short->str_u.str_useful);
595 ar = stab_xarray(cmd->c_expr[1].arg_ptr.arg_stab);
596 if (cmd->c_type != C_WHILE && savestack->ary_fill > firstsave)
597 restorelist(firstsave);
600 if (match >= ar->ary_fill) { /* we're in LAST, probably */
601 if (match < 0 && /* er, probably not... */
602 savestack->ary_fill > aryoptsave)
603 restorelist(aryoptsave);
605 cmd->c_short->str_u.str_useful = -1; /* actually redundant */
610 if (!(retstr = ar->ary_array[match]))
611 retstr = afetch(ar,match,TRUE);
612 stab_val(cmd->c_stab) = retstr;
613 cmd->c_short->str_u.str_useful = match;
621 if (DBsingle->str_u.str_nval != 0)
623 if (DBsignal->str_u.str_nval != 0)
625 if (DBtrace->str_u.str_nval != 0)
630 /* we have tried to make this normal case as abnormal as possible */
633 if (gimme == G_ARRAY) {
634 lastretstr = Nullstr;
636 lastsize = newsp - sp;
642 while (tmps_max > tmps_base) { /* clean up after last eval */
643 str_free(tmps_list[tmps_max]);
644 tmps_list[tmps_max--] = Nullstr;
646 newsp = eval(cmd->c_expr,
647 gimme && (cmdflags & CF_TERM) && cmd->c_type == C_EXPR &&
648 !cmd->ucmd.acmd.ac_expr,
650 st = stack->ary_array; /* possibly reallocated */
652 if (newsp > sp && retstr)
653 match = str_true(retstr);
658 /* if flipflop was true, flop it */
661 if (match && cmdflags & CF_FLIP) {
662 while (tmps_max > tmps_base) { /* clean up after last eval */
663 str_free(tmps_list[tmps_max]);
664 tmps_list[tmps_max--] = Nullstr;
666 if (cmd->c_expr->arg_type == O_FLOP) { /* currently toggled? */
667 newsp = eval(cmd->c_expr,G_SCALAR,sp);/*let eval undo it*/
668 cmdflags = copyopt(cmd,cmd->c_expr[3].arg_ptr.arg_cmd);
671 newsp = eval(cmd->c_expr,G_SCALAR,sp);/* let eval do it */
672 if (cmd->c_expr->arg_type == O_FLOP) /* still toggled? */
673 cmdflags = copyopt(cmd,cmd->c_expr[4].arg_ptr.arg_cmd);
676 else if (cmdflags & CF_FLIP) {
677 if (cmd->c_expr->arg_type == O_FLOP) { /* currently toggled? */
678 match = TRUE; /* force on */
682 /* at this point, match says whether our expression was true */
685 if (cmdflags & CF_INVERT)
691 tainted = 0; /* modifier doesn't affect regular expression */
694 /* now to do the actual command, if any */
696 switch (cmd->c_type) {
698 fatal("panic: cmd_exec");
699 case C_EXPR: /* evaluated for side effects */
700 if (cmd->ucmd.acmd.ac_expr) { /* more to do? */
701 if (gimme == G_ARRAY) {
702 lastretstr = Nullstr;
704 lastsize = newsp - sp;
710 while (tmps_max > tmps_base) { /* clean up after last eval */
711 str_free(tmps_list[tmps_max]);
712 tmps_list[tmps_max--] = Nullstr;
714 newsp = eval(cmd->ucmd.acmd.ac_expr,gimme && (cmdflags&CF_TERM),sp);
715 st = stack->ary_array; /* possibly reallocated */
721 double value = str_gnum(STAB_STR(cmd->c_stab));
725 if (((double)match) > value)
726 --match; /* was fractional--truncate other way */
731 match = *(str_get(STAB_STR(cmd->c_stab))) & 255;
733 match -= cmd->ucmd.scmd.sc_offset;
736 else if (match > cmd->ucmd.scmd.sc_max)
737 match = cmd->ucmd.scmd.sc_max;
738 cmd = cmd->ucmd.scmd.sc_next[match];
739 goto tail_recursion_entry;
741 cmd = cmd->ucmd.ccmd.cc_alt;
742 goto tail_recursion_entry;
744 fatal("panic: ELSIF");
747 oldsave = savestack->ary_fill;
753 if (cmd->ucmd.ccmd.cc_true) {
756 debname[dlevel] = 't';
757 debdelim[dlevel] = '_';
758 if (++dlevel >= dlmax)
762 newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme && (cmdflags & CF_TERM),sp);
763 st = stack->ary_array; /* possibly reallocated */
767 if (savestack->ary_fill > oldsave)
768 restorelist(oldsave);
772 cmd = cmd->ucmd.ccmd.cc_alt;
773 goto tail_recursion_entry;
776 oldsave = savestack->ary_fill;
782 if (cmd->ucmd.ccmd.cc_true) {
785 debname[dlevel] = 'e';
786 debdelim[dlevel] = '_';
787 if (++dlevel >= dlmax)
791 newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme && (cmdflags & CF_TERM),sp);
792 st = stack->ary_array; /* possibly reallocated */
796 if (savestack->ary_fill > oldsave)
797 restorelist(oldsave);
804 if (!(cmdflags & CF_ONCE)) { /* first time through here? */
806 if (++loop_ptr >= loop_max) {
808 Renew(loop_stack, loop_max, struct loop);
810 loop_stack[loop_ptr].loop_label = cmd->c_label;
811 loop_stack[loop_ptr].loop_sp = sp;
814 deb("(Pushing label #%d %s)\n",
815 loop_ptr, cmd->c_label ? cmd->c_label : "");
822 match = setjmp(loop_stack[loop_ptr].loop_env);
824 st = stack->ary_array; /* possibly reallocated */
827 cmdflags = cmd->c_flags|CF_ONCE;
830 if (savestack->ary_fill > oldsave)
831 restorelist(oldsave);
834 fatal("longjmp returned bad value (%d)",match);
841 newsp = sp + lastsize;
864 oldsave = savestack->ary_fill;
869 if (cmd->ucmd.ccmd.cc_true) {
872 debname[dlevel] = 't';
873 debdelim[dlevel] = '_';
874 if (++dlevel >= dlmax)
878 newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme && (cmdflags & CF_TERM),sp);
879 st = stack->ary_array; /* possibly reallocated */
882 /* actually, this spot is rarely reached anymore since the above
883 * cmd_exec() returns through longjmp(). Hooray for structure.
889 if (cmd->ucmd.ccmd.cc_alt) {
892 debname[dlevel] = 'a';
893 debdelim[dlevel] = '_';
894 if (++dlevel >= dlmax)
898 newsp = cmd_exec(cmd->ucmd.ccmd.cc_alt,gimme && (cmdflags & CF_TERM),sp);
899 st = stack->ary_array; /* possibly reallocated */
904 if (savestack->ary_fill > oldsave) {
905 if (cmdflags & CF_TERM) {
906 for (match = sp + 1; match <= newsp; match++)
907 st[match] = str_mortal(st[match]);
910 restorelist(oldsave);
913 dlevel = olddlevel - 1;
915 if (cmd->c_type != C_BLOCK)
916 goto until_loop; /* go back and evaluate conditional again */
918 if (cmdflags & CF_LOOP) {
919 cmdflags |= CF_COND; /* now test the condition */
926 if (cmdflags & CF_ONCE) {
929 tmps = loop_stack[loop_ptr].loop_label;
930 deb("(Popping label #%d %s)\n",loop_ptr, tmps ? tmps : "");
934 if ((cmdflags & CF_OPTIMIZE) == CFT_ARRAY &&
935 savestack->ary_fill > aryoptsave)
936 restorelist(aryoptsave);
939 goto tail_recursion_entry;
945 deb(pat,a1,a2,a3,a4,a5,a6,a7,a8)
950 fprintf(stderr,"%-4ld",(long)curcmd->c_line);
951 for (i=0; i<dlevel; i++)
952 fprintf(stderr,"%c%c ",debname[i],debdelim[i]);
953 fprintf(stderr,pat,a1,a2,a3,a4,a5,a6,a7,a8);
965 fprintf(stderr,"%-4ld",(long)curcmd->c_line);
966 for (i=0; i<dlevel; i++)
967 fprintf(stderr,"%c%c ",debname[i],debdelim[i]);
969 pat = va_arg(args, char *);
970 (void) vfprintf(stderr,pat,args);
980 cmd->c_flags &= CF_ONCE|CF_COND|CF_LOOP;
981 cmd->c_flags |= which->c_flags;
982 cmd->c_short = which->c_short;
983 cmd->c_slen = which->c_slen;
984 cmd->c_stab = which->c_stab;
995 str->str_state = SS_SARY;
996 str->str_u.str_stab = stab;
998 Safefree(str->str_ptr);
999 str->str_ptr = Nullch;
1002 str->str_ptr = (char*)stab_array(stab);
1003 (void)apush(savestack,str); /* save array ptr */
1004 stab_xarray(stab) = Null(ARRAY*);
1005 return stab_xarray(aadd(stab));
1014 str = Str_new(11,0);
1015 str->str_state = SS_SHASH;
1016 str->str_u.str_stab = stab;
1018 Safefree(str->str_ptr);
1019 str->str_ptr = Nullch;
1022 str->str_ptr = (char*)stab_hash(stab);
1023 (void)apush(savestack,str); /* save hash ptr */
1024 stab_xhash(stab) = Null(HASH*);
1025 return stab_xhash(hadd(stab));
1034 (void)apush(savestack,item); /* remember the pointer */
1035 str = Str_new(12,0);
1037 (void)apush(savestack,str); /* remember the value */
1046 str = Str_new(13,0);
1047 str->str_state = SS_SINT;
1048 str->str_u.str_useful = (long)*intp; /* remember value */
1050 Safefree(str->str_ptr);
1053 str->str_ptr = (char*)intp; /* remember pointer */
1054 (void)apush(savestack,str);
1063 str = Str_new(14,0);
1064 str->str_state = SS_SLONG;
1065 str->str_u.str_useful = *longp; /* remember value */
1067 Safefree(str->str_ptr);
1070 str->str_ptr = (char*)longp; /* remember pointer */
1071 (void)apush(savestack,str);
1080 str = Str_new(15,0);
1081 str->str_state = SS_SSTRP;
1082 str->str_magic = *sptr; /* remember value */
1084 Safefree(str->str_ptr);
1087 str->str_ptr = (char*)sptr; /* remember pointer */
1088 (void)apush(savestack,str);
1097 str = Str_new(16,0);
1098 str->str_state = SS_SNSTAB;
1099 str->str_magic = (STR*)stab; /* remember which stab to free */
1100 (void)apush(savestack,str);
1109 str = Str_new(17,0);
1110 str->str_state = SS_SHPTR;
1111 str->str_u.str_hash = *hptr; /* remember value */
1113 Safefree(str->str_ptr);
1116 str->str_ptr = (char*)hptr; /* remember pointer */
1117 (void)apush(savestack,str);
1126 str = Str_new(17,0);
1127 str->str_state = SS_SAPTR;
1128 str->str_u.str_array = *aptr; /* remember value */
1130 Safefree(str->str_ptr);
1133 str->str_ptr = (char*)aptr; /* remember pointer */
1134 (void)apush(savestack,str);
1138 savelist(sarg,maxsarg)
1139 register STR **sarg;
1145 for (i = 1; i <= maxsarg; i++) {
1146 (void)apush(savestack,sarg[i]); /* remember the pointer */
1147 str = Str_new(18,0);
1148 str_sset(str,sarg[i]);
1149 (void)apush(savestack,str); /* remember the value */
1150 sarg[i]->str_u.str_useful = -1;
1159 register STR *value;
1160 register STAB *stab;
1163 fatal("panic: corrupt saved stack index");
1164 while (savestack->ary_fill > base) {
1165 value = apop(savestack);
1166 switch (value->str_state) {
1167 case SS_NORM: /* normal string */
1169 str = apop(savestack);
1170 str_replace(str,value);
1173 case SS_SARY: /* array reference */
1174 stab = value->str_u.str_stab;
1175 afree(stab_xarray(stab));
1176 stab_xarray(stab) = (ARRAY*)value->str_ptr;
1177 value->str_ptr = Nullch;
1180 case SS_SHASH: /* hash reference */
1181 stab = value->str_u.str_stab;
1182 (void)hfree(stab_xhash(stab), FALSE);
1183 stab_xhash(stab) = (HASH*)value->str_ptr;
1184 value->str_ptr = Nullch;
1187 case SS_SINT: /* int reference */
1188 *((int*)value->str_ptr) = (int)value->str_u.str_useful;
1189 value->str_ptr = Nullch;
1192 case SS_SLONG: /* long reference */
1193 *((long*)value->str_ptr) = value->str_u.str_useful;
1194 value->str_ptr = Nullch;
1197 case SS_SSTRP: /* STR* reference */
1198 *((STR**)value->str_ptr) = value->str_magic;
1199 value->str_magic = Nullstr;
1200 value->str_ptr = Nullch;
1203 case SS_SHPTR: /* HASH* reference */
1204 *((HASH**)value->str_ptr) = value->str_u.str_hash;
1205 value->str_ptr = Nullch;
1208 case SS_SAPTR: /* ARRAY* reference */
1209 *((ARRAY**)value->str_ptr) = value->str_u.str_array;
1210 value->str_ptr = Nullch;
1214 stab = (STAB*)value->str_magic;
1215 value->str_magic = Nullstr;
1216 (void)stab_clear(stab);
1219 case SS_SCSV: /* callsave structure */
1221 CSV *csv = (CSV*) value->str_ptr;
1223 curcmd = csv->curcmd;
1224 curcsv = csv->curcsv;
1225 csv->sub->depth = csv->depth;
1226 if (csv->hasargs) { /* put back old @_ */
1227 afree(csv->argarray);
1228 stab_xarray(defstab) = csv->savearray;
1234 fatal("panic: restorelist inconsistency");
1244 Renew(debname, dlmax, char);
1245 Renew(debdelim, dlmax, char);