diff --git a/src/expr.c b/src/expr.c index 36401ed..5b9aee8 100644 --- a/src/expr.c +++ b/src/expr.c @@ -333,14 +333,15 @@ product(char **p) while ((op == '*') || (op == '&') || (op == '/') || (op == '%') || (op == '<' && op2 == '<') || (op == '>' && op2 == '>') || - (op == '|' && op2 == '|') || (op == '&' && op2 == '&')) { + (op == '|' && op2 == '|') || (op == '&' && op2 == '&') || + (op == '?' && op2 == ':')) { /* Skip operator. */ (*p)++; /* For double-character operators, skip the second character. */ if ((op == '<' || op == '>' || op == '|') || - (op == '&' && op2 == '&')) + (op == '&' && op2 == '&') || (op == '?' && op2 == ':')) (*p)++; n2 = primary(p, 1); @@ -383,6 +384,11 @@ product(char **p) case '>': // bitwise shift RIGHT res.v = res.v >> n2.v; break; + + case '?': // undefined default + if (! DEFINED(res)) + res = n2; + break; } INFER_TYPE(res, n2); INFER_DEFINED(res, n2); @@ -557,7 +563,10 @@ expr(char **p) #endif op = **p; - if (starts_with(*p, "NOT ")) { op = '~'; *p += 4; }; + if (starts_with(*p, "NOT ")) { + op = '~'; + *p += 4; + }; if (op == '>') { /* High-byte (MSB) operator. */ diff --git a/src/pseudo.c b/src/pseudo.c index 079fea3..75059b6 100644 --- a/src/pseudo.c +++ b/src/pseudo.c @@ -8,7 +8,7 @@ * * Handle directives and pseudo-ops. * - * Version: @(#)pseudo.c 1.0.2 2023/04/22 + * Version: @(#)pseudo.c 1.0.3 2023/04/25 * * Authors: Fred N. van Kempen, * Bernd B”ckmann, @@ -596,6 +596,39 @@ do_ifdef(char **p, int pass) } +/* The ".ifn " directive. */ +static char * +do_ifn(char **p, int pass) +{ + value_t v; + + skip_white(p); + + /* Get the value of the expression. */ + v = expr(p); + + /* + * It may have been that one of the symbols + * referenced was not defined. We can make + * this an error, or simply "assume" the + * value to be 0. + */ + if ((pass == 2) && UNDEFINED(v)) { +#ifndef ALLOW_UNDEFINED_IF + error(ERR_UNDEF, NULL); +#endif + } + + if (iflevel < MAX_IFLEVEL) { + ifstack[iflevel++] = ifstate; + newifstate = !!!v.v; + } else + error(ERR_IF, NULL); + + return NULL; +} + + /* The ".ifndef " directive. */ static char * do_ifndef(char **p, int pass) @@ -963,11 +996,6 @@ do_warn(char **p, int pass) static const pseudo_t pseudos[] = { - { "IF", 1, do_if, NULL }, - { "IFDEF", 1, do_ifdef, NULL }, - { "IFNDEF", 1, do_ifndef, NULL }, - { "ELSE", 1, do_else, NULL }, - { "ENDIF", 1, do_endif, NULL }, { "ALIGN", 0, do_align, NULL }, { "ASCIIZ", 0, do_asciz, NULL }, { "ASCIZ", 0, do_asciz, NULL }, @@ -982,10 +1010,16 @@ static const pseudo_t pseudos[] = { { "DL", 0, do_dword, NULL }, { "DW", 0, do_word, NULL }, { "ECHO", 0, do_echo, NULL }, + { "ELSE", 1, do_else, NULL }, { "END", 0, do_end, NULL }, + { "ENDIF", 1, do_endif, NULL }, { "ERROR", 0, do_error, NULL }, { "EQU", 0, do_equ, NULL }, { "FILL", 0, do_fill, NULL }, + { "IF", 1, do_if, NULL }, + { "IFDEF", 1, do_ifdef, NULL }, + { "IFN", 1, do_ifn, NULL }, + { "IFNDEF", 1, do_ifndef, NULL }, { "INCLUDE", 0, do_include, NULL }, { "ORG", 0, do_org, NULL }, { "PAGE", 0, do_page, NULL }, @@ -1006,10 +1040,14 @@ const pseudo_t * is_pseudo(const char *name) { const pseudo_t *ptr; + int i; - for (ptr = pseudos; ptr->name != NULL; ptr++) - if (! strcmp(ptr->name, name)) + for (ptr = pseudos; ptr->name != NULL; ptr++) { + if ((i = strcmp(ptr->name, name)) == 0) return ptr; + if (i > 0) + break; + } return NULL; }