3 source/interpret.c | 281 ++++++++++++++++++++++++++++++++++++++---------------
4 source/interpret.h | 17 +--
6 source/parse.y | 21 ++-
7 4 files changed, 227 insertions(+), 93 deletions(-)
9 diff --quilt old/source/interpret.c new/source/interpret.c
10 --- old/source/interpret.c
11 +++ new/source/interpret.c
12 @@ -27,6 +27,7 @@ static const char CVSID[] = "$Id: interp
14 *******************************************************************************/
16 +#define _POSIX_C_SOURCE 200112L
18 #include "../config.h"
20 @@ -288,12 +289,11 @@ Program *FinishCreatingProgram(Accumulat
23 newProg = XtNew(Program);
24 - newProg->name = XtMalloc(strlen(ProgramName) + 1); /* +1 for '\0' */
25 + newProg->name = LookupString(ProgramName, True);
26 progLen = ProgP - Prog;
27 newProg->code = (Inst *)XtCalloc(progLen, sizeof(Inst));
28 memcpy(newProg->code, Prog, progLen * sizeof(Inst));
29 newProg->localSymList = LocalSymList;
30 - strcpy(newProg->name, ProgramName);
31 newProg->refcount = 1;
33 /* Local variables' values are stored on the stack. Here we assign
34 @@ -314,7 +314,6 @@ void FreeProgram(Program *prog)
35 if (--prog->refcount == 0) {
36 freeSymbolList(prog->localSymList);
37 XtFree((char *)prog->code);
38 - XtFree((char *)prog->name);
42 @@ -365,6 +364,21 @@ int AddImmediate(int immed, char **msg)
46 +** Add an string value operand to the current program
48 +int AddString(const char *str, char **msg)
50 + if (ProgP >= &Prog[PROGRAM_SIZE]) {
51 + *msg = "macro too large";
54 + ProgP->type = STRING_INST;
55 + ProgP->val.str = str;
61 ** Add a branch offset operand to the current program
63 int AddBranchOffset(Inst *to, char **msg)
64 @@ -822,47 +836,6 @@ void SetMacroFocusWindow(WindowInfo *win
69 -** Lookup a constant string by its value. This allows reuse of string
70 -** constants and fixing a leak in the interpreter.
72 -Symbol *LookupStringConstSymbol(const char *value)
77 - for (idx = 0; idx < GLOBAL_SYMTAB_SIZE; idx++) {
78 - for (s = GlobalSymTab[idx]; s != NULL; s = s->next) {
79 - if (s->type == CONST_SYM
80 - && s->value.tag == STRING_TAG
81 - && !strcmp(s->value.val.str.rep, value)) {
91 -** install string str in the global symbol table with a string name
93 -Symbol *InstallStringConstSymbol(const char *str)
95 - static int stringConstIndex = 0;
96 - char stringName[35];
98 - Symbol *sym = LookupStringConstSymbol(str);
103 - sprintf(stringName, "string #%d", stringConstIndex++);
104 - value.tag = STRING_TAG;
105 - AllocNStringCpy(&value.val.str, str);
106 - return(InstallSymbol(stringName, CONST_SYM, value));
109 static Symbol *lookupSymbol(Symbol *symlist, const char *name,
112 @@ -909,8 +882,7 @@ Symbol *InstallSymbol(const char *name,
116 - s->name = (char *)XtMalloc(strlen(name) + 1); /* +1 for '\0' */
117 - strcpy(s->name, name);
118 + s->name = LookupString(name, True);
121 s->hash = hashName(s->name);
122 @@ -1290,7 +1262,6 @@ static void freeSymbolList(Symbol *symLi
123 while (symList != NULL) {
126 - XtFree((char *)s->name);
130 @@ -1352,6 +1323,16 @@ static void addToGlobalSymTab(Symbol *sy
134 +#define GET_STR(s) \
136 + if (PC->type != STRING_INST) { \
137 + EXEC_ERROR("Unexpected instruction, expected <string>: <%s>", \
138 + instTypeToStr(PC->type)); \
147 @@ -1534,7 +1515,7 @@ static int pushSymVal(void)
149 if (s->type == LOCAL_SYM) {
150 symVal = FP_GET_SYM_VAL(FrameP, s);
151 - } else if (s->type == GLOBAL_SYM || s->type == CONST_SYM) {
152 + } else if (s->type == GLOBAL_SYM) {
154 } else if (s->type == ARG_SYM) {
155 nArgs = FP_GET_ARG_COUNT(FrameP);
156 @@ -1586,6 +1567,27 @@ static int pushImmed(void)
161 +** push string onto the stack
162 +** Before: Prog-> [string], next, ...
163 +** TheStack-> next, ...
164 +** After: Prog-> string, [next], ...
165 +** TheStack-> [string], next, ...
167 +static int pushString(void)
176 + PUSH_STRING((char *)str, strlen(str));
181 static int pushArgVal(void)
184 @@ -2924,7 +2926,7 @@ int OverlayRoutineFromProg(Program *prog
187 sym.type = MACRO_FUNCTION_SYM;
188 - sym.name = prog->name;
189 + sym.name = LookupString(prog->name, True);
190 sym.value.tag = NO_TAG;
191 sym.value.val.prog = prog;
193 @@ -4093,6 +4095,100 @@ static int errCheck(const char *s)
197 +** string lookup stuff
200 +/* should be the pagesize */
201 +#define STRING_BLK_SIZE 4096
203 +typedef struct stringEntryTag {
204 + struct stringEntryTag *next;
206 + char str[1]; /* [1] for inUse */
209 +typedef struct stringBlkHdrTag {
210 + struct stringBlkHdrTag *next;
216 +static stringBlkHdr *lookupStringBlks;
217 +#define STR_LOOKUP_TAB_SHIFT 10
218 +#define STR_LOOKUP_TAB_SIZE (1u << (STR_LOOKUP_TAB_SHIFT))
219 +#define STR_LOOKUP_TAB_MASK ((STR_LOOKUP_TAB_SIZE) - 1)
220 +static stringEntry *stringTbl[STR_LOOKUP_TAB_SIZE];
222 +const char *LookupString(const char *str, int create)
224 +#define ROUNDUP(x, align) (-(-((size_t)(x)) & -((size_t)(align))))
225 + unsigned int len = strlen(str) + 1;
226 + unsigned int hash = hashName(str);
227 + unsigned int idx = hash & STR_LOOKUP_TAB_MASK;
228 + stringBlkHdr **blkp = &lookupStringBlks;
232 + /* search str in hash table */
233 + for (e = stringTbl[idx]; e; e = e->next) {
234 + if (e->hash == hash && 0 == strcmp(str, &e->str[1]))
241 + /* find space for str */
243 + if ((*blkp)->rem >= len) {
246 + blkp = &(*blkp)->next;
250 + /* no space found, create new string bulk */
253 + size_t size = ROUNDUP(sizeof(stringBlkHdr), sizeof(void *))
254 + + sizeof(stringEntry) + len;
255 + size = ROUNDUP(size, STRING_BLK_SIZE);
257 + posix_memalign(&ptr, STRING_BLK_SIZE, size);
262 + /* round up to sizeof(void *) */
263 + blk->free = (void *)ROUNDUP((char *)blk + sizeof(stringBlkHdr), sizeof(void *));
264 + blk->rem = ((char *)blk + blk->size) - ((char *)blk->free + sizeof(stringEntry));
267 + /* mark string as constant and copy str into bulk */
268 + blk->free->str[0] = 1;
269 + strcpy(&blk->free->str[1], str);
270 + str = &blk->free->str[1];
272 + /* insert string into hash table */
273 + blk->free->next = stringTbl[idx];
274 + blk->free->hash = hash;
275 + stringTbl[idx] = blk->free;
277 + /* calculate remaining space */
278 + blk->free = (void *)ROUNDUP((char *)blk->free + sizeof(stringEntry) + len,
280 + if (((char *)blk + blk->size) >= ((char *)blk->free + sizeof(stringEntry))) {
281 + blk->rem = ((char *)blk + blk->size) - ((char *)blk->free + sizeof(stringEntry));
291 ** build a stack dump string, reallocating s as necessary.
293 static char *stackDumpStr(RestartData *context, const char *msg, char **s, int *pLen)
294 @@ -4271,6 +4367,8 @@ static const char *instTypeToStr(enum in
303 @@ -4354,6 +4452,41 @@ int outPrintd(void)
304 #endif /* #ifdef DEBUG_DISASSEMBLER */
306 #ifdef DEBUG_DISASSEMBLER /* dumping values in disassembly or stack dump */
307 +static const char *printableString(const char *src, int *shortaged)
312 + for (k = 0, l = 0; src[k] && l < sizeof s - 1; k++, l++) {
314 + const char to[] = "\\\"ntbrfave";
315 +#ifdef EBCDIC_CHARSET
316 + const char from[] = "\\\"\n\t\b\r\f\a\v\x27"; /* EBCDIC escape */
318 + const char from[] = "\\\"\n\t\b\r\f\a\v\x1B"; /* ASCII escape */
320 + if ((e = strchr(from, src[k]))) {
321 + if (l < sizeof s - 2) {
323 + s[l] = to[e - from];
326 + else if (isprint(src[k])) {
336 + *shortaged = !!src[k];
342 static void dumpVal(DataValue dv)
345 @@ -4362,38 +4495,16 @@ static void dumpVal(DataValue dv)
351 const char *src = dv.val.str.rep;
352 - unsigned len = dv.val.str.len;
354 printd(" <%s NULL>", tagToStr(STRING_TAG));
357 - for (k = 0, l = 0; src[k] && l < sizeof s - 1; k++, l++) {
359 - const char to[] = "\\\"ntbrfave";
360 -#ifdef EBCDIC_CHARSET
361 - const char from[] = "\\\"\n\t\b\r\f\a\v\x27"; /* EBCDIC escape */
363 - const char from[] = "\\\"\n\t\b\r\f\a\v\x1B"; /* ASCII escape */
365 - if ((e = strchr(from, src[k]))) {
366 - if (l < sizeof s - 2) {
368 - s[l] = to[e - from];
371 - else if (isprint(src[k])) {
380 + unsigned len = dv.val.str.len;
381 + src = printableString(src, &cut);
382 printd(" <%s %u:\"%s\"%s>", tagToStr(STRING_TAG),
383 - len, s, src[k] ? "..." : "");
384 + len, src, cut ? "..." : "");
388 @@ -4456,6 +4567,16 @@ static void dumpInst(Inst *inst, const c
389 printd(" <%s %d>", name, inst->val.immed);
392 + case STRING_INST: {
393 + const char *str = inst->val.str;
395 + unsigned len = strlen(str);
396 + str = printableString(str, &cut);
397 + printd(" <%s %u:\"%s\"%s>", name,
398 + len, str, cut ? "..." : "");
403 printd(" <%s %+td:%p>", name,
404 inst->val.branch, inst + inst->val.branch);
405 @@ -4510,10 +4631,6 @@ static void disasmInternal(Inst *inst, i
407 CHECK_OPERANDS(1, SYM_INST);
408 dumpInst(&inst[i+1], NULL);
409 - if (inst[i+1].val.sym->type == CONST_SYM
410 - && inst[i+1].val.sym->value.tag == STRING_TAG) {
411 - dumpVal(inst[i+1].val.sym->value);
416 @@ -4523,6 +4640,12 @@ static void disasmInternal(Inst *inst, i
420 + case OP_PUSH_STRING:
421 + CHECK_OPERANDS(1, STRING_INST);
422 + dumpInst(&inst[i+1], NULL);
427 CHECK_OPERANDS(1, IMMED_INST);
428 dumpInst(&inst[i+1], "index");
429 diff --quilt old/source/interpret.h new/source/interpret.h
430 --- old/source/interpret.h
431 +++ new/source/interpret.h
433 #define LOOP_STACK_SIZE 256 /* (Approx.) Number of break/continue stmts
434 allowed per program */
436 -enum symTypes {CONST_SYM, GLOBAL_SYM, LOCAL_SYM, ARG_SYM, PROC_VALUE_SYM,
437 +enum symTypes {GLOBAL_SYM, LOCAL_SYM, ARG_SYM, PROC_VALUE_SYM,
438 C_FUNCTION_SYM, MACRO_FUNCTION_SYM, ACTION_ROUTINE_SYM};
441 @@ -54,7 +54,7 @@ enum typeTags {NO_TAG, INT_TAG, STRING_T
443 enum execReturnCodes {MACRO_TIME_LIMIT, MACRO_PREEMPT, MACRO_DONE, MACRO_ERROR};
445 -enum instTypes {NO_INST, OP_INST, IMMED_INST, BRANCH_INST, SYM_INST};
446 +enum instTypes {NO_INST, OP_INST, IMMED_INST, STRING_INST, BRANCH_INST, SYM_INST};
448 #define ARRAY_DIM_SEP "\034"
450 @@ -68,6 +68,7 @@ typedef struct InstTag {
456 struct SymbolRec *sym;
458 @@ -104,7 +105,7 @@ typedef struct SparseArrayEntryTag {
460 /* symbol table entry */
461 typedef struct SymbolRec {
467 @@ -112,7 +113,7 @@ typedef struct SymbolRec {
470 typedef struct ProgramTag {
473 Symbol *localSymList;
476 @@ -158,21 +159,21 @@ Program *FinishCreatingProgram(Accumulat
477 int AddOp(int op, char **msg);
478 int AddSym(Symbol *sym, char **msg);
479 int AddImmediate(int immed, char **msg);
480 +int AddString(const char *str, char **msg);
481 int AddBranchOffset(Inst *to, char **msg);
482 int SetBranchOffset(Inst *from, Inst *to, char **msg);
484 -Symbol *LookupStringConstSymbol(const char *value);
485 -Symbol *InstallStringConstSymbol(const char *str);
486 Symbol *LookupSymbol(const char *name);
487 Symbol *InstallSymbol(const char *name, enum symTypes type, DataValue value);
488 +const char *LookupString(const char *str, int create);
489 Inst *SwapCode(Inst *start, Inst *boundary, Inst *end);
490 int StartLoopAddrList(char **msg);
491 int AddBreakAddr(Inst *addr, char **msg);
492 int AddContinueAddr(Inst *addr, char **msg);
493 int FillLoopAddrs(Inst *breakAddr, Inst *continueAddr, char **msg);
495 -/* create a permanently allocated static string (only for use with static strings) */
496 -#define PERM_ALLOC_STR(xStr) (((char *)("\001" xStr)) + 1)
497 +/* create a permanently allocated static string */
498 +#define PERM_ALLOC_STR(xStr) (char *)LookupString(xStr, 1)
500 /* Routines for executing programs */
501 int ExecuteMacro(WindowInfo *window, Program *prog, int nArgs, DataValue *args,
502 diff --quilt old/source/ops.h new/source/ops.h
505 @@ -7,6 +7,7 @@ OP(RETURN_NO_VAL, returnNoVal)
506 OP(RETURN, returnVal) /* pop(ret), rewind, push(ret) */
507 OP(PUSH_SYM, pushSymVal) /* sym */ /* push(sym.v) */
508 OP(PUSH_IMMED, pushImmed) /* immed */ /* push(immed) */
509 +OP(PUSH_STRING, pushString) /* str */ /* push(str) */
510 OP(POP, popStack) /* pop(v) */
511 OP(DUP, dupStack) /* pop(v), push(v,v) */
512 OP(PEEK_PUSH, peekPush) /* n */ /* peek(v, n), push(v) */
513 diff --quilt old/source/parse.y new/source/parse.y
514 --- old/source/parse.y
515 +++ new/source/parse.y
520 +#define ADD_STR(str) \
522 + if (!AddString(str, &ErrMsg)) { \
526 #define ADD_BR_OFF(to) \
528 if (!AddBranchOffset(to, &ErrMsg)) { \
529 @@ -114,13 +120,15 @@ static int nextSymIsField = 0;
534 enum operations oper;
536 AccumulatorData *acc;
540 -%token <sym> STRING SYMBOL FIELD
542 +%token <str> STRING FIELD
544 %token DELETE ARG_LOOKUP
545 %token IF WHILE DO ELSE FOR BREAK CONTINUE RETURN DEFINE TYPEOF KEYVAL
546 @@ -632,7 +640,7 @@ arraylv: SYMBOL {
550 - ADD_OP(OP_PUSH_SYM); ADD_SYM($1);
551 + ADD_OP(OP_PUSH_STRING); ADD_STR($1);
553 /* this bit allows things like array.5 for array[5] **
555 @@ -682,7 +690,7 @@ arrentry: blank {
557 numexpr: '(' blank expr blank ')'
558 | NUMBER { ADD_OP(OP_PUSH_IMMED); ADD_IMMED($1); }
559 - | STRING { ADD_OP(OP_PUSH_SYM); ADD_SYM($1); }
560 + | STRING { ADD_OP(OP_PUSH_STRING); ADD_STR($1); }
561 | SYMBOL { ADD_OP(OP_PUSH_SYM); ADD_SYM($1); }
563 ADD_OP(OP_FETCH_RET_VAL);
564 @@ -933,7 +941,7 @@ static int yylex(void)
565 if (!strcmp(symName, "typeof")) return TYPEOF;
566 if (nextSymIsField) {
568 - yylval.sym = InstallStringConstSymbol(symName);
569 + yylval.str = LookupString(symName, True);
572 if ((s=LookupSymbol(symName)) == NULL) {
573 @@ -1268,12 +1276,13 @@ static int scanString(void)
574 if (*InPtr == stopper) {
576 /* this was the size measurement and validation */
577 - p = string = AllocString(len);
578 + p = string = XtMalloc(len);
581 /* OK: string now contains our string text */
582 InPtr++; /* skip past stopper */
583 - yylval.sym = InstallStringConstSymbol(string);
584 + yylval.str = LookupString(string, True);