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