]> git.sur5r.net Git - cc65/blob - src/cc65/compile.c
Renamed some functions for better readbility.
[cc65] / src / cc65 / compile.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                                 compile.c                                 */
4 /*                                                                           */
5 /*                       Top level compiler subroutine                       */
6 /*                                                                           */
7 /*                                                                           */
8 /*                                                                           */
9 /* (C) 2000-2001 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
38 /* common */
39 #include "version.h"
40
41 /* cc65 */
42 #include "asmlabel.h"
43 #include "codegen.h"
44 #include "declare.h"
45 #include "error.h"
46 #include "expr.h"
47 #include "function.h"
48 #include "global.h"
49 #include "incpath.h"
50 #include "input.h"
51 #include "litpool.h"
52 #include "macrotab.h"
53 #include "pragma.h"
54 #include "symtab.h"
55 #include "compile.h"
56
57
58
59 /*****************************************************************************/
60 /*                                   Code                                    */
61 /*****************************************************************************/
62
63
64
65 static void Parse (void)
66 /* Top level parser routine. */
67 {
68     int comma;
69     SymEntry* Entry;
70
71     /* Go... */
72     NextToken ();
73     NextToken ();
74
75     /* Parse until end of input */
76     while (CurTok.Tok != TOK_CEOF) {
77
78         DeclSpec        Spec;
79         Declaration     Decl;
80         int             NeedStorage;
81
82         /* Check for empty statements */
83         if (CurTok.Tok == TOK_SEMI) {
84             NextToken ();
85             continue;
86         }
87
88         /* Check for an ASM statement (which is allowed also on global level) */
89         if (CurTok.Tok == TOK_ASM) {
90             doasm ();
91             ConsumeSemi ();
92             continue;
93         }
94
95         /* Check for a #pragma */
96         if (CurTok.Tok == TOK_PRAGMA) {
97             DoPragma ();
98             continue;
99         }
100
101         /* Read variable defs and functions */
102         ParseDeclSpec (&Spec, SC_EXTERN | SC_STATIC, T_INT);
103
104         /* Don't accept illegal storage classes */
105         if (Spec.StorageClass == SC_AUTO || Spec.StorageClass == SC_REGISTER) {
106             Error ("Illegal storage class");
107             Spec.StorageClass = SC_EXTERN | SC_STATIC;
108         }
109
110         /* Check if this is only a type declaration */
111         if (CurTok.Tok == TOK_SEMI) {
112             CheckEmptyDecl (&Spec);
113             NextToken ();
114             continue;
115         }
116
117         /* Check if we must reserve storage for the variable. We do
118          * this if we don't had a storage class given ("int i") or
119          * if the storage class is explicitly specified as static.
120          * This means that "extern int i" will not get storage
121          * allocated.
122          */
123         NeedStorage = (Spec.StorageClass & SC_TYPEDEF) == 0 &&
124                       ((Spec.Flags & DS_DEF_STORAGE) != 0  ||
125                       (Spec.StorageClass & (SC_STATIC | SC_EXTERN)) == SC_STATIC);
126
127         /* Read declarations for this type */
128         Entry = 0;
129         comma = 0;
130         while (1) {
131
132             unsigned SymFlags;
133
134             /* Read the next declaration */
135             ParseDecl (&Spec, &Decl, DM_NEED_IDENT);
136             if (Decl.Ident[0] == '\0') {
137                 NextToken ();
138                 break;
139             }
140
141             /* Get the symbol flags */
142             SymFlags = Spec.StorageClass;
143             if (IsTypeFunc (Decl.Type)) {
144                 SymFlags |= SC_FUNC;
145             } else {
146                 if (NeedStorage) {
147                     /* We will allocate storage, variable is defined */
148                     SymFlags |= SC_STORAGE | SC_DEF;
149                 }
150             }
151
152             /* Add an entry to the symbol table */
153             Entry = AddGlobalSym (Decl.Ident, Decl.Type, SymFlags);
154
155             /* Reserve storage for the variable if we need to */
156             if (SymFlags & SC_STORAGE) {
157
158                 /* Get the size of the variable */
159                 unsigned Size = SizeOf (Decl.Type);
160
161                 /* Allow initialization */
162                 if (CurTok.Tok == TOK_ASSIGN) {
163
164                     /* We cannot initialize types of unknown size, or
165                      * void types in non ANSI mode.
166                      */
167                     if (Size == 0) {
168                         if (!IsTypeVoid (Decl.Type)) {
169                             if (!IsTypeArray (Decl.Type)) {
170                                 /* Size is unknown and not an array */
171                                 Error ("Variable `%s' has unknown size", Decl.Ident);
172                             }
173                         } else if (ANSI) {
174                             /* We cannot declare variables of type void */
175                             Error ("Illegal type for variable `%s'", Decl.Ident);
176                         }
177                     }
178
179                     /* Switch to the data or rodata segment */
180                     if (IsQualConst (Decl.Type)) {
181                         g_userodata ();
182                     } else {
183                         g_usedata ();
184                     }
185
186                     /* Define a label */
187                     g_defgloblabel (Entry->Name);
188
189                     /* Skip the '=' */
190                     NextToken ();
191
192                     /* Parse the initialization */
193                     ParseInit (Entry->Type);
194                 } else {
195
196                     if (IsTypeVoid (Decl.Type)) {
197                         /* We cannot declare variables of type void */
198                         Error ("Illegal type for variable `%s'", Decl.Ident);
199                     } else if (Size == 0) {
200                         /* Size is unknown */
201                         Error ("Variable `%s' has unknown size", Decl.Ident);
202                     }
203
204                     /* Switch to the BSS segment */
205                     g_usebss ();
206
207                     /* Define a label */
208                     g_defgloblabel (Entry->Name);
209
210                     /* Allocate space for uninitialized variable */
211                     g_res (SizeOf (Entry->Type));
212                 }
213
214             }
215
216             /* Check for end of declaration list */
217             if (CurTok.Tok == TOK_COMMA) {
218                 NextToken ();
219                 comma = 1;
220             } else {
221                 break;
222             }
223         }
224
225         /* Function declaration? */
226         if (Entry && IsTypeFunc (Entry->Type)) {
227
228             /* Function */
229             if (!comma) {
230
231                 if (CurTok.Tok == TOK_SEMI) {
232
233                     /* Prototype only */
234                     NextToken ();
235
236                 } else {
237                     if (Entry) {
238                         NewFunc (Entry);
239                     }
240                 }
241             }
242
243         } else {
244
245             /* Must be followed by a semicolon */
246             ConsumeSemi ();
247
248         }
249     }
250 }
251
252
253
254 void Compile (const char* FileName)
255 /* Top level compile routine. Will setup things and call the parser. */
256 {
257     char* Path;
258
259
260     /* Add some standard paths to the include search path */
261     AddIncludePath ("", INC_USER);              /* Current directory */
262     AddIncludePath ("include", INC_SYS);
263 #ifdef CC65_INC
264     AddIncludePath (CC65_INC, INC_SYS);
265 #else
266     AddIncludePath ("/usr/lib/cc65/include", INC_SYS);
267 #endif
268     Path = getenv ("CC65_INC");
269     if (Path) {
270         AddIncludePath (Path, INC_SYS | INC_USER);
271     }
272
273     /* Add macros that are always defined */
274     DefineNumericMacro ("__CC65__", (VER_MAJOR * 0x100) + (VER_MINOR * 0x10) + VER_PATCH);
275
276     /* Strict ANSI macro */
277     if (ANSI) {
278         DefineNumericMacro ("__STRICT_ANSI__", 1);
279     }
280
281     /* Optimization macros */
282     if (Optimize) {
283         DefineNumericMacro ("__OPT__", 1);
284         if (FavourSize == 0) {
285             DefineNumericMacro ("__OPT_i__", 1);
286         }
287         if (EnableRegVars) {
288             DefineNumericMacro ("__OPT_r__", 1);
289         }
290         if (InlineStdFuncs) {
291             DefineNumericMacro ("__OPT_s__", 1);
292         }
293     }
294
295     /* Initialize the literal pool */
296     InitLiteralPool ();
297
298     /* Create the base lexical level */
299     EnterGlobalLevel ();
300
301     /* Generate the code generator preamble */
302     g_preamble ();
303
304     /* Open the input file */
305     OpenMainFile (FileName);
306
307     /* Ok, start the ball rolling... */
308     Parse ();
309
310     /* Dump the literal pool. */
311     DumpLiteralPool ();
312
313     /* Write imported/exported symbols */
314     EmitExternals ();
315
316     if (Debug) {
317         PrintLiteralPoolStats (stdout);
318         PrintMacroStats (stdout);
319     }
320
321     /* Leave the main lexical level */
322     LeaveGlobalLevel ();
323
324     /* Print an error report */
325     ErrorReport ();
326 }
327
328
329