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