Added license information preproc.h
git-svn-id: svn://svn.cc65.org/cc65/trunk@3135 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
@@ -57,6 +57,7 @@
|
|||||||
|
|
||||||
|
|
||||||
/* Predefined type strings */
|
/* Predefined type strings */
|
||||||
|
type type_schar[] = { T_SCHAR, T_END };
|
||||||
type type_uchar[] = { T_UCHAR, T_END };
|
type type_uchar[] = { T_UCHAR, T_END };
|
||||||
type type_int[] = { T_INT, T_END };
|
type type_int[] = { T_INT, T_END };
|
||||||
type type_uint[] = { T_UINT, T_END };
|
type type_uint[] = { T_UINT, T_END };
|
||||||
@@ -777,3 +778,23 @@ type* GetElementType (type* T)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
type* IntPromotion (type* T)
|
||||||
|
/* Apply the integer promotions to T and return the result. The returned type
|
||||||
|
* string may be T if there is no need to change it.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
/* We must have an int to apply int promotions */
|
||||||
|
PRECONDITION (IsClassInt (T));
|
||||||
|
|
||||||
|
/* An integer can represent all values from either signed or unsigned char,
|
||||||
|
* so convert chars to int and leave all other types alone.
|
||||||
|
*/
|
||||||
|
if (IsTypeChar (T)) {
|
||||||
|
return type_int;
|
||||||
|
} else {
|
||||||
|
return T;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -161,6 +161,7 @@ typedef unsigned short type;
|
|||||||
#define SIZEOF_PTR 2
|
#define SIZEOF_PTR 2
|
||||||
|
|
||||||
/* Predefined type strings */
|
/* Predefined type strings */
|
||||||
|
extern type type_schar[];
|
||||||
extern type type_uchar[];
|
extern type type_uchar[];
|
||||||
extern type type_int[];
|
extern type type_int[];
|
||||||
extern type type_uint[];
|
extern type type_uint[];
|
||||||
@@ -490,6 +491,11 @@ long GetElementCount (const type* T);
|
|||||||
type* GetElementType (type* T);
|
type* GetElementType (type* T);
|
||||||
/* Return the element type of the given array type. */
|
/* Return the element type of the given array type. */
|
||||||
|
|
||||||
|
type* IntPromotion (type* T);
|
||||||
|
/* Apply the integer promotions to T and return the result. The returned type
|
||||||
|
* string may be T if there is no need to change it.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* End of datatype.h */
|
/* End of datatype.h */
|
||||||
|
|||||||
204
src/cc65/expr.c
204
src/cc65/expr.c
@@ -68,17 +68,6 @@ static GenDesc GenOASGN = { TOK_OR_ASSIGN, GEN_NOPUSH, g_or };
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
/* Function forwards */
|
|
||||||
/*****************************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void hie0 (ExprDesc *lval);
|
|
||||||
/* Parse comma operator. */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* Helper functions */
|
/* Helper functions */
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
@@ -2277,7 +2266,7 @@ static void parsesub (ExprDesc* Expr)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void hie8 (ExprDesc* Expr)
|
void hie8 (ExprDesc* Expr)
|
||||||
/* Process + and - binary operators. */
|
/* Process + and - binary operators. */
|
||||||
{
|
{
|
||||||
hie9 (Expr);
|
hie9 (Expr);
|
||||||
@@ -2293,16 +2282,191 @@ static void hie8 (ExprDesc* Expr)
|
|||||||
|
|
||||||
|
|
||||||
static void hie7 (ExprDesc* Expr)
|
static void hie7 (ExprDesc* Expr)
|
||||||
/* Parse << and >>. */
|
/* Parse the << and >> operators. */
|
||||||
{
|
{
|
||||||
static const GenDesc hie7_ops [] = {
|
ExprDesc Expr2;
|
||||||
{ TOK_SHL, GEN_NOPUSH, g_asl },
|
CodeMark Mark1;
|
||||||
{ TOK_SHR, GEN_NOPUSH, g_asr },
|
CodeMark Mark2;
|
||||||
{ TOK_INVALID, 0, 0 }
|
token_t Tok; /* The operator token */
|
||||||
};
|
unsigned ltype, rtype, flags;
|
||||||
int UsedGen;
|
int rconst; /* Operand is a constant */
|
||||||
|
|
||||||
hie_internal (hie7_ops, Expr, hie8, &UsedGen);
|
|
||||||
|
/* Evaluate the lhs */
|
||||||
|
ExprWithCheck (hie8, Expr);
|
||||||
|
|
||||||
|
while (CurTok.Tok == TOK_SHL || CurTok.Tok == TOK_SHR) {
|
||||||
|
|
||||||
|
/* All operators that call this function expect an int on the lhs */
|
||||||
|
if (!IsClassInt (Expr->Type)) {
|
||||||
|
Error ("Integer expression expected");
|
||||||
|
ED_MakeConstAbsInt (Expr, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remember the operator token, then skip it */
|
||||||
|
Tok = CurTok.Tok;
|
||||||
|
NextToken ();
|
||||||
|
|
||||||
|
/* Get the lhs on stack */
|
||||||
|
Mark1 = GetCodePos ();
|
||||||
|
ltype = TypeOf (Expr->Type);
|
||||||
|
if (ED_IsConstAbs (Expr)) {
|
||||||
|
/* Constant value */
|
||||||
|
Mark2 = GetCodePos ();
|
||||||
|
g_push (ltype | CF_CONST, Expr->IVal);
|
||||||
|
} else {
|
||||||
|
/* Value not constant */
|
||||||
|
LoadExpr (CF_NONE, Expr);
|
||||||
|
Mark2 = GetCodePos ();
|
||||||
|
g_push (ltype, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the right hand side */
|
||||||
|
ExprWithCheck (hie8, &Expr2);
|
||||||
|
|
||||||
|
/* Check the type of the rhs */
|
||||||
|
if (!IsClassInt (Expr2.Type)) {
|
||||||
|
Error ("Integer expression expected");
|
||||||
|
ED_MakeConstAbsInt (&Expr2, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check for a constant right side expression */
|
||||||
|
rconst = ED_IsConstAbs (&Expr2);
|
||||||
|
if (!rconst) {
|
||||||
|
|
||||||
|
/* Not constant, load into the primary */
|
||||||
|
LoadExpr (CF_NONE, &Expr2);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
/* If the right hand side is constant, we can check a lot of
|
||||||
|
* things:
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* If the shift count is zero, nothing happens */
|
||||||
|
if (Expr2.IVal == 0) {
|
||||||
|
|
||||||
|
/* Result is already in Expr, remove the generated code */
|
||||||
|
RemoveCode (Mark1);
|
||||||
|
pop (ltype);
|
||||||
|
|
||||||
|
/* Done */
|
||||||
|
goto Next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the left hand side is a constant, the result is constant */
|
||||||
|
if (ED_IsConstAbs (Expr)) {
|
||||||
|
|
||||||
|
/* Evaluate the result */
|
||||||
|
Expr->IVal = kcalc (Tok, Expr->IVal, Expr2.IVal);
|
||||||
|
|
||||||
|
/* Both operands are constant, remove the generated code */
|
||||||
|
RemoveCode (Mark1);
|
||||||
|
pop (ltype);
|
||||||
|
|
||||||
|
/* Done */
|
||||||
|
goto Next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we're shifting to the left, and the shift count is larger
|
||||||
|
* or equal than the bit count of the integer type, the result
|
||||||
|
* is zero.
|
||||||
|
*/
|
||||||
|
if (Tok == TOK_SHL && Expr2.IVal >= (long) SizeOf (Expr->Type) * 8) {
|
||||||
|
|
||||||
|
/* Set the result */
|
||||||
|
ED_MakeConstAbs (Expr, 0, Expr->Type);
|
||||||
|
|
||||||
|
/* Result is zero, remove the generated code */
|
||||||
|
RemoveCode (Mark1);
|
||||||
|
pop (ltype);
|
||||||
|
|
||||||
|
/* Done */
|
||||||
|
goto Next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we're shifting an integer or unsigned to the right, the
|
||||||
|
* lhs has a const address, and the shift count is larger than 8,
|
||||||
|
* we can load just the high byte as a char with the correct
|
||||||
|
* signedness, and reduce the shift count by 8. If the remaining
|
||||||
|
* shift count is zero, we're done.
|
||||||
|
*/
|
||||||
|
if (Tok == TOK_SHR &&
|
||||||
|
IsTypeInt (Expr->Type) &&
|
||||||
|
ED_IsLVal (Expr) &&
|
||||||
|
(ED_IsLocConst (Expr) || ED_IsLocStack (Expr)) &&
|
||||||
|
Expr2.IVal >= 8) {
|
||||||
|
|
||||||
|
type* OldType;
|
||||||
|
|
||||||
|
/* Increase the address by one and decrease the shift count */
|
||||||
|
++Expr->IVal;
|
||||||
|
Expr2.IVal -= 8;
|
||||||
|
|
||||||
|
/* Replace the type of the expression temporarily by the
|
||||||
|
* corresponding char type.
|
||||||
|
*/
|
||||||
|
OldType = Expr->Type;
|
||||||
|
if (IsSignUnsigned (Expr->Type)) {
|
||||||
|
Expr->Type = type_uchar;
|
||||||
|
} else {
|
||||||
|
Expr->Type = type_schar;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove the generated load code */
|
||||||
|
RemoveCode (Mark1);
|
||||||
|
pop (ltype);
|
||||||
|
|
||||||
|
/* Generate again code for the load */
|
||||||
|
LoadExpr (CF_NONE, Expr);
|
||||||
|
|
||||||
|
/* Reset the type */
|
||||||
|
Expr->Type = OldType;
|
||||||
|
|
||||||
|
/* If the shift count is now zero, we're done */
|
||||||
|
if (Expr2.IVal == 0) {
|
||||||
|
/* Be sure to mark the value as in the primary */
|
||||||
|
goto Loaded;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Otherwise generate code to push the value */
|
||||||
|
Mark2 = GetCodePos ();
|
||||||
|
g_push (ltype, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the right hand side is a constant, remove the push of the
|
||||||
|
* primary register.
|
||||||
|
*/
|
||||||
|
rtype = TypeOf (Expr2.Type);
|
||||||
|
flags = 0;
|
||||||
|
if (rconst) {
|
||||||
|
flags |= CF_CONST;
|
||||||
|
rtype |= CF_CONST;
|
||||||
|
RemoveCode (Mark2);
|
||||||
|
pop (ltype);
|
||||||
|
ltype |= CF_REG; /* Value is in register */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Determine the type of the operation result. */
|
||||||
|
flags |= g_typeadjust (ltype, rtype);
|
||||||
|
|
||||||
|
/* Generate code */
|
||||||
|
switch (Tok) {
|
||||||
|
case TOK_SHL: g_asl (flags, Expr2.IVal); break;
|
||||||
|
case TOK_SHR: g_asr (flags, Expr2.IVal); break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Loaded:
|
||||||
|
/* We have a rvalue in the primary now */
|
||||||
|
ED_MakeRValExpr (Expr);
|
||||||
|
|
||||||
|
Next:
|
||||||
|
/* Get the type of the result */
|
||||||
|
Expr->Type = promoteint (Expr->Type, Expr2.Type);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -39,9 +39,6 @@ void Store (ExprDesc* Expr, const type* StoreType);
|
|||||||
* is NULL, use lval->Type instead.
|
* is NULL, use lval->Type instead.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void hie0 (ExprDesc* Expr);
|
|
||||||
/* Parse comma operator. */
|
|
||||||
|
|
||||||
int evalexpr (unsigned flags, void (*Func) (ExprDesc*), ExprDesc* Expr);
|
int evalexpr (unsigned flags, void (*Func) (ExprDesc*), ExprDesc* Expr);
|
||||||
/* Will evaluate an expression via the given function. If the result is a
|
/* Will evaluate an expression via the given function. If the result is a
|
||||||
* constant, 0 is returned and the value is put in the lval struct. If the
|
* constant, 0 is returned and the value is put in the lval struct. If the
|
||||||
@@ -76,9 +73,15 @@ void ConstAbsIntExpr (void (*Func) (ExprDesc*), ExprDesc* Expr);
|
|||||||
void hie10 (ExprDesc* lval);
|
void hie10 (ExprDesc* lval);
|
||||||
/* Handle ++, --, !, unary - etc. */
|
/* Handle ++, --, !, unary - etc. */
|
||||||
|
|
||||||
|
void hie8 (ExprDesc* Expr);
|
||||||
|
/* Process + and - binary operators. */
|
||||||
|
|
||||||
void hie1 (ExprDesc* lval);
|
void hie1 (ExprDesc* lval);
|
||||||
/* Parse first level of expression hierarchy. */
|
/* Parse first level of expression hierarchy. */
|
||||||
|
|
||||||
|
void hie0 (ExprDesc* Expr);
|
||||||
|
/* Parse comma operator. */
|
||||||
|
|
||||||
void DefineData (ExprDesc* lval);
|
void DefineData (ExprDesc* lval);
|
||||||
/* Output a data definition for the given expression */
|
/* Output a data definition for the given expression */
|
||||||
|
|
||||||
|
|||||||
@@ -209,16 +209,6 @@ int ED_IsConst (const ExprDesc* Expr)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
int ED_IsConstAbs (const ExprDesc* Expr)
|
|
||||||
/* Return true if the expression denotes a constant absolute value. This can be
|
|
||||||
* a numeric constant, cast to any type.
|
|
||||||
*/
|
|
||||||
{
|
|
||||||
return (Expr->Flags & (E_MASK_LOC|E_MASK_RTYPE)) == (E_LOC_ABS|E_RTYPE_RVAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int ED_IsConstAbsInt (const ExprDesc* Expr)
|
int ED_IsConstAbsInt (const ExprDesc* Expr)
|
||||||
/* Return true if the expression is a constant (numeric) integer. */
|
/* Return true if the expression is a constant (numeric) integer. */
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -307,10 +307,18 @@ int ED_IsConst (const ExprDesc* Expr);
|
|||||||
* similar.
|
* similar.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int ED_IsConstAbs (const ExprDesc* Expr);
|
#if defined(HAVE_INLINE)
|
||||||
|
INLINE int ED_IsConstAbs (const ExprDesc* Expr)
|
||||||
/* Return true if the expression denotes a constant absolute value. This can be
|
/* Return true if the expression denotes a constant absolute value. This can be
|
||||||
* a numeric constant, cast to any type.
|
* a numeric constant, cast to any type.
|
||||||
*/
|
*/
|
||||||
|
{
|
||||||
|
return (Expr->Flags & (E_MASK_LOC|E_MASK_RTYPE)) == (E_LOC_ABS|E_RTYPE_RVAL);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
# define ED_IsConstAbs(E) \
|
||||||
|
(((E)->Flags & (E_MASK_LOC|E_MASK_RTYPE)) == (E_LOC_ABS|E_RTYPE_RVAL))
|
||||||
|
#endif
|
||||||
|
|
||||||
int ED_IsConstAbsInt (const ExprDesc* Expr);
|
int ED_IsConstAbsInt (const ExprDesc* Expr);
|
||||||
/* Return true if the expression is a constant (numeric) integer. */
|
/* Return true if the expression is a constant (numeric) integer. */
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
|
/*
|
||||||
/* C pre-processor functions */
|
* C pre-processor functions.
|
||||||
|
* Portions of this code are copyright (C) 1989 John R. Dunning.
|
||||||
|
* See copyleft.jrd for license information.
|
||||||
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|||||||
@@ -1,8 +1,35 @@
|
|||||||
/*
|
/*****************************************************************************/
|
||||||
* preproc.h
|
/* */
|
||||||
*
|
/* preproc.h */
|
||||||
* Ullrich von Bassewitz, 07.06.1998
|
/* */
|
||||||
*/
|
/* C preprocessor */
|
||||||
|
/* */
|
||||||
|
/* */
|
||||||
|
/* */
|
||||||
|
/* (C) 1998-2004 Ullrich von Bassewitz */
|
||||||
|
/* R<>merstra<72>e 52 */
|
||||||
|
/* D-70794 Filderstadt */
|
||||||
|
/* EMail: uz@cc65.org */
|
||||||
|
/* */
|
||||||
|
/* */
|
||||||
|
/* This software is provided 'as-is', without any expressed or implied */
|
||||||
|
/* warranty. In no event will the authors be held liable for any damages */
|
||||||
|
/* arising from the use of this software. */
|
||||||
|
/* */
|
||||||
|
/* Permission is granted to anyone to use this software for any purpose, */
|
||||||
|
/* including commercial applications, and to alter it and redistribute it */
|
||||||
|
/* freely, subject to the following restrictions: */
|
||||||
|
/* */
|
||||||
|
/* 1. The origin of this software must not be misrepresented; you must not */
|
||||||
|
/* claim that you wrote the original software. If you use this software */
|
||||||
|
/* in a product, an acknowledgment in the product documentation would be */
|
||||||
|
/* appreciated but is not required. */
|
||||||
|
/* 2. Altered source versions must be plainly marked as such, and must not */
|
||||||
|
/* be misrepresented as being the original software. */
|
||||||
|
/* 3. This notice may not be removed or altered from any source */
|
||||||
|
/* distribution. */
|
||||||
|
/* */
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -17,7 +44,7 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Set when the pp calls expr() recursively */
|
/* Set when the preprocessor calls ConstExpr() recursively */
|
||||||
extern unsigned char Preprocessing;
|
extern unsigned char Preprocessing;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -195,6 +195,12 @@ void TypeConversion (ExprDesc* Expr, type* NewType)
|
|||||||
Error ("Illegal type");
|
Error ("Illegal type");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If both types are equal, no conversion is needed */
|
||||||
|
if (TypeCmp (Expr->Type, NewType) >= TC_EQUAL) {
|
||||||
|
/* We're already done */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Check for conversion problems */
|
/* Check for conversion problems */
|
||||||
if (IsClassInt (NewType)) {
|
if (IsClassInt (NewType)) {
|
||||||
|
|
||||||
@@ -202,7 +208,13 @@ void TypeConversion (ExprDesc* Expr, type* NewType)
|
|||||||
if (IsClassPtr (Expr->Type)) {
|
if (IsClassPtr (Expr->Type)) {
|
||||||
/* Pointer -> int conversion */
|
/* Pointer -> int conversion */
|
||||||
Warning ("Converting pointer to integer without a cast");
|
Warning ("Converting pointer to integer without a cast");
|
||||||
} else if (!IsClassInt (Expr->Type)) {
|
} else if (!IsClassInt (Expr->Type) && !IsClassFloat (Expr->Type)) {
|
||||||
|
Error ("Incompatible types");
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (IsClassFloat (NewType)) {
|
||||||
|
|
||||||
|
if (!IsClassFloat (Expr->Type) && !IsClassInt (Expr->Type)) {
|
||||||
Error ("Incompatible types");
|
Error ("Incompatible types");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user