📄 ccsym.c
字号:
/* 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 + -