diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/preproc/asm_file.cpp | 81 | ||||
-rw-r--r-- | tools/preproc/asm_file.h | 4 | ||||
-rw-r--r-- | tools/preproc/char_util.h | 6 | ||||
-rw-r--r-- | tools/preproc/charmap.cpp | 2 | ||||
-rw-r--r-- | tools/preproc/preproc.cpp | 15 |
5 files changed, 72 insertions, 36 deletions
diff --git a/tools/preproc/asm_file.cpp b/tools/preproc/asm_file.cpp index e2f6d81c9..b05ebab3f 100644 --- a/tools/preproc/asm_file.cpp +++ b/tools/preproc/asm_file.cpp @@ -314,39 +314,63 @@ std::string AsmFile::ReadCharOrEscape() } // Reads a charmap constant, i.e. "{FOO}". -std::string AsmFile::ReadConstant() +std::string AsmFile::ReadBracketedConstants() { + std::string totalSequence; + m_pos++; // Assume we're on the left curly bracket. - long startPos = m_pos; + while (m_buffer[m_pos] != '}') + { + SkipWhitespace(); - while (IsIdentifierChar(m_buffer[m_pos])) - m_pos++; + if (IsIdentifierStartingChar(m_buffer[m_pos])) + { + long startPos = m_pos; - if (m_buffer[m_pos] != '}') - { - if (m_buffer[m_pos] == 0) + m_pos++; + + while (IsIdentifierChar(m_buffer[m_pos])) + m_pos++; + + std::string sequence = g_charmap->Constant(std::string(&m_buffer[startPos], m_pos - startPos)); + + if (sequence.length() == 0) + { + m_buffer[m_pos] = 0; + RaiseError("unknown constant '%s'", &m_buffer[startPos]); + } + + totalSequence += sequence; + } + else if (IsAsciiDigit(m_buffer[m_pos])) + { + int value = ReadInteger(255); + + if (value == -1) + RaiseError("integers within curly brackets cannot exceed 255"); + + totalSequence += (char)value; + } + else if (m_buffer[m_pos] == 0) { if (m_pos >= m_size) - RaiseError("unexpected EOF in identifier"); + RaiseError("unexpected EOF after left curly bracket"); else - RaiseError("unexpected null character in identifier"); + RaiseError("unexpected null character within curly brackets"); + } + else + { + if (IsAsciiPrintable(m_buffer[m_pos])) + RaiseError("unexpected character '%c' within curly brackets", m_buffer[m_pos]); + else + RaiseError("unexpected character '\\x%02X' within curly brackets", m_buffer[m_pos]); } - - RaiseError("unexpected character in identifier"); - } - - std::string sequence = g_charmap->Constant(std::string(&m_buffer[startPos], m_pos - startPos)); - - if (sequence.length() == 0) - { - m_buffer[m_pos] = 0; - RaiseError("unknown constant '%s'", &m_buffer[startPos]); } m_pos++; // Go past the right curly bracket. - return sequence; + return totalSequence; } // Reads a charmap string. @@ -363,7 +387,7 @@ int AsmFile::ReadString(unsigned char* s) while (m_buffer[m_pos] != '"') { - std::string sequence = (m_buffer[m_pos] == '{') ? ReadConstant() : ReadCharOrEscape(); + std::string sequence = (m_buffer[m_pos] == '{') ? ReadBracketedConstants() : ReadCharOrEscape(); for (const char& c : sequence) { @@ -381,7 +405,10 @@ int AsmFile::ReadString(unsigned char* s) if (ConsumeComma()) { SkipWhitespace(); - int padLength = ReadPadLength(); + int padLength = ReadInteger(kMaxStringLength); + + if (padLength == -1) + RaiseError("pad length greater than maximum length (%d)", kMaxStringLength); while (length < padLength) { @@ -424,8 +451,8 @@ static int ConvertDigit(char c, int radix) return (digit < radix) ? digit : -1; } -// Reads the pad length for a charmap string. -int AsmFile::ReadPadLength() +// Reads an integer. If the integer is greater than maxValue, it returns -1. +int AsmFile::ReadInteger(int maxValue) { if (!IsAsciiDigit(m_buffer[m_pos])) RaiseError("expected integer"); @@ -438,15 +465,15 @@ int AsmFile::ReadPadLength() m_pos += 2; } - int n = 0; + unsigned n = 0; int digit; while ((digit = ConvertDigit(m_buffer[m_pos], radix)) != -1) { n = n * radix + digit; - if (n > kMaxStringLength) - RaiseError("pad length greater than maximum length (%d)", kMaxStringLength); + if (n > (unsigned)maxValue) + return -1; m_pos++; } diff --git a/tools/preproc/asm_file.h b/tools/preproc/asm_file.h index f6bfe8a36..398c46a36 100644 --- a/tools/preproc/asm_file.h +++ b/tools/preproc/asm_file.h @@ -56,11 +56,11 @@ private: std::string m_filename; bool ConsumeComma(); - int ReadPadLength(); + int ReadInteger(int maxValue); void RemoveComments(); bool CheckForDirective(std::string name); std::string ReadCharOrEscape(); - std::string ReadConstant(); + std::string ReadBracketedConstants(); void SkipWhitespace(); void ExpectEmptyRestOfLine(); void ReportDiagnostic(const char* type, const char* format, std::va_list args); diff --git a/tools/preproc/char_util.h b/tools/preproc/char_util.h index 05f9a1dd4..ab20dbc53 100644 --- a/tools/preproc/char_util.h +++ b/tools/preproc/char_util.h @@ -56,6 +56,12 @@ inline bool IsAsciiPrintable(unsigned char c) return (c >= ' ' && c <= '~'); } +// Returns whether the character can start the identifier of a "{FOO}" constant in strings. +inline bool IsIdentifierStartingChar(unsigned char c) +{ + return IsAsciiAlpha(c) || c == '_'; +} + // Returns whether the character can be used in the identifier of a "{FOO}" constant in strings. inline bool IsIdentifierChar(unsigned char c) { diff --git a/tools/preproc/charmap.cpp b/tools/preproc/charmap.cpp index c7091c4b8..573981694 100644 --- a/tools/preproc/charmap.cpp +++ b/tools/preproc/charmap.cpp @@ -183,7 +183,7 @@ Lhs CharmapReader::ReadLhs() lhs.type = LhsType::Char; } } - else if (IsIdentifierChar(m_buffer[m_pos])) + else if (IsIdentifierStartingChar(m_buffer[m_pos])) { lhs.type = LhsType::Constant; lhs.name = ReadConstant(); diff --git a/tools/preproc/preproc.cpp b/tools/preproc/preproc.cpp index 7fc3f5c10..4f216f23a 100644 --- a/tools/preproc/preproc.cpp +++ b/tools/preproc/preproc.cpp @@ -64,15 +64,18 @@ int main(int argc, char **argv) unsigned char s[kMaxStringLength]; int length = stack.top().ReadString(s); - printf("\t.byte "); - for (int i = 0; i < length; i++) + if (length > 0) { - printf("0x%02X", s[i]); + printf("\t.byte "); + for (int i = 0; i < length; i++) + { + printf("0x%02X", s[i]); - if (i < length - 1) - printf(", "); + if (i < length - 1) + printf(", "); + } + putchar('\n'); } - putchar('\n'); break; } case Directive::Unknown: |