X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fcc65%2Fexpr.c;h=92d6013d80c678e0bc59d5f5a24fe1940906f87a;hb=98da4b581175232d89630f5c19f22e37a7588c7b;hp=3142ad93b898e80f9ca69be79b924bc8a7d8b9bf;hpb=5548b6fd56c8dc5a203804ce63db9649aab37abb;p=cc65 diff --git a/src/cc65/expr.c b/src/cc65/expr.c index 3142ad93b..92d6013d8 100644 --- a/src/cc65/expr.c +++ b/src/cc65/expr.c @@ -8,18 +8,18 @@ #include #include -#include /* common */ #include "check.h" +#include "debugflag.h" #include "xmalloc.h" /* cc65 */ #include "asmcode.h" #include "asmlabel.h" #include "asmstmt.h" +#include "assignment.h" #include "codegen.h" -#include "datatype.h" #include "declare.h" #include "error.h" #include "funcdesc.h" @@ -87,6 +87,9 @@ static GenDesc GenOASGN = { TOK_OR_ASSIGN, GEN_NOPUSH, g_or }; +static int hie0 (ExprDesc *lval); +/* Parse comma operator. */ + static int expr (int (*func) (ExprDesc*), ExprDesc *lval); /* Expression parser; func is either hie0 or hie1. */ @@ -319,7 +322,7 @@ void DefineData (ExprDesc* Expr) -static void lconst (unsigned Flags, ExprDesc* Expr) +static void LoadConstant (unsigned Flags, ExprDesc* Expr) /* Load the primary register with some constant value. */ { switch (Expr->Flags & E_MCTYPE) { @@ -362,7 +365,7 @@ static void lconst (unsigned Flags, ExprDesc* Expr) -static int kcalc (int tok, long val1, long val2) +static int kcalc (token_t tok, long val1, long val2) /* Calculate an operation with left and right operand constant. */ { switch (tok) { @@ -437,12 +440,12 @@ static int istypeexpr (void) (NextTok.Tok == TOK_CONST) || (NextTok.Tok == TOK_IDENT && (Entry = FindSym (NextTok.Ident)) != 0 && - IsTypeDef (Entry))); + SymIsTypeDef (Entry))); } -static void PushAddr (ExprDesc* lval) +void PushAddr (ExprDesc* lval) /* If the expression contains an address that was somehow evaluated, * push this address on the stack. This is a helper function for all * sorts of implicit or explicit assignment functions where the lvalue @@ -451,23 +454,13 @@ static void PushAddr (ExprDesc* lval) { /* Get the address on stack if needed */ if (lval->Flags != E_MREG && (lval->Flags & E_MEXPR)) { - /* Push the address (always a pointer) */ - g_push (CF_PTR, 0); + /* Push the address (always a pointer) */ + g_push (CF_PTR, 0); } } -static void MakeConstIntExpr (ExprDesc* Expr, long Value) -/* Make Expr a constant integer expression with the given value */ -{ - Expr->Flags = E_MCONST; - Expr->Type = type_int; - Expr->ConstVal = Value; -} - - - void ConstSubExpr (int (*F) (ExprDesc*), ExprDesc* Expr) /* Will evaluate an expression via the given function. If the result is not * a constant, a diagnostic will be printed, and the value is replaced by @@ -475,11 +468,28 @@ void ConstSubExpr (int (*F) (ExprDesc*), ExprDesc* Expr) * from this input error. */ { - memset (Expr, 0, sizeof (*Expr)); + InitExprDesc (Expr); if (F (Expr) != 0 || Expr->Flags != E_MCONST) { Error ("Constant expression expected"); /* To avoid any compiler errors, make the expression a valid const */ - MakeConstIntExpr (Expr, 1); + MakeConstIntExpr (Expr, 1); + } +} + + + +void CheckBoolExpr (ExprDesc* lval) +/* Check if the given expression is a boolean expression, output a diagnostic + * if not. + */ +{ + /* 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 + */ + if (!IsClassInt (lval->Type) && !IsClassPtr (lval->Type)) { + Error ("Boolean expression expected"); + /* To avoid any compiler errors, make the expression a valid int */ + MakeConstIntExpr (lval, 1); } } @@ -491,7 +501,7 @@ void ConstSubExpr (int (*F) (ExprDesc*), ExprDesc* Expr) -void exprhs (unsigned flags, int k, ExprDesc *lval) +void exprhs (unsigned flags, int k, ExprDesc* lval) /* Put the result of an expression into the primary register */ { int f; @@ -525,7 +535,7 @@ void exprhs (unsigned flags, int k, ExprDesc *lval) g_inc (flags | CF_CONST, lval->ConstVal); } else if ((f & E_MEXPR) == 0) { /* Constant of some sort, load it into the primary */ - lconst (flags, lval); + LoadConstant (flags, lval); } /* Are we testing this value? */ if (lval->Test & E_FORCETEST) { @@ -851,7 +861,7 @@ static int primary (ExprDesc* lval) */ if (CurTok.Tok == TOK_LPAREN) { NextToken (); - memset (lval, 0, sizeof (*lval)); /* Remove any attributes */ + InitExprDesc (lval); /* Remove any attributes */ k = hie0 (lval); ConsumeRParen (); return k; @@ -908,7 +918,7 @@ static int primary (ExprDesc* lval) /* Check for legal symbol types */ if ((Sym->Flags & SC_CONST) == SC_CONST) { /* Enum or some other numeric constant */ - lval->Flags = E_MCONST; + lval->Flags = E_MCONST | E_TCONST; lval->ConstVal = Sym->V.ConstVal; return 0; } else if ((Sym->Flags & SC_FUNC) == SC_FUNC) { @@ -931,6 +941,11 @@ static int primary (ExprDesc* lval) lval->Flags = E_MLOCAL | E_TLOFFS; lval->ConstVal = Sym->V.Offs; } + } else if ((Sym->Flags & SC_REGISTER) == SC_REGISTER) { + /* Register variable, zero page based */ + lval->Flags = E_MGLOBAL | E_MCONST | E_TREGISTER; + lval->Name = Sym->V.R.RegOffs; + lval->ConstVal = 0; } else if ((Sym->Flags & SC_STATIC) == SC_STATIC) { /* Static variable */ if (Sym->Flags & (SC_EXTERN | SC_STORAGE)) { @@ -941,11 +956,6 @@ static int primary (ExprDesc* lval) lval->Name = Sym->V.Label; } lval->ConstVal = 0; - } else if ((Sym->Flags & SC_REGISTER) == SC_REGISTER) { - /* Register variable, zero page based */ - lval->Flags = E_MGLOBAL | E_MCONST | E_TREGISTER; - lval->Name = Sym->V.Offs; - lval->ConstVal = 0; } else { /* Local static variable */ lval->Flags = E_MGLOBAL | E_MCONST | E_TLLAB; @@ -1095,9 +1105,10 @@ static int arrayref (int k, ExprDesc* lval) RemoveCode (Mark1); /* Handle constant base array on stack. Be sure NOT to - * handle pointers the same way, this won't work. + * handle pointers the same way, and check for character literals + * (both won't work). */ - if (IsTypeArray (tptr1) && + if (IsTypeArray (tptr1) && lval->Flags != (E_MCONST | E_TLIT) && ((lval->Flags & ~E_MCTYPE) == E_MCONST || (lval->Flags & ~E_MCTYPE) == E_MLOCAL || (lval->Flags & E_MGLOBAL) != 0 || @@ -1204,12 +1215,12 @@ static int arrayref (int k, ExprDesc* lval) (rflags & E_MGLOBAL) != 0 || /* Static array, or ... */ rflags == E_MLOCAL; /* Local array */ - if (ConstSubAddr && CheckedSizeOf (lval->Type) == 1) { + if (ConstSubAddr && CheckedSizeOf (lval->Type) == SIZEOF_CHAR) { type* SavedType; /* Reverse the order of evaluation */ - unsigned flags = (CheckedSizeOf (lval2.Type) == 1)? CF_CHAR : CF_INT; + unsigned flags = (CheckedSizeOf (lval2.Type) == SIZEOF_CHAR)? CF_CHAR : CF_INT; RemoveCode (Mark2); /* Get a pointer to the array into the primary. We have changed @@ -1225,7 +1236,7 @@ static int arrayref (int k, ExprDesc* lval) if (rflags == E_MLOCAL) { g_addlocal (flags, lval2.ConstVal); } else { - flags |= GlobalModeFlags (lval2.Flags); + flags |= GlobalModeFlags (lval2.Flags); g_addstatic (flags, lval2.Name, lval2.ConstVal); } } else { @@ -1234,20 +1245,20 @@ static int arrayref (int k, ExprDesc* lval) g_inc (CF_INT | CF_UNSIGNED, lval->ConstVal); } else if (lflags == E_MLOCAL) { /* Base address is a local variable address */ - if (IsTypeArray (tptr1)) { + if (IsTypeArray (tptr1)) { g_addaddr_local (CF_INT, lval->ConstVal); - } else { + } else { g_addlocal (CF_PTR, lval->ConstVal); - } + } } else { /* Base address is a static variable address */ unsigned flags = CF_INT; - flags |= GlobalModeFlags (lval->Flags); - if (IsTypeArray (tptr1)) { + flags |= GlobalModeFlags (lval->Flags); + if (IsTypeArray (tptr1)) { g_addaddr_static (flags, lval->Name, lval->ConstVal); - } else { - g_addstatic (flags, lval->Name, lval->ConstVal); - } + } else { + g_addstatic (flags, lval->Name, lval->ConstVal); + } } } } @@ -1370,34 +1381,46 @@ static int hie11 (ExprDesc *lval) -static void store (ExprDesc* lval) -/* Store primary reg into this reference */ +void Store (ExprDesc* lval, const type* StoreType) +/* Store the primary register into the location denoted by lval. If StoreType + * is given, use this type when storing instead of lval->Type. If StoreType + * is NULL, use lval->Type instead. + */ { - int f; - unsigned flags; + unsigned Flags; - f = lval->Flags; - flags = TypeOf (lval->Type); + unsigned f = lval->Flags; + + /* If StoreType was not given, use lval->Type instead */ + if (StoreType == 0) { + StoreType = lval->Type; + } + + /* Get the code generator flags */ + Flags = TypeOf (StoreType); if (f & E_MGLOBAL) { - flags |= GlobalModeFlags (f); + Flags |= GlobalModeFlags (f); if (lval->Test) { - /* Just testing */ - flags |= CF_TEST; - } + /* Just testing */ + Flags |= CF_TEST; + } /* Generate code */ - g_putstatic (flags, lval->Name, lval->ConstVal); + g_putstatic (Flags, lval->Name, lval->ConstVal); } else if (f & E_MLOCAL) { - g_putlocal (flags, lval->ConstVal, 0); + /* Store an auto variable */ + g_putlocal (Flags, lval->ConstVal, 0); } else if (f == E_MEOFFS) { - g_putind (flags, lval->ConstVal); + /* Store indirect with offset */ + g_putind (Flags, lval->ConstVal); } else if (f != E_MREG) { if (f & E_MEXPR) { - g_putind (flags, 0); + /* Indirect without offset */ + g_putind (Flags, 0); } else { /* Store into absolute address */ - g_putstatic (flags | CF_ABSOLUTE, lval->ConstVal, 0); + g_putstatic (Flags | CF_ABSOLUTE, lval->ConstVal, 0); } } @@ -1442,7 +1465,7 @@ static void pre_incdec (ExprDesc* lval, void (*inc) (unsigned, unsigned long)) inc (flags, val); /* Store the result back */ - store (lval); + Store (lval, 0); } else { @@ -1518,7 +1541,7 @@ static void post_incdec (ExprDesc* lval, int k, void (*inc) (unsigned, unsigned } /* Store the result back */ - store (lval); + Store (lval, 0); /* Restore the original value */ g_restore (flags | CF_FORCECHAR); @@ -1588,29 +1611,37 @@ int hie10 (ExprDesc* lval) case TOK_BOOL_NOT: NextToken (); if (evalexpr (CF_NONE, hie10, lval) == 0) { - /* Constant expression */ - lval->ConstVal = !lval->ConstVal; + /* Constant expression */ + lval->ConstVal = !lval->ConstVal; } else { - g_bneg (TypeOf (lval->Type)); - lval->Test |= E_CC; /* bneg will set cc */ - lval->Flags = E_MEXPR; /* say it's an expr */ + g_bneg (TypeOf (lval->Type)); + lval->Test |= E_CC; /* bneg will set cc */ + lval->Flags = E_MEXPR; /* say it's an expr */ } return 0; /* expr not storable */ case TOK_STAR: NextToken (); if (evalexpr (CF_NONE, hie10, lval) != 0) { - /* Expression is not const, indirect value loaded into primary */ - lval->Flags = E_MEXPR; - lval->ConstVal = 0; /* Offset is zero now */ + /* Expression is not const, indirect value loaded into primary */ + lval->Flags = E_MEXPR; + lval->ConstVal = 0; /* Offset is zero now */ } - t = lval->Type; - if (IsClassPtr (t)) { - lval->Type = Indirect (t); - } else { - Error ("Illegal indirection"); - } - return 1; + /* If the expression is already a pointer to function, the + * additional dereferencing operator must be ignored. + */ + if (IsTypeFuncPtr (lval->Type)) { + /* Expression not storable */ + return 0; + } else { + if (IsClassPtr (lval->Type)) { + lval->Type = Indirect (lval->Type); + } else { + Error ("Illegal indirection"); + } + return 1; + } + break; case TOK_AND: NextToken (); @@ -1619,32 +1650,32 @@ int hie10 (ExprDesc* lval) * applied to functions, even if they're no lvalues. */ if (k == 0 && !IsTypeFunc (lval->Type)) { - /* Allow the & operator with an array */ - if (!IsTypeArray (lval->Type)) { - Error ("Illegal address"); - } + /* Allow the & operator with an array */ + if (!IsTypeArray (lval->Type)) { + Error ("Illegal address"); + } } else { - t = TypeAlloc (TypeLen (lval->Type) + 2); - t [0] = T_PTR; - TypeCpy (t + 1, lval->Type); - lval->Type = t; + t = TypeAlloc (TypeLen (lval->Type) + 2); + t [0] = T_PTR; + TypeCpy (t + 1, lval->Type); + lval->Type = t; } return 0; case TOK_SIZEOF: NextToken (); if (istypeexpr ()) { - type Type[MAXTYPELEN]; - NextToken (); - lval->ConstVal = CheckedSizeOf (ParseType (Type)); - ConsumeRParen (); + type Type[MAXTYPELEN]; + NextToken (); + lval->ConstVal = CheckedSizeOf (ParseType (Type)); + ConsumeRParen (); } else { - /* Remember the output queue pointer */ - CodeMark Mark = GetCodePos (); - hie10 (lval); + /* Remember the output queue pointer */ + CodeMark Mark = GetCodePos (); + hie10 (lval); lval->ConstVal = CheckedSizeOf (lval->Type); - /* Remove any generated code */ - RemoveCode (Mark); + /* Remove any generated code */ + RemoveCode (Mark); } lval->Flags = E_MCONST | E_TCONST; lval->Type = type_uint; @@ -1653,8 +1684,8 @@ int hie10 (ExprDesc* lval) default: if (istypeexpr ()) { - /* A cast */ - return TypeCast (lval); + /* A cast */ + return TypeCast (lval); } } @@ -1678,7 +1709,7 @@ int hie10 (ExprDesc* lval) static int hie_internal (const GenDesc** ops, /* List of generators */ ExprDesc* lval, /* parent expr's lval */ int (*hienext) (ExprDesc*), - int* UsedGen) /* next higher level */ + int* UsedGen) /* next higher level */ /* Helper function */ { int k; @@ -2004,53 +2035,53 @@ static void parseadd (int k, ExprDesc* lval) g_scale (CF_INT, CheckedPSizeOf (lhst)); /* Operate on pointers, result type is a pointer */ flags |= CF_PTR; - /* Generate the code for the add */ - if (lval->Flags == E_MCONST) { - /* Numeric constant */ - g_inc (flags, lval->ConstVal); - } else { - /* Constant address */ - g_addaddr_static (flags, lval->Name, lval->ConstVal); - } + /* Generate the code for the add */ + if (lval->Flags == E_MCONST) { + /* Numeric constant */ + g_inc (flags, lval->ConstVal); + } else { + /* Constant address */ + g_addaddr_static (flags, lval->Name, lval->ConstVal); + } } else if (IsClassInt (lhst) && IsClassPtr (rhst)) { /* Left is int, right is pointer, must scale lhs. */ - unsigned ScaleFactor = CheckedPSizeOf (rhst); + unsigned ScaleFactor = CheckedPSizeOf (rhst); /* Operate on pointers, result type is a pointer */ - flags |= CF_PTR; - lval->Type = lval2.Type; - - /* Since we do already have rhs in the primary, if lhs is - * not a numeric constant, and the scale factor is not one - * (no scaling), we must take the long way over the stack. - */ - if (lval->Flags == E_MCONST) { - /* Numeric constant, scale lhs */ - lval->ConstVal *= ScaleFactor; - /* Generate the code for the add */ - g_inc (flags, lval->ConstVal); - } else if (ScaleFactor == 1) { - /* Constant address but no need to scale */ - g_addaddr_static (flags, lval->Name, lval->ConstVal); - } else { - /* Constant address that must be scaled */ + flags |= CF_PTR; + lval->Type = lval2.Type; + + /* Since we do already have rhs in the primary, if lhs is + * not a numeric constant, and the scale factor is not one + * (no scaling), we must take the long way over the stack. + */ + if (lval->Flags == E_MCONST) { + /* Numeric constant, scale lhs */ + lval->ConstVal *= ScaleFactor; + /* Generate the code for the add */ + g_inc (flags, lval->ConstVal); + } else if (ScaleFactor == 1) { + /* Constant address but no need to scale */ + g_addaddr_static (flags, lval->Name, lval->ConstVal); + } else { + /* Constant address that must be scaled */ g_push (TypeOf (lval2.Type), 0); /* rhs --> stack */ - g_getimmed (flags, lval->Name, lval->ConstVal); - g_scale (CF_PTR, ScaleFactor); - g_add (CF_PTR, 0); - } + g_getimmed (flags, lval->Name, lval->ConstVal); + g_scale (CF_PTR, ScaleFactor); + g_add (CF_PTR, 0); + } } else if (IsClassInt (lhst) && IsClassInt (rhst)) { /* Integer addition */ flags |= typeadjust (lval, &lval2, 1); - /* Generate the code for the add */ - if (lval->Flags == E_MCONST) { - /* Numeric constant */ - g_inc (flags, lval->ConstVal); - } else { - /* Constant address */ - g_addaddr_static (flags, lval->Name, lval->ConstVal); - } + /* Generate the code for the add */ + if (lval->Flags == E_MCONST) { + /* Numeric constant */ + g_inc (flags, lval->ConstVal); + } else { + /* Constant address */ + g_addaddr_static (flags, lval->Name, lval->ConstVal); + } } else { /* OOPS */ Error ("Invalid operands for binary operator `+'"); @@ -2126,8 +2157,16 @@ static void parseadd (int k, ExprDesc* lval) flags = CF_PTR; lval->Type = lval2.Type; } else if (IsClassInt (lhst) && IsClassInt (rhst)) { - /* Integer addition */ - flags = typeadjust (lval, &lval2, 0); + /* Integer addition. Note: Result is never constant. + * Problem here is that typeadjust does not know if the + * variable is an rvalue or lvalue, so if both operands + * are dereferenced constant numeric addresses, typeadjust + * thinks the operation works on constants. Removing + * CF_CONST here means handling the symptoms, however, the + * whole parser is such a mess that I fear to break anything + * when trying to apply another solution. + */ + flags = typeadjust (lval, &lval2, 0) & ~CF_CONST; } else { /* OOPS */ Error ("Invalid operands for binary operator `+'"); @@ -2629,9 +2668,6 @@ static int hieQuest (ExprDesc *lval) type* type2; /* Type of expression 2 */ type* type3; /* Type of expression 3 */ type* rtype; /* Type of result */ - CodeMark Mark1; /* Save position in output code */ - CodeMark Mark2; /* Save position in output code */ - k = Preprocessing? hieOrPP (lval) : hieOr (lval); @@ -2690,14 +2726,12 @@ static int hieQuest (ExprDesc *lval) * the type cast code for expr2. */ labf = GetLocalLabel (); /* Get new label */ - Mark1 = GetCodePos (); /* Remember current position */ g_jump (labf); /* Jump around code */ /* The jump for expr2 goes here */ g_defcodelabel (labt); /* Create the typecast code for expr2 */ - Mark2 = GetCodePos (); /* Remember position */ g_typecast (TypeOf (rtype), TypeOf (type2)); /* Jump here around the typecase code. */ @@ -2707,7 +2741,7 @@ static int hieQuest (ExprDesc *lval) } else if (IsClassPtr (type2) && IsClassPtr (type3)) { /* Must point to same type */ if (TypeCmp (Indirect (type2), Indirect (type3)) < TC_EQUAL) { - Error ("Incompatible pointer types"); + Error ("Incompatible pointer types"); } /* Result has the common type */ rtype = lval2.Type; @@ -2786,7 +2820,7 @@ static void opeq (const GenDesc* Gen, ExprDesc *lval, int k) /* If the lhs is character sized, the operation may be later done * with characters. */ - if (CheckedSizeOf (lval->Type) == 1) { + if (CheckedSizeOf (lval->Type) == SIZEOF_CHAR) { flags |= CF_FORCECHAR; } @@ -2808,14 +2842,14 @@ static void opeq (const GenDesc* Gen, ExprDesc *lval, int k) /* If the lhs is character sized, the operation may be later done * with characters. */ - if (CheckedSizeOf (lval->Type) == 1) { + if (CheckedSizeOf (lval->Type) == SIZEOF_CHAR) { flags |= CF_FORCECHAR; } /* Adjust the types of the operands if needed */ Gen->Func (g_typeadjust (flags, TypeOf (lval2.Type)), 0); } - store (lval); + Store (lval, 0); lval->Flags = E_MEXPR; } @@ -2920,85 +2954,6 @@ static void addsubeq (const GenDesc* Gen, ExprDesc *lval, int k) -static void Assignment (ExprDesc* lval) -/* Parse an assignment */ -{ - int k; - ExprDesc lval2; - unsigned flags; - type* ltype = lval->Type; - - /* 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 - * family, allow it here. - */ - if (IsClassStruct (ltype)) { - - /* Bring the address of the lhs into the primary and push it */ - exprhs (0, 0, lval); - g_push (CF_PTR | CF_UNSIGNED, 0); - - /* Get the expression on the right of the '=' into the primary */ - k = hie1 (&lval2); - if (k) { - /* Get the address */ - exprhs (0, 0, &lval2); - } - - /* 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 (TypeCmp (ltype, lval2.Type) < TC_STRICT_COMPATIBLE) { - Error ("Incompatible types"); - } - - /* Load the size of the struct into the primary */ - g_getimmed (CF_INT | CF_UNSIGNED | CF_CONST, CheckedSizeOf (ltype), 0); - - /* Call the memcpy function */ - g_call (CF_FIXARGC, "memcpy", 4); - - } else { - - /* Get the address on stack if needed */ - PushAddr (lval); - - /* No struct, setup flags for the load */ -#if 0 - /* Generates wrong code!!! ### */ - flags = CheckedSizeOf (ltype) == 1? CF_FORCECHAR : CF_NONE; -#else - flags = CF_NONE; -#endif - - /* Get the expression on the right of the '=' into the primary */ - if (evalexpr (flags, hie1, &lval2) == 0) { - /* Constant expression. Adjust the types */ - assignadjust (ltype, &lval2); - /* Put the value into the primary register */ - lconst (flags, &lval2); - } else { - /* Expression is not constant and already in the primary */ - assignadjust (ltype, &lval2); - } - - /* Generate a store instruction */ - store (lval); - - } - - /* Value is still in primary */ - lval->Flags = E_MEXPR; -} - - - int hie1 (ExprDesc* lval) /* Parse first level of expression hierarchy. */ { @@ -3068,7 +3023,7 @@ int hie1 (ExprDesc* lval) -int hie0 (ExprDesc *lval) +static int hie0 (ExprDesc *lval) /* Parse comma operator. */ { int k; @@ -3134,7 +3089,7 @@ void expression1 (ExprDesc* lval) * the primary register */ { - memset (lval, 0, sizeof (*lval)); + InitExprDesc (lval); exprhs (CF_NONE, expr (hie1, lval), lval); } @@ -3143,7 +3098,7 @@ void expression1 (ExprDesc* lval) void expression (ExprDesc* lval) /* Evaluate an expression and put it into the primary register */ { - memset (lval, 0, sizeof (*lval)); + InitExprDesc (lval); exprhs (CF_NONE, expr (hie0, lval), lval); } @@ -3152,7 +3107,7 @@ void expression (ExprDesc* lval) void ConstExpr (ExprDesc* lval) /* Get a constant value */ { - memset (lval, 0, sizeof (*lval)); + InitExprDesc (lval); if (expr (hie1, lval) != 0 || (lval->Flags & E_MCONST) == 0) { Error ("Constant expression expected"); /* To avoid any compiler errors, make the expression a valid const */ @@ -3165,7 +3120,7 @@ void ConstExpr (ExprDesc* lval) void ConstIntExpr (ExprDesc* Val) /* Get a constant int value */ { - memset (Val, 0, sizeof (*Val)); + InitExprDesc (Val); if (expr (hie1, Val) != 0 || (Val->Flags & E_MCONST) == 0 || !IsClassInt (Val->Type)) { @@ -3190,70 +3145,62 @@ void intexpr (ExprDesc* lval) -void boolexpr (ExprDesc* lval) -/* Get a boolean expression */ -{ - /* Read an expression */ - 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 - */ - if (!IsClassInt (lval->Type) && !IsClassPtr (lval->Type)) { - Error ("Boolean expression expected"); - /* To avoid any compiler errors, make the expression a valid int */ - MakeConstIntExpr (lval, 1); - } -} - - - -void test (unsigned label, int cond) -/* Generate code to perform test and jump if false. */ +void Test (unsigned Label, int Invert) +/* Evaluate a boolean test expression and jump depending on the result of + * the test and on Invert. + */ { int k; ExprDesc lval; - /* Eat the parenthesis */ - ConsumeLParen (); + /* Evaluate the expression */ + k = expr (hie0, InitExprDesc (&lval)); - /* Prepare the expression, setup labels */ - memset (&lval, 0, sizeof (lval)); + /* Check for a boolean expression */ + CheckBoolExpr (&lval); - /* Generate code to eval the expr */ - k = expr (hie0, &lval); + /* Check for a constant expression */ if (k == 0 && lval.Flags == E_MCONST) { + /* Constant rvalue */ - if (cond == 0 && lval.ConstVal == 0) { - g_jump (label); + if (!Invert && lval.ConstVal == 0) { + g_jump (Label); Warning ("Unreachable code"); - } else if (cond && lval.ConstVal) { - g_jump (label); + } else if (Invert && lval.ConstVal != 0) { + g_jump (Label); } - ConsumeRParen (); - return; - } - /* If the expr hasn't set condition codes, set the force-test flag */ - if ((lval.Test & E_CC) == 0) { - lval.Test |= E_FORCETEST; - } + } else { - /* Load the value into the primary register */ - exprhs (CF_FORCECHAR, k, &lval); + /* If the expr hasn't set condition codes, set the force-test flag */ + if ((lval.Test & E_CC) == 0) { + lval.Test |= E_FORCETEST; + } - /* Generate the jump */ - if (cond) { - g_truejump (CF_NONE, label); - } else { - /* Special case (putting this here is a small hack - but hey, the - * compiler itself is one big hack...): If a semicolon follows, we - * don't have a statement and may omit the jump. - */ - if (CurTok.Tok != TOK_SEMI) { - g_falsejump (CF_NONE, label); - } + /* Load the value into the primary register */ + exprhs (CF_FORCECHAR, k, &lval); + + /* Generate the jump */ + if (Invert) { + g_truejump (CF_NONE, Label); + } else { + g_falsejump (CF_NONE, Label); + } } +} + + + +void TestInParens (unsigned Label, int Invert) +/* Evaluate a boolean test expression in parenthesis and jump depending on + * the result of the test * and on Invert. + */ +{ + /* Eat the parenthesis */ + ConsumeLParen (); + + /* Do the test */ + Test (Label, Invert); /* Check for the closing brace */ ConsumeRParen (); @@ -3261,4 +3208,3 @@ void test (unsigned label, int cond) -