From 2d11dfba277b2f9d98f00a32510d612e779ba757 Mon Sep 17 00:00:00 2001 From: Jack Palevich Date: Mon, 8 Jun 2009 14:34:26 -0700 Subject: [PATCH] Move macros into their own table. Catch attempts to define macros with parens (not supported.) --- libacc/Android.mk | 2 +- libacc/acc.cpp | 253 +++++++++++++++++++++++++++++++++++++++------- 2 files changed, 220 insertions(+), 35 deletions(-) diff --git a/libacc/Android.mk b/libacc/Android.mk index 77c71c6a2..923de60f5 100644 --- a/libacc/Android.mk +++ b/libacc/Android.mk @@ -12,7 +12,7 @@ ifeq ($(TARGET_ARCH),arm) LOCAL_SRC_FILES += disassem.cpp endif -LOCAL_SHARED_LIBRARIES := libdl +LOCAL_SHARED_LIBRARIES := libdl libcutils include $(BUILD_SHARED_LIBRARY) diff --git a/libacc/acc.cpp b/libacc/acc.cpp index de36ce552..a3a70d187 100644 --- a/libacc/acc.cpp +++ b/libacc/acc.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #if defined(__arm__) #include @@ -1098,7 +1099,6 @@ class Compiler : public ErrorSink { 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* last_id; - void* pSymbolBase; char* pGlobalBase; char* pVarsBase; // Value of variables @@ -1115,18 +1115,34 @@ class Compiler : public ErrorSink { mSize = 0; } + String(char* item, int len, bool adopt) { + if (adopt) { + mpBase = item; + mUsed = len; + mSize = len + 1; + } else { + mpBase = 0; + mUsed = 0; + mSize = 0; + appendBytes(item, len); + } + } + ~String() { if (mpBase) { free(mpBase); } } - char* getUnwrapped() { + inline char* getUnwrapped() { return mpBase; } void appendCStr(const char* s) { - int n = strlen(s); + appendBytes(s, strlen(s)); + } + + void appendBytes(const char* s, int n) { memcpy(ensure(n), s, n + 1); } @@ -1134,6 +1150,14 @@ class Compiler : public ErrorSink { * ensure(1) = c; } + char* orphan() { + char* result = mpBase; + mpBase = 0; + mUsed = 0; + mSize = 0; + return result; + } + void printf(const char* fmt,...) { va_list ap; va_start(ap, fmt); @@ -1148,7 +1172,7 @@ class Compiler : public ErrorSink { free(temp); } - size_t len() { + inline size_t len() { return mUsed; } @@ -1174,6 +1198,148 @@ class Compiler : public ErrorSink { size_t mSize; }; + /** + * Wrap an externally allocated string for use as a hash key. + */ + class FakeString : public String { + public: + FakeString(char* string, size_t length) : + String(string, length, true) {} + + ~FakeString() { + orphan(); + } + }; + + template class StringTable { + public: + StringTable(size_t initialCapacity) { + mpMap = hashmapCreate(initialCapacity, hashFn, equalsFn); + } + + ~StringTable() { + clear(); + } + + void clear() { + hashmapForEach(mpMap, freeKeyValue, this); + } + + bool contains(String* pKey) { + bool result = hashmapContainsKey(mpMap, pKey); + return result; + } + + V* get(String* pKey) { + V* result = (V*) hashmapGet(mpMap, pKey); + return result; + } + + V* remove(String* pKey) { + V* result = (V*) hashmapRemove(mpMap, pKey); + return result; + } + + V* put(String* pKey, V* value) { + V* result = (V*) hashmapPut(mpMap, pKey, value); + if (result) { + // The key was not adopted by the map, so delete it here. + delete pKey; + } + return result; + } + + protected: + static int hashFn(void* pKey) { + String* pString = (String*) pKey; + return hashmapHash(pString->getUnwrapped(), pString->len()); + } + + static bool equalsFn(void* keyA, void* keyB) { + String* pStringA = (String*) keyA; + String* pStringB = (String*) keyB; + return pStringA->len() == pStringB->len() + && strcmp(pStringA->getUnwrapped(), pStringB->getUnwrapped()) + == 0; + } + + static bool freeKeyValue(void* key, void* value, void* context) { + delete (String*) key; + delete (V*) value; + return true; + } + + Hashmap* mpMap; + }; + + class MacroTable : public StringTable { + public: + MacroTable() : StringTable(10) {} + }; + + template class Array { + public: + Array() { + mpBase = 0; + mUsed = 0; + mSize = 0; + } + + ~Array() { + if (mpBase) { + free(mpBase); + } + } + + E get(int i) { + if (i < 0 || i > mUsed) { + error("internal error: Index out of range"); + return E(); + } + return mpBase[i]; + } + + void set(int i, E val) { + mpBase[i] = val; + } + + void pop() { + if (mUsed > 0) { + mUsed -= 1; + } + } + + void push(E item) { + * ensure(1) = item; + } + + size_t len() { + return mUsed; + } + + private: + E* ensure(int n) { + size_t newUsed = mUsed + n; + if (newUsed > mSize) { + size_t newSize = mSize * 2 + 10; + if (newSize < newUsed) { + newSize = newUsed; + } + mpBase = (E*) realloc(mpBase, sizeof(E) * newSize); + mSize = newSize; + } + E* result = mpBase + mUsed; + mUsed = newUsed; + return result; + } + + E* mpBase; + size_t mUsed; + size_t mSize; + }; + + MacroTable mMacros; + String mErrorBuf; jmp_buf mErrorRecoveryJumpBuf; @@ -1208,7 +1374,6 @@ class Compiler : public ErrorSink { /* tokens in string heap */ static const int TAG_TOK = ' '; - static const int TAG_MACRO = 2; static const int OP_INCREMENT = 0; static const int OP_DECREMENT = 1; @@ -1251,7 +1416,7 @@ class Compiler : public ErrorSink { void inp() { if (dptr) { ch = *dptr++; - if (ch == TAG_MACRO) { + if (ch == 0) { dptr = 0; ch = dch; } @@ -1283,16 +1448,7 @@ class Compiler : public ErrorSink { inp(); next(); if (tok == TOK_DEFINE) { - next(); - pdef(TAG_TOK); /* fill last ident tag */ - *(int *) tok = SYM_DEFINE; - *(char* *) (tok + 4) = dstk; /* define stack */ - while (ch != '\n') { - pdef(ch); - inp(); - } - pdef(ch); - pdef(TAG_MACRO); + doDefine(); } else if (tok == TOK_PRAGMA) { doPragma(); } else { @@ -1319,24 +1475,29 @@ class Compiler : public ErrorSink { if (dstk - sym_stk + 1 > ALLOC_SIZE) { error("symbol stack overflow"); } - * dstk = TAG_TOK; /* no need to mark end of string (we - suppose data is initialized to zero by calloc) */ - tok = (intptr_t) (strstr(sym_stk, (last_id - 1)) - - sym_stk); - * dstk = 0; /* mark real end of ident for dlsym() */ - tok = tok * 8 + TOK_IDENT; - if (tok > TOK_DEFINE) { - if (tok + 8 > ALLOC_SIZE) { - error("Variable Table overflow."); - } - tok = (intptr_t) (pVarsBase + tok); - /* printf("tok=%s %x\n", last_id, tok); */ - /* define handling */ - if (*(int *) tok == SYM_DEFINE) { - dptr = *(char* *) (tok + 4); - dch = ch; - inp(); - next(); + FakeString token(last_id, dstk-last_id); + // Is this a macro? + String* pValue = mMacros.get(&token); + if (pValue) { + // Yes, it is a macro + dstk = last_id-1; + dptr = pValue->getUnwrapped(); + dch = ch; + inp(); + next(); + } else { + * dstk = TAG_TOK; /* no need to mark end of string (we + suppose data is initialized to zero by calloc) */ + tok = (intptr_t) (strstr(sym_stk, (last_id - 1)) + - sym_stk); + * dstk = 0; /* mark real end of ident for dlsym() */ + tok = tok * 8 + TOK_IDENT; + if (tok > TOK_DEFINE) { + if (tok + 8 > ALLOC_SIZE) { + error("Variable Table overflow."); + } + tok = (intptr_t) (pVarsBase + tok); + /* printf("tok=%s %x\n", last_id, tok); */ } } } @@ -1415,6 +1576,30 @@ class Compiler : public ErrorSink { #endif } + void doDefine() { + String* pName = new String(); + while (isspace(ch)) { + inp(); + } + while (isid()) { + pName->append(ch); + inp(); + } + if (ch == '(') { + delete pName; + error("Defines with arguments not supported"); + } + while (isspace(ch)) { + inp(); + } + String* pValue = new String(); + while (ch != '\n' && ch != EOF) { + pValue->append(ch); + inp(); + } + delete mMacros.put(pName, pValue); + } + void doPragma() { // # pragma name(val) int state = 0;