mirror of
https://github.com/pret/pokeemerald.git
synced 2026-09-10 03:56:24 -05:00
Merge pull request #2294 from mrgriffin/pret-preproc-line-diagnostics
Fix line numbers in preproc diagnostics
This commit is contained in:
@@ -156,6 +156,8 @@ Directive AsmFile::GetDirective()
|
||||
return Directive::Braille;
|
||||
else if (CheckForDirective("enum"))
|
||||
return Directive::Enum;
|
||||
else if (CheckForDirective(".macro"))
|
||||
return Directive::Macro;
|
||||
else
|
||||
return Directive::Unknown;
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ enum class Directive
|
||||
String,
|
||||
Braille,
|
||||
Enum,
|
||||
Macro,
|
||||
Unknown
|
||||
};
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -98,6 +98,20 @@ void PreprocAsmFile(std::string filename, bool isStdin, bool doEnum)
|
||||
stack.top().OutputLine();
|
||||
break;
|
||||
}
|
||||
case Directive::Macro:
|
||||
{
|
||||
// GNU as misreports the filename (but not line!) when an
|
||||
// error occurs in a macro, so we work around this bug by
|
||||
// emitting an explicit location inside the macro
|
||||
// definition.
|
||||
// ... but only on the first pass, because on the second
|
||||
// pass we have lost track of our location.
|
||||
if (!isStdin)
|
||||
{
|
||||
stack.top().OutputLine();
|
||||
stack.top().OutputLocation();
|
||||
}
|
||||
}
|
||||
case Directive::Unknown:
|
||||
{
|
||||
std::string globalLabel = stack.top().GetGlobalLabel();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user