]> git.sur5r.net Git - cc65/blobdiff - src/cc65/parser.c
Allow __fastcall__ for C function. Contrary to the name, this is a size
[cc65] / src / cc65 / parser.c
index 62aedd667d4896c2d71c68abbd23522ab0004d6c..932d3875a0e4710c518dbf78773cba9b14c9ace6 100644 (file)
@@ -6,7 +6,7 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 2000     Ullrich von Bassewitz                                       */
+/* (C) 2000-2001 Ullrich von Bassewitz                                       */
 /*               Wacholderweg 14                                             */
 /*               D-70597 Stuttgart                                           */
 /* EMail:        uz@musoftware.de                                            */
@@ -96,6 +96,27 @@ static int IsTypeExpr (void)
 
 
 
+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                      */
 /*****************************************************************************/
@@ -109,7 +130,7 @@ static ExprNode* GetIntNode (int Value)
  */
 {
     ExprNode* N = AllocExprNode (NT_CONST, type_int, RVALUE);
-    N->V.I = Value;
+    N->IVal = Value;
     return N;
 }
 
@@ -143,7 +164,7 @@ ExprNode* DoAsm (void)
     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 (""));
@@ -151,14 +172,14 @@ ExprNode* DoAsm (void)
     } 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 */
@@ -193,7 +214,7 @@ static ExprNode* Primary (void)
 
        /* 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 ();
@@ -205,7 +226,7 @@ static ExprNode* Primary (void)
 
        /* 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 ();
@@ -217,7 +238,7 @@ static ExprNode* Primary (void)
      */
     if (Preprocessing) {
                /* Illegal expression in PP mode */
-       Error (ERR_CPP_EXPR_EXPECTED);
+       Error ("Preprocessor expression expected");
 
        /* Skip the token for error recovery */
        NextToken ();
@@ -245,11 +266,11 @@ static ExprNode* Primary (void)
            /* 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);
            }
@@ -286,7 +307,7 @@ static ExprNode* Primary (void)
            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
@@ -299,7 +320,7 @@ static ExprNode* Primary (void)
            } 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);
@@ -313,8 +334,8 @@ static ExprNode* Primary (void)
     } 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) {
 
@@ -349,7 +370,7 @@ static ExprNode* Primary (void)
     } else {
 
        /* Illegal primary. */
-       Error (ERR_EXPR_EXPECTED);
+       Error ("Expression expected");
                N = GetIntNode (0);
 
     }
@@ -375,15 +396,13 @@ static ExprNode* DoArray (ExprNode* Left)
     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
             */
@@ -394,9 +413,9 @@ static ExprNode* DoArray (ExprNode* Left)
        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
             */
@@ -412,7 +431,7 @@ static ExprNode* DoArray (ExprNode* Left)
        /* 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);
     }
@@ -454,7 +473,7 @@ static ExprNode* DoStruct (ExprNode* Left)
     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);
@@ -462,7 +481,7 @@ static ExprNode* DoStruct (ExprNode* Left)
        NT = NT_STRUCT_ACCESS;
     }
     if (!IsClassStruct (StructType)) {
-       Error (ERR_STRUCT_EXPECTED);
+       Error ("Struct expected");
        return GetIntNode (0);
     }
 
@@ -470,7 +489,7 @@ static ExprNode* DoStruct (ExprNode* Left)
     NextToken ();
     if (CurTok.Tok != TOK_IDENT) {
        /* Print an error */
-       Error (ERR_IDENT_EXPECTED);
+       Error ("Identifier expected");
        /* Return an integer expression instead */
        return GetIntNode (0);
     }
@@ -481,7 +500,7 @@ static ExprNode* DoStruct (ExprNode* Left)
     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);
     }
@@ -520,10 +539,10 @@ static ExprNode* DoFunctionCall (ExprNode* Left)
     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);
@@ -571,7 +590,7 @@ static ExprNode* DoFunctionCall (ExprNode* Left)
            /* 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.
@@ -596,7 +615,7 @@ static ExprNode* DoFunctionCall (ExprNode* Left)
 
     /* 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 */
@@ -620,7 +639,7 @@ static ExprNode* DoPostIncDec (ExprNode* Left)
     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
@@ -702,7 +721,7 @@ static ExprNode* DoPreIncDec (void)
     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
@@ -738,11 +757,11 @@ static ExprNode* DoUnaryPlusMinus (void)
     /* 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);
@@ -759,10 +778,10 @@ static ExprNode* DoUnaryPlusMinus (void)
        /* 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 */
@@ -798,10 +817,10 @@ static ExprNode* DoComplement (void)
     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);
@@ -811,7 +830,7 @@ static ExprNode* DoComplement (void)
     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 {
@@ -871,14 +890,13 @@ static ExprNode* DoAddress (void)
        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;
 
     }
@@ -906,10 +924,10 @@ static ExprNode* DoIndirect (void)
     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);
@@ -960,13 +978,13 @@ static ExprNode* DoSizeOf (void)
                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;
 }
 
@@ -1001,8 +1019,8 @@ static ExprNode* DoTypeCast (void)
 
     } 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;
 
@@ -1029,7 +1047,7 @@ static ExprNode* UnaryExpr (void)
 
            case TOK_PLUS:
            case TOK_MINUS:
-               return DoUnaryPlusMinus ();
+                       return DoUnaryPlusMinus ();
 
            case TOK_COMP:
                return DoComplement ();
@@ -1046,22 +1064,59 @@ static ExprNode* UnaryExpr (void)
            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 '%' */
 {
@@ -1074,6 +1129,7 @@ static ExprNode* MultExpr (void)
        switch (CurTok.Tok) {
 
            case TOK_MUL:
+               Root = DoMul (Root);
                break;
 
            case TOK_DIV:
@@ -1226,15 +1282,52 @@ static ExprNode* AndExpr (void)
     /* 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 */
@@ -1252,15 +1345,52 @@ static ExprNode* XorExpr (void)
     /* 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 */
@@ -1278,15 +1408,52 @@ static ExprNode* OrExpr (void)
     /* 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 */
@@ -1304,14 +1471,36 @@ static ExprNode* BoolAndExpr (void)
     /* 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);
+
+       }
 
     }
 
@@ -1330,14 +1519,36 @@ static ExprNode* BoolOrExpr (void)
     /* 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);
+
+       }
 
     }
 
@@ -1382,7 +1593,7 @@ static ExprNode* ConditionalExpr (void)
        AppendItem (Root, Cond);
        AppendItem (Root, Expr1);
        AppendItem (Root, Expr2);
-                                
+
        /* Return the result */
        return Root;