Move macros into their own table.
Catch attempts to define macros with parens (not supported.)
diff --git a/libacc/acc.cpp b/libacc/acc.cpp
index de36ce5..a3a70d1 100644
--- a/libacc/acc.cpp
+++ b/libacc/acc.cpp
@@ -16,6 +16,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <cutils/hashmap.h>
#if defined(__arm__)
#include <unistd.h>
@@ -1098,7 +1099,6 @@
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 @@
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 @@
* 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 @@
free(temp);
}
- size_t len() {
+ inline size_t len() {
return mUsed;
}
@@ -1174,6 +1198,148 @@
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 V> 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<String> {
+ public:
+ MacroTable() : StringTable<String>(10) {}
+ };
+
+ template<class E> 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 @@
/* 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 @@
void inp() {
if (dptr) {
ch = *dptr++;
- if (ch == TAG_MACRO) {
+ if (ch == 0) {
dptr = 0;
ch = dch;
}
@@ -1283,16 +1448,7 @@
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 @@
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 @@
#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;