Support for preprocessing info file via cpp or m4.
This commit is contained in:
parent
b74ab9de89
commit
335a8972b9
4 changed files with 245 additions and 38 deletions
|
@ -53,6 +53,7 @@ Short options:
|
||||||
-o name Name the output file
|
-o name Name the output file
|
||||||
-v Increase verbosity
|
-v Increase verbosity
|
||||||
-F Add formfeeds to the output
|
-F Add formfeeds to the output
|
||||||
|
-s Accept line markers in the info file
|
||||||
-S addr Set the start/load address
|
-S addr Set the start/load address
|
||||||
-V Print the disassembler version
|
-V Print the disassembler version
|
||||||
|
|
||||||
|
@ -70,6 +71,7 @@ Long options:
|
||||||
--mnemonic-column n Specify mnemonic start column
|
--mnemonic-column n Specify mnemonic start column
|
||||||
--pagelength n Set the page length for the listing
|
--pagelength n Set the page length for the listing
|
||||||
--start-addr addr Set the start/load address
|
--start-addr addr Set the start/load address
|
||||||
|
--sync-lines Accept line markers in the info file
|
||||||
--text-column n Specify text start column
|
--text-column n Specify text start column
|
||||||
--verbose Increase verbosity
|
--verbose Increase verbosity
|
||||||
--version Print the disassembler version
|
--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.
|
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">
|
<label id="option--text-column">
|
||||||
<tag><tt>--text-column n</tt></tag>
|
<tag><tt>--text-column n</tt></tag>
|
||||||
|
|
||||||
|
@ -299,9 +312,10 @@ anything). Each attribute is terminated by a semicolon.
|
||||||
|
|
||||||
<sect1>Comments<p>
|
<sect1>Comments<p>
|
||||||
|
|
||||||
Comments start with a hash mark (<tt/#/); and, extend from the position of
|
Comments start with a hash mark (<tt/#/) or a double slashe (<tt>//</tt>);
|
||||||
the mark to the end of the current line. Hash marks inside of strings will
|
and, extend from the position of the mark to the end of the current line.
|
||||||
<em/not/ start a comment, of course.
|
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>
|
<sect1>Specifying global options<label id="global-options"><p>
|
||||||
|
|
|
@ -82,6 +82,7 @@ static void Usage (void)
|
||||||
" -v\t\t\tIncrease verbosity\n"
|
" -v\t\t\tIncrease verbosity\n"
|
||||||
" -F\t\t\tAdd formfeeds to the output\n"
|
" -F\t\t\tAdd formfeeds to the output\n"
|
||||||
" -S addr\t\tSet the start/load address\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"
|
" -V\t\t\tPrint the disassembler version\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Long options:\n"
|
"Long options:\n"
|
||||||
|
@ -98,6 +99,7 @@ static void Usage (void)
|
||||||
" --mnemonic-column n\tSpecify mnemonic start column\n"
|
" --mnemonic-column n\tSpecify mnemonic start column\n"
|
||||||
" --pagelength n\tSet the page length for the listing\n"
|
" --pagelength n\tSet the page length for the listing\n"
|
||||||
" --start-addr addr\tSet the start/load address\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"
|
" --text-column n\tSpecify text start column\n"
|
||||||
" --verbose\t\tIncrease verbosity\n"
|
" --verbose\t\tIncrease verbosity\n"
|
||||||
" --version\t\tPrint the disassembler version\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 */
|
||||||
|
{
|
||||||
|
InfoSyncLines = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void OptTextColumn (const char* Opt, const char* Arg)
|
static void OptTextColumn (const char* Opt, const char* Arg)
|
||||||
/* Handle the --text-column option */
|
/* Handle the --text-column option */
|
||||||
{
|
{
|
||||||
|
@ -539,6 +550,7 @@ int main (int argc, char* argv [])
|
||||||
{ "--mnemonic-column", 1, OptMnemonicColumn },
|
{ "--mnemonic-column", 1, OptMnemonicColumn },
|
||||||
{ "--pagelength", 1, OptPageLength },
|
{ "--pagelength", 1, OptPageLength },
|
||||||
{ "--start-addr", 1, OptStartAddr },
|
{ "--start-addr", 1, OptStartAddr },
|
||||||
|
{ "--sync-lines", 0, OptSyncLines },
|
||||||
{ "--text-column", 1, OptTextColumn },
|
{ "--text-column", 1, OptTextColumn },
|
||||||
{ "--verbose", 0, OptVerbose },
|
{ "--verbose", 0, OptVerbose },
|
||||||
{ "--version", 0, OptVersion },
|
{ "--version", 0, OptVersion },
|
||||||
|
@ -589,6 +601,10 @@ int main (int argc, char* argv [])
|
||||||
OptStartAddr (Arg, GetArg (&I, 2));
|
OptStartAddr (Arg, GetArg (&I, 2));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 's':
|
||||||
|
OptSyncLines (Arg, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
case 'V':
|
case 'V':
|
||||||
OptVersion (Arg, 0);
|
OptVersion (Arg, 0);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -41,6 +41,8 @@
|
||||||
/* common */
|
/* common */
|
||||||
#include "chartype.h"
|
#include "chartype.h"
|
||||||
#include "xsprintf.h"
|
#include "xsprintf.h"
|
||||||
|
#include "xmalloc.h"
|
||||||
|
#include "strbuf.h"
|
||||||
|
|
||||||
/* ld65 */
|
/* ld65 */
|
||||||
#include "global.h"
|
#include "global.h"
|
||||||
|
@ -72,7 +74,10 @@ static int C = ' ';
|
||||||
static unsigned InputLine = 1;
|
static unsigned InputLine = 1;
|
||||||
static unsigned InputCol = 0;
|
static unsigned InputCol = 0;
|
||||||
static FILE* InputFile = 0;
|
static FILE* InputFile = 0;
|
||||||
|
static char* InputSrcName = 0;
|
||||||
|
|
||||||
|
/* Options */
|
||||||
|
unsigned char InfoSyncLines = 0;
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
@ -91,7 +96,8 @@ void InfoWarning (const char* Format, ...)
|
||||||
xvsprintf (Buf, sizeof (Buf), Format, ap);
|
xvsprintf (Buf, sizeof (Buf), Format, ap);
|
||||||
va_end (ap);
|
va_end (ap);
|
||||||
|
|
||||||
Warning ("%s(%u): %s", InfoFile, InfoErrorLine, Buf);
|
fprintf (stderr, "%s(%u): Warning: %s\n",
|
||||||
|
InputSrcName, InfoErrorLine, Buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -106,7 +112,9 @@ void InfoError (const char* Format, ...)
|
||||||
xvsprintf (Buf, sizeof (Buf), Format, ap);
|
xvsprintf (Buf, sizeof (Buf), Format, ap);
|
||||||
va_end (ap);
|
va_end (ap);
|
||||||
|
|
||||||
Error ("%s(%u): %s", InfoFile, InfoErrorLine, Buf);
|
fprintf (stderr, "%s(%u): Error: %s\n",
|
||||||
|
InputSrcName, InfoErrorLine, Buf);
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -149,17 +157,171 @@ static unsigned DigitVal (int C)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void SkipBlanks (int SingleLine)
|
||||||
|
{
|
||||||
|
while (C != EOF && (!SingleLine || C != '\n') && IsSpace (C)) {
|
||||||
|
NextChar ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static long GetDecimalToken ()
|
||||||
|
{
|
||||||
|
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)
|
void InfoNextTok (void)
|
||||||
/* Read the next token from the input stream */
|
/* Read the next token from the input stream */
|
||||||
{
|
{
|
||||||
unsigned I;
|
unsigned I;
|
||||||
int Esc;
|
char DecodeBuf [2];
|
||||||
|
|
||||||
Again:
|
Again:
|
||||||
/* Skip whitespace */
|
/* Skip whitespace */
|
||||||
while (IsSpace (C)) {
|
SkipBlanks (0);
|
||||||
NextChar ();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Remember the current position */
|
/* Remember the current position */
|
||||||
InfoErrorLine = InputLine;
|
InfoErrorLine = InputLine;
|
||||||
|
@ -198,11 +360,7 @@ Again:
|
||||||
|
|
||||||
/* Decimal number? */
|
/* Decimal number? */
|
||||||
if (IsDigit (C)) {
|
if (IsDigit (C)) {
|
||||||
InfoIVal = 0;
|
InfoIVal = GetDecimalToken ();
|
||||||
while (IsDigit (C)) {
|
|
||||||
InfoIVal = InfoIVal * 10 + DigitVal (C);
|
|
||||||
NextChar ();
|
|
||||||
}
|
|
||||||
InfoTok = INFOTOK_INTCON;
|
InfoTok = INFOTOK_INTCON;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -248,38 +406,31 @@ Again:
|
||||||
case '\"':
|
case '\"':
|
||||||
NextChar ();
|
NextChar ();
|
||||||
I = 0;
|
I = 0;
|
||||||
while (C != '\"') {
|
while (C != EOF && C != '\"') {
|
||||||
Esc = (C == '\\');
|
if (GetEncodedChar (InfoSVal, &I, sizeof InfoSVal) < 0) {
|
||||||
if (Esc) {
|
if (C == EOF) {
|
||||||
NextChar ();
|
InfoError ("Unterminated string");
|
||||||
|
} else {
|
||||||
|
InfoError ("Invalid escape char: %c", C);
|
||||||
}
|
}
|
||||||
if (C == EOF || C == '\n') {
|
}
|
||||||
|
}
|
||||||
|
if (C != '\"') {
|
||||||
InfoError ("Unterminated string");
|
InfoError ("Unterminated string");
|
||||||
}
|
}
|
||||||
if (Esc) {
|
|
||||||
switch (C) {
|
|
||||||
case '\"': C = '\"'; break;
|
|
||||||
case '\'': C = '\''; break;
|
|
||||||
default: InfoError ("Invalid escape char: %c", C);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (I < CFG_MAX_IDENT_LEN) {
|
|
||||||
InfoSVal [I++] = C;
|
|
||||||
}
|
|
||||||
NextChar ();
|
NextChar ();
|
||||||
}
|
|
||||||
NextChar ();
|
|
||||||
InfoSVal [I] = '\0';
|
|
||||||
InfoTok = INFOTOK_STRCON;
|
InfoTok = INFOTOK_STRCON;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '\'':
|
case '\'':
|
||||||
NextChar ();
|
NextChar ();
|
||||||
if (C == EOF || IsControl (C)) {
|
if (C == EOF || IsControl (C) || C == '\'') {
|
||||||
InfoError ("Invalid character constant");
|
InfoError ("Invalid character constant");
|
||||||
}
|
}
|
||||||
InfoIVal = C;
|
if (GetEncodedChar (DecodeBuf, &I, sizeof DecodeBuf) < 0 || I != 1) {
|
||||||
NextChar ();
|
InfoError ("Invalid character constant");
|
||||||
|
}
|
||||||
|
InfoIVal = DecodeBuf [0];
|
||||||
if (C != '\'') {
|
if (C != '\'') {
|
||||||
InfoError ("Unterminated character constant");
|
InfoError ("Unterminated character constant");
|
||||||
}
|
}
|
||||||
|
@ -288,8 +439,13 @@ Again:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '#':
|
case '#':
|
||||||
/* Comment */
|
/* # lineno "sourcefile" or # comment */
|
||||||
while (C != '\n' && C != EOF) {
|
if (InfoSyncLines && InputCol == 1) {
|
||||||
|
LineMarkerOrComment ();
|
||||||
|
} else {
|
||||||
|
do {
|
||||||
|
NextChar ();
|
||||||
|
} while (C != EOF && C != '\n');
|
||||||
NextChar ();
|
NextChar ();
|
||||||
}
|
}
|
||||||
if (C != EOF) {
|
if (C != EOF) {
|
||||||
|
@ -298,6 +454,21 @@ Again:
|
||||||
InfoTok = INFOTOK_EOF;
|
InfoTok = INFOTOK_EOF;
|
||||||
break;
|
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:
|
case EOF:
|
||||||
InfoTok = INFOTOK_EOF;
|
InfoTok = INFOTOK_EOF;
|
||||||
break;
|
break;
|
||||||
|
@ -484,15 +655,19 @@ void InfoSetName (const char* Name)
|
||||||
/* Set a name for a config file */
|
/* Set a name for a config file */
|
||||||
{
|
{
|
||||||
InfoFile = Name;
|
InfoFile = Name;
|
||||||
|
xfree(InputSrcName);
|
||||||
|
InputSrcName = xstrdup(Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef unused
|
||||||
const char* InfoGetName (void)
|
const char* InfoGetName (void)
|
||||||
/* Get the name of the config file */
|
/* Get the name of the config file */
|
||||||
{
|
{
|
||||||
return InfoFile? InfoFile : "";
|
return InfoFile? InfoFile : "";
|
||||||
}
|
}
|
||||||
|
#endif /* unused */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -137,6 +137,8 @@ extern long InfoIVal;
|
||||||
extern unsigned InfoErrorLine;
|
extern unsigned InfoErrorLine;
|
||||||
extern unsigned InfoErrorCol;
|
extern unsigned InfoErrorCol;
|
||||||
|
|
||||||
|
/* Options */
|
||||||
|
extern unsigned char InfoSyncLines;
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
Loading…
Add table
Reference in a new issue