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(',')) {