1 From: Tony Balinski <ajbj@free.fr>
2 Subject: Provide NEdit Macro stack traces
6 http://sourceforge.net/tracker/index.php?func=detail&aid=970501&group_id=11005&atid=311005
7 [ 970501 ] Provide NEdit Macro stack traces
8 InterpretDebug.diff 2004-06-10 11:51
10 Macro function names are listed when a crash occurs in one of your macros.
11 The usual error message is followed by a list of the NEdit macro functions
12 called before getting there. (It doesn't tell you how the macro was invoked
13 however.) This provides a good clue as to where a macro programming problem
16 Also, debug tracing enhanced to show symbol values in stack traces listed to
17 terminal output: a boon to interpret.c hackers.
19 Try changing the definition
21 #define STACKDUMP(n, x) stackdump(n, x)
25 #define STACKDUMP(n, x) stackdump(n, x + 50)
27 and watching the output of NEdit in an xterm generated while running your
30 (You will need to add -DDEBUG_STACK and -DDEBUG_ASSEMBLY in your compilation
31 flags to enable the debug tracing.)
33 Thanks to Eddy De Greef!
35 InterpretDebug2.diff 2004-06-11 17:13
37 This version passes an extra "name" string to ParseMacro(). This name is
38 used as a "function name" in the stack dumps, when there is no available
39 function symbol name available (usually at the top level of invocation from
40 NEdit's user interface). It allows the user to determine which macro is
41 being invoked or which file is being interpreted when an error occurs.
45 source/interpret.c | 405 +++++++++++++++++++++++++++++++++++++++++---------
46 source/interpret.h | 2
51 source/parse_noyacc.c | 9 -
52 source/smartIndent.c | 20 +-
53 source/userCmds.c | 49 +++---
54 9 files changed, 404 insertions(+), 107 deletions(-)
56 diff --quilt old/source/interpret.c new/source/interpret.c
57 --- old/source/interpret.c
58 +++ new/source/interpret.c
59 @@ -38,7 +38,9 @@ static const char CVSID[] = "$Id: interp
69 @@ -104,7 +106,10 @@ static const char *tagToStr(enum typeTag
71 #if defined(DEBUG_ASSEMBLY) || defined(DEBUG_STACK)
72 #define DEBUG_DISASSEMBLER
73 +static const char *printd(const char *f, ...);
74 +static int outPrintd();
75 static void disasm(Inst *inst, int nInstr);
76 +static void disasmInternal(Inst *inst, int nInstr);
77 #endif /* #if defined(DEBUG_ASSEMBLY) || defined(DEBUG_STACK) */
79 #ifdef DEBUG_ASSEMBLY /* for disassembly */
80 @@ -115,6 +120,7 @@ static void disasm(Inst *inst, int nInst
82 #ifdef DEBUG_STACK /* for run-time instruction and stack trace */
83 static void stackdump(int n, int extra);
84 +static void stackdumpInternal(int n, int extra);
85 #define STACKDUMP(n, x) stackdump(n, x)
86 #define DISASM_RT(i, n) disasm(i, n)
87 #else /* #ifndef DEBUG_STACK */
88 @@ -172,14 +178,18 @@ static int (*OpFns[])() = {
91 /* Stack-> symN-sym0(FP), argArray, nArgs, oldFP, retPC, argN-arg1, next, ... */
92 -#define FP_ARG_ARRAY_CACHE_INDEX (-1)
93 +#define FP_ARG_ARRAY_INDEX (-1)
94 #define FP_ARG_COUNT_INDEX (-2)
95 -#define FP_OLD_FP_INDEX (-3)
96 -#define FP_RET_PC_INDEX (-4)
97 -#define FP_PROG_INDEX (-5)
98 -#define FP_TO_ARGS_DIST (5) /* should be 0 - (above index) */
99 +#define FP_FUNCTION_NAME (-3) /* !! */
100 +#define FP_SYMBOL_TABLE (-4) /* !! */
101 +#define FP_OLD_FP_INDEX (-5)
102 +#define FP_RET_PC_INDEX (-6)
103 +#define FP_PROG_INDEX (-7)
105 +#define FP_TO_ARGS_DIST (0 - FP_PROG_INDEX) /* should be 0 - (above index) */
107 #define FP_GET_ITEM(xFrameP,xIndex) (*(xFrameP + xIndex))
108 -#define FP_GET_ARG_ARRAY_CACHE(xFrameP) (FP_GET_ITEM(xFrameP, FP_ARG_ARRAY_CACHE_INDEX))
109 +#define FP_GET_ARG_ARRAY(xFrameP) (FP_GET_ITEM(xFrameP, FP_ARG_ARRAY_INDEX))
110 #define FP_GET_ARG_COUNT(xFrameP) (FP_GET_ITEM(xFrameP, FP_ARG_COUNT_INDEX).val.n)
111 #define FP_GET_OLD_FP(xFrameP) ((FP_GET_ITEM(xFrameP, FP_OLD_FP_INDEX)).val.dataval)
112 #define FP_GET_RET_PC(xFrameP) ((FP_GET_ITEM(xFrameP, FP_RET_PC_INDEX)).val.inst)
113 @@ -267,6 +277,7 @@ Program *FinishCreatingProgram(Accumulat
114 newProg->code = (Inst *)XtMalloc(progLen);
115 memcpy(newProg->code, Prog, progLen);
116 newProg->localSymList = LocalSymList;
117 + newProg->name = NULL;
118 newProg->refcount = 1;
120 /* Local variables' values are stored on the stack. Here we assign
121 @@ -291,6 +302,7 @@ void FreeProgram(Program *prog)
122 if (--prog->refcount == 0) {
123 freeSymbolTable(prog->localSymList);
124 XtFree((char *)prog->code);
125 + XtFree((char *)prog->name);
126 XtFree((char *)prog);
129 @@ -441,7 +453,8 @@ void FillLoopAddrs(Inst *breakAddr, Inst
130 ** helper function to setup the next frame
132 static void setupFrame(DataValue **frameP, DataValue **stackP,
133 - Inst **pc, Program *prog, int nArgs, DataValue *args)
134 + Inst **pc, Program *prog, int nArgs, DataValue *args,
137 static DataValue noValue = {NO_TAG, {0}};
139 @@ -475,6 +488,17 @@ static void setupFrame(DataValue **frame
140 (*stackP)->val.dataval = *frameP;
144 + (*stackP)->tag = NO_TAG;
145 + (*stackP)->val.sym = prog->localSymList;
149 + (*stackP)->tag = STRING_TAG;
150 + (*stackP)->val.str.rep = name;
151 + (*stackP)->val.str.len = strlen(name);
155 (*stackP)->tag = NO_TAG;
156 (*stackP)->val.n = nArgs;
157 @@ -551,7 +575,7 @@ int ExecuteMacro(WindowInfo *window, Pro
158 /* prog will be freed by cller, but by stack also, so inc refcount */
160 setupFrame(&context->frameP, &context->stackP, &context->pc,
161 - prog, nArgs, args);
162 + prog, nArgs, args, prog->name ? prog->name : "<exec-macro>");
164 /* Begin execution, return on error or preemption */
165 return ContinueMacro(context, result, msg);
166 @@ -627,7 +651,8 @@ int ContinueMacro(RestartData *continuat
168 void RunMacroAsSubrCall(Program *prog)
170 - setupFrame(&FrameP, &StackP, &PC, prog, 0, NULL);
171 + setupFrame(&FrameP, &StackP, &PC, prog, 0, NULL,
172 + prog->name ? prog->name : "<run-macro>");
175 void FreeRestartData(RestartData *context)
176 @@ -1419,7 +1444,7 @@ static int pushArgArray(void)
179 nArgs = FP_GET_ARG_COUNT(FrameP);
180 - resultArray = &FP_GET_ARG_ARRAY_CACHE(FrameP);
181 + resultArray = &FP_GET_ARG_ARRAY(FrameP);
182 if (resultArray->tag != ARRAY_TAG) {
183 resultArray->tag = ARRAY_TAG;
184 resultArray->val.arrayPtr = ArrayNew();
185 @@ -2187,7 +2212,7 @@ static int callSubroutine(void)
186 prog = sym->value.val.prog;
188 /* -nArgs means 'arguments are on stack' */
189 - setupFrame(&FrameP, &StackP, &PC, prog, -nArgs, NULL);
190 + setupFrame(&FrameP, &StackP, &PC, prog, -nArgs, NULL, sym->name);
194 @@ -2713,7 +2738,7 @@ static int arrayRef(void)
198 - STACKDUMP(nDim, 3);
199 + STACKDUMP(nDim+1, 3);
202 errNum = makeArrayKeyFromArgs(nDim, &keyString, 0);
203 @@ -2764,7 +2789,7 @@ static int arrayAssign(void)
207 - STACKDUMP(nDim, 3);
208 + STACKDUMP(nDim+2, 3);
212 @@ -2802,9 +2827,9 @@ static int arrayAssign(void)
213 ** for use with assign-op operators (eg a[i,j] += k
215 ** Before: Prog-> [binOp], nDim, next, ...
216 -** TheStack-> [rhs], indnDim, ... ind1, next, ...
217 +** TheStack-> [rhs], indnDim, ... ind1, ArraySym, next, ...
218 ** After: Prog-> binOp, nDim, [next], ...
219 -** TheStack-> [rhs], arrayValue, next, ...
220 +** TheStack-> [rhs], arrayValue, ArraySym, next, ...
222 static int arrayRefAndAssignSetup(void)
224 @@ -2819,7 +2844,7 @@ static int arrayRefAndAssignSetup(void)
228 - STACKDUMP(nDim + 1, 3);
229 + STACKDUMP(nDim + (binaryOp ? 2 : 1), 3);
233 @@ -3073,6 +3098,59 @@ static int errCheck(const char *s)
237 +** build a stack dump string, reallocating s as necessary.
239 +static char *stackDumpStr(DataValue *fp, const char *msg, char **s, int *pLen)
244 + DataValue *nfp = fp;
249 + disasmInternal(PC - 1, 1);
250 + stackdumpInternal(0, 50);
251 + dump = printd(NULL);
254 + /* first measure the lengths */
255 + len = strlen(msg) + 1;
256 + for (nfp = fp; nfp; nfp = FP_GET_OLD_FP(nfp)) {
257 + len = len + FP_GET_ITEM(nfp, FP_FUNCTION_NAME).val.str.len + 1;
260 + len += strlen(dump);
264 + *s = *s ? XtRealloc(*s, len) : XtMalloc(len);
273 + for (nfp = fp; nfp; nfp = FP_GET_OLD_FP(nfp)) {
275 + op = FP_GET_ITEM(nfp, FP_FUNCTION_NAME).val.str.rep;
290 ** combine two strings in a static area and set ErrMsg to point to the
291 ** result. Returns false so a single return execError() statement can
292 ** be used to both process the message and return.
293 @@ -3080,9 +3158,11 @@ static int errCheck(const char *s)
294 static int execError(const char *s1, const char *s2)
296 static char msg[MAX_ERR_MSG_LEN];
297 + static char *err = NULL;
298 + static int errlen = 0;
300 sprintf(msg, s1, s2);
302 + ErrMsg = stackDumpStr(FrameP, msg, &err, &errlen);
306 @@ -3136,11 +3216,83 @@ static const char *tagToStr(enum typeTag
309 #ifdef DEBUG_DISASSEMBLER /* dumping values in disassembly or stack dump */
310 +static char *printdBuffer = NULL;
311 +static int printdPos = 0;
312 +static int printdSize = 0;
314 +static const char *printd(const char *f, ...)
322 + printdPos = 0; /* reset for next time */
323 + return printdBuffer;
327 + vsprintf(buffer, f, args);
330 + len = strlen(buffer);
334 + printdBuffer = XtMalloc(printdSize);
339 + int needSize = printdPos + len + 1;
340 + if (needSize > printdSize)
342 + int newSize = printdSize;
343 + while (newSize < needSize)
345 + printdBuffer = XtRealloc(printdBuffer, newSize);
346 + printdSize = newSize;
349 + strcpy(&printdBuffer[printdPos], buffer);
352 + return printdBuffer;
357 + const char *s = printd(NULL);
360 + static int outIsTTY = -1;
361 + if (outIsTTY == -1)
362 + outIsTTY = isatty(fileno(stdout));
366 + for (cp = s; *cp; cp++)
368 + printf("\033[K\n");
374 + for (cp = s; *cp; cp++)
379 +#endif /* #ifdef DEBUG_DISASSEMBLER */
381 +#ifdef DEBUG_DISASSEMBLER /* dumping values in disassembly or stack dump */
382 static void dumpVal(DataValue dv)
386 - printf("i=%d", dv.val.n);
387 + printd("i=%d", dv.val.n);
391 @@ -3148,38 +3300,39 @@ static void dumpVal(DataValue dv)
393 char *src = dv.val.str.rep;
395 - printf("s=<NULL>");
396 + printd("s=<NULL>");
399 for (k = 0; src[k] && k < sizeof s - 1; k++) {
400 s[k] = isprint(src[k]) ? src[k] : '?';
403 - printf("s=\"%s\"%s[%d]", s,
404 + printd("s=\"%s\"%s[%d]", s,
405 src[k] ? "..." : "", strlen(src));
410 - printf("<%s>", tagToStr(ARRAY_TAG));
411 + printd("%08p <%s>[%d]", dv.val.arrayPtr, tagToStr(ARRAY_TAG),
416 - printf("<%s>", tagToStr(NO_TAG));
417 + printd("<%s>", tagToStr(NO_TAG));
420 - printf("?%8p", dv.val.inst);
421 + printd("?%8p", dv.val.inst);
425 - printf("UNKNOWN DATA TAG %d ?%8p", dv.tag, dv.val.inst);
426 + printd("UNKNOWN DATA TAG %d ?%8p", dv.tag, dv.val.inst);
430 #endif /* #ifdef DEBUG_DISASSEMBLER */
432 #ifdef DEBUG_DISASSEMBLER /* For debugging code generation */
433 -static void disasm(Inst *inst, int nInstr)
434 +static void disasmInternal(Inst *inst, int nInstr)
436 static const char *opNames[] = {
437 #define OP(name, fn) #name,
438 @@ -3188,15 +3341,15 @@ static void disasm(Inst *inst, int nInst
444 for (i = 0; i < nInstr; ++i) {
445 - printf("Prog %8p ", &inst[i]);
446 + printd("Prog %8p ", &inst[i]);
447 for (j = 0; j < N_OPS; ++j) {
448 if (inst[i].func == OpFns[j]) {
449 - printf("%22s ", opNames[j]);
450 + printd("%22s ", opNames[j]);
451 if (j == OP_PUSH_SYM || j == OP_ASSIGN) {
452 Symbol *sym = inst[i+1].sym;
453 - printf("%s", sym->name);
454 + printd("%s", sym->name);
455 if (sym->value.tag == STRING_TAG &&
456 strncmp(sym->name, "string #", 8) == 0) {
458 @@ -3204,29 +3357,29 @@ static void disasm(Inst *inst, int nInst
461 else if (j == OP_PUSH_IMMED) {
462 - printf("i=%d", inst[i+1].value);
463 + printd("i=%d", inst[i+1].value);
466 else if (j == OP_BRANCH || j == OP_BRANCH_FALSE ||
467 j == OP_BRANCH_NEVER || j == OP_BRANCH_TRUE) {
468 - printf("to=(%d) %p", inst[i+1].value,
469 + printd("to=(%d) %p", inst[i+1].value,
470 &inst[i+1] + inst[i+1].value);
473 else if (j == OP_CONCAT) {
474 - printf("nExpr=%d", inst[i+1].value);
475 + printd("nExpr=%d", inst[i+1].value);
478 else if (j == OP_SUBR_CALL) {
479 - printf("%s (%d arg)", inst[i+1].sym->name, inst[i+2].value);
480 + printd("%s (%d arg)", inst[i+1].sym->name, inst[i+2].value);
483 else if (j == OP_BEGIN_ARRAY_ITER) {
484 - printf("%s in", inst[i+1].sym->name);
485 + printd("%s in", inst[i+1].sym->name);
488 else if (j == OP_ARRAY_ITER) {
489 - printf("%s = %s++ end-loop=(%d) %p",
490 + printd("%s = %s++ end-loop=(%d) %p",
493 inst[i+3].value, &inst[i+3] + inst[i+3].value);
494 @@ -3234,68 +3387,182 @@ static void disasm(Inst *inst, int nInst
496 else if (j == OP_ARRAY_REF || j == OP_ARRAY_DELETE ||
497 j == OP_ARRAY_ASSIGN) {
498 - printf("nDim=%d", inst[i+1].value);
499 + printd("nDim=%d", inst[i+1].value);
502 else if (j == OP_ARRAY_REF_ASSIGN_SETUP) {
503 - printf("binOp=%s ", inst[i+1].value ? "true" : "false");
504 - printf("nDim=%d", inst[i+2].value);
505 + printd("binOp=%s ", inst[i+1].value ? "true" : "false");
506 + printd("nDim=%d", inst[i+2].value);
509 else if (j == OP_PUSH_ARRAY_SYM) {
510 - printf("%s", inst[++i].sym->name);
511 - printf(" %s", inst[i+1].value ? "createAndRef" : "refOnly");
512 + printd("%s", inst[++i].sym->name);
513 + printd(" %s", inst[i+1].value ? "createAndRef" : "refOnly");
523 - printf("%x\n", inst[i].value);
524 + printd("%x\n", inst[i].value);
529 +static void disasm(Inst *inst, int nInstr)
531 + static int outIsTTY = -1;
532 + if (outIsTTY == -1) outIsTTY = isatty(fileno(stdout));
533 + if (outIsTTY) { printd("\033[H"); }
534 + disasmInternal(inst, nInstr);
535 + if (outIsTTY) { printd("\033[J\n"); }
538 #endif /* #ifdef DEBUG_DISASSEMBLER */
540 #ifdef DEBUG_STACK /* for run-time stack dumping */
541 -#define STACK_DUMP_ARG_PREFIX "Arg"
542 -static void stackdump(int n, int extra)
544 - /* TheStack-> symN-sym1(FP), argArray, nArgs, oldFP, retPC, argN-arg1, next, ... */
545 - int nArgs = FP_GET_ARG_COUNT(FrameP);
547 - char buffer[sizeof(STACK_DUMP_ARG_PREFIX) + TYPE_INT_STR_SIZE(int)];
548 - printf("Stack ----->\n");
549 - for (i = 0; i < n + extra; i++) {
551 - DataValue *dv = &StackP[-i - 1];
552 - if (dv < TheStack) {
553 - printf("--------------Stack base--------------\n");
555 +#define STACK_DUMP_ARG_PREFIX " $"
556 +static void stackdumpframe(DataValue *arrow, DataValue *outpt, DataValue *fp,
557 + DataValue *sp, char topMark)
559 + DataValue *baseF = &FP_GET_ITEM(fp, FP_OLD_FP_INDEX);
560 + DataValue *oldFP = baseF ? baseF->val.dataval : NULL;
561 + DataValue *arg1 = &FP_GET_ARG_N(fp, 0);
562 + DataValue *fnNm = &FP_GET_ITEM(fp, FP_FUNCTION_NAME);
564 + DataValue *endDv = (arg1 > outpt) ? arg1 : outpt;
565 + int nArgs = FP_GET_ARG_COUNT(fp);
568 + static int symLen = 0;
569 + Symbol *syms = FP_GET_ITEM(fp, FP_SYMBOL_TABLE).val.sym;
572 +#ifdef DEBUG_STACK_HEADFIRST
574 + /* do caller's frame */
575 + if (oldFP || arg1 > endDv)
576 + stackdumpframe(arrow, outpt, oldFP, arg1, ' ');
577 +#endif /* #ifdef DEBUG_STACK_HEADFIRST */
579 + /* do current frame */
580 + /* how many symbols are there? */
581 + for (sym = syms, nSyms = 0; sym != NULL; sym = sym->next) {
584 + int len = strlen(sym->name);
590 - offset = dv - FrameP;
593 + /* output instructions between endDv and sp - 1 inclusive */
594 +#ifdef DEBUG_STACK_HEADFIRST
596 + while (--dv >= endDv)
598 + for (dv = endDv; dv < sp; dv++)
599 +#endif /* #ifdef DEBUG_STACK_HEADFIRST */
601 + const char *posFmt = "%-6s ";
602 + const char *symName = "";
604 - printf("%4.4s", i < n ? ">>>>" : "");
605 - printf("%8p ", dv);
607 + char buffer[sizeof(STACK_DUMP_ARG_PREFIX) + TYPE_INT_STR_SIZE(int)];
608 + int offset = dv - fp;
609 + const char *leadIn = (dv >= arrow) ? ">>>>" :
610 + (dv == arg1) ? "----" :
611 + (dv == fnNm) ? "====" : "";
612 + printd("%4.4s", leadIn);
613 + printd("%8p%c", dv, topMark);
615 - case 0: pos = "FrameP"; break; /* first local symbol value */
616 - case FP_ARG_ARRAY_CACHE_INDEX: pos = "args"; break; /* arguments array */
617 - case FP_ARG_COUNT_INDEX: pos = "NArgs"; break; /* number of arguments */
618 - case FP_OLD_FP_INDEX: pos = "OldFP"; break;
619 - case FP_RET_PC_INDEX: pos = "RetPC"; break;
620 - case FP_PROG_INDEX: pos = "Prog"; break;
621 + case FP_ARG_ARRAY_INDEX: pos = "args[]"; break; /* argument array */
622 + case FP_ARG_COUNT_INDEX: pos = "NArgs"; break; /* num. arguments */
623 + case FP_FUNCTION_NAME: pos = "FnName"; break;
624 + case FP_SYMBOL_TABLE: pos = "FnSyms"; break;
625 + case FP_OLD_FP_INDEX: pos = "OldFP"; break;
626 + case FP_RET_PC_INDEX: pos = "RetPC"; break;
627 + case FP_PROG_INDEX: pos = "Prog"; break;
629 - if (offset < -FP_TO_ARGS_DIST && offset >= -FP_TO_ARGS_DIST - nArgs) {
630 + if (offset < -FP_TO_ARGS_DIST &&
631 + offset >= -FP_TO_ARGS_DIST - nArgs)
633 sprintf(pos = buffer, STACK_DUMP_ARG_PREFIX "%d",
634 offset + FP_TO_ARGS_DIST + nArgs + 1);
636 + else if (0 <= offset && offset < nSyms) {
637 + sprintf(pos = buffer, offset ? "[%d]" : "FP[%d]", offset);
640 + else if (offset == 0) {
645 - printf("%-6s ", pos);
648 + printd(posFmt, pos);
650 + /* local symbol names? */
651 + if (0 <= offset && offset < nSyms) {
652 + for (sym = syms; sym != NULL; sym = sym->next) {
653 + if (sym->value.val.n == offset) {
654 + symName = sym->name;
659 + printd("%-*.*s ", symLen, symLen, symName);
661 + if (dv == fnNm && dv->tag == STRING_TAG && dv->val.str.rep)
662 + printd("%s", dv->val.str.rep);
669 +#ifdef DEBUG_STACK_HEADFIRST
670 + /* do caller's frame */
671 + if (oldFP || arg1 > endDv)
672 + stackdumpframe(arrow, outpt, oldFP, arg1, ' ');
674 +#endif /* #ifdef DEBUG_STACK_HEADFIRST */
677 +static void stackdumpInternal(int n, int extra)
679 + DataValue *arrow = StackP - n;
680 + DataValue *outpt = StackP - n - extra;
682 +#ifdef DEBUG_STACK_HEADFIRST
683 + printd("Stack ----->\n");
684 + stackdumpframe(arrow, outpt, FrameP, StackP, '*');
685 + if (outpt < TheStack)
686 + printd("--------------Stack base--------------\n");
688 + if (outpt < TheStack)
689 + printd("--------------Stack base--------------\n");
690 + stackdumpframe(arrow, outpt, FrameP, StackP, '*');
691 + printd("Stack ----->\n");
692 +#endif /* #ifdef DEBUG_STACK_HEADFIRST */
695 +static void stackdump(int n, int extra)
697 + static int outIsTTY = -1;
698 + if (outIsTTY == -1)
699 + outIsTTY = isatty(fileno(stdout));
701 + stackdumpInternal(n, extra);
704 + printd("\033[J\n");
710 #endif /* ifdef DEBUG_STACK */
711 diff --quilt old/source/interpret.h new/source/interpret.h
712 --- old/source/interpret.h
713 +++ new/source/interpret.h
714 @@ -86,6 +86,7 @@ typedef struct DataValueTag {
716 struct DataValueTag* dataval;
717 struct SparseArrayEntryTag *arrayPtr;
718 + struct SymbolRec *sym;
722 @@ -107,6 +108,7 @@ typedef struct ProgramTag {
723 Symbol *localSymList;
729 /* Information needed to re-start a preempted macro */
730 diff --quilt old/source/macro.c new/source/macro.c
731 --- old/source/macro.c
732 +++ new/source/macro.c
733 @@ -842,7 +842,8 @@ void Replay(WindowInfo *window)
734 window->macroCmdData == NULL) {
735 /* Parse the replay macro (it's stored in text form) and compile it into
736 an executable program "prog" */
737 - prog = ParseMacro(ReplayMacro, &errMsg, &stoppedAt, False);
738 + prog = ParseMacro(ReplayMacro, &errMsg, &stoppedAt, False,
742 "NEdit internal error, learn/replay macro syntax error: %s\n",
743 @@ -940,7 +941,7 @@ static int readCheckMacroString(Widget d
744 char *stoppedAt, *errMsg;
747 - prog = ParseMacro(string, &errMsg, &stoppedAt, True);
748 + prog = ParseMacro(string, &errMsg, &stoppedAt, True, errIn);
750 if (errPos != NULL) {
752 @@ -1222,7 +1223,7 @@ void DoMacro(WindowInfo *window, const c
753 tMacro[macroLen+1] = '\0';
755 /* Parse the macro and report errors if it fails */
756 - prog = ParseMacro(tMacro, &errMsg, &stoppedAt, False);
757 + prog = ParseMacro(tMacro, &errMsg, &stoppedAt, False, errInName);
759 ParseError(window->shell, tMacro, stoppedAt, errInName, errMsg);
761 @@ -1486,7 +1487,7 @@ selEnd += $text_length - startLength\n}\
762 sprintf(loopedCmd, loopMacro, how, command);
764 /* Parse the resulting macro into an executable program "prog" */
765 - prog = ParseMacro(loopedCmd, &errMsg, &stoppedAt, False);
766 + prog = ParseMacro(loopedCmd, &errMsg, &stoppedAt, False, "repeat macro");
768 fprintf(stderr, "NEdit internal error, repeat macro syntax wrong: %s\n",
770 diff --quilt old/source/nedit.c new/source/nedit.c
771 --- old/source/nedit.c
772 +++ new/source/nedit.c
773 @@ -832,10 +832,10 @@ static int checkDoMacroArg(const char *m
774 tMacro[macroLen+1] = '\0';
776 /* Do a test parse */
777 - prog = ParseMacro(tMacro, &errMsg, &stoppedAt, False);
778 + prog = ParseMacro(tMacro, &errMsg, &stoppedAt, False, "-do macro");
781 - ParseError(NULL, tMacro, stoppedAt, "argument to -do", errMsg);
782 + ParseError(NULL, tMacro, stoppedAt, "-do macro", errMsg);
786 diff --quilt old/source/parse.h new/source/parse.h
787 --- old/source/parse.h
788 +++ new/source/parse.h
791 #include "interpret.h"
793 -Program *ParseMacro(char *expr, char **msg, char **stoppedAt, int allowDefine);
794 +Program *ParseMacro(char *expr, char **msg, char **stoppedAt, int allowDefine,
797 #endif /* NEDIT_PARSE_H_INCLUDED */
798 diff --quilt old/source/parse.y new/source/parse.y
799 --- old/source/parse.y
800 +++ new/source/parse.y
801 @@ -632,10 +632,12 @@ blank: /* nothing */
802 ** as a pointer to a static string in msg, and the length of the string up
803 ** to where parsing failed in stoppedAt.
805 -Program *ParseMacro(char *expr, char **msg, char **stoppedAt, int allowDefine)
806 +Program *ParseMacro(char *expr, char **msg, char **stoppedAt, int allowDefine,
810 AccumulatorData *acc = XtNew(AccumulatorData);
811 + static const char *prefix = ">> ";
814 int oldyydebug = yydebug;
815 @@ -670,6 +672,12 @@ Program *ParseMacro(char *expr, char **m
816 prog = FinishCreatingProgram(acc);
820 + name = "--unknown--";
822 + prog->name = XtMalloc(strlen(name) + strlen(prefix) + 1);
823 + strcat(strcpy(prog->name, prefix), name);
825 /* parse succeeded */
828 diff --quilt old/source/parse_noyacc.c new/source/parse_noyacc.c
829 --- old/source/parse_noyacc.c
830 +++ new/source/parse_noyacc.c
831 @@ -746,9 +746,10 @@ int yystacksize;
832 ** as a pointer to a static string in msg, and the length of the string up
833 ** to where parsing failed in stoppedAt.
835 -Program *ParseMacro(char *expr, char **msg, char **stoppedAt)
836 +Program *ParseMacro(char *expr, char **msg, char **stoppedAt, const char *name)
839 + static const char *prefix = ">> ";
841 BeginCreatingProgram();
843 @@ -766,6 +767,12 @@ Program *ParseMacro(char *expr, char **m
844 /* get the newly created program */
845 prog = FinishCreatingProgram();
848 + name = "--unknown--";
850 + prog->name = XtMalloc(strlen(name) + strlen(prefix) + 1);
851 + strcat(strcpy(prog->name, prefix), name);
853 /* parse succeeded */
856 diff --quilt old/source/smartIndent.c new/source/smartIndent.c
857 --- old/source/smartIndent.c
858 +++ new/source/smartIndent.c
859 @@ -747,18 +747,18 @@ void BeginSmartIndent(WindowInfo *window
860 winData->inNewLineMacro = 0;
861 winData->inModMacro = 0;
862 winData->newlineMacro = ParseMacro(indentMacros->newlineMacro, &errMsg,
863 - &stoppedAt, False);
864 + &stoppedAt, False, "smart indent newline macro");
865 if (winData->newlineMacro == NULL) {
866 XtFree((char *)winData);
867 - ParseError(window->shell, indentMacros->newlineMacro, stoppedAt,
868 - "newline macro", errMsg);
869 + ParseError(window->shell, indentMacros->newlineMacro, stoppedAt,
870 + "smart indent newline macro", errMsg);
873 if (indentMacros->modMacro == NULL)
874 winData->modMacro = NULL;
876 winData->modMacro = ParseMacro(indentMacros->modMacro, &errMsg,
877 - &stoppedAt, False);
878 + &stoppedAt, False, "smart indent modify macro");
879 if (winData->modMacro == NULL) {
880 FreeProgram(winData->newlineMacro);
881 XtFree((char *)winData);
882 @@ -1415,7 +1415,7 @@ static int checkSmartIndentDialogData(vo
883 if (!TextWidgetIsBlank(SmartIndentDialog.initMacro)) {
884 widgetText =ensureNewline(XmTextGetString(SmartIndentDialog.initMacro));
885 if (!CheckMacroString(SmartIndentDialog.shell, widgetText,
886 - "initialization macro", &stoppedAt)) {
887 + "smart indent initialization macro", &stoppedAt)) {
888 XmTextSetInsertionPosition(SmartIndentDialog.initMacro,
889 stoppedAt - widgetText);
890 XmProcessTraversal(SmartIndentDialog.initMacro, XmTRAVERSE_CURRENT);
891 @@ -1434,10 +1434,11 @@ static int checkSmartIndentDialogData(vo
894 widgetText = ensureNewline(XmTextGetString(SmartIndentDialog.newlineMacro));
895 - prog = ParseMacro(widgetText, &errMsg, &stoppedAt, False);
896 + prog = ParseMacro(widgetText, &errMsg, &stoppedAt, False,
897 + "smart indent newline macro");
899 ParseError(SmartIndentDialog.shell, widgetText, stoppedAt,
900 - "newline macro", errMsg);
901 + "smart indent newline macro", errMsg);
902 XmTextSetInsertionPosition(SmartIndentDialog.newlineMacro,
903 stoppedAt - widgetText);
904 XmProcessTraversal(SmartIndentDialog.newlineMacro, XmTRAVERSE_CURRENT);
905 @@ -1450,10 +1451,11 @@ static int checkSmartIndentDialogData(vo
906 /* Test compile the modify macro */
907 if (!TextWidgetIsBlank(SmartIndentDialog.modMacro)) {
908 widgetText = ensureNewline(XmTextGetString(SmartIndentDialog.modMacro));
909 - prog = ParseMacro(widgetText, &errMsg, &stoppedAt, False);
910 + prog = ParseMacro(widgetText, &errMsg, &stoppedAt, False,
911 + "smart indent modify macro");
913 ParseError(SmartIndentDialog.shell, widgetText, stoppedAt,
914 - "modify macro", errMsg);
915 + "smart indent modify macro", errMsg);
916 XmTextSetInsertionPosition(SmartIndentDialog.modMacro,
917 stoppedAt - widgetText);
918 XmProcessTraversal(SmartIndentDialog.modMacro, XmTRAVERSE_CURRENT);
919 diff --quilt old/source/userCmds.c new/source/userCmds.c
920 --- old/source/userCmds.c
921 +++ new/source/userCmds.c
922 @@ -241,6 +241,8 @@ static Widget BGMenuPasteReplayBtn = NUL
923 static void editMacroOrBGMenu(WindowInfo *window, int dialogType);
924 static void dimSelDepItemsInMenu(Widget menuPane, menuItemRec **menuList,
925 int nMenuItems, int sensitive);
926 +static int doMacroMenuCmd(WindowInfo *window, const char *itemName,
927 + menuItemRec **menu, int nMenu, const char *menuName);
928 static void rebuildMenuOfAllWindows(int menuType);
929 static void rebuildMenu(WindowInfo *window, int menuType);
930 static Widget findInMenuTree(menuTreeItem *menuTree, int nTreeEntries,
931 @@ -1260,30 +1262,37 @@ int DoNamedShellMenuCmd(WindowInfo *wind
932 ** with menu item name "itemName". Returns True on successs and False on
935 -int DoNamedMacroMenuCmd(WindowInfo *window, const char *itemName)
936 +static int doMacroMenuCmd(WindowInfo *window, const char *itemName,
937 + menuItemRec **menu, int nMenu, const char *menuName)
941 - for (i=0; i<NMacroMenuItems; i++) {
942 - if (!strcmp(MacroMenuItems[i]->name, itemName)) {
943 - DoMacro(window, MacroMenuItems[i]->cmd, "macro menu command");
947 + Boolean result = False;
949 + for (i = 0; i < nMenu; i++) {
950 + if (!strcmp(menu[i]->name, itemName)) {
951 + name = XtMalloc(strlen(menuName) + strlen(itemName) + 1);
952 + strcat(strcpy(name, menuName), itemName);
953 + DoMacro(window, menu[i]->cmd, name);
964 +int DoNamedMacroMenuCmd(WindowInfo *window, const char *itemName)
966 + return doMacroMenuCmd(window, itemName, MacroMenuItems, NMacroMenuItems,
970 int DoNamedBGMenuCmd(WindowInfo *window, const char *itemName)
974 - for (i=0; i<NBGMenuItems; i++) {
975 - if (!strcmp(BGMenuItems[i]->name, itemName)) {
976 - DoMacro(window, BGMenuItems[i]->cmd, "background menu macro");
981 + return doMacroMenuCmd(window, itemName, BGMenuItems, NBGMenuItems,
982 + "background-menu>");
986 @@ -2080,7 +2089,7 @@ static int checkMacroText(char *macro, W
988 char *errMsg, *stoppedAt;
990 - prog = ParseMacro(macro, &errMsg, &stoppedAt, False);
991 + prog = ParseMacro(macro, &errMsg, &stoppedAt, False, "macro");
993 if (errorParent != NULL) {
994 ParseError(errorParent, macro, stoppedAt, "macro", errMsg);
995 @@ -2092,7 +2101,7 @@ static int checkMacroText(char *macro, W
997 if (*stoppedAt != '\0') {
998 if (errorParent != NULL) {
999 - ParseError(errorParent, macro, stoppedAt,"macro","syntax error");
1000 + ParseError(errorParent, macro, stoppedAt, "macro", "syntax error");
1001 XmTextSetInsertionPosition(errFocus, stoppedAt - macro);
1002 XmProcessTraversal(errFocus, XmTRAVERSE_CURRENT);
1004 @@ -3019,7 +3028,7 @@ static char *copyMacroToEnd(char **inPtr
1007 /* Parse the input */
1008 - prog = ParseMacro(*inPtr, &errMsg, &stoppedAt, False);
1009 + prog = ParseMacro(*inPtr, &errMsg, &stoppedAt, False, "macro menu item");
1011 ParseError(NULL, *inPtr, stoppedAt, "macro menu item", errMsg);