]> git.sur5r.net Git - cc65/blob - src/cc65/pragma.c
c68009c02ec43de4a531606e0389dcb7bf092d57
[cc65] / src / cc65 / pragma.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                                 pragma.c                                  */
4 /*                                                                           */
5 /*                  Pragma handling for the cc65 C compiler                  */
6 /*                                                                           */
7 /*                                                                           */
8 /*                                                                           */
9 /* (C) 1998-2000 Ullrich von Bassewitz                                       */
10 /*               Wacholderweg 14                                             */
11 /*               D-70597 Stuttgart                                           */
12 /* EMail:        uz@musoftware.de                                            */
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 <stdlib.h>
37 #include <string.h>
38 #include <ctype.h>
39                    
40 /* cc65 */
41 #include "codegen.h"
42 #include "error.h"
43 #include "expr.h"
44 #include "global.h"
45 #include "litpool.h"
46 #include "scanner.h"
47 #include "segname.h"
48 #include "symtab.h"
49 #include "pragma.h"
50
51
52
53 /*****************************************************************************/
54 /*                                   data                                    */
55 /*****************************************************************************/
56
57
58
59 /* Tokens for the #pragmas */
60 typedef enum {
61     PR_BSSSEG,
62     PR_CODESEG,
63     PR_DATASEG,
64     PR_REGVARADDR,
65     PR_RODATASEG,
66     PR_SIGNEDCHARS,
67     PR_STATICLOCALS,
68     PR_ZPSYM,
69     PR_ILLEGAL
70 } pragma_t;
71
72 /* Pragma table */
73 static const struct Pragma {
74     const char* Key;            /* Keyword */
75     pragma_t    Tok;            /* Token */
76 } Pragmas[] = {
77     {   "bssseg",       PR_BSSSEG       },
78     {   "codeseg",      PR_CODESEG      },
79     {   "dataseg",      PR_DATASEG      },
80     {   "regvaraddr",   PR_REGVARADDR   },
81     {   "rodataseg",    PR_RODATASEG    },
82     {   "signedchars",  PR_SIGNEDCHARS  },
83     {   "staticlocals", PR_STATICLOCALS },
84     {   "zpsym",        PR_ZPSYM        },
85 };
86
87 /* Number of pragmas */
88 #define PRAGMA_COUNT    (sizeof(Pragmas) / sizeof(Pragmas[0]))
89
90
91
92 /*****************************************************************************/
93 /*                                   Code                                    */
94 /*****************************************************************************/
95
96
97
98 static int CmpKey (const void* Key, const void* Elem)
99 /* Compare function for bsearch */
100 {
101     return strcmp ((const char*) Key, ((const struct Pragma*) Elem)->Key);
102 }
103
104
105
106 static pragma_t FindPragma (const char* Key)
107 /* Find a pragma and return the token. Return PR_ILLEGAL if the keyword is
108  * not a valid pragma.
109  */
110 {
111     struct Pragma* P;
112     P = bsearch (Key, Pragmas, PRAGMA_COUNT, sizeof (Pragmas[0]), CmpKey);
113     return P? P->Tok : PR_ILLEGAL;
114 }
115
116
117
118 static void StringPragma (void (*Func) (const char*))
119 /* Handle a pragma that expects a string parameter */
120 {
121     if (curtok != TOK_SCONST) {
122         Error ("String literal expected");
123     } else {
124         /* Get the string */
125         const char* Name = GetLiteral (curval);
126
127         /* Call the given function with the string argument */
128         Func (Name);
129
130         /* Reset the string pointer, removing the string from the pool */
131         ResetLiteralOffs (curval);
132     }
133
134     /* Skip the string (or error) token */
135     NextToken ();
136 }
137
138
139
140 static void SegNamePragma (void (*Func) (const char*))
141 /* Handle a pragma that expects a segment name parameter */
142 {
143     if (curtok != TOK_SCONST) {
144         Error ("String literal expected");
145     } else {
146         /* Get the segment name */
147         const char* Name = GetLiteral (curval);
148
149         /* Check if the name is valid */
150         if (ValidSegName (Name)) {
151
152             /* Call the given function to set the name */
153             Func (Name);
154
155         } else {
156
157             /* Segment name is invalid */
158             Error ("Illegal segment name: `%s'", Name);
159
160         }
161
162         /* Reset the string pointer, removing the string from the pool */
163         ResetLiteralOffs (curval);
164     }
165
166     /* Skip the string (or error) token */
167     NextToken ();
168 }
169
170
171
172 static void FlagPragma (unsigned char* Flag)
173 /* Handle a pragma that expects a boolean paramater */
174 {
175     /* Read a constant expression */
176     struct expent val;
177     constexpr (&val);
178
179     /* Store the value into the flag parameter */
180     *Flag = (val.e_const != 0);
181 }
182
183
184
185 void DoPragma (void)
186 /* Handle pragmas */
187 {
188     pragma_t Pragma;
189
190     /* Skip the token itself */
191     NextToken ();
192
193     /* Identifier must follow */
194     if (curtok != TOK_IDENT) {
195         Error ("Identifier expected");
196         return;
197     }
198
199     /* Do we know this pragma? */
200     Pragma = FindPragma (CurTok.Ident);
201     if (Pragma == PR_ILLEGAL) {
202         /* According to the ANSI standard, we're not allowed to generate errors
203          * for unknown pragmas, however, we're allowed to warn - and we will
204          * do so. Otherwise one typo may give you hours of bug hunting...
205          */
206         Warning ("Unknown #pragma `%s'", CurTok.Ident);
207         return;
208     }
209
210     /* Skip the identifier and check for an open paren */
211     NextToken ();
212     ConsumeLParen ();
213
214     /* Switch for the different pragmas */
215     switch (Pragma) {
216
217         case PR_BSSSEG:
218             SegNamePragma (g_bssname);
219             break;
220
221         case PR_CODESEG:
222             SegNamePragma (g_codename);
223             break;
224
225         case PR_DATASEG:
226             SegNamePragma (g_dataname);
227             break;
228
229         case PR_REGVARADDR:
230             FlagPragma (&AllowRegVarAddr);
231             break;
232
233         case PR_RODATASEG:
234             SegNamePragma (g_rodataname);
235             break;
236
237         case PR_SIGNEDCHARS:
238             FlagPragma (&SignedChars);
239             break;
240
241         case PR_STATICLOCALS:
242             FlagPragma (&StaticLocals);
243             break;
244
245         case PR_ZPSYM:
246             StringPragma (MakeZPSym);
247             break;
248
249         default:
250             Internal ("Invalid pragma");
251     }
252
253     /* Closing paren needed */
254     ConsumeRParen ();
255 }
256
257
258