drops and reorders
[nedit-bw.git] / pushString.patch
blob8544bd53032e57e5b222a311fc0a47303b83ade0
1 ---
3 source/interpret.c | 287 ++++++++++++++++++++++++++++++++++++++---------------
4 source/interpret.h | 13 +-
5 source/ops.h | 1
6 source/parse.y | 21 ++-
7 4 files changed, 233 insertions(+), 89 deletions(-)
9 diff --quilt old/source/interpret.c new/source/interpret.c
10 --- old/source/interpret.c
11 +++ new/source/interpret.c
12 @@ -288,12 +288,11 @@ Program *FinishCreatingProgram(Accumulat
13 Symbol *s;
15 newProg = XtNew(Program);
16 - newProg->name = XtMalloc(strlen(ProgramName) + 1); /* +1 for '\0' */
17 + newProg->name = LookupString(ProgramName, True);
18 progLen = ProgP - Prog;
19 newProg->code = (Inst *)XtCalloc(progLen, sizeof(Inst));
20 memcpy(newProg->code, Prog, progLen * sizeof(Inst));
21 newProg->localSymList = LocalSymList;
22 - strcpy(newProg->name, ProgramName);
23 newProg->refcount = 1;
25 /* Local variables' values are stored on the stack. Here we assign
26 @@ -314,7 +313,6 @@ void FreeProgram(Program *prog)
27 if (--prog->refcount == 0) {
28 freeSymbolList(prog->localSymList);
29 XtFree((char *)prog->code);
30 - XtFree((char *)prog->name);
31 XtFree((char *)prog);
34 @@ -365,6 +363,21 @@ int AddImmediate(int immed, char **msg)
38 +** Add an string value operand to the current program
39 +*/
40 +int AddString(const char *str, char **msg)
42 + if (ProgP >= &Prog[PROGRAM_SIZE]) {
43 + *msg = "macro too large";
44 + return 0;
45 + }
46 + ProgP->type = STRING_INST;
47 + ProgP->val.str = str;
48 + ProgP++;
49 + return 1;
52 +/*
53 ** Add a branch offset operand to the current program
55 int AddBranchOffset(Inst *to, char **msg)
56 @@ -817,47 +830,6 @@ void SetMacroFocusWindow(WindowInfo *win
60 -/*
61 -** Lookup a constant string by its value. This allows reuse of string
62 -** constants and fixing a leak in the interpreter.
63 -*/
64 -Symbol *LookupStringConstSymbol(const char *value)
66 - unsigned int idx;
67 - Symbol *s;
69 - for (idx = 0; idx < GLOBAL_SYMTAB_SIZE; idx++) {
70 - for (s = GlobalSymTab[idx]; s != NULL; s = s->next) {
71 - if (s->type == CONST_SYM
72 - && s->value.tag == STRING_TAG
73 - && !strcmp(s->value.val.str.rep, value)) {
74 - return(s);
75 - }
76 - }
77 - }
79 - return(NULL);
82 -/*
83 -** install string str in the global symbol table with a string name
84 -*/
85 -Symbol *InstallStringConstSymbol(const char *str)
87 - static int stringConstIndex = 0;
88 - char stringName[35];
89 - DataValue value;
90 - Symbol *sym = LookupStringConstSymbol(str);
91 - if (sym) {
92 - return sym;
93 - }
95 - sprintf(stringName, "string #%d", stringConstIndex++);
96 - value.tag = STRING_TAG;
97 - AllocNStringCpy(&value.val.str, str);
98 - return(InstallSymbol(stringName, CONST_SYM, value));
101 static Symbol *lookupSymbol(Symbol *symlist, const char *name,
102 unsigned int hash)
104 @@ -904,8 +876,7 @@ Symbol *InstallSymbol(const char *name,
105 Symbol *s;
107 s = XtNew(Symbol);
108 - s->name = (char *)XtMalloc(strlen(name) + 1); /* +1 for '\0' */
109 - strcpy(s->name, name);
110 + s->name = LookupString(name, True);
111 s->type = type;
112 s->value = value;
113 s->hash = hashName(s->name);
114 @@ -1285,7 +1256,6 @@ static void freeSymbolList(Symbol *symLi
115 while (symList != NULL) {
116 s = symList;
117 symList = s->next;
118 - XtFree((char *)s->name);
119 XtFree((char *)s);
122 @@ -1347,6 +1317,16 @@ static void addToGlobalSymTab(Symbol *sy
123 PC++; \
124 } while (0)
126 +#define GET_STR(s) \
127 + do { \
128 + if (PC->type != STRING_INST) { \
129 + EXEC_ERROR("Unexpected instruction, expected <string>: <%s>", \
130 + instTypeToStr(PC->type)); \
131 + } \
132 + s = PC->val.str; \
133 + PC++; \
134 + } while (0)
136 #define JUMP(a) \
137 do { \
138 PC = (a); \
139 @@ -1529,7 +1509,7 @@ static int pushSymVal(void)
141 if (s->type == LOCAL_SYM) {
142 symVal = FP_GET_SYM_VAL(FrameP, s);
143 - } else if (s->type == GLOBAL_SYM || s->type == CONST_SYM) {
144 + } else if (s->type == GLOBAL_SYM) {
145 symVal = s->value;
146 } else if (s->type == ARG_SYM) {
147 nArgs = FP_GET_ARG_COUNT(FrameP);
148 @@ -1581,6 +1561,27 @@ static int pushImmed(void)
149 return STAT_OK;
153 +** push string onto the stack
154 +** Before: Prog-> [string], next, ...
155 +** TheStack-> next, ...
156 +** After: Prog-> string, [next], ...
157 +** TheStack-> [string], next, ...
159 +static int pushString(void)
161 + const char *str;
163 + DISASM_RT();
164 + STACKDUMP(0, 3);
166 + GET_STR(str);
168 + PUSH_STRING((char *)str, strlen(str));
170 + return STAT_OK;
173 static int pushArgVal(void)
175 int nArgs, argNum;
176 @@ -2919,7 +2920,7 @@ int OverlayRoutineFromProg(Program *prog
177 Symbol sym;
179 sym.type = MACRO_FUNCTION_SYM;
180 - sym.name = prog->name;
181 + sym.name = LookupString(prog->name, True);
182 sym.value.val.prog = prog;
183 sym.next = NULL;
185 @@ -4087,6 +4088,108 @@ static int errCheck(const char *s)
189 +** string lookup stuff
192 +/* should be the pagesize */
193 +#define STRING_BLK_SIZE 4096
195 +typedef struct stringEntryTag {
196 + struct stringEntryTag *next;
197 + unsigned int hash;
198 + char str[1]; /* [1] for inUse */
199 +} stringEntry;
201 +struct stringBlkTag;
202 +typedef struct stringBlkHdrTag {
203 + struct stringBlkTag *next;
204 + unsigned size;
205 + unsigned rem;
206 + stringEntry *free;
207 +} stringBlkHdr;
209 +typedef struct stringBlkTag {
210 + stringBlkHdr hdr;
211 + char blk[1];
212 +} stringBlk;
214 +static stringBlk *lookupStringBlks;
215 +#define STR_LOOKUP_TAB_SHIFT 10
216 +#define STR_LOOKUP_TAB_SIZE (1u << (STR_LOOKUP_TAB_SHIFT))
217 +#define STR_LOOKUP_TAB_MASK ((STR_LOOKUP_TAB_SIZE) - 1)
218 +static stringEntry *stringTbl[STR_LOOKUP_TAB_SIZE];
220 +const char *LookupString(const char *str, int create)
222 +#define ROUNDUP(x, align) (void *)(-(-((intptr_t)(x)) & -(align)))
223 + unsigned int len = strlen(str) + 1;
224 + unsigned int hash = hashName(str);
225 + unsigned int idx = hash & STR_LOOKUP_TAB_MASK;
226 + stringBlk **blkp = &lookupStringBlks;
227 + stringBlk *blk;
228 + stringEntry *e;
230 + /* search str in hash table */
231 + for (e = stringTbl[idx]; e; e = e->next) {
232 + if (e->hash == hash && 0 == strcmp(str, &e->str[1]))
233 + return &e->str[1];
235 + if (!create) {
236 + return NULL;
239 + /* find space for str */
240 + while (*blkp) {
241 + if ((*blkp)->hdr.rem >= len) {
242 + break;
244 + blkp = &(*blkp)->hdr.next;
246 + blk = *blkp;
248 + /* no space found, create new string bulk */
249 + if (!blk) {
250 + void *ptr;
251 + unsigned size = (unsigned)ROUNDUP(sizeof(stringBlkHdr), sizeof(void *))
252 + + sizeof(stringEntry) + len;
253 + size = (unsigned)ROUNDUP(size, STRING_BLK_SIZE);
255 + posix_memalign(&ptr, STRING_BLK_SIZE, size);
256 + *blkp = blk = ptr;
257 + blk->hdr.size = size;
258 + blk->hdr.next = NULL;
260 + /* round up to sizeof(void *) */
261 + blk->hdr.free = ROUNDUP(blk->blk, sizeof(void *));
262 + blk->hdr.rem = ((char *)blk + blk->hdr.size)
263 + - blk->hdr.free->str - sizeof(stringEntry);
266 + /* mark string as constant and copy str into bulk */
267 + blk->hdr.free->str[1] = 1;
268 + strcpy(&blk->hdr.free->str[1], str);
269 + str = &blk->hdr.free->str[1];
271 + /* insert string into hash table */
272 + blk->hdr.free->next = stringTbl[idx];
273 + blk->hdr.free->hash = hash;
274 + stringTbl[idx] = blk->hdr.free;
276 + /* calculate remaining space */
277 + blk->hdr.free = ROUNDUP((char *)blk->hdr.free + sizeof(stringEntry) + len,
278 + sizeof(void *));
279 + blk->hdr.rem = ((char *)blk + blk->hdr.size) - blk->hdr.free->str;
280 + if (blk->hdr.rem <= sizeof(stringEntry) + 2) {
281 + blk->hdr.rem = 0;
282 + } else {
283 + blk->hdr.rem -= sizeof(stringEntry);
286 + return str;
287 +#undef ROUNDUP
291 ** build a stack dump string, reallocating s as necessary.
293 static char *stackDumpStr(DataValue *fp, const char *msg, char **s, int *pLen)
294 @@ -4265,6 +4368,8 @@ static const char *instTypeToStr(enum in
295 return "operation";
296 case IMMED_INST:
297 return "immediate";
298 + case STRING_INST:
299 + return "string";
300 case BRANCH_INST:
301 return "branch";
302 case SYM_INST:
303 @@ -4275,6 +4380,41 @@ static const char *instTypeToStr(enum in
306 #ifdef DEBUG_DISASSEMBLER /* dumping values in disassembly or stack dump */
307 +static const char *printableString(const char *src, int *shortaged)
309 + int k, l;
310 + static char s[64];
312 + for (k = 0, l = 0; src[k] && l < sizeof s - 1; k++, l++) {
313 + const char *e;
314 + const char to[] = "\\\"ntbrfave";
315 +#ifdef EBCDIC_CHARSET
316 + const char from[] = "\\\"\n\t\b\r\f\a\v\x27"; /* EBCDIC escape */
317 +#else
318 + const char from[] = "\\\"\n\t\b\r\f\a\v\x1B"; /* ASCII escape */
319 +#endif
320 + if ((e = strchr(from, src[k]))) {
321 + if (l < sizeof s - 2) {
322 + s[l++] = '\\';
323 + s[l] = to[e - from];
326 + else if (isprint(src[k])) {
327 + s[l] = src[k];
329 + else {
330 + s[l] = '?';
333 + s[l] = 0;
335 + if (shortaged) {
336 + *shortaged = !!src[k];
339 + return s;
342 static char *printdBuffer = NULL;
343 static int printdPos = 0;
344 static int printdSize = 0;
345 @@ -4362,30 +4502,11 @@ static void dumpVal(DataValue dv)
346 printd(" <%s NULL>", tagToStr(STRING_TAG));
348 else {
349 - for (k = 0, l = 0; src[k] && l < sizeof s - 1; k++, l++) {
350 - char *e;
351 - const char to[] = "\\\"ntbrfave";
352 -#ifdef EBCDIC_CHARSET
353 - const char from[] = "\\\"\n\t\b\r\f\a\v\x27"; /* EBCDIC escape */
354 -#else
355 - const char from[] = "\\\"\n\t\b\r\f\a\v\x1B"; /* ASCII escape */
356 -#endif
357 - if ((e = strchr(from, src[k]))) {
358 - if (l < sizeof s - 2) {
359 - s[l++] = '\\';
360 - s[l] = to[e - from];
363 - else if (isprint(src[k])) {
364 - s[l] = src[k];
366 - else {
367 - s[l] = '?';
370 - s[l] = 0;
371 - printd(" <%s %u:\"%s\"%s>", tagToStr(STRING_TAG),
372 - (unsigned)strlen(src), s, src[k] ? "..." : "");
373 + int cut;
374 + unsigned len = strlen(src);
375 + src = printableString(src, &cut);
376 + printd(" <%s %u:\"%s\"%s>", tagToStr(STRING_TAG), len, src,
377 + cut ? "..." : "");
380 break;
381 @@ -4448,6 +4569,16 @@ static void dumpInst(Inst *inst, const c
382 printd(" <%s %d>", name, inst->val.immed);
383 break;
385 + case STRING_INST: {
386 + const char *str = inst->val.str;
387 + int cut;
388 + unsigned len = strlen(str);
389 + str = printableString(str, &cut);
390 + printd(" <%s %u:\"%s\"%s>", name,
391 + len, str, cut ? "..." : "");
393 + break;
395 case BRANCH_INST:
396 printd(" <%s %+td:%8p>", name,
397 inst->val.branch, inst + inst->val.branch);
398 @@ -4501,10 +4632,6 @@ static void disasmInternal(Inst *inst, i
399 case OP_ASSIGN:
400 CHECK_OPERANDS(1, SYM_INST);
401 dumpInst(&inst[i+1], NULL);
402 - if (inst[i+1].val.sym->type == CONST_SYM
403 - && inst[i+1].val.sym->value.tag == STRING_TAG) {
404 - dumpVal(inst[i+1].val.sym->value);
406 ++i;
407 break;
409 @@ -4520,6 +4647,12 @@ static void disasmInternal(Inst *inst, i
410 ++i;
411 break;
413 + case OP_PUSH_STRING:
414 + CHECK_OPERANDS(1, STRING_INST);
415 + dumpInst(&inst[i+1], NULL);
416 + ++i;
417 + break;
419 case OP_BRANCH:
420 case OP_BRANCH_TRUE:
421 case OP_BRANCH_FALSE:
422 diff --quilt old/source/interpret.h new/source/interpret.h
423 --- old/source/interpret.h
424 +++ new/source/interpret.h
425 @@ -40,7 +40,7 @@
426 #define LOOP_STACK_SIZE 256 /* (Approx.) Number of break/continue stmts
427 allowed per program */
429 -enum symTypes {CONST_SYM, GLOBAL_SYM, LOCAL_SYM, ARG_SYM, PROC_VALUE_SYM,
430 +enum symTypes {GLOBAL_SYM, LOCAL_SYM, ARG_SYM, PROC_VALUE_SYM,
431 C_FUNCTION_SYM, MACRO_FUNCTION_SYM, ACTION_ROUTINE_SYM};
433 enum operations {
434 @@ -54,7 +54,7 @@ enum typeTags {NO_TAG, INT_TAG, STRING_T
436 enum execReturnCodes {MACRO_TIME_LIMIT, MACRO_PREEMPT, MACRO_DONE, MACRO_ERROR};
438 -enum instTypes {OP_INST, IMMED_INST, BRANCH_INST, SYM_INST};
439 +enum instTypes {OP_INST, IMMED_INST, STRING_INST, BRANCH_INST, SYM_INST};
441 #define ARRAY_DIM_SEP "\034"
443 @@ -68,6 +68,7 @@ typedef struct InstTag {
444 union {
445 enum operations op;
446 int immed;
447 + const char *str;
448 ptrdiff_t branch;
449 struct SymbolRec *sym;
450 } val;
451 @@ -104,7 +105,7 @@ typedef struct SparseArrayEntryTag {
453 /* symbol table entry */
454 typedef struct SymbolRec {
455 - char *name;
456 + const char *name;
457 enum symTypes type;
458 DataValue value;
459 unsigned int hash;
460 @@ -112,7 +113,7 @@ typedef struct SymbolRec {
461 } Symbol;
463 typedef struct ProgramTag {
464 - char *name;
465 + const char *name;
466 Symbol *localSymList;
467 Inst *code;
468 unsigned refcount;
469 @@ -158,13 +159,13 @@ Program *FinishCreatingProgram(Accumulat
470 int AddOp(int op, char **msg);
471 int AddSym(Symbol *sym, char **msg);
472 int AddImmediate(int immed, char **msg);
473 +int AddString(const char *str, char **msg);
474 int AddBranchOffset(Inst *to, char **msg);
475 int SetBranchOffset(Inst *from, Inst *to, char **msg);
476 Inst *GetPC(void);
477 -Symbol *LookupStringConstSymbol(const char *value);
478 -Symbol *InstallStringConstSymbol(const char *str);
479 Symbol *LookupSymbol(const char *name);
480 Symbol *InstallSymbol(const char *name, enum symTypes type, DataValue value);
481 +const char *LookupString(const char *str, int create);
482 Inst *SwapCode(Inst *start, Inst *boundary, Inst *end);
483 int StartLoopAddrList(char **msg);
484 int AddBreakAddr(Inst *addr, char **msg);
485 diff --quilt old/source/ops.h new/source/ops.h
486 --- old/source/ops.h
487 +++ new/source/ops.h
488 @@ -7,6 +7,7 @@ OP(RETURN_NO_VAL, returnNoVal)
489 OP(RETURN, returnVal) /* pop(ret), rewind, push(ret) */
490 OP(PUSH_SYM, pushSymVal) /* sym */ /* push(sym.v) */
491 OP(PUSH_IMMED, pushImmed) /* immed */ /* push(immed) */
492 +OP(PUSH_STRING, pushString) /* str */ /* push(str) */
493 OP(POP, popStack) /* pop(v) */
494 OP(DUP, dupStack) /* pop(v), push(v,v) */
495 OP(PEEK_PUSH, peekPush) /* n */ /* peek(v, n), push(v) */
496 diff --quilt old/source/parse.y new/source/parse.y
497 --- old/source/parse.y
498 +++ new/source/parse.y
499 @@ -47,6 +47,12 @@
500 return 1; \
502 } while (0)
503 +#define ADD_STR(str) \
504 + do { \
505 + if (!AddString(str, &ErrMsg)) { \
506 + return 1; \
507 + } \
508 + } while (0)
509 #define ADD_BR_OFF(to) \
510 do { \
511 if (!AddBranchOffset(to, &ErrMsg)) { \
512 @@ -108,13 +114,15 @@ static int nextSymIsField = 0;
513 Symbol *sym;
514 Inst *inst;
515 int num;
516 + const char *str;
517 enum operations oper;
518 struct {
519 AccumulatorData *acc;
520 Symbol *sym;
521 } define;
523 -%token <sym> STRING SYMBOL FIELD
524 +%token <sym> SYMBOL
525 +%token <str> STRING FIELD
526 %token <num> NUMBER
527 %token DELETE ARG_LOOKUP
528 %token IF WHILE DO ELSE FOR BREAK CONTINUE RETURN DEFINE TYPEOF KEYVAL
529 @@ -624,7 +632,7 @@ arraylv: SYMBOL {
532 field: FIELD {
533 - ADD_OP(OP_PUSH_SYM); ADD_SYM($1);
534 + ADD_OP(OP_PUSH_STRING); ADD_STR($1);
536 /* this bit allows things like array.5 for array[5] **
537 | NUMBER {
538 @@ -674,7 +682,7 @@ arrentry: blank {
540 numexpr: '(' blank expr blank ')'
541 | NUMBER { ADD_OP(OP_PUSH_IMMED); ADD_IMMED($1); }
542 - | STRING { ADD_OP(OP_PUSH_SYM); ADD_SYM($1); }
543 + | STRING { ADD_OP(OP_PUSH_STRING); ADD_STR($1); }
544 | SYMBOL { ADD_OP(OP_PUSH_SYM); ADD_SYM($1); }
545 | funccall {
546 ADD_OP(OP_FETCH_RET_VAL);
547 @@ -925,7 +933,7 @@ static int yylex(void)
548 if (!strcmp(symName, "typeof")) return TYPEOF;
549 if (nextSymIsField) {
550 nextSymIsField = 0;
551 - yylval.sym = InstallStringConstSymbol(symName);
552 + yylval.str = LookupString(symName, True);
553 return FIELD;
555 if ((s=LookupSymbol(symName)) == NULL) {
556 @@ -1260,12 +1268,13 @@ static int scanString(void)
557 if (*InPtr == stopper) {
558 if (!p) {
559 /* this was the size measurement and validation */
560 - p = string = AllocString(len);
561 + p = string = XtMalloc(len);
563 else {
564 /* OK: string now contains our string text */
565 InPtr++; /* skip past stopper */
566 - yylval.sym = InstallStringConstSymbol(string);
567 + yylval.str = LookupString(string, True);
568 + XtFree(string);
569 return STRING;