]> git.sur5r.net Git - cc65/commitdiff
Merge remote-tracking branch 'origin' into da65-synclines
authorAIDA Shinra <shinra@j10n.org>
Mon, 25 Jun 2018 14:38:43 +0000 (23:38 +0900)
committerAIDA Shinra <shinra@j10n.org>
Mon, 25 Jun 2018 14:38:43 +0000 (23:38 +0900)
13 files changed:
doc/da65.sgml
src/da65/global.c
src/da65/global.h
src/da65/main.c
src/da65/scanner.c
testcode/disasm/.gitignore [new file with mode: 0644]
testcode/disasm/bank0.da [new file with mode: 0644]
testcode/disasm/bank0.dai [new file with mode: 0644]
testcode/disasm/bank1.da [new file with mode: 0644]
testcode/disasm/bank1.dai [new file with mode: 0644]
testcode/disasm/fixed.da [new file with mode: 0644]
testcode/disasm/fixed.dai [new file with mode: 0644]
testcode/disasm/sample-unix.mk [new file with mode: 0644]

index 54a3416157d4aa035756e939756c4c2312142687..05154ffd89e9c70ebf1ddfe4d0363b64ff20b23e 100644 (file)
@@ -53,6 +53,7 @@ Short options:
   -o name               Name the output file
   -v                    Increase verbosity
   -F                    Add formfeeds to the output
+  -s                    Accept line markers in the info file
   -S addr               Set the start/load address
   -V                    Print the disassembler version
 
@@ -70,6 +71,7 @@ Long options:
   --mnemonic-column n   Specify mnemonic start column
   --pagelength n        Set the page length for the listing
   --start-addr addr     Set the start/load address
+  --sync-lines          Accept line markers in the info file
   --text-column n       Specify text start column
   --verbose             Increase verbosity
   --version             Print the disassembler version
@@ -205,6 +207,17 @@ Here is a description of all the command line options:
   start address is specified, $10000 minus the size of the input file is used.
 
 
+  <label id="option--sync-lines">
+  <tag><tt>-s, --sync-lines</tt></tag>
+
+  Accept line markers in the info file in the following syntax:
+<tscreen><verb>
+#line <lineno> ["<filename>"]
+# <lineno> "<filename>" [<flag>] ...
+</verb></tscreen>
+  This option is intended for preprocessing info files with "cpp" or "m4".
+
+
   <label id="option--text-column">
   <tag><tt>--text-column n</tt></tag>
 
@@ -299,9 +312,10 @@ anything). Each attribute is terminated by a semicolon.
 
 <sect1>Comments<p>
 
-Comments start with a hash mark (<tt/#/); and, extend from the position of
-the mark to the end of the current line. Hash marks inside of strings will
-<em/not/ start a comment, of course.
+Comments start with a hash mark (<tt/#/) or a double slash (<tt>//</tt>);
+and, extend from the position of the mark to the end of the current line.
+Hash marks or double slashes inside of strings will <em/not/ start a comment,
+of course.
 
 
 <sect1>Specifying global options<label id="global-options"><p>
index e2b1fd144135ec1e38273a1fa771cb51b3ee0796..7df1bd977f6779b8da44f97d9d5991369941e7ad 100644 (file)
@@ -59,6 +59,7 @@ unsigned char PassCount       = 2;      /* How many passed do we do? */
 signed char   NewlineAfterJMP = -1;     /* Add a newline after a JMP insn? */
 signed char   NewlineAfterRTS = -1;     /* Add a newline after a RTS insn? */
 long          StartAddr       = -1L;    /* Start/load address of the program */
+unsigned char SyncLines       = 0;      /* Accept line markers in the info file */
 long          InputOffs       = -1L;    /* Offset into input file */
 long          InputSize       = -1L;    /* Number of bytes to read from input */
 
index 14b1133990cb4e0021b1a71507169b1b6818472f..c85c7a79e4dca84b9162b2d6e9b89599e7c21501 100644 (file)
@@ -60,6 +60,7 @@ extern unsigned char    PassCount;      /* How many passed do we do? */
 extern signed char      NewlineAfterJMP;/* Add a newline after a JMP insn? */
 extern signed char      NewlineAfterRTS;/* Add a newline after a RTS insn? */
 extern long             StartAddr;      /* Start/load address of the program */
+extern unsigned char    SyncLines;      /* Accept line markers in the info file */
 extern long             InputOffs;      /* Offset into input file */
 extern long             InputSize;      /* Number of bytes to read from input */
 
index 1454d01fb831bf1b3ff158bb874f072e85209f54..b0a784dd88338ceb5f03bf4fb5efbde4310e0f78 100644 (file)
@@ -82,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"
@@ -98,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",
@@ -312,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 */
 {
@@ -539,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              },
@@ -589,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;
index 8dc8d393a77fb389fa86fa87828b56ef938a4525..a579939f9070c1dfc84d3258815281b9ba741a55 100644 (file)
@@ -41,6 +41,8 @@
 /* common */
 #include "chartype.h"
 #include "xsprintf.h"
+#include "xmalloc.h"
+#include "strbuf.h"
 
 /* ld65 */
 #include "global.h"
@@ -72,6 +74,7 @@ static int              C               = ' ';
 static unsigned         InputLine       = 1;
 static unsigned         InputCol        = 0;
 static FILE*            InputFile       = 0;
+static char*            InputSrcName    = 0;
 
 
 
@@ -91,7 +94,8 @@ void InfoWarning (const char* Format, ...)
     xvsprintf (Buf, sizeof (Buf), Format, ap);
     va_end (ap);
 
-    Warning ("%s(%u): %s", InfoFile, InfoErrorLine, Buf);
+    fprintf (stderr, "%s(%u): Warning: %s\n",
+            InputSrcName, InfoErrorLine, Buf);
 }
 
 
@@ -106,11 +110,14 @@ void InfoError (const char* Format, ...)
     xvsprintf (Buf, sizeof (Buf), Format, ap);
     va_end (ap);
 
-    Error ("%s(%u): %s", InfoFile, InfoErrorLine, Buf);
+    fprintf (stderr, "%s(%u): Error: %s\n",
+            InputSrcName, InfoErrorLine, Buf);
+    exit (EXIT_FAILURE);
 }
 
 
 
+
 /*****************************************************************************/
 /*                                   Code                                    */
 /*****************************************************************************/
@@ -149,17 +156,171 @@ static unsigned DigitVal (int C)
 
 
 
+static void SkipBlanks (int SingleLine)
+{
+    while (C != EOF && (!SingleLine || C != '\n') && IsSpace (C)) {
+        NextChar ();
+    }
+}
+
+static long GetDecimalToken (void)
+{
+    long Value = 0;
+
+    while (C != EOF && IsDigit (C)) {
+        Value = Value * 10 + DigitVal (C);
+        NextChar ();
+    }
+    return Value;
+}
+
+static int GetEncodedChar (char *Buf, unsigned *IPtr, unsigned Size)
+{
+    char Decoded = 0;
+    int Count;
+
+    if (C == EOF) {
+        return -1;
+    } else if (C != '\\') {
+        Decoded = C;
+        NextChar ();
+        goto Store;
+    }
+    NextChar (); /* consume '\\' */
+    if (C == EOF) {
+        return -1;
+    } else if (IsODigit (C)) {
+        Count = 3;
+        do {
+            Decoded = Decoded * 8 + DigitVal (C);
+            NextChar ();
+            --Count;
+        } while (Count > 0 && C != EOF && IsODigit (C));
+    } else if (C == 'x') {
+        NextChar (); /* consume 'x' */
+        Count = 2;
+        while (Count > 0 && C != EOF && IsXDigit (C)) {
+            Decoded = Decoded * 16 + DigitVal (C);
+            NextChar ();
+            --Count;
+        }
+    } else {
+        switch (C) {
+            case '"': case '\'': case '\\':
+                        Decoded = C;       break;
+            case 't':  Decoded = '\t';     break;
+            case 'r':  Decoded = '\r';     break;
+            case 'n':  Decoded = '\n';     break;
+            default:   return -1;
+        }
+        NextChar ();
+    }
+Store:
+    if (*IPtr < Size - 1) {
+        Buf [(*IPtr)++] = Decoded;
+    }
+    Buf [*IPtr] = 0;
+    return 0;
+}
+
+static void LineMarkerOrComment ()
+/* Handle a line beginning with '#'. Possible interpretations are:
+** - #line <lineno> ["<filename>"]         (C preprocessor input)
+** - # <lineno> "<filename>" [<flag>]...    (gcc preprocessor output)
+** - #<comment>
+*/
+{
+    unsigned long LineNo = 0;
+    int LineDirective = 0;
+    StrBuf SrcNameBuf = AUTO_STRBUF_INITIALIZER;
+
+    /* Skip the first "# " */
+    NextChar ();
+    SkipBlanks (1);
+
+    /* Check "line" */
+    if (C == 'l') {
+        char MaybeLine [6];
+        unsigned I;
+        for (I = 0; I < sizeof MaybeLine - 1 && C != EOF && IsAlNum (C); ++I) {
+            MaybeLine [I] = C;
+            NextChar ();
+        }
+        MaybeLine [I] = 0;
+        if (strcmp (MaybeLine, "line") != 0) {
+            goto NotMarker;
+        }
+        LineDirective = 1;
+        SkipBlanks (1);
+    }
+
+    /* Get line number */
+    if (C == EOF || !IsDigit (C)) {
+        goto NotMarker;
+    }
+    LineNo = GetDecimalToken ();
+    SkipBlanks (1);
+
+    /* Get the source file name */
+    if (C != '\"') {
+        /* The source file name is missing */
+        if (LineDirective && C == '\n') {
+            /* got #line <lineno> */
+            NextChar ();
+            InputLine = LineNo;
+            goto Last;
+        } else {
+            goto NotMarker;
+        }
+    }
+    NextChar ();
+    while (C != EOF && C != '\n' && C != '\"') {
+        char DecodeBuf [2];
+        unsigned I = 0;
+        if (GetEncodedChar (DecodeBuf, &I, sizeof DecodeBuf) < 0) {
+            goto BadMarker;
+        }
+        SB_AppendBuf (&SrcNameBuf, DecodeBuf, I);
+    }
+    if (C != '\"') {
+        goto BadMarker;
+    }
+    NextChar ();
+
+    /* Ignore until the end of line */
+    while (C != EOF && C != '\n') {
+        NextChar ();
+    }
+
+    /* Accepted a line marker */
+    SB_Terminate (&SrcNameBuf);
+    xfree (InputSrcName);
+    InputSrcName = SB_GetBuf (&SrcNameBuf);
+    SB_Init (&SrcNameBuf);
+    InputLine = (unsigned)LineNo;
+    NextChar ();
+    goto Last;
+
+BadMarker:
+    InfoWarning ("Bad line marker");
+NotMarker:
+    while (C != EOF && C != '\n') {
+        NextChar ();
+    }
+    NextChar ();
+Last:
+    SB_Done (&SrcNameBuf);
+}
+
 void InfoNextTok (void)
 /* Read the next token from the input stream */
 {
     unsigned I;
-    int      Esc;
+    char DecodeBuf [2];
 
 Again:
     /* Skip whitespace */
-    while (IsSpace (C)) {
-        NextChar ();
-    }
+    SkipBlanks (0);
 
     /* Remember the current position */
     InfoErrorLine = InputLine;
@@ -198,11 +359,7 @@ Again:
 
     /* Decimal number? */
     if (IsDigit (C)) {
-        InfoIVal = 0;
-        while (IsDigit (C)) {
-            InfoIVal = InfoIVal * 10 + DigitVal (C);
-            NextChar ();
-        }
+        InfoIVal = GetDecimalToken ();
         InfoTok = INFOTOK_INTCON;
         return;
     }
@@ -248,38 +405,31 @@ Again:
         case '\"':
             NextChar ();
             I = 0;
-            while (C != '\"') {
-                Esc = (C == '\\');
-                if (Esc) {
-                    NextChar ();
-                }
-                if (C == EOF || C == '\n') {
-                    InfoError ("Unterminated string");
-                }
-                if (Esc) {
-                    switch (C) {
-                        case '\"':      C = '\"';       break;
-                        case '\'':      C = '\'';       break;
-                        default:        InfoError ("Invalid escape char: %c", C);
+            while (C != EOF && C != '\"') {
+                if (GetEncodedChar (InfoSVal, &I, sizeof InfoSVal) < 0) {
+                    if (C == EOF) {
+                        InfoError ("Unterminated string");
+                    } else  {
+                        InfoError ("Invalid escape char: %c", C);
                     }
                 }
-                if (I < CFG_MAX_IDENT_LEN) {
-                    InfoSVal [I++] = C;
-                }
-                NextChar ();
             }
-            NextChar ();
-            InfoSVal [I] = '\0';
+            if (C != '\"') {
+                InfoError ("Unterminated string");
+            }
+           NextChar ();
             InfoTok = INFOTOK_STRCON;
             break;
 
         case '\'':
             NextChar ();
-            if (C == EOF || IsControl (C)) {
+            if (C == EOF || IsControl (C) || C == '\'') {
                 InfoError ("Invalid character constant");
             }
-            InfoIVal = C;
-            NextChar ();
+            if (GetEncodedChar (DecodeBuf, &I, sizeof DecodeBuf) < 0 || I != 1) {
+                InfoError ("Invalid character constant");
+            }
+            InfoIVal = DecodeBuf [0];
             if (C != '\'') {
                 InfoError ("Unterminated character constant");
             }
@@ -288,8 +438,13 @@ Again:
             break;
 
         case '#':
-            /* Comment */
-            while (C != '\n' && C != EOF) {
+            /* # lineno "sourcefile" or # comment */
+            if (SyncLines && InputCol == 1) {
+                LineMarkerOrComment ();
+            } else {
+                do {
+                    NextChar ();
+                } while (C != EOF && C != '\n');
                 NextChar ();
             }
             if (C != EOF) {
@@ -298,6 +453,21 @@ Again:
             InfoTok = INFOTOK_EOF;
             break;
 
+        case '/':
+            /* C++ style comment */
+            NextChar ();
+            if (C != '/') {
+                InfoError ("Invalid token `/'");
+            }
+            do {
+                NextChar ();
+            } while (C != '\n' && C != EOF);
+            if (C != EOF) {
+                goto Again;
+            }
+            InfoTok = INFOTOK_EOF;
+            break;
+
         case EOF:
             InfoTok = INFOTOK_EOF;
             break;
@@ -484,15 +654,19 @@ void InfoSetName (const char* Name)
 /* Set a name for a config file */
 {
     InfoFile = Name;
+    xfree(InputSrcName);
+    InputSrcName = xstrdup(Name);
 }
 
 
 
+#ifdef unused
 const char* InfoGetName (void)
 /* Get the name of the config file */
 {
     return InfoFile? InfoFile : "";
 }
+#endif /* unused */
 
 
 
diff --git a/testcode/disasm/.gitignore b/testcode/disasm/.gitignore
new file mode 100644 (file)
index 0000000..46c4eca
--- /dev/null
@@ -0,0 +1,2 @@
+*.s
+image.bin
diff --git a/testcode/disasm/bank0.da b/testcode/disasm/bank0.da
new file mode 100644 (file)
index 0000000..4fb96ce
--- /dev/null
@@ -0,0 +1,16 @@
+// Da65 input file before preprocessed by cpp
+// Bank0 ROM map
+
+#define TARGET_BANK 0
+global {
+    inputoffs $00010;
+    inputsize $4000;
+    startaddr $8000;
+    cpu "6502";
+};
+
+#include "fixed.da"
+
+label { addr $8000; name "Bank0ProcA"; };
+label { addr $8123; name "Bank0ProcB"; };
+range { start $A000; end $BFFF; name "Bank0Data"; type ByteTable; };
diff --git a/testcode/disasm/bank0.dai b/testcode/disasm/bank0.dai
new file mode 100644 (file)
index 0000000..2d865e7
--- /dev/null
@@ -0,0 +1,33 @@
+# 1 "bank0.da"
+# 1 "<built-in>"
+# 1 "<command-line>"
+# 1 "bank0.da"
+
+
+
+
+global {
+    inputoffs $00010;
+    inputsize $4000;
+    startaddr $8000;
+    cpu "6502";
+};
+
+# 1 "fixed.da" 1
+# 18 "fixed.da"
+label { addr $00; name "VariableA"; };
+label { addr $01; name "VariableB"; };
+label { addr $0100; name "Stack"; size $0100; };
+
+
+
+
+
+label { addr $C000; name "CommonProcA"; };
+label { addr $C123; name "CommonProcB"; };
+range { start $E123; end $FFFF; name "CommonData"; type ByteTable; };
+# 13 "bank0.da" 2
+
+label { addr $8000; name "Bank0ProcA"; };
+label { addr $8123; name "Bank0ProcB"; };
+range { start $A000; end $BFFF; name "Bank0Data"; type ByteTable; };
diff --git a/testcode/disasm/bank1.da b/testcode/disasm/bank1.da
new file mode 100644 (file)
index 0000000..fd5e324
--- /dev/null
@@ -0,0 +1,16 @@
+// Da65 input file before preprocessed by cpp
+// Bank1 ROM map
+
+#define TARGET_BANK 1
+global {
+    inputoffs $04010;
+    inputsize $4000;
+    startaddr $8000;
+    cpu "6502";
+};
+
+#include "fixed.da"
+
+range { start $8000; end $AFFF; name "Bank1Data"; type ByteTable; };
+label { addr $B000; name "Bank1ProcA"; };
+label { addr $B123; name "Bank1ProcB"; };
diff --git a/testcode/disasm/bank1.dai b/testcode/disasm/bank1.dai
new file mode 100644 (file)
index 0000000..2b5b685
--- /dev/null
@@ -0,0 +1,33 @@
+# 1 "bank1.da"
+# 1 "<built-in>"
+# 1 "<command-line>"
+# 1 "bank1.da"
+
+
+
+
+global {
+    inputoffs $04010;
+    inputsize $4000;
+    startaddr $8000;
+    cpu "6502";
+};
+
+# 1 "fixed.da" 1
+# 18 "fixed.da"
+label { addr $00; name "VariableA"; };
+label { addr $01; name "VariableB"; };
+label { addr $0100; name "Stack"; size $0100; };
+
+
+
+
+
+label { addr $C000; name "CommonProcA"; };
+label { addr $C123; name "CommonProcB"; };
+range { start $E123; end $FFFF; name "CommonData"; type ByteTable; };
+# 13 "bank1.da" 2
+
+range { start $8000; end $AFFF; name "Bank1Data"; type ByteTable; };
+label { addr $B000; name "Bank1ProcA"; };
+label { addr $B123; name "Bank1ProcB"; };
diff --git a/testcode/disasm/fixed.da b/testcode/disasm/fixed.da
new file mode 100644 (file)
index 0000000..e8aa034
--- /dev/null
@@ -0,0 +1,30 @@
+// Da65 input file before preprocessed by cpp
+// RAM and Fixed ROM map
+
+#ifndef FIXED_DA_INCLUDED
+#define FIXED_DA_INCLUDED
+
+#ifndef TARGET_BANK
+#define TARGET_BANK -1
+global {
+    inputoffs $1C010;
+    inputsize $4000;
+    startaddr $C000;
+    cpu "6502";
+};
+#endif /* !defined(TARGET_BANK) */
+
+// ---- RAM map ----
+label { addr $00; name "VariableA"; };
+label { addr $01; name "VariableB"; };
+label { addr $0100; name "Stack"; size $0100; };
+#if defined(TEST_ERROR) && TARGET_BANK == 0
+erroneous_line;
+#endif
+
+// ---- Fixed ROM map ----
+label { addr $C000; name "CommonProcA"; };
+label { addr $C123; name "CommonProcB"; };
+range { start $E123; end $FFFF; name "CommonData"; type ByteTable; };
+
+#endif /* !defined(FIXED_DA_INCLUDED) */
diff --git a/testcode/disasm/fixed.dai b/testcode/disasm/fixed.dai
new file mode 100644 (file)
index 0000000..d73155c
--- /dev/null
@@ -0,0 +1,25 @@
+# 1 "fixed.da"
+# 1 "<built-in>"
+# 1 "<command-line>"
+# 1 "fixed.da"
+# 9 "fixed.da"
+global {
+    inputoffs $1C010;
+    inputsize $4000;
+    startaddr $C000;
+    cpu "6502";
+};
+
+
+
+label { addr $00; name "VariableA"; };
+label { addr $01; name "VariableB"; };
+label { addr $0100; name "Stack"; size $0100; };
+
+
+
+
+
+label { addr $C000; name "CommonProcA"; };
+label { addr $C123; name "CommonProcB"; };
+range { start $E123; end $FFFF; name "CommonData"; type ByteTable; };
diff --git a/testcode/disasm/sample-unix.mk b/testcode/disasm/sample-unix.mk
new file mode 100644 (file)
index 0000000..0ef64a5
--- /dev/null
@@ -0,0 +1,28 @@
+# Sample makefile using a preprocessor against info files
+# and the --sync-lines option
+
+CPP = env LANG=C cpp
+CPPFLAGS = # -DTEST_ERROR
+
+ASMS = fixed.s bank0.s bank1.s
+DAIS = fixed.dai bank0.dai bank1.dai
+
+.SUFFIXES: .da .dai .s
+.PHONY: all clean maintainer-clean
+.SECONDARY: $(DAIS)
+
+.da.dai:
+       $(CPP) -o $@ $(CPPFLAGS) $<
+
+.dai.s:
+       da65 --sync-lines -o $@ -i $< image.bin
+
+all: $(ASMS)
+
+clean:
+       rm -f $(ASMS)
+
+maintainer-clean: clean
+       rm -f $(DAIS)
+
+$(DAIS): fixed.da