X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fcc65%2Fdeclattr.c;h=ac45db2211348340d96cdb5a18cf8ba9ab0307ff;hb=1bcd4b44f84d322871ac774dff831d6524733f21;hp=b06c36aed3dfc5b460af0093483661bef1f84f2c;hpb=d341e0ad767e43518364bbcceb2dd2900f92ddb9;p=cc65 diff --git a/src/cc65/declattr.c b/src/cc65/declattr.c index b06c36aed..ac45db221 100644 --- a/src/cc65/declattr.c +++ b/src/cc65/declattr.c @@ -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 */ @@ -33,107 +33,157 @@ +#include + +/* 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 }, }; /*****************************************************************************/ -/* Code */ +/* 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; +} + + + +/*****************************************************************************/ +/* 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. */ { - attrib_t A; + unsigned A; /* For now do a linear search */ - for (A = 0; A < atCount; ++A) { - if (strcmp (Attr, AttrNames[A]) == 0) { - /* Found */ - return 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 handling code */ +/*****************************************************************************/ - /* Attribute is verified, set the stuff in the attribute description */ - A->AttrType = atAlias; - A->V.Sym = Sym; + + +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 */ @@ -143,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 (); }