]> git.sur5r.net Git - cc65/blob - src/cc65/declattr.c
Removed (pretty inconsistently used) tab chars from source code base.
[cc65] / src / cc65 / declattr.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                                declattr.c                                 */
4 /*                                                                           */
5 /*                          Declaration attributes                           */
6 /*                                                                           */
7 /*                                                                           */
8 /*                                                                           */
9 /* (C) 1998-2009, Ullrich von Bassewitz                                      */
10 /*                Roemerstrasse 52                                           */
11 /*                D-70794 Filderstadt                                        */
12 /* EMail:         uz@cc65.org                                                */
13 /*                                                                           */
14 /*                                                                           */
15 /* This software is provided 'as-is', without any expressed or implied       */
16 /* warranty.  In no event will the authors be held liable for any damages    */
17 /* arising from the use of this software.                                    */
18 /*                                                                           */
19 /* Permission is granted to anyone to use this software for any purpose,     */
20 /* including commercial applications, and to alter it and redistribute it    */
21 /* freely, subject to the following restrictions:                            */
22 /*                                                                           */
23 /* 1. The origin of this software must not be misrepresented; you must not   */
24 /*    claim that you wrote the original software. If you use this software   */
25 /*    in a product, an acknowledgment in the product documentation would be  */
26 /*    appreciated but is not required.                                       */
27 /* 2. Altered source versions must be plainly marked as such, and must not   */
28 /*    be misrepresented as being the original software.                      */
29 /* 3. This notice may not be removed or altered from any source              */
30 /*    distribution.                                                          */
31 /*                                                                           */
32 /*****************************************************************************/
33
34
35
36 #include <string.h>
37
38 /* common */
39 #include "xmalloc.h"
40
41 /* cc65 */
42 #include "declare.h"
43 #include "declattr.h"
44 #include "error.h"
45 #include "scanner.h"
46 #include "symtab.h"
47 #include "typecmp.h"
48
49
50
51 /*****************************************************************************/
52 /*                                   Data                                    */
53 /*****************************************************************************/
54
55
56
57 /* Forwards for attribute handlers */
58 static void NoReturnAttr (Declaration* D);
59 static void UnusedAttr (Declaration* D);
60
61
62
63 /* Attribute table */
64 typedef struct AttrDesc AttrDesc;
65 struct AttrDesc {
66     const char  Name[15];
67     void        (*Handler) (Declaration*);
68 };
69 static const AttrDesc AttrTable [] = {
70     { "__noreturn__",   NoReturnAttr    },
71     { "__unused__",     UnusedAttr      },
72     { "noreturn",       NoReturnAttr    },
73     { "unused",         UnusedAttr      },
74 };
75
76
77
78 /*****************************************************************************/
79 /*                              Struct DeclAttr                              */
80 /*****************************************************************************/
81
82
83
84 static DeclAttr* NewDeclAttr (DeclAttrType AttrType)
85 /* Create a new DeclAttr struct and return it */
86 {
87     /* Allocate memory */
88     DeclAttr* A = xmalloc (sizeof (DeclAttr));
89
90     /* Initialize the fields */
91     A->AttrType = AttrType;
92
93     /* Return the new struct */
94     return A;
95 }
96
97
98
99 /*****************************************************************************/
100 /*                             Helper functions                              */
101 /*****************************************************************************/
102
103
104
105 static const AttrDesc* FindAttribute (const char* Attr)
106 /* Search the attribute and return the corresponding attribute descriptor.
107  * Return NULL if the attribute name is not known.
108  */
109 {
110     unsigned A;
111
112     /* For now do a linear search */
113     for (A = 0; A < sizeof (AttrTable) / sizeof (AttrTable[0]); ++A) {
114         if (strcmp (Attr, AttrTable[A].Name) == 0) {
115             /* Found */
116             return AttrTable + A;
117         }
118     }
119
120     /* Not found */
121     return 0;
122 }
123
124
125
126 static void ErrorSkip (void)
127 {
128     /* List of tokens to skip */
129     static const token_t SkipList[] = { TOK_RPAREN, TOK_SEMI };
130
131     /* Skip until closing brace or semicolon */
132     SkipTokens (SkipList, sizeof (SkipList) / sizeof (SkipList[0]));
133
134     /* If we have a closing brace, read it, otherwise bail out */
135     if (CurTok.Tok == TOK_RPAREN) {
136         /* Read the two closing braces */
137         ConsumeRParen ();
138         ConsumeRParen ();
139     }
140 }
141
142
143
144 static void AddAttr (Declaration* D, DeclAttr* A)
145 /* Add an attribute to a declaration */
146 {
147     /* Allocate the list if necessary, the add the attribute */
148     if (D->Attributes == 0) {
149         D->Attributes = NewCollection ();
150     }
151     CollAppend (D->Attributes, A);
152 }
153
154
155
156 /*****************************************************************************/
157 /*                          Attribute handling code                          */
158 /*****************************************************************************/
159
160
161
162 static void NoReturnAttr (Declaration* D)
163 /* Parse the "noreturn" attribute */
164 {
165     /* Add the noreturn attribute */
166     AddAttr (D, NewDeclAttr (atNoReturn));
167 }
168
169
170
171 static void UnusedAttr (Declaration* D)
172 /* Parse the "unused" attribute */
173 {
174     /* Add the noreturn attribute */
175     AddAttr (D, NewDeclAttr (atUnused));
176 }
177
178
179
180 void ParseAttribute (Declaration* D)
181 /* Parse an additional __attribute__ modifier */
182 {
183     /* Do we have an attribute? */
184     if (CurTok.Tok != TOK_ATTRIBUTE) {
185         /* No attribute, bail out */
186         return;
187     }
188
189     /* Skip the attribute token */
190     NextToken ();
191
192     /* Expect two(!) open braces */
193     ConsumeLParen ();
194     ConsumeLParen ();
195
196     /* Read a list of attributes */
197     while (1) {
198
199         ident           AttrName;
200         const AttrDesc* Attr = 0;
201
202         /* Identifier follows */
203         if (CurTok.Tok != TOK_IDENT) {
204
205             /* No attribute name */
206             Error ("Attribute name expected");
207
208             /* Skip until end of attribute */
209             ErrorSkip ();
210
211             /* Bail out */
212             return;
213         }
214
215         /* Map the attribute name to its id, then skip the identifier */
216         strcpy (AttrName, CurTok.Ident);
217         Attr = FindAttribute (AttrName);
218         NextToken ();
219
220         /* Did we find a valid attribute? */
221         if (Attr) {
222
223             /* Call the handler */
224             Attr->Handler (D);
225
226         } else {
227             /* Attribute not known, maybe typo */
228             Error ("Illegal attribute: `%s'", AttrName);
229
230             /* Skip until end of attribute */
231             ErrorSkip ();
232
233             /* Bail out */
234             return;
235         }
236
237         /* If a comma follows, there's a next attribute. Otherwise this is the
238          * end of the attribute list.
239          */
240         if (CurTok.Tok != TOK_COMMA) {
241             break;
242         }
243         NextToken ();
244     }
245
246     /* The declaration is terminated with two closing braces */
247     ConsumeRParen ();
248     ConsumeRParen ();
249 }
250
251
252