mirror of
https://github.com/cc65/cc65.git
synced 2025-01-11 11:30:13 +00:00
Added support for the #line directive.
This commit is contained in:
parent
0063f73f8a
commit
bb9c98f4c9
@ -92,6 +92,7 @@ struct AFile {
|
||||
FILE* F; /* Input file stream */
|
||||
IFile* Input; /* Points to corresponding IFile */
|
||||
int SearchPath; /* True if we've added a path for this file */
|
||||
char* PName; /* Presumed name of the file */
|
||||
PPIfStack IfStack; /* PP #if stack */
|
||||
int MissingNL; /* Last input line was missing a newline */
|
||||
};
|
||||
@ -159,6 +160,7 @@ static AFile* NewAFile (IFile* IF, FILE* F)
|
||||
AF->Line = 0;
|
||||
AF->F = F;
|
||||
AF->Input = IF;
|
||||
AF->PName = 0;
|
||||
AF->IfStack.Index = -1;
|
||||
AF->MissingNL = 0;
|
||||
|
||||
@ -209,6 +211,9 @@ static AFile* NewAFile (IFile* IF, FILE* F)
|
||||
static void FreeAFile (AFile* AF)
|
||||
/* Free an AFile structure */
|
||||
{
|
||||
if (AF->PName != 0) {
|
||||
xfree (AF->PName);
|
||||
}
|
||||
xfree (AF);
|
||||
}
|
||||
|
||||
@ -599,8 +604,8 @@ const char* GetCurrentFile (void)
|
||||
{
|
||||
unsigned AFileCount = CollCount (&AFiles);
|
||||
if (AFileCount > 0) {
|
||||
const AFile* AF = (const AFile*) CollAt (&AFiles, AFileCount-1);
|
||||
return AF->Input->Name;
|
||||
const AFile* AF = CollLast (&AFiles);
|
||||
return AF->PName == 0 ? AF->Input->Name : AF->PName;
|
||||
} else {
|
||||
/* No open file */
|
||||
return "(outside file scope)";
|
||||
@ -614,7 +619,7 @@ unsigned GetCurrentLine (void)
|
||||
{
|
||||
unsigned AFileCount = CollCount (&AFiles);
|
||||
if (AFileCount > 0) {
|
||||
const AFile* AF = (const AFile*) CollAt (&AFiles, AFileCount-1);
|
||||
const AFile* AF = CollLast (&AFiles);
|
||||
return AF->Line;
|
||||
} else {
|
||||
/* No open file */
|
||||
@ -624,6 +629,35 @@ unsigned GetCurrentLine (void)
|
||||
|
||||
|
||||
|
||||
void SetCurrentLine (unsigned LineNum)
|
||||
/* Set the line number in the current input file */
|
||||
{
|
||||
unsigned AFileCount = CollCount (&AFiles);
|
||||
if (AFileCount > 0) {
|
||||
AFile* AF = CollLast (&AFiles);
|
||||
AF->Line = LineNum;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void SetCurrentFilename (const char* Name)
|
||||
/* Set the presumed name of the current input file */
|
||||
{
|
||||
unsigned AFileCount = CollCount (&AFiles);
|
||||
if (AFileCount > 0) {
|
||||
size_t Len = strlen (Name);
|
||||
AFile* AF = CollLast (&AFiles);
|
||||
if (AF->PName != 0) {
|
||||
xfree (AF->PName);
|
||||
}
|
||||
AF->PName = xmalloc (Len + 1);
|
||||
memcpy (AF->PName, Name, Len + 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void WriteEscaped (FILE* F, const char* Name)
|
||||
/* Write a file name to a dependency file escaping spaces */
|
||||
{
|
||||
|
@ -122,6 +122,12 @@ const char* GetCurrentFile (void);
|
||||
unsigned GetCurrentLine (void);
|
||||
/* Return the line number in the current input file */
|
||||
|
||||
void SetCurrentLine (unsigned LineNum);
|
||||
/* Set the line number in the current input file */
|
||||
|
||||
void SetCurrentFilename (const char* Name);
|
||||
/* Set the presumed name of the current input file */
|
||||
|
||||
void CreateDependencies (void);
|
||||
/* Create dependency files requested by the user */
|
||||
|
||||
|
@ -57,6 +57,7 @@
|
||||
#include "ppexpr.h"
|
||||
#include "preproc.h"
|
||||
#include "scanner.h"
|
||||
#include "scanstrbuf.h"
|
||||
#include "standard.h"
|
||||
|
||||
|
||||
@ -1294,6 +1295,95 @@ Done:
|
||||
|
||||
|
||||
|
||||
static unsigned GetLineDirectiveNum (void)
|
||||
/* Get a decimal digit-sequence from the input. Return 0 on errors. */
|
||||
{
|
||||
unsigned long Num = 0;
|
||||
StrBuf Buf = AUTO_STRBUF_INITIALIZER;
|
||||
|
||||
/* The only non-decimal-numeric character allowed in the digit-sequence is
|
||||
** the digit separator '\'' as of C23, but we haven't supported it yet.
|
||||
*/
|
||||
SkipWhitespace (0);
|
||||
while (IsDigit (CurC))
|
||||
{
|
||||
SB_AppendChar (&Buf, CurC);
|
||||
NextChar ();
|
||||
}
|
||||
|
||||
/* Ensure the buffer is terminated with a '\0' */
|
||||
SB_Terminate (&Buf);
|
||||
if (SkipWhitespace (0) != 0 || CurC == '\0') {
|
||||
const char* Str = SB_GetConstBuf (&Buf);
|
||||
if (Str[0] == '\0') {
|
||||
PPWarning ("#line directive interprets number as decimal, not octal");
|
||||
} else {
|
||||
Num = strtoul (Str, 0, 10);
|
||||
if (Num > 2147483647) {
|
||||
PPError ("#line directive requires an integer argument not greater than 2147483647");
|
||||
ClearLine ();
|
||||
Num = 0;
|
||||
} else if (Num == 0) {
|
||||
PPError ("#line directive requires a positive integer argument");
|
||||
ClearLine ();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
PPError ("#line directive requires a simple decimal digit sequence");
|
||||
ClearLine ();
|
||||
}
|
||||
|
||||
/* Done with the buffer */
|
||||
SB_Done (&Buf);
|
||||
|
||||
return (unsigned)Num;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void DoLine (void)
|
||||
/* Process #line directive */
|
||||
{
|
||||
unsigned LineNum;
|
||||
|
||||
/* Macro-replace a single line with support for the "defined" operator */
|
||||
SB_Clear (MLine);
|
||||
PreprocessDirective (Line, MLine, MSM_NONE);
|
||||
|
||||
/* Read from the processed line */
|
||||
SB_Reset (MLine);
|
||||
MLine = InitLine (MLine);
|
||||
|
||||
/* Parse and check the specified line number */
|
||||
LineNum = GetLineDirectiveNum ();
|
||||
if (LineNum != 0) {
|
||||
/* Parse and check the optional filename argument */
|
||||
if (SB_GetIndex (Line) < SB_GetLen (Line)) {
|
||||
StrBuf Filename = AUTO_STRBUF_INITIALIZER;
|
||||
if (SB_GetString (Line, &Filename)) {
|
||||
SB_Terminate (&Filename);
|
||||
SetCurrentFilename (SB_GetConstBuf (&Filename));
|
||||
} else {
|
||||
PPError ("Invalid filename for #line directive");
|
||||
LineNum = 0;
|
||||
}
|
||||
SB_Done (&Filename);
|
||||
}
|
||||
|
||||
/* #line actually sets the line number of the next line */
|
||||
if (LineNum > 0) {
|
||||
SetCurrentLine (LineNum - 1);
|
||||
/* Check for extra tokens at the end */
|
||||
CheckExtraTokens ("line");
|
||||
}
|
||||
}
|
||||
|
||||
/* Restore input source */
|
||||
MLine = InitLine (MLine);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void DoPragma (void)
|
||||
/* Handle a #pragma line by converting the #pragma preprocessor directive into
|
||||
** the _Pragma() compiler operator.
|
||||
@ -1476,9 +1566,8 @@ static int ParseDirectives (unsigned ModeFlags)
|
||||
break;
|
||||
|
||||
case PPD_LINE:
|
||||
/* Should do something in C99 at least, but we ignore it */
|
||||
if (!PPSkip) {
|
||||
ClearLine ();
|
||||
DoLine ();
|
||||
}
|
||||
break;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user