ref: 80244a46e09e3ce670be5c94ecc836659bff404c
dir: /decl.c/
#include <assert.h>
#include <stddef.h>
#include <string.h>
#include "cc.h"
#include "tokens.h"
#include "types.h"
#include "syntax.h"
#include "symbol.h"
char parser_out_home;
static void declarator(void);
static struct symbol *newiden(char *s, unsigned char key)
{
register struct symbol *sym = lookup(yytext, yyhash);
if (!sym)
sym = install(yytext, yyhash);
else if (sym->level == nested_level)
error("redeclaration of '%s'", yytext);
return sym;
}
static void dirdcl(void)
{
if (accept('(')) {
declarator();
expect(')');
} else if (yytoken == IDEN) {
newiden(yytext, yyhash);
next();
} else {
error("expected '(' or identifier before of '%s'", yytext);
}
for (;;) {
if (accept('(')) {
next();
pushtype(FTN);
if (accept(')'))
; /* TODO: k&r function */
else
/* TODO: prototyped function */;
continue;
} else if (accept('[')) {
pushtype(ARY);
if (accept(']'))
; /* TODO: automatic size array */
else
/* TODO: specify size of array */;
continue;
} else {
return;
}
}
}
/*
*
*/
static struct type *types[][2] = {{T_VOID, NULL},
{T_SCHAR, T_UCHAR},
{T_SHORT, T_USHORT},
{T_INT, T_UINT},
{T_LONG, T_ULONG},
{T_LLONG, T_ULLONG},
{T_FLOAT, NULL},
{T_DOUBLE, NULL},
{T_LDOUBLE, NULL}};
#define F_VOID 0
#define F_CHAR 1
#define F_SHORT 2
#define F_INT 3
#define F_LONG 4
#define F_LLONG 5
#define F_FLOAT 6
#define F_DOUBLE 7
#define F_LDOUBLE 8
static struct type *specifier(void)
{
auto unsigned char sign, sclass, tqlf, nt;
auto struct type *t;
t = NULL;
tqlf = sign = sclass = 0;
for (;; next()) {
switch (yytoken) {
case TYPEDEF:case EXTERN:case STATIC:case AUTO:case REGISTER:
if (sclass != 0)
error("Two or more storage specifier");
sclass = yytoken;
continue;
case CONST:
if (!(tqlf ^= T_CONST))
goto duplicated_qlf;
continue;
case RESTRICTED:
if (!(tqlf ^= T_RESTRICTED))
goto duplicated_qlf;
continue;
case VOLATILE:
if (!(tqlf ^= T_VOLATILE))
goto duplicated_qlf;
continue;
case VOID: nt = F_VOID; goto check_type;
case CHAR: nt = F_CHAR; goto check_type;
case SHORT: nt = F_SHORT; goto check_type;
case INT: nt = F_INT; goto check_type;
case FLOAT: nt = F_FLOAT; goto check_type;
case DOUBLE: nt = F_DOUBLE; goto check_type;
case LONG: nt = F_LONG; goto check_type;
case SIGNED: case UNSIGNED:
if (sign != 0) {
error((sign != yytoken) ?
"signed and unsigned in declaration" :
"duplicated %s", yytext);
}
sign = yytoken;
if (t == NULL)
continue; /* we don't have type now */
goto check_type;
case STRUCT: /* TODO */
case UNION: /* TODO */
case ENUM: /* TODO */
default:
if (t) {
return t;
} else if (tqlf) {
if (tqlf & T_CONST) pushtype(CONST);
if (tqlf & T_RESTRICTED) pushtype(RESTRICTED);
if (tqlf & T_VOLATILE) pushtype(VOLATILE);
return decl_type(t);
} else if (nested_level == 0 && yytoken == IDEN) {
warning_error(user_opt.implicit_int,
"type defaults to 'int' "
"in declaration of '%s'",
yytext);
return T_INT;
} else if (nested_level == 0) {
error("declaration expected");
}
return NULL;
}
check_type:
if (nt == F_LONG) {
if (t == NULL ||
t == T_INT || t == T_UINT || t == T_LONG) {
/* nothing */;
} else if (t == T_LONG || t == T_ULONG) {
nt = F_LLONG;
} else if (t == T_DOUBLE) {
nt = F_LDOUBLE;
} else if (t == T_LLONG || t == T_ULLONG) {
error("'long long long' is too long");
} else if (t == T_LDOUBLE) {
error("'long long double' is too long");
} else {
goto two_or_more_btype;
}
} else if (t != NULL) {
goto two_or_more_btype;
} if (nt == F_VOID && sign != 0) {
goto incorrect_sign;
} if (nt == F_CHAR && sign == 0) {
t = T_UCHAR; /* char by default is unsigned */
} else if (!(t = types[nt][sign == UNSIGNED])) {
goto incorrect_sign;
}
}
duplicated_qlf:
error("duplicated '%s'", yytext);
two_or_more_btype:
error("two or more basic types");
incorrect_sign:
error("sign specifier applied to incorrect type");
}
#undef F_VOID
#undef F_CHAR
#undef F_SHORT
#undef F_INT
#undef F_LONG
#undef F_LLong
#undef F_FLOAT
#undef F_DOUBLE
#undef F_LDOUBLE
static void declarator(void)
{
unsigned char qlf[PTRLEVEL_MAX], *bp, *lim;
lim = qlf + PTRLEVEL_MAX;
for (bp = qlf; yytoken == '*' && bp != lim; ++bp) {
*bp = 0;
repeat_qlf:
next();
switch (yytoken) {
case CONST:
if (!(*bp ^= T_CONST))
goto duplicated;
goto repeat_qlf;
case RESTRICTED:
if (!(*bp ^= T_RESTRICTED))
goto duplicated;
goto repeat_qlf;
case VOLATILE:
if (!(*bp ^= T_VOLATILE))
goto duplicated;
goto repeat_qlf;
default:
break;
}
}
if (bp == lim)
error("Too much indirection levels");
dirdcl();
while (bp-- != qlf) {
if (*bp & T_CONST) pushtype(CONST);
if (*bp & T_RESTRICTED) pushtype(RESTRICTED);
if (*bp & T_VOLATILE) pushtype(VOLATILE);
pushtype(PTR);
}
return;
duplicated:
error("duplicated '%s'", yytext);
}
unsigned char decl(void)
{
auto struct type *tp, *tbase;
auto unsigned char nd = 0;
if (!(tbase = specifier()))
return 0;
if (yytoken != ';') {
do {
declarator();
tp = decl_type(tbase);
if (isfunction(tp) && yytoken == '{') {
compound();
return 1;
}
++nd;
} while (accept(','));
}
expect(';');
if (nd == 0) {
warning_error(user_opt.useless_typename,
"useless type name in empty declaration");
}
return 1;
}
void type_name()
{
}