1 /*****************************************************************************/
5 /* Target configuration file for the ld65 linker */
9 /* (C) 1998-2000 Ullrich von Bassewitz */
11 /* D-70597 Stuttgart */
12 /* EMail: uz@musoftware.de */
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. */
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: */
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 */
32 /*****************************************************************************/
59 /*****************************************************************************/
61 /*****************************************************************************/
66 static File* FileList; /* Single linked list */
67 static unsigned FileCount; /* Number of entries in the list */
72 static Memory* MemoryList; /* Single linked list */
73 static Memory* MemoryLast; /* Last element in list */
74 static unsigned MemoryCount; /* Number of entries in the list */
76 /* Memory attributes */
77 #define MA_START 0x0001
78 #define MA_SIZE 0x0002
79 #define MA_TYPE 0x0004
80 #define MA_FILE 0x0008
81 #define MA_DEFINE 0x0010
82 #define MA_FILL 0x0020
83 #define MA_FILLVAL 0x0040
88 SegDesc* SegDescList; /* Single linked list */
89 unsigned SegDescCount; /* Number of entries in list */
91 /* Segment attributes */
92 #define SA_TYPE 0x0001
93 #define SA_LOAD 0x0002
95 #define SA_ALIGN 0x0008
96 #define SA_DEFINE 0x0010
97 #define SA_OFFSET 0x0020
98 #define SA_START 0x0040
102 /* Descriptor holding information about the binary formats */
103 static BinDesc* BinFmtDesc = 0;
104 static O65Desc* O65FmtDesc = 0;
106 /* Attributes for the o65 format */
107 static unsigned O65Attr = 0;
109 #define OA_TYPE 0x0002
110 #define OA_VERSION 0x0004
111 #define OA_OSVERSION 0x0008
112 #define OA_TEXT 0x0010
113 #define OA_DATA 0x0020
114 #define OA_BSS 0x0040
119 /*****************************************************************************/
121 /*****************************************************************************/
125 static File* NewFile (const char* Name);
126 /* Create a new file descriptor and insert it into the list */
130 /*****************************************************************************/
131 /* List management */
132 /*****************************************************************************/
136 static File* FindFile (const char* Name)
137 /* Find a file with a given name. */
141 if (strcmp (F->Name, Name) == 0) {
151 static File* GetFile (const char* Name)
152 /* Get a file entry with the given name. Create a new one if needed. */
154 File* F = FindFile (Name);
156 /* Create a new one */
164 static void FileInsert (File* F, Memory* M)
165 /* Insert the memory area into the files list */
168 if (F->MemList == 0) {
172 F->MemLast->FNext = M;
179 static Memory* CfgFindMemory (const char* Name)
180 /* Find the memory are with the given name. Return NULL if not found */
182 Memory* M = MemoryList;
184 if (strcmp (M->Name, Name) == 0) {
194 static Memory* CfgGetMemory (const char* Name)
195 /* Find the memory are with the given name. Print an error on an invalid name */
197 Memory* M = CfgFindMemory (Name);
199 CfgError ("Invalid memory area `%s'", Name);
206 static SegDesc* CfgFindSegDesc (const char* Name)
207 /* Find the segment descriptor with the given name, return NULL if not found. */
209 SegDesc* S = SegDescList;
211 if (strcmp (S->Name, Name) == 0) {
224 static void SegDescInsert (SegDesc* S)
225 /* Insert a segment descriptor into the list of segment descriptors */
227 /* Insert the struct into the list */
228 S->Next = SegDescList;
235 static void MemoryInsert (Memory* M, SegDesc* S)
236 /* Insert the segment descriptor into the memory area list */
238 /* Create a new node for the entry */
239 MemListNode* N = xmalloc (sizeof (MemListNode));
243 if (M->SegLast == 0) {
247 M->SegLast->Next = N;
254 /*****************************************************************************/
255 /* Constructors/Destructors */
256 /*****************************************************************************/
260 static File* NewFile (const char* Name)
261 /* Create a new file descriptor and insert it into the list */
263 /* Get the length of the name */
264 unsigned Len = strlen (Name);
266 /* Allocate memory */
267 File* F = xmalloc (sizeof (File) + Len);
269 /* Initialize the fields */
271 F->Format = BINFMT_DEFAULT;
274 memcpy (F->Name, Name, Len);
275 F->Name [Len] = '\0';
277 /* Insert the struct into the list */
282 /* ...and return it */
288 static Memory* NewMemory (const char* Name)
289 /* Create a new memory section and insert it into the list */
291 /* Get the length of the name */
292 unsigned Len = strlen (Name);
294 /* Check for duplicate names */
295 Memory* M = CfgFindMemory (Name);
297 CfgError ("Memory area `%s' defined twice", Name);
300 /* Allocate memory */
301 M = xmalloc (sizeof (Memory) + Len);
303 /* Initialize the fields */
315 memcpy (M->Name, Name, Len);
316 M->Name [Len] = '\0';
318 /* Insert the struct into the list */
319 if (MemoryLast == 0) {
323 MemoryLast->Next = M;
328 /* ...and return it */
334 static SegDesc* NewSegDesc (const char* Name)
335 /* Create a segment descriptor */
339 /* Get the length of the name */
340 unsigned Len = strlen (Name);
342 /* Check for duplicate names */
343 SegDesc* S = CfgFindSegDesc (Name);
345 CfgError ("Segment `%s' defined twice", Name);
348 /* Verify that the given segment does really exist */
349 Seg = SegFind (Name);
351 CfgWarning ("Segment `%s' does not exist", Name);
354 /* Allocate memory */
355 S = xmalloc (sizeof (SegDesc) + Len);
357 /* Initialize the fields */
363 memcpy (S->Name, Name, Len);
364 S->Name [Len] = '\0';
366 /* ...and return it */
372 static void FreeSegDesc (SegDesc* S)
373 /* Free a segment descriptor */
380 /*****************************************************************************/
382 /*****************************************************************************/
386 static void FlagAttr (unsigned* Flags, unsigned Mask, const char* Name)
387 /* Check if the item is already defined. Print an error if so. If not, set
388 * the marker that we have a definition now.
392 CfgError ("%s is already defined", Name);
399 static void AttrCheck (unsigned Attr, unsigned Mask, const char* Name)
400 /* Check that a mandatory attribute was given */
402 if ((Attr & Mask) == 0) {
403 CfgError ("%s attribute is missing", Name);
409 static void ParseMemory (void)
410 /* Parse a MEMORY section */
412 static const IdentTok Attributes [] = {
413 { "START", CFGTOK_START },
414 { "SIZE", CFGTOK_SIZE },
415 { "TYPE", CFGTOK_TYPE },
416 { "FILE", CFGTOK_FILE },
417 { "DEFINE", CFGTOK_DEFINE },
418 { "FILL", CFGTOK_FILL },
419 { "FILLVAL", CFGTOK_FILLVAL },
421 static const IdentTok Types [] = {
426 while (CfgTok == CFGTOK_IDENT) {
428 /* Create a new entry on the heap */
429 Memory* M = NewMemory (CfgSVal);
431 /* Skip the name and the following colon */
435 /* Read the attributes */
436 while (CfgTok == CFGTOK_IDENT) {
438 /* Map the identifier to a token */
440 CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Attribute");
443 /* An optional assignment follows */
445 CfgOptionalAssign ();
447 /* Check which attribute was given */
451 FlagAttr (&M->Attr, MA_START, "START");
457 FlagAttr (&M->Attr, MA_SIZE, "SIZE");
463 FlagAttr (&M->Attr, MA_TYPE, "TYPE");
464 CfgSpecialToken (Types, ENTRY_COUNT (Types), "Type");
465 if (CfgTok == CFGTOK_RO) {
471 FlagAttr (&M->Attr, MA_FILE, "FILE");
473 /* Get the file entry and insert the memory area */
474 FileInsert (GetFile (CfgSVal), M);
478 FlagAttr (&M->Attr, MA_DEFINE, "DEFINE");
479 /* Map the token to a boolean */
481 if (CfgTok == CFGTOK_TRUE) {
482 M->Flags |= MF_DEFINE;
487 FlagAttr (&M->Attr, MA_FILL, "FILL");
488 /* Map the token to a boolean */
490 if (CfgTok == CFGTOK_TRUE) {
496 FlagAttr (&M->Attr, MA_FILLVAL, "FILLVAL");
498 CfgRangeCheck (0, 0xFF);
499 M->FillVal = (unsigned char) CfgIVal;
503 FAIL ("Unexpected attribute token");
507 /* Skip the attribute value and an optional comma */
512 /* Skip the semicolon */
515 /* Check for mandatory parameters */
516 AttrCheck (M->Attr, MA_START, "START");
517 AttrCheck (M->Attr, MA_SIZE, "SIZE");
519 /* If we don't have a file name for output given, use the default
522 if ((M->Attr & MA_FILE) == 0) {
523 FileInsert (GetFile (OutputName), M);
530 static void ParseFiles (void)
531 /* Parse a FILES section */
533 static const IdentTok Attributes [] = {
534 { "FORMAT", CFGTOK_FORMAT },
536 static const IdentTok Formats [] = {
537 { "O65", CFGTOK_O65 },
538 { "BIN", CFGTOK_BIN },
539 { "BINARY", CFGTOK_BIN },
543 /* Parse all files */
544 while (CfgTok != CFGTOK_RCURLY) {
548 /* We expect a string value here */
551 /* Search for the file, it must exist */
552 F = FindFile (CfgSVal);
554 CfgError ("No such file: `%s'", CfgSVal);
557 /* Skip the token and the following colon */
561 /* Read the attributes */
562 while (CfgTok == CFGTOK_IDENT) {
564 /* Map the identifier to a token */
566 CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Attribute");
569 /* An optional assignment follows */
571 CfgOptionalAssign ();
573 /* Check which attribute was given */
577 if (F->Format != BINFMT_DEFAULT) {
578 /* We've set the format already! */
579 Error ("Cannot set a file format twice");
581 /* Read the format token */
582 CfgSpecialToken (Formats, ENTRY_COUNT (Formats), "Format");
586 F->Format = BINFMT_BINARY;
590 F->Format = BINFMT_O65;
594 Error ("Unexpected format token");
599 FAIL ("Unexpected attribute token");
603 /* Skip the attribute value and an optional comma */
608 /* Skip the semicolon */
616 static void ParseSegments (void)
617 /* Parse a SEGMENTS section */
619 static const IdentTok Attributes [] = {
620 { "LOAD", CFGTOK_LOAD },
621 { "RUN", CFGTOK_RUN },
622 { "TYPE", CFGTOK_TYPE },
623 { "ALIGN", CFGTOK_ALIGN },
624 { "DEFINE", CFGTOK_DEFINE },
625 { "OFFSET", CFGTOK_OFFSET },
626 { "START", CFGTOK_START },
628 static const IdentTok Types [] = {
631 { "BSS", CFGTOK_BSS },
633 { "WP", CFGTOK_WPROT },
634 { "WPROT", CFGTOK_WPROT },
639 while (CfgTok == CFGTOK_IDENT) {
643 /* Create a new entry on the heap */
644 S = NewSegDesc (CfgSVal);
646 /* Skip the name and the following colon */
650 /* Read the attributes */
651 while (CfgTok == CFGTOK_IDENT) {
653 /* Map the identifier to a token */
655 CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Attribute");
658 /* An optional assignment follows */
660 CfgOptionalAssign ();
662 /* Check which attribute was given */
666 FlagAttr (&S->Attr, SA_LOAD, "LOAD");
667 S->Load = CfgGetMemory (CfgSVal);
671 FlagAttr (&S->Attr, SA_RUN, "RUN");
672 S->Run = CfgGetMemory (CfgSVal);
676 FlagAttr (&S->Attr, SA_TYPE, "TYPE");
677 CfgSpecialToken (Types, ENTRY_COUNT (Types), "Type");
679 case CFGTOK_RO: S->Flags |= SF_RO; break;
680 case CFGTOK_RW: /* Default */ break;
681 case CFGTOK_BSS: S->Flags |= SF_BSS; break;
682 case CFGTOK_ZP: S->Flags |= (SF_BSS | SF_ZP); break;
683 case CFGTOK_WPROT: S->Flags |= (SF_RO | SF_WPROT); break;
684 default: Internal ("Unexpected token: %d", CfgTok);
690 FlagAttr (&S->Attr, SA_ALIGN, "ALIGN");
691 CfgRangeCheck (1, 0x10000);
692 S->Align = BitFind (CfgIVal);
693 if ((0x01UL << S->Align) != CfgIVal) {
694 CfgError ("Alignment must be a power of 2");
696 S->Flags |= SF_ALIGN;
700 FlagAttr (&S->Attr, SA_DEFINE, "DEFINE");
701 /* Map the token to a boolean */
703 if (CfgTok == CFGTOK_TRUE) {
704 S->Flags |= SF_DEFINE;
710 FlagAttr (&S->Attr, SA_OFFSET, "OFFSET");
711 CfgRangeCheck (1, 0x1000000);
713 S->Flags |= SF_OFFSET;
718 FlagAttr (&S->Attr, SA_START, "START");
719 CfgRangeCheck (1, 0x1000000);
721 S->Flags |= SF_START;
725 FAIL ("Unexpected attribute token");
729 /* Skip the attribute value and an optional comma */
734 /* Skip the semicolon */
737 /* Check for mandatory parameters */
738 AttrCheck (S->Attr, SA_LOAD, "LOAD");
740 /* Set defaults for stuff not given */
741 if ((S->Attr & SA_RUN) == 0) {
745 /* Both attributes given */
746 S->Flags |= SF_LOAD_AND_RUN;
748 if ((S->Attr & SA_ALIGN) == 0) {
753 /* If the segment is marked as BSS style, check that there's no
754 * initialized data in the segment.
756 if ((S->Flags & SF_BSS) != 0 && !IsBSSType (S->Seg)) {
757 Warning ("%s(%u): Segment with type `bss' contains initialized data",
758 CfgGetName (), CfgErrorLine);
761 /* Don't allow read/write data to be put into a readonly area */
762 if ((S->Flags & SF_RO) == 0) {
763 if (S->Run->Flags & MF_RO) {
764 CfgError ("Cannot put r/w segment `%s' in r/o memory area `%s'",
765 S->Name, S->Run->Name);
769 /* Only one of ALIGN, START and OFFSET may be used */
770 Count = ((S->Flags & SF_ALIGN) != 0) +
771 ((S->Flags & SF_OFFSET) != 0) +
772 ((S->Flags & SF_START) != 0);
774 CfgError ("Only one of ALIGN, START, OFFSET may be used");
777 /* If this segment does exist in any of the object files, insert the
778 * descriptor into the list of segment descriptors. Otherwise discard
779 * it silently, because the segment pointer in the descriptor is
783 /* Insert the descriptor into the list of all descriptors */
785 /* Insert the segment into the memory area list */
786 MemoryInsert (S->Run, S);
787 if ((S->Flags & SF_LOAD_AND_RUN) != 0) {
788 /* We have a separate RUN area given */
789 MemoryInsert (S->Load, S);
792 /* Segment does not exist, discard the descriptor */
800 static void ParseO65 (void)
801 /* Parse the o65 format section */
803 static const IdentTok Attributes [] = {
804 { "EXPORT", CFGTOK_EXPORT },
805 { "IMPORT", CFGTOK_IMPORT },
806 { "TYPE", CFGTOK_TYPE },
809 static const IdentTok Types [] = {
810 { "SMALL", CFGTOK_SMALL },
811 { "LARGE", CFGTOK_LARGE },
813 static const IdentTok OperatingSystems [] = {
814 { "LUNIX", CFGTOK_LUNIX },
815 { "OSA65", CFGTOK_OSA65 },
818 while (CfgTok == CFGTOK_IDENT) {
820 /* Map the identifier to a token */
822 CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Attribute");
825 /* An optional assignment follows */
827 CfgOptionalAssign ();
829 /* Check which attribute was given */
833 /* We expect an identifier */
835 /* Check if we have this symbol defined already. The entry
836 * routine will check this also, but we get a more verbose
837 * error message when checking it here.
839 if (O65GetExport (O65FmtDesc, CfgSVal) != 0) {
840 CfgError ("Duplicate exported symbol: `%s'", CfgSVal);
842 /* Insert the symbol into the table */
843 O65SetExport (O65FmtDesc, CfgSVal);
847 /* We expect an identifier */
849 /* Check if we have this symbol defined already. The entry
850 * routine will check this also, but we get a more verbose
851 * error message when checking it here.
853 if (O65GetImport (O65FmtDesc, CfgSVal) != 0) {
854 CfgError ("Duplicate imported symbol: `%s'", CfgSVal);
856 /* Insert the symbol into the table */
857 O65SetImport (O65FmtDesc, CfgSVal);
861 /* Cannot have this attribute twice */
862 FlagAttr (&O65Attr, OA_TYPE, "TYPE");
863 /* Get the type of the executable */
864 CfgSpecialToken (Types, ENTRY_COUNT (Types), "Type");
868 /* Default, nothing to do */
872 O65SetLargeModel (O65FmtDesc);
876 CfgError ("Unexpected type token");
881 /* Cannot use this attribute twice */
882 FlagAttr (&O65Attr, OA_OS, "OS");
883 /* Get the operating system */
884 CfgSpecialToken (OperatingSystems, ENTRY_COUNT (OperatingSystems), "OS type");
888 O65SetOS (O65FmtDesc, O65OS_LUNIX);
892 O65SetOS (O65FmtDesc, O65OS_OSA65);
896 CfgError ("Unexpected OS token");
901 FAIL ("Unexpected attribute token");
905 /* Skip the attribute value and an optional comma */
913 static void ParseFormats (void)
914 /* Parse a target format section */
916 static const IdentTok Formats [] = {
917 { "O65", CFGTOK_O65 },
918 { "BIN", CFGTOK_BIN },
919 { "BINARY", CFGTOK_BIN },
922 while (CfgTok == CFGTOK_IDENT) {
924 /* Map the identifier to a token */
926 CfgSpecialToken (Formats, ENTRY_COUNT (Formats), "Format");
929 /* Skip the name and the following colon */
933 /* Parse the format options */
941 /* No attribibutes available */
945 Error ("Unexpected format token");
948 /* Skip the semicolon */
955 static void ParseConDes (void)
956 /* Parse the CONDES feature */
958 static const IdentTok Attributes [] = {
959 { "SEGMENT", CFGTOK_SEGMENT },
960 { "LABEL", CFGTOK_LABEL },
961 { "COUNT", CFGTOK_COUNT },
962 { "TYPE", CFGTOK_TYPE },
963 { "ORDER", CFGTOK_ORDER },
966 static const IdentTok Types [] = {
967 { "CONSTRUCTOR", CFGTOK_CONSTRUCTOR },
968 { "DESTRUCTOR", CFGTOK_DESTRUCTOR },
971 static const IdentTok Orders [] = {
972 { "DECREASING", CFGTOK_DECREASING },
973 { "INCREASING", CFGTOK_INCREASING },
976 /* Attribute values. */
977 char SegName[sizeof (CfgSVal)];
978 char Label[sizeof (CfgSVal)];
979 char Count[sizeof (CfgSVal)];
980 /* Initialize to avoid gcc warnings: */
982 ConDesOrder Order = cdIncreasing;
984 /* Bitmask to remember the attributes we got already */
993 unsigned AttrFlags = atNone;
995 /* Parse the attributes */
998 /* Map the identifier to a token */
1000 CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Attribute");
1003 /* An optional assignment follows */
1005 CfgOptionalAssign ();
1007 /* Check which attribute was given */
1010 case CFGTOK_SEGMENT:
1011 /* Don't allow this twice */
1012 FlagAttr (&AttrFlags, atSegName, "SEGMENT");
1013 /* We expect an identifier */
1015 /* Remember the value for later */
1016 strcpy (SegName, CfgSVal);
1020 /* Don't allow this twice */
1021 FlagAttr (&AttrFlags, atLabel, "LABEL");
1022 /* We expect an identifier */
1024 /* Remember the value for later */
1025 strcpy (Label, CfgSVal);
1029 /* Don't allow this twice */
1030 FlagAttr (&AttrFlags, atCount, "COUNT");
1031 /* We expect an identifier */
1033 /* Remember the value for later */
1034 strcpy (Count, CfgSVal);
1038 /* Don't allow this twice */
1039 FlagAttr (&AttrFlags, atType, "TYPE");
1040 /* The type may be given as id or numerical */
1041 if (CfgTok == CFGTOK_INTCON) {
1042 CfgRangeCheck (CD_TYPE_MIN, CD_TYPE_MAX);
1043 Type = (int) CfgIVal;
1045 CfgSpecialToken (Types, ENTRY_COUNT (Types), "Type");
1047 case CFGTOK_CONSTRUCTOR: Type = CD_TYPE_CON; break;
1048 case CFGTOK_DESTRUCTOR: Type = CD_TYPE_DES; break;
1049 default: FAIL ("Unexpected type token");
1055 /* Don't allow this twice */
1056 FlagAttr (&AttrFlags, atOrder, "ORDER");
1057 CfgSpecialToken (Orders, ENTRY_COUNT (Orders), "Order");
1059 case CFGTOK_DECREASING: Order = cdDecreasing; break;
1060 case CFGTOK_INCREASING: Order = cdIncreasing; break;
1061 default: FAIL ("Unexpected order token");
1066 FAIL ("Unexpected attribute token");
1070 /* Skip the attribute value */
1073 /* Semicolon ends the ConDes decl, otherwise accept an optional comma */
1074 if (CfgTok == CFGTOK_SEMI) {
1076 } else if (CfgTok == CFGTOK_COMMA) {
1081 /* Check if we have all mandatory attributes */
1082 AttrCheck (AttrFlags, atSegName, "SEGMENT");
1083 AttrCheck (AttrFlags, atLabel, "LABEL");
1084 AttrCheck (AttrFlags, atType, "TYPE");
1086 /* Check if the condes has already attributes defined */
1087 if (ConDesHasSegName(Type) || ConDesHasLabel(Type)) {
1088 CfgError ("CONDES attributes for type %d are already defined", Type);
1091 /* Define the attributes */
1092 ConDesSetSegName (Type, SegName);
1093 ConDesSetLabel (Type, Label);
1094 if (AttrFlags & atCount) {
1095 ConDesSetCountSym (Type, Count);
1097 if (AttrFlags & atOrder) {
1098 ConDesSetOrder (Type, Order);
1104 static void ParseFeatures (void)
1105 /* Parse a features section */
1107 static const IdentTok Features [] = {
1108 { "CONDES", CFGTOK_CONDES },
1111 while (CfgTok == CFGTOK_IDENT) {
1113 /* Map the identifier to a token */
1114 cfgtok_t FeatureTok;
1115 CfgSpecialToken (Features, ENTRY_COUNT (Features), "Feature");
1116 FeatureTok = CfgTok;
1118 /* Skip the name and the following colon */
1122 /* Parse the format options */
1123 switch (FeatureTok) {
1130 Error ("Unexpected feature token");
1133 /* Skip the semicolon */
1140 static void ParseConfig (void)
1141 /* Parse the config file */
1143 static const IdentTok BlockNames [] = {
1144 { "MEMORY", CFGTOK_MEMORY },
1145 { "FILES", CFGTOK_FILES },
1146 { "SEGMENTS", CFGTOK_SEGMENTS },
1147 { "FORMATS", CFGTOK_FORMATS },
1148 { "FEATURES", CFGTOK_FEATURES },
1154 /* Read the block ident */
1155 CfgSpecialToken (BlockNames, ENTRY_COUNT (BlockNames), "Block identifier");
1159 /* Expected a curly brace */
1160 CfgConsume (CFGTOK_LCURLY, "`{' expected");
1162 /* Read the block */
1173 case CFGTOK_SEGMENTS:
1177 case CFGTOK_FORMATS:
1181 case CFGTOK_FEATURES:
1186 FAIL ("Unexpected block token");
1190 /* Skip closing brace */
1191 CfgConsume (CFGTOK_RCURLY, "`}' expected");
1193 } while (CfgTok != CFGTOK_EOF);
1199 /* Read the configuration */
1201 /* Create the descriptors for the binary formats */
1202 BinFmtDesc = NewBinDesc ();
1203 O65FmtDesc = NewO65Desc ();
1205 /* If we have a config name given, open the file, otherwise we will read
1210 /* Parse the file */
1213 /* Close the input file */
1219 static void CreateRunDefines (Memory* M, SegDesc* S, unsigned long Addr)
1220 /* Create the defines for a RUN segment */
1224 sprintf (Buf, "__%s_RUN__", S->Name);
1225 CreateMemExport (Buf, M, Addr - M->Start);
1226 sprintf (Buf, "__%s_SIZE__", S->Name);
1227 CreateConstExport (Buf, S->Seg->Size);
1228 S->Flags |= SF_RUN_DEF;
1233 static void CreateLoadDefines (Memory* M, SegDesc* S, unsigned long Addr)
1234 /* Create the defines for a LOAD segment */
1238 sprintf (Buf, "__%s_LOAD__", S->Name);
1239 CreateMemExport (Buf, M, Addr - M->Start);
1240 S->Flags |= SF_LOAD_DEF;
1245 void CfgAssignSegments (void)
1246 /* Assign segments, define linker symbols where requested */
1248 /* Walk through each of the memory sections. Add up the sizes and check
1249 * for an overflow of the section. Assign the start addresses of the
1250 * segments while doing this.
1252 Memory* M = MemoryList;
1255 /* Get the start address of this memory area */
1256 unsigned long Addr = M->Start;
1258 /* Walk through the segments in this memory area */
1259 MemListNode* N = M->SegList;
1262 /* Get the segment from the node */
1263 SegDesc* S = N->Seg;
1265 /* Handle ALIGN and OFFSET/START */
1266 if (S->Flags & SF_ALIGN) {
1267 /* Align the address */
1268 unsigned long Val = (0x01UL << S->Align) - 1;
1269 Addr = (Addr + Val) & ~Val;
1270 } else if (S->Flags & (SF_OFFSET | SF_START)) {
1271 /* Give the segment a fixed starting address */
1272 unsigned long NewAddr = S->Addr;
1273 if (S->Flags & SF_OFFSET) {
1274 /* An offset was given, no address, make an address */
1275 NewAddr += M->Start;
1277 if (Addr > NewAddr) {
1278 /* Offset already too large */
1279 if (S->Flags & SF_OFFSET) {
1280 Error ("Offset too small in `%s', segment `%s'",
1283 Error ("Start address too low in `%s', segment `%s'",
1290 /* If this is the run area, set the start address of this segment */
1295 /* Increment the fill level of the memory area and check for an
1298 M->FillLevel = Addr + S->Seg->Size - M->Start;
1299 if (M->FillLevel > M->Size) {
1300 Error ("Memory area overflow in `%s', segment `%s' (%lu bytes)",
1301 M->Name, S->Name, M->FillLevel - M->Size);
1304 /* If requested, define symbols for the start and size of the
1307 if (S->Flags & SF_DEFINE) {
1308 if ((S->Flags & SF_LOAD_AND_RUN) && S->Run == S->Load) {
1309 /* RUN and LOAD given and in one memory area.
1310 * Be careful: We will encounter this code twice, the
1311 * first time when walking the RUN list, second time when
1312 * walking the LOAD list. Be sure to define only the
1313 * relevant symbols on each walk.
1316 if ((S->Flags & SF_LOAD_DEF) == 0) {
1317 CreateLoadDefines (M, S, Addr);
1319 CHECK ((S->Flags & SF_RUN_DEF) == 0);
1320 CreateRunDefines (M, S, Addr);
1324 /* RUN and LOAD in different memory areas, or RUN not
1325 * given, so RUN defaults to LOAD. In the latter case, we
1326 * have only one copy of the segment in the area.
1329 CreateRunDefines (M, S, Addr);
1332 CreateLoadDefines (M, S, Addr);
1337 /* Calculate the new address */
1338 Addr += S->Seg->Size;
1344 /* If requested, define symbols for start and size of the memory area */
1345 if (M->Flags & MF_DEFINE) {
1347 sprintf (Buf, "__%s_START__", M->Name);
1348 CreateMemExport (Buf, M, 0);
1349 sprintf (Buf, "__%s_SIZE__", M->Name);
1350 CreateConstExport (Buf, M->Size);
1351 sprintf (Buf, "__%s_LAST__", M->Name);
1352 CreateConstExport (Buf, M->FillLevel);
1355 /* Next memory area */
1362 void CfgWriteTarget (void)
1363 /* Write the target file(s) */
1367 /* Walk through the files list */
1370 /* We don't need to look at files with no memory areas */
1373 /* Is there an output file? */
1374 if (strlen (F->Name) > 0) {
1376 /* Assign a proper binary format */
1377 if (F->Format == BINFMT_DEFAULT) {
1378 F->Format = DefaultBinFmt;
1381 /* Call the apropriate routine for the binary format */
1382 switch (F->Format) {
1385 BinWriteTarget (BinFmtDesc, F);
1389 O65WriteTarget (O65FmtDesc, F);
1393 Internal ("Invalid binary format: %u", F->Format);
1399 /* No output file. Walk through the list and mark all segments
1400 * loading into these memory areas in this file as dumped.
1409 printf ("Skipping `%s'...\n", M->Name);
1412 /* Walk throught the segments */
1415 if (N->Seg->Load == M) {
1416 /* Load area - mark the segment as dumped */
1417 N->Seg->Seg->Dumped = 1;
1420 /* Next segment node */
1423 /* Next memory area */