]> git.sur5r.net Git - cc65/blobdiff - src/cc65/declattr.c
Merged branch "master" into ubiquitous.
[cc65] / src / cc65 / declattr.c
index beeb8a76b81ed4af7f3e6dbf587c444e9456b5a0..ac45db2211348340d96cdb5a18cf8ba9ab0307ff 100644 (file)
@@ -1,15 +1,15 @@
 /*****************************************************************************/
 /*                                                                           */
-/*                               declattr.c                                 */
+/*                                declattr.c                                 */
 /*                                                                           */
-/*                         Declaration attributes                           */
+/*                          Declaration attributes                           */
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 2000     Ullrich von Bassewitz                                        */
-/*              Wacholderweg 14                                              */
-/*              D-70597 Stuttgart                                            */
-/* EMail:       uz@musoftware.de                                             */
+/* (C) 1998-2009, Ullrich von Bassewitz                                      */
+/*                Roemerstrasse 52                                           */
+/*                D-70794 Filderstadt                                        */
+/* EMail:         uz@cc65.org                                                */
 /*                                                                           */
 /*                                                                           */
 /* This software is provided 'as-is', without any expressed or implied       */
 
 #include <string.h>
 
+/* common */
+#include "xmalloc.h"
+
 /* cc65 */
+#include "declare.h"
+#include "declattr.h"
 #include "error.h"
 #include "scanner.h"
 #include "symtab.h"
 #include "typecmp.h"
-#include "declattr.h"
 
 
 
 /*****************************************************************************/
-/*                                  Data                                    */
+/*                                   Data                                    */
 /*****************************************************************************/
 
 
 
-/* Attribute names */
-static const char* const AttrNames [atCount] = {
-    "alias",
+/* Forwards for attribute handlers */
+static void NoReturnAttr (Declaration* D);
+static void UnusedAttr (Declaration* D);
+
+
+
+/* Attribute table */
+typedef struct AttrDesc AttrDesc;
+struct AttrDesc {
+    const char  Name[15];
+    void        (*Handler) (Declaration*);
 };
+static const AttrDesc AttrTable [] = {
+    { "__noreturn__",   NoReturnAttr    },
+    { "__unused__",     UnusedAttr      },
+    { "noreturn",       NoReturnAttr    },
+    { "unused",         UnusedAttr      },
+};
+
+
+
+/*****************************************************************************/
+/*                              Struct DeclAttr                              */
+/*****************************************************************************/
+
+
+
+static DeclAttr* NewDeclAttr (DeclAttrType AttrType)
+/* Create a new DeclAttr struct and return it */
+{
+    /* Allocate memory */
+    DeclAttr* A = xmalloc (sizeof (DeclAttr));
+
+    /* Initialize the fields */
+    A->AttrType = AttrType;
+
+    /* Return the new struct */
+    return A;
+}
 
 
 
 /*****************************************************************************/
-/*                                  Code                                    */
+/*                             Helper functions                              */
 /*****************************************************************************/
 
 
 
-static attrib_t FindAttribute (const char* Attr)
-/* Search the attribute and return the corresponding attribute constant.
- * Return atNone if the attribute name is not known.
+static const AttrDesc* FindAttribute (const char* Attr)
+/* Search the attribute and return the corresponding attribute descriptor.
+ * Return NULL if the attribute name is not known.
  */
 {
-    int A;
+    unsigned A;
 
     /* For now do a linear search */
-    for (A = 0; A < atCount; ++A) {
-       if (strcmp (Attr, AttrNames[A]) == 0) {
-           /* Found */
-                   return (attrib_t) A;
-       }
+    for (A = 0; A < sizeof (AttrTable) / sizeof (AttrTable[0]); ++A) {
+        if (strcmp (Attr, AttrTable[A].Name) == 0) {
+            /* Found */
+            return AttrTable + A;
+        }
     }
 
     /* Not found */
-    return atNone;
+    return 0;
 }
 
 
 
-static void AliasAttrib (const Declaration* D, DeclAttr* A)
-/* Handle the "alias" attribute */
+static void ErrorSkip (void)
 {
-    SymEntry* Sym;
+    /* List of tokens to skip */
+    static const token_t SkipList[] = { TOK_RPAREN, TOK_SEMI };
 
-    /* Comma expected */
-    ConsumeComma ();
+    /* Skip until closing brace or semicolon */
+    SkipTokens (SkipList, sizeof (SkipList) / sizeof (SkipList[0]));
 
-    /* The next identifier is the name of the alias symbol */
-    if (CurTok.Tok != TOK_IDENT) {
-               Error ("Identifier expected");
-       return;
+    /* If we have a closing brace, read it, otherwise bail out */
+    if (CurTok.Tok == TOK_RPAREN) {
+        /* Read the two closing braces */
+        ConsumeRParen ();
+        ConsumeRParen ();
     }
+}
 
-    /* Lookup the symbol for this name, it must exist */
-    Sym = FindSym (CurTok.Ident);
-    if (Sym == 0) {
-       Error ("Unknown identifier: `%s'", CurTok.Ident);
-       NextToken ();
-       return;
-    }
 
-    /* Since we have the symbol entry now, skip the name */
-    NextToken ();
 
-    /* Check if the types of the symbols are identical */
-    if (TypeCmp (D->Type, Sym->Type) < TC_EQUAL) {
-       /* Types are not identical */
-       Error ("Incompatible types");
-       return;
+static void AddAttr (Declaration* D, DeclAttr* A)
+/* Add an attribute to a declaration */
+{
+    /* Allocate the list if necessary, the add the attribute */
+    if (D->Attributes == 0) {
+        D->Attributes = NewCollection ();
     }
+    CollAppend (D->Attributes, A);
+}
 
-    /* Attribute is verified, set the stuff in the attribute description */
-    A->AttrType = atAlias;
-    A->V.Sym   = Sym;
+
+
+/*****************************************************************************/
+/*                          Attribute handling code                          */
+/*****************************************************************************/
+
+
+
+static void NoReturnAttr (Declaration* D)
+/* Parse the "noreturn" attribute */
+{
+    /* Add the noreturn attribute */
+    AddAttr (D, NewDeclAttr (atNoReturn));
 }
 
 
 
-void ParseAttribute (const Declaration* D, DeclAttr* A)
-/* Parse an additional __attribute__ modifier */
+static void UnusedAttr (Declaration* D)
+/* Parse the "unused" attribute */
 {
-    ident    AttrName;
-    attrib_t AttrType;
+    /* Add the noreturn attribute */
+    AddAttr (D, NewDeclAttr (atUnused));
+}
+
 
-    /* Initialize the attribute description with "no attribute" */
-    A->AttrType = atNone;
 
+void ParseAttribute (Declaration* D)
+/* Parse an additional __attribute__ modifier */
+{
     /* Do we have an attribute? */
     if (CurTok.Tok != TOK_ATTRIBUTE) {
-       /* No attribute, bail out */
-       return;
+        /* No attribute, bail out */
+        return;
     }
 
     /* Skip the attribute token */
@@ -145,32 +193,57 @@ void ParseAttribute (const Declaration* D, DeclAttr* A)
     ConsumeLParen ();
     ConsumeLParen ();
 
-    /* Identifier follows */
-    if (CurTok.Tok != TOK_IDENT) {
-               Error ("Identifier expected");
-       /* We should *really* try to recover here, but for now: */
-       return;
-    }
+    /* Read a list of attributes */
+    while (1) {
 
-    /* Map the attribute name to its id, then skip the identifier */
-    strcpy (AttrName, CurTok.Ident);
-    AttrType = FindAttribute (AttrName);
-    NextToken ();
+        ident           AttrName;
+        const AttrDesc* Attr = 0;
+
+        /* Identifier follows */
+        if (CurTok.Tok != TOK_IDENT) {
+
+            /* No attribute name */
+            Error ("Attribute name expected");
+
+            /* Skip until end of attribute */
+            ErrorSkip ();
+
+            /* Bail out */
+            return;
+        }
+
+        /* Map the attribute name to its id, then skip the identifier */
+        strcpy (AttrName, CurTok.Ident);
+        Attr = FindAttribute (AttrName);
+        NextToken ();
+
+        /* Did we find a valid attribute? */
+        if (Attr) {
+
+            /* Call the handler */
+            Attr->Handler (D);
+
+        } else {
+            /* Attribute not known, maybe typo */
+            Error ("Illegal attribute: `%s'", AttrName);
 
-    /* Handle possible attributes */
-    switch (AttrType) {
+            /* Skip until end of attribute */
+            ErrorSkip ();
 
-       case atAlias:
-           AliasAttrib (D, A);
-           break;
+            /* Bail out */
+            return;
+        }
 
-       default:
-           /* Attribute not known, maybe typo */
-           Error ("Illegal attribute: `%s'", AttrName);
-           break;
+        /* If a comma follows, there's a next attribute. Otherwise this is the
+         * end of the attribute list.
+         */
+        if (CurTok.Tok != TOK_COMMA) {
+            break;
+        }
+        NextToken ();
     }
 
-    /* Read the two closing braces */
+    /* The declaration is terminated with two closing braces */
     ConsumeRParen ();
     ConsumeRParen ();
 }