Move macros into their own table.

Catch attempts to define macros with parens (not supported.)
This commit is contained in:
Jack Palevich 2009-06-08 14:34:26 -07:00
parent ce51b3b55f
commit 2d11dfba27
2 changed files with 220 additions and 35 deletions

View file

@ -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)

View file

@ -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 @@ 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 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 @@ 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;