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

Commit 8c246a9d authored by Jack Palevich's avatar Jack Palevich
Browse files

Add accRegisterSymbolCallback API to control external symbol linkage.

Until now dlsym was used to lookup external symbols. Now you can
register your own function to be called when an undefined symbol is
used.
parent fd3db48e
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -48,6 +48,11 @@ ACCscript* accCreateScript();

void accDeleteScript(ACCscript* script);

typedef ACCvoid* (*ACCSymbolLookupFn)(ACCvoid* pContext, const ACCchar * name);

void accRegisterSymbolCallback(ACCscript* script, ACCSymbolLookupFn pFn,
                               ACCvoid* pContext);

ACCenum accGetError( ACCscript* script );

void accScriptSource(ACCscript* script,
+30 −2
Original line number Diff line number Diff line
@@ -3232,6 +3232,8 @@ 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* pGlobalBase;
    ACCSymbolLookupFn mpSymbolLookupFn;
    void* mpSymbolLookupContext;

    // Arena for the duration of the compile
    Arena mGlobalArena;
@@ -3792,6 +3794,7 @@ class Compiler : public ErrorSink {
        }
        return false;
    }

    /* Parse and evaluate a unary expression.
     * allowAssignment is true if '=' parsing wanted (quick hack)
     */
@@ -3880,9 +3883,12 @@ class Compiler : public ErrorSink {
                }
                VariableInfo* pVI = VI(t);
                n = (intptr_t) pVI->pAddress;
                /* forward reference: try dlsym */
                /* forward reference: try our lookup function */
                if (!n) {
                    n = (intptr_t) dlsym(RTLD_DEFAULT, nameof(t));
                    if (mpSymbolLookupFn) {
                        n = (intptr_t) mpSymbolLookupFn(
                            mpSymbolLookupContext, nameof(t));
                    }
                    if (pVI->pType == NULL) {
                        if (tok == '(') {
                            pVI->pType = mkpIntFn;
@@ -4613,6 +4619,12 @@ class Compiler : public ErrorSink {
        }
    }

    // One-time initialization, when class is constructed.
    void init() {
        mpSymbolLookupFn = 0;
        mpSymbolLookupContext = 0;
    }

    void clear() {
        tok = 0;
        tokc = 0;
@@ -4673,6 +4685,7 @@ public:
    };

    Compiler() {
        init();
        clear();
    }

@@ -4680,6 +4693,11 @@ public:
        cleanup();
    }

    void registerSymbolCallback(ACCSymbolLookupFn pFn, ACCvoid* pContext) {
        mpSymbolLookupFn = pFn;
        mpSymbolLookupContext = pContext;
    }

    int compile(const char* text, size_t textLength) {
        int result;

@@ -4848,6 +4866,10 @@ struct ACCscript {
        delete text;
    }

    void registerSymbolCallback(ACCSymbolLookupFn pFn, ACCvoid* pContext) {
        compiler.registerSymbolCallback(pFn, pContext);
    }

    void setError(ACCenum error) {
        if (accError == ACC_NO_ERROR && error != ACC_NO_ERROR) {
            accError = error;
@@ -4882,6 +4904,12 @@ void accDeleteScript(ACCscript* script) {
    delete script;
}

extern "C"
void accRegisterSymbolCallback(ACCscript* script, ACCSymbolLookupFn pFn,
                               ACCvoid* pContext) {
    script->registerSymbolCallback(pFn, pContext);
}

extern "C"
void accScriptSource(ACCscript* script,
    ACCsizei count,
+32 −0
Original line number Diff line number Diff line
@@ -31,3 +31,35 @@ LOCAL_CFLAGS := -O0 -g
LOCAL_MODULE_TAGS := tests

include $(BUILD_EXECUTABLE)

# Runtime tests for host
# ========================================================
include $(CLEAR_VARS)
LOCAL_MODULE:= accRuntimeTest

LOCAL_SRC_FILES:= \
	runtimeTest.cpp

LOCAL_SHARED_LIBRARIES := \
    libacc

LOCAL_MODULE_TAGS := tests

include $(BUILD_HOST_EXECUTABLE)

# Runtime tests for target
# ========================================================
include $(CLEAR_VARS)
LOCAL_MODULE:= accRuntimeTest

LOCAL_SRC_FILES:= \
	runtimeTest.cpp

LOCAL_SHARED_LIBRARIES := \
    libacc

LOCAL_CFLAGS := -O0 -g 

LOCAL_MODULE_TAGS := tests

include $(BUILD_EXECUTABLE)
+6 −0
Original line number Diff line number Diff line
@@ -34,6 +34,10 @@ int run(MainPtr mainFunc, int argc, char** argv) {
extern "C"
void accDisassemble(ACCscript* script);

ACCvoid* symbolLookup(ACCvoid* pContext, const ACCchar* name) {
    return (ACCvoid*) dlsym(RTLD_DEFAULT, name);
}

int main(int argc, char** argv) {
    const char* inFile = NULL;
    bool printListing;
@@ -91,6 +95,8 @@ int main(int argc, char** argv) {
    accScriptSource(script, 1, scriptSource, NULL);
    delete[] text;

    accRegisterSymbolCallback(script, symbolLookup, NULL);

    accCompileScript(script);
    int result = accGetError(script);
    MainPtr mainPointer = 0;
+110 −0
Original line number Diff line number Diff line
/*
 * RuntimeTest for ACC compiler.
 *
 */

#include <ctype.h>
#include <dlfcn.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#if defined(__arm__)
#include <unistd.h>
#endif

#include <acc/acc.h>


typedef void (*ScriptPtr)();

// This is a separate function so it can easily be set by breakpoint in gdb.
void run(ScriptPtr scriptFn) {
    scriptFn();
}

// Private API for development:

extern "C"
void accDisassemble(ACCscript* script);

void op_int(int a) {
    printf("op_int(%d)\n", a);
}

void op_float12(float a, float b, float c, float d,
                float e, float f, float g, float h,
                float i, float j, float k, float l) {
    printf("op_float12(%g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g)\n",
           a, b, c, d, e, f, g, h, i, j, k, l);
}

const char* text = "void op_int(int a);\n"
    "void op_float12(float a, float b, float c, float d,\n"
    "           float e, float f, float g, float h,\n"
    "           float i, float j, float k, float l);\n"
    "void script() {\n"
    "  op_int(123);\n"
    "  op_float12(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0);\n"
    "}\n";

ACCvoid* symbolLookup(ACCvoid* pContext, const ACCchar* name) {
    if (strcmp("op_int", name) == 0) {
        return (ACCvoid*) op_int;
    }
    if (strcmp("op_float12", name) == 0) {
        return (ACCvoid*) op_float12;
    }
    return (ACCvoid*) dlsym(RTLD_DEFAULT, name);
}

int main(int argc, char** argv) {
    ACCscript* script = accCreateScript();

    accRegisterSymbolCallback(script, symbolLookup, NULL);

    const ACCchar* scriptSource[] = {text};
    accScriptSource(script, 1, scriptSource, NULL);

    accCompileScript(script);
    int result = accGetError(script);
    ScriptPtr scriptPointer = 0;
    if (result != 0) {
        char buf[1024];
        accGetScriptInfoLog(script, sizeof(buf), NULL, buf);
        fprintf(stderr, "%s", buf);
        goto exit;
    }

    {
        ACCsizei numPragmaStrings;
        accGetPragmas(script, &numPragmaStrings, 0, NULL);
        if (numPragmaStrings) {
            char** strings = new char*[numPragmaStrings];
            accGetPragmas(script, NULL, numPragmaStrings, strings);
            for(ACCsizei i = 0; i < numPragmaStrings; i += 2) {
                fprintf(stderr, "#pragma %s(%s)\n", strings[i], strings[i+1]);
            }
            delete[] strings;
        }
    }

    accGetScriptLabel(script, "script", (ACCvoid**) & scriptPointer);

    result = accGetError(script);
    if (result != ACC_NO_ERROR) {
        fprintf(stderr, "Could not find script: %d\n", result);
    } else {
        fprintf(stderr, "Executing script:\n");
        run(scriptPointer);
    }


exit:

    accDeleteScript(script);

    return result;
}