📄 ccsym.c
字号:
if (!isvowel(*sp) && *sp != '_')
--i, *++cp = *sp;
}
*++cp = 0;
if (!smapmatch(ms = sixbit(sym6)))
{
s->Smaplab = ms;
return;
}
/* Sigh sigh, fall into step 3 -- add digits on end */
if (i > 0) /* Fill out rest of name with '0's */
{
while (--i >= 0)
*++cp = '0';
*++cp = 0;
}
for (;;)
{
if (!smapmatch(ms = sixbit(sym6)))
{
s->Smaplab = ms;
return;
}
/* Increment number again */
cp = &sym6[5];
for (;;)
{
if (!isdigit(*cp))
{
*cp = '1';
break;
}
else if (*cp != '9')
{
++(*cp);
break;
}
*cp = '0'; /* Wrap from 9 to 0 */
--cp; /* and carry to prev digit */
}
}
}
/* LABEL MANAGEMENT CODE */
static int maxlabel; /* Current highest-numbered label */
static SYMBOL *fllist = NULL; /* Free label list */
static SYMBOL *flprev = NULL; /* queue of almost-free labels */
#if DEBUG_KCC /* 8/91 shrink KCC */
static int nlabels = 0; /* # labels allocated */
#endif
/* LABINIT - Initialize label stuff.
** Called by SYMINIT at start of compilation for each file.
*/
static void
labinit()
{
maxlabel = 0; /* Reset internal label numbering to 0 */
cleanlabs(); /* Ensure no queued labels */
/* Note that "fllist" is left alone in case it contains free labels,
** which will save us the bother of allocating them.
*/
}
/*
** Get a new label to play with.
**
** The argument should be nonzero if the label will be emitted after all
** uses of it, rather than before. If it is zero, the label is emitted.
*/
SYMBOL *
newlabel()
{
SYMBOL *lab;
/* find a free label */
if ((lab = fllist) != NULL) /* If have one already free, */
fllist = fllist->Snext; /* remove it from freelist */
/* KAR-8/91, Changed to calloc() call to ensure memory is zeroed */
else if ((lab = (SYMBOL *) calloc(1, sizeof (*lab))) == NULL)/*make new */
efatal("Out of memory for labels");
#if DEBUG_KCC /* 8/91 shrink KCC */
else
nlabels++; /* Bump # of labels allocated */
#endif
/* fill it out */
lab->Sclass = SC_ILABEL; /* this is an internal label */
sprintf(lab->Sname, "$%d", ++maxlabel); /* give it a name */
lab->Svalue = 0; /* no uses yet */
return lab;
}
/* REFLABEL - Reference or dereference a label.
**
** The second argument is how much to add to the reference count.
** The label may be NULL or not a SC_ILABEL; in that case nothing happens.
*/
void
reflabel(lab, count)
SYMBOL * lab;
{
if (lab != NULL && lab->Sclass == SC_ILABEL)
lab->Svalue += count;
}
/* FREELABEL - release a label
**
** Unfortunately we can't know when the last instance in the peephole
** buffer has been emitted, at least until we flush the whole thing out.
** So we keep explicitly freed labels on another list and only transfer
** them after we have emitted a new label (and thus called flushcode()).
**
** This list chains through sprev rather than snext to keep things simple.
*/
void
freelabel(lab)
SYMBOL *lab;
{
lab->Sprev = flprev; /* chain old freelist onto it */
flprev = lab; /* it is now head of freelist */
}
/* CLEANLABS() - actually free up all "almost-free" labels.
*/
void
cleanlabs()
{
while (flprev != NULL) /* peephole buffer is now empty */
{
realfreelabel(flprev); /* so free the list of labels queued */
flprev = flprev->Sprev; /* by freelabel() */
} /* (nb sprev unchanged by realfree) */
}
/* REALFREELABEL - Really free a label.
**
** This should be called after the last possible reference to the label.
** It will be called automatically on emission of forward labels.
** Note sprev must not be changed (see cleanlabs()).
*/
static void
realfreelabel(lab)
SYMBOL *lab;
{
lab->Snext = fllist; /* chain old freelist onto it */
fllist = lab; /* it is now head of freelist */
}
#if DEBUG_KCC /* 5/91 KCC size */
/* SYMDUMP - Dump symbol table info to debugging output.
*/
#if __STDC__
static void shoffset(INT);
#else
static void shoffset();
#endif
extern FILE *fsym;
void
symdump(table, name)
SYMBOL *table;
char *name;
{
int u;
char *str, *c, tmpstr[50];
SYMBOL *s;
fprintf(fsym, "\n-- Symbols for %s --\n\n", name);
for (s = table; s != NULL; s = s->Snext)
{
switch (u=s->Sclass)
{
case SC_UNDEF:
str = "undefined";
break;
case SC_RW:
str = "reserved word";
break;
case SC_MACRO:
str = "macro";
break;
case SC_TAG:
str = "structure tag";
break;
case SC_UTAG:
str = "undef structure tag";
break;
case SC_TYPEDEF:
str = "typedef";
break;
case SC_XEXTREF:
str = "ex-extern-ref";
break;
case SC_EXTREF:
str = "extern-ref";
break;
case SC_EXTDEF:
str = "extern-def";
break;
case SC_EXLINK:
str = "extern-tntdef";
break;
case SC_INTREF:
str = "intern-ref";
break;
case SC_INTDEF:
str = "intern-def";
break;
case SC_INLINK:
str = "intern-tntdef";
break;
case SC_ISTATIC:
str = "local-static";
break;
case SC_ARG:
str = "argument";
break;
case SC_RARG:
str = "register-arg";
break;
case SC_REGISTER:
str = "register";
break;
case SC_MEMBER:
str = "struct member";
break;
case SC_AUTO:
str = "auto";
break;
case SC_RAUTO:
str = "register-auto";
break;
case SC_LABEL:
str = "goto label";
break;
case SC_ENUM:
str = "enumerated type";
break;
case SC_ULABEL:
str = "undefined goto label";
break;
default:
sprintf(tmpstr, "ILLEGAL symbol class %d", u);
str = tmpstr;
}
c = s->Sname;
fprintf(fsym, "%-10s: %s", c, str);
if (s->Sflags)
fprintf(fsym," (%lo)", (INT) s->Sflags);
fprintf(fsym,", refs %d", (int) s->Srefs);
if (u != SC_MACRO && u != SC_TAG && s->Stype)
{
fprintf(fsym, ", type %d", s->Stype-types);
if (s->Stype->Tspec == TS_STRUCT
|| s->Stype->Tspec == TS_UNION) /* struct or union? */
fprintf(fsym, ", struct %s", s->Stype->Tsmtag->Sname+1);
fprintf(fsym, ", tsize %ld", (INT) sizetype(s->Stype));
}
switch (u)
{
case SC_RAUTO:
fprintf (fsym, ", register %d", s->Sreg);
break;
case SC_AUTO:
fprintf (fsym, ", offset %ld", (INT) s->Svalue + 1);
break;
case SC_RARG:
fprintf (fsym, ", register %d", s->Sreg);
break;
case SC_ARG:
fprintf (fsym, ", offset %ld", (INT) - s->Svalue);
break;
case SC_ENUM:
case SC_TAG:
fprintf(fsym, ", value %ld", (INT) s->Svalue);
break;
case SC_EXTDEF:
case SC_INTDEF:
if (s->Stype->Tspec == TS_FUNCT && s->Shproto)
fprintf(fsym, ", Shproto %d", s->Shproto - types);
break;
case SC_MEMBER:
shoffset(s->Svalue);
break;
case SC_MACRO:
fprintf(fsym, ", nargs %d, parlen %d, len %d=",
(int) s->Smacnpar, (int) s->Smacparlen, (int) s->Smaclen);
if (!s->Smacptr)
fputs("NULL", fsym);
else
{
int i = s->Smaclen;
char *cp = s->Smacptr;
putc('"', fsym);
while (--i >= 0)
putc(*cp++, fsym);
putc('"', fsym);
}
break;
}
putc ('\n', fsym);
}
}
static void
shoffset(off)
INT off;
{
if (off >= 0)
fprintf(fsym, ", offset %ld", (INT) off);
else
{
unsigned INT o = -off; /* negate */
fprintf(fsym, ", offset %lu, width %lu, bit offset %lu",
o >> 12, o & 077, 36 - ((o & 07700) >> 6) - (o & 077));
}
}
#endif
#if 0 /* debug stuff */
shohash()
{
int n;
SYMBOL *s;
for(n=0; n < MAXHSH; n++)
if(s = htable[n])
{
printf("Hash %o:", n);
do
printf(" %o=%s", s, s->Sname);
while (s = s->Snhash)
;
printf("\n");
}
}
#endif
static int maxtype = 0; /* maximum types used */
/* TYPEINIT - Initialize things for support of C types.
** Mainly initializes the type table with the supported basic types.
*/
static void
typeinit()
{
int i;
/* First a crock to ensure "char" byte size selection has effect */
typbsiztab[TS_CHAR] = typbsiztab[TS_UCHAR] = tgcsize;
maxtype = 0;
for (i = 0 ; i < MAXTYPE ; i++)
ttable[i] = NULL; /* Clear hash table */
for (i = 0; i < TS_MAX; i++)
if (i == TS_VOID || typsiztab[i] != 0)
typeptr[i] = findtype(i, (TYPE *)NULL);
else
typeptr[i] = NULL;
/* Machine-dependent... clobber table so some types are equivalent */
/* Someday clean this up and make it table-driven also */
chartype = uchartype; /* Say plain "char" is "unsigned char" */
deftype = inttype; /* Default type is "int" */
strcontype = findtype(TS_PTR, chartype); /* Type of string constant */
voidptrtype = findtype(TS_PTR, voidtype); /* (void *) */
siztype = (clevel >= CLEV_ANSI) ? uinttype /* Std C wants unsigned, ugh */
: inttype;
ptrdifftype = inttype; /* What ptrdiff_t is */
}
/* NOTE on the various "type finding" routines below:
** Much of KCC relies on being able to compare types simply by
** comparing the pointers to TYPE nodes. This, and the desire to share
** type definitions, means that all type declarations must first look for
** an identical existing type, and only create a new type if no existing
** definition matches.
** In order to do this most efficiently, we indulge in non-portable
** type punning for the arguments to these routines. Specifically, the
** values of the two unions in the TYPE structure are declared below as
** being (int) and (TYPE *) but may in fact contain other things.
** This is a deliberate but reasonable sacrifice of clumsy theoretical
** portability in return for speed.
*/
/* FINDTYPE - Find or create an unqualified type.
** Note CCDECL's tagspec() calls this with a symbol (tag) pointer instead
** of a type pointer.
*/
TYPE *
findtype(tsp, subt)
TYPE *subt;
{
return findctype(tsp,
typbsiztab[tsp], /* Use default flags and # bits */
typsiztab[tsp], /* Use default size in words */
subt);
}
#if 0 /* 5/91 KCC size */
/* FINDSZTYPE - Same, but use specified Tsize instead of default.
*/
TYPE *
findsztype(tsp, siz, subt)
int tsp;
INT siz;
TYPE *subt;
{
return findctype(tsp,
typbsiztab[tsp], /* Use default flags and # bits */
siz, /* Use specified size in words */
subt);
}
#endif
/* FINDUTYPE - Find or create the unqualified version of a given type.
*/
TYPE *
findutype(t)
TYPE *t;
{
return !(t->Tflag&(TF_QUALS|TF_SIQUALS)) ? t /* No prob if no quals */
: findctype(t->Tspec, t->Tflag&(~(TF_QUALS|TF_SIQUALS)),
t->Tsize, t->Tsubt);
}
/* FINDQTYPE - Find or create the qualified version of a given type.
** The given qualifier flags are added into any that already exist.
*/
TYPE *
findqtype(t, quals)
TYPE *t;
INT quals;
{
return findctype(t->Tspec, t->Tflag|(quals & TF_QUALS),
t->Tsize, t->Tsubt);
}
/* FINDFTYPE - Find or create a function type.
** Tspec is always set to TS_FUNCT and flags to 0.
** The two arguments are the return type and prototype list pointer.
*/
TYPE *
findftype(rtyp, plist)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -