Program memory leaks
[nedit-bw.git] / parse-define.patch
blobad18eb14f7d6f6227eddbe3bbdc69e815127856d
1 From 843e5c23eb9f637981697621276d5b4aed5a8b0e Mon Sep 17 00:00:00 2001
2 From: Bert Wesarg <bert.wesarg@googlemail.com>
3 Date: Tue, 2 Sep 2008 10:36:47 +0200
4 Subject: [PATCH v3] parse "define" in the parser
6 This removes the ugly parsing of the "define" keyword. It solves this by
7 saving and restoring the state of the program accumulation. This solves
8 a long standing problam, that parts between "define" definition aren't
9 in the same scope, i.e. this works now:
11 a = 0
13 define t {
16 t_print(a "\n")
18 ChangeLog:
19 v3:
20 * add missing OP_RETURN_NO_VAL after define
21 v2:
22 * make the define statement special, prevents recursion of the define
23 keyword
24 * need to PromoteToGlobal() the new function symbol
25 * prevent overriding of non macro functions
27 ---
29 source/interpret.c | 24 +++++---
30 source/interpret.h | 16 ++++-
31 source/macro.c | 147 +++++++++------------------------------------------
32 source/nedit.c | 2
33 source/parse.h | 2
34 source/parse.y | 78 ++++++++++++++++++++++-----
35 source/smartIndent.c | 8 +-
36 source/userCmds.c | 4 -
37 8 files changed, 131 insertions(+), 150 deletions(-)
39 diff --quilt old/source/interpret.c new/source/interpret.c
40 --- old/source/interpret.c
41 +++ new/source/interpret.c
42 @@ -60,14 +60,11 @@ static const char CVSID[] = "$Id: interp
44 #ifdef HAVE_DEBUG_H
45 #include "../debug.h"
46 #endif
48 -#define PROGRAM_SIZE 4096 /* Maximum program size */
49 #define MAX_ERR_MSG_LEN 256 /* Max. length for error messages */
50 -#define LOOP_STACK_SIZE 200 /* (Approx.) Number of break/continue stmts
51 - allowed per program */
52 #define INSTRUCTION_LIMIT 100 /* Number of instructions the interpreter is
53 allowed to execute before preempting and
54 returning to allow other things to run */
56 /* Temporary markers placed in a branch address location to designate
57 @@ -237,42 +234,55 @@ void InitMacroGlobals(void)
60 ** Start collecting instructions for a program. Clears the program
61 ** and the symbol table.
63 -void BeginCreatingProgram(void)
64 -{
65 +void BeginCreatingProgram(AccumulatorData *acc)
67 + /* save state */
68 + acc->localSymList = LocalSymList;
69 + memcpy(acc->prog, Prog, sizeof(Inst) * PROGRAM_SIZE);
70 + acc->progP = ProgP;
71 + memcpy(acc->loopStack, LoopStack, sizeof(Inst) * LOOP_STACK_SIZE);
72 + acc->loopStackPtr = LoopStackPtr;
74 LocalSymList = NULL;
75 ProgP = Prog;
76 LoopStackPtr = LoopStack;
80 ** Finish up the program under construction, and return it (code and
81 ** symbol table) as a package that ExecuteMacro can execute. This
82 ** program must be freed with FreeProgram.
84 -Program *FinishCreatingProgram(void)
85 +Program *FinishCreatingProgram(AccumulatorData *acc)
87 Program *newProg;
88 int progLen, fpOffset = 0;
89 Symbol *s;
91 newProg = (Program *)XtMalloc(sizeof(Program));
92 progLen = ((char *)ProgP) - ((char *)Prog);
93 newProg->code = (Inst *)XtMalloc(progLen);
94 memcpy(newProg->code, Prog, progLen);
95 newProg->localSymList = LocalSymList;
96 - LocalSymList = NULL;
98 /* Local variables' values are stored on the stack. Here we assign
99 frame pointer offsets to them. */
100 for (s = newProg->localSymList; s != NULL; s = s->next)
101 s->value.val.n = fpOffset++;
103 DISASM(newProg->code, ProgP - Prog);
105 + /* restore state */
106 + LocalSymList = acc->localSymList;
107 + memcpy(Prog, acc->prog, sizeof(Inst) * PROGRAM_SIZE);
108 + ProgP = acc->progP;
109 + memcpy(LoopStack, acc->loopStack, sizeof(Inst) * LOOP_STACK_SIZE);
110 + LoopStackPtr = acc->loopStackPtr;
112 return newProg;
115 void FreeProgram(Program *prog)
117 diff --quilt old/source/interpret.h new/source/interpret.h
118 --- old/source/interpret.h
119 +++ new/source/interpret.h
120 @@ -35,10 +35,13 @@
121 #define STACK_SIZE 1024 /* Maximum stack size */
122 #define MAX_SYM_LEN 100 /* Max. symbol name length */
123 #define MACRO_EVENT_MARKER 2 /* Special value for the send_event field of
124 events passed to action routines. Tells
125 them that they were called from a macro */
126 +#define PROGRAM_SIZE 4096 /* Maximum program size */
127 +#define LOOP_STACK_SIZE 256 /* (Approx.) Number of break/continue stmts
128 + allowed per program */
130 enum symTypes {CONST_SYM, GLOBAL_SYM, LOCAL_SYM, ARG_SYM, PROC_VALUE_SYM,
131 C_FUNCTION_SYM, MACRO_FUNCTION_SYM, ACTION_ROUTINE_SYM};
133 enum operations {
134 @@ -114,10 +117,19 @@ typedef struct {
135 Inst *pc;
136 WindowInfo *runWindow;
137 WindowInfo *focusWindow;
138 } RestartData;
140 +/* state of the accumulator (aka compiler) */
141 +typedef struct AccumulatorDataTag {
142 + Symbol *localSymList;
143 + Inst prog[PROGRAM_SIZE];
144 + Inst *progP;
145 + Inst *loopStack[LOOP_STACK_SIZE];
146 + Inst **loopStackPtr;
147 +} AccumulatorData;
149 void InitMacroGlobals(void);
151 SparseArrayEntry *arrayIterateFirst(DataValue *theArray);
152 SparseArrayEntry *arrayIterateNext(SparseArrayEntry *iterator);
153 SparseArrayEntry *ArrayNew(void);
154 @@ -128,22 +140,22 @@ unsigned ArraySize(DataValue *theArray);
155 Boolean ArrayGet(DataValue* theArray, char* keyStr, DataValue* theValue);
156 int ArrayCopy(DataValue *dstArray, DataValue *srcArray);
158 /* Routines for creating a program, (accumulated beginning with
159 BeginCreatingProgram and returned via FinishCreatingProgram) */
160 -void BeginCreatingProgram(void);
161 +void BeginCreatingProgram(AccumulatorData *acc);
162 int AddOp(int op, char **msg);
163 int AddSym(Symbol *sym, char **msg);
164 int AddImmediate(int value, char **msg);
165 int AddBranchOffset(Inst *to, char **msg);
166 Inst *GetPC(void);
167 Symbol *InstallIteratorSymbol(void);
168 Symbol *LookupStringConstSymbol(const char *value);
169 Symbol *InstallStringConstSymbol(const char *str);
170 Symbol *LookupSymbol(const char *name);
171 Symbol *InstallSymbol(const char *name, enum symTypes type, DataValue value);
172 -Program *FinishCreatingProgram(void);
173 +Program *FinishCreatingProgram(AccumulatorData *acc);
174 void SwapCode(Inst *start, Inst *boundary, Inst *end);
175 void StartLoopAddrList(void);
176 int AddBreakAddr(Inst *addr);
177 int AddContinueAddr(Inst *addr);
178 void FillLoopAddrs(Inst *breakAddr, Inst *continueAddr);
179 diff --quilt old/source/macro.c new/source/macro.c
180 --- old/source/macro.c
181 +++ new/source/macro.c
182 @@ -754,11 +754,11 @@ void Replay(WindowInfo *window)
183 if (ReplayMacro != NULL &&
184 ReplayMacro[0] != 0 &&
185 window->macroCmdData == NULL) {
186 /* Parse the replay macro (it's stored in text form) and compile it into
187 an executable program "prog" */
188 - prog = ParseMacro(ReplayMacro, &errMsg, &stoppedAt);
189 + prog = ParseMacro(ReplayMacro, &errMsg, &stoppedAt, False);
190 if (prog == NULL) {
191 fprintf(stderr,
192 "NEdit internal error, learn/replay macro syntax error: %s\n",
193 errMsg);
194 return;
195 @@ -849,133 +849,40 @@ int CheckMacroString(Widget dialogParent
196 ** returns a pointer to the error location in the string.
198 static int readCheckMacroString(Widget dialogParent, char *string,
199 WindowInfo *runWindow, const char *errIn, char **errPos)
201 - char *stoppedAt, *inPtr, *namePtr, *errMsg;
202 - char subrName[MAX_SYM_LEN];
203 + char *stoppedAt, *errMsg;
204 Program *prog;
205 - Symbol *sym;
206 - DataValue subrPtr;
207 - Stack* progStack = (Stack*) XtMalloc(sizeof(Stack));
208 - progStack->top = NULL;
209 - progStack->size = 0;
211 - inPtr = string;
212 - while (*inPtr != '\0') {
214 - /* skip over white space and comments */
215 - while (*inPtr==' ' || *inPtr=='\t' || *inPtr=='\n'|| *inPtr=='#') {
216 - if (*inPtr == '#')
217 - while (*inPtr != '\n' && *inPtr != '\0') inPtr++;
218 - else
219 - inPtr++;
221 - if (*inPtr == '\0')
222 - break;
224 - /* look for define keyword, and compile and store defined routines */
225 - if (!strncmp(inPtr, "define", 6) && (inPtr[6]==' ' || inPtr[6]=='\t')) {
226 - inPtr += 6;
227 - inPtr += strspn(inPtr, " \t\n");
228 - namePtr = subrName;
229 - while ((namePtr < &subrName[MAX_SYM_LEN - 1])
230 - && (isalnum((unsigned char)*inPtr) || *inPtr == '_')) {
231 - *namePtr++ = *inPtr++;
233 - *namePtr = '\0';
234 - if (isalnum((unsigned char)*inPtr) || *inPtr == '_') {
235 - return ParseError(dialogParent, string, inPtr, errIn,
236 - "subroutine name too long");
238 - inPtr += strspn(inPtr, " \t\n");
239 - if (*inPtr != '{') {
240 - if (errPos != NULL) *errPos = stoppedAt;
241 - return ParseError(dialogParent, string, inPtr,
242 - errIn, "expected '{'");
244 - prog = ParseMacro(inPtr, &errMsg, &stoppedAt);
245 - if (prog == NULL) {
246 - if (errPos != NULL) *errPos = stoppedAt;
247 - return ParseError(dialogParent, string, stoppedAt,
248 - errIn, errMsg);
250 - if (runWindow != NULL) {
251 - sym = LookupSymbol(subrName);
252 - if (sym == NULL) {
253 - subrPtr.val.prog = prog;
254 - subrPtr.tag = NO_TAG;
255 - sym = InstallSymbol(subrName, MACRO_FUNCTION_SYM, subrPtr);
256 - } else {
257 - if (sym->type == MACRO_FUNCTION_SYM)
258 - /* its unsafe to free the old program,
259 - ** maybe it is currently in use
260 - */
261 - /* FreeProgram(sym->value.val.prog) */;
262 - else
263 - sym->type = MACRO_FUNCTION_SYM;
264 - sym->value.val.prog = prog;
267 - inPtr = stoppedAt;
269 - /* Parse and execute immediate (outside of any define) macro commands
270 - and WAIT for them to finish executing before proceeding. Note that
271 - the code below is not perfect. If you interleave code blocks with
272 - definitions in a file which is loaded from another macro file, it
273 - will probably run the code blocks in reverse order! */
274 - } else {
275 - prog = ParseMacro(inPtr, &errMsg, &stoppedAt);
276 - if (prog == NULL) {
277 - if (errPos != NULL) {
278 - *errPos = stoppedAt;
281 - return ParseError(dialogParent, string, stoppedAt,
282 - errIn, errMsg);
285 - if (runWindow != NULL) {
286 - XEvent nextEvent;
287 - if (runWindow->macroCmdData == NULL) {
288 - /* runMacro() is responsable for freeing prog */
289 - runMacro(runWindow, prog);
290 - while (runWindow->macroCmdData != NULL) {
291 - XtAppNextEvent(XtWidgetToApplicationContext(
292 - runWindow->shell), &nextEvent);
293 - ServerDispatchEvent(&nextEvent);
295 - } else {
296 - /* If we come here this means that the string was parsed
297 - from within another macro via load_macro_file(). In
298 - this case, plain code segments outside of define
299 - blocks are rolled into one Program each and put on
300 - the stack. At the end, the stack is unrolled, so the
301 - plain Programs would be executed in the wrong order.
303 - So we don't hand the Programs over to the interpreter
304 - just yet (via RunMacroAsSubrCall()), but put it on a
305 - stack of our own, reversing order once again. */
306 - Push(progStack, (void*) prog);
309 - inPtr = stoppedAt;
312 - /* we are in 'parse only' mode, therefore release the prog */
313 - if (runWindow == NULL) {
314 - FreeProgram(prog);
315 + prog = ParseMacro(string, &errMsg, &stoppedAt, True);
316 + if (prog == NULL) {
317 + if (errPos != NULL) {
318 + *errPos = stoppedAt;
320 + return ParseError(dialogParent, string, stoppedAt, errIn, errMsg);
323 - /* Unroll reversal stack for macros loaded from macros. */
324 - while (NULL != (prog = (Program*) Pop(progStack))) {
325 - RunMacroAsSubrCall(prog);
326 + if (runWindow != NULL) {
327 + XEvent nextEvent;
328 + if (runWindow->macroCmdData == NULL) {
329 + /* runMacro() is responsable for freeing prog */
330 + runMacro(runWindow, prog);
331 + while (runWindow->macroCmdData != NULL) {
332 + XtAppNextEvent(XtWidgetToApplicationContext(runWindow->shell),
333 + &nextEvent);
334 + ServerDispatchEvent(&nextEvent);
337 + else {
338 + RunMacroAsSubrCall(prog);
341 + else {
342 + /* we are in 'parse only' mode, therefore release the prog */
343 + FreeProgram(prog);
346 - /* This stack is empty, so just free it without checking the members. */
347 - XtFree((char*) progStack);
349 return True;
353 @@ -1231,11 +1138,11 @@ void DoMacro(WindowInfo *window, const c
354 strncpy(tMacro, macro, macroLen);
355 tMacro[macroLen] = '\n';
356 tMacro[macroLen+1] = '\0';
358 /* Parse the macro and report errors if it fails */
359 - prog = ParseMacro(tMacro, &errMsg, &stoppedAt);
360 + prog = ParseMacro(tMacro, &errMsg, &stoppedAt, False);
361 if (prog == NULL) {
362 ParseError(window->shell, tMacro, stoppedAt, errInName, errMsg);
363 XtFree(tMacro);
364 return;
366 @@ -1495,11 +1402,11 @@ selEnd += $text_length - startLength\n}\
367 sprintf(loopedCmd, loopMacro, command);
368 else
369 sprintf(loopedCmd, loopMacro, how, command);
371 /* Parse the resulting macro into an executable program "prog" */
372 - prog = ParseMacro(loopedCmd, &errMsg, &stoppedAt);
373 + prog = ParseMacro(loopedCmd, &errMsg, &stoppedAt, False);
374 if (prog == NULL) {
375 fprintf(stderr, "NEdit internal error, repeat macro syntax wrong: %s\n",
376 errMsg);
377 return;
379 diff --quilt old/source/nedit.c new/source/nedit.c
380 --- old/source/nedit.c
381 +++ new/source/nedit.c
382 @@ -830,11 +830,11 @@ static int checkDoMacroArg(const char *m
383 strncpy(tMacro, macro, macroLen);
384 tMacro[macroLen] = '\n';
385 tMacro[macroLen+1] = '\0';
387 /* Do a test parse */
388 - prog = ParseMacro(tMacro, &errMsg, &stoppedAt);
389 + prog = ParseMacro(tMacro, &errMsg, &stoppedAt, False);
390 XtFree(tMacro);
391 if (prog == NULL) {
392 ParseError(NULL, tMacro, stoppedAt, "argument to -do", errMsg);
393 return False;
395 diff --quilt old/source/parse.h new/source/parse.h
396 --- old/source/parse.h
397 +++ new/source/parse.h
398 @@ -28,8 +28,8 @@
399 #ifndef NEDIT_PARSE_H_INCLUDED
400 #define NEDIT_PARSE_H_INCLUDED
402 #include "interpret.h"
404 -Program *ParseMacro(char *expr, char **msg, char **stoppedAt);
405 +Program *ParseMacro(char *expr, char **msg, char **stoppedAt, int allowDefine);
407 #endif /* NEDIT_PARSE_H_INCLUDED */
408 diff --quilt old/source/parse.y new/source/parse.y
409 --- old/source/parse.y
410 +++ new/source/parse.y
411 @@ -73,20 +73,24 @@ static Symbol *matchesActionRoutine(char
412 static char *ErrMsg;
413 static char *InPtr;
414 extern Inst *LoopStack[]; /* addresses of break, cont stmts */
415 extern Inst **LoopStackPtr; /* to fill at the end of a loop */
417 +static int AllowDefine;
421 %union {
422 Symbol *sym;
423 Inst *inst;
424 int nArgs;
425 + AccumulatorData *acc;
427 %token <sym> NUMBER STRING SYMBOL
428 %token DELETE ARG_LOOKUP
429 %token IF WHILE ELSE FOR BREAK CONTINUE RETURN
430 +%token <acc> DEFINE
431 %type <nArgs> arglist
432 %type <inst> cond comastmts for while else and or arrayexpr
433 %type <sym> evalsym
435 %nonassoc IF_NO_ELSE
436 @@ -109,11 +113,11 @@ extern Inst **LoopStackPtr; /* to fill
437 %nonassoc '['
438 %nonassoc '('
440 %% /* Rules */
442 -program: blank stmts {
443 +program: blank allstmts {
444 ADD_OP(OP_RETURN_NO_VAL); return 0;
446 | blank '{' blank stmts '}' {
447 ADD_OP(OP_RETURN_NO_VAL); return 0;
449 @@ -122,17 +126,63 @@ program: blank stmts {
451 | error {
452 return 1;
455 -block: '{' blank stmts '}' blank
456 +blockwb: '{' blank stmts '}' blank
457 | '{' blank '}' blank
459 +block: blockwb
460 | stmt
462 stmts: stmt
463 | stmts stmt
465 +allstmts: allstmt
466 + | allstmts allstmt
468 +allstmt: stmt
469 + | define
471 +define: DEFINE {
472 + /* bail out early, in case of unallowed "define" */
473 + if (!AllowDefine) {
474 + yyerror("macro definitions not allowed"); YYERROR;
477 + blank SYMBOL {
478 + $1 = (AccumulatorData *)XtMalloc(sizeof(AccumulatorData));
479 + /* we can't really be sure, that we not overwrite any
480 + ** wrong symbol
481 + **
482 + ** we should only overwrite installed MACRO_FUNCTION_SYM
483 + ** and this is questionable.
484 + */
485 + if ($4->type == MACRO_FUNCTION_SYM) {
486 + /* its unsafe to free the old program,
487 + ** maybe it is currently in use
488 + */
489 + /* FreeProgram($4->value.val.prog) */;
491 + else if ($4->type == LOCAL_SYM ||
492 + $4->type == GLOBAL_SYM) {
493 + /* newly created sym, or we overwrite a local sym */;
494 + } else {
495 + yyerror("try to override built-in subroutine"); YYERROR;
497 + $4 = PromoteToGlobal($4);
498 + BeginCreatingProgram($1);
500 + blank blockwb {
501 + ADD_OP(OP_RETURN_NO_VAL);
502 + Program *prog = FinishCreatingProgram($1);
503 + XtFree((char *)$1);
504 + $4->type = MACRO_FUNCTION_SYM;
505 + $4->value.tag = NO_TAG;
506 + $4->value.val.prog = prog;
509 stmt: simpstmt '\n' blank
510 | IF '(' cond ')' blank block %prec IF_NO_ELSE {
511 SET_BR_OFF($3, GetPC());
513 | IF '(' cond ')' blank block else blank block %prec ELSE {
514 @@ -472,29 +522,35 @@ blank: /* nothing */
515 ** executed using ExecuteProgram. Returns program on success, or NULL
516 ** on failure. If the command failed, the error message is returned
517 ** as a pointer to a static string in msg, and the length of the string up
518 ** to where parsing failed in stoppedAt.
520 -Program *ParseMacro(char *expr, char **msg, char **stoppedAt)
521 +Program *ParseMacro(char *expr, char **msg, char **stoppedAt, int allowDefine)
523 Program *prog;
524 + AccumulatorData *acc = (AccumulatorData *)XtMalloc(sizeof(*acc));
526 + BeginCreatingProgram(acc);
528 - BeginCreatingProgram();
529 + /* whether we allow the "define" keyword */
530 + AllowDefine = allowDefine;
532 /* call yyparse to parse the string and check for success. If the parse
533 failed, return the error message and string index (the grammar aborts
534 parsing at the first error) */
535 InPtr = expr;
536 if (yyparse()) {
537 *msg = ErrMsg;
538 *stoppedAt = InPtr;
539 - FreeProgram(FinishCreatingProgram());
540 + FreeProgram(FinishCreatingProgram(acc));
541 + XtFree((char *)acc);
542 return NULL;
545 /* get the newly created program */
546 - prog = FinishCreatingProgram();
547 + prog = FinishCreatingProgram(acc);
548 + XtFree((char *)acc);
550 /* parse succeeded */
551 *msg = "";
552 *stoppedAt = InPtr;
553 return prog;
554 @@ -548,13 +604,12 @@ static int yylex(void)
555 if ((yylval.sym=LookupSymbol(name)) == NULL)
556 yylval.sym = InstallSymbol(name, CONST_SYM, value);
557 return NUMBER;
560 - /* process symbol tokens. "define" is a special case not handled
561 - by this parser, considered end of input. Another special case
562 - is action routine names which are allowed to contain '-' despite
563 + /* process symbol tokens. A special case are action
564 + routine names which are allowed to contain '-' despite
565 the ambiguity, handled in matchesActionRoutine. */
566 if (isalpha((unsigned char)*InPtr) || *InPtr == '$') {
567 if ((s=matchesActionRoutine(&InPtr)) == NULL) {
568 char symName[MAX_SYM_LEN+1], *p = symName;
569 *p++ = *InPtr++;
570 @@ -573,14 +628,11 @@ static int yylex(void)
571 if (!strcmp(symName, "continue")) return CONTINUE;
572 if (!strcmp(symName, "return")) return RETURN;
573 if (!strcmp(symName, "in")) return IN;
574 if (!strcmp(symName, "$args")) return ARG_LOOKUP;
575 if (!strcmp(symName, "delete") && follow_non_whitespace('(', SYMBOL, DELETE) == DELETE) return DELETE;
576 - if (!strcmp(symName, "define")) {
577 - InPtr -= 6;
578 - return 0;
580 + if (!strcmp(symName, "define")) return DEFINE;
581 if ((s=LookupSymbol(symName)) == NULL) {
582 s = InstallSymbol(symName, symName[0]=='$' ?
583 (((symName[1] > '0' && symName[1] <= '9') && symName[2] == 0) ?
584 ARG_SYM : GLOBAL_SYM) : LOCAL_SYM, value);
585 s->value.tag = NO_TAG;
586 diff --quilt old/source/smartIndent.c new/source/smartIndent.c
587 --- old/source/smartIndent.c
588 +++ new/source/smartIndent.c
589 @@ -745,21 +745,21 @@ void BeginSmartIndent(WindowInfo *window
590 /* Compile the newline and modify macros and attach them to the window */
591 winData = (windowSmartIndentData *)XtMalloc(sizeof(windowSmartIndentData));
592 winData->inNewLineMacro = 0;
593 winData->inModMacro = 0;
594 winData->newlineMacro = ParseMacro(indentMacros->newlineMacro, &errMsg,
595 - &stoppedAt);
596 + &stoppedAt, False);
597 if (winData->newlineMacro == NULL) {
598 ParseError(window->shell, indentMacros->newlineMacro, stoppedAt,
599 "newline macro", errMsg);
600 return;
602 if (indentMacros->modMacro == NULL)
603 winData->modMacro = NULL;
604 else {
605 winData->modMacro = ParseMacro(indentMacros->modMacro, &errMsg,
606 - &stoppedAt);
607 + &stoppedAt, False);
608 if (winData->modMacro == NULL) {
609 ParseError(window->shell, indentMacros->modMacro, stoppedAt,
610 "smart indent modify macro", errMsg);
611 return;
613 @@ -1435,11 +1435,11 @@ static int checkSmartIndentDialogData(vo
614 "Newline macro required", "OK");
615 return False;
618 widgetText = ensureNewline(XmTextGetString(SmartIndentDialog.newlineMacro));
619 - prog = ParseMacro(widgetText, &errMsg, &stoppedAt);
620 + prog = ParseMacro(widgetText, &errMsg, &stoppedAt, False);
621 if (prog == NULL) {
622 ParseError(SmartIndentDialog.shell, widgetText, stoppedAt,
623 "newline macro", errMsg);
624 XmTextSetInsertionPosition(SmartIndentDialog.newlineMacro,
625 stoppedAt - widgetText);
626 @@ -1451,11 +1451,11 @@ static int checkSmartIndentDialogData(vo
627 FreeProgram(prog);
629 /* Test compile the modify macro */
630 if (!TextWidgetIsBlank(SmartIndentDialog.modMacro)) {
631 widgetText = ensureNewline(XmTextGetString(SmartIndentDialog.modMacro));
632 - prog = ParseMacro(widgetText, &errMsg, &stoppedAt);
633 + prog = ParseMacro(widgetText, &errMsg, &stoppedAt, False);
634 if (prog == NULL) {
635 ParseError(SmartIndentDialog.shell, widgetText, stoppedAt,
636 "modify macro", errMsg);
637 XmTextSetInsertionPosition(SmartIndentDialog.modMacro,
638 stoppedAt - widgetText);
639 diff --quilt old/source/userCmds.c new/source/userCmds.c
640 --- old/source/userCmds.c
641 +++ new/source/userCmds.c
642 @@ -2078,11 +2078,11 @@ static int checkMacro(userCmdDialog *ucd
643 static int checkMacroText(char *macro, Widget errorParent, Widget errFocus)
645 Program *prog;
646 char *errMsg, *stoppedAt;
648 - prog = ParseMacro(macro, &errMsg, &stoppedAt);
649 + prog = ParseMacro(macro, &errMsg, &stoppedAt, False);
650 if (prog == NULL) {
651 if (errorParent != NULL) {
652 ParseError(errorParent, macro, stoppedAt, "macro", errMsg);
653 XmTextSetInsertionPosition(errFocus, stoppedAt - macro);
654 XmProcessTraversal(errFocus, XmTRAVERSE_CURRENT);
655 @@ -3017,11 +3017,11 @@ static char *copyMacroToEnd(char **inPtr
656 ParseError(NULL, *inPtr, *inPtr-1, "macro menu item", "expecting '{'");
657 return NULL;
660 /* Parse the input */
661 - prog = ParseMacro(*inPtr, &errMsg, &stoppedAt);
662 + prog = ParseMacro(*inPtr, &errMsg, &stoppedAt, False);
663 if (prog == NULL) {
664 ParseError(NULL, *inPtr, stoppedAt, "macro menu item", errMsg);
665 return NULL;
667 FreeProgram(prog);