Commit | Line | Data |
---|---|---|
ca2dddd6 C |
1 | /* $RCSfile: stab.c,v $$Revision: 4.0.1.5 $$Date: 1993/02/05 19:42:47 $ |
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: stab.c,v $ | |
9 | * Revision 4.0.1.5 1993/02/05 19:42:47 lwall | |
10 | * patch36: length returned wrong value on certain semi-magical variables | |
11 | * | |
12 | * Revision 4.0.1.4 92/06/08 15:32:19 lwall | |
13 | * patch20: fixed confusion between a *var's real name and its effective name | |
14 | * patch20: the debugger now warns you on lines that can't set a breakpoint | |
15 | * patch20: the debugger made perl forget the last pattern used by // | |
16 | * patch20: paragraph mode now skips extra newlines automatically | |
17 | * patch20: ($<,$>) = ... didn't work on some architectures | |
18 | * | |
19 | * Revision 4.0.1.3 91/11/05 18:35:33 lwall | |
20 | * patch11: length($x) was sometimes wrong for numeric $x | |
21 | * patch11: perl now issues warning if $SIG{'ALARM'} is referenced | |
22 | * patch11: *foo = undef coredumped | |
23 | * patch11: solitary subroutine references no longer trigger typo warnings | |
24 | * patch11: local(*FILEHANDLE) had a memory leak | |
25 | * | |
26 | * Revision 4.0.1.2 91/06/07 11:55:53 lwall | |
27 | * patch4: new copyright notice | |
28 | * patch4: added $^P variable to control calling of perldb routines | |
29 | * patch4: added $^F variable to specify maximum system fd, default 2 | |
30 | * patch4: $` was busted inside s/// | |
31 | * patch4: default top-of-form format is now FILEHANDLE_TOP | |
32 | * patch4: length($`), length($&), length($') now optimized to avoid string copy | |
33 | * patch4: $^D |= 1024 now does syntax tree dump at run-time | |
34 | * | |
35 | * Revision 4.0.1.1 91/04/12 09:10:24 lwall | |
36 | * patch1: Configure now differentiates getgroups() type from getgid() type | |
37 | * patch1: you may now use "die" and "caller" in a signal handler | |
38 | * | |
39 | * Revision 4.0 91/03/20 01:39:41 lwall | |
40 | * 4.0 baseline. | |
41 | * | |
42 | */ | |
43 | ||
44 | #include "EXTERN.h" | |
45 | #include "perl.h" | |
46 | ||
47 | #if !defined(NSIG) || defined(M_UNIX) || defined(M_XENIX) | |
48 | #include <signal.h> | |
49 | #endif | |
50 | ||
51 | static char *sig_name[] = { | |
52 | SIG_NAME,0 | |
53 | }; | |
54 | ||
55 | #ifdef VOIDSIG | |
56 | #define handlertype void | |
57 | #else | |
58 | #define handlertype int | |
59 | #endif | |
60 | ||
61 | static handlertype sighandler(); | |
62 | ||
63 | static int origalen = 0; | |
64 | ||
65 | STR * | |
66 | stab_str(str) | |
67 | STR *str; | |
68 | { | |
69 | STAB *stab = str->str_u.str_stab; | |
70 | register int paren; | |
71 | register char *s; | |
72 | register int i; | |
73 | ||
74 | if (str->str_rare) | |
75 | return stab_val(stab); | |
76 | ||
77 | switch (*stab->str_magic->str_ptr) { | |
78 | case '\004': /* ^D */ | |
79 | #ifdef DEBUGGING | |
80 | str_numset(stab_val(stab),(double)(debug & 32767)); | |
81 | #endif | |
82 | break; | |
83 | case '\006': /* ^F */ | |
84 | str_numset(stab_val(stab),(double)maxsysfd); | |
85 | break; | |
86 | case '\t': /* ^I */ | |
87 | if (inplace) | |
88 | str_set(stab_val(stab), inplace); | |
89 | else | |
90 | str_sset(stab_val(stab),&str_undef); | |
91 | break; | |
92 | case '\020': /* ^P */ | |
93 | str_numset(stab_val(stab),(double)perldb); | |
94 | break; | |
95 | case '\024': /* ^T */ | |
96 | str_numset(stab_val(stab),(double)basetime); | |
97 | break; | |
98 | case '\027': /* ^W */ | |
99 | str_numset(stab_val(stab),(double)dowarn); | |
100 | break; | |
101 | case '1': case '2': case '3': case '4': | |
102 | case '5': case '6': case '7': case '8': case '9': case '&': | |
103 | if (curspat) { | |
104 | paren = atoi(stab_ename(stab)); | |
105 | getparen: | |
106 | if (curspat->spat_regexp && | |
107 | paren <= curspat->spat_regexp->nparens && | |
108 | (s = curspat->spat_regexp->startp[paren]) ) { | |
109 | i = curspat->spat_regexp->endp[paren] - s; | |
110 | if (i >= 0) | |
111 | str_nset(stab_val(stab),s,i); | |
112 | else | |
113 | str_sset(stab_val(stab),&str_undef); | |
114 | } | |
115 | else | |
116 | str_sset(stab_val(stab),&str_undef); | |
117 | } | |
118 | break; | |
119 | case '+': | |
120 | if (curspat) { | |
121 | paren = curspat->spat_regexp->lastparen; | |
122 | goto getparen; | |
123 | } | |
124 | break; | |
125 | case '`': | |
126 | if (curspat) { | |
127 | if (curspat->spat_regexp && | |
128 | (s = curspat->spat_regexp->subbeg) ) { | |
129 | i = curspat->spat_regexp->startp[0] - s; | |
130 | if (i >= 0) | |
131 | str_nset(stab_val(stab),s,i); | |
132 | else | |
133 | str_nset(stab_val(stab),"",0); | |
134 | } | |
135 | else | |
136 | str_nset(stab_val(stab),"",0); | |
137 | } | |
138 | break; | |
139 | case '\'': | |
140 | if (curspat) { | |
141 | if (curspat->spat_regexp && | |
142 | (s = curspat->spat_regexp->endp[0]) ) { | |
143 | str_nset(stab_val(stab),s, curspat->spat_regexp->subend - s); | |
144 | } | |
145 | else | |
146 | str_nset(stab_val(stab),"",0); | |
147 | } | |
148 | break; | |
149 | case '.': | |
150 | #ifndef lint | |
151 | if (last_in_stab && stab_io(last_in_stab)) { | |
152 | str_numset(stab_val(stab),(double)stab_io(last_in_stab)->lines); | |
153 | } | |
154 | #endif | |
155 | break; | |
156 | case '?': | |
157 | str_numset(stab_val(stab),(double)statusvalue); | |
158 | break; | |
159 | case '^': | |
160 | s = stab_io(curoutstab)->top_name; | |
161 | if (s) | |
162 | str_set(stab_val(stab),s); | |
163 | else { | |
164 | str_set(stab_val(stab),stab_ename(curoutstab)); | |
165 | str_cat(stab_val(stab),"_TOP"); | |
166 | } | |
167 | break; | |
168 | case '~': | |
169 | s = stab_io(curoutstab)->fmt_name; | |
170 | if (!s) | |
171 | s = stab_ename(curoutstab); | |
172 | str_set(stab_val(stab),s); | |
173 | break; | |
174 | #ifndef lint | |
175 | case '=': | |
176 | str_numset(stab_val(stab),(double)stab_io(curoutstab)->page_len); | |
177 | break; | |
178 | case '-': | |
179 | str_numset(stab_val(stab),(double)stab_io(curoutstab)->lines_left); | |
180 | break; | |
181 | case '%': | |
182 | str_numset(stab_val(stab),(double)stab_io(curoutstab)->page); | |
183 | break; | |
184 | #endif | |
185 | case ':': | |
186 | break; | |
187 | case '/': | |
188 | break; | |
189 | case '[': | |
190 | str_numset(stab_val(stab),(double)arybase); | |
191 | break; | |
192 | case '|': | |
193 | if (!stab_io(curoutstab)) | |
194 | stab_io(curoutstab) = stio_new(); | |
195 | str_numset(stab_val(stab), | |
196 | (double)((stab_io(curoutstab)->flags & IOF_FLUSH) != 0) ); | |
197 | break; | |
198 | case ',': | |
199 | str_nset(stab_val(stab),ofs,ofslen); | |
200 | break; | |
201 | case '\\': | |
202 | str_nset(stab_val(stab),ors,orslen); | |
203 | break; | |
204 | case '#': | |
205 | str_set(stab_val(stab),ofmt); | |
206 | break; | |
207 | case '!': | |
208 | str_numset(stab_val(stab), (double)errno); | |
209 | str_set(stab_val(stab), errno ? strerror(errno) : ""); | |
210 | stab_val(stab)->str_nok = 1; /* what a wonderful hack! */ | |
211 | break; | |
212 | case '<': | |
213 | str_numset(stab_val(stab),(double)uid); | |
214 | break; | |
215 | case '>': | |
216 | str_numset(stab_val(stab),(double)euid); | |
217 | break; | |
218 | case '(': | |
219 | s = buf; | |
220 | (void)sprintf(s,"%d",(int)gid); | |
221 | goto add_groups; | |
222 | case ')': | |
223 | s = buf; | |
224 | (void)sprintf(s,"%d",(int)egid); | |
225 | add_groups: | |
226 | while (*s) s++; | |
227 | #ifdef HAS_GETGROUPS | |
228 | #ifndef NGROUPS | |
229 | #define NGROUPS 32 | |
230 | #endif | |
231 | { | |
232 | GROUPSTYPE gary[NGROUPS]; | |
233 | ||
234 | i = getgroups(NGROUPS,gary); | |
235 | while (--i >= 0) { | |
236 | (void)sprintf(s," %ld", (long)gary[i]); | |
237 | while (*s) s++; | |
238 | } | |
239 | } | |
240 | #endif | |
241 | str_set(stab_val(stab),buf); | |
242 | break; | |
243 | case '*': | |
244 | break; | |
245 | case '0': | |
246 | break; | |
247 | default: | |
248 | { | |
249 | struct ufuncs *uf = (struct ufuncs *)str->str_ptr; | |
250 | ||
251 | if (uf && uf->uf_val) | |
252 | (*uf->uf_val)(uf->uf_index, stab_val(stab)); | |
253 | } | |
254 | break; | |
255 | } | |
256 | return stab_val(stab); | |
257 | } | |
258 | ||
259 | STRLEN | |
260 | stab_len(str) | |
261 | STR *str; | |
262 | { | |
263 | STAB *stab = str->str_u.str_stab; | |
264 | int paren; | |
265 | int i; | |
266 | char *s; | |
267 | ||
268 | if (str->str_rare) | |
269 | return str_len(stab_val(stab)); | |
270 | ||
271 | switch (*stab->str_magic->str_ptr) { | |
272 | case '1': case '2': case '3': case '4': | |
273 | case '5': case '6': case '7': case '8': case '9': case '&': | |
274 | if (curspat) { | |
275 | paren = atoi(stab_ename(stab)); | |
276 | getparen: | |
277 | if (curspat->spat_regexp && | |
278 | paren <= curspat->spat_regexp->nparens && | |
279 | (s = curspat->spat_regexp->startp[paren]) ) { | |
280 | i = curspat->spat_regexp->endp[paren] - s; | |
281 | if (i >= 0) | |
282 | return i; | |
283 | else | |
284 | return 0; | |
285 | } | |
286 | else | |
287 | return 0; | |
288 | } | |
289 | break; | |
290 | case '+': | |
291 | if (curspat) { | |
292 | paren = curspat->spat_regexp->lastparen; | |
293 | goto getparen; | |
294 | } | |
295 | break; | |
296 | case '`': | |
297 | if (curspat) { | |
298 | if (curspat->spat_regexp && | |
299 | (s = curspat->spat_regexp->subbeg) ) { | |
300 | i = curspat->spat_regexp->startp[0] - s; | |
301 | if (i >= 0) | |
302 | return i; | |
303 | else | |
304 | return 0; | |
305 | } | |
306 | else | |
307 | return 0; | |
308 | } | |
309 | break; | |
310 | case '\'': | |
311 | if (curspat) { | |
312 | if (curspat->spat_regexp && | |
313 | (s = curspat->spat_regexp->endp[0]) ) { | |
314 | return (STRLEN) (curspat->spat_regexp->subend - s); | |
315 | } | |
316 | else | |
317 | return 0; | |
318 | } | |
319 | break; | |
320 | case ',': | |
321 | return (STRLEN)ofslen; | |
322 | case '\\': | |
323 | return (STRLEN)orslen; | |
324 | } | |
325 | return str_len(stab_str(str)); | |
326 | } | |
327 | ||
328 | void | |
329 | stabset(mstr,str) | |
330 | register STR *mstr; | |
331 | STR *str; | |
332 | { | |
333 | STAB *stab; | |
334 | register char *s; | |
335 | int i; | |
336 | ||
337 | switch (mstr->str_rare) { | |
338 | case 'E': | |
339 | my_setenv(mstr->str_ptr,str_get(str)); | |
340 | /* And you'll never guess what the dog had */ | |
341 | /* in its mouth... */ | |
342 | #ifdef TAINT | |
343 | if (strEQ(mstr->str_ptr,"PATH")) { | |
344 | char *strend = str->str_ptr + str->str_cur; | |
345 | ||
346 | s = str->str_ptr; | |
347 | while (s < strend) { | |
348 | s = cpytill(tokenbuf,s,strend,':',&i); | |
349 | s++; | |
350 | if (*tokenbuf != '/' | |
351 | || (stat(tokenbuf,&statbuf) && (statbuf.st_mode & 2)) ) | |
352 | str->str_tainted = 2; | |
353 | } | |
354 | } | |
355 | #endif | |
356 | break; | |
357 | case 'S': | |
358 | s = str_get(str); | |
359 | i = whichsig(mstr->str_ptr); /* ...no, a brick */ | |
360 | if (!i && (dowarn || strEQ(mstr->str_ptr,"ALARM"))) | |
361 | warn("No such signal: SIG%s", mstr->str_ptr); | |
362 | if (strEQ(s,"IGNORE")) | |
363 | #ifndef lint | |
364 | (void)signal(i,SIG_IGN); | |
365 | #else | |
366 | ; | |
367 | #endif | |
368 | else if (strEQ(s,"DEFAULT") || !*s) | |
369 | (void)signal(i,SIG_DFL); | |
370 | else { | |
371 | (void)signal(i,sighandler); | |
372 | if (!index(s,'\'')) { | |
373 | sprintf(tokenbuf, "main'%s",s); | |
374 | str_set(str,tokenbuf); | |
375 | } | |
376 | } | |
377 | break; | |
378 | #ifdef SOME_DBM | |
379 | case 'D': | |
380 | stab = mstr->str_u.str_stab; | |
381 | hdbmstore(stab_hash(stab),mstr->str_ptr,mstr->str_cur,str); | |
382 | break; | |
383 | #endif | |
384 | case 'L': | |
385 | { | |
386 | CMD *cmd; | |
387 | ||
388 | stab = mstr->str_u.str_stab; | |
389 | i = str_true(str); | |
390 | str = afetch(stab_xarray(stab),atoi(mstr->str_ptr), FALSE); | |
391 | if (str->str_magic && (cmd = str->str_magic->str_u.str_cmd)) { | |
392 | cmd->c_flags &= ~CF_OPTIMIZE; | |
393 | cmd->c_flags |= i? CFT_D1 : CFT_D0; | |
394 | } | |
395 | else | |
396 | warn("Can't break at that line\n"); | |
397 | } | |
398 | break; | |
399 | case '#': | |
400 | stab = mstr->str_u.str_stab; | |
401 | afill(stab_array(stab), (int)str_gnum(str) - arybase); | |
402 | break; | |
403 | case 'X': /* merely a copy of a * string */ | |
404 | break; | |
405 | case '*': | |
406 | s = str->str_pok ? str_get(str) : ""; | |
407 | if (strNE(s,"StB") || str->str_cur != sizeof(STBP)) { | |
408 | stab = mstr->str_u.str_stab; | |
409 | if (!*s) { | |
410 | STBP *stbp; | |
411 | ||
412 | /*SUPPRESS 701*/ | |
413 | (void)savenostab(stab); /* schedule a free of this stab */ | |
414 | if (stab->str_len) | |
415 | Safefree(stab->str_ptr); | |
416 | Newz(601,stbp, 1, STBP); | |
417 | stab->str_ptr = stbp; | |
418 | stab->str_len = stab->str_cur = sizeof(STBP); | |
419 | stab->str_pok = 1; | |
420 | strcpy(stab_magic(stab),"StB"); | |
421 | stab_val(stab) = Str_new(70,0); | |
422 | stab_line(stab) = curcmd->c_line; | |
423 | stab_estab(stab) = stab; | |
424 | } | |
425 | else { | |
426 | stab = stabent(s,TRUE); | |
427 | if (!stab_xarray(stab)) | |
428 | aadd(stab); | |
429 | if (!stab_xhash(stab)) | |
430 | hadd(stab); | |
431 | if (!stab_io(stab)) | |
432 | stab_io(stab) = stio_new(); | |
433 | } | |
434 | str_sset(str, (STR*) stab); | |
435 | } | |
436 | break; | |
437 | case 's': { | |
438 | struct lstring *lstr = (struct lstring*)str; | |
439 | char *tmps; | |
440 | ||
441 | mstr->str_rare = 0; | |
442 | str->str_magic = Nullstr; | |
443 | tmps = str_get(str); | |
444 | str_insert(mstr,lstr->lstr_offset,lstr->lstr_len, | |
445 | tmps,str->str_cur); | |
446 | } | |
447 | break; | |
448 | ||
449 | case 'v': | |
450 | do_vecset(mstr,str); | |
451 | break; | |
452 | ||
453 | case 0: | |
454 | /*SUPPRESS 560*/ | |
455 | if (!(stab = mstr->str_u.str_stab)) | |
456 | break; | |
457 | switch (*stab->str_magic->str_ptr) { | |
458 | case '\004': /* ^D */ | |
459 | #ifdef DEBUGGING | |
460 | debug = (int)(str_gnum(str)) | 32768; | |
461 | if (debug & 1024) | |
462 | dump_all(); | |
463 | #endif | |
464 | break; | |
465 | case '\006': /* ^F */ | |
466 | maxsysfd = (int)str_gnum(str); | |
467 | break; | |
468 | case '\t': /* ^I */ | |
469 | if (inplace) | |
470 | Safefree(inplace); | |
471 | if (str->str_pok || str->str_nok) | |
472 | inplace = savestr(str_get(str)); | |
473 | else | |
474 | inplace = Nullch; | |
475 | break; | |
476 | case '\020': /* ^P */ | |
477 | i = (int)str_gnum(str); | |
478 | if (i != perldb) { | |
479 | static SPAT *oldlastspat; | |
480 | ||
481 | if (perldb) | |
482 | oldlastspat = lastspat; | |
483 | else | |
484 | lastspat = oldlastspat; | |
485 | } | |
486 | perldb = i; | |
487 | break; | |
488 | case '\024': /* ^T */ | |
489 | basetime = (time_t)str_gnum(str); | |
490 | break; | |
491 | case '\027': /* ^W */ | |
492 | dowarn = (bool)str_gnum(str); | |
493 | break; | |
494 | case '.': | |
495 | if (localizing) | |
496 | savesptr((STR**)&last_in_stab); | |
497 | break; | |
498 | case '^': | |
499 | Safefree(stab_io(curoutstab)->top_name); | |
500 | stab_io(curoutstab)->top_name = s = savestr(str_get(str)); | |
501 | stab_io(curoutstab)->top_stab = stabent(s,TRUE); | |
502 | break; | |
503 | case '~': | |
504 | Safefree(stab_io(curoutstab)->fmt_name); | |
505 | stab_io(curoutstab)->fmt_name = s = savestr(str_get(str)); | |
506 | stab_io(curoutstab)->fmt_stab = stabent(s,TRUE); | |
507 | break; | |
508 | case '=': | |
509 | stab_io(curoutstab)->page_len = (long)str_gnum(str); | |
510 | break; | |
511 | case '-': | |
512 | stab_io(curoutstab)->lines_left = (long)str_gnum(str); | |
513 | if (stab_io(curoutstab)->lines_left < 0L) | |
514 | stab_io(curoutstab)->lines_left = 0L; | |
515 | break; | |
516 | case '%': | |
517 | stab_io(curoutstab)->page = (long)str_gnum(str); | |
518 | break; | |
519 | case '|': | |
520 | if (!stab_io(curoutstab)) | |
521 | stab_io(curoutstab) = stio_new(); | |
522 | stab_io(curoutstab)->flags &= ~IOF_FLUSH; | |
523 | if (str_gnum(str) != 0.0) { | |
524 | stab_io(curoutstab)->flags |= IOF_FLUSH; | |
525 | } | |
526 | break; | |
527 | case '*': | |
528 | i = (int)str_gnum(str); | |
529 | multiline = (i != 0); | |
530 | break; | |
531 | case '/': | |
532 | if (str->str_pok) { | |
533 | rs = str_get(str); | |
534 | rslen = str->str_cur; | |
535 | if (rspara = !rslen) { | |
536 | rs = "\n\n"; | |
537 | rslen = 2; | |
538 | } | |
539 | rschar = rs[rslen - 1]; | |
540 | } | |
541 | else { | |
542 | rschar = 0777; /* fake a non-existent char */ | |
543 | rslen = 1; | |
544 | } | |
545 | break; | |
546 | case '\\': | |
547 | if (ors) | |
548 | Safefree(ors); | |
549 | ors = savestr(str_get(str)); | |
550 | orslen = str->str_cur; | |
551 | break; | |
552 | case ',': | |
553 | if (ofs) | |
554 | Safefree(ofs); | |
555 | ofs = savestr(str_get(str)); | |
556 | ofslen = str->str_cur; | |
557 | break; | |
558 | case '#': | |
559 | if (ofmt) | |
560 | Safefree(ofmt); | |
561 | ofmt = savestr(str_get(str)); | |
562 | break; | |
563 | case '[': | |
564 | arybase = (int)str_gnum(str); | |
565 | break; | |
566 | case '?': | |
567 | statusvalue = U_S(str_gnum(str)); | |
568 | break; | |
569 | case '!': | |
570 | errno = (int)str_gnum(str); /* will anyone ever use this? */ | |
571 | break; | |
572 | case '<': | |
573 | uid = (int)str_gnum(str); | |
574 | if (delaymagic) { | |
575 | delaymagic |= DM_RUID; | |
576 | break; /* don't do magic till later */ | |
577 | } | |
578 | #ifdef HAS_SETRUID | |
579 | (void)setruid((UIDTYPE)uid); | |
580 | #else | |
581 | #ifdef HAS_SETREUID | |
582 | (void)setreuid((UIDTYPE)uid, (UIDTYPE)-1); | |
583 | #else | |
584 | if (uid == euid) /* special case $< = $> */ | |
585 | (void)setuid(uid); | |
586 | else | |
587 | fatal("setruid() not implemented"); | |
588 | #endif | |
589 | #endif | |
590 | uid = (int)getuid(); | |
591 | break; | |
592 | case '>': | |
593 | euid = (int)str_gnum(str); | |
594 | if (delaymagic) { | |
595 | delaymagic |= DM_EUID; | |
596 | break; /* don't do magic till later */ | |
597 | } | |
598 | #ifdef HAS_SETEUID | |
599 | (void)seteuid((UIDTYPE)euid); | |
600 | #else | |
601 | #ifdef HAS_SETREUID | |
602 | (void)setreuid((UIDTYPE)-1, (UIDTYPE)euid); | |
603 | #else | |
604 | if (euid == uid) /* special case $> = $< */ | |
605 | setuid(euid); | |
606 | else | |
607 | fatal("seteuid() not implemented"); | |
608 | #endif | |
609 | #endif | |
610 | euid = (int)geteuid(); | |
611 | break; | |
612 | case '(': | |
613 | gid = (int)str_gnum(str); | |
614 | if (delaymagic) { | |
615 | delaymagic |= DM_RGID; | |
616 | break; /* don't do magic till later */ | |
617 | } | |
618 | #ifdef HAS_SETRGID | |
619 | (void)setrgid((GIDTYPE)gid); | |
620 | #else | |
621 | #ifdef HAS_SETREGID | |
622 | (void)setregid((GIDTYPE)gid, (GIDTYPE)-1); | |
623 | #else | |
624 | if (gid == egid) /* special case $( = $) */ | |
625 | (void)setgid(gid); | |
626 | else | |
627 | fatal("setrgid() not implemented"); | |
628 | #endif | |
629 | #endif | |
630 | gid = (int)getgid(); | |
631 | break; | |
632 | case ')': | |
633 | egid = (int)str_gnum(str); | |
634 | if (delaymagic) { | |
635 | delaymagic |= DM_EGID; | |
636 | break; /* don't do magic till later */ | |
637 | } | |
638 | #ifdef HAS_SETEGID | |
639 | (void)setegid((GIDTYPE)egid); | |
640 | #else | |
641 | #ifdef HAS_SETREGID | |
642 | (void)setregid((GIDTYPE)-1, (GIDTYPE)egid); | |
643 | #else | |
644 | if (egid == gid) /* special case $) = $( */ | |
645 | (void)setgid(egid); | |
646 | else | |
647 | fatal("setegid() not implemented"); | |
648 | #endif | |
649 | #endif | |
650 | egid = (int)getegid(); | |
651 | break; | |
652 | case ':': | |
653 | chopset = str_get(str); | |
654 | break; | |
655 | case '0': | |
656 | if (!origalen) { | |
657 | s = origargv[0]; | |
658 | s += strlen(s); | |
659 | /* See if all the arguments are contiguous in memory */ | |
660 | for (i = 1; i < origargc; i++) { | |
661 | if (origargv[i] == s + 1) | |
662 | s += strlen(++s); /* this one is ok too */ | |
663 | } | |
664 | if (origenviron[0] == s + 1) { /* can grab env area too? */ | |
665 | my_setenv("NoNeSuCh", Nullch); | |
666 | /* force copy of environment */ | |
667 | for (i = 0; origenviron[i]; i++) | |
668 | if (origenviron[i] == s + 1) | |
669 | s += strlen(++s); | |
670 | } | |
671 | origalen = s - origargv[0]; | |
672 | } | |
673 | s = str_get(str); | |
674 | i = str->str_cur; | |
675 | if (i >= origalen) { | |
676 | i = origalen; | |
677 | str->str_cur = i; | |
678 | str->str_ptr[i] = '\0'; | |
679 | Copy(s, origargv[0], i, char); | |
680 | } | |
681 | else { | |
682 | Copy(s, origargv[0], i, char); | |
683 | s = origargv[0]+i; | |
684 | *s++ = '\0'; | |
685 | while (++i < origalen) | |
686 | *s++ = ' '; | |
687 | } | |
688 | break; | |
689 | default: | |
690 | { | |
691 | struct ufuncs *uf = (struct ufuncs *)str->str_magic->str_ptr; | |
692 | ||
693 | if (uf && uf->uf_set) | |
694 | (*uf->uf_set)(uf->uf_index, str); | |
695 | } | |
696 | break; | |
697 | } | |
698 | break; | |
699 | } | |
700 | } | |
701 | ||
702 | int | |
703 | whichsig(sig) | |
704 | char *sig; | |
705 | { | |
706 | register char **sigv; | |
707 | ||
708 | for (sigv = sig_name+1; *sigv; sigv++) | |
709 | if (strEQ(sig,*sigv)) | |
710 | return sigv - sig_name; | |
711 | #ifdef SIGCLD | |
712 | if (strEQ(sig,"CHLD")) | |
713 | return SIGCLD; | |
714 | #endif | |
715 | #ifdef SIGCHLD | |
716 | if (strEQ(sig,"CLD")) | |
717 | return SIGCHLD; | |
718 | #endif | |
719 | return 0; | |
720 | } | |
721 | ||
722 | static handlertype | |
723 | sighandler(sig) | |
724 | int sig; | |
725 | { | |
726 | STAB *stab; | |
727 | STR *str; | |
728 | int oldsave = savestack->ary_fill; | |
729 | int oldtmps_base = tmps_base; | |
730 | register CSV *csv; | |
731 | SUBR *sub; | |
732 | ||
733 | #ifdef OS2 /* or anybody else who requires SIG_ACK */ | |
734 | signal(sig, SIG_ACK); | |
735 | #endif | |
736 | stab = stabent( | |
737 | str_get(hfetch(stab_hash(sigstab),sig_name[sig],strlen(sig_name[sig]), | |
738 | TRUE)), TRUE); | |
739 | sub = stab_sub(stab); | |
740 | if (!sub && *sig_name[sig] == 'C' && instr(sig_name[sig],"LD")) { | |
741 | if (sig_name[sig][1] == 'H') | |
742 | stab = stabent(str_get(hfetch(stab_hash(sigstab),"CLD",3,TRUE)), | |
743 | TRUE); | |
744 | else | |
745 | stab = stabent(str_get(hfetch(stab_hash(sigstab),"CHLD",4,TRUE)), | |
746 | TRUE); | |
747 | sub = stab_sub(stab); /* gag */ | |
748 | } | |
749 | if (!sub) { | |
750 | if (dowarn) | |
751 | warn("SIG%s handler \"%s\" not defined.\n", | |
752 | sig_name[sig], stab_ename(stab) ); | |
753 | return; | |
754 | } | |
755 | /*SUPPRESS 701*/ | |
756 | saveaptr(&stack); | |
757 | str = Str_new(15, sizeof(CSV)); | |
758 | str->str_state = SS_SCSV; | |
759 | (void)apush(savestack,str); | |
760 | csv = (CSV*)str->str_ptr; | |
761 | csv->sub = sub; | |
762 | csv->stab = stab; | |
763 | csv->curcsv = curcsv; | |
764 | csv->curcmd = curcmd; | |
765 | csv->depth = sub->depth; | |
766 | csv->wantarray = G_SCALAR; | |
767 | csv->hasargs = TRUE; | |
768 | csv->savearray = stab_xarray(defstab); | |
769 | csv->argarray = stab_xarray(defstab) = stack = anew(defstab); | |
770 | stack->ary_flags = 0; | |
771 | curcsv = csv; | |
772 | str = str_mortal(&str_undef); | |
773 | str_set(str,sig_name[sig]); | |
774 | (void)apush(stab_xarray(defstab),str); | |
775 | sub->depth++; | |
776 | if (sub->depth >= 2) { /* save temporaries on recursion? */ | |
777 | if (sub->depth == 100 && dowarn) | |
778 | warn("Deep recursion on subroutine \"%s\"",stab_ename(stab)); | |
779 | savelist(sub->tosave->ary_array,sub->tosave->ary_fill); | |
780 | } | |
781 | ||
782 | tmps_base = tmps_max; /* protect our mortal string */ | |
783 | (void)cmd_exec(sub->cmd,G_SCALAR,0); /* so do it already */ | |
784 | tmps_base = oldtmps_base; | |
785 | ||
786 | restorelist(oldsave); /* put everything back */ | |
787 | } | |
788 | ||
789 | STAB * | |
790 | aadd(stab) | |
791 | register STAB *stab; | |
792 | { | |
793 | if (!stab_xarray(stab)) | |
794 | stab_xarray(stab) = anew(stab); | |
795 | return stab; | |
796 | } | |
797 | ||
798 | STAB * | |
799 | hadd(stab) | |
800 | register STAB *stab; | |
801 | { | |
802 | if (!stab_xhash(stab)) | |
803 | stab_xhash(stab) = hnew(COEFFSIZE); | |
804 | return stab; | |
805 | } | |
806 | ||
807 | STAB * | |
808 | fstab(name) | |
809 | char *name; | |
810 | { | |
811 | char tmpbuf[1200]; | |
812 | STAB *stab; | |
813 | ||
814 | sprintf(tmpbuf,"'_<%s", name); | |
815 | stab = stabent(tmpbuf, TRUE); | |
816 | str_set(stab_val(stab), name); | |
817 | if (perldb) | |
818 | (void)hadd(aadd(stab)); | |
819 | return stab; | |
820 | } | |
821 | ||
822 | STAB * | |
823 | stabent(name,add) | |
824 | register char *name; | |
825 | int add; | |
826 | { | |
827 | register STAB *stab; | |
828 | register STBP *stbp; | |
829 | int len; | |
830 | register char *namend; | |
831 | HASH *stash; | |
832 | char *sawquote = Nullch; | |
833 | char *prevquote = Nullch; | |
834 | bool global = FALSE; | |
835 | ||
836 | if (isUPPER(*name)) { | |
837 | if (*name > 'I') { | |
838 | if (*name == 'S' && ( | |
839 | strEQ(name, "SIG") || | |
840 | strEQ(name, "STDIN") || | |
841 | strEQ(name, "STDOUT") || | |
842 | strEQ(name, "STDERR") )) | |
843 | global = TRUE; | |
844 | } | |
845 | else if (*name > 'E') { | |
846 | if (*name == 'I' && strEQ(name, "INC")) | |
847 | global = TRUE; | |
848 | } | |
849 | else if (*name > 'A') { | |
850 | if (*name == 'E' && strEQ(name, "ENV")) | |
851 | global = TRUE; | |
852 | } | |
853 | else if (*name == 'A' && ( | |
854 | strEQ(name, "ARGV") || | |
855 | strEQ(name, "ARGVOUT") )) | |
856 | global = TRUE; | |
857 | } | |
858 | for (namend = name; *namend; namend++) { | |
859 | if (*namend == '\'' && namend[1]) | |
860 | prevquote = sawquote, sawquote = namend; | |
861 | } | |
862 | if (sawquote == name && name[1]) { | |
863 | stash = defstash; | |
864 | sawquote = Nullch; | |
865 | name++; | |
866 | } | |
867 | else if (!isALPHA(*name) || global) | |
868 | stash = defstash; | |
869 | else if ((CMD*)curcmd == &compiling) | |
870 | stash = curstash; | |
871 | else | |
872 | stash = curcmd->c_stash; | |
873 | if (sawquote) { | |
874 | char tmpbuf[256]; | |
875 | char *s, *d; | |
876 | ||
877 | *sawquote = '\0'; | |
878 | /*SUPPRESS 560*/ | |
879 | if (s = prevquote) { | |
880 | strncpy(tmpbuf,name,s-name+1); | |
881 | d = tmpbuf+(s-name+1); | |
882 | *d++ = '_'; | |
883 | strcpy(d,s+1); | |
884 | } | |
885 | else { | |
886 | *tmpbuf = '_'; | |
887 | strcpy(tmpbuf+1,name); | |
888 | } | |
889 | stab = stabent(tmpbuf,TRUE); | |
890 | if (!(stash = stab_xhash(stab))) | |
891 | stash = stab_xhash(stab) = hnew(0); | |
892 | if (!stash->tbl_name) | |
893 | stash->tbl_name = savestr(name); | |
894 | name = sawquote+1; | |
895 | *sawquote = '\''; | |
896 | } | |
897 | len = namend - name; | |
898 | stab = (STAB*)hfetch(stash,name,len,add); | |
899 | if (stab == (STAB*)&str_undef) | |
900 | return Nullstab; | |
901 | if (stab->str_pok) { | |
902 | stab->str_pok |= SP_MULTI; | |
903 | return stab; | |
904 | } | |
905 | else { | |
906 | if (stab->str_len) | |
907 | Safefree(stab->str_ptr); | |
908 | Newz(602,stbp, 1, STBP); | |
909 | stab->str_ptr = stbp; | |
910 | stab->str_len = stab->str_cur = sizeof(STBP); | |
911 | stab->str_pok = 1; | |
912 | strcpy(stab_magic(stab),"StB"); | |
913 | stab_val(stab) = Str_new(72,0); | |
914 | stab_line(stab) = curcmd->c_line; | |
915 | stab_estab(stab) = stab; | |
916 | str_magic((STR*)stab, stab, '*', name, len); | |
917 | stab_stash(stab) = stash; | |
918 | if (isDIGIT(*name) && *name != '0') { | |
919 | stab_flags(stab) = SF_VMAGIC; | |
920 | str_magic(stab_val(stab), stab, 0, Nullch, 0); | |
921 | } | |
922 | if (add & 2) | |
923 | stab->str_pok |= SP_MULTI; | |
924 | return stab; | |
925 | } | |
926 | } | |
927 | ||
928 | void | |
929 | stab_fullname(str,stab) | |
930 | STR *str; | |
931 | STAB *stab; | |
932 | { | |
933 | HASH *tb = stab_stash(stab); | |
934 | ||
935 | if (!tb) | |
936 | return; | |
937 | str_set(str,tb->tbl_name); | |
938 | str_ncat(str,"'", 1); | |
939 | str_scat(str,stab->str_magic); | |
940 | } | |
941 | ||
942 | void | |
943 | stab_efullname(str,stab) | |
944 | STR *str; | |
945 | STAB *stab; | |
946 | { | |
947 | HASH *tb = stab_estash(stab); | |
948 | ||
949 | if (!tb) | |
950 | return; | |
951 | str_set(str,tb->tbl_name); | |
952 | str_ncat(str,"'", 1); | |
953 | str_scat(str,stab_estab(stab)->str_magic); | |
954 | } | |
955 | ||
956 | STIO * | |
957 | stio_new() | |
958 | { | |
959 | STIO *stio; | |
960 | ||
961 | Newz(603,stio,1,STIO); | |
962 | stio->page_len = 60; | |
963 | return stio; | |
964 | } | |
965 | ||
966 | void | |
967 | stab_check(min,max) | |
968 | int min; | |
969 | register int max; | |
970 | { | |
971 | register HENT *entry; | |
972 | register int i; | |
973 | register STAB *stab; | |
974 | ||
975 | for (i = min; i <= max; i++) { | |
976 | for (entry = defstash->tbl_array[i]; entry; entry = entry->hent_next) { | |
977 | stab = (STAB*)entry->hent_val; | |
978 | if (stab->str_pok & SP_MULTI) | |
979 | continue; | |
980 | curcmd->c_line = stab_line(stab); | |
981 | warn("Possible typo: \"%s\"", stab_name(stab)); | |
982 | } | |
983 | } | |
984 | } | |
985 | ||
986 | static int gensym = 0; | |
987 | ||
988 | STAB * | |
989 | genstab() | |
990 | { | |
991 | (void)sprintf(tokenbuf,"_GEN_%d",gensym++); | |
992 | return stabent(tokenbuf,TRUE); | |
993 | } | |
994 | ||
995 | /* hopefully this is only called on local symbol table entries */ | |
996 | ||
997 | void | |
998 | stab_clear(stab) | |
999 | register STAB *stab; | |
1000 | { | |
1001 | STIO *stio; | |
1002 | SUBR *sub; | |
1003 | ||
1004 | if (!stab || !stab->str_ptr) | |
1005 | return; | |
1006 | afree(stab_xarray(stab)); | |
1007 | stab_xarray(stab) = Null(ARRAY*); | |
1008 | (void)hfree(stab_xhash(stab), FALSE); | |
1009 | stab_xhash(stab) = Null(HASH*); | |
1010 | str_free(stab_val(stab)); | |
1011 | stab_val(stab) = Nullstr; | |
1012 | /*SUPPRESS 560*/ | |
1013 | if (stio = stab_io(stab)) { | |
1014 | do_close(stab,FALSE); | |
1015 | Safefree(stio->top_name); | |
1016 | Safefree(stio->fmt_name); | |
1017 | Safefree(stio); | |
1018 | } | |
1019 | /*SUPPRESS 560*/ | |
1020 | if (sub = stab_sub(stab)) { | |
1021 | afree(sub->tosave); | |
1022 | cmd_free(sub->cmd); | |
1023 | } | |
1024 | Safefree(stab->str_ptr); | |
1025 | stab->str_ptr = Null(STBP*); | |
1026 | stab->str_len = 0; | |
1027 | stab->str_cur = 0; | |
1028 | } | |
1029 | ||
1030 | #if defined(CRIPPLED_CC) && (defined(iAPX286) || defined(M_I286) || defined(I80286)) | |
1031 | #define MICROPORT | |
1032 | #endif | |
1033 | ||
1034 | #ifdef MICROPORT /* Microport 2.4 hack */ | |
1035 | ARRAY *stab_array(stab) | |
1036 | register STAB *stab; | |
1037 | { | |
1038 | if (((STBP*)(stab->str_ptr))->stbp_array) | |
1039 | return ((STBP*)(stab->str_ptr))->stbp_array; | |
1040 | else | |
1041 | return ((STBP*)(aadd(stab)->str_ptr))->stbp_array; | |
1042 | } | |
1043 | ||
1044 | HASH *stab_hash(stab) | |
1045 | register STAB *stab; | |
1046 | { | |
1047 | if (((STBP*)(stab->str_ptr))->stbp_hash) | |
1048 | return ((STBP*)(stab->str_ptr))->stbp_hash; | |
1049 | else | |
1050 | return ((STBP*)(hadd(stab)->str_ptr))->stbp_hash; | |
1051 | } | |
1052 | #endif /* Microport 2.4 hack */ |