MultipleAssignment selectors
[nedit-bw.git] / symbol-lookup.patch
blob19cdc07f0e4647b4b8906e14b293ac4450e33271
1 ---
3 source/interpret.c | 616 ++++++++++++++++++++++++++---------------------------
4 source/interpret.h | 27 --
5 source/macro.c | 6
6 source/ops.h | 1
7 source/parse.y | 82 +++----
8 5 files changed, 360 insertions(+), 372 deletions(-)
10 diff --quilt old/source/interpret.c new/source/interpret.c
11 --- old/source/interpret.c
12 +++ new/source/interpret.c
13 @@ -170,7 +170,6 @@ static AccumulatorData *Accumulator;
14 #define ProgP (Accumulator->progP)
15 #define LoopStack (Accumulator->loopStack)
16 #define LoopStackPtr (Accumulator->loopStackPtr)
17 -#define LocalSymList (Accumulator->localSymList)
18 #define ProgramName (Accumulator->name)
20 /* Global data for the interpreter */
21 @@ -212,8 +211,8 @@ static int (*OpFns[])() = {
22 #define FP_GET_PROG(xFrameP) ((FP_GET_ITEM(xFrameP, FP_PROG_INDEX)).val.prog)
23 #define FP_ARG_START_INDEX(xFrameP) (-(FP_GET_ARG_COUNT(xFrameP) + FP_TO_ARGS_DIST))
24 #define FP_GET_ARG_N(xFrameP,xN) (FP_GET_ITEM(xFrameP, xN + FP_ARG_START_INDEX(xFrameP)))
25 -#define FP_GET_SYM_N(xFrameP,xN) (FP_GET_ITEM(xFrameP, xN))
26 -#define FP_GET_SYM_VAL(xFrameP,xSym) (FP_GET_SYM_N(xFrameP, xSym->value.val.n))
27 +#define FP_GET_SYM_TAB(xFrameP) (FP_GET_ITEM(xFrameP, FP_SYMBOL_TABLE).val.sym)
28 +#define LocalSymList FP_GET_SYM_TAB(Interpreter->frameP)
31 ** Initialize macro language global variables. Must be called before
32 @@ -266,10 +265,9 @@ void InitMacroGlobals(void)
33 AccumulatorData *BeginCreatingProgram(const char *name)
35 AccumulatorData *old = Accumulator;
36 - Accumulator = (AccumulatorData *)XtMalloc(sizeof(*Accumulator));
37 + Accumulator = XtNew(AccumulatorData);
38 memset(Accumulator, 0, sizeof(*Accumulator));
40 - LocalSymList = NULL;
41 ProgP = Prog;
42 LoopStackPtr = LoopStack;
43 ProgramName = name;
44 @@ -285,22 +283,15 @@ AccumulatorData *BeginCreatingProgram(co
45 Program *FinishCreatingProgram(AccumulatorData *old)
47 Program *newProg;
48 - int progLen, fpOffset = 0;
49 - Symbol *s;
50 + int progLen;
52 - newProg = (Program *)XtMalloc(sizeof(Program) + strlen(ProgramName));
53 + newProg = XtNew(Program);
54 + newProg->name = LookupString(ProgramName, True);
55 progLen = ProgP - Prog;
56 - newProg->code = (Inst *)XtMalloc(progLen * sizeof(Inst));
57 + newProg->code = (Inst *)XtCalloc(progLen, sizeof(Inst));
58 memcpy(newProg->code, Prog, progLen * sizeof(Inst));
59 - newProg->localSymList = LocalSymList;
60 - strcpy(newProg->name, ProgramName);
61 newProg->refcount = 1;
63 - /* Local variables' values are stored on the stack. Here we assign
64 - frame pointer offsets to them. */
65 - for (s = newProg->localSymList; s != NULL; s = s->next)
66 - s->value.val.n = fpOffset++;
68 DISASM(newProg->name, newProg->code, ProgP - Prog);
70 XtFree((char *)Accumulator);
71 @@ -312,7 +303,6 @@ Program *FinishCreatingProgram(Accumulat
72 void FreeProgram(Program *prog)
74 if (--prog->refcount == 0) {
75 - freeSymbolList(prog->localSymList);
76 XtFree((char *)prog->code);
77 XtFree((char *)prog);
79 @@ -336,14 +326,14 @@ int AddOp(int op, char **msg)
81 ** Add a symbol operand to the current program
83 -int AddSym(Symbol *sym, char **msg)
84 +int AddSym(const char *sym, char **msg)
86 if (ProgP >= &Prog[PROGRAM_SIZE]) {
87 *msg = "macro too large";
88 return 0;
90 ProgP->type = SYM_INST;
91 - ProgP->val.sym = sym;
92 + ProgP->val.str = sym;
93 ProgP++;
94 return 1;
96 @@ -364,6 +354,21 @@ int AddImmediate(int immed, char **msg)
100 +** Add an string value operand to the current program
102 +int AddString(const char *str, char **msg)
104 + if (ProgP >= &Prog[PROGRAM_SIZE]) {
105 + *msg = "macro too large";
106 + return 0;
108 + ProgP->type = STRING_INST;
109 + ProgP->val.str = str;
110 + ProgP++;
111 + return 1;
115 ** Add a branch offset operand to the current program
117 int AddBranchOffset(Inst *to, char **msg)
118 @@ -507,7 +512,6 @@ static int setupFrame(RestartData *conte
120 static DataValue noValue = {NO_TAG, {0}};
121 int i, totalPushs = 7;
122 - Symbol *s;
125 ** we push only if we have room for the whole frame, so pre-calc the
126 @@ -516,9 +520,6 @@ static int setupFrame(RestartData *conte
127 if (nArgs >= 0) {
128 totalPushs += nArgs;
130 - for (s = prog->localSymList; s != NULL; s = s->next) {
131 - totalPushs++;
134 /* !OK_TO_PUSH(totalPushs) */
135 if (!((context->stackP + totalPushs) <= (context->stack + STACK_SIZE))) {
136 @@ -556,14 +557,14 @@ static int setupFrame(RestartData *conte
137 context->stackP->val.dataval = context->frameP;
138 context->stackP++;
140 - /* symbol table */
141 + /* start a new local symbol list */
142 context->stackP->tag = NO_TAG;
143 - context->stackP->val.sym = prog->localSymList;
144 + context->stackP->val.sym = NULL;
145 context->stackP++;
147 /* macro name */
148 context->stackP->tag = STRING_TAG;
149 - context->stackP->val.str.rep = name;
150 + context->stackP->val.str.rep = (char *)name;
151 context->stackP->val.str.len = strlen(name);
152 context->stackP++;
154 @@ -574,12 +575,6 @@ static int setupFrame(RestartData *conte
156 context->frameP = context->stackP;
158 - /* Initialize and make room on the stack for local variables */
159 - for (s = prog->localSymList; s != NULL; s = s->next) {
160 - FP_GET_SYM_VAL(context->frameP, s) = noValue;
161 - context->stackP++;
164 context->pc = prog->code;
166 return STAT_OK;
167 @@ -592,6 +587,9 @@ static void rewindFrame(RestartData *con
168 DataValue *newFrameP = FP_GET_OLD_FP(context->frameP);
169 Inst *newPC = FP_GET_RET_PC(context->frameP);
170 Program *prog = FP_GET_PROG(context->frameP);
171 + Symbol *symList = FP_GET_SYM_TAB(context->frameP);
173 + freeSymbolList(symList);
175 /* pop past local variables */
176 context->stackP = context->frameP;
177 @@ -636,7 +634,7 @@ int ExecuteMacro(WindowInfo *window, Pro
178 /* Create an execution context (a stack, a stack pointer, a frame pointer,
179 and a program counter) which will retain the program state across
180 preemption and resumption of execution */
181 - context = (RestartData *)XtMalloc(sizeof(RestartData));
182 + context = XtNew(RestartData);
183 memset(context, 0, sizeof(*context));
184 *continuation = context;
185 context->stackP = context->stack;
186 @@ -817,72 +815,12 @@ void SetMacroFocusWindow(WindowInfo *win
191 -** install a list assign (multi-assign) rvalue expression holder into the local
192 -** namespace.
194 -Symbol *InstallMultiAssignExpr(void)
196 - static const char symbolName[] = "list assign expr";
197 - Symbol *sym = LookupSymbol(symbolName);
198 - DataValue value;
199 - value.tag = NO_TAG;
200 - value.val.n = 0;
201 - if (!sym) {
202 - sym = InstallSymbol(symbolName, LOCAL_SYM, value);
204 - return sym;
208 -** Lookup a constant string by its value. This allows reuse of string
209 -** constants and fixing a leak in the interpreter.
211 -Symbol *LookupStringConstSymbol(const char *value)
213 - unsigned int idx;
214 - Symbol *s;
216 - for (idx = 0; idx < GLOBAL_SYMTAB_SIZE; idx++) {
217 - for (s = GlobalSymTab[idx]; s != NULL; s = s->next) {
218 - if (s->type == CONST_SYM
219 - && s->value.tag == STRING_TAG
220 - && !strcmp(s->value.val.str.rep, value)) {
221 - return(s);
226 - return(NULL);
230 -** install string str in the global symbol table with a string name
232 -#define STRING_CONST_SYM_PREFIX "string #"
233 -Symbol *InstallStringConstSymbol(const char *str)
235 - static int stringConstIndex;
236 - char stringName[sizeof(STRING_CONST_SYM_PREFIX) + TYPE_INT_STR_SIZE(int)];
237 - DataValue value;
239 - Symbol *sym = LookupStringConstSymbol(str);
240 - if (sym) {
241 - return sym;
244 - sprintf(stringName, STRING_CONST_SYM_PREFIX "%d", stringConstIndex++);
245 - value.tag = STRING_TAG;
246 - AllocNStringCpy(&value.val.str, str);
247 - return(InstallSymbol(stringName, CONST_SYM, value));
250 static Symbol *lookupSymbol(const Symbol *symlist, const char *name,
251 unsigned int hash)
253 while (NULL != symlist) {
254 if (hash == symlist->hash && strcmp(symlist->name, name) == 0)
255 - return symlist;
256 + return (Symbol *)symlist;
257 symlist = symlist->next;
260 @@ -891,17 +829,20 @@ static Symbol *lookupSymbol(const Symbol
263 ** find a symbol in the symbol table
265 +** will create only LOCAL_SYM and GLOBAL_SYM (depending on first character)
266 +** with a NO_TAG value
268 -Symbol *LookupSymbol(const char *name)
269 +Symbol *LookupSymbol(const char *name, int create)
271 unsigned int hash;
272 - Symbol *s;
273 + Symbol *s = NULL;
275 /* calculate hash for name */
276 hash = hashName(name);
278 /* search in local symbols */
279 - if (Accumulator) {
280 + if (Interpreter) {
281 s = lookupSymbol(LocalSymList, name, hash);
282 if (NULL != s)
283 return s;
284 @@ -912,7 +853,13 @@ Symbol *LookupSymbol(const char *name)
285 if (NULL != s)
286 return s;
288 - return NULL;
289 + if (create) {
290 + DataValue noValue = {NO_TAG, {0}};
291 + s = InstallSymbol(name, name[0] == '$' ? GLOBAL_SYM : LOCAL_SYM,
292 + noValue);
295 + return s;
299 @@ -922,15 +869,23 @@ Symbol *InstallSymbol(const char *name,
301 Symbol *s;
303 - /* no +1, because of .name[1] */
304 - s = malloc(sizeof(Symbol) + strlen(name));
305 - strcpy(s->name, name);
306 + s = XtNew(Symbol);
307 + s->name = LookupString(name, True);
308 s->type = type;
309 s->value = value;
310 s->hash = hashName(s->name);
311 if (type == LOCAL_SYM) {
312 - s->next = LocalSymList;
313 - LocalSymList = s;
314 + if (Interpreter) {
315 + s->next = LocalSymList;
316 + LocalSymList = s;
318 + else {
319 + fprintf(stderr,
320 + "NEdit: try to install local sym without "
321 + "macro context: %s\n", name);
322 + XtFree((char *)s);
323 + s = NULL;
325 } else {
326 addToGlobalSymTab(s);
328 @@ -938,70 +893,6 @@ Symbol *InstallSymbol(const char *name,
332 -** Promote a symbol from local to global, removing it from the local symbol
333 -** list.
335 -** This is used as a forward declaration feature for macro functions.
336 -** If a function is called (ie while parsing the macro) where the
337 -** function isn't defined yet, the symbol is put into the GlobalSymList
338 -** so that the function definition uses the same symbol.
341 -Symbol *PromoteToGlobal(Symbol *sym)
343 - Symbol *s;
345 - if (sym->type != LOCAL_SYM)
346 - return sym;
348 - /* Remove sym from the local symbol list */
349 - if (sym == LocalSymList)
350 - LocalSymList = sym->next;
351 - else {
352 - for (s = LocalSymList; s != NULL; s = s->next) {
353 - if (s->next == sym) {
354 - s->next = sym->next;
355 - break;
360 - /* There are two scenarios which could make this check succeed:
361 - a) this sym is in the GlobalSymList as a LOCAL_SYM symbol
362 - b) there is another symbol as a non-LOCAL_SYM in the GlobalSymList
363 - Both are errors, without question.
364 - We currently just print this warning, but we should error out the
365 - parsing process. */
366 - s = LookupSymbol(sym->name);
367 - if (sym == s) {
368 - /* case a)
369 - just make this symbol a GLOBAL_SYM symbol and return */
370 - fprintf(stderr,
371 - "nedit: To boldly go where no local sym has gone before: %s\n",
372 - sym->name);
373 - sym->type = GLOBAL_SYM;
374 - return sym;
375 - } else if (NULL != s) {
376 - /* case b)
377 - sym will shadow the old symbol from the GlobalSymList */
378 - fprintf(stderr,
379 - "nedit: duplicate symbol in LocalSymList and GlobalSymList: %s\n",
380 - sym->name);
383 - /* Add the symbol directly to the GlobalSymList, because InstallSymbol()
384 - will allocate a new Symbol, which results in a memory leak of sym.
385 - Don't use MACRO_FUNCTION_SYM as type, because in
386 - macro.c:readCheckMacroString() we use ProgramFree() for the .val.prog,
387 - but this symbol has no program attached and ProgramFree() is not NULL
388 - pointer safe */
389 - sym->type = GLOBAL_SYM;
390 - addToGlobalSymTab(sym);
392 - return sym;
396 ** Convert a long value to its decimal string representation, returned in a
397 ** static string.
399 @@ -1171,7 +1062,7 @@ static SparseArrayEntry *allocateSparseA
401 SparseArrayEntryWrapper *mem;
403 - mem = (SparseArrayEntryWrapper *)XtMalloc(sizeof(SparseArrayEntryWrapper));
404 + mem = XtNew(SparseArrayEntryWrapper);
405 mem->next = AllocatedSparseArrayEntries;
406 AllocatedSparseArrayEntries = mem;
407 #ifdef TRACK_GARBAGE_LEAKS
408 @@ -1335,14 +1226,19 @@ static void addToGlobalSymTab(Symbol *sy
410 #define EXEC_ERROR(s1, s2) return execError(s1, s2)
412 -#define GET_SYM(s) \
413 +#define GET_SYM(s, create) \
414 do { \
415 + const char *_n; \
416 if (PC->type != SYM_INST) { \
417 EXEC_ERROR("Unexpected instruction, expected <symbol>: <%s>", \
418 instTypeToStr(PC->type)); \
420 - s = PC->val.sym; \
421 + _n = PC->val.str; \
422 + s = LookupSymbol(_n, create); \
423 PC++; \
424 + if (!s) { \
425 + EXEC_ERROR("No such symbol: %s", _n); \
426 + } \
427 } while (0)
429 #define GET_IMMED(i) \
430 @@ -1365,6 +1261,16 @@ static void addToGlobalSymTab(Symbol *sy
431 PC++; \
432 } while (0)
434 +#define GET_STR(s) \
435 + do { \
436 + if (PC->type != STRING_INST) { \
437 + EXEC_ERROR("Unexpected instruction, expected <string>: <%s>", \
438 + instTypeToStr(PC->type)); \
439 + } \
440 + s = PC->val.str; \
441 + PC++; \
442 + } while (0)
444 #define JUMP(a) \
445 do { \
446 PC = (a); \
447 @@ -1543,11 +1449,9 @@ static int pushSymVal(void)
448 DISASM_RT();
449 STACKDUMP(0, 3);
451 - GET_SYM(s);
452 + GET_SYM(s, False);
454 - if (s->type == LOCAL_SYM) {
455 - symVal = FP_GET_SYM_VAL(FrameP, s);
456 - } else if (s->type == GLOBAL_SYM || s->type == CONST_SYM) {
457 + if (s->type == LOCAL_SYM || s->type == GLOBAL_SYM) {
458 symVal = s->value;
459 } else if (s->type == ARG_SYM) {
460 nArgs = FP_GET_ARG_COUNT(FrameP);
461 @@ -1599,6 +1503,27 @@ static int pushImmed(void)
462 return STAT_OK;
466 +** push string onto the stack
467 +** Before: Prog-> [string], next, ...
468 +** TheStack-> next, ...
469 +** After: Prog-> string, [next], ...
470 +** TheStack-> [string], next, ...
472 +static int pushString(void)
474 + const char *str;
476 + DISASM_RT();
477 + STACKDUMP(0, 3);
479 + GET_STR(str);
481 + PUSH_STRING((char *)str, strlen(str));
483 + return STAT_OK;
486 static int pushArgVal(void)
488 int nArgs, argNum;
489 @@ -1676,18 +1601,13 @@ static int pushArraySymVal(void)
490 DISASM_RT();
491 STACKDUMP(0, 3);
493 - GET_SYM(sym);
494 + GET_SYM(sym, True);
495 GET_IMMED(initEmpty);
497 - if (sym->type == LOCAL_SYM) {
498 - dataPtr = &FP_GET_SYM_VAL(FrameP, sym);
500 - else if (sym->type == GLOBAL_SYM) {
501 - dataPtr = &sym->value;
503 - else {
504 + if (sym->type != LOCAL_SYM && sym->type != GLOBAL_SYM) {
505 EXEC_ERROR("assigning to non-lvalue array or non-array: %s", sym->name);
507 + dataPtr = &sym->value;
509 if (initEmpty && dataPtr->tag == NO_TAG) {
510 dataPtr->tag = ARRAY_TAG;
511 @@ -1989,7 +1909,7 @@ static int assign(void)
512 DISASM_RT();
513 STACKDUMP(1, 3);
515 - GET_SYM(sym);
516 + GET_SYM(sym, True);
518 if (sym->type != GLOBAL_SYM && sym->type != LOCAL_SYM) {
519 if (sym->type == ARG_SYM) {
520 @@ -2002,13 +1922,7 @@ static int assign(void)
521 EXEC_ERROR("assignment to non-variable: %s", sym->name);
525 - if (sym->type == LOCAL_SYM) {
526 - dataPtr = &FP_GET_SYM_VAL(FrameP, sym);
528 - else {
529 - dataPtr = &sym->value;
531 + dataPtr = &sym->value;
533 POP(value);
535 @@ -2768,7 +2682,7 @@ static int callSubroutine(void)
537 DISASM_RT();
539 - GET_SYM(sym);
540 + GET_SYM(sym, False);
541 GET_IMMED(nArgs);
543 STACKDUMP(nArgs > 0 ? nArgs : -nArgs, 3);
544 @@ -2794,7 +2708,7 @@ static int callSubroutineStackedN(void)
546 DISASM_RT();
548 - GET_SYM(sym);
549 + GET_SYM(sym, False);
551 PEEK_INT(nArgs, 0);
552 STACKDUMP(-nArgs + 1, 3); /* +1 for stacked nArgs */
553 @@ -2856,25 +2770,15 @@ int OverlayRoutineFromSymbol(Symbol *sym
555 int OverlayRoutineFromProg(Program *prog, int nArgs, int removeArgs)
557 - Symbol *sym;
558 - int ret;
559 + Symbol sym;
561 - /* no +1, because of .name[1] */
562 - sym = malloc(sizeof(Symbol) + strlen(prog->name));
563 - if (NULL == sym) {
564 - return STAT_ERROR;
566 + sym.type = MACRO_FUNCTION_SYM;
567 + sym.name = prog->name;
568 + sym.value.tag = NO_TAG;
569 + sym.value.val.prog = prog;
570 + sym.next = NULL;
572 - sym->type = MACRO_FUNCTION_SYM;
573 - strcpy(sym->name, prog->name);
574 - sym->value.val.prog = prog;
575 - sym->next = NULL;
577 - ret = OverlayRoutineFromSymbol(sym, nArgs, removeArgs);
579 - free(sym);
581 - return ret;
582 + return OverlayRoutineFromSymbol(&sym, nArgs, removeArgs);
586 @@ -3659,35 +3563,25 @@ static int arrayIter(void)
587 STACKDUMP(1, 4);
589 GET_IMMED(withVal);
590 - GET_SYM(keySym);
591 + GET_SYM(keySym, True);
592 if (withVal) {
593 - GET_SYM(valSym);
594 + GET_SYM(valSym, True);
596 GET_BRANCH(branchAddr);
598 POP(iterator);
600 - if (keySym->type == LOCAL_SYM) {
601 - keyValPtr = &FP_GET_SYM_VAL(FrameP, keySym);
603 - else if (keySym->type == GLOBAL_SYM) {
604 - keyValPtr = &(keySym->value);
606 - else {
607 + if (keySym->type != LOCAL_SYM && keySym->type != GLOBAL_SYM) {
608 EXEC_ERROR("can't assign to: %s", keySym->name);
610 + keyValPtr = &keySym->value;
611 keyValPtr->tag = NO_TAG;
613 if (withVal) {
614 - if (valSym->type == LOCAL_SYM) {
615 - valPtr = &FP_GET_SYM_VAL(FrameP, valSym);
617 - else if (valSym->type == GLOBAL_SYM) {
618 - valPtr = &(valSym->value);
620 - else {
621 + if (valSym->type != LOCAL_SYM && valSym->type != GLOBAL_SYM) {
622 EXEC_ERROR("can't assign to: %s", valSym->name);
624 + valPtr = &valSym->value;
625 valPtr->tag = NO_TAG;
628 @@ -3826,37 +3720,27 @@ static int arrayIterArray(void)
629 STACKDUMP(2, 4);
631 GET_IMMED(withVal);
632 - GET_SYM(keyArraySym);
633 + GET_SYM(keyArraySym, True);
634 if (withVal) {
635 - GET_SYM(valSym);
636 + GET_SYM(valSym, True);
638 GET_BRANCH(branchAddr);
640 POP(iterator);
641 PEEK_INT(nDims, 0);
643 - if (keyArraySym->type == LOCAL_SYM) {
644 - keyArrayPtr = &FP_GET_SYM_VAL(FrameP, keyArraySym);
646 - else if (keyArraySym->type == GLOBAL_SYM) {
647 - keyArrayPtr = &(keyArraySym->value);
649 - else {
650 + if (keyArraySym->type != LOCAL_SYM && keyArraySym->type != GLOBAL_SYM) {
651 EXEC_ERROR("can't assign to: %s", keyArraySym->name);
653 + keyArrayPtr = &keyArraySym->value;
654 keyArrayPtr->tag = ARRAY_TAG;
655 keyArrayPtr->val.arrayPtr = NULL;
657 if (withVal) {
658 - if (valSym->type == LOCAL_SYM) {
659 - valPtr = &FP_GET_SYM_VAL(FrameP, valSym);
661 - else if (valSym->type == GLOBAL_SYM) {
662 - valPtr = &valSym->value;
664 - else {
665 + if (valSym->type != LOCAL_SYM && valSym->type != GLOBAL_SYM) {
666 EXEC_ERROR("can't assign to: %s", valSym->name);
668 + valPtr = &valSym->value;
669 valPtr->tag = NO_TAG;
672 @@ -4124,6 +4008,108 @@ static int errCheck(const char *s)
676 +** string lookup stuff
679 +/* should be the pagesize */
680 +#define STRING_BLK_SIZE 4096
682 +typedef struct stringEntryTag {
683 + struct stringEntryTag *next;
684 + unsigned int hash;
685 + char str[1]; /* [1] for inUse */
686 +} stringEntry;
688 +struct stringBlkTag;
689 +typedef struct stringBlkHdrTag {
690 + struct stringBlkTag *next;
691 + unsigned size;
692 + unsigned rem;
693 + stringEntry *free;
694 +} stringBlkHdr;
696 +typedef struct stringBlkTag {
697 + stringBlkHdr hdr;
698 + char blk[];
699 +} stringBlk;
701 +static stringBlk *lookupStringBlks;
702 +#define STR_LOOKUP_TAB_SHIFT 10
703 +#define STR_LOOKUP_TAB_SIZE (1u << (STR_LOOKUP_TAB_SHIFT))
704 +#define STR_LOOKUP_TAB_MASK ((STR_LOOKUP_TAB_SIZE) - 1)
705 +static stringEntry *stringTbl[STR_LOOKUP_TAB_SIZE];
707 +const char *LookupString(const char *str, int doInsert)
709 +#define ROUNDUP(x, align) (void *)(-(-((intptr_t)(x)) & -(align)))
710 + unsigned int len = strlen(str) + 1;
711 + unsigned int hash = hashName(str);
712 + unsigned int idx = hash & STR_LOOKUP_TAB_MASK;
713 + stringBlk **blkp = &lookupStringBlks;
714 + stringBlk *blk;
715 + stringEntry *e;
717 + /* search str in hash table */
718 + for (e = stringTbl[idx]; e; e = e->next) {
719 + if (e->hash == hash && 0 == strcmp(str, &e->str[1]))
720 + return &e->str[1];
722 + if (!doInsert) {
723 + return NULL;
726 + /* find space for str */
727 + while (*blkp) {
728 + if ((*blkp)->hdr.rem >= len) {
729 + break;
731 + blkp = &(*blkp)->hdr.next;
733 + blk = *blkp;
735 + /* no space found, create new string bulk */
736 + if (!blk) {
737 + void *ptr;
738 + unsigned size = (unsigned)ROUNDUP(sizeof(stringBlkHdr), sizeof(void *))
739 + + sizeof(stringEntry) + len;
740 + size = (unsigned)ROUNDUP(size, STRING_BLK_SIZE);
742 + posix_memalign(&ptr, STRING_BLK_SIZE, size);
743 + *blkp = blk = ptr;
744 + blk->hdr.size = size;
745 + blk->hdr.next = NULL;
747 + /* round up to sizeof(void *) */
748 + blk->hdr.free = ROUNDUP(blk->blk, sizeof(void *));
749 + blk->hdr.rem = ((char *)blk + blk->hdr.size)
750 + - blk->hdr.free->str - sizeof(stringEntry);
753 + /* mark string as constant and copy str into bulk */
754 + blk->hdr.free->str[1] = 1;
755 + strcpy(&blk->hdr.free->str[1], str);
756 + str = &blk->hdr.free->str[1];
758 + /* insert string into hash table */
759 + blk->hdr.free->next = stringTbl[idx];
760 + blk->hdr.free->hash = hash;
761 + stringTbl[idx] = blk->hdr.free;
763 + /* calculate remaining space */
764 + blk->hdr.free = ROUNDUP((char *)blk->hdr.free + sizeof(stringEntry) + len,
765 + sizeof(void *));
766 + blk->hdr.rem = ((char *)blk + blk->hdr.size) - blk->hdr.free->str;
767 + if (blk->hdr.rem <= sizeof(stringEntry) + 2) {
768 + blk->hdr.rem = 0;
769 + } else {
770 + blk->hdr.rem -= sizeof(stringEntry);
773 + return str;
774 +#undef ROUNDUP
778 ** build a stack dump string, reallocating s as necessary.
780 static char *stackDumpStr(DataValue *fp, const char *msg, char **s, int *pLen)
781 @@ -4161,7 +4147,7 @@ static char *stackDumpStr(DataValue *fp,
782 #endif
783 if (*pLen < len)
785 - *s = *s ? XtRealloc(*s, len) : XtMalloc(len);
786 + *s = XtRealloc(*s, len);
787 *pLen = len;
789 /* now copy */
790 @@ -4294,6 +4280,8 @@ static const char *instTypeToStr(enum in
791 return "operation";
792 case IMMED_INST:
793 return "immediate";
794 + case STRING_INST:
795 + return "string";
796 case BRANCH_INST:
797 return "branch";
798 case SYM_INST:
799 @@ -4376,6 +4364,41 @@ int outPrintd()
800 #endif /* #ifdef DEBUG_DISASSEMBLER */
802 #ifdef DEBUG_DISASSEMBLER /* dumping values in disassembly or stack dump */
803 +static const char *printableString(const char *src, int *shortaged)
805 + int k, l;
806 + static char s[64];
808 + for (k = 0, l = 0; src[k] && l < sizeof s - 1; k++, l++) {
809 + const char *e;
810 + const char to[] = "\\\"ntbrfave";
811 +#ifdef EBCDIC_CHARSET
812 + const char from[] = "\\\"\n\t\b\r\f\a\v\x27"; /* EBCDIC escape */
813 +#else
814 + const char from[] = "\\\"\n\t\b\r\f\a\v\x1B"; /* ASCII escape */
815 +#endif
816 + if ((e = strchr(from, src[k]))) {
817 + if (l < sizeof s - 2) {
818 + s[l++] = '\\';
819 + s[l] = to[e - from];
822 + else if (isprint(src[k])) {
823 + s[l] = src[k];
825 + else {
826 + s[l] = '?';
829 + s[l] = 0;
831 + if (shortaged) {
832 + *shortaged = !!src[k];
835 + return s;
838 static void dumpVal(DataValue dv)
840 printd(" ");
841 @@ -4392,30 +4415,11 @@ static void dumpVal(DataValue dv)
842 printd("<%s NULL>", tagToStr(STRING_TAG));
844 else {
845 - for (k = 0, l = 0; src[k] && l < sizeof s - 1; k++, l++) {
846 - char *e;
847 - const char to[] = "\\\"ntbrfave";
848 -#ifdef EBCDIC_CHARSET
849 - const char from[] = "\\\"\n\t\b\r\f\a\v\x27"; /* EBCDIC escape */
850 -#else
851 - const char from[] = "\\\"\n\t\b\r\f\a\v\x1B"; /* ASCII escape */
852 -#endif
853 - if ((e = strchr(from, src[k]))) {
854 - if (l < sizeof s - 2) {
855 - s[l++] = '\\';
856 - s[l] = to[e - from];
859 - else if (isprint(src[k])) {
860 - s[l] = src[k];
862 - else {
863 - s[l] = '?';
866 - s[l] = 0;
867 - printd("<%s:%u \"%s\"%s>", tagToStr(STRING_TAG),
868 - (unsigned)strlen(src), s, src[k] ? "..." : "");
869 + int cut;
870 + unsigned len = strlen(src);
871 + src = printableString(src, &cut);
872 + printd("<%s:%u \"%s\"%s>", tagToStr(STRING_TAG), len, src,
873 + cut ? "..." : "");
876 break;
877 @@ -4468,6 +4472,17 @@ static void disasmInternal(Inst *inst, i
878 inst[i].val.immed);
879 break;
881 + case STRING_INST: {
882 + const char *str = inst[i].val.str;
883 + int cut;
884 + unsigned len = strlen(str);
885 + str = printableString(str, &cut);
886 + printd(" <%s:%u \"%s\"%s>\n",
887 + instTypeToStr(inst[i].type),
888 + len, str, cut ? "..." : "");
890 + break;
892 case BRANCH_INST:
893 printd(" <%s (%+td) %8p>\n",
894 instTypeToStr(inst[i].type),
895 @@ -4478,7 +4493,7 @@ static void disasmInternal(Inst *inst, i
896 case SYM_INST:
897 printd(" <%s %s>\n",
898 instTypeToStr(inst[i].type),
899 - inst[i].val.sym->name);
900 + inst[i].val.str);
901 break;
903 default:
904 @@ -4499,11 +4514,7 @@ static void disasmInternal(Inst *inst, i
905 switch (inst[i].val.op) {
906 case OP_PUSH_SYM:
907 case OP_ASSIGN:
908 - printd(" %s", inst[i+1].val.sym->name);
909 - if (inst[i+1].val.sym->type == CONST_SYM
910 - && inst[i+1].val.sym->value.tag == STRING_TAG) {
911 - dumpVal(inst[i+1].val.sym->value);
913 + printd(" %s", inst[i+1].val.str);
914 ++i;
915 break;
917 @@ -4512,6 +4523,17 @@ static void disasmInternal(Inst *inst, i
918 ++i;
919 break;
921 + case OP_PUSH_STRING: {
922 + const char *str = inst[i+1].val.str;
923 + int cut;
924 + unsigned len = strlen(str);
925 + str = printableString(str, &cut);
926 + printd(" <string:%u \"%s\"%s>",
927 + len, str, cut ? "..." : "");
928 + ++i;
930 + break;
932 case OP_BRANCH:
933 case OP_BRANCH_TRUE:
934 case OP_BRANCH_FALSE:
935 @@ -4529,7 +4551,7 @@ static void disasmInternal(Inst *inst, i
937 case OP_SUBR_CALL: {
938 int args = inst[i+2].val.immed;
939 - printd(" %s", inst[i+1].val.sym->name);
940 + printd(" %s", inst[i+1].val.str);
941 if (args < 0) {
942 printd(" %d+args[] (%d)", -args - 1, args);
944 @@ -4553,7 +4575,7 @@ static void disasmInternal(Inst *inst, i
945 break;
947 case OP_SUBR_CALL_STACKED_N:
948 - printd(" %s =args[] (?)", inst[i+1].val.sym->name);
949 + printd(" %s =args[] (?)", inst[i+1].val.str);
950 ++i;
951 break;
953 @@ -4561,7 +4583,7 @@ static void disasmInternal(Inst *inst, i
954 if (!inst[i+1].val.immed) {
955 /* without val */
956 printd(" %s = iter++ end-loop=(%+td) %8p",
957 - inst[i+2].val.sym->name,
958 + inst[i+2].val.str,
959 inst[i+3].val.branch,
960 &inst[i+3] + inst[i+3].val.branch);
961 i += 3;
962 @@ -4569,8 +4591,8 @@ static void disasmInternal(Inst *inst, i
963 else {
964 /* with val */
965 printd(" %s=%s = iter++ end-loop=(%+td) %8p",
966 - inst[i+2].val.sym->name,
967 - inst[i+3].val.sym->name,
968 + inst[i+2].val.str,
969 + inst[i+3].val.str,
970 inst[i+4].val.branch,
971 &inst[i+4] + inst[i+4].val.branch);
972 i += 4;
973 @@ -4581,7 +4603,7 @@ static void disasmInternal(Inst *inst, i
974 if (!inst[i+1].val.immed) {
975 /* without val */
976 printd(" %s[] = iter++ end-loop=(%+td) %8p",
977 - inst[i+2].val.sym->name,
978 + inst[i+2].val.str,
979 inst[i+3].val.branch,
980 &inst[i+3] + inst[i+3].val.branch);
981 i += 3;
982 @@ -4589,8 +4611,8 @@ static void disasmInternal(Inst *inst, i
983 else {
984 /* with val */
985 printd(" %s[]=%s = iter++ end-loop=(%+td) %8p",
986 - inst[i+2].val.sym->name,
987 - inst[i+3].val.sym->name,
988 + inst[i+2].val.str,
989 + inst[i+3].val.str,
990 inst[i+4].val.branch,
991 &inst[i+4] + inst[i+4].val.branch);
992 i += 4;
993 @@ -4616,7 +4638,7 @@ static void disasmInternal(Inst *inst, i
995 case OP_PUSH_ARRAY_SYM:
996 printd(" %s %s",
997 - inst[i+1].val.sym->name,
998 + inst[i+1].val.str,
999 inst[i+2].val.immed ? "createAndRef" : "refOnly");
1000 i += 2;
1001 break;
1002 @@ -4659,11 +4681,6 @@ static void stackdumpframe(DataValue *ar
1003 DataValue *endDv = (arg1 > outpt) ? arg1 : outpt;
1004 int nArgs = FP_GET_ARG_COUNT(fp);
1006 - int nSyms;
1007 - static int symLen = 0;
1008 - Symbol *syms = FP_GET_ITEM(fp, FP_SYMBOL_TABLE).val.sym;
1009 - Symbol *sym;
1011 #ifdef DEBUG_STACK_HEADFIRST
1012 #else
1013 /* do caller's frame */
1014 @@ -4672,17 +4689,6 @@ static void stackdumpframe(DataValue *ar
1015 #endif /* #ifdef DEBUG_STACK_HEADFIRST */
1017 /* do current frame */
1018 - /* how many symbols are there? */
1019 - for (sym = syms, nSyms = 0; sym != NULL; sym = sym->next) {
1020 - nSyms++;
1021 - if (symLen < 27) {
1022 - int len = strlen(sym->name);
1023 - if (len > 27)
1024 - len = 27;
1025 - if (len > symLen)
1026 - symLen = len;
1030 /* output instructions between endDv and sp - 1 inclusive */
1031 #ifdef DEBUG_STACK_HEADFIRST
1032 @@ -4693,7 +4699,6 @@ static void stackdumpframe(DataValue *ar
1033 #endif /* #ifdef DEBUG_STACK_HEADFIRST */
1035 const char *posFmt = "%-6s";
1036 - const char *symName = "";
1038 char *pos = "";
1039 char buffer[sizeof(STACK_DUMP_ARG_PREFIX) + TYPE_INT_STR_SIZE(int)];
1040 @@ -4717,10 +4722,6 @@ static void stackdumpframe(DataValue *ar
1041 sprintf(pos = buffer, STACK_DUMP_ARG_PREFIX "%d",
1042 offset + FP_TO_ARGS_DIST + nArgs + 1);
1044 - else if (0 <= offset && offset < nSyms) {
1045 - sprintf(pos = buffer, offset ? "[%d]" : "FP[%d]", offset);
1046 - posFmt = "%6s";
1048 else if (offset == 0) {
1049 pos = "FrameP";
1051 @@ -4728,17 +4729,6 @@ static void stackdumpframe(DataValue *ar
1053 printd(posFmt, pos);
1055 - /* local symbol names? */
1056 - if (0 <= offset && offset < nSyms) {
1057 - for (sym = syms; sym != NULL; sym = sym->next) {
1058 - if (sym->value.val.n == offset) {
1059 - symName = sym->name;
1060 - break;
1064 - printd(" %-*.*s", symLen, symLen, symName);
1066 if (dv == fnNm && dv->tag == STRING_TAG && dv->val.str.rep)
1067 printd(" %s", dv->val.str.rep);
1068 else
1069 diff --quilt old/source/interpret.h new/source/interpret.h
1070 --- old/source/interpret.h
1071 +++ new/source/interpret.h
1072 @@ -40,7 +40,7 @@
1073 #define LOOP_STACK_SIZE 256 /* (Approx.) Number of break/continue stmts
1074 allowed per program */
1076 -enum symTypes {CONST_SYM, GLOBAL_SYM, LOCAL_SYM, ARG_SYM, PROC_VALUE_SYM,
1077 +enum symTypes {GLOBAL_SYM, LOCAL_SYM, ARG_SYM, PROC_VALUE_SYM,
1078 C_FUNCTION_SYM, MACRO_FUNCTION_SYM, ACTION_ROUTINE_SYM};
1080 enum operations {
1081 @@ -54,7 +54,7 @@ enum typeTags {NO_TAG, INT_TAG, STRING_T
1083 enum execReturnCodes {MACRO_TIME_LIMIT, MACRO_PREEMPT, MACRO_DONE, MACRO_ERROR};
1085 -enum instTypes {OP_INST, IMMED_INST, BRANCH_INST, SYM_INST};
1086 +enum instTypes {OP_INST, IMMED_INST, STRING_INST, BRANCH_INST, SYM_INST};
1088 #define ARRAY_DIM_SEP "\034"
1090 @@ -68,8 +68,8 @@ typedef struct InstTag {
1091 union {
1092 enum operations op;
1093 int immed;
1094 + const char *str;
1095 ptrdiff_t branch;
1096 - struct SymbolRec *sym;
1097 } val;
1098 } Inst;
1100 @@ -108,14 +108,13 @@ typedef struct SymbolRec {
1101 DataValue value;
1102 unsigned int hash;
1103 struct SymbolRec *next; /* to link to another */
1104 - char name[1];
1105 + const char *name;
1106 } Symbol;
1108 typedef struct ProgramTag {
1109 - Symbol *localSymList;
1110 + const char *name;
1111 Inst *code;
1112 unsigned refcount;
1113 - char name[1];
1114 } Program;
1116 /* Information needed to re-start a preempted macro */
1117 @@ -131,7 +130,6 @@ typedef struct {
1119 /* state of the accumulator (aka compiler) */
1120 typedef struct AccumulatorDataTag {
1121 - Symbol *localSymList;
1122 Inst prog[PROGRAM_SIZE];
1123 Inst *progP;
1124 Inst *loopStack[LOOP_STACK_SIZE];
1125 @@ -156,25 +154,23 @@ int ArrayCopy(DataValue *dstArray, DataV
1126 AccumulatorData *BeginCreatingProgram(const char *name);
1127 Program *FinishCreatingProgram(AccumulatorData *old);
1128 int AddOp(int op, char **msg);
1129 -int AddSym(Symbol *sym, char **msg);
1130 +int AddSym(const char *str, char **msg);
1131 int AddImmediate(int immed, char **msg);
1132 +int AddString(const char *str, char **msg);
1133 int AddBranchOffset(Inst *to, char **msg);
1134 int SetBranchOffset(Inst *from, Inst *to, char **msg);
1135 Inst *GetPC(void);
1136 -Symbol *InstallIteratorSymbol(void);
1137 -Symbol *LookupStringConstSymbol(const char *value);
1138 -Symbol *InstallStringConstSymbol(const char *str);
1139 -Symbol *LookupSymbol(const char *name);
1140 +Symbol *LookupSymbol(const char *name, int create);
1141 Symbol *InstallSymbol(const char *name, enum symTypes type, DataValue value);
1142 -Symbol *InstallMultiAssignExpr(void);
1143 +const char *LookupString(const char *str, int doInsert);
1144 Inst *SwapCode(Inst *start, Inst *boundary, Inst *end);
1145 int StartLoopAddrList(char **msg);
1146 int AddBreakAddr(Inst *addr, char **msg);
1147 int AddContinueAddr(Inst *addr, char **msg);
1148 void FillLoopAddrs(Inst *breakAddr, Inst *continueAddr);
1150 -/* create a permanently allocated static string (only for use with static strings) */
1151 -#define PERM_ALLOC_STR(xStr) (((char *)("\001" xStr)) + 1)
1152 +/* create a permanently allocated static string */
1153 +#define PERM_ALLOC_STR(xStr) (char *)LookupString(xStr, 1)
1155 /* Routines for executing programs */
1156 int ExecuteMacro(WindowInfo *window, Program *prog, int nArgs, DataValue *args,
1157 @@ -195,7 +191,6 @@ int AllocNStringNCpy(NString *string, co
1158 int AllocNStringCpy(NString *string, const char *s);
1159 void GarbageCollectStrings(void);
1160 void FreeRestartData(RestartData *context);
1161 -Symbol *PromoteToGlobal(Symbol *sym);
1162 void FreeProgram(Program *prog);
1163 void ModifyReturnedValue(RestartData *context, DataValue dv);
1164 WindowInfo *MacroRunWindow(void);
1165 diff --quilt old/source/ops.h new/source/ops.h
1166 --- old/source/ops.h
1167 +++ new/source/ops.h
1168 @@ -7,6 +7,7 @@ OP(RETURN_NO_VAL, returnNoVal)
1169 OP(RETURN, returnVal) /* pop(ret), rewind, push(ret) */
1170 OP(PUSH_SYM, pushSymVal) /* sym */ /* push(sym.v) */
1171 OP(PUSH_IMMED, pushImmed) /* immed */ /* push(immed) */
1172 +OP(PUSH_STRING, pushString) /* str */ /* push(str) */
1173 OP(POP, popStack) /* pop(v) */
1174 OP(DUP, dupStack) /* pop(v), push(v,v) */
1175 OP(ADD, add) /* pop(v2,v1), push(v1 + v2) */
1176 diff --quilt old/source/parse.y new/source/parse.y
1177 --- old/source/parse.y
1178 +++ new/source/parse.y
1179 @@ -41,6 +41,12 @@
1180 return 1; \
1182 } while (0)
1183 +#define ADD_STR(str) \
1184 + do { \
1185 + if (!AddString(str, &ErrMsg)) { \
1186 + return 1; \
1187 + } \
1188 + } while (0)
1189 #define ADD_IMMED(val) \
1190 do { \
1191 if (!AddImmediate(val, &ErrMsg)) { \
1192 @@ -114,7 +120,7 @@ typedef struct LVinst {
1195 %union {
1196 - Symbol *sym;
1197 + const char *str;
1198 Inst *inst;
1199 int num;
1200 enum operations oper;
1201 @@ -124,13 +130,13 @@ typedef struct LVinst {
1202 Symbol *sym;
1203 } define;
1205 -%token <sym> STRING SYMBOL FIELD
1206 +%token <str> STRING SYMBOL FIELD
1207 %token <num> NUMBER
1208 %token DELETE ARG_LOOKUP
1209 %token IF WHILE DO ELSE FOR BREAK CONTINUE RETURN DEFINE TYPEOF KEYVAL
1210 %type <num> arglistopt arglist catlist fnarglsopt fnarglist fnarg
1211 %type <inst> cond comastmts comastmtlst for while do else and or arrayexpr mark
1212 -%type <sym> evalsym
1213 +%type <str> evalsym
1214 %type <define> definesym
1215 %type <oper> operassign incrdecr
1216 %token <oper> '=' ADDEQ SUBEQ MULEQ DIVEQ MODEQ ANDEQ OREQ
1217 @@ -200,31 +206,24 @@ definekw: DEFINE {
1220 definesym: SYMBOL {
1221 - /* we can't really be sure, that we not overwrite any
1222 - ** wrong symbol
1223 - **
1224 - ** we should only overwrite installed MACRO_FUNCTION_SYM
1225 - ** and this is questionable.
1226 - */
1227 - if ($1->type == MACRO_FUNCTION_SYM) {
1228 - FreeProgram($1->value.val.prog);
1229 + $$.sym = LookupSymbol($1, False);
1230 + if ($$.sym) {
1231 + if ($$.sym->type != MACRO_FUNCTION_SYM) {
1232 + yyerror("try to override built-in subroutine"); YYERROR;
1235 - else if ($1->type == LOCAL_SYM ||
1236 - $1->type == GLOBAL_SYM) {
1237 - /* newly created sym, or we overwrite a local sym */;
1238 - } else {
1239 - yyerror("try to override built-in subroutine"); YYERROR;
1240 + else {
1241 + DataValue subrPtr;
1242 + subrPtr.tag = NO_TAG;
1243 + subrPtr.val.prog = NULL;
1244 + $$.sym = InstallSymbol($1, MACRO_FUNCTION_SYM, subrPtr);
1246 - $$.sym = PromoteToGlobal($1);
1247 $$.acc = BeginCreatingProgram($$.sym->name);
1250 define: definekw blank definesym blank blockwb {
1251 ADD_OP(OP_RETURN_NO_VAL);
1252 - Program *prog = FinishCreatingProgram($3.acc);
1253 - $3.sym->type = MACRO_FUNCTION_SYM;
1254 - $3.sym->value.tag = NO_TAG;
1255 - $3.sym->value.val.prog = prog;
1256 + $3.sym->value.val.prog = FinishCreatingProgram($3.acc);
1260 @@ -441,7 +440,8 @@ simpstmt: /* simple variable assignmen
1262 lvlistexpr: '(' lvlist ')' blank '=' blank expr {
1263 /* store expression value */
1264 - ADD_OP(OP_ASSIGN); ADD_SYM(InstallMultiAssignExpr());
1265 + ADD_OP(OP_ASSIGN);
1266 + ADD_SYM(LookupString("list assign expr", True));
1267 /* swap expression evaluation code into position */
1268 SwapCode($2.mid, $2.next, GetPC());
1270 @@ -488,7 +488,8 @@ lventry: mark SYMBOL {
1271 /* Push code: null */
1272 $$.mid = GetPC();
1273 /* Assign code: stack: N, ... */
1274 - ADD_OP(OP_PUSH_SYM); ADD_SYM(InstallMultiAssignExpr());
1275 + ADD_OP(OP_PUSH_SYM);
1276 + ADD_SYM(LookupString("list assign expr", True));
1277 /* stack: E, N, ... */
1278 ADD_OP(OP_SWAP_TOP2); /* stack: N, E, ... */
1279 ADD_OP(OP_ARRAY_REF); ADD_IMMED(1); /* stack: E[N] ... */
1280 @@ -501,7 +502,8 @@ lventry: mark SYMBOL {
1281 /* Push code dealt with in "initarraylv '[' arglist ']'" */
1282 $$.mid = GetPC();
1283 /* Assign code: stack: N, ... */
1284 - ADD_OP(OP_PUSH_SYM); ADD_SYM(InstallMultiAssignExpr());
1285 + ADD_OP(OP_PUSH_SYM);
1286 + ADD_SYM(LookupString("list assign expr", True));
1287 /* stack: E, N, ... */
1288 ADD_OP(OP_SWAP_TOP2); /* stack: N, E, ... */
1289 ADD_OP(OP_ARRAY_REF); ADD_IMMED(1); /* stack: E[N] ... */
1290 @@ -514,7 +516,8 @@ lventry: mark SYMBOL {
1291 /* Push code dealt with in "initarraylv dot field" */
1292 $$.mid = GetPC();
1293 /* Assign code: stack: N, ... */
1294 - ADD_OP(OP_PUSH_SYM); ADD_SYM(InstallMultiAssignExpr());
1295 + ADD_OP(OP_PUSH_SYM);
1296 + ADD_SYM(LookupString("list assign expr", True));
1297 /* stack: E, N, ... */
1298 ADD_OP(OP_SWAP_TOP2); /* stack: N, E, ... */
1299 ADD_OP(OP_ARRAY_REF); ADD_IMMED(1); /* stack: E[N] ... */
1300 @@ -556,21 +559,21 @@ funccall: TYPEOF '(' {
1302 | SYMBOL '(' fnarglsopt ')' {
1303 ADD_OP(OP_SUBR_CALL);
1304 - ADD_SYM(PromoteToGlobal($1)); ADD_IMMED($3);
1305 + ADD_SYM($1); ADD_IMMED($3);
1307 | SYMBOL '(' blank '=' blank expr blank ')' {
1308 /* a single array replaces the argument list */
1309 ADD_OP(OP_UNPACKTOARGS);
1310 ADD_IMMED(0); /* zero arguments */
1311 ADD_OP(OP_SUBR_CALL_STACKED_N);
1312 - ADD_SYM(PromoteToGlobal($1));
1313 + ADD_SYM($1);
1315 | SYMBOL '(' fnarglist ARGSEP blank '=' blank expr blank ')' {
1316 /* a single array replaces the argument list */
1317 ADD_OP(OP_UNPACKTOARGS);
1318 ADD_IMMED($3);
1319 ADD_OP(OP_SUBR_CALL_STACKED_N);
1320 - ADD_SYM(PromoteToGlobal($1));
1321 + ADD_SYM($1);
1325 @@ -658,7 +661,7 @@ arraylv: SYMBOL {
1328 field: FIELD {
1329 - ADD_OP(OP_PUSH_SYM); ADD_SYM($1);
1330 + ADD_OP(OP_PUSH_STRING); ADD_STR($1);
1332 /* this bit allows things like array.5 for array[5] **
1333 | NUMBER {
1334 @@ -710,7 +713,7 @@ arrentry: blank {
1336 numexpr: '(' blank expr blank ')'
1337 | NUMBER { ADD_OP(OP_PUSH_IMMED); ADD_IMMED($1); }
1338 - | STRING { ADD_OP(OP_PUSH_SYM); ADD_SYM($1); }
1339 + | STRING { ADD_OP(OP_PUSH_STRING); ADD_STR($1); }
1340 | SYMBOL { ADD_OP(OP_PUSH_SYM); ADD_SYM($1); }
1341 | funccall {
1342 ADD_OP(OP_FETCH_RET_VAL);
1343 @@ -959,19 +962,17 @@ static int yylex(void)
1344 if (!strcmp(symName, "delete") && follow_non_whitespace('(', SYMBOL, DELETE) == DELETE) return DELETE;
1345 if (!strcmp(symName, "define") && follow_non_whitespace('(', SYMBOL, DEFINE) == DEFINE) return DEFINE;
1346 if (!strcmp(symName, "typeof")) return TYPEOF;
1348 + yylval.str = LookupString(symName, True);
1349 if (nextSymIsField) {
1350 nextSymIsField = 0;
1351 - yylval.sym = InstallStringConstSymbol(symName);
1352 return FIELD;
1354 - if ((s=LookupSymbol(symName)) == NULL) {
1355 - s = InstallSymbol(symName, symName[0]=='$' ?
1356 - (((symName[1] > '0' && symName[1] <= '9') && symName[2] == 0) ?
1357 - ARG_SYM : GLOBAL_SYM) : LOCAL_SYM, value);
1358 - s->value.tag = NO_TAG;
1359 + else {
1360 + return SYMBOL;
1363 - yylval.sym = s;
1364 + yylval.str = LookupString(s->name, True);
1365 return SYMBOL;
1367 nextSymIsField = 0;
1368 @@ -1133,7 +1134,7 @@ static Symbol *matchesActionRoutine(char
1369 if (!hasDash)
1370 return NULL;
1371 *symPtr = '\0';
1372 - s = LookupSymbol(symbolName);
1373 + s = LookupSymbol(symbolName, False);
1374 if (s != NULL)
1375 *inPtr = c;
1376 return s;
1377 @@ -1296,12 +1297,13 @@ static int scanString(void)
1378 if (*InPtr == stopper) {
1379 if (!p) {
1380 /* this was the size measurement and validation */
1381 - p = string = AllocString(len);
1382 + p = string = XtMalloc(len);
1384 else {
1385 /* OK: string now contains our string text */
1386 InPtr++; /* skip past stopper */
1387 - yylval.sym = InstallStringConstSymbol(string);
1388 + yylval.str = LookupString(string, True);
1389 + XtFree(string);
1390 return STRING;
1393 diff --quilt old/source/macro.c new/source/macro.c
1394 --- old/source/macro.c
1395 +++ new/source/macro.c
1396 @@ -3828,7 +3828,7 @@ static int callMS(WindowInfo *window, Da
1397 return False;
1400 - sym = LookupSymbol(fnname);
1401 + sym = LookupSymbol(fnname, False);
1403 if (!sym) {
1404 *errMsg = "subroutine name invalid";
1405 @@ -3906,7 +3906,7 @@ static int defineMS(WindowInfo *window,
1407 XtFree(bodysave);
1409 - sym = LookupSymbol(name);
1410 + sym = LookupSymbol(name, False);
1411 if (sym) {
1412 if (!override) {
1413 FreeProgram(prog);
1414 @@ -7317,7 +7317,7 @@ Boolean MacroApplyHook(WindowInfo *docum
1415 Symbol *hookSymbol;
1416 Boolean succ = False;
1418 - hookSymbol = LookupSymbol(hook);
1419 + hookSymbol = LookupSymbol(hook, False);
1420 if (NULL != hookSymbol && MACRO_FUNCTION_SYM == hookSymbol->type) {
1421 Program *hookProg = hookSymbol->value.val.prog;
1422 RestartData *restartData;