⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ccsym.c

📁 KCC , a good c compiler, write by Ken Harrenstien
💻 C
📖 第 1 页 / 共 5 页
字号:
/* 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 + -