-/* $Header: stab.c,v 1.0.1.1 88/01/28 10:35:17 root Exp $
+/* $Header: stab.c,v 3.0.1.5 90/03/12 17:00:11 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 1.0.1.1 88/01/28 10:35:17 root
- * patch8: changed some stabents to support eval operator.
+ * Revision 3.0.1.5 90/03/12 17:00:11 lwall
+ * patch13: undef $/ didn't work as advertised
+ *
+ * Revision 3.0.1.4 90/02/28 18:19:14 lwall
+ * patch9: $0 is now always the command name
+ * patch9: you may now undef $/ to have no input record separator
+ * patch9: local($.) didn't work
+ * patch9: sometimes perl thought ordinary data was a symbol table entry
+ * patch9: stab_array() and stab_hash() weren't defined on MICROPORT
+ *
+ * Revision 3.0.1.3 89/12/21 20:18:40 lwall
+ * patch7: ANSI strerror() is now supported
+ * patch7: errno may now be a macro with an lvalue
+ * patch7: in stab.c, sighandler() may now return either void or int
+ *
+ * Revision 3.0.1.2 89/11/17 15:35:37 lwall
+ * patch5: sighandler() needed to be static
*
- * Revision 1.0 87/12/18 13:06:14 root
- * Initial revision
+ * Revision 3.0.1.1 89/11/11 04:55:07 lwall
+ * patch2: sys_errlist[sys_nerr] is illegal
+ *
+ * Revision 3.0 89/10/18 15:23:23 lwall
+ * 3.0 baseline
*
*/
-#include <signal.h>
-#include "handy.h"
#include "EXTERN.h"
-#include "search.h"
-#include "util.h"
#include "perl.h"
+#include <signal.h>
+
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"
+ SIG_NAME,0
+};
+
+#ifdef VOIDSIG
+#define handlertype void
+#else
+#define handlertype int
#endif
-#ifdef SIGUSR2
- ,"USR2"
-#endif /* SIGUSR2 */
-#endif /* SIGLOST */
-#endif /* SIGWINCH */
-#endif /* SIGPROF */
-#endif /* SIGTSTP */
- ,0
- };
STR *
-stab_str(stab)
-STAB *stab;
+stab_str(str)
+STR *str;
{
+ STAB *stab = str->str_u.str_stab;
register int paren;
register char *s;
- extern int errno;
+ register int i;
+
+ if (str->str_rare)
+ return stab_val(stab);
- switch (*stab->stab_name) {
- case '0': case '1': case '2': case '3': case '4':
+ switch (*stab->str_magic->str_ptr) {
+ 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);
- if (curspat->spat_compex.subend[paren] &&
- (s = getparen(&curspat->spat_compex,paren))) {
- curspat->spat_compex.subend[paren] = Nullch;
- str_set(stab->stab_val,s);
+ 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_val(stab),s,i);
+ else
+ str_sset(stab_val(stab),&str_undef);
}
+ else
+ str_sset(stab_val(stab),&str_undef);
}
break;
case '+':
if (curspat) {
- paren = curspat->spat_compex.lastparen;
- if (curspat->spat_compex.subend[paren] &&
- (s = getparen(&curspat->spat_compex,paren))) {
- curspat->spat_compex.subend[paren] = Nullch;
- str_set(stab->stab_val,s);
+ paren = curspat->spat_regexp->lastparen;
+ 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->lines);
+ 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);
- break;
- case '(':
- if (curspat) {
- str_numset(stab->stab_val,(double)(curspat->spat_compex.subbeg[0] -
- curspat->spat_compex.subbase));
- }
- break;
- case ')':
- if (curspat) {
- str_numset(stab->stab_val,(double)(curspat->spat_compex.subend[0] -
- curspat->spat_compex.subbeg[0]));
- }
+ 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);
+ if (record_separator != 12345) {
+ *tokenbuf = record_separator;
+ tokenbuf[1] = '\0';
+ 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_numset(stab_val(stab), (double)errno);
+ str_set(stab_val(stab), strerror(errno));
+ stab_val(stab)->str_nok = 1; /* what a wonderful hack! */
+ break;
+ case '<':
+ str_numset(stab_val(stab),(double)uid);
+ break;
+ case '>':
+ str_numset(stab_val(stab),(double)euid);
+ break;
+ case '(':
+ s = buf;
+ (void)sprintf(s,"%d",(int)gid);
+ goto add_groups;
+ case ')':
+ s = buf;
+ (void)sprintf(s,"%d",(int)egid);
+ add_groups:
+ while (*s) s++;
+#ifdef GETGROUPS
+#ifndef NGROUPS
+#define NGROUPS 32
+#endif
+ {
+ GIDTYPE gary[NGROUPS];
+
+ i = getgroups(NGROUPS,gary);
+ while (--i >= 0) {
+ (void)sprintf(s," %ld", (long)gary[i]);
+ while (*s) s++;
+ }
+ }
+#endif
+ 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();
+ static handlertype sighandler();
+
+ 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 (strNE(s,"StB") || 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;
+ strcpy(stab_magic(stab),"StB");
+ 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;
- if (stab->stab_flags & SF_VMAGIC) {
- switch (stab->stab_name[0]) {
+ 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 '.':
+ if (localizing)
+ savesptr((STR**)&last_in_stab);
+ break;
case '^':
- safefree(curoutstab->stab_io->top_name);
- curoutstab->stab_io->top_name = str_get(str);
- curoutstab->stab_io->top_stab = stabent(str_get(str),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 = str_get(str);
- curoutstab->stab_io->fmt_stab = stabent(str_get(str),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);
+ if (str->str_pok) {
+ record_separator = *str_get(str);
+ rslen = str->str_cur;
+ }
+ else {
+ record_separator = 12345; /* fake a non-existent char */
+ rslen = 1;
+ }
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 '[':
arybase = (int)str_gnum(str);
break;
+ case '?':
+ statusvalue = (unsigned short)str_gnum(str);
+ break;
case '!':
errno = (int)str_gnum(str); /* will anyone ever use this? */
break;
- case '.':
- case '+':
- case '&':
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
+ case '<':
+ uid = (int)str_gnum(str);
+#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 '>':
+ euid = (int)str_gnum(str);
+#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
+ (void)setrgid((GIDTYPE)gid);
+#else
+#ifdef SETREGID
+ (void)setregid((GIDTYPE)gid, (GIDTYPE)-1);
+#else
+ fatal("setrgid() not implemented");
+#endif
+#endif
+ break;
case ')':
- break; /* "read-only" registers */
+ egid = (int)str_gnum(str);
+#ifdef SETREGID
+ if (delaymagic) {
+ delaymagic |= DM_REGID;
+ break; /* don't do magic till later */
+ }
+#endif /* SETREGID */
+#ifdef SETEGID
+ (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;
}
- }
- 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;
+ break;
}
}
-whichsig(signame)
-char *signame;
+whichsig(sig)
+char *sig;
{
register char **sigv;
for (sigv = sig_name+1; *sigv; sigv++)
- if (strEQ(signame,*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;
}
+static handlertype
sighandler(sig)
int sig;
{
STAB *stab;
ARRAY *savearray;
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);
- savearray = defstab->stab_array;
- defstab->stab_array = anew();
- str = str_new(0);
+ 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_name(stab) );
+ return;
+ }
+ 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);
- str = cmd_exec(stab->stab_sub);
- afree(defstab->stab_array); /* put back old $_[] */
- defstab->stab_array = savearray;
-}
+ (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_name(stab));
+ savelist(sub->tosave->ary_array,sub->tosave->ary_fill);
+ }
+ filename = sub->filename;
-char *
-reg_get(name)
-char *name;
-{
- return STAB_GET(stabent(name,TRUE));
-}
+ (void)cmd_exec(sub->cmd,G_SCALAR,1); /* so do it already */
-#ifdef NOTUSED
-reg_set(name,value)
-char *name;
-char *value;
-{
- str_set(STAB_STR(stabent(name,TRUE)),value);
+ sub->depth--; /* assuming no longjumps out of here */
+ 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);
}
-#endif
STAB *
aadd(stab)
register STAB *stab;
{
- if (!stab->stab_array)
- stab->stab_array = anew();
+ if (!stab_xarray(stab))
+ stab_xarray(stab) = anew(stab);
return 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;
}
+
+STAB *
+stabent(name,add)
+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;
+
+ 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 = '\'';
+ }
+ 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;
+ strcpy(stab_magic(stab),"StB");
+ stab_val(stab) = Str_new(72,0);
+ stab_line(stab) = line;
+ str_magic(stab,stab,'*',name,len);
+ return stab;
+ }
+}
+
+STIO *
+stio_new()
+{
+ STIO *stio;
+
+ Newz(603,stio,1,STIO);
+ stio->page_len = 60;
+ return stio;
+}
+
+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 (entry = defstash->tbl_array[i]; entry; entry = entry->hent_next) {
+ stab = (STAB*)entry->hent_val;
+ if (stab->str_pok & SP_MULTI)
+ continue;
+ 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;
+}
+
+#if defined(CRIPPLED_CC) && (defined(iAPX286) || defined(M_I286) || defined(I80286))
+#define MICROPORT
+#endif
+
+#ifdef MICROPORT /* Microport 2.4 hack */
+ARRAY *stab_array(stab)
+register STAB *stab;
+{
+ if (((STBP*)(stab->str_ptr))->stbp_array)
+ return ((STBP*)(stab->str_ptr))->stbp_array;
+ else
+ return ((STBP*)(aadd(stab)->str_ptr))->stbp_array;
+}
+
+HASH *stab_hash(stab)
+register STAB *stab;
+{
+ if (((STBP*)(stab->str_ptr))->stbp_hash)
+ return ((STBP*)(stab->str_ptr))->stbp_hash;
+ else
+ return ((STBP*)(hadd(stab)->str_ptr))->stbp_hash;
+}
+#endif /* Microport 2.4 hack */