]> git.sur5r.net Git - cc65/blob - src/da65/config.c
Fix codesize setting
[cc65] / src / da65 / config.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                                 config.c                                  */
4 /*                                                                           */
5 /*                 Disassembler configuration file handling                  */
6 /*                                                                           */
7 /*                                                                           */
8 /*                                                                           */
9 /* (C) 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 <stdio.h>
37 #include <string.h>
38 #if defined(_MSC_VER)
39 /* Microsoft compiler */
40 #  include <io.h>
41 #else
42 /* Anyone else */
43 #  include <unistd.h>
44 #endif
45
46 /* common */
47 #include "xmalloc.h"
48
49 /* da65 */
50 #include "attrtab.h"
51 #include "error.h"
52 #include "global.h"
53 #include "scanner.h"
54 #include "config.h"
55
56
57
58 /*****************************************************************************/
59 /*                                   Code                                    */
60 /*****************************************************************************/
61
62
63
64 static void GlobalSection (void)
65 /* Parse a global section */
66 {
67     static const IdentTok GlobalDefs[] = {
68         {   "INPUTNAME",        CFGTOK_INPUTNAME        },
69         {   "OUTPUTNAME",       CFGTOK_OUTPUTNAME       },
70         {   "PAGELENGTH",       CFGTOK_PAGELENGTH       },
71         {   "STARTADDR",        CFGTOK_STARTADDR        },
72     };
73
74     /* Skip the token */
75     CfgNextTok ();
76
77     /* Expect the opening curly brace */
78     CfgConsumeLCurly ();
79
80     /* Look for section tokens */
81     while (CfgTok != CFGTOK_RCURLY) {
82
83         /* Convert to special token */
84         CfgSpecialToken (GlobalDefs, ENTRY_COUNT (GlobalDefs), "Global directive");
85
86         /* Look at the token */
87         switch (CfgTok) {
88
89             case CFGTOK_INPUTNAME:
90                 CfgNextTok ();
91                 CfgAssureStr ();
92                 if (InFile) {
93                     CfgError ("Input file name already given");
94                 }
95                 InFile = xstrdup (CfgSVal);
96                 CfgNextTok ();
97                 break;
98
99             case CFGTOK_OUTPUTNAME:
100                 CfgNextTok ();
101                 CfgAssureStr ();
102                 if (OutFile) {
103                     CfgError ("Output file name already given");
104                 }
105                 OutFile = xstrdup (CfgSVal);
106                 CfgNextTok ();
107                 break;
108
109             case CFGTOK_PAGELENGTH:
110                 CfgNextTok ();
111                 CfgAssureInt ();
112                 if (CfgIVal != -1) {
113                     CfgRangeCheck (MIN_PAGE_LEN, MAX_PAGE_LEN);
114                 }
115                 PageLength = CfgIVal;
116                 CfgNextTok ();
117                 break;
118
119             case CFGTOK_STARTADDR:
120                 CfgNextTok ();
121                 CfgAssureInt ();
122                 CfgRangeCheck (0x0000, 0xFFFF);
123                 StartAddr = CfgIVal;
124                 CfgNextTok ();
125                 break;
126
127         }
128
129         /* Directive is followed by a semicolon */
130         CfgConsumeSemi ();
131
132     }
133
134     /* Consume the closing brace */
135     CfgConsumeRCurly ();
136 }
137
138
139
140 static void RangeSection (void)
141 /* Parse a range section */
142 {
143     static const IdentTok RangeDefs[] = {
144         {   "START",            CFGTOK_START    },
145         {   "END",              CFGTOK_END      },
146         {   "TYPE",             CFGTOK_TYPE     },
147     };
148
149     static const IdentTok TypeDefs[] = {
150         {   "CODE",             CFGTOK_CODE     },
151         {   "BYTETABLE",        CFGTOK_BYTETAB  },
152         {   "WORDTABLE",        CFGTOK_WORDTAB  },
153         {   "DWORDTABLE",       CFGTOK_DWORDTAB },
154         {   "ADDRTABLE",        CFGTOK_ADDRTAB  },
155         {   "RTSTABLE",         CFGTOK_RTSTAB   },
156         {   "TEXTTABLE",        CFGTOK_TEXTTAB  },
157     };
158
159
160     /* Which values did we get? */
161     enum {
162         tNone   = 0x00,
163         tStart  = 0x01,
164         tEnd    = 0x02,
165         tType   = 0x04,
166         tAll    = 0x07
167     } Needed = tNone;
168
169     /* Locals - initialize to avoid gcc warnings */
170     unsigned Start      = 0;
171     unsigned End        = 0;
172     unsigned char Type  = 0;
173
174     /* Skip the token */
175     CfgNextTok ();
176
177     /* Expect the opening curly brace */
178     CfgConsumeLCurly ();
179
180     /* Look for section tokens */
181     while (CfgTok != CFGTOK_RCURLY) {
182
183         /* Convert to special token */
184         CfgSpecialToken (RangeDefs, ENTRY_COUNT (RangeDefs), "Range directive");
185
186         /* Look at the token */
187         switch (CfgTok) {
188
189             case CFGTOK_START:
190                 CfgNextTok ();
191                 CfgAssureInt ();
192                 CfgRangeCheck (0x0000, 0xFFFF);
193                 Start = CfgIVal;
194                 Needed |= tStart;
195                 CfgNextTok ();
196                 break;
197
198             case CFGTOK_END:
199                 CfgNextTok ();
200                 CfgAssureInt ();
201                 CfgRangeCheck (0x0000, 0xFFFF);
202                 End = CfgIVal;
203                 Needed |= tEnd;
204                 CfgNextTok ();
205                 break;
206
207             case CFGTOK_TYPE:
208                 CfgNextTok ();
209                 CfgSpecialToken (TypeDefs, ENTRY_COUNT (TypeDefs), "Type");
210                 switch (CfgTok) {
211                     case CFGTOK_CODE:           Type = atCode;          break;
212                     case CFGTOK_BYTETAB:        Type = atByteTab;       break;
213                     case CFGTOK_WORDTAB:        Type = atWordTab;       break;
214                     case CFGTOK_DWORDTAB:       Type = atDWordTab;      break;
215                     case CFGTOK_ADDRTAB:        Type = atAddrTab;       break;
216                     case CFGTOK_RTSTAB:         Type = atRtsTab;        break;
217                     case CFGTOK_TEXTTAB:        Type = atTextTab;       break;
218                 }
219                 Needed |= tType;
220                 CfgNextTok ();
221                 break;
222         }
223
224         /* Directive is followed by a semicolon */
225         CfgConsumeSemi ();
226
227     }
228
229     /* Did we get all required values? */
230     if (Needed != tAll) {
231         CfgError ("Required values missing from this section");
232     }
233
234     /* Start must be less than end */
235     if (Start > End) {
236         CfgError ("Start value must not be greater than end value");
237     }
238
239     /* Set the range */
240     MarkRange (Start, End, Type);
241
242     /* Consume the closing brace */
243     CfgConsumeRCurly ();
244 }
245
246
247
248 static void LabelSection (void)
249 /* Parse a label section */
250 {
251     static const IdentTok LabelDefs[] = {
252         {   "NAME",     CFGTOK_NAME     },
253         {   "ADDR",     CFGTOK_ADDR     },
254         {   "SIZE",     CFGTOK_SIZE     },
255     };
256
257     /* Locals - initialize to avoid gcc warnings */
258     char* Name = 0;
259     long Value = -1;
260     long Size  = -1;
261
262     /* Skip the token */
263     CfgNextTok ();
264
265     /* Expect the opening curly brace */
266     CfgConsumeLCurly ();
267
268     /* Look for section tokens */
269     while (CfgTok != CFGTOK_RCURLY) {
270
271         /* Convert to special token */
272         CfgSpecialToken (LabelDefs, ENTRY_COUNT (LabelDefs), "Label directive");
273
274         /* Look at the token */
275         switch (CfgTok) {
276
277             case CFGTOK_NAME:
278                 CfgNextTok ();
279                 if (Name) {
280                     CfgError ("Name already given");
281                 }
282                 CfgAssureStr ();
283                 if (CfgSVal[0] == '\0') {
284                     CfgError ("Name may not be empty");
285                 }
286                 Name = xstrdup (CfgSVal);
287                 CfgNextTok ();
288                 break;
289
290             case CFGTOK_ADDR:
291                 CfgNextTok ();
292                 if (Value >= 0) {
293                     CfgError ("Value already given");
294                 }
295                 CfgAssureInt ();
296                 CfgRangeCheck (0, 0xFFFF);
297                 Value = CfgIVal;
298                 CfgNextTok ();
299                 break;
300
301             case CFGTOK_SIZE:
302                 CfgNextTok ();
303                 if (Size >= 0) {
304                     CfgError ("Size already given");
305                 }
306                 CfgAssureInt ();
307                 CfgRangeCheck (1, 0x10000);
308                 Size = CfgIVal;
309                 CfgNextTok ();
310                 break;
311
312         }
313
314         /* Directive is followed by a semicolon */
315         CfgConsumeSemi ();
316     }
317
318     /* Did we get the necessary data */
319     if (Name == 0) {
320         CfgError ("Label name is missing");
321     }
322     if (Value < 0) {
323         CfgError ("Label value is missing");
324     }
325     if (Size < 0) {
326         /* Use default */
327         Size = 1;
328     }
329     if (Value + Size > 0x10000) {
330         CfgError ("Invalid size (address out of range)");
331     }
332     if (HaveLabel ((unsigned) Value)) {
333         CfgError ("Label for address $%04lX already defined", Value);
334     }
335
336     /* Define the label */
337     AddLabel ((unsigned) Value, atExtLabel, Name);
338
339     /* Define dependent labels if necessary */
340     if (Size > 1) {
341         unsigned Offs;
342
343         /* Allocate memory for the dependent label names */
344         unsigned NameLen = strlen (Name);
345         char*    DepName = xmalloc (NameLen + 7);
346         char*    DepOffs = DepName + NameLen + 1;
347
348         /* Copy the original name into the buffer */
349         memcpy (DepName, Name, NameLen);
350         DepName[NameLen] = '+';
351
352         /* Define the labels */
353         for (Offs = 1; Offs < (unsigned) Size; ++Offs) {
354             sprintf (DepOffs, "%u", Offs);
355             AddLabel ((unsigned) Value+Offs, atDepLabel, DepName);
356         }
357
358         /* Free the name buffer */
359         xfree (DepName);
360     }
361
362     /* Delete the dynamically allocated memory for Name */
363     xfree (Name);
364
365     /* Consume the closing brace */
366     CfgConsumeRCurly ();
367 }
368
369
370
371 static void CfgParse (void)
372 /* Parse the config file */
373 {
374     static const IdentTok Globals[] = {
375         {   "GLOBAL",   CFGTOK_GLOBAL   },
376         {   "RANGE",    CFGTOK_RANGE    },
377         {   "LABEL",    CFGTOK_LABEL    },
378     };
379
380     while (CfgTok != CFGTOK_EOF) {
381
382         /* Convert an identifier into a token */
383         CfgSpecialToken (Globals, ENTRY_COUNT (Globals), "Config directive");
384
385         /* Check the token */
386         switch (CfgTok) {
387
388             case CFGTOK_GLOBAL:
389                 GlobalSection ();
390                 break;
391
392             case CFGTOK_RANGE:
393                 RangeSection ();
394                 break;
395
396             case CFGTOK_LABEL:
397                 LabelSection ();
398                 break;
399
400         }
401
402         /* Semicolon expected */
403         CfgConsumeSemi ();
404     }
405 }
406
407
408
409 void CfgRead (void)
410 /* Read the configuration if a configuration file exists */
411 {
412     /* Check if we have a config file given */
413     if (!CfgAvail() || access (CfgGetName(), 0) != 0) {
414         /* No name given or file not found */
415         return;
416     }
417
418     /* Open the config file */
419     CfgOpenInput ();
420
421     /* Parse the config file */
422     CfgParse ();
423
424     /* Close the file */
425     CfgCloseInput ();
426 }
427
428
429
430
431
432