mathing_patterns: fix off by one alloc error
[nedit-bw.git] / pushString.patch
blob9162d2286d8514a8e7e28c718a66286b4328a501
1 ---
3 source/interpret.c | 281 ++++++++++++++++++++++++++++++++++++++---------------
4 source/interpret.h | 17 +--
5 source/ops.h | 1
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
13 * *
14 *******************************************************************************/
16 +#define _POSIX_C_SOURCE 200112L
17 #ifdef HAVE_CONFIG_H
18 #include "../config.h"
19 #endif
20 @@ -288,12 +289,11 @@ Program *FinishCreatingProgram(Accumulat
21 Symbol *s;
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);
39 XtFree((char *)prog);
42 @@ -365,6 +364,21 @@ int AddImmediate(int immed, char **msg)
46 +** Add an string value operand to the current program
47 +*/
48 +int AddString(const char *str, char **msg)
50 + if (ProgP >= &Prog[PROGRAM_SIZE]) {
51 + *msg = "macro too large";
52 + return 0;
53 + }
54 + ProgP->type = STRING_INST;
55 + ProgP->val.str = str;
56 + ProgP++;
57 + return 1;
60 +/*
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
68 -/*
69 -** Lookup a constant string by its value. This allows reuse of string
70 -** constants and fixing a leak in the interpreter.
71 -*/
72 -Symbol *LookupStringConstSymbol(const char *value)
74 - unsigned int idx;
75 - Symbol *s;
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)) {
82 - return(s);
83 - }
84 - }
85 - }
87 - return(NULL);
90 -/*
91 -** install string str in the global symbol table with a string name
92 -*/
93 -Symbol *InstallStringConstSymbol(const char *str)
95 - static int stringConstIndex = 0;
96 - char stringName[35];
97 - DataValue value;
98 - Symbol *sym = LookupStringConstSymbol(str);
99 - if (sym) {
100 - return sym;
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,
110 unsigned int hash)
112 @@ -909,8 +882,7 @@ Symbol *InstallSymbol(const char *name,
113 Symbol *s;
115 s = XtNew(Symbol);
116 - s->name = (char *)XtMalloc(strlen(name) + 1); /* +1 for '\0' */
117 - strcpy(s->name, name);
118 + s->name = LookupString(name, True);
119 s->type = type;
120 s->value = value;
121 s->hash = hashName(s->name);
122 @@ -1290,7 +1262,6 @@ static void freeSymbolList(Symbol *symLi
123 while (symList != NULL) {
124 s = symList;
125 symList = s->next;
126 - XtFree((char *)s->name);
127 XtFree((char *)s);
130 @@ -1352,6 +1323,16 @@ static void addToGlobalSymTab(Symbol *sy
131 PC++; \
132 } while (0)
134 +#define GET_STR(s) \
135 + do { \
136 + if (PC->type != STRING_INST) { \
137 + EXEC_ERROR("Unexpected instruction, expected <string>: <%s>", \
138 + instTypeToStr(PC->type)); \
139 + } \
140 + s = PC->val.str; \
141 + PC++; \
142 + } while (0)
144 #define JUMP(a) \
145 do { \
146 PC = (a); \
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) {
153 symVal = s->value;
154 } else if (s->type == ARG_SYM) {
155 nArgs = FP_GET_ARG_COUNT(FrameP);
156 @@ -1586,6 +1567,27 @@ static int pushImmed(void)
157 return STAT_OK;
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)
169 + const char *str;
171 + DISASM_RT();
172 + STACKDUMP(0, 3);
174 + GET_STR(str);
176 + PUSH_STRING((char *)str, strlen(str));
178 + return STAT_OK;
181 static int pushArgVal(void)
183 int nArgs, argNum;
184 @@ -2924,7 +2926,7 @@ int OverlayRoutineFromProg(Program *prog
185 Symbol sym;
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;
192 sym.next = NULL;
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;
205 + unsigned int hash;
206 + char str[1]; /* [1] for inUse */
207 +} stringEntry;
209 +typedef struct stringBlkHdrTag {
210 + struct stringBlkHdrTag *next;
211 + size_t size;
212 + size_t rem;
213 + stringEntry *free;
214 +} stringBlkHdr;
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;
229 + stringBlkHdr *blk;
230 + stringEntry *e;
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]))
235 + return &e->str[1];
237 + if (!create) {
238 + return NULL;
241 + /* find space for str */
242 + while (*blkp) {
243 + if ((*blkp)->rem >= len) {
244 + break;
246 + blkp = &(*blkp)->next;
248 + blk = *blkp;
250 + /* no space found, create new string bulk */
251 + if (!blk) {
252 + void *ptr = NULL;
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);
258 + *blkp = blk = ptr;
259 + blk->size = size;
260 + blk->next = NULL;
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,
279 + sizeof(void *));
280 + if (((char *)blk + blk->size) >= ((char *)blk->free + sizeof(stringEntry))) {
281 + blk->rem = ((char *)blk + blk->size) - ((char *)blk->free + sizeof(stringEntry));
282 + } else {
283 + blk->rem = 0;
286 + return str;
287 +#undef ROUNDUP
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
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 @@ -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)
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 void dumpVal(DataValue dv)
344 switch (dv.tag) {
345 @@ -4362,38 +4495,16 @@ static void dumpVal(DataValue dv)
346 break;
347 case STRING_TAG:
349 - int k, l;
350 - char s[64];
351 const char *src = dv.val.str.rep;
352 - unsigned len = dv.val.str.len;
353 if (!src) {
354 printd(" <%s NULL>", tagToStr(STRING_TAG));
356 else {
357 - for (k = 0, l = 0; src[k] && l < sizeof s - 1; k++, l++) {
358 - char *e;
359 - const char to[] = "\\\"ntbrfave";
360 -#ifdef EBCDIC_CHARSET
361 - const char from[] = "\\\"\n\t\b\r\f\a\v\x27"; /* EBCDIC escape */
362 -#else
363 - const char from[] = "\\\"\n\t\b\r\f\a\v\x1B"; /* ASCII escape */
364 -#endif
365 - if ((e = strchr(from, src[k]))) {
366 - if (l < sizeof s - 2) {
367 - s[l++] = '\\';
368 - s[l] = to[e - from];
371 - else if (isprint(src[k])) {
372 - s[l] = src[k];
374 - else {
375 - s[l] = '?';
378 - s[l] = 0;
379 + int cut;
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 ? "..." : "");
387 break;
388 @@ -4456,6 +4567,16 @@ static void dumpInst(Inst *inst, const c
389 printd(" <%s %d>", name, inst->val.immed);
390 break;
392 + case STRING_INST: {
393 + const char *str = inst->val.str;
394 + int cut;
395 + unsigned len = strlen(str);
396 + str = printableString(str, &cut);
397 + printd(" <%s %u:\"%s\"%s>", name,
398 + len, str, cut ? "..." : "");
400 + break;
402 case BRANCH_INST:
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
406 case OP_ASSIGN:
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);
413 ++i;
414 break;
416 @@ -4523,6 +4640,12 @@ static void disasmInternal(Inst *inst, i
417 ++i;
418 break;
420 + case OP_PUSH_STRING:
421 + CHECK_OPERANDS(1, STRING_INST);
422 + dumpInst(&inst[i+1], NULL);
423 + ++i;
424 + break;
426 case OP_PEEK_PUSH:
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
432 @@ -40,7 +40,7 @@
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};
440 enum operations {
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 {
451 union {
452 enum operations op;
453 int immed;
454 + const char *str;
455 ptrdiff_t branch;
456 struct SymbolRec *sym;
457 } val;
458 @@ -104,7 +105,7 @@ typedef struct SparseArrayEntryTag {
460 /* symbol table entry */
461 typedef struct SymbolRec {
462 - char *name;
463 + const char *name;
464 enum symTypes type;
465 DataValue value;
466 unsigned int hash;
467 @@ -112,7 +113,7 @@ typedef struct SymbolRec {
468 } Symbol;
470 typedef struct ProgramTag {
471 - char *name;
472 + const char *name;
473 Symbol *localSymList;
474 Inst *code;
475 unsigned refcount;
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);
483 Inst *GetPC(void);
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
503 --- old/source/ops.h
504 +++ 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
516 @@ -47,6 +47,12 @@
517 return 1; \
519 } while (0)
520 +#define ADD_STR(str) \
521 + do { \
522 + if (!AddString(str, &ErrMsg)) { \
523 + return 1; \
524 + } \
525 + } while (0)
526 #define ADD_BR_OFF(to) \
527 do { \
528 if (!AddBranchOffset(to, &ErrMsg)) { \
529 @@ -114,13 +120,15 @@ static int nextSymIsField = 0;
530 Symbol *sym;
531 Inst *inst;
532 int num;
533 + const char *str;
534 enum operations oper;
535 struct {
536 AccumulatorData *acc;
537 Symbol *sym;
538 } define;
540 -%token <sym> STRING SYMBOL FIELD
541 +%token <sym> SYMBOL
542 +%token <str> STRING FIELD
543 %token <num> NUMBER
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 {
549 field: FIELD {
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] **
554 | NUMBER {
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); }
562 | funccall {
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) {
567 nextSymIsField = 0;
568 - yylval.sym = InstallStringConstSymbol(symName);
569 + yylval.str = LookupString(symName, True);
570 return FIELD;
572 if ((s=LookupSymbol(symName)) == NULL) {
573 @@ -1268,12 +1276,13 @@ static int scanString(void)
574 if (*InPtr == stopper) {
575 if (!p) {
576 /* this was the size measurement and validation */
577 - p = string = AllocString(len);
578 + p = string = XtMalloc(len);
580 else {
581 /* OK: string now contains our string text */
582 InPtr++; /* skip past stopper */
583 - yylval.sym = InstallStringConstSymbol(string);
584 + yylval.str = LookupString(string, True);
585 + XtFree(string);
586 return STRING;