X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fcc65%2Fdatatype.c;h=1c17c27960007cdb3ad02da11436b774d5b96b78;hb=3f4096d3030095605f28b4cfa73563c53a563df6;hp=c7070725735768c8e2b76e76a369d9011b9ef276;hpb=e133416d05e72faae9306ea830f656c89246850b;p=cc65 diff --git a/src/cc65/datatype.c b/src/cc65/datatype.c index c70707257..1c17c2796 100644 --- a/src/cc65/datatype.c +++ b/src/cc65/datatype.c @@ -6,10 +6,10 @@ /* */ /* */ /* */ -/* (C) 1998-2000 Ullrich von Bassewitz */ -/* Wacholderweg 14 */ -/* D-70597 Stuttgart */ -/* EMail: uz@musoftware.de */ +/* (C) 1998-2004 Ullrich von Bassewitz */ +/* Römerstraße 52 */ +/* D-70794 Filderstadt */ +/* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ @@ -51,19 +51,19 @@ /*****************************************************************************/ -/* 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_SCHAR, T_END }; -type type_puchar [] = { T_PTR, T_UCHAR, T_END }; +type type_size_t [] = { T_UINT, T_END }; @@ -77,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; @@ -85,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 */ { @@ -126,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); } @@ -136,7 +122,7 @@ type* TypeAlloc (unsigned Len) * trailing T_END. */ { - return xmalloc (Len * sizeof (type)); + return (type*) xmalloc (Len * sizeof (type)); } @@ -149,10 +135,22 @@ void TypeFree (type* T) +int SignExtendChar (int C) +/* Do correct sign extension of a character */ +{ + if (IS_Get (&SignedChars) && (C & 0x80) != 0) { + return C | ~0xFF; + } else { + return C & 0xFF; + } +} + + + type GetDefaultChar (void) /* Return the default char type (signed/unsigned) depending on the settings */ { - return SignedChars? T_SCHAR : T_UCHAR; + return IS_Get (&SignedChars)? T_SCHAR : T_UCHAR; } @@ -187,7 +185,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; @@ -205,13 +203,34 @@ type* GetImplicitFuncType (void) +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); + fprintf (F, "%s ", Name); T &= ~Mask; } return T; @@ -222,69 +241,123 @@ static type PrintTypeComp (FILE* F, type T, type Mask, const char* Name) 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; + unsigned long Size; /* 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. 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"); + } + 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"); + 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\n"); - break; - case T_TYPE_STRUCT: - fprintf (F, "struct %s\n", ((SymEntry*) DecodePtr (Type))->Name); - Type += DECODE_SIZE; + fprintf (F, "void"); + break; + case T_TYPE_STRUCT: + fprintf (F, "struct %s", ((SymEntry*) DecodePtr (Type))->Name); + Type += DECODE_SIZE; break; case T_TYPE_UNION: - fprintf (F, "union %s\n", ((SymEntry*) DecodePtr (Type))->Name); + fprintf (F, "union %s", ((SymEntry*) DecodePtr (Type))->Name); Type += DECODE_SIZE; break; case T_TYPE_ARRAY: - fprintf (F, "array[%lu] of ", Decode (Type)); - Type += DECODE_SIZE; - break; + /* 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: - fprintf (F, "pointer to "); - break; + /* Recursive call */ + PrintType (F, Type); + fprintf (F, "*"); + return; case T_TYPE_FUNC: fprintf (F, "function returning "); Type += DECODE_SIZE; break; default: - fprintf (F, "unknown type: %04X\n", T); + fprintf (F, "unknown type: %04X", T); } - /* Get the next type element */ - T = *Type++; + } +} + + + +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_NEAR) { + fprintf (F, " __near__"); + } + if (D->Flags & FD_FAR) { + fprintf (F, " __far__"); + } + 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, ", "); + } + if (SymIsRegVar (E)) { + fprintf (F, "register "); + } + PrintType (F, E->Type); + E = E->NextSym; + } + } - } while (T != T_END); + /* End of parameter list */ + fprintf (F, ")"); } @@ -301,7 +374,7 @@ void PrintRawType (FILE* F, const type* Type) void Encode (type* Type, unsigned long Val) -/* Encode p[0] and p[1] so that neither p[0] nore p[1] is zero */ +/* Encode Val into the given type string */ { int I; for (I = 0; I < DECODE_SIZE; ++I) { @@ -345,7 +418,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); } @@ -362,38 +435,45 @@ unsigned SizeOf (const type* T) /* Compute size of object represented by type array. */ { SymEntry* Entry; + long ElementCount; - switch (*T) { + switch (UnqualifiedType (T[0])) { - case T_VOID: - Error (ERR_ILLEGAL_SIZE); - return 0; + case T_VOID: + return 0; /* Assume voids have size zero */ case T_SCHAR: case T_UCHAR: - return 1; + return SIZEOF_CHAR; case T_SHORT: case T_USHORT: + return SIZEOF_SHORT; + case T_INT: case T_UINT: + return SIZEOF_INT; + case T_PTR: - return 2; + case T_FUNC: /* Maybe pointer to function */ + return SIZEOF_PTR; case T_LONG: case T_ULONG: - return 4; + return SIZEOF_LONG; case T_LONGLONG: case T_ULONGLONG: - return 8; + return SIZEOF_LONGLONG; case T_ENUM: - return 2; + return SIZEOF_INT; case T_FLOAT: + return SIZEOF_FLOAT; + case T_DOUBLE: - return 4; + return SIZEOF_DOUBLE; case T_STRUCT: case T_UNION: @@ -401,7 +481,13 @@ unsigned SizeOf (const type* T) return Entry->V.S.Size; case T_ARRAY: - return (Decode (T+ 1) * SizeOf (T + DECODE_SIZE + 1)); + ElementCount = GetElementCount (T); + if (ElementCount < 0) { + /* Array with unspecified size */ + return 0; + } else { + return ElementCount * SizeOf (T + DECODE_SIZE + 1); + } default: Internal ("Unknown type in SizeOf: %04X", *T); @@ -416,10 +502,10 @@ unsigned PSizeOf (const type* T) /* Compute size of pointer object. */ { /* We are expecting a pointer expression */ - CHECK ((*T & T_CLASS_PTR) != 0); + CHECK ((T[0] & T_MASK_CLASS) == T_CLASS_PTR); /* 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); @@ -428,12 +514,44 @@ unsigned PSizeOf (const type* T) -unsigned TypeOf (const type* Type) +unsigned CheckedSizeOf (const type* T) +/* Return the size of a data type. If the size is zero, emit an error and + * return some valid size instead (so the rest of the compiler doesn't have + * to work with invalid sizes). + */ +{ + unsigned Size = SizeOf (T); + if (Size == 0) { + Error ("Size of data type is unknown"); + Size = SIZEOF_CHAR; /* Don't return zero */ + } + return Size; +} + + + +unsigned CheckedPSizeOf (const type* T) +/* Return the size of a data type that is pointed to by a pointer. If the + * size is zero, emit an error and return some valid size instead (so the + * rest of the compiler doesn't have to work with invalid sizes). + */ +{ + unsigned Size = PSizeOf (T); + if (Size == 0) { + Error ("Size of data type is unknown"); + Size = SIZEOF_CHAR; /* Don't return zero */ + } + return Size; +} + + + +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; @@ -458,9 +576,14 @@ unsigned TypeOf (const type* Type) case T_ULONG: return CF_LONG | CF_UNSIGNED; + case T_FLOAT: + case T_DOUBLE: + /* These two are identical in the backend */ + return CF_FLOAT; + case T_FUNC: - F = DecodePtr (Type+1); - return (F->Flags & FD_ELLIPSIS)? 0 : CF_FIXARGC; + F = DecodePtr (T+1); + return (F->Flags & FD_VARIADIC)? 0 : CF_FIXARGC; case T_STRUCT: case T_UNION: @@ -468,7 +591,7 @@ unsigned TypeOf (const type* Type) return CF_INT | CF_UNSIGNED; default: - Error (ERR_ILLEGAL_TYPE); + Error ("Illegal type"); return CF_INT; } } @@ -481,10 +604,10 @@ type* Indirect (type* T) */ { /* We are expecting a pointer expression */ - CHECK ((*T & T_MASK_CLASS) == T_CLASS_PTR); + CHECK ((T[0] & 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; @@ -493,47 +616,51 @@ type* Indirect (type* T) -int IsTypeVoid (const type* T) -/* Return true if this is a void type */ +type* ArrayToPtr (const type* T) +/* Convert an array to a pointer to it's first element */ { - return (T[0] == T_VOID && T[1] == T_END); + /* Function must only be called for an array */ + CHECK ((T[0] & T_MASK_TYPE) == T_TYPE_ARRAY); + + /* Return pointer to first element */ + return PointerTo (T + DECODE_SIZE + 1); } -int IsPtr (const type* T) -/* Return true if this is a pointer type */ +int IsClassInt (const type* T) +/* Return true if this is an integer type */ { - return (T[0] & T_MASK_CLASS) == T_CLASS_PTR; + return (T[0] & T_MASK_CLASS) == T_CLASS_INT; } -int IsChar (const type* T) -/* Return true if this is a character type */ +int IsClassFloat (const type* T) +/* Return true if this is a float type */ { - return (T[0] & T_MASK_TYPE) == T_TYPE_CHAR && T[1] == T_END; + return (T[0] & T_MASK_CLASS) == T_CLASS_FLOAT; } -int IsInt (const type* T) -/* Return true if this is an integer type */ +int IsClassPtr (const type* T) +/* Return true if this is a pointer type */ { - return (T[0] & T_MASK_CLASS) == T_CLASS_INT; + return (T[0] & T_MASK_CLASS) == T_CLASS_PTR; } -int IsLong (const type* T) -/* Return true if this is a long type (signed or unsigned) */ +int IsClassStruct (const type* T) +/* Return true if this is a struct type */ { - return (T[0] & T_MASK_SIZE) == T_SIZE_LONG; + return (T[0] & T_MASK_CLASS) == T_CLASS_STRUCT; } -int IsUnsigned (const type* T) +int IsSignUnsigned (const type* T) /* Return true if this is an unsigned type */ { return (T[0] & T_MASK_SIGN) == T_SIGN_UNSIGNED; @@ -541,53 +668,62 @@ int IsUnsigned (const type* T) -int IsStruct (const type* T) -/* Return true if this is a struct type */ +int IsQualConst (const type* T) +/* Return true if the given type has a const memory image */ { - return (T[0] & T_MASK_CLASS) == T_CLASS_STRUCT; + return (GetQualifier (T) & T_QUAL_CONST) != 0; } -int IsFunc (const type* T) -/* Return true if this is a function type */ +int IsQualVolatile (const type* T) +/* Return true if the given type has a volatile type qualifier */ { - return (T[0] == T_FUNC); + return (GetQualifier (T) & T_QUAL_VOLATILE) != 0; } 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 or pointer to function with + * __fastcall__ calling conventions + */ { - FuncDesc* F; - CHECK (T[0] == T_FUNC); - F = DecodePtr (T+1); + FuncDesc* F = GetFuncDesc (T); return (F->Flags & FD_FASTCALL) != 0; } -int IsFuncPtr (const type* T) -/* Return true if this is a function pointer */ +int IsVariadicFunc (const type* T) +/* Return true if this is a function type or pointer to function type with + * variable parameter list + */ { - return (T[0] == T_PTR && T[1] == T_FUNC); + FuncDesc* F = GetFuncDesc (T); + return (F->Flags & FD_VARIADIC) != 0; } -int IsArray (const type* T) -/* Return true if this is an array type */ +type GetQualifier (const type* T) +/* Get the qualifier from the given type string */ { - return (T[0] == T_ARRAY); + /* 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); } -struct FuncDesc* GetFuncDesc (const type* T) +FuncDesc* GetFuncDesc (const type* T) /* Get the FuncDesc pointer from a function or pointer-to-function type */ { - if (T[0] == T_PTR) { + if (UnqualifiedType (T[0]) == T_PTR) { /* Pointer to function */ ++T; } @@ -601,4 +737,41 @@ struct FuncDesc* GetFuncDesc (const type* T) +type* GetFuncReturn (type* T) +/* Return a pointer to the return type of a function or pointer-to-function type */ +{ + if (UnqualifiedType (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; + +} + + + +long GetElementCount (const type* T) +/* Get the element count of the array specified in T (which must be of + * array type). + */ +{ + CHECK (IsTypeArray (T)); + return (unsigned) Decode (T+1); +} + + + +type* GetElementType (type* T) +/* Return the element type of the given array type. */ +{ + CHECK (IsTypeArray (T)); + return T + DECODE_SIZE + 1; +} + +