ref: 7d77cd4c9f3bd9c9a4ad49890b08a4181552ff3d
dir: /decl.c/
#include <assert.h>
#include <stddef.h>
#include <string.h>
#include "sizes.h"
#include "cc.h"
#include "tokens.h"
#include "syntax.h"
#include "symbol.h"
char parser_out_home;
static struct symbol *cursym;
static unsigned char nr_structs = NS_ANY + 1;
static unsigned char structbuf[NR_STRUCT_LEVEL], *structp = &structbuf[0];
static void declarator(struct ctype *tp, unsigned char ns);
static struct symbol *
namespace(register unsigned char ns, signed char alloc)
{
register struct symbol *sym = yyval.sym;
unsigned char yyns = sym->ns;
if (!alloc) {
if (yyns == NS_ANY)
return NULL;
else if (yyns == ns)
return sym;
else
return find(yytext, ns);
} else {
if (yyns == NS_ANY) {
sym->ns = ns;
return sym;
} else if (yyns == ns && sym->ctx == curctx) {
if (alloc < 0)
return sym;
error("redeclaration of '%s'", yytext);
}
return lookup(yytext, ns);
}
}
static void
dirdcl(register struct ctype *tp, unsigned char ns)
{
if (accept('(')) {
declarator(tp, ns);
expect(')');
} else if (yytoken == IDEN) {
cursym = namespace(ns, 1);
next();
} else {
error("expected '(' or identifier before of '%s'", yytext);
}
for (;;) {
if (accept('(')) {
pushtype(FTN);
if (accept(')'))
; /* TODO: k&r function */
else
/* TODO: prototyped function */;
continue;
} else if (accept('[')) {
unsigned len;
if (accept(']')) {
len = 0;
} else {
expect(CONSTANT);
len = yyval.sym->val;
expect(']');
}
pushtype(len);
pushtype(ARY);
continue;
} else {
return;
}
}
}
static void
new_struct(register struct ctype *tp)
{
struct symbol *sym = NULL;
if (yytoken == IDEN) {
sym = namespace(NS_STRUCT, -1);
(sym->ctype = tp)->refcnt++;
next();
}
if (nr_structs == NR_MAXSTRUCTS)
error("too much structs/unions/enum defined");
if (structp == &structbuf[NR_STRUCT_LEVEL])
error("too much nested structs/unions");
tp->ns = *structp++ = nr_structs;
tp->forward = 1;
tp->sym = sym;
}
static struct ctype * spec(void);
static struct ctype *
struct_dcl(unsigned char ns)
{
register struct ctype *tp, *base;
if (!(base = spec())) {
base = newctype();
base->type = INT;
warn(options.implicit,
"data definition has no type or storage class");
}
if (base->c_typedef || base->c_static || base->c_auto ||
base->c_register || base->c_extern) {
error("storage specifier in a struct/union field declaration");
}
do {
declarator(base, ns);
tp = decl_type(base);
if (accept(':')) {
expect(CONSTANT);
switch (tp->type) {
case INT: case BOOL:
tp = btype(NULL, BITFLD);
tp->len = yyval.sym->val;
break;
default:
error("bit-field '%s' has invalid type",
cursym->name);
}
}
(cursym->ctype = tp)->refcnt++;
} while (accept(','));
expect(';');
return tp;
}
static struct ctype *
struct_spec(register struct ctype *tp)
{
new_struct(tp);
if (!accept('{'))
return tp;
if (!tp->forward)
error("struct/union already defined");
do
struct_dcl(tp->ns);
while (!accept('}'));
tp->forward = 0;
return tp;
}
static struct ctype *
enum_dcl(struct ctype *base)
{
short val = 0;
new_struct(base);
if (!accept('{'))
return base;
do {
register struct symbol *sym;
register struct ctype *tp = btype(NULL, INT);
if (yytoken == '}')
break;
expect(IDEN);
((sym = namespace(NS_IDEN, 1))->ctype = tp)->refcnt++;
if (accept('=')) {
expect(CONSTANT);
val = yyval.sym->val;
}
sym->val = val++;
} while (accept(','));
expect('}');
return base;
}
struct ctype *
spec(void)
{
register struct ctype *tp = NULL;
for (;; next()) {
switch (yytoken) {
case TYPEDEF: case EXTERN: case STATIC: case AUTO:
case REGISTER: case CONST: case VOLATILE:
tp = storage(tp, yytoken);
break;
case UNSIGNED: case SIGNED:
case COMPLEX: case IMAGINARY:
case FLOAT: case DOUBLE: case BOOL:
case VOID: case CHAR: case SHORT:
case INT: case LONG:
tp = btype(tp, yytoken);
break;
case ENUM:
tp = btype(tp, yytoken);
next();
return enum_dcl(tp);
case STRUCT: case UNION:
tp = btype(tp, yytoken);
next();
return struct_spec(tp);
case IDEN:
if (!tp || !tp->type) {
struct symbol *sym;
unsigned char tok = ahead();
sym = namespace(NS_TYPEDEF, 0);
if (sym && tok != ';' && tok != ',') {
if (!tp)
tp = newctype();
tp->type = TYPEDEF;
(tp->base = sym->ctype)->refcnt++;
break;
}
}
/* it is not a type name */
default:
if (!tp)
return NULL;
if (!tp->type) {
warn(options.implicit,
"type defaults to 'int' in declaration");
tp->type = INT;
}
if (!tp->c_signed && !tp->c_unsigned) {
switch (tp->type) {
case CHAR:
if (!options.charsign) {
case BOOL: tp->c_unsigned = 1;
break;
}
case INT: case SHORT: case LONG: case LLONG:
tp->c_signed = 1;
}
}
return tp;
}
}
}
static void
declarator(struct ctype *tp, unsigned char ns)
{
unsigned char qlf[NR_DECLARATORS];
register unsigned char *bp, *lim;
lim = &qlf[NR_DECLARATORS];
for (bp = qlf; yytoken == '*' && bp != lim; ) {
next();
*bp++ = PTR;
while (bp != lim) {
switch (yytoken) {
case CONST: case VOLATILE: case RESTRICT:
*bp++ = yytoken;
next();
break;
default:
goto continue_outer;
}
}
continue_outer: ;
}
if (bp == lim)
error("Too much type declarators");
dirdcl(tp, ns);
for (lim = bp, bp = qlf; bp < lim; ++bp)
pushtype(*bp);
}
static struct node *
initializer(register struct ctype *tp)
{
register struct node *np;
if (accept('{')) {
np = nodecomp();
addstmt(np, initializer(tp));
while (accept(',')) {
if (accept('}'))
return np;
addstmt(np, initializer(tp));
}
expect('}');
} else {
np = expr();
}
return np;
}
static struct node *
listdcl(struct ctype *base)
{
struct node *lp = nodecomp();
do {
struct node *sp, *np;
register struct ctype *tp;
declarator(base, base->c_typedef ? NS_TYPEDEF : NS_IDEN);
tp = decl_type(base);
(cursym->ctype = tp)->refcnt++;
if ((tp->type == STRUCT || tp->type == UNION) && tp->forward)
error("declaration of variable with incomplete type");
sp = nodesym(cursym);
if (tp->type == FTN && yytoken == '{') {
np = node(ODEF, sp, function(cursym));
return addstmt(lp, np);
}
np = node(ODEF, sp, accept('=') ? initializer(tp) : NULL);
lp = addstmt(lp, np);
} while (accept(','));
expect(';');
return lp;
}
struct node *
decl(void)
{
register struct ctype *tp;
repeat: if (!(tp = spec())) {
if (curctx != CTX_OUTER || yytoken != IDEN)
return NULL;
tp = newctype();
tp->type = INT;
warn(options.implicit,
"data definition has no type or storage class");
} else if (accept(';')) {
register unsigned char type = tp->type;
if (type == STRUCT || type == UNION || type == ENUM) {
if (tp->c_extern || tp->c_static || tp->c_auto ||
tp->c_register || tp->c_const || tp->c_volatile) {
warn(options.useless,
"useless storage class specifier in empty declaration");
}
if (!tp->sym && type != ENUM) {
warn(options.useless,
"unnamed struct/union that defines no instances");
}
} else {
warn(options.useless,
"useless type name in empty declaration");
}
delctype(tp);
goto repeat;
}
return listdcl(tp);
}
void
type_name()
{
}