X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fcc65%2Fdatatype.c;h=47944b37a4849418dc6bf52142c1e05c3e995509;hb=1366b6cbea1b374fa7502354cf2cb8a971f71c5f;hp=330a08eb679e7d83bd3b0c9f75b254c2bb979039;hpb=9cc25f13b6aabc4fd299c54c9c38c5825689eb47;p=cc65 diff --git a/src/cc65/datatype.c b/src/cc65/datatype.c index 330a08eb6..47944b37a 100644 --- a/src/cc65/datatype.c +++ b/src/cc65/datatype.c @@ -6,10 +6,10 @@ /* */ /* */ /* */ -/* (C) 1998 Ullrich von Bassewitz */ -/* Wacholderweg 14 */ -/* D-70597 Stuttgart */ -/* EMail: uz@musoftware.de */ +/* (C) 1998-2000 Ullrich von Bassewitz */ +/* Wacholderweg 14 */ +/* D-70597 Stuttgart */ +/* EMail: uz@musoftware.de */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ @@ -35,32 +35,35 @@ #include +/* common */ #include "check.h" +#include "xmalloc.h" + +/* cc65 */ #include "codegen.h" #include "datatype.h" #include "error.h" #include "funcdesc.h" #include "global.h" -#include "mem.h" #include "util.h" #include "symtab.h" /*****************************************************************************/ -/* Data */ +/* Data */ /*****************************************************************************/ /* Predefined type strings */ +type type_uchar [] = { T_UCHAR, T_END }; type type_int [] = { T_INT, T_END }; type type_uint [] = { T_UINT, T_END }; type type_long [] = { T_LONG, T_END }; type type_ulong [] = { T_ULONG, T_END }; type type_void [] = { T_VOID, T_END }; -type type_pschar [] = { T_PTR, T_CHAR, T_END }; -type type_puchar [] = { T_PTR, T_UCHAR, T_END }; +type type_size_t [] = { T_UINT, T_END }; @@ -74,7 +77,7 @@ unsigned TypeLen (const type* T) /* Return the length of the type string */ { const type* Start = T; - while (*T) { + while (*T != T_END) { ++T; } return T - Start; @@ -82,20 +85,6 @@ unsigned TypeLen (const type* T) -int TypeCmp (const type* T1, const type* T2) -/* Compare two type strings */ -{ - int A, B, D; - do { - A = *T1++; - B = *T2++; - D = A - B; - } while (D == 0 && A != 0); - return D; -} - - - type* TypeCpy (type* Dest, const type* Src) /* Copy a type string */ { @@ -123,7 +112,7 @@ type* TypeDup (const type* T) /* Create a copy of the given type on the heap */ { unsigned Len = (TypeLen (T) + 1) * sizeof (type); - return memcpy (xmalloc (Len), T, Len); + return (type*) memcpy (xmalloc (Len), T, Len); } @@ -133,7 +122,7 @@ type* TypeAlloc (unsigned Len) * trailing T_END. */ { - return xmalloc (Len * sizeof (type)); + return (type*) xmalloc (Len * sizeof (type)); } @@ -149,7 +138,7 @@ void TypeFree (type* T) type GetDefaultChar (void) /* Return the default char type (signed/unsigned) depending on the settings */ { - return SignedChars? T_CHAR : T_UCHAR; + return SignedChars? T_SCHAR : T_UCHAR; } @@ -184,7 +173,7 @@ type* GetImplicitFuncType (void) type* T = TypeAlloc (1 + DECODE_SIZE + 2); /* Prepare the function descriptor */ - F->Flags = FD_IMPLICIT | FD_EMPTY | FD_ELLIPSIS; + F->Flags = FD_IMPLICIT | FD_EMPTY | FD_VARIADIC; F->SymTab = &EmptySymTab; F->TagTab = &EmptySymTab; @@ -202,64 +191,152 @@ type* GetImplicitFuncType (void) -void PrintType (FILE* F, const type* tarray) +type* PointerTo (const type* T) +/* Return a type string that is "pointer to T". The type string is allocated + * on the heap and may be freed after use. + */ +{ + /* Get the size of the type string including the terminator */ + unsigned Size = TypeLen (T) + 1; + + /* Allocate the new type string */ + type* P = TypeAlloc (Size + 1); + + /* Create the return type... */ + P[0] = T_PTR; + memcpy (P+1, T, Size * sizeof (type)); + + /* ...and return it */ + return P; +} + + + +static type PrintTypeComp (FILE* F, type T, type Mask, const char* Name) +/* Check for a specific component of the type. If it is there, print the + * name and remove it. Return the type with the component removed. + */ +{ + if ((T & Mask) == Mask) { + fprintf (F, "%s ", Name); + T &= ~Mask; + } + return T; +} + + + +void PrintType (FILE* F, const type* Type) /* Output translation of type array. */ { - const type* p; + type T; + unsigned long Size; - for (p = tarray; *p != T_END; ++p) { - if (*p & T_UNSIGNED) { - fprintf (F, "unsigned "); + /* Walk over the complete string */ + while ((T = *Type++) != T_END) { + + /* Print any qualifiers */ + T = PrintTypeComp (F, T, T_QUAL_CONST, "const"); + T = PrintTypeComp (F, T, T_QUAL_VOLATILE, "volatile"); + + /* Signedness. Omit the signedness specifier for long and int */ + if ((T & T_MASK_TYPE) != T_TYPE_INT && (T & T_MASK_TYPE) != T_TYPE_LONG) { + T = PrintTypeComp (F, T, T_SIGN_SIGNED, "signed"); } - switch (*p) { - case T_VOID: - fprintf (F, "void\n"); - break; - case T_CHAR: - case T_UCHAR: - fprintf (F, "char\n"); - break; - case T_INT: - case T_UINT: - fprintf (F, "int\n"); - break; - case T_SHORT: - case T_USHORT: - fprintf (F, "short\n"); - break; - case T_LONG: - case T_ULONG: - fprintf (F, "long\n"); - break; - case T_FLOAT: - fprintf (F, "float\n"); - break; - case T_DOUBLE: - fprintf (F, "double\n"); - break; - case T_PTR: - fprintf (F, "pointer to "); + T = PrintTypeComp (F, T, T_SIGN_UNSIGNED, "unsigned"); + + /* Now check the real type */ + switch (T & T_MASK_TYPE) { + case T_TYPE_CHAR: + fprintf (F, "char"); + break; + case T_TYPE_SHORT: + fprintf (F, "short"); + break; + case T_TYPE_INT: + fprintf (F, "int"); + break; + case T_TYPE_LONG: + fprintf (F, "long"); + break; + case T_TYPE_LONGLONG: + fprintf (F, "long long"); + break; + case T_TYPE_FLOAT: + fprintf (F, "float"); + break; + case T_TYPE_DOUBLE: + fprintf (F, "double"); + break; + case T_TYPE_VOID: + fprintf (F, "void"); + break; + case T_TYPE_STRUCT: + fprintf (F, "struct %s", ((SymEntry*) DecodePtr (Type))->Name); + Type += DECODE_SIZE; break; - case T_ARRAY: - fprintf (F, "array[%lu] of ", Decode (p + 1)); - p += DECODE_SIZE; + case T_TYPE_UNION: + fprintf (F, "union %s", ((SymEntry*) DecodePtr (Type))->Name); + Type += DECODE_SIZE; break; - case T_STRUCT: - fprintf (F, "struct %s\n", ((SymEntry*) Decode (p + 1))->Name); - p += DECODE_SIZE; - break; - case T_UNION: - fprintf (F, "union %s\n", ((SymEntry*) Decode (p + 1))->Name); - p += DECODE_SIZE; - break; - case T_FUNC: + case T_TYPE_ARRAY: + /* Recursive call */ + PrintType (F, Type + DECODE_SIZE); + Size = Decode (Type); + if (Size == 0) { + fprintf (F, "[]"); + } else { + fprintf (F, "[%lu]", Size); + } + return; + case T_TYPE_PTR: + /* Recursive call */ + PrintType (F, Type); + fprintf (F, "*"); + return; + case T_TYPE_FUNC: fprintf (F, "function returning "); - p += DECODE_SIZE; + Type += DECODE_SIZE; break; default: - fprintf (F, "unknown type: %04X\n", *p); + fprintf (F, "unknown type: %04X", T); } + + } +} + + + +void PrintFuncSig (FILE* F, const char* Name, type* Type) +/* Print a function signature. */ +{ + /* Get the function descriptor */ + const FuncDesc* D = GetFuncDesc (Type); + + /* Print a comment with the function signature */ + PrintType (F, GetFuncReturn (Type)); + if (D->Flags & FD_FASTCALL) { + fprintf (F, " __fastcall__"); } + fprintf (F, " %s (", Name); + + /* Parameters */ + if (D->Flags & FD_VOID_PARAM) { + fprintf (F, "void"); + } else { + unsigned I; + SymEntry* E = D->SymTab->SymHead; + for (I = 0; I < D->ParamCount; ++I) { + if (I > 0) { + fprintf (F, ", "); + } + PrintType (F, E->Type); + E = E->NextSym; + } + } + + /* End of parameter list */ + fprintf (F, ")"); } @@ -320,7 +397,7 @@ void* DecodePtr (const type* Type) 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); } @@ -333,42 +410,61 @@ void CopyEncode (const type* Source, type* Target) -unsigned SizeOf (const type* tarray) +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 (*tarray) { + switch (UnqualifiedType (T[0])) { - case T_VOID: - return 0; + case T_VOID: + Error ("Variable has unknown size"); + return 1; /* Return something that makes sense */ - case T_CHAR: + case T_SCHAR: case T_UCHAR: return 1; - case T_INT: - case T_UINT: case T_SHORT: case T_USHORT: + case T_INT: + case T_UINT: case T_PTR: - case T_ENUM: return 2; case T_LONG: case T_ULONG: return 4; - case T_ARRAY: - return (Decode (tarray + 1) * SizeOf (tarray + DECODE_SIZE + 1)); + case T_LONGLONG: + case T_ULONGLONG: + return 8; + + case T_ENUM: + return 2; + + case T_FLOAT: + case T_DOUBLE: + return 4; case T_STRUCT: case T_UNION: - Entry = DecodePtr (tarray+1); + Entry = (SymEntry*) DecodePtr (T+1); return Entry->V.S.Size; + case T_ARRAY: + return (Decode (T+ 1) * SizeOf (T + DECODE_SIZE + 1)); + default: - Internal ("Unknown type: %04X", *tarray); + Internal ("Unknown type in SizeOf: %04X", *T); return 0; } @@ -376,30 +472,30 @@ unsigned SizeOf (const type* tarray) -unsigned PSizeOf (const type* tptr) +unsigned PSizeOf (const type* T) /* Compute size of pointer object. */ { /* We are expecting a pointer expression */ - CHECK (*tptr & T_POINTER); + CHECK ((*T & T_CLASS_PTR) != 0); /* Skip the pointer or array token itself */ - if (*tptr == T_ARRAY) { - return SizeOf (tptr + DECODE_SIZE + 1); + if (IsTypeArray (T)) { + return SizeOf (T + DECODE_SIZE + 1); } else { - return SizeOf (tptr + 1); + 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_CHAR: + case T_SCHAR: return CF_CHAR; case T_UCHAR: @@ -423,8 +519,8 @@ unsigned TypeOf (const type* Type) return CF_LONG | CF_UNSIGNED; case T_FUNC: - F = DecodePtr (Type+1); - return (F->Flags & FD_ELLIPSIS)? 0 : CF_FIXARGC; + F = (FuncDesc*) DecodePtr (T+1); + return (F->Flags & FD_VARIADIC)? 0 : CF_FIXARGC; case T_STRUCT: case T_UNION: @@ -432,135 +528,270 @@ unsigned TypeOf (const type* Type) return CF_INT | CF_UNSIGNED; default: - Error (ERR_ILLEGAL_TYPE); + Error ("Illegal type"); return CF_INT; } } -type* Indirect (type* Type) +type* Indirect (type* T) /* Do one indirection for the given type, that is, return the type where the * given type points to. */ { /* We are expecting a pointer expression */ - CHECK (Type[0] & T_POINTER); + CHECK ((*T & T_MASK_CLASS) == T_CLASS_PTR); /* Skip the pointer or array token itself */ - if (Type[0] == T_ARRAY) { - return Type + DECODE_SIZE + 1; + if (IsTypeArray (T)) { + return T + DECODE_SIZE + 1; } else { - return Type + 1; + return T + 1; } } -int IsVoid (const type* Type) -/* Return true if this is a void type */ +int IsTypeChar (const type* T) +/* Return true if this is a character type */ +{ + return (T[0] & T_MASK_TYPE) == T_TYPE_CHAR; +} + + + +int IsTypeInt (const type* T) +/* Return true if this is an int type (signed or unsigned) */ +{ + return (T[0] & T_MASK_TYPE) == T_TYPE_INT; +} + + + +int IsTypeLong (const type* T) +/* Return true if this is a long type (signed or unsigned) */ +{ + return (T[0] & T_MASK_TYPE) == T_TYPE_LONG; +} + + + +int IsTypeFloat (const type* T) +/* Return true if this is a float type */ +{ + return (T[0] & T_MASK_TYPE) == T_TYPE_FLOAT; +} + + + +int IsTypeDouble (const type* T) +/* Return true if this is a double type */ { - return (Type[0] == T_VOID && Type[1] == T_END); + return (T[0] & T_MASK_TYPE) == T_TYPE_DOUBLE; } -int IsPtr (const type* Type) +int IsTypePtr (const type* T) /* Return true if this is a pointer type */ { - return (Type[0] & T_POINTER) != 0; + return ((T[0] & T_MASK_TYPE) == T_TYPE_PTR); } -int IsChar (const type* Type) -/* Return true if this is a character type */ +int IsTypeArray (const type* T) +/* Return true if this is an array type */ { - return (Type[0] == T_CHAR || Type[0] == T_UCHAR) && Type[1] == T_END; + return ((T[0] & T_MASK_TYPE) == T_TYPE_ARRAY); } -int IsInt (const type* Type) +int IsTypeVoid (const type* T) +/* Return true if this is a void type */ +{ + return (T[0] & T_MASK_TYPE) == T_TYPE_VOID; +} + + + +int IsTypeFunc (const type* T) +/* Return true if this is a function class */ +{ + return ((T[0] & T_MASK_TYPE) == T_TYPE_FUNC); +} + + + +int IsClassInt (const type* T) /* Return true if this is an integer type */ { - return (Type[0] & T_INTEGER) != 0; + return (T[0] & T_MASK_CLASS) == T_CLASS_INT; } -int IsLong (const type* Type) -/* Return true if this is a long type (signed or unsigned) */ +int IsClassFloat (const type* T) +/* Return true if this is a float type */ { - return (Type[0] & T_LONG) == T_LONG; + return (T[0] & T_MASK_CLASS) == T_CLASS_FLOAT; } -int IsUnsigned (const type* Type) -/* Return true if this is an unsigned type */ +int IsClassPtr (const type* T) +/* Return true if this is a pointer type */ { - return (Type[0] & T_UNSIGNED) != 0; + return (T[0] & T_MASK_CLASS) == T_CLASS_PTR; } -int IsStruct (const type* Type) +int IsClassStruct (const type* T) /* Return true if this is a struct type */ { - return (Type[0] == T_STRUCT || Type[0] == T_UNION); + return (T[0] & T_MASK_CLASS) == T_CLASS_STRUCT; } -int IsFunc (const type* Type) -/* Return true if this is a function type */ +int IsSignUnsigned (const type* T) +/* Return true if this is an unsigned type */ { - return (Type[0] == T_FUNC); + return (T[0] & T_MASK_SIGN) == T_SIGN_UNSIGNED; } -int IsFastCallFunc (const type* Type) -/* Return true if this is a function type with __fastcall__ calling conventions */ +int IsQualConst (const type* T) +/* Return true if the given type has a const memory image */ { - FuncDesc* F; - CHECK (*Type == T_FUNC); - F = DecodePtr (Type+1); + return (GetQualifier (T) & T_QUAL_CONST) != 0; +} + + + +int IsQualVolatile (const type* T) +/* Return true if the given type has a volatile type qualifier */ +{ + return (GetQualifier (T) & T_QUAL_VOLATILE) != 0; +} + + + +int IsFastCallFunc (const type* T) +/* Return true if this is a function type or pointer to function with + * __fastcall__ calling conventions + */ +{ + FuncDesc* F = GetFuncDesc (T); return (F->Flags & FD_FASTCALL) != 0; } -int IsFuncPtr (const type* Type) +int IsVariadicFunc (const type* T) +/* Return true if this is a function type or pointer to function type with + * variable parameter list + */ +{ + FuncDesc* F = GetFuncDesc (T); + return (F->Flags & FD_VARIADIC) != 0; +} + + + +int IsTypeFuncPtr (const type* T) /* Return true if this is a function pointer */ { - return (Type[0] == T_PTR && Type[1] == T_FUNC); + return ((T[0] & T_MASK_TYPE) == T_TYPE_PTR && (T[1] & T_MASK_TYPE) == T_TYPE_FUNC); } -int IsArray (const type* Type) -/* Return true if this is an array type */ +type GetType (const type* T) +/* Get the raw type */ +{ + PRECONDITION (T[0] != T_END); + return (T[0] & T_MASK_TYPE); +} + + + +type GetClass (const type* T) +/* Get the class of a type string */ +{ + PRECONDITION (T[0] != T_END); + return (T[0] & T_MASK_CLASS); +} + + + +type GetSignedness (const type* T) +/* Get the sign of a type */ +{ + PRECONDITION (T[0] != T_END); + return (T[0] & T_MASK_SIGN); +} + + + +type GetSizeModifier (const type* T) +/* Get the size modifier of a type */ { - return (Type[0] == T_ARRAY); + PRECONDITION (T[0] != T_END); + return (T[0] & T_MASK_SIZE); } -struct FuncDesc* GetFuncDesc (const type* Type) +type GetQualifier (const type* T) +/* Get the qualifier from the given type string */ +{ + /* 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); +} + + + +FuncDesc* GetFuncDesc (const type* T) /* Get the FuncDesc pointer from a function or pointer-to-function type */ { - if (Type[0] == T_PTR) { + if (T[0] == T_PTR) { /* Pointer to function */ - ++Type; + ++T; } /* Be sure it's a function type */ - CHECK (Type[0] == T_FUNC); + CHECK (T[0] == T_FUNC); /* Decode the function descriptor and return it */ - return DecodePtr (Type+1); + return (FuncDesc*) DecodePtr (T+1); +} + + + +type* GetFuncReturn (type* T) +/* Return a pointer to the return type of a function or pointer-to-function type */ +{ + if (T[0] == T_PTR) { + /* Pointer to function */ + ++T; + } + + /* Be sure it's a function type */ + CHECK (T[0] == T_FUNC); + + /* Return a pointer to the return type */ + return T + 1 + DECODE_SIZE; + }