📄 ccsym.c
字号:
/* SYMFFLAG - Auxiliary to find a non-ordinary symbol
** (special overloading class) matching the given flag.
** Starts with given symbol (NOTE: not a string and not next sym!).
** If symbol provided is at start of hash list (is undefined) then
** we can skip the initial hash!
*/
SYMBOL *
symfflag(sym, flag)
SYMBOL *sym;
{
register SYMBOL *s = sym;
BUGMSG(("symfflag \"%s\"\n", s->Sname))
if (s->Sclass != SC_UNDEF) /* Hack: see if at start of hash */
{
s->Srefs--; /* Undo ref to original sym */
s = htable[symhash(s)]; /* No, must find start. Bleah. */
}
do
{
if (((s->Sflags&(SF_XLOCAL|SF_OVCLS)) == flag)
&& (s == sym || symcmp(sym, s)))
{
s->Srefs++;
break;
}
}
while ((s = s->Snhash) != NULL)
;
return s;
}
SYMBOL *
symfmember(sym, tag)
SYMBOL *sym, *tag;
{
register SYMBOL *s = sym;
BUGMSG(("symfmember \"%s\"\n", s->Sname))
if (s->Sclass != SC_UNDEF) /* Hack: see if at start of hash */
{
s->Srefs--; /* Undo ref to original sym */
s = htable[symhash(s)]; /* No, must find start. Bleah. */
}
do
{
if (((s->Sflags&(SF_XLOCAL|SF_OVCLS)) == SF_MEMBER)
&& s->Ssmtag == tag
&& (s == sym || symcmp(sym, s)))
{
s->Srefs++;
break;
}
}
while ((s = s->Snhash) != NULL)
;
return s;
}
/* SYMFXEXT - Find an SC_XEXTREF (out-of-scope external reference) symbol,
** if any exists.
** Argument is a SC_UNDEF symbol (thus at the start of hash chain).
** Returns a pointer either to the same symbol, if no SC_XEXTREF exists,
** or to the SC_XEXTREF symbol. In the latter case, the SC_UNDEF
** symbol is flushed! This is unlike the other symbol finding routines.
**
** Only invoked by CCDECL's funchk() and dodecl().
*/
SYMBOL *
symfxext(sym)
SYMBOL *sym;
{
register SYMBOL *s = sym;
BUGMSG(("symfxext \"%s\"\n", s->Sname))
if (sym->Sclass != SC_UNDEF)
return sym;
while ((s = s->Snhash) != NULL) /* Get next sym on hash chain */
if (s->Sclass == SC_XEXTREF && symcmp(sym, s))
{
freesym(sym); /* It's a winner! Flush undef sym */
s->Sflags &= ~SF_XLOCAL; /* bring old back into scope */
s->Srefs++; /* and bump ref count */
return s;
}
return sym;
}
/* -------------------------------------- */
/* free a symbol table location */
/* -------------------------------------- */
void
freesym(s)
SYMBOL *s;
{
register SYMBOL *sym;
int h;
BUGMSG(("freesym \"%s\"\n", s->Sname))
sym = htable[h = symhash(s)]; /* Find head of hash chain */
if (sym == s)
htable[h] = s->Snhash;
else
{
for (;; sym = sym->Snhash)
{
if (!sym)
{
int_error("freesym: sym not on hash list");
return;
}
if (sym->Snhash == s)
break;
}
sym->Snhash = s->Snhash; /* Found, take off hash list */
}
retsym(s); /* give sym back to mem allocator */
}
/* CREATSYM - Create a symbol table entry.
** Symbol will be local or global depending on current context,
** i.e. the setting of lsymhead. If NULL, current "block" is top level
** and symbol will be put on the global list. Otherwise, it is put on
** the local list.
*/
SYMBOL *
creatsym(id)
char *id;
{
SYMBOL *s;
BUGMSG(("creatsym %s \"%s\"", (lsymhead?"local":"global"), id))
if (!lsymhead)
return symgcreat(id); /* Create and return global symbol */
s = mksym(id, &loctail); /* Nope, do local symbol */
s->Sflags |= SF_LOCAL;
return s;
}
/* SYMGCREAT - create a global symbol table entry
*/
SYMBOL *
symgcreat(id)
char *id;
{
BUGMSG(("symgcreat \"%s\"", id))
return mksym(id, &symtail);
}
/* MAKELSYM - Make global symbol a local one.
** Sometimes needed when lexer creates a global entry for
** a new identifier, and it later needs to be made local instead.
*/
static void
makelsym(s)
SYMBOL *s;
{
/* Remove from global list */
if (s == symtail) /* If sym is most recent one on global list, */
symtail = s->Sprev; /* must update the tail pointer. */
if (s->Sprev)
s->Sprev->Snext = s->Snext;
if (s->Snext)
s->Snext->Sprev = s->Sprev;
/* Add to local list */
s->Sprev = loctail;
s->Snext = (SYMBOL *) NULL;
loctail->Snext = s;
loctail = s;
s->Sflags |= SF_LOCAL;
}
/* MAKEGSYM - Make local symbol a global one.
** Used by ridlsym() when preserving tags defined within a
** function prototype.
*/
static void
makegsym(s)
SYMBOL *s;
{
/* Remove from local list */
if (s == loctail) /* If sym is most recent one on global list, */
loctail = s->Sprev; /* must update the tail pointer. */
if (s->Sprev)
s->Sprev->Snext = s->Snext;
if (s->Snext)
s->Snext->Sprev = s->Sprev;
/* Add to global list */
s->Sprev = symtail;
s->Snext = (SYMBOL *) NULL;
symtail->Snext = s;
symtail = s;
s->Sflags &= ~SF_LOCAL;
}
/* SYMQCREATE - Quick symbol creation. Given a symbol pointer, returns
** a pointer to an unique symbol table entry with the same name. This
** will either re-use the current entry (if it is undefined)
** or will create a new duplicate symbol of the appropriate scope.
** No reference counts are adjusted by this routine. CCDECL and
** CCSTMT rely on this for creating new tag/label/member symbols since
** the symftag() routines etc have already done the mistaken-reference
** correction.
**
** UNIQSYM - Just like SYMQCREATE, except that
** if a new duplicate symbol is made, the reference count of the
** original symbol is decremented to compensate for what was a mistaken
** reference. This is commonly used in CCDECL.
**
** Any checks for duplicate definition errors should be made before
** these routines are called!
*/
SYMBOL *
uniqsym(s)
SYMBOL *s;
{
if (s->Sclass != SC_UNDEF) /* If sym is already defined, */
s->Srefs--; /* correct its ref count. */
return symqcreat(s); /* Now create it quickly */
}
SYMBOL *
symqcreat(s)
SYMBOL *s;
{
if (s->Sclass != SC_UNDEF) /* If sym already exists, */
/* If this symbol has same identifier as a macro symbol, then
** after creating it, the shadow flag needs to be propagated, and
** the macro sym entry needs to be moved up. shmacsym() does this.
*/
{
if (s->Sflags & SF_MACSHADOW) /* Shadowing a macro def? */
return shmacsym(creatsym(s->Sname)); /* Yes, shadow after create! */
return creatsym(s->Sname); /* No, just return a duplicate. */
}
/* Can use this symtab entry, just make sure it has right scope. */
if (lsymhead && !(s->Sflags & SF_LOCAL)) /* If current scope is local */
makelsym(s); /* change sym from global to local */
return s;
}
/* ISDUPSYM - Returns NULL/FALSE if symbol not yet defined in current block:
* if symbol is already defined, returns its address (ie. TRUE).
*/
SYMBOL *
isdupsym(sym)
SYMBOL *sym;
{
SYMBOL *ls;
if (sym->Sclass == SC_UNDEF) /* If it has this class */
return NULL; /* then it was never defined before */
if (lsymhead == NULL) /* Symbol is defined. If now at top level, */
return (SYMBOL *) 1; /* the symbol is always top-level also. */
/* here we'd need to use symfidstr() ****************************************/
/* We are in a local block. To see whether the symbol is defined
** within this block, we start scanning the local symbol list beginning
** with the current local block head. If we encounter the symbol then
** it is defined in the current block.
** Symbols from inner blocks will never be given as args since symfidstr
** never returns inactivated symbols.
** Symbols from outer blocks will never be scanned because all symbols
** for outer blocks precede those of the current block in the local
** symbol list.
*/
for (ls = lsymhead; (ls = ls->Snext) != NULL;)
if (ls == sym)
return ls;
return NULL;
}
/* MKSYM - Create a symbol table entry - internal workhorse auxiliary.
** Symbol will be added to whatever list is provided (locsym or symtail).
*/
static SYMBOL *
mksym(id, tailptr)
char *id;
SYMBOL **tailptr;
{
register SYMBOL *sym;
sym = getsym(tailptr); /* Get a free symbol struct */
(void) idcpy(sym, id); /* Copy ident, get hash, ignore any trunc */
sym->Snhash = htable[(int) sym->Svalue];
htable[(int) sym->Svalue] = sym;
BUGMSG((" = %lo, hash %lo\n", (INT) sym, (INT) sym->Svalue)) /* Finish bug msg if one */
sym->Sclass = SC_UNDEF; /* Set common initial values */
sym->Sflags = 0;
sym->Stype = NULL;
sym->Svalue = 0; /* This clobbers hash, oh well */
sym->Srefs = 0;
return sym;
}
/* SYMMK - Create a symbol table entry - internal workhorse auxiliary.
** Symbol will be added to whatever list is provided (locsym or symtail).
*/
static SYMBOL *
symmk(SYMBOL *s, int hval, SYMBOL **tailptr) /* Pre-computed hash value */
{
register SYMBOL *sym;
sym = getsym(tailptr);
BUGMSG((" = %lo, hash %o\n", (INT) sym, (int) hval)) /* Finish off bug msg if one */
sym->Snhash = htable[hval];
htable[hval] = sym;
sym->Scontents.Sid = s->Scontents.Sid; /* Copy symbol identifier */
sym->Sclass = SC_UNDEF;
sym->Sflags = 0;
sym->Stype = NULL;
sym->Svalue = 0;
sym->Srefs = 0;
return sym;
}
/* SHMACSYM - Say this symbol shadows a macro symbol.
** Sets flag and moves macro symbol matching this one to top of hash list.
** This is used by uniqsym() and CCPP's findident() whenever they
** create a new symbol which shadows an existing macro symbol; the
** macro symbol needs to be moved up to the head of the hash list
** to ensure that it is always found by symfind() before the new symbol.
** Always returns its arg, for convenience.
*/
SYMBOL *
shmacsym(sym)
SYMBOL *sym;
{
register SYMBOL *s, *prev = NULL;
int n;
sym->Sflags |= SF_MACSHADOW; /* Set flag in this symbol */
for (s = htable[n = symhash(sym)]; s != NULL; prev = s, s = s->Snhash)
if (s->Sclass == SC_MACRO && symcmp(sym, s))
{
/* Found the matching macro symbol! Unlink from hash chain */
if (!prev) /* If already at start of chain, */
break; /* nothing to do, just return */
prev->Snhash = s->Snhash; /* Unlink */
s->Snhash = htable[n]; /* Then put at start */
htable[n] = s;
break;
}
return sym;
}
/* GETSYM - allocate a symbol entry.
*/
static SYMBOL *
getsym(tailptr)
SYMBOL **tailptr;
{
SYMBOL *newptr;
if ((newptr = symflist) != NULL) /* If freelist has one, take it off */
symflist = newptr->Snext;
/* KAR-8/91, Changed to calloc() call to ensure memory is zeroed */
else if ((newptr = (SYMBOL *) calloc(1, sizeof(SYMBOL))) == NULL)
efatal("Out of memory for symbols");
#if DEBUG_KCC /* 8/91 shrink KCC */
else
nsymbols++; /* Bump # of symbols allocated */
#endif
newptr->Sprev = *tailptr;
newptr->Snext = (SYMBOL *) NULL;
(*tailptr)->Snext = newptr;
*tailptr = newptr;
return newptr;
}
/* RETSYM - De-allocate a symbol entry.
*/
static void
retsym(syment)
SYMBOL *syment;
{
if (syment == symtail)
symtail = syment->Sprev;
else if (syment == loctail)
loctail = syment->Sprev;
if (syment->Sprev)
syment->Sprev->Snext = syment->Snext;
if (syment->Snext)
syment->Snext->Sprev = syment->Sprev;
/* free((char *)syment); */
syment->Snext = symflist; /* Put entry on freelist */
symflist = syment;
}
/* COPYSYM - Copy basic parts of symbol struct.
** Does not copy Snhash, Sprev, Snext, or Srefs.
*/
void
copysym(s,t)
SYMBOL *s, *t;
{ /* Use struct assignment since have unions inside */
s->Scontents = t->Scontents;
}
#if 0
/* IDCMP - Compare symbol identifiers for equality
** Can do without count since existing symbol string is null-terminated
*/
static int
idcmp(s,t)
char *s, *t;
{
if (*s == *t)
while (*++s == *++t)
if (*s == '\0')
return 1;
return 0;
}
#endif
/* SYMCMP - Compare symbol identifiers for equality
** Can do without count since symbol strings are null-terminated
*/
static int
symcmp(s1, s2)
SYMBOL *s1, *s2;
{
register INT *p1 = s1->Sidwds, *p2 = s2->Sidwds;
for (; *p1 == *p2; ++p1, ++p2) /* Do word compare */
if ((*p1 & lastwd) == 0)
return 1;
return 0;
}
/* IDCPY - Copy string into a symbol structure, ensuring that remainder of
** last word of string is zeroed out.
** Returns non-zero if identifier was truncated.
** Bonus points: puts hash value in Svalue!
*/
static int
idcpy(s, cp)
SYMBOL *s;
char *cp;
{
register int i = IDENTSIZE;
register char *to = s->Sname;
register int hash;
if ((hash = *to = *cp) != 0)
{
--i;
while ((*++to = *++cp) != '\0')
if (--i > 0)
hash += hash + *cp;
else /* Stop if written into last char */
{
*to = '\0'; /* Change last char to a null */
s->Svalue = hash & (MAXHSH-1); /* Return hash value */
return 1; /* And say truncated */
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -