1 Subject: interpret.c: macro cleanup
3 Use 'do { } while (0)' syntax for macros and consolidate num/string conversion.
7 source/interpret.c | 406 +++++++++++++++++++++++++++++++----------------------
8 1 file changed, 239 insertions(+), 167 deletions(-)
10 diff --quilt old/source/interpret.c new/source/interpret.c
11 --- old/source/interpret.c
12 +++ new/source/interpret.c
13 @@ -134,10 +134,12 @@ static rbTreeNode *arrayAllocateNode(rbT
14 static int arrayEntryCopyToNode(rbTreeNode *dst, rbTreeNode *src);
15 static int arrayEntryCompare(rbTreeNode *left, rbTreeNode *right);
16 static void arrayDisposeNode(rbTreeNode *src);
17 static SparseArrayEntry *allocateSparseArrayEntry(void);
19 +static const char *tagToStr(enum typeTags tag);
21 /*#define DEBUG_ASSEMBLY*/
22 /*#define DEBUG_STACK*/
24 #if defined(DEBUG_ASSEMBLY) || defined(DEBUG_STACK)
25 #define DEBUG_DISASSEMBLER
26 @@ -175,11 +177,11 @@ static SparseArrayEntryWrapper *Allocate
28 /* Message strings used in macros (so they don't get repeated every time
29 the macros are used */
30 static const char *StackOverflowMsg = "macro stack overflow";
31 static const char *StackUnderflowMsg = "macro stack underflow";
32 -static const char *StringToNumberMsg = "string could not be converted to number";
33 +static const char *StringToNumberMsg = "string '%s' could not be converted to number";
35 /* Temporary global data for use while accumulating programs */
36 static Symbol *LocalSymList = NULL; /* symbols local to the program */
37 static Inst Prog[PROGRAM_SIZE]; /* the program */
38 static Inst *ProgP; /* next free spot for code gen. */
39 @@ -1089,102 +1091,156 @@ static void freeSymbolTable(Symbol *symT
45 +/* true, if you can pop n values */
46 +#define OK_TO_POP(n) \
47 + ((StackP - (n)) >= TheStack)
49 +#define POP_CHECK(n) \
51 + if (!OK_TO_POP(n)) { \
52 + return execError(StackUnderflowMsg, ""); \
56 +/* true, if you can push n values */
57 +#define OK_TO_PUSH(n) \
58 + (StackP + (n) <= &TheStack[STACK_SIZE])
60 + #define PUSH_CHECK(n) \
62 + if (!OK_TO_PUSH(n)) { \
63 + return execError(StackOverflowMsg, ""); \
67 +#define PEEK_CHECK(n) \
69 + if (!OK_TO_POP((n) + 1)) { \
70 + return execError(StackUnderflowMsg, ""); \
72 + if (!OK_TO_PUSH(-(n))) { \
73 + return execError(StackOverflowMsg, ""); \
77 #define POP(dataVal) \
78 - if (StackP == TheStack) \
79 - return execError(StackUnderflowMsg, ""); \
80 - dataVal = *--StackP;
83 + dataVal = *--StackP; \
86 #define PUSH(dataVal) \
87 - if (StackP >= &TheStack[STACK_SIZE]) \
88 - return execError(StackOverflowMsg, ""); \
89 - *StackP++ = dataVal;
92 + *StackP++ = dataVal; \
95 #define PEEK(dataVal, peekIndex) \
96 - dataVal = *(StackP - peekIndex - 1);
98 + PEEK_CHECK(peekIndex); \
99 + dataVal = *(StackP - peekIndex - 1); \
102 +#define TO_INT(dataVal, number) \
105 + if (dataVal.tag == INT_TAG) { \
106 + __int = dataVal.val.n; \
107 + } else if (dataVal.tag == STRING_TAG) { \
108 + if (!StringToNum(dataVal.val.str.rep, &__int)) {\
109 + return execError(StringToNumberMsg, dataVal.val.str.rep); \
112 + return(execError("incompatible type in integer context: %s", \
113 + tagToStr(dataVal.tag))); \
118 +#define TO_STRING(dataVal, string) \
121 + if (dataVal.tag == STRING_TAG) { \
122 + __str = dataVal.val.str.rep; \
123 + } else if (dataVal.tag == INT_TAG) { \
124 + __str = AllocString(TYPE_INT_STR_SIZE(int)); \
125 + sprintf(__str, "%d", dataVal.val.n); \
127 + return(execError("incompatible type in string context: %s", \
128 + tagToStr(dataVal.tag))); \
133 #define POP_INT(number) \
134 - if (StackP == TheStack) \
135 - return execError(StackUnderflowMsg, ""); \
137 - if (StackP->tag == STRING_TAG) { \
138 - if (!StringToNum(StackP->val.str.rep, &number)) \
139 - return execError(StringToNumberMsg, ""); \
140 - } else if (StackP->tag == INT_TAG) \
141 - number = StackP->val.n; \
143 - return(execError("can't convert array to integer", NULL));
147 + TO_INT(dv, number); \
150 #define POP_STRING(string) \
151 - if (StackP == TheStack) \
152 - return execError(StackUnderflowMsg, ""); \
154 - if (StackP->tag == INT_TAG) { \
155 - string = AllocString(TYPE_INT_STR_SIZE(int)); \
156 - sprintf(string, "%d", StackP->val.n); \
157 - } else if (StackP->tag == STRING_TAG) \
158 - string = StackP->val.str.rep; \
160 - return(execError("can't convert array to string", NULL));
162 -#define PEEK_STRING(string, peekIndex) \
163 - if ((StackP - peekIndex - 1)->tag == INT_TAG) { \
164 - string = AllocString(TYPE_INT_STR_SIZE(int)); \
165 - sprintf(string, "%d", (StackP - peekIndex - 1)->val.n); \
167 - else if ((StackP - peekIndex - 1)->tag == STRING_TAG) { \
168 - string = (StackP - peekIndex - 1)->val.str.rep; \
171 - return(execError("can't convert array to string", NULL)); \
176 + TO_STRING(dv, string); \
179 #define PEEK_INT(number, peekIndex) \
180 - if ((StackP - peekIndex - 1)->tag == STRING_TAG) { \
181 - if (!StringToNum((StackP - peekIndex - 1)->val.str.rep, &number)) { \
182 - return execError(StringToNumberMsg, ""); \
184 - } else if ((StackP - peekIndex - 1)->tag == INT_TAG) { \
185 - number = (StackP - peekIndex - 1)->val.n; \
188 - return(execError("can't convert array to string", NULL)); \
192 + PEEK(dv, peekIndex); \
193 + TO_INT(dv, number); \
196 +#define PEEK_STRING(string, peekIndex) \
200 + TO_STRING(dv, string); \
203 #define PUSH_INT(number) \
204 - if (StackP >= &TheStack[STACK_SIZE]) \
205 - return execError(StackOverflowMsg, ""); \
206 - StackP->tag = INT_TAG; \
207 - StackP->val.n = number; \
212 + dv.tag = INT_TAG; \
213 + dv.val.n = (number); \
217 #define PUSH_STRING(string, length) \
218 - if (StackP >= &TheStack[STACK_SIZE]) \
219 - return execError(StackOverflowMsg, ""); \
220 - StackP->tag = STRING_TAG; \
221 - StackP->val.str.rep = string; \
222 - StackP->val.str.len = length; \
226 + dv.tag = STRING_TAG; \
227 + dv.val.str.rep = (string); \
228 + dv.val.str.len = (length); \
232 #define BINARY_NUMERIC_OPERATION(operator) \
234 - DISASM_RT(PC-1, 1); \
238 - PUSH_INT(n1 operator n2) \
242 + DISASM_RT(PC-1, 1); \
246 + PUSH_INT(n1 operator n2); \
250 #define UNARY_NUMERIC_OPERATION(operator) \
252 - DISASM_RT(PC-1, 1); \
255 - PUSH_INT(operator n) \
259 + DISASM_RT(PC-1, 1); \
262 + PUSH_INT(operator n); \
267 ** copy a symbol's value onto the stack
268 ** Before: Prog-> [Sym], next, ...
269 ** TheStack-> next, ...
270 @@ -1230,11 +1286,11 @@ static int pushSymVal(void)
271 return execError("reading non-variable: %s", s->name);
272 if (symVal.tag == NO_TAG) {
273 return execError("variable not set: %s", s->name);
282 static int pushArgVal(void)
283 @@ -1242,11 +1298,11 @@ static int pushArgVal(void)
292 nArgs = FP_GET_ARG_COUNT(FrameP);
293 if (argNum >= nArgs || argNum < 0) {
294 char argStr[TYPE_INT_STR_SIZE(argNum)];
295 sprintf(argStr, "%d", argNum + 1);
296 @@ -1333,11 +1389,11 @@ static int pushArraySymVal(void)
298 if (dataPtr->tag == NO_TAG) {
299 return execError("variable not set: %s", sym->name);
309 @@ -1377,11 +1433,11 @@ static int assign(void)
312 dataPtr = &sym->value;
318 if (value.tag == ARRAY_TAG) {
319 ArrayCopy(dataPtr, &value);
322 @@ -1400,12 +1456,12 @@ static int dupStack(void)
337 @@ -1422,20 +1478,20 @@ static int add(void)
345 if (rightVal.tag == ARRAY_TAG) {
348 if (leftVal.tag == ARRAY_TAG) {
349 SparseArrayEntry *leftIter, *rightIter;
350 resultArray.tag = ARRAY_TAG;
351 resultArray.val.arrayPtr = ArrayNew();
357 leftIter = arrayIterateFirst(&leftVal);
358 rightIter = arrayIterateFirst(&rightVal);
359 while (leftIter || rightIter) {
360 Boolean insertResult = True;
362 @@ -1465,20 +1521,20 @@ static int add(void)
365 return(execError("array insertion failure", NULL));
372 return(execError("can't mix math with arrays and non-arrays", NULL));
387 @@ -1494,20 +1550,20 @@ static int subtract(void)
395 if (rightVal.tag == ARRAY_TAG) {
398 if (leftVal.tag == ARRAY_TAG) {
399 SparseArrayEntry *leftIter, *rightIter;
400 resultArray.tag = ARRAY_TAG;
401 resultArray.val.arrayPtr = ArrayNew();
407 leftIter = arrayIterateFirst(&leftVal);
408 rightIter = arrayIterateFirst(&rightVal);
410 Boolean insertResult = True;
412 @@ -1531,20 +1587,20 @@ static int subtract(void)
415 return(execError("array insertion failure", NULL));
422 return(execError("can't mix math with arrays and non-arrays", NULL));
437 @@ -1556,78 +1612,78 @@ static int subtract(void)
438 ** Before: TheStack-> value, next, ...
439 ** After: TheStack-> resValue, next, ...
441 static int multiply(void)
443 - BINARY_NUMERIC_OPERATION(*)
444 + BINARY_NUMERIC_OPERATION(*);
447 static int divide(void)
459 return execError("division by zero", "");
466 static int modulo(void)
478 return execError("modulo by zero", "");
485 static int negate(void)
487 - UNARY_NUMERIC_OPERATION(-)
488 + UNARY_NUMERIC_OPERATION(-);
491 static int increment(void)
493 - UNARY_NUMERIC_OPERATION(++)
494 + UNARY_NUMERIC_OPERATION(++);
497 static int decrement(void)
499 - UNARY_NUMERIC_OPERATION(--)
500 + UNARY_NUMERIC_OPERATION(--);
505 - BINARY_NUMERIC_OPERATION(>)
506 + BINARY_NUMERIC_OPERATION(>);
511 - BINARY_NUMERIC_OPERATION(<)
512 + BINARY_NUMERIC_OPERATION(<);
517 - BINARY_NUMERIC_OPERATION(>=)
518 + BINARY_NUMERIC_OPERATION(>=);
523 - BINARY_NUMERIC_OPERATION(<=)
524 + BINARY_NUMERIC_OPERATION(<=);
528 ** verify that compares are between integers and/or strings only
529 ** Before: TheStack-> value1, value2, next, ...
530 @@ -1639,12 +1695,12 @@ static int eq(void)
540 if (v1.tag == INT_TAG && v2.tag == INT_TAG) {
541 v1.val.n = v1.val.n == v2.val.n;
543 else if (v1.tag == STRING_TAG && v2.tag == STRING_TAG) {
544 v1.val.n = !strcmp(v1.val.str.rep, v2.val.str.rep);
545 @@ -1669,11 +1725,11 @@ static int eq(void)
548 return(execError("incompatible types to compare", NULL));
556 /* negated eq() call */
558 @@ -1695,20 +1751,20 @@ static int bitAnd(void)
566 if (rightVal.tag == ARRAY_TAG) {
569 if (leftVal.tag == ARRAY_TAG) {
570 SparseArrayEntry *leftIter, *rightIter;
571 resultArray.tag = ARRAY_TAG;
572 resultArray.val.arrayPtr = ArrayNew();
578 leftIter = arrayIterateFirst(&leftVal);
579 rightIter = arrayIterateFirst(&rightVal);
580 while (leftIter && rightIter) {
581 Boolean insertResult = True;
582 int compareResult = arrayEntryCompare((rbTreeNode *)leftIter, (rbTreeNode *)rightIter);
583 @@ -1726,20 +1782,20 @@ static int bitAnd(void)
586 return(execError("array insertion failure", NULL));
593 return(execError("can't mix math with arrays and non-arrays", NULL));
608 @@ -1755,20 +1811,20 @@ static int bitOr(void)
616 if (rightVal.tag == ARRAY_TAG) {
619 if (leftVal.tag == ARRAY_TAG) {
620 SparseArrayEntry *leftIter, *rightIter;
621 resultArray.tag = ARRAY_TAG;
622 resultArray.val.arrayPtr = ArrayNew();
628 leftIter = arrayIterateFirst(&leftVal);
629 rightIter = arrayIterateFirst(&rightVal);
630 while (leftIter || rightIter) {
631 Boolean insertResult = True;
633 @@ -1797,37 +1853,37 @@ static int bitOr(void)
636 return(execError("array insertion failure", NULL));
643 return(execError("can't mix math with arrays and non-arrays", NULL));
659 - BINARY_NUMERIC_OPERATION(&&)
660 + BINARY_NUMERIC_OPERATION(&&);
665 - BINARY_NUMERIC_OPERATION(||)
666 + BINARY_NUMERIC_OPERATION(||);
671 - UNARY_NUMERIC_OPERATION(!)
672 + UNARY_NUMERIC_OPERATION(!);
676 ** raise one number to the power of another
677 ** Before: TheStack-> raisedBy, number, next, ...
678 @@ -1838,12 +1894,12 @@ static int power(void)
688 /* We need to round to deal with pow() giving results slightly above
689 or below the real result since it deals with floating point numbers.
690 Note: We're not really wanting rounded results, we merely
691 want to deal with this simple issue. So, 2^-2 = .5, but we
692 don't want to round this to 1. This is mainly intended to deal with
693 @@ -1867,11 +1923,11 @@ static int power(void)
695 /* round to nearest integer for positive values*/
696 n3 = (int)(pow((double)n1, (double)n2) + (double)0.5);
701 return errCheck("exponentiation");
705 ** concatenate two top items on the stack
706 @@ -1884,18 +1940,18 @@ static int concat(void)
718 out = AllocString(len1 + len2 + 1);
719 strncpy(out, s1, len1);
720 strcpy(&out[len1], s2);
721 - PUSH_STRING(out, len1 + len2)
722 + PUSH_STRING(out, len1 + len2);
727 ** Call a subroutine or function (user defined or built-in). Args are the
728 @@ -1946,11 +2002,11 @@ static int callSubroutine(void)
729 return execError(errMsg, sym->name);
730 if (PC->func == fetchRetVal) {
731 if (result.tag == NO_TAG) {
732 return execError("%s does not return a value", sym->name);
738 return PreemptRequest ? STAT_PREEMPT : STAT_OK;
741 @@ -2019,11 +2075,11 @@ static int callSubroutine(void)
742 key_event.window=key_event.root=key_event.subwindow=win;
744 argList = (String *)XtCalloc(nArgs, sizeof(*argList));
745 /* pop arguments off the stack and put them in the argument list */
746 for (i=nArgs-1; i>=0; i--) {
747 - POP_STRING(argList[i])
748 + POP_STRING(argList[i]);
751 /* Call the action routine and check for preemption */
752 PreemptRequest = False;
753 sym->value.val.xtproc(FocusWindow->lastFocus,
754 @@ -2077,11 +2133,11 @@ static int returnValOrNone(int valOnStac
756 STACKDUMP(StackP - FrameP + FP_GET_ARG_COUNT(FrameP) + FP_TO_ARGS_DIST, 3);
758 /* return value is on the stack */
764 /* get stored return information */
765 nArgs = FP_GET_ARG_COUNT(FrameP);
766 newFrameP = FP_GET_OLD_FP(FrameP);
767 @@ -2099,17 +2155,17 @@ static int returnValOrNone(int valOnStac
770 /* push returned value, if requsted */
779 } else if (PC->func == fetchRetVal) {
786 "using return value of %s which does not return a value",
787 ((PC-2)->sym->name));
788 @@ -2149,11 +2205,11 @@ static int branchTrue(void)
796 addr = PC + PC->value;
801 @@ -2165,11 +2221,11 @@ static int branchFalse(void)
809 addr = PC + PC->value;
814 @@ -2244,11 +2300,11 @@ static int makeArrayKeyFromArgs(int nArg
818 keyLength = sepLen * (nArgs - 1);
819 for (i = nArgs - 1; i >= 0; --i) {
822 if (tmpVal.tag == INT_TAG) {
823 keyLength += TYPE_INT_STR_SIZE(tmpVal.val.n);
825 else if (tmpVal.tag == STRING_TAG) {
826 keyLength += tmpVal.val.str.len;
827 @@ -2261,11 +2317,11 @@ static int makeArrayKeyFromArgs(int nArg
829 for (i = nArgs - 1; i >= 0; --i) {
830 if (i != nArgs - 1) {
831 strcat(*keyString, ARRAY_DIM_SEP);
835 if (tmpVal.tag == INT_TAG) {
836 sprintf(&((*keyString)[strlen(*keyString)]), "%d", tmpVal.val.n);
838 else if (tmpVal.tag == STRING_TAG) {
839 strcat(*keyString, tmpVal.val.str.rep);
840 @@ -2274,11 +2330,11 @@ static int makeArrayKeyFromArgs(int nArg
841 return(execError("can only index array with string or int.", NULL));
845 for (i = nArgs - 1; i >= 0; --i) {
853 @@ -2498,26 +2554,26 @@ static int arrayRef(void)
854 errNum = makeArrayKeyFromArgs(nDim, &keyString, 0);
855 if (errNum != STAT_OK) {
861 if (srcArray.tag == ARRAY_TAG) {
862 if (!ArrayGet(&srcArray, keyString, &valueItem)) {
863 return(execError("referenced array value not in array: %s", keyString));
870 return(execError("operator [] on non-array", NULL));
876 if (srcArray.tag == ARRAY_TAG) {
877 - PUSH_INT(ArraySize(&srcArray))
878 + PUSH_INT(ArraySize(&srcArray));
882 return(execError("operator [] on non-array", NULL));
884 @@ -2544,18 +2600,18 @@ static int arrayAssign(void)
893 errNum = makeArrayKeyFromArgs(nDim, &keyString, 0);
894 if (errNum != STAT_OK) {
901 if (dstArray.tag != ARRAY_TAG && dstArray.tag != NO_TAG) {
902 return(execError("cannot assign array element of non-array", NULL));
904 if (srcValue.tag == ARRAY_TAG) {
905 @@ -2599,27 +2655,27 @@ static int arrayRefAndAssignSetup(void)
908 STACKDUMP(nDim + 1, 3);
916 errNum = makeArrayKeyFromArgs(nDim, &keyString, 1);
917 if (errNum != STAT_OK) {
921 - PEEK(srcArray, nDim)
922 + PEEK(srcArray, nDim);
923 if (srcArray.tag == ARRAY_TAG) {
924 if (!ArrayGet(&srcArray, keyString, &valueItem)) {
925 return(execError("referenced array value not in array: %s", keyString));
936 return(execError("operator [] on non-array", NULL));
937 @@ -2652,11 +2708,11 @@ static int beginArrayIter(void)
946 if (iterator->type == LOCAL_SYM) {
947 iteratorValPtr = &FP_GET_SYM_VAL(FrameP, iterator);
950 @@ -2764,33 +2820,33 @@ static int inArray(void)
958 if (theArray.tag != ARRAY_TAG) {
959 return(execError("operator in on non-array", NULL));
962 + PEEK(leftArray, 0);
963 if (leftArray.tag == ARRAY_TAG) {
964 SparseArrayEntry *iter;
969 iter = arrayIterateFirst(&leftArray);
970 while (inResult && iter) {
971 inResult = inResult && ArrayGet(&theArray, iter->key, &theValue);
972 iter = arrayIterateNext(iter);
977 + POP_STRING(keyStr);
978 if (ArrayGet(&theArray, keyStr, &theValue)) {
983 + PUSH_INT(inResult);
988 ** remove a given key from an array unless nDim is 0, then all keys are removed
989 @@ -2820,11 +2876,11 @@ static int deleteArrayElement(void)
990 if (errNum != STAT_OK) {
997 if (theArray.tag == ARRAY_TAG) {
999 ArrayDelete(&theArray, keyString);
1002 @@ -2892,10 +2948,26 @@ int StringToNum(const char *string, int
1009 +static const char *tagToStr(enum typeTags tag)
1013 + return "<integer>";
1015 + return "<string>";
1020 + return "<no value>";
1024 #ifdef DEBUG_DISASSEMBLER /* dumping values in disassembly or stack dump */
1025 static void dumpVal(DataValue dv)