]> git.sur5r.net Git - cc65/commitdiff
Working
authorcuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Sat, 8 Feb 2003 23:00:40 +0000 (23:00 +0000)
committercuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Sat, 8 Feb 2003 23:00:40 +0000 (23:00 +0000)
git-svn-id: svn://svn.cc65.org/cc65/trunk@1949 b7a2c559-68d2-44c3-8de9-860c34a00d81

src/co65/global.c
src/co65/global.h
src/co65/main.c
src/co65/o65.c
src/co65/o65.h

index ed65c9c2bd08524c356043a50500a5af84b87245..4d6219a2292b6ad12a9c72e7741156e29696681a 100644 (file)
@@ -48,8 +48,8 @@
 
 
 /* File names */
-const char* InFilename      = 0;                /* Name of input file */
-const char* OutFilename     = 0;                /* Name of output file */
+const char* InputName       = 0;                /* Name of input file */
+const char* OutputName      = 0;                /* Name of output file */
 
 /* Default extensions */
 const char AsmExt[]         = ".s";             /* Default assembler extension */
@@ -60,6 +60,12 @@ const char* DataSeg         = SEGNAME_DATA;     /* Name of the data segment */
 const char* BssSeg          = SEGNAME_BSS;      /* Name of the bss segment */
 const char* ZeropageSeg     = SEGNAME_ZEROPAGE; /* Name of the zeropage segment */
 
+/* Labels */
+const char* CodeLabel       = 0;                /* Label for the code segment */
+const char* DataLabel       = 0;                /* Label for the data segment */
+const char* BssLabel        = 0;                /* Label for the bss segment */
+const char* ZeropageLabel   = 0;                /* Label for the zeropage segment */
+
 /* Flags */
 unsigned char DebugInfo     = 0;                /* Enable debug info */
 
index 634537b7f746ee1be5a03b1b1de1d6a0587dcdae..4359b4cdae97e41e599857ee70acffeb3125e178 100644 (file)
@@ -45,8 +45,8 @@
 
 
 /* File names */
-extern const char*             InFilename;         /* Name of input file */
-extern const char*             OutFilename;        /* Name of output file */
+extern const char*             InputName;          /* Name of input file */
+extern const char*             OutputName;         /* Name of output file */
 
 /* Default extensions */
 extern const char              AsmExt[];           /* Default assembler extension */
@@ -57,6 +57,12 @@ extern const char*      DataSeg;            /* Name of the data segment */
 extern const char*      BssSeg;             /* Name of the bss segment */
 extern const char*      ZeropageSeg;        /* Name of the zeropage segment */
 
+/* Labels */
+extern const char*      CodeLabel;          /* Label for the code segment */
+extern const char*      DataLabel;          /* Label for the data segment */
+extern const char*      BssLabel;           /* Label for the bss segment */
+extern const char*      ZeropageLabel;      /* Label for the zeropage segment */
+
 /* Flags */
 extern unsigned char    DebugInfo;          /* Enable debug info */
 
index 74812947bca3ccce0cc678ed36b6e235d171dd73..b1d38c2893f0e9f4d69b32ec73d92448ffa38978 100644 (file)
@@ -40,6 +40,7 @@
 #include <time.h>
 
 /* common */
+#include "chartype.h"
 #include "cmdline.h"
 #include "fname.h"
 #include "print.h"
@@ -74,19 +75,43 @@ static void Usage (void)
                     "  -v\t\t\tIncrease verbosity\n"
             "\n"
             "Long options:\n"
+             "  --bss-label name\tDefine and export a BSS segment label\n"
             "  --bss-name seg\tSet the name of the BSS segment\n"
+             "  --code-label name\tDefine and export a CODE segment label\n"
                     "  --code-name seg\tSet the name of the CODE segment\n"
+             "  --data-label name\tDefine and export a DATA segment label\n"
                     "  --data-name seg\tSet the name of the DATA segment\n"
                     "  --debug-info\t\tAdd debug info to object file\n"
             "  --help\t\tHelp (this text)\n"
                     "  --verbose\t\tIncrease verbosity\n"
                     "  --version\t\tPrint the version number\n"
+             "  --zeropage-label name\tDefine and export a ZEROPAGE segment label\n"
                     "  --zeropage-name seg\tSet the name of the ZEROPAGE segment\n",
             ProgName);
 }
 
 
 
+static void CheckLabelName (const char* Label)
+/* Check if the given label is a valid label name */
+{
+    const char* L = Label;
+
+    if (strlen (L) < 256 && (IsAlpha (*L) || *L== '_')) {
+        while (*++L) {
+            if (!IsAlNum (*L) && *L != '_') {
+                break;
+            }
+        }
+    }
+
+    if (*L) {
+        Error ("Label name `%s' is invalid", Label);
+    }
+}
+
+
+
 static void CheckSegName (const char* Seg)
 /* Abort if the given name is not a valid segment name */
 {
@@ -98,6 +123,18 @@ static void CheckSegName (const char* Seg)
 
 
 
+static void OptBssLabel (const char* Opt attribute ((unused)), const char* Arg)
+/* Handle the --bss-label option */
+{
+    /* Check for a label name */
+    CheckLabelName (Arg);
+
+    /* Set the label */
+    BssLabel = xstrdup (Arg);
+}
+
+
+
 static void OptBssName (const char* Opt attribute ((unused)), const char* Arg)
 /* Handle the --bss-name option */
 {
@@ -110,6 +147,18 @@ static void OptBssName (const char* Opt attribute ((unused)), const char* Arg)
 
 
 
+static void OptCodeLabel (const char* Opt attribute ((unused)), const char* Arg)
+/* Handle the --code-label option */
+{
+    /* Check for a label name */
+    CheckLabelName (Arg);
+
+    /* Set the label */
+    CodeLabel = xstrdup (Arg);
+}
+
+
+
 static void OptCodeName (const char* Opt attribute ((unused)), const char* Arg)
 /* Handle the --code-name option */
 {
@@ -122,6 +171,18 @@ static void OptCodeName (const char* Opt attribute ((unused)), const char* Arg)
 
 
 
+static void OptDataLabel (const char* Opt attribute ((unused)), const char* Arg)
+/* Handle the --data-label option */
+{
+    /* Check for a label name */
+    CheckLabelName (Arg);
+
+    /* Set the label */
+    DataLabel = xstrdup (Arg);
+}
+
+
+
 static void OptDataName (const char* Opt attribute ((unused)), const char* Arg)
 /* Handle the --data-name option */
 {
@@ -173,6 +234,18 @@ static void OptVersion (const char* Opt attribute ((unused)),
 
 
 
+static void OptZeropageLabel (const char* Opt attribute ((unused)), const char* Arg)
+/* Handle the --zeropage-label option */
+{
+    /* Check for a label name */
+    CheckLabelName (Arg);
+
+    /* Set the label */
+    ZeropageLabel = xstrdup (Arg);
+}
+
+
+
 static void OptZeropageName (const char* Opt attribute ((unused)), const char* Arg)
 /* Handle the --zeropage-name option */
 {
@@ -201,19 +274,19 @@ static const char* SegReloc (const O65Data* D, const O65Reloc* R, unsigned long
             break;
 
         case O65_SEGID_TEXT:
-            xsprintf (Buf, sizeof (Buf), "%s%+ld", CodeSeg, (long) (Val - D->Header.tbase));
+            xsprintf (Buf, sizeof (Buf), "%s%+ld", CodeLabel, (long) (Val - D->Header.tbase));
             break;
 
         case O65_SEGID_DATA:
-            xsprintf (Buf, sizeof (Buf), "%s%+ld", DataSeg, (long) (Val - D->Header.dbase));
+            xsprintf (Buf, sizeof (Buf), "%s%+ld", DataLabel, (long) (Val - D->Header.dbase));
             break;
 
         case O65_SEGID_BSS:
-            xsprintf (Buf, sizeof (Buf), "%s%+ld", BssSeg, (long) (Val - D->Header.bbase));
+            xsprintf (Buf, sizeof (Buf), "%s%+ld", BssLabel, (long) (Val - D->Header.bbase));
             break;
 
         case O65_SEGID_ZP:
-            xsprintf (Buf, sizeof (Buf), "%s%+ld", ZeropageSeg, (long) Val - D->Header.zbase);
+            xsprintf (Buf, sizeof (Buf), "%s%+ld", ZeropageLabel, (long) Val - D->Header.zbase);
             break;
 
         case O65_SEGID_ABS:
@@ -284,9 +357,12 @@ static void ConvertSeg (FILE* F, const O65Data* D, const Collection* Relocs,
                         fprintf (F, "\t.faraddr\t%s\n", SegReloc (D, R, Val));
                     }
                     break;
+
                 case O65_RTYPE_SEG:
+                    /* FALLTHROUGH for now */
                 default:
-                    Internal ("Invalid relocation type at %lu", Byte);
+                    Internal ("Cannot handle relocation type %d at %lu",
+                              R->Type, Byte);
             }
 
             /* Get the next relocation entry */
@@ -310,11 +386,13 @@ static void ConvertSeg (FILE* F, const O65Data* D, const Collection* Relocs,
 static void Convert (void)
 /* Do file conversion */
 {
-    FILE* F;
-    unsigned  I;
+    FILE*       F;
+    unsigned    I;
+    int         cc65;
+    char*       Author = 0;
 
     /* Read the o65 file into memory */
-    O65Data* D = ReadO65File (InFilename);
+    O65Data* D = ReadO65File (InputName);
 
     /* For now, we do only accept o65 files generated by the ld65 linker which
      * have a specific format.
@@ -322,7 +400,7 @@ static void Convert (void)
     if (D->Header.mode != O65_MODE_CC65) {
         Error ("Cannot convert o65 files of this type");
     }
-                     
+
     /* Output statistics */
     Print (stdout, 1, "Size of text segment:               %5lu\n", D->Header.tlen);
     Print (stdout, 1, "Size of data segment:               %5lu\n", D->Header.dlen);
@@ -333,22 +411,110 @@ static void Convert (void)
     Print (stdout, 1, "Number of text segment relocations: %5u\n", CollCount (&D->TextReloc));
     Print (stdout, 1, "Number of data segment relocations: %5u\n", CollCount (&D->DataReloc));
 
+    /* Walk through the options and print them if verbose mode is enabled.
+     * Check for a os=cc65 option and bail out if we didn't find one (for
+     * now - later we switch to special handling).
+     */
+    cc65 = 0;
+    for (I = 0; I < CollCount (&D->Options); ++I) {
+
+        /* Get the next option */
+        const O65Option* O = CollConstAt (&D->Options, I);
+
+        /* Check the type */
+        switch (O->Type) {
+            case O65_OPT_FILENAME:
+                Print (stdout, 1, "O65 filename option:         `%s'\n",
+                       GetO65OptionText (O));
+                break;
+            case O65_OPT_OS:
+                if (O->Len == 2) {
+                    Warning ("Operating system option without data found");
+                } else {
+                    cc65 = (O->Data[0] == O65_OS_CC65_MODULE);
+                    Print (stdout, 1, "O65 operating system option: `%s'\n",
+                           GetO65OSName (O->Data[0]));
+                }
+                break;
+            case O65_OPT_ASM:
+                Print (stdout, 1, "O65 assembler option:        `%s'\n",
+                       GetO65OptionText (O));
+                break;
+            case O65_OPT_AUTHOR:
+                if (Author) {
+                    xfree (Author);
+                }
+                Author = xstrdup (GetO65OptionText (O));
+                Print (stdout, 1, "O65 author option:           `%s'\n", Author);
+                break;
+            case O65_OPT_TIMESTAMP:
+                Print (stdout, 1, "O65 timestamp option:        `%s'\n",
+                       GetO65OptionText (O));
+                break;
+            default:
+                Warning ("Found unknown option, type %d, length %d",
+                         O->Type, O->Len);
+                break;
+        }
+    }
+
     /* Open the output file */
-    F = fopen (OutFilename, "wb");
+    F = fopen (OutputName, "wb");
     if (F == 0) {
-        Error ("Cannot open `%s': %s", OutFilename, strerror (errno));
+        Error ("Cannot open `%s': %s", OutputName, strerror (errno));
     }
 
     /* Create a header */
-    if ((D->Header.mode & O65_CPU_MASK) == O65_CPU_65816) {
-       fprintf (F, "\t.p816\n");
-    }
     fprintf (F, ";\n; File generated by co65 v %u.%u.%u\n;\n",
              VER_MAJOR, VER_MINOR, VER_PATCH);
+
+    /* Select the CPU */
+    if ((D->Header.mode & O65_CPU_MASK) == O65_CPU_65816) {
+       fprintf (F, "\t.p816\n");
+    }
+
+    /* Object file options */
     fprintf (F, "\t.fopt\t\tcompiler,\"co65 v %u.%u.%u\"\n",
              VER_MAJOR, VER_MINOR, VER_PATCH);
+    if (Author) {
+        fprintf (F, "\t.fopt\t\tauthor, \"%s\"\n", Author);
+        xfree (Author);
+        Author = 0;
+    }
+
+    /* Several other assembler options */
     fprintf (F, "\t.case\t\ton\n");
     fprintf (F, "\t.debuginfo\t%s\n", (DebugInfo != 0)? "on" : "off");
+
+    /* Setup/export the segment labels */
+    if (BssLabel) {
+        fprintf (F, "\t.export\t\t%s\n", BssLabel);
+    } else {
+        BssLabel = xstrdup ("__BSS__");
+    }
+    if (CodeLabel) {
+        fprintf (F, "\t.export\t\t%s\n", CodeLabel);
+    } else {
+        CodeLabel = xstrdup ("__CODE__");
+    }
+    if (DataLabel) {
+        fprintf (F, "\t.export\t\t%s\n", DataLabel);
+    } else {
+        DataLabel = xstrdup ("__DATA__");
+    }
+    if (ZeropageLabel) {
+        fprintf (F, "\t.export\t\t%s\n", ZeropageLabel);
+    } else {
+        /* If this is a cc65 module, override the name for the zeropage segment */
+        if (cc65) {
+            ZeropageLabel = "__ZP_RUN__";
+            fprintf (F, "\t.import\t\t__ZP_RUN__\t; Linker generated symbol\n");
+        } else {
+            ZeropageLabel = xstrdup ("__ZEROPAGE__");
+        }
+    }
+
+    /* End of header */
     fprintf (F, "\n");
 
     /* Imported identifiers */
@@ -371,7 +537,10 @@ static void Convert (void)
             /* Get the next import */
             O65Export* Export = CollAtUnchecked (&D->Exports, I);
 
-            /* Import it by name */
+            /* First define it */
+            fprintf (F, "%s = XXX\n", Export->Name);    /* ### */
+
+            /* The export it by name */
             fprintf (F, "\t.export\t%s\n", Export->Name);
         }
         fprintf (F, "\n");
@@ -379,17 +548,17 @@ static void Convert (void)
 
     /* Code segment */
     fprintf (F, ".segment\t\"%s\"\n", CodeSeg);
-    fprintf (F, "%s:\n", CodeSeg);
+    fprintf (F, "%s:\n", CodeLabel);
     ConvertSeg (F, D, &D->TextReloc, D->Text, D->Header.tlen);
 
     /* Data segment */
     fprintf (F, ".segment\t\"%s\"\n", DataSeg);
-    fprintf (F, "%s:\n", DataSeg);
+    fprintf (F, "%s:\n", DataLabel);
     ConvertSeg (F, D, &D->DataReloc, D->Data, D->Header.dlen);
 
     /* BSS segment */
     fprintf (F, ".segment\t\"%s\"\n", BssSeg);
-    fprintf (F, "%s:\n", BssSeg);
+    fprintf (F, "%s:\n", BssLabel);
     fprintf (F, "\t.res\t%lu\n", D->Header.blen);
     fprintf (F, "\n");
 
@@ -404,13 +573,17 @@ int main (int argc, char* argv [])
 {
     /* Program long options */
     static const LongOpt OptTab[] = {
+               { "--bss-label",        1,      OptBssLabel             },
        { "--bss-name",         1,      OptBssName              },
+               { "--code-label",       1,      OptCodeLabel            },
        { "--code-name",        1,      OptCodeName             },
+               { "--data-label",       1,      OptDataLabel            },
        { "--data-name",        1,      OptDataName             },
        { "--debug-info",       0,      OptDebugInfo            },
        { "--help",             0,      OptHelp                 },
        { "--verbose",          0,      OptVerbose              },
        { "--version",          0,      OptVersion              },
+               { "--zeropage-label",   1,      OptZeropageLabel        },
                { "--zeropage-name",    1,      OptZeropageName         },
     };
 
@@ -443,7 +616,7 @@ int main (int argc, char* argv [])
                    break;
 
                        case 'o':
-                           OutFilename = GetArg (&I, 2);
+                           OutputName = GetArg (&I, 2);
                            break;
 
                        case 'v':
@@ -461,10 +634,10 @@ int main (int argc, char* argv [])
            }
                } else {
            /* Filename. Check if we already had one */
-           if (InFilename) {
+           if (InputName) {
                Error ("Don't know what to do with `%s'\n", Arg);
            } else {
-               InFilename = Arg;
+               InputName = Arg;
            }
        }
 
@@ -473,13 +646,13 @@ int main (int argc, char* argv [])
     }
 
     /* Do we have an input file? */
-    if (InFilename == 0) {
+    if (InputName == 0) {
                Error ("No input file\n");
     }
 
     /* Generate the name of the output file if none was specified */
-    if (OutFilename == 0) {
-        OutFilename = MakeFilename (InFilename, AsmExt);
+    if (OutputName == 0) {
+        OutputName = MakeFilename (InputName, AsmExt);
     }
 
     /* Do the conversion */
index aa000f307720d8f8b15b2363ea5417684a038a36..976e23a70e11f7f956d6af9d971a55ecad19bb3f 100644 (file)
@@ -38,6 +38,7 @@
 #include <errno.h>
 
 /* common */
+#include "chartype.h"
 #include "xmalloc.h"
 
 /* co65 */
@@ -153,14 +154,18 @@ static O65Option* ReadO65Option (FILE* F)
     if (Len == 0) {
         return 0;
     }
+    if (Len < 2) {
+        Error ("Found option with length < 2 (input file corrupt)");
+    }
+    Len -= 2;
 
     /* Allocate a new O65Option structure of the needed size */
-    O = xmalloc (sizeof (*O) - sizeof (O->Data) + Len - 2);
+    O = xmalloc (sizeof (*O) - sizeof (O->Data) + Len);
 
     /* Assign the length and read the remaining option data */
     O->Len  = Len;
     O->Type = Read8 (F);
-    ReadData (F, O->Data, Len - 2);
+    ReadData (F, O->Data, Len);
 
     /* Return the new struct */
     return O;
@@ -367,3 +372,64 @@ O65Data* ReadO65File (const char* Name)
 
 
 
+const char* GetO65OSName (unsigned char OS)
+/* Return the name of the operating system given by OS */
+{
+    switch (OS) {
+        case O65_OS_OSA65:              return "OS/A65";
+        case O65_OS_LUNIX:              return "Lunix";
+        case O65_OS_CC65_MODULE:        return "cc65 module";
+        default:                        return "unknown";
+    }
+}
+
+
+
+const char* GetO65OptionText (const O65Option* O)
+/* Return the data of the given option as a readable text. The function returns
+ * a pointer to a static buffer that is reused on the next call, so if in doubt,
+ * make a copy (and no, the function is not thread safe).
+ */
+{
+    static char Buf[256];
+    unsigned I, J;
+
+    /* Get the length of the text */
+    unsigned Len = 0;
+    while (Len < O->Len && O->Data[Len] != '\0') {
+        ++Len;
+    }
+
+    /* Copy into the buffer converting non readable characters */
+    I = J = 0;
+    while (I < sizeof (Buf) - 1 && J < Len) {
+        if (!IsControl (O->Data[J])) {
+            Buf[I++] = O->Data[J];
+        } else {
+            Buf[I++] = '\\';
+            if (I >= sizeof (Buf) - 4) {
+                --I;
+                break;
+            }
+            switch (O->Data[J]) {
+                case '\t':      Buf[I++] = 't'; break;
+                case '\b':      Buf[I++] = 'b'; break;
+                case '\n':      Buf[I++] = 'n'; break;
+                case '\r':      Buf[I++] = 'r'; break;
+                case '\v':      Buf[I++] = 'v'; break;
+                default:
+                    sprintf (Buf + I, "x%02X", O->Data[J]);
+                    I += 3;
+                    break;
+            }
+        }
+        ++J;
+    }
+
+    /* Terminate the string and return it */
+    Buf[I] = '\0';
+    return Buf;
+}
+
+
+
index 4cb395fa66a66087f075882bb7b9e47abc75098f..e2ee4fa4aff6ebc030d5fcbd8798ddc675c0a21c 100644 (file)
@@ -212,6 +212,15 @@ O65Data* ReadO65File (const char* Name);
  * created O65Data struct.
  */
 
+const char* GetO65OSName (unsigned char OS);
+/* Return the name of the operating system given by OS */
+
+const char* GetO65OptionText (const O65Option* O);
+/* Return the data of the given option as a readable text. The function returns
+ * a pointer to a static buffer that is reused on the next call, so if in doubt,
+ * make a copy (and no, the function is not thread safe).
+ */
+
 
 
 /* End of o65.h */