]> git.sur5r.net Git - cc65/blob - src/da65/config.c
7bbe4634090e078a27a94a79a88299bbae13c691
[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     };
157
158
159     /* Which values did we get? */
160     enum {
161         tNone   = 0x00,
162         tStart  = 0x01,
163         tEnd    = 0x02,
164         tType   = 0x04,
165         tAll    = 0x07
166     } Needed = tNone;
167
168     /* Locals - initialize to avoid gcc warnings */
169     unsigned Start      = 0;
170     unsigned End        = 0;
171     unsigned char Type  = 0;
172
173     /* Skip the token */
174     CfgNextTok ();
175
176     /* Expect the opening curly brace */
177     CfgConsumeLCurly ();
178
179     /* Look for section tokens */
180     while (CfgTok != CFGTOK_RCURLY) {
181
182         /* Convert to special token */
183         CfgSpecialToken (RangeDefs, ENTRY_COUNT (RangeDefs), "Range directive");
184
185         /* Look at the token */
186         switch (CfgTok) {
187
188             case CFGTOK_START:
189                 CfgNextTok ();
190                 CfgAssureInt ();
191                 CfgRangeCheck (0x0000, 0xFFFF);
192                 Start = CfgIVal;
193                 Needed |= tStart;
194                 CfgNextTok ();
195                 break;
196
197             case CFGTOK_END:
198                 CfgNextTok ();
199                 CfgAssureInt ();
200                 CfgRangeCheck (0x0000, 0xFFFF);
201                 End = CfgIVal;
202                 Needed |= tEnd;
203                 CfgNextTok ();
204                 break;
205
206             case CFGTOK_TYPE:
207                 CfgNextTok ();
208                 CfgSpecialToken (TypeDefs, ENTRY_COUNT (TypeDefs), "Type");
209                 switch (CfgTok) {
210                     case CFGTOK_CODE:           Type = atCode;          break;
211                     case CFGTOK_BYTETAB:        Type = atByteTab;       break;
212                     case CFGTOK_WORDTAB:        Type = atWordTab;       break;
213                     case CFGTOK_DWORDTAB:       Type = atDWordTab;      break;
214                     case CFGTOK_ADDRTAB:        Type = atAddrTab;       break;
215                     case CFGTOK_RTSTAB:         Type = atRtsTab;        break;
216                 }
217                 Needed |= tType;
218                 CfgNextTok ();
219                 break;
220         }
221
222         /* Directive is followed by a semicolon */
223         CfgConsumeSemi ();
224
225     }
226
227     /* Did we get all required values? */
228     if (Needed != tAll) {
229         CfgError ("Required values missing from this section");
230     }
231
232     /* Start must be less than end */
233     if (Start > End) {
234         CfgError ("Start value must not be greater than end value");
235     }
236
237     /* Set the range */
238     MarkRange (Start, End, Type);
239
240     /* Consume the closing brace */
241     CfgConsumeRCurly ();
242 }
243
244
245
246 static void LabelSection (void)
247 /* Parse a label section */
248 {
249     static const IdentTok LabelDefs[] = {
250         {   "NAME",     CFGTOK_NAME     },
251         {   "ADDR",     CFGTOK_ADDR     },
252         {   "SIZE",     CFGTOK_SIZE     },
253     };
254
255     /* Locals - initialize to avoid gcc warnings */
256     char* Name = 0;
257     long Value = -1;
258     long Size  = -1;
259
260     /* Skip the token */
261     CfgNextTok ();
262
263     /* Expect the opening curly brace */
264     CfgConsumeLCurly ();
265
266     /* Look for section tokens */
267     while (CfgTok != CFGTOK_RCURLY) {
268
269         /* Convert to special token */
270         CfgSpecialToken (LabelDefs, ENTRY_COUNT (LabelDefs), "Label directive");
271
272         /* Look at the token */
273         switch (CfgTok) {
274
275             case CFGTOK_NAME:
276                 CfgNextTok ();
277                 if (Name) {
278                     CfgError ("Name already given");
279                 }
280                 CfgAssureStr ();
281                 if (CfgSVal[0] == '\0') {
282                     CfgError ("Name may not be empty");
283                 }
284                 Name = xstrdup (CfgSVal);
285                 CfgNextTok ();
286                 break;
287
288             case CFGTOK_ADDR:
289                 CfgNextTok ();
290                 if (Value >= 0) {
291                     CfgError ("Value already given");
292                 }
293                 CfgAssureInt ();
294                 CfgRangeCheck (0, 0xFFFF);
295                 Value = CfgIVal;
296                 CfgNextTok ();
297                 break;
298
299             case CFGTOK_SIZE:
300                 CfgNextTok ();
301                 if (Size >= 0) {
302                     CfgError ("Size already given");
303                 }
304                 CfgAssureInt ();
305                 CfgRangeCheck (1, 0x10000);
306                 Size = CfgIVal;
307                 CfgNextTok ();
308                 break;
309
310         }
311
312         /* Directive is followed by a semicolon */
313         CfgConsumeSemi ();
314     }
315
316     /* Did we get the necessary data */
317     if (Name == 0) {
318         CfgError ("Label name is missing");
319     }
320     if (Value < 0) {
321         CfgError ("Label value is missing");
322     }
323     if (Size < 0) {
324         /* Use default */
325         Size = 1;
326     }
327     if (Value + Size > 0x10000) {
328         CfgError ("Invalid size (address out of range)");
329     }
330     if (HaveLabel ((unsigned) Value)) {
331         CfgError ("Label for address $%04lX already defined", Value);
332     }
333
334     /* Define the label */
335     AddLabel ((unsigned) Value, atExtLabel, Name);
336
337     /* Define dependent labels if necessary */
338     if (Size > 1) {
339         unsigned Offs;
340
341         /* Allocate memory for the dependent label names */
342         unsigned NameLen = strlen (Name);
343         char*    DepName = xmalloc (NameLen + 7);
344         char*    DepOffs = DepName + NameLen + 1;
345
346         /* Copy the original name into the buffer */
347         memcpy (DepName, Name, NameLen);
348         DepName[NameLen] = '+';
349
350         /* Define the labels */
351         for (Offs = 1; Offs < (unsigned) Size; ++Offs) {
352             sprintf (DepOffs, "%u", Offs);
353             AddLabel ((unsigned) Value+Offs, atDepLabel, DepName);
354         }
355
356         /* Free the name buffer */
357         xfree (DepName);
358     }
359
360     /* Delete the dynamically allocated memory for Name */
361     xfree (Name);
362
363     /* Consume the closing brace */
364     CfgConsumeRCurly ();
365 }
366
367
368
369 static void CfgParse (void)
370 /* Parse the config file */
371 {
372     static const IdentTok Globals[] = {
373         {   "GLOBAL",   CFGTOK_GLOBAL   },
374         {   "RANGE",    CFGTOK_RANGE    },
375         {   "LABEL",    CFGTOK_LABEL    },
376     };
377
378     while (CfgTok != CFGTOK_EOF) {
379
380         /* Convert an identifier into a token */
381         CfgSpecialToken (Globals, ENTRY_COUNT (Globals), "Config directive");
382
383         /* Check the token */
384         switch (CfgTok) {
385
386             case CFGTOK_GLOBAL:
387                 GlobalSection ();
388                 break;
389
390             case CFGTOK_RANGE:
391                 RangeSection ();
392                 break;
393
394             case CFGTOK_LABEL:
395                 LabelSection ();
396                 break;
397
398         }
399
400         /* Semicolon expected */
401         CfgConsumeSemi ();
402     }
403 }
404
405
406
407 void CfgRead (void)
408 /* Read the configuration if a configuration file exists */
409 {
410     /* Check if we have a config file given */
411     if (!CfgAvail() || access (CfgGetName(), 0) != 0) {
412         /* No name given or file not found */
413         return;
414     }
415
416     /* Open the config file */
417     CfgOpenInput ();
418
419     /* Parse the config file */
420     CfgParse ();
421
422     /* Close the file */
423     CfgCloseInput ();
424 }
425
426
427
428
429
430