/* common */
#include "version.h"
-
+
/* cc65 */
#include "asmlabel.h"
#include "codegen.h"
/* Get the symbol flags */
SymFlags = Spec.StorageClass;
- if (IsFunc (Decl.Type)) {
+ if (IsTypeFunc (Decl.Type)) {
SymFlags |= SC_FUNC;
} else {
if (NeedStorage) {
* void types in non ANSI mode.
*/
if (Size == 0) {
- if (!IsTypeVoid (Decl.Type)) {
- if (!IsArray (Decl.Type)) {
- /* Size is unknown and not an array */
- Error (ERR_UNKNOWN_SIZE);
- }
- } else if (ANSI) {
- /* We cannot declare variables of type void */
- Error (ERR_ILLEGAL_TYPE);
- }
+ if (!IsTypeVoid (Decl.Type)) {
+ if (!IsTypeArray (Decl.Type)) {
+ /* Size is unknown and not an array */
+ Error (ERR_UNKNOWN_SIZE);
+ }
+ } else if (ANSI) {
+ /* We cannot declare variables of type void */
+ Error (ERR_ILLEGAL_TYPE);
+ }
}
- /* Switch to the data segment */
- g_usedata ();
+ /* Switch to the data or rodata segment */
+ if (IsConst (Decl.Type)) {
+ g_userodata ();
+ } else {
+ g_usedata ();
+ }
/* Define a label */
g_defgloblabel (Entry->Name);
}
/* Function declaration? */
- if (IsFunc (Decl.Type)) {
+ if (IsTypeFunc (Decl.Type)) {
/* Function */
if (!comma) {
void PrintType (FILE* F, const type* Type)
/* Output translation of type array. */
{
- /* If the first field has const and/or volatile qualifiers, print and
- * remove them.
- */
- type T = *Type++;
- T = PrintTypeComp (F, T, T_QUAL_CONST, "const");
- T = PrintTypeComp (F, T, T_QUAL_VOLATILE, "volatile");
+ type T;
+
/* Walk over the complete string */
- do {
+ while ((T = *Type++) != T_END) {
- /* Check for the sizes */
- T = PrintTypeComp (F, T, T_SIZE_SHORT, "short");
- T = PrintTypeComp (F, T, T_SIZE_LONG, "long");
- T = PrintTypeComp (F, T, T_SIZE_LONGLONG, "long long");
+ /* Print any qualifiers */
+ T = PrintTypeComp (F, T, T_QUAL_CONST, "const");
+ T = PrintTypeComp (F, T, T_QUAL_VOLATILE, "volatile");
- /* Signedness */
- T = PrintTypeComp (F, T, T_SIGN_SIGNED, "signed");
- T = PrintTypeComp (F, T, T_SIGN_UNSIGNED, "unsigned");
+ /* Signedness */
+ T = PrintTypeComp (F, T, T_SIGN_SIGNED, "signed");
+ T = PrintTypeComp (F, T, T_SIGN_UNSIGNED, "unsigned");
- /* Now check the real type */
+ /* Now check the real type */
switch (T & T_MASK_TYPE) {
- case T_TYPE_CHAR:
- fprintf (F, "char\n");
- break;
- case T_TYPE_INT:
- fprintf (F, "int\n");
- break;
- case T_TYPE_FLOAT:
- fprintf (F, "float\n");
- break;
- case T_TYPE_DOUBLE:
- fprintf (F, "double\n");
- break;
+ case T_TYPE_CHAR:
+ fprintf (F, "char\n");
+ break;
+ case T_TYPE_SHORT:
+ fprintf (F, "short\n");
+ break;
+ case T_TYPE_INT:
+ fprintf (F, "int\n");
+ break;
+ case T_TYPE_LONG:
+ fprintf (F, "long\n");
+ 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:
fprintf (F, "void\n");
- break;
- case T_TYPE_STRUCT:
- fprintf (F, "struct %s\n", ((SymEntry*) DecodePtr (Type))->Name);
- Type += DECODE_SIZE;
+ break;
+ case T_TYPE_STRUCT:
+ fprintf (F, "struct %s\n", ((SymEntry*) DecodePtr (Type))->Name);
+ Type += DECODE_SIZE;
break;
case T_TYPE_UNION:
fprintf (F, "union %s\n", ((SymEntry*) DecodePtr (Type))->Name);
fprintf (F, "unknown type: %04X\n", T);
}
- /* Get the next type element */
- T = *Type++;
-
- } while (T != T_END);
+ }
}
int HasEncode (const type* Type)
/* Return true if the given type has encoded data */
{
- return IsStruct (Type) || IsArray (Type) || IsFunc (Type);
+ return IsClassStruct (Type) || IsTypeArray (Type) || IsTypeFunc (Type);
}
+type UnqualifiedType (type T)
+/* Return the unqalified type */
+{
+ return (T & ~T_MASK_QUAL);
+}
+
+
+
unsigned SizeOf (const type* T)
/* Compute size of object represented by type array. */
{
SymEntry* Entry;
- switch (*T) {
+ switch (UnqualifiedType (T[0])) {
- case T_VOID:
- Error (ERR_ILLEGAL_SIZE);
+ case T_VOID:
+ Error (ERR_ILLEGAL_SIZE);
return 0;
case T_SCHAR:
CHECK ((*T & T_CLASS_PTR) != 0);
/* Skip the pointer or array token itself */
- if (*T == T_ARRAY) {
+ if (IsTypeArray (T)) {
return SizeOf (T + DECODE_SIZE + 1);
} else {
return SizeOf (T + 1);
-unsigned TypeOf (const type* Type)
+unsigned TypeOf (const type* T)
/* Get the code generator base type of the object */
{
FuncDesc* F;
- switch (*Type) {
+ switch (UnqualifiedType (T[0])) {
case T_SCHAR:
return CF_CHAR;
return CF_LONG | CF_UNSIGNED;
case T_FUNC:
- F = DecodePtr (Type+1);
+ F = DecodePtr (T+1);
return (F->Flags & FD_ELLIPSIS)? 0 : CF_FIXARGC;
case T_STRUCT:
CHECK ((*T & T_MASK_CLASS) == T_CLASS_PTR);
/* Skip the pointer or array token itself */
- if (*T == T_ARRAY) {
+ if (IsTypeArray (T)) {
return T + DECODE_SIZE + 1;
} else {
return T + 1;
+int IsConst (const type* T)
+/* Return true if the given type has a const memory image */
+{
+ /* 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 IsTypeVoid (const type* T)
/* Return true if this is a void type */
{
- return (T[0] == T_VOID && T[1] == T_END);
+ return ((T[0] & T_MASK_TYPE) == T_TYPE_VOID && T[1] == T_END);
}
-int IsPtr (const type* T)
+int IsClassPtr (const type* T)
/* Return true if this is a pointer type */
{
return (T[0] & T_MASK_CLASS) == T_CLASS_PTR;
-int IsChar (const type* T)
+int IsTypeChar (const type* T)
/* Return true if this is a character type */
{
return (T[0] & T_MASK_TYPE) == T_TYPE_CHAR && T[1] == T_END;
-int IsInt (const type* T)
+int IsClassInt (const type* T)
/* Return true if this is an integer type */
{
return (T[0] & T_MASK_CLASS) == T_CLASS_INT;
-int IsLong (const type* T)
+int IsTypeLong (const type* T)
/* 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;
}
-int IsStruct (const type* T)
+int IsClassStruct (const type* T)
/* Return true if this is a struct type */
{
return (T[0] & T_MASK_CLASS) == T_CLASS_STRUCT;
-int IsFunc (const type* T)
-/* Return true if this is a function type */
+int IsTypeFunc (const type* T)
+/* Return true if this is a function class */
{
- return (T[0] == T_FUNC);
+ return ((T[0] & T_MASK_TYPE) == T_TYPE_FUNC);
}
/* Return true if this is a function type with __fastcall__ calling conventions */
{
FuncDesc* F;
- CHECK (T[0] == T_FUNC);
+ CHECK (IsTypeFunc (T));
F = DecodePtr (T+1);
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 (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 (T[0] == T_ARRAY);
+ return ((T[0] & T_MASK_TYPE) == T_TYPE_ARRAY);
}
// Basic types
T_TYPE_NONE = 0x0000,
T_TYPE_CHAR = 0x0001,
- T_TYPE_INT = 0x0002,
- T_TYPE_ENUM = 0x0003,
- T_TYPE_FLOAT = 0x0004,
- T_TYPE_DOUBLE = 0x0005,
- T_TYPE_VOID = 0x0006,
- T_TYPE_STRUCT = 0x0007,
- T_TYPE_UNION = 0x0008,
- T_TYPE_ARRAY = 0x0009,
- T_TYPE_PTR = 0x000A,
- T_TYPE_FUNC = 0x000B,
+ T_TYPE_SHORT = 0x0002,
+ T_TYPE_INT = 0x0003,
+ T_TYPE_LONG = 0x0004,
+ T_TYPE_LONGLONG = 0x0005,
+ T_TYPE_ENUM = 0x0006,
+ T_TYPE_FLOAT = 0x0007,
+ T_TYPE_DOUBLE = 0x0008,
+ T_TYPE_VOID = 0x0009,
+ T_TYPE_STRUCT = 0x000A,
+ T_TYPE_UNION = 0x000B,
+ T_TYPE_ARRAY = 0x000C,
+ T_TYPE_PTR = 0x000D,
+ T_TYPE_FUNC = 0x000E,
T_MASK_TYPE = 0x001F,
// Type classes
T_MASK_QUAL = 0x3000,
// Types
- 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_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_USHORT = T_TYPE_INT | T_CLASS_INT | T_SIGN_UNSIGNED | T_SIZE_SHORT,
- 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_LONG = T_TYPE_INT | T_CLASS_INT | T_SIGN_SIGNED | T_SIZE_LONG,
- T_ULONG = T_TYPE_INT | T_CLASS_INT | T_SIGN_UNSIGNED | T_SIZE_LONG,
- T_LONGLONG = T_TYPE_INT | T_CLASS_INT | T_SIGN_SIGNED | T_SIZE_LONGLONG,
- T_ULONGLONG = T_TYPE_INT | T_CLASS_INT | T_SIGN_UNSIGNED | T_SIZE_LONGLONG,
- 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_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_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_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_FUNC = T_TYPE_FUNC | T_CLASS_FUNC | T_SIGN_NONE | 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_UCHAR = T_TYPE_CHAR | T_CLASS_INT | T_SIGN_UNSIGNED | T_SIZE_NONE,
+ T_SHORT = T_TYPE_SHORT | T_CLASS_INT | T_SIGN_SIGNED | 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_UINT = T_TYPE_INT | T_CLASS_INT | T_SIGN_UNSIGNED | T_SIZE_NONE,
+ T_LONG = T_TYPE_LONG | T_CLASS_INT | T_SIGN_SIGNED | T_SIZE_LONG,
+ T_ULONG = T_TYPE_LONG | T_CLASS_INT | T_SIGN_UNSIGNED | T_SIZE_LONG,
+ T_LONGLONG = T_TYPE_LONGLONG | T_CLASS_INT | T_SIGN_SIGNED | 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_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_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_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_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,
};
void CopyEncode (const type* Source, type* Target);
/* Copy encoded data from Source to Target */
+type UnqualifiedType (type T);
+/* Return the unqalified type */
+
unsigned SizeOf (const type* Type);
/* Compute size of object represented by type array. */
* 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);
/* 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 */
-int IsChar (const type* Type);
+int IsTypeChar (const type* 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 */
-int IsLong (const type* Type);
+int IsTypeLong (const type* Type);
/* Return true if this is a long type (signed or unsigned) */
int IsUnsigned (const type* 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 */
-int IsFunc (const type* Type);
-/* Return true if this is a function type */
+int IsTypeFunc (const type* Type);
+/* Return true if this is a function class */
int IsFastCallFunc (const type* Type);
/* 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 */
-int IsArray (const type* Type);
+int IsTypeArray (const type* Type);
/* Return true if this is an array type */
struct FuncDesc* GetFuncDesc (const type* Type);
#include <errno.h>
#include <ctype.h>
-#include "../common/xmalloc.h"
+/* common */
+#include "xmalloc.h"
+/* cc65 */
#include "anonname.h"
#include "codegen.h"
#include "datatype.h"
-static void optional_modifiers (void)
-/* Eat optional "const" or "volatile" tokens */
+static type OptionalQualifiers (type Q)
+/* Read type qualifiers if we have any */
{
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;
}
/* Initialize the Declaration struct for use */
{
D->Ident[0] = '\0';
- D->Type[0] = T_END;
+ D->Type[0] = T_END;
D->T = D->Type;
}
static void ParseTypeSpec (DeclSpec* D, int Default)
/* Parse a type specificier */
{
- ident Ident;
+ ident Ident;
SymEntry* Entry;
type StructType;
+ type Qualifiers; /* Type qualifiers */
/* Assume we have an explicit type */
D->Flags &= ~DS_DEF_TYPE;
- /* Skip const or volatile modifiers if needed */
- optional_modifiers ();
+ /* Read type qualifiers if we have any */
+ Qualifiers = OptionalQualifiers (T_QUAL_NONE);
/* Look at the data type */
switch (curtok) {
case TOK_LONG:
NextToken ();
if (curtok == TOK_UNSIGNED) {
- NextToken ();
- optionalint ();
- D->Type[0] = T_ULONG;
- D->Type[1] = T_END;
+ NextToken ();
+ optionalint ();
+ D->Type[0] = T_ULONG;
+ D->Type[1] = T_END;
} else {
- optionalsigned ();
- optionalint ();
- D->Type[0] = T_LONG;
- D->Type[1] = T_END;
+ optionalsigned ();
+ optionalint ();
+ D->Type[0] = T_LONG;
+ D->Type[1] = T_END;
}
break;
case TOK_SHORT:
NextToken ();
if (curtok == TOK_UNSIGNED) {
- NextToken ();
- optionalint ();
- D->Type[0] = T_USHORT;
- D->Type[1] = T_END;
+ NextToken ();
+ optionalint ();
+ D->Type[0] = T_USHORT;
+ D->Type[1] = T_END;
} else {
- optionalsigned ();
- optionalint ();
- D->Type[0] = T_SHORT;
+ optionalsigned ();
+ optionalint ();
+ D->Type[0] = T_SHORT;
D->Type[1] = T_END;
}
break;
}
break;
}
+
+ /* There may also be qualifiers *after* the initial type */
+ D->Type[0] |= OptionalQualifiers (Qualifiers);
}
* resulting type.
*/
{
- if (IsArray (T)) {
+ if (IsTypeArray (T)) {
T += DECODE_SIZE;
T[0] = T_PTR;
}
static void Decl (Declaration* D, unsigned Mode)
/* Recursively process declarators. Build a type array in reverse order. */
{
+
if (curtok == TOK_STAR) {
+ type T = T_PTR;
NextToken ();
- /* Allow optional const or volatile modifiers */
- optional_modifiers ();
+ /* Allow optional const or volatile qualifiers */
+ T |= OptionalQualifiers (T_QUAL_NONE);
Decl (D, Mode);
- *D->T++ = T_PTR;
+ *D->T++ = T;
return;
} else if (curtok == TOK_LPAREN) {
NextToken ();
/* Parse the function */
Decl (D, Mode);
/* Set the fastcall flag */
- if (!IsFunc (T)) {
+ if (!IsTypeFunc (T)) {
Error (ERR_ILLEGAL_MODIFIER);
} else {
FuncDesc* F = DecodePtr (T+1);
TypeCpy (D->T, Spec->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);
}
}
-
-
-void ParseInit (type *tptr)
-/* Parse initialization of variables */
+void ParseInit (type* T)
+/* Parse initialization of variables. */
{
int count;
struct expent lval;
const char* str;
int sz;
- switch (*tptr) {
+ switch (UnqualifiedType (*T)) {
case T_SCHAR:
case T_UCHAR:
/* Make it byte sized */
lval.e_const &= 0xFF;
}
- assignadjust (tptr, &lval);
+ assignadjust (T, &lval);
DefineData (&lval);
break;
/* Make it word sized */
lval.e_const &= 0xFFFF;
}
- assignadjust (tptr, &lval);
+ assignadjust (T, &lval);
DefineData (&lval);
break;
/* Make it long sized */
lval.e_const &= 0xFFFFFFFF;
}
- assignadjust (tptr, &lval);
+ assignadjust (T, &lval);
DefineData (&lval);
break;
case T_ARRAY:
- sz = Decode (tptr + 1);
- t = tptr + DECODE_SIZE + 1;
- if ((t [0] == T_CHAR || t [0] == T_UCHAR) && curtok == TOK_SCONST) {
+ sz = Decode (T + 1);
+ t = T + DECODE_SIZE + 1;
+ if (IsTypeChar(t) && curtok == TOK_SCONST) {
str = GetLiteral (curval);
count = strlen (str) + 1;
TranslateLiteralPool (curval); /* Translate into target charset */
ConsumeLCurly ();
count = 0;
while (curtok != TOK_RCURLY) {
- ParseInit (tptr + DECODE_SIZE + 1);
+ ParseInit (T + DECODE_SIZE + 1);
++count;
if (curtok != TOK_COMMA)
break;
ConsumeRCurly ();
}
if (sz == 0) {
- Encode (tptr + 1, count);
+ Encode (T + 1, count);
} 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) {
Error (ERR_TOO_MANY_INITIALIZERS);
}
case T_STRUCT:
case T_UNION:
- ParseStructInit (tptr);
+ ParseStructInit (T);
break;
case T_VOID:
*/
void ParseInit (type* tptr);
-/* Parse initialization of variables */
+/* Parse initialization of variables. */
"Illegal hex digit",
"Illegal character constant",
"Illegal modifier",
+ "Illegal type qualifier",
"Illegal storage class",
"Illegal segment name: `%s'",
"Division by zero",
"__fastcall__ is not allowed for C functions",
"Variable has unknown size",
"Unknown identifier: `%s'",
+ "Duplicate qualifier: `%s'",
+ "Assignment to const",
};
ERR_ILLEGAL_HEX_DIGIT,
ERR_ILLEGAL_CHARCONST,
ERR_ILLEGAL_MODIFIER,
+ ERR_ILLEGAL_QUALIFIER,
ERR_ILLEGAL_STORAGE_CLASS,
ERR_ILLEGAL_SEG_NAME,
ERR_DIV_BY_ZERO,
ERR_FASTCALL,
ERR_UNKNOWN_SIZE,
ERR_UNKNOWN_IDENT,
+ ERR_DUPLICATE_QUALIFIER,
+ ERR_CONST_ASSIGN,
ERR_COUNT /* Error count */
};
static int IsNullPtr (struct expent* lval)
/* 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_const == 0); /* And is it's value zero? */
}
* - If one of the values is unsigned, the result is also unsigned.
* - Otherwise the result is an int.
*/
- if (IsLong (lhst) || IsLong (rhst)) {
+ if (IsTypeLong (lhst) || IsTypeLong (rhst)) {
if (IsUnsigned (lhst) || IsUnsigned (rhst)) {
return type_ulong;
} else {
* error message.
*/
Error (ERR_ILLEGAL_TYPE);
- } else if (IsInt (lhst)) {
- if (IsPtr (rhst)) {
+ } else if (IsClassInt (lhst)) {
+ if (IsClassPtr (rhst)) {
/* Pointer -> int conversion */
Warning (WARN_PTR_TO_INT_CONV);
- } else if (!IsInt (rhst)) {
+ } else if (!IsClassInt (rhst)) {
Error (ERR_INCOMPATIBLE_TYPES);
} else {
/* Adjust the int types. To avoid manipulation of TOS mark lhs
}
return g_typeadjust (TypeOf (lhst) | CF_CONST, flags);
}
- } else if (IsPtr (lhst)) {
- if (IsPtr (rhst)) {
+ } else if (IsClassPtr (lhst)) {
+ if (IsClassPtr (rhst)) {
/* Pointer to pointer assignment is valid, if:
* - both point to the same types, or
* - the rhs pointer is a void pointer, or
if (!EqualTypes (left, right) && *left != T_VOID && *right != T_VOID) {
Error (ERR_INCOMPATIBLE_POINTERS);
}
- } else if (IsInt (rhst)) {
+ } else if (IsClassInt (rhst)) {
/* Int to pointer assignment is valid only for constant zero */
if ((rhs->e_flags & E_MCONST) == 0 || rhs->e_const != 0) {
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
* that both functions have the same parameter list.
*/
/* The symbol is referenced now */
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 1;
exprhs (CF_NONE, k, lval);
}
- if (IsPtr (tptr1)) {
+ if (IsClassPtr (tptr1)) {
/* Scale the subscript value according to element size */
lval2.e_const *= PSizeOf (tptr1);
/* Handle constant base array on stack. Be sure NOT to
* 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_MLOCAL ||
(lval->e_flags & E_MGLOBAL) != 0 ||
/* Done */
goto end_array;
- } else if (IsPtr (tptr2 = lval2.e_tptr)) {
+ } else if (IsClassPtr (tptr2 = lval2.e_tptr)) {
/* Subscript is pointer, get element type */
lval2.e_tptr = Indirect (tptr2);
exprhs (CF_NONE, l, &lval2);
tptr2 = lval2.e_tptr;
- if (IsPtr (tptr1)) {
+ if (IsClassPtr (tptr1)) {
/* Get the element type */
lval->e_tptr = Indirect (tptr1);
*/
g_scale (CF_INT, SizeOf (lval->e_tptr));
- } else if (IsPtr (tptr2)) {
+ } else if (IsClassPtr (tptr2)) {
/* Get the element type */
lval2.e_tptr = Indirect (tptr2);
g_inc (CF_INT | CF_UNSIGNED, lval->e_const);
} else if (lflags == E_MLOCAL) {
/* Base address is a local variable address */
- if (IsArray (tptr1)) {
+ if (IsTypeArray (tptr1)) {
g_addaddr_local (CF_INT, lval->e_const);
} else {
g_addlocal (CF_PTR, lval->e_const);
/* Base address is a static variable address */
unsigned flags = CF_INT;
flags |= GlobalModeFlags (lval->e_flags);
- if (IsArray (tptr1)) {
+ if (IsTypeArray (tptr1)) {
g_addaddr_static (flags, lval->e_name, lval->e_const);
} else {
g_addstatic (flags, lval->e_name, lval->e_const);
lval->e_flags = E_MEXPR;
end_array:
ConsumeRBrack ();
- return !IsArray (lval->e_tptr);
+ return !IsTypeArray (lval->e_tptr);
}
lval->e_flags = E_MEOFFS;
}
lval->e_tptr = Field->Type;
- return !IsArray (Field->Type);
+ return !IsTypeArray (Field->Type);
}
/* Function call. Skip the opening parenthesis */
NextToken ();
tptr = lval->e_tptr;
- if (IsFunc (tptr) || IsFuncPtr (tptr)) {
- if (IsFuncPtr (tptr)) {
+ if (IsTypeFunc (tptr) || IsTypeFuncPtr (tptr)) {
+ if (IsTypeFuncPtr (tptr)) {
/* Pointer to function. Handle transparently */
exprhs (CF_NONE, k, lval); /* Function pointer to A/X */
++lval->e_tptr; /* Skip T_PTR */
} else if (curtok == TOK_DOT) {
- if (!IsStruct (lval->e_tptr)) {
+ if (!IsClassStruct (lval->e_tptr)) {
Error (ERR_STRUCT_EXPECTED);
}
k = structref (0, lval);
lval->e_const = 0; /* Offset is zero now */
}
t = lval->e_tptr;
- if (IsPtr (t)) {
+ if (IsClassPtr (t)) {
lval->e_tptr = Indirect (t);
} else {
Error (ERR_ILLEGAL_INDIRECT);
k = hie10 (lval);
if (k == 0) {
/* Allow the & operator with an array */
- if (!IsArray (lval->e_tptr)) {
+ if (!IsTypeArray (lval->e_tptr)) {
Error (ERR_ILLEGAL_ADDRESS);
}
} else {
*UsedGen = 1;
/* 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);
}
rconst = (evalexpr (CF_NONE, hienext, &lval2) == 0);
/* Check the type of the rhs */
- if (!IsInt (lval2.e_tptr)) {
+ if (!IsClassInt (lval2.e_tptr)) {
Error (ERR_INT_EXPR_EXPECTED);
}
rconst = (evalexpr (CF_NONE, hienext, &lval2) == 0);
/* Make sure, the types are compatible */
- if (IsInt (lval->e_tptr)) {
- if (!IsInt (lval2.e_tptr) && !(IsPtr(lval2.e_tptr) && IsNullPtr(lval))) {
+ if (IsClassInt (lval->e_tptr)) {
+ if (!IsClassInt (lval2.e_tptr) && !(IsClassPtr(lval2.e_tptr) && IsNullPtr(lval))) {
Error (ERR_INCOMPATIBLE_TYPES);
}
- } else if (IsPtr (lval->e_tptr)) {
- if (IsPtr (lval2.e_tptr)) {
+ } else if (IsClassPtr (lval->e_tptr)) {
+ if (IsClassPtr (lval2.e_tptr)) {
/* Both pointers are allowed in comparison if they point to
* the same type, or if one of them is a void pointer.
*/
* operation as char operation. Otherwise the default
* 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;
if (IsUnsigned (lval->e_tptr) || IsUnsigned (lval2.e_tptr)) {
flags |= CF_UNSIGNED;
rhst = lval2.e_tptr;
/* 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 */
lval->e_const = lval->e_const + lval2.e_const * PSizeOf (lhst);
/* 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 */
lval->e_const = lval->e_const * PSizeOf (rhst) + lval2.e_const;
/* Result type is a pointer */
lval->e_tptr = lval2.e_tptr;
- } else if (IsInt (lhst) && IsInt (rhst)) {
+ } else if (IsClassInt (lhst) && IsClassInt (rhst)) {
/* Integer addition */
lval->e_const += lval2.e_const;
typeadjust (lval, &lval2, 1);
rhst = lval2.e_tptr;
/* Check for pointer arithmetic */
- if (IsPtr (lhst) && IsInt (rhst)) {
+ if (IsClassPtr (lhst) && IsClassInt (rhst)) {
/* Left is pointer, right is int, must scale rhs */
g_scale (CF_INT, PSizeOf (lhst));
/* Operate on pointers, result type is a pointer */
flags = CF_PTR;
- } else if (IsInt (lhst) && IsPtr (rhst)) {
+ } else if (IsClassInt (lhst) && IsClassPtr (rhst)) {
/* Left is int, right is pointer, must scale lhs */
lval->e_const *= PSizeOf (rhst);
/* Operate on pointers, result type is a pointer */
flags = CF_PTR;
lval->e_tptr = lval2.e_tptr;
- } else if (IsInt (lhst) && IsInt (rhst)) {
+ } else if (IsClassInt (lhst) && IsClassInt (rhst)) {
/* Integer addition */
flags = typeadjust (lval, &lval2, 1);
} else {
pop (TypeOf (lval->e_tptr));
/* Check for pointer arithmetic */
- if (IsPtr (lhst) && IsInt (rhst)) {
+ if (IsClassPtr (lhst) && IsClassInt (rhst)) {
/* Left is pointer, right is int, must scale rhs */
lval2.e_const *= PSizeOf (lhst);
/* Operate on pointers, result type is a pointer */
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) */
g_scale (CF_INT | CF_CONST, PSizeOf (rhst));
/* Operate on pointers, result type is a pointer */
flags = CF_PTR;
lval->e_tptr = lval2.e_tptr;
- } else if (IsInt (lhst) && IsInt (rhst)) {
+ } else if (IsClassInt (lhst) && IsClassInt (rhst)) {
/* Integer addition */
flags = typeadjust (lval, &lval2, 1);
} else {
rhst = lval2.e_tptr;
/* Check for pointer arithmetic */
- if (IsPtr (lhst) && IsInt (rhst)) {
+ if (IsClassPtr (lhst) && IsClassInt (rhst)) {
/* Left is pointer, right is int, must scale rhs */
g_scale (CF_INT, PSizeOf (lhst));
/* Operate on pointers, result type is a pointer */
flags = CF_PTR;
- } else if (IsInt (lhst) && IsPtr (rhst)) {
+ } else if (IsClassInt (lhst) && IsClassPtr (rhst)) {
/* Left is int, right is pointer, must scale lhs */
g_tosint (TypeOf (rhst)); /* Make sure, TOS is int */
g_swap (CF_INT); /* Swap TOS and primary */
/* Operate on pointers, result type is a pointer */
flags = CF_PTR;
lval->e_tptr = lval2.e_tptr;
- } else if (IsInt (lhst) && IsInt (rhst)) {
+ } else if (IsClassInt (lhst) && IsClassInt (rhst)) {
/* Integer addition */
flags = typeadjust (lval, &lval2, 0);
} else {
pop (TypeOf (lhst)); /* Clean up the stack */
/* Check for pointer arithmetic */
- if (IsPtr (lhst) && IsInt (rhst)) {
+ if (IsClassPtr (lhst) && IsClassInt (rhst)) {
/* Left is pointer, right is int, must scale rhs */
lval->e_const -= lval2.e_const * PSizeOf (lhst);
/* 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 */
if (TypeCmp (Indirect (lhst), Indirect (rhst)) != 0) {
Error (ERR_INCOMPATIBLE_POINTERS);
}
/* Operate on pointers, result type is an integer */
lval->e_tptr = type_int;
- } else if (IsInt (lhst) && IsInt (rhst)) {
+ } else if (IsClassInt (lhst) && IsClassInt (rhst)) {
/* Integer subtraction */
typeadjust (lval, &lval2, 1);
lval->e_const -= lval2.e_const;
RemoveCode (Mark2);
pop (TypeOf (lhst));
- if (IsPtr (lhst) && IsInt (rhst)) {
+ if (IsClassPtr (lhst) && IsClassInt (rhst)) {
/* Left is pointer, right is int, must scale rhs */
lval2.e_const *= PSizeOf (lhst);
/* Operate on pointers, result type is a pointer */
flags = CF_PTR;
- } else if (IsPtr (lhst) && IsPtr (rhst)) {
+ } else if (IsClassPtr (lhst) && IsClassPtr (rhst)) {
/* Left is pointer, right is pointer, must scale result */
if (TypeCmp (Indirect (lhst), Indirect (rhst)) != 0) {
Error (ERR_INCOMPATIBLE_POINTERS);
/* Operate on pointers, result type is an integer */
flags = CF_PTR;
lval->e_tptr = type_int;
- } else if (IsInt (lhst) && IsInt (rhst)) {
+ } else if (IsClassInt (lhst) && IsClassInt (rhst)) {
/* Integer subtraction */
flags = typeadjust (lval, &lval2, 1);
} else {
rhst = lval2.e_tptr;
/* Check for pointer arithmetic */
- if (IsPtr (lhst) && IsInt (rhst)) {
+ if (IsClassPtr (lhst) && IsClassInt (rhst)) {
/* Left is pointer, right is int, must scale rhs */
g_scale (CF_INT, PSizeOf (lhst));
/* Operate on pointers, result type is a pointer */
flags = CF_PTR;
- } else if (IsPtr (lhst) && IsPtr (rhst)) {
+ } else if (IsClassPtr (lhst) && IsClassPtr (rhst)) {
/* Left is pointer, right is pointer, must scale result */
if (TypeCmp (Indirect (lhst), Indirect (rhst)) != 0) {
Error (ERR_INCOMPATIBLE_POINTERS);
/* Operate on pointers, result type is an integer */
flags = CF_PTR;
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
* the lhs is const, we have to remove this mark, since this is no
* longer true, lhs is on stack instead.
*/
type2 = lval2.e_tptr;
type3 = lval3.e_tptr;
- if (IsInt (type2) && IsInt (type3)) {
+ if (IsClassInt (type2) && IsClassInt (type3)) {
/* Get common type */
rtype = promoteint (type2, type3);
labt = 0; /* Mark other label as invalid */
}
- } else if (IsPtr (type2) && IsPtr (type3)) {
+ } else if (IsClassPtr (type2) && IsClassPtr (type3)) {
/* Must point to same type */
if (TypeCmp (Indirect (type2), Indirect (type3)) != 0) {
Error (ERR_INCOMPATIBLE_TYPES);
}
/* Result has the common type */
rtype = lval2.e_tptr;
- } else if (IsPtr (type2) && IsNullPtr (&lval3)) {
+ } else if (IsClassPtr (type2) && IsNullPtr (&lval3)) {
/* Result type is pointer, no cast needed */
rtype = lval2.e_tptr;
- } else if (IsNullPtr (&lval2) && IsPtr (type3)) {
+ } else if (IsNullPtr (&lval2) && IsClassPtr (type3)) {
/* Result type is pointer, no cast needed */
rtype = lval3.e_tptr;
} else {
unsigned flags;
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
* assigning structs is one of the more useful operations from this
* familiy, allow it here.
*/
- if (IsStruct (ltype)) {
+ if (IsClassStruct (ltype)) {
/* Bring the address of the lhs into the primary and push it */
exprhs (0, 0, lval);
/* Get an integer expression */
{
expression (lval);
- if (!IsInt (lval->e_tptr)) {
+ if (!IsClassInt (lval->e_tptr)) {
Error (ERR_INT_EXPR_EXPECTED);
/* To avoid any compiler errors, make the expression a valid int */
lval->e_flags = E_MCONST;
* the pointer used in a boolean context is also ok (Ootherwise check if it's a pointer
* expression.
*/
- if (!IsInt (lval->e_tptr) && !IsPtr (lval->e_tptr)) {
+ if (!IsClassInt (lval->e_tptr) && !IsClassPtr (lval->e_tptr)) {
Error (ERR_INT_EXPR_EXPECTED);
/* To avoid any compiler errors, make the expression a valid int */
lval->e_flags = E_MCONST;
ParseDecl (Spec, &Decl, DM_NEED_IDENT);
/* Set the correct storage class for functions */
- if (IsFunc (Decl.Type)) {
+ if (IsTypeFunc (Decl.Type)) {
/* Function prototypes are always external */
if ((SC & SC_EXTERN) == 0) {
Warning (WARN_FUNC_MUST_BE_EXTERN);
#include <stdio.h>
#include <string.h>
-#include "../common/xmalloc.h"
-
+/* common */
+#include "xmalloc.h"
+
+/* cc65 */
#include "asmcode.h"
#include "asmlabel.h"
#include "codegen.h"
/* Read the selector expression */
constexpr (&lval);
- if (!IsInt (lval.e_tptr)) {
+ if (!IsClassInt (lval.e_tptr)) {
Error (ERR_ILLEGAL_TYPE);
}
if (curtok == TOK_CASE) {
NextToken ();
constexpr (&lval);
- if (!IsInt (lval.e_tptr)) {
+ if (!IsClassInt (lval.e_tptr)) {
Error (ERR_ILLEGAL_TYPE);
}
p->sw_const = lval.e_const;
ConsumeLCurly ();
/* 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);
} else {
tableswitch (&eval);
}
/* Non-structs do not have any struct fields... */
- if (IsStruct (Type)) {
+ if (IsClassStruct (Type)) {
const SymTable* Tab;
/* Add an external or global symbol to the symbol table and return the entry */
{
/* 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? */
SymEntry* Entry = FindSymInTable (Tab, Name, HashStr (Name));
* incomplete declaration. Accept this, and if the exsting entry is
* incomplete, complete it.
*/
- if (IsArray (Type) && IsArray (EType)) {
+ if (IsTypeArray (Type) && IsTypeArray (EType)) {
/* Get the array sizes */
unsigned Size = Decode (Type + 1);
* contains pointers to the new symbol tables that are needed if
* an actual function definition follows.
*/
- if (IsFunc (Type)) {
+ if (IsTypeFunc (Type)) {
CopyEncode (Type+1, EType+1);
}
}