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 @@ -115,10 +115,11 @@ static int not(void);
18 static int power(void);
19 static int concatenateNwithSep(int nVals, const char *sep, char **result,
21 static int concat(void);
22 static int assign(void);
23 +static int callSubroutineFromSymbol(Symbol *sym, int nArgs);
24 static int callSubroutine(void);
25 static int fetchRetVal(void);
26 static int branch(void);
27 static int branchTrue(void);
28 static int branchFalse(void);
29 @@ -2329,37 +2330,31 @@ static int concat(void)
31 ** For a macro subroutine, the return address, frame pointer, number of
32 ** arguments and space for local variables are added to the stack, and the
33 ** PC is set to point to the new function. For a built-in routine, the
34 ** arguments are popped off the stack, and the routine is just called.
38 +** For callSubroutine:
39 ** Before: Prog-> [subrSym], nArgs, next, ...
40 ** TheStack-> argArray?, argN-arg1, next, ...
41 ** After: Prog-> next, ... -- (built-in called subr)
42 ** TheStack-> retVal?, next, ...
43 ** or: Prog-> (in called)next, ... -- (macro code called subr)
44 ** TheStack-> symN-sym1(FP), nArgs, oldFP, retPC, argArray, argN-arg1, next, ...
46 -static int callSubroutine(void)
47 +static int callSubroutineFromSymbol(Symbol *sym, int nArgs)
53 static DataValue noValue = {NO_TAG, {0}};
63 - haveNamedArgs = (nArgs < 0);
64 - nArgs = (haveNamedArgs) ? -nArgs - 1 : nArgs;
65 + int haveNamedArgs = (nArgs < 0);
68 - STACKDUMP(nArgs + haveNamedArgs, 3);
73 ** If the subroutine is built-in, call the built-in routine
75 if (sym->type == C_FUNCTION_SYM) {
76 @@ -2482,10 +2477,78 @@ static int callSubroutine(void)
77 /* Calling a non subroutine symbol */
78 return execError("%s is not a function or subroutine", sym->name);
82 +** Before: Prog-> [subrSym], nArgs, next, ...
83 +** Stack-> argN-arg1, next, ...
85 +** After: Prog-> next, ... -- (built-in called subr)
86 +** Stack-> retVal?, next, ...
87 +** or: Prog-> (in called)next, ... -- (macro code called subr)
88 +** Stack-> symN-sym1(FP), argArray, nArgs, oldFP, retPC, argN-arg1, next, ...
90 +static int callSubroutine(void)
97 + nArgs = PC++->value;
100 + STACKDUMP(nArgs, 3);
102 + return callSubroutineFromSymbol(sym, nArgs);
106 +** Assumes a valid symbol. Invokes callSubroutineFromSymbol(), correcting nArgs
107 +** to match that routine's expectations. This allows a callMS() function to be
108 +** written in macro.c. If the caller has already "consumed" stack elements,
109 +** removeArgs must indicate how many.
112 +int OverlayRoutineFromSymbol(Symbol *sym, int nArgs, int removeArgs)
114 + DataValue *stackTop = StackP + nArgs - removeArgs;
116 + if (removeArgs > 0) {
117 + DataValue *from = StackP + removeArgs;
118 + DataValue *to = StackP;
119 + int n = nArgs - removeArgs;
128 + return callSubroutineFromSymbol(sym, nArgs);
132 +** Assumes a valid prog. Wraps the program in a dummy symbol then calls
133 +** OverlayRoutineFromSymbol(). In this way a piece of compiled code can be
134 +** executed in the caller's context from a function in macro.c.
137 +int OverlayRoutineFromProg(Program *prog, int nArgs, int removeArgs)
141 + sym.type = MACRO_FUNCTION_SYM;
142 + sym.name = "<overlaid function>";
143 + sym.value.val.str.rep = (char *)prog;
146 + return OverlayRoutineFromSymbol(&sym, nArgs, removeArgs);
150 ** This should never be executed, returnVal checks for the presence of this
151 ** instruction at the PC to decide whether to push the function's return
152 ** value, then skips over it without executing.
154 static int fetchRetVal(void)
155 diff --quilt old/source/interpret.h new/source/interpret.h
156 --- old/source/interpret.h
157 +++ new/source/interpret.h
158 @@ -163,10 +163,14 @@ void FillLoopAddrs(Inst *breakAddr, Inst
159 int ExecuteMacro(WindowInfo *window, Program *prog, int nArgs, DataValue *args,
160 DataValue *result, RestartData **continuation, char **msg);
161 int ContinueMacro(RestartData *continuation, DataValue *result, char **msg);
162 void RunMacroAsSubrCall(Program *prog);
163 void PreemptMacro(void);
165 +int OverlayRoutineFromProg(Program *prog, int nArgs, int removeArgs);
166 +int OverlayRoutineFromSymbol(Symbol *sym, int nArgs, int removeArgs);
168 char *AllocString(int length);
169 char *AllocStringNCpy(const char *s, int length);
170 char *AllocStringCpy(const char *s);
171 char *AllocStringOfNumber(long val);
172 int AllocNString(NString *string, int length);
173 diff --quilt old/source/macro.c new/source/macro.c
174 --- old/source/macro.c
175 +++ new/source/macro.c
176 @@ -403,10 +403,12 @@ static int getStyleByNameMS(WindowInfo *
177 DataValue *result, char **errMsg);
178 static int getStyleAtPosMS(WindowInfo *window, DataValue *argList, int nArgs,
179 DataValue *result, char **errMsg);
180 static int filenameDialogMS(WindowInfo* window, DataValue* argList, int nArgs,
181 DataValue* result, char** errMsg);
182 +static int callMS(WindowInfo *window, DataValue *argList,
183 + int nArgs, DataValue *result, char **errMsg);
185 /* Built-in subroutines and variables for the macro language */
186 static const BuiltInSubrName MacroSubrs[] = {
187 { "length", lengthMS },
188 { "get_range", getRangeMS },
189 @@ -462,10 +464,11 @@ static const BuiltInSubrName MacroSubrs[
190 { "get_pattern_by_name", getPatternByNameMS },
191 { "get_pattern_at_pos", getPatternAtPosMS },
192 { "get_style_by_name", getStyleByNameMS },
193 { "get_style_at_pos", getStyleAtPosMS },
194 { "filename_dialog", filenameDialogMS },
195 + { "call", callMS },
196 { NULL, NULL } /* sentinel */
199 static const BuiltInSubrName SpecialVars[] = {
200 { "$cursor", cursorMV },
201 @@ -3564,10 +3567,35 @@ static int filenameDialogMS(WindowInfo*
208 + * call(fnname, arg, ...)
210 +static int callMS(WindowInfo *window, DataValue *argList,
211 + int nArgs, DataValue *result, char **errMsg)
213 + char stringStorage[TYPE_INT_STR_SIZE(int)];
218 + *errMsg = "subroutine %s called without arguments";
221 + if (!readStringArg(argList[0], &fnname, stringStorage, errMsg)) {
224 + sym = LookupSymbol(fnname);
226 + *errMsg = "subroutine name invalid";
229 + return OverlayRoutineFromSymbol(sym, nArgs, 1);
233 static int listDialogMS(WindowInfo *window, DataValue *argList, int nArgs,
234 DataValue *result, char **errMsg)
236 macroCmdInfo *cmdData;