Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2d11dfba authored by Jack Palevich's avatar Jack Palevich
Browse files

Move macros into their own table.

Catch attempts to define macros with parens (not supported.)
parent ce51b3b5
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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)

+219 −34
Original line number Diff line number Diff line
@@ -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,6 +1475,17 @@ class Compiler : public ErrorSink {
                if (dstk - sym_stk + 1 > ALLOC_SIZE) {
                    error("symbol stack overflow");
                }
                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))
@@ -1331,12 +1498,6 @@ class Compiler : public ErrorSink {
                        }
                        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();
                    }
                }
            }
@@ -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;