]> git.sur5r.net Git - cc65/blobdiff - src/cc65/expr.c
Fixed multi line macro bug
[cc65] / src / cc65 / expr.c
index 5d59e0b96ccc5e94fd50704df99cbceda95b4136..276215f7418617bcd7a9695cbf99f5d19121d30f 100644 (file)
@@ -226,7 +226,7 @@ unsigned assignadjust (type* lhst, struct expent* rhs)
             * 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);
@@ -257,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)) {
@@ -309,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:
@@ -352,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:
@@ -431,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)));
 }
 
 
@@ -502,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;
@@ -510,68 +508,89 @@ 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 ("Too many arguments in function call");
            }
@@ -588,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;
        }
@@ -599,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) {
@@ -615,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 ("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 */
@@ -652,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);
     }
 }
 
@@ -671,18 +744,35 @@ void doasm (void)
     ConsumeLParen ();
 
     /* String literal */
-    if (curtok != TOK_SCONST) {
+    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 */
@@ -703,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;
     }
@@ -714,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);
@@ -734,7 +824,7 @@ static int primary (struct expent* lval)
     }
 
     /* Identifier? */
-    if (curtok == TOK_IDENT) {
+    if (CurTok.Tok == TOK_IDENT) {
 
        SymEntry* Sym;
        ident Ident;
@@ -764,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 */
@@ -774,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)) {
@@ -812,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.
@@ -839,16 +941,16 @@ static int primary (struct expent* lval)
     }
 
     /* 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;
@@ -857,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;
@@ -1117,7 +1219,7 @@ static int structref (int k, struct expent* lval)
 
     /* Skip the token and check for an identifier */
     NextToken ();
-    if (curtok != TOK_IDENT) {
+    if (CurTok.Tok != TOK_IDENT) {
        Error ("Identifier expected");
        lval->e_tptr = type_int;
        return 0;
@@ -1161,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 ();
@@ -1185,7 +1287,7 @@ 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 {
@@ -1193,14 +1295,14 @@ static int hie11 (struct expent *lval)
            }
            k = 0;
 
-       } else if (curtok == TOK_DOT) {
+       } else if (CurTok.Tok == TOK_DOT) {
 
            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) {
@@ -1235,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) {
@@ -1381,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);
@@ -1509,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);
@@ -1522,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:
@@ -1599,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;
@@ -1634,7 +1736,7 @@ 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;
@@ -1645,7 +1747,7 @@ static int hie_internal (GenDesc** ops,           /* List of generators */
        }
 
        /* Remember the operator token, then skip it */
-               tok = curtok;
+               tok = CurTok.Tok;
        NextToken ();
 
        /* Get the lhs on stack */
@@ -1742,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 */
@@ -1883,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) {
@@ -1911,7 +2013,7 @@ static void parseadd (int k, struct expent* lval)
            }
 
                    /* Result is constant, condition codes not set */
-                   lval->e_test = E_MCONST;
+                   lval->e_test &= ~E_CC;
 
        } else {
 
@@ -2068,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);
@@ -2098,7 +2200,7 @@ static void parsesub (int k, struct expent* lval)
            }
 
            /* Result is constant, condition codes not set */
-           lval->e_flags = E_MCONST;
+           /* lval->e_flags = E_MCONST; ### */
            lval->e_test &= ~E_CC;
 
        } else {
@@ -2202,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);
@@ -2298,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) {
@@ -2318,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 ();
@@ -2331,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 */
@@ -2340,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;
@@ -2363,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) {
@@ -2390,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 ();
@@ -2409,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
@@ -2423,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;
 }
@@ -2452,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.
@@ -2494,27 +2596,20 @@ 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 */
@@ -2536,7 +2631,7 @@ static int hieQuest (struct expent *lval)
 
        /* If we don't have the label defined until now, do it */
        if (labt) {
-           g_defloclabel (labt);
+           g_defcodelabel (labt);
        }
 
        /* Setup the target expression */
@@ -2737,7 +2832,7 @@ static void Assignment (struct expent* lval)
 
     /* 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)) {
 
@@ -2805,7 +2900,7 @@ int hie1 (struct expent* lval)
     int k;
 
     k = hieQuest (lval);
-    switch (curtok) {
+    switch (CurTok.Tok) {
 
        case TOK_RPAREN:
        case TOK_SEMI:
@@ -2874,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);
     }
@@ -2906,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;
@@ -3033,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);
@@ -3044,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 ();
 }