]> git.sur5r.net Git - cc65/blobdiff - src/da65/infofile.c
Started to add support for segments.
[cc65] / src / da65 / infofile.c
index 3491f15bde4306fb4040fc3eb6ee09eee7ecb440..4a96f700dc755fb58d1ba0f6fdccf8e342f67724 100644 (file)
@@ -6,8 +6,8 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 2000-2005 Ullrich von Bassewitz                                       */
-/*               Römerstrasse 52                                             */
+/* (C) 2000-2007 Ullrich von Bassewitz                                       */
+/*               Roemerstrasse 52                                            */
 /*               D-70794 Filderstadt                                         */
 /* EMail:        uz@cc65.org                                                 */
 /*                                                                           */
@@ -58,6 +58,7 @@
 #include "labels.h"
 #include "opctable.h"
 #include "scanner.h"
+#include "segment.h"
 
 
 
@@ -79,6 +80,99 @@ static void AddAttr (const char* Name, unsigned* Set, unsigned Attr)
 
 
 
+static void AsmIncSection (void)
+/* Parse a asminc section */
+{
+    static const IdentTok LabelDefs[] = {
+        {   "COMMENTSTART",     INFOTOK_COMMENTSTART    },
+               {   "FILE",             INFOTOK_FILE            },                     
+        {   "IGNOREUNKNOWN",    INFOTOK_IGNOREUNKNOWN   },
+    };
+
+    /* Locals - initialize to avoid gcc warnings */
+    char* Name = 0;
+    int CommentStart = EOF;
+    int IgnoreUnknown = -1;
+
+    /* Skip the token */
+    InfoNextTok ();
+
+    /* Expect the opening curly brace */
+    InfoConsumeLCurly ();
+
+    /* Look for section tokens */
+    while (InfoTok != INFOTOK_RCURLY) {
+
+       /* Convert to special token */
+               InfoSpecialToken (LabelDefs, ENTRY_COUNT (LabelDefs), "Asminc directive");
+
+       /* Look at the token */
+       switch (InfoTok) {
+
+            case INFOTOK_COMMENTSTART:
+                InfoNextTok ();
+                if (CommentStart != EOF) {
+                    InfoError ("Commentstart already given");
+                }
+                InfoAssureChar ();
+                CommentStart = (char) InfoIVal;
+                InfoNextTok ();
+                break;
+
+           case INFOTOK_FILE:
+               InfoNextTok ();
+               if (Name) {
+                   InfoError ("File name already given");
+               }
+               InfoAssureStr ();
+               if (InfoSVal[0] == '\0') {
+                   InfoError ("File name may not be empty");
+               }
+               Name = xstrdup (InfoSVal);
+               InfoNextTok ();
+               break;
+
+            case INFOTOK_IGNOREUNKNOWN:
+                InfoNextTok ();
+                if (IgnoreUnknown != -1) {
+                    InfoError ("Ignoreunknown already specified");
+                }
+                InfoBoolToken ();
+                IgnoreUnknown = (InfoTok != INFOTOK_FALSE);
+                InfoNextTok ();
+                break;
+
+            default:
+                Internal ("Unexpected token: %u", InfoTok);
+       }
+
+       /* Directive is followed by a semicolon */
+       InfoConsumeSemi ();
+    }
+
+    /* Check for the necessary data and assume defaults */
+    if (Name == 0) {
+       InfoError ("File name is missing");
+    }
+    if (CommentStart == EOF) {
+       CommentStart = ';';
+    }
+    if (IgnoreUnknown == -1) {
+        IgnoreUnknown = 0;
+    }
+
+    /* Open the file and read the symbol definitions */
+    AsmInc (Name, CommentStart, IgnoreUnknown);
+
+    /* Delete the dynamically allocated memory for Name */
+    xfree (Name);
+
+    /* Consume the closing brace */
+    InfoConsumeRCurly ();
+}
+
+
+
 static void GlobalSection (void)
 /* Parse a global section */
 {
@@ -256,6 +350,134 @@ static void GlobalSection (void)
 
 
 
+static void LabelSection (void)
+/* Parse a label section */
+{
+    static const IdentTok LabelDefs[] = {
+               {   "COMMENT",  INFOTOK_COMMENT },
+       {   "ADDR",     INFOTOK_ADDR    },
+               {   "NAME",     INFOTOK_NAME    },
+               {   "SIZE",     INFOTOK_SIZE    },
+    };
+
+    /* Locals - initialize to avoid gcc warnings */
+    char* Name    = 0;
+    char* Comment = 0;
+    long Value    = -1;
+    long Size     = -1;
+
+    /* Skip the token */
+    InfoNextTok ();
+
+    /* Expect the opening curly brace */
+    InfoConsumeLCurly ();
+
+    /* Look for section tokens */
+    while (InfoTok != INFOTOK_RCURLY) {
+
+       /* Convert to special token */
+               InfoSpecialToken (LabelDefs, ENTRY_COUNT (LabelDefs), "Label attribute");
+
+       /* Look at the token */
+       switch (InfoTok) {
+
+           case INFOTOK_ADDR:
+               InfoNextTok ();
+               if (Value >= 0) {
+                   InfoError ("Value already given");
+               }
+               InfoAssureInt ();
+               InfoRangeCheck (0, 0xFFFF);
+               Value = InfoIVal;
+               InfoNextTok ();
+               break;
+
+           case INFOTOK_COMMENT:
+               InfoNextTok ();
+               if (Comment) {
+                   InfoError ("Comment already given");
+               }
+               InfoAssureStr ();
+               if (InfoSVal[0] == '\0') {
+                   InfoError ("Comment may not be empty");
+               }
+               Comment = xstrdup (InfoSVal);
+               InfoNextTok ();
+               break;
+
+           case INFOTOK_NAME:
+               InfoNextTok ();
+               if (Name) {
+                   InfoError ("Name already given");
+               }
+               InfoAssureStr ();
+               Name = xstrdup (InfoSVal);
+               InfoNextTok ();
+               break;
+
+           case INFOTOK_SIZE:
+               InfoNextTok ();
+               if (Size >= 0) {
+                   InfoError ("Size already given");
+               }
+               InfoAssureInt ();
+               InfoRangeCheck (1, 0x10000);
+               Size = InfoIVal;
+               InfoNextTok ();
+               break;
+
+            default:
+                Internal ("Unexpected token: %u", InfoTok);
+       }
+
+       /* Directive is followed by a semicolon */
+       InfoConsumeSemi ();
+    }
+
+    /* Did we get the necessary data */
+    if (Name == 0) {
+       InfoError ("Label name is missing");
+    }
+    if (Name[0] == '\0' && Size > 1) {
+        InfoError ("Unnamed labels must not have a size > 1");
+    }
+    if (Value < 0) {
+       InfoError ("Label value is missing");
+    }
+    if (Size < 0) {
+       /* Use default */
+       Size = 1;
+    }
+    if (Value + Size > 0x10000) {
+       InfoError ("Invalid size (address out of range)");
+    }
+    if (HaveLabel ((unsigned) Value)) {
+       InfoError ("Label for address $%04lX already defined", Value);
+    }
+
+    /* Define the label(s) */
+    if (Name[0] == '\0') {
+        /* Size has already beed checked */
+        AddUnnamedLabel (Value);
+    } else {
+        AddExtLabelRange ((unsigned) Value, Name, Size);
+    }
+
+    /* Define the comment */
+    if (Comment) {
+        SetComment (Value, Comment);
+    }
+
+    /* Delete the dynamically allocated memory for Name and Comment */
+    xfree (Name);
+    xfree (Comment);
+
+    /* Consume the closing brace */
+    InfoConsumeRCurly ();
+}
+
+
+
 static void RangeSection (void)
 /* Parse a range section */
 {
@@ -311,7 +533,7 @@ static void RangeSection (void)
     while (InfoTok != INFOTOK_RCURLY) {
 
        /* Convert to special token */
-               InfoSpecialToken (RangeDefs, ENTRY_COUNT (RangeDefs), "Range directive");
+               InfoSpecialToken (RangeDefs, ENTRY_COUNT (RangeDefs), "Range attribute");
 
        /* Look at the token */
        switch (InfoTok) {
@@ -425,21 +647,19 @@ static void RangeSection (void)
 
 
 
-static void LabelSection (void)
-/* Parse a label section */
+static void SegmentSection (void)
+/* Parse a segment section */
 {
     static const IdentTok LabelDefs[] = {
-               {   "COMMENT",  INFOTOK_COMMENT },
-       {   "ADDR",     INFOTOK_ADDR    },
+               {   "END",      INFOTOK_END     },
                {   "NAME",     INFOTOK_NAME    },
-               {   "SIZE",     INFOTOK_SIZE    },
+       {   "START",    INFOTOK_START   },
     };
 
     /* Locals - initialize to avoid gcc warnings */
-    char* Name    = 0;
-    char* Comment = 0;
-    long Value    = -1;
-    long Size     = -1;
+    long End    = -1;
+    long Start  = -1;
+    char* Name  = 0;
 
     /* Skip the token */
     InfoNextTok ();
@@ -450,34 +670,21 @@ static void LabelSection (void)
     /* Look for section tokens */
     while (InfoTok != INFOTOK_RCURLY) {
 
-       /* Convert to special token */
-               InfoSpecialToken (LabelDefs, ENTRY_COUNT (LabelDefs), "Label directive");
+       /* Convert to special token */
+               InfoSpecialToken (LabelDefs, ENTRY_COUNT (LabelDefs), "Segment attribute");
 
-       /* Look at the token */
-       switch (InfoTok) {
+       /* Look at the token */
+       switch (InfoTok) {
 
-           case INFOTOK_ADDR:
-               InfoNextTok ();
-               if (Value >= 0) {
-                   InfoError ("Value already given");
-               }
+           case INFOTOK_END:
+               InfoNextTok ();
+               if (End >= 0) {
+                   InfoError ("Value already given");
+               }
                InfoAssureInt ();
-               InfoRangeCheck (0, 0xFFFF);
-               Value = InfoIVal;
-               InfoNextTok ();
-               break;
-
-           case INFOTOK_COMMENT:
-               InfoNextTok ();
-               if (Comment) {
-                   InfoError ("Comment already given");
-               }
-               InfoAssureStr ();
-               if (InfoSVal[0] == '\0') {
-                   InfoError ("Comment may not be empty");
-               }
-               Comment = xstrdup (InfoSVal);
-               InfoNextTok ();
+               InfoRangeCheck (0, 0xFFFF);
+               End = InfoIVal;
+               InfoNextTok ();
                break;
 
            case INFOTOK_NAME:
@@ -490,16 +697,16 @@ static void LabelSection (void)
                InfoNextTok ();
                break;
 
-           case INFOTOK_SIZE:
-               InfoNextTok ();
-               if (Size >= 0) {
-                   InfoError ("Size already given");
-               }
-               InfoAssureInt ();
-               InfoRangeCheck (1, 0x10000);
-               Size = InfoIVal;
-               InfoNextTok ();
-               break;
+           case INFOTOK_START:
+               InfoNextTok ();
+               if (Start >= 0) {
+                   InfoError ("Value already given");
+               }
+               InfoAssureInt ();
+               InfoRangeCheck (0, 0xFFFF);
+               Start = InfoIVal;
+               InfoNextTok ();
+               break;
 
             default:
                 Internal ("Unexpected token: %u", InfoTok);
@@ -509,133 +716,30 @@ static void LabelSection (void)
        InfoConsumeSemi ();
     }
 
-    /* Did we get the necessary data */
-    if (Name == 0) {
-       InfoError ("Label name is missing");
-    }
-    if (Name[0] == '\0' && Size > 1) {
-        InfoError ("Unnamed labels must not have a size > 1");
-    }
-    if (Value < 0) {
-       InfoError ("Label value is missing");
-    }
-    if (Size < 0) {
-       /* Use default */
-       Size = 1;
+    /* Did we get the necessary data, and is it correct? */
+    if (Name == 0 || Name[0] == '\0') {
+               InfoError ("Segment name is missing");
     }
-    if (Value + Size > 0x10000) {
-       InfoError ("Invalid size (address out of range)");
+    if (End < 0) {
+        InfoError ("End address is missing");
     }
-    if (HaveLabel ((unsigned) Value)) {
-       InfoError ("Label for address $%04lX already defined", Value);
+    if (Start < 0) {
+       InfoError ("Start address is missing");
     }
-
-    /* Define the label(s) */
-    if (Name[0] == '\0') {
-        /* Size has already beed checked */
-        AddUnnamedLabel (Value);
-    } else {
-        AddExtLabelRange ((unsigned) Value, Name, Size);
+    if (Start == End) {
+        InfoError ("Segment is empty");
     }
-
-    /* Define the comment */
-    if (Comment) {
-        SetComment (Value, Comment);
-    }
-
-    /* Delete the dynamically allocated memory for Name and Comment */
-    xfree (Name);
-    xfree (Comment);
-
-    /* Consume the closing brace */
-    InfoConsumeRCurly ();
-}
-
-
-
-static void AsmIncSection (void)
-/* Parse a asminc section */
-{
-    static const IdentTok LabelDefs[] = {
-        {   "COMMENTSTART",     INFOTOK_COMMENTSTART    },
-               {   "FILE",             INFOTOK_FILE            },
-        {   "IGNOREUNKNOWN",    INFOTOK_IGNOREUNKNOWN   },
-    };
-
-    /* Locals - initialize to avoid gcc warnings */
-    char* Name = 0;
-    int CommentStart = EOF;
-    int IgnoreUnknown = -1;
-
-    /* Skip the token */
-    InfoNextTok ();
-
-    /* Expect the opening curly brace */
-    InfoConsumeLCurly ();
-
-    /* Look for section tokens */
-    while (InfoTok != INFOTOK_RCURLY) {
-
-       /* Convert to special token */
-               InfoSpecialToken (LabelDefs, ENTRY_COUNT (LabelDefs), "Asminc directive");
-
-       /* Look at the token */
-       switch (InfoTok) {
-
-            case INFOTOK_COMMENTSTART:
-                InfoNextTok ();
-                if (CommentStart != EOF) {
-                    InfoError ("Commentstart already given");
-                }
-                InfoAssureChar ();
-                CommentStart = (char) InfoIVal;
-                InfoNextTok ();
-                break;
-
-           case INFOTOK_FILE:
-               InfoNextTok ();
-               if (Name) {
-                   InfoError ("File name already given");
-               }
-               InfoAssureStr ();
-               if (InfoSVal[0] == '\0') {
-                   InfoError ("File name may not be empty");
-               }
-               Name = xstrdup (InfoSVal);
-               InfoNextTok ();
-               break;
-
-            case INFOTOK_IGNOREUNKNOWN:
-                InfoNextTok ();
-                if (IgnoreUnknown != -1) {
-                    InfoError ("Ignoreunknown already specified");
-                }
-                InfoBoolToken ();
-                IgnoreUnknown = (InfoTok != INFOTOK_FALSE);
-                InfoNextTok ();
-                break;
-
-            default:
-                Internal ("Unexpected token: %u", InfoTok);
-       }
-
-       /* Directive is followed by a semicolon */
-       InfoConsumeSemi ();
+    if (Start > End) {
+        InfoError ("Start address of segment is greater than end address");
     }
 
-    /* Check for the necessary data and assume defaults */
-    if (Name == 0) {
-       InfoError ("File name is missing");
-    }
-    if (CommentStart == EOF) {
-       CommentStart = ';';
-    }
-    if (IgnoreUnknown == -1) {
-        IgnoreUnknown = 0;
+    /* Check that segments do not overlap */
+    if (SegmentDefined ((unsigned) Start, (unsigned) End)) {
+        InfoError ("Segments cannot overlap");
     }
 
-    /* Open the file and read the symbol definitions */
-    AsmInc (Name, CommentStart, IgnoreUnknown);
+    /* Remember the segment data */
+    AddAbsSegment ((unsigned) Start, (unsigned) End, Name);
 
     /* Delete the dynamically allocated memory for Name */
     xfree (Name);
@@ -650,10 +754,11 @@ static void InfoParse (void)
 /* Parse the config file */
 {
     static const IdentTok Globals[] = {
+        {   "ASMINC",   INFOTOK_ASMINC  },
        {   "GLOBAL",   INFOTOK_GLOBAL  },
-       {   "RANGE",    INFOTOK_RANGE   },
        {   "LABEL",    INFOTOK_LABEL   },
-        {   "ASMINC",   INFOTOK_ASMINC  },
+       {   "RANGE",    INFOTOK_RANGE   },
+        {   "SEGMENT",  INFOTOK_SEGMENT },
     };
 
     while (InfoTok != INFOTOK_EOF) {
@@ -664,20 +769,24 @@ static void InfoParse (void)
        /* Check the token */
        switch (InfoTok) {
 
+            case INFOTOK_ASMINC:
+                AsmIncSection ();
+                break;
+
            case INFOTOK_GLOBAL:
                GlobalSection ();
                break;
 
-           case INFOTOK_RANGE:
-               RangeSection ();
-               break;
-
            case INFOTOK_LABEL:
                LabelSection ();
                break;
 
-            case INFOTOK_ASMINC:
-                AsmIncSection ();
+           case INFOTOK_RANGE:
+               RangeSection ();
+               break;
+
+            case INFOTOK_SEGMENT:
+                SegmentSection ();
                 break;
 
             default: