drops and reorders
[nedit-bw.git] / InterpretDebug5.diff
blob43cb2f8187737dc29f1f1c49dbe70697d97a29bd
1 From: Tony Balinski <ajbj@free.fr>
2 Subject: Provide NEdit Macro stack traces
4 Avaliable as a patch:
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
14 lies.
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
28 favorite macros!
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.
43 ---
45 source/interpret.c | 405 +++++++++++++++++++++++++++++++++++++++++---------
46 source/interpret.h | 2
47 source/macro.c | 9 -
48 source/nedit.c | 4
49 source/parse.h | 3
50 source/parse.y | 10 +
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
60 #include "text.h"
61 #include "rbTree.h"
63 +#include <unistd.h>
64 #include <stdio.h>
65 +#include <stdarg.h>
66 #include <stdlib.h>
67 #include <string.h>
68 #include <math.h>
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,
135 + const char *name)
137 static DataValue noValue = {NO_TAG, {0}};
138 int i;
139 @@ -475,6 +488,17 @@ static void setupFrame(DataValue **frame
140 (*stackP)->val.dataval = *frameP;
141 (*stackP)++;
143 + /* symbol table */
144 + (*stackP)->tag = NO_TAG;
145 + (*stackP)->val.sym = prog->localSymList;
146 + (*stackP)++;
148 + /* macro name */
149 + (*stackP)->tag = STRING_TAG;
150 + (*stackP)->val.str.rep = name;
151 + (*stackP)->val.str.len = strlen(name);
152 + (*stackP)++;
154 /* nArgs */
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 */
159 prog->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)
177 STACKDUMP(0, 3);
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;
187 prog->refcount++;
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);
191 return STAT_OK;
194 @@ -2713,7 +2738,7 @@ static int arrayRef(void)
195 PC++;
197 DISASM_RT(PC-2, 2);
198 - STACKDUMP(nDim, 3);
199 + STACKDUMP(nDim+1, 3);
201 if (nDim > 0) {
202 errNum = makeArrayKeyFromArgs(nDim, &keyString, 0);
203 @@ -2764,7 +2789,7 @@ static int arrayAssign(void)
204 PC++;
206 DISASM_RT(PC-2, 1);
207 - STACKDUMP(nDim, 3);
208 + STACKDUMP(nDim+2, 3);
210 if (nDim > 0) {
211 POP(srcValue);
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)
225 PC++;
227 DISASM_RT(PC-3, 3);
228 - STACKDUMP(nDim + 1, 3);
229 + STACKDUMP(nDim + (binaryOp ? 2 : 1), 3);
231 if (binaryOp) {
232 POP(moveExpr);
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)
241 + int len;
242 + const char *op;
243 + char *np;
244 + DataValue *nfp = fp;
246 +#ifdef DEBUG_STACK
247 + const char *dump;
248 + printd("\n\n");
249 + disasmInternal(PC - 1, 1);
250 + stackdumpInternal(0, 50);
251 + dump = printd(NULL);
252 +#endif
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;
259 +#ifdef DEBUG_STACK
260 + len += strlen(dump);
261 +#endif
262 + if (*pLen < len)
264 + *s = *s ? XtRealloc(*s, len) : XtMalloc(len);
265 + *pLen = len;
267 + /* now copy */
268 + np = *s;
269 + op = msg;
270 + while (*op)
271 + *np++ = *op++;
273 + for (nfp = fp; nfp; nfp = FP_GET_OLD_FP(nfp)) {
274 + *np++ = '\n';
275 + op = FP_GET_ITEM(nfp, FP_FUNCTION_NAME).val.str.rep;
276 + while (*op)
277 + *np++ = *op++;
279 +#ifdef DEBUG_STACK
280 + op = dump;
281 + while (*op)
282 + *np++ = *op++;
283 +#endif
285 + *np = 0;
286 + return *s;
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);
301 - ErrMsg = msg;
302 + ErrMsg = stackDumpStr(FrameP, msg, &err, &errlen);
303 return STAT_ERROR;
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, ...)
316 + char buffer[4096];
317 + int len;
318 + va_list args;
320 + if (!f)
322 + printdPos = 0; /* reset for next time */
323 + return printdBuffer;
326 + va_start(args, f);
327 + vsprintf(buffer, f, args);
328 + va_end(args);
330 + len = strlen(buffer);
331 + if (!printdBuffer)
333 + printdSize = 4096;
334 + printdBuffer = XtMalloc(printdSize);
335 + printdPos = 0;
337 + else
339 + int needSize = printdPos + len + 1;
340 + if (needSize > printdSize)
342 + int newSize = printdSize;
343 + while (newSize < needSize)
344 + newSize *= 2;
345 + printdBuffer = XtRealloc(printdBuffer, newSize);
346 + printdSize = newSize;
349 + strcpy(&printdBuffer[printdPos], buffer);
350 + printdPos += len;
352 + return printdBuffer;
355 +int outPrintd()
357 + const char *s = printd(NULL);
358 + const char *cp;
360 + static int outIsTTY = -1;
361 + if (outIsTTY == -1)
362 + outIsTTY = isatty(fileno(stdout));
364 + if (outIsTTY)
366 + for (cp = s; *cp; cp++)
367 + if (*cp == '\n')
368 + printf("\033[K\n");
369 + else
370 + putchar(*cp);
372 + else
374 + for (cp = s; *cp; cp++)
375 + putchar(*cp);
377 + return cp - s;
379 +#endif /* #ifdef DEBUG_DISASSEMBLER */
381 +#ifdef DEBUG_DISASSEMBLER /* dumping values in disassembly or stack dump */
382 static void dumpVal(DataValue dv)
384 switch (dv.tag) {
385 case INT_TAG:
386 - printf("i=%d", dv.val.n);
387 + printd("i=%d", dv.val.n);
388 break;
389 case STRING_TAG:
391 @@ -3148,38 +3300,39 @@ static void dumpVal(DataValue dv)
392 char s[21];
393 char *src = dv.val.str.rep;
394 if (!src) {
395 - printf("s=<NULL>");
396 + printd("s=<NULL>");
398 else {
399 for (k = 0; src[k] && k < sizeof s - 1; k++) {
400 s[k] = isprint(src[k]) ? src[k] : '?';
402 s[k] = 0;
403 - printf("s=\"%s\"%s[%d]", s,
404 + printd("s=\"%s\"%s[%d]", s,
405 src[k] ? "..." : "", strlen(src));
408 break;
409 case ARRAY_TAG:
410 - printf("<%s>", tagToStr(ARRAY_TAG));
411 + printd("%08p <%s>[%d]", dv.val.arrayPtr, tagToStr(ARRAY_TAG),
412 + ArraySize(&dv));
413 break;
414 case NO_TAG:
415 if (!dv.val.inst) {
416 - printf("<%s>", tagToStr(NO_TAG));
417 + printd("<%s>", tagToStr(NO_TAG));
419 else {
420 - printf("?%8p", dv.val.inst);
421 + printd("?%8p", dv.val.inst);
423 break;
424 default:
425 - printf("UNKNOWN DATA TAG %d ?%8p", dv.tag, dv.val.inst);
426 + printd("UNKNOWN DATA TAG %d ?%8p", dv.tag, dv.val.inst);
427 break;
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
440 int i, j;
442 - printf("\n");
443 + printd("\n");
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) {
457 dumpVal(sym->value);
458 @@ -3204,29 +3357,29 @@ static void disasm(Inst *inst, int nInst
459 ++i;
461 else if (j == OP_PUSH_IMMED) {
462 - printf("i=%d", inst[i+1].value);
463 + printd("i=%d", inst[i+1].value);
464 ++i;
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);
471 ++i;
473 else if (j == OP_CONCAT) {
474 - printf("nExpr=%d", inst[i+1].value);
475 + printd("nExpr=%d", inst[i+1].value);
476 ++i;
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);
481 i += 2;
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);
486 ++i;
488 else if (j == OP_ARRAY_ITER) {
489 - printf("%s = %s++ end-loop=(%d) %p",
490 + printd("%s = %s++ end-loop=(%d) %p",
491 inst[i+1].sym->name,
492 inst[i+2].sym->name,
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);
500 ++i;
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);
507 i += 2;
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");
514 ++i;
517 - printf("\n");
518 + printd("\n");
519 break;
522 if (j == N_OPS) {
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"); }
536 + outPrintd();
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);
546 - int i, offset;
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++) {
550 - char *pos = "";
551 - DataValue *dv = &StackP[-i - 1];
552 - if (dv < TheStack) {
553 - printf("--------------Stack base--------------\n");
554 - break;
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);
563 + DataValue *dv;
564 + DataValue *endDv = (arg1 > outpt) ? arg1 : outpt;
565 + int nArgs = FP_GET_ARG_COUNT(fp);
567 + int nSyms;
568 + static int symLen = 0;
569 + Symbol *syms = FP_GET_ITEM(fp, FP_SYMBOL_TABLE).val.sym;
570 + Symbol *sym;
572 +#ifdef DEBUG_STACK_HEADFIRST
573 +#else
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) {
582 + nSyms++;
583 + if (symLen < 27) {
584 + int len = strlen(sym->name);
585 + if (len > 27)
586 + len = 27;
587 + if (len > symLen)
588 + symLen = len;
590 - offset = dv - FrameP;
593 + /* output instructions between endDv and sp - 1 inclusive */
594 +#ifdef DEBUG_STACK_HEADFIRST
595 + dv = sp;
596 + while (--dv >= endDv)
597 +#else
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);
606 + char *pos = "";
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);
614 switch (offset) {
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;
628 default:
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);
638 + posFmt = "%6s ";
640 + else if (offset == 0) {
641 + pos = "FrameP";
643 break;
645 - printf("%-6s ", pos);
646 - dumpVal(*dv);
647 - printf("\n");
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;
655 + break;
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);
663 + else
664 + dumpVal(*dv);
666 + printd("\n");
669 +#ifdef DEBUG_STACK_HEADFIRST
670 + /* do caller's frame */
671 + if (oldFP || arg1 > endDv)
672 + stackdumpframe(arrow, outpt, oldFP, arg1, ' ');
673 +#else
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");
687 +#else
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);
703 + if (outIsTTY)
704 + printd("\033[J\n");
706 + outPrintd();
707 + fflush(stdout);
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 {
715 Inst* inst;
716 struct DataValueTag* dataval;
717 struct SparseArrayEntryTag *arrayPtr;
718 + struct SymbolRec *sym;
719 } val;
720 } DataValue;
722 @@ -107,6 +108,7 @@ typedef struct ProgramTag {
723 Symbol *localSymList;
724 Inst *code;
725 unsigned refcount;
726 + char *name;
727 } Program;
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,
739 + "replay macro");
740 if (prog == NULL) {
741 fprintf(stderr,
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;
745 Program *prog;
747 - prog = ParseMacro(string, &errMsg, &stoppedAt, True);
748 + prog = ParseMacro(string, &errMsg, &stoppedAt, True, errIn);
749 if (prog == NULL) {
750 if (errPos != NULL) {
751 *errPos = stoppedAt;
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);
758 if (prog == NULL) {
759 ParseError(window->shell, tMacro, stoppedAt, errInName, errMsg);
760 XtFree(tMacro);
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");
767 if (prog == NULL) {
768 fprintf(stderr, "NEdit internal error, repeat macro syntax wrong: %s\n",
769 errMsg);
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");
779 XtFree(tMacro);
780 if (prog == NULL) {
781 - ParseError(NULL, tMacro, stoppedAt, "argument to -do", errMsg);
782 + ParseError(NULL, tMacro, stoppedAt, "-do macro", errMsg);
783 return False;
785 FreeProgram(prog);
786 diff --quilt old/source/parse.h new/source/parse.h
787 --- old/source/parse.h
788 +++ new/source/parse.h
789 @@ -30,6 +30,7 @@
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,
795 + const char *name);
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,
807 + const char *name)
809 Program *prog;
810 AccumulatorData *acc = XtNew(AccumulatorData);
811 + static const char *prefix = ">> ";
813 #if YYDEBUG
814 int oldyydebug = yydebug;
815 @@ -670,6 +672,12 @@ Program *ParseMacro(char *expr, char **m
816 prog = FinishCreatingProgram(acc);
817 XtFree((char *)acc);
819 + if (!name)
820 + name = "--unknown--";
822 + prog->name = XtMalloc(strlen(name) + strlen(prefix) + 1);
823 + strcat(strcpy(prog->name, prefix), name);
825 /* parse succeeded */
826 *msg = "";
827 *stoppedAt = InPtr;
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)
838 Program *prog;
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();
847 + if (!name)
848 + name = "--unknown--";
850 + prog->name = XtMalloc(strlen(name) + strlen(prefix) + 1);
851 + strcat(strcpy(prog->name, prefix), name);
853 /* parse succeeded */
854 *msg = "";
855 *stoppedAt = InPtr;
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);
871 return;
873 if (indentMacros->modMacro == NULL)
874 winData->modMacro = NULL;
875 else {
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");
898 if (prog == NULL) {
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");
912 if (prog == NULL) {
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
933 ** failure.
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)
939 int i;
941 - for (i=0; i<NMacroMenuItems; i++) {
942 - if (!strcmp(MacroMenuItems[i]->name, itemName)) {
943 - DoMacro(window, MacroMenuItems[i]->cmd, "macro menu command");
944 - return True;
946 + char *name = NULL;
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);
954 + result = True;
957 - return False;
958 + if (name) {
959 + XtFree(name);
961 + return result;
964 +int DoNamedMacroMenuCmd(WindowInfo *window, const char *itemName)
966 + return doMacroMenuCmd(window, itemName, MacroMenuItems, NMacroMenuItems,
967 + "macro-menu>");
970 int DoNamedBGMenuCmd(WindowInfo *window, const char *itemName)
972 - int i;
974 - for (i=0; i<NBGMenuItems; i++) {
975 - if (!strcmp(BGMenuItems[i]->name, itemName)) {
976 - DoMacro(window, BGMenuItems[i]->cmd, "background menu macro");
977 - return True;
980 - return False;
981 + return doMacroMenuCmd(window, itemName, BGMenuItems, NBGMenuItems,
982 + "background-menu>");
986 @@ -2080,7 +2089,7 @@ static int checkMacroText(char *macro, W
987 Program *prog;
988 char *errMsg, *stoppedAt;
990 - prog = ParseMacro(macro, &errMsg, &stoppedAt, False);
991 + prog = ParseMacro(macro, &errMsg, &stoppedAt, False, "macro");
992 if (prog == NULL) {
993 if (errorParent != NULL) {
994 ParseError(errorParent, macro, stoppedAt, "macro", errMsg);
995 @@ -2092,7 +2101,7 @@ static int checkMacroText(char *macro, W
996 FreeProgram(prog);
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");
1010 if (prog == NULL) {
1011 ParseError(NULL, *inPtr, stoppedAt, "macro menu item", errMsg);
1012 return NULL;