Support nested macros. (Still don't support macro arguments.)

Now you can say:

    #define A B
    #define B C
    #define C 4

int x = A;

And it will work as expected.

Print an error message rather than assert when we're expecting a
function value, but don't find one.
diff --git a/libacc/acc.cpp b/libacc/acc.cpp
index 6d9213c..09ce64d 100644
--- a/libacc/acc.cpp
+++ b/libacc/acc.cpp
@@ -3896,6 +3896,16 @@
         Vector<Mark> mLevelStack;
     };
 
+    struct MacroState {
+        tokenid_t name; // Name of the current macro we are expanding
+        char* dptr; // point to macro text during macro playback
+        int dch; // Saves old value of ch during a macro playback
+    };
+
+#define MACRO_NESTING_MAX 32
+    MacroState macroState[MACRO_NESTING_MAX];
+    int macroLevel; // -1 means not playing any macro.
+
     int ch; // Current input character, or EOF
     tokenid_t tok;      // token
     intptr_t tokc;    // token extra info
@@ -3907,8 +3917,6 @@
     char* glo;  // global variable index
     String mTokenString;
     bool mbSuppressMacroExpansion;
-    char* dptr; // Macro state: Points to macro text during macro playback.
-    int dch;    // Macro state: Saves old value of ch during a macro playback.
     char* pGlobalBase;
     ACCSymbolLookupFn mpSymbolLookupFn;
     void* mpSymbolLookupContext;
@@ -4016,9 +4024,6 @@
 
     static const int LOCAL = 0x200;
 
-    static const int SYM_FORWARD = 0;
-    static const int SYM_DEFINE = 1;
-
     /* tokens in string heap */
     static const int TAG_TOK = ' ';
 
@@ -4100,11 +4105,17 @@
     }
 
     void inp() {
-        if (dptr) {
-            ch = *dptr++;
+        // Close any totally empty macros. We leave them on the stack until now
+        // so that we know which macros are being expanded when checking if the
+        // last token in the macro is a macro that's already being expanded.
+        while (macroLevel >= 0 && macroState[macroLevel].dptr == NULL) {
+            macroLevel--;
+        }
+        if (macroLevel >= 0) {
+            ch = *macroState[macroLevel].dptr++;
             if (ch == 0) {
-                dptr = 0;
-                ch = dch;
+                ch = macroState[macroLevel].dch;
+                macroState[macroLevel].dptr = NULL; // This macro's done
             }
         } else {
             if (mbBumpLine) {
@@ -4269,6 +4280,15 @@
         // fprintf(stderr, "float constant: %s (%d) %g\n", pText, tok, tokd);
     }
 
+    bool currentlyBeingExpanded(tokenid_t id) {
+        for (int i = 0; i <= macroLevel; i++) {
+            if (macroState[macroLevel].name == id) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     void next() {
         int l, a;
 
@@ -4350,12 +4370,22 @@
             if (! mbSuppressMacroExpansion) {
                 // Is this a macro?
                 char* pMacroDefinition = mTokenTable[tok].mpMacroDefinition;
-                if (pMacroDefinition) {
+                if (pMacroDefinition && !currentlyBeingExpanded(tok)) {
                     // Yes, it is a macro
-                    dptr = pMacroDefinition;
-                    dch = ch;
-                    inp();
-                    next();
+#if 0
+                    printf("Expanding macro %s -> %s",
+                            mTokenString.getUnwrapped(), pMacroDefinition);
+#endif
+                    if (macroLevel >= MACRO_NESTING_MAX-1) {
+                        error("Too many levels of macro recursion.");
+                    } else {
+                        macroLevel++;
+                        macroState[macroLevel].name = tok;
+                        macroState[macroLevel].dptr = pMacroDefinition;
+                        macroState[macroLevel].dch = ch;
+                        inp();
+                        next();
+                    }
                 }
             }
         } else {
@@ -4441,9 +4471,7 @@
         next();
         mbSuppressMacroExpansion = false;
         tokenid_t name = tok;
-        String* pName = new String();
         if (ch == '(') {
-            delete pName;
             error("Defines with arguments not supported");
             return;
         }
@@ -4471,6 +4499,13 @@
         memcpy(pDefn, value.getUnwrapped(), value.len());
         pDefn[value.len()] = 0;
         mTokenTable[name].mpMacroDefinition = pDefn;
+#if 0
+        {
+            String buf;
+            decodeToken(buf, name, true);
+            fprintf(stderr, "define %s = \"%s\"\n", buf.getUnwrapped(), pDefn);
+        }
+#endif
     }
 
     void doPragma() {
@@ -4769,57 +4804,59 @@
                 Type* pDecl = NULL;
                 VariableInfo* pVI = NULL;
                 Type* pFn = pGen->getR0Type();
-                assert(pFn->tag == TY_POINTER);
-                assert(pFn->pHead->tag == TY_FUNC);
-                pDecl = pFn->pHead;
-                pGen->pushR0();
-                Type* pArgList = pDecl->pTail;
-                bool varArgs = pArgList == NULL;
-                /* push args and invert order */
-                a = pGen->beginFunctionCallArguments();
-                int l = 0;
-                int argCount = 0;
-                while (tok != ')' && tok != EOF) {
-                    if (! varArgs && !pArgList) {
-                        error("Unexpected argument.");
-                    }
-                    expr();
-                    pGen->forceR0RVal();
-                    Type* pTargetType;
-                    if (pArgList) {
-                        pTargetType = pArgList->pHead;
-                        pArgList = pArgList->pTail;
-                    } else {
-                        // This is a ... function, just pass arguments in their
-                        // natural type.
-                        pTargetType = pGen->getR0Type();
-                        if (pTargetType->tag == TY_FLOAT) {
-                            pTargetType = mkpDouble;
-                        } else if (pTargetType->tag == TY_ARRAY) {
-                            // Pass arrays by pointer.
-                            pTargetType = pTargetType->pTail;
+                if (pFn->tag == TY_POINTER && pFn->pHead->tag == TY_FUNC) {
+                    pDecl = pFn->pHead;
+                    pGen->pushR0();
+                    Type* pArgList = pDecl->pTail;
+                    bool varArgs = pArgList == NULL;
+                    /* push args and invert order */
+                    a = pGen->beginFunctionCallArguments();
+                    int l = 0;
+                    int argCount = 0;
+                    while (tok != ')' && tok != EOF) {
+                        if (! varArgs && !pArgList) {
+                            error("Unexpected argument.");
                         }
+                        expr();
+                        pGen->forceR0RVal();
+                        Type* pTargetType;
+                        if (pArgList) {
+                            pTargetType = pArgList->pHead;
+                            pArgList = pArgList->pTail;
+                        } else {
+                            // This is a ... function, just pass arguments in their
+                            // natural type.
+                            pTargetType = pGen->getR0Type();
+                            if (pTargetType->tag == TY_FLOAT) {
+                                pTargetType = mkpDouble;
+                            } else if (pTargetType->tag == TY_ARRAY) {
+                                // Pass arrays by pointer.
+                                pTargetType = pTargetType->pTail;
+                            }
+                        }
+                        if (pTargetType->tag == TY_VOID) {
+                            error("Can't pass void value for argument %d",
+                                  argCount + 1);
+                        } else {
+                            l += pGen->storeR0ToArg(l, pTargetType);
+                        }
+                        if (accept(',')) {
+                            // fine
+                        } else if ( tok != ')') {
+                            error("Expected ',' or ')'");
+                        }
+                        argCount += 1;
                     }
-                    if (pTargetType->tag == TY_VOID) {
-                        error("Can't pass void value for argument %d",
-                              argCount + 1);
-                    } else {
-                        l += pGen->storeR0ToArg(l, pTargetType);
+                    if (! varArgs && pArgList) {
+                        error("Expected more argument(s). Saw %d", argCount);
                     }
-                    if (accept(',')) {
-                        // fine
-                    } else if ( tok != ')') {
-                        error("Expected ',' or ')'");
-                    }
-                    argCount += 1;
+                    pGen->endFunctionCallArguments(pDecl, a, l);
+                    skip(')');
+                    pGen->callIndirect(l, pDecl);
+                    pGen->adjustStackAfterCall(pDecl, l, true);
+                } else {
+                    error("Expected a function value to left of '('.");
                 }
-                if (! varArgs && pArgList) {
-                    error("Expected more argument(s). Saw %d", argCount);
-                }
-                pGen->endFunctionCallArguments(pDecl, a, l);
-                skip(')');
-                pGen->callIndirect(l, pDecl);
-                pGen->adjustStackAfterCall(pDecl, l, true);
             } else {
                 break;
             }
@@ -5620,8 +5657,12 @@
         if (token == EOF ) {
             buffer.printf("EOF");
         } else if (token == TOK_NUM) {
-            buffer.printf("numeric constant");
-        } else if (token >= 0 && token < 256) {
+            buffer.printf("numeric constant %d(0x%x)", tokc, tokc);
+        } else if (token == TOK_NUM_FLOAT) {
+            buffer.printf("numeric constant float %g", tokd);
+        } else if (token == TOK_NUM_DOUBLE) {
+            buffer.printf("numeric constant double %g", tokd);
+        }  else if (token >= 0 && token < 256) {
             if (token < 32) {
                 buffer.printf("'\\x%02x'", token);
             } else {
@@ -5828,8 +5869,7 @@
         rsym = 0;
         loc = 0;
         glo = 0;
-        dptr = 0;
-        dch = 0;
+        macroLevel = -1;
         file = 0;
         pGlobalBase = 0;
         pCodeBuf = 0;
diff --git a/libacc/tests/data/macros.c b/libacc/tests/data/macros.c
new file mode 100644
index 0000000..50e54dc
--- /dev/null
+++ b/libacc/tests/data/macros.c
@@ -0,0 +1,10 @@
+#define A B + B
+#define B C
+
+int main() {
+    int C = 3;
+    printf("A = %d\n", A);
+#define C 5
+    printf("A = %d\n", A);
+    return 0;
+}
diff --git a/libacc/tests/main.cpp b/libacc/tests/main.cpp
index 948f4cb..e4e386f 100644
--- a/libacc/tests/main.cpp
+++ b/libacc/tests/main.cpp
@@ -38,14 +38,7 @@
 }
 
 ACCvoid* symbolLookup(ACCvoid* pContext, const ACCchar* name) {
-    // Call dlerror once to clear out any preexisting error condition.
-    (void) dlerror();
-    ACCvoid* result = (ACCvoid*) dlsym(RTLD_DEFAULT, name);
-    const char* error = dlerror();
-    if (error) {
-        fprintf(stderr, "%s\"%s\"\n", error, name);
-    }
-    return result;
+    return (ACCvoid*) dlsym(RTLD_DEFAULT, name);
 }
 
 #ifdef PROVIDE_ARM_DISASSEMBLY
diff --git a/libacc/tests/test.py b/libacc/tests/test.py
index c982d16..8f4920b 100644
--- a/libacc/tests/test.py
+++ b/libacc/tests/test.py
@@ -373,6 +373,12 @@
 Total bad: 0
 """)
 
+    def testMacros(self):
+        self.compileCheck(["-R", "data/macros.c"], """Executing compiled code:
+result: 0""", """A = 6
+A = 10
+""")
+
     def testpointers2(self):
         self.compileCheck(["-R", "data/pointers2.c"], """Executing compiled code:
 result: 0""", """a = 0, *pa = 0