system/corennnnn
Revision | 8c246a9dc294760f2a981cf5144fe4939d1554e6 (tree) |
---|---|
Time | 2009-07-15 13:14:10 |
Author | Jack Palevich <jackpal@goog...> |
Commiter | Jack Palevich |
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.
@@ -48,6 +48,11 @@ ACCscript* accCreateScript(); | ||
48 | 48 | |
49 | 49 | void accDeleteScript(ACCscript* script); |
50 | 50 | |
51 | +typedef ACCvoid* (*ACCSymbolLookupFn)(ACCvoid* pContext, const ACCchar * name); | |
52 | + | |
53 | +void accRegisterSymbolCallback(ACCscript* script, ACCSymbolLookupFn pFn, | |
54 | + ACCvoid* pContext); | |
55 | + | |
51 | 56 | ACCenum accGetError( ACCscript* script ); |
52 | 57 | |
53 | 58 | void accScriptSource(ACCscript* script, |
@@ -3232,6 +3232,8 @@ class Compiler : public ErrorSink { | ||
3232 | 3232 | char* dptr; // Macro state: Points to macro text during macro playback. |
3233 | 3233 | int dch; // Macro state: Saves old value of ch during a macro playback. |
3234 | 3234 | char* pGlobalBase; |
3235 | + ACCSymbolLookupFn mpSymbolLookupFn; | |
3236 | + void* mpSymbolLookupContext; | |
3235 | 3237 | |
3236 | 3238 | // Arena for the duration of the compile |
3237 | 3239 | Arena mGlobalArena; |
@@ -3792,6 +3794,7 @@ class Compiler : public ErrorSink { | ||
3792 | 3794 | } |
3793 | 3795 | return false; |
3794 | 3796 | } |
3797 | + | |
3795 | 3798 | /* Parse and evaluate a unary expression. |
3796 | 3799 | * allowAssignment is true if '=' parsing wanted (quick hack) |
3797 | 3800 | */ |
@@ -3880,9 +3883,12 @@ class Compiler : public ErrorSink { | ||
3880 | 3883 | } |
3881 | 3884 | VariableInfo* pVI = VI(t); |
3882 | 3885 | n = (intptr_t) pVI->pAddress; |
3883 | - /* forward reference: try dlsym */ | |
3886 | + /* forward reference: try our lookup function */ | |
3884 | 3887 | if (!n) { |
3885 | - n = (intptr_t) dlsym(RTLD_DEFAULT, nameof(t)); | |
3888 | + if (mpSymbolLookupFn) { | |
3889 | + n = (intptr_t) mpSymbolLookupFn( | |
3890 | + mpSymbolLookupContext, nameof(t)); | |
3891 | + } | |
3886 | 3892 | if (pVI->pType == NULL) { |
3887 | 3893 | if (tok == '(') { |
3888 | 3894 | pVI->pType = mkpIntFn; |
@@ -4613,6 +4619,12 @@ class Compiler : public ErrorSink { | ||
4613 | 4619 | } |
4614 | 4620 | } |
4615 | 4621 | |
4622 | + // One-time initialization, when class is constructed. | |
4623 | + void init() { | |
4624 | + mpSymbolLookupFn = 0; | |
4625 | + mpSymbolLookupContext = 0; | |
4626 | + } | |
4627 | + | |
4616 | 4628 | void clear() { |
4617 | 4629 | tok = 0; |
4618 | 4630 | tokc = 0; |
@@ -4673,6 +4685,7 @@ public: | ||
4673 | 4685 | }; |
4674 | 4686 | |
4675 | 4687 | Compiler() { |
4688 | + init(); | |
4676 | 4689 | clear(); |
4677 | 4690 | } |
4678 | 4691 |
@@ -4680,6 +4693,11 @@ public: | ||
4680 | 4693 | cleanup(); |
4681 | 4694 | } |
4682 | 4695 | |
4696 | + void registerSymbolCallback(ACCSymbolLookupFn pFn, ACCvoid* pContext) { | |
4697 | + mpSymbolLookupFn = pFn; | |
4698 | + mpSymbolLookupContext = pContext; | |
4699 | + } | |
4700 | + | |
4683 | 4701 | int compile(const char* text, size_t textLength) { |
4684 | 4702 | int result; |
4685 | 4703 |
@@ -4848,6 +4866,10 @@ struct ACCscript { | ||
4848 | 4866 | delete text; |
4849 | 4867 | } |
4850 | 4868 | |
4869 | + void registerSymbolCallback(ACCSymbolLookupFn pFn, ACCvoid* pContext) { | |
4870 | + compiler.registerSymbolCallback(pFn, pContext); | |
4871 | + } | |
4872 | + | |
4851 | 4873 | void setError(ACCenum error) { |
4852 | 4874 | if (accError == ACC_NO_ERROR && error != ACC_NO_ERROR) { |
4853 | 4875 | accError = error; |
@@ -4883,6 +4905,12 @@ void accDeleteScript(ACCscript* script) { | ||
4883 | 4905 | } |
4884 | 4906 | |
4885 | 4907 | extern "C" |
4908 | +void accRegisterSymbolCallback(ACCscript* script, ACCSymbolLookupFn pFn, | |
4909 | + ACCvoid* pContext) { | |
4910 | + script->registerSymbolCallback(pFn, pContext); | |
4911 | +} | |
4912 | + | |
4913 | +extern "C" | |
4886 | 4914 | void accScriptSource(ACCscript* script, |
4887 | 4915 | ACCsizei count, |
4888 | 4916 | const ACCchar ** string, |
@@ -31,3 +31,35 @@ LOCAL_CFLAGS := -O0 -g | ||
31 | 31 | LOCAL_MODULE_TAGS := tests |
32 | 32 | |
33 | 33 | include $(BUILD_EXECUTABLE) |
34 | + | |
35 | +# Runtime tests for host | |
36 | +# ======================================================== | |
37 | +include $(CLEAR_VARS) | |
38 | +LOCAL_MODULE:= accRuntimeTest | |
39 | + | |
40 | +LOCAL_SRC_FILES:= \ | |
41 | + runtimeTest.cpp | |
42 | + | |
43 | +LOCAL_SHARED_LIBRARIES := \ | |
44 | + libacc | |
45 | + | |
46 | +LOCAL_MODULE_TAGS := tests | |
47 | + | |
48 | +include $(BUILD_HOST_EXECUTABLE) | |
49 | + | |
50 | +# Runtime tests for target | |
51 | +# ======================================================== | |
52 | +include $(CLEAR_VARS) | |
53 | +LOCAL_MODULE:= accRuntimeTest | |
54 | + | |
55 | +LOCAL_SRC_FILES:= \ | |
56 | + runtimeTest.cpp | |
57 | + | |
58 | +LOCAL_SHARED_LIBRARIES := \ | |
59 | + libacc | |
60 | + | |
61 | +LOCAL_CFLAGS := -O0 -g | |
62 | + | |
63 | +LOCAL_MODULE_TAGS := tests | |
64 | + | |
65 | +include $(BUILD_EXECUTABLE) |
@@ -34,6 +34,10 @@ int run(MainPtr mainFunc, int argc, char** argv) { | ||
34 | 34 | extern "C" |
35 | 35 | void accDisassemble(ACCscript* script); |
36 | 36 | |
37 | +ACCvoid* symbolLookup(ACCvoid* pContext, const ACCchar* name) { | |
38 | + return (ACCvoid*) dlsym(RTLD_DEFAULT, name); | |
39 | +} | |
40 | + | |
37 | 41 | int main(int argc, char** argv) { |
38 | 42 | const char* inFile = NULL; |
39 | 43 | bool printListing; |
@@ -91,6 +95,8 @@ int main(int argc, char** argv) { | ||
91 | 95 | accScriptSource(script, 1, scriptSource, NULL); |
92 | 96 | delete[] text; |
93 | 97 | |
98 | + accRegisterSymbolCallback(script, symbolLookup, NULL); | |
99 | + | |
94 | 100 | accCompileScript(script); |
95 | 101 | int result = accGetError(script); |
96 | 102 | MainPtr mainPointer = 0; |
@@ -0,0 +1,110 @@ | ||
1 | +/* | |
2 | + * RuntimeTest for ACC compiler. | |
3 | + * | |
4 | + */ | |
5 | + | |
6 | +#include <ctype.h> | |
7 | +#include <dlfcn.h> | |
8 | +#include <stdarg.h> | |
9 | +#include <stdint.h> | |
10 | +#include <stdio.h> | |
11 | +#include <stdlib.h> | |
12 | +#include <string.h> | |
13 | + | |
14 | +#if defined(__arm__) | |
15 | +#include <unistd.h> | |
16 | +#endif | |
17 | + | |
18 | +#include <acc/acc.h> | |
19 | + | |
20 | + | |
21 | +typedef void (*ScriptPtr)(); | |
22 | + | |
23 | +// This is a separate function so it can easily be set by breakpoint in gdb. | |
24 | +void run(ScriptPtr scriptFn) { | |
25 | + scriptFn(); | |
26 | +} | |
27 | + | |
28 | +// Private API for development: | |
29 | + | |
30 | +extern "C" | |
31 | +void accDisassemble(ACCscript* script); | |
32 | + | |
33 | +void op_int(int a) { | |
34 | + printf("op_int(%d)\n", a); | |
35 | +} | |
36 | + | |
37 | +void op_float12(float a, float b, float c, float d, | |
38 | + float e, float f, float g, float h, | |
39 | + float i, float j, float k, float l) { | |
40 | + printf("op_float12(%g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g)\n", | |
41 | + a, b, c, d, e, f, g, h, i, j, k, l); | |
42 | +} | |
43 | + | |
44 | +const char* text = "void op_int(int a);\n" | |
45 | + "void op_float12(float a, float b, float c, float d,\n" | |
46 | + " float e, float f, float g, float h,\n" | |
47 | + " float i, float j, float k, float l);\n" | |
48 | + "void script() {\n" | |
49 | + " op_int(123);\n" | |
50 | + " 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" | |
51 | + "}\n"; | |
52 | + | |
53 | +ACCvoid* symbolLookup(ACCvoid* pContext, const ACCchar* name) { | |
54 | + if (strcmp("op_int", name) == 0) { | |
55 | + return (ACCvoid*) op_int; | |
56 | + } | |
57 | + if (strcmp("op_float12", name) == 0) { | |
58 | + return (ACCvoid*) op_float12; | |
59 | + } | |
60 | + return (ACCvoid*) dlsym(RTLD_DEFAULT, name); | |
61 | +} | |
62 | + | |
63 | +int main(int argc, char** argv) { | |
64 | + ACCscript* script = accCreateScript(); | |
65 | + | |
66 | + accRegisterSymbolCallback(script, symbolLookup, NULL); | |
67 | + | |
68 | + const ACCchar* scriptSource[] = {text}; | |
69 | + accScriptSource(script, 1, scriptSource, NULL); | |
70 | + | |
71 | + accCompileScript(script); | |
72 | + int result = accGetError(script); | |
73 | + ScriptPtr scriptPointer = 0; | |
74 | + if (result != 0) { | |
75 | + char buf[1024]; | |
76 | + accGetScriptInfoLog(script, sizeof(buf), NULL, buf); | |
77 | + fprintf(stderr, "%s", buf); | |
78 | + goto exit; | |
79 | + } | |
80 | + | |
81 | + { | |
82 | + ACCsizei numPragmaStrings; | |
83 | + accGetPragmas(script, &numPragmaStrings, 0, NULL); | |
84 | + if (numPragmaStrings) { | |
85 | + char** strings = new char*[numPragmaStrings]; | |
86 | + accGetPragmas(script, NULL, numPragmaStrings, strings); | |
87 | + for(ACCsizei i = 0; i < numPragmaStrings; i += 2) { | |
88 | + fprintf(stderr, "#pragma %s(%s)\n", strings[i], strings[i+1]); | |
89 | + } | |
90 | + delete[] strings; | |
91 | + } | |
92 | + } | |
93 | + | |
94 | + accGetScriptLabel(script, "script", (ACCvoid**) & scriptPointer); | |
95 | + | |
96 | + result = accGetError(script); | |
97 | + if (result != ACC_NO_ERROR) { | |
98 | + fprintf(stderr, "Could not find script: %d\n", result); | |
99 | + } else { | |
100 | + fprintf(stderr, "Executing script:\n"); | |
101 | + run(scriptPointer); | |
102 | + } | |
103 | + | |
104 | + | |
105 | +exit: | |
106 | + | |
107 | + accDeleteScript(script); | |
108 | + | |
109 | + return result; | |
110 | +} |