CVS rebase
[nedit-bw.git] / InterpretDebug4.diff
blob0639b327bc0b2567d787936372f4a61ccef886da
1 Provide NEdit Macro stack traces
3 Avaliable as a patch:
5 http://sourceforge.net/tracker/index.php?func=detail&aid=970501&group_id=11005&atid=311005
6 [ 970501 ] Provide NEdit Macro stack traces
7 InterpretDebug.diff 2004-06-10 11:51
9 Macro function names are listed when a crash occurs in one of your macros.
10 The usual error message is followed by a list of the NEdit macro functions
11 called before getting there. (It doesn't tell you how the macro was invoked
12 however.) This provides a good clue as to where a macro programming
13 problem lies.
15 Also, debug tracing enhanced to show symbol values in stack traces listed to
16 terminal output: a boon to interpret.c hackers.
18 Try changing the definition
19 #define STACKDUMP(n, x) stackdump(n, x)
21 #define STACKDUMP(n, x) stackdump(n, x + 50)
22 and watching the output of NEdit in an xterm generated while running your
23 favorite macros!
25 (You will need to add -DDEBUG_STACK and -DDEBUG_ASSEMBLY in your compilation
26 flags to enable the debug tracing.)
28 Thanks to Eddy De Greef!
30 InterpretDebug2.diff 2004-06-11 17:13
32 This version passes an extra "name" string to ParseMacro().
33 This name is used as a "function name" in the stack dumps,
34 when there is no available function symbol name available
35 (usually at the top level of invocation from NEdit's user
36 interface). It allows the user to determine which macro is
37 being invoked or which file is being interpreted when an error
38 occurs.
40 ---
42 source/interpret.c | 398 ++++++++++++++++++++++++++++++++++++++++++--------
43 source/interpret.h | 2
44 source/macro.c | 10 -
45 source/nedit.c | 2
46 source/parse.h | 2
47 source/parse.y | 9 +
48 source/parse_noyacc.c | 9 +
49 source/smartIndent.c | 12 -
50 source/userCmds.c | 47 +++--
51 9 files changed, 400 insertions(+), 91 deletions(-)
53 diff --quilt old/source/interpret.c new/source/interpret.c
54 --- old/source/interpret.c
55 +++ new/source/interpret.c
56 @@ -38,7 +38,9 @@ static const char CVSID[] = "$Id: interp
57 #include "text.h"
58 #include "rbTree.h"
60 +#include <unistd.h>
61 #include <stdio.h>
62 +#include <stdarg.h>
63 #include <stdlib.h>
64 #include <string.h>
65 #include <math.h>
66 @@ -143,7 +145,10 @@ static SparseArrayEntry *allocateSparseA
68 #if defined(DEBUG_ASSEMBLY) || defined(DEBUG_STACK)
69 #define DEBUG_DISASSEMBLER
70 +static const char *printd(const char *f, ...);
71 +static int outPrintd();
72 static void disasm(Inst *inst, int nInstr);
73 +static void disasmInternal(Inst *inst, int nInstr);
74 #endif /* #if defined(DEBUG_ASSEMBLY) || defined(DEBUG_STACK) */
76 #ifdef DEBUG_ASSEMBLY /* for disassembly */
77 @@ -154,6 +159,7 @@ static void disasm(Inst *inst, int nInst
79 #ifdef DEBUG_STACK /* for run-time instruction and stack trace */
80 static void stackdump(int n, int extra);
81 +static void stackdumpInternal(int n, int extra);
82 #define STACKDUMP(n, x) stackdump(n, x)
83 #define DISASM_RT(i, n) disasm(i, n)
84 #else /* #ifndef DEBUG_STACK */
85 @@ -213,13 +219,17 @@ static int (*OpFns[N_OPS])() = {returnNo
86 arrayRefAndAssignSetup, pushArgVal, pushArgCount, pushArgArray};
88 /* Stack-> symN-sym0(FP), argArray, nArgs, oldFP, retPC, argN-arg1, next, ... */
89 -#define FP_ARG_ARRAY_CACHE_INDEX (-1)
90 +#define FP_ARG_ARRAY_INDEX (-1)
91 #define FP_ARG_COUNT_INDEX (-2)
92 -#define FP_OLD_FP_INDEX (-3)
93 -#define FP_RET_PC_INDEX (-4)
94 -#define FP_TO_ARGS_DIST (4) /* should be 0 - (above index) */
95 +#define FP_FUNCTION_NAME (-3) /* !! */
96 +#define FP_SYMBOL_TABLE (-4) /* !! */
97 +#define FP_OLD_FP_INDEX (-5)
98 +#define FP_RET_PC_INDEX (-6)
100 +#define FP_TO_ARGS_DIST (0 - FP_RET_PC_INDEX) /* should be 0 - (above index) */
102 #define FP_GET_ITEM(xFrameP,xIndex) (*(xFrameP + xIndex))
103 -#define FP_GET_ARG_ARRAY_CACHE(xFrameP) (FP_GET_ITEM(xFrameP, FP_ARG_ARRAY_CACHE_INDEX))
104 +#define FP_GET_ARG_ARRAY_CACHE(xFrameP) (FP_GET_ITEM(xFrameP, FP_ARG_ARRAY_INDEX))
105 #define FP_GET_ARG_COUNT(xFrameP) (FP_GET_ITEM(xFrameP, FP_ARG_COUNT_INDEX).val.n)
106 #define FP_GET_OLD_FP(xFrameP) ((FP_GET_ITEM(xFrameP, FP_OLD_FP_INDEX)).val.dataval)
107 #define FP_GET_RET_PC(xFrameP) ((FP_GET_ITEM(xFrameP, FP_RET_PC_INDEX)).val.inst)
108 @@ -300,6 +310,7 @@ Program *FinishCreatingProgram(void)
109 memcpy(newProg->code, Prog, progLen);
110 newProg->localSymList = LocalSymList;
111 LocalSymList = NULL;
112 + newProg->name = NULL;
114 /* Local variables' values are stored on the stack. Here we assign
115 frame pointer offsets to them. */
116 @@ -315,6 +326,9 @@ void FreeProgram(Program *prog)
118 freeSymbolTable(prog->localSymList);
119 XtFree((char *)prog->code);
120 + if (prog->name) {
121 + XtFree((char *)prog->name);
123 XtFree((char *)prog);
126 @@ -496,6 +510,15 @@ int ExecuteMacro(WindowInfo *window, Pro
128 *(context->stackP++) = noValue; /* old FrameP */
130 + context->stackP->tag = NO_TAG;
131 + context->stackP->val.sym = prog->localSymList; /* symbol table */
132 + context->stackP++;
134 + context->stackP->tag = STRING_TAG;
135 + context->stackP->val.str.rep = prog->name ? prog->name : "<exec-macro>";
136 + context->stackP->val.str.len = strlen(context->stackP->val.str.rep);
137 + context->stackP++;
139 context->stackP->tag = NO_TAG; /* nArgs */
140 context->stackP->val.n = nArgs;
141 context->stackP++;
142 @@ -595,6 +618,15 @@ void RunMacroAsSubrCall(Program *prog)
143 StackP->val.dataval = FrameP; /* old FrameP */
144 StackP++;
146 + StackP->tag = NO_TAG;
147 + StackP->val.sym = prog->localSymList; /* symbol table */
148 + StackP++;
150 + StackP->tag = STRING_TAG;
151 + StackP->val.str.rep = prog->name ? prog->name : "<run-macro>";
152 + StackP->val.str.len = strlen(StackP->val.str.rep);
153 + StackP++;
155 StackP->tag = NO_TAG; /* nArgs */
156 StackP->val.n = 0;
157 StackP++;
158 @@ -2082,6 +2114,8 @@ static int callSubroutine(void)
159 ** values which are already there.
161 if (sym->type == MACRO_FUNCTION_SYM) {
162 + prog = sym->value.val.prog;
164 StackP->tag = NO_TAG; /* return PC */
165 StackP->val.inst = PC;
166 StackP++;
167 @@ -2090,6 +2124,15 @@ static int callSubroutine(void)
168 StackP->val.dataval = FrameP;
169 StackP++;
171 + StackP->tag = NO_TAG;
172 + StackP->val.sym = prog->localSymList; /* symbol table */
173 + StackP++;
175 + StackP->tag = STRING_TAG;
176 + StackP->val.str.rep = sym->name; /* function name */
177 + StackP->val.str.len = strlen(sym->name);
178 + StackP++;
180 StackP->tag = NO_TAG; /* nArgs */
181 StackP->val.n = nArgs;
182 StackP++;
183 @@ -2097,7 +2140,6 @@ static int callSubroutine(void)
184 *(StackP++) = noValue; /* cached arg array */
186 FrameP = StackP;
187 - prog = sym->value.val.prog;
188 PC = prog->code;
189 for (s = prog->localSymList; s != NULL; s = s->next) {
190 FP_GET_SYM_VAL(FrameP, s) = noValue;
191 @@ -2564,7 +2606,7 @@ static int arrayRef(void)
192 PC++;
194 DISASM_RT(PC-2, 2);
195 - STACKDUMP(nDim, 3);
196 + STACKDUMP(nDim+1, 3);
198 if (nDim > 0) {
199 errNum = makeArrayKeyFromArgs(nDim, &keyString, 0);
200 @@ -2615,7 +2657,7 @@ static int arrayAssign(void)
201 PC++;
203 DISASM_RT(PC-2, 1);
204 - STACKDUMP(nDim, 3);
205 + STACKDUMP(nDim+2, 3);
207 if (nDim > 0) {
208 POP(srcValue)
209 @@ -2653,9 +2695,9 @@ static int arrayAssign(void)
210 ** for use with assign-op operators (eg a[i,j] += k
212 ** Before: Prog-> [binOp], nDim, next, ...
213 -** TheStack-> [rhs], indnDim, ... ind1, next, ...
214 +** TheStack-> [rhs], indnDim, ... ind1, ArraySym, next, ...
215 ** After: Prog-> binOp, nDim, [next], ...
216 -** TheStack-> [rhs], arrayValue, next, ...
217 +** TheStack-> [rhs], arrayValue, ArraySym, next, ...
219 static int arrayRefAndAssignSetup(void)
221 @@ -2670,7 +2712,7 @@ static int arrayRefAndAssignSetup(void)
222 PC++;
224 DISASM_RT(PC-3, 3);
225 - STACKDUMP(nDim + 1, 3);
226 + STACKDUMP(nDim + (binaryOp ? 2 : 1), 3);
228 if (binaryOp) {
229 POP(moveExpr)
230 @@ -2924,6 +2966,59 @@ static int errCheck(const char *s)
234 +** build a stack dump string, reallocating s as necessary.
236 +static char *stackDumpStr(DataValue *fp, const char *msg, char **s, int *pLen)
238 + int len;
239 + const char *op;
240 + char *np;
241 + DataValue *nfp = fp;
243 +#ifdef DEBUG_STACK
244 + const char *dump;
245 + printd("\n\n");
246 + disasmInternal(PC - 1, 1);
247 + stackdumpInternal(0, 50);
248 + dump = printd(NULL);
249 +#endif
251 + /* first measure the lengths */
252 + len = strlen(msg) + 1;
253 + for (nfp = fp; nfp; nfp = FP_GET_OLD_FP(nfp)) {
254 + len = len + FP_GET_ITEM(nfp, FP_FUNCTION_NAME).val.str.len + 1;
256 +#ifdef DEBUG_STACK
257 + len += strlen(dump);
258 +#endif
259 + if (*pLen < len)
261 + *s = *s ? XtRealloc(*s, len) : XtMalloc(len);
262 + *pLen = len;
264 + /* now copy */
265 + np = *s;
266 + op = msg;
267 + while (*op)
268 + *np++ = *op++;
270 + for (nfp = fp; nfp; nfp = FP_GET_OLD_FP(nfp)) {
271 + *np++ = '\n';
272 + op = FP_GET_ITEM(nfp, FP_FUNCTION_NAME).val.str.rep;
273 + while (*op)
274 + *np++ = *op++;
276 +#ifdef DEBUG_STACK
277 + op = dump;
278 + while (*op)
279 + *np++ = *op++;
280 +#endif
282 + *np = 0;
283 + return *s;
287 ** combine two strings in a static area and set ErrMsg to point to the
288 ** result. Returns false so a single return execError() statement can
289 ** be used to both process the message and return.
290 @@ -2931,9 +3026,11 @@ static int errCheck(const char *s)
291 static int execError(const char *s1, const char *s2)
293 static char msg[MAX_ERR_MSG_LEN];
294 + static char *err = NULL;
295 + static int errlen = 0;
297 sprintf(msg, s1, s2);
298 - ErrMsg = msg;
299 + ErrMsg = stackDumpStr(FrameP, msg, &err, &errlen);
300 return STAT_ERROR;
303 @@ -2967,11 +3064,83 @@ int StringToNum(const char *string, int
306 #ifdef DEBUG_DISASSEMBLER /* dumping values in disassembly or stack dump */
307 +static char *printdBuffer = NULL;
308 +static int printdPos = 0;
309 +static int printdSize = 0;
311 +static const char *printd(const char *f, ...)
313 + char buffer[4096];
314 + int len;
315 + va_list args;
317 + if (!f)
319 + printdPos = 0; /* reset for next time */
320 + return printdBuffer;
323 + va_start(args, f);
324 + vsprintf(buffer, f, args);
325 + va_end(args);
327 + len = strlen(buffer);
328 + if (!printdBuffer)
330 + printdSize = 4096;
331 + printdBuffer = XtMalloc(printdSize);
332 + printdPos = 0;
334 + else
336 + int needSize = printdPos + len + 1;
337 + if (needSize > printdSize)
339 + int newSize = printdSize;
340 + while (newSize < needSize)
341 + newSize *= 2;
342 + printdBuffer = XtRealloc(printdBuffer, newSize);
343 + printdSize = newSize;
346 + strcpy(&printdBuffer[printdPos], buffer);
347 + printdPos += len;
349 + return printdBuffer;
352 +int outPrintd()
354 + const char *s = printd(NULL);
355 + const char *cp;
357 + static int outIsTTY = -1;
358 + if (outIsTTY == -1)
359 + outIsTTY = isatty(fileno(stdout));
361 + if (outIsTTY)
363 + for (cp = s; *cp; cp++)
364 + if (*cp == '\n')
365 + printf("\033[K\n");
366 + else
367 + putchar(*cp);
369 + else
371 + for (cp = s; *cp; cp++)
372 + putchar(*cp);
374 + return cp - s;
376 +#endif /* #ifdef DEBUG_DISASSEMBLER */
378 +#ifdef DEBUG_DISASSEMBLER /* dumping values in disassembly or stack dump */
379 static void dumpVal(DataValue dv)
381 switch (dv.tag) {
382 case INT_TAG:
383 - printf("i=%d", dv.val.n);
384 + printd("i=%d", dv.val.n);
385 break;
386 case STRING_TAG:
388 @@ -2979,38 +3148,38 @@ static void dumpVal(DataValue dv)
389 char s[21];
390 char *src = dv.val.str.rep;
391 if (!src) {
392 - printf("s=<NULL>");
393 + printd("s=<NULL>");
395 else {
396 for (k = 0; src[k] && k < sizeof s - 1; k++) {
397 s[k] = isprint(src[k]) ? src[k] : '?';
399 s[k] = 0;
400 - printf("s=\"%s\"%s[%d]", s,
401 + printd("s=\"%s\"%s[%d]", s,
402 src[k] ? "..." : "", strlen(src));
405 break;
406 case ARRAY_TAG:
407 - printf("<array>");
408 + printd("%08p <array>[%d]", dv.val.arrayPtr, ArraySize(&dv));
409 break;
410 case NO_TAG:
411 if (!dv.val.inst) {
412 - printf("<no value>");
413 + printd("<no value>");
415 else {
416 - printf("?%8p", dv.val.inst);
417 + printd("?%8p", dv.val.inst);
419 break;
420 default:
421 - printf("UNKNOWN DATA TAG %d ?%8p", dv.tag, dv.val.inst);
422 + printd("UNKNOWN DATA TAG %d ?%8p", dv.tag, dv.val.inst);
423 break;
426 #endif /* #ifdef DEBUG_DISASSEMBLER */
428 #ifdef DEBUG_DISASSEMBLER /* For debugging code generation */
429 -static void disasm(Inst *inst, int nInstr)
430 +static void disasmInternal(Inst *inst, int nInstr)
432 static const char *opNames[N_OPS] = {
433 "RETURN_NO_VAL", /* returnNoVal */
434 @@ -3059,15 +3228,15 @@ static void disasm(Inst *inst, int nInst
436 int i, j;
438 - printf("\n");
439 + printd("\n");
440 for (i = 0; i < nInstr; ++i) {
441 - printf("Prog %8p ", &inst[i]);
442 + printd("Prog %8p ", &inst[i]);
443 for (j = 0; j < N_OPS; ++j) {
444 if (inst[i].func == OpFns[j]) {
445 - printf("%22s ", opNames[j]);
446 + printd("%22s ", opNames[j]);
447 if (j == OP_PUSH_SYM || j == OP_ASSIGN) {
448 Symbol *sym = inst[i+1].sym;
449 - printf("%s", sym->name);
450 + printd("%s", sym->name);
451 if (sym->value.tag == STRING_TAG &&
452 strncmp(sym->name, "string #", 8) == 0) {
453 dumpVal(sym->value);
454 @@ -3076,7 +3245,7 @@ static void disasm(Inst *inst, int nInst
456 else if (j == OP_BRANCH || j == OP_BRANCH_FALSE ||
457 j == OP_BRANCH_NEVER || j == OP_BRANCH_TRUE) {
458 - printf("to=(%d) %p", inst[i+1].value,
459 + printd("to=(%d) %p", inst[i+1].value,
460 &inst[i+1] + inst[i+1].value);
461 ++i;
463 @@ -3085,15 +3254,15 @@ static void disasm(Inst *inst, int nInst
464 ++i;
466 else if (j == OP_SUBR_CALL) {
467 - printf("%s (%d arg)", inst[i+1].sym->name, inst[i+2].value);
468 + printd("%s (%d arg)", inst[i+1].sym->name, inst[i+2].value);
469 i += 2;
471 else if (j == OP_BEGIN_ARRAY_ITER) {
472 - printf("%s in", inst[i+1].sym->name);
473 + printd("%s in", inst[i+1].sym->name);
474 ++i;
476 else if (j == OP_ARRAY_ITER) {
477 - printf("%s = %s++ end-loop=(%d) %p",
478 + printd("%s = %s++ end-loop=(%d) %p",
479 inst[i+1].sym->name,
480 inst[i+2].sym->name,
481 inst[i+3].value, &inst[i+3] + inst[i+3].value);
482 @@ -3101,67 +3270,180 @@ static void disasm(Inst *inst, int nInst
484 else if (j == OP_ARRAY_REF || j == OP_ARRAY_DELETE ||
485 j == OP_ARRAY_ASSIGN) {
486 - printf("nDim=%d", inst[i+1].value);
487 + printd("nDim=%d", inst[i+1].value);
488 ++i;
490 else if (j == OP_ARRAY_REF_ASSIGN_SETUP) {
491 - printf("binOp=%s ", inst[i+1].value ? "true" : "false");
492 - printf("nDim=%d", inst[i+2].value);
493 + printd("binOp=%s ", inst[i+1].value ? "true" : "false");
494 + printd("nDim=%d", inst[i+2].value);
495 i += 2;
497 else if (j == OP_PUSH_ARRAY_SYM) {
498 - printf("%s", inst[++i].sym->name);
499 - printf(" %s", inst[i+1].value ? "createAndRef" : "refOnly");
500 + printd("%s", inst[++i].sym->name);
501 + printd(" %s", inst[i+1].value ? "createAndRef" : "refOnly");
502 ++i;
505 - printf("\n");
506 + printd("\n");
507 break;
510 if (j == N_OPS) {
511 - printf("%x\n", inst[i].value);
512 + printd("%x\n", inst[i].value);
517 +static void disasm(Inst *inst, int nInstr)
519 + static int outIsTTY = -1;
520 + if (outIsTTY == -1) outIsTTY = isatty(fileno(stdout));
521 + if (outIsTTY) { printd("\033[H"); }
522 + disasmInternal(inst, nInstr);
523 + outPrintd();
525 #endif /* #ifdef DEBUG_DISASSEMBLER */
527 #ifdef DEBUG_STACK /* for run-time stack dumping */
528 #define STACK_DUMP_ARG_PREFIX "Arg"
529 -static void stackdump(int n, int extra)
530 +static void stackdumpframe(DataValue *arrow, DataValue *outpt, DataValue *fp,
531 + DataValue *sp, char topMark)
533 - /* TheStack-> symN-sym1(FP), argArray, nArgs, oldFP, retPC, argN-arg1, next, ... */
534 - int nArgs = FP_GET_ARG_COUNT(FrameP);
535 - int i, offset;
536 - char buffer[sizeof(STACK_DUMP_ARG_PREFIX) + TYPE_INT_STR_SIZE(int)];
537 - printf("Stack ----->\n");
538 - for (i = 0; i < n + extra; i++) {
539 - char *pos = "";
540 - DataValue *dv = &StackP[-i - 1];
541 - if (dv < TheStack) {
542 - printf("--------------Stack base--------------\n");
543 - break;
544 + DataValue *baseF = &FP_GET_ITEM(fp, FP_OLD_FP_INDEX);
545 + DataValue *oldFP = baseF ? baseF->val.dataval : NULL;
546 + DataValue *arg1 = &FP_GET_ARG_N(fp, 0);
547 + DataValue *fnNm = &FP_GET_ITEM(fp, FP_FUNCTION_NAME);
548 + DataValue *dv;
549 + DataValue *endDv = (arg1 > outpt) ? arg1 : outpt;
550 + int nArgs = FP_GET_ARG_COUNT(fp);
552 + int nSyms;
553 + static int symLen = 0;
554 + Symbol *syms = FP_GET_ITEM(fp, FP_SYMBOL_TABLE).val.sym;
555 + Symbol *sym;
557 +#ifdef DEBUG_STACK_HEADFIRST
558 +#else
559 + /* do caller's frame */
560 + if (oldFP || arg1 > endDv)
561 + stackdumpframe(arrow, outpt, oldFP, arg1, ' ');
562 +#endif /* #ifdef DEBUG_STACK_HEADFIRST */
564 + /* do current frame */
565 + /* how many symbols are there? */
566 + for (sym = syms, nSyms = 0; sym != NULL; sym = sym->next) {
567 + nSyms++;
568 + if (symLen < 27) {
569 + int len = strlen(sym->name);
570 + if (len > 27)
571 + len = 27;
572 + if (len > symLen)
573 + symLen = len;
576 - offset = dv - FrameP;
578 - printf("%4.4s", i < n ? ">>>>" : "");
579 - printf("%8p ", dv);
580 + /* output instructions between endDv and sp - 1 inclusive */
581 +#ifdef DEBUG_STACK_HEADFIRST
582 + dv = sp;
583 + while (--dv >= endDv)
584 +#else
585 + for (dv = endDv; dv < sp; dv++)
586 +#endif /* #ifdef DEBUG_STACK_HEADFIRST */
588 + const char *posFmt = "%-6s ";
589 + const char *symName = "";
591 + char *pos = "";
592 + char buffer[sizeof(STACK_DUMP_ARG_PREFIX) + TYPE_INT_STR_SIZE(int)];
593 + int offset = dv - fp;
594 + const char *leadIn = (dv >= arrow) ? ">>>>" :
595 + (dv == arg1) ? "----" :
596 + (dv == fnNm) ? "====" : "";
597 + printd("%4.4s", leadIn);
598 + printd("%8p%c", dv, topMark);
599 switch (offset) {
600 - case 0: pos = "FrameP"; break; /* first local symbol value */
601 - case FP_ARG_ARRAY_CACHE_INDEX: pos = "args"; break; /* arguments array */
602 - case FP_ARG_COUNT_INDEX: pos = "NArgs"; break; /* number of arguments */
603 - case FP_OLD_FP_INDEX: pos = "OldFP"; break;
604 - case FP_RET_PC_INDEX: pos = "RetPC"; break;
605 + case FP_ARG_ARRAY_INDEX: pos = "args[]"; break; /* argument array */
606 + case FP_ARG_COUNT_INDEX: pos = "NArgs"; break; /* num. arguments */
607 + case FP_FUNCTION_NAME: pos = "FnName"; break;
608 + case FP_SYMBOL_TABLE: pos = "FnSyms"; break;
609 + case FP_OLD_FP_INDEX: pos = "OldFP"; break;
610 + case FP_RET_PC_INDEX: pos = "RetPC"; break;
611 default:
612 - if (offset < -FP_TO_ARGS_DIST && offset >= -FP_TO_ARGS_DIST - nArgs) {
613 + if (offset < -FP_TO_ARGS_DIST &&
614 + offset >= -FP_TO_ARGS_DIST - nArgs)
616 sprintf(pos = buffer, STACK_DUMP_ARG_PREFIX "%d",
617 offset + FP_TO_ARGS_DIST + nArgs + 1);
619 + else if (0 <= offset && offset < nSyms) {
620 + sprintf(pos = buffer, offset ? "[%d]" : "FP[%d]", offset);
621 + posFmt = "%6s ";
623 + else if (offset == 0) {
624 + pos = "FrameP";
626 break;
628 - printf("%-6s ", pos);
629 + printd(posFmt, pos);
631 + /* local symbol names? */
632 + if (offset < nSyms) {
633 + for (sym = syms; sym != NULL; sym = sym->next) {
634 + if (sym->value.val.n == offset) {
635 + symName = sym->name;
636 + break;
640 + printd("%-*.*s ", symLen, symLen, symName);
642 + if (dv == fnNm && dv->tag == STRING_TAG && dv->val.str.rep)
643 + printd("%s", dv->val.str.rep);
644 + else
645 dumpVal(*dv);
646 - printf("\n");
648 + printd("\n");
651 +#ifdef DEBUG_STACK_HEADFIRST
652 + /* do caller's frame */
653 + if (oldFP || arg1 > endDv)
654 + stackdumpframe(arrow, outpt, oldFP, arg1, ' ');
655 +#else
656 +#endif /* #ifdef DEBUG_STACK_HEADFIRST */
659 +static void stackdumpInternal(int n, int extra)
661 + DataValue *arrow = StackP - n;
662 + DataValue *outpt = StackP - n - extra;
664 +#ifdef DEBUG_STACK_HEADFIRST
665 + printd("Stack ----->\n");
666 + stackdumpframe(arrow, outpt, FrameP, StackP, '*');
667 + if (outpt < TheStack)
668 + printd("--------------Stack base--------------\n");
669 +#else
670 + if (outpt < TheStack)
671 + printd("--------------Stack base--------------\n");
672 + stackdumpframe(arrow, outpt, FrameP, StackP, '*');
673 + printd("Stack ----->\n");
674 +#endif /* #ifdef DEBUG_STACK_HEADFIRST */
677 +static void stackdump(int n, int extra)
679 + static int outIsTTY = -1;
680 + if (outIsTTY == -1)
681 + outIsTTY = isatty(fileno(stdout));
683 + stackdumpInternal(n, extra);
685 + if (outIsTTY)
686 + printd("\033[J\n");
688 + outPrintd();
689 + fflush(stdout);
692 #endif /* ifdef DEBUG_STACK */
693 diff --quilt old/source/interpret.h new/source/interpret.h
694 --- old/source/interpret.h
695 +++ new/source/interpret.h
696 @@ -86,6 +86,7 @@ typedef struct DataValueTag {
697 Inst* inst;
698 struct DataValueTag* dataval;
699 struct SparseArrayEntryTag *arrayPtr;
700 + struct SymbolRec *sym;
701 } val;
702 } DataValue;
704 @@ -106,6 +107,7 @@ typedef struct SymbolRec {
705 typedef struct ProgramTag {
706 Symbol *localSymList;
707 Inst *code;
708 + char *name;
709 } Program;
711 /* Information needed to re-start a preempted macro */
712 diff --quilt old/source/macro.c new/source/macro.c
713 --- old/source/macro.c
714 +++ new/source/macro.c
715 @@ -831,7 +831,7 @@ void Replay(WindowInfo *window)
716 window->macroCmdData == NULL) {
717 /* Parse the replay macro (it's stored in text form) and compile it into
718 an executable program "prog" */
719 - prog = ParseMacro(ReplayMacro, &errMsg, &stoppedAt);
720 + prog = ParseMacro(ReplayMacro, &errMsg, &stoppedAt, "replay macro");
721 if (prog == NULL) {
722 fprintf(stderr,
723 "NEdit internal error, learn/replay macro syntax error: %s\n",
724 @@ -965,7 +965,7 @@ static int readCheckMacroString(Widget d
725 return ParseError(dialogParent, string, inPtr,
726 errIn, "expected '{'");
728 - prog = ParseMacro(inPtr, &errMsg, &stoppedAt);
729 + prog = ParseMacro(inPtr, &errMsg, &stoppedAt, subrName);
730 if (prog == NULL) {
731 if (errPos != NULL) *errPos = stoppedAt;
732 return ParseError(dialogParent, string, stoppedAt,
733 @@ -993,7 +993,7 @@ static int readCheckMacroString(Widget d
734 definitions in a file which is loaded from another macro file, it
735 will probably run the code blocks in reverse order! */
736 } else {
737 - prog = ParseMacro(inPtr, &errMsg, &stoppedAt);
738 + prog = ParseMacro(inPtr, &errMsg, &stoppedAt, errIn);
739 if (prog == NULL) {
740 if (errPos != NULL) {
741 *errPos = stoppedAt;
742 @@ -1296,7 +1296,7 @@ void DoMacro(WindowInfo *window, const c
743 tMacro[macroLen+1] = '\0';
745 /* Parse the macro and report errors if it fails */
746 - prog = ParseMacro(tMacro, &errMsg, &stoppedAt);
747 + prog = ParseMacro(tMacro, &errMsg, &stoppedAt, errInName);
748 if (prog == NULL) {
749 ParseError(window->shell, tMacro, stoppedAt, errInName, errMsg);
750 XtFree(tMacro);
751 @@ -1560,7 +1560,7 @@ selEnd += $text_length - startLength\n}\
752 sprintf(loopedCmd, loopMacro, how, command);
754 /* Parse the resulting macro into an executable program "prog" */
755 - prog = ParseMacro(loopedCmd, &errMsg, &stoppedAt);
756 + prog = ParseMacro(loopedCmd, &errMsg, &stoppedAt, "repeat macro");
757 if (prog == NULL) {
758 fprintf(stderr, "NEdit internal error, repeat macro syntax wrong: %s\n",
759 errMsg);
760 diff --quilt old/source/nedit.c new/source/nedit.c
761 --- old/source/nedit.c
762 +++ new/source/nedit.c
763 @@ -832,7 +832,7 @@ static int checkDoMacroArg(const char *m
764 tMacro[macroLen+1] = '\0';
766 /* Do a test parse */
767 - prog = ParseMacro(tMacro, &errMsg, &stoppedAt);
768 + prog = ParseMacro(tMacro, &errMsg, &stoppedAt, "-do Argument");
769 XtFree(tMacro);
770 if (prog == NULL) {
771 ParseError(NULL, tMacro, stoppedAt, "argument to -do", errMsg);
772 diff --quilt old/source/parse.h new/source/parse.h
773 --- old/source/parse.h
774 +++ new/source/parse.h
775 @@ -30,6 +30,6 @@
777 #include "interpret.h"
779 -Program *ParseMacro(char *expr, char **msg, char **stoppedAt);
780 +Program *ParseMacro(char *expr, char **msg, char **stoppedAt, const char *name);
782 #endif /* NEDIT_PARSE_H_INCLUDED */
783 diff --quilt old/source/parse.y new/source/parse.y
784 --- old/source/parse.y
785 +++ new/source/parse.y
786 @@ -548,9 +548,10 @@ blank: /* nothing */
787 ** as a pointer to a static string in msg, and the length of the string up
788 ** to where parsing failed in stoppedAt.
790 -Program *ParseMacro(char *expr, char **msg, char **stoppedAt)
791 +Program *ParseMacro(char *expr, char **msg, char **stoppedAt, const char *name)
793 Program *prog;
794 + static const char *prefix = ">> ";
796 BeginCreatingProgram();
798 @@ -568,6 +569,12 @@ Program *ParseMacro(char *expr, char **m
799 /* get the newly created program */
800 prog = FinishCreatingProgram();
802 + if (!name)
803 + name = "--unknown--";
805 + prog->name = XtMalloc(strlen(name) + strlen(prefix) + 1);
806 + strcat(strcpy(prog->name, prefix), name);
808 /* parse succeeded */
809 *msg = "";
810 *stoppedAt = InPtr;
811 diff --quilt old/source/parse_noyacc.c new/source/parse_noyacc.c
812 --- old/source/parse_noyacc.c
813 +++ new/source/parse_noyacc.c
814 @@ -746,9 +746,10 @@ int yystacksize;
815 ** as a pointer to a static string in msg, and the length of the string up
816 ** to where parsing failed in stoppedAt.
818 -Program *ParseMacro(char *expr, char **msg, char **stoppedAt)
819 +Program *ParseMacro(char *expr, char **msg, char **stoppedAt, const char *name)
821 Program *prog;
822 + static const char *prefix = ">> ";
824 BeginCreatingProgram();
826 @@ -766,6 +767,12 @@ Program *ParseMacro(char *expr, char **m
827 /* get the newly created program */
828 prog = FinishCreatingProgram();
830 + if (!name)
831 + name = "--unknown--";
833 + prog->name = XtMalloc(strlen(name) + strlen(prefix) + 1);
834 + strcat(strcpy(prog->name, prefix), name);
836 /* parse succeeded */
837 *msg = "";
838 *stoppedAt = InPtr;
839 diff --quilt old/source/smartIndent.c new/source/smartIndent.c
840 --- old/source/smartIndent.c
841 +++ new/source/smartIndent.c
842 @@ -747,17 +747,17 @@ void BeginSmartIndent(WindowInfo *window
843 winData->inNewLineMacro = 0;
844 winData->inModMacro = 0;
845 winData->newlineMacro = ParseMacro(indentMacros->newlineMacro, &errMsg,
846 - &stoppedAt);
847 + &stoppedAt, "smart indent newline macro");
848 if (winData->newlineMacro == NULL) {
849 ParseError(window->shell, indentMacros->newlineMacro, stoppedAt,
850 - "newline macro", errMsg);
851 + "smart indent newline macro", errMsg);
852 return;
854 if (indentMacros->modMacro == NULL)
855 winData->modMacro = NULL;
856 else {
857 winData->modMacro = ParseMacro(indentMacros->modMacro, &errMsg,
858 - &stoppedAt);
859 + &stoppedAt, "smart indent modify macro");
860 if (winData->modMacro == NULL) {
861 ParseError(window->shell, indentMacros->modMacro, stoppedAt,
862 "smart indent modify macro", errMsg);
863 @@ -1431,7 +1431,8 @@ static int checkSmartIndentDialogData(vo
866 widgetText = ensureNewline(XmTextGetString(SmartIndentDialog.newlineMacro));
867 - prog = ParseMacro(widgetText, &errMsg, &stoppedAt);
868 + prog = ParseMacro(widgetText, &errMsg, &stoppedAt,
869 + "smart indent newline macro");
870 if (prog == NULL) {
871 ParseError(SmartIndentDialog.shell, widgetText, stoppedAt,
872 "newline macro", errMsg);
873 @@ -1447,7 +1448,8 @@ static int checkSmartIndentDialogData(vo
874 /* Test compile the modify macro */
875 if (!TextWidgetIsBlank(SmartIndentDialog.modMacro)) {
876 widgetText = ensureNewline(XmTextGetString(SmartIndentDialog.modMacro));
877 - prog = ParseMacro(widgetText, &errMsg, &stoppedAt);
878 + prog = ParseMacro(widgetText, &errMsg, &stoppedAt,
879 + "smart indent modify macro");
880 if (prog == NULL) {
881 ParseError(SmartIndentDialog.shell, widgetText, stoppedAt,
882 "modify macro", errMsg);
883 diff --quilt old/source/userCmds.c new/source/userCmds.c
884 --- old/source/userCmds.c
885 +++ new/source/userCmds.c
886 @@ -241,6 +241,8 @@ static Widget BGMenuPasteReplayBtn = NUL
887 static void editMacroOrBGMenu(WindowInfo *window, int dialogType);
888 static void dimSelDepItemsInMenu(Widget menuPane, menuItemRec **menuList,
889 int nMenuItems, int sensitive);
890 +static int doMacroMenuCmd(WindowInfo *window, const char *itemName,
891 + menuItemRec **menu, int nMenu, const char *menuName);
892 static void rebuildMenuOfAllWindows(int menuType);
893 static void rebuildMenu(WindowInfo *window, int menuType);
894 static Widget findInMenuTree(menuTreeItem *menuTree, int nTreeEntries,
895 @@ -1260,30 +1262,37 @@ int DoNamedShellMenuCmd(WindowInfo *wind
896 ** with menu item name "itemName". Returns True on successs and False on
897 ** failure.
899 -int DoNamedMacroMenuCmd(WindowInfo *window, const char *itemName)
900 +static int doMacroMenuCmd(WindowInfo *window, const char *itemName,
901 + menuItemRec **menu, int nMenu, const char *menuName)
903 int i;
905 - for (i=0; i<NMacroMenuItems; i++) {
906 - if (!strcmp(MacroMenuItems[i]->name, itemName)) {
907 - DoMacro(window, MacroMenuItems[i]->cmd, "macro menu command");
908 - return True;
910 + char *name = NULL;
911 + Boolean result = False;
913 + for (i = 0; i < nMenu; i++) {
914 + if (!strcmp(menu[i]->name, itemName)) {
915 + name = XtMalloc(strlen(menuName) + strlen(itemName) + 1);
916 + strcat(strcpy(name, menuName), itemName);
917 + DoMacro(window, menu[i]->cmd, name);
918 + result = True;
921 - return False;
922 + if (name) {
923 + XtFree(name);
925 + return result;
928 +int DoNamedMacroMenuCmd(WindowInfo *window, const char *itemName)
930 + return doMacroMenuCmd(window, itemName, MacroMenuItems, NMacroMenuItems,
931 + "macro-menu>");
934 int DoNamedBGMenuCmd(WindowInfo *window, const char *itemName)
936 - int i;
938 - for (i=0; i<NBGMenuItems; i++) {
939 - if (!strcmp(BGMenuItems[i]->name, itemName)) {
940 - DoMacro(window, BGMenuItems[i]->cmd, "background menu macro");
941 - return True;
944 - return False;
945 + return doMacroMenuCmd(window, itemName, BGMenuItems, NBGMenuItems,
946 + "background-menu>");
950 @@ -2080,7 +2089,7 @@ static int checkMacroText(char *macro, W
951 Program *prog;
952 char *errMsg, *stoppedAt;
954 - prog = ParseMacro(macro, &errMsg, &stoppedAt);
955 + prog = ParseMacro(macro, &errMsg, &stoppedAt, "macro");
956 if (prog == NULL) {
957 if (errorParent != NULL) {
958 ParseError(errorParent, macro, stoppedAt, "macro", errMsg);
959 @@ -3019,7 +3028,7 @@ static char *copyMacroToEnd(char **inPtr
962 /* Parse the input */
963 - prog = ParseMacro(*inPtr, &errMsg, &stoppedAt);
964 + prog = ParseMacro(*inPtr, &errMsg, &stoppedAt, "macro menu item");
965 if (prog == NULL) {
966 ParseError(NULL, *inPtr, stoppedAt, "macro menu item", errMsg);
967 return NULL;