3 source/interpret.c | 503 ++++++++++++++++++++++++++++++-----------------------
5 source/parse.y | 33 ++-
6 3 files changed, 328 insertions(+), 223 deletions(-)
8 diff --quilt old/source/macro.c new/source/macro.c
10 +++ new/source/macro.c
11 @@ -110,12 +110,23 @@ static const char CVSID[] = "$Id: macro.
12 /* How long to wait (msec) before putting up Macro Command banner */
13 #define BANNER_WAIT_TIME 6000
15 /* The following definitions cause an exit from the macro with a message */
16 /* added if (1) to remove compiler warnings on solaris */
17 -#define M_FAILURE(s) do { *errMsg = s; if (1) return False; } while (0)
18 -#define M_STR_ALLOC_ASSERT(xDV) do { if (xDV.tag == STRING_TAG && !xDV.val.str.rep) { *errMsg = "Failed to allocate value: %s"; return(False); } } while (0)
19 +#define M_FAILURE(s) \
25 +#define M_STR_ALLOC_ASSERT(xDV) \
27 + if (xDV.tag == STRING_TAG && !xDV.val.str.rep) { \
28 + *errMsg = "Failed to allocate value: %s"; \
32 #define M_ARRAY_INSERT_FAILURE() M_FAILURE("array element failed to insert: %s")
34 /* Data attached to window during shell command execution with
35 information for controling and communicating with the process */
37 diff --quilt old/source/parse.y new/source/parse.y
38 --- old/source/parse.y
39 +++ new/source/parse.y
45 /* Macros to add error processing to AddOp and AddSym calls */
46 -#define ADD_OP(op) if (!AddOp(op, &ErrMsg)) return 1
47 -#define ADD_SYM(sym) if (!AddSym(sym, &ErrMsg)) return 1
48 -#define ADD_IMMED(val) if (!AddImmediate(val, &ErrMsg)) return 1
49 -#define ADD_BR_OFF(to) if (!AddBranchOffset(to, &ErrMsg)) return 1
50 -#define SET_BR_OFF(from, to) ((from)->value) = ((Inst *)(to)) - ((Inst *)(from))
53 + if (!AddOp(op, &ErrMsg)) { \
57 +#define ADD_SYM(sym) \
59 + if (!AddSym(sym, &ErrMsg)) { \
63 +#define ADD_IMMED(val) \
65 + if (!AddImmediate(val, &ErrMsg)) { \
69 +#define ADD_BR_OFF(to) \
71 + if (!AddBranchOffset(to, &ErrMsg)) { \
75 +#define SET_BR_OFF(from, to) \
77 + ((from)->value) = ((Inst *)(to)) - ((Inst *)(from)); \
80 /* Max. length for a string constant (... there shouldn't be a maximum) */
81 #define MAX_STRING_CONST_LEN 5000
83 static const char CVSID[] = "$Id: parse.y,v 1.29 2007/01/12 16:17:42 tringali Exp $";
84 diff --quilt old/source/interpret.c new/source/interpret.c
85 --- old/source/interpret.c
86 +++ new/source/interpret.c
87 @@ -66,11 +66,11 @@ static const char CVSID[] = "$Id: interp
91 #define PROGRAM_SIZE 4096 /* Maximum program size */
92 #define MAX_ERR_MSG_LEN 256 /* Max. length for error messages */
93 -#define LOOP_STACK_SIZE 200 /* (Approx.) Number of break/continue stmts
94 +#define LOOP_STACK_SIZE 256 /* (Approx.) Number of break/continue stmts
95 allowed per program */
96 #define INSTRUCTION_LIMIT 100 /* Number of instructions the interpreter is
97 allowed to execute before preempting and
98 returning to allow other things to run */
100 @@ -209,11 +209,11 @@ static SparseArrayEntryWrapper *Allocate
102 /* Message strings used in macros (so they don't get repeated every time
103 the macros are used */
104 static const char *StackOverflowMsg = "macro stack overflow";
105 static const char *StackUnderflowMsg = "macro stack underflow";
106 -static const char *StringToNumberMsg = "string could not be converted to number";
107 +static const char *StringToNumberMsg = "string '%s' could not be converted to number";
109 /* Temporary global data for use while accumulating programs */
110 static Symbol *LocalSymList = NULL; /* symbols local to the program */
111 static Inst Prog[PROGRAM_SIZE]; /* the program */
112 static Inst *ProgP; /* next free spot for code gen. */
113 @@ -271,16 +271,43 @@ static int (*OpFns[N_OPS])() = {returnNo
114 #define FP_ARG_START_INDEX(xFrameP) (-(FP_GET_ARG_COUNT(xFrameP) + FP_TO_ARGS_DIST))
115 #define FP_GET_ARG_N(xFrameP,xN) (FP_GET_ITEM(xFrameP, xN + FP_ARG_START_INDEX(xFrameP)))
116 #define FP_GET_SYM_N(xFrameP,xN) (FP_GET_ITEM(xFrameP, xN))
117 #define FP_GET_SYM_VAL(xFrameP,xSym) (FP_GET_SYM_N(xFrameP, xSym->value.val.n))
119 -#define PUSH_CHECK_TOO_MUCH(n) \
120 - (StackP + (n) > &TheStack[STACK_SIZE])
121 +/* true, if you can pop n values */
122 +#define OK_TO_POP(n) \
123 + ((StackP - (n)) >= TheStack)
125 +#define POP_CHECK(n) \
127 + if (!OK_TO_POP(n)) { \
128 + return execError(StackUnderflowMsg, ""); \
132 +/* true, if you can push n values */
133 +#define OK_TO_PUSH(n) \
134 + (StackP + (n) <= &TheStack[STACK_SIZE])
136 #define PUSH_CHECK(n) \
137 - if (PUSH_CHECK_TOO_MUCH(n)) \
138 - return execError(StackOverflowMsg, "");
140 + if (!OK_TO_PUSH(n)) { \
141 + return execError(StackOverflowMsg, ""); \
145 +#define PEEK_CHECK(n) \
147 + if (!OK_TO_POP((n) + 1)) { \
148 + return execError(StackUnderflowMsg, ""); \
150 + if (!OK_TO_PUSH(-(n))) { \
151 + return execError(StackOverflowMsg, ""); \
155 +static const char *tagToStr(enum typeTags tag);
158 ** Initialize macro language global variables. Must be called before
159 ** any macros are even parsed, because the parser uses action routine
160 ** symbols to comprehend hyphenated names.
161 @@ -491,11 +518,11 @@ int AddContinueAddr(Inst *addr)
165 static void addLoopAddr(Inst *addr)
167 - if (LoopStackPtr > &LoopStack[LOOP_STACK_SIZE-1]) {
168 + if (LoopStackPtr >= &LoopStack[LOOP_STACK_SIZE]) {
169 fprintf(stderr, "NEdit: loop stack overflow in macro parser");
172 *LoopStackPtr++ = addr;
174 @@ -663,11 +690,11 @@ void RunMacroAsSubrCall(Program *prog)
176 static DataValue noValue = {NO_TAG, {0}};
178 /* See subroutine "callSubroutine" for a description of the stack frame
179 for a subroutine call */
180 - /* if (PUSH_CHECK_TOO_MUCH(4)) return MACRO_ERROR; */
181 + /* if (!OK_TO_PUSH(4)) return MACRO_ERROR; */
183 *(StackP++) = noValue; /* cached arg array */
185 StackP->tag = NO_TAG;
186 StackP->val.inst = PC; /* return PC */
187 @@ -691,11 +718,11 @@ void RunMacroAsSubrCall(Program *prog)
192 for (s = prog->localSymList; s != NULL; s = s->next) {
193 - /* if (PUSH_CHECK_TOO_MUCH(1)) return MACRO_ERROR; */
194 + /* if (!OK_TO_PUSH(1)) return MACRO_ERROR; */
195 FP_GET_SYM_VAL(FrameP, s) = noValue;
198 /* return MACRO_DONE? MACRO_PREEMPT? MACRO_TIME_LIMIT? */
200 @@ -870,14 +897,21 @@ Symbol *PromoteToGlobal(Symbol *sym)
206 - s = LookupSymbol(sym->name);
209 - return InstallSymbol(sym->name, GLOBAL_SYM, noValue);
210 + if (NULL != LookupSymbol(sym->name)) {
212 + "nedit: To boldly go where no local sym has gone before: %s\n",
216 + sym->type = GLOBAL_SYM;
217 + sym->next = GlobalSymList;
218 + GlobalSymList = sym;
224 ** Convert a long value to its decimal string representation, returned in a
226 @@ -1195,99 +1229,122 @@ static void freeSymbolTable(Symbol *symT
231 #define POP(dataVal) \
232 - if (StackP == TheStack) \
233 - return execError(StackUnderflowMsg, ""); \
234 - dataVal = *--StackP;
237 + dataVal = *--StackP; \
240 #define PUSH(dataVal) \
241 - if (StackP >= &TheStack[STACK_SIZE]) \
242 - return execError(StackOverflowMsg, ""); \
243 - *StackP++ = dataVal;
246 + *StackP++ = dataVal; \
249 #define PEEK(dataVal, peekIndex) \
250 - dataVal = *(StackP - peekIndex - 1);
252 + PEEK_CHECK(peekIndex); \
253 + dataVal = *(StackP - peekIndex - 1); \
256 +#define TO_INT(dataVal, number) \
259 + if (dataVal.tag == INT_TAG) { \
260 + __int = dataVal.val.n; \
261 + } else if (dataVal.tag == STRING_TAG) { \
262 + if (!StringToNum(dataVal.val.str.rep, &__int)) {\
263 + return execError(StringToNumberMsg, dataVal.val.str.rep); \
266 + return(execError("incompatible type in integer context: %s", \
267 + tagToStr(dataVal.tag))); \
272 +#define TO_STRING(dataVal, string) \
275 + if (dataVal.tag == STRING_TAG) { \
276 + __str = dataVal.val.str.rep; \
277 + } else if (dataVal.tag == INT_TAG) { \
278 + __str = AllocStringOfNumber(dataVal.val.n); \
280 + return(execError("incompatible type in string context: %s", \
281 + tagToStr(dataVal.tag))); \
286 #define POP_INT(number) \
287 - if (StackP == TheStack) \
288 - return execError(StackUnderflowMsg, ""); \
290 - if (StackP->tag == STRING_TAG) { \
291 - if (!StringToNum(StackP->val.str.rep, &number)) \
292 - return execError(StringToNumberMsg, ""); \
293 - } else if (StackP->tag == INT_TAG) \
294 - number = StackP->val.n; \
296 - return(execError("can't convert array to integer", NULL));
300 + TO_INT(dv, number); \
303 #define POP_STRING(string) \
304 - if (StackP == TheStack) \
305 - return execError(StackUnderflowMsg, ""); \
307 - if (StackP->tag == INT_TAG) { \
308 - string = AllocStringOfNumber(StackP->val.n); \
309 - } else if (StackP->tag == STRING_TAG) \
310 - string = StackP->val.str.rep; \
312 - return(execError("can't convert array to string", NULL));
314 -#define PEEK_STRING(string, peekIndex) \
315 - if ((StackP - peekIndex - 1)->tag == INT_TAG) { \
316 - string = AllocStringOfNumber((StackP - peekIndex - 1)->val.n); \
318 - else if ((StackP - peekIndex - 1)->tag == STRING_TAG) { \
319 - string = (StackP - peekIndex - 1)->val.str.rep; \
322 - return(execError("can't convert array to string", NULL)); \
327 + TO_STRING(dv, string); \
330 #define PEEK_INT(number, peekIndex) \
331 - if ((StackP - peekIndex - 1)->tag == STRING_TAG) { \
332 - if (!StringToNum((StackP - peekIndex - 1)->val.str.rep, &number)) { \
333 - return execError(StringToNumberMsg, ""); \
335 - } else if ((StackP - peekIndex - 1)->tag == INT_TAG) { \
336 - number = (StackP - peekIndex - 1)->val.n; \
339 - return(execError("can't convert array to string", NULL)); \
343 + PEEK(dv, peekIndex); \
344 + TO_INT(dv, number); \
347 +#define PEEK_STRING(string, peekIndex) \
351 + TO_STRING(dv, string); \
354 #define PUSH_INT(number) \
355 - if (StackP >= &TheStack[STACK_SIZE]) \
356 - return execError(StackOverflowMsg, ""); \
357 - StackP->tag = INT_TAG; \
358 - StackP->val.n = number; \
363 + dv.tag = INT_TAG; \
364 + dv.val.n = (number); \
368 #define PUSH_STRING(string, length) \
369 - if (StackP >= &TheStack[STACK_SIZE]) \
370 - return execError(StackOverflowMsg, ""); \
371 - StackP->tag = STRING_TAG; \
372 - StackP->val.str.rep = string; \
373 - StackP->val.str.len = length; \
377 + dv.tag = STRING_TAG; \
378 + dv.val.str.rep = string; \
379 + dv.val.str.len = length; \
383 #define BINARY_NUMERIC_OPERATION(operator) \
385 - DISASM_RT(PC-1, 1); \
389 - PUSH_INT(n1 operator n2) \
393 + DISASM_RT(PC-1, 1); \
397 + PUSH_INT(n1 operator n2); \
401 #define UNARY_NUMERIC_OPERATION(operator) \
403 - DISASM_RT(PC-1, 1); \
406 - PUSH_INT(operator n) \
410 + DISASM_RT(PC-1, 1); \
413 + PUSH_INT(operator n); \
418 ** copy a symbol's value onto the stack
419 ** Before: Prog-> [Sym], next, ...
420 ** TheStack-> next, ...
421 @@ -1333,11 +1390,11 @@ static int pushSymVal(void)
422 return execError("reading non-variable: %s", s->name);
423 if (symVal.tag == NO_TAG && !inTypeOfMode) {
424 return execError("variable not set: %s", s->name);
433 static int pushArgVal(void)
434 @@ -1345,11 +1402,11 @@ static int pushArgVal(void)
443 nArgs = FP_GET_ARG_COUNT(FrameP);
444 if (argNum >= nArgs || argNum < 0) {
445 return execError("referenced undefined argument: $args[%s]",
446 longAsStr(argNum + 1));
447 @@ -1421,17 +1478,15 @@ static int pushArraySymVal(void)
449 initEmpty = PC->value;
452 if (sym->type == LOCAL_SYM) {
453 - dataPtr = &FP_GET_SYM_VAL(FrameP, sym);
455 - else if (sym->type == GLOBAL_SYM) {
456 - dataPtr = &sym->value;
459 - return execError("assigning to non-lvalue array or non-array: %s", sym->name);
460 + dataPtr = &FP_GET_SYM_VAL(FrameP, sym);
461 + } else if (sym->type == GLOBAL_SYM) {
462 + dataPtr = &sym->value;
464 + return execError("assigning to non-lvalue array or non-array: %s", sym->name);
467 if (initEmpty && dataPtr->tag == NO_TAG) {
468 dataPtr->tag = ARRAY_TAG;
469 dataPtr->val.arrayPtr = ArrayNew();
470 @@ -1439,11 +1494,11 @@ static int pushArraySymVal(void)
472 if (dataPtr->tag == NO_TAG && !inTypeOfMode) {
473 return execError("variable not set: %s", sym->name);
483 @@ -1465,14 +1520,14 @@ static int anonArrayOpen(void)
484 /* make an empty array */
485 dataVal.tag = ARRAY_TAG;
486 dataVal.val.arrayPtr = ArrayNew();
488 /* push the default next index value first */
492 /* and the empty array */
500 @@ -1491,19 +1546,19 @@ static int anonArraySkip(void)
509 + POP_INT(nextIndex);
511 /* we need to increment the index for next time */
514 /* push the default next index value first, then the array */
515 - PUSH_INT(nextIndex)
517 + PUSH_INT(nextIndex);
524 @@ -1523,25 +1578,25 @@ static int anonArrayNextVal(void)
525 char numString[TYPE_INT_STR_SIZE(int)];
535 + POP_INT(nextIndex);
537 sprintf(numString, "%d", nextIndex);
538 if (!ArrayInsert(&anonArray, AllocStringCpy(numString), &exprVal)) {
539 return(execError("array insertion failure", NULL));
542 /* we need to increment the index for next time */
545 /* push the default next index value first, then the array */
546 - PUSH_INT(nextIndex)
548 + PUSH_INT(nextIndex);
555 @@ -1563,20 +1618,20 @@ static int anonArrayIndexVal(void)
559 STACKDUMP(nDim+3, 3);
564 /* the next nDim stack entries form the index */
565 errNum = makeArrayKeyFromArgs(nDim, &keyString, 0);
566 if (errNum != STAT_OK) {
573 + POP_INT(nextIndex);
575 /* if our index is numeric (or can be converted to a number) we must
576 change the next index value */
577 if (nDim == 1 && StringToNum(keyString, &index)) {
578 nextIndex = index + 1;
579 @@ -1585,12 +1640,12 @@ static int anonArrayIndexVal(void)
580 if (!ArrayInsert(&anonArray, keyString, &exprVal)) {
581 return(execError("array insertion failure", NULL));
584 /* push the default next index value first, then the array */
585 - PUSH_INT(nextIndex)
587 + PUSH_INT(nextIndex);
594 @@ -1609,14 +1664,14 @@ static int anonArrayClose(void)
599 /* remove top two elements */
604 /* put back the array content */
612 @@ -1655,16 +1710,17 @@ static int namedArg1orN(Boolean isFirst)
614 char *keyString = NULL;
615 DataValue exprVal, argsArray;
618 - nDim = (PC++)->value;
623 STACKDUMP(nDim + (isFirst ? 2 : 1), 3);
628 /* the next nDim stack entries form the index */
629 errNum = makeArrayKeyFromArgs(nDim, &keyString, 0);
630 if (errNum != STAT_OK) {
632 @@ -1681,19 +1737,19 @@ static int namedArg1orN(Boolean isFirst)
633 argsArray.tag = ARRAY_TAG;
634 argsArray.val.arrayPtr = NULL;
637 /* use the array at the top of the stack */
642 if (!ArrayInsert(&argsArray, keyString, &exprVal)) {
643 return(execError("named argument insertion failure", NULL));
646 /* and (re)push the array */
654 @@ -1704,14 +1760,14 @@ static int swapTop2(void)
673 @@ -1751,11 +1807,11 @@ static int assign(void)
676 dataPtr = &sym->value;
682 if (value.tag == ARRAY_TAG) {
683 ArrayCopy(dataPtr, &value);
686 @@ -1792,11 +1848,11 @@ static int arrayIndex(void)
688 keyData.tag = STRING_TAG;
689 keyData.val.str.rep = keyString;
690 keyData.val.str.len = strlen(keyString);
699 @@ -1809,12 +1865,12 @@ static int dupStack(void)
714 @@ -1831,20 +1887,20 @@ static int add(void)
722 if (rightVal.tag == ARRAY_TAG) {
725 if (leftVal.tag == ARRAY_TAG) {
726 SparseArrayEntry *leftIter, *rightIter;
727 resultArray.tag = ARRAY_TAG;
728 resultArray.val.arrayPtr = ArrayNew();
734 leftIter = arrayIterateFirst(&leftVal);
735 rightIter = arrayIterateFirst(&rightVal);
736 while (leftIter || rightIter) {
737 Boolean insertResult = True;
739 @@ -1874,20 +1930,20 @@ static int add(void)
742 return(execError("array insertion failure", NULL));
749 return(execError("can't mix math with arrays and non-arrays", NULL));
764 @@ -1903,20 +1959,20 @@ static int subtract(void)
772 if (rightVal.tag == ARRAY_TAG) {
775 if (leftVal.tag == ARRAY_TAG) {
776 SparseArrayEntry *leftIter, *rightIter;
777 resultArray.tag = ARRAY_TAG;
778 resultArray.val.arrayPtr = ArrayNew();
784 leftIter = arrayIterateFirst(&leftVal);
785 rightIter = arrayIterateFirst(&rightVal);
787 Boolean insertResult = True;
789 @@ -1940,20 +1996,20 @@ static int subtract(void)
792 return(execError("array insertion failure", NULL));
799 return(execError("can't mix math with arrays and non-arrays", NULL));
814 @@ -1965,78 +2021,78 @@ static int subtract(void)
815 ** Before: TheStack-> value, next, ...
816 ** After: TheStack-> resValue, next, ...
818 static int multiply(void)
820 - BINARY_NUMERIC_OPERATION(*)
821 + BINARY_NUMERIC_OPERATION(*);
824 static int divide(void)
836 return execError("division by zero", "");
843 static int modulo(void)
855 return execError("modulo by zero", "");
862 static int negate(void)
864 - UNARY_NUMERIC_OPERATION(-)
865 + UNARY_NUMERIC_OPERATION(-);
868 static int increment(void)
870 - UNARY_NUMERIC_OPERATION(++)
871 + UNARY_NUMERIC_OPERATION(++);
874 static int decrement(void)
876 - UNARY_NUMERIC_OPERATION(--)
877 + UNARY_NUMERIC_OPERATION(--);
882 - BINARY_NUMERIC_OPERATION(>)
883 + BINARY_NUMERIC_OPERATION(>);
888 - BINARY_NUMERIC_OPERATION(<)
889 + BINARY_NUMERIC_OPERATION(<);
894 - BINARY_NUMERIC_OPERATION(>=)
895 + BINARY_NUMERIC_OPERATION(>=);
900 - BINARY_NUMERIC_OPERATION(<=)
901 + BINARY_NUMERIC_OPERATION(<=);
905 ** verify that compares are between integers and/or strings only
906 ** Before: TheStack-> value1, value2, next, ...
907 @@ -2048,12 +2104,12 @@ static int eq(void)
917 if (v1.tag == INT_TAG && v2.tag == INT_TAG) {
918 v1.val.n = v1.val.n == v2.val.n;
920 else if (v1.tag == STRING_TAG && v2.tag == STRING_TAG) {
921 v1.val.n = !strcmp(v1.val.str.rep, v2.val.str.rep);
922 @@ -2078,11 +2134,11 @@ static int eq(void)
925 return(execError("incompatible types to compare", NULL));
933 /* negated eq() call */
935 @@ -2104,20 +2160,20 @@ static int bitAnd(void)
943 if (rightVal.tag == ARRAY_TAG) {
946 if (leftVal.tag == ARRAY_TAG) {
947 SparseArrayEntry *leftIter, *rightIter;
948 resultArray.tag = ARRAY_TAG;
949 resultArray.val.arrayPtr = ArrayNew();
955 leftIter = arrayIterateFirst(&leftVal);
956 rightIter = arrayIterateFirst(&rightVal);
957 while (leftIter && rightIter) {
958 Boolean insertResult = True;
959 int compareResult = arrayEntryCompare((rbTreeNode *)leftIter, (rbTreeNode *)rightIter);
960 @@ -2135,20 +2191,20 @@ static int bitAnd(void)
963 return(execError("array insertion failure", NULL));
970 return(execError("can't mix math with arrays and non-arrays", NULL));
985 @@ -2164,20 +2220,20 @@ static int bitOr(void)
993 if (rightVal.tag == ARRAY_TAG) {
996 if (leftVal.tag == ARRAY_TAG) {
997 SparseArrayEntry *leftIter, *rightIter;
998 resultArray.tag = ARRAY_TAG;
999 resultArray.val.arrayPtr = ArrayNew();
1005 leftIter = arrayIterateFirst(&leftVal);
1006 rightIter = arrayIterateFirst(&rightVal);
1007 while (leftIter || rightIter) {
1008 Boolean insertResult = True;
1010 @@ -2206,37 +2262,37 @@ static int bitOr(void)
1012 if (!insertResult) {
1013 return(execError("array insertion failure", NULL));
1017 + PUSH(resultArray);
1020 return(execError("can't mix math with arrays and non-arrays", NULL));
1029 + PUSH_INT(n1 | n2);
1034 static int and(void)
1036 - BINARY_NUMERIC_OPERATION(&&)
1037 + BINARY_NUMERIC_OPERATION(&&);
1042 - BINARY_NUMERIC_OPERATION(||)
1043 + BINARY_NUMERIC_OPERATION(||);
1046 static int not(void)
1048 - UNARY_NUMERIC_OPERATION(!)
1049 + UNARY_NUMERIC_OPERATION(!);
1053 ** raise one number to the power of another
1054 ** Before: TheStack-> raisedBy, number, next, ...
1055 @@ -2247,12 +2303,12 @@ static int power(void)
1065 /* We need to round to deal with pow() giving results slightly above
1066 or below the real result since it deals with floating point numbers.
1067 Note: We're not really wanting rounded results, we merely
1068 want to deal with this simple issue. So, 2^-2 = .5, but we
1069 don't want to round this to 1. This is mainly intended to deal with
1070 @@ -2276,11 +2332,11 @@ static int power(void)
1072 /* round to nearest integer for positive values*/
1073 n3 = (int)(pow((double)n1, (double)n2) + (double)0.5);
1078 return errCheck("exponentiation");
1082 ** A helper routine used in concat(), and makeArrayKeyFromArgs().
1083 @@ -2308,11 +2364,11 @@ static int concatenateNwithSep(int nVals
1084 sepLen = strlen(sep);
1086 /* evaluate total length (upper limit) */
1087 len = sepLen * (nVals - 1);
1088 for (i = nVals - 1; i >= 0; --i) {
1091 if (value.tag == INT_TAG) {
1092 len += lenLongAsStr(value.val.n);
1094 else if (value.tag == STRING_TAG) {
1095 len += value.val.str.len;
1096 @@ -2325,11 +2381,11 @@ static int concatenateNwithSep(int nVals
1097 /* allocate the string */
1098 res = AllocString(len + 1);
1100 /* write everything into the result */
1101 for (i = nVals - 1; i >= 0; --i) {
1104 if (value.tag == INT_TAG) {
1105 pos += strlen(strcpy(pos, longAsStr(value.val.n)));
1107 else { /* value.tag == STRING_TAG */
1108 strcpy(pos, value.val.str.rep);
1109 @@ -2342,11 +2398,11 @@ static int concatenateNwithSep(int nVals
1112 /* remove the source expression values */
1120 /* now return the results */
1122 @@ -2376,11 +2432,11 @@ static int concat(void)
1124 len = concatenateNwithSep(nExpr, "", &out, False);
1126 return(execError("can only concatenate with string or integer", NULL));
1128 - PUSH_STRING(out, len)
1129 + PUSH_STRING(out, len);
1134 ** Call a subroutine or function (user defined or built-in). Args are the
1135 @@ -2425,11 +2481,11 @@ static int callSubroutineFromSymbol(Symb
1137 if (sym->type == C_FUNCTION_SYM) {
1140 if (!haveNamedArgs) {
1141 - PUSH(noValue) /* push dummy named arg array */
1142 + PUSH(noValue); /* push dummy named arg array */
1145 /* "pop" stack back to the first argument in the call stack */
1146 StackP -= nArgs + 1;
1148 @@ -2451,11 +2507,11 @@ static int callSubroutineFromSymbol(Symb
1149 ** Push all of the required information to resume, and make space on the
1150 ** stack for local variables (and initialize them), on top of the argument
1151 ** values which are already there.
1153 if (sym->type == MACRO_FUNCTION_SYM) {
1154 - PUSH_CHECK(3 + !haveNamedArgs)
1155 + PUSH_CHECK(3 + !haveNamedArgs);
1157 prog = sym->value.val.prog;
1160 *(StackP++) = noValue; /* push dummy named arg array */
1161 @@ -2482,11 +2538,11 @@ static int callSubroutineFromSymbol(Symb
1166 for (s = prog->localSymList; s != NULL; s = s->next) {
1169 FP_GET_SYM_VAL(FrameP, s) = noValue;
1174 @@ -2523,11 +2579,11 @@ static int callSubroutineFromSymbol(Symb
1175 key_event.display=disp;
1176 key_event.window=key_event.root=key_event.subwindow=win;
1178 /* pop arguments off the stack and put them in the argument list */
1179 for (i=nArgs-1; i>=0; i--) {
1180 - POP_STRING(argList[i])
1181 + POP_STRING(argList[i]);
1184 /* Call the action routine and check for preemption */
1185 PreemptRequest = False;
1186 sym->value.val.xtproc(FocusWindow->lastFocus,
1187 @@ -2582,15 +2638,15 @@ static int callSubroutineStackedN(void)
1188 /* this is much like callSubroutine, but we get nArgs off the stack
1189 and it will always be negative since there is always an argArray */
1193 - PEEK_INT(nArgs, 0)
1194 + PEEK_INT(nArgs, 0);
1196 STACKDUMP(-nArgs + 1, 3); /* +1 for stacked nArgs */
1204 /* should never happen */
1205 @@ -2683,11 +2739,11 @@ static int unpackArrayToArgs(void)
1206 DataValue dvEntry, dvArray;
1214 if (dvEntry.tag != ARRAY_TAG) {
1215 return execError("argument array call made with non-array value", NULL);
1217 res = ArrayCopy(&dvArray, &dvEntry);
1218 @@ -2700,14 +2756,14 @@ static int unpackArrayToArgs(void)
1219 char *ind = (char *)longAsStr(nArgs);
1220 if (!ArrayGet(&dvArray, ind, &dvEntry))
1222 /* remove them from remaining array */
1223 ArrayDelete(&dvArray, ind);
1235 ** This should never be executed, returnVal checks for the presence of this
1236 @@ -2819,11 +2875,11 @@ static int branchIf(Boolean trueOrFalse)
1244 addr = PC + PC->value;
1247 if (!value == !trueOrFalse)
1249 @@ -3118,26 +3174,26 @@ static int arrayRef(void)
1250 errNum = makeArrayKeyFromArgs(nDim, &keyString, 0);
1251 if (errNum != STAT_OK) {
1257 if (srcArray.tag == ARRAY_TAG) {
1258 if (!ArrayGet(&srcArray, keyString, &valueItem)) {
1259 return(execError("referenced array value not in array: %s", keyString));
1266 return(execError("operator [] on non-array", NULL));
1272 if (srcArray.tag == ARRAY_TAG) {
1273 - PUSH_INT(ArraySize(&srcArray))
1274 + PUSH_INT(ArraySize(&srcArray));
1278 return(execError("operator [] on non-array", NULL));
1280 @@ -3164,18 +3220,18 @@ static int arrayAssign(void)
1283 STACKDUMP(nDim+2, 3);
1289 errNum = makeArrayKeyFromArgs(nDim, &keyString, 0);
1290 if (errNum != STAT_OK) {
1297 if (dstArray.tag != ARRAY_TAG && dstArray.tag != NO_TAG) {
1298 return(execError("cannot assign array element of non-array", NULL));
1300 if (srcValue.tag == ARRAY_TAG) {
1301 @@ -3219,27 +3275,27 @@ static int arrayRefAndAssignSetup(void)
1304 STACKDUMP(nDim + (binaryOp ? 2 : 1), 3);
1312 errNum = makeArrayKeyFromArgs(nDim, &keyString, 1);
1313 if (errNum != STAT_OK) {
1317 - PEEK(srcArray, nDim)
1318 + PEEK(srcArray, nDim);
1319 if (srcArray.tag == ARRAY_TAG) {
1320 if (!ArrayGet(&srcArray, keyString, &valueItem)) {
1321 return(execError("referenced array value not in array: %s", keyString));
1332 return(execError("operator [] on non-array", NULL));
1333 @@ -3272,11 +3328,11 @@ static int beginArrayIter(void)
1342 if (iterator->type == LOCAL_SYM) {
1343 iteratorValPtr = &FP_GET_SYM_VAL(FrameP, iterator);
1346 @@ -3604,12 +3660,12 @@ static int beginArrayMultiIterArray(void
1353 - PEEK_INT(nDims, 0)
1355 + PEEK_INT(nDims, 0);
1357 if (iterator->type == LOCAL_SYM) {
1358 iteratorValPtr = &FP_GET_SYM_VAL(FrameP, iterator);
1361 @@ -3813,33 +3869,33 @@ static int inArray(void)
1369 if (theArray.tag != ARRAY_TAG) {
1370 return(execError("operator in on non-array", NULL));
1372 - PEEK(leftArray, 0)
1373 + PEEK(leftArray, 0);
1374 if (leftArray.tag == ARRAY_TAG) {
1375 SparseArrayEntry *iter;
1380 iter = arrayIterateFirst(&leftArray);
1381 while (inResult && iter) {
1382 inResult = inResult && ArrayGet(&theArray, iter->key, &theValue);
1383 iter = arrayIterateNext(iter);
1387 - POP_STRING(keyStr)
1388 + POP_STRING(keyStr);
1389 if (ArrayGet(&theArray, keyStr, &theValue)) {
1393 - PUSH_INT(inResult)
1394 + PUSH_INT(inResult);
1399 ** remove a given key from an array unless nDim is 0, then all keys are removed
1400 @@ -3869,11 +3925,11 @@ static int deleteArrayElement(void)
1401 if (errNum != STAT_OK) {
1408 if (theArray.tag == ARRAY_TAG) {
1410 ArrayDelete(&theArray, keyString);
1413 @@ -3906,11 +3962,11 @@ static int typeOfOut(void)
1414 return(execError("I'm not in typeof-mode", NULL));
1422 retVal.tag = STRING_TAG;
1425 retVal.val.str.rep = PERM_ALLOC_STR("UNDEFINED");
1426 @@ -4064,10 +4120,25 @@ int StringToNum(const char *string, int
1432 +static const char *tagToStr(enum typeTags tag)
1436 + return "<integer>";
1438 + return "<string>";
1443 + return "<no value>";
1447 #ifdef DEBUG_DISASSEMBLER /* dumping values in disassembly or stack dump */
1448 static char *printdBuffer = NULL;
1449 static int printdPos = 0;
1450 static int printdSize = 0;