1 Provide a call() macro function which calls another function given its name
3 The function invokes new code in interpret.c which calls the desired, named
4 function with any remaining arguments to call(). In this way, the function
5 is called using the same interpretation environment as call()'s invoker.
9 source/interpret.c | 93 ++++++++++++++++++++++++++++++++++++++++++++---------
10 source/interpret.h | 4 ++
11 source/macro.c | 28 +++++++++++++++
12 3 files changed, 110 insertions(+), 15 deletions(-)
14 diff --quilt old/source/interpret.c new/source/interpret.c
15 --- old/source/interpret.c
16 +++ new/source/interpret.c
17 @@ -117,6 +117,7 @@ static int concatenateNwithSep(int nVals
19 static int concat(void);
20 static int assign(void);
21 +static int callSubroutineFromSymbol(Symbol *sym, int nArgs);
22 static int callSubroutine(void);
23 static int fetchRetVal(void);
24 static int branch(void);
25 @@ -2366,7 +2367,9 @@ static int concat(void)
26 ** arguments and space for local variables are added to the stack, and the
27 ** PC is set to point to the new function. For a built-in routine, the
28 ** arguments are popped off the stack, and the routine is just called.
32 +** For callSubroutine:
33 ** Before: Prog-> [subrSym], nArgs, next, ...
34 ** TheStack-> argArray?, argN-arg1, next, ...
35 ** After: Prog-> next, ... -- (built-in called subr)
36 @@ -2374,25 +2377,17 @@ static int concat(void)
37 ** or: Prog-> (in called)next, ... -- (macro code called subr)
38 ** TheStack-> symN-sym1(FP), nArgs, oldFP, retPC, argArray, argN-arg1, next, ...
40 -static int callSubroutine(void)
41 +static int callSubroutineFromSymbol(Symbol *sym, int nArgs)
47 static DataValue noValue = {NO_TAG, {0}};
57 - haveNamedArgs = (nArgs < 0);
58 - nArgs = (haveNamedArgs) ? -nArgs - 1 : nArgs;
59 + int haveNamedArgs = (nArgs < 0);
62 - STACKDUMP(nArgs + haveNamedArgs, 3);
67 ** If the subroutine is built-in, call the built-in routine
68 @@ -2519,6 +2514,74 @@ static int callSubroutine(void)
72 +** Before: Prog-> [subrSym], nArgs, next, ...
73 +** Stack-> argN-arg1, next, ...
75 +** After: Prog-> next, ... -- (built-in called subr)
76 +** Stack-> retVal?, next, ...
77 +** or: Prog-> (in called)next, ... -- (macro code called subr)
78 +** Stack-> symN-sym1(FP), argArray, nArgs, oldFP, retPC, argN-arg1, next, ...
80 +static int callSubroutine(void)
87 + nArgs = PC++->value;
90 + STACKDUMP(nArgs, 3);
92 + return callSubroutineFromSymbol(sym, nArgs);
96 +** Assumes a valid symbol. Invokes callSubroutineFromSymbol(), correcting nArgs
97 +** to match that routine's expectations. This allows a callMS() function to be
98 +** written in macro.c. If the caller has already "consumed" stack elements,
99 +** removeArgs must indicate how many.
102 +int OverlayRoutineFromSymbol(Symbol *sym, int nArgs, int removeArgs)
104 + DataValue *stackTop = StackP + nArgs - removeArgs;
106 + if (removeArgs > 0) {
107 + DataValue *from = StackP + removeArgs;
108 + DataValue *to = StackP;
109 + int n = nArgs - removeArgs;
118 + return callSubroutineFromSymbol(sym, nArgs);
122 +** Assumes a valid prog. Wraps the program in a dummy symbol then calls
123 +** OverlayRoutineFromSymbol(). In this way a piece of compiled code can be
124 +** executed in the caller's context from a function in macro.c.
127 +int OverlayRoutineFromProg(Program *prog, int nArgs, int removeArgs)
131 + sym.type = MACRO_FUNCTION_SYM;
132 + sym.name = "<overlaid function>";
133 + sym.value.val.str.rep = (char *)prog;
136 + return OverlayRoutineFromSymbol(&sym, nArgs, removeArgs);
140 ** This should never be executed, returnVal checks for the presence of this
141 ** instruction at the PC to decide whether to push the function's return
142 ** value, then skips over it without executing.
143 diff --quilt old/source/interpret.h new/source/interpret.h
144 --- old/source/interpret.h
145 +++ new/source/interpret.h
146 @@ -165,6 +165,10 @@ int ExecuteMacro(WindowInfo *window, Pro
147 int ContinueMacro(RestartData *continuation, DataValue *result, char **msg);
148 void RunMacroAsSubrCall(Program *prog);
149 void PreemptMacro(void);
151 +int OverlayRoutineFromProg(Program *prog, int nArgs, int removeArgs);
152 +int OverlayRoutineFromSymbol(Symbol *sym, int nArgs, int removeArgs);
154 char *AllocString(int length);
155 char *AllocStringNCpy(const char *s, int length);
156 char *AllocStringCpy(const char *s);
157 diff --quilt old/source/macro.c new/source/macro.c
158 --- old/source/macro.c
159 +++ new/source/macro.c
160 @@ -405,6 +405,8 @@ static int getStyleAtPosMS(WindowInfo *w
161 DataValue *result, char **errMsg);
162 static int filenameDialogMS(WindowInfo* window, DataValue* argList, int nArgs,
163 DataValue* result, char** errMsg);
164 +static int callMS(WindowInfo *window, DataValue *argList,
165 + int nArgs, DataValue *result, char **errMsg);
167 /* Built-in subroutines and variables for the macro language */
168 static const BuiltInSubrName MacroSubrs[] = {
169 @@ -464,6 +466,7 @@ static const BuiltInSubrName MacroSubrs[
170 { "get_style_by_name", getStyleByNameMS },
171 { "get_style_at_pos", getStyleAtPosMS },
172 { "filename_dialog", filenameDialogMS },
173 + { "call", callMS },
174 { NULL, NULL } /* sentinel */
177 @@ -3566,6 +3569,31 @@ static int filenameDialogMS(WindowInfo*
182 + * call(fnname, arg, ...)
184 +static int callMS(WindowInfo *window, DataValue *argList,
185 + int nArgs, DataValue *result, char **errMsg)
187 + char stringStorage[TYPE_INT_STR_SIZE(int)];
192 + *errMsg = "subroutine %s called without arguments";
195 + if (!readStringArg(argList[0], &fnname, stringStorage, errMsg)) {
198 + sym = LookupSymbol(fnname);
200 + *errMsg = "subroutine name invalid";
203 + return OverlayRoutineFromSymbol(sym, nArgs, 1);
207 static int listDialogMS(WindowInfo *window, DataValue *argList, int nArgs,
208 DataValue *result, char **errMsg)