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

📄 ccsym.c

📁 KCC , a good c compiler, write by Ken Harrenstien
💻 C
📖 第 1 页 / 共 5 页
字号:

    /* Zap all remaining bits in last word. "i" has # bytes left, not
    ** counting the terminating null char.  Get # bytes untouched in last wd.
    */
    if ((i = (IDENTSIZE - (i-1)) % sizeof(INT)) != 0)	/* # bytes in last word */
#if __MSDOS__
	*(INT *) (to-(i - 1))
#else
	*(INT *)to
#endif
		&= chmask[i];		/* Zap em if any */
    s->Svalue = hash & (MAXHSH-1);	/* Return hash value */
    return 0;				/* And say identifier length was OK */
}


/* HASH - Compute symbol hash for a string.
**	The MAXHSH macro must have a value of 2^N.
*/
int
hash(s)
register char *s;
{
    register int i, count;

    if ((i = *s) != 0)
	{
	count = IDENTSIZE-1;
	while (--count > 0 && *++s)
	    i += i + *s;
	}
    return (i & (MAXHSH-1));
}

/* SYMHASH - Compute hash value for a symbol.
*/
int
symhash(s)
SYMBOL *s;
{
    register char *cp = s->Sname;
    register int i;

    if ((i = *cp) != '\0')
	while (*++cp)
	    i += i + *cp;
    return (i & (MAXHSH-1));
}

/* BEGLSYM - Begin a local symbol block.
**	Called when a block (compound statement or function) is entered.
** Sets up a new block pointer, a global variable which points to the start of
** the local symbol list for this block.
** Returns the PREVIOUS value of this pointer (the parent block).  This
** should be saved by the caller and given back to endlsym() when the
** new block is finished.
**	Only called by CCSTMT's compound() and CCDECL's funcdef().
*/
SYMBOL *
beglsym()
{
    SYMBOL *retsym;
    BUGMSG(("beglsym %lo => %lo\n", (INT) lsymhead, (INT) loctail))
    retsym = lsymhead;		/* Remember current block head */
    lsymhead = loctail;		/* Set new head */
    return retsym;		/* Return what is now previous block head */
}

/* ENDLSYM - End a local symbol block.
**	Deactivates all symbols in the current block, and restores the
** previous block head pointer (which must be furnished by caller).
** As part of the cleanup, we check for local symbols created with
** linkage elsewhere -- these should always be SC_EXTREF.  They are
** moved onto the global list and changed to SC_XEXTREF.
**	Only called by CCSTMT's compound().
*/
void
endlsym(prevptr)
SYMBOL *prevptr;
{
    register SYMBOL *sym, *s;

    BUGMSG(("endlsym %lo => %lo\n", (INT) lsymhead, (INT) prevptr))
    if ((sym = lsymhead) == NULL)
	int_error("endlsym: treating top level as block");
    else
	while ((sym = sym->Snext) != NULL)
	    {
	    switch (sym->Sclass)
		{
		default:			/* Zap everything except labels */
		    break;			/* Zap the sym */

		case SC_RAUTO:
		    if (sym->Srefs == 0
		      && !(sym->Sflags&SF_XLOCAL))	/* Only barf first time */
			note("Register %S not used", sym);

#if 0 /* KAR-11/92, removed for now; will finish later */
		/*
		 * KAR-9/92, added check to advise when an RAUTO's value
		 * is set but the RAUTO isn't used.
		 */
		    if ((sym->Sinit) && !(sym->Sused))
			note("Register %S is given a value but not used", sym);
#endif

		    break;

		case SC_AUTO:
		    if (sym->Srefs == 0
		      && !(sym->Sflags&SF_XLOCAL))	/* Only barf first time */
			note("Auto %S not used", sym);

#if 0 /* KAR-11/92, removed for now; will finish later */
		/*
		 * KAR-9/92, added check to advise when an RAUTO's value
		 * is set but the RAUTO isn't used.
		 */
		    if ((sym->Sinit) && !(sym->Sused))
			note("Auto %S is given a value but not used", sym);
#endif

		    break;

		case SC_RARG:		/* flushing final function block. */
		    if (prevptr == NULL && sym->Srefs == 0)
			note("Register parameter %S not used", sym);
		    break;

		case SC_ARG:		/* Only complain about params if */
		    if (prevptr == NULL && sym->Srefs == 0)
			note("Parameter %S not used", sym);
		    break;

		case SC_ISTATIC:
		    if (sym->Srefs == 0
		      && !(sym->Sflags&SF_XLOCAL))	/* Only barf first time */
			note("Internal static %S not used", sym);
		    break;

		case SC_LABEL:	/* Labels are active throughout function */
		case SC_ULABEL:
		    continue;
		case SC_EXTREF:
		    s = sym->Sprev;		/* Remember previous */
		    if (sym->Srefs == 0)
			{
			note("External %S not used", sym);
			break;		/* No special handling, just flush */
			}
		/* Turn a block-scope external into a global. */
		    sym->Sclass = SC_XEXTREF;
		    sym->Sflags |= SF_XLOCAL;	/* Render sym invisible */
		    makegsym(sym);		/* Put it on global list */
		    sym = s;		/* Set up to get next local sym */
		    continue;
		}
	    sym->Sflags |= SF_XLOCAL;	/* Zap the sym, get next */
	    }
    lsymhead = prevptr;		/* Then restore ptr to parent block */
}

/* RIDLSYM - Flush local symbols in current and inner blocks.
**	Harsher than endlsym() because the symbols are actually freed.
**	See ccsym.h for explanation of SF_PROTOTAG checking.
**	If arg is NULL, flushes all local symbols.  This is normally
**	only done after the code generation for a function is completely
**	finished, by CCGEN's gencode(),
**	but the top level parser in CCDECL also uses it for error recovery.
*/
void
ridlsym(prevptr)
SYMBOL *prevptr;
{
    SYMBOL *beg;

    BUGMSG(("ridlsym %lo => %lo\n-----", (INT) lsymhead, (INT) prevptr))
    if (prevptr == NULL)
	beg = locsymbol;	/* NULL means flush all */
    else if ((beg = lsymhead) == 0)
	{
	int_error("ridlsym: treating top level as block");
	return;
	}

    switch (abs (debcsi))
	{
	case KCC_DBG_SDBG:
	case KCC_DBG_FDBG:		    /* FW 2A(42) PPS4575 */

	    if (curfn && beg->Snext)
		savesymtab(beg->Snext);		/* save local symbol table */
	    break;


	default:
	    break;
	}

#if DEBUG_KCC		/* 5/91 KCC size */
    if (debsym && beg->Snext)
	symdump(beg->Snext, curfn->Sname);
#endif

    while (loctail != beg)
	{
	switch (loctail->Sclass)
	    {
	    case SC_TAG:
	    case SC_UTAG:
		if (loctail->Sflags & SF_PROTOTAG)
		    {
		    loctail->Sflags |= SF_XLOCAL;	/* Ensure sym never found */
		    loctail->Ssmnext = NULL;	/* Forget any members */
		    makegsym(loctail);		/* and move to global list */
		    continue;
		    }
		break;
	    case SC_ULABEL:			 /* Undefined label? (fall through) */
		error("Goto label %S never defined", loctail);
	    case SC_ISTATIC:
		freelabel(loctail->Ssym);	/* Flush no longer useful label */
		break;
	    case SC_LABEL:
		if (loctail->Srefs == 0)
		    if (loctail->Sname[0] != '%'
#if !__MSDOS__
	     || !isdigit(loctail->Sname[1])
#endif
			    )
			note("Label %S never used", loctail);

		if (loctail->Ssym != NULL)
		    freelabel(loctail->Ssym);	/* Flush no longer useful label */
		break;
	    default:
		;	/* do nothing */
	    }
	freesym(loctail);
	}
    lsymhead = prevptr;		/* Then restore ptr to parent block */
    BUGMSG(("ridlsym done---"))
}

/*
 * Identifier mangling
 *
 * Because traditional PDP-10 utilities (in particular, MACRO, LINK and
 * DDT) are limited to 6-character monocase external symbols, C identifiers
 * must be mapped into these limitations.
 *
 * For identifiers with external linkage (class SC_EX*):
 *	The identifier is passed through mapextsym (), which translates
 *	its first six (at most) characters.  It is then passed through
 *	smapmatch (), a collision detector, which maintains a list of
 *	all mangled identifiers that have been seen hitherto, and
 *	reports if a collision occurs.
 *
 * For identifiers with internal linkage (class SC_IN*):
 *	The resulting mapped name must always be unique, but since these
 *	identifiers are internal, we are at liberty to do anything
 *	necessary to ensure this uniqueness.  The current algorithm is
 *
 *	[0] Always prefix with '$' - this avoids conflicts with
 *		external linkage symbols as well as the C runtime syms.
 *	[1] Add the first 5 monocase identifier chars.  If unique, win.
 *	[2] Else, remove vowels (a,e,i,o,u) and underscores from the
 *		identifier (except for its first char), and try the
 *		first 5 chars of the result, as before.
 *	[3] Else, begin adding digits to the result of [2].  The sequence
 *		produced is: x0 ... x9, x10 ... x99, etc.
 *		This will ultimately succeed.
 */

typedef
INT	    mpdsym;

static
mpdsym*	    maptab;	/* Pointer to table of maps thus far */
static
int	    maptlen;	/* # elements in map table */
static
int	    maptused;	/* # elements actually used */

#define MAPTINC 50	/* # elements to ask for each time we realloc */

/*
 * smapinit
 *
 * Initialize symbol mapping tables.
 */

static
void
smapinit (void)
    {
    if (maptab)
	free ((char *)maptab);

    maptab = NULL;
    maptlen = maptused = 0;
    }

/*
 * smapmatch
 *
 * Returns TRUE if the given symbol was found in the table;
 * otherwise, adds the given symbol to the table and returns 0.
 */

static
int
smapmatch (mpdsym ms)
    {
    mpdsym*	p = maptab;
    int		i = maptused;


    /* Simple-minded table search */

    while (--i >= 0)
	{
	if (*p++ == ms)
	    return 1;
	}

    /* Not in table, add it. */

    if (maptused >= maptlen)		/* Get larger table if needed */
	{
	char*	    nptr;

	if ((nptr = realloc ((char *)maptab,
			     (maptlen + MAPTINC)*sizeof(mpdsym))) == 0)
	    {
	    error ("Out of memory for symbol linkage map");
	    return 0;
	    }
	else
	    {
	    maptab = (mpdsym *) nptr;
	    maptlen += MAPTINC;
	    }
	}

    maptab[maptused++] = ms;
    return 0;
    }

/*
 * mapextsym
 *
 * Map a symbol with external linkage.  Returns 0 if a conflict exists.
 * 
 */

#define UNDERSCORE_MAPCHR '%'
#define STATIC_PREFIXCHAR '$'

int
mapextsym (SYMBOL* s)
    {
    int		i = 6*6;
    int		c;
    unsigned
    INT		val = 0;
    char*	str;


    str = s->Sname;

    if (*str != SPC_IDQUOT)
	--str;				/* Skip 1st char if backquoted. */

    while (i > 0 && (c = *(++str)) != '\0')
	{
	if (c == SPC_IDQUOT)
	    break;

	if (c == '_')
	    c = UNDERSCORE_MAPCHR;

	/* Accumulate translated characters in val */

#ifdef __COMPILER_KCC__
	val |= (INT) tosixbit (c) << (i -= 6);
#else
	val = (val * 050) + torad50((char) c); // FW KCC-NT
	i -= 6;
#endif
	}

    /* Update the symbol. */

    s->Smaplab = val;

    /*
     * Pass the mangled identifier through the collision detector, and
     * report success or failure.
     */

    return !(smapmatch ((mpdsym) val));	/* Succeed if no existing match */
    }



#if __MSDOS__
INT	    rad50 (char *);
#ifdef	sixbit							// FW KCC-NT
 #undef	sixbit
#endif
#define sixbit(c) rad50(c)
#endif

/*
 * mapintsym
 *
 * Map a symbol with internal linkage.  Always wins.
 */

void
mapintsym (SYMBOL* s)
    {
    char	sym6[6+1];
    mpdsym	ms;
    int		i = 6;
    char*	cp = sym6;
    char*	sp = s->Sname;


    if (*sp == SPC_IDQUOT)	/* Treat `ident` specially */
	{
	i = 6;
	--cp;
	}
    else
	{
	i = 5;
	--sp;				/* Normal sym */
	*cp = STATIC_PREFIXCHAR;	/* Always starts with this prefix */
	}

    while (--i >= 0)
	{
	if ((*++cp = (*++sp == '_' ? UNDERSCORE_MAPCHR : *sp)) == 0)
	    break;
	}

    if (i < 0)
	*++cp = 0;	/* Tie off */

    /* Now have mapped ident in temp buff */

    if (!smapmatch(ms = sixbit(sym6)))		/* Won right off? */
	{
	s->Smaplab = ms;
	return;
	}

    /* Sigh, try step 2 -- flush vowels and underscores after 1st char. */

    for (i = 4, cp = sym6+1, sp = s->Sname; *++sp && i;)
	{

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -