Commit | Line | Data |
68decaef |
1 | /* $RCSfile: cmd.c,v $$Revision: 4.0.1.5 $$Date: 92/06/08 12:00:39 $ |
a687059c |
2 | * |
2b317908 |
3 | * Copyright (c) 1991, Larry Wall |
a687059c |
4 | * |
2b317908 |
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. |
8d063cd8 |
7 | * |
8 | * $Log: cmd.c,v $ |
68decaef |
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 |
12 | * |
988174c1 |
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 |
16 | * |
55204971 |
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 |
21 | * |
2b317908 |
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 |
25 | * |
1c3d792e |
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 |
28 | * |
fe14fcc3 |
29 | * Revision 4.0 91/03/20 01:04:18 lwall |
30 | * 4.0 baseline. |
8d063cd8 |
31 | * |
32 | */ |
33 | |
8d063cd8 |
34 | #include "EXTERN.h" |
8d063cd8 |
35 | #include "perl.h" |
36 | |
a687059c |
37 | #ifdef I_VARARGS |
38 | # include <varargs.h> |
39 | #endif |
40 | |
68decaef |
41 | static STR strchop; |
8d063cd8 |
42 | |
a687059c |
43 | void grow_dlevel(); |
44 | |
d8f2e4cc |
45 | /* do longjmps() clobber register variables? */ |
46 | |
2b317908 |
47 | #if defined(cray) || defined(STANDARD_C) |
d8f2e4cc |
48 | #define JMPCLOBBER |
49 | #endif |
50 | |
8d063cd8 |
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. |
54 | */ |
55 | |
a687059c |
56 | int |
d8f2e4cc |
57 | cmd_exec(cmdparm,gimme,sp) |
58 | CMD *VOLATILE cmdparm; |
afd9f252 |
59 | VOLATILE int gimme; |
60 | VOLATILE int sp; |
8d063cd8 |
61 | { |
d8f2e4cc |
62 | register CMD *cmd = cmdparm; |
63 | SPAT *VOLATILE oldspat; |
afd9f252 |
64 | VOLATILE int firstsave = savestack->ary_fill; |
d8f2e4cc |
65 | VOLATILE int oldsave; |
66 | VOLATILE int aryoptsave; |
8d063cd8 |
67 | #ifdef DEBUGGING |
d8f2e4cc |
68 | VOLATILE int olddlevel; |
69 | VOLATILE int entdlevel; |
8d063cd8 |
70 | #endif |
a687059c |
71 | register STR *retstr = &str_undef; |
8d063cd8 |
72 | register char *tmps; |
73 | register int cmdflags; |
378cc40b |
74 | register int match; |
8d063cd8 |
75 | register char *go_to = goto_targ; |
a687059c |
76 | register int newsp = -2; |
77 | register STR **st = stack->ary_array; |
ff2452de |
78 | FILE *VOLATILE fp; |
79 | ARRAY *VOLATILE ar; |
8d063cd8 |
80 | |
a687059c |
81 | lastsize = 0; |
8d063cd8 |
82 | #ifdef DEBUGGING |
83 | entdlevel = dlevel; |
84 | #endif |
85 | tail_recursion_entry: |
86 | #ifdef DEBUGGING |
87 | dlevel = entdlevel; |
68decaef |
88 | if (debug & 4) |
89 | deb("mortals = (%d/%d) stack, = (%d/%d)\n", |
90 | tmps_max, tmps_base, |
91 | savestack->ary_fill, firstsave); |
8d063cd8 |
92 | #endif |
a687059c |
93 | #ifdef TAINT |
94 | tainted = 0; /* Each statement is presumed innocent */ |
95 | #endif |
96 | if (cmd == Nullcmd) { |
97 | if (gimme == G_ARRAY && newsp > -2) |
98 | return newsp; |
99 | else { |
100 | st[++sp] = retstr; |
101 | return sp; |
102 | } |
103 | } |
8d063cd8 |
104 | cmdflags = cmd->c_flags; /* hopefully load register */ |
105 | if (go_to) { |
106 | if (cmd->c_label && strEQ(go_to,cmd->c_label)) |
107 | goto_targ = go_to = Nullch; /* here at last */ |
108 | else { |
109 | switch (cmd->c_type) { |
110 | case C_IF: |
111 | oldspat = curspat; |
378cc40b |
112 | oldsave = savestack->ary_fill; |
8d063cd8 |
113 | #ifdef DEBUGGING |
114 | olddlevel = dlevel; |
115 | #endif |
116 | retstr = &str_yes; |
a687059c |
117 | newsp = -2; |
8d063cd8 |
118 | if (cmd->ucmd.ccmd.cc_true) { |
119 | #ifdef DEBUGGING |
378cc40b |
120 | if (debug) { |
121 | debname[dlevel] = 't'; |
a687059c |
122 | debdelim[dlevel] = '_'; |
123 | if (++dlevel >= dlmax) |
124 | grow_dlevel(); |
378cc40b |
125 | } |
8d063cd8 |
126 | #endif |
21d892ea |
127 | newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme && (cmdflags & CF_TERM),sp); |
a687059c |
128 | st = stack->ary_array; /* possibly reallocated */ |
129 | retstr = st[newsp]; |
8d063cd8 |
130 | } |
a687059c |
131 | if (!goto_targ) |
8d063cd8 |
132 | go_to = Nullch; |
a687059c |
133 | curspat = oldspat; |
134 | if (savestack->ary_fill > oldsave) |
135 | restorelist(oldsave); |
8d063cd8 |
136 | #ifdef DEBUGGING |
a687059c |
137 | dlevel = olddlevel; |
8d063cd8 |
138 | #endif |
a687059c |
139 | cmd = cmd->ucmd.ccmd.cc_alt; |
140 | goto tail_recursion_entry; |
141 | case C_ELSE: |
142 | oldspat = curspat; |
143 | oldsave = savestack->ary_fill; |
144 | #ifdef DEBUGGING |
145 | olddlevel = dlevel; |
146 | #endif |
147 | retstr = &str_undef; |
148 | newsp = -2; |
149 | if (cmd->ucmd.ccmd.cc_true) { |
150 | #ifdef DEBUGGING |
151 | if (debug) { |
152 | debname[dlevel] = 'e'; |
153 | debdelim[dlevel] = '_'; |
154 | if (++dlevel >= dlmax) |
155 | grow_dlevel(); |
8d063cd8 |
156 | } |
a687059c |
157 | #endif |
21d892ea |
158 | newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme && (cmdflags & CF_TERM),sp); |
a687059c |
159 | st = stack->ary_array; /* possibly reallocated */ |
160 | retstr = st[newsp]; |
8d063cd8 |
161 | } |
162 | if (!goto_targ) |
163 | go_to = Nullch; |
164 | curspat = oldspat; |
378cc40b |
165 | if (savestack->ary_fill > oldsave) |
166 | restorelist(oldsave); |
8d063cd8 |
167 | #ifdef DEBUGGING |
168 | dlevel = olddlevel; |
169 | #endif |
170 | break; |
171 | case C_BLOCK: |
172 | case C_WHILE: |
173 | if (!(cmdflags & CF_ONCE)) { |
174 | cmdflags |= CF_ONCE; |
a687059c |
175 | if (++loop_ptr >= loop_max) { |
176 | loop_max += 128; |
177 | Renew(loop_stack, loop_max, struct loop); |
178 | } |
8d063cd8 |
179 | loop_stack[loop_ptr].loop_label = cmd->c_label; |
a687059c |
180 | loop_stack[loop_ptr].loop_sp = sp; |
8d063cd8 |
181 | #ifdef DEBUGGING |
182 | if (debug & 4) { |
183 | deb("(Pushing label #%d %s)\n", |
a687059c |
184 | loop_ptr, cmd->c_label ? cmd->c_label : ""); |
8d063cd8 |
185 | } |
186 | #endif |
187 | } |
d8f2e4cc |
188 | #ifdef JMPCLOBBER |
189 | cmdparm = cmd; |
190 | #endif |
e5d73d77 |
191 | match = setjmp(loop_stack[loop_ptr].loop_env); |
192 | if (match) { |
a687059c |
193 | st = stack->ary_array; /* possibly reallocated */ |
afd9f252 |
194 | #ifdef JMPCLOBBER |
d8f2e4cc |
195 | cmd = cmdparm; |
196 | cmdflags = cmd->c_flags|CF_ONCE; |
197 | #endif |
afd9f252 |
198 | if (savestack->ary_fill > oldsave) |
199 | restorelist(oldsave); |
d8f2e4cc |
200 | switch (match) { |
afd9f252 |
201 | default: |
202 | fatal("longjmp returned bad value (%d)",match); |
d8f2e4cc |
203 | case O_LAST: /* not done unless go_to found */ |
204 | go_to = Nullch; |
205 | if (lastretstr) { |
206 | retstr = lastretstr; |
207 | newsp = -2; |
208 | } |
209 | else { |
210 | newsp = sp + lastsize; |
211 | retstr = st[newsp]; |
212 | } |
8d063cd8 |
213 | #ifdef DEBUGGING |
d8f2e4cc |
214 | olddlevel = dlevel; |
8d063cd8 |
215 | #endif |
d8f2e4cc |
216 | curspat = oldspat; |
d8f2e4cc |
217 | goto next_cmd; |
218 | case O_NEXT: /* not done unless go_to found */ |
219 | go_to = Nullch; |
220 | #ifdef JMPCLOBBER |
221 | newsp = -2; |
222 | retstr = &str_undef; |
223 | #endif |
224 | goto next_iter; |
225 | case O_REDO: /* not done unless go_to found */ |
226 | go_to = Nullch; |
227 | #ifdef JMPCLOBBER |
228 | newsp = -2; |
229 | retstr = &str_undef; |
230 | #endif |
231 | goto doit; |
232 | } |
8d063cd8 |
233 | } |
234 | oldspat = curspat; |
378cc40b |
235 | oldsave = savestack->ary_fill; |
8d063cd8 |
236 | #ifdef DEBUGGING |
237 | olddlevel = dlevel; |
238 | #endif |
239 | if (cmd->ucmd.ccmd.cc_true) { |
240 | #ifdef DEBUGGING |
378cc40b |
241 | if (debug) { |
242 | debname[dlevel] = 't'; |
a687059c |
243 | debdelim[dlevel] = '_'; |
244 | if (++dlevel >= dlmax) |
245 | grow_dlevel(); |
378cc40b |
246 | } |
8d063cd8 |
247 | #endif |
21d892ea |
248 | newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme && (cmdflags & CF_TERM),sp); |
a687059c |
249 | st = stack->ary_array; /* possibly reallocated */ |
55204971 |
250 | if (newsp >= 0) |
251 | retstr = st[newsp]; |
8d063cd8 |
252 | } |
253 | if (!goto_targ) { |
254 | go_to = Nullch; |
255 | goto next_iter; |
256 | } |
257 | #ifdef DEBUGGING |
258 | dlevel = olddlevel; |
259 | #endif |
260 | if (cmd->ucmd.ccmd.cc_alt) { |
261 | #ifdef DEBUGGING |
378cc40b |
262 | if (debug) { |
263 | debname[dlevel] = 'a'; |
a687059c |
264 | debdelim[dlevel] = '_'; |
265 | if (++dlevel >= dlmax) |
266 | grow_dlevel(); |
378cc40b |
267 | } |
8d063cd8 |
268 | #endif |
21d892ea |
269 | newsp = cmd_exec(cmd->ucmd.ccmd.cc_alt,gimme && (cmdflags & CF_TERM),sp); |
a687059c |
270 | st = stack->ary_array; /* possibly reallocated */ |
55204971 |
271 | if (newsp >= 0) |
272 | retstr = st[newsp]; |
8d063cd8 |
273 | } |
274 | if (goto_targ) |
275 | break; |
276 | go_to = Nullch; |
277 | goto finish_while; |
278 | } |
279 | cmd = cmd->c_next; |
378cc40b |
280 | if (cmd && cmd->c_head == cmd) |
281 | /* reached end of while loop */ |
a687059c |
282 | return sp; /* targ isn't in this block */ |
378cc40b |
283 | if (cmdflags & CF_ONCE) { |
284 | #ifdef DEBUGGING |
285 | if (debug & 4) { |
a687059c |
286 | tmps = loop_stack[loop_ptr].loop_label; |
378cc40b |
287 | deb("(Popping label #%d %s)\n",loop_ptr, |
a687059c |
288 | tmps ? tmps : "" ); |
378cc40b |
289 | } |
290 | #endif |
291 | loop_ptr--; |
292 | } |
8d063cd8 |
293 | goto tail_recursion_entry; |
294 | } |
295 | } |
296 | |
297 | until_loop: |
298 | |
378cc40b |
299 | /* Set line number so run-time errors can be located */ |
300 | |
87250799 |
301 | curcmd = cmd; |
378cc40b |
302 | |
8d063cd8 |
303 | #ifdef DEBUGGING |
378cc40b |
304 | if (debug) { |
305 | if (debug & 2) { |
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, |
309 | curspat); |
310 | } |
311 | debname[dlevel] = cmdname[cmd->c_type][0]; |
a687059c |
312 | debdelim[dlevel] = '!'; |
313 | if (++dlevel >= dlmax) |
314 | grow_dlevel(); |
8d063cd8 |
315 | } |
8d063cd8 |
316 | #endif |
8d063cd8 |
317 | |
318 | /* Here is some common optimization */ |
319 | |
320 | if (cmdflags & CF_COND) { |
321 | switch (cmdflags & CF_OPTIMIZE) { |
322 | |
323 | case CFT_FALSE: |
378cc40b |
324 | retstr = cmd->c_short; |
a687059c |
325 | newsp = -2; |
8d063cd8 |
326 | match = FALSE; |
327 | if (cmdflags & CF_NESURE) |
328 | goto maybe; |
329 | break; |
330 | case CFT_TRUE: |
378cc40b |
331 | retstr = cmd->c_short; |
a687059c |
332 | newsp = -2; |
8d063cd8 |
333 | match = TRUE; |
334 | if (cmdflags & CF_EQSURE) |
335 | goto flipmaybe; |
336 | break; |
337 | |
338 | case CFT_REG: |
339 | retstr = STAB_STR(cmd->c_stab); |
a687059c |
340 | newsp = -2; |
8d063cd8 |
341 | match = str_true(retstr); /* => retstr = retstr, c2 should fix */ |
342 | if (cmdflags & (match ? CF_EQSURE : CF_NESURE)) |
343 | goto flipmaybe; |
344 | break; |
345 | |
346 | case CFT_ANCHOR: /* /^pat/ optimization */ |
347 | if (multiline) { |
378cc40b |
348 | if (*cmd->c_short->str_ptr && !(cmdflags & CF_EQSURE)) |
8d063cd8 |
349 | goto scanner; /* just unanchor it */ |
350 | else |
351 | break; /* must evaluate */ |
352 | } |
55204971 |
353 | match = 0; |
354 | goto strop; |
355 | |
8d063cd8 |
356 | case CFT_STROP: /* string op optimization */ |
55204971 |
357 | match = 1; |
358 | strop: |
8d063cd8 |
359 | retstr = STAB_STR(cmd->c_stab); |
a687059c |
360 | newsp = -2; |
361 | #ifndef I286 |
378cc40b |
362 | if (*cmd->c_short->str_ptr == *str_get(retstr) && |
55204971 |
363 | (match ? retstr->str_cur == cmd->c_slen - 1 : |
364 | retstr->str_cur >= cmd->c_slen) && |
a687059c |
365 | bcmp(cmd->c_short->str_ptr, str_get(retstr), |
366 | cmd->c_slen) == 0 ) { |
8d063cd8 |
367 | if (cmdflags & CF_EQSURE) { |
a687059c |
368 | if (sawampersand && (cmdflags & CF_OPTIMIZE) != CFT_STROP) { |
369 | curspat = Nullspat; |
370 | if (leftstab) |
371 | str_nset(stab_val(leftstab),"",0); |
372 | if (amperstab) |
373 | str_sset(stab_val(amperstab),cmd->c_short); |
374 | if (rightstab) |
375 | str_nset(stab_val(rightstab), |
376 | retstr->str_ptr + cmd->c_slen, |
377 | retstr->str_cur - cmd->c_slen); |
378 | } |
fe14fcc3 |
379 | if (cmd->c_spat) |
380 | lastspat = cmd->c_spat; |
8d063cd8 |
381 | match = !(cmdflags & CF_FIRSTNEG); |
988174c1 |
382 | retstr = match ? &str_yes : &str_no; |
8d063cd8 |
383 | goto flipmaybe; |
384 | } |
385 | } |
386 | else if (cmdflags & CF_NESURE) { |
387 | match = cmdflags & CF_FIRSTNEG; |
988174c1 |
388 | retstr = match ? &str_yes : &str_no; |
8d063cd8 |
389 | goto flipmaybe; |
390 | } |
a687059c |
391 | #else |
392 | { |
393 | char *zap1, *zap2, zap1c, zap2c; |
394 | int zaplen; |
988174c1 |
395 | int lenok; |
a687059c |
396 | |
397 | zap1 = cmd->c_short->str_ptr; |
398 | zap2 = str_get(retstr); |
399 | zap1c = *zap1; |
400 | zap2c = *zap2; |
401 | zaplen = cmd->c_slen; |
988174c1 |
402 | if (match) |
403 | lenok = (retstr->str_cur == cmd->c_slen - 1); |
404 | else |
405 | lenok = (retstr->str_cur >= cmd->c_slen); |
406 | if ((zap1c == zap2c) && lenok && (bcmp(zap1, zap2, zaplen) == 0)) { |
a687059c |
407 | if (cmdflags & CF_EQSURE) { |
408 | if (sawampersand && |
409 | (cmdflags & CF_OPTIMIZE) != CFT_STROP) { |
410 | curspat = Nullspat; |
411 | if (leftstab) |
412 | str_nset(stab_val(leftstab),"",0); |
413 | if (amperstab) |
414 | str_sset(stab_val(amperstab),cmd->c_short); |
415 | if (rightstab) |
416 | str_nset(stab_val(rightstab), |
417 | retstr->str_ptr + cmd->c_slen, |
418 | retstr->str_cur - cmd->c_slen); |
419 | } |
fe14fcc3 |
420 | if (cmd->c_spat) |
421 | lastspat = cmd->c_spat; |
a687059c |
422 | match = !(cmdflags & CF_FIRSTNEG); |
988174c1 |
423 | retstr = match ? &str_yes : &str_no; |
a687059c |
424 | goto flipmaybe; |
425 | } |
426 | } |
427 | else if (cmdflags & CF_NESURE) { |
428 | match = cmdflags & CF_FIRSTNEG; |
988174c1 |
429 | retstr = match ? &str_yes : &str_no; |
a687059c |
430 | goto flipmaybe; |
431 | } |
432 | } |
433 | #endif |
8d063cd8 |
434 | break; /* must evaluate */ |
435 | |
436 | case CFT_SCAN: /* non-anchored search */ |
437 | scanner: |
438 | retstr = STAB_STR(cmd->c_stab); |
a687059c |
439 | newsp = -2; |
440 | if (retstr->str_pok & SP_STUDIED) |
378cc40b |
441 | if (screamfirst[cmd->c_short->str_rare] >= 0) |
442 | tmps = screaminstr(retstr, cmd->c_short); |
443 | else |
444 | tmps = Nullch; |
445 | else { |
446 | tmps = str_get(retstr); /* make sure it's pok */ |
a687059c |
447 | #ifndef lint |
448 | tmps = fbminstr((unsigned char*)tmps, |
449 | (unsigned char*)tmps + retstr->str_cur, cmd->c_short); |
450 | #endif |
378cc40b |
451 | } |
452 | if (tmps) { |
8d063cd8 |
453 | if (cmdflags & CF_EQSURE) { |
a687059c |
454 | ++cmd->c_short->str_u.str_useful; |
455 | if (sawampersand) { |
456 | curspat = Nullspat; |
457 | if (leftstab) |
458 | str_nset(stab_val(leftstab),retstr->str_ptr, |
459 | tmps - retstr->str_ptr); |
460 | if (amperstab) |
fe14fcc3 |
461 | str_nset(stab_val(amperstab), |
462 | tmps, cmd->c_short->str_cur); |
a687059c |
463 | if (rightstab) |
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); |
468 | } |
fe14fcc3 |
469 | lastspat = cmd->c_spat; |
8d063cd8 |
470 | match = !(cmdflags & CF_FIRSTNEG); |
988174c1 |
471 | retstr = match ? &str_yes : &str_no; |
8d063cd8 |
472 | goto flipmaybe; |
473 | } |
378cc40b |
474 | else |
475 | hint = tmps; |
476 | } |
477 | else { |
478 | if (cmdflags & CF_NESURE) { |
a687059c |
479 | ++cmd->c_short->str_u.str_useful; |
378cc40b |
480 | match = cmdflags & CF_FIRSTNEG; |
988174c1 |
481 | retstr = match ? &str_yes : &str_no; |
378cc40b |
482 | goto flipmaybe; |
483 | } |
484 | } |
a687059c |
485 | if (--cmd->c_short->str_u.str_useful < 0) { |
ff2452de |
486 | cmdflags &= ~CF_OPTIMIZE; |
378cc40b |
487 | cmdflags |= CFT_EVAL; /* never try this optimization again */ |
ff2452de |
488 | cmd->c_flags = (cmdflags & ~CF_ONCE); |
378cc40b |
489 | } |
490 | break; /* must evaluate */ |
491 | |
492 | case CFT_NUMOP: /* numeric op optimization */ |
493 | retstr = STAB_STR(cmd->c_stab); |
a687059c |
494 | newsp = -2; |
378cc40b |
495 | switch (cmd->c_slen) { |
496 | case O_EQ: |
a687059c |
497 | if (dowarn) { |
498 | if ((!retstr->str_nok && !looks_like_number(retstr))) |
499 | warn("Possible use of == on string value"); |
500 | } |
501 | match = (str_gnum(retstr) == cmd->c_short->str_u.str_nval); |
378cc40b |
502 | break; |
503 | case O_NE: |
a687059c |
504 | match = (str_gnum(retstr) != cmd->c_short->str_u.str_nval); |
378cc40b |
505 | break; |
506 | case O_LT: |
a687059c |
507 | match = (str_gnum(retstr) < cmd->c_short->str_u.str_nval); |
378cc40b |
508 | break; |
509 | case O_LE: |
a687059c |
510 | match = (str_gnum(retstr) <= cmd->c_short->str_u.str_nval); |
378cc40b |
511 | break; |
512 | case O_GT: |
a687059c |
513 | match = (str_gnum(retstr) > cmd->c_short->str_u.str_nval); |
378cc40b |
514 | break; |
515 | case O_GE: |
a687059c |
516 | match = (str_gnum(retstr) >= cmd->c_short->str_u.str_nval); |
378cc40b |
517 | break; |
518 | } |
519 | if (match) { |
520 | if (cmdflags & CF_EQSURE) { |
521 | retstr = &str_yes; |
522 | goto flipmaybe; |
523 | } |
8d063cd8 |
524 | } |
525 | else if (cmdflags & CF_NESURE) { |
8d063cd8 |
526 | retstr = &str_no; |
527 | goto flipmaybe; |
528 | } |
529 | break; /* must evaluate */ |
530 | |
378cc40b |
531 | case CFT_INDGETS: /* while (<$foo>) */ |
532 | last_in_stab = stabent(str_get(STAB_STR(cmd->c_stab)),TRUE); |
a687059c |
533 | if (!stab_io(last_in_stab)) |
534 | stab_io(last_in_stab) = stio_new(); |
378cc40b |
535 | goto dogets; |
8d063cd8 |
536 | case CFT_GETS: /* really a while (<file>) */ |
537 | last_in_stab = cmd->c_stab; |
378cc40b |
538 | dogets: |
a687059c |
539 | fp = stab_io(last_in_stab)->ifp; |
540 | retstr = stab_val(defstab); |
541 | newsp = -2; |
bf38876a |
542 | keepgoing: |
a687059c |
543 | if (fp && str_gets(retstr, fp, 0)) { |
544 | if (*retstr->str_ptr == '0' && retstr->str_cur == 1) |
378cc40b |
545 | match = FALSE; |
546 | else |
547 | match = TRUE; |
a687059c |
548 | stab_io(last_in_stab)->lines++; |
8d063cd8 |
549 | } |
bf38876a |
550 | else if (stab_io(last_in_stab)->flags & IOF_ARGV) { |
551 | if (!fp) |
552 | goto doeval; /* first time through */ |
553 | fp = nextargv(last_in_stab); |
554 | if (fp) |
555 | goto keepgoing; |
556 | (void)do_close(last_in_stab,FALSE); |
557 | stab_io(last_in_stab)->flags |= IOF_START; |
558 | retstr = &str_undef; |
559 | match = FALSE; |
560 | } |
8d063cd8 |
561 | else { |
a687059c |
562 | retstr = &str_undef; |
8d063cd8 |
563 | match = FALSE; |
564 | } |
565 | goto flipmaybe; |
566 | case CFT_EVAL: |
567 | break; |
568 | case CFT_UNFLIP: |
fe14fcc3 |
569 | while (tmps_max > tmps_base) { /* clean up after last eval */ |
570 | str_free(tmps_list[tmps_max]); |
571 | tmps_list[tmps_max--] = Nullstr; |
572 | } |
a687059c |
573 | newsp = eval(cmd->c_expr,gimme && (cmdflags & CF_TERM),sp); |
574 | st = stack->ary_array; /* possibly reallocated */ |
575 | retstr = st[newsp]; |
8d063cd8 |
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); |
579 | goto maybe; |
580 | case CFT_CHOP: |
a687059c |
581 | retstr = stab_val(cmd->c_stab); |
582 | newsp = -2; |
8d063cd8 |
583 | match = (retstr->str_cur != 0); |
584 | tmps = str_get(retstr); |
585 | tmps += retstr->str_cur - match; |
68decaef |
586 | str_nset(&strchop,tmps,match); |
8d063cd8 |
587 | *tmps = '\0'; |
588 | retstr->str_nok = 0; |
589 | retstr->str_cur = tmps - retstr->str_ptr; |
fe14fcc3 |
590 | STABSET(retstr); |
68decaef |
591 | retstr = &strchop; |
8d063cd8 |
592 | goto flipmaybe; |
378cc40b |
593 | case CFT_ARRAY: |
0d3e774c |
594 | match = cmd->c_short->str_u.str_useful; /* just to get register */ |
378cc40b |
595 | |
a687059c |
596 | if (match < 0) { /* first time through here? */ |
0d3e774c |
597 | ar = stab_array(cmd->c_expr[1].arg_ptr.arg_stab); |
a687059c |
598 | aryoptsave = savestack->ary_fill; |
599 | savesptr(&stab_val(cmd->c_stab)); |
0d3e774c |
600 | savelong(&cmd->c_short->str_u.str_useful); |
a687059c |
601 | } |
afd9f252 |
602 | else { |
0d3e774c |
603 | ar = stab_xarray(cmd->c_expr[1].arg_ptr.arg_stab); |
afd9f252 |
604 | if (cmd->c_type != C_WHILE && savestack->ary_fill > firstsave) |
605 | restorelist(firstsave); |
606 | } |
378cc40b |
607 | |
a687059c |
608 | if (match >= ar->ary_fill) { /* we're in LAST, probably */ |
55204971 |
609 | if (match < 0 && /* er, probably not... */ |
610 | savestack->ary_fill > aryoptsave) |
611 | restorelist(aryoptsave); |
a687059c |
612 | retstr = &str_undef; |
0d3e774c |
613 | cmd->c_short->str_u.str_useful = -1; /* actually redundant */ |
378cc40b |
614 | match = FALSE; |
615 | } |
616 | else { |
617 | match++; |
39c3038c |
618 | if (!(retstr = ar->ary_array[match])) |
619 | retstr = afetch(ar,match,TRUE); |
620 | stab_val(cmd->c_stab) = retstr; |
0d3e774c |
621 | cmd->c_short->str_u.str_useful = match; |
378cc40b |
622 | match = TRUE; |
623 | } |
a687059c |
624 | newsp = -2; |
378cc40b |
625 | goto maybe; |
39c3038c |
626 | case CFT_D1: |
627 | break; |
628 | case CFT_D0: |
629 | if (DBsingle->str_u.str_nval != 0) |
630 | break; |
631 | if (DBsignal->str_u.str_nval != 0) |
632 | break; |
633 | if (DBtrace->str_u.str_nval != 0) |
634 | break; |
635 | goto next_cmd; |
8d063cd8 |
636 | } |
637 | |
638 | /* we have tried to make this normal case as abnormal as possible */ |
639 | |
640 | doeval: |
a687059c |
641 | if (gimme == G_ARRAY) { |
642 | lastretstr = Nullstr; |
643 | lastspbase = sp; |
644 | lastsize = newsp - sp; |
fe14fcc3 |
645 | if (lastsize < 0) |
646 | lastsize = 0; |
a687059c |
647 | } |
648 | else |
649 | lastretstr = retstr; |
fe14fcc3 |
650 | while (tmps_max > tmps_base) { /* clean up after last eval */ |
651 | str_free(tmps_list[tmps_max]); |
652 | tmps_list[tmps_max--] = Nullstr; |
653 | } |
87250799 |
654 | newsp = eval(cmd->c_expr, |
655 | gimme && (cmdflags & CF_TERM) && cmd->c_type == C_EXPR && |
656 | !cmd->ucmd.acmd.ac_expr, |
657 | sp); |
a687059c |
658 | st = stack->ary_array; /* possibly reallocated */ |
659 | retstr = st[newsp]; |
d8f2e4cc |
660 | if (newsp > sp && retstr) |
a687059c |
661 | match = str_true(retstr); |
662 | else |
663 | match = FALSE; |
8d063cd8 |
664 | goto maybe; |
665 | |
666 | /* if flipflop was true, flop it */ |
667 | |
668 | flipmaybe: |
669 | if (match && cmdflags & CF_FLIP) { |
fe14fcc3 |
670 | while (tmps_max > tmps_base) { /* clean up after last eval */ |
671 | str_free(tmps_list[tmps_max]); |
672 | tmps_list[tmps_max--] = Nullstr; |
673 | } |
8d063cd8 |
674 | if (cmd->c_expr->arg_type == O_FLOP) { /* currently toggled? */ |
a687059c |
675 | newsp = eval(cmd->c_expr,G_SCALAR,sp);/*let eval undo it*/ |
8d063cd8 |
676 | cmdflags = copyopt(cmd,cmd->c_expr[3].arg_ptr.arg_cmd); |
677 | } |
678 | else { |
a687059c |
679 | newsp = eval(cmd->c_expr,G_SCALAR,sp);/* let eval do it */ |
8d063cd8 |
680 | if (cmd->c_expr->arg_type == O_FLOP) /* still toggled? */ |
681 | cmdflags = copyopt(cmd,cmd->c_expr[4].arg_ptr.arg_cmd); |
682 | } |
683 | } |
684 | else if (cmdflags & CF_FLIP) { |
685 | if (cmd->c_expr->arg_type == O_FLOP) { /* currently toggled? */ |
686 | match = TRUE; /* force on */ |
687 | } |
688 | } |
689 | |
690 | /* at this point, match says whether our expression was true */ |
691 | |
692 | maybe: |
693 | if (cmdflags & CF_INVERT) |
694 | match = !match; |
a687059c |
695 | if (!match) |
378cc40b |
696 | goto next_cmd; |
8d063cd8 |
697 | } |
a687059c |
698 | #ifdef TAINT |
699 | tainted = 0; /* modifier doesn't affect regular expression */ |
700 | #endif |
8d063cd8 |
701 | |
702 | /* now to do the actual command, if any */ |
703 | |
704 | switch (cmd->c_type) { |
705 | case C_NULL: |
378cc40b |
706 | fatal("panic: cmd_exec"); |
8d063cd8 |
707 | case C_EXPR: /* evaluated for side effects */ |
708 | if (cmd->ucmd.acmd.ac_expr) { /* more to do? */ |
a687059c |
709 | if (gimme == G_ARRAY) { |
710 | lastretstr = Nullstr; |
711 | lastspbase = sp; |
712 | lastsize = newsp - sp; |
fe14fcc3 |
713 | if (lastsize < 0) |
714 | lastsize = 0; |
a687059c |
715 | } |
716 | else |
717 | lastretstr = retstr; |
fe14fcc3 |
718 | while (tmps_max > tmps_base) { /* clean up after last eval */ |
719 | str_free(tmps_list[tmps_max]); |
720 | tmps_list[tmps_max--] = Nullstr; |
721 | } |
a687059c |
722 | newsp = eval(cmd->ucmd.acmd.ac_expr,gimme && (cmdflags&CF_TERM),sp); |
723 | st = stack->ary_array; /* possibly reallocated */ |
724 | retstr = st[newsp]; |
8d063cd8 |
725 | } |
726 | break; |
a687059c |
727 | case C_NSWITCH: |
87250799 |
728 | { |
729 | double value = str_gnum(STAB_STR(cmd->c_stab)); |
730 | |
731 | match = (int)value; |
732 | if (value < 0.0) { |
733 | if (((double)match) > value) |
734 | --match; /* was fractional--truncate other way */ |
735 | } |
736 | } |
a687059c |
737 | goto doswitch; |
738 | case C_CSWITCH: |
68decaef |
739 | if (multiline) { |
740 | cmd = cmd->c_next; /* can't assume anything */ |
741 | goto tail_recursion_entry; |
742 | } |
a687059c |
743 | match = *(str_get(STAB_STR(cmd->c_stab))) & 255; |
744 | doswitch: |
745 | match -= cmd->ucmd.scmd.sc_offset; |
746 | if (match < 0) |
747 | match = 0; |
748 | else if (match > cmd->ucmd.scmd.sc_max) |
ff2452de |
749 | match = cmd->ucmd.scmd.sc_max; |
a687059c |
750 | cmd = cmd->ucmd.scmd.sc_next[match]; |
751 | goto tail_recursion_entry; |
752 | case C_NEXT: |
753 | cmd = cmd->ucmd.ccmd.cc_alt; |
754 | goto tail_recursion_entry; |
755 | case C_ELSIF: |
756 | fatal("panic: ELSIF"); |
8d063cd8 |
757 | case C_IF: |
758 | oldspat = curspat; |
378cc40b |
759 | oldsave = savestack->ary_fill; |
8d063cd8 |
760 | #ifdef DEBUGGING |
761 | olddlevel = dlevel; |
762 | #endif |
a687059c |
763 | retstr = &str_yes; |
764 | newsp = -2; |
765 | if (cmd->ucmd.ccmd.cc_true) { |
8d063cd8 |
766 | #ifdef DEBUGGING |
a687059c |
767 | if (debug) { |
768 | debname[dlevel] = 't'; |
769 | debdelim[dlevel] = '_'; |
770 | if (++dlevel >= dlmax) |
771 | grow_dlevel(); |
8d063cd8 |
772 | } |
a687059c |
773 | #endif |
21d892ea |
774 | newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme && (cmdflags & CF_TERM),sp); |
a687059c |
775 | st = stack->ary_array; /* possibly reallocated */ |
776 | retstr = st[newsp]; |
8d063cd8 |
777 | } |
a687059c |
778 | curspat = oldspat; |
779 | if (savestack->ary_fill > oldsave) |
780 | restorelist(oldsave); |
8d063cd8 |
781 | #ifdef DEBUGGING |
a687059c |
782 | dlevel = olddlevel; |
8d063cd8 |
783 | #endif |
a687059c |
784 | cmd = cmd->ucmd.ccmd.cc_alt; |
785 | goto tail_recursion_entry; |
786 | case C_ELSE: |
787 | oldspat = curspat; |
788 | oldsave = savestack->ary_fill; |
789 | #ifdef DEBUGGING |
790 | olddlevel = dlevel; |
791 | #endif |
792 | retstr = &str_undef; |
793 | newsp = -2; |
794 | if (cmd->ucmd.ccmd.cc_true) { |
795 | #ifdef DEBUGGING |
796 | if (debug) { |
797 | debname[dlevel] = 'e'; |
798 | debdelim[dlevel] = '_'; |
799 | if (++dlevel >= dlmax) |
800 | grow_dlevel(); |
8d063cd8 |
801 | } |
a687059c |
802 | #endif |
21d892ea |
803 | newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme && (cmdflags & CF_TERM),sp); |
a687059c |
804 | st = stack->ary_array; /* possibly reallocated */ |
805 | retstr = st[newsp]; |
8d063cd8 |
806 | } |
807 | curspat = oldspat; |
378cc40b |
808 | if (savestack->ary_fill > oldsave) |
809 | restorelist(oldsave); |
8d063cd8 |
810 | #ifdef DEBUGGING |
811 | dlevel = olddlevel; |
812 | #endif |
813 | break; |
814 | case C_BLOCK: |
815 | case C_WHILE: |
816 | if (!(cmdflags & CF_ONCE)) { /* first time through here? */ |
817 | cmdflags |= CF_ONCE; |
a687059c |
818 | if (++loop_ptr >= loop_max) { |
819 | loop_max += 128; |
820 | Renew(loop_stack, loop_max, struct loop); |
821 | } |
8d063cd8 |
822 | loop_stack[loop_ptr].loop_label = cmd->c_label; |
a687059c |
823 | loop_stack[loop_ptr].loop_sp = sp; |
8d063cd8 |
824 | #ifdef DEBUGGING |
825 | if (debug & 4) { |
826 | deb("(Pushing label #%d %s)\n", |
a687059c |
827 | loop_ptr, cmd->c_label ? cmd->c_label : ""); |
8d063cd8 |
828 | } |
829 | #endif |
830 | } |
d8f2e4cc |
831 | #ifdef JMPCLOBBER |
832 | cmdparm = cmd; |
833 | #endif |
e5d73d77 |
834 | match = setjmp(loop_stack[loop_ptr].loop_env); |
835 | if (match) { |
a687059c |
836 | st = stack->ary_array; /* possibly reallocated */ |
afd9f252 |
837 | #ifdef JMPCLOBBER |
d8f2e4cc |
838 | cmd = cmdparm; |
839 | cmdflags = cmd->c_flags|CF_ONCE; |
840 | go_to = goto_targ; |
841 | #endif |
afd9f252 |
842 | if (savestack->ary_fill > oldsave) |
843 | restorelist(oldsave); |
d8f2e4cc |
844 | switch (match) { |
afd9f252 |
845 | default: |
846 | fatal("longjmp returned bad value (%d)",match); |
d8f2e4cc |
847 | case O_LAST: |
848 | if (lastretstr) { |
849 | retstr = lastretstr; |
850 | newsp = -2; |
851 | } |
852 | else { |
853 | newsp = sp + lastsize; |
854 | retstr = st[newsp]; |
855 | } |
856 | curspat = oldspat; |
d8f2e4cc |
857 | goto next_cmd; |
858 | case O_NEXT: |
859 | #ifdef JMPCLOBBER |
a687059c |
860 | newsp = -2; |
d8f2e4cc |
861 | retstr = &str_undef; |
862 | #endif |
863 | goto next_iter; |
864 | case O_REDO: |
36ce8bec |
865 | #ifdef DEBUGGING |
d8f2e4cc |
866 | dlevel = olddlevel; |
36ce8bec |
867 | #endif |
d8f2e4cc |
868 | #ifdef JMPCLOBBER |
869 | newsp = -2; |
870 | retstr = &str_undef; |
871 | #endif |
872 | goto doit; |
873 | } |
8d063cd8 |
874 | } |
875 | oldspat = curspat; |
378cc40b |
876 | oldsave = savestack->ary_fill; |
8d063cd8 |
877 | #ifdef DEBUGGING |
878 | olddlevel = dlevel; |
879 | #endif |
880 | doit: |
881 | if (cmd->ucmd.ccmd.cc_true) { |
882 | #ifdef DEBUGGING |
378cc40b |
883 | if (debug) { |
884 | debname[dlevel] = 't'; |
a687059c |
885 | debdelim[dlevel] = '_'; |
886 | if (++dlevel >= dlmax) |
887 | grow_dlevel(); |
378cc40b |
888 | } |
8d063cd8 |
889 | #endif |
21d892ea |
890 | newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme && (cmdflags & CF_TERM),sp); |
a687059c |
891 | st = stack->ary_array; /* possibly reallocated */ |
892 | retstr = st[newsp]; |
8d063cd8 |
893 | } |
378cc40b |
894 | /* actually, this spot is rarely reached anymore since the above |
8d063cd8 |
895 | * cmd_exec() returns through longjmp(). Hooray for structure. |
896 | */ |
897 | next_iter: |
898 | #ifdef DEBUGGING |
899 | dlevel = olddlevel; |
900 | #endif |
901 | if (cmd->ucmd.ccmd.cc_alt) { |
902 | #ifdef DEBUGGING |
378cc40b |
903 | if (debug) { |
904 | debname[dlevel] = 'a'; |
a687059c |
905 | debdelim[dlevel] = '_'; |
906 | if (++dlevel >= dlmax) |
907 | grow_dlevel(); |
378cc40b |
908 | } |
8d063cd8 |
909 | #endif |
21d892ea |
910 | newsp = cmd_exec(cmd->ucmd.ccmd.cc_alt,gimme && (cmdflags & CF_TERM),sp); |
a687059c |
911 | st = stack->ary_array; /* possibly reallocated */ |
912 | retstr = st[newsp]; |
8d063cd8 |
913 | } |
914 | finish_while: |
915 | curspat = oldspat; |
afd9f252 |
916 | if (savestack->ary_fill > oldsave) { |
917 | if (cmdflags & CF_TERM) { |
918 | for (match = sp + 1; match <= newsp; match++) |
fe14fcc3 |
919 | st[match] = str_mortal(st[match]); |
afd9f252 |
920 | retstr = st[newsp]; |
921 | } |
378cc40b |
922 | restorelist(oldsave); |
afd9f252 |
923 | } |
8d063cd8 |
924 | #ifdef DEBUGGING |
925 | dlevel = olddlevel - 1; |
926 | #endif |
927 | if (cmd->c_type != C_BLOCK) |
928 | goto until_loop; /* go back and evaluate conditional again */ |
929 | } |
930 | if (cmdflags & CF_LOOP) { |
931 | cmdflags |= CF_COND; /* now test the condition */ |
378cc40b |
932 | #ifdef DEBUGGING |
933 | dlevel = entdlevel; |
934 | #endif |
8d063cd8 |
935 | goto until_loop; |
936 | } |
378cc40b |
937 | next_cmd: |
938 | if (cmdflags & CF_ONCE) { |
939 | #ifdef DEBUGGING |
940 | if (debug & 4) { |
a687059c |
941 | tmps = loop_stack[loop_ptr].loop_label; |
942 | deb("(Popping label #%d %s)\n",loop_ptr, tmps ? tmps : ""); |
378cc40b |
943 | } |
944 | #endif |
945 | loop_ptr--; |
afd9f252 |
946 | if ((cmdflags & CF_OPTIMIZE) == CFT_ARRAY && |
947 | savestack->ary_fill > aryoptsave) |
a687059c |
948 | restorelist(aryoptsave); |
378cc40b |
949 | } |
8d063cd8 |
950 | cmd = cmd->c_next; |
951 | goto tail_recursion_entry; |
952 | } |
953 | |
954 | #ifdef DEBUGGING |
1c3d792e |
955 | # ifndef I_VARARGS |
8d063cd8 |
956 | /*VARARGS1*/ |
68decaef |
957 | void deb(pat,a1,a2,a3,a4,a5,a6,a7,a8) |
8d063cd8 |
958 | char *pat; |
959 | { |
960 | register int i; |
961 | |
87250799 |
962 | fprintf(stderr,"%-4ld",(long)curcmd->c_line); |
8d063cd8 |
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); |
966 | } |
a687059c |
967 | # else |
968 | /*VARARGS1*/ |
68decaef |
969 | void deb(va_alist) |
a687059c |
970 | va_dcl |
971 | { |
972 | va_list args; |
973 | char *pat; |
974 | register int i; |
975 | |
976 | va_start(args); |
87250799 |
977 | fprintf(stderr,"%-4ld",(long)curcmd->c_line); |
a687059c |
978 | for (i=0; i<dlevel; i++) |
979 | fprintf(stderr,"%c%c ",debname[i],debdelim[i]); |
980 | |
981 | pat = va_arg(args, char *); |
982 | (void) vfprintf(stderr,pat,args); |
983 | va_end( args ); |
984 | } |
985 | # endif |
8d063cd8 |
986 | #endif |
987 | |
68decaef |
988 | int |
8d063cd8 |
989 | copyopt(cmd,which) |
990 | register CMD *cmd; |
991 | register CMD *which; |
992 | { |
993 | cmd->c_flags &= CF_ONCE|CF_COND|CF_LOOP; |
994 | cmd->c_flags |= which->c_flags; |
378cc40b |
995 | cmd->c_short = which->c_short; |
996 | cmd->c_slen = which->c_slen; |
8d063cd8 |
997 | cmd->c_stab = which->c_stab; |
998 | return cmd->c_flags; |
999 | } |
378cc40b |
1000 | |
a687059c |
1001 | ARRAY * |
1002 | saveary(stab) |
1003 | STAB *stab; |
1004 | { |
1005 | register STR *str; |
1006 | |
1007 | str = Str_new(10,0); |
1008 | str->str_state = SS_SARY; |
1009 | str->str_u.str_stab = stab; |
1010 | if (str->str_ptr) { |
1011 | Safefree(str->str_ptr); |
fe14fcc3 |
1012 | str->str_ptr = Nullch; |
a687059c |
1013 | str->str_len = 0; |
1014 | } |
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)); |
1019 | } |
1020 | |
1021 | HASH * |
1022 | savehash(stab) |
1023 | STAB *stab; |
1024 | { |
1025 | register STR *str; |
1026 | |
1027 | str = Str_new(11,0); |
1028 | str->str_state = SS_SHASH; |
1029 | str->str_u.str_stab = stab; |
1030 | if (str->str_ptr) { |
1031 | Safefree(str->str_ptr); |
fe14fcc3 |
1032 | str->str_ptr = Nullch; |
a687059c |
1033 | str->str_len = 0; |
1034 | } |
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)); |
1039 | } |
1040 | |
1041 | void |
1042 | saveitem(item) |
1043 | register STR *item; |
1044 | { |
1045 | register STR *str; |
1046 | |
1047 | (void)apush(savestack,item); /* remember the pointer */ |
1048 | str = Str_new(12,0); |
1049 | str_sset(str,item); |
1050 | (void)apush(savestack,str); /* remember the value */ |
1051 | } |
1052 | |
1053 | void |
1054 | saveint(intp) |
1055 | int *intp; |
1056 | { |
1057 | register STR *str; |
1058 | |
1059 | str = Str_new(13,0); |
1060 | str->str_state = SS_SINT; |
1061 | str->str_u.str_useful = (long)*intp; /* remember value */ |
1062 | if (str->str_ptr) { |
1063 | Safefree(str->str_ptr); |
1064 | str->str_len = 0; |
1065 | } |
1066 | str->str_ptr = (char*)intp; /* remember pointer */ |
1067 | (void)apush(savestack,str); |
1068 | } |
1069 | |
1070 | void |
1071 | savelong(longp) |
1072 | long *longp; |
1073 | { |
1074 | register STR *str; |
1075 | |
1076 | str = Str_new(14,0); |
1077 | str->str_state = SS_SLONG; |
1078 | str->str_u.str_useful = *longp; /* remember value */ |
1079 | if (str->str_ptr) { |
1080 | Safefree(str->str_ptr); |
1081 | str->str_len = 0; |
1082 | } |
1083 | str->str_ptr = (char*)longp; /* remember pointer */ |
1084 | (void)apush(savestack,str); |
1085 | } |
1086 | |
1087 | void |
1088 | savesptr(sptr) |
1089 | STR **sptr; |
1090 | { |
1091 | register STR *str; |
1092 | |
1093 | str = Str_new(15,0); |
1094 | str->str_state = SS_SSTRP; |
1095 | str->str_magic = *sptr; /* remember value */ |
1096 | if (str->str_ptr) { |
1097 | Safefree(str->str_ptr); |
1098 | str->str_len = 0; |
1099 | } |
1100 | str->str_ptr = (char*)sptr; /* remember pointer */ |
1101 | (void)apush(savestack,str); |
1102 | } |
1103 | |
1104 | void |
1105 | savenostab(stab) |
1106 | STAB *stab; |
1107 | { |
1108 | register STR *str; |
1109 | |
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); |
1114 | } |
1115 | |
1116 | void |
1117 | savehptr(hptr) |
1118 | HASH **hptr; |
1119 | { |
1120 | register STR *str; |
1121 | |
1122 | str = Str_new(17,0); |
1123 | str->str_state = SS_SHPTR; |
1124 | str->str_u.str_hash = *hptr; /* remember value */ |
1125 | if (str->str_ptr) { |
1126 | Safefree(str->str_ptr); |
1127 | str->str_len = 0; |
1128 | } |
1129 | str->str_ptr = (char*)hptr; /* remember pointer */ |
1130 | (void)apush(savestack,str); |
1131 | } |
1132 | |
378cc40b |
1133 | void |
1c3d792e |
1134 | saveaptr(aptr) |
1135 | ARRAY **aptr; |
1136 | { |
1137 | register STR *str; |
1138 | |
1139 | str = Str_new(17,0); |
1140 | str->str_state = SS_SAPTR; |
1141 | str->str_u.str_array = *aptr; /* remember value */ |
1142 | if (str->str_ptr) { |
1143 | Safefree(str->str_ptr); |
1144 | str->str_len = 0; |
1145 | } |
1146 | str->str_ptr = (char*)aptr; /* remember pointer */ |
1147 | (void)apush(savestack,str); |
1148 | } |
1149 | |
1150 | void |
378cc40b |
1151 | savelist(sarg,maxsarg) |
1152 | register STR **sarg; |
1153 | int maxsarg; |
1154 | { |
1155 | register STR *str; |
1156 | register int i; |
1157 | |
1158 | for (i = 1; i <= maxsarg; i++) { |
a687059c |
1159 | (void)apush(savestack,sarg[i]); /* remember the pointer */ |
1160 | str = Str_new(18,0); |
378cc40b |
1161 | str_sset(str,sarg[i]); |
a687059c |
1162 | (void)apush(savestack,str); /* remember the value */ |
d8f2e4cc |
1163 | sarg[i]->str_u.str_useful = -1; |
378cc40b |
1164 | } |
1165 | } |
1166 | |
1167 | void |
1168 | restorelist(base) |
1169 | int base; |
1170 | { |
1171 | register STR *str; |
1172 | register STR *value; |
a687059c |
1173 | register STAB *stab; |
378cc40b |
1174 | |
a687059c |
1175 | if (base < -1) |
1176 | fatal("panic: corrupt saved stack index"); |
378cc40b |
1177 | while (savestack->ary_fill > base) { |
1178 | value = apop(savestack); |
a687059c |
1179 | switch (value->str_state) { |
1180 | case SS_NORM: /* normal string */ |
1181 | case SS_INCR: |
1182 | str = apop(savestack); |
1183 | str_replace(str,value); |
1184 | STABSET(str); |
1185 | break; |
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; |
1191 | str_free(value); |
1192 | break; |
1193 | case SS_SHASH: /* hash reference */ |
1194 | stab = value->str_u.str_stab; |
39c3038c |
1195 | (void)hfree(stab_xhash(stab), FALSE); |
a687059c |
1196 | stab_xhash(stab) = (HASH*)value->str_ptr; |
1197 | value->str_ptr = Nullch; |
1198 | str_free(value); |
1199 | break; |
1200 | case SS_SINT: /* int reference */ |
1201 | *((int*)value->str_ptr) = (int)value->str_u.str_useful; |
1202 | value->str_ptr = Nullch; |
1203 | str_free(value); |
1204 | break; |
1205 | case SS_SLONG: /* long reference */ |
1206 | *((long*)value->str_ptr) = value->str_u.str_useful; |
1207 | value->str_ptr = Nullch; |
1208 | str_free(value); |
1209 | break; |
1210 | case SS_SSTRP: /* STR* reference */ |
1211 | *((STR**)value->str_ptr) = value->str_magic; |
1212 | value->str_magic = Nullstr; |
1213 | value->str_ptr = Nullch; |
1214 | str_free(value); |
1215 | break; |
1216 | case SS_SHPTR: /* HASH* reference */ |
1217 | *((HASH**)value->str_ptr) = value->str_u.str_hash; |
1218 | value->str_ptr = Nullch; |
1219 | str_free(value); |
1220 | break; |
1c3d792e |
1221 | case SS_SAPTR: /* ARRAY* reference */ |
1222 | *((ARRAY**)value->str_ptr) = value->str_u.str_array; |
1223 | value->str_ptr = Nullch; |
1224 | str_free(value); |
1225 | break; |
a687059c |
1226 | case SS_SNSTAB: |
1227 | stab = (STAB*)value->str_magic; |
1228 | value->str_magic = Nullstr; |
1229 | (void)stab_clear(stab); |
1230 | str_free(value); |
1231 | break; |
39c3038c |
1232 | case SS_SCSV: /* callsave structure */ |
1233 | { |
1234 | CSV *csv = (CSV*) value->str_ptr; |
1235 | |
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; |
1242 | } |
1243 | str_free(value); |
1244 | } |
1245 | break; |
a687059c |
1246 | default: |
1247 | fatal("panic: restorelist inconsistency"); |
1248 | } |
378cc40b |
1249 | } |
1250 | } |
a687059c |
1251 | |
bf38876a |
1252 | #ifdef DEBUGGING |
a687059c |
1253 | void |
1254 | grow_dlevel() |
1255 | { |
1256 | dlmax += 128; |
1257 | Renew(debname, dlmax, char); |
1258 | Renew(debdelim, dlmax, char); |
1259 | } |
bf38876a |
1260 | #endif |