]> git.sur5r.net Git - cc65/blobdiff - src/da65/main.c
Followed the discussions in the Pull request #682.
[cc65] / src / da65 / main.c
index 921951f3a04b779df17b21924be2d786de0f4fb4..b0a784dd88338ceb5f03bf4fb5efbde4310e0f78 100644 (file)
@@ -6,10 +6,10 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 1998-2011, Ullrich von Bassewitz                                       */
-/*                Roemerstrasse 52                                            */
-/*                D-70794 Filderstadt                                         */
-/* EMail:         uz@cc65.org                                                 */
+/* (C) 1998-2014, Ullrich von Bassewitz                                      */
+/*                Roemerstrasse 52                                           */
+/*                D-70794 Filderstadt                                        */
+/* EMail:         uz@cc65.org                                                */
 /*                                                                           */
 /*                                                                           */
 /* This software is provided 'as-is', without any expressed or implied       */
@@ -60,6 +60,7 @@
 #include "opctable.h"
 #include "output.h"
 #include "scanner.h"
+#include "segment.h"
 
 
 
@@ -81,6 +82,7 @@ static void Usage (void)
             "  -v\t\t\tIncrease verbosity\n"
             "  -F\t\t\tAdd formfeeds to the output\n"
             "  -S addr\t\tSet the start/load address\n"
+            "  -s\t\t\tAccept line markers in the info file\n"
             "  -V\t\t\tPrint the disassembler version\n"
             "\n"
             "Long options:\n"
@@ -97,6 +99,7 @@ static void Usage (void)
             "  --mnemonic-column n\tSpecify mnemonic start column\n"
             "  --pagelength n\tSet the page length for the listing\n"
             "  --start-addr addr\tSet the start/load address\n"
+            "  --sync-lines\t\tAccept line markers in the info file\n"
             "  --text-column n\tSpecify text start column\n"
             "  --verbose\t\tIncrease verbosity\n"
             "  --version\t\tPrint the disassembler version\n",
@@ -108,8 +111,8 @@ static void Usage (void)
 static void RangeCheck (const char* Opt, unsigned long Val,
                         unsigned long Min, unsigned long Max)
 /* Do a range check for the given option and abort if there's a range
- * error.
- */
+** error.
+*/
 {
     if (Val < Min || Val > Max) {
         Error ("Argument for %s outside valid range (%ld-%ld)", Opt, Min, Max);
@@ -120,8 +123,8 @@ static void RangeCheck (const char* Opt, unsigned long Val,
 
 static unsigned long CvtNumber (const char* Arg, const char* Number)
 /* Convert a number from a string. Allow '$' and '0x' prefixes for hex
- * numbers.
- */
+** numbers.
+*/
 {
     unsigned long Val;
     int           Converted;
@@ -311,6 +314,15 @@ static void OptStartAddr (const char* Opt, const char* Arg)
 
 
 
+static void OptSyncLines (const char* Opt attribute ((unused)),
+                          const char* Arg attribute ((unused)))
+/* Handle the --sync-lines option */
+{
+    SyncLines = 1;
+}
+
+
+
 static void OptTextColumn (const char* Opt, const char* Arg)
 /* Handle the --text-column option */
 {
@@ -339,7 +351,8 @@ static void OptVersion (const char* Opt attribute ((unused)),
                         const char* Arg attribute ((unused)))
 /* Print the disassembler version */
 {
-    fprintf (stderr, "da65 V%s\n", GetVersionAsString ());
+    fprintf (stderr, "%s V%s\n", ProgName, GetVersionAsString ());
+    exit(EXIT_SUCCESS);
 }
 
 
@@ -347,6 +360,9 @@ static void OptVersion (const char* Opt attribute ((unused)),
 static void OneOpcode (unsigned RemainingBytes)
 /* Disassemble one opcode */
 {
+    unsigned I;
+    unsigned OldPC = PC;
+
     /* Get the opcode from the current address */
     unsigned char OPC = GetCodeByte (PC);
 
@@ -356,9 +372,17 @@ static void OneOpcode (unsigned RemainingBytes)
     /* Get the output style for the current PC */
     attr_t Style = GetStyleAttr (PC);
 
+    /* If a segment begins here, then name that segment.
+    ** Note that the segment is named even if its code is being skipped,
+    ** because some of its later code might not be skipped.
+    */
+    if (IsSegmentStart (PC)) {
+        StartSegment (GetSegmentStartName (PC), GetSegmentAddrSize (PC));
+    }
+
     /* If we have a label at this address, output the label and an attached
-     * comment, provided that we aren't in a skip area.
-     */
+    ** comment, provided that we aren't in a skip area.
+    */
     if (Style != atSkip && MustDefLabel (PC)) {
         const char* Comment = GetComment (PC);
         if (Comment) {
@@ -368,11 +392,12 @@ static void OneOpcode (unsigned RemainingBytes)
     }
 
     /* Check...
-     *   - ...if we have enough bytes remaining for the code at this address.
-     *   - ...if the current instruction is valid for the given CPU.
-     *   - ...if there is no label somewhere between the instruction bytes.
-     * If any of these conditions is false, switch to data mode.
-     */
+    **   - ...if we have enough bytes remaining for the code at this address.
+    **   - ...if the current instruction is valid for the given CPU.
+    **   - ...if there is no label somewhere between the instruction bytes.
+    **   - ...if there is no segment change between the instruction bytes.
+    ** If any one of those conditions is false, switch to data mode.
+    */
     if (Style == atDefault) {
         if (D->Size > RemainingBytes) {
             Style = atIllegal;
@@ -381,9 +406,15 @@ static void OneOpcode (unsigned RemainingBytes)
             Style = atIllegal;
             MarkAddr (PC, Style);
         } else {
-            unsigned I;
-            for (I = 1; I < D->Size; ++I) {
-                if (HaveLabel (PC+I) || HaveSegmentChange (PC+I)) {
+            for (I = PC + D->Size; --I > PC; ) {
+                if (HaveLabel (I) || IsSegmentStart (I)) {
+                    Style = atIllegal;
+                    MarkAddr (PC, Style);
+                    break;
+                }
+            }
+            for (I = 0; I < D->Size - 1u; ++I) {
+                if (IsSegmentEnd (PC + I)) {
                     Style = atIllegal;
                     MarkAddr (PC, Style);
                     break;
@@ -402,11 +433,10 @@ static void OneOpcode (unsigned RemainingBytes)
 
         case atCode:
             /* Beware: If we don't have enough bytes left to disassemble the
-             * following insn, fall through to byte mode.
-             */
+            ** following insn, fall through to byte mode.
+            */
             if (D->Size <= RemainingBytes) {
                 /* Output labels within the next insn */
-                unsigned I;
                 for (I = 1; I < D->Size; ++I) {
                     ForwardLabel (I);
                 }
@@ -453,7 +483,16 @@ static void OneOpcode (unsigned RemainingBytes)
             DataByteLine (1);
             ++PC;
             break;
+    }
 
+    /* Change back to the default CODE segment if
+    ** a named segment stops at the current address.
+    */
+    for (I = PC - OldPC; I > 0; --I) {
+        if (IsSegmentEnd (PC - I)) {
+            EndSegment ();
+            break;
+        }
     }
 }
 
@@ -511,6 +550,7 @@ int main (int argc, char* argv [])
         { "--mnemonic-column",  1,      OptMnemonicColumn       },
         { "--pagelength",       1,      OptPageLength           },
         { "--start-addr",       1,      OptStartAddr            },
+        { "--sync-lines",       0,      OptSyncLines            },
         { "--text-column",      1,      OptTextColumn           },
         { "--verbose",          0,      OptVerbose              },
         { "--version",          0,      OptVersion              },
@@ -561,6 +601,10 @@ int main (int argc, char* argv [])
                     OptStartAddr (Arg, GetArg (&I, 2));
                     break;
 
+                case 's':
+                    OptSyncLines (Arg, 0);
+                    break;
+
                 case 'V':
                     OptVersion (Arg, 0);
                     break;
@@ -594,9 +638,9 @@ int main (int argc, char* argv [])
     }
 
     /* Check the formatting options for reasonable values. Note: We will not
-     * really check that they make sense, just that they aren't complete
-     * garbage.
-     */
+    ** really check that they make sense, just that they aren't complete
+    ** garbage.
+    */
     if (MCol >= ACol) {
         AbEnd ("mnemonic-column value must be smaller than argument-column value");
     }
@@ -613,8 +657,8 @@ int main (int argc, char* argv [])
     }
 
     /* Get the current time and convert it to string so it can be used in
-     * the output page headers.
-     */
+    ** the output page headers.
+    */
     T = time (0);
     strftime (Now, sizeof (Now), "%Y-%m-%d %H:%M:%S", localtime (&T));