diff --git a/src/ca65/listing.c b/src/ca65/listing.c index 6eb2330bf..4994f690f 100644 --- a/src/ca65/listing.c +++ b/src/ca65/listing.c @@ -41,6 +41,7 @@ #include "check.h" #include "fname.h" #include "fragdefs.h" +#include "strbuf.h" #include "version.h" #include "xmalloc.h" @@ -81,7 +82,7 @@ static int ListingEnabled = 1; /* Enabled if > 0 */ -void NewListingLine (const char* Line, unsigned char File, unsigned char Depth) +void NewListingLine (const StrBuf* Line, unsigned char File, unsigned char Depth) /* Create a new ListLine struct and insert it */ { /* Store only if listing is enabled */ @@ -90,10 +91,10 @@ void NewListingLine (const char* Line, unsigned char File, unsigned char Depth) ListLine* L; /* Get the length of the line */ - unsigned Len = strlen (Line); + unsigned Len = SB_GetLen (Line); /* Ignore trailing newlines */ - while (Len > 0 && Line[Len-1] == '\n') { + while (Len > 0 && SB_AtUnchecked (Line, Len-1) == '\n') { --Len; } @@ -110,8 +111,8 @@ void NewListingLine (const char* Line, unsigned char File, unsigned char Depth) L->Depth = Depth; L->Output = (ListingEnabled > 0); L->ListBytes = (unsigned char) ListBytes; - memcpy (L->Line, Line, Len); - L->Line [Len] = '\0'; + memcpy (L->Line, SB_GetConstBuf (Line), Len); + L->Line[Len] = '\0'; /* Insert the line into the list of lines */ if (LineList == 0) { @@ -303,8 +304,8 @@ void CreateListing (void) /* Open the real listing file */ F = fopen (SB_GetConstBuf (&ListingName), "w"); if (F == 0) { - Fatal ("Cannot open listing file `%s': %s", - SB_GetConstBuf (&ListingName), + Fatal ("Cannot open listing file `%s': %s", + SB_GetConstBuf (&ListingName), strerror (errno)); } diff --git a/src/ca65/listing.h b/src/ca65/listing.h index 01df0c360..33debd524 100644 --- a/src/ca65/listing.h +++ b/src/ca65/listing.h @@ -6,10 +6,10 @@ /* */ /* */ /* */ -/* (C) 2000-2003 Ullrich von Bassewitz */ -/* Römerstrasse 52 */ -/* D-70794 Filderstadt */ -/* EMail: uz@cc65.org */ +/* (C) 2000-2011, Ullrich von Bassewitz */ +/* Roemerstrasse 52 */ +/* D-70794 Filderstadt */ +/* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ @@ -44,7 +44,17 @@ /*****************************************************************************/ -/* Data */ +/* Forwards */ +/*****************************************************************************/ + + + +struct StrBuf; + + + +/*****************************************************************************/ +/* Data */ /*****************************************************************************/ @@ -89,7 +99,8 @@ extern int PageLength; /* Length of a listing page */ -void NewListingLine (const char* Line, unsigned char File, unsigned char Depth); +void NewListingLine (const struct StrBuf* Line, unsigned char File, + unsigned char Depth); /* Create a new ListLine struct */ void EnableListing (void); diff --git a/src/ca65/scanner.c b/src/ca65/scanner.c index 723978a86..40b99041a 100644 --- a/src/ca65/scanner.c +++ b/src/ca65/scanner.c @@ -80,10 +80,10 @@ struct InputFile { FilePos Pos; /* Position in file */ token_t Tok; /* Last token */ int C; /* Last character */ - char Line[256]; /* The current input line */ + StrBuf Line; /* The current input line */ int IncSearchPath; /* True if we've added a search path */ int BinSearchPath; /* True if we've added a search path */ - InputFile* Next; /* Linked list of input files */ + InputFile* Next; /* Linked list of input files */ }; /* Struct to handle textual input data */ @@ -91,10 +91,10 @@ typedef struct InputData InputData; struct InputData { char* Text; /* Pointer to the text data */ const char* Pos; /* Pointer to current position */ - int Malloced; /* Memory was malloced */ + int Malloced; /* Memory was malloced */ token_t Tok; /* Last token */ - int C; /* Last character */ - InputData* Next; /* Linked list of input data */ + int C; /* Last character */ + InputData* Next; /* Linked list of input data */ }; /* Input source: Either file or data */ @@ -267,7 +267,7 @@ struct DotKeyword { { ".SEGMENT", TOK_SEGMENT }, { ".SET", TOK_SET }, { ".SETCPU", TOK_SETCPU }, - { ".SHL", TOK_SHL }, + { ".SHL", TOK_SHL }, { ".SHR", TOK_SHR }, { ".SIZEOF", TOK_SIZEOF }, { ".SMART", TOK_SMART }, @@ -363,47 +363,71 @@ static void IFNextChar (CharSource* S) /* Read the next character from the input file */ { /* Check for end of line, read the next line if needed */ - while (S->V.File.Line [S->V.File.Pos.Col] == '\0') { + while (SB_GetIndex (&S->V.File.Line) >= SB_GetLen (&S->V.File.Line)) { - unsigned Len, Removed; + unsigned Len; /* End of current line reached, read next line */ - if (fgets (S->V.File.Line, sizeof (S->V.File.Line), S->V.File.F) == 0) { - /* End of file. Add an empty line to the listing. This is a - * small hack needed to keep the PC output in sync. - */ - NewListingLine ("", S->V.File.Pos.Name, FCount); - C = EOF; - return; + SB_Clear (&S->V.File.Line); + while (1) { + + int N = fgetc (S->V.File.F); + if (N == EOF) { + /* End of file. Accept files without a newline at the end */ + if (SB_NotEmpty (&S->V.File.Line)) { + break; + } + + /* No more data - add an empty line to the listing. This + * is a small hack needed to keep the PC output in sync. + */ + NewListingLine (&EmptyStrBuf, S->V.File.Pos.Name, FCount); + C = EOF; + return; + + /* Check for end of line */ + } else if (N == '\n') { + + /* End of line */ + break; + + /* Collect other stuff */ + } else { + + /* Append data to line */ + SB_AppendChar (&S->V.File.Line, N); + + } } - /* For better handling of files with unusual line endings (DOS - * files that are accidently translated on Unix for example), - * first remove all whitespace at the end, then add a single - * newline. + + /* If we come here, we have a new input line. To avoid problems + * with strange line terminators, remove all whitespace from the + * end of the line, the add a single newline. */ - Len = strlen (S->V.File.Line); - Removed = 0; - while (Len > 0 && IsSpace (S->V.File.Line[Len-1])) { - ++Removed; + Len = SB_GetLen (&S->V.File.Line); + while (Len > 0 && IsSpace (SB_AtUnchecked (&S->V.File.Line, Len-1))) { --Len; } - if (Removed) { - S->V.File.Line[Len+0] = '\n'; - S->V.File.Line[Len+1] = '\0'; - } + SB_Drop (&S->V.File.Line, SB_GetLen (&S->V.File.Line) - Len); + SB_AppendChar (&S->V.File.Line, '\n'); + + /* Terminate the string buffer */ + SB_Terminate (&S->V.File.Line); /* One more line */ S->V.File.Pos.Line++; - S->V.File.Pos.Col = 0; /* Remember the new line for the listing */ - NewListingLine (S->V.File.Line, S->V.File.Pos.Name, FCount); + NewListingLine (&S->V.File.Line, S->V.File.Pos.Name, FCount); } - /* Return the next character from the file */ - C = S->V.File.Line [S->V.File.Pos.Col++]; + /* Set the column pointer */ + S->V.File.Pos.Col = SB_GetIndex (&S->V.File.Line); + + /* Return the next character from the buffer */ + C = SB_Get (&S->V.File.Line); } @@ -427,6 +451,9 @@ void IFDone (CharSource* S) PopSearchPath (BinSearchPath); } + /* Free the line buffer */ + SB_Done (&S->V.File.Line); + /* Close the input file and decrement the file count. We will ignore * errors here, since we were just reading from the file. */ @@ -508,7 +535,7 @@ int NewInputFile (const char* Name) S->V.File.Pos.Line = 0; S->V.File.Pos.Col = 0; S->V.File.Pos.Name = FileIdx; - S->V.File.Line[0] = '\0'; + SB_Init (&S->V.File.Line); /* Push the path for this file onto the include search lists */ SB_CopyBuf (&Path, Name, FindName (Name) - Name);