mirror of
https://github.com/pret/pokeemerald.git
synced 2026-05-19 19:18:12 -05:00
preproc: Parse cpp linemarkers
The line numbers in preproc's errors involving strings or INCBINs were incorrect before this change because all the lines from '#include'd files incremented the line number that would be reported.
This commit is contained in:
parent
a3c551fe21
commit
e38dfaa92c
|
|
@ -36,26 +36,26 @@
|
|||
CFile::CFile(const char * filenameCStr, bool isStdin, const char * graphicsRootCStr)
|
||||
{
|
||||
if (isStdin)
|
||||
m_filename = std::string{"<stdin>/"}.append(filenameCStr);
|
||||
m_location.filename = std::string{"<stdin>/"}.append(filenameCStr);
|
||||
else
|
||||
m_filename = std::string(filenameCStr);
|
||||
m_location.filename = std::string(filenameCStr);
|
||||
m_location.lineNum = 1;
|
||||
m_location.acceptLineMarker = isStdin;
|
||||
|
||||
m_buffer = ReadFileToBuffer(filenameCStr, isStdin, &m_size);
|
||||
|
||||
m_pos = 0;
|
||||
m_lineNum = 1;
|
||||
m_isStdin = isStdin;
|
||||
m_graphicsRoot = graphicsRootCStr;
|
||||
if (m_graphicsRoot.empty()) m_graphicsRoot = "./";
|
||||
if (m_graphicsRoot[m_graphicsRoot.length() - 1] != '/') m_graphicsRoot.push_back('/');
|
||||
}
|
||||
|
||||
CFile::CFile(CFile&& other) : m_filename(std::move(other.m_filename))
|
||||
CFile::CFile(CFile&& other) : m_location(std::move(other.m_location))
|
||||
{
|
||||
m_buffer = other.m_buffer;
|
||||
m_pos = other.m_pos;
|
||||
m_size = other.m_size;
|
||||
m_lineNum = other.m_lineNum;
|
||||
m_isStdin = other.m_isStdin;
|
||||
|
||||
other.m_buffer = NULL;
|
||||
|
|
@ -72,6 +72,66 @@ void CFile::Preproc()
|
|||
|
||||
while (m_pos < m_size)
|
||||
{
|
||||
if (m_location.acceptLineMarker)
|
||||
{
|
||||
if (m_buffer[m_pos] == '#')
|
||||
{
|
||||
long hashPos = m_pos;
|
||||
|
||||
long startPos;
|
||||
long lineNum;
|
||||
std::string filename;
|
||||
|
||||
m_pos++;
|
||||
|
||||
if (m_buffer[m_pos] != ' ')
|
||||
goto linemarker_error;
|
||||
m_pos++;
|
||||
|
||||
startPos = m_pos;
|
||||
if (!IsAsciiDigit(m_buffer[m_pos]))
|
||||
goto linemarker_error;
|
||||
do
|
||||
m_pos++;
|
||||
while (IsAsciiDigit(m_buffer[m_pos]));
|
||||
lineNum = atol(&m_buffer[startPos]);
|
||||
|
||||
if (m_buffer[m_pos] != ' ')
|
||||
goto linemarker_error;
|
||||
m_pos++;
|
||||
|
||||
if (m_buffer[m_pos] != '"')
|
||||
goto linemarker_error;
|
||||
m_pos++;
|
||||
|
||||
startPos = m_pos;
|
||||
while (m_pos < m_size && m_buffer[m_pos] != '"')
|
||||
m_pos++;
|
||||
filename = std::string(&m_buffer[startPos], m_pos - startPos);
|
||||
|
||||
if (m_buffer[m_pos] != '"')
|
||||
goto linemarker_error;
|
||||
m_pos++;
|
||||
|
||||
while (m_pos < m_size && m_buffer[m_pos] != '\n')
|
||||
m_pos++;
|
||||
if (m_buffer[m_pos] != '\n')
|
||||
goto linemarker_error;
|
||||
m_pos++;
|
||||
|
||||
m_location.lineNum = lineNum - 1;
|
||||
m_location.filename = std::move(filename);
|
||||
linemarker_error:
|
||||
m_location.acceptLineMarker = false;
|
||||
// Re-parse this line so that it's available to cc1.
|
||||
m_pos = hashPos;
|
||||
}
|
||||
else if (!IsAsciiWhitespace(m_buffer[m_pos]))
|
||||
{
|
||||
m_location.acceptLineMarker = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (stringChar)
|
||||
{
|
||||
if (m_buffer[m_pos] == stringChar)
|
||||
|
|
@ -89,7 +149,7 @@ void CFile::Preproc()
|
|||
else
|
||||
{
|
||||
if (m_buffer[m_pos] == '\n')
|
||||
m_lineNum++;
|
||||
Newline();
|
||||
std::putchar(m_buffer[m_pos]);
|
||||
m_pos++;
|
||||
}
|
||||
|
|
@ -108,7 +168,7 @@ void CFile::Preproc()
|
|||
std::putchar(c);
|
||||
|
||||
if (c == '\n')
|
||||
m_lineNum++;
|
||||
Newline();
|
||||
else if (c == '"')
|
||||
stringChar = '"';
|
||||
else if (c == '\'')
|
||||
|
|
@ -133,7 +193,7 @@ bool CFile::ConsumeNewline()
|
|||
if (m_buffer[m_pos] == '\r' && m_buffer[m_pos + 1] == '\n')
|
||||
{
|
||||
m_pos += 2;
|
||||
m_lineNum++;
|
||||
Newline();
|
||||
std::putchar('\n');
|
||||
return true;
|
||||
}
|
||||
|
|
@ -141,7 +201,7 @@ bool CFile::ConsumeNewline()
|
|||
if (m_buffer[m_pos] == '\n')
|
||||
{
|
||||
m_pos++;
|
||||
m_lineNum++;
|
||||
Newline();
|
||||
std::putchar('\n');
|
||||
return true;
|
||||
}
|
||||
|
|
@ -149,6 +209,12 @@ bool CFile::ConsumeNewline()
|
|||
return false;
|
||||
}
|
||||
|
||||
void CFile::Newline()
|
||||
{
|
||||
m_location.lineNum++;
|
||||
m_location.acceptLineMarker = m_isStdin;
|
||||
}
|
||||
|
||||
void CFile::SkipWhitespace()
|
||||
{
|
||||
while (ConsumeHorizontalWhitespace() || ConsumeNewline())
|
||||
|
|
@ -158,7 +224,7 @@ void CFile::SkipWhitespace()
|
|||
void CFile::TryConvertString()
|
||||
{
|
||||
long oldPos = m_pos;
|
||||
long oldLineNum = m_lineNum;
|
||||
auto oldLocation = m_location;
|
||||
bool noTerminator = false;
|
||||
|
||||
if (m_buffer[m_pos] != '_' || (m_pos > 0 && IsIdentifierChar(m_buffer[m_pos - 1])))
|
||||
|
|
@ -177,7 +243,7 @@ void CFile::TryConvertString()
|
|||
if (m_buffer[m_pos] != '(')
|
||||
{
|
||||
m_pos = oldPos;
|
||||
m_lineNum = oldLineNum;
|
||||
m_location = oldLocation;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -335,7 +401,7 @@ void CFile::TryConvertIncbin()
|
|||
int size = 1 << incbinType;
|
||||
|
||||
long oldPos = m_pos;
|
||||
long oldLineNum = m_lineNum;
|
||||
auto oldLocation = m_location;
|
||||
|
||||
m_pos += idents[incbinType].length();
|
||||
|
||||
|
|
@ -344,7 +410,7 @@ void CFile::TryConvertIncbin()
|
|||
if (m_buffer[m_pos] != '(')
|
||||
{
|
||||
m_pos = oldPos;
|
||||
m_lineNum = oldLineNum;
|
||||
m_location = oldLocation;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -412,7 +478,7 @@ void CFile::TryConvertIncgfx()
|
|||
int size = 1 << incgfxType;
|
||||
|
||||
long oldPos = m_pos;
|
||||
long oldLineNum = m_lineNum;
|
||||
auto oldLocation = m_location;
|
||||
|
||||
m_pos += idents[incgfxType].length();
|
||||
|
||||
|
|
@ -420,7 +486,7 @@ void CFile::TryConvertIncgfx()
|
|||
if (m_buffer[m_pos] != '(')
|
||||
{
|
||||
m_pos = oldPos;
|
||||
m_lineNum = oldLineNum;
|
||||
m_location = oldLocation;
|
||||
return;
|
||||
}
|
||||
m_pos++;
|
||||
|
|
@ -497,7 +563,7 @@ void CFile::ReportDiagnostic(const char* type, const char* format, std::va_list
|
|||
const int bufferSize = 1024;
|
||||
char buffer[bufferSize];
|
||||
std::vsnprintf(buffer, bufferSize, format, args);
|
||||
std::fprintf(stderr, "%s:%ld: %s: %s\n", m_filename.c_str(), m_lineNum, type, buffer);
|
||||
std::fprintf(stderr, "%s:%ld: %s: %s\n", m_location.filename.c_str(), m_location.lineNum, type, buffer);
|
||||
}
|
||||
|
||||
#define DO_REPORT(type) \
|
||||
|
|
|
|||
|
|
@ -40,13 +40,17 @@ private:
|
|||
char* m_buffer;
|
||||
long m_pos;
|
||||
long m_size;
|
||||
long m_lineNum;
|
||||
std::string m_filename;
|
||||
struct LogicalLocation {
|
||||
std::string filename;
|
||||
long lineNum;
|
||||
bool acceptLineMarker;
|
||||
} m_location;
|
||||
bool m_isStdin;
|
||||
std::string m_graphicsRoot;
|
||||
|
||||
bool ConsumeHorizontalWhitespace();
|
||||
bool ConsumeNewline();
|
||||
void Newline();
|
||||
void SkipWhitespace();
|
||||
void TryConvertString();
|
||||
std::unique_ptr<unsigned char[]> ReadWholeFile(const std::string& path, int& size);
|
||||
|
|
|
|||
|
|
@ -56,6 +56,11 @@ inline bool IsAsciiPrintable(unsigned char c)
|
|||
return (c >= ' ' && c <= '~');
|
||||
}
|
||||
|
||||
inline bool IsAsciiWhitespace(unsigned char c)
|
||||
{
|
||||
return c == ' ' || c == '\t' || c == '\f' || c == '\n' || c == '\r' || c == '\v';
|
||||
}
|
||||
|
||||
// Returns whether the character can start a C identifier or the identifier of a "{FOO}" constant in strings.
|
||||
inline bool IsIdentifierStartingChar(unsigned char c)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -204,8 +204,9 @@ void StringParser::RaiseError(const char* format, ...)
|
|||
|
||||
std::va_list args;
|
||||
va_start(args, format);
|
||||
std::vsnprintf(buffer, bufferSize, format, args);
|
||||
int n = std::vsnprintf(buffer, bufferSize, format, args);
|
||||
va_end(args);
|
||||
std::snprintf(buffer + n, bufferSize - n, " before '%.10s'", &m_buffer[m_pos]);
|
||||
|
||||
throw std::runtime_error(buffer);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user