]> git.sur5r.net Git - cc65/commitdiff
Reworked type comparison and handling of type qualifiers
authorcuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Mon, 14 Aug 2000 22:18:26 +0000 (22:18 +0000)
committercuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Mon, 14 Aug 2000 22:18:26 +0000 (22:18 +0000)
git-svn-id: svn://svn.cc65.org/cc65/trunk@285 b7a2c559-68d2-44c3-8de9-860c34a00d81

16 files changed:
src/cc65/compile.c
src/cc65/datatype.c
src/cc65/datatype.h
src/cc65/error.c
src/cc65/error.h
src/cc65/expr.c
src/cc65/locals.c
src/cc65/make/gcc.mak
src/cc65/make/watcom.mak
src/cc65/scanner.c
src/cc65/scanner.h
src/cc65/stdfunc.c
src/cc65/symtab.c
src/cc65/symtab.h
src/cc65/typecmp.c [new file with mode: 0644]
src/cc65/typecmp.h [new file with mode: 0644]

index cb3dd92c51fa318e843975eb4ec18a8b0beda6ba..58ee19f5cab69dd1c9f3f1b50975662c5947a985 100644 (file)
@@ -173,7 +173,7 @@ static void Parse (void)
                    }
 
                    /* Switch to the data or rodata segment */
-                   if (IsConst (Decl.Type)) {
+                   if (IsQualConst (Decl.Type)) {
                        g_userodata ();
                    } else {
                        g_usedata ();
index a450d0972e25adc1b09c65f0809d7672b7b0ef19..ba2fa33ff823d775a916537b6336e2592556c7c1 100644 (file)
@@ -62,8 +62,6 @@ 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 };
 
 
 
@@ -77,7 +75,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 +83,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 */
 {
@@ -502,40 +486,58 @@ type* Indirect (type* T)
 
 
 
-int IsConst (const type* T)
-/* Return true if the given type has a const memory image */
+int IsTypeChar (const type* T)
+/* Return true if this is a character type */
 {
-    /* 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);
+    return (T[0] & T_MASK_TYPE) == T_TYPE_CHAR;
 }
 
 
 
-int IsTypeVoid (const type* T)
-/* Return true if this is a void type */
+int IsTypeInt (const type* T)
+/* Return true if this is an int type (signed or unsigned) */
 {
-    return ((T[0] & T_MASK_TYPE) == T_TYPE_VOID && T[1] == T_END);
+    return (T[0] & T_MASK_TYPE) == T_TYPE_INT;
 }
 
 
 
-int IsClassPtr (const type* T)
+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 IsTypePtr (const type* T)
 /* Return true if this is a pointer type */
 {
-    return (T[0] & T_MASK_CLASS) == T_CLASS_PTR;
+    return ((T[0] & T_MASK_TYPE) == T_TYPE_PTR);
 }
 
 
 
-int IsTypeChar (const type* T)
-/* Return true if this is a character type */
+int IsTypeArray (const type* T)
+/* Return true if this is an array type */
+{
+    return ((T[0] & T_MASK_TYPE) == T_TYPE_ARRAY);
+}
+
+
+
+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_CHAR && T[1] == T_END;
+    return ((T[0] & T_MASK_TYPE) == T_TYPE_FUNC);
 }
 
 
@@ -548,15 +550,23 @@ int IsClassInt (const type* T)
 
 
 
-int IsTypeLong (const type* T)
-/* Return true if this is a long type (signed or unsigned) */
+int IsClassPtr (const type* T)
+/* Return true if this is a pointer type */
 {
-    return (T[0] & T_MASK_TYPE) == T_TYPE_LONG;
+    return (T[0] & T_MASK_CLASS) == T_CLASS_PTR;
+}
+
+
+
+int IsClassStruct (const type* T)
+/* Return true if this is a struct type */
+{
+    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;
@@ -564,18 +574,18 @@ int IsUnsigned (const type* T)
 
 
 
-int IsClassStruct (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 IsTypeFunc (const type* T)
-/* Return true if this is a function class */
+int IsQualVolatile (const type* T)
+/* Return true if the given type has a volatile type qualifier */
 {
-    return ((T[0] & T_MASK_TYPE) == T_TYPE_FUNC);
+    return (GetQualifier (T) & T_QUAL_VOLATILE) != 0;
 }
 
 
@@ -599,10 +609,52 @@ int IsTypeFuncPtr (const type* T)
 
 
 
-int IsTypeArray (const type* T)
-/* Return true if this is an array type */
+type GetType (const type* T)
+/* Get the raw type */
 {
-    return ((T[0] & T_MASK_TYPE) == T_TYPE_ARRAY);
+    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 */
+{
+    PRECONDITION (T[0] != T_END);
+    return (T[0] & T_MASK_SIZE);
+}
+
+
+
+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);
 }
 
 
index cdef535f8f819f4b9a5c342196afbdf036e69508..a710dc9e138ae28a2d7b79a03b459929107fd16c 100644 (file)
@@ -143,8 +143,6 @@ extern type type_uint [];
 extern type type_long [];
 extern type type_ulong [];
 extern type type_void [];
-extern type type_pschar [];
-extern type type_puchar [];
 
 
 
@@ -157,9 +155,6 @@ extern type type_puchar [];
 unsigned TypeLen (const type* Type);
 /* Return the length of the type string */
 
-int TypeCmp (const type* T1, const type* T2);
-/* Compare two type strings */
-
 type* TypeCpy (type* Dest, const type* Src);
 /* Copy a type string */
 
@@ -227,43 +222,67 @@ type* Indirect (type* Type);
  * given type points to.
  */
 
-int IsConst (const type* T);
-/* Return true if the given type has a const memory image */
+int IsTypeChar (const type* T);
+/* Return true if this is a character type */
 
-int IsTypeVoid (const type* Type);
-/* Return true if this is a void type */
+int IsTypeInt (const type* T);
+/* Return true if this is an int type (signed or unsigned) */
 
-int IsClassPtr (const type* Type);
+int IsTypeLong (const type* T);
+/* Return true if this is a long type (signed or unsigned) */
+
+int IsTypePtr (const type* Type);
 /* Return true if this is a pointer type */
 
-int IsTypeChar (const type* Type);
-/* Return true if this is a character type */
+int IsTypeArray (const type* Type);
+/* Return true if this is an array type */
+
+int IsTypeVoid (const type* Type);
+/* Return true if this is a void type */
+
+int IsTypeFunc (const type* Type);
+/* Return true if this is a function class */
 
 int IsClassInt (const type* Type);
 /* Return true if this is an integer 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 IsClassPtr (const type* Type);
+/* Return true if this is a pointer type */
 
 int IsClassStruct (const type* Type);
 /* Return true if this is a struct type */
 
-int IsTypeFunc (const type* Type);
-/* Return true if this is a function class */
+int IsSignUnsigned (const type* Type);
+/* Return true if this is an unsigned type */
 
-int IsFastCallFunc (const type* Type);
+int IsQualConst (const type* T);
+/* Return true if the given type has a const memory image */
+
+int IsQualVolatile (const type* T);
+/* Return true if the given type has a volatile type qualifier */
+
+int IsFastCallFunc (const type* T);
 /* Return true if this is a function type with __fastcall__ calling conventions */
 
-int IsTypeFuncPtr (const type* Type);
+int IsTypeFuncPtr (const type* T);
 /* Return true if this is a function pointer */
 
-int IsTypeArray (const type* Type);
-/* Return true if this is an array type */
+type GetType (const type* T);
+/* Get the raw type */
+
+type GetClass (const type* T);
+/* Get the class of a type string */
+
+type GetSignedness (const type* T);
+/* Get the sign of a type */
+
+type GetSizeModifier (const type* T);
+/* Get the size modifier of a type */
+
+type GetQualifier (const type* T);
+/* Get the qualifier from the given type string */
 
-struct FuncDesc* GetFuncDesc (const type* Type);
+struct FuncDesc* GetFuncDesc (const type* T);
 /* Get the FuncDesc pointer from a function or pointer-to-function type */
 
 
index 4a8a0ecb7e2977fab1eb8f856c5945112d3de064..13cb24db51a0d73daa61030c8909e94891bd18b0 100644 (file)
@@ -107,7 +107,8 @@ static char* ErrMsg [ERR_COUNT-1] = {
     "Unexpected `#else'",
     "`#endif' expected",
     "Compiler directive expected",
-    "Symbol `%s' defined more than once",
+    "Redefinition of `%s'",
+    "Conflicting types for `%s'",
     "String literal expected",
     "`while' expected",
     "Function must return a value",
@@ -152,8 +153,8 @@ static char* ErrMsg [ERR_COUNT-1] = {
     "Variable has unknown size",
     "Unknown identifier: `%s'",
     "Duplicate qualifier: `%s'",
-    "Assignment discards `const' qualifier",
-    "Passing argument %u discards `const' qualifier",
+    "Assignment to const",
+    "Pointer types differ in type qualifiers",
 };
 
 
index 4220d86a58629a5d4758403414f58c0fe1efea46..afedb3dd3cf0d2fd6a38231483b8d408fb762c77 100644 (file)
@@ -103,6 +103,7 @@ enum Errors {
     ERR_CPP_ENDIF_EXPECTED,
     ERR_CPP_DIRECTIVE_EXPECTED,
     ERR_MULTIPLE_DEFINITION,
+    ERR_CONFLICTING_TYPES,
     ERR_STRLIT_EXPECTED,
     ERR_WHILE_EXPECTED,
     ERR_MUST_RETURN_VALUE,
@@ -148,7 +149,7 @@ enum Errors {
     ERR_UNKNOWN_IDENT,
     ERR_DUPLICATE_QUALIFIER,
     ERR_CONST_ASSIGN,
-    ERR_CONST_PARAM,
+    ERR_QUAL_DIFF,
     ERR_COUNT                          /* Error count */
 };
 
index 434813220b25965d5120aae1c3919f3127d84f03..dc2252c7dd53466cd869e8c599b2e05e53a45743 100644 (file)
@@ -30,6 +30,7 @@
 #include "scanner.h"
 #include "stdfunc.h"
 #include "symtab.h"
+#include "typecmp.h"
 #include "expr.h"
 
 
@@ -132,13 +133,13 @@ static type* promoteint (type* lhst, type* rhst)
      *   - Otherwise the result is an int.
      */
     if (IsTypeLong (lhst) || IsTypeLong (rhst)) {
-       if (IsUnsigned (lhst) || IsUnsigned (rhst)) {
+               if (IsSignUnsigned (lhst) || IsSignUnsigned (rhst)) {
                    return type_ulong;
        } else {
            return type_long;
        }
     } else {
-       if (IsUnsigned (lhst) || IsUnsigned (rhst)) {
+       if (IsSignUnsigned (lhst) || IsSignUnsigned (rhst)) {
            return type_uint;
        } else {
            return type_int;
@@ -232,11 +233,23 @@ unsigned assignadjust (type* lhst, struct expent* rhs)
             *   - the rhs pointer is a void pointer, or
             *   - the lhs pointer is a void pointer.
             */
-           type* left  = Indirect (lhst);
-           type* right = Indirect (rhst);
-                   if (!EqualTypes (left, right) && *left != T_VOID && *right != T_VOID) {
-               Error (ERR_INCOMPATIBLE_POINTERS);
-           }
+           if (!IsTypeVoid (Indirect (lhst)) && !IsTypeVoid (Indirect (rhst))) {
+               /* Compare the types */
+               switch (TypeCmp (lhst, rhst)) {
+
+                   case TC_INCOMPATIBLE:
+                       Error (ERR_INCOMPATIBLE_POINTERS);
+                       break;
+
+                   case TC_QUAL_DIFF:
+                       Error (ERR_QUAL_DIFF);
+                       break;
+
+                   default:
+                       /* Ok */
+                       break;
+               }
+           }
        } 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) {
@@ -246,7 +259,7 @@ unsigned assignadjust (type* lhst, struct expent* rhs)
            /* Assignment of function to function pointer is allowed, provided
             * that both functions have the same parameter list.
             */
-           if (!EqualTypes(Indirect (lhst), rhst)) {
+           if (TypeCmp (Indirect (lhst), rhst) < TC_EQUAL) {
                Error (ERR_INCOMPATIBLE_TYPES);
            }
        } else {
@@ -580,18 +593,9 @@ static void callfunction (struct expent* lval)
         * convert the actual argument to the type needed.
         */
                if (!Ellipsis) {
-           /* If the left side is not const and the right is const, print
-            * an error. Note: This is an incomplete check, since other parts
-            * of the type string may have a const qualifier, but it catches
-            * some errors and is cheap here. We will redo it the right way
-            * as soon as the parser is rewritten. ####
-            */
-           if (!IsConst (Param->Type) && IsConst (lval2.e_tptr)) {
-               Error (ERR_CONST_PARAM, ParamCount);
-           }
-
            /* Promote the argument if needed */
                    assignadjust (Param->Type, &lval2);
+
            /* If we have a prototype, chars may be pushed as chars */
            Flags |= CF_FORCECHAR;
                }
@@ -1713,7 +1717,7 @@ static int hie_compare (GenDesc** ops,            /* List of generators */
                 */
                        type* left  = Indirect (lval->e_tptr);
                type* right = Indirect (lval2.e_tptr);
-               if (!EqualTypes (left, right) && *left != T_VOID && *right != T_VOID) {
+               if (TypeCmp (left, right) < TC_EQUAL && *left != T_VOID && *right != T_VOID) {
                    /* Incomatible pointers */
                    Error (ERR_INCOMPATIBLE_TYPES);
                }
@@ -1756,7 +1760,7 @@ static int hie_compare (GenDesc** ops,            /* List of generators */
             */
            if (IsTypeChar (lval->e_tptr) && (IsTypeChar (lval2.e_tptr) || rconst)) {
                flags |= CF_CHAR;
-               if (IsUnsigned (lval->e_tptr) || IsUnsigned (lval2.e_tptr)) {
+               if (IsSignUnsigned (lval->e_tptr) || IsSignUnsigned (lval2.e_tptr)) {
                    flags |= CF_UNSIGNED;
                }
                if (rconst) {
@@ -2017,7 +2021,7 @@ static void parsesub (int k, struct expent* lval)
                /* Operate on pointers, result type is a pointer */
            } else if (IsClassPtr (lhst) && IsClassPtr (rhst)) {
                /* Left is pointer, right is pointer, must scale result */
-               if (TypeCmp (Indirect (lhst), Indirect (rhst)) != 0) {
+               if (TypeCmp (Indirect (lhst), Indirect (rhst)) < TC_EQUAL) {
                    Error (ERR_INCOMPATIBLE_POINTERS);
                } else {
                    lval->e_const = (lval->e_const - lval2.e_const) / PSizeOf (lhst);
@@ -2052,7 +2056,7 @@ static void parsesub (int k, struct expent* lval)
                flags = CF_PTR;
            } else if (IsClassPtr (lhst) && IsClassPtr (rhst)) {
                /* Left is pointer, right is pointer, must scale result */
-               if (TypeCmp (Indirect (lhst), Indirect (rhst)) != 0) {
+               if (TypeCmp (Indirect (lhst), Indirect (rhst)) < TC_EQUAL) {
                    Error (ERR_INCOMPATIBLE_POINTERS);
                } else {
                    rscale = PSizeOf (lhst);
@@ -2095,7 +2099,7 @@ static void parsesub (int k, struct expent* lval)
            flags = CF_PTR;
        } else if (IsClassPtr (lhst) && IsClassPtr (rhst)) {
            /* Left is pointer, right is pointer, must scale result */
-           if (TypeCmp (Indirect (lhst), Indirect (rhst)) != 0) {
+           if (TypeCmp (Indirect (lhst), Indirect (rhst)) < TC_EQUAL) {
                Error (ERR_INCOMPATIBLE_POINTERS);
            } else {
                rscale = PSizeOf (lhst);
@@ -2454,7 +2458,7 @@ static int hieQuest (struct expent *lval)
 
        } else if (IsClassPtr (type2) && IsClassPtr (type3)) {
            /* Must point to same type */
-           if (TypeCmp (Indirect (type2), Indirect (type3)) != 0) {
+           if (TypeCmp (Indirect (type2), Indirect (type3)) < TC_EQUAL) {
                Error (ERR_INCOMPATIBLE_TYPES);
            }
            /* Result has the common type */
@@ -2667,7 +2671,7 @@ static void Assignment (struct expent* lval)
     type* ltype = lval->e_tptr;
 
     /* Check for assignment to const */
-    if (IsConst (ltype)) {
+    if (IsQualConst (ltype)) {
        Error (ERR_CONST_ASSIGN);
     }
 
@@ -2695,7 +2699,7 @@ static void Assignment (struct expent* lval)
        g_push (CF_PTR | CF_UNSIGNED, 0);
 
        /* Check for equality of the structs */
-       if (!EqualTypes (ltype, lval2.e_tptr)) {
+       if (TypeCmp (ltype, lval2.e_tptr) < TC_EQUAL) {
            Error (ERR_INCOMPATIBLE_TYPES);
        }
 
index 3a6e6a5ab3e9e4cc8f8c46142944f201709bcd87..332c7589c89cbef985177093cc07e256cda1c706 100644 (file)
@@ -269,7 +269,7 @@ static void ParseOneDecl (const DeclSpec* Spec)
            if (curtok == TOK_ASSIGN) {
 
                /* Initialization ahead, switch to data segment */
-               if (IsConst (Decl.Type)) {
+               if (IsQualConst (Decl.Type)) {
                    g_userodata ();
                } else {
                    g_usedata ();
index 5ec17501711a2465118a4c111de4da44c641512d..cc6f8b086d06edfa1f89e525505aa6e2e5cb55cd 100644 (file)
@@ -45,6 +45,7 @@ OBJS =        anonname.o      \
        stmt.o          \
        symentry.o      \
        symtab.o        \
+       typecmp.o       \
        util.o
 
 LIBS = $(COMMON)/common.a
index 056b6ed1f8a85609f0ff121b03b793168f3fe7bd..000f33a4bef1a64301b0a608f85b9073bcd16f06 100644 (file)
@@ -100,6 +100,7 @@ OBJS =      anonname.obj    \
        stdfunc.obj     \
        symentry.obj    \
        symtab.obj      \
+       typecmp.obj     \
        util.obj
 
 LIBS = ..\common\common.lib
@@ -156,6 +157,7 @@ FILE segname.obj
 FILE stdfunc.obj
 FILE symentry.obj
 FILE symtab.obj
+FILE typecmp.obj
 FILE util.obj
 LIBRARY ..\common\common.lib
 |
index 445d11405e32362a5f2ea0f602eaec9d011bb4f1..95d01b39ff38e30b71c79a87040cb1cf85b538be 100644 (file)
@@ -52,6 +52,7 @@ static const struct Keyword {
     { "__EAX__",               TOK_EAX,        TT_C    },
     { "__asm__",               TOK_ASM,        TT_C    },
     { "__attribute__", TOK_ATTRIBUTE,  TT_C    },
+    { "__far__",       TOK_FAR,        TT_C    },
     { "__fastcall__",          TOK_FASTCALL,   TT_C    },
     { "asm",                   TOK_ASM,        TT_EXT  },
     { "auto",                  TOK_AUTO,       TT_C    },
@@ -66,6 +67,7 @@ static const struct Keyword {
     { "else",                  TOK_ELSE,       TT_C    },
     { "enum",                  TOK_ENUM,       TT_C    },
     { "extern",                TOK_EXTERN,     TT_C    },
+    { "far",           TOK_FAR,        TT_EXT  },
     { "fastcall",              TOK_FASTCALL,   TT_EXT  },
     { "float",                 TOK_FLOAT,      TT_C    },
     { "for",                   TOK_FOR,        TT_C    },
@@ -129,7 +131,7 @@ static int FindKey (const char* Key)
 }
 
 
-                         
+
 static int SkipWhite (void)
 /* Skip white space in the input stream, reading and preprocessing new lines
  * if necessary. Return 0 if end of file is reached, return 1 otherwise.
index bbbed9ee650ea51ba41fdf96daf9521d35b07fe7..a707e4d1492364d31ce4534c221eb2bf147cd995 100644 (file)
@@ -125,10 +125,11 @@ typedef enum token_t {
     TOK_FCONST,
 
     TOK_ATTRIBUTE,
+    TOK_FAR,
     TOK_FASTCALL,
     TOK_AX,
     TOK_EAX,
-
+           
     TOK_PRAGMA
 } token_t;
 
index bc6faebf006964f7f0b46ab1cb1abb6d83b5e9a2..60576ff523f024c716b0bffa33799c11f3ba1708 100644 (file)
@@ -111,6 +111,8 @@ static void StdFunc_strlen (struct expent* lval)
 /* Handle the strlen function */
 {
     struct expent pval;
+    static type ArgType[] = { T_PTR, T_SCHAR, T_END };
+
 
     /* Fetch the parameter */
     int k = hie1 (&pval);
@@ -135,8 +137,11 @@ static void StdFunc_strlen (struct expent* lval)
        exprhs (CF_NONE, k, &pval);
     }
 
+    /* Setup the argument type string */
+    ArgType[1] = GetDefaultChar () | T_QUAL_CONST;
+
     /* Convert the parameter type to the type needed, check for mismatches */
-    assignadjust (SignedChars? type_pschar : type_puchar, &pval);
+    assignadjust (ArgType, &pval);
 
     /* Generate the strlen code */
     g_strlen (flags, pval.e_name, pval.e_const);
index 7a80b81be110ca60b53ea21005b92670cda3635f..11a4252f49a43a3fa7ecbe57f203dd00e7817ee4 100644 (file)
@@ -53,6 +53,7 @@
 #include "funcdesc.h"
 #include "global.h"
 #include "symentry.h"
+#include "typecmp.h"
 #include "symtab.h"
 
 
@@ -692,9 +693,9 @@ SymEntry* AddGlobalSym (const char* Name, type* Type, unsigned Flags)
            unsigned ESize = Decode (EType + 1);
 
            if ((Size != 0 && ESize != 0) ||
-               TypeCmp (Type+DECODE_SIZE+1, EType+DECODE_SIZE+1) != 0) {
-               /* Types not identical: Duplicate definition */
-               Error (ERR_MULTIPLE_DEFINITION, Name);
+               TypeCmp (Type+DECODE_SIZE+1, EType+DECODE_SIZE+1) < TC_EQUAL) {
+               /* Types not identical: Conflicting types */
+               Error (ERR_CONFLICTING_TYPES, Name);
            } else {
                /* Check if we have a size in the existing definition */
                if (ESize == 0) {
@@ -705,8 +706,8 @@ SymEntry* AddGlobalSym (const char* Name, type* Type, unsigned Flags)
 
                } else {
            /* New type must be identical */
-           if (!EqualTypes (EType, Type) != 0) {
-               Error (ERR_MULTIPLE_DEFINITION, Name);
+           if (TypeCmp (EType, Type) < TC_EQUAL) {
+               Error (ERR_CONFLICTING_TYPES, Name);
            }
 
            /* In case of a function, use the new type descriptor, since it
@@ -761,152 +762,6 @@ int SymIsLocal (SymEntry* Sym)
 
 
 
-static int EqualSymTables (SymTable* Tab1, SymTable* Tab2)
-/* Compare two symbol tables. Return 1 if they are equal and 0 otherwise */
-{
-    /* Compare the parameter lists */
-    SymEntry* Sym1 = Tab1->SymHead;
-    SymEntry* Sym2 = Tab2->SymHead;
-
-    /* Compare the fields */
-    while (Sym1 && Sym2) {
-
-       /* Compare this field */
-       if (!EqualTypes (Sym1->Type, Sym2->Type)) {
-           /* Field types not equal */
-           return 0;
-       }
-
-       /* Get the pointers to the next fields */
-       Sym1 = Sym1->NextSym;
-       Sym2 = Sym2->NextSym;
-    }
-
-    /* Check both pointers against NULL to compare the field count */
-    return (Sym1 == 0 && Sym2 == 0);
-}
-
-
-
-int EqualTypes (const type* Type1, const type* Type2)
-/* Recursively compare two types. Return 1 if the types match, return 0
- * otherwise.
- */
-{
-    int v1, v2;
-    SymEntry* Sym1;
-    SymEntry* Sym2;
-    SymTable* Tab1;
-    SymTable* Tab2;
-    FuncDesc* F1;
-    FuncDesc* F2;
-    int              Ok;
-
-
-    /* Shortcut here: If the pointers are identical, the types are identical */
-    if (Type1 == Type2) {
-       return 1;
-    }
-
-    /* Compare two types. Determine, where they differ */
-    while (*Type1 == *Type2 && *Type1 != T_END) {
-
-       switch (*Type1) {
-
-           case T_FUNC:
-               /* Compare the function descriptors */
-               F1 = DecodePtr (Type1+1);
-               F2 = DecodePtr (Type2+1);
-
-               /* If one of the functions is implicitly declared, both
-                * functions are considered equal. If one of the functions is
-                * old style, and the other is empty, the functions are
-                * considered equal.
-                */
-                       if ((F1->Flags & FD_IMPLICIT) != 0 || (F2->Flags & FD_IMPLICIT) != 0) {
-                   Ok = 1;
-               } else if ((F1->Flags & FD_OLDSTYLE) != 0 && (F2->Flags & FD_EMPTY) != 0) {
-                   Ok = 1;
-               } else if ((F1->Flags & FD_EMPTY) != 0 && (F2->Flags & FD_OLDSTYLE) != 0) {
-                   Ok = 1;
-               } else {
-                   Ok = 0;
-               }
-
-               if (!Ok) {
-
-                   /* Check the remaining flags */
-                   if ((F1->Flags & ~FD_IGNORE) != (F2->Flags & ~FD_IGNORE)) {
-                       /* Flags differ */
-                       return 0;
-                   }
-
-                   /* Compare the parameter lists */
-                   if (EqualSymTables (F1->SymTab, F2->SymTab) == 0 ||
-                       EqualSymTables (F1->TagTab, F2->TagTab) == 0) {
-                       /* One of the tables is not identical */
-                       return 0;
-                   }
-               }
-
-               /* Skip the FuncDesc pointers to compare the return type */
-               Type1 += DECODE_SIZE;
-               Type2 += DECODE_SIZE;
-               break;
-
-           case T_ARRAY:
-               /* Check member count */
-               v1 = Decode (Type1+1);
-               v2 = Decode (Type2+1);
-               if (v1 != 0 && v2 != 0 && v1 != v2) {
-                   /* Member count given but different */
-                   return 0;
-               }
-               Type1 += DECODE_SIZE;
-               Type2 += DECODE_SIZE;
-               break;
-
-           case T_STRUCT:
-           case T_UNION:
-                       /* Compare the fields recursively. To do that, we fetch the
-                * pointer to the struct definition from the type, and compare
-                * the fields.
-                */
-               Sym1 = DecodePtr (Type1+1);
-               Sym2 = DecodePtr (Type2+1);
-
-               /* Get the field tables from the struct entry */
-               Tab1 = Sym1->V.S.SymTab;
-               Tab2 = Sym2->V.S.SymTab;
-
-               /* One or both structs may be forward definitions. In this case,
-                * the symbol tables are both non existant. Assume that the
-                * structs are equal in this case.
-                */
-               if (Tab1 != 0 && Tab2 != 0) {
-
-                   if (EqualSymTables (Tab1, Tab2) == 0) {
-                       /* Field lists are not equal */
-                       return 0;
-                   }
-
-               }
-
-               /* Structs are equal */
-               Type1 += DECODE_SIZE;
-               Type2 += DECODE_SIZE;
-               break;
-       }
-       ++Type1;
-               ++Type2;
-    }
-
-    /* Done, types are equal */
-    return 1;
-}
-
-
-
 void MakeZPSym (const char* Name)
 /* Mark the given symbol as zero page symbol */
 {
index 5c37f218644f08dd1da62d7302950234adb336ae..2e8c2a0e5ed25620a95b0f631c3d6c6cd7d85e8d 100644 (file)
@@ -163,11 +163,6 @@ SymTable* GetSymTab (void);
 int SymIsLocal (SymEntry* Sym);
 /* Return true if the symbol is defined in the highest lexical level */
 
-int EqualTypes (const type* t1, const type* t2);
-/* Recursively compare two types. Return 1 if the types match, return 0
- * otherwise.
- */
-
 void MakeZPSym (const char* Name);
 /* Mark the given symbol as zero page symbol */
 
@@ -185,6 +180,3 @@ void EmitExternals (void);
 
 
 
-
-
-
diff --git a/src/cc65/typecmp.c b/src/cc65/typecmp.c
new file mode 100644 (file)
index 0000000..46eda0b
--- /dev/null
@@ -0,0 +1,315 @@
+/*****************************************************************************/
+/*                                                                           */
+/*                                typecmp.c                                 */
+/*                                                                           */
+/*              Type compare function for the cc65 C compiler               */
+/*                                                                           */
+/*                                                                           */
+/*                                                                           */
+/* (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       */
+/* warranty.  In no event will the authors be held liable for any damages    */
+/* arising from the use of this software.                                    */
+/*                                                                           */
+/* Permission is granted to anyone to use this software for any purpose,     */
+/* including commercial applications, and to alter it and redistribute it    */
+/* freely, subject to the following restrictions:                            */
+/*                                                                           */
+/* 1. The origin of this software must not be misrepresented; you must not   */
+/*    claim that you wrote the original software. If you use this software   */
+/*    in a product, an acknowledgment in the product documentation would be  */
+/*    appreciated but is not required.                                       */
+/* 2. Altered source versions must be plainly marked as such, and must not   */
+/*    be misrepresented as being the original software.                      */
+/* 3. This notice may not be removed or altered from any source              */
+/*    distribution.                                                          */
+/*                                                                           */
+/*****************************************************************************/
+
+
+
+#include "funcdesc.h"
+#include "symtab.h"
+#include "typecmp.h"
+
+
+
+/*****************************************************************************/
+/*                                  Code                                    */
+/*****************************************************************************/
+
+
+
+static void SetResult (typecmp_t* Result, typecmp_t Val)
+/* Set a new result value if it is less than the existing one */
+{
+    if (Val < *Result) {
+       *Result = Val;
+    }
+}
+
+
+
+static int EqualSymTables (SymTable* Tab1, SymTable* Tab2)
+/* Compare two symbol tables. Return 1 if they are equal and 0 otherwise */
+{
+    /* Compare the parameter lists */
+    SymEntry* Sym1 = Tab1->SymHead;
+    SymEntry* Sym2 = Tab2->SymHead;
+
+    /* Compare the fields */
+    while (Sym1 && Sym2) {
+
+       /* Compare this field */
+               if (TypeCmp (Sym1->Type, Sym2->Type) < TC_EQUAL) {
+           /* Field types not equal */
+           return 0;
+       }
+
+       /* Get the pointers to the next fields */
+       Sym1 = Sym1->NextSym;
+       Sym2 = Sym2->NextSym;
+    }
+
+    /* Check both pointers against NULL to compare the field count */
+    return (Sym1 == 0 && Sym2 == 0);
+}
+
+
+
+static void DoCompare (const type* lhs, const type* rhs, typecmp_t* Result)
+/* Recursively compare two types. */
+{
+    unsigned   Indirections;
+    unsigned   ElementCount;
+    SymEntry*  Sym1;
+    SymEntry*  Sym2;
+    SymTable*  Tab1;
+    SymTable*  Tab2;
+    FuncDesc*  F1;
+    FuncDesc*  F2;
+    int                Ok;
+
+
+    /* Initialize stuff */
+    Indirections = 0;
+    ElementCount = 0;
+
+    /* Compare two types. Determine, where they differ */
+    while (*lhs != T_END) {
+
+               type LeftType, RightType;
+       type LeftSign, RightSign;
+       type LeftQual, RightQual;
+       unsigned LeftCount, RightCount;
+
+               /* Check if the end of the type string is reached */
+               if (*rhs == T_END) {
+                   /* End of comparison reached */
+                   return;
+               }
+
+       /* Get the raw left and right types, signs and qualifiers */
+       LeftType  = GetType (lhs);
+       RightType = GetType (rhs);
+       LeftSign  = GetSignedness (lhs);
+       RightSign = GetSignedness (rhs);
+       LeftQual  = GetQualifier (lhs);
+       RightQual = GetQualifier (rhs);
+
+       /* If the left type is a pointer and the right is an array, both
+        * are compatible.
+        */
+       if (LeftType == T_TYPE_PTR && RightType == T_TYPE_ARRAY) {
+           RightType = T_TYPE_PTR;
+           rhs += DECODE_SIZE;
+       }
+
+       /* If the raw types are not identical, the types are incompatible */
+       if (LeftType != RightType) {
+           SetResult (Result, TC_INCOMPATIBLE);
+           return;
+       }
+
+       /* On indirection level zero, a qualifier or sign difference is
+        * accepted. The types are no longer equal, but compatible.
+        */
+       if (LeftSign != RightSign) {
+                   if (ElementCount == 0) {
+                       SetResult (Result, TC_SIGN_DIFF);
+                   } else {
+                       SetResult (Result, TC_INCOMPATIBLE);
+                       return;
+                   }
+               }
+               if (LeftQual != RightQual) {
+           /* On the first indirection level, different qualifiers mean
+            * that the types are still compatible. On the second level,
+            * this is a (maybe minor) error, so we create a special
+            * return code, since a qualifier is dropped from a pointer.
+            * Starting from the next level, the types are incompatible
+            * if the qualifiers differ.
+            */
+           switch (Indirections) {
+
+               case 0:
+                   SetResult (Result, TC_STRICT_COMPATIBLE);
+                   break;
+
+               case 1:
+                   /* A non const value on the right is compatible to a
+                    * const one to the left, same for volatile.
+                    */
+                   if ((LeftQual & T_QUAL_CONST) < (RightQual & T_QUAL_CONST) ||
+                       (LeftQual & T_QUAL_VOLATILE) < (RightQual & T_QUAL_VOLATILE)) {
+                       SetResult (Result, TC_QUAL_DIFF);
+                   } else {
+                       SetResult (Result, TC_STRICT_COMPATIBLE);
+                   }
+                   break;
+
+               default:
+                   SetResult (Result, TC_INCOMPATIBLE);
+                   return;
+           }
+               }
+
+               /* Check for special type elements */
+               switch (LeftType) {
+
+           case T_TYPE_PTR:
+               ++Indirections;
+               break;
+
+                   case T_TYPE_FUNC:
+                       /* Compare the function descriptors */
+                       F1 = DecodePtr (lhs+1);
+                       F2 = DecodePtr (rhs+1);
+
+                       /* If one of the functions is implicitly declared, both
+                        * functions are considered equal. If one of the functions is
+                        * old style, and the other is empty, the functions are
+                        * considered equal.
+                        */
+                       if ((F1->Flags & FD_IMPLICIT) != 0 || (F2->Flags & FD_IMPLICIT) != 0) {
+                           Ok = 1;
+                       } else if ((F1->Flags & FD_OLDSTYLE) != 0 && (F2->Flags & FD_EMPTY) != 0) {
+                           Ok = 1;
+                       } else if ((F1->Flags & FD_EMPTY) != 0 && (F2->Flags & FD_OLDSTYLE) != 0) {
+                           Ok = 1;
+                       } else {
+                           Ok = 0;
+                       }
+
+                       if (!Ok) {
+
+                           /* Check the remaining flags */
+                           if ((F1->Flags & ~FD_IGNORE) != (F2->Flags & ~FD_IGNORE)) {
+                               /* Flags differ */
+                       SetResult (Result, TC_INCOMPATIBLE);
+                               return;
+                           }
+
+                           /* Compare the parameter lists */
+                           if (EqualSymTables (F1->SymTab, F2->SymTab) == 0 ||
+                               EqualSymTables (F1->TagTab, F2->TagTab) == 0) {
+                               /* One of the tables is not identical */
+                       SetResult (Result, TC_INCOMPATIBLE);
+                               return;
+                           }
+               }
+
+               /* Skip the FuncDesc pointers to compare the return type */
+               lhs += DECODE_SIZE;
+               rhs += DECODE_SIZE;
+               break;
+
+           case T_TYPE_ARRAY:
+               /* Check member count */
+               LeftCount  = Decode (lhs+1);
+               RightCount = Decode (rhs+1);
+               if (LeftCount != 0 && RightCount != 0 && LeftCount != RightCount) {
+                   /* Member count given but different */
+                   SetResult (Result, TC_INCOMPATIBLE);
+                   return;
+               }
+               lhs += DECODE_SIZE;
+               rhs += DECODE_SIZE;
+               break;
+
+           case T_TYPE_STRUCT:
+           case T_TYPE_UNION:
+                       /* Compare the fields recursively. To do that, we fetch the
+                * pointer to the struct definition from the type, and compare
+                * the fields.
+                */
+               Sym1 = DecodePtr (lhs+1);
+               Sym2 = DecodePtr (rhs+1);
+
+               /* Get the field tables from the struct entry */
+               Tab1 = Sym1->V.S.SymTab;
+               Tab2 = Sym2->V.S.SymTab;
+
+               /* One or both structs may be forward definitions. In this case,
+                * the symbol tables are both non existant. Assume that the
+                * structs are equal in this case.
+                */
+               if (Tab1 != 0 && Tab2 != 0) {
+
+                   if (EqualSymTables (Tab1, Tab2) == 0) {
+                       /* Field lists are not equal */
+                       SetResult (Result, TC_INCOMPATIBLE);
+                       return;
+                   }
+
+               }
+
+               /* Structs are equal */
+               lhs += DECODE_SIZE;
+               rhs += DECODE_SIZE;
+               break;
+       }
+
+       /* Next type string element */
+       ++lhs;
+               ++rhs;
+       ++ElementCount;
+    }
+
+    /* Check if end of rhs reached */
+    if (*rhs == T_END) {
+       SetResult (Result, TC_EQUAL);
+    } else {
+       SetResult (Result, TC_INCOMPATIBLE);
+    }
+}
+
+
+
+typecmp_t TypeCmp (const type* lhs, const type* rhs)
+/* Compare two types and return the result */
+{
+    /* Assume the types are identical */
+    typecmp_t  Result = TC_IDENTICAL;
+
+#if 0
+    printf ("Left : "); PrintRawType (stdout, lhs);
+    printf ("Right: "); PrintRawType (stdout, rhs);
+#endif
+
+    /* Recursively compare the types if they aren't identical */
+    if (rhs != lhs) {
+       DoCompare (lhs, rhs, &Result);
+    }
+
+    /* Return the result */
+    return Result;
+}
+
+
+
diff --git a/src/cc65/typecmp.h b/src/cc65/typecmp.h
new file mode 100644 (file)
index 0000000..584bd2c
--- /dev/null
@@ -0,0 +1,81 @@
+/*****************************************************************************/
+/*                                                                           */
+/*                                typecmp.h                                 */
+/*                                                                           */
+/*              Type compare function for the cc65 C compiler               */
+/*                                                                           */
+/*                                                                           */
+/*                                                                           */
+/* (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       */
+/* warranty.  In no event will the authors be held liable for any damages    */
+/* arising from the use of this software.                                    */
+/*                                                                           */
+/* Permission is granted to anyone to use this software for any purpose,     */
+/* including commercial applications, and to alter it and redistribute it    */
+/* freely, subject to the following restrictions:                            */
+/*                                                                           */
+/* 1. The origin of this software must not be misrepresented; you must not   */
+/*    claim that you wrote the original software. If you use this software   */
+/*    in a product, an acknowledgment in the product documentation would be  */
+/*    appreciated but is not required.                                       */
+/* 2. Altered source versions must be plainly marked as such, and must not   */
+/*    be misrepresented as being the original software.                      */
+/* 3. This notice may not be removed or altered from any source              */
+/*    distribution.                                                          */
+/*                                                                           */
+/*****************************************************************************/
+
+
+
+#ifndef TYPECMP_H
+#define TYPECMP_H
+
+
+
+#include "datatype.h"
+
+
+
+/*****************************************************************************/
+/*                                  Data                                    */
+/*****************************************************************************/
+
+
+
+/* Degree of type compatibility. Must be in ascending order */
+typedef enum {
+    TC_INCOMPATIBLE,             /* Distinct types */
+    TC_QUAL_DIFF,                /* Types differ in qualifier of pointer */
+    TC_SIGN_DIFF,                /* Signedness differs */
+    TC_COMPATIBLE = TC_SIGN_DIFF, /* Compatible types */
+    TC_STRICT_COMPATIBLE,                /* Struct compatibility */
+    TC_EQUAL,                    /* Types are equal */
+    TC_IDENTICAL                 /* Types are identical */
+} typecmp_t;
+
+
+
+/*****************************************************************************/
+/*                                  Code                                    */
+/*****************************************************************************/
+
+
+
+typecmp_t TypeCmp (const type* lhs, const type* rhs);
+/* Compare two types and return the result */
+
+
+
+/* End of typecmp.h */
+
+#endif
+
+
+
+