1 | /* $RCSfile: cmd.c,v $$Revision: 1.1.1.1 $$Date: 1996-10-02 06:39:57 $ |
---|
2 | * |
---|
3 | * Copyright (c) 1991, Larry Wall |
---|
4 | * |
---|
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. |
---|
7 | * |
---|
8 | * $Log: not supported by cvs2svn $ |
---|
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 | * |
---|
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 | * |
---|
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 | * |
---|
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 | * |
---|
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 | * |
---|
29 | * Revision 4.0 91/03/20 01:04:18 lwall |
---|
30 | * 4.0 baseline. |
---|
31 | * |
---|
32 | */ |
---|
33 | |
---|
34 | #include "EXTERN.h" |
---|
35 | #include "perl.h" |
---|
36 | |
---|
37 | #ifdef I_VARARGS |
---|
38 | # include <varargs.h> |
---|
39 | #endif |
---|
40 | |
---|
41 | static STR strchop; |
---|
42 | |
---|
43 | void grow_dlevel(); |
---|
44 | |
---|
45 | /* do longjmps() clobber register variables? */ |
---|
46 | |
---|
47 | #if defined(cray) || defined(STANDARD_C) |
---|
48 | #define JMPCLOBBER |
---|
49 | #endif |
---|
50 | |
---|
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 | |
---|
56 | int |
---|
57 | cmd_exec(cmdparm,gimme,sp) |
---|
58 | CMD *VOLATILE cmdparm; |
---|
59 | VOLATILE int gimme; |
---|
60 | VOLATILE int sp; |
---|
61 | { |
---|
62 | register CMD *cmd = cmdparm; |
---|
63 | SPAT *VOLATILE oldspat; |
---|
64 | VOLATILE int firstsave = savestack->ary_fill; |
---|
65 | VOLATILE int oldsave; |
---|
66 | VOLATILE int aryoptsave; |
---|
67 | #ifdef DEBUGGING |
---|
68 | VOLATILE int olddlevel; |
---|
69 | VOLATILE int entdlevel; |
---|
70 | #endif |
---|
71 | register STR *retstr = &str_undef; |
---|
72 | register char *tmps; |
---|
73 | register int cmdflags; |
---|
74 | register int match; |
---|
75 | register char *go_to = goto_targ; |
---|
76 | register int newsp = -2; |
---|
77 | register STR **st = stack->ary_array; |
---|
78 | FILE *VOLATILE fp; |
---|
79 | ARRAY *VOLATILE ar; |
---|
80 | |
---|
81 | lastsize = 0; |
---|
82 | #ifdef DEBUGGING |
---|
83 | entdlevel = dlevel; |
---|
84 | #endif |
---|
85 | tail_recursion_entry: |
---|
86 | #ifdef DEBUGGING |
---|
87 | dlevel = entdlevel; |
---|
88 | if (debug & 4) |
---|
89 | deb("mortals = (%d/%d) stack, = (%d/%d)\n", |
---|
90 | tmps_max, tmps_base, |
---|
91 | savestack->ary_fill, firstsave); |
---|
92 | #endif |
---|
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 | } |
---|
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; |
---|
112 | oldsave = savestack->ary_fill; |
---|
113 | #ifdef DEBUGGING |
---|
114 | olddlevel = dlevel; |
---|
115 | #endif |
---|
116 | retstr = &str_yes; |
---|
117 | newsp = -2; |
---|
118 | if (cmd->ucmd.ccmd.cc_true) { |
---|
119 | #ifdef DEBUGGING |
---|
120 | if (debug) { |
---|
121 | debname[dlevel] = 't'; |
---|
122 | debdelim[dlevel] = '_'; |
---|
123 | if (++dlevel >= dlmax) |
---|
124 | grow_dlevel(); |
---|
125 | } |
---|
126 | #endif |
---|
127 | newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme && (cmdflags & CF_TERM),sp); |
---|
128 | st = stack->ary_array; /* possibly reallocated */ |
---|
129 | retstr = st[newsp]; |
---|
130 | } |
---|
131 | if (!goto_targ) |
---|
132 | go_to = Nullch; |
---|
133 | curspat = oldspat; |
---|
134 | if (savestack->ary_fill > oldsave) |
---|
135 | restorelist(oldsave); |
---|
136 | #ifdef DEBUGGING |
---|
137 | dlevel = olddlevel; |
---|
138 | #endif |
---|
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(); |
---|
156 | } |
---|
157 | #endif |
---|
158 | newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme && (cmdflags & CF_TERM),sp); |
---|
159 | st = stack->ary_array; /* possibly reallocated */ |
---|
160 | retstr = st[newsp]; |
---|
161 | } |
---|
162 | if (!goto_targ) |
---|
163 | go_to = Nullch; |
---|
164 | curspat = oldspat; |
---|
165 | if (savestack->ary_fill > oldsave) |
---|
166 | restorelist(oldsave); |
---|
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; |
---|
175 | if (++loop_ptr >= loop_max) { |
---|
176 | loop_max += 128; |
---|
177 | Renew(loop_stack, loop_max, struct loop); |
---|
178 | } |
---|
179 | loop_stack[loop_ptr].loop_label = cmd->c_label; |
---|
180 | loop_stack[loop_ptr].loop_sp = sp; |
---|
181 | #ifdef DEBUGGING |
---|
182 | if (debug & 4) { |
---|
183 | deb("(Pushing label #%d %s)\n", |
---|
184 | loop_ptr, cmd->c_label ? cmd->c_label : ""); |
---|
185 | } |
---|
186 | #endif |
---|
187 | } |
---|
188 | #ifdef JMPCLOBBER |
---|
189 | cmdparm = cmd; |
---|
190 | #endif |
---|
191 | match = setjmp(loop_stack[loop_ptr].loop_env); |
---|
192 | if (match) { |
---|
193 | st = stack->ary_array; /* possibly reallocated */ |
---|
194 | #ifdef JMPCLOBBER |
---|
195 | cmd = cmdparm; |
---|
196 | cmdflags = cmd->c_flags|CF_ONCE; |
---|
197 | #endif |
---|
198 | if (savestack->ary_fill > oldsave) |
---|
199 | restorelist(oldsave); |
---|
200 | switch (match) { |
---|
201 | default: |
---|
202 | fatal("longjmp returned bad value (%d)",match); |
---|
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 | } |
---|
213 | #ifdef DEBUGGING |
---|
214 | olddlevel = dlevel; |
---|
215 | #endif |
---|
216 | curspat = oldspat; |
---|
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 | } |
---|
233 | } |
---|
234 | oldspat = curspat; |
---|
235 | oldsave = savestack->ary_fill; |
---|
236 | #ifdef DEBUGGING |
---|
237 | olddlevel = dlevel; |
---|
238 | #endif |
---|
239 | if (cmd->ucmd.ccmd.cc_true) { |
---|
240 | #ifdef DEBUGGING |
---|
241 | if (debug) { |
---|
242 | debname[dlevel] = 't'; |
---|
243 | debdelim[dlevel] = '_'; |
---|
244 | if (++dlevel >= dlmax) |
---|
245 | grow_dlevel(); |
---|
246 | } |
---|
247 | #endif |
---|
248 | newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme && (cmdflags & CF_TERM),sp); |
---|
249 | st = stack->ary_array; /* possibly reallocated */ |
---|
250 | if (newsp >= 0) |
---|
251 | retstr = st[newsp]; |
---|
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 |
---|
262 | if (debug) { |
---|
263 | debname[dlevel] = 'a'; |
---|
264 | debdelim[dlevel] = '_'; |
---|
265 | if (++dlevel >= dlmax) |
---|
266 | grow_dlevel(); |
---|
267 | } |
---|
268 | #endif |
---|
269 | newsp = cmd_exec(cmd->ucmd.ccmd.cc_alt,gimme && (cmdflags & CF_TERM),sp); |
---|
270 | st = stack->ary_array; /* possibly reallocated */ |
---|
271 | if (newsp >= 0) |
---|
272 | retstr = st[newsp]; |
---|
273 | } |
---|
274 | if (goto_targ) |
---|
275 | break; |
---|
276 | go_to = Nullch; |
---|
277 | goto finish_while; |
---|
278 | } |
---|
279 | cmd = cmd->c_next; |
---|
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) { |
---|
284 | #ifdef DEBUGGING |
---|
285 | if (debug & 4) { |
---|
286 | tmps = loop_stack[loop_ptr].loop_label; |
---|
287 | deb("(Popping label #%d %s)\n",loop_ptr, |
---|
288 | tmps ? tmps : "" ); |
---|
289 | } |
---|
290 | #endif |
---|
291 | loop_ptr--; |
---|
292 | } |
---|
293 | goto tail_recursion_entry; |
---|
294 | } |
---|
295 | } |
---|
296 | |
---|
297 | until_loop: |
---|
298 | |
---|
299 | /* Set line number so run-time errors can be located */ |
---|
300 | |
---|
301 | curcmd = cmd; |
---|
302 | |
---|
303 | #ifdef DEBUGGING |
---|
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]; |
---|
312 | debdelim[dlevel] = '!'; |
---|
313 | if (++dlevel >= dlmax) |
---|
314 | grow_dlevel(); |
---|
315 | } |
---|
316 | #endif |
---|
317 | |
---|
318 | /* Here is some common optimization */ |
---|
319 | |
---|
320 | if (cmdflags & CF_COND) { |
---|
321 | switch (cmdflags & CF_OPTIMIZE) { |
---|
322 | |
---|
323 | case CFT_FALSE: |
---|
324 | retstr = cmd->c_short; |
---|
325 | newsp = -2; |
---|
326 | match = FALSE; |
---|
327 | if (cmdflags & CF_NESURE) |
---|
328 | goto maybe; |
---|
329 | break; |
---|
330 | case CFT_TRUE: |
---|
331 | retstr = cmd->c_short; |
---|
332 | newsp = -2; |
---|
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); |
---|
340 | newsp = -2; |
---|
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) { |
---|
348 | if (*cmd->c_short->str_ptr && !(cmdflags & CF_EQSURE)) |
---|
349 | goto scanner; /* just unanchor it */ |
---|
350 | else |
---|
351 | break; /* must evaluate */ |
---|
352 | } |
---|
353 | match = 0; |
---|
354 | goto strop; |
---|
355 | |
---|
356 | case CFT_STROP: /* string op optimization */ |
---|
357 | match = 1; |
---|
358 | strop: |
---|
359 | retstr = STAB_STR(cmd->c_stab); |
---|
360 | newsp = -2; |
---|
361 | #ifndef I286 |
---|
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) { |
---|
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 | } |
---|
379 | if (cmd->c_spat) |
---|
380 | lastspat = cmd->c_spat; |
---|
381 | match = !(cmdflags & CF_FIRSTNEG); |
---|
382 | retstr = match ? &str_yes : &str_no; |
---|
383 | goto flipmaybe; |
---|
384 | } |
---|
385 | } |
---|
386 | else if (cmdflags & CF_NESURE) { |
---|
387 | match = cmdflags & CF_FIRSTNEG; |
---|
388 | retstr = match ? &str_yes : &str_no; |
---|
389 | goto flipmaybe; |
---|
390 | } |
---|
391 | #else |
---|
392 | { |
---|
393 | char *zap1, *zap2, zap1c, zap2c; |
---|
394 | int zaplen; |
---|
395 | int lenok; |
---|
396 | |
---|
397 | zap1 = cmd->c_short->str_ptr; |
---|
398 | zap2 = str_get(retstr); |
---|
399 | zap1c = *zap1; |
---|
400 | zap2c = *zap2; |
---|
401 | zaplen = cmd->c_slen; |
---|
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)) { |
---|
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 | } |
---|
420 | if (cmd->c_spat) |
---|
421 | lastspat = cmd->c_spat; |
---|
422 | match = !(cmdflags & CF_FIRSTNEG); |
---|
423 | retstr = match ? &str_yes : &str_no; |
---|
424 | goto flipmaybe; |
---|
425 | } |
---|
426 | } |
---|
427 | else if (cmdflags & CF_NESURE) { |
---|
428 | match = cmdflags & CF_FIRSTNEG; |
---|
429 | retstr = match ? &str_yes : &str_no; |
---|
430 | goto flipmaybe; |
---|
431 | } |
---|
432 | } |
---|
433 | #endif |
---|
434 | break; /* must evaluate */ |
---|
435 | |
---|
436 | case CFT_SCAN: /* non-anchored search */ |
---|
437 | scanner: |
---|
438 | retstr = STAB_STR(cmd->c_stab); |
---|
439 | newsp = -2; |
---|
440 | if (retstr->str_pok & SP_STUDIED) |
---|
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 */ |
---|
447 | #ifndef lint |
---|
448 | tmps = fbminstr((unsigned char*)tmps, |
---|
449 | (unsigned char*)tmps + retstr->str_cur, cmd->c_short); |
---|
450 | #endif |
---|
451 | } |
---|
452 | if (tmps) { |
---|
453 | if (cmdflags & CF_EQSURE) { |
---|
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) |
---|
461 | str_nset(stab_val(amperstab), |
---|
462 | tmps, cmd->c_short->str_cur); |
---|
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 | } |
---|
469 | lastspat = cmd->c_spat; |
---|
470 | match = !(cmdflags & CF_FIRSTNEG); |
---|
471 | retstr = match ? &str_yes : &str_no; |
---|
472 | goto flipmaybe; |
---|
473 | } |
---|
474 | else |
---|
475 | hint = tmps; |
---|
476 | } |
---|
477 | else { |
---|
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; |
---|
482 | goto flipmaybe; |
---|
483 | } |
---|
484 | } |
---|
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); |
---|
489 | } |
---|
490 | break; /* must evaluate */ |
---|
491 | |
---|
492 | case CFT_NUMOP: /* numeric op optimization */ |
---|
493 | retstr = STAB_STR(cmd->c_stab); |
---|
494 | newsp = -2; |
---|
495 | switch (cmd->c_slen) { |
---|
496 | case O_EQ: |
---|
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); |
---|
502 | break; |
---|
503 | case O_NE: |
---|
504 | match = (str_gnum(retstr) != cmd->c_short->str_u.str_nval); |
---|
505 | break; |
---|
506 | case O_LT: |
---|
507 | match = (str_gnum(retstr) < cmd->c_short->str_u.str_nval); |
---|
508 | break; |
---|
509 | case O_LE: |
---|
510 | match = (str_gnum(retstr) <= cmd->c_short->str_u.str_nval); |
---|
511 | break; |
---|
512 | case O_GT: |
---|
513 | match = (str_gnum(retstr) > cmd->c_short->str_u.str_nval); |
---|
514 | break; |
---|
515 | case O_GE: |
---|
516 | match = (str_gnum(retstr) >= cmd->c_short->str_u.str_nval); |
---|
517 | break; |
---|
518 | } |
---|
519 | if (match) { |
---|
520 | if (cmdflags & CF_EQSURE) { |
---|
521 | retstr = &str_yes; |
---|
522 | goto flipmaybe; |
---|
523 | } |
---|
524 | } |
---|
525 | else if (cmdflags & CF_NESURE) { |
---|
526 | retstr = &str_no; |
---|
527 | goto flipmaybe; |
---|
528 | } |
---|
529 | break; /* must evaluate */ |
---|
530 | |
---|
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(); |
---|
535 | goto dogets; |
---|
536 | case CFT_GETS: /* really a while (<file>) */ |
---|
537 | last_in_stab = cmd->c_stab; |
---|
538 | dogets: |
---|
539 | fp = stab_io(last_in_stab)->ifp; |
---|
540 | retstr = stab_val(defstab); |
---|
541 | newsp = -2; |
---|
542 | keepgoing: |
---|
543 | if (fp && str_gets(retstr, fp, 0)) { |
---|
544 | if (*retstr->str_ptr == '0' && retstr->str_cur == 1) |
---|
545 | match = FALSE; |
---|
546 | else |
---|
547 | match = TRUE; |
---|
548 | stab_io(last_in_stab)->lines++; |
---|
549 | } |
---|
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 | } |
---|
561 | else { |
---|
562 | retstr = &str_undef; |
---|
563 | match = FALSE; |
---|
564 | } |
---|
565 | goto flipmaybe; |
---|
566 | case CFT_EVAL: |
---|
567 | break; |
---|
568 | case CFT_UNFLIP: |
---|
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 | } |
---|
573 | newsp = eval(cmd->c_expr,gimme && (cmdflags & CF_TERM),sp); |
---|
574 | st = stack->ary_array; /* possibly reallocated */ |
---|
575 | retstr = st[newsp]; |
---|
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: |
---|
581 | retstr = stab_val(cmd->c_stab); |
---|
582 | newsp = -2; |
---|
583 | match = (retstr->str_cur != 0); |
---|
584 | tmps = str_get(retstr); |
---|
585 | tmps += retstr->str_cur - match; |
---|
586 | str_nset(&strchop,tmps,match); |
---|
587 | *tmps = '\0'; |
---|
588 | retstr->str_nok = 0; |
---|
589 | retstr->str_cur = tmps - retstr->str_ptr; |
---|
590 | STABSET(retstr); |
---|
591 | retstr = &strchop; |
---|
592 | goto flipmaybe; |
---|
593 | case CFT_ARRAY: |
---|
594 | match = cmd->c_short->str_u.str_useful; /* just to get register */ |
---|
595 | |
---|
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); |
---|
601 | } |
---|
602 | else { |
---|
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); |
---|
606 | } |
---|
607 | |
---|
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); |
---|
612 | retstr = &str_undef; |
---|
613 | cmd->c_short->str_u.str_useful = -1; /* actually redundant */ |
---|
614 | match = FALSE; |
---|
615 | } |
---|
616 | else { |
---|
617 | match++; |
---|
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; |
---|
622 | match = TRUE; |
---|
623 | } |
---|
624 | newsp = -2; |
---|
625 | goto maybe; |
---|
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; |
---|
636 | } |
---|
637 | |
---|
638 | /* we have tried to make this normal case as abnormal as possible */ |
---|
639 | |
---|
640 | doeval: |
---|
641 | if (gimme == G_ARRAY) { |
---|
642 | lastretstr = Nullstr; |
---|
643 | lastspbase = sp; |
---|
644 | lastsize = newsp - sp; |
---|
645 | if (lastsize < 0) |
---|
646 | lastsize = 0; |
---|
647 | } |
---|
648 | else |
---|
649 | lastretstr = retstr; |
---|
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 | } |
---|
654 | newsp = eval(cmd->c_expr, |
---|
655 | gimme && (cmdflags & CF_TERM) && cmd->c_type == C_EXPR && |
---|
656 | !cmd->ucmd.acmd.ac_expr, |
---|
657 | sp); |
---|
658 | st = stack->ary_array; /* possibly reallocated */ |
---|
659 | retstr = st[newsp]; |
---|
660 | if (newsp > sp && retstr) |
---|
661 | match = str_true(retstr); |
---|
662 | else |
---|
663 | match = FALSE; |
---|
664 | goto maybe; |
---|
665 | |
---|
666 | /* if flipflop was true, flop it */ |
---|
667 | |
---|
668 | flipmaybe: |
---|
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; |
---|
673 | } |
---|
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); |
---|
677 | } |
---|
678 | else { |
---|
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); |
---|
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; |
---|
695 | if (!match) |
---|
696 | goto next_cmd; |
---|
697 | } |
---|
698 | #ifdef TAINT |
---|
699 | tainted = 0; /* modifier doesn't affect regular expression */ |
---|
700 | #endif |
---|
701 | |
---|
702 | /* now to do the actual command, if any */ |
---|
703 | |
---|
704 | switch (cmd->c_type) { |
---|
705 | case C_NULL: |
---|
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; |
---|
711 | lastspbase = sp; |
---|
712 | lastsize = newsp - sp; |
---|
713 | if (lastsize < 0) |
---|
714 | lastsize = 0; |
---|
715 | } |
---|
716 | else |
---|
717 | lastretstr = retstr; |
---|
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 | } |
---|
722 | newsp = eval(cmd->ucmd.acmd.ac_expr,gimme && (cmdflags&CF_TERM),sp); |
---|
723 | st = stack->ary_array; /* possibly reallocated */ |
---|
724 | retstr = st[newsp]; |
---|
725 | } |
---|
726 | break; |
---|
727 | case C_NSWITCH: |
---|
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 | } |
---|
737 | goto doswitch; |
---|
738 | case C_CSWITCH: |
---|
739 | if (multiline) { |
---|
740 | cmd = cmd->c_next; /* can't assume anything */ |
---|
741 | goto tail_recursion_entry; |
---|
742 | } |
---|
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) |
---|
749 | match = cmd->ucmd.scmd.sc_max; |
---|
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"); |
---|
757 | case C_IF: |
---|
758 | oldspat = curspat; |
---|
759 | oldsave = savestack->ary_fill; |
---|
760 | #ifdef DEBUGGING |
---|
761 | olddlevel = dlevel; |
---|
762 | #endif |
---|
763 | retstr = &str_yes; |
---|
764 | newsp = -2; |
---|
765 | if (cmd->ucmd.ccmd.cc_true) { |
---|
766 | #ifdef DEBUGGING |
---|
767 | if (debug) { |
---|
768 | debname[dlevel] = 't'; |
---|
769 | debdelim[dlevel] = '_'; |
---|
770 | if (++dlevel >= dlmax) |
---|
771 | grow_dlevel(); |
---|
772 | } |
---|
773 | #endif |
---|
774 | newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme && (cmdflags & CF_TERM),sp); |
---|
775 | st = stack->ary_array; /* possibly reallocated */ |
---|
776 | retstr = st[newsp]; |
---|
777 | } |
---|
778 | curspat = oldspat; |
---|
779 | if (savestack->ary_fill > oldsave) |
---|
780 | restorelist(oldsave); |
---|
781 | #ifdef DEBUGGING |
---|
782 | dlevel = olddlevel; |
---|
783 | #endif |
---|
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(); |
---|
801 | } |
---|
802 | #endif |
---|
803 | newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme && (cmdflags & CF_TERM),sp); |
---|
804 | st = stack->ary_array; /* possibly reallocated */ |
---|
805 | retstr = st[newsp]; |
---|
806 | } |
---|
807 | curspat = oldspat; |
---|
808 | if (savestack->ary_fill > oldsave) |
---|
809 | restorelist(oldsave); |
---|
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; |
---|
818 | if (++loop_ptr >= loop_max) { |
---|
819 | loop_max += 128; |
---|
820 | Renew(loop_stack, loop_max, struct loop); |
---|
821 | } |
---|
822 | loop_stack[loop_ptr].loop_label = cmd->c_label; |
---|
823 | loop_stack[loop_ptr].loop_sp = sp; |
---|
824 | #ifdef DEBUGGING |
---|
825 | if (debug & 4) { |
---|
826 | deb("(Pushing label #%d %s)\n", |
---|
827 | loop_ptr, cmd->c_label ? cmd->c_label : ""); |
---|
828 | } |
---|
829 | #endif |
---|
830 | } |
---|
831 | #ifdef JMPCLOBBER |
---|
832 | cmdparm = cmd; |
---|
833 | #endif |
---|
834 | match = setjmp(loop_stack[loop_ptr].loop_env); |
---|
835 | if (match) { |
---|
836 | st = stack->ary_array; /* possibly reallocated */ |
---|
837 | #ifdef JMPCLOBBER |
---|
838 | cmd = cmdparm; |
---|
839 | cmdflags = cmd->c_flags|CF_ONCE; |
---|
840 | go_to = goto_targ; |
---|
841 | #endif |
---|
842 | if (savestack->ary_fill > oldsave) |
---|
843 | restorelist(oldsave); |
---|
844 | switch (match) { |
---|
845 | default: |
---|
846 | fatal("longjmp returned bad value (%d)",match); |
---|
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; |
---|
857 | goto next_cmd; |
---|
858 | case O_NEXT: |
---|
859 | #ifdef JMPCLOBBER |
---|
860 | newsp = -2; |
---|
861 | retstr = &str_undef; |
---|
862 | #endif |
---|
863 | goto next_iter; |
---|
864 | case O_REDO: |
---|
865 | #ifdef DEBUGGING |
---|
866 | dlevel = olddlevel; |
---|
867 | #endif |
---|
868 | #ifdef JMPCLOBBER |
---|
869 | newsp = -2; |
---|
870 | retstr = &str_undef; |
---|
871 | #endif |
---|
872 | goto doit; |
---|
873 | } |
---|
874 | } |
---|
875 | oldspat = curspat; |
---|
876 | oldsave = savestack->ary_fill; |
---|
877 | #ifdef DEBUGGING |
---|
878 | olddlevel = dlevel; |
---|
879 | #endif |
---|
880 | doit: |
---|
881 | if (cmd->ucmd.ccmd.cc_true) { |
---|
882 | #ifdef DEBUGGING |
---|
883 | if (debug) { |
---|
884 | debname[dlevel] = 't'; |
---|
885 | debdelim[dlevel] = '_'; |
---|
886 | if (++dlevel >= dlmax) |
---|
887 | grow_dlevel(); |
---|
888 | } |
---|
889 | #endif |
---|
890 | newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme && (cmdflags & CF_TERM),sp); |
---|
891 | st = stack->ary_array; /* possibly reallocated */ |
---|
892 | retstr = st[newsp]; |
---|
893 | } |
---|
894 | /* actually, this spot is rarely reached anymore since the above |
---|
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 |
---|
903 | if (debug) { |
---|
904 | debname[dlevel] = 'a'; |
---|
905 | debdelim[dlevel] = '_'; |
---|
906 | if (++dlevel >= dlmax) |
---|
907 | grow_dlevel(); |
---|
908 | } |
---|
909 | #endif |
---|
910 | newsp = cmd_exec(cmd->ucmd.ccmd.cc_alt,gimme && (cmdflags & CF_TERM),sp); |
---|
911 | st = stack->ary_array; /* possibly reallocated */ |
---|
912 | retstr = st[newsp]; |
---|
913 | } |
---|
914 | finish_while: |
---|
915 | curspat = oldspat; |
---|
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]); |
---|
920 | retstr = st[newsp]; |
---|
921 | } |
---|
922 | restorelist(oldsave); |
---|
923 | } |
---|
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 */ |
---|
932 | #ifdef DEBUGGING |
---|
933 | dlevel = entdlevel; |
---|
934 | #endif |
---|
935 | goto until_loop; |
---|
936 | } |
---|
937 | next_cmd: |
---|
938 | if (cmdflags & CF_ONCE) { |
---|
939 | #ifdef DEBUGGING |
---|
940 | if (debug & 4) { |
---|
941 | tmps = loop_stack[loop_ptr].loop_label; |
---|
942 | deb("(Popping label #%d %s)\n",loop_ptr, tmps ? tmps : ""); |
---|
943 | } |
---|
944 | #endif |
---|
945 | loop_ptr--; |
---|
946 | if ((cmdflags & CF_OPTIMIZE) == CFT_ARRAY && |
---|
947 | savestack->ary_fill > aryoptsave) |
---|
948 | restorelist(aryoptsave); |
---|
949 | } |
---|
950 | cmd = cmd->c_next; |
---|
951 | goto tail_recursion_entry; |
---|
952 | } |
---|
953 | |
---|
954 | #ifdef DEBUGGING |
---|
955 | # ifndef I_VARARGS |
---|
956 | /*VARARGS1*/ |
---|
957 | void deb(pat,a1,a2,a3,a4,a5,a6,a7,a8) |
---|
958 | char *pat; |
---|
959 | { |
---|
960 | register int i; |
---|
961 | |
---|
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); |
---|
966 | } |
---|
967 | # else |
---|
968 | /*VARARGS1*/ |
---|
969 | void deb(va_alist) |
---|
970 | va_dcl |
---|
971 | { |
---|
972 | va_list args; |
---|
973 | char *pat; |
---|
974 | register int i; |
---|
975 | |
---|
976 | va_start(args); |
---|
977 | fprintf(stderr,"%-4ld",(long)curcmd->c_line); |
---|
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 |
---|
986 | #endif |
---|
987 | |
---|
988 | int |
---|
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; |
---|
995 | cmd->c_short = which->c_short; |
---|
996 | cmd->c_slen = which->c_slen; |
---|
997 | cmd->c_stab = which->c_stab; |
---|
998 | return cmd->c_flags; |
---|
999 | } |
---|
1000 | |
---|
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); |
---|
1012 | str->str_ptr = Nullch; |
---|
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); |
---|
1032 | str->str_ptr = Nullch; |
---|
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 | |
---|
1133 | void |
---|
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 |
---|
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++) { |
---|
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; |
---|
1164 | } |
---|
1165 | } |
---|
1166 | |
---|
1167 | void |
---|
1168 | restorelist(base) |
---|
1169 | int base; |
---|
1170 | { |
---|
1171 | register STR *str; |
---|
1172 | register STR *value; |
---|
1173 | register STAB *stab; |
---|
1174 | |
---|
1175 | if (base < -1) |
---|
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 */ |
---|
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; |
---|
1195 | (void)hfree(stab_xhash(stab), FALSE); |
---|
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; |
---|
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; |
---|
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; |
---|
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; |
---|
1246 | default: |
---|
1247 | fatal("panic: restorelist inconsistency"); |
---|
1248 | } |
---|
1249 | } |
---|
1250 | } |
---|
1251 | |
---|
1252 | #ifdef DEBUGGING |
---|
1253 | void |
---|
1254 | grow_dlevel() |
---|
1255 | { |
---|
1256 | dlmax += 128; |
---|
1257 | Renew(debname, dlmax, char); |
---|
1258 | Renew(debdelim, dlmax, char); |
---|
1259 | } |
---|
1260 | #endif |
---|