add cast to XtCalloc() call
[nedit-bw.git] / callMacroFnByName2.diff
blob16e1c7099bd86cf8234940136f70fc6c70454bf3
1 From: Tony Balinski <ajbj@free.fr>
2 Subject: Provide a call() macro function which calls another function given its name
4 The function invokes new code in interpret.c which calls the desired, named
5 function with any remaining arguments to call(). In this way, the function
6 is called using the same interpretation environment as call()'s invoker.
8 ---
10 source/interpret.c | 93 ++++++++++++++++++++++++++++++++++++++++++++---------
11 source/interpret.h | 4 ++
12 source/macro.c | 28 +++++++++++++++
13 3 files changed, 110 insertions(+), 15 deletions(-)
15 diff --quilt old/source/interpret.c new/source/interpret.c
16 --- old/source/interpret.c
17 +++ new/source/interpret.c
18 @@ -87,10 +87,11 @@ static void restoreContext(RestartData *
19 #undef OP
20 static int returnValOrNone(int valOnStack);
21 static int branchIf(Boolean trueOrFalse);
22 static int namedArg1orN(Boolean isFirst);
24 +static int callSubroutineFromSymbol(Symbol *sym, int nArgs);
25 static int concatenateNwithSep(int nVals, const char *sep, char **result,
26 int leaveParams);
27 static int makeArrayKeyFromArgs(int nArgs, char **keyString, int leaveParams);
28 static void freeSymbolTable(Symbol *symTab);
29 static int errCheck(const char *s);
30 @@ -2435,37 +2436,31 @@ static int concat(void)
32 ** For a macro subroutine, the return address, frame pointer, number of
33 ** arguments and space for local variables are added to the stack, and the
34 ** PC is set to point to the new function. For a built-in routine, the
35 ** arguments are popped off the stack, and the routine is just called.
36 -**
37 +*/
38 +/*
39 +** For callSubroutine:
40 ** Before: Prog-> [subrSym], nArgs, next, ...
41 ** TheStack-> argArray?, argN-arg1, next, ...
42 ** After: Prog-> next, ... -- (built-in called subr)
43 ** TheStack-> retVal?, next, ...
44 ** or: Prog-> (in called)next, ... -- (macro code called subr)
45 ** TheStack-> symN-sym1(FP), nArgs, oldFP, retPC, argArray, argN-arg1, next, ...
47 -static int callSubroutine(void)
48 +static int callSubroutineFromSymbol(Symbol *sym, int nArgs)
50 - Symbol *sym, *s;
51 - int i, nArgs;
52 + Symbol *s;
53 + int i;
54 static DataValue noValue = {NO_TAG, {0}};
55 Program *prog;
56 char *errMsg;
57 - int haveNamedArgs;
59 - sym = PC->sym;
60 - PC++;
61 - nArgs = PC->value;
62 - PC++;
64 - haveNamedArgs = (nArgs < 0);
65 - nArgs = (haveNamedArgs) ? -nArgs - 1 : nArgs;
66 + int haveNamedArgs = (nArgs < 0);
68 - DISASM_RT(PC-3, 3);
69 - STACKDUMP(nArgs + haveNamedArgs, 3);
70 + if (haveNamedArgs)
71 + nArgs = -nArgs - 1;
74 ** If the subroutine is built-in, call the built-in routine
76 if (sym->type == C_FUNCTION_SYM) {
77 @@ -2590,10 +2585,78 @@ static int callSubroutine(void)
78 /* Calling a non subroutine symbol */
79 return execError("%s is not a function or subroutine", sym->name);
83 +** Before: Prog-> [subrSym], nArgs, next, ...
84 +** Stack-> argN-arg1, next, ...
85 +**
86 +** After: Prog-> next, ... -- (built-in called subr)
87 +** Stack-> retVal?, next, ...
88 +** or: Prog-> (in called)next, ... -- (macro code called subr)
89 +** Stack-> symN-sym1(FP), argArray, nArgs, oldFP, retPC, argN-arg1, next, ...
90 +*/
91 +static int callSubroutine(void)
93 + Symbol *sym;
94 + int nArgs;
95 + int n;
97 + sym = PC++->sym;
98 + nArgs = PC++->value;
100 + DISASM_RT(PC-3, 3);
101 + STACKDUMP(nArgs, 3);
103 + return callSubroutineFromSymbol(sym, nArgs);
107 +** Assumes a valid symbol. Invokes callSubroutineFromSymbol(), correcting nArgs
108 +** to match that routine's expectations. This allows a callMS() function to be
109 +** written in macro.c. If the caller has already "consumed" stack elements,
110 +** removeArgs must indicate how many.
113 +int OverlayRoutineFromSymbol(Symbol *sym, int nArgs, int removeArgs)
115 + DataValue *stackTop = StackP + nArgs - removeArgs;
117 + if (removeArgs > 0) {
118 + DataValue *from = StackP + removeArgs;
119 + DataValue *to = StackP;
120 + int n = nArgs - removeArgs;
122 + nArgs = n;
123 + while (n--) {
124 + *to++ = *from++;
128 + StackP = stackTop;
129 + return callSubroutineFromSymbol(sym, nArgs);
133 +** Assumes a valid prog. Wraps the program in a dummy symbol then calls
134 +** OverlayRoutineFromSymbol(). In this way a piece of compiled code can be
135 +** executed in the caller's context from a function in macro.c.
138 +int OverlayRoutineFromProg(Program *prog, int nArgs, int removeArgs)
140 + Symbol sym;
142 + sym.type = MACRO_FUNCTION_SYM;
143 + sym.name = "<overlaid function>";
144 + sym.value.val.str.rep = (char *)prog;
145 + sym.next = NULL;
147 + return OverlayRoutineFromSymbol(&sym, nArgs, removeArgs);
151 ** This should never be executed, returnVal checks for the presence of this
152 ** instruction at the PC to decide whether to push the function's return
153 ** value, then skips over it without executing.
155 static int fetchRetVal(void)
156 diff --quilt old/source/interpret.h new/source/interpret.h
157 --- old/source/interpret.h
158 +++ new/source/interpret.h
159 @@ -168,10 +168,14 @@ void FillLoopAddrs(Inst *breakAddr, Inst
160 int ExecuteMacro(WindowInfo *window, Program *prog, int nArgs, DataValue *args,
161 DataValue *result, RestartData **continuation, char **msg);
162 int ContinueMacro(RestartData *continuation, DataValue *result, char **msg);
163 void RunMacroAsSubrCall(Program *prog);
164 void PreemptMacro(void);
166 +int OverlayRoutineFromProg(Program *prog, int nArgs, int removeArgs);
167 +int OverlayRoutineFromSymbol(Symbol *sym, int nArgs, int removeArgs);
169 char *AllocString(int length);
170 char *AllocStringNCpy(const char *s, int length);
171 char *AllocStringCpy(const char *s);
172 char *AllocStringOfNumber(long val);
173 int AllocNString(NString *string, int length);
174 diff --quilt old/source/macro.c new/source/macro.c
175 --- old/source/macro.c
176 +++ new/source/macro.c
177 @@ -414,10 +414,12 @@ static int getStyleByNameMS(WindowInfo *
178 DataValue *result, char **errMsg);
179 static int getStyleAtPosMS(WindowInfo *window, DataValue *argList, int nArgs,
180 DataValue *result, char **errMsg);
181 static int filenameDialogMS(WindowInfo* window, DataValue* argList, int nArgs,
182 DataValue* result, char** errMsg);
183 +static int callMS(WindowInfo *window, DataValue *argList,
184 + int nArgs, DataValue *result, char **errMsg);
186 /* Built-in subroutines and variables for the macro language */
187 static const BuiltInSubrName MacroSubrs[] = {
188 { "length", lengthMS },
189 { "get_range", getRangeMS },
190 @@ -473,10 +475,11 @@ static const BuiltInSubrName MacroSubrs[
191 { "get_pattern_by_name", getPatternByNameMS },
192 { "get_pattern_at_pos", getPatternAtPosMS },
193 { "get_style_by_name", getStyleByNameMS },
194 { "get_style_at_pos", getStyleAtPosMS },
195 { "filename_dialog", filenameDialogMS },
196 + { "call", callMS },
197 { NULL, NULL } /* sentinel */
200 static const BuiltInSubrName SpecialVars[] = {
201 { "$cursor", cursorMV },
202 @@ -3495,10 +3498,35 @@ static int filenameDialogMS(WindowInfo*
205 return True;
209 + * call(fnname, arg, ...)
210 + */
211 +static int callMS(WindowInfo *window, DataValue *argList,
212 + int nArgs, DataValue *result, char **errMsg)
214 + char stringStorage[TYPE_INT_STR_SIZE(int)];
215 + Symbol *sym;
216 + char *fnname;
218 + if (nArgs < 1) {
219 + *errMsg = "subroutine %s called without arguments";
220 + return False;
222 + if (!readStringArg(argList[0], &fnname, stringStorage, errMsg)) {
223 + return False;
225 + sym = LookupSymbol(fnname);
226 + if (!sym) {
227 + *errMsg = "subroutine name invalid";
228 + return False;
230 + return OverlayRoutineFromSymbol(sym, nArgs, 1);
233 /* T Balinski */
234 static int listDialogMS(WindowInfo *window, DataValue *argList, int nArgs,
235 DataValue *result, char **errMsg)
237 macroCmdInfo *cmdData;