1
0
mirror of https://github.com/cc65/cc65.git synced 2024-06-07 23:29:39 +00:00

Support for preprocessing info file via cpp or m4.

This commit is contained in:
AIDA Shinra 2018-06-11 01:53:35 +09:00
parent b74ab9de89
commit 335a8972b9
4 changed files with 245 additions and 38 deletions

View 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 slashe (<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>

View 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 */
{
InfoSyncLines = 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;

View File

@ -41,6 +41,8 @@
/* common */
#include "chartype.h"
#include "xsprintf.h"
#include "xmalloc.h"
#include "strbuf.h"
/* ld65 */
#include "global.h"
@ -72,7 +74,10 @@ static int C = ' ';
static unsigned InputLine = 1;
static unsigned InputCol = 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);
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);
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)
/* 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 +360,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 +406,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 +439,13 @@ Again:
break;
case '#':
/* Comment */
while (C != '\n' && C != EOF) {
/* # lineno "sourcefile" or # comment */
if (InfoSyncLines && InputCol == 1) {
LineMarkerOrComment ();
} else {
do {
NextChar ();
} while (C != EOF && C != '\n');
NextChar ();
}
if (C != EOF) {
@ -298,6 +454,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 +655,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 */

View File

@ -137,6 +137,8 @@ extern long InfoIVal;
extern unsigned InfoErrorLine;
extern unsigned InfoErrorCol;
/* Options */
extern unsigned char InfoSyncLines;
/*****************************************************************************/