]> git.sur5r.net Git - cc65/blobdiff - src/cc65/expr.c
Fixed multi line macro bug
[cc65] / src / cc65 / expr.c
index b7bd14ac2d16867df42a6f947376f98ec0226c9a..276215f7418617bcd7a9695cbf99f5d19121d30f 100644 (file)
@@ -198,8 +198,13 @@ 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;
@@ -209,19 +214,19 @@ unsigned assignadjust (type* lhst, struct expent* rhs)
        /* If one of the sides are of type void, output a more apropriate
         * error message.
         */
-               Error (ERR_ILLEGAL_TYPE);
+               Error ("Illegal type");
     } else if (IsClassInt (lhst)) {
                if (IsClassPtr (rhst)) {
            /* Pointer -> int conversion */
            Warning ("Converting pointer to integer without a cast");
                } else if (!IsClassInt (rhst)) {
-           Error (ERR_INCOMPATIBLE_TYPES);                        
+           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);
@@ -238,11 +243,11 @@ unsigned assignadjust (type* lhst, struct expent* rhs)
                switch (TypeCmp (lhst, rhst)) {
 
                    case TC_INCOMPATIBLE:
-                       Error (ERR_INCOMPATIBLE_POINTERS);
+                       Error ("Incompatible pointer types");
                        break;
 
                    case TC_QUAL_DIFF:
-                       Error (ERR_QUAL_DIFF);
+                       Error ("Pointer types differ in type qualifiers");
                        break;
 
                    default:
@@ -252,7 +257,7 @@ unsigned assignadjust (type* lhst, struct expent* rhs)
            }
        } 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) {
+           if (rhs->e_flags != E_MCONST || rhs->e_const != 0) {
                Warning ("Converting integer to pointer without a cast");
            }
        } else if (IsTypeFuncPtr (lhst) && IsTypeFunc(rhst)) {
@@ -260,13 +265,13 @@ unsigned assignadjust (type* lhst, struct expent* rhs)
             * that both functions have the same parameter list.
             */
            if (TypeCmp (Indirect (lhst), rhst) < TC_EQUAL) {
-               Error (ERR_INCOMPATIBLE_TYPES);
+               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 */
@@ -292,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 */
 
@@ -304,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:
@@ -333,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 */
 
@@ -347,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:
@@ -387,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);
@@ -426,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)));
 }
 
 
@@ -497,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;
@@ -505,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.
@@ -583,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;
        }
@@ -594,14 +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) {
@@ -610,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 */
@@ -647,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);
     }
 }
 
@@ -666,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 */
@@ -698,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;
     }
@@ -709,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);
@@ -722,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;
@@ -747,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;
@@ -762,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 */
@@ -772,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)) {
@@ -810,7 +914,7 @@ 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.
@@ -830,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;
@@ -855,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;
@@ -865,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;
@@ -973,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,
@@ -1023,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
@@ -1115,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;
     }
@@ -1126,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;
     }
@@ -1159,19 +1263,19 @@ 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 ();
@@ -1183,26 +1287,26 @@ static int hie11 (struct expent *lval)
                    ++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 (!IsClassStruct (lval->e_tptr)) {
-               Error (ERR_STRUCT_EXPECTED);
+               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);
 
@@ -1233,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) {
@@ -1260,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;
     }
 
@@ -1294,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");
@@ -1339,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;
     }
 
@@ -1378,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);
@@ -1424,7 +1529,12 @@ static int typecast (struct expent* lval)
     /* Read the expression we have to cast */
     k = hie10 (lval);
 
-    /* Check for a const expression */
+    /* If the expression is a function, treat it as pointer-to-function */
+    if (IsTypeFunc (lval->e_tptr)) {
+       lval->e_tptr = PointerTo (lval->e_tptr);
+    }
+
+    /* 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,
@@ -1446,17 +1556,17 @@ static int typecast (struct expent* lval)
                /* 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);
-               }
+               /* 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 */
+               /* 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);
+                       lval->e_const |= ((~0L) << OldBits);
                    }
                }
            }
@@ -1469,18 +1579,18 @@ static int typecast (struct expent* lval)
 
            /* 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 teh value in the primary register.
+            * 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);
+               /* 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));
+               /* 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;
+               /* Value is now in primary */
+               lval->e_flags = E_MEXPR;
                        k = 0;
            }
        }
@@ -1501,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);
@@ -1514,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:
@@ -1527,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 ();
@@ -1540,17 +1650,20 @@ static int hie10 (struct expent* lval)
                    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 (!IsTypeArray (lval->e_tptr)) {
-                   Error (ERR_ILLEGAL_ADDRESS);
+                   Error ("Illegal address");
                }
            } else {
                t = TypeAlloc (TypeLen (lval->e_tptr) + 2);
@@ -1588,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;
@@ -1607,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;
@@ -1615,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 */
 
@@ -1623,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 (!IsClassInt (lval->e_tptr)) {
-           Error (ERR_INT_EXPR_EXPECTED);
+           Error ("Integer expression expected");
        }
 
        /* Remember the operator token, then skip it */
-               tok = curtok;
+               tok = CurTok.Tok;
        NextToken ();
 
        /* Get the lhs on stack */
@@ -1656,7 +1769,7 @@ static int hie_internal (GenDesc** ops,           /* List of generators */
 
        /* Check the type of the rhs */
        if (!IsClassInt (lval2.e_tptr)) {
-           Error (ERR_INT_EXPR_EXPECTED);
+           Error ("Integer expression expected");
        }
 
        /* Check for const operands */
@@ -1685,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);
@@ -1731,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 */
@@ -1757,7 +1870,7 @@ static int hie_compare (GenDesc** ops,            /* List of generators */
        /* Make sure, the types are compatible */
        if (IsClassInt (lval->e_tptr)) {
            if (!IsClassInt (lval2.e_tptr) && !(IsClassPtr(lval2.e_tptr) && IsNullPtr(lval))) {
-               Error (ERR_INCOMPATIBLE_TYPES);
+               Error ("Incompatible types");
            }
        } else if (IsClassPtr (lval->e_tptr)) {
            if (IsClassPtr (lval2.e_tptr)) {
@@ -1768,10 +1881,10 @@ static int hie_compare (GenDesc** ops,          /* List of generators */
                type* right = Indirect (lval2.e_tptr);
                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");
            }
        }
 
@@ -1872,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) {
@@ -1896,11 +2009,11 @@ static void parseadd (int k, struct expent* lval)
                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 {
 
@@ -1924,7 +2037,7 @@ static void parseadd (int k, struct expent* lval)
                        flags = typeadjust (lval, &lval2, 1);
            } else {
                        /* OOPS */
-               Error (ERR_OP_NOT_ALLOWED);
+               Error ("Invalid operands for binary operator `+'");
                    }
 
            /* Generate code for the add */
@@ -1970,7 +2083,7 @@ static void parseadd (int k, struct expent* lval)
                flags = typeadjust (lval, &lval2, 1);
                    } else {
                        /* OOPS */
-               Error (ERR_OP_NOT_ALLOWED);
+               Error ("Invalid operands for binary operator `+'");
            }
 
            /* Generate code for the add */
@@ -2004,7 +2117,7 @@ static void parseadd (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 add */
@@ -2032,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 */
 
 
@@ -2057,7 +2170,7 @@ 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);
@@ -2071,7 +2184,7 @@ static void parsesub (int k, struct expent* lval)
            } else if (IsClassPtr (lhst) && IsClassPtr (rhst)) {
                /* Left is pointer, right is pointer, must scale result */
                if (TypeCmp (Indirect (lhst), Indirect (rhst)) < TC_EQUAL) {
-                   Error (ERR_INCOMPATIBLE_POINTERS);
+                   Error ("Incompatible pointer types");
                } else {
                    lval->e_const = (lval->e_const - lval2.e_const) / PSizeOf (lhst);
                }
@@ -2083,11 +2196,11 @@ static void parsesub (int k, struct expent* lval)
                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 {
@@ -2106,7 +2219,7 @@ static void parsesub (int k, struct expent* lval)
            } else if (IsClassPtr (lhst) && IsClassPtr (rhst)) {
                /* Left is pointer, right is pointer, must scale result */
                if (TypeCmp (Indirect (lhst), Indirect (rhst)) < TC_EQUAL) {
-                   Error (ERR_INCOMPATIBLE_POINTERS);
+                   Error ("Incompatible pointer types");
                } else {
                    rscale = PSizeOf (lhst);
                }
@@ -2118,7 +2231,7 @@ static void parsesub (int k, struct expent* lval)
                        flags = typeadjust (lval, &lval2, 1);
            } else {
                /* OOPS */
-               Error (ERR_OP_NOT_ALLOWED);
+               Error ("Invalid operands for binary operator `-'");
            }
 
            /* Do the subtraction */
@@ -2149,7 +2262,7 @@ static void parsesub (int k, struct expent* lval)
        } else if (IsClassPtr (lhst) && IsClassPtr (rhst)) {
            /* Left is pointer, right is pointer, must scale result */
            if (TypeCmp (Indirect (lhst), Indirect (rhst)) < TC_EQUAL) {
-               Error (ERR_INCOMPATIBLE_POINTERS);
+               Error ("Incompatible pointer types");
            } else {
                rscale = PSizeOf (lhst);
            }
@@ -2168,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) */
@@ -2191,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);
@@ -2287,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) {
@@ -2307,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 ();
@@ -2320,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 */
@@ -2329,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;
@@ -2352,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) {
@@ -2379,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 ();
@@ -2398,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
@@ -2412,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;
 }
@@ -2441,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.
@@ -2483,32 +2596,25 @@ 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 (IsClassPtr (type2) && IsClassPtr (type3)) {
            /* Must point to same type */
            if (TypeCmp (Indirect (type2), Indirect (type3)) < TC_EQUAL) {
-               Error (ERR_INCOMPATIBLE_TYPES);
+               Error ("Incompatible pointer types");
            }
            /* Result has the common type */
            rtype = lval2.e_tptr;
@@ -2519,13 +2625,13 @@ static int hieQuest (struct expent *lval)
            /* 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 */
@@ -2548,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;
     }
 
@@ -2628,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;
     }
 
@@ -2721,12 +2827,12 @@ static void Assignment (struct expent* lval)
 
     /* Check for assignment to const */
     if (IsQualConst (ltype)) {
-       Error (ERR_CONST_ASSIGN);
+       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 (IsClassStruct (ltype)) {
 
@@ -2741,7 +2847,7 @@ 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) */
@@ -2749,7 +2855,7 @@ static void Assignment (struct expent* lval)
 
        /* Check for equality of the structs */
        if (TypeCmp (ltype, lval2.e_tptr) < TC_EQUAL) {
-           Error (ERR_INCOMPATIBLE_TYPES);
+           Error ("Incompatible types");
        }
 
        /* Load the size of the struct into the primary */
@@ -2794,7 +2900,7 @@ int hie1 (struct expent* lval)
     int k;
 
     k = hieQuest (lval);
-    switch (curtok) {
+    switch (CurTok.Tok) {
 
        case TOK_RPAREN:
        case TOK_SEMI:
@@ -2803,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);
            }
@@ -2863,7 +2969,7 @@ int hie0 (struct expent *lval)
     int k;
 
     k = hie1 (lval);
-    while (curtok == TOK_COMMA) {
+    while (CurTok.Tok == TOK_COMMA) {
        NextToken ();
        k = hie1 (lval);
     }
@@ -2895,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;
@@ -2943,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;
@@ -2958,7 +3064,7 @@ void intexpr (struct expent* lval)
 {
     expression (lval);
     if (!IsClassInt (lval->e_tptr)) {
-       Error (ERR_INT_EXPR_EXPECTED);
+       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;
@@ -2975,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 (!IsClassInt (lval->e_tptr) && !IsClassPtr (lval->e_tptr)) {
-       Error (ERR_INT_EXPR_EXPECTED);
+       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;
@@ -3000,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);
@@ -3024,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);
@@ -3035,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 ();
 }