diff options
Diffstat (limited to 'stab.c')
-rw-r--r-- | stab.c | 590 |
1 files changed, 387 insertions, 203 deletions
@@ -1,8 +1,13 @@ -/* $Header: stab.c,v 2.0 88/06/05 00:11:01 root Exp $ +/* $Header: stab.c,v 3.0 89/10/18 15:23:23 lwall Locked $ + * + * Copyright (c) 1989, Larry Wall + * + * You may distribute under the terms of the GNU General Public License + * as specified in the README file that comes with the perl 3.0 kit. * * $Log: stab.c,v $ - * Revision 2.0 88/06/05 00:11:01 root - * Baseline version 2.0. + * Revision 3.0 89/10/18 15:23:23 lwall + * 3.0 baseline * */ @@ -11,83 +16,45 @@ #include <signal.h> +/* This oughta be generated by Configure. */ + static char *sig_name[] = { - "", - "HUP", - "INT", - "QUIT", - "ILL", - "TRAP", - "IOT", - "EMT", - "FPE", - "KILL", - "BUS", - "SEGV", - "SYS", - "PIPE", - "ALRM", - "TERM", - "???" -#ifdef SIGTSTP - ,"STOP", - "TSTP", - "CONT", - "CHLD", - "TTIN", - "TTOU", - "TINT", - "XCPU", - "XFSZ" -#ifdef SIGPROF - ,"VTALARM", - "PROF" -#ifdef SIGWINCH - ,"WINCH" -#ifdef SIGLOST - ,"LOST" -#ifdef SIGUSR1 - ,"USR1" -#endif -#ifdef SIGUSR2 - ,"USR2" -#endif /* SIGUSR2 */ -#endif /* SIGLOST */ -#endif /* SIGWINCH */ -#endif /* SIGPROF */ -#endif /* SIGTSTP */ - ,0 - }; + SIG_NAME,0 +}; extern int errno; extern int sys_nerr; extern char *sys_errlist[]; STR * -stab_str(stab) -STAB *stab; +stab_str(str) +STR *str; { + STAB *stab = str->str_u.str_stab; register int paren; register char *s; register int i; - switch (*stab->stab_name) { + if (str->str_rare) + return stab_val(stab); + + switch (*stab->str_magic->str_ptr) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '&': if (curspat) { - paren = atoi(stab->stab_name); + paren = atoi(stab_name(stab)); getparen: if (curspat->spat_regexp && paren <= curspat->spat_regexp->nparens && (s = curspat->spat_regexp->startp[paren]) ) { i = curspat->spat_regexp->endp[paren] - s; if (i >= 0) - str_nset(stab->stab_val,s,i); + str_nset(stab_val(stab),s,i); else - str_nset(stab->stab_val,"",0); + str_sset(stab_val(stab),&str_undef); } else - str_nset(stab->stab_val,"",0); + str_sset(stab_val(stab),&str_undef); } break; case '+': @@ -96,71 +63,99 @@ STAB *stab; goto getparen; } break; + case '`': + if (curspat) { + if (curspat->spat_regexp && + (s = curspat->spat_regexp->subbase) ) { + i = curspat->spat_regexp->startp[0] - s; + if (i >= 0) + str_nset(stab_val(stab),s,i); + else + str_nset(stab_val(stab),"",0); + } + else + str_nset(stab_val(stab),"",0); + } + break; + case '\'': + if (curspat) { + if (curspat->spat_regexp && + (s = curspat->spat_regexp->endp[0]) ) { + str_set(stab_val(stab),s); + } + else + str_nset(stab_val(stab),"",0); + } + break; case '.': +#ifndef lint if (last_in_stab) { - str_numset(stab->stab_val,(double)last_in_stab->stab_io->lines); + str_numset(stab_val(stab),(double)stab_io(last_in_stab)->lines); } +#endif break; case '?': - str_numset(stab->stab_val,(double)statusvalue); + str_numset(stab_val(stab),(double)statusvalue); break; case '^': - s = curoutstab->stab_io->top_name; - str_set(stab->stab_val,s); + s = stab_io(curoutstab)->top_name; + str_set(stab_val(stab),s); break; case '~': - s = curoutstab->stab_io->fmt_name; - str_set(stab->stab_val,s); + s = stab_io(curoutstab)->fmt_name; + str_set(stab_val(stab),s); break; +#ifndef lint case '=': - str_numset(stab->stab_val,(double)curoutstab->stab_io->page_len); + str_numset(stab_val(stab),(double)stab_io(curoutstab)->page_len); break; case '-': - str_numset(stab->stab_val,(double)curoutstab->stab_io->lines_left); + str_numset(stab_val(stab),(double)stab_io(curoutstab)->lines_left); break; case '%': - str_numset(stab->stab_val,(double)curoutstab->stab_io->page); + str_numset(stab_val(stab),(double)stab_io(curoutstab)->page); break; +#endif case '/': *tokenbuf = record_separator; tokenbuf[1] = '\0'; - str_set(stab->stab_val,tokenbuf); + str_nset(stab_val(stab),tokenbuf,rslen); break; case '[': - str_numset(stab->stab_val,(double)arybase); + str_numset(stab_val(stab),(double)arybase); break; case '|': - str_numset(stab->stab_val, - (double)((curoutstab->stab_io->flags & IOF_FLUSH) != 0) ); + str_numset(stab_val(stab), + (double)((stab_io(curoutstab)->flags & IOF_FLUSH) != 0) ); break; case ',': - str_set(stab->stab_val,ofs); + str_nset(stab_val(stab),ofs,ofslen); break; case '\\': - str_set(stab->stab_val,ors); + str_nset(stab_val(stab),ors,orslen); break; case '#': - str_set(stab->stab_val,ofmt); + str_set(stab_val(stab),ofmt); break; case '!': - str_numset(stab->stab_val, (double)errno); - str_set(stab->stab_val, + str_numset(stab_val(stab), (double)errno); + str_set(stab_val(stab), errno < 0 || errno > sys_nerr ? "(unknown)" : sys_errlist[errno]); - stab->stab_val->str_nok = 1; /* what a wonderful hack! */ + stab_val(stab)->str_nok = 1; /* what a wonderful hack! */ break; case '<': - str_numset(stab->stab_val,(double)uid); + str_numset(stab_val(stab),(double)uid); break; case '>': - str_numset(stab->stab_val,(double)euid); + str_numset(stab_val(stab),(double)euid); break; case '(': - s = tokenbuf; - sprintf(s,"%d",(int)getgid()); + s = buf; + (void)sprintf(s,"%d",(int)gid); goto add_groups; case ')': - s = tokenbuf; - sprintf(s,"%d",(int)getegid()); + s = buf; + (void)sprintf(s,"%d",(int)egid); add_groups: while (*s) s++; #ifdef GETGROUPS @@ -172,71 +167,143 @@ STAB *stab; i = getgroups(NGROUPS,gary); while (--i >= 0) { - sprintf(s," %ld", (long)gary[i]); + (void)sprintf(s," %ld", (long)gary[i]); while (*s) s++; } } #endif - str_set(stab->stab_val,tokenbuf); + str_set(stab_val(stab),buf); break; } - return stab->stab_val; + return stab_val(stab); } -stabset(stab,str) -register STAB *stab; +stabset(mstr,str) +register STR *mstr; STR *str; { + STAB *stab = mstr->str_u.str_stab; char *s; int i; int sighandler(); - if (stab->stab_flags & SF_VMAGIC) { - switch (stab->stab_name[0]) { + switch (mstr->str_rare) { + case 'E': + setenv(mstr->str_ptr,str_get(str)); + /* And you'll never guess what the dog had */ + break; /* in its mouth... */ + case 'S': + s = str_get(str); + i = whichsig(mstr->str_ptr); /* ...no, a brick */ + if (strEQ(s,"IGNORE")) +#ifndef lint + (void)signal(i,SIG_IGN); +#else + ; +#endif + else if (strEQ(s,"DEFAULT") || !*s) + (void)signal(i,SIG_DFL); + else + (void)signal(i,sighandler); + break; +#ifdef SOME_DBM + case 'D': + hdbmstore(stab_hash(stab),mstr->str_ptr,mstr->str_cur,str); + break; +#endif + case '#': + afill(stab_array(stab), (int)str_gnum(str) - arybase); + break; + case 'X': /* merely a copy of a * string */ + break; + case '*': + s = str_get(str); + if (strnNE(s,"Stab",4) || str->str_cur != sizeof(STBP)) { + if (!*s) { + STBP *stbp; + + (void)savenostab(stab); /* schedule a free of this stab */ + if (stab->str_len) + Safefree(stab->str_ptr); + Newz(601,stbp, 1, STBP); + stab->str_ptr = stbp; + stab->str_len = stab->str_cur = sizeof(STBP); + stab->str_pok = 1; + strncpy(stab_magic(stab),"Stab",4); + stab_val(stab) = Str_new(70,0); + stab_line(stab) = line; + } + else + stab = stabent(s,TRUE); + str_sset(str,stab); + } + break; + case 's': { + struct lstring *lstr = (struct lstring*)str; + + mstr->str_rare = 0; + str->str_magic = Nullstr; + str_insert(mstr,lstr->lstr_offset,lstr->lstr_len, + str->str_ptr,str->str_cur); + } + break; + + case 'v': + do_vecset(mstr,str); + break; + + case 0: + switch (*stab->str_magic->str_ptr) { case '^': - safefree(curoutstab->stab_io->top_name); - curoutstab->stab_io->top_name = s = savestr(str_get(str)); - curoutstab->stab_io->top_stab = stabent(s,TRUE); + Safefree(stab_io(curoutstab)->top_name); + stab_io(curoutstab)->top_name = s = savestr(str_get(str)); + stab_io(curoutstab)->top_stab = stabent(s,TRUE); break; case '~': - safefree(curoutstab->stab_io->fmt_name); - curoutstab->stab_io->fmt_name = s = savestr(str_get(str)); - curoutstab->stab_io->fmt_stab = stabent(s,TRUE); + Safefree(stab_io(curoutstab)->fmt_name); + stab_io(curoutstab)->fmt_name = s = savestr(str_get(str)); + stab_io(curoutstab)->fmt_stab = stabent(s,TRUE); break; case '=': - curoutstab->stab_io->page_len = (long)str_gnum(str); + stab_io(curoutstab)->page_len = (long)str_gnum(str); break; case '-': - curoutstab->stab_io->lines_left = (long)str_gnum(str); + stab_io(curoutstab)->lines_left = (long)str_gnum(str); + if (stab_io(curoutstab)->lines_left < 0L) + stab_io(curoutstab)->lines_left = 0L; break; case '%': - curoutstab->stab_io->page = (long)str_gnum(str); + stab_io(curoutstab)->page = (long)str_gnum(str); break; case '|': - curoutstab->stab_io->flags &= ~IOF_FLUSH; + stab_io(curoutstab)->flags &= ~IOF_FLUSH; if (str_gnum(str) != 0.0) { - curoutstab->stab_io->flags |= IOF_FLUSH; + stab_io(curoutstab)->flags |= IOF_FLUSH; } break; case '*': - multiline = (int)str_gnum(str) != 0; + i = (int)str_gnum(str); + multiline = (i != 0); break; case '/': record_separator = *str_get(str); + rslen = str->str_cur; break; case '\\': if (ors) - safefree(ors); + Safefree(ors); ors = savestr(str_get(str)); + orslen = str->str_cur; break; case ',': if (ofs) - safefree(ofs); + Safefree(ofs); ofs = savestr(str_get(str)); + ofslen = str->str_cur; break; case '#': if (ofmt) - safefree(ofmt); + Safefree(ofmt); ofmt = savestr(str_get(str)); break; case '[': @@ -249,73 +316,86 @@ STR *str; errno = (int)str_gnum(str); /* will anyone ever use this? */ break; case '<': -#ifdef SETRUID uid = (int)str_gnum(str); - if (setruid(uid) < 0) +#ifdef SETREUID + if (delaymagic) { + delaymagic |= DM_REUID; + break; /* don't do magic till later */ + } +#endif /* SETREUID */ +#ifdef SETRUID + if (setruid((UIDTYPE)uid) < 0) + uid = (int)getuid(); +#else +#ifdef SETREUID + if (setreuid((UIDTYPE)uid, (UIDTYPE)-1) < 0) uid = (int)getuid(); #else fatal("setruid() not implemented"); #endif +#endif break; case '>': -#ifdef SETEUID euid = (int)str_gnum(str); - if (seteuid(euid) < 0) +#ifdef SETREUID + if (delaymagic) { + delaymagic |= DM_REUID; + break; /* don't do magic till later */ + } +#endif /* SETREUID */ +#ifdef SETEUID + if (seteuid((UIDTYPE)euid) < 0) + euid = (int)geteuid(); +#else +#ifdef SETREUID + if (setreuid((UIDTYPE)-1, (UIDTYPE)euid) < 0) euid = (int)geteuid(); #else fatal("seteuid() not implemented"); #endif +#endif break; case '(': + gid = (int)str_gnum(str); +#ifdef SETREGID + if (delaymagic) { + delaymagic |= DM_REGID; + break; /* don't do magic till later */ + } +#endif /* SETREGID */ #ifdef SETRGID - setrgid((int)str_gnum(str)); + (void)setrgid((GIDTYPE)gid); +#else +#ifdef SETREGID + (void)setregid((GIDTYPE)gid, (GIDTYPE)-1); #else fatal("setrgid() not implemented"); #endif +#endif break; case ')': + egid = (int)str_gnum(str); +#ifdef SETREGID + if (delaymagic) { + delaymagic |= DM_REGID; + break; /* don't do magic till later */ + } +#endif /* SETREGID */ #ifdef SETEGID - setegid((int)str_gnum(str)); + (void)setegid((GIDTYPE)egid); +#else +#ifdef SETREGID + (void)setregid((GIDTYPE)-1, (GIDTYPE)egid); #else fatal("setegid() not implemented"); #endif +#endif + break; + case ':': + chopset = str_get(str); break; - case '.': - case '+': - case '&': - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - break; /* "read-only" registers */ } - } - else if (stab == envstab && envname) { - setenv(envname,str_get(str)); - /* And you'll never guess what the dog had */ - safefree(envname); /* in its mouth... */ - envname = Nullch; - } - else if (stab == sigstab && signame) { - s = str_get(str); - i = whichsig(signame); /* ...no, a brick */ - if (strEQ(s,"IGNORE")) - signal(i,SIG_IGN); - else if (strEQ(s,"DEFAULT") || !*s) - signal(i,SIG_DFL); - else - signal(i,sighandler); - safefree(signame); - signame = Nullch; - } - else if (stab->stab_array) { - afill(stab->stab_array, (int)str_gnum(str) - arybase); + break; } } @@ -327,6 +407,14 @@ char *sig; for (sigv = sig_name+1; *sigv; sigv++) if (strEQ(sig,*sigv)) return sigv - sig_name; +#ifdef SIGCLD + if (strEQ(sig,"CHLD")) + return SIGCLD; +#endif +#ifdef SIGCHLD + if (strEQ(sig,"CLD")) + return SIGCHLD; +#endif return 0; } @@ -338,61 +426,60 @@ int sig; STR *str; char *oldfile = filename; int oldsave = savestack->ary_fill; + ARRAY *oldstack = stack; SUBR *sub; - stab = stabent(str_get(hfetch(sigstab->stab_hash,sig_name[sig])),TRUE); - sub = stab->stab_sub; + stab = stabent( + str_get(hfetch(stab_hash(sigstab),sig_name[sig],strlen(sig_name[sig]), + TRUE)), TRUE); + sub = stab_sub(stab); + if (!sub && *sig_name[sig] == 'C' && instr(sig_name[sig],"LD")) { + if (sig_name[sig][1] == 'H') + stab = stabent(str_get(hfetch(stab_hash(sigstab),"CLD",3,TRUE)), + TRUE); + else + stab = stabent(str_get(hfetch(stab_hash(sigstab),"CHLD",4,TRUE)), + TRUE); + sub = stab_sub(stab); /* gag */ + } if (!sub) { if (dowarn) warn("SIG%s handler \"%s\" not defined.\n", - sig_name[sig], stab->stab_name ); + sig_name[sig], stab_name(stab) ); return; } - savearray = defstab->stab_array; - defstab->stab_array = anew(defstab); - str = str_new(0); + savearray = stab_xarray(defstab); + stab_xarray(defstab) = stack = anew(defstab); + stack->ary_flags = 0; + str = Str_new(71,0); str_set(str,sig_name[sig]); - apush(defstab->stab_array,str); + (void)apush(stab_xarray(defstab),str); sub->depth++; if (sub->depth >= 2) { /* save temporaries on recursion? */ if (sub->depth == 100 && dowarn) - warn("Deep recursion on subroutine \"%s\"",stab->stab_name); + warn("Deep recursion on subroutine \"%s\"",stab_name(stab)); savelist(sub->tosave->ary_array,sub->tosave->ary_fill); } filename = sub->filename; - str = cmd_exec(sub->cmd); /* so do it already */ + (void)cmd_exec(sub->cmd,G_SCALAR,1); /* so do it already */ sub->depth--; /* assuming no longjumps out of here */ - afree(defstab->stab_array); /* put back old $_[] */ - defstab->stab_array = savearray; + str_free(stack->ary_array[0]); /* free the one real string */ + afree(stab_xarray(defstab)); /* put back old $_[] */ + stab_xarray(defstab) = savearray; + stack = oldstack; filename = oldfile; if (savestack->ary_fill > oldsave) restorelist(oldsave); } -char * -reg_get(name) -char *name; -{ - return STAB_GET(stabent(name,TRUE)); -} - -#ifdef NOTUSED -reg_set(name,value) -char *name; -char *value; -{ - str_set(STAB_STR(stabent(name,TRUE)),value); -} -#endif - STAB * aadd(stab) register STAB *stab; { - if (!stab->stab_array) - stab->stab_array = anew(stab); + if (!stab_xarray(stab)) + stab_xarray(stab) = anew(stab); return stab; } @@ -400,8 +487,8 @@ STAB * hadd(stab) register STAB *stab; { - if (!stab->stab_hash) - stab->stab_hash = hnew(); + if (!stab_xhash(stab)) + stab_xhash(stab) = hnew(COEFFSIZE); return stab; } @@ -411,34 +498,99 @@ register char *name; int add; { register STAB *stab; + register STBP *stbp; + int len; + register char *namend; + HASH *stash; + char *sawquote = Nullch; + char *prevquote = Nullch; + bool global = FALSE; - for (stab = stab_index[*name]; stab; stab = stab->stab_next) { - if (strEQ(name,stab->stab_name)) { - stab->stab_flags |= SF_MULTI; /* is okay, probably */ - return stab; + if (isascii(*name) && isupper(*name)) { + if (*name > 'I') { + if (*name == 'S' && ( + strEQ(name, "SIG") || + strEQ(name, "STDIN") || + strEQ(name, "STDOUT") || + strEQ(name, "STDERR") )) + global = TRUE; } + else if (*name > 'E') { + if (*name == 'I' && strEQ(name, "INC")) + global = TRUE; + } + else if (*name >= 'A') { + if (*name == 'E' && strEQ(name, "ENV")) + global = TRUE; + } + else if (*name == 'A' && ( + strEQ(name, "ARGV") || + strEQ(name, "ARGVOUT") )) + global = TRUE; + } + for (namend = name; *namend; namend++) { + if (*namend == '\'' && namend[1]) + prevquote = sawquote, sawquote = namend; + } + if (sawquote == name && name[1]) { + stash = defstash; + sawquote = Nullch; + name++; + } + else if (!isalpha(*name) || global) + stash = defstash; + else + stash = curstash; + if (sawquote) { + char tmpbuf[256]; + char *s, *d; + + *sawquote = '\0'; + if (s = prevquote) { + strncpy(tmpbuf,name,s-name+1); + d = tmpbuf+(s-name+1); + *d++ = '_'; + strcpy(d,s+1); + } + else { + *tmpbuf = '_'; + strcpy(tmpbuf+1,name); + } + stab = stabent(tmpbuf,TRUE); + if (!(stash = stab_xhash(stab))) + stash = stab_xhash(stab) = hnew(0); + name = sawquote+1; + *sawquote = '\''; } - - /* no entry--should we add one? */ - - if (add) { - stab = (STAB *) safemalloc(sizeof(STAB)); - bzero((char*)stab, sizeof(STAB)); - stab->stab_name = savestr(name); - stab->stab_val = str_new(0); - stab->stab_next = stab_index[*name]; - stab_index[*name] = stab; + len = namend - name; + stab = (STAB*)hfetch(stash,name,len,add); + if (!stab) + return Nullstab; + if (stab->str_pok) { + stab->str_pok |= SP_MULTI; + return stab; + } + else { + if (stab->str_len) + Safefree(stab->str_ptr); + Newz(602,stbp, 1, STBP); + stab->str_ptr = stbp; + stab->str_len = stab->str_cur = sizeof(STBP); + stab->str_pok = 1; + strncpy(stab_magic(stab),"Stab",4); + stab_val(stab) = Str_new(72,0); + stab_line(stab) = line; + str_magic(stab,stab,'*',name,len); return stab; } - return Nullstab; } STIO * stio_new() { - STIO *stio = (STIO *) safemalloc(sizeof(STIO)); + STIO *stio; - bzero((char*)stio, sizeof(STIO)); + Newz(603,stio,1,STIO); stio->page_len = 60; return stio; } @@ -447,22 +599,54 @@ stab_check(min,max) int min; register int max; { + register HENT *entry; register int i; register STAB *stab; for (i = min; i <= max; i++) { - for (stab = stab_index[i]; stab; stab = stab->stab_next) { - if (stab->stab_flags & SF_MULTI) - continue; - if (i == 'A' && strEQ(stab->stab_name, "ARGV")) - continue; - if (i == 'E' && strEQ(stab->stab_name, "ENV")) + for (entry = defstash->tbl_array[i]; entry; entry = entry->hent_next) { + stab = (STAB*)entry->hent_val; + if (stab->str_pok & SP_MULTI) continue; - if (i == 'S' && strEQ(stab->stab_name, "SIG")) - continue; - if (i == 'I' && strEQ(stab->stab_name, "INC")) - continue; - warn("Possible typo: %s,", stab->stab_name); + line = stab_line(stab); + warn("Possible typo: \"%s\"", stab_name(stab)); } } } + +static int gensym = 0; + +STAB * +genstab() +{ + (void)sprintf(tokenbuf,"_GEN_%d",gensym++); + return stabent(tokenbuf,TRUE); +} + +/* hopefully this is only called on local symbol table entries */ + +void +stab_clear(stab) +register STAB *stab; +{ + STIO *stio; + SUBR *sub; + + afree(stab_xarray(stab)); + (void)hfree(stab_xhash(stab)); + str_free(stab_val(stab)); + if (stio = stab_io(stab)) { + do_close(stab,FALSE); + Safefree(stio->top_name); + Safefree(stio->fmt_name); + } + if (sub = stab_sub(stab)) { + afree(sub->tosave); + cmd_free(sub->cmd); + } + Safefree(stab->str_ptr); + stab->str_ptr = Null(STBP*); + stab->str_len = 0; + stab->str_cur = 0; +} + |