From 3f937a2ab53c5fa20f5468e59c278da9d8c54b02 Mon Sep 17 00:00:00 2001 From: ggn Date: Tue, 31 May 2022 22:42:55 +0300 Subject: [PATCH] Added "-4" switch that enables C style operator precedence (original work by Bastian Schick) --- docs/rmac.rst | 33 ++++++++++++++++--- expr.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++----- rmac.c | 7 +++- 3 files changed, 116 insertions(+), 13 deletions(-) diff --git a/docs/rmac.rst b/docs/rmac.rst index 9cddd4b..78e2d34 100644 --- a/docs/rmac.rst +++ b/docs/rmac.rst @@ -127,7 +127,7 @@ Switch Description -fx Atari 800 com/exe/xex output object file format. -i\ *path* Set include-file directory search path. -l\ *[file[prn]]* Construct and direct assembly listing to the specified file. --l\ *\*[filename]* Create an output listing file without pagination +-l\ *\*[filename]* Create an output listing file without pagination. -m\ *cpu* Switch CPU type `68000 - MC68000` @@ -203,8 +203,9 @@ Switch Description -s Warn about unoptimized long branches and applied optimisations. -u Force referenced and undefined symbols global. -v Verbose mode (print running dialogue). --x Turn on debugging mode +-x Turn on debugging mode. -yn Set listing page size to n lines. +-4 Use C style operator precedence. file\ *[s]* Assemble the specified file. =================== =========== @@ -296,6 +297,9 @@ the table. space), sets the number of lines in a page. RMAC will produce *N* lines before emitting a form-feed. If *N* is missing or less than 10 an error message is generated. +**-4** + Use C style order of precedence in expressions. See `Order of Evaluation`_ for more + information. `Using RMAC`_ =============== @@ -425,7 +429,8 @@ necessary to make other assemblers' source code assemble. character codes. Watch out for GEMDOS path names in ASCII constants - you will have to convert them to double-backslashes. * Expression evaluation is done left-to-right without operator precedence. Use parentheses to - force the expression evaluation as you wish. + force the expression evaluation as you wish. Alternatively, use the **-4** switch to switch + to C style precedence. For more information refer to `Order of Evaluation`_. * Mark your segments across files. Branching to a code segment that could be identified as BSS will cause a "Error: cannot initialize non-storage (BSS) section" * In 68020+ mode **Zan** and **Zri** (register suppression) is not supported. @@ -746,6 +751,24 @@ true. Thus the expression "1+2*3" evaluates to 9, not 7. However, precedence may be forced with parenthesis (**()**) or square-brackets (**[]**). +All the above behavior is the default. However if the command line switch **-4** +is used, then C style of operator precedence is enforced. The following list +shows the order of precedence in this mode, from lowest to highest: + + * bitwise XOR ^ + + * bitwise OR | + + * bitwise AND & + + * relational = < <= >= > != + + * shifts << >> + + * sum + - + + * product * / + `Types`_ ''''''''' Expressions belong to one of three classes: undefined, absolute or relocatable. An @@ -842,7 +865,9 @@ Operator Description =========== ============================================== * All binary operators have the same precedence: - expressions are evaluated strictly left to right. + expressions are evaluated strictly left to right, + with the exception of the **-4** switch. For more information + refer to `Order of Evaluation`_. * Division or modulo by zero yields an assembly error. diff --git a/expr.c b/expr.c index 2361817..5a9155c 100644 --- a/expr.c +++ b/expr.c @@ -93,24 +93,97 @@ void InitExpression(void) symbolNum = 0; } +extern int correctMathRules; +int xor(void); +int and(void); +int rel(void); +int shift(void); +int sum(void); +int product(void); + // -// Binary operators (all the same precedence) +// Binary operators (all the same precedence, +// except if -4 is passed to the command line) // +#define precedence(HIERARCHY_HIGHER, HIERARCHY_CURRENT) \ +do \ +{ \ + if (HIERARCHY_HIGHER() != OK) \ + return ERROR; \ + while (tokenClass[*tok] == HIERARCHY_CURRENT) \ + { \ + TOKEN t = *tok++; \ + if (HIERARCHY_HIGHER() != OK) \ + return ERROR; \ + *evalTokenBuffer.u32++ = t; \ + } \ +}while (0) + int expr0(void) { - if (expr1() != OK) - return ERROR; - - while (tokenClass[*tok] >= MULT) + if ( correctMathRules == 0 ) { - TOKEN t = *tok++; - if (expr1() != OK) return ERROR; - *evalTokenBuffer.u32++ = t; + while (tokenClass[*tok] >= MULT) + { + TOKEN t = *tok++; + + if (expr1() != OK) + return ERROR; + + *evalTokenBuffer.u32++ = t; + } } + else + { + // The order of C precedence (lower to higher): + // bitwise XOR ^ + // bitwise OR | + // bitwise AND & + // relational = < <= >= > != + // shifts << >> + // sum + - + // product * / + precedence(xor, OR); + } + return OK; +} +int xor(void) +{ + precedence(and, XOR); + return OK; +} + +int and(void) +{ + precedence(rel, AND); + return OK; +} + +int rel(void) +{ + precedence(shift, REL); + return OK; +} + +int shift(void) +{ + precedence(sum, SHIFT); + return OK; +} + +int sum(void) +{ + precedence(product, ADD); + return OK; +} + +int product(void) +{ + precedence(expr1, MULT); return OK; } diff --git a/rmac.c b/rmac.c index 9259d41..5946105 100644 --- a/rmac.c +++ b/rmac.c @@ -60,6 +60,7 @@ int activecpu = CPU_68000; // Active 68k CPU (68000 by default) int activefpu = FPU_NONE; // Active FPU (none by default) int org68k_active = 0; // .org switch for 68k (only with RAW output format) uint32_t org68k_address; // .org for 68k +int correctMathRules; // 1, use C operator precedence in expressions // // Convert a string to uppercase @@ -206,6 +207,7 @@ void DisplayHelp(void) " -v Set verbose mode\n" " -x Turn on debugging mode\n" " -y[pagelen] Set page line length (default: 61)\n" + " -4 Use C style operator precedence\n" "\n", cmdlnexec); } @@ -334,7 +336,7 @@ int Process(int argc, char ** argv) regtab = reg68tab; // Idem regcheck = reg68check; // Idem regaccept = reg68accept; // Idem - + correctMathRules = 0; // respect operator precedence // Initialize modules InitSymbolTable(); // Symbol table InitTokenizer(); // Tokenizer @@ -353,6 +355,9 @@ int Process(int argc, char ** argv) { switch (argv[argno][1]) { + case '4': + correctMathRules = 1; + break; case 'd': // Define symbol case 'D': for(s=argv[argno]+2; *s!=EOS;) -- 2.37.2