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