]> git.sur5r.net Git - cc65/blobdiff - src/cc65/expr.c
Fixed multi line macro bug
[cc65] / src / cc65 / expr.c
index 470d690f85c4b337c23336c79acc293fa8b00418..276215f7418617bcd7a9695cbf99f5d19121d30f 100644 (file)
 #include <stdlib.h>
 #include <string.h>
 
-#include "../common/xmalloc.h"
+/* common */
+#include "check.h"
+#include "xmalloc.h"
 
+/* cc65 */
 #include "asmcode.h"
 #include "asmlabel.h"
-#include "check.h"
 #include "codegen.h"
 #include "datatype.h"
 #include "declare.h"
 #include "funcdesc.h"
 #include "function.h"
 #include "global.h"
-#include "io.h"
 #include "litpool.h"
 #include "macrotab.h"
 #include "preproc.h"
 #include "scanner.h"
 #include "stdfunc.h"
 #include "symtab.h"
+#include "typecmp.h"
 #include "expr.h"
 
 
@@ -115,7 +117,7 @@ static unsigned GlobalModeFlags (unsigned flags)
 static int IsNullPtr (struct expent* lval)
 /* Return true if this is the NULL pointer constant */
 {
-    return (IsInt (lval->e_tptr) &&            /* Is it an int? */
+    return (IsClassInt (lval->e_tptr) &&       /* Is it an int? */
                    lval->e_flags == E_MCONST &&        /* Is it constant? */
            lval->e_const == 0);                /* And is it's value zero? */
 }
@@ -130,14 +132,14 @@ static type* promoteint (type* lhst, type* rhst)
      *   - If one of the values        is unsigned, the result is also unsigned.
      *   - Otherwise the result is an int.
      */
-    if (IsLong (lhst) || IsLong (rhst)) {
-       if (IsUnsigned (lhst) || IsUnsigned (rhst)) {
+    if (IsTypeLong (lhst) || IsTypeLong (rhst)) {
+               if (IsSignUnsigned (lhst) || IsSignUnsigned (rhst)) {
                    return type_ulong;
        } else {
            return type_long;
        }
     } else {
-       if (IsUnsigned (lhst) || IsUnsigned (rhst)) {
+       if (IsSignUnsigned (lhst) || IsSignUnsigned (rhst)) {
            return type_uint;
        } else {
            return type_int;
@@ -196,63 +198,80 @@ unsigned assignadjust (type* lhst, struct expent* rhs)
  * set to the type of the left hand side.
  */
 {
-    /* Get the type of the right hand side */
+    /* Get the type of the right hand side. Treat function types as
+     * pointer-to-function
+     */
     type* rhst = rhs->e_tptr;
+    if (IsTypeFunc (rhst)) {
+       rhst = PointerTo (rhst);
+    }
 
     /* After calling this function, rhs will have the type of the lhs */
     rhs->e_tptr = lhst;
 
     /* First, do some type checking */
-    if (IsVoid (lhst) || IsVoid (rhst)) {
+    if (IsTypeVoid (lhst) || IsTypeVoid (rhst)) {
        /* If one of the sides are of type void, output a more apropriate
         * error message.
         */
-               Error (ERR_ILLEGAL_TYPE);
-    } else if (IsInt (lhst)) {
-       if (IsPtr (rhst)) {
+               Error ("Illegal type");
+    } else if (IsClassInt (lhst)) {
+               if (IsClassPtr (rhst)) {
            /* Pointer -> int conversion */
-           Warning (WARN_PTR_TO_INT_CONV);
-               } else if (!IsInt (rhst)) {
-           Error (ERR_INCOMPATIBLE_TYPES);
+           Warning ("Converting pointer to integer without a cast");
+               } else if (!IsClassInt (rhst)) {
+           Error ("Incompatible types");
        } else {
            /* Adjust the int types. To avoid manipulation of TOS mark lhs
             * as const.
             */
            unsigned flags = TypeOf (rhst);
-                   if (rhs->e_flags & E_MCONST) {
+                   if (rhs->e_flags == E_MCONST) {
                flags |= CF_CONST;
            }
            return g_typeadjust (TypeOf (lhst) | CF_CONST, flags);
         }
-    } else if (IsPtr (lhst)) {
-       if (IsPtr (rhst)) {
+    } else if (IsClassPtr (lhst)) {
+       if (IsClassPtr (rhst)) {
            /* Pointer to pointer assignment is valid, if:
             *   - both point to the same types, or
             *   - the rhs pointer is a void pointer, or
             *   - the lhs pointer is a void pointer.
             */
-           type* left  = Indirect (lhst);
-           type* right = Indirect (rhst);
-                   if (!EqualTypes (left, right) && *left != T_VOID && *right != T_VOID) {
-               Error (ERR_INCOMPATIBLE_POINTERS);
-           }
-       } else if (IsInt (rhst)) {
+           if (!IsTypeVoid (Indirect (lhst)) && !IsTypeVoid (Indirect (rhst))) {
+               /* Compare the types */
+               switch (TypeCmp (lhst, rhst)) {
+
+                   case TC_INCOMPATIBLE:
+                       Error ("Incompatible pointer types");
+                       break;
+
+                   case TC_QUAL_DIFF:
+                       Error ("Pointer types differ in type qualifiers");
+                       break;
+
+                   default:
+                       /* Ok */
+                       break;
+               }
+           }
+       } else if (IsClassInt (rhst)) {
            /* Int to pointer assignment is valid only for constant zero */
-           if ((rhs->e_flags & E_MCONST) == 0 || rhs->e_const != 0) {
-               Warning (WARN_INT_TO_PTR_CONV);
+           if (rhs->e_flags != E_MCONST || rhs->e_const != 0) {
+               Warning ("Converting integer to pointer without a cast");
            }
-       } else if (IsFuncPtr (lhst) && IsFunc(rhst)) {
+       } else if (IsTypeFuncPtr (lhst) && IsTypeFunc(rhst)) {
            /* Assignment of function to function pointer is allowed, provided
             * that both functions have the same parameter list.
             */
-           if (!EqualTypes(Indirect (lhst), rhst)) {
-               Error (ERR_INCOMPATIBLE_TYPES);
+           if (TypeCmp (Indirect (lhst), rhst) < TC_EQUAL) {
+               Error ("Incompatible types");
            }
        } else {
-           Error (ERR_INCOMPATIBLE_TYPES);
+           Error ("Incompatible types");
        }
     } else {
-       Error (ERR_INCOMPATIBLE_TYPES);
+       Error ("Incompatible types");
     }
 
     /* Return an int value in all cases where the operands are not both ints */
@@ -278,7 +297,7 @@ void DefineData (struct expent* lval)
             * allowed.
             */
            if (!AllowRegVarAddr) {
-               Error (ERR_CANNOT_TAKE_ADDR_OF_REG);
+               Error ("Cannot take the address of a register variable");
            }
            /* FALLTHROUGH */
 
@@ -290,7 +309,7 @@ void DefineData (struct expent* lval)
 
                case E_TLIT:
            /* a literal of some kind */
-                   g_defdata (CF_STATIC, LiteralLabel, lval->e_const);
+                   g_defdata (CF_STATIC, LiteralPoolLabel, lval->e_const);
                    break;
 
                default:
@@ -319,7 +338,7 @@ static void lconst (unsigned flags, struct expent* lval)
             * allowed.
             */
            if (!AllowRegVarAddr) {
-               Error (ERR_CANNOT_TAKE_ADDR_OF_REG);
+               Error ("Cannot take the address of a register variable");
            }
            /* FALLTHROUGH */
 
@@ -333,7 +352,7 @@ static void lconst (unsigned flags, struct expent* lval)
 
                case E_TLIT:
            /* Literal string */
-           g_getimmed (CF_STATIC, LiteralLabel, lval->e_const);
+           g_getimmed (CF_STATIC, LiteralPoolLabel, lval->e_const);
                    break;
 
                default:
@@ -373,13 +392,13 @@ static int kcalc (int tok, long val1, long val2)
            return (val1 * val2);
                case TOK_DIV:
            if (val2 == 0) {
-               Error (ERR_DIV_BY_ZERO);
+               Error ("Division by zero");
                return 0x7FFFFFFF;
            }
            return (val1 / val2);
                case TOK_MOD:
            if (val2 == 0) {
-               Error (ERR_MOD_BY_ZERO);
+               Error ("Modulo operation with zero");
                return 0;
            }
            return (val1 % val2);
@@ -412,13 +431,12 @@ static int istypeexpr (void)
 {
     SymEntry* Entry;
 
-    return curtok == TOK_LPAREN && (
-                   (nxttok >= TOK_FIRSTTYPE && nxttok <= TOK_LASTTYPE) ||
-           (nxttok == TOK_CONST)                               ||
-                   (nxttok  == TOK_IDENT                               &&
-           (Entry = FindSym (NextTok.Ident)) != 0              &&
-           IsTypeDef (Entry))
-           );
+    return CurTok.Tok == TOK_LPAREN && (
+                  (NextTok.Tok >= TOK_FIRSTTYPE && NextTok.Tok <= TOK_LASTTYPE) ||
+          (NextTok.Tok == TOK_CONST)                                    ||
+                  (NextTok.Tok  == TOK_IDENT                                    &&
+          (Entry = FindSym (NextTok.Ident)) != 0                        &&
+          IsTypeDef (Entry)));
 }
 
 
@@ -483,7 +501,6 @@ void exprhs (unsigned flags, int k, struct expent *lval)
     }
     if (lval->e_test & E_FORCETEST) {  /* we testing this value? */
        /* debug... */
-       AddCodeHint ("forcetest");
        flags |= TypeOf (lval->e_tptr);
                g_test (flags);                 /* yes, force a test */
                lval->e_test &= ~E_FORCETEST;
@@ -491,70 +508,91 @@ void exprhs (unsigned flags, int k, struct expent *lval)
 }
 
 
-static void callfunction (struct expent* lval)
-/* Perform a function call.  Called from hie11, this routine will
- * either call the named function, or if the supplied ptr is zero,
- * will call the contents of P.
+
+static unsigned FunctionParamList (FuncDesc* Func)
+/* Parse a function parameter list and pass the parameters to the called
+ * function. Depending on several criteria this may be done by just pushing
+ * each parameter separately, or creating the parameter frame once and then
+ * storing into this frame.
+ * The function returns the size of the parameters pushed.
  */
 {
-    struct expent lval2;
-    FuncDesc*    Func;         /* Function descriptor */
-    int                  Ellipsis;     /* True if we have an open param list */
-    SymEntry*    Param;        /* Current formal parameter */
-    unsigned     ParamCount;   /* Actual parameter count */
-    unsigned     ParamSize;    /* Number of parameter bytes */
-    unsigned     Flags;
-    unsigned     CFlags;
-    CodeMark     Mark;
-
-
-    /* Get a pointer to the function descriptor from the type string */
-    Func = GetFuncDesc (lval->e_tptr);
-
-    /* Initialize vars to keep gcc silent */
-    Param = 0;
-    Mark  = 0;
+    struct expent lval;
 
-    /* Check if this is a function pointer. If so, save it. If not, check for
-     * special known library functions that may be inlined.
+    /* Initialize variables */
+    SymEntry* Param              = 0;  /* Keep gcc silent */
+    unsigned  ParamSize   = 0; /* Size of parameters pushed */
+    unsigned  ParamCount  = 0; /* Number of parameters pushed */
+    unsigned  FrameSize   = 0; /* Size of parameter frame */
+    unsigned  FrameParams = 0; /* Number of params in frame */
+    int       FrameOffs   = 0; /* Offset into parameter frame */
+    int              Ellipsis    = 0;  /* Function is variadic */
+
+    /* As an optimization, we may allocate the complete parameter frame at
+     * once instead of pushing each parameter as it comes. We may do that,
+     * if...
+     *
+     *  - optimizations that increase code size are enabled (allocating the
+     *    stack frame at once gives usually larger code).
+     *  - we have more than one parameter to push (don't count the last param
+     *    for __fastcall__ functions).
      */
-    if (lval->e_flags & E_MEXPR) {
-               /* Function pointer is in primary register, save it */
-               Mark = GetCodePos ();
-               g_save (CF_PTR);
-    } else if (InlineStdFuncs && IsStdFunc ((const char*) lval->e_name)) {
-               /* Inline this function */
-               HandleStdFunc (lval);
-               return;
+    if (CodeSizeFactor >= 200) {
+
+       /* Calculate the number and size of the parameters */
+       FrameParams = Func->ParamCount;
+       FrameSize   = Func->ParamSize;
+       if (FrameParams > 0 && (Func->Flags & FD_FASTCALL) != 0) {
+           /* Last parameter is not pushed */
+           const SymEntry* LastParam = Func->SymTab->SymTail;
+           FrameSize -= SizeOf (LastParam->Type);
+           --FrameParams;
+       }
+
+       /* Do we have more than one parameter in the frame? */
+       if (FrameParams > 1) {
+           /* Okeydokey, setup the frame */
+           FrameOffs = oursp;
+           g_space (FrameSize);
+           oursp -= FrameSize;
+       } else {
+           /* Don't use a preallocated frame */
+           FrameSize = 0;
+       }
     }
 
     /* Parse the actual parameter list */
-    ParamSize  = 0;
-    ParamCount = 0;
-    Ellipsis   = 0;
-    while (curtok != TOK_RPAREN) {
+    while (CurTok.Tok != TOK_RPAREN) {
 
-       /* Add a hint for the optimizer */
-       AddCodeHint ("param:start");
+       unsigned CFlags;
+       unsigned Flags;
 
-       /* Count arguments */
-       ++ParamCount;
+       /* Count arguments */
+       ++ParamCount;
 
        /* Fetch the pointer to the next argument, check for too many args */
        if (ParamCount <= Func->ParamCount) {
+           /* Beware: If there are parameters with identical names, they
+            * cannot go into the same symbol table, which means that in this
+            * case of errorneous input, the number of nodes in the symbol
+            * table and ParamCount are NOT equal. We have to handle this case
+            * below to avoid segmentation violations. Since we know that this
+            * problem can only occur if there is more than one parameter,
+            * we will just use the last one.
+            */
            if (ParamCount == 1) {
-               /* First argument */
-               Param = Func->SymTab->SymHead;
-           } else {
+               /* First argument */
+               Param = Func->SymTab->SymHead;
+           } else if (Param->NextSym != 0) {
                /* Next argument */
                Param = Param->NextSym;
                CHECK ((Param->Flags & SC_PARAM) != 0);
            }
        } else if (!Ellipsis) {
            /* Too many arguments. Do we have an open param list? */
-           if ((Func->Flags & FD_ELLIPSIS) == 0) {
+           if ((Func->Flags & FD_VARIADIC) == 0) {
                /* End of param list reached, no ellipsis */
-               Error (ERR_TOO_MANY_FUNC_ARGS);
+               Error ("Too many arguments in function call");
            }
            /* Assume an ellipsis even in case of errors to avoid an error
             * message for each other argument.
@@ -569,8 +607,8 @@ static void callfunction (struct expent* lval)
                if (!Ellipsis && SizeOf (Param->Type) == 1) {
            CFlags = CF_FORCECHAR;
        }
-       Flags = 0;
-               if (evalexpr (CFlags, hie1, &lval2) == 0) {
+       Flags = CF_NONE;
+               if (evalexpr (CFlags, hie1, &lval) == 0) {
                    /* A constant value */
            Flags |= CF_CONST;
        }
@@ -580,13 +618,14 @@ static void callfunction (struct expent* lval)
         */
                if (!Ellipsis) {
            /* Promote the argument if needed */
-                   assignadjust (Param->Type, &lval2);
+                   assignadjust (Param->Type, &lval);
+
            /* If we have a prototype, chars may be pushed as chars */
            Flags |= CF_FORCECHAR;
                }
 
        /* Use the type of the argument for the push */
-               Flags |= TypeOf (lval2.e_tptr);
+               Flags |= TypeOf (lval.e_tptr);
 
        /* If this is a fastcall function, don't push the last argument */
                if (ParamCount == Func->ParamCount && (Func->Flags & FD_FASTCALL) != 0) {
@@ -595,32 +634,86 @@ static void callfunction (struct expent* lval)
             * the primary.
             */
            if (Flags & CF_CONST) {
-               exprhs (CF_FORCECHAR, 0, &lval2);
+               exprhs (CF_FORCECHAR, 0, &lval);
            }
        } else {
-           /* Push the argument, count the argument size */
-           g_push (Flags, lval2.e_const);
-           ParamSize += sizeofarg (Flags);
-       }
+           unsigned ArgSize = sizeofarg (Flags);
+           if (FrameSize > 0) {
+               /* We have the space already allocated, store in the frame */
+               CHECK (FrameSize >= ArgSize);
+               FrameSize -= ArgSize;
+               FrameOffs -= ArgSize;
+               /* Store */
+               g_putlocal (Flags | CF_NOKEEP, FrameOffs, lval.e_const);
+           } else {
+               /* Push the argument */
+               g_push (Flags, lval.e_const);
+           }
 
-       /* Add an optimizer hint */
-       AddCodeHint ("param:end");
+           /* Calculate total parameter size */
+           ParamSize += ArgSize;
+       }
 
        /* Check for end of argument list */
-       if (curtok != TOK_COMMA) {
+       if (CurTok.Tok != TOK_COMMA) {
            break;
        }
        NextToken ();
     }
 
-    /* We need the closing bracket here */
-    ConsumeRParen ();
-
     /* Check if we had enough parameters */
     if (ParamCount < Func->ParamCount) {
-       Error (ERR_TOO_FEW_FUNC_ARGS);
+       Error ("Too few arguments in function call");
+    }
+
+    /* The function returns the size of all parameters pushed onto the stack.
+     * However, if there are parameters missing (which is an error and was
+     * flagged by the compiler) AND a stack frame was preallocated above,
+     * we would loose track of the stackpointer and generate an internal error
+     * later. So we correct the value by the parameters that should have been
+     * pushed to avoid an internal compiler error. Since an error was
+     * generated before, no code will be output anyway.
+     */
+    return ParamSize + FrameSize;
+}
+
+
+
+static void CallFunction (struct expent* lval)
+/* Perform a function call.  Called from hie11, this routine will
+ * either call the named function, or the function pointer in a/x.
+ */
+{
+    FuncDesc*    Func;         /* Function descriptor */
+    unsigned     ParamSize;    /* Number of parameter bytes */
+    CodeMark     Mark;
+
+
+    /* Get a pointer to the function descriptor from the type string */
+    Func = GetFuncDesc (lval->e_tptr);
+
+    /* Initialize vars to keep gcc silent */
+    Mark  = 0;
+
+    /* Check if this is a function pointer. If so, save it. If not, check for
+     * special known library functions that may be inlined.
+     */
+    if (lval->e_flags & E_MEXPR) {
+               /* Function pointer is in primary register, save it */
+               Mark = GetCodePos ();
+               g_save (CF_PTR);
+    } else if (InlineStdFuncs && IsStdFunc ((const char*) lval->e_name)) {
+               /* Inline this function */
+               HandleStdFunc (lval);
+               return;
     }
 
+    /* Parse the parameter list */
+    ParamSize = FunctionParamList (Func);
+
+    /* We need the closing bracket here */
+    ConsumeRParen ();
+
     /* */
     if (lval->e_flags & E_MEXPR) {
        /* Function called via pointer: Restore it and call function */
@@ -632,7 +725,7 @@ static void callfunction (struct expent* lval)
        }
        g_callind (TypeOf (lval->e_tptr), ParamSize);
     } else {
-               g_call (TypeOf (lval->e_tptr), (char*) lval->e_name, ParamSize);
+               g_call (TypeOf (lval->e_tptr), (const char*) lval->e_name, ParamSize);
     }
 }
 
@@ -651,18 +744,35 @@ void doasm (void)
     ConsumeLParen ();
 
     /* String literal */
-    if (curtok != TOK_SCONST) {
-       Error (ERR_STRLIT_EXPECTED);
+    if (CurTok.Tok != TOK_SCONST) {
+       Error ("String literal expected");
     } else {
-       /* Write the string directly into the output, followed by a newline */
-               AddCodeLine (GetLiteral (curval));
+
+       /* The string literal may consist of more than one line of assembler
+        * code. Separate the single lines and output the code.
+        */
+       const char* S = GetLiteral (CurTok.IVal);
+       while (*S) {
+
+           /* Allow lines up to 256 bytes */
+           const char* E = strchr (S, '\n');
+           if (E) {
+               /* Found a newline */
+               g_asmcode (S, E-S);
+               S = E+1;
+           } else {
+               int Len = strlen (S);
+               g_asmcode (S, Len);
+               S += Len;
+           }
+       }
 
        /* Reset the string pointer, effectivly clearing the string from the
         * string table. Since we're working with one token lookahead, this
         * will fail if the next token is also a string token, but that's a
         * syntax error anyway, because we expect a right paren.
         */
-       ResetLiteralOffs (curval);
+       ResetLiteralPoolOffs (CurTok.IVal);
     }
 
     /* Skip the string token */
@@ -683,10 +793,10 @@ static int primary (struct expent* lval)
     lval->e_test = 0;
 
     /* Character and integer constants. */
-    if (curtok == TOK_ICONST || curtok == TOK_CCONST) {
+    if (CurTok.Tok == TOK_ICONST || CurTok.Tok == TOK_CCONST) {
        lval->e_flags = E_MCONST | E_TCONST;
-       lval->e_tptr  = curtype;
-       lval->e_const = curval;
+       lval->e_tptr  = CurTok.Type;
+       lval->e_const = CurTok.IVal;
        NextToken ();
        return 0;
     }
@@ -694,7 +804,7 @@ static int primary (struct expent* lval)
     /* Process parenthesized subexpression by calling the whole parser
      * recursively.
      */
-    if (curtok == TOK_LPAREN) {
+    if (CurTok.Tok == TOK_LPAREN) {
        NextToken ();
        memset (lval, 0, sizeof (*lval));       /* Remove any attributes */
        k = hie0 (lval);
@@ -707,14 +817,14 @@ static int primary (struct expent* lval)
      */
     if (Preprocessing) {
                /* Illegal expression in PP mode */
-       Error (ERR_CPP_EXPR_EXPECTED);
+       Error ("Preprocessor expression expected");
        lval->e_flags = E_MCONST;
        lval->e_tptr = type_int;
        return 0;
     }
 
     /* Identifier? */
-    if (curtok == TOK_IDENT) {
+    if (CurTok.Tok == TOK_IDENT) {
 
        SymEntry* Sym;
        ident Ident;
@@ -732,13 +842,10 @@ static int primary (struct expent* lval)
            lval->e_tptr = Sym->Type;
 
            /* Check for illegal symbol types */
-           if ((Sym->Flags & SC_LABEL) == SC_LABEL) {
-               /* Cannot use labels in expressions */
-               Error (ERR_SYMBOL_KIND);
-               return 1;
-                   } else if (Sym->Flags & SC_TYPE) {
+           CHECK ((Sym->Flags & SC_LABEL) != SC_LABEL);
+                   if (Sym->Flags & SC_TYPE) {
                /* Cannot use type symbols */
-               Error (ERR_VAR_IDENT_EXPECTED);
+               Error ("Variable identifier expected");
                /* Assume an int type to make lval valid */
                lval->e_flags = E_MLOCAL | E_TLOFFS;
                lval->e_tptr = type_int;
@@ -747,9 +854,10 @@ static int primary (struct expent* lval)
            }
 
            /* Check for legal symbol types */
-                   if ((Sym->Flags & SC_ENUM) == SC_ENUM) {
+                   if ((Sym->Flags & SC_CONST) == SC_CONST) {
+               /* Enum or some other numeric constant */
                lval->e_flags = E_MCONST;
-               lval->e_const = Sym->V.EnumVal;
+               lval->e_const = Sym->V.ConstVal;
                return 0;
            } else if ((Sym->Flags & SC_FUNC) == SC_FUNC) {
                /* Function */
@@ -757,9 +865,20 @@ static int primary (struct expent* lval)
                lval->e_name = (unsigned long) Sym->Name;
                lval->e_const = 0;
            } else if ((Sym->Flags & SC_AUTO) == SC_AUTO) {
-               /* Local variable */
-               lval->e_flags = E_MLOCAL | E_TLOFFS;
-               lval->e_const = Sym->V.Offs;
+               /* Local variable. If this is a parameter for a variadic
+                * function, we have to add some address calculations, and the
+                * address is not const.
+                */
+                       if ((Sym->Flags & SC_PARAM) == SC_PARAM && IsVariadic (CurrentFunc)) {
+                   /* Variadic parameter */
+                   g_leavariadic (Sym->V.Offs - GetParamSize (CurrentFunc));
+                   lval->e_flags = E_MEXPR;
+                   lval->e_const = 0;
+               } else {
+                   /* Normal parameter */
+                   lval->e_flags = E_MLOCAL | E_TLOFFS;
+                   lval->e_const = Sym->V.Offs;
+               }
            } else if ((Sym->Flags & SC_STATIC) == SC_STATIC) {
                /* Static variable */
                if (Sym->Flags & (SC_EXTERN | SC_STORAGE)) {
@@ -784,7 +903,7 @@ static int primary (struct expent* lval)
 
            /* The symbol is referenced now */
            Sym->Flags |= SC_REF;
-                   if (IsFunc (lval->e_tptr) || IsArray (lval->e_tptr)) {
+                   if (IsTypeFunc (lval->e_tptr) || IsTypeArray (lval->e_tptr)) {
                return 0;
            }
            return 1;
@@ -795,13 +914,13 @@ static int primary (struct expent* lval)
        NextToken ();
 
        /* IDENT is either an auto-declared function or an undefined variable. */
-       if (curtok == TOK_LPAREN) {
+       if (CurTok.Tok == TOK_LPAREN) {
            /* Declare a function returning int. For that purpose, prepare a
             * function signature for a function having an empty param list
             * and returning int.
             */
-           Warning (WARN_FUNC_WITHOUT_PROTO);
-           Sym = AddGlobalSym (Ident, GetImplicitFuncType(), SC_EXTERN | SC_REF);
+           Warning ("Function call without a prototype");
+           Sym = AddGlobalSym (Ident, GetImplicitFuncType(), SC_EXTERN | SC_REF | SC_FUNC);
            lval->e_tptr  = Sym->Type;
            lval->e_flags = E_MGLOBAL | E_MCONST | E_TGLAB;
                    lval->e_name  = (unsigned long) Sym->Name;
@@ -815,23 +934,23 @@ static int primary (struct expent* lval)
            lval->e_flags = E_MLOCAL | E_TLOFFS;
            lval->e_tptr = type_int;
            lval->e_const = 0;
-           Error (ERR_UNDEFINED_SYMBOL, Ident);
+           Error ("Undefined symbol: `%s'", Ident);
            return 1;
 
        }
     }
 
     /* String literal? */
-    if (curtok == TOK_SCONST) {
+    if (CurTok.Tok == TOK_SCONST) {
        lval->e_flags = E_MCONST | E_TLIT;
-               lval->e_const = curval;
-       lval->e_tptr  = GetCharArrayType (strlen (GetLiteral (curval)));
+               lval->e_const = CurTok.IVal;
+       lval->e_tptr  = GetCharArrayType (strlen (GetLiteral (CurTok.IVal)));
        NextToken ();
        return 0;
     }
 
     /* ASM statement? */
-    if (curtok == TOK_ASM) {
+    if (CurTok.Tok == TOK_ASM) {
        doasm ();
        lval->e_tptr  = type_void;
        lval->e_flags = E_MEXPR;
@@ -840,8 +959,8 @@ static int primary (struct expent* lval)
     }
 
     /* __AX__ and __EAX__ pseudo values? */
-    if (curtok == TOK_AX || curtok == TOK_EAX) {
-               lval->e_tptr  = (curtok == TOK_AX)? type_uint : type_ulong;
+    if (CurTok.Tok == TOK_AX || CurTok.Tok == TOK_EAX) {
+               lval->e_tptr  = (CurTok.Tok == TOK_AX)? type_uint : type_ulong;
        lval->e_flags = E_MREG;
        lval->e_test &= ~E_CC;
        lval->e_const = 0;
@@ -850,7 +969,7 @@ static int primary (struct expent* lval)
     }
 
     /* Illegal primary. */
-    Error (ERR_EXPR_EXPECTED);
+    Error ("Expression expected");
     lval->e_flags = E_MCONST;
     lval->e_tptr = type_int;
     return 0;
@@ -916,7 +1035,7 @@ static int arrayref (int k, struct expent* lval)
            exprhs (CF_NONE, k, lval);
        }
 
-       if (IsPtr (tptr1)) {
+       if (IsClassPtr (tptr1)) {
 
            /* Scale the subscript value according to element size */
            lval2.e_const *= PSizeOf (tptr1);
@@ -927,7 +1046,7 @@ static int arrayref (int k, struct expent* lval)
            /* Handle constant base array on stack. Be sure NOT to
             * handle pointers the same way, this won't work.
             */
-           if (IsArray (tptr1) &&
+           if (IsTypeArray (tptr1) &&
                ((lval->e_flags & ~E_MCTYPE) == E_MCONST ||
                (lval->e_flags & ~E_MCTYPE) == E_MLOCAL ||
                (lval->e_flags & E_MGLOBAL) != 0 ||
@@ -949,7 +1068,7 @@ static int arrayref (int k, struct expent* lval)
            /* Done */
            goto end_array;
 
-               } else if ((tptr2 = lval2.e_tptr) [0] & T_POINTER) {
+               } else if (IsClassPtr (tptr2 = lval2.e_tptr)) {
            /* Subscript is pointer, get element type */
            lval2.e_tptr = Indirect (tptr2);
 
@@ -958,7 +1077,7 @@ static int arrayref (int k, struct expent* lval)
            /* */
            lval->e_tptr = lval2.e_tptr;
        } else {
-           Error (ERR_CANNOT_SUBSCRIPT);
+           Error ("Cannot subscript");
        }
 
        /* Add the subscript. Since arrays are indexed by integers,
@@ -974,7 +1093,7 @@ static int arrayref (int k, struct expent* lval)
         exprhs (CF_NONE, l, &lval2);
 
        tptr2 = lval2.e_tptr;
-       if (IsPtr (tptr1)) {
+       if (IsClassPtr (tptr1)) {
 
            /* Get the element type */
            lval->e_tptr = Indirect (tptr1);
@@ -985,7 +1104,7 @@ static int arrayref (int k, struct expent* lval)
             */
            g_scale (CF_INT, SizeOf (lval->e_tptr));
 
-       } else if (IsPtr (tptr2)) {
+       } else if (IsClassPtr (tptr2)) {
 
            /* Get the element type */
            lval2.e_tptr = Indirect (tptr2);
@@ -995,7 +1114,7 @@ static int arrayref (int k, struct expent* lval)
                     * if necessary and the second one is a pointer).
             * Note: If ConstBaseAddr is true, we don't have a value on
             * stack, so to "swap" both, just push the subscript.
-            */
+            */
            if (ConstBaseAddr) {
                g_push (CF_INT, 0);
                exprhs (CF_NONE, k, lval);
@@ -1008,7 +1127,7 @@ static int arrayref (int k, struct expent* lval)
            g_scale (TypeOf (tptr1), SizeOf (lval2.e_tptr));
            lval->e_tptr = lval2.e_tptr;
        } else {
-           Error (ERR_CANNOT_SUBSCRIPT);
+           Error ("Cannot subscript");
        }
 
        /* The offset is now in the primary register. It didn't have a
@@ -1032,7 +1151,7 @@ static int arrayref (int k, struct expent* lval)
            rflags = lval2.e_flags & ~E_MCTYPE;
            ConstSubAddr = (rflags == E_MCONST)       || /* Constant numeric address */
                                    (rflags & E_MGLOBAL) != 0 || /* Static array, or ... */
-                           rflags == E_MLOCAL;          /* Local array */
+                           rflags == E_MLOCAL;          /* Local array */
 
                    if (ConstSubAddr && SizeOf (lval->e_tptr) == 1) {
 
@@ -1040,7 +1159,7 @@ static int arrayref (int k, struct expent* lval)
 
                /* Reverse the order of evaluation */
                unsigned flags = (SizeOf (lval2.e_tptr) == 1)? CF_CHAR : CF_INT;
-               RemoveCode (Mark2);
+               RemoveCode (Mark2);
 
                /* Get a pointer to the array into the primary. We have changed
                 * e_tptr above but we need the original type to load the
@@ -1064,7 +1183,7 @@ static int arrayref (int k, struct expent* lval)
                    g_inc (CF_INT | CF_UNSIGNED, lval->e_const);
                } else if (lflags == E_MLOCAL) {
                    /* Base address is a local variable address */
-                   if (IsArray (tptr1)) {
+                   if (IsTypeArray (tptr1)) {
                        g_addaddr_local (CF_INT, lval->e_const);
                    } else {
                        g_addlocal (CF_PTR, lval->e_const);
@@ -1073,7 +1192,7 @@ static int arrayref (int k, struct expent* lval)
                    /* Base address is a static variable address */
                    unsigned flags = CF_INT;
                    flags |= GlobalModeFlags (lval->e_flags);
-                   if (IsArray (tptr1)) {
+                   if (IsTypeArray (tptr1)) {
                        g_addaddr_static (flags, lval->e_name, lval->e_const);
                    } else {
                        g_addstatic (flags, lval->e_name, lval->e_const);
@@ -1085,7 +1204,7 @@ static int arrayref (int k, struct expent* lval)
     lval->e_flags = E_MEXPR;
 end_array:
     ConsumeRBrack ();
-    return !IsArray (lval->e_tptr);
+    return !IsTypeArray (lval->e_tptr);
 
 }
 
@@ -1100,8 +1219,8 @@ static int structref (int k, struct expent* lval)
 
     /* Skip the token and check for an identifier */
     NextToken ();
-    if (curtok != TOK_IDENT) {
-       Error (ERR_IDENT_EXPECTED);
+    if (CurTok.Tok != TOK_IDENT) {
+       Error ("Identifier expected");
        lval->e_tptr = type_int;
        return 0;
     }
@@ -1111,7 +1230,7 @@ static int structref (int k, struct expent* lval)
     NextToken ();
     Field = FindStructField (lval->e_tptr, Ident);
     if (Field == 0) {
-       Error (ERR_STRUCT_FIELD_MISMATCH, Ident);
+       Error ("Struct/union has no field named `%s'", Ident);
                lval->e_tptr = type_int;
        return 0;
     }
@@ -1131,7 +1250,7 @@ static int structref (int k, struct expent* lval)
        lval->e_flags = E_MEOFFS;
     }
     lval->e_tptr = Field->Type;
-    return !IsArray (Field->Type);
+    return !IsTypeArray (Field->Type);
 }
 
 
@@ -1144,50 +1263,50 @@ static int hie11 (struct expent *lval)
 
 
     k = primary (lval);
-    if (curtok < TOK_LBRACK || curtok > TOK_PTR_REF) {
+    if (CurTok.Tok < TOK_LBRACK || CurTok.Tok > TOK_PTR_REF) {
        /* Not for us */
                return k;
     }
 
     while (1) {
 
-       if (curtok == TOK_LBRACK) {
+       if (CurTok.Tok == TOK_LBRACK) {
 
            /* Array reference */
            k = arrayref (k, lval);
 
-       } else if (curtok == TOK_LPAREN) {
+       } else if (CurTok.Tok == TOK_LPAREN) {
 
            /* Function call. Skip the opening parenthesis */
            NextToken ();
            tptr = lval->e_tptr;
-           if (IsFunc (tptr) || IsFuncPtr (tptr)) {
-               if (IsFuncPtr (tptr)) {
+           if (IsTypeFunc (tptr) || IsTypeFuncPtr (tptr)) {
+               if (IsTypeFuncPtr (tptr)) {
                    /* Pointer to function. Handle transparently */
                    exprhs (CF_NONE, k, lval);  /* Function pointer to A/X */
                    ++lval->e_tptr;             /* Skip T_PTR */
                    lval->e_flags |= E_MEXPR;
                }
-               callfunction (lval);
+               CallFunction (lval);
                lval->e_flags = E_MEXPR;
                lval->e_tptr += DECODE_SIZE + 1;        /* Set to result */
            } else {
-               Error (ERR_ILLEGAL_FUNC_CALL);
+               Error ("Illegal function call");
            }
            k = 0;
 
-       } else if (curtok == TOK_DOT) {
+       } else if (CurTok.Tok == TOK_DOT) {
 
-           if (!IsStruct (lval->e_tptr)) {
-               Error (ERR_STRUCT_EXPECTED);
+           if (!IsClassStruct (lval->e_tptr)) {
+               Error ("Struct expected");
            }
            k = structref (0, lval);
 
-       } else if (curtok == TOK_PTR_REF) {
+       } else if (CurTok.Tok == TOK_PTR_REF) {
 
            tptr = lval->e_tptr;
            if (tptr[0] != T_PTR || (tptr[1] & T_STRUCT) == 0) {
-               Error (ERR_STRUCT_PTR_EXPECTED);
+               Error ("Struct pointer expected");
            }
            k = structref (k, lval);
 
@@ -1218,7 +1337,7 @@ static void store (struct expent* lval)
                g_putstatic (flags, lval->e_name, lval->e_const);
 
     } else if (f & E_MLOCAL) {
-               g_putlocal (flags, lval->e_const);
+               g_putlocal (flags, lval->e_const, 0);
     } else if (f == E_MEOFFS) {
        g_putind (flags, lval->e_const);
     } else if (f != E_MREG) {
@@ -1245,7 +1364,7 @@ static void pre_incdec (struct expent* lval, void (*inc) (unsigned, unsigned lon
 
     NextToken ();
     if ((k = hie10 (lval)) == 0) {
-       Error (ERR_LVALUE_EXPECTED);
+       Error ("Invalid lvalue");
        return;
     }
 
@@ -1279,31 +1398,32 @@ static void pre_incdec (struct expent* lval, void (*inc) (unsigned, unsigned lon
        if (lval->e_flags & E_MGLOBAL) {
            flags |= GlobalModeFlags (lval->e_flags);
            if (inc == g_inc) {
-               g_addeqstatic (flags, lval->e_name, lval->e_const, val);
+               g_addeqstatic (flags, lval->e_name, lval->e_const, val);
            } else {
-               g_subeqstatic (flags, lval->e_name, lval->e_const, val);
+               g_subeqstatic (flags, lval->e_name, lval->e_const, val);
            }
        } else if (lval->e_flags & E_MLOCAL) {
            /* ref to localvar */
            if (inc == g_inc) {
-               g_addeqlocal (flags, lval->e_const, val);
+               g_addeqlocal (flags, lval->e_const, val);
            } else {
-               g_subeqlocal (flags, lval->e_const, val);
+               g_subeqlocal (flags, lval->e_const, val);
            }
        } else if (lval->e_flags & E_MCONST) {
            /* ref to absolute address */
            flags |= CF_ABSOLUTE;
            if (inc == g_inc) {
-               g_addeqstatic (flags, lval->e_const, 0, val);
+               g_addeqstatic (flags, lval->e_const, 0, val);
            } else {
-               g_subeqstatic (flags, lval->e_const, 0, val);
+               g_subeqstatic (flags, lval->e_const, 0, val);
            }
        } else if (lval->e_flags & E_MEXPR) {
-           /* Address in a/x. */
+           /* Address in a/x, check if we have an offset */
+           unsigned Offs = (lval->e_flags == E_MEOFFS)? lval->e_const : 0;
            if (inc == g_inc) {
-               g_addeqind (flags, lval->e_const, val);
+               g_addeqind (flags, Offs, val);
            } else {
-               g_subeqind (flags, lval->e_const, val);
+               g_subeqind (flags, Offs, val);
            }
        } else {
            Internal ("Invalid addressing mode");
@@ -1324,7 +1444,7 @@ static void post_incdec (struct expent *lval, int k, void (*inc) (unsigned, unsi
 
     NextToken ();
     if (k == 0) {
-       Error (ERR_LVALUE_EXPECTED);
+       Error ("Invalid lvalue");
                return;
     }
 
@@ -1363,10 +1483,10 @@ static void unaryop (int tok, struct expent* lval)
 
     NextToken ();
     k = hie10 (lval);
-    if (k == 0 && lval->e_flags & E_MCONST) {
+    if (k == 0 && (lval->e_flags & E_MCONST) != 0) {
        /* Value is constant */
        switch (tok) {
-           case TOK_MINUS: lval->e_const =     -lval->e_const; break;
+           case TOK_MINUS: lval->e_const = -lval->e_const;     break;
            case TOK_PLUS:                                      break;
            case TOK_COMP:  lval->e_const = ~lval->e_const;     break;
            default:        Internal ("Unexpected token: %d", tok);
@@ -1396,7 +1516,6 @@ static int typecast (struct expent* lval)
 {
     int k;
     type Type[MAXTYPELEN];
-    unsigned rflags;
 
     /* Skip the left paren */
     NextToken ();
@@ -1410,19 +1529,74 @@ static int typecast (struct expent* lval)
     /* Read the expression we have to cast */
     k = hie10 (lval);
 
-    /* Get the type of the expression and honor constant values */
-    rflags = TypeOf (lval->e_tptr);
-    if (lval->e_flags & E_MCONST) {
-       rflags |= CF_CONST;
+    /* If the expression is a function, treat it as pointer-to-function */
+    if (IsTypeFunc (lval->e_tptr)) {
+       lval->e_tptr = PointerTo (lval->e_tptr);
     }
 
-    /* Do the actual cast. Special handling for void casts */
-    if (!IsVoid (Type)) {
-       /* Mark the lhs as const to avoid a manipulation of TOS */
-        g_typecast (TypeOf (Type) | CF_CONST, rflags);
+    /* Check for a constant on the right side */
+    if (k == 0 && lval->e_flags == E_MCONST) {
+
+       /* A cast of a constant to something else. If the new type is an int,
+        * be sure to handle the size extension correctly. If the new type is
+        * not an int, the cast is implementation specific anyway, so leave
+        * the value alone.
+        */
+       if (IsClassInt (Type)) {
+
+           /* Get the current and new size of the value */
+           unsigned OldSize = SizeOf (lval->e_tptr);
+           unsigned NewSize = SizeOf (Type);
+           unsigned OldBits = OldSize * 8;
+           unsigned NewBits = NewSize * 8;
+
+           /* Check if the new datatype will have a smaller range */
+           if (NewSize < OldSize) {
+
+               /* Cut the value to the new size */
+               lval->e_const &= (0xFFFFFFFFUL >> (32 - NewBits));
+
+               /* If the new value is signed, sign extend the value */
+               if (!IsSignUnsigned (Type)) {
+                   lval->e_const |= ((~0L) << NewBits);
+               }
+
+           } else if (NewSize > OldSize) {
+
+               /* Sign extend the value if needed */
+               if (!IsSignUnsigned (Type) && !IsSignUnsigned (lval->e_tptr)) {
+                   if (lval->e_const & (0x01UL << (OldBits-1))) {
+                       lval->e_const |= ((~0L) << OldBits);
+                   }
+               }
+           }
+       }
+
+    } else {
+
+       /* Not a constant. Be sure to ignore casts to void */
+       if (!IsTypeVoid (Type)) {
+
+           /* If the size does not change, leave the value alone. Otherwise,
+            * we have to load the value into the primary and generate code to
+            * cast the value in the primary register.
+            */
+           if (SizeOf (Type) != SizeOf (lval->e_tptr)) {
+
+               /* Load the value into the primary */
+               exprhs (CF_NONE, k, lval);
+
+               /* Mark the lhs as const to avoid a manipulation of TOS */
+               g_typecast (TypeOf (Type) | CF_CONST, TypeOf (lval->e_tptr));
+
+               /* Value is now in primary */
+               lval->e_flags = E_MEXPR;
+                       k = 0;
+           }
+       }
     }
 
-    /* Use the new type */
+    /* In any case, use the new type */
     lval->e_tptr = TypeDup (Type);
 
     /* Done */
@@ -1437,7 +1611,7 @@ static int hie10 (struct expent* lval)
     int k;
     type* t;
 
-    switch (curtok) {
+    switch (CurTok.Tok) {
 
        case TOK_INC:
            pre_incdec (lval, g_inc);
@@ -1450,7 +1624,7 @@ static int hie10 (struct expent* lval)
        case TOK_PLUS:
        case TOK_MINUS:
        case TOK_COMP:
-           unaryop (curtok, lval);
+           unaryop (CurTok.Tok, lval);
            return 0;
 
        case TOK_BOOL_NOT:
@@ -1463,7 +1637,7 @@ static int hie10 (struct expent* lval)
                lval->e_test |= E_CC;                   /* bneg will set cc */
                lval->e_flags = E_MEXPR;                /* say it's an expr */
            }
-           return 0;                           /* expr not storable */
+           return 0;                           /* expr not storable */
 
        case TOK_STAR:
            NextToken ();
@@ -1473,20 +1647,23 @@ static int hie10 (struct expent* lval)
                lval->e_const = 0;              /* Offset is zero now */
            }
            t = lval->e_tptr;
-                   if (IsPtr (t)) {
+                   if (IsClassPtr (t)) {
                        lval->e_tptr = Indirect (t);
            } else {
-               Error (ERR_ILLEGAL_INDIRECT);
+               Error ("Illegal indirection");
            }
            return 1;
 
        case TOK_AND:
            NextToken ();
            k = hie10 (lval);
-           if (k == 0) {
+           /* The & operator may be applied to any lvalue, and it may be
+            * applied to functions, even if they're no lvalues.
+            */
+           if (k == 0 && !IsTypeFunc (lval->e_tptr)) {
                /* Allow the & operator with an array */
-               if (!IsArray (lval->e_tptr)) {
-                   Error (ERR_ILLEGAL_ADDRESS);
+               if (!IsTypeArray (lval->e_tptr)) {
+                   Error ("Illegal address");
                }
            } else {
                t = TypeAlloc (TypeLen (lval->e_tptr) + 2);
@@ -1524,7 +1701,7 @@ static int hie10 (struct expent* lval)
     }
 
     k = hie11 (lval);
-    switch (curtok) {
+    switch (CurTok.Tok) {
        case TOK_INC:
                    post_incdec (lval, k, g_inc);
            return 0;
@@ -1543,7 +1720,7 @@ static int hie10 (struct expent* lval)
 static int hie_internal (GenDesc** ops,                /* List of generators */
                                 struct expent* lval,   /* parent expr's lval */
                                 int (*hienext) (struct expent*),
-                        int* UsedGen)          /* next higher level */
+                        int* UsedGen)          /* next higher level */
 /* Helper function */
 {
     int k;
@@ -1551,7 +1728,7 @@ static int hie_internal (GenDesc** ops,           /* List of generators */
     CodeMark Mark1;
     CodeMark Mark2;
     GenDesc* Gen;
-    token_t tok;                       /* The operator token */
+    token_t tok;                               /* The operator token */
     unsigned ltype, type;
     int rconst;                                /* Operand is a constant */
 
@@ -1559,18 +1736,18 @@ static int hie_internal (GenDesc** ops,         /* List of generators */
     k = hienext (lval);
 
     *UsedGen = 0;
-    while ((Gen = FindGen (curtok, ops)) != 0) {
+    while ((Gen = FindGen (CurTok.Tok, ops)) != 0) {
 
        /* Tell the caller that we handled it's ops */
        *UsedGen = 1;
 
        /* All operators that call this function expect an int on the lhs */
-       if (!IsInt (lval->e_tptr)) {
-           Error (ERR_INT_EXPR_EXPECTED);
+       if (!IsClassInt (lval->e_tptr)) {
+           Error ("Integer expression expected");
        }
 
        /* Remember the operator token, then skip it */
-               tok = curtok;
+               tok = CurTok.Tok;
        NextToken ();
 
        /* Get the lhs on stack */
@@ -1591,8 +1768,8 @@ static int hie_internal (GenDesc** ops,           /* List of generators */
        rconst = (evalexpr (CF_NONE, hienext, &lval2) == 0);
 
        /* Check the type of the rhs */
-       if (!IsInt (lval2.e_tptr)) {
-           Error (ERR_INT_EXPR_EXPECTED);
+       if (!IsClassInt (lval2.e_tptr)) {
+           Error ("Integer expression expected");
        }
 
        /* Check for const operands */
@@ -1621,9 +1798,9 @@ static int hie_internal (GenDesc** ops,           /* List of generators */
                type |= CF_CONST;
                rtype |= CF_CONST;
                if (tok == TOK_DIV && lval2.e_const == 0) {
-                   Error (ERR_DIV_BY_ZERO);
+                   Error ("Division by zero");
                } else if (tok == TOK_MOD && lval2.e_const == 0) {
-                   Error (ERR_MOD_BY_ZERO);
+                   Error ("Modulo operation with zero");
                }
                if ((Gen->Flags & GEN_NOPUSH) != 0) {
                    RemoveCode (Mark2);
@@ -1667,10 +1844,10 @@ static int hie_compare (GenDesc** ops,          /* List of generators */
 
     k = hienext (lval);
 
-    while ((Gen = FindGen (curtok, ops)) != 0) {
+    while ((Gen = FindGen (CurTok.Tok, ops)) != 0) {
 
        /* Remember the operator token, then skip it */
-               tok = curtok;
+               tok = CurTok.Tok;
        NextToken ();
 
        /* Get the lhs on stack */
@@ -1691,23 +1868,23 @@ static int hie_compare (GenDesc** ops,          /* List of generators */
        rconst = (evalexpr (CF_NONE, hienext, &lval2) == 0);
 
        /* Make sure, the types are compatible */
-       if (IsInt (lval->e_tptr)) {
-           if (!IsInt (lval2.e_tptr) && !(IsPtr(lval2.e_tptr) && IsNullPtr(lval))) {
-               Error (ERR_INCOMPATIBLE_TYPES);
+       if (IsClassInt (lval->e_tptr)) {
+           if (!IsClassInt (lval2.e_tptr) && !(IsClassPtr(lval2.e_tptr) && IsNullPtr(lval))) {
+               Error ("Incompatible types");
            }
-       } else if (IsPtr (lval->e_tptr)) {
-           if (IsPtr (lval2.e_tptr)) {
+       } else if (IsClassPtr (lval->e_tptr)) {
+           if (IsClassPtr (lval2.e_tptr)) {
                /* Both pointers are allowed in comparison if they point to
                 * the same type, or if one of them is a void pointer.
                 */
                        type* left  = Indirect (lval->e_tptr);
                type* right = Indirect (lval2.e_tptr);
-               if (!EqualTypes (left, right) && *left != T_VOID && *right != T_VOID) {
+               if (TypeCmp (left, right) < TC_EQUAL && *left != T_VOID && *right != T_VOID) {
                    /* Incomatible pointers */
-                   Error (ERR_INCOMPATIBLE_TYPES);
+                   Error ("Incompatible types");
                }
            } else if (!IsNullPtr (&lval2)) {
-               Error (ERR_INCOMPATIBLE_TYPES);
+               Error ("Incompatible types");
            }
        }
 
@@ -1743,9 +1920,9 @@ static int hie_compare (GenDesc** ops,            /* List of generators */
             * operation as char operation. Otherwise the default
             * promotions are used.
             */
-           if (IsChar (lval->e_tptr) && (IsChar (lval2.e_tptr) || rconst)) {
+           if (IsTypeChar (lval->e_tptr) && (IsTypeChar (lval2.e_tptr) || rconst)) {
                flags |= CF_CHAR;
-               if (IsUnsigned (lval->e_tptr) || IsUnsigned (lval2.e_tptr)) {
+               if (IsSignUnsigned (lval->e_tptr) || IsSignUnsigned (lval2.e_tptr)) {
                    flags |= CF_UNSIGNED;
                }
                if (rconst) {
@@ -1808,7 +1985,7 @@ static void parseadd (int k, struct expent* lval)
     flags = 0;
 
     /* Check for constness on both sides */
-    if (k == 0 && lval->e_flags == E_MCONST) {
+    if (k == 0 && (lval->e_flags & E_MCONST) != 0) {
 
        /* The left hand side is a constant. Good. Get rhs */
                if (evalexpr (CF_NONE, hie9, &lval2) == 0) {
@@ -1817,26 +1994,26 @@ static void parseadd (int k, struct expent* lval)
            rhst = lval2.e_tptr;
 
            /* Both expressions are constants. Check for pointer arithmetic */
-                   if (IsPtr (lhst) && IsInt (rhst)) {
+                   if (IsClassPtr (lhst) && IsClassInt (rhst)) {
                        /* Left is pointer, right is int, must scale rhs */
                lval->e_const = lval->e_const + lval2.e_const * PSizeOf (lhst);
                /* Result type is a pointer */
-           } else if (IsInt (lhst) && IsPtr (rhst)) {
+           } else if (IsClassInt (lhst) && IsClassPtr (rhst)) {
                /* Left is int, right is pointer, must scale lhs */
                        lval->e_const = lval->e_const * PSizeOf (rhst) + lval2.e_const;
                /* Result type is a pointer */
                lval->e_tptr = lval2.e_tptr;
-                   } else if (IsInt (lhst) && IsInt (rhst)) {
+                   } else if (IsClassInt (lhst) && IsClassInt (rhst)) {
                /* Integer addition */
                lval->e_const += lval2.e_const;
                typeadjust (lval, &lval2, 1);
            } else {
                        /* OOPS */
-               Error (ERR_OP_NOT_ALLOWED);
+               Error ("Invalid operands for binary operator `+'");
            }
 
                    /* Result is constant, condition codes not set */
-                   lval->e_test = E_MCONST;
+                   lval->e_test &= ~E_CC;
 
        } else {
 
@@ -1844,23 +2021,23 @@ static void parseadd (int k, struct expent* lval)
            rhst = lval2.e_tptr;
 
            /* Check for pointer arithmetic */
-           if (IsPtr (lhst) && IsInt (rhst)) {
+           if (IsClassPtr (lhst) && IsClassInt (rhst)) {
                /* Left is pointer, right is int, must scale rhs */
                g_scale (CF_INT, PSizeOf (lhst));
                /* Operate on pointers, result type is a pointer */
                flags = CF_PTR;
-           } else if (IsInt (lhst) && IsPtr (rhst)) {
+           } else if (IsClassInt (lhst) && IsClassPtr (rhst)) {
                /* Left is int, right is pointer, must scale lhs */
                        lval->e_const *= PSizeOf (rhst);
                /* Operate on pointers, result type is a pointer */
                flags = CF_PTR;
                lval->e_tptr = lval2.e_tptr;
-                   } else if (IsInt (lhst) && IsInt (rhst)) {
+                   } else if (IsClassInt (lhst) && IsClassInt (rhst)) {
                /* Integer addition */
                        flags = typeadjust (lval, &lval2, 1);
            } else {
                        /* OOPS */
-               Error (ERR_OP_NOT_ALLOWED);
+               Error ("Invalid operands for binary operator `+'");
                    }
 
            /* Generate code for the add */
@@ -1890,23 +2067,23 @@ static void parseadd (int k, struct expent* lval)
            pop (TypeOf (lval->e_tptr));
 
                    /* Check for pointer arithmetic */
-                   if (IsPtr (lhst) && IsInt (rhst)) {
+                   if (IsClassPtr (lhst) && IsClassInt (rhst)) {
                /* Left is pointer, right is int, must scale rhs */
                lval2.e_const *= PSizeOf (lhst);
                /* Operate on pointers, result type is a pointer */
                flags = CF_PTR;
-           } else if (IsInt (lhst) && IsPtr (rhst)) {
+           } else if (IsClassInt (lhst) && IsClassPtr (rhst)) {
                /* Left is int, right is pointer, must scale lhs (ptr only) */
                        g_scale (CF_INT | CF_CONST, PSizeOf (rhst));
                        /* Operate on pointers, result type is a pointer */
                flags = CF_PTR;
                lval->e_tptr = lval2.e_tptr;
-                   } else if (IsInt (lhst) && IsInt (rhst)) {
+                   } else if (IsClassInt (lhst) && IsClassInt (rhst)) {
                /* Integer addition */
                flags = typeadjust (lval, &lval2, 1);
                    } else {
                        /* OOPS */
-               Error (ERR_OP_NOT_ALLOWED);
+               Error ("Invalid operands for binary operator `+'");
            }
 
            /* Generate code for the add */
@@ -1922,12 +2099,12 @@ static void parseadd (int k, struct expent* lval)
            rhst = lval2.e_tptr;
 
            /* Check for pointer arithmetic */
-           if (IsPtr (lhst) && IsInt (rhst)) {
+           if (IsClassPtr (lhst) && IsClassInt (rhst)) {
                /* Left is pointer, right is int, must scale rhs */
                g_scale (CF_INT, PSizeOf (lhst));
                /* Operate on pointers, result type is a pointer */
                flags = CF_PTR;
-           } else if (IsInt (lhst) && IsPtr (rhst)) {
+           } else if (IsClassInt (lhst) && IsClassPtr (rhst)) {
                /* Left is int, right is pointer, must scale lhs */
                g_tosint (TypeOf (rhst));       /* Make sure, TOS is int */
                g_swap (CF_INT);                /* Swap TOS and primary */
@@ -1935,12 +2112,12 @@ static void parseadd (int k, struct expent* lval)
                /* Operate on pointers, result type is a pointer */
                flags = CF_PTR;
                lval->e_tptr = lval2.e_tptr;
-                   } else if (IsInt (lhst) && IsInt (rhst)) {
+                   } else if (IsClassInt (lhst) && IsClassInt (rhst)) {
                /* Integer addition */
                        flags = typeadjust (lval, &lval2, 0);
            } else {
                        /* OOPS */
-               Error (ERR_OP_NOT_ALLOWED);
+               Error ("Invalid operands for binary operator `+'");
            }
 
            /* Generate code for the add */
@@ -1968,7 +2145,7 @@ static void parsesub (int k, struct expent* lval)
     type* lhst;                        /* Type of left hand side */
     type* rhst;                        /* Type of right hand side */
     CodeMark Mark1;            /* Save position of output queue */
-    CodeMark Mark2;            /* Another position in the queue */
+    CodeMark Mark2;                    /* Another position in the queue */
     int rscale;                /* Scale factor for the result */
 
 
@@ -1993,37 +2170,37 @@ static void parsesub (int k, struct expent* lval)
                rhst = lval2.e_tptr;
 
        /* Check left hand side */
-       if (k == 0 && lval->e_flags & E_MCONST) {
+       if (k == 0 && (lval->e_flags & E_MCONST) != 0) {
 
            /* Both sides are constant, remove generated code */
            RemoveCode (Mark1);
            pop (TypeOf (lhst));        /* Clean up the stack */
 
            /* Check for pointer arithmetic */
-           if (IsPtr (lhst) && IsInt (rhst)) {
+           if (IsClassPtr (lhst) && IsClassInt (rhst)) {
                /* Left is pointer, right is int, must scale rhs */
                lval->e_const -= lval2.e_const * PSizeOf (lhst);
                /* Operate on pointers, result type is a pointer */
-           } else if (IsPtr (lhst) && IsPtr (rhst)) {
+           } else if (IsClassPtr (lhst) && IsClassPtr (rhst)) {
                /* Left is pointer, right is pointer, must scale result */
-               if (TypeCmp (Indirect (lhst), Indirect (rhst)) != 0) {
-                   Error (ERR_INCOMPATIBLE_POINTERS);
+               if (TypeCmp (Indirect (lhst), Indirect (rhst)) < TC_EQUAL) {
+                   Error ("Incompatible pointer types");
                } else {
                    lval->e_const = (lval->e_const - lval2.e_const) / PSizeOf (lhst);
                }
                /* Operate on pointers, result type is an integer */
                lval->e_tptr = type_int;
-           } else if (IsInt (lhst) && IsInt (rhst)) {
+           } else if (IsClassInt (lhst) && IsClassInt (rhst)) {
                /* Integer subtraction */
                        typeadjust (lval, &lval2, 1);
                lval->e_const -= lval2.e_const;
            } else {
                /* OOPS */
-               Error (ERR_OP_NOT_ALLOWED);
+               Error ("Invalid operands for binary operator `-'");
            }
 
            /* Result is constant, condition codes not set */
-           lval->e_flags = E_MCONST;
+           /* lval->e_flags = E_MCONST; ### */
            lval->e_test &= ~E_CC;
 
        } else {
@@ -2034,27 +2211,27 @@ static void parsesub (int k, struct expent* lval)
            RemoveCode (Mark2);
            pop (TypeOf (lhst));
 
-           if (IsPtr (lhst) && IsInt (rhst)) {
+           if (IsClassPtr (lhst) && IsClassInt (rhst)) {
                /* Left is pointer, right is int, must scale rhs */
                        lval2.e_const *= PSizeOf (lhst);
                /* Operate on pointers, result type is a pointer */
                flags = CF_PTR;
-           } else if (IsPtr (lhst) && IsPtr (rhst)) {
+           } else if (IsClassPtr (lhst) && IsClassPtr (rhst)) {
                /* Left is pointer, right is pointer, must scale result */
-               if (TypeCmp (Indirect (lhst), Indirect (rhst)) != 0) {
-                   Error (ERR_INCOMPATIBLE_POINTERS);
+               if (TypeCmp (Indirect (lhst), Indirect (rhst)) < TC_EQUAL) {
+                   Error ("Incompatible pointer types");
                } else {
                    rscale = PSizeOf (lhst);
                }
                /* Operate on pointers, result type is an integer */
                flags = CF_PTR;
                lval->e_tptr = type_int;
-           } else if (IsInt (lhst) && IsInt (rhst)) {
+           } else if (IsClassInt (lhst) && IsClassInt (rhst)) {
                /* Integer subtraction */
                        flags = typeadjust (lval, &lval2, 1);
            } else {
                /* OOPS */
-               Error (ERR_OP_NOT_ALLOWED);
+               Error ("Invalid operands for binary operator `-'");
            }
 
            /* Do the subtraction */
@@ -2077,22 +2254,22 @@ static void parsesub (int k, struct expent* lval)
        rhst = lval2.e_tptr;
 
                /* Check for pointer arithmetic */
-       if (IsPtr (lhst) && IsInt (rhst)) {
+       if (IsClassPtr (lhst) && IsClassInt (rhst)) {
            /* Left is pointer, right is int, must scale rhs */
            g_scale (CF_INT, PSizeOf (lhst));
            /* Operate on pointers, result type is a pointer */
            flags = CF_PTR;
-       } else if (IsPtr (lhst) && IsPtr (rhst)) {
+       } else if (IsClassPtr (lhst) && IsClassPtr (rhst)) {
            /* Left is pointer, right is pointer, must scale result */
-           if (TypeCmp (Indirect (lhst), Indirect (rhst)) != 0) {
-               Error (ERR_INCOMPATIBLE_POINTERS);
+           if (TypeCmp (Indirect (lhst), Indirect (rhst)) < TC_EQUAL) {
+               Error ("Incompatible pointer types");
            } else {
                rscale = PSizeOf (lhst);
            }
            /* Operate on pointers, result type is an integer */
            flags = CF_PTR;
            lval->e_tptr = type_int;
-       } else if (IsInt (lhst) && IsInt (rhst)) {
+       } else if (IsClassInt (lhst) && IsClassInt (rhst)) {
            /* Integer subtraction. If the left hand side descriptor says that
             * the lhs is const, we have to remove this mark, since this is no
             * longer true, lhs is on stack instead.
@@ -2104,7 +2281,7 @@ static void parsesub (int k, struct expent* lval)
            flags = typeadjust (lval, &lval2, 0);
        } else {
            /* OOPS */
-           Error (ERR_OP_NOT_ALLOWED);
+           Error ("Invalid operands for binary operator `-'");
        }
 
        /* Generate code for the sub (the & is a hack here) */
@@ -2127,9 +2304,9 @@ static int hie8 (struct expent* lval)
 /* Process + and - binary operators. */
 {
     int k = hie9 (lval);
-    while (curtok == TOK_PLUS || curtok == TOK_MINUS) {
+    while (CurTok.Tok == TOK_PLUS || CurTok.Tok == TOK_MINUS) {
 
-               if (curtok == TOK_PLUS) {
+               if (CurTok.Tok == TOK_PLUS) {
                    parseadd (k, lval);
                } else {
                    parsesub (k, lval);
@@ -2223,13 +2400,13 @@ static int hieAnd (struct expent* lval, unsigned TrueLab, int* BoolOp)
     struct expent lval2;
 
     k = hie2 (lval);
-    if (curtok == TOK_BOOL_AND) {
+    if (CurTok.Tok == TOK_BOOL_AND) {
 
                /* Tell our caller that we're evaluating a boolean */
                *BoolOp = 1;
 
                /* Get a label that we will use for false expressions */
-               lab = GetLabel ();
+               lab = GetLocalLabel ();
 
                /* If the expr hasn't set condition codes, set the force-test flag */
                if ((lval->e_test & E_CC) == 0) {
@@ -2243,7 +2420,7 @@ static int hieAnd (struct expent* lval, unsigned TrueLab, int* BoolOp)
                g_falsejump (CF_NONE, lab);
 
                /* Parse more boolean and's */
-               while (curtok == TOK_BOOL_AND) {
+               while (CurTok.Tok == TOK_BOOL_AND) {
 
                    /* Skip the && */
            NextToken ();
@@ -2256,7 +2433,7 @@ static int hieAnd (struct expent* lval, unsigned TrueLab, int* BoolOp)
            exprhs (CF_FORCECHAR, k, &lval2);
 
                    /* Do short circuit evaluation */
-           if (curtok == TOK_BOOL_AND) {
+           if (CurTok.Tok == TOK_BOOL_AND) {
                g_falsejump (CF_NONE, lab);
                    } else {
                        /* Last expression - will evaluate to true */
@@ -2265,7 +2442,7 @@ static int hieAnd (struct expent* lval, unsigned TrueLab, int* BoolOp)
                }
 
                /* Define the false jump label here */
-               g_defloclabel (lab);
+               g_defcodelabel (lab);
 
                /* Define the label */
                lval->e_flags = E_MEXPR;
@@ -2288,13 +2465,13 @@ static int hieOr (struct expent *lval)
     unsigned DoneLab;
 
     /* Get a label */
-    TrueLab = GetLabel ();
+    TrueLab = GetLocalLabel ();
 
     /* Call the next level parser */
     k = hieAnd (lval, TrueLab, &BoolOp);
 
     /* Any boolean or's? */
-    if (curtok == TOK_BOOL_OR) {
+    if (CurTok.Tok == TOK_BOOL_OR) {
 
        /* If the expr hasn't set condition codes, set the force-test flag */
                if ((lval->e_test & E_CC) == 0) {
@@ -2315,7 +2492,7 @@ static int hieOr (struct expent *lval)
        BoolOp = 1;
 
        /* while there's more expr */
-               while (curtok == TOK_BOOL_OR) {
+               while (CurTok.Tok == TOK_BOOL_OR) {
 
                    /* skip the || */
            NextToken ();
@@ -2334,7 +2511,7 @@ static int hieOr (struct expent *lval)
             */
 #if    0
 /* Seems this sometimes generates wrong code */
-           if (curtok == TOK_BOOL_OR && !AndOp) {
+           if (CurTok.Tok == TOK_BOOL_OR && !AndOp) {
                g_truejump (CF_NONE, TrueLab);
                    }
 #else
@@ -2348,12 +2525,12 @@ static int hieOr (struct expent *lval)
 
     /* If we really had boolean ops, generate the end sequence */
     if (BoolOp) {
-       DoneLab = GetLabel ();
+       DoneLab = GetLocalLabel ();
        g_getimmed (CF_INT | CF_CONST, 0, 0);   /* Load FALSE */
                g_falsejump (CF_NONE, DoneLab);
-       g_defloclabel (TrueLab);
+       g_defcodelabel (TrueLab);
        g_getimmed (CF_INT | CF_CONST, 1, 0);   /* Load TRUE */
-       g_defloclabel (DoneLab);
+       g_defcodelabel (DoneLab);
     }
     return k;
 }
@@ -2377,22 +2554,22 @@ static int hieQuest (struct expent *lval)
 
 
     k = hieOr (lval);
-    if (curtok == TOK_QUEST) {
+    if (CurTok.Tok == TOK_QUEST) {
        NextToken ();
        if ((lval->e_test & E_CC) == 0) {
            /* Condition codes not set, force a test */
            lval->e_test |= E_FORCETEST;
        }
        exprhs (CF_NONE, k, lval);
-       labf = GetLabel ();
+       labf = GetLocalLabel ();
        g_falsejump (CF_NONE, labf);
 
        /* Parse second and third expression */
        expression1 (&lval2);
-       labt = GetLabel ();
+       labt = GetLocalLabel ();
        ConsumeColon ();
        g_jump (labt);
-       g_defloclabel (labf);
+       g_defcodelabel (labf);
        expression1 (&lval3);
 
        /* Check if any conversions are needed, if so, do them.
@@ -2408,7 +2585,7 @@ static int hieQuest (struct expent *lval)
         */
        type2 = lval2.e_tptr;
        type3 = lval3.e_tptr;
-       if (IsInt (type2) && IsInt (type3)) {
+       if (IsClassInt (type2) && IsClassInt (type3)) {
 
            /* Get common type */
            rtype = promoteint (type2, type3);
@@ -2419,49 +2596,42 @@ static int hieQuest (struct expent *lval)
            /* Setup a new label so that the expr3 code will jump around
             * the type cast code for expr2.
             */
-                   labf = GetLabel ();         /* Get new label */
+                   labf = GetLocalLabel ();    /* Get new label */
            Mark1 = GetCodePos ();      /* Remember current position */
            g_jump (labf);              /* Jump around code */
 
            /* The jump for expr2 goes here */
-           g_defloclabel (labt);
+           g_defcodelabel (labt);
 
            /* Create the typecast code for expr2 */
            Mark2 = GetCodePos ();      /* Remember position */
            g_typecast (TypeOf (rtype), TypeOf (type2));
 
-           /* If the typecast did not produce code, remove the jump,
-            * otherwise output the label.
-            */
-           if (GetCodePos() == Mark2) {
-               RemoveCode (Mark1);     /* Remove code */
-           } else {
-               /* We have typecast code, output label */
-               g_defloclabel (labf);
-               labt = 0;               /* Mark other label as invalid */
-           }
+           /* Jump here around the typecase code. */
+           g_defcodelabel (labf);
+           labt = 0;           /* Mark other label as invalid */
 
-       } else if (IsPtr (type2) && IsPtr (type3)) {
+       } else if (IsClassPtr (type2) && IsClassPtr (type3)) {
            /* Must point to same type */
-           if (TypeCmp (Indirect (type2), Indirect (type3)) != 0) {
-               Error (ERR_INCOMPATIBLE_TYPES);
+           if (TypeCmp (Indirect (type2), Indirect (type3)) < TC_EQUAL) {
+               Error ("Incompatible pointer types");
            }
            /* Result has the common type */
            rtype = lval2.e_tptr;
-       } else if (IsPtr (type2) && IsNullPtr (&lval3)) {
+       } else if (IsClassPtr (type2) && IsNullPtr (&lval3)) {
            /* Result type is pointer, no cast needed */
            rtype = lval2.e_tptr;
-       } else if (IsNullPtr (&lval2) && IsPtr (type3)) {
+       } else if (IsNullPtr (&lval2) && IsClassPtr (type3)) {
            /* Result type is pointer, no cast needed */
            rtype = lval3.e_tptr;
        } else {
-           Error (ERR_INCOMPATIBLE_TYPES);
+           Error ("Incompatible types");
            rtype = lval2.e_tptr;               /* Doesn't matter here */
        }
 
        /* If we don't have the label defined until now, do it */
        if (labt) {
-           g_defloclabel (labt);
+           g_defcodelabel (labt);
        }
 
        /* Setup the target expression */
@@ -2484,7 +2654,7 @@ static void opeq (GenDesc* Gen, struct expent *lval, int k)
 
     NextToken ();
     if (k == 0) {
-       Error (ERR_LVALUE_EXPECTED);
+       Error ("Invalid lvalue in assignment");
        return;
     }
 
@@ -2564,7 +2734,7 @@ static void addsubeq (GenDesc* Gen, struct expent *lval, int k)
 
 
     if (k == 0) {
-       Error (ERR_LVALUE_EXPECTED);
+       Error ("Invalid lvalue in assignment");
        return;
     }
 
@@ -2655,11 +2825,16 @@ static void Assignment (struct expent* lval)
     unsigned flags;
     type* ltype = lval->e_tptr;
 
+    /* Check for assignment to const */
+    if (IsQualConst (ltype)) {
+       Error ("Assignment to const");
+    }
+
     /* cc65 does not have full support for handling structs by value. Since
      * assigning structs is one of the more useful operations from this
-     * familiy, allow it here.
+     * family, allow it here.
      */
-    if (IsStruct (ltype)) {
+    if (IsClassStruct (ltype)) {
 
                /* Bring the address of the lhs into the primary and push it */
        exprhs (0, 0, lval);
@@ -2672,15 +2847,15 @@ static void Assignment (struct expent* lval)
            exprhs (0, 0, &lval2);
        } else {
            /* We need an lvalue */
-           Error (ERR_LVALUE_EXPECTED);
+           Error ("Invalid lvalue in assignment");
        }
 
        /* Push the address (or whatever is in ax in case of errors) */
        g_push (CF_PTR | CF_UNSIGNED, 0);
 
        /* Check for equality of the structs */
-       if (!EqualTypes (ltype, lval2.e_tptr)) {
-           Error (ERR_INCOMPATIBLE_TYPES);
+       if (TypeCmp (ltype, lval2.e_tptr) < TC_EQUAL) {
+           Error ("Incompatible types");
        }
 
        /* Load the size of the struct into the primary */
@@ -2725,7 +2900,7 @@ int hie1 (struct expent* lval)
     int k;
 
     k = hieQuest (lval);
-    switch (curtok) {
+    switch (CurTok.Tok) {
 
        case TOK_RPAREN:
        case TOK_SEMI:
@@ -2734,7 +2909,7 @@ int hie1 (struct expent* lval)
        case TOK_ASSIGN:
            NextToken ();
            if (k == 0) {
-               Error (ERR_LVALUE_EXPECTED);
+               Error ("Invalid lvalue in assignment");
            } else {
                Assignment (lval);
            }
@@ -2794,9 +2969,9 @@ int hie0 (struct expent *lval)
     int k;
 
     k = hie1 (lval);
-    while (curtok == TOK_COMMA) {
+    while (CurTok.Tok == TOK_COMMA) {
        NextToken ();
-       k = hie1 (lval);
+       k = hie1 (lval);
     }
     return k;
 }
@@ -2815,10 +2990,10 @@ int evalexpr (unsigned flags, int (*f) (struct expent*), struct expent* lval)
     /* Evaluate */
     k = f (lval);
     if (k == 0 && lval->e_flags == E_MCONST) {
-       /* Constant expression */
-       return 0;
+       /* Constant expression */
+       return 0;
     } else {
-       /* Not constant, load into the primary */
+       /* Not constant, load into the primary */
         exprhs (flags, k, lval);
        return 1;
     }
@@ -2826,7 +3001,7 @@ int evalexpr (unsigned flags, int (*f) (struct expent*), struct expent* lval)
 
 
 
-int expr (int (*func) (), struct expent *lval)
+int expr (int (*func) (struct expent*), struct expent *lval)
 /* Expression parser; func is either hie0 or hie1. */
 {
     int k;
@@ -2874,7 +3049,7 @@ void constexpr (struct expent* lval)
 {
     memset (lval, 0, sizeof (*lval));
     if (expr (hie1, lval) != 0 || (lval->e_flags & E_MCONST) == 0) {
-       Error (ERR_CONST_EXPR_EXPECTED);
+       Error ("Constant expression expected");
        /* To avoid any compiler errors, make the expression a valid const */
        lval->e_flags = E_MCONST;
        lval->e_tptr = type_int;
@@ -2888,8 +3063,8 @@ void intexpr (struct expent* lval)
 /* Get an integer expression */
 {
     expression (lval);
-    if (!IsInt (lval->e_tptr)) {
-       Error (ERR_INT_EXPR_EXPECTED);
+    if (!IsClassInt (lval->e_tptr)) {
+       Error ("Integer expression expected");
        /* To avoid any compiler errors, make the expression a valid int */
        lval->e_flags = E_MCONST;
        lval->e_tptr = type_int;
@@ -2906,11 +3081,10 @@ void boolexpr (struct expent* lval)
     expression (lval);
 
     /* If it's an integer, it's ok. If it's not an integer, but a pointer,
-     * the pointer used in a boolean context is also ok (Ootherwise check if it's a pointer
-     * expression.
+     * the pointer used in a boolean context is also ok
      */
-    if (!IsInt (lval->e_tptr) && !IsPtr (lval->e_tptr)) {
-       Error (ERR_INT_EXPR_EXPECTED);
+    if (!IsClassInt (lval->e_tptr) && !IsClassPtr (lval->e_tptr)) {
+       Error ("Boolean expression expected");
        /* To avoid any compiler errors, make the expression a valid int */
        lval->e_flags = E_MCONST;
        lval->e_tptr = type_int;
@@ -2931,7 +3105,6 @@ void test (unsigned label, int cond)
 
     /* Prepare the expression, setup labels */
     memset (&lval, 0, sizeof (lval));
-    lval.e_test = E_TEST;
 
     /* Generate code to eval the expr */
     k = expr (hie0, &lval);
@@ -2939,7 +3112,7 @@ void test (unsigned label, int cond)
        /* Constant rvalue */
                if (cond == 0 && lval.e_const == 0) {
            g_jump (label);
-           Warning (WARN_UNREACHABLE_CODE);
+           Warning ("Unreachable code");
        } else if (cond && lval.e_const) {
            g_jump (label);
        }
@@ -2955,9 +3128,6 @@ void test (unsigned label, int cond)
     /* Load the value into the primary register */
     exprhs (CF_FORCECHAR, k, &lval);
 
-    /* Check for the closing brace */
-    ConsumeRParen ();
-
     /* Generate the jump */
     if (cond) {
        g_truejump (CF_NONE, label);
@@ -2966,10 +3136,13 @@ void test (unsigned label, int cond)
         * compiler itself is one big hack...): If a semicolon follows, we
         * don't have a statement and may omit the jump.
         */
-       if (curtok != TOK_SEMI) {
+       if (CurTok.Tok != TOK_SEMI) {
             g_falsejump (CF_NONE, label);
        }
     }
+
+    /* Check for the closing brace */
+    ConsumeRParen ();
 }