Fixed the existing but unused attribute parsing code. Added
__attribute__((noexit)) that may be used to mark functions that won't return. Added this attribute to the exit() function in stdlib.h. git-svn-id: svn://svn.cc65.org/cc65/trunk@4372 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
parent
0ce362a69b
commit
5a00b38aab
10 changed files with 270 additions and 173 deletions
|
@ -109,7 +109,7 @@ int __fastcall__ atexit (void (*exitfunc) (void));
|
||||||
void* __fastcall__ bsearch (const void* key, const void* base, size_t n,
|
void* __fastcall__ bsearch (const void* key, const void* base, size_t n,
|
||||||
size_t size, int (*cmp) (const void*, const void*));
|
size_t size, int (*cmp) (const void*, const void*));
|
||||||
div_t __fastcall__ div (int numer, int denom);
|
div_t __fastcall__ div (int numer, int denom);
|
||||||
void __fastcall__ exit (int ret);
|
void __fastcall__ exit (int ret) __attribute__ ((noreturn));
|
||||||
char* __fastcall__ getenv (const char* name);
|
char* __fastcall__ getenv (const char* name);
|
||||||
void __fastcall__ qsort (void* base, size_t count, size_t size,
|
void __fastcall__ qsort (void* base, size_t count, size_t size,
|
||||||
int (*compare) (const void*, const void*));
|
int (*compare) (const void*, const void*));
|
||||||
|
|
|
@ -83,7 +83,6 @@ static void Parse (void)
|
||||||
while (CurTok.Tok != TOK_CEOF) {
|
while (CurTok.Tok != TOK_CEOF) {
|
||||||
|
|
||||||
DeclSpec Spec;
|
DeclSpec Spec;
|
||||||
Declaration Decl;
|
|
||||||
|
|
||||||
/* Check for empty statements */
|
/* Check for empty statements */
|
||||||
if (CurTok.Tok == TOK_SEMI) {
|
if (CurTok.Tok == TOK_SEMI) {
|
||||||
|
@ -128,6 +127,8 @@ static void Parse (void)
|
||||||
comma = 0;
|
comma = 0;
|
||||||
while (1) {
|
while (1) {
|
||||||
|
|
||||||
|
Declaration Decl;
|
||||||
|
|
||||||
/* Read the next declaration */
|
/* Read the next declaration */
|
||||||
ParseDecl (&Spec, &Decl, DM_NEED_IDENT);
|
ParseDecl (&Spec, &Decl, DM_NEED_IDENT);
|
||||||
if (Decl.Ident[0] == '\0') {
|
if (Decl.Ident[0] == '\0') {
|
||||||
|
@ -168,6 +169,9 @@ static void Parse (void)
|
||||||
/* Add an entry to the symbol table */
|
/* Add an entry to the symbol table */
|
||||||
Entry = AddGlobalSym (Decl.Ident, Decl.Type, Decl.StorageClass);
|
Entry = AddGlobalSym (Decl.Ident, Decl.Type, Decl.StorageClass);
|
||||||
|
|
||||||
|
/* Add declaration attributes */
|
||||||
|
SymUseAttributes (Entry, &Decl);
|
||||||
|
|
||||||
/* Reserve storage for the variable if we need to */
|
/* Reserve storage for the variable if we need to */
|
||||||
if (Decl.StorageClass & SC_STORAGE) {
|
if (Decl.StorageClass & SC_STORAGE) {
|
||||||
|
|
||||||
|
@ -334,7 +338,7 @@ void Compile (const char* FileName)
|
||||||
strftime (TimeStr, sizeof (TimeStr), "\"%H:%M:%S\"", TM);
|
strftime (TimeStr, sizeof (TimeStr), "\"%H:%M:%S\"", TM);
|
||||||
DefineTextMacro ("__DATE__", DateStr);
|
DefineTextMacro ("__DATE__", DateStr);
|
||||||
DefineTextMacro ("__TIME__", TimeStr);
|
DefineTextMacro ("__TIME__", TimeStr);
|
||||||
|
|
||||||
/* Other standard macros */
|
/* Other standard macros */
|
||||||
/* DefineNumericMacro ("__STDC__", 1); <- not now */
|
/* DefineNumericMacro ("__STDC__", 1); <- not now */
|
||||||
DefineNumericMacro ("__STDC_HOSTED__", 1);
|
DefineNumericMacro ("__STDC_HOSTED__", 1);
|
||||||
|
|
|
@ -249,9 +249,10 @@ static void InitDeclSpec (DeclSpec* D)
|
||||||
static void InitDeclaration (Declaration* D)
|
static void InitDeclaration (Declaration* D)
|
||||||
/* Initialize the Declaration struct for use */
|
/* Initialize the Declaration struct for use */
|
||||||
{
|
{
|
||||||
D->Ident[0] = '\0';
|
D->Ident[0] = '\0';
|
||||||
D->Type[0].C = T_END;
|
D->Type[0].C = T_END;
|
||||||
D->Index = 0;
|
D->Index = 0;
|
||||||
|
D->Attributes = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1123,7 +1124,6 @@ static void ParseAnsiParamList (FuncDesc* F)
|
||||||
|
|
||||||
DeclSpec Spec;
|
DeclSpec Spec;
|
||||||
Declaration Decl;
|
Declaration Decl;
|
||||||
DeclAttr Attr;
|
|
||||||
|
|
||||||
/* Allow an ellipsis as last parameter */
|
/* Allow an ellipsis as last parameter */
|
||||||
if (CurTok.Tok == TOK_ELLIPSIS) {
|
if (CurTok.Tok == TOK_ELLIPSIS) {
|
||||||
|
@ -1161,8 +1161,8 @@ static void ParseAnsiParamList (FuncDesc* F)
|
||||||
Decl.StorageClass &= ~SC_DEF;
|
Decl.StorageClass &= ~SC_DEF;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parse an attribute ### */
|
/* Parse attributes for this parameter */
|
||||||
ParseAttribute (&Decl, &Attr);
|
ParseAttribute (&Decl);
|
||||||
|
|
||||||
/* Create a symbol table entry */
|
/* Create a symbol table entry */
|
||||||
AddLocalSym (Decl.Ident, ParamTypeCvt (Decl.Type), Decl.StorageClass, 0);
|
AddLocalSym (Decl.Ident, ParamTypeCvt (Decl.Type), Decl.StorageClass, 0);
|
||||||
|
@ -1195,8 +1195,7 @@ static void ParseAnsiParamList (FuncDesc* F)
|
||||||
/* Print an error if we have unnamed parameters and cc65 extensions
|
/* Print an error if we have unnamed parameters and cc65 extensions
|
||||||
* are disabled.
|
* are disabled.
|
||||||
*/
|
*/
|
||||||
if (IS_Get (&Standard) != STD_CC65 &&
|
if (IS_Get (&Standard) != STD_CC65 && (F->Flags & FD_UNNAMED_PARAMS)) {
|
||||||
(F->Flags & FD_UNNAMED_PARAMS) != 0) {
|
|
||||||
Error ("Parameter name omitted");
|
Error ("Parameter name omitted");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1204,7 +1203,7 @@ static void ParseAnsiParamList (FuncDesc* F)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static FuncDesc* ParseFuncDecl (void)
|
static FuncDesc* ParseFuncDecl (Declaration* D)
|
||||||
/* Parse the argument list of a function. */
|
/* Parse the argument list of a function. */
|
||||||
{
|
{
|
||||||
unsigned Offs;
|
unsigned Offs;
|
||||||
|
@ -1238,8 +1237,24 @@ static FuncDesc* ParseFuncDecl (void)
|
||||||
|
|
||||||
/* Parse params */
|
/* Parse params */
|
||||||
if ((F->Flags & FD_OLDSTYLE) == 0) {
|
if ((F->Flags & FD_OLDSTYLE) == 0) {
|
||||||
|
|
||||||
/* New style function */
|
/* New style function */
|
||||||
ParseAnsiParamList (F);
|
ParseAnsiParamList (F);
|
||||||
|
|
||||||
|
/* Allow attributes */
|
||||||
|
ParseAttribute (D);
|
||||||
|
|
||||||
|
/* Check if this is a function definition */
|
||||||
|
if (CurTok.Tok == TOK_LCURLY) {
|
||||||
|
/* Print an error if we have unnamed parameters and cc65 extensions
|
||||||
|
* are disabled.
|
||||||
|
*/
|
||||||
|
if (IS_Get (&Standard) != STD_CC65 &&
|
||||||
|
(F->Flags & FD_UNNAMED_PARAMS)) {
|
||||||
|
Error ("Parameter name omitted");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
/* Old style function */
|
/* Old style function */
|
||||||
ParseOldStyleParamList (F);
|
ParseOldStyleParamList (F);
|
||||||
|
@ -1344,7 +1359,7 @@ static void Declarator (const DeclSpec* Spec, Declaration* D, declmode_t Mode)
|
||||||
NextToken ();
|
NextToken ();
|
||||||
|
|
||||||
/* Parse the function declaration */
|
/* Parse the function declaration */
|
||||||
F = ParseFuncDecl ();
|
F = ParseFuncDecl (D);
|
||||||
|
|
||||||
/* We cannot specify fastcall for variadic functions */
|
/* We cannot specify fastcall for variadic functions */
|
||||||
if ((F->Flags & FD_VARIADIC) && (Qualifiers & T_QUAL_FASTCALL)) {
|
if ((F->Flags & FD_VARIADIC) && (Qualifiers & T_QUAL_FASTCALL)) {
|
||||||
|
|
|
@ -6,10 +6,10 @@
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* (C) 1998-2008 Ullrich von Bassewitz */
|
/* (C) 1998-2009, Ullrich von Bassewitz */
|
||||||
/* Roemerstrasse 52 */
|
/* Roemerstrasse 52 */
|
||||||
/* D-70794 Filderstadt */
|
/* D-70794 Filderstadt */
|
||||||
/* EMail: uz@cc65.org */
|
/* EMail: uz@cc65.org */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* This software is provided 'as-is', without any expressed or implied */
|
/* This software is provided 'as-is', without any expressed or implied */
|
||||||
|
@ -38,6 +38,9 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* common */
|
||||||
|
#include "coll.h"
|
||||||
|
|
||||||
/* cc65 */
|
/* cc65 */
|
||||||
#include "scanner.h"
|
#include "scanner.h"
|
||||||
#include "symtab.h"
|
#include "symtab.h"
|
||||||
|
@ -58,9 +61,9 @@
|
||||||
/* Result of ParseDeclSpec */
|
/* Result of ParseDeclSpec */
|
||||||
typedef struct DeclSpec DeclSpec;
|
typedef struct DeclSpec DeclSpec;
|
||||||
struct DeclSpec {
|
struct DeclSpec {
|
||||||
unsigned StorageClass; /* One of the SC_xxx flags */
|
unsigned StorageClass; /* One of the SC_xxx flags */
|
||||||
Type Type[MAXTYPELEN]; /* Type of the declaration spec */
|
Type Type[MAXTYPELEN]; /* Type of the declaration spec */
|
||||||
unsigned Flags; /* Bitmapped flags */
|
unsigned Flags; /* Bitmapped flags */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Result of ParseDecl */
|
/* Result of ParseDecl */
|
||||||
|
@ -68,14 +71,15 @@ typedef struct Declaration Declaration;
|
||||||
struct Declaration {
|
struct Declaration {
|
||||||
unsigned StorageClass; /* A set of SC_xxx flags */
|
unsigned StorageClass; /* A set of SC_xxx flags */
|
||||||
Type Type[MAXTYPELEN]; /* The type */
|
Type Type[MAXTYPELEN]; /* The type */
|
||||||
ident Ident; /* The identifier if any, else empty */
|
ident Ident; /* The identifier, if any*/
|
||||||
|
Collection* Attributes; /* Attributes if any */
|
||||||
|
|
||||||
/* Working variables */
|
/* Working variables */
|
||||||
unsigned Index; /* Used to build Type */
|
unsigned Index; /* Used to build Type */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Modes for ParseDecl */
|
/* Modes for ParseDecl */
|
||||||
typedef enum {
|
typedef enum {
|
||||||
DM_NEED_IDENT, /* We must have an identifier */
|
DM_NEED_IDENT, /* We must have an identifier */
|
||||||
DM_NO_IDENT, /* We won't read an identifier */
|
DM_NO_IDENT, /* We won't read an identifier */
|
||||||
DM_ACCEPT_IDENT, /* We will accept an id if there is one */
|
DM_ACCEPT_IDENT, /* We will accept an id if there is one */
|
||||||
|
|
|
@ -6,10 +6,10 @@
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* (C) 2000-2002 Ullrich von Bassewitz */
|
/* (C) 1998-2009, Ullrich von Bassewitz */
|
||||||
/* Wacholderweg 14 */
|
/* Roemerstrasse 52 */
|
||||||
/* D-70597 Stuttgart */
|
/* D-70794 Filderstadt */
|
||||||
/* EMail: uz@musoftware.de */
|
/* EMail: uz@cc65.org */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* This software is provided 'as-is', without any expressed or implied */
|
/* This software is provided 'as-is', without any expressed or implied */
|
||||||
|
@ -35,12 +35,16 @@
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
/* common */
|
||||||
|
#include "xmalloc.h"
|
||||||
|
|
||||||
/* cc65 */
|
/* cc65 */
|
||||||
|
#include "declare.h"
|
||||||
|
#include "declattr.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "scanner.h"
|
#include "scanner.h"
|
||||||
#include "symtab.h"
|
#include "symtab.h"
|
||||||
#include "typecmp.h"
|
#include "typecmp.h"
|
||||||
#include "declattr.h"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -51,28 +55,46 @@
|
||||||
|
|
||||||
|
|
||||||
/* Forwards for attribute handlers */
|
/* Forwards for attribute handlers */
|
||||||
static void AliasAttr (const Declaration* D, DeclAttr* A);
|
static void NoReturnAttr (Declaration* D);
|
||||||
static void UnusedAttr (const Declaration* D, DeclAttr* A);
|
|
||||||
static void ZeroPageAttr (const Declaration* D, DeclAttr* A);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Attribute table */
|
/* Attribute table */
|
||||||
typedef struct AttrDesc AttrDesc;
|
typedef struct AttrDesc AttrDesc;
|
||||||
struct AttrDesc {
|
struct AttrDesc {
|
||||||
const char Name[12];
|
const char Name[15];
|
||||||
void (*Handler) (const Declaration*, DeclAttr*);
|
void (*Handler) (Declaration*);
|
||||||
};
|
};
|
||||||
static const AttrDesc AttrTable [atCount] = {
|
static const AttrDesc AttrTable [] = {
|
||||||
{ "alias", AliasAttr },
|
{ "__noreturn__", NoReturnAttr },
|
||||||
{ "unused", UnusedAttr },
|
{ "noreturn", NoReturnAttr },
|
||||||
{ "zeropage", ZeroPageAttr },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* 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 */
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
@ -85,7 +107,7 @@ static const AttrDesc* FindAttribute (const char* Attr)
|
||||||
unsigned A;
|
unsigned A;
|
||||||
|
|
||||||
/* For now do a linear search */
|
/* For now do a linear search */
|
||||||
for (A = 0; A < atCount; ++A) {
|
for (A = 0; A < sizeof (AttrTable) / sizeof (AttrTable[0]); ++A) {
|
||||||
if (strcmp (Attr, AttrTable[A].Name) == 0) {
|
if (strcmp (Attr, AttrTable[A].Name) == 0) {
|
||||||
/* Found */
|
/* Found */
|
||||||
return AttrTable + A;
|
return AttrTable + A;
|
||||||
|
@ -98,72 +120,54 @@ static const AttrDesc* FindAttribute (const char* Attr)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void AliasAttr (const Declaration* D, DeclAttr* A)
|
static void ErrorSkip (void)
|
||||||
/* Handle the "alias" attribute */
|
|
||||||
{
|
{
|
||||||
SymEntry* Sym;
|
/* List of tokens to skip */
|
||||||
|
static const token_t SkipList[] = { TOK_RPAREN, TOK_SEMI };
|
||||||
|
|
||||||
/* Comma expected */
|
/* Skip until closing brace or semicolon */
|
||||||
ConsumeComma ();
|
SkipTokens (SkipList, sizeof (SkipList) / sizeof (SkipList[0]));
|
||||||
|
|
||||||
/* The next identifier is the name of the alias symbol */
|
/* If we have a closing brace, read it, otherwise bail out */
|
||||||
if (CurTok.Tok != TOK_IDENT) {
|
if (CurTok.Tok == TOK_RPAREN) {
|
||||||
Error ("Identifier expected");
|
/* Read the two closing braces */
|
||||||
return;
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Attribute is verified, set the stuff in the attribute description */
|
|
||||||
A->AttrType = atAlias;
|
|
||||||
A->V.Sym = Sym;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void UnusedAttr (const Declaration* D attribute ((unused)), DeclAttr* A)
|
static void AddAttr (Declaration* D, DeclAttr* A)
|
||||||
/* Handle the "unused" attribute */
|
/* Add an attribute to a declaration */
|
||||||
{
|
{
|
||||||
/* No parameters */
|
/* Allocate the list if necessary, the add the attribute */
|
||||||
A->AttrType = atUnused;
|
if (D->Attributes == 0) {
|
||||||
|
D->Attributes = NewCollection ();
|
||||||
|
}
|
||||||
|
CollAppend (D->Attributes, A);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void ZeroPageAttr (const Declaration* D attribute ((unused)), DeclAttr* A)
|
/*****************************************************************************/
|
||||||
/* Handle the "zeropage" attribute */
|
/* Attribute handling code */
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void NoReturnAttr (Declaration* D)
|
||||||
|
/* Parse the "noreturn" attribute */
|
||||||
{
|
{
|
||||||
/* No parameters */
|
/* Add the noreturn attribute */
|
||||||
A->AttrType = atZeroPage;
|
AddAttr (D, NewDeclAttr (atNoReturn));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void ParseAttribute (const Declaration* D, DeclAttr* A)
|
void ParseAttribute (Declaration* D)
|
||||||
/* Parse an additional __attribute__ modifier */
|
/* Parse an additional __attribute__ modifier */
|
||||||
{
|
{
|
||||||
ident AttrName;
|
|
||||||
const AttrDesc* Attr;
|
|
||||||
|
|
||||||
/* Initialize the attribute description with "no attribute" */
|
|
||||||
A->AttrType = atNone;
|
|
||||||
|
|
||||||
/* Do we have an attribute? */
|
/* Do we have an attribute? */
|
||||||
if (CurTok.Tok != TOK_ATTRIBUTE) {
|
if (CurTok.Tok != TOK_ATTRIBUTE) {
|
||||||
/* No attribute, bail out */
|
/* No attribute, bail out */
|
||||||
|
@ -177,45 +181,59 @@ void ParseAttribute (const Declaration* D, DeclAttr* A)
|
||||||
ConsumeLParen ();
|
ConsumeLParen ();
|
||||||
ConsumeLParen ();
|
ConsumeLParen ();
|
||||||
|
|
||||||
/* Identifier follows */
|
/* Read a list of attributes */
|
||||||
if (CurTok.Tok != TOK_IDENT) {
|
while (1) {
|
||||||
Error ("Identifier expected");
|
|
||||||
/* We should *really* try to recover here, but for now: */
|
ident AttrName;
|
||||||
return;
|
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);
|
||||||
|
|
||||||
|
/* Skip until end of attribute */
|
||||||
|
ErrorSkip ();
|
||||||
|
|
||||||
|
/* Bail out */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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 ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Map the attribute name to its id, then skip the identifier */
|
/* The declaration is terminated with two closing braces */
|
||||||
strcpy (AttrName, CurTok.Ident);
|
ConsumeRParen ();
|
||||||
Attr = FindAttribute (AttrName);
|
ConsumeRParen ();
|
||||||
NextToken ();
|
|
||||||
|
|
||||||
/* Did we find a valid attribute? */
|
|
||||||
if (Attr) {
|
|
||||||
|
|
||||||
/* Call the handler */
|
|
||||||
Attr->Handler (D, A);
|
|
||||||
|
|
||||||
/* Read the two closing braces */
|
|
||||||
ConsumeRParen ();
|
|
||||||
ConsumeRParen ();
|
|
||||||
|
|
||||||
} else {
|
|
||||||
/* List of tokens to skip */
|
|
||||||
static const token_t SkipList[] = { TOK_LPAREN, TOK_SEMI };
|
|
||||||
|
|
||||||
/* Attribute not known, maybe typo */
|
|
||||||
Error ("Illegal attribute: `%s'", AttrName);
|
|
||||||
|
|
||||||
/* Skip until closing brace or semicolon */
|
|
||||||
SkipTokens (SkipList, sizeof (SkipList) / sizeof (SkipList[0]));
|
|
||||||
|
|
||||||
/* If we have a closing brace, read it, otherwise bail out */
|
|
||||||
if (CurTok.Tok == TOK_LPAREN) {
|
|
||||||
/* Read the two closing braces */
|
|
||||||
ConsumeRParen ();
|
|
||||||
ConsumeRParen ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -6,10 +6,10 @@
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* (C) 2000-2002 Ullrich von Bassewitz */
|
/* (C) 1998-2009, Ullrich von Bassewitz */
|
||||||
/* Wacholderweg 14 */
|
/* Roemerstrasse 52 */
|
||||||
/* D-70597 Stuttgart */
|
/* D-70794 Filderstadt */
|
||||||
/* EMail: uz@musoftware.de */
|
/* EMail: uz@cc65.org */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* This software is provided 'as-is', without any expressed or implied */
|
/* This software is provided 'as-is', without any expressed or implied */
|
||||||
|
@ -38,45 +38,38 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#include "declare.h"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* Data */
|
/* Data */
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Forward */
|
||||||
|
struct Declaration;
|
||||||
|
|
||||||
/* Supported attribute types */
|
/* Supported attribute types */
|
||||||
typedef enum {
|
typedef enum {
|
||||||
atNone = -1, /* No attribute */
|
atNone = -1, /* No attribute */
|
||||||
atAlias, /* Alias declaration */
|
atNoReturn, /* Function does not return */
|
||||||
atUnused, /* Variable is unused */
|
|
||||||
atZeroPage, /* Zero page symbol */
|
|
||||||
|
|
||||||
atCount /* Number of attributes */
|
atCount /* Number of attributes */
|
||||||
} attrib_t;
|
} DeclAttrType;
|
||||||
|
|
||||||
/* An actual attribute description */
|
/* An actual attribute description */
|
||||||
typedef struct DeclAttr DeclAttr;
|
typedef struct DeclAttr DeclAttr;
|
||||||
struct DeclAttr {
|
struct DeclAttr {
|
||||||
attrib_t AttrType; /* Type of attribute */
|
DeclAttrType AttrType; /* Type of attribute */
|
||||||
|
|
||||||
union {
|
|
||||||
struct SymEntry* Sym; /* Symbol for alias */
|
|
||||||
} V;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* Code */
|
/* Code */
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void ParseAttribute (const Declaration* D, DeclAttr* A);
|
void ParseAttribute (struct Declaration* D);
|
||||||
/* Parse an additional __attribute__ modifier */
|
/* Parse an additional __attribute__ modifier */
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -486,6 +486,12 @@ static void FunctionCall (ExprDesc* Expr)
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
/* Check function attributes */
|
||||||
|
if (Expr->Sym && SymGetAttribute (Expr->Sym, atNoReturn)) {
|
||||||
|
/* For now, handle as if a return statement was encountered */
|
||||||
|
F_ReturnFound (CurrentFunc);
|
||||||
|
}
|
||||||
|
|
||||||
/* Check for known standard functions and inline them */
|
/* Check for known standard functions and inline them */
|
||||||
if (Expr->Name != 0) {
|
if (Expr->Name != 0) {
|
||||||
int StdFunc = FindStdFunc ((const char*) Expr->Name);
|
int StdFunc = FindStdFunc ((const char*) Expr->Name);
|
||||||
|
|
|
@ -40,6 +40,8 @@
|
||||||
|
|
||||||
/* cc65 */
|
/* cc65 */
|
||||||
#include "anonname.h"
|
#include "anonname.h"
|
||||||
|
#include "declare.h"
|
||||||
|
#include "error.h"
|
||||||
#include "symentry.h"
|
#include "symentry.h"
|
||||||
|
|
||||||
|
|
||||||
|
@ -67,6 +69,7 @@ SymEntry* NewSymEntry (const char* Name, unsigned Flags)
|
||||||
E->Owner = 0;
|
E->Owner = 0;
|
||||||
E->Flags = Flags;
|
E->Flags = Flags;
|
||||||
E->Type = 0;
|
E->Type = 0;
|
||||||
|
E->Attr = 0;
|
||||||
E->AsmName = 0;
|
E->AsmName = 0;
|
||||||
memcpy (E->Name, Name, Len+1);
|
memcpy (E->Name, Name, Len+1);
|
||||||
|
|
||||||
|
@ -150,6 +153,49 @@ void DumpSymEntry (FILE* F, const SymEntry* E)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const DeclAttr* SymGetAttribute (const SymEntry* Sym, DeclAttrType AttrType)
|
||||||
|
/* Return an attribute for this symbol or NULL if the attribute does not exist */
|
||||||
|
{
|
||||||
|
/* Beware: We may not even have a collection */
|
||||||
|
if (Sym->Attr) {
|
||||||
|
unsigned I;
|
||||||
|
for (I = 0; I < CollCount (Sym->Attr); ++I) {
|
||||||
|
|
||||||
|
/* Get the next attribute */
|
||||||
|
const DeclAttr* A = CollConstAt (Sym->Attr, I);
|
||||||
|
|
||||||
|
/* If this is the one we're searching for, return it */
|
||||||
|
if (A->AttrType == AttrType) {
|
||||||
|
return A;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Not found */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void SymUseAttributes (SymEntry* Sym, struct Declaration* D)
|
||||||
|
/* Use the attributes from the declaration for this symbol */
|
||||||
|
{
|
||||||
|
/* We cannot specify attributes twice */
|
||||||
|
if ((Sym->Flags & SC_HAVEATTR) != 0) {
|
||||||
|
if (D->Attributes != 0) {
|
||||||
|
Error ("Attributes must be specified in the first declaration");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Move the attributes */
|
||||||
|
Sym->Attr = D->Attributes;
|
||||||
|
D->Attributes = 0;
|
||||||
|
Sym->Flags |= SC_HAVEATTR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void CvtRegVarToAuto (SymEntry* Sym)
|
void CvtRegVarToAuto (SymEntry* Sym)
|
||||||
/* Convert a register variable to an auto variable */
|
/* Convert a register variable to an auto variable */
|
||||||
{
|
{
|
||||||
|
|
|
@ -6,10 +6,10 @@
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* (C) 2000-2009 Ullrich von Bassewitz */
|
/* (C) 2000-2009, Ullrich von Bassewitz */
|
||||||
/* Roemerstrasse 52 */
|
/* Roemerstrasse 52 */
|
||||||
/* D-70794 Filderstadt */
|
/* D-70794 Filderstadt */
|
||||||
/* EMail: uz@cc65.org */
|
/* EMail: uz@cc65.org */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* This software is provided 'as-is', without any expressed or implied */
|
/* This software is provided 'as-is', without any expressed or implied */
|
||||||
|
@ -41,10 +41,12 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
/* common */
|
/* common */
|
||||||
|
#include "coll.h"
|
||||||
#include "inline.h"
|
#include "inline.h"
|
||||||
|
|
||||||
/* cc65 */
|
/* cc65 */
|
||||||
#include "datatype.h"
|
#include "datatype.h"
|
||||||
|
#include "declattr.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -65,31 +67,33 @@ struct Segments;
|
||||||
|
|
||||||
|
|
||||||
/* Storage classes and flags */
|
/* Storage classes and flags */
|
||||||
#define SC_AUTO 0x0001U
|
#define SC_AUTO 0x0001U /* Auto variable */
|
||||||
#define SC_REGISTER 0x0002U /* Register variable, is in static storage */
|
#define SC_REGISTER 0x0002U /* Register variable */
|
||||||
#define SC_STATIC 0x0004U
|
#define SC_STATIC 0x0004U /* Static */
|
||||||
#define SC_EXTERN 0x0008U
|
#define SC_EXTERN 0x0008U /* Extern linkage */
|
||||||
|
|
||||||
#define SC_ENUM 0x0030U /* An enum (numeric constant) */
|
#define SC_ENUM 0x0030U /* An enum */
|
||||||
#define SC_CONST 0x0020U /* A numeric constant with a type */
|
#define SC_CONST 0x0020U /* A numeric constant with a type */
|
||||||
#define SC_LABEL 0x0040U /* A goto label */
|
#define SC_LABEL 0x0040U /* A goto label */
|
||||||
#define SC_PARAM 0x0080U /* This is a function parameter */
|
#define SC_PARAM 0x0080U /* A function parameter */
|
||||||
#define SC_FUNC 0x0100U /* Function entry */
|
#define SC_FUNC 0x0100U /* A function */
|
||||||
|
|
||||||
#define SC_DEFTYPE 0x0200U /* Parameter has default type (=int, old style) */
|
#define SC_DEFTYPE 0x0200U /* Parameter has default type (=int, old style) */
|
||||||
#define SC_STORAGE 0x0400U /* Symbol with associated storage */
|
#define SC_STORAGE 0x0400U /* Symbol with associated storage */
|
||||||
#define SC_DEFAULT 0x0800U /* Flag: default storage class was used */
|
#define SC_DEFAULT 0x0800U /* Flag: default storage class was used */
|
||||||
|
|
||||||
#define SC_DEF 0x1000U /* Symbol is defined */
|
#define SC_DEF 0x1000U /* Symbol is defined */
|
||||||
#define SC_REF 0x2000U /* Symbol is referenced */
|
#define SC_REF 0x2000U /* Symbol is referenced */
|
||||||
|
|
||||||
#define SC_TYPE 0x4000U /* This is a type, struct, typedef, etc. */
|
#define SC_TYPE 0x4000U /* This is a type, struct, typedef, etc. */
|
||||||
#define SC_STRUCT 0x4001U /* Struct or union */
|
#define SC_STRUCT 0x4001U /* Struct or union */
|
||||||
#define SC_STRUCTFIELD 0x4002U /* Struct or union field */
|
#define SC_STRUCTFIELD 0x4002U /* Struct or union field */
|
||||||
#define SC_BITFIELD 0x4004U /* A bit-field inside a struct or union */
|
#define SC_BITFIELD 0x4004U /* A bit-field inside a struct or union */
|
||||||
#define SC_TYPEDEF 0x4008U /* A typedef */
|
#define SC_TYPEDEF 0x4008U /* A typedef */
|
||||||
|
|
||||||
#define SC_ZEROPAGE 0x8000U /* Symbol marked as zeropage */
|
#define SC_ZEROPAGE 0x8000U /* Symbol marked as zeropage */
|
||||||
|
|
||||||
|
#define SC_HAVEATTR 0x10000U /* Symbol has attributes */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -103,6 +107,7 @@ struct SymEntry {
|
||||||
struct SymTable* Owner; /* Symbol table the symbol is in */
|
struct SymTable* Owner; /* Symbol table the symbol is in */
|
||||||
unsigned Flags; /* Symbol flags */
|
unsigned Flags; /* Symbol flags */
|
||||||
Type* Type; /* Symbol type */
|
Type* Type; /* Symbol type */
|
||||||
|
Collection* Attr; /* Attribute list if any */
|
||||||
char* AsmName; /* Assembler name if any */
|
char* AsmName; /* Assembler name if any */
|
||||||
|
|
||||||
/* Data that differs for the different symbol types */
|
/* Data that differs for the different symbol types */
|
||||||
|
@ -226,6 +231,12 @@ INLINE const char* SymGetAsmName (const SymEntry* Sym)
|
||||||
# define SymGetAsmName(Sym) ((Sym)->AsmName)
|
# define SymGetAsmName(Sym) ((Sym)->AsmName)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
const DeclAttr* SymGetAttribute (const SymEntry* Sym, DeclAttrType AttrType);
|
||||||
|
/* Return an attribute for this symbol or NULL if the attribute does not exist */
|
||||||
|
|
||||||
|
void SymUseAttributes (SymEntry* Sym, struct Declaration* D);
|
||||||
|
/* Use the attributes from the declaration for this symbol */
|
||||||
|
|
||||||
void CvtRegVarToAuto (SymEntry* Sym);
|
void CvtRegVarToAuto (SymEntry* Sym);
|
||||||
/* Convert a register variable to an auto variable */
|
/* Convert a register variable to an auto variable */
|
||||||
|
|
||||||
|
|
|
@ -181,7 +181,7 @@ static void CheckSymTable (SymTable* Tab)
|
||||||
/* Undefined label */
|
/* Undefined label */
|
||||||
Error ("Undefined label: `%s'", Entry->Name);
|
Error ("Undefined label: `%s'", Entry->Name);
|
||||||
} else if (!SymIsRef (Entry)) {
|
} else if (!SymIsRef (Entry)) {
|
||||||
/* Defined but not used */
|
/* Defined but not used */
|
||||||
if (IS_Get (&WarnUnusedLabel)) {
|
if (IS_Get (&WarnUnusedLabel)) {
|
||||||
Warning ("`%s' is defined but never used", Entry->Name);
|
Warning ("`%s' is defined but never used", Entry->Name);
|
||||||
}
|
}
|
||||||
|
@ -768,7 +768,7 @@ SymEntry* AddGlobalSym (const char* Name, const Type* T, unsigned Flags)
|
||||||
TypeCmp (T + 1, EType + 1) < TC_EQUAL) {
|
TypeCmp (T + 1, EType + 1) < TC_EQUAL) {
|
||||||
/* Types not identical: Conflicting types */
|
/* Types not identical: Conflicting types */
|
||||||
Error ("Conflicting types for `%s'", Name);
|
Error ("Conflicting types for `%s'", Name);
|
||||||
return Entry;
|
return Entry;
|
||||||
} else {
|
} else {
|
||||||
/* Check if we have a size in the existing definition */
|
/* Check if we have a size in the existing definition */
|
||||||
if (ESize == UNSPECIFIED) {
|
if (ESize == UNSPECIFIED) {
|
||||||
|
@ -781,7 +781,7 @@ SymEntry* AddGlobalSym (const char* Name, const Type* T, unsigned Flags)
|
||||||
/* New type must be identical */
|
/* New type must be identical */
|
||||||
if (TypeCmp (EType, T) < TC_EQUAL) {
|
if (TypeCmp (EType, T) < TC_EQUAL) {
|
||||||
Error ("Conflicting types for `%s'", Name);
|
Error ("Conflicting types for `%s'", Name);
|
||||||
return Entry;
|
return Entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* In case of a function, use the new type descriptor, since it
|
/* In case of a function, use the new type descriptor, since it
|
||||||
|
@ -791,9 +791,9 @@ SymEntry* AddGlobalSym (const char* Name, const Type* T, unsigned Flags)
|
||||||
* empty parameter list.
|
* empty parameter list.
|
||||||
*/
|
*/
|
||||||
if (IsFunc) {
|
if (IsFunc) {
|
||||||
/* Get the function descriptor from the new type */
|
/* Get the function descriptor from the new type */
|
||||||
FuncDesc* F = GetFuncDesc (T);
|
FuncDesc* F = GetFuncDesc (T);
|
||||||
/* Use this new function descriptor if it doesn't contain
|
/* Use this new function descriptor if it doesn't contain
|
||||||
* an empty parameter list.
|
* an empty parameter list.
|
||||||
*/
|
*/
|
||||||
if ((F->Flags & FD_EMPTY) == 0) {
|
if ((F->Flags & FD_EMPTY) == 0) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue