final step to context based macro interpreter
[nedit-bw.git] / handle-error-in-RunMacroAsSubrCall.patch
blob09f2efeecd47550cd5f3866df2b20a5868ae1462
1 ---
3 source/interpret.c | 118 ++++++++++++++++++++++++++++++++++-------------------
4 source/interpret.h | 2
5 source/macro.c | 11 ++++
6 3 files changed, 87 insertions(+), 44 deletions(-)
8 diff --quilt old/source/macro.c new/source/macro.c
9 --- old/source/macro.c
10 +++ new/source/macro.c
11 @@ -1064,8 +1064,15 @@ static void runMacro(WindowInfo *window,
12 instead of starting a new one, so we don't have to keep a separate
13 context, and the macros will serialize themselves automatically */
14 if (window->macroCmdData != NULL) {
15 - RunMacroAsSubrCall(prog);
16 - return;
17 + macroCmdInfo *cmdData = window->macroCmdData;
18 + stat = RunMacroAsSubrCall(cmdData->context, prog, &errMsg);
19 + if (stat == MACRO_ERROR) {
20 + finishMacroCmdExecution(window);
21 + FreeProgram(prog);
22 + DialogF(DF_ERR, window->shell, 1, "Macro Error",
23 + "Error executing macro: %s", "OK", errMsg);
24 + }
25 + return;
28 /* put up a watch cursor over the waiting window */
29 diff --quilt old/source/interpret.c new/source/interpret.c
30 --- old/source/interpret.c
31 +++ new/source/interpret.c
32 @@ -512,19 +512,34 @@ void FillLoopAddrs(Inst *breakAddr, Inst
34 ** helper function to setup the next frame
36 -static void setupFrame(DataValue **frameP, DataValue **stackP,
37 - Inst **pc, Program *prog,
38 +static int setupFrame(RestartData *context, Program *prog,
39 int nArgs, DataValue *args, DataValue argArray,
40 const char *name)
42 static DataValue noValue = {NO_TAG, {0}};
43 - int i;
44 + int i, totalPushs = 7;
45 Symbol *s;
47 + /*
48 + ** we push only if we have room for the whole frame, so pre-calc the
49 + ** needed space and check for the room
50 + */
51 + if (nArgs >= 0) {
52 + totalPushs += nArgs;
53 + }
54 + for (s = prog->localSymList; s != NULL; s = s->next) {
55 + totalPushs++;
56 + }
58 + /* !OK_TO_PUSH(totalPushs) */
59 + if (!((context->stackP + totalPushs) <= &context->stack[STACK_SIZE])) {
60 + return execError(StackOverflowMsg, "");
61 + }
63 /* Push arguments and caller information onto the stack */
64 if (nArgs >= 0) {
65 for (i = 0; i < nArgs; i++) {
66 - *((*stackP)++) = args[i];
67 + *(context->stackP++) = args[i];
70 else {
71 @@ -535,48 +550,50 @@ static void setupFrame(DataValue **frame
74 /* cached arg array */
75 - *((*stackP)++) = argArray;
76 + *(context->stackP++) = argArray;
78 /* prog to free, if requested */
79 - (*stackP)->tag = NO_TAG;
80 - (*stackP)->val.prog = prog;
81 - (*stackP)++;
82 + context->stackP->tag = NO_TAG;
83 + context->stackP->val.prog = prog;
84 + context->stackP++;
86 /* return PC */
87 - (*stackP)->tag = NO_TAG;
88 - (*stackP)->val.inst = *pc;
89 - (*stackP)++;
90 + context->stackP->tag = NO_TAG;
91 + context->stackP->val.inst = context->pc;
92 + context->stackP++;
94 /* old FrameP */
95 - (*stackP)->tag = NO_TAG;
96 - (*stackP)->val.dataval = *frameP;
97 - (*stackP)++;
98 + context->stackP->tag = NO_TAG;
99 + context->stackP->val.dataval = context->frameP;
100 + context->stackP++;
102 /* symbol table */
103 - (*stackP)->tag = NO_TAG;
104 - (*stackP)->val.sym = prog->localSymList;
105 - (*stackP)++;
106 + context->stackP->tag = NO_TAG;
107 + context->stackP->val.sym = prog->localSymList;
108 + context->stackP++;
110 /* macro name */
111 - (*stackP)->tag = STRING_TAG;
112 - (*stackP)->val.str.rep = name;
113 - (*stackP)->val.str.len = strlen(name);
114 - (*stackP)++;
115 + context->stackP->tag = STRING_TAG;
116 + context->stackP->val.str.rep = name;
117 + context->stackP->val.str.len = strlen(name);
118 + context->stackP++;
120 /* nArgs */
121 - (*stackP)->tag = INT_TAG;
122 - (*stackP)->val.n = nArgs;
123 - (*stackP)++;
124 + context->stackP->tag = INT_TAG;
125 + context->stackP->val.n = nArgs;
126 + context->stackP++;
128 - *frameP = *stackP;
129 + context->frameP = context->stackP;
131 /* Initialize and make room on the stack for local variables */
132 for (s = prog->localSymList; s != NULL; s = s->next) {
133 - FP_GET_SYM_VAL(*frameP, s) = noValue;
134 - (*stackP)++;
135 + FP_GET_SYM_VAL(context->frameP, s) = noValue;
136 + context->stackP++;
139 - *pc = prog->code;
140 + context->pc = prog->code;
142 + return STAT_OK;
145 static Inst *rewindFrame(DataValue **frameP, DataValue **stackP)
146 @@ -599,10 +616,10 @@ static Inst *rewindFrame(DataValue **fra
147 return newPC;
150 -static void rewindStack(Inst *pc, DataValue *frameP, DataValue *stackP)
151 +static void rewindStack(RestartData *context)
153 - while (pc) {
154 - pc = rewindFrame(&frameP, &stackP);
155 + while (context->pc) {
156 + context->pc = rewindFrame(&context->frameP, &context->stackP);
160 @@ -618,9 +635,8 @@ int ExecuteMacro(WindowInfo *window, Pro
162 RestartData *context;
163 static DataValue argArray = {NO_TAG, {0}};
164 - Symbol *s;
165 - int i;
166 int haveNamedArgs;
167 + int status;
169 haveNamedArgs = (nArgs < 0);
170 if (haveNamedArgs) {
171 @@ -642,10 +658,15 @@ int ExecuteMacro(WindowInfo *window, Pro
172 context->pc = NULL;
173 /* prog will be freed by cller, but by stack also, so inc refcount */
174 prog->refcount++;
175 - setupFrame(&context->frameP, &context->stackP, &context->pc,
176 - prog, nArgs, args, argArray,
177 + status = setupFrame(context, prog, nArgs, args, argArray,
178 prog->name ? prog->name : "<exec-macro>");
180 + if (status == STAT_ERROR) {
181 + *msg = ErrMsg;
182 + FreeRestartData(context);
183 + return MACRO_ERROR;
186 /* Begin execution, return on error or preemption */
187 return ContinueMacro(context, result, msg);
189 @@ -732,17 +753,29 @@ int ContinueMacro(RestartData *continuat
190 ** separate contexts, and serializes processing of the two macros without
191 ** additional work.
193 -void RunMacroAsSubrCall(Program *prog)
194 +int RunMacroAsSubrCall(RestartData *context, Program *prog, char **msg)
196 static DataValue noValue = {NO_TAG, {0}};
197 + int status;
199 - setupFrame(&FrameP, &StackP, &PC, prog, 0, NULL, noValue,
200 + status = setupFrame(context, prog, 0, NULL, noValue,
201 prog->name ? prog->name : "<run-macro>");
203 + if (status == STAT_ERROR) {
204 + *msg = ErrMsg;
205 + FreeRestartData(context);
206 + return MACRO_ERROR;
209 + /* we could invent a MACRO_READY_TO_GO, but the error case is the only
210 + ** important thing here, so stick at MACRO_DONE
211 + */
212 + return MACRO_DONE;
215 void FreeRestartData(RestartData *context)
217 - rewindStack(context->pc, context->frameP, context->stackP);
218 + rewindStack(context);
219 XtFree((char *)context->stack);
220 XtFree((char *)context);
222 @@ -2760,12 +2793,15 @@ static int callSubroutineFromSymbol(Symb
223 ** values which are already there.
225 if (sym->type == MACRO_FUNCTION_SYM) {
226 + RestartData context;
227 + int status;
228 prog = sym->value.val.prog;
229 prog->refcount++;
230 /* -nArgs means 'arguments are on stack' */
231 - setupFrame(&FrameP, &StackP, &PC, prog, -nArgs, NULL, argArray,
232 - sym->name);
233 - return STAT_OK;
234 + saveContext(&context);
235 + status = setupFrame(&context, prog, -nArgs, NULL, argArray, sym->name);
236 + restoreContext(&context);
237 + return status;
241 diff --quilt old/source/interpret.h new/source/interpret.h
242 --- old/source/interpret.h
243 +++ new/source/interpret.h
244 @@ -180,7 +180,7 @@ void FillLoopAddrs(Inst *breakAddr, Inst
245 int ExecuteMacro(WindowInfo *window, Program *prog, int nArgs, DataValue *args,
246 DataValue *result, RestartData **continuation, char **msg);
247 int ContinueMacro(RestartData *continuation, DataValue *result, char **msg);
248 -void RunMacroAsSubrCall(Program *prog);
249 +int RunMacroAsSubrCall(RestartData *context, Program *prog, char **msg);
250 void PreemptMacro(void);
252 int OverlayRoutineFromProg(Program *prog, int nArgs, int removeArgs);