1
0
mirror of https://github.com/cc65/cc65.git synced 2025-01-10 19:29:45 +00:00

Some changes in the way, types and type strings are handled.

Check for and honour const in several places: Assignment to const is flagged
with an error. Const data is placed in the rodata segment.


git-svn-id: svn://svn.cc65.org/cc65/trunk@252 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
cuz 2000-08-01 18:45:08 +00:00
parent 5ee8618510
commit 85417b6d1b
11 changed files with 310 additions and 229 deletions

View File

@ -136,7 +136,7 @@ static void Parse (void)
/* Get the symbol flags */ /* Get the symbol flags */
SymFlags = Spec.StorageClass; SymFlags = Spec.StorageClass;
if (IsFunc (Decl.Type)) { if (IsTypeFunc (Decl.Type)) {
SymFlags |= SC_FUNC; SymFlags |= SC_FUNC;
} else { } else {
if (NeedStorage) { if (NeedStorage) {
@ -161,19 +161,23 @@ static void Parse (void)
* void types in non ANSI mode. * void types in non ANSI mode.
*/ */
if (Size == 0) { if (Size == 0) {
if (!IsTypeVoid (Decl.Type)) { if (!IsTypeVoid (Decl.Type)) {
if (!IsArray (Decl.Type)) { if (!IsTypeArray (Decl.Type)) {
/* Size is unknown and not an array */ /* Size is unknown and not an array */
Error (ERR_UNKNOWN_SIZE); Error (ERR_UNKNOWN_SIZE);
} }
} else if (ANSI) { } else if (ANSI) {
/* We cannot declare variables of type void */ /* We cannot declare variables of type void */
Error (ERR_ILLEGAL_TYPE); Error (ERR_ILLEGAL_TYPE);
} }
} }
/* Switch to the data segment */ /* Switch to the data or rodata segment */
g_usedata (); if (IsConst (Decl.Type)) {
g_userodata ();
} else {
g_usedata ();
}
/* Define a label */ /* Define a label */
g_defgloblabel (Entry->Name); g_defgloblabel (Entry->Name);
@ -215,7 +219,7 @@ static void Parse (void)
} }
/* Function declaration? */ /* Function declaration? */
if (IsFunc (Decl.Type)) { if (IsTypeFunc (Decl.Type)) {
/* Function */ /* Function */
if (!comma) { if (!comma) {

View File

@ -222,45 +222,49 @@ static type PrintTypeComp (FILE* F, type T, type Mask, const char* Name)
void PrintType (FILE* F, const type* Type) void PrintType (FILE* F, const type* Type)
/* Output translation of type array. */ /* Output translation of type array. */
{ {
/* If the first field has const and/or volatile qualifiers, print and type T;
* remove them.
*/
type T = *Type++;
T = PrintTypeComp (F, T, T_QUAL_CONST, "const");
T = PrintTypeComp (F, T, T_QUAL_VOLATILE, "volatile");
/* Walk over the complete string */ /* Walk over the complete string */
do { while ((T = *Type++) != T_END) {
/* Check for the sizes */ /* Print any qualifiers */
T = PrintTypeComp (F, T, T_SIZE_SHORT, "short"); T = PrintTypeComp (F, T, T_QUAL_CONST, "const");
T = PrintTypeComp (F, T, T_SIZE_LONG, "long"); T = PrintTypeComp (F, T, T_QUAL_VOLATILE, "volatile");
T = PrintTypeComp (F, T, T_SIZE_LONGLONG, "long long");
/* Signedness */ /* Signedness */
T = PrintTypeComp (F, T, T_SIGN_SIGNED, "signed"); T = PrintTypeComp (F, T, T_SIGN_SIGNED, "signed");
T = PrintTypeComp (F, T, T_SIGN_UNSIGNED, "unsigned"); T = PrintTypeComp (F, T, T_SIGN_UNSIGNED, "unsigned");
/* Now check the real type */ /* Now check the real type */
switch (T & T_MASK_TYPE) { switch (T & T_MASK_TYPE) {
case T_TYPE_CHAR: case T_TYPE_CHAR:
fprintf (F, "char\n"); fprintf (F, "char\n");
break; break;
case T_TYPE_INT: case T_TYPE_SHORT:
fprintf (F, "int\n"); fprintf (F, "short\n");
break; break;
case T_TYPE_FLOAT: case T_TYPE_INT:
fprintf (F, "float\n"); fprintf (F, "int\n");
break; break;
case T_TYPE_DOUBLE: case T_TYPE_LONG:
fprintf (F, "double\n"); fprintf (F, "long\n");
break; break;
case T_TYPE_LONGLONG:
fprintf (F, "long long\n");
break;
case T_TYPE_FLOAT:
fprintf (F, "float\n");
break;
case T_TYPE_DOUBLE:
fprintf (F, "double\n");
break;
case T_TYPE_VOID: case T_TYPE_VOID:
fprintf (F, "void\n"); fprintf (F, "void\n");
break; break;
case T_TYPE_STRUCT: case T_TYPE_STRUCT:
fprintf (F, "struct %s\n", ((SymEntry*) DecodePtr (Type))->Name); fprintf (F, "struct %s\n", ((SymEntry*) DecodePtr (Type))->Name);
Type += DECODE_SIZE; Type += DECODE_SIZE;
break; break;
case T_TYPE_UNION: case T_TYPE_UNION:
fprintf (F, "union %s\n", ((SymEntry*) DecodePtr (Type))->Name); fprintf (F, "union %s\n", ((SymEntry*) DecodePtr (Type))->Name);
@ -281,10 +285,7 @@ void PrintType (FILE* F, const type* Type)
fprintf (F, "unknown type: %04X\n", T); fprintf (F, "unknown type: %04X\n", T);
} }
/* Get the next type element */ }
T = *Type++;
} while (T != T_END);
} }
@ -345,7 +346,7 @@ void* DecodePtr (const type* Type)
int HasEncode (const type* Type) int HasEncode (const type* Type)
/* Return true if the given type has encoded data */ /* Return true if the given type has encoded data */
{ {
return IsStruct (Type) || IsArray (Type) || IsFunc (Type); return IsClassStruct (Type) || IsTypeArray (Type) || IsTypeFunc (Type);
} }
@ -358,15 +359,23 @@ void CopyEncode (const type* Source, type* Target)
type UnqualifiedType (type T)
/* Return the unqalified type */
{
return (T & ~T_MASK_QUAL);
}
unsigned SizeOf (const type* T) unsigned SizeOf (const type* T)
/* Compute size of object represented by type array. */ /* Compute size of object represented by type array. */
{ {
SymEntry* Entry; SymEntry* Entry;
switch (*T) { switch (UnqualifiedType (T[0])) {
case T_VOID: case T_VOID:
Error (ERR_ILLEGAL_SIZE); Error (ERR_ILLEGAL_SIZE);
return 0; return 0;
case T_SCHAR: case T_SCHAR:
@ -419,7 +428,7 @@ unsigned PSizeOf (const type* T)
CHECK ((*T & T_CLASS_PTR) != 0); CHECK ((*T & T_CLASS_PTR) != 0);
/* Skip the pointer or array token itself */ /* Skip the pointer or array token itself */
if (*T == T_ARRAY) { if (IsTypeArray (T)) {
return SizeOf (T + DECODE_SIZE + 1); return SizeOf (T + DECODE_SIZE + 1);
} else { } else {
return SizeOf (T + 1); return SizeOf (T + 1);
@ -428,12 +437,12 @@ unsigned PSizeOf (const type* T)
unsigned TypeOf (const type* Type) unsigned TypeOf (const type* T)
/* Get the code generator base type of the object */ /* Get the code generator base type of the object */
{ {
FuncDesc* F; FuncDesc* F;
switch (*Type) { switch (UnqualifiedType (T[0])) {
case T_SCHAR: case T_SCHAR:
return CF_CHAR; return CF_CHAR;
@ -459,7 +468,7 @@ unsigned TypeOf (const type* Type)
return CF_LONG | CF_UNSIGNED; return CF_LONG | CF_UNSIGNED;
case T_FUNC: case T_FUNC:
F = DecodePtr (Type+1); F = DecodePtr (T+1);
return (F->Flags & FD_ELLIPSIS)? 0 : CF_FIXARGC; return (F->Flags & FD_ELLIPSIS)? 0 : CF_FIXARGC;
case T_STRUCT: case T_STRUCT:
@ -484,7 +493,7 @@ type* Indirect (type* T)
CHECK ((*T & T_MASK_CLASS) == T_CLASS_PTR); CHECK ((*T & T_MASK_CLASS) == T_CLASS_PTR);
/* Skip the pointer or array token itself */ /* Skip the pointer or array token itself */
if (*T == T_ARRAY) { if (IsTypeArray (T)) {
return T + DECODE_SIZE + 1; return T + DECODE_SIZE + 1;
} else { } else {
return T + 1; return T + 1;
@ -493,15 +502,29 @@ type* Indirect (type* T)
int IsTypeVoid (const type* T) int IsConst (const type* T)
/* Return true if this is a void type */ /* Return true if the given type has a const memory image */
{ {
return (T[0] == T_VOID && T[1] == T_END); /* If this is an array, look at the element type, otherwise look at the
* type itself.
*/
if (IsTypeArray (T)) {
T += DECODE_SIZE + 1;
}
return ((T[0] & T_QUAL_CONST) == T_QUAL_CONST);
} }
int IsPtr (const type* T) int IsTypeVoid (const type* T)
/* Return true if this is a void type */
{
return ((T[0] & T_MASK_TYPE) == T_TYPE_VOID && T[1] == T_END);
}
int IsClassPtr (const type* T)
/* Return true if this is a pointer type */ /* Return true if this is a pointer type */
{ {
return (T[0] & T_MASK_CLASS) == T_CLASS_PTR; return (T[0] & T_MASK_CLASS) == T_CLASS_PTR;
@ -509,7 +532,7 @@ int IsPtr (const type* T)
int IsChar (const type* T) int IsTypeChar (const type* T)
/* Return true if this is a character type */ /* Return true if this is a character type */
{ {
return (T[0] & T_MASK_TYPE) == T_TYPE_CHAR && T[1] == T_END; return (T[0] & T_MASK_TYPE) == T_TYPE_CHAR && T[1] == T_END;
@ -517,7 +540,7 @@ int IsChar (const type* T)
int IsInt (const type* T) int IsClassInt (const type* T)
/* Return true if this is an integer type */ /* Return true if this is an integer type */
{ {
return (T[0] & T_MASK_CLASS) == T_CLASS_INT; return (T[0] & T_MASK_CLASS) == T_CLASS_INT;
@ -525,10 +548,10 @@ int IsInt (const type* T)
int IsLong (const type* T) int IsTypeLong (const type* T)
/* Return true if this is a long type (signed or unsigned) */ /* Return true if this is a long type (signed or unsigned) */
{ {
return (T[0] & T_MASK_SIZE) == T_SIZE_LONG; return (T[0] & T_MASK_TYPE) == T_TYPE_LONG;
} }
@ -541,7 +564,7 @@ int IsUnsigned (const type* T)
int IsStruct (const type* T) int IsClassStruct (const type* T)
/* Return true if this is a struct type */ /* Return true if this is a struct type */
{ {
return (T[0] & T_MASK_CLASS) == T_CLASS_STRUCT; return (T[0] & T_MASK_CLASS) == T_CLASS_STRUCT;
@ -549,10 +572,10 @@ int IsStruct (const type* T)
int IsFunc (const type* T) int IsTypeFunc (const type* T)
/* Return true if this is a function type */ /* Return true if this is a function class */
{ {
return (T[0] == T_FUNC); return ((T[0] & T_MASK_TYPE) == T_TYPE_FUNC);
} }
@ -561,25 +584,25 @@ int IsFastCallFunc (const type* T)
/* Return true if this is a function type with __fastcall__ calling conventions */ /* Return true if this is a function type with __fastcall__ calling conventions */
{ {
FuncDesc* F; FuncDesc* F;
CHECK (T[0] == T_FUNC); CHECK (IsTypeFunc (T));
F = DecodePtr (T+1); F = DecodePtr (T+1);
return (F->Flags & FD_FASTCALL) != 0; return (F->Flags & FD_FASTCALL) != 0;
} }
int IsFuncPtr (const type* T) int IsTypeFuncPtr (const type* T)
/* Return true if this is a function pointer */ /* Return true if this is a function pointer */
{ {
return (T[0] == T_PTR && T[1] == T_FUNC); return ((T[0] & T_MASK_TYPE) == T_TYPE_PTR && (T[1] & T_MASK_TYPE) == T_TYPE_FUNC);
} }
int IsArray (const type* T) int IsTypeArray (const type* T)
/* Return true if this is an array type */ /* Return true if this is an array type */
{ {
return (T[0] == T_ARRAY); return ((T[0] & T_MASK_TYPE) == T_TYPE_ARRAY);
} }

View File

@ -56,16 +56,19 @@ enum {
// Basic types // Basic types
T_TYPE_NONE = 0x0000, T_TYPE_NONE = 0x0000,
T_TYPE_CHAR = 0x0001, T_TYPE_CHAR = 0x0001,
T_TYPE_INT = 0x0002, T_TYPE_SHORT = 0x0002,
T_TYPE_ENUM = 0x0003, T_TYPE_INT = 0x0003,
T_TYPE_FLOAT = 0x0004, T_TYPE_LONG = 0x0004,
T_TYPE_DOUBLE = 0x0005, T_TYPE_LONGLONG = 0x0005,
T_TYPE_VOID = 0x0006, T_TYPE_ENUM = 0x0006,
T_TYPE_STRUCT = 0x0007, T_TYPE_FLOAT = 0x0007,
T_TYPE_UNION = 0x0008, T_TYPE_DOUBLE = 0x0008,
T_TYPE_ARRAY = 0x0009, T_TYPE_VOID = 0x0009,
T_TYPE_PTR = 0x000A, T_TYPE_STRUCT = 0x000A,
T_TYPE_FUNC = 0x000B, T_TYPE_UNION = 0x000B,
T_TYPE_ARRAY = 0x000C,
T_TYPE_PTR = 0x000D,
T_TYPE_FUNC = 0x000E,
T_MASK_TYPE = 0x001F, T_MASK_TYPE = 0x001F,
// Type classes // Type classes
@ -97,26 +100,26 @@ enum {
T_MASK_QUAL = 0x3000, T_MASK_QUAL = 0x3000,
// Types // Types
T_CHAR = T_TYPE_CHAR | T_CLASS_INT | T_SIGN_UNSIGNED | T_SIZE_NONE, T_CHAR = T_TYPE_CHAR | T_CLASS_INT | T_SIGN_UNSIGNED | T_SIZE_NONE,
T_SCHAR = T_TYPE_CHAR | T_CLASS_INT | T_SIGN_SIGNED | T_SIZE_NONE, T_SCHAR = T_TYPE_CHAR | T_CLASS_INT | T_SIGN_SIGNED | T_SIZE_NONE,
T_UCHAR = T_TYPE_CHAR | T_CLASS_INT | T_SIGN_UNSIGNED | T_SIZE_NONE, T_UCHAR = T_TYPE_CHAR | T_CLASS_INT | T_SIGN_UNSIGNED | T_SIZE_NONE,
T_SHORT = T_TYPE_INT | T_CLASS_INT | T_SIGN_SIGNED | T_SIZE_SHORT, T_SHORT = T_TYPE_SHORT | T_CLASS_INT | T_SIGN_SIGNED | T_SIZE_SHORT,
T_USHORT = T_TYPE_INT | T_CLASS_INT | T_SIGN_UNSIGNED | T_SIZE_SHORT, T_USHORT = T_TYPE_SHORT | T_CLASS_INT | T_SIGN_UNSIGNED | T_SIZE_SHORT,
T_INT = T_TYPE_INT | T_CLASS_INT | T_SIGN_SIGNED | T_SIZE_NONE, T_INT = T_TYPE_INT | T_CLASS_INT | T_SIGN_SIGNED | T_SIZE_NONE,
T_UINT = T_TYPE_INT | T_CLASS_INT | T_SIGN_UNSIGNED | T_SIZE_NONE, T_UINT = T_TYPE_INT | T_CLASS_INT | T_SIGN_UNSIGNED | T_SIZE_NONE,
T_LONG = T_TYPE_INT | T_CLASS_INT | T_SIGN_SIGNED | T_SIZE_LONG, T_LONG = T_TYPE_LONG | T_CLASS_INT | T_SIGN_SIGNED | T_SIZE_LONG,
T_ULONG = T_TYPE_INT | T_CLASS_INT | T_SIGN_UNSIGNED | T_SIZE_LONG, T_ULONG = T_TYPE_LONG | T_CLASS_INT | T_SIGN_UNSIGNED | T_SIZE_LONG,
T_LONGLONG = T_TYPE_INT | T_CLASS_INT | T_SIGN_SIGNED | T_SIZE_LONGLONG, T_LONGLONG = T_TYPE_LONGLONG | T_CLASS_INT | T_SIGN_SIGNED | T_SIZE_LONGLONG,
T_ULONGLONG = T_TYPE_INT | T_CLASS_INT | T_SIGN_UNSIGNED | T_SIZE_LONGLONG, T_ULONGLONG = T_TYPE_LONGLONG | T_CLASS_INT | T_SIGN_UNSIGNED | T_SIZE_LONGLONG,
T_ENUM = T_TYPE_ENUM | T_CLASS_INT | T_SIGN_SIGNED | T_SIZE_NONE, T_ENUM = T_TYPE_ENUM | T_CLASS_INT | T_SIGN_SIGNED | T_SIZE_NONE,
T_FLOAT = T_TYPE_FLOAT | T_CLASS_FLOAT | T_SIGN_NONE | T_SIZE_NONE, T_FLOAT = T_TYPE_FLOAT | T_CLASS_FLOAT | T_SIGN_NONE | T_SIZE_NONE,
T_DOUBLE = T_TYPE_DOUBLE | T_CLASS_FLOAT | T_SIGN_NONE | T_SIZE_NONE, T_DOUBLE = T_TYPE_DOUBLE | T_CLASS_FLOAT | T_SIGN_NONE | T_SIZE_NONE,
T_VOID = T_TYPE_VOID | T_CLASS_NONE | T_SIGN_NONE | T_SIZE_NONE, T_VOID = T_TYPE_VOID | T_CLASS_NONE | T_SIGN_NONE | T_SIZE_NONE,
T_STRUCT = T_TYPE_STRUCT | T_CLASS_STRUCT | T_SIGN_NONE | T_SIZE_NONE, T_STRUCT = T_TYPE_STRUCT | T_CLASS_STRUCT | T_SIGN_NONE | T_SIZE_NONE,
T_UNION = T_TYPE_UNION | T_CLASS_STRUCT | T_SIGN_NONE | T_SIZE_NONE, T_UNION = T_TYPE_UNION | T_CLASS_STRUCT | T_SIGN_NONE | T_SIZE_NONE,
T_ARRAY = T_TYPE_ARRAY | T_CLASS_PTR | T_SIGN_NONE | T_SIZE_NONE, T_ARRAY = T_TYPE_ARRAY | T_CLASS_PTR | T_SIGN_NONE | T_SIZE_NONE,
T_PTR = T_TYPE_PTR | T_CLASS_PTR | T_SIGN_NONE | T_SIZE_NONE, T_PTR = T_TYPE_PTR | T_CLASS_PTR | T_SIGN_NONE | T_SIZE_NONE,
T_FUNC = T_TYPE_FUNC | T_CLASS_FUNC | T_SIGN_NONE | T_SIZE_NONE, T_FUNC = T_TYPE_FUNC | T_CLASS_FUNC | T_SIGN_NONE | T_SIZE_NONE,
}; };
@ -207,6 +210,9 @@ int HasEncode (const type* Type);
void CopyEncode (const type* Source, type* Target); void CopyEncode (const type* Source, type* Target);
/* Copy encoded data from Source to Target */ /* Copy encoded data from Source to Target */
type UnqualifiedType (type T);
/* Return the unqalified type */
unsigned SizeOf (const type* Type); unsigned SizeOf (const type* Type);
/* Compute size of object represented by type array. */ /* Compute size of object represented by type array. */
@ -221,37 +227,40 @@ type* Indirect (type* Type);
* given type points to. * given type points to.
*/ */
int IsConst (const type* T);
/* Return true if the given type has a const memory image */
int IsTypeVoid (const type* Type); int IsTypeVoid (const type* Type);
/* Return true if this is a void type */ /* Return true if this is a void type */
int IsPtr (const type* Type); int IsClassPtr (const type* Type);
/* Return true if this is a pointer type */ /* Return true if this is a pointer type */
int IsChar (const type* Type); int IsTypeChar (const type* Type);
/* Return true if this is a character type */ /* Return true if this is a character type */
int IsInt (const type* Type); int IsClassInt (const type* Type);
/* Return true if this is an integer type */ /* Return true if this is an integer type */
int IsLong (const type* Type); int IsTypeLong (const type* Type);
/* Return true if this is a long type (signed or unsigned) */ /* Return true if this is a long type (signed or unsigned) */
int IsUnsigned (const type* Type); int IsUnsigned (const type* Type);
/* Return true if this is an unsigned type */ /* Return true if this is an unsigned type */
int IsStruct (const type* Type); int IsClassStruct (const type* Type);
/* Return true if this is a struct type */ /* Return true if this is a struct type */
int IsFunc (const type* Type); int IsTypeFunc (const type* Type);
/* Return true if this is a function type */ /* Return true if this is a function class */
int IsFastCallFunc (const type* Type); int IsFastCallFunc (const type* Type);
/* Return true if this is a function type with __fastcall__ calling conventions */ /* Return true if this is a function type with __fastcall__ calling conventions */
int IsFuncPtr (const type* Type); int IsTypeFuncPtr (const type* Type);
/* Return true if this is a function pointer */ /* Return true if this is a function pointer */
int IsArray (const type* Type); int IsTypeArray (const type* Type);
/* Return true if this is an array type */ /* Return true if this is an array type */
struct FuncDesc* GetFuncDesc (const type* Type); struct FuncDesc* GetFuncDesc (const type* Type);

View File

@ -11,8 +11,10 @@
#include <errno.h> #include <errno.h>
#include <ctype.h> #include <ctype.h>
#include "../common/xmalloc.h" /* common */
#include "xmalloc.h"
/* cc65 */
#include "anonname.h" #include "anonname.h"
#include "codegen.h" #include "codegen.h"
#include "datatype.h" #include "datatype.h"
@ -46,13 +48,39 @@ static void ParseTypeSpec (DeclSpec* D, int Default);
static void optional_modifiers (void) static type OptionalQualifiers (type Q)
/* Eat optional "const" or "volatile" tokens */ /* Read type qualifiers if we have any */
{ {
while (curtok == TOK_CONST || curtok == TOK_VOLATILE) { while (curtok == TOK_CONST || curtok == TOK_VOLATILE) {
/* Skip it */
NextToken (); switch (curtok) {
case TOK_CONST:
if (Q & T_QUAL_CONST) {
Error (ERR_DUPLICATE_QUALIFIER, "const");
}
Q |= T_QUAL_CONST;
break;
case TOK_VOLATILE:
if (Q & T_QUAL_VOLATILE) {
Error (ERR_DUPLICATE_QUALIFIER, "volatile");
}
Q |= T_QUAL_VOLATILE;
break;
default:
/* Keep gcc silent */
break;
}
/* Skip the token */
NextToken ();
} }
/* Return the qualifiers read */
return Q;
} }
@ -93,7 +121,7 @@ static void InitDeclaration (Declaration* D)
/* Initialize the Declaration struct for use */ /* Initialize the Declaration struct for use */
{ {
D->Ident[0] = '\0'; D->Ident[0] = '\0';
D->Type[0] = T_END; D->Type[0] = T_END;
D->T = D->Type; D->T = D->Type;
} }
@ -278,15 +306,16 @@ static SymEntry* ParseStructDecl (const char* Name, type StructType)
static void ParseTypeSpec (DeclSpec* D, int Default) static void ParseTypeSpec (DeclSpec* D, int Default)
/* Parse a type specificier */ /* Parse a type specificier */
{ {
ident Ident; ident Ident;
SymEntry* Entry; SymEntry* Entry;
type StructType; type StructType;
type Qualifiers; /* Type qualifiers */
/* Assume we have an explicit type */ /* Assume we have an explicit type */
D->Flags &= ~DS_DEF_TYPE; D->Flags &= ~DS_DEF_TYPE;
/* Skip const or volatile modifiers if needed */ /* Read type qualifiers if we have any */
optional_modifiers (); Qualifiers = OptionalQualifiers (T_QUAL_NONE);
/* Look at the data type */ /* Look at the data type */
switch (curtok) { switch (curtok) {
@ -306,29 +335,29 @@ static void ParseTypeSpec (DeclSpec* D, int Default)
case TOK_LONG: case TOK_LONG:
NextToken (); NextToken ();
if (curtok == TOK_UNSIGNED) { if (curtok == TOK_UNSIGNED) {
NextToken (); NextToken ();
optionalint (); optionalint ();
D->Type[0] = T_ULONG; D->Type[0] = T_ULONG;
D->Type[1] = T_END; D->Type[1] = T_END;
} else { } else {
optionalsigned (); optionalsigned ();
optionalint (); optionalint ();
D->Type[0] = T_LONG; D->Type[0] = T_LONG;
D->Type[1] = T_END; D->Type[1] = T_END;
} }
break; break;
case TOK_SHORT: case TOK_SHORT:
NextToken (); NextToken ();
if (curtok == TOK_UNSIGNED) { if (curtok == TOK_UNSIGNED) {
NextToken (); NextToken ();
optionalint (); optionalint ();
D->Type[0] = T_USHORT; D->Type[0] = T_USHORT;
D->Type[1] = T_END; D->Type[1] = T_END;
} else { } else {
optionalsigned (); optionalsigned ();
optionalint (); optionalint ();
D->Type[0] = T_SHORT; D->Type[0] = T_SHORT;
D->Type[1] = T_END; D->Type[1] = T_END;
} }
break; break;
@ -480,6 +509,9 @@ static void ParseTypeSpec (DeclSpec* D, int Default)
} }
break; break;
} }
/* There may also be qualifiers *after* the initial type */
D->Type[0] |= OptionalQualifiers (Qualifiers);
} }
@ -489,7 +521,7 @@ static type* ParamTypeCvt (type* T)
* resulting type. * resulting type.
*/ */
{ {
if (IsArray (T)) { if (IsTypeArray (T)) {
T += DECODE_SIZE; T += DECODE_SIZE;
T[0] = T_PTR; T[0] = T_PTR;
} }
@ -717,12 +749,14 @@ static FuncDesc* ParseFuncDecl (void)
static void Decl (Declaration* D, unsigned Mode) static void Decl (Declaration* D, unsigned Mode)
/* Recursively process declarators. Build a type array in reverse order. */ /* Recursively process declarators. Build a type array in reverse order. */
{ {
if (curtok == TOK_STAR) { if (curtok == TOK_STAR) {
type T = T_PTR;
NextToken (); NextToken ();
/* Allow optional const or volatile modifiers */ /* Allow optional const or volatile qualifiers */
optional_modifiers (); T |= OptionalQualifiers (T_QUAL_NONE);
Decl (D, Mode); Decl (D, Mode);
*D->T++ = T_PTR; *D->T++ = T;
return; return;
} else if (curtok == TOK_LPAREN) { } else if (curtok == TOK_LPAREN) {
NextToken (); NextToken ();
@ -736,7 +770,7 @@ static void Decl (Declaration* D, unsigned Mode)
/* Parse the function */ /* Parse the function */
Decl (D, Mode); Decl (D, Mode);
/* Set the fastcall flag */ /* Set the fastcall flag */
if (!IsFunc (T)) { if (!IsTypeFunc (T)) {
Error (ERR_ILLEGAL_MODIFIER); Error (ERR_ILLEGAL_MODIFIER);
} else { } else {
FuncDesc* F = DecodePtr (T+1); FuncDesc* F = DecodePtr (T+1);
@ -840,7 +874,7 @@ void ParseDecl (const DeclSpec* Spec, Declaration* D, unsigned Mode)
TypeCpy (D->T, Spec->Type); TypeCpy (D->T, Spec->Type);
/* Check the size of the generated type */ /* Check the size of the generated type */
if (!IsFunc (D->Type) && !IsTypeVoid (D->Type) && SizeOf (D->Type) >= 0x10000) { if (!IsTypeFunc (D->Type) && !IsTypeVoid (D->Type) && SizeOf (D->Type) >= 0x10000) {
Error (ERR_ILLEGAL_SIZE); Error (ERR_ILLEGAL_SIZE);
} }
} }
@ -979,10 +1013,8 @@ static void ParseStructInit (type* Type)
void ParseInit (type* T)
/* Parse initialization of variables. */
void ParseInit (type *tptr)
/* Parse initialization of variables */
{ {
int count; int count;
struct expent lval; struct expent lval;
@ -990,7 +1022,7 @@ void ParseInit (type *tptr)
const char* str; const char* str;
int sz; int sz;
switch (*tptr) { switch (UnqualifiedType (*T)) {
case T_SCHAR: case T_SCHAR:
case T_UCHAR: case T_UCHAR:
@ -999,7 +1031,7 @@ void ParseInit (type *tptr)
/* Make it byte sized */ /* Make it byte sized */
lval.e_const &= 0xFF; lval.e_const &= 0xFF;
} }
assignadjust (tptr, &lval); assignadjust (T, &lval);
DefineData (&lval); DefineData (&lval);
break; break;
@ -1013,7 +1045,7 @@ void ParseInit (type *tptr)
/* Make it word sized */ /* Make it word sized */
lval.e_const &= 0xFFFF; lval.e_const &= 0xFFFF;
} }
assignadjust (tptr, &lval); assignadjust (T, &lval);
DefineData (&lval); DefineData (&lval);
break; break;
@ -1024,14 +1056,14 @@ void ParseInit (type *tptr)
/* Make it long sized */ /* Make it long sized */
lval.e_const &= 0xFFFFFFFF; lval.e_const &= 0xFFFFFFFF;
} }
assignadjust (tptr, &lval); assignadjust (T, &lval);
DefineData (&lval); DefineData (&lval);
break; break;
case T_ARRAY: case T_ARRAY:
sz = Decode (tptr + 1); sz = Decode (T + 1);
t = tptr + DECODE_SIZE + 1; t = T + DECODE_SIZE + 1;
if ((t [0] == T_CHAR || t [0] == T_UCHAR) && curtok == TOK_SCONST) { if (IsTypeChar(t) && curtok == TOK_SCONST) {
str = GetLiteral (curval); str = GetLiteral (curval);
count = strlen (str) + 1; count = strlen (str) + 1;
TranslateLiteralPool (curval); /* Translate into target charset */ TranslateLiteralPool (curval); /* Translate into target charset */
@ -1042,7 +1074,7 @@ void ParseInit (type *tptr)
ConsumeLCurly (); ConsumeLCurly ();
count = 0; count = 0;
while (curtok != TOK_RCURLY) { while (curtok != TOK_RCURLY) {
ParseInit (tptr + DECODE_SIZE + 1); ParseInit (T + DECODE_SIZE + 1);
++count; ++count;
if (curtok != TOK_COMMA) if (curtok != TOK_COMMA)
break; break;
@ -1051,9 +1083,9 @@ void ParseInit (type *tptr)
ConsumeRCurly (); ConsumeRCurly ();
} }
if (sz == 0) { if (sz == 0) {
Encode (tptr + 1, count); Encode (T + 1, count);
} else if (count < sz) { } else if (count < sz) {
g_zerobytes ((sz - count) * SizeOf (tptr + DECODE_SIZE + 1)); g_zerobytes ((sz - count) * SizeOf (T + DECODE_SIZE + 1));
} else if (count > sz) { } else if (count > sz) {
Error (ERR_TOO_MANY_INITIALIZERS); Error (ERR_TOO_MANY_INITIALIZERS);
} }
@ -1061,7 +1093,7 @@ void ParseInit (type *tptr)
case T_STRUCT: case T_STRUCT:
case T_UNION: case T_UNION:
ParseStructInit (tptr); ParseStructInit (T);
break; break;
case T_VOID: case T_VOID:

View File

@ -74,7 +74,7 @@ void CheckEmptyDecl (const DeclSpec* D);
*/ */
void ParseInit (type* tptr); void ParseInit (type* tptr);
/* Parse initialization of variables */ /* Parse initialization of variables. */

View File

@ -135,6 +135,7 @@ static char* ErrMsg [ERR_COUNT-1] = {
"Illegal hex digit", "Illegal hex digit",
"Illegal character constant", "Illegal character constant",
"Illegal modifier", "Illegal modifier",
"Illegal type qualifier",
"Illegal storage class", "Illegal storage class",
"Illegal segment name: `%s'", "Illegal segment name: `%s'",
"Division by zero", "Division by zero",
@ -150,6 +151,8 @@ static char* ErrMsg [ERR_COUNT-1] = {
"__fastcall__ is not allowed for C functions", "__fastcall__ is not allowed for C functions",
"Variable has unknown size", "Variable has unknown size",
"Unknown identifier: `%s'", "Unknown identifier: `%s'",
"Duplicate qualifier: `%s'",
"Assignment to const",
}; };

View File

@ -130,6 +130,7 @@ enum Errors {
ERR_ILLEGAL_HEX_DIGIT, ERR_ILLEGAL_HEX_DIGIT,
ERR_ILLEGAL_CHARCONST, ERR_ILLEGAL_CHARCONST,
ERR_ILLEGAL_MODIFIER, ERR_ILLEGAL_MODIFIER,
ERR_ILLEGAL_QUALIFIER,
ERR_ILLEGAL_STORAGE_CLASS, ERR_ILLEGAL_STORAGE_CLASS,
ERR_ILLEGAL_SEG_NAME, ERR_ILLEGAL_SEG_NAME,
ERR_DIV_BY_ZERO, ERR_DIV_BY_ZERO,
@ -145,6 +146,8 @@ enum Errors {
ERR_FASTCALL, ERR_FASTCALL,
ERR_UNKNOWN_SIZE, ERR_UNKNOWN_SIZE,
ERR_UNKNOWN_IDENT, ERR_UNKNOWN_IDENT,
ERR_DUPLICATE_QUALIFIER,
ERR_CONST_ASSIGN,
ERR_COUNT /* Error count */ ERR_COUNT /* Error count */
}; };

View File

@ -116,7 +116,7 @@ static unsigned GlobalModeFlags (unsigned flags)
static int IsNullPtr (struct expent* lval) static int IsNullPtr (struct expent* lval)
/* Return true if this is the NULL pointer constant */ /* Return true if this is the NULL pointer constant */
{ {
return (IsInt (lval->e_tptr) && /* Is it an int? */ return (IsClassInt (lval->e_tptr) && /* Is it an int? */
lval->e_flags == E_MCONST && /* Is it constant? */ lval->e_flags == E_MCONST && /* Is it constant? */
lval->e_const == 0); /* And is it's value zero? */ lval->e_const == 0); /* And is it's value zero? */
} }
@ -131,7 +131,7 @@ static type* promoteint (type* lhst, type* rhst)
* - If one of the values is unsigned, the result is also unsigned. * - If one of the values is unsigned, the result is also unsigned.
* - Otherwise the result is an int. * - Otherwise the result is an int.
*/ */
if (IsLong (lhst) || IsLong (rhst)) { if (IsTypeLong (lhst) || IsTypeLong (rhst)) {
if (IsUnsigned (lhst) || IsUnsigned (rhst)) { if (IsUnsigned (lhst) || IsUnsigned (rhst)) {
return type_ulong; return type_ulong;
} else { } else {
@ -209,11 +209,11 @@ unsigned assignadjust (type* lhst, struct expent* rhs)
* error message. * error message.
*/ */
Error (ERR_ILLEGAL_TYPE); Error (ERR_ILLEGAL_TYPE);
} else if (IsInt (lhst)) { } else if (IsClassInt (lhst)) {
if (IsPtr (rhst)) { if (IsClassPtr (rhst)) {
/* Pointer -> int conversion */ /* Pointer -> int conversion */
Warning (WARN_PTR_TO_INT_CONV); Warning (WARN_PTR_TO_INT_CONV);
} else if (!IsInt (rhst)) { } else if (!IsClassInt (rhst)) {
Error (ERR_INCOMPATIBLE_TYPES); Error (ERR_INCOMPATIBLE_TYPES);
} else { } else {
/* Adjust the int types. To avoid manipulation of TOS mark lhs /* Adjust the int types. To avoid manipulation of TOS mark lhs
@ -225,8 +225,8 @@ unsigned assignadjust (type* lhst, struct expent* rhs)
} }
return g_typeadjust (TypeOf (lhst) | CF_CONST, flags); return g_typeadjust (TypeOf (lhst) | CF_CONST, flags);
} }
} else if (IsPtr (lhst)) { } else if (IsClassPtr (lhst)) {
if (IsPtr (rhst)) { if (IsClassPtr (rhst)) {
/* Pointer to pointer assignment is valid, if: /* Pointer to pointer assignment is valid, if:
* - both point to the same types, or * - both point to the same types, or
* - the rhs pointer is a void pointer, or * - the rhs pointer is a void pointer, or
@ -237,12 +237,12 @@ unsigned assignadjust (type* lhst, struct expent* rhs)
if (!EqualTypes (left, right) && *left != T_VOID && *right != T_VOID) { if (!EqualTypes (left, right) && *left != T_VOID && *right != T_VOID) {
Error (ERR_INCOMPATIBLE_POINTERS); Error (ERR_INCOMPATIBLE_POINTERS);
} }
} else if (IsInt (rhst)) { } else if (IsClassInt (rhst)) {
/* Int to pointer assignment is valid only for constant zero */ /* 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) == 0 || rhs->e_const != 0) {
Warning (WARN_INT_TO_PTR_CONV); Warning (WARN_INT_TO_PTR_CONV);
} }
} else if (IsFuncPtr (lhst) && IsFunc(rhst)) { } else if (IsTypeFuncPtr (lhst) && IsTypeFunc(rhst)) {
/* Assignment of function to function pointer is allowed, provided /* Assignment of function to function pointer is allowed, provided
* that both functions have the same parameter list. * that both functions have the same parameter list.
*/ */
@ -785,7 +785,7 @@ static int primary (struct expent* lval)
/* The symbol is referenced now */ /* The symbol is referenced now */
Sym->Flags |= SC_REF; Sym->Flags |= SC_REF;
if (IsFunc (lval->e_tptr) || IsArray (lval->e_tptr)) { if (IsTypeFunc (lval->e_tptr) || IsTypeArray (lval->e_tptr)) {
return 0; return 0;
} }
return 1; return 1;
@ -917,7 +917,7 @@ static int arrayref (int k, struct expent* lval)
exprhs (CF_NONE, k, lval); exprhs (CF_NONE, k, lval);
} }
if (IsPtr (tptr1)) { if (IsClassPtr (tptr1)) {
/* Scale the subscript value according to element size */ /* Scale the subscript value according to element size */
lval2.e_const *= PSizeOf (tptr1); lval2.e_const *= PSizeOf (tptr1);
@ -928,7 +928,7 @@ static int arrayref (int k, struct expent* lval)
/* Handle constant base array on stack. Be sure NOT to /* Handle constant base array on stack. Be sure NOT to
* handle pointers the same way, this won't work. * handle pointers the same way, this won't work.
*/ */
if (IsArray (tptr1) && if (IsTypeArray (tptr1) &&
((lval->e_flags & ~E_MCTYPE) == E_MCONST || ((lval->e_flags & ~E_MCTYPE) == E_MCONST ||
(lval->e_flags & ~E_MCTYPE) == E_MLOCAL || (lval->e_flags & ~E_MCTYPE) == E_MLOCAL ||
(lval->e_flags & E_MGLOBAL) != 0 || (lval->e_flags & E_MGLOBAL) != 0 ||
@ -950,7 +950,7 @@ static int arrayref (int k, struct expent* lval)
/* Done */ /* Done */
goto end_array; goto end_array;
} else if (IsPtr (tptr2 = lval2.e_tptr)) { } else if (IsClassPtr (tptr2 = lval2.e_tptr)) {
/* Subscript is pointer, get element type */ /* Subscript is pointer, get element type */
lval2.e_tptr = Indirect (tptr2); lval2.e_tptr = Indirect (tptr2);
@ -975,7 +975,7 @@ static int arrayref (int k, struct expent* lval)
exprhs (CF_NONE, l, &lval2); exprhs (CF_NONE, l, &lval2);
tptr2 = lval2.e_tptr; tptr2 = lval2.e_tptr;
if (IsPtr (tptr1)) { if (IsClassPtr (tptr1)) {
/* Get the element type */ /* Get the element type */
lval->e_tptr = Indirect (tptr1); lval->e_tptr = Indirect (tptr1);
@ -986,7 +986,7 @@ static int arrayref (int k, struct expent* lval)
*/ */
g_scale (CF_INT, SizeOf (lval->e_tptr)); g_scale (CF_INT, SizeOf (lval->e_tptr));
} else if (IsPtr (tptr2)) { } else if (IsClassPtr (tptr2)) {
/* Get the element type */ /* Get the element type */
lval2.e_tptr = Indirect (tptr2); lval2.e_tptr = Indirect (tptr2);
@ -1065,7 +1065,7 @@ static int arrayref (int k, struct expent* lval)
g_inc (CF_INT | CF_UNSIGNED, lval->e_const); g_inc (CF_INT | CF_UNSIGNED, lval->e_const);
} else if (lflags == E_MLOCAL) { } else if (lflags == E_MLOCAL) {
/* Base address is a local variable address */ /* Base address is a local variable address */
if (IsArray (tptr1)) { if (IsTypeArray (tptr1)) {
g_addaddr_local (CF_INT, lval->e_const); g_addaddr_local (CF_INT, lval->e_const);
} else { } else {
g_addlocal (CF_PTR, lval->e_const); g_addlocal (CF_PTR, lval->e_const);
@ -1074,7 +1074,7 @@ static int arrayref (int k, struct expent* lval)
/* Base address is a static variable address */ /* Base address is a static variable address */
unsigned flags = CF_INT; unsigned flags = CF_INT;
flags |= GlobalModeFlags (lval->e_flags); flags |= GlobalModeFlags (lval->e_flags);
if (IsArray (tptr1)) { if (IsTypeArray (tptr1)) {
g_addaddr_static (flags, lval->e_name, lval->e_const); g_addaddr_static (flags, lval->e_name, lval->e_const);
} else { } else {
g_addstatic (flags, lval->e_name, lval->e_const); g_addstatic (flags, lval->e_name, lval->e_const);
@ -1086,7 +1086,7 @@ static int arrayref (int k, struct expent* lval)
lval->e_flags = E_MEXPR; lval->e_flags = E_MEXPR;
end_array: end_array:
ConsumeRBrack (); ConsumeRBrack ();
return !IsArray (lval->e_tptr); return !IsTypeArray (lval->e_tptr);
} }
@ -1132,7 +1132,7 @@ static int structref (int k, struct expent* lval)
lval->e_flags = E_MEOFFS; lval->e_flags = E_MEOFFS;
} }
lval->e_tptr = Field->Type; lval->e_tptr = Field->Type;
return !IsArray (Field->Type); return !IsTypeArray (Field->Type);
} }
@ -1162,8 +1162,8 @@ static int hie11 (struct expent *lval)
/* Function call. Skip the opening parenthesis */ /* Function call. Skip the opening parenthesis */
NextToken (); NextToken ();
tptr = lval->e_tptr; tptr = lval->e_tptr;
if (IsFunc (tptr) || IsFuncPtr (tptr)) { if (IsTypeFunc (tptr) || IsTypeFuncPtr (tptr)) {
if (IsFuncPtr (tptr)) { if (IsTypeFuncPtr (tptr)) {
/* Pointer to function. Handle transparently */ /* Pointer to function. Handle transparently */
exprhs (CF_NONE, k, lval); /* Function pointer to A/X */ exprhs (CF_NONE, k, lval); /* Function pointer to A/X */
++lval->e_tptr; /* Skip T_PTR */ ++lval->e_tptr; /* Skip T_PTR */
@ -1179,7 +1179,7 @@ static int hie11 (struct expent *lval)
} else if (curtok == TOK_DOT) { } else if (curtok == TOK_DOT) {
if (!IsStruct (lval->e_tptr)) { if (!IsClassStruct (lval->e_tptr)) {
Error (ERR_STRUCT_EXPECTED); Error (ERR_STRUCT_EXPECTED);
} }
k = structref (0, lval); k = structref (0, lval);
@ -1474,7 +1474,7 @@ static int hie10 (struct expent* lval)
lval->e_const = 0; /* Offset is zero now */ lval->e_const = 0; /* Offset is zero now */
} }
t = lval->e_tptr; t = lval->e_tptr;
if (IsPtr (t)) { if (IsClassPtr (t)) {
lval->e_tptr = Indirect (t); lval->e_tptr = Indirect (t);
} else { } else {
Error (ERR_ILLEGAL_INDIRECT); Error (ERR_ILLEGAL_INDIRECT);
@ -1486,7 +1486,7 @@ static int hie10 (struct expent* lval)
k = hie10 (lval); k = hie10 (lval);
if (k == 0) { if (k == 0) {
/* Allow the & operator with an array */ /* Allow the & operator with an array */
if (!IsArray (lval->e_tptr)) { if (!IsTypeArray (lval->e_tptr)) {
Error (ERR_ILLEGAL_ADDRESS); Error (ERR_ILLEGAL_ADDRESS);
} }
} else { } else {
@ -1566,7 +1566,7 @@ static int hie_internal (GenDesc** ops, /* List of generators */
*UsedGen = 1; *UsedGen = 1;
/* All operators that call this function expect an int on the lhs */ /* All operators that call this function expect an int on the lhs */
if (!IsInt (lval->e_tptr)) { if (!IsClassInt (lval->e_tptr)) {
Error (ERR_INT_EXPR_EXPECTED); Error (ERR_INT_EXPR_EXPECTED);
} }
@ -1592,7 +1592,7 @@ static int hie_internal (GenDesc** ops, /* List of generators */
rconst = (evalexpr (CF_NONE, hienext, &lval2) == 0); rconst = (evalexpr (CF_NONE, hienext, &lval2) == 0);
/* Check the type of the rhs */ /* Check the type of the rhs */
if (!IsInt (lval2.e_tptr)) { if (!IsClassInt (lval2.e_tptr)) {
Error (ERR_INT_EXPR_EXPECTED); Error (ERR_INT_EXPR_EXPECTED);
} }
@ -1692,12 +1692,12 @@ static int hie_compare (GenDesc** ops, /* List of generators */
rconst = (evalexpr (CF_NONE, hienext, &lval2) == 0); rconst = (evalexpr (CF_NONE, hienext, &lval2) == 0);
/* Make sure, the types are compatible */ /* Make sure, the types are compatible */
if (IsInt (lval->e_tptr)) { if (IsClassInt (lval->e_tptr)) {
if (!IsInt (lval2.e_tptr) && !(IsPtr(lval2.e_tptr) && IsNullPtr(lval))) { if (!IsClassInt (lval2.e_tptr) && !(IsClassPtr(lval2.e_tptr) && IsNullPtr(lval))) {
Error (ERR_INCOMPATIBLE_TYPES); Error (ERR_INCOMPATIBLE_TYPES);
} }
} else if (IsPtr (lval->e_tptr)) { } else if (IsClassPtr (lval->e_tptr)) {
if (IsPtr (lval2.e_tptr)) { if (IsClassPtr (lval2.e_tptr)) {
/* Both pointers are allowed in comparison if they point to /* Both pointers are allowed in comparison if they point to
* the same type, or if one of them is a void pointer. * the same type, or if one of them is a void pointer.
*/ */
@ -1744,7 +1744,7 @@ static int hie_compare (GenDesc** ops, /* List of generators */
* operation as char operation. Otherwise the default * operation as char operation. Otherwise the default
* promotions are used. * promotions are used.
*/ */
if (IsChar (lval->e_tptr) && (IsChar (lval2.e_tptr) || rconst)) { if (IsTypeChar (lval->e_tptr) && (IsTypeChar (lval2.e_tptr) || rconst)) {
flags |= CF_CHAR; flags |= CF_CHAR;
if (IsUnsigned (lval->e_tptr) || IsUnsigned (lval2.e_tptr)) { if (IsUnsigned (lval->e_tptr) || IsUnsigned (lval2.e_tptr)) {
flags |= CF_UNSIGNED; flags |= CF_UNSIGNED;
@ -1818,16 +1818,16 @@ static void parseadd (int k, struct expent* lval)
rhst = lval2.e_tptr; rhst = lval2.e_tptr;
/* Both expressions are constants. Check for pointer arithmetic */ /* Both expressions are constants. Check for pointer arithmetic */
if (IsPtr (lhst) && IsInt (rhst)) { if (IsClassPtr (lhst) && IsClassInt (rhst)) {
/* Left is pointer, right is int, must scale rhs */ /* Left is pointer, right is int, must scale rhs */
lval->e_const = lval->e_const + lval2.e_const * PSizeOf (lhst); lval->e_const = lval->e_const + lval2.e_const * PSizeOf (lhst);
/* Result type is a pointer */ /* Result type is a pointer */
} else if (IsInt (lhst) && IsPtr (rhst)) { } else if (IsClassInt (lhst) && IsClassPtr (rhst)) {
/* Left is int, right is pointer, must scale lhs */ /* Left is int, right is pointer, must scale lhs */
lval->e_const = lval->e_const * PSizeOf (rhst) + lval2.e_const; lval->e_const = lval->e_const * PSizeOf (rhst) + lval2.e_const;
/* Result type is a pointer */ /* Result type is a pointer */
lval->e_tptr = lval2.e_tptr; lval->e_tptr = lval2.e_tptr;
} else if (IsInt (lhst) && IsInt (rhst)) { } else if (IsClassInt (lhst) && IsClassInt (rhst)) {
/* Integer addition */ /* Integer addition */
lval->e_const += lval2.e_const; lval->e_const += lval2.e_const;
typeadjust (lval, &lval2, 1); typeadjust (lval, &lval2, 1);
@ -1845,18 +1845,18 @@ static void parseadd (int k, struct expent* lval)
rhst = lval2.e_tptr; rhst = lval2.e_tptr;
/* Check for pointer arithmetic */ /* Check for pointer arithmetic */
if (IsPtr (lhst) && IsInt (rhst)) { if (IsClassPtr (lhst) && IsClassInt (rhst)) {
/* Left is pointer, right is int, must scale rhs */ /* Left is pointer, right is int, must scale rhs */
g_scale (CF_INT, PSizeOf (lhst)); g_scale (CF_INT, PSizeOf (lhst));
/* Operate on pointers, result type is a pointer */ /* Operate on pointers, result type is a pointer */
flags = CF_PTR; flags = CF_PTR;
} else if (IsInt (lhst) && IsPtr (rhst)) { } else if (IsClassInt (lhst) && IsClassPtr (rhst)) {
/* Left is int, right is pointer, must scale lhs */ /* Left is int, right is pointer, must scale lhs */
lval->e_const *= PSizeOf (rhst); lval->e_const *= PSizeOf (rhst);
/* Operate on pointers, result type is a pointer */ /* Operate on pointers, result type is a pointer */
flags = CF_PTR; flags = CF_PTR;
lval->e_tptr = lval2.e_tptr; lval->e_tptr = lval2.e_tptr;
} else if (IsInt (lhst) && IsInt (rhst)) { } else if (IsClassInt (lhst) && IsClassInt (rhst)) {
/* Integer addition */ /* Integer addition */
flags = typeadjust (lval, &lval2, 1); flags = typeadjust (lval, &lval2, 1);
} else { } else {
@ -1891,18 +1891,18 @@ static void parseadd (int k, struct expent* lval)
pop (TypeOf (lval->e_tptr)); pop (TypeOf (lval->e_tptr));
/* Check for pointer arithmetic */ /* Check for pointer arithmetic */
if (IsPtr (lhst) && IsInt (rhst)) { if (IsClassPtr (lhst) && IsClassInt (rhst)) {
/* Left is pointer, right is int, must scale rhs */ /* Left is pointer, right is int, must scale rhs */
lval2.e_const *= PSizeOf (lhst); lval2.e_const *= PSizeOf (lhst);
/* Operate on pointers, result type is a pointer */ /* Operate on pointers, result type is a pointer */
flags = CF_PTR; flags = CF_PTR;
} else if (IsInt (lhst) && IsPtr (rhst)) { } else if (IsClassInt (lhst) && IsClassPtr (rhst)) {
/* Left is int, right is pointer, must scale lhs (ptr only) */ /* Left is int, right is pointer, must scale lhs (ptr only) */
g_scale (CF_INT | CF_CONST, PSizeOf (rhst)); g_scale (CF_INT | CF_CONST, PSizeOf (rhst));
/* Operate on pointers, result type is a pointer */ /* Operate on pointers, result type is a pointer */
flags = CF_PTR; flags = CF_PTR;
lval->e_tptr = lval2.e_tptr; lval->e_tptr = lval2.e_tptr;
} else if (IsInt (lhst) && IsInt (rhst)) { } else if (IsClassInt (lhst) && IsClassInt (rhst)) {
/* Integer addition */ /* Integer addition */
flags = typeadjust (lval, &lval2, 1); flags = typeadjust (lval, &lval2, 1);
} else { } else {
@ -1923,12 +1923,12 @@ static void parseadd (int k, struct expent* lval)
rhst = lval2.e_tptr; rhst = lval2.e_tptr;
/* Check for pointer arithmetic */ /* Check for pointer arithmetic */
if (IsPtr (lhst) && IsInt (rhst)) { if (IsClassPtr (lhst) && IsClassInt (rhst)) {
/* Left is pointer, right is int, must scale rhs */ /* Left is pointer, right is int, must scale rhs */
g_scale (CF_INT, PSizeOf (lhst)); g_scale (CF_INT, PSizeOf (lhst));
/* Operate on pointers, result type is a pointer */ /* Operate on pointers, result type is a pointer */
flags = CF_PTR; flags = CF_PTR;
} else if (IsInt (lhst) && IsPtr (rhst)) { } else if (IsClassInt (lhst) && IsClassPtr (rhst)) {
/* Left is int, right is pointer, must scale lhs */ /* Left is int, right is pointer, must scale lhs */
g_tosint (TypeOf (rhst)); /* Make sure, TOS is int */ g_tosint (TypeOf (rhst)); /* Make sure, TOS is int */
g_swap (CF_INT); /* Swap TOS and primary */ g_swap (CF_INT); /* Swap TOS and primary */
@ -1936,7 +1936,7 @@ static void parseadd (int k, struct expent* lval)
/* Operate on pointers, result type is a pointer */ /* Operate on pointers, result type is a pointer */
flags = CF_PTR; flags = CF_PTR;
lval->e_tptr = lval2.e_tptr; lval->e_tptr = lval2.e_tptr;
} else if (IsInt (lhst) && IsInt (rhst)) { } else if (IsClassInt (lhst) && IsClassInt (rhst)) {
/* Integer addition */ /* Integer addition */
flags = typeadjust (lval, &lval2, 0); flags = typeadjust (lval, &lval2, 0);
} else { } else {
@ -2001,11 +2001,11 @@ static void parsesub (int k, struct expent* lval)
pop (TypeOf (lhst)); /* Clean up the stack */ pop (TypeOf (lhst)); /* Clean up the stack */
/* Check for pointer arithmetic */ /* Check for pointer arithmetic */
if (IsPtr (lhst) && IsInt (rhst)) { if (IsClassPtr (lhst) && IsClassInt (rhst)) {
/* Left is pointer, right is int, must scale rhs */ /* Left is pointer, right is int, must scale rhs */
lval->e_const -= lval2.e_const * PSizeOf (lhst); lval->e_const -= lval2.e_const * PSizeOf (lhst);
/* Operate on pointers, result type is a pointer */ /* Operate on pointers, result type is a pointer */
} else if (IsPtr (lhst) && IsPtr (rhst)) { } else if (IsClassPtr (lhst) && IsClassPtr (rhst)) {
/* Left is pointer, right is pointer, must scale result */ /* Left is pointer, right is pointer, must scale result */
if (TypeCmp (Indirect (lhst), Indirect (rhst)) != 0) { if (TypeCmp (Indirect (lhst), Indirect (rhst)) != 0) {
Error (ERR_INCOMPATIBLE_POINTERS); Error (ERR_INCOMPATIBLE_POINTERS);
@ -2014,7 +2014,7 @@ static void parsesub (int k, struct expent* lval)
} }
/* Operate on pointers, result type is an integer */ /* Operate on pointers, result type is an integer */
lval->e_tptr = type_int; lval->e_tptr = type_int;
} else if (IsInt (lhst) && IsInt (rhst)) { } else if (IsClassInt (lhst) && IsClassInt (rhst)) {
/* Integer subtraction */ /* Integer subtraction */
typeadjust (lval, &lval2, 1); typeadjust (lval, &lval2, 1);
lval->e_const -= lval2.e_const; lval->e_const -= lval2.e_const;
@ -2035,12 +2035,12 @@ static void parsesub (int k, struct expent* lval)
RemoveCode (Mark2); RemoveCode (Mark2);
pop (TypeOf (lhst)); pop (TypeOf (lhst));
if (IsPtr (lhst) && IsInt (rhst)) { if (IsClassPtr (lhst) && IsClassInt (rhst)) {
/* Left is pointer, right is int, must scale rhs */ /* Left is pointer, right is int, must scale rhs */
lval2.e_const *= PSizeOf (lhst); lval2.e_const *= PSizeOf (lhst);
/* Operate on pointers, result type is a pointer */ /* Operate on pointers, result type is a pointer */
flags = CF_PTR; flags = CF_PTR;
} else if (IsPtr (lhst) && IsPtr (rhst)) { } else if (IsClassPtr (lhst) && IsClassPtr (rhst)) {
/* Left is pointer, right is pointer, must scale result */ /* Left is pointer, right is pointer, must scale result */
if (TypeCmp (Indirect (lhst), Indirect (rhst)) != 0) { if (TypeCmp (Indirect (lhst), Indirect (rhst)) != 0) {
Error (ERR_INCOMPATIBLE_POINTERS); Error (ERR_INCOMPATIBLE_POINTERS);
@ -2050,7 +2050,7 @@ static void parsesub (int k, struct expent* lval)
/* Operate on pointers, result type is an integer */ /* Operate on pointers, result type is an integer */
flags = CF_PTR; flags = CF_PTR;
lval->e_tptr = type_int; lval->e_tptr = type_int;
} else if (IsInt (lhst) && IsInt (rhst)) { } else if (IsClassInt (lhst) && IsClassInt (rhst)) {
/* Integer subtraction */ /* Integer subtraction */
flags = typeadjust (lval, &lval2, 1); flags = typeadjust (lval, &lval2, 1);
} else { } else {
@ -2078,12 +2078,12 @@ static void parsesub (int k, struct expent* lval)
rhst = lval2.e_tptr; rhst = lval2.e_tptr;
/* Check for pointer arithmetic */ /* Check for pointer arithmetic */
if (IsPtr (lhst) && IsInt (rhst)) { if (IsClassPtr (lhst) && IsClassInt (rhst)) {
/* Left is pointer, right is int, must scale rhs */ /* Left is pointer, right is int, must scale rhs */
g_scale (CF_INT, PSizeOf (lhst)); g_scale (CF_INT, PSizeOf (lhst));
/* Operate on pointers, result type is a pointer */ /* Operate on pointers, result type is a pointer */
flags = CF_PTR; flags = CF_PTR;
} else if (IsPtr (lhst) && IsPtr (rhst)) { } else if (IsClassPtr (lhst) && IsClassPtr (rhst)) {
/* Left is pointer, right is pointer, must scale result */ /* Left is pointer, right is pointer, must scale result */
if (TypeCmp (Indirect (lhst), Indirect (rhst)) != 0) { if (TypeCmp (Indirect (lhst), Indirect (rhst)) != 0) {
Error (ERR_INCOMPATIBLE_POINTERS); Error (ERR_INCOMPATIBLE_POINTERS);
@ -2093,7 +2093,7 @@ static void parsesub (int k, struct expent* lval)
/* Operate on pointers, result type is an integer */ /* Operate on pointers, result type is an integer */
flags = CF_PTR; flags = CF_PTR;
lval->e_tptr = type_int; lval->e_tptr = type_int;
} else if (IsInt (lhst) && IsInt (rhst)) { } else if (IsClassInt (lhst) && IsClassInt (rhst)) {
/* Integer subtraction. If the left hand side descriptor says that /* Integer subtraction. If the left hand side descriptor says that
* the lhs is const, we have to remove this mark, since this is no * the lhs is const, we have to remove this mark, since this is no
* longer true, lhs is on stack instead. * longer true, lhs is on stack instead.
@ -2409,7 +2409,7 @@ static int hieQuest (struct expent *lval)
*/ */
type2 = lval2.e_tptr; type2 = lval2.e_tptr;
type3 = lval3.e_tptr; type3 = lval3.e_tptr;
if (IsInt (type2) && IsInt (type3)) { if (IsClassInt (type2) && IsClassInt (type3)) {
/* Get common type */ /* Get common type */
rtype = promoteint (type2, type3); rtype = promoteint (type2, type3);
@ -2442,17 +2442,17 @@ static int hieQuest (struct expent *lval)
labt = 0; /* Mark other label as invalid */ labt = 0; /* Mark other label as invalid */
} }
} else if (IsPtr (type2) && IsPtr (type3)) { } else if (IsClassPtr (type2) && IsClassPtr (type3)) {
/* Must point to same type */ /* Must point to same type */
if (TypeCmp (Indirect (type2), Indirect (type3)) != 0) { if (TypeCmp (Indirect (type2), Indirect (type3)) != 0) {
Error (ERR_INCOMPATIBLE_TYPES); Error (ERR_INCOMPATIBLE_TYPES);
} }
/* Result has the common type */ /* Result has the common type */
rtype = lval2.e_tptr; rtype = lval2.e_tptr;
} else if (IsPtr (type2) && IsNullPtr (&lval3)) { } else if (IsClassPtr (type2) && IsNullPtr (&lval3)) {
/* Result type is pointer, no cast needed */ /* Result type is pointer, no cast needed */
rtype = lval2.e_tptr; rtype = lval2.e_tptr;
} else if (IsNullPtr (&lval2) && IsPtr (type3)) { } else if (IsNullPtr (&lval2) && IsClassPtr (type3)) {
/* Result type is pointer, no cast needed */ /* Result type is pointer, no cast needed */
rtype = lval3.e_tptr; rtype = lval3.e_tptr;
} else { } else {
@ -2656,11 +2656,16 @@ static void Assignment (struct expent* lval)
unsigned flags; unsigned flags;
type* ltype = lval->e_tptr; type* ltype = lval->e_tptr;
/* Check for assignment to const */
if (IsConst (ltype)) {
Error (ERR_CONST_ASSIGN);
}
/* cc65 does not have full support for handling structs by value. Since /* cc65 does not have full support for handling structs by value. Since
* assigning structs is one of the more useful operations from this * assigning structs is one of the more useful operations from this
* familiy, allow it here. * familiy, allow it here.
*/ */
if (IsStruct (ltype)) { if (IsClassStruct (ltype)) {
/* Bring the address of the lhs into the primary and push it */ /* Bring the address of the lhs into the primary and push it */
exprhs (0, 0, lval); exprhs (0, 0, lval);
@ -2889,7 +2894,7 @@ void intexpr (struct expent* lval)
/* Get an integer expression */ /* Get an integer expression */
{ {
expression (lval); expression (lval);
if (!IsInt (lval->e_tptr)) { if (!IsClassInt (lval->e_tptr)) {
Error (ERR_INT_EXPR_EXPECTED); Error (ERR_INT_EXPR_EXPECTED);
/* To avoid any compiler errors, make the expression a valid int */ /* To avoid any compiler errors, make the expression a valid int */
lval->e_flags = E_MCONST; lval->e_flags = E_MCONST;
@ -2910,7 +2915,7 @@ void boolexpr (struct expent* lval)
* the pointer used in a boolean context is also ok (Ootherwise check if it's a pointer * the pointer used in a boolean context is also ok (Ootherwise check if it's a pointer
* expression. * expression.
*/ */
if (!IsInt (lval->e_tptr) && !IsPtr (lval->e_tptr)) { if (!IsClassInt (lval->e_tptr) && !IsClassPtr (lval->e_tptr)) {
Error (ERR_INT_EXPR_EXPECTED); Error (ERR_INT_EXPR_EXPECTED);
/* To avoid any compiler errors, make the expression a valid int */ /* To avoid any compiler errors, make the expression a valid int */
lval->e_flags = E_MCONST; lval->e_flags = E_MCONST;

View File

@ -146,7 +146,7 @@ static void ParseOneDecl (const DeclSpec* Spec)
ParseDecl (Spec, &Decl, DM_NEED_IDENT); ParseDecl (Spec, &Decl, DM_NEED_IDENT);
/* Set the correct storage class for functions */ /* Set the correct storage class for functions */
if (IsFunc (Decl.Type)) { if (IsTypeFunc (Decl.Type)) {
/* Function prototypes are always external */ /* Function prototypes are always external */
if ((SC & SC_EXTERN) == 0) { if ((SC & SC_EXTERN) == 0) {
Warning (WARN_FUNC_MUST_BE_EXTERN); Warning (WARN_FUNC_MUST_BE_EXTERN);

View File

@ -11,8 +11,10 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include "../common/xmalloc.h" /* common */
#include "xmalloc.h"
/* cc65 */
#include "asmcode.h" #include "asmcode.h"
#include "asmlabel.h" #include "asmlabel.h"
#include "codegen.h" #include "codegen.h"
@ -298,7 +300,7 @@ static void cascadeswitch (struct expent* eval)
/* Read the selector expression */ /* Read the selector expression */
constexpr (&lval); constexpr (&lval);
if (!IsInt (lval.e_tptr)) { if (!IsClassInt (lval.e_tptr)) {
Error (ERR_ILLEGAL_TYPE); Error (ERR_ILLEGAL_TYPE);
} }
@ -456,7 +458,7 @@ static void tableswitch (struct expent* eval)
if (curtok == TOK_CASE) { if (curtok == TOK_CASE) {
NextToken (); NextToken ();
constexpr (&lval); constexpr (&lval);
if (!IsInt (lval.e_tptr)) { if (!IsClassInt (lval.e_tptr)) {
Error (ERR_ILLEGAL_TYPE); Error (ERR_ILLEGAL_TYPE);
} }
p->sw_const = lval.e_const; p->sw_const = lval.e_const;
@ -538,7 +540,7 @@ static void doswitch (void)
ConsumeLCurly (); ConsumeLCurly ();
/* Now decide which sort of switch we will create: */ /* Now decide which sort of switch we will create: */
if (IsChar (eval.e_tptr) || (FavourSize == 0 && IsInt (eval.e_tptr))) { if (IsTypeChar (eval.e_tptr) || (FavourSize == 0 && IsClassInt (eval.e_tptr))) {
cascadeswitch (&eval); cascadeswitch (&eval);
} else { } else {
tableswitch (&eval); tableswitch (&eval);

View File

@ -467,7 +467,7 @@ SymEntry* FindStructField (const type* Type, const char* Name)
} }
/* Non-structs do not have any struct fields... */ /* Non-structs do not have any struct fields... */
if (IsStruct (Type)) { if (IsClassStruct (Type)) {
const SymTable* Tab; const SymTable* Tab;
@ -664,7 +664,7 @@ SymEntry* AddGlobalSym (const char* Name, type* Type, unsigned Flags)
/* Add an external or global symbol to the symbol table and return the entry */ /* Add an external or global symbol to the symbol table and return the entry */
{ {
/* Functions must be inserted in the global symbol table */ /* Functions must be inserted in the global symbol table */
SymTable* Tab = IsFunc (Type)? SymTab0 : SymTab; SymTable* Tab = IsTypeFunc (Type)? SymTab0 : SymTab;
/* Do we have an entry with this name already? */ /* Do we have an entry with this name already? */
SymEntry* Entry = FindSymInTable (Tab, Name, HashStr (Name)); SymEntry* Entry = FindSymInTable (Tab, Name, HashStr (Name));
@ -685,7 +685,7 @@ SymEntry* AddGlobalSym (const char* Name, type* Type, unsigned Flags)
* incomplete declaration. Accept this, and if the exsting entry is * incomplete declaration. Accept this, and if the exsting entry is
* incomplete, complete it. * incomplete, complete it.
*/ */
if (IsArray (Type) && IsArray (EType)) { if (IsTypeArray (Type) && IsTypeArray (EType)) {
/* Get the array sizes */ /* Get the array sizes */
unsigned Size = Decode (Type + 1); unsigned Size = Decode (Type + 1);
@ -713,7 +713,7 @@ SymEntry* AddGlobalSym (const char* Name, type* Type, unsigned Flags)
* contains pointers to the new symbol tables that are needed if * contains pointers to the new symbol tables that are needed if
* an actual function definition follows. * an actual function definition follows.
*/ */
if (IsFunc (Type)) { if (IsTypeFunc (Type)) {
CopyEncode (Type+1, EType+1); CopyEncode (Type+1, EType+1);
} }
} }