]> git.sur5r.net Git - cc65/blob - src/da65/infofile.c
Fixes for the watcom makefiles:
[cc65] / src / da65 / infofile.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                                infofile.h                                 */
4 /*                                                                           */
5 /*                      Disassembler info file handling                      */
6 /*                                                                           */
7 /*                                                                           */
8 /*                                                                           */
9 /* (C) 2000-2007 Ullrich von Bassewitz                                       */
10 /*               Roemerstrasse 52                                            */
11 /*               D-70794 Filderstadt                                         */
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 <stdio.h>
37 #include <string.h>
38 #include <limits.h>
39 #if defined(_MSC_VER)
40 /* Microsoft compiler */
41 #  include <io.h>
42 #else
43 /* Anyone else */
44 #  include <unistd.h>
45 #endif
46
47 /* common */
48 #include "cpu.h"
49 #include "xmalloc.h"
50
51 /* da65 */
52 #include "asminc.h"
53 #include "attrtab.h"
54 #include "comments.h"
55 #include "error.h"
56 #include "global.h"
57 #include "infofile.h"
58 #include "labels.h"
59 #include "opctable.h"
60 #include "scanner.h"
61 #include "segment.h"
62
63
64
65 /*****************************************************************************/
66 /*                                   Code                                    */
67 /*****************************************************************************/
68
69
70
71 static void AddAttr (const char* Name, unsigned* Set, unsigned Attr)
72 /* Add an attribute to the set and check that it is not given twice */
73 {
74     if (*Set & Attr) {
75         /* Attribute is already in the set */
76         InfoError ("%s given twice", Name);
77     }
78     *Set |= Attr;
79 }
80
81
82
83 static void AsmIncSection (void)
84 /* Parse a asminc section */
85 {
86     static const IdentTok LabelDefs[] = {
87         {   "COMMENTSTART",     INFOTOK_COMMENTSTART    },
88         {   "FILE",             INFOTOK_FILE            },                     
89         {   "IGNOREUNKNOWN",    INFOTOK_IGNOREUNKNOWN   },
90     };
91
92     /* Locals - initialize to avoid gcc warnings */
93     char* Name = 0;
94     int CommentStart = EOF;
95     int IgnoreUnknown = -1;
96
97     /* Skip the token */
98     InfoNextTok ();
99
100     /* Expect the opening curly brace */
101     InfoConsumeLCurly ();
102
103     /* Look for section tokens */
104     while (InfoTok != INFOTOK_RCURLY) {
105
106         /* Convert to special token */
107         InfoSpecialToken (LabelDefs, ENTRY_COUNT (LabelDefs), "Asminc directive");
108
109         /* Look at the token */
110         switch (InfoTok) {
111
112             case INFOTOK_COMMENTSTART:
113                 InfoNextTok ();
114                 if (CommentStart != EOF) {
115                     InfoError ("Commentstart already given");
116                 }
117                 InfoAssureChar ();
118                 CommentStart = (char) InfoIVal;
119                 InfoNextTok ();
120                 break;
121
122             case INFOTOK_FILE:
123                 InfoNextTok ();
124                 if (Name) {
125                     InfoError ("File name already given");
126                 }
127                 InfoAssureStr ();
128                 if (InfoSVal[0] == '\0') {
129                     InfoError ("File name may not be empty");
130                 }
131                 Name = xstrdup (InfoSVal);
132                 InfoNextTok ();
133                 break;
134
135             case INFOTOK_IGNOREUNKNOWN:
136                 InfoNextTok ();
137                 if (IgnoreUnknown != -1) {
138                     InfoError ("Ignoreunknown already specified");
139                 }
140                 InfoBoolToken ();
141                 IgnoreUnknown = (InfoTok != INFOTOK_FALSE);
142                 InfoNextTok ();
143                 break;
144
145             default:
146                 Internal ("Unexpected token: %u", InfoTok);
147         }
148
149         /* Directive is followed by a semicolon */
150         InfoConsumeSemi ();
151     }
152
153     /* Check for the necessary data and assume defaults */
154     if (Name == 0) {
155         InfoError ("File name is missing");
156     }
157     if (CommentStart == EOF) {
158         CommentStart = ';';
159     }
160     if (IgnoreUnknown == -1) {
161         IgnoreUnknown = 0;
162     }
163
164     /* Open the file and read the symbol definitions */
165     AsmInc (Name, CommentStart, IgnoreUnknown);
166
167     /* Delete the dynamically allocated memory for Name */
168     xfree (Name);
169
170     /* Consume the closing brace */
171     InfoConsumeRCurly ();
172 }
173
174
175
176 static void GlobalSection (void)
177 /* Parse a global section */
178 {
179     static const IdentTok GlobalDefs[] = {
180         {   "ARGUMENTCOL",      INFOTOK_ARGUMENT_COLUMN },
181         {   "ARGUMENTCOLUMN",   INFOTOK_ARGUMENT_COLUMN },
182         {   "COMMENTCOL",       INFOTOK_COMMENT_COLUMN  },
183         {   "COMMENTCOLUMN",    INFOTOK_COMMENT_COLUMN  },
184         {   "COMMENTS",         INFOTOK_COMMENTS        },
185         {   "CPU",              INFOTOK_CPU             },
186         {   "HEXOFFS",          INFOTOK_HEXOFFS         },
187         {   "INPUTNAME",        INFOTOK_INPUTNAME       },
188         {   "INPUTOFFS",        INFOTOK_INPUTOFFS       },
189         {   "INPUTSIZE",        INFOTOK_INPUTSIZE       },
190         {   "LABELBREAK",       INFOTOK_LABELBREAK      },
191         {   "MNEMONICCOL",      INFOTOK_MNEMONIC_COLUMN },
192         {   "MNEMONICCOLUMN",   INFOTOK_MNEMONIC_COLUMN },
193         {   "OUTPUTNAME",       INFOTOK_OUTPUTNAME      },
194         {   "PAGELENGTH",       INFOTOK_PAGELENGTH      },
195         {   "STARTADDR",        INFOTOK_STARTADDR       },
196         {   "TEXTCOL",          INFOTOK_TEXT_COLUMN     },
197         {   "TEXTCOLUMN",       INFOTOK_TEXT_COLUMN     },
198     };
199
200     /* Skip the token */
201     InfoNextTok ();
202
203     /* Expect the opening curly brace */
204     InfoConsumeLCurly ();
205
206     /* Look for section tokens */
207     while (InfoTok != INFOTOK_RCURLY) {
208
209         /* Convert to special token */
210         InfoSpecialToken (GlobalDefs, ENTRY_COUNT (GlobalDefs), "Global directive");
211
212         /* Look at the token */
213         switch (InfoTok) {
214
215             case INFOTOK_ARGUMENT_COLUMN:
216                 InfoNextTok ();
217                 InfoAssureInt ();
218                 InfoRangeCheck (MIN_ACOL, MAX_ACOL);
219                 ACol = InfoIVal;
220                 InfoNextTok ();
221                 break;
222
223             case INFOTOK_COMMENT_COLUMN:
224                 InfoNextTok ();
225                 InfoAssureInt ();
226                 InfoRangeCheck (MIN_CCOL, MAX_CCOL);
227                 CCol = InfoIVal;
228                 InfoNextTok ();
229                 break;
230
231             case INFOTOK_COMMENTS:
232                 InfoNextTok ();
233                 InfoAssureInt ();
234                 InfoRangeCheck (MIN_COMMENTS, MAX_COMMENTS);
235                 Comments = InfoIVal;
236                 InfoNextTok ();
237                 break;
238
239             case INFOTOK_CPU:
240                 InfoNextTok ();
241                 InfoAssureStr ();
242                 if (CPU != CPU_UNKNOWN) {
243                     InfoError ("CPU already specified");
244                 }
245                 CPU = FindCPU (InfoSVal);
246                 SetOpcTable (CPU);
247                 InfoNextTok ();
248                 break;
249
250             case INFOTOK_HEXOFFS:
251                 InfoNextTok ();
252                 InfoBoolToken ();
253                 switch (InfoTok) {
254                     case INFOTOK_FALSE: UseHexOffs = 0; break;
255                     case INFOTOK_TRUE:  UseHexOffs = 1; break;
256                 }
257                 InfoNextTok ();
258                 break;
259
260             case INFOTOK_INPUTNAME:
261                 InfoNextTok ();
262                 InfoAssureStr ();
263                 if (InFile) {
264                     InfoError ("Input file name already given");
265                 }
266                 InFile = xstrdup (InfoSVal);
267                 InfoNextTok ();
268                 break;
269
270             case INFOTOK_INPUTOFFS:
271                 InfoNextTok ();
272                 InfoAssureInt ();
273                 InputOffs = InfoIVal;
274                 InfoNextTok ();
275                 break;
276
277             case INFOTOK_INPUTSIZE:
278                 InfoNextTok ();
279                 InfoAssureInt ();
280                 InfoRangeCheck (1, 0x10000);
281                 InputSize = InfoIVal;
282                 InfoNextTok ();
283                 break;
284
285             case INFOTOK_LABELBREAK:
286                 InfoNextTok ();
287                 InfoAssureInt ();
288                 InfoRangeCheck (0, UCHAR_MAX);
289                 LBreak = (unsigned char) InfoIVal;
290                 InfoNextTok ();
291                 break;
292
293             case INFOTOK_MNEMONIC_COLUMN:
294                 InfoNextTok ();
295                 InfoAssureInt ();
296                 InfoRangeCheck (MIN_MCOL, MAX_MCOL);
297                 MCol = InfoIVal;
298                 InfoNextTok ();
299                 break;
300
301             case INFOTOK_OUTPUTNAME:
302                 InfoNextTok ();
303                 InfoAssureStr ();
304                 if (OutFile) {
305                     InfoError ("Output file name already given");
306                 }
307                 OutFile = xstrdup (InfoSVal);
308                 InfoNextTok ();
309                 break;
310
311             case INFOTOK_PAGELENGTH:
312                 InfoNextTok ();
313                 InfoAssureInt ();
314                 if (InfoIVal != 0) {
315                     InfoRangeCheck (MIN_PAGE_LEN, MAX_PAGE_LEN);
316                 }
317                 PageLength = InfoIVal;
318                 InfoNextTok ();
319                 break;
320
321             case INFOTOK_STARTADDR:
322                 InfoNextTok ();
323                 InfoAssureInt ();
324                 InfoRangeCheck (0x0000, 0xFFFF);
325                 StartAddr = InfoIVal;
326                 InfoNextTok ();
327                 break;
328
329             case INFOTOK_TEXT_COLUMN:
330                 InfoNextTok ();
331                 InfoAssureInt ();
332                 InfoRangeCheck (MIN_TCOL, MAX_TCOL);
333                 TCol = InfoIVal;
334                 InfoNextTok ();
335                 break;
336
337             default:
338                 Internal ("Unexpected token: %u", InfoTok);
339
340         }
341
342         /* Directive is followed by a semicolon */
343         InfoConsumeSemi ();
344
345     }
346
347     /* Consume the closing brace */
348     InfoConsumeRCurly ();
349 }
350
351
352
353 static void LabelSection (void)
354 /* Parse a label section */
355 {
356     static const IdentTok LabelDefs[] = {
357         {   "COMMENT",  INFOTOK_COMMENT },
358         {   "ADDR",     INFOTOK_ADDR    },
359         {   "NAME",     INFOTOK_NAME    },
360         {   "SIZE",     INFOTOK_SIZE    },
361     };
362
363     /* Locals - initialize to avoid gcc warnings */
364     char* Name    = 0;
365     char* Comment = 0;
366     long Value    = -1;
367     long Size     = -1;
368
369     /* Skip the token */
370     InfoNextTok ();
371
372     /* Expect the opening curly brace */
373     InfoConsumeLCurly ();
374
375     /* Look for section tokens */
376     while (InfoTok != INFOTOK_RCURLY) {
377
378         /* Convert to special token */
379         InfoSpecialToken (LabelDefs, ENTRY_COUNT (LabelDefs), "Label attribute");
380
381         /* Look at the token */
382         switch (InfoTok) {
383
384             case INFOTOK_ADDR:
385                 InfoNextTok ();
386                 if (Value >= 0) {
387                     InfoError ("Value already given");
388                 }
389                 InfoAssureInt ();
390                 InfoRangeCheck (0, 0xFFFF);
391                 Value = InfoIVal;
392                 InfoNextTok ();
393                 break;
394
395             case INFOTOK_COMMENT:
396                 InfoNextTok ();
397                 if (Comment) {
398                     InfoError ("Comment already given");
399                 }
400                 InfoAssureStr ();
401                 if (InfoSVal[0] == '\0') {
402                     InfoError ("Comment may not be empty");
403                 }
404                 Comment = xstrdup (InfoSVal);
405                 InfoNextTok ();
406                 break;
407
408             case INFOTOK_NAME:
409                 InfoNextTok ();
410                 if (Name) {
411                     InfoError ("Name already given");
412                 }
413                 InfoAssureStr ();
414                 Name = xstrdup (InfoSVal);
415                 InfoNextTok ();
416                 break;
417
418             case INFOTOK_SIZE:
419                 InfoNextTok ();
420                 if (Size >= 0) {
421                     InfoError ("Size already given");
422                 }
423                 InfoAssureInt ();
424                 InfoRangeCheck (1, 0x10000);
425                 Size = InfoIVal;
426                 InfoNextTok ();
427                 break;
428
429             default:
430                 Internal ("Unexpected token: %u", InfoTok);
431         }
432
433         /* Directive is followed by a semicolon */
434         InfoConsumeSemi ();
435     }
436
437     /* Did we get the necessary data */
438     if (Name == 0) {
439         InfoError ("Label name is missing");
440     }
441     if (Name[0] == '\0' && Size > 1) {
442         InfoError ("Unnamed labels must not have a size > 1");
443     }
444     if (Value < 0) {
445         InfoError ("Label value is missing");
446     }
447     if (Size < 0) {
448         /* Use default */
449         Size = 1;
450     }
451     if (Value + Size > 0x10000) {
452         InfoError ("Invalid size (address out of range)");
453     }
454     if (HaveLabel ((unsigned) Value)) {
455         InfoError ("Label for address $%04lX already defined", Value);
456     }
457
458     /* Define the label(s) */
459     if (Name[0] == '\0') {
460         /* Size has already beed checked */
461         AddUnnamedLabel (Value);
462     } else {
463         AddExtLabelRange ((unsigned) Value, Name, Size);
464     }
465
466     /* Define the comment */
467     if (Comment) {
468         SetComment (Value, Comment);
469     }
470
471     /* Delete the dynamically allocated memory for Name and Comment */
472     xfree (Name);
473     xfree (Comment);
474
475     /* Consume the closing brace */
476     InfoConsumeRCurly ();
477 }
478
479
480
481 static void RangeSection (void)
482 /* Parse a range section */
483 {
484     static const IdentTok RangeDefs[] = {
485         {   "COMMENT",          INFOTOK_COMMENT },
486         {   "END",              INFOTOK_END     },
487         {   "NAME",             INFOTOK_NAME    },
488         {   "START",            INFOTOK_START   },
489         {   "TYPE",             INFOTOK_TYPE    },
490     };
491
492     static const IdentTok TypeDefs[] = {
493         {   "ADDRTABLE",        INFOTOK_ADDRTAB  },
494         {   "BYTETABLE",        INFOTOK_BYTETAB  },
495         {   "CODE",             INFOTOK_CODE     },
496         {   "DBYTETABLE",       INFOTOK_DBYTETAB },
497         {   "DWORDTABLE",       INFOTOK_DWORDTAB },
498         {   "RTSTABLE",         INFOTOK_RTSTAB   },
499         {   "SKIP",             INFOTOK_SKIP     },
500         {   "TEXTTABLE",        INFOTOK_TEXTTAB  },
501         {   "WORDTABLE",        INFOTOK_WORDTAB  },
502     };
503
504
505     /* Which values did we get? */
506     enum {
507         tNone   = 0x00,
508         tStart  = 0x01,
509         tEnd    = 0x02,
510         tType   = 0x04,
511         tName   = 0x08,
512         tComment= 0x10,
513         tNeeded = (tStart | tEnd | tType)
514     };
515     unsigned Attributes = tNone;
516
517     /* Locals - initialize to avoid gcc warnings */
518     unsigned Start      = 0;
519     unsigned End        = 0;
520     unsigned char Type  = 0;
521     char* Name          = 0;
522     char* Comment       = 0;
523     unsigned MemberSize = 0;
524
525
526     /* Skip the token */
527     InfoNextTok ();
528
529     /* Expect the opening curly brace */
530     InfoConsumeLCurly ();
531
532     /* Look for section tokens */
533     while (InfoTok != INFOTOK_RCURLY) {
534
535         /* Convert to special token */
536         InfoSpecialToken (RangeDefs, ENTRY_COUNT (RangeDefs), "Range attribute");
537
538         /* Look at the token */
539         switch (InfoTok) {
540
541             case INFOTOK_COMMENT:
542                 AddAttr ("COMMENT", &Attributes, tComment);
543                 InfoNextTok ();
544                 InfoAssureStr ();
545                 if (InfoSVal[0] == '\0') {
546                     InfoError ("Comment may not be empty");
547                 }
548                 Comment = xstrdup (InfoSVal);
549                 Attributes |= tComment;
550                 InfoNextTok ();
551                 break;
552
553             case INFOTOK_END:
554                 AddAttr ("END", &Attributes, tEnd);
555                 InfoNextTok ();
556                 InfoAssureInt ();
557                 InfoRangeCheck (0x0000, 0xFFFF);
558                 End = InfoIVal;
559                 InfoNextTok ();
560                 break;
561
562             case INFOTOK_NAME:
563                 AddAttr ("NAME", &Attributes, tName);
564                 InfoNextTok ();
565                 InfoAssureStr ();
566                 if (InfoSVal[0] == '\0') {
567                     InfoError ("Name may not be empty");
568                 }
569                 Name = xstrdup (InfoSVal);
570                 Attributes |= tName;
571                 InfoNextTok ();
572                 break;
573
574             case INFOTOK_START:
575                 AddAttr ("START", &Attributes, tStart);
576                 InfoNextTok ();
577                 InfoAssureInt ();
578                 InfoRangeCheck (0x0000, 0xFFFF);
579                 Start = InfoIVal;
580                 InfoNextTok ();
581                 break;
582
583             case INFOTOK_TYPE:
584                 AddAttr ("TYPE", &Attributes, tType);
585                 InfoNextTok ();
586                 InfoSpecialToken (TypeDefs, ENTRY_COUNT (TypeDefs), "TYPE");
587                 switch (InfoTok) {
588                     case INFOTOK_ADDRTAB:  Type = atAddrTab;  MemberSize = 2; break;
589                     case INFOTOK_BYTETAB:  Type = atByteTab;  MemberSize = 1; break;
590                     case INFOTOK_CODE:     Type = atCode;     MemberSize = 1; break;
591                     case INFOTOK_DBYTETAB: Type = atDByteTab; MemberSize = 2; break;
592                     case INFOTOK_DWORDTAB: Type = atDWordTab; MemberSize = 4; break;
593                     case INFOTOK_RTSTAB:   Type = atRtsTab;   MemberSize = 2; break;
594                     case INFOTOK_SKIP:     Type = atSkip;     MemberSize = 1; break;
595                     case INFOTOK_TEXTTAB:  Type = atTextTab;  MemberSize = 1; break;
596                     case INFOTOK_WORDTAB:  Type = atWordTab;  MemberSize = 2; break;
597                 }
598                 InfoNextTok ();
599                 break;
600
601             default:
602                 Internal ("Unexpected token: %u", InfoTok);
603         }
604
605         /* Directive is followed by a semicolon */
606         InfoConsumeSemi ();
607
608     }
609
610     /* Did we get all required values? */
611     if ((Attributes & tNeeded) != tNeeded) {
612         InfoError ("Required values missing from this section");
613     }
614
615     /* Start must be less than end */
616     if (Start > End) {
617         InfoError ("Start value must not be greater than end value");
618     }
619
620     /* Check the granularity */
621     if (((End - Start + 1) % MemberSize) != 0) {
622         InfoError ("Type of range needs a granularity of %u", MemberSize);
623     }
624
625     /* Set the range */
626     MarkRange (Start, End, Type);
627
628     /* Do we have a label? */
629     if (Attributes & tName) {
630
631         /* Define a label for the table */
632         AddExtLabel (Start, Name);
633
634         /* Set the comment if we have one */
635         if (Comment) {
636             SetComment (Start, Comment);
637         }
638
639         /* Delete name and comment */
640         xfree (Name);
641         xfree (Comment);
642     }
643
644     /* Consume the closing brace */
645     InfoConsumeRCurly ();
646 }
647
648
649
650 static void SegmentSection (void)
651 /* Parse a segment section */
652 {
653     static const IdentTok LabelDefs[] = {
654         {   "END",      INFOTOK_END     },
655         {   "NAME",     INFOTOK_NAME    },
656         {   "START",    INFOTOK_START   },
657     };
658
659     /* Locals - initialize to avoid gcc warnings */
660     long End    = -1;
661     long Start  = -1;
662     char* Name  = 0;
663
664     /* Skip the token */
665     InfoNextTok ();
666
667     /* Expect the opening curly brace */
668     InfoConsumeLCurly ();
669
670     /* Look for section tokens */
671     while (InfoTok != INFOTOK_RCURLY) {
672
673         /* Convert to special token */
674         InfoSpecialToken (LabelDefs, ENTRY_COUNT (LabelDefs), "Segment attribute");
675
676         /* Look at the token */
677         switch (InfoTok) {
678
679             case INFOTOK_END:
680                 InfoNextTok ();
681                 if (End >= 0) {
682                     InfoError ("Value already given");
683                 }
684                 InfoAssureInt ();
685                 InfoRangeCheck (0, 0xFFFF);
686                 End = InfoIVal;
687                 InfoNextTok ();
688                 break;
689
690             case INFOTOK_NAME:
691                 InfoNextTok ();
692                 if (Name) {
693                     InfoError ("Name already given");
694                 }
695                 InfoAssureStr ();
696                 Name = xstrdup (InfoSVal);
697                 InfoNextTok ();
698                 break;
699
700             case INFOTOK_START:
701                 InfoNextTok ();
702                 if (Start >= 0) {
703                     InfoError ("Value already given");
704                 }
705                 InfoAssureInt ();
706                 InfoRangeCheck (0, 0xFFFF);
707                 Start = InfoIVal;
708                 InfoNextTok ();
709                 break;
710
711             default:
712                 Internal ("Unexpected token: %u", InfoTok);
713         }
714
715         /* Directive is followed by a semicolon */
716         InfoConsumeSemi ();
717     }
718
719     /* Did we get the necessary data, and is it correct? */
720     if (Name == 0 || Name[0] == '\0') {
721         InfoError ("Segment name is missing");
722     }
723     if (End < 0) {
724         InfoError ("End address is missing");
725     }
726     if (Start < 0) {
727         InfoError ("Start address is missing");
728     }
729     if (Start == End) {
730         InfoError ("Segment is empty");
731     }
732     if (Start > End) {
733         InfoError ("Start address of segment is greater than end address");
734     }
735
736     /* Check that segments do not overlap */
737     if (SegmentDefined ((unsigned) Start, (unsigned) End)) {
738         InfoError ("Segments cannot overlap");
739     }
740
741     /* Remember the segment data */
742     AddAbsSegment ((unsigned) Start, (unsigned) End, Name);
743
744     /* Delete the dynamically allocated memory for Name */
745     xfree (Name);
746
747     /* Consume the closing brace */
748     InfoConsumeRCurly ();
749 }
750
751
752
753 static void InfoParse (void)
754 /* Parse the config file */
755 {
756     static const IdentTok Globals[] = {
757         {   "ASMINC",   INFOTOK_ASMINC  },
758         {   "GLOBAL",   INFOTOK_GLOBAL  },
759         {   "LABEL",    INFOTOK_LABEL   },
760         {   "RANGE",    INFOTOK_RANGE   },
761         {   "SEGMENT",  INFOTOK_SEGMENT },
762     };
763
764     while (InfoTok != INFOTOK_EOF) {
765
766         /* Convert an identifier into a token */
767         InfoSpecialToken (Globals, ENTRY_COUNT (Globals), "Config directive");
768
769         /* Check the token */
770         switch (InfoTok) {
771
772             case INFOTOK_ASMINC:
773                 AsmIncSection ();
774                 break;
775
776             case INFOTOK_GLOBAL:
777                 GlobalSection ();
778                 break;
779
780             case INFOTOK_LABEL:
781                 LabelSection ();
782                 break;
783
784             case INFOTOK_RANGE:
785                 RangeSection ();
786                 break;
787
788             case INFOTOK_SEGMENT:
789                 SegmentSection ();
790                 break;
791
792             default:
793                 Internal ("Unexpected token: %u", InfoTok);
794         }
795
796         /* Semicolon expected */
797         InfoConsumeSemi ();
798     }
799 }
800
801
802
803 void ReadInfoFile (void)
804 /* Read the info file */
805 {
806     /* Check if we have a info file given */
807     if (InfoAvail()) {
808         /* Open the config file */
809         InfoOpenInput ();
810
811         /* Parse the config file */
812         InfoParse ();
813
814         /* Close the file */
815         InfoCloseInput ();
816     }
817 }
818
819
820
821
822
823