Implement typedef.
diff --git a/libacc/acc.cpp b/libacc/acc.cpp
index 09ce64d..d9cecdd 100644
--- a/libacc/acc.cpp
+++ b/libacc/acc.cpp
@@ -151,6 +151,7 @@
class Compiler : public ErrorSink {
typedef int tokenid_t;
enum TypeTag {
+ TY_UNKNOWN = -1,
TY_INT, // 0
TY_CHAR, // 1
TY_SHORT, // 2
@@ -164,8 +165,18 @@
TY_PARAM // 10
};
+ enum StorageClass {
+ SC_DEFAULT, // 0
+ SC_AUTO, // 1
+ SC_REGISTER, // 2
+ SC_STATIC, // 3
+ SC_EXTERN, // 4
+ SC_TYPEDEF // 5
+ };
+
struct Type {
TypeTag tag;
+ StorageClass storageClass;
tokenid_t id; // For function arguments, global vars, local vars, struct elements
tokenid_t structTag; // For structs the name of the struct
int length; // length of array, offset of struct element. -1 means struct is forward defined
@@ -4996,7 +5007,7 @@
intptr_t a, n, t;
Type* pBaseType;
- if ((pBaseType = acceptPrimitiveType())) {
+ if ((pBaseType = acceptPrimitiveType(true))) {
/* declarations */
localDeclarations(pBaseType);
} else if (tok == TOK_IF) {
@@ -5102,9 +5113,10 @@
}
Type* createType(TypeTag tag, Type* pHead, Type* pTail) {
- assert(tag >= TY_INT && tag <= TY_PARAM);
+ assert(tag >= TY_UNKNOWN && tag <= TY_PARAM);
Type* pType = (Type*) mpCurrentArena->alloc(sizeof(Type));
memset(pType, 0, sizeof(*pType));
+ pType->storageClass = SC_DEFAULT;
pType->tag = tag;
pType->pHead = pHead;
pType->pTail = pTail;
@@ -5267,38 +5279,124 @@
fprintf(stderr, "%s\n", buffer.getUnwrapped());
}
- Type* acceptPrimitiveType() {
- Type* pType;
- if (tok == TOK_INT) {
- pType = mkpInt;
- } else if (tok == TOK_SHORT) {
- pType = mkpShort;
- } else if (tok == TOK_CHAR) {
- pType = mkpChar;
- } else if (tok == TOK_VOID) {
- pType = mkpVoid;
- } else if (tok == TOK_FLOAT) {
- pType = mkpFloat;
- } else if (tok == TOK_DOUBLE) {
- pType = mkpDouble;
- } else if (tok == TOK_STRUCT || tok == TOK_UNION) {
- return acceptStruct();
+ void insertTypeSpecifier(Type** ppType, TypeTag tag) {
+ if (! *ppType) {
+ *ppType = createType(tag, NULL, NULL);
} else {
- return NULL;
+ if ((*ppType)->tag != TY_UNKNOWN) {
+ error("Only one type specifier allowed.");
+ } else {
+ (*ppType)->tag = tag;
+ }
}
- next();
+ }
+
+ void insertStorageClass(Type** ppType, StorageClass storageClass) {
+ if (! *ppType) {
+ *ppType = createType(TY_UNKNOWN, NULL, NULL);
+ }
+ if ((*ppType)->storageClass != SC_DEFAULT) {
+ error("Only one storage class allowed.");
+ } else {
+ (*ppType)->storageClass = storageClass;
+ }
+ }
+
+ Type* acceptPrimitiveType(bool allowStorageClass) {
+ Type* pType = NULL;
+ for (bool keepGoing = true; keepGoing;) {
+ switch(tok) {
+ case TOK_AUTO:
+ insertStorageClass(&pType, SC_AUTO);
+ break;
+ case TOK_REGISTER:
+ insertStorageClass(&pType, SC_REGISTER);
+ break;
+ case TOK_STATIC:
+ insertStorageClass(&pType, SC_STATIC);
+ break;
+ case TOK_EXTERN:
+ insertStorageClass(&pType, SC_EXTERN);
+ break;
+ case TOK_TYPEDEF:
+ insertStorageClass(&pType, SC_TYPEDEF);
+ break;
+ case TOK_INT:
+ insertTypeSpecifier(&pType, TY_INT);
+ break;
+ case TOK_SHORT:
+ insertTypeSpecifier(&pType, TY_SHORT);
+ break;
+ case TOK_CHAR:
+ insertTypeSpecifier(&pType, TY_CHAR);
+ break;
+ case TOK_VOID:
+ insertTypeSpecifier(&pType, TY_VOID);
+ break;
+ case TOK_FLOAT:
+ insertTypeSpecifier(&pType, TY_FLOAT);
+ break;
+ case TOK_DOUBLE:
+ insertTypeSpecifier(&pType, TY_DOUBLE);
+ break;
+ case TOK_STRUCT:
+ case TOK_UNION:
+ {
+ insertTypeSpecifier(&pType, TY_STRUCT);
+ bool isStruct = (tok == TOK_STRUCT);
+ next();
+ pType = acceptStruct(pType, isStruct);
+ keepGoing = false;
+ }
+ break;
+ default:
+ // Is it a typedef?
+ if (isSymbol(tok)) {
+ VariableInfo* pV = VI(tok);
+ if (pV && pV->pType->storageClass == SC_TYPEDEF) {
+ if (! pType) {
+ pType = createType(TY_UNKNOWN, NULL, NULL);
+ }
+ StorageClass storageClass = pType->storageClass;
+ *pType = *pV->pType;
+ pType->storageClass = storageClass;
+ } else {
+ keepGoing = false;
+ }
+ } else {
+ keepGoing = false;
+ }
+ }
+ if (keepGoing) {
+ next();
+ }
+ }
+ if (pType) {
+ if (pType->tag == TY_UNKNOWN) {
+ pType->tag = TY_INT;
+ }
+ if (allowStorageClass) {
+ switch(pType->storageClass) {
+ case SC_AUTO: error("auto not supported."); break;
+ case SC_REGISTER: error("register not supported."); break;
+ case SC_STATIC: error("static not supported."); break;
+ case SC_EXTERN: error("extern not supported."); break;
+ default: break;
+ }
+ } else {
+ if (pType->storageClass != SC_DEFAULT) {
+ error("An explicit storage class is not allowed in this type declaration");
+ }
+ }
+ }
return pType;
}
- Type* acceptStruct() {
- assert(tok == TOK_STRUCT || tok == TOK_UNION);
- bool isStruct = tok == TOK_STRUCT;
- next();
+ Type* acceptStruct(Type* pStructType, bool isStruct) {
tokenid_t structTag = acceptSymbol();
bool isDeclaration = accept('{');
bool fail = false;
- Type* pStructType = createType(TY_STRUCT, NULL, NULL);
if (structTag) {
Token* pToken = &mTokenTable[structTag];
VariableInfo* pStructInfo = pToken->mpStructInfo;
@@ -5327,9 +5425,11 @@
if (needToDeclare) {
// This is a new struct name
pToken->mpStructInfo = mpCurrentSymbolStack->addStructTag(structTag);
+ StorageClass storageClass = pStructType->storageClass;
pStructType = createType(TY_STRUCT, NULL, NULL);
pStructType->structTag = structTag;
pStructType->pHead = pStructType;
+ pStructType->storageClass = storageClass;
if (! isDeclaration) {
// A forward declaration
pStructType->length = -1;
@@ -5347,7 +5447,7 @@
size_t structAlignment = 0;
Type** pParamHolder = & pStructType->pHead->pTail;
while (tok != '}' && tok != EOF) {
- Type* pPrimitiveType = expectPrimitiveType();
+ Type* pPrimitiveType = expectPrimitiveType(false);
if (pPrimitiveType) {
while (tok != ';' && tok != EOF) {
Type* pItem = acceptDeclaration(pPrimitiveType, true, false);
@@ -5410,6 +5510,7 @@
Type* acceptDeclaration(Type* pType, bool nameAllowed, bool nameRequired) {
tokenid_t declName = 0;
bool reportFailure = false;
+ StorageClass storageClass = pType->storageClass;
pType = acceptDecl2(pType, declName, nameAllowed,
nameRequired, reportFailure);
if (declName) {
@@ -5418,6 +5519,7 @@
pType = createType(pType->tag, pType->pHead, pType->pTail);
*pType = *pOldType;
pType->id = declName;
+ pType->storageClass = storageClass;
} else if (nameRequired) {
error("Expected a variable name");
}
@@ -5442,7 +5544,7 @@
/* Used for accepting types that appear in casts */
Type* acceptCastTypeDeclaration() {
- Type* pType = acceptPrimitiveType();
+ Type* pType = acceptPrimitiveType(false);
if (pType) {
pType = acceptDeclaration(pType, false, false);
}
@@ -5530,7 +5632,7 @@
Type* pHead = NULL;
Type* pTail = NULL;
for(;;) {
- Type* pBaseArg = acceptPrimitiveType();
+ Type* pBaseArg = acceptPrimitiveType(false);
if (pBaseArg) {
Type* pArg = acceptDeclaration(pBaseArg, nameAllowed, false);
if (pArg) {
@@ -5551,8 +5653,8 @@
return pHead;
}
- Type* expectPrimitiveType() {
- Type* pType = acceptPrimitiveType();
+ Type* expectPrimitiveType(bool allowStorageClass) {
+ Type* pType = acceptPrimitiveType(allowStorageClass);
if (!pType) {
String buf;
decodeToken(buf, tok, true);
@@ -5620,7 +5722,7 @@
break;
}
// Else it's a forward declaration of a function.
- } else {
+ } else if (pDecl->storageClass != SC_TYPEDEF) {
int variableAddress = 0;
size_t alignment = pGen->alignmentOf(pDecl);
assert(alignment > 0);
@@ -5645,7 +5747,7 @@
next();
}
skip(';');
- pBaseType = acceptPrimitiveType();
+ pBaseType = acceptPrimitiveType(true);
}
}
@@ -5709,7 +5811,7 @@
void globalDeclarations() {
mpCurrentSymbolStack = &mGlobals;
while (tok != EOF) {
- Type* pBaseType = expectPrimitiveType();
+ Type* pBaseType = expectPrimitiveType(true);
if (!pBaseType) {
break;
}
@@ -5726,7 +5828,6 @@
skip(';');
continue;
}
-
if (! isDefined(pDecl->id)) {
addGlobalSymbol(pDecl);
}
@@ -5737,19 +5838,23 @@
if (pDecl->tag < TY_FUNC) {
// it's a variable declaration
for(;;) {
- if (name && !name->pAddress) {
- name->pAddress = (int*) allocGlobalSpace(
- pGen->alignmentOf(name->pType),
- pGen->sizeOf(name->pType));
- }
- if (accept('=')) {
- if (tok == TOK_NUM) {
- if (name) {
- * (int*) name->pAddress = tokc;
+ if (pDecl->storageClass == SC_TYPEDEF) {
+ // Do not allocate storage.
+ } else {
+ if (name && !name->pAddress) {
+ name->pAddress = (int*) allocGlobalSpace(
+ pGen->alignmentOf(name->pType),
+ pGen->sizeOf(name->pType));
+ }
+ if (accept('=')) {
+ if (tok == TOK_NUM) {
+ if (name) {
+ * (int*) name->pAddress = tokc;
+ }
+ next();
+ } else {
+ error("Expected an integer constant");
}
- next();
- } else {
- error("Expected an integer constant");
}
}
if (!accept(',')) {