]> git.sur5r.net Git - cc65/blob - src/cc65/pragma.c
Improve type casts for ints.
[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-2002 Ullrich von Bassewitz                                       */
10 /*               Wacholderweg 14                                             */
11 /*               D-70597 Stuttgart                                           */
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 <stdlib.h>
37 #include <string.h>
38
39 /* common */
40 #include "tgttrans.h"
41
42 /* cc65 */
43 #include "codegen.h"
44 #include "error.h"
45 #include "expr.h"
46 #include "global.h"
47 #include "litpool.h"
48 #include "scanner.h"
49 #include "segments.h"
50 #include "symtab.h"
51 #include "pragma.h"
52
53
54
55 /*****************************************************************************/
56 /*                                   data                                    */
57 /*****************************************************************************/
58
59
60
61 /* Tokens for the #pragmas */
62 typedef enum {
63     PR_ILLEGAL = -1,
64     PR_BSSSEG,
65     PR_CHARMAP,
66     PR_CHECKSTACK,
67     PR_CODESEG,
68     PR_DATASEG,
69     PR_REGVARADDR,
70     PR_RODATASEG,
71     PR_SIGNEDCHARS,
72     PR_STATICLOCALS,
73     PR_ZPSYM,       
74     PR_COUNT
75 } pragma_t;
76
77 /* Pragma table */
78 static const struct Pragma {
79     const char* Key;            /* Keyword */
80     pragma_t    Tok;            /* Token */
81 } Pragmas[PR_COUNT] = {
82     {   "bssseg",       PR_BSSSEG       },
83     {   "charmap",      PR_CHARMAP      },
84     {   "checkstack",   PR_CHECKSTACK   },
85     {   "codeseg",      PR_CODESEG      },
86     {   "dataseg",      PR_DATASEG      },
87     {   "regvaraddr",   PR_REGVARADDR   },
88     {   "rodataseg",    PR_RODATASEG    },
89     {   "signedchars",  PR_SIGNEDCHARS  },
90     {   "staticlocals", PR_STATICLOCALS },
91     {   "zpsym",        PR_ZPSYM        },
92 };
93
94
95
96 /*****************************************************************************/
97 /*                                   Code                                    */
98 /*****************************************************************************/
99
100
101
102 static int CmpKey (const void* Key, const void* Elem)
103 /* Compare function for bsearch */
104 {
105     return strcmp ((const char*) Key, ((const struct Pragma*) Elem)->Key);
106 }
107
108
109
110 static pragma_t FindPragma (const char* Key)
111 /* Find a pragma and return the token. Return PR_ILLEGAL if the keyword is
112  * not a valid pragma.
113  */
114 {
115     struct Pragma* P;
116     P = bsearch (Key, Pragmas, PR_COUNT, sizeof (Pragmas[0]), CmpKey);
117     return P? P->Tok : PR_ILLEGAL;
118 }
119
120
121
122 static void StringPragma (void (*Func) (const char*))
123 /* Handle a pragma that expects a string parameter */
124 {
125     if (CurTok.Tok != TOK_SCONST) {
126         Error ("String literal expected");
127     } else {
128         /* Get the string */
129         const char* Name = GetLiteral (CurTok.IVal);
130
131         /* Call the given function with the string argument */
132         Func (Name);
133
134         /* Reset the string pointer, removing the string from the pool */
135         ResetLiteralPoolOffs (CurTok.IVal);
136     }
137
138     /* Skip the string (or error) token */
139     NextToken ();
140 }
141
142
143
144 static void SegNamePragma (segment_t Seg)
145 /* Handle a pragma that expects a segment name parameter */
146 {
147     if (CurTok.Tok != TOK_SCONST) {
148         Error ("String literal expected");
149     } else {
150         /* Get the segment name */
151         const char* Name = GetLiteral (CurTok.IVal);
152
153         /* Check if the name is valid */
154         if (ValidSegName (Name)) {
155
156             /* Set the new name */
157             g_segname (Seg, Name);
158
159         } else {
160
161             /* Segment name is invalid */
162             Error ("Illegal segment name: `%s'", Name);
163
164         }
165
166         /* Reset the string pointer, removing the string from the pool */
167         ResetLiteralPoolOffs (CurTok.IVal);
168     }
169
170     /* Skip the string (or error) token */
171     NextToken ();
172 }
173
174
175
176 static void CharMapPragma (void)
177 /* Change the character map */
178 {
179     unsigned Index, C;
180
181     ExprDesc Val;
182
183     /* Read the character index */
184     ConstIntExpr (&Val);
185     if (Val.ConstVal < 1 || Val.ConstVal > 255) {
186         Error ("Character index out of range");
187         Index = 'A';
188     } else {
189         Index = Val.ConstVal;
190     }
191
192     /* Comma follows */
193     ConsumeComma ();
194
195     /* Read the character code */
196     ConstIntExpr (&Val);
197     if (Val.ConstVal < 1 || Val.ConstVal > 255) {
198         Error ("Character code out of range");
199         C = 'A';
200     } else {
201         C = Val.ConstVal;
202     }
203
204     /* Remap the character */
205     TgtTranslateSet (Index, C);
206 }
207
208
209
210 static void FlagPragma (unsigned char* Flag)
211 /* Handle a pragma that expects a boolean paramater */
212 {
213     /* Read a constant integer expression */
214     ExprDesc Val;
215     ConstIntExpr (&Val);
216
217     /* Store the value into the flag parameter */
218     *Flag = (Val.ConstVal != 0);
219 }
220
221
222
223 void DoPragma (void)
224 /* Handle pragmas */
225 {
226     pragma_t Pragma;
227
228     /* Skip the token itself */
229     NextToken ();
230
231     /* Identifier must follow */
232     if (CurTok.Tok != TOK_IDENT) {
233         Error ("Identifier expected");
234         return;
235     }
236
237     /* Search for the name, then skip the identifier */
238     Pragma = FindPragma (CurTok.Ident);
239     NextToken ();
240
241     /* Do we know this pragma? */
242     if (Pragma == PR_ILLEGAL) {
243         /* According to the ANSI standard, we're not allowed to generate errors
244          * for unknown pragmas, however, we're allowed to warn - and we will
245          * do so. Otherwise one typo may give you hours of bug hunting...
246          */
247         Warning ("Unknown #pragma `%s'", CurTok.Ident);
248         return;
249     }
250
251     /* Check for an open paren */
252     ConsumeLParen ();
253
254     /* Switch for the different pragmas */
255     switch (Pragma) {
256
257         case PR_BSSSEG:
258             SegNamePragma (SEG_BSS);
259             break;
260
261         case PR_CHARMAP:
262             CharMapPragma ();
263             break;
264
265         case PR_CHECKSTACK:
266             FlagPragma (&CheckStack);
267             break;
268
269         case PR_CODESEG:
270             SegNamePragma (SEG_CODE);
271             break;
272
273         case PR_DATASEG:
274             SegNamePragma (SEG_DATA);
275             break;
276
277         case PR_REGVARADDR:
278             FlagPragma (&AllowRegVarAddr);
279             break;
280
281         case PR_RODATASEG:
282             SegNamePragma (SEG_RODATA);
283             break;
284
285         case PR_SIGNEDCHARS:
286             FlagPragma (&SignedChars);
287             break;
288
289         case PR_STATICLOCALS:
290             FlagPragma (&StaticLocals);
291             break;
292
293         case PR_ZPSYM:
294             StringPragma (MakeZPSym);
295             break;
296
297         default:
298             Internal ("Invalid pragma");
299     }
300
301     /* Closing paren needed */
302     ConsumeRParen ();
303 }
304
305
306