/* */
/* */
/* */
-/* (C) 2000 Ullrich von Bassewitz */
+/* (C) 2000-2001 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
+static int GetBoolRep (const ExprNode* N)
+/* Get the boolean representation of a constant expression node */
+{
+ if (IsClassInt (N->Type)) {
+ /* An integer constant */
+ return (N->IVal != 0);
+ } else if (IsClassFloat (N->Type)) {
+ /* A float constant */
+ return (N->FVal != 0.0);
+ } else if (IsTypeArray (N->Type) && IsTypeChar (Indirect (N->Type))) {
+ /* A string constant - useless but allowed */
+ return 1;
+ } else {
+ Internal ("GetBoolRep: Unknown type");
+ /* NOTREACHED */
+ return 0;
+ }
+}
+
+
+
/*****************************************************************************/
/* Expression node helper functions */
/*****************************************************************************/
*/
{
ExprNode* N = AllocExprNode (NT_CONST, type_int, RVALUE);
- N->V.I = Value;
+ N->IVal = Value;
return N;
}
if (CurTok.Tok != TOK_SCONST) {
/* Print an error */
- Error (ERR_STRLIT_EXPECTED);
+ Error ("String literal expected");
/* To be on the safe side later, insert an empty asm string */
AppendItem (N, xstrdup (""));
} else {
/* Insert a copy of the string into the expression node */
- AppendItem (N, xstrdup (GetLiteral (curval)));
+ AppendItem (N, xstrdup (GetLiteral (CurTok.IVal)));
/* 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);
+ ResetLiteralOffs (CurTok.IVal);
}
/* Skip the string token */
/* Create the new node */
N = AllocExprNode (NT_CONST, CurTok.Type, RVALUE);
- N->V.I = CurTok.IVal;
+ N->IVal = CurTok.IVal;
/* Skip the token and return the result */
NextToken ();
/* Create the new node */
N = AllocExprNode (NT_CONST, CurTok.Type, RVALUE);
- N->V.F = CurTok.FVal;
+ N->FVal = CurTok.FVal;
/* Skip the token and return the result */
NextToken ();
*/
if (Preprocessing) {
/* Illegal expression in PP mode */
- Error (ERR_CPP_EXPR_EXPECTED);
+ Error ("Preprocessor expression expected");
/* Skip the token for error recovery */
NextToken ();
/* Check for illegal symbol types */
if ((Sym->Flags & SC_LABEL) == SC_LABEL) {
/* Cannot use labels in expressions */
- Error (ERR_SYMBOL_KIND);
+ Error ("Cannot use a label in an expression");
return GetIntNode (0);
} else if (Sym->Flags & SC_TYPE) {
/* Cannot use type symbols */
- Error (ERR_VAR_IDENT_EXPECTED);
+ Error ("Cannot use a type in an expression");
/* Assume an int type to make lval valid */
return GetIntNode (0);
}
if (CurTok.Tok == TOK_LPAREN) {
/* Warn about the use of a function without prototype */
- Warning (WARN_FUNC_WITHOUT_PROTO);
+ Warning ("Function call without a prototype");
/* Declare a function returning int. For that purpose, prepare
* a function signature for a function having an empty param
} else {
/* Print an error about an undeclared variable */
- Error (ERR_UNDEFINED_SYMBOL, Ident);
+ Error ("Undefined symbiol: `%s'", Ident);
/* Undeclared Variable */
Sym = AddLocalSym (Ident, type_int, SC_AUTO | SC_REF, 0);
} else if (CurTok.Tok == TOK_SCONST) {
/* String literal */
- N = AllocExprNode (NT_CONST, GetCharArrayType (strlen (GetLiteral (curval))), RVALUE);
- N->V.I = curval;
+ N = AllocExprNode (NT_CONST, GetCharArrayType (strlen (GetLiteral (CurTok.IVal))), RVALUE);
+ N->IVal = CurTok.IVal;
} else if (CurTok.Tok == TOK_ASM) {
} else {
/* Illegal primary. */
- Error (ERR_EXPR_EXPECTED);
+ Error ("Expression expected");
N = GetIntNode (0);
}
Right = Expression ();
/* Check the types. As special "C" feature, accept a reversal of base and
- * index types:
- * char C = 3["abcdefg"];
- * is legal C!
+ * index types: char C = 3["abcdefg"] is legal C!
*/
if (IsClassPtr (Left->Type)) {
/* Right side must be some sort of integer */
if (!IsClassInt (Right->Type)) {
/* Print an error */
- Error (ERR_CANNOT_SUBSCRIPT);
+ Error ("Invalid subscript");
/* To avoid problems later, create a new, legal subscript
* expression
*/
ExprNode* Tmp;
/* Left side must be some sort of integer */
- if (!IsClassInt (Right->Type)) {
+ if (!IsClassInt (Left->Type)) {
/* Print an error */
- Error (ERR_CANNOT_SUBSCRIPT);
+ Error ("Invalid subscript");
/* To avoid problems later, create a new, legal subscript
* expression
*/
/* Invalid array expression. Skip the closing bracket, then return
* an integer instead of the array expression to be safe later.
*/
- Error (ERR_CANNOT_SUBSCRIPT);
+ Error ("Invalid subscript");
ConsumeRBrack ();
return GetIntNode (0);
}
if (CurTok.Tok == TOK_PTR_REF) {
NT = NT_STRUCTPTR_ACCESS;
if (!IsTypePtr (StructType)) {
- Error (ERR_STRUCT_PTR_EXPECTED);
+ Error ("Struct pointer expected");
return GetIntNode (0);
}
StructType = Indirect (StructType);
NT = NT_STRUCT_ACCESS;
}
if (!IsClassStruct (StructType)) {
- Error (ERR_STRUCT_EXPECTED);
+ Error ("Struct expected");
return GetIntNode (0);
}
NextToken ();
if (CurTok.Tok != TOK_IDENT) {
/* Print an error */
- Error (ERR_IDENT_EXPECTED);
+ Error ("Identifier expected");
/* Return an integer expression instead */
return GetIntNode (0);
}
Field = FindStructField (StructType, Ident);
if (Field == 0) {
/* Struct field not found */
- Error (ERR_STRUCT_FIELD_MISMATCH, Ident);
+ Error ("Struct/union has no field named `%s'", Ident);
/* Return an integer expression instead */
return GetIntNode (0);
}
if (!IsTypeFunc (Left->Type) && !IsTypeFuncPtr (Left->Type)) {
/* Call to non function */
- Error (ERR_ILLEGAL_FUNC_CALL);
+ Error ("Illegal function call");
- /* Free the old node */
- FreeExprNode (Left);
+ /* Free the old tree */
+ FreeExprTree (Left);
/* Return something safe */
return GetIntNode (0);
/* Too many arguments. Do we have an open param list? */
if ((Func->Flags & FD_ELLIPSIS) == 0) {
/* End of param list reached, no ellipsis */
- Error (ERR_TOO_MANY_FUNC_ARGS);
+ Error ("Too many function arguments");
}
/* Assume an ellipsis even in case of errors to avoid an error
* message for each other argument.
/* Check if we had enough parameters */
if (ParamCount < Func->ParamCount) {
- Error (ERR_TOO_FEW_FUNC_ARGS);
+ Error ("Too few function arguments");
}
/* Return the function call node */
if (Left->LValue == 0) {
/* Print a diagnostics */
- Error (ERR_LVALUE_EXPECTED);
+ Error ("lvalue expected");
/* It is safe to return the operand expression and probably better
* than returning an int, since the operand expression already has
if (Op->LValue == 0) {
/* Print a diagnostics */
- Error (ERR_LVALUE_EXPECTED);
+ Error ("lvalue expected");
/* It is safe to return the operand expression and probably better
* than returning an int, since the operand expression already has
/* Type check */
if (!IsClassInt (Op->Type) && !IsClassFloat (Op->Type)) {
- /* Display diagnostic */
- Error (ERR_SYNTAX);
+ /* Output diagnostic */
+ Error ("Syntax error");
/* Free the errorneous node */
- FreeExprNode (Op);
+ FreeExprTree (Op);
/* Return something that makes sense later */
return GetIntNode (0);
/* The value is constant, change it according to the insn */
if (IsClassInt (Op->Type)) {
/* Integer */
- Op->V.I = -Op->V.I;
+ Op->IVal = -Op->IVal;
} else {
/* Float */
- Op->V.F = -Op->V.F;
+ Op->FVal = -Op->FVal;
}
/* Return the operand itself */
if (!IsClassInt (Op->Type)) {
/* Display diagnostic */
- Error (ERR_OP_NOT_ALLOWED);
+ Error ("Operation not allowed on this type");
/* Free the errorneous node */
- FreeExprNode (Op);
+ FreeExprTree (Op);
/* Return something that makes sense later */
return GetIntNode (0);
if (Op->NT == NT_CONST) {
/* Change the value and return the operand node */
- Op->V.I = ~Op->V.I;
+ Op->IVal = ~Op->IVal;
return Op;
} else {
ExprNode* Root;
/* Print diagnostics */
- Error (ERR_ILLEGAL_ADDRESS);
+ Error ("Cannot take address of rvalue");
- /* Free the problematic node */
- FreeExprNode (Op);
+ /* Free the problematic tree */
+ FreeExprTree (Op);
/* Return something that is safe later */
Root = AllocExprNode (NT_CONST, PointerTo (type_void), 0);
- Root->V.I = 0;
return Root;
}
if (!IsClassPtr (Op->Type)) {
/* Print diagnostics */
- Error (ERR_ILLEGAL_INDIRECT);
+ Error ("Illegal indirection");
- /* Free the problematic node */
- FreeExprNode (Op);
+ /* Free the problematic tree */
+ FreeExprTree (Op);
/* Return something that is safe later ### */
return GetIntNode (0);
Size = SizeOf (N->Type);
/* Free the node */
- FreeExprNode (N);
+ FreeExprTree (N);
}
/* Create a constant node with type size_t and return it */
N = AllocExprNode (NT_CONST, type_size_t, RVALUE);
- N->V.I = Size;
+ N->IVal = Size;
return N;
}
} else {
- /* Must be casted. Setup the expression tree and return the new node */
- Root = AllocExprNode (NT_BOOL_NOT, TargetType, RVALUE);
+ /* Must be casted. Setup the expression tree and return the new node */
+ Root = AllocExprNode (NT_BOOL_NOT, TargetType, RVALUE);
SetLeftNode (Root, Op);
return Root;
case TOK_PLUS:
case TOK_MINUS:
- return DoUnaryPlusMinus ();
+ return DoUnaryPlusMinus ();
case TOK_COMP:
return DoComplement ();
case TOK_SIZEOF:
return DoSizeOf ();
- default:
- /* Type cast */
- return DoTypeCast ();
+ default:
+ /* Type cast */
+ return DoTypeCast ();
- }
+ }
} else {
- /* Call the lower level */
- return PostfixExpr ();
+ /* Call the lower level */
+ return PostfixExpr ();
}
}
+static ExprNode* DoMul (ExprNode* Left)
+/* Handle multiplication */
+{
+ type TargetType[MAXTYPELEN];
+ ExprNode* Right;
+ ExprNode* Root;
+
+ /* Check the type of the left operand */
+ if (!IsClassInt (Left->Type) && !IsClassFloat (Left->Type)) {
+ Error ("Invalid left operand to binary operator `*'");
+ FreeExprTree (Left);
+ Left = GetIntNode (0);
+ }
+
+ /* Skip the operator token */
+ NextToken ();
+
+ /* Read the right expression */
+ Right = UnaryExpr ();
+
+ /* Check the type of the right operand */
+ if (!IsClassInt (Right->Type) && !IsClassFloat (Right->Type)) {
+ Error ("Invalid right operand to binary operator `*'");
+ FreeExprTree (Right);
+ Right = GetIntNode (0);
+ }
+
+ /* Make the root node */
+ Root = AllocExprNode (NT_BOOL_NOT, TargetType, RVALUE);
+ SetLeftNode (Root, Left);
+ SetRightNode (Root, Right);
+
+ return Root;
+}
+
+
+
static ExprNode* MultExpr (void)
/* Handle multiplicative expressions: '*' '/' and '%' */
{
switch (CurTok.Tok) {
case TOK_MUL:
+ Root = DoMul (Root);
break;
case TOK_DIV:
/* Check if this is for us */
while (CurTok.Tok == TOK_AND) {
- switch (CurTok.Tok) {
+ ExprNode* Left = Root;
+ ExprNode* Right;
- case TOK_AND:
- break;
+ /* Skip the token */
+ NextToken ();
- default:
- Internal ("Unexpected token");
- }
+ /* Get the right operand */
+ Right = EqualityExpr ();
+
+ /* Type check */
+ if (!IsClassInt (Left->Type) || !IsClassInt (Right->Type)) {
+
+ /* Print a diagnostic */
+ Error ("Operation not allowed for these types");
+
+ /* Remove the unneeded nodes */
+ FreeExprTree (Right);
+ FreeExprTree (Left);
+ /* Create something safe */
+ Root = GetIntNode (0);
+
+ } else {
+
+ /* Check if both operands are constant */
+ if (Left->NT == NT_CONST && Right->NT == NT_CONST) {
+
+ /* Get the constant result */
+ int Result = GetBoolRep (Left) & GetBoolRep (Right);
+
+ /* Remove the unneeded nodes */
+ FreeExprTree (Right);
+ FreeExprTree (Left);
+
+ /* Create a constant result */
+ Root = GetIntNode (Result);
+
+ } else {
+
+ /* Make an operator node */
+ Root = AllocExprNode (NT_AND, type_int, RVALUE);
+ SetRightNode (Root, Right);
+ SetLeftNode (Root, Left);
+
+ }
+ }
}
/* Return the resulting expression */
/* Check if this is for us */
while (CurTok.Tok == TOK_XOR) {
- switch (CurTok.Tok) {
+ ExprNode* Left = Root;
+ ExprNode* Right;
- case TOK_XOR:
- break;
+ /* Skip the token */
+ NextToken ();
- default:
- Internal ("Unexpected token");
- }
+ /* Get the right operand */
+ Right = AndExpr ();
+
+ /* Type check */
+ if (!IsClassInt (Left->Type) || !IsClassInt (Right->Type)) {
+ /* Print a diagnostic */
+ Error ("Operation not allowed for these types");
+
+ /* Remove the unneeded nodes */
+ FreeExprTree (Right);
+ FreeExprTree (Left);
+
+ /* Create something safe */
+ Root = GetIntNode (0);
+
+ } else {
+
+ /* Check if both operands are constant */
+ if (Left->NT == NT_CONST && Right->NT == NT_CONST) {
+
+ /* Get the constant result */
+ int Result = GetBoolRep (Left) ^ GetBoolRep (Right);
+
+ /* Remove the unneeded nodes */
+ FreeExprTree (Right);
+ FreeExprTree (Left);
+
+ /* Create a constant result */
+ Root = GetIntNode (Result);
+
+ } else {
+
+ /* Make an operator node */
+ Root = AllocExprNode (NT_XOR, type_int, RVALUE);
+ SetRightNode (Root, Right);
+ SetLeftNode (Root, Left);
+
+ }
+ }
}
/* Return the resulting expression */
/* Check if this is for us */
while (CurTok.Tok == TOK_OR) {
- switch (CurTok.Tok) {
+ ExprNode* Left = Root;
+ ExprNode* Right;
- case TOK_OR:
- break;
+ /* Skip the token */
+ NextToken ();
- default:
- Internal ("Unexpected token");
- }
+ /* Get the right operand */
+ Right = XorExpr ();
+ /* Type check */
+ if (!IsClassInt (Left->Type) || !IsClassInt (Right->Type)) {
+
+ /* Print a diagnostic */
+ Error ("Operation not allowed for these types");
+
+ /* Remove the unneeded nodes */
+ FreeExprTree (Right);
+ FreeExprTree (Left);
+
+ /* Create something safe */
+ Root = GetIntNode (0);
+
+ } else {
+
+ /* Check if both operands are constant */
+ if (Left->NT == NT_CONST && Right->NT == NT_CONST) {
+
+ /* Get the constant result */
+ int Result = GetBoolRep (Left) | GetBoolRep (Right);
+
+ /* Remove the unneeded nodes */
+ FreeExprTree (Right);
+ FreeExprTree (Left);
+
+ /* Create a constant result */
+ Root = GetIntNode (Result);
+
+ } else {
+
+ /* Make an operator node */
+ Root = AllocExprNode (NT_OR, type_int, RVALUE);
+ SetRightNode (Root, Right);
+ SetLeftNode (Root, Left);
+
+ }
+ }
}
/* Return the resulting expression */
/* Check if this is for us */
while (CurTok.Tok == TOK_BOOL_AND) {
- switch (CurTok.Tok) {
+ ExprNode* Left = Root;
+ ExprNode* Right;
- case TOK_BOOL_AND:
- break;
+ /* Skip the token */
+ NextToken ();
- default:
- Internal ("Unexpected token");
- }
+ /* Get the right operand */
+ Right = OrExpr ();
+
+ /* Check if both operands are constant */
+ if (Left->NT == NT_CONST && Right->NT == NT_CONST) {
+
+ /* Get the constant result */
+ int Result = GetBoolRep (Left) && GetBoolRep (Right);
+
+ /* Remove the unneeded nodes */
+ FreeExprTree (Right);
+ FreeExprTree (Left);
+
+ /* Create a constant result */
+ Root = GetIntNode (Result);
+
+ } else {
+
+ /* Make an operator node */
+ Root = AllocExprNode (NT_BOOL_AND, type_int, RVALUE);
+ SetRightNode (Root, Right);
+ SetLeftNode (Root, Left);
+
+ }
}
/* Check if this is for us */
while (CurTok.Tok == TOK_BOOL_OR) {
- switch (CurTok.Tok) {
+ ExprNode* Left = Root;
+ ExprNode* Right;
- case TOK_BOOL_OR:
- break;
+ /* Skip the token */
+ NextToken ();
- default:
- Internal ("Unexpected token");
- }
+ /* Get the right operand */
+ Right = BoolAndExpr ();
+
+ /* Check if both operands are constant */
+ if (Left->NT == NT_CONST && Right->NT == NT_CONST) {
+
+ /* Get the constant result */
+ int Result = GetBoolRep (Left) && GetBoolRep (Right);
+
+ /* Remove the unneeded nodes */
+ FreeExprTree (Right);
+ FreeExprTree (Left);
+
+ /* Create a constant result */
+ Root = GetIntNode (Result);
+
+ } else {
+
+ /* Make an operator node */
+ Root = AllocExprNode (NT_BOOL_OR, type_int, RVALUE);
+ SetRightNode (Root, Right);
+ SetLeftNode (Root, Left);
+
+ }
}
AppendItem (Root, Cond);
AppendItem (Root, Expr1);
AppendItem (Root, Expr2);
-
+
/* Return the result */
return Root;