Remove eval.c and evel.h and use expression_evaluate_and_read_into for if statements
authorRobert Pengelly <robertapengelly@hotmail.com>
Mon, 21 Apr 2025 13:18:25 +0000 (14:18 +0100)
committerRobert Pengelly <robertapengelly@hotmail.com>
Mon, 21 Apr 2025 13:18:25 +0000 (14:18 +0100)
Makefile.p32
Makefile.pdw
Makefile.unix
Makefile.w32
Makefile.wat
eval.c [deleted file]
eval.h [deleted file]
process.c

index 60facf8dbe8db17410997be5bcdc43385f68ef50..77e1a8790927bbe271ca16198de75c2c9e133283 100644 (file)
@@ -6,7 +6,7 @@ CC=gcc386
 LD=ld386
 
 COPTS=-S -O2 -fno-common -ansi -I. -I./include -I../pdos/pdpclib -I../pdos/src -D__PDOS386__ -D__32BIT__ -D__NOBIVA__ -D__PDOS__ -Wall -Werror -ansi -m32 -pedantic
-COBJ=as.o bin.o cstr.o elks.o eval.o expr.o fixup.o frag.o hashtab.o intel.o kwd.o lex.o lib.o list.o listing.o ll.o macro.o process.o report.o section.o symbol.o vector.o
+COBJ=as.o bin.o cstr.o elks.o expr.o fixup.o frag.o hashtab.o intel.o kwd.o lex.o lib.o list.o listing.o ll.o macro.o process.o report.o section.o symbol.o vector.o
 
 all: clean sasm.exe
 
index c33cb871d4ad3f1bbcf7f2cccda4aa335edce510..01ab4cf04003c3fae76ab602ea801493c2d45691 100644 (file)
@@ -6,7 +6,7 @@ CC=gccwin
 LD=ldwin
 
 COPTS=-S -O2 -fno-common -ansi -I. -I./include -I../pdos/pdpclib -I../pdos/src -D__WIN32__ -D__NOBIVA__ -D__PDOS__ -Wall -Werror -ansi -m32 -pedantic
-COBJ=as.o bin.o cstr.o elks.o eval.o expr.o fixup.o frag.o hashtab.o intel.o kwd.o lex.o lib.o list.o listing.o ll.o macro.o process.o report.o section.o symbol.o vector.o
+COBJ=as.o bin.o cstr.o elks.o expr.o fixup.o frag.o hashtab.o intel.o kwd.o lex.o lib.o list.o listing.o ll.o macro.o process.o report.o section.o symbol.o vector.o
 
 all: clean sasm.exe
 
index b859deb039d652908b9160f5a74d7907b3e14f88..6870fa34b3e28f194195d5983269690afdc7ef78 100644 (file)
@@ -7,7 +7,7 @@ VPATH               :=  $(SRCDIR)
 CC                  :=  gcc
 CFLAGS              :=  -D_FILE_OFFSET_BITS=64 -O2 -Wall -Werror -Wextra -ansi -pedantic -std=c90
 
-CSRC                :=  as.c bin.c cstr.c elks.c eval.c expr.c fixup.c frag.c hashtab.c intel.c kwd.c lex.c lib.c list.c listing.c ll.c macro.c process.c report.c section.c symbol.c vector.c
+CSRC                :=  as.c bin.c cstr.c elks.c expr.c fixup.c frag.c hashtab.c intel.c kwd.c lex.c lib.c list.c listing.c ll.c macro.c process.c report.c section.c symbol.c vector.c
 
 ifeq ($(OS), Windows_NT)
 all: sasm.exe
index 41bb95fbe76e97b8f036acbab4af3d4592556362..10643476896adf76fd3b4c0be20cc865553787f6 100644 (file)
@@ -7,7 +7,7 @@ VPATH               :=  $(SRCDIR)
 CC                  :=  gcc
 CFLAGS              :=  -D_FILE_OFFSET_BITS=64 -O2 -Wall -Werror -Wextra -ansi -pedantic -std=c90
 
-CSRC                :=  as.c bin.c cstr.c elks.c eval.c expr.c fixup.c frag.c hashtab.c intel.c kwd.c lex.c lib.c list.c listing.c ll.c macro.c process.c report.c section.c symbol.c vector.c
+CSRC                :=  as.c bin.c cstr.c elks.c expr.c fixup.c frag.c hashtab.c intel.c kwd.c lex.c lib.c list.c listing.c ll.c macro.c process.c report.c section.c symbol.c vector.c
 
 all: sasm.exe
 
index 4abd488bb7db0ec32306cb137651167b724026f3..788c3d3bfefb4d15b98fadb82bbbcdd7f4eb1106 100644 (file)
@@ -4,7 +4,7 @@
 SRCDIR              ?=  $(CURDIR)
 VPATH               :=  $(SRCDIR)
 
-SRC                 :=   as.c bin.c cstr.c elks.c eval.c expr.c fixup.c frag.c hashtab.c intel.c kwd.c lex.c lib.c list.c listing.c ll.c macro.c process.c report.c section.c symbol.c vector.c
+SRC                 :=   as.c bin.c cstr.c elks.c expr.c fixup.c frag.c hashtab.c intel.c kwd.c lex.c lib.c list.c listing.c ll.c macro.c process.c report.c section.c symbol.c vector.c
 
 all: sasm.exe
 
diff --git a/eval.c b/eval.c
deleted file mode 100644 (file)
index 7193bba..0000000
--- a/eval.c
+++ /dev/null
@@ -1,634 +0,0 @@
-/******************************************************************************
- * @file            eval.c
- *****************************************************************************/
-#include    <assert.h>
-#include    <ctype.h>
-#include    <stdio.h>
-#include    <stdlib.h>
-#include    <string.h>
-
-#include    "as.h"
-#include    "eval.h"
-#include    "lex.h"
-#include    "lib.h"
-#include    "macro.h"
-#include    "report.h"
-
-static unsigned int eval_expr (unsigned int lhs, char *start, char **pp, int outer_prec);
-
-static unsigned int eval_unary (unsigned int lhs, char *start, char **pp) {
-
-    *pp = skip_whitespace (*pp);
-    
-    if (isdigit ((int) **pp)) {
-    
-        unsigned int temp, temp2;
-        int ch;
-        
-        if ((*pp)[0] == '0' && tolower ((int) (*pp)[1]) == 'x') {
-        
-            unsigned int base = 16;
-            *pp += 2;
-            
-            while (isxdigit ((int) **pp)) {
-            
-                temp = lhs * base;
-                ch = *((*pp)++);
-                
-                if (ch >= '0' && ch <= '9') {
-                    temp2 = ch - '0';
-                } else {
-                    temp2 = (ch & 0xdf) - ('A' - 10);
-                }
-                
-                lhs = temp + temp2;
-            
-            }
-        
-        } else if ((*pp)[0] == '0') {
-        
-            unsigned int base = 8;
-            
-            while (isdigit ((int) **pp)) {
-            
-                temp = lhs * base;
-                lhs = (temp + (*((*pp)++) - '0'));
-            
-            }
-        
-        } else {
-        
-            unsigned int base = 10;
-            
-            while (isdigit ((int) **pp)) {
-            
-                temp = lhs * base;
-                lhs = (temp + (*((*pp)++) - '0'));
-            
-            }
-        
-        }
-        
-        return lhs;
-    
-    }
-    
-    if (is_name_beginner ((int) **pp)) {
-   
-        char *sname, *caret;
-        
-        struct hashtab_name *key;
-        struct macro *m;
-        
-        caret = *pp;
-        
-        while (is_name_part ((int) *caret)) {
-            caret++;
-        }
-        
-        if (memcmp (*pp, "defined", caret - *pp) == 0) {
-        
-            caret = skip_whitespace (caret);
-            *pp = caret;
-            
-            if (*caret == '(') {
-            
-                caret = skip_whitespace (caret + 1);
-                *pp = caret;
-                
-                while (!is_end_of_line[(int) *caret]) {
-                
-                    if (isspace ((int) *caret) || *caret == ')') { break; }
-                    caret++;
-                
-                }
-                
-                sname = xstrndup (*pp, caret - *pp);
-                caret = skip_whitespace (caret);
-                
-                if (*caret != ')') {
-                    report_line_at (get_filename (), get_line_number (), REPORT_ERROR, start, caret, "missing ')' after \"defined\"");
-                }
-            
-            } else {
-                sname = xstrndup (*pp, caret - *pp);
-            }
-            
-            if (*caret == ')') { caret++; }
-            *pp = skip_whitespace (caret);
-            
-            (void) sname;
-            (void) key;
-            
-            lhs = (find_macro (sname) != NULL);
-            return lhs;
-        
-        }
-        
-        sname = xstrndup (*pp, caret - *pp);
-        *pp = skip_whitespace (caret);
-        
-        if ((key = find_macro (sname))) {
-        
-            if ((m = get_macro (key))) {
-            
-                char *temp = process_macro (start, pp, m);
-                lhs = eval_unary (lhs, temp, &temp);
-            
-            }
-        
-        }
-        
-        return lhs;
-    
-    }
-    
-    if (**pp == '@') {
-    
-        char *arg, *temp = (*pp + 1);
-        
-        if ((arg = symname (&temp))) {
-        
-            if (xstrcasecmp (arg, "DataSize") == 0) {
-            
-                *pp = temp;
-                free (arg);
-                
-                return state->data_size;
-            
-            }
-            
-            if (xstrcasecmp (arg, "Model") == 0) {
-            
-                *pp = temp;
-                free (arg);
-                
-                return (state->model > 0 ? state->model : 1);
-            
-            }
-            
-            free (arg);
-        
-        }
-    
-    }
-    
-    if (**pp == '!') {
-    
-        unsigned int temp = 0;
-        
-        *pp = skip_whitespace (*pp + 1);
-        temp = eval_unary (temp, start, pp);
-        
-        lhs = (temp == 0);
-        return lhs;
-    
-    }
-    
-    if (**pp == '~') {
-    
-        int flip_bits = 0;
-        
-        while (**pp == '~') {
-        
-            flip_bits = !flip_bits;
-            *pp = skip_whitespace (*pp + 1);
-        
-        }
-        
-        lhs = eval_unary (lhs, start, pp);
-        
-        if (flip_bits) {
-            lhs = ~lhs;
-        }
-        
-        return lhs;
-    
-    }
-    
-    if (**pp == '-') {
-    
-        int sign = 1;
-        
-        while (**pp == '-' || **pp == '+') {
-        
-            if (**pp == '-') { sign = !sign; }
-            *pp = skip_whitespace (*pp + 1);
-        
-        }
-        
-        lhs = eval_unary (lhs, start, pp);
-        
-        if (!sign) {
-            lhs = -lhs;
-        }
-        
-        return lhs;
-    
-    }
-    
-    if (**pp == '(') {
-    
-        char *caret = (*pp)++;
-        int depth = 0;
-        
-        while (!is_end_of_line[(int) **pp]) {
-        
-            if (**pp == '(') {
-            
-                (*pp)++;
-                
-                depth++;
-                continue;
-            
-            }
-            
-            if (**pp == ')') {
-            
-                if (depth > 0) {
-                
-                    (*pp)++;
-                    
-                    depth--;
-                    continue;
-                
-                }
-                
-                break;
-            
-            }
-            
-            (*pp)++;
-        
-        }
-        
-        if (**pp != ')') {
-            report_line_at (get_filename (), get_line_number (), REPORT_WARNING, start, caret, "missing ')' in expression");
-        } else {
-            (*pp)++;
-        }
-        
-        memmove (caret, caret + 1, (*pp - caret) - 1);
-        *(caret + ((*pp - caret) - 1)) = '\0';
-        
-        lhs = eval_unary (lhs, start, &caret);
-        lhs = eval_expr (lhs, start, &caret, 15);
-        
-        return lhs;
-    
-    }
-    
-    if (!is_end_of_line[(int) **pp]) {
-    
-        report_line_at (get_filename (), get_line_number (), REPORT_INTERNAL_ERROR, start, *pp, "unexpected %c character", **pp);
-        
-        while (!is_end_of_line[(int) **pp]) {
-            (*pp)++;
-        }
-    
-    }
-    
-    return lhs;
-
-}
-
-#define     OP_MUL                      0
-#define     OP_DIV                      1
-#define     OP_MOD                      2
-#define     OP_PLUS                     3
-#define     OP_MINUS                    4
-#define     OP_LT                       5
-#define     OP_GT                       6
-#define     OP_LTEQ                     7
-#define     OP_GTEQ                     8
-#define     OP_EQEQ                     9
-#define     OP_NOTEQ                    11
-#define     OP_AND                      12
-#define     OP_XOR                      13
-#define     OP_OR                       14
-#define     OP_ANDAND                   15
-#define     OP_OROR                     16
-#define     OP_LSHIFT                   17
-#define     OP_RSHIFT                   18
-#define     OP_QUEST                    19
-#define     OP_MAX                      20
-
-struct op {
-
-    char *word;
-    int kind;
-
-};
-
-static struct op *get_op (char **pp) {
-
-    static struct op kws[] = {
-    
-        {   "and",      OP_AND      },
-        {   "eq",       OP_EQEQ     },
-        {   "ge",       OP_GTEQ     },
-        {   "gt",       OP_GT       },
-        {   "le",       OP_LTEQ     },
-        {   "lt",       OP_LT       },
-        {   "mod",      OP_MOD      },
-        {   "ne",       OP_NOTEQ    },
-        {   "or",       OP_OR       },
-        {   "shl",      OP_LSHIFT   },
-        {   "shr",      OP_RSHIFT   },
-        {   "xor",      OP_XOR      },
-        
-        {   "<=",       OP_LTEQ     },
-        {   ">=",       OP_GTEQ     },
-        {   "==",       OP_EQEQ     },
-        {   "!=",       OP_NOTEQ    },
-        {   "&&",       OP_ANDAND   },
-        {   "||",       OP_OROR     },
-        {   "<<",       OP_LSHIFT   },
-        {   ">>",       OP_RSHIFT   },
-        
-        {   "*",        OP_MUL      },
-        {   "/",        OP_DIV      },
-        {   "%",        OP_MOD      },
-        {   "+",        OP_PLUS     },
-        {   "-",        OP_MINUS    },
-        {   "<",        OP_LT       },
-        {   ">",        OP_GT       },
-        {   "&",        OP_AND      },
-        {   "^",        OP_XOR      },
-        {   "|",        OP_OR       },
-        {   "?",        OP_QUEST    },
-    
-    };
-    
-    struct op *kw;
-    unsigned int i;
-    
-    for (i = 0; i < (sizeof (kws) / sizeof (*kws)); i++) {
-    
-        kw = &kws[i];
-        
-        if (strncmp (*pp, kw->word, strlen (kw->word)) == 0) {
-        
-            *pp += strlen (kw->word);
-            return kw;
-        
-        }
-    
-    }
-    
-    return 0;
-
-}
-
-static int get_prec (int kind) {
-
-    switch (kind) {
-    
-        case OP_MUL:    case OP_DIV:    case OP_MOD:
-        
-            return 3;
-        
-        case OP_PLUS:   case OP_MINUS:
-        
-            return 4;
-        
-        case OP_LSHIFT:                 case OP_RSHIFT:
-        
-            return 5;
-        
-        case OP_LT:     case OP_GT:     case OP_LTEQ:       case OP_GTEQ:
-        
-            return 6;
-        
-        case OP_EQEQ:   case OP_NOTEQ:
-        
-            return 7;
-        
-        case OP_AND:
-        
-            return 8;
-        
-        case OP_XOR:
-        
-            return 9;
-        
-        case OP_OR:
-        
-            return 10;
-        
-        case OP_ANDAND:
-        
-            return 11;
-        
-        case OP_OROR:
-        
-            return 12;
-        
-        case OP_QUEST:
-        
-            return 13;
-        
-        default:
-        
-            break;
-    
-    } 
-    
-    return 100;
-
-}
-
-static unsigned int eval_expr (unsigned int lhs, char *start, char **pp, int outer_prec) {
-
-    struct op *op1, *op2;
-    unsigned int rhs;
-    
-    int prec, look_ahead;
-    
-    for (;;) {
-    
-        *pp = skip_whitespace (*pp);
-        
-        if (is_end_of_line[(int) **pp]) {
-            break;
-        }
-        
-        op1 = get_op (pp);
-        
-        if (!op1 || (prec = get_prec (op1->kind)) > outer_prec) {
-        
-            if (op1) { *pp -= strlen (op1->word); }
-            break;
-        
-        }
-        
-        *pp = skip_whitespace (*pp);
-        
-        if (op1->kind == OP_QUEST) {
-        
-            unsigned int left = 0, right = 0;
-            
-            left = eval_unary (left, start, pp);
-            left = eval_expr (left, start, pp, 14);
-            
-            *pp = skip_whitespace (*pp);
-            assert (**pp == ':');
-            *pp = skip_whitespace (*pp + 1);
-            
-            right = eval_unary (right, start, pp);
-            right = eval_expr (right, start, pp, 14);
-            
-            if (lhs != 0) {
-                lhs = left;
-            } else {
-                lhs = right;
-            }
-            
-            continue;
-        
-        }
-        
-        if (is_end_of_line[(int) **pp]) {
-            break;
-        }
-        
-        rhs = 0;
-        rhs = eval_unary (rhs, start, pp);
-        
-        for (;;) {
-        
-            *pp = skip_whitespace (*pp);
-            
-            if (is_end_of_line[(int) **pp]) {
-                break;
-            }
-            
-            op2 = get_op (pp);
-            
-            if (!op2 || (look_ahead = get_prec (op2->kind)) > prec) {
-            
-                if (op2) { *pp -= strlen (op2->word); }
-                break;
-            
-            }
-            
-            *pp = skip_whitespace (*pp);
-            rhs = eval_expr (rhs, start, pp, look_ahead);
-        
-        }
-        
-        switch (op1->kind) {
-        
-            case OP_MUL:
-            
-                lhs *= rhs;
-                break;
-            
-            case OP_DIV:
-            
-                lhs /= rhs;
-                break;
-            
-            case OP_MOD:
-            
-                lhs %= rhs;
-                break;
-            
-            case OP_PLUS:
-            
-                lhs += rhs;
-                break;
-            
-            case OP_MINUS:
-            
-                lhs -= rhs;
-                break;
-            
-            case OP_LT:
-            
-                lhs = (lhs < rhs);
-                break;
-            
-            case OP_GT:
-            
-                lhs = (lhs > rhs);
-                break;
-            
-            case OP_LTEQ:
-            
-                lhs = (lhs <= rhs);
-                break;
-            
-            case OP_GTEQ:
-            
-                lhs = (lhs >= rhs);
-                break;
-            
-            case OP_EQEQ:
-            
-                lhs = (lhs == rhs);
-                break;
-            
-            case OP_NOTEQ:
-            
-                lhs = (lhs != rhs);
-                break;
-            
-            case OP_AND:
-            
-                lhs &= rhs;
-                break;
-            
-            case OP_XOR:
-            
-                lhs ^= rhs;
-                break;
-            
-            case OP_OR:
-            
-                lhs |= rhs;
-                break;
-            
-            case OP_ANDAND:
-            
-                lhs = ((lhs != 0) && (rhs != 0));
-                break;
-            
-            case OP_OROR:
-            
-                lhs = ((lhs != 0) || (rhs != 0));
-                break;
-            
-            case OP_LSHIFT:
-            
-                lhs <<= rhs;
-                break;
-            
-            case OP_RSHIFT:
-            
-                lhs >>= rhs;
-                break;
-            
-            default:
-            
-                report_at (__FILE__, __LINE__, REPORT_INTERNAL_ERROR, "unimplemented");
-                break;
-        
-        }
-    
-    }
-    
-    return lhs;
-
-}
-
-int eval (char *start, char **pp) {
-
-    unsigned int lhs = 0;
-    
-    lhs = eval_unary (lhs, start, pp);
-    lhs = eval_expr (lhs, start, pp, 15);
-    
-    return (lhs != 0);
-
-}
diff --git a/eval.h b/eval.h
deleted file mode 100644 (file)
index 9361938..0000000
--- a/eval.h
+++ /dev/null
@@ -1,9 +0,0 @@
-/******************************************************************************
- * @file            eval.h
- *****************************************************************************/
-#ifndef     _EVAL_H
-#define     _EVAL_H
-
-int eval (char *start, char **pp);
-
-#endif      /* _EVAL_H */
index 8264d8cfe1f3eb635a33fd8fb0b4e6b6487a8cb8..62fe72f6374235234002945f56ac4e16d5de26e1 100644 (file)
--- a/process.c
+++ b/process.c
@@ -9,7 +9,6 @@
 
 #include    "as.h"
 #include    "cstr.h"
-#include    "eval.h"
 #include    "expr.h"
 #include    "frag.h"
 #include    "hashtab.h"
 #include    "symbol.h"
 #include    "vector.h"
 
+static char *preprocess_line (char *src, int in_macro) {
+
+    struct cstring cstr;
+    char *line;
+    
+    char *caret = src, *start;
+    char *sname, ch;
+    
+    struct hashtab_name *key;
+    struct macro *m;
+    
+    cstr_new (&cstr);
+    
+    while (!is_end_of_line[(int) *caret]) {
+    
+        start = caret;
+        
+        if (*caret == ' ' || *caret == '\t') {
+        
+            while (*caret == ' ' || *caret == '\t') {
+            
+                cstr_ccat (&cstr, ' ');
+                caret++;
+            
+            }
+            
+            continue;
+        
+        }
+        
+        if (*caret == '"' || *caret == '\'') {
+        
+            ch = *caret++;
+            
+            while (!is_end_of_line[(int) *caret]) {
+            
+                if (*caret == '\\') {
+                
+                    caret++;
+                    
+                    if (!is_end_of_line[(int) *caret]) {
+                        caret++;
+                    }
+                    
+                    continue;
+                
+                }
+                
+                if (*caret == ch) { break; }
+                caret++;
+            
+            }
+            
+            if (*caret != ch) {
+            
+                char *temp = xmalloc ((caret - start) + 2);
+                sprintf (temp, "%.*s%c", (int) (caret - start), start, ch);
+                
+                report_line_at (get_filename (), get_line_number (), REPORT_WARNING, src, start, "missing terminating %c character", ch);
+                cstr_cat (&cstr, temp, strlen (temp));
+                
+                continue;
+            
+            }
+            
+            caret++;
+            
+            cstr_cat (&cstr, start, caret - start);
+            continue;
+        
+        }
+        
+        if (is_name_beginner ((int) *caret)) {
+        
+            sname = symname (&caret);
+            
+            if ((key = find_macro (sname))) {
+            
+                if ((m = get_macro (key))) {
+                
+                    char *pm;
+                    int spaces = 0;
+                    
+                    if (*caret == ' ' || *caret == '\t') {
+                    
+                        cstr_ccat (&cstr, ' ');
+                        
+                        while (*caret == ' ' || *caret == '\t') {
+                        
+                            spaces++;
+                            caret++;
+                        
+                        }
+                    
+                    }
+                    
+                    if ((pm = process_macro (start, &caret, m))) {
+                    
+                        char *temp = preprocess_line (pm, 1);
+                        cstr_cat (&cstr, temp, strlen (temp));
+                        
+                        if (!is_end_of_line[(int) *pm]) {
+                        
+                            while (spaces--) {
+                                cstr_ccat (&cstr, ' ');
+                            }
+                        
+                        }
+                    
+                    }
+                
+                }
+                
+                continue;
+            
+            }
+            
+            cstr_cat (&cstr, start, caret - start);
+            continue;
+        
+        }
+        
+        if (*caret == '@') {
+        
+            char *arg, *temp = (caret + 1);
+            
+            if ((arg = symname (&temp))) {
+            
+                if (xstrcasecmp (arg, "DataSize") == 0) {
+                
+                    caret = temp;
+                    free (arg);
+                    
+                    cstr_ccat (&cstr, state->data_size | 0x30);
+                    continue;
+                
+                }
+                
+                if (xstrcasecmp (arg, "Model") == 0) {
+                
+                    caret = temp;
+                    free (arg);
+                    
+                    cstr_ccat (&cstr, (state->model > 0 ? state->model | 0x30 : '1'));
+                    continue;
+                
+                }
+                
+                free (arg);
+            
+            }
+        
+        }
+        
+        if (isdigit ((int) *caret)) {
+        
+            if (caret[0] == '0' && tolower ((int) caret[1]) == 'x') {
+                caret += 2;
+            }
+            
+            while (isdigit ((int) *caret)) {
+                caret++;
+            }
+            
+            cstr_cat (&cstr, start, caret - start);
+            continue;
+        
+        }
+        
+        if (ispunct ((int) *caret)) {
+        
+            cstr_ccat (&cstr, *caret);
+            
+            caret++;
+            continue;
+        
+        }
+        
+        report_line_at (get_filename (), get_line_number (), REPORT_INTERNAL_ERROR, src, caret, "Do we see this???");
+        caret++;
+    
+    }
+    
+    if (!in_macro && state->ofp) {
+        cstr_ccat (&cstr, '\n');
+    }
+    
+    cstr_ccat (&cstr, '\0');
+    
+    line = xstrdup (cstr.data);;
+    cstr_free (&cstr);
+    
+    return line;
+
+}
+
+
 struct pp_pseudo_op_entry {
 
     const char *name;
@@ -52,6 +248,20 @@ static int ignore_line = 0, iflevel = 0;
 static void handler_if (char *start, char **pp) {
 
     struct cond *cond;
+    struct expr expr_s;
+    
+    char *tokenized_line, *tokenized_start;
+    unsigned long pos = *pp - start;
+    
+    tokenized_start = (tokenized_line = preprocess_line (start, 0));
+    tokenized_line += pos;
+    
+    expression_evaluate_and_read_into (tokenized_start, &tokenized_line, &expr_s);
+    free (tokenized_start);
+    
+    if (expr_s.type != EXPR_TYPE_CONSTANT) {
+        report_at (get_filename (), get_line_number (), REPORT_ERROR, "non-constant expression in \"%if\" statement");
+    }
     
     if (!ignore_line) {
     
@@ -64,7 +274,7 @@ static void handler_if (char *start, char **pp) {
         cond->line_number = get_line_number ();
         
         vec_push (&vec_ifstack, cond);
-        ignore_line = !eval (start, pp);
+        ignore_line = (expr_s.add_number == 0);
     
     } else {
         iflevel++;
@@ -165,6 +375,16 @@ static void handler_ifndef (char *start, char **pp) {
 static void handler_elif (char *start, char **pp) {
 
     struct cond *cond;
+    struct expr expr_s;
+    
+    char *tokenized_line, *tokenized_start;
+    unsigned long pos = *pp - start;
+    
+    tokenized_start = (tokenized_line = preprocess_line (start, 0));
+    tokenized_line += pos;
+    
+    expression_evaluate_and_read_into (tokenized_start, &tokenized_line, &expr_s);
+    free (tokenized_start);
     
     if (!iflevel) {
     
@@ -186,7 +406,7 @@ static void handler_elif (char *start, char **pp) {
         
         }
         
-        ignore_line = (ignore_line && !eval (start, pp));
+        ignore_line = (ignore_line && (expr_s.add_number == 0));
     
     }
 
@@ -613,202 +833,6 @@ int preprocess_init (void) {
 }
 
 
-static char *preprocess_line (char *src, int in_macro) {
-
-    struct cstring cstr;
-    char *line;
-    
-    char *caret = src, *start;
-    char *sname, ch;
-    
-    struct hashtab_name *key;
-    struct macro *m;
-    
-    cstr_new (&cstr);
-    
-    while (!is_end_of_line[(int) *caret]) {
-    
-        start = caret;
-        
-        if (*caret == ' ' || *caret == '\t') {
-        
-            while (*caret == ' ' || *caret == '\t') {
-            
-                cstr_ccat (&cstr, ' ');
-                caret++;
-            
-            }
-            
-            continue;
-        
-        }
-        
-        if (*caret == '"' || *caret == '\'') {
-        
-            ch = *caret++;
-            
-            while (!is_end_of_line[(int) *caret]) {
-            
-                if (*caret == '\\') {
-                
-                    caret++;
-                    
-                    if (!is_end_of_line[(int) *caret]) {
-                        caret++;
-                    }
-                    
-                    continue;
-                
-                }
-                
-                if (*caret == ch) { break; }
-                caret++;
-            
-            }
-            
-            if (*caret != ch) {
-            
-                char *temp = xmalloc ((caret - start) + 2);
-                sprintf (temp, "%.*s%c", (int) (caret - start), start, ch);
-                
-                report_line_at (get_filename (), get_line_number (), REPORT_WARNING, src, start, "missing terminating %c character", ch);
-                cstr_cat (&cstr, temp, strlen (temp));
-                
-                continue;
-            
-            }
-            
-            caret++;
-            
-            cstr_cat (&cstr, start, caret - start);
-            continue;
-        
-        }
-        
-        if (is_name_beginner ((int) *caret)) {
-        
-            sname = symname (&caret);
-            
-            if ((key = find_macro (sname))) {
-            
-                if ((m = get_macro (key))) {
-                
-                    char *pm;
-                    int spaces = 0;
-                    
-                    if (*caret == ' ' || *caret == '\t') {
-                    
-                        cstr_ccat (&cstr, ' ');
-                        
-                        while (*caret == ' ' || *caret == '\t') {
-                        
-                            spaces++;
-                            caret++;
-                        
-                        }
-                    
-                    }
-                    
-                    if ((pm = process_macro (start, &caret, m))) {
-                    
-                        char *temp = preprocess_line (pm, 1);
-                        cstr_cat (&cstr, temp, strlen (temp));
-                        
-                        if (!is_end_of_line[(int) *pm]) {
-                        
-                            while (spaces--) {
-                                cstr_ccat (&cstr, ' ');
-                            }
-                        
-                        }
-                    
-                    }
-                
-                }
-                
-                continue;
-            
-            }
-            
-            cstr_cat (&cstr, start, caret - start);
-            continue;
-        
-        }
-        
-        if (*caret == '@') {
-        
-            char *arg, *temp = (caret + 1);
-            
-            if ((arg = symname (&temp))) {
-            
-                if (xstrcasecmp (arg, "DataSize") == 0) {
-                
-                    caret = temp;
-                    free (arg);
-                    
-                    cstr_ccat (&cstr, state->data_size | 0x30);
-                    continue;
-                
-                }
-                
-                if (xstrcasecmp (arg, "Model") == 0) {
-                
-                    caret = temp;
-                    free (arg);
-                    
-                    cstr_ccat (&cstr, (state->model > 0 ? state->model | 0x30 : '1'));
-                    continue;
-                
-                }
-                
-                free (arg);
-            
-            }
-        
-        }
-        
-        if (isdigit ((int) *caret)) {
-        
-            if (caret[0] == '0' && tolower ((int) caret[1]) == 'x') {
-                caret += 2;
-            }
-            
-            while (isdigit ((int) *caret)) {
-                caret++;
-            }
-            
-            cstr_cat (&cstr, start, caret - start);
-            continue;
-        
-        }
-        
-        if (ispunct ((int) *caret)) {
-        
-            cstr_ccat (&cstr, *caret);
-            
-            caret++;
-            continue;
-        
-        }
-        
-        report_line_at (get_filename (), get_line_number (), REPORT_INTERNAL_ERROR, src, caret, "Do we see this???");
-        caret++;
-    
-    }
-    
-    if (!in_macro && state->ofp) {
-        cstr_ccat (&cstr, '\n');
-    }
-    
-    cstr_ccat (&cstr, '\0');
-    
-    line = xstrdup (cstr.data);;
-    cstr_free (&cstr);
-    
-    return line;
-
-}
-
 struct section *machine_dependent_simplified_expression_read_into (char *start, char **pp, struct expr *expr);
 
 static struct section *get_known_section_expression (char *start, char **pp, struct expr *expr) {