perl 3.0 patch #8 patch 7 continued
[p5sagit/p5-mst-13.2.git] / stab.c
CommitLineData
663a0e37 1/* $Header: stab.c,v 3.0.1.3 89/12/21 20:18:40 lwall Locked $
a687059c 2 *
3 * Copyright (c) 1989, Larry Wall
4 *
5 * You may distribute under the terms of the GNU General Public License
6 * as specified in the README file that comes with the perl 3.0 kit.
8d063cd8 7 *
8 * $Log: stab.c,v $
663a0e37 9 * Revision 3.0.1.3 89/12/21 20:18:40 lwall
10 * patch7: ANSI strerror() is now supported
11 * patch7: errno may now be a macro with an lvalue
12 * patch7: in stab.c, sighandler() may now return either void or int
13 *
ffed7fef 14 * Revision 3.0.1.2 89/11/17 15:35:37 lwall
15 * patch5: sighandler() needed to be static
16 *
ae986130 17 * Revision 3.0.1.1 89/11/11 04:55:07 lwall
18 * patch2: sys_errlist[sys_nerr] is illegal
19 *
a687059c 20 * Revision 3.0 89/10/18 15:23:23 lwall
21 * 3.0 baseline
8d063cd8 22 *
23 */
24
8d063cd8 25#include "EXTERN.h"
8d063cd8 26#include "perl.h"
27
378cc40b 28#include <signal.h>
29
8d063cd8 30static char *sig_name[] = {
a687059c 31 SIG_NAME,0
32};
8d063cd8 33
663a0e37 34#ifdef VOIDSIG
35#define handlertype void
36#else
37#define handlertype int
38#endif
2e1b3b7e 39
8d063cd8 40STR *
a687059c 41stab_str(str)
42STR *str;
8d063cd8 43{
a687059c 44 STAB *stab = str->str_u.str_stab;
8d063cd8 45 register int paren;
46 register char *s;
378cc40b 47 register int i;
8d063cd8 48
a687059c 49 if (str->str_rare)
50 return stab_val(stab);
51
52 switch (*stab->str_magic->str_ptr) {
8d063cd8 53 case '0': case '1': case '2': case '3': case '4':
54 case '5': case '6': case '7': case '8': case '9': case '&':
55 if (curspat) {
a687059c 56 paren = atoi(stab_name(stab));
378cc40b 57 getparen:
58 if (curspat->spat_regexp &&
59 paren <= curspat->spat_regexp->nparens &&
60 (s = curspat->spat_regexp->startp[paren]) ) {
61 i = curspat->spat_regexp->endp[paren] - s;
62 if (i >= 0)
a687059c 63 str_nset(stab_val(stab),s,i);
378cc40b 64 else
a687059c 65 str_sset(stab_val(stab),&str_undef);
8d063cd8 66 }
378cc40b 67 else
a687059c 68 str_sset(stab_val(stab),&str_undef);
8d063cd8 69 }
70 break;
71 case '+':
72 if (curspat) {
378cc40b 73 paren = curspat->spat_regexp->lastparen;
74 goto getparen;
8d063cd8 75 }
76 break;
a687059c 77 case '`':
78 if (curspat) {
79 if (curspat->spat_regexp &&
80 (s = curspat->spat_regexp->subbase) ) {
81 i = curspat->spat_regexp->startp[0] - s;
82 if (i >= 0)
83 str_nset(stab_val(stab),s,i);
84 else
85 str_nset(stab_val(stab),"",0);
86 }
87 else
88 str_nset(stab_val(stab),"",0);
89 }
90 break;
91 case '\'':
92 if (curspat) {
93 if (curspat->spat_regexp &&
94 (s = curspat->spat_regexp->endp[0]) ) {
95 str_set(stab_val(stab),s);
96 }
97 else
98 str_nset(stab_val(stab),"",0);
99 }
100 break;
8d063cd8 101 case '.':
a687059c 102#ifndef lint
8d063cd8 103 if (last_in_stab) {
a687059c 104 str_numset(stab_val(stab),(double)stab_io(last_in_stab)->lines);
8d063cd8 105 }
a687059c 106#endif
8d063cd8 107 break;
108 case '?':
a687059c 109 str_numset(stab_val(stab),(double)statusvalue);
8d063cd8 110 break;
111 case '^':
a687059c 112 s = stab_io(curoutstab)->top_name;
113 str_set(stab_val(stab),s);
8d063cd8 114 break;
115 case '~':
a687059c 116 s = stab_io(curoutstab)->fmt_name;
117 str_set(stab_val(stab),s);
8d063cd8 118 break;
a687059c 119#ifndef lint
8d063cd8 120 case '=':
a687059c 121 str_numset(stab_val(stab),(double)stab_io(curoutstab)->page_len);
8d063cd8 122 break;
123 case '-':
a687059c 124 str_numset(stab_val(stab),(double)stab_io(curoutstab)->lines_left);
8d063cd8 125 break;
126 case '%':
a687059c 127 str_numset(stab_val(stab),(double)stab_io(curoutstab)->page);
8d063cd8 128 break;
a687059c 129#endif
8d063cd8 130 case '/':
131 *tokenbuf = record_separator;
132 tokenbuf[1] = '\0';
a687059c 133 str_nset(stab_val(stab),tokenbuf,rslen);
8d063cd8 134 break;
135 case '[':
a687059c 136 str_numset(stab_val(stab),(double)arybase);
8d063cd8 137 break;
138 case '|':
a687059c 139 str_numset(stab_val(stab),
140 (double)((stab_io(curoutstab)->flags & IOF_FLUSH) != 0) );
8d063cd8 141 break;
142 case ',':
a687059c 143 str_nset(stab_val(stab),ofs,ofslen);
8d063cd8 144 break;
145 case '\\':
a687059c 146 str_nset(stab_val(stab),ors,orslen);
8d063cd8 147 break;
148 case '#':
a687059c 149 str_set(stab_val(stab),ofmt);
8d063cd8 150 break;
151 case '!':
a687059c 152 str_numset(stab_val(stab), (double)errno);
663a0e37 153 str_set(stab_val(stab), strerror(errno));
a687059c 154 stab_val(stab)->str_nok = 1; /* what a wonderful hack! */
378cc40b 155 break;
156 case '<':
a687059c 157 str_numset(stab_val(stab),(double)uid);
378cc40b 158 break;
159 case '>':
a687059c 160 str_numset(stab_val(stab),(double)euid);
378cc40b 161 break;
162 case '(':
a687059c 163 s = buf;
164 (void)sprintf(s,"%d",(int)gid);
378cc40b 165 goto add_groups;
166 case ')':
a687059c 167 s = buf;
168 (void)sprintf(s,"%d",(int)egid);
378cc40b 169 add_groups:
170 while (*s) s++;
171#ifdef GETGROUPS
172#ifndef NGROUPS
173#define NGROUPS 32
174#endif
175 {
176 GIDTYPE gary[NGROUPS];
177
178 i = getgroups(NGROUPS,gary);
179 while (--i >= 0) {
a687059c 180 (void)sprintf(s," %ld", (long)gary[i]);
378cc40b 181 while (*s) s++;
182 }
183 }
184#endif
a687059c 185 str_set(stab_val(stab),buf);
8d063cd8 186 break;
187 }
a687059c 188 return stab_val(stab);
8d063cd8 189}
190
a687059c 191stabset(mstr,str)
192register STR *mstr;
8d063cd8 193STR *str;
194{
a687059c 195 STAB *stab = mstr->str_u.str_stab;
8d063cd8 196 char *s;
197 int i;
663a0e37 198 static handlertype sighandler();
8d063cd8 199
a687059c 200 switch (mstr->str_rare) {
201 case 'E':
202 setenv(mstr->str_ptr,str_get(str));
203 /* And you'll never guess what the dog had */
204 break; /* in its mouth... */
205 case 'S':
206 s = str_get(str);
207 i = whichsig(mstr->str_ptr); /* ...no, a brick */
208 if (strEQ(s,"IGNORE"))
209#ifndef lint
210 (void)signal(i,SIG_IGN);
211#else
212 ;
213#endif
214 else if (strEQ(s,"DEFAULT") || !*s)
215 (void)signal(i,SIG_DFL);
216 else
217 (void)signal(i,sighandler);
218 break;
219#ifdef SOME_DBM
220 case 'D':
221 hdbmstore(stab_hash(stab),mstr->str_ptr,mstr->str_cur,str);
222 break;
223#endif
224 case '#':
225 afill(stab_array(stab), (int)str_gnum(str) - arybase);
226 break;
227 case 'X': /* merely a copy of a * string */
228 break;
229 case '*':
230 s = str_get(str);
231 if (strnNE(s,"Stab",4) || str->str_cur != sizeof(STBP)) {
232 if (!*s) {
233 STBP *stbp;
234
235 (void)savenostab(stab); /* schedule a free of this stab */
236 if (stab->str_len)
237 Safefree(stab->str_ptr);
238 Newz(601,stbp, 1, STBP);
239 stab->str_ptr = stbp;
240 stab->str_len = stab->str_cur = sizeof(STBP);
241 stab->str_pok = 1;
242 strncpy(stab_magic(stab),"Stab",4);
243 stab_val(stab) = Str_new(70,0);
244 stab_line(stab) = line;
245 }
246 else
247 stab = stabent(s,TRUE);
248 str_sset(str,stab);
249 }
250 break;
251 case 's': {
252 struct lstring *lstr = (struct lstring*)str;
253
254 mstr->str_rare = 0;
255 str->str_magic = Nullstr;
256 str_insert(mstr,lstr->lstr_offset,lstr->lstr_len,
257 str->str_ptr,str->str_cur);
258 }
259 break;
260
261 case 'v':
262 do_vecset(mstr,str);
263 break;
264
265 case 0:
266 switch (*stab->str_magic->str_ptr) {
8d063cd8 267 case '^':
a687059c 268 Safefree(stab_io(curoutstab)->top_name);
269 stab_io(curoutstab)->top_name = s = savestr(str_get(str));
270 stab_io(curoutstab)->top_stab = stabent(s,TRUE);
8d063cd8 271 break;
272 case '~':
a687059c 273 Safefree(stab_io(curoutstab)->fmt_name);
274 stab_io(curoutstab)->fmt_name = s = savestr(str_get(str));
275 stab_io(curoutstab)->fmt_stab = stabent(s,TRUE);
8d063cd8 276 break;
277 case '=':
a687059c 278 stab_io(curoutstab)->page_len = (long)str_gnum(str);
8d063cd8 279 break;
280 case '-':
a687059c 281 stab_io(curoutstab)->lines_left = (long)str_gnum(str);
282 if (stab_io(curoutstab)->lines_left < 0L)
283 stab_io(curoutstab)->lines_left = 0L;
8d063cd8 284 break;
285 case '%':
a687059c 286 stab_io(curoutstab)->page = (long)str_gnum(str);
8d063cd8 287 break;
288 case '|':
a687059c 289 stab_io(curoutstab)->flags &= ~IOF_FLUSH;
8d063cd8 290 if (str_gnum(str) != 0.0) {
a687059c 291 stab_io(curoutstab)->flags |= IOF_FLUSH;
8d063cd8 292 }
293 break;
294 case '*':
a687059c 295 i = (int)str_gnum(str);
296 multiline = (i != 0);
8d063cd8 297 break;
298 case '/':
299 record_separator = *str_get(str);
a687059c 300 rslen = str->str_cur;
8d063cd8 301 break;
302 case '\\':
303 if (ors)
a687059c 304 Safefree(ors);
8d063cd8 305 ors = savestr(str_get(str));
a687059c 306 orslen = str->str_cur;
8d063cd8 307 break;
308 case ',':
309 if (ofs)
a687059c 310 Safefree(ofs);
8d063cd8 311 ofs = savestr(str_get(str));
a687059c 312 ofslen = str->str_cur;
8d063cd8 313 break;
314 case '#':
315 if (ofmt)
a687059c 316 Safefree(ofmt);
8d063cd8 317 ofmt = savestr(str_get(str));
318 break;
319 case '[':
320 arybase = (int)str_gnum(str);
321 break;
378cc40b 322 case '?':
323 statusvalue = (unsigned short)str_gnum(str);
324 break;
8d063cd8 325 case '!':
326 errno = (int)str_gnum(str); /* will anyone ever use this? */
327 break;
378cc40b 328 case '<':
378cc40b 329 uid = (int)str_gnum(str);
a687059c 330#ifdef SETREUID
331 if (delaymagic) {
332 delaymagic |= DM_REUID;
333 break; /* don't do magic till later */
334 }
335#endif /* SETREUID */
336#ifdef SETRUID
337 if (setruid((UIDTYPE)uid) < 0)
338 uid = (int)getuid();
339#else
340#ifdef SETREUID
341 if (setreuid((UIDTYPE)uid, (UIDTYPE)-1) < 0)
378cc40b 342 uid = (int)getuid();
343#else
344 fatal("setruid() not implemented");
345#endif
a687059c 346#endif
378cc40b 347 break;
348 case '>':
378cc40b 349 euid = (int)str_gnum(str);
a687059c 350#ifdef SETREUID
351 if (delaymagic) {
352 delaymagic |= DM_REUID;
353 break; /* don't do magic till later */
354 }
355#endif /* SETREUID */
356#ifdef SETEUID
357 if (seteuid((UIDTYPE)euid) < 0)
358 euid = (int)geteuid();
359#else
360#ifdef SETREUID
361 if (setreuid((UIDTYPE)-1, (UIDTYPE)euid) < 0)
378cc40b 362 euid = (int)geteuid();
363#else
364 fatal("seteuid() not implemented");
365#endif
a687059c 366#endif
378cc40b 367 break;
368 case '(':
a687059c 369 gid = (int)str_gnum(str);
370#ifdef SETREGID
371 if (delaymagic) {
372 delaymagic |= DM_REGID;
373 break; /* don't do magic till later */
374 }
375#endif /* SETREGID */
378cc40b 376#ifdef SETRGID
a687059c 377 (void)setrgid((GIDTYPE)gid);
378#else
379#ifdef SETREGID
380 (void)setregid((GIDTYPE)gid, (GIDTYPE)-1);
378cc40b 381#else
382 fatal("setrgid() not implemented");
383#endif
a687059c 384#endif
378cc40b 385 break;
386 case ')':
a687059c 387 egid = (int)str_gnum(str);
388#ifdef SETREGID
389 if (delaymagic) {
390 delaymagic |= DM_REGID;
391 break; /* don't do magic till later */
392 }
393#endif /* SETREGID */
378cc40b 394#ifdef SETEGID
a687059c 395 (void)setegid((GIDTYPE)egid);
396#else
397#ifdef SETREGID
398 (void)setregid((GIDTYPE)-1, (GIDTYPE)egid);
378cc40b 399#else
400 fatal("setegid() not implemented");
401#endif
a687059c 402#endif
403 break;
404 case ':':
405 chopset = str_get(str);
378cc40b 406 break;
8d063cd8 407 }
a687059c 408 break;
378cc40b 409 }
8d063cd8 410}
411
378cc40b 412whichsig(sig)
413char *sig;
8d063cd8 414{
415 register char **sigv;
416
417 for (sigv = sig_name+1; *sigv; sigv++)
378cc40b 418 if (strEQ(sig,*sigv))
8d063cd8 419 return sigv - sig_name;
a687059c 420#ifdef SIGCLD
421 if (strEQ(sig,"CHLD"))
422 return SIGCLD;
423#endif
424#ifdef SIGCHLD
425 if (strEQ(sig,"CLD"))
426 return SIGCHLD;
427#endif
8d063cd8 428 return 0;
429}
430
663a0e37 431static handlertype
8d063cd8 432sighandler(sig)
433int sig;
434{
435 STAB *stab;
436 ARRAY *savearray;
437 STR *str;
378cc40b 438 char *oldfile = filename;
439 int oldsave = savestack->ary_fill;
a687059c 440 ARRAY *oldstack = stack;
378cc40b 441 SUBR *sub;
8d063cd8 442
a687059c 443 stab = stabent(
444 str_get(hfetch(stab_hash(sigstab),sig_name[sig],strlen(sig_name[sig]),
445 TRUE)), TRUE);
446 sub = stab_sub(stab);
447 if (!sub && *sig_name[sig] == 'C' && instr(sig_name[sig],"LD")) {
448 if (sig_name[sig][1] == 'H')
449 stab = stabent(str_get(hfetch(stab_hash(sigstab),"CLD",3,TRUE)),
450 TRUE);
451 else
452 stab = stabent(str_get(hfetch(stab_hash(sigstab),"CHLD",4,TRUE)),
453 TRUE);
454 sub = stab_sub(stab); /* gag */
455 }
378cc40b 456 if (!sub) {
457 if (dowarn)
458 warn("SIG%s handler \"%s\" not defined.\n",
a687059c 459 sig_name[sig], stab_name(stab) );
378cc40b 460 return;
461 }
a687059c 462 savearray = stab_xarray(defstab);
463 stab_xarray(defstab) = stack = anew(defstab);
464 stack->ary_flags = 0;
465 str = Str_new(71,0);
8d063cd8 466 str_set(str,sig_name[sig]);
a687059c 467 (void)apush(stab_xarray(defstab),str);
378cc40b 468 sub->depth++;
469 if (sub->depth >= 2) { /* save temporaries on recursion? */
470 if (sub->depth == 100 && dowarn)
a687059c 471 warn("Deep recursion on subroutine \"%s\"",stab_name(stab));
378cc40b 472 savelist(sub->tosave->ary_array,sub->tosave->ary_fill);
473 }
474 filename = sub->filename;
475
a687059c 476 (void)cmd_exec(sub->cmd,G_SCALAR,1); /* so do it already */
378cc40b 477
478 sub->depth--; /* assuming no longjumps out of here */
a687059c 479 str_free(stack->ary_array[0]); /* free the one real string */
480 afree(stab_xarray(defstab)); /* put back old $_[] */
481 stab_xarray(defstab) = savearray;
482 stack = oldstack;
378cc40b 483 filename = oldfile;
484 if (savestack->ary_fill > oldsave)
485 restorelist(oldsave);
8d063cd8 486}
487
8d063cd8 488STAB *
489aadd(stab)
490register STAB *stab;
491{
a687059c 492 if (!stab_xarray(stab))
493 stab_xarray(stab) = anew(stab);
8d063cd8 494 return stab;
495}
496
497STAB *
498hadd(stab)
499register STAB *stab;
500{
a687059c 501 if (!stab_xhash(stab))
502 stab_xhash(stab) = hnew(COEFFSIZE);
8d063cd8 503 return stab;
504}
378cc40b 505
506STAB *
507stabent(name,add)
508register char *name;
509int add;
510{
511 register STAB *stab;
a687059c 512 register STBP *stbp;
513 int len;
514 register char *namend;
515 HASH *stash;
516 char *sawquote = Nullch;
517 char *prevquote = Nullch;
518 bool global = FALSE;
378cc40b 519
a687059c 520 if (isascii(*name) && isupper(*name)) {
521 if (*name > 'I') {
522 if (*name == 'S' && (
523 strEQ(name, "SIG") ||
524 strEQ(name, "STDIN") ||
525 strEQ(name, "STDOUT") ||
526 strEQ(name, "STDERR") ))
527 global = TRUE;
378cc40b 528 }
a687059c 529 else if (*name > 'E') {
530 if (*name == 'I' && strEQ(name, "INC"))
531 global = TRUE;
532 }
533 else if (*name >= 'A') {
534 if (*name == 'E' && strEQ(name, "ENV"))
535 global = TRUE;
536 }
537 else if (*name == 'A' && (
538 strEQ(name, "ARGV") ||
539 strEQ(name, "ARGVOUT") ))
540 global = TRUE;
541 }
542 for (namend = name; *namend; namend++) {
543 if (*namend == '\'' && namend[1])
544 prevquote = sawquote, sawquote = namend;
545 }
546 if (sawquote == name && name[1]) {
547 stash = defstash;
548 sawquote = Nullch;
549 name++;
550 }
551 else if (!isalpha(*name) || global)
552 stash = defstash;
553 else
554 stash = curstash;
555 if (sawquote) {
556 char tmpbuf[256];
557 char *s, *d;
558
559 *sawquote = '\0';
560 if (s = prevquote) {
561 strncpy(tmpbuf,name,s-name+1);
562 d = tmpbuf+(s-name+1);
563 *d++ = '_';
564 strcpy(d,s+1);
565 }
566 else {
567 *tmpbuf = '_';
568 strcpy(tmpbuf+1,name);
569 }
570 stab = stabent(tmpbuf,TRUE);
571 if (!(stash = stab_xhash(stab)))
572 stash = stab_xhash(stab) = hnew(0);
573 name = sawquote+1;
574 *sawquote = '\'';
378cc40b 575 }
a687059c 576 len = namend - name;
577 stab = (STAB*)hfetch(stash,name,len,add);
578 if (!stab)
579 return Nullstab;
580 if (stab->str_pok) {
581 stab->str_pok |= SP_MULTI;
582 return stab;
583 }
584 else {
585 if (stab->str_len)
586 Safefree(stab->str_ptr);
587 Newz(602,stbp, 1, STBP);
588 stab->str_ptr = stbp;
589 stab->str_len = stab->str_cur = sizeof(STBP);
590 stab->str_pok = 1;
591 strncpy(stab_magic(stab),"Stab",4);
592 stab_val(stab) = Str_new(72,0);
593 stab_line(stab) = line;
594 str_magic(stab,stab,'*',name,len);
378cc40b 595 return stab;
596 }
378cc40b 597}
598
599STIO *
600stio_new()
601{
a687059c 602 STIO *stio;
378cc40b 603
a687059c 604 Newz(603,stio,1,STIO);
378cc40b 605 stio->page_len = 60;
606 return stio;
607}
608
609stab_check(min,max)
610int min;
611register int max;
612{
a687059c 613 register HENT *entry;
378cc40b 614 register int i;
615 register STAB *stab;
616
617 for (i = min; i <= max; i++) {
a687059c 618 for (entry = defstash->tbl_array[i]; entry; entry = entry->hent_next) {
619 stab = (STAB*)entry->hent_val;
620 if (stab->str_pok & SP_MULTI)
378cc40b 621 continue;
a687059c 622 line = stab_line(stab);
623 warn("Possible typo: \"%s\"", stab_name(stab));
378cc40b 624 }
625 }
626}
a687059c 627
628static int gensym = 0;
629
630STAB *
631genstab()
632{
633 (void)sprintf(tokenbuf,"_GEN_%d",gensym++);
634 return stabent(tokenbuf,TRUE);
635}
636
637/* hopefully this is only called on local symbol table entries */
638
639void
640stab_clear(stab)
641register STAB *stab;
642{
643 STIO *stio;
644 SUBR *sub;
645
646 afree(stab_xarray(stab));
647 (void)hfree(stab_xhash(stab));
648 str_free(stab_val(stab));
649 if (stio = stab_io(stab)) {
650 do_close(stab,FALSE);
651 Safefree(stio->top_name);
652 Safefree(stio->fmt_name);
653 }
654 if (sub = stab_sub(stab)) {
655 afree(sub->tosave);
656 cmd_free(sub->cmd);
657 }
658 Safefree(stab->str_ptr);
659 stab->str_ptr = Null(STBP*);
660 stab->str_len = 0;
661 stab->str_cur = 0;
662}
663