summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tools/preproc/asm_file.cpp81
-rw-r--r--tools/preproc/asm_file.h4
-rw-r--r--tools/preproc/char_util.h6
-rw-r--r--tools/preproc/charmap.cpp2
-rw-r--r--tools/preproc/preproc.cpp15
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: