mirror of
https://github.com/zeldaret/tmc
synced 2026-09-03 02:13:43 -04:00
apply clang-format to tool sources
This commit is contained in:
Executable → Regular
+69
-165
@@ -27,9 +27,8 @@
|
||||
#include "utf8.h"
|
||||
#include "string_parser.h"
|
||||
|
||||
AsmFile::AsmFile(std::string filename) : m_filename(filename)
|
||||
{
|
||||
FILE *fp = std::fopen(filename.c_str(), "rb");
|
||||
AsmFile::AsmFile(std::string filename) : m_filename(filename) {
|
||||
FILE* fp = std::fopen(filename.c_str(), "rb");
|
||||
|
||||
if (fp == NULL) {
|
||||
// The include might be an asset.
|
||||
@@ -64,8 +63,7 @@ AsmFile::AsmFile(std::string filename) : m_filename(filename)
|
||||
RemoveComments();
|
||||
}
|
||||
|
||||
AsmFile::AsmFile(AsmFile&& other) : m_filename(std::move(other.m_filename))
|
||||
{
|
||||
AsmFile::AsmFile(AsmFile&& other) : m_filename(std::move(other.m_filename)) {
|
||||
m_buffer = other.m_buffer;
|
||||
m_pos = other.m_pos;
|
||||
m_size = other.m_size;
|
||||
@@ -75,8 +73,7 @@ AsmFile::AsmFile(AsmFile&& other) : m_filename(std::move(other.m_filename))
|
||||
other.m_buffer = nullptr;
|
||||
}
|
||||
|
||||
AsmFile::~AsmFile()
|
||||
{
|
||||
AsmFile::~AsmFile() {
|
||||
delete[] m_buffer;
|
||||
}
|
||||
|
||||
@@ -84,60 +81,44 @@ AsmFile::~AsmFile()
|
||||
// It stops upon encountering a null character,
|
||||
// which may or may not be the end of file marker.
|
||||
// If it's not, the error will be caught later.
|
||||
void AsmFile::RemoveComments()
|
||||
{
|
||||
void AsmFile::RemoveComments() {
|
||||
long pos = 0;
|
||||
char stringChar = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
for (;;) {
|
||||
if (m_buffer[pos] == 0)
|
||||
return;
|
||||
|
||||
if (stringChar != 0)
|
||||
{
|
||||
if (m_buffer[pos] == '\\' && m_buffer[pos + 1] == stringChar)
|
||||
{
|
||||
if (stringChar != 0) {
|
||||
if (m_buffer[pos] == '\\' && m_buffer[pos + 1] == stringChar) {
|
||||
pos += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
if (m_buffer[pos] == stringChar)
|
||||
stringChar = 0;
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
else if (m_buffer[pos] == '@' && (pos == 0 || m_buffer[pos - 1] != '\\'))
|
||||
{
|
||||
} else if (m_buffer[pos] == '@' && (pos == 0 || m_buffer[pos - 1] != '\\')) {
|
||||
while (m_buffer[pos] != '\n' && m_buffer[pos] != 0)
|
||||
m_buffer[pos++] = ' ';
|
||||
}
|
||||
else if (m_buffer[pos] == '/' && m_buffer[pos + 1] == '*')
|
||||
{
|
||||
} else if (m_buffer[pos] == '/' && m_buffer[pos + 1] == '*') {
|
||||
m_buffer[pos++] = ' ';
|
||||
m_buffer[pos++] = ' ';
|
||||
|
||||
for (;;)
|
||||
{
|
||||
for (;;) {
|
||||
if (m_buffer[pos] == 0)
|
||||
return;
|
||||
|
||||
if (m_buffer[pos] == '*' && m_buffer[pos + 1] == '/')
|
||||
{
|
||||
if (m_buffer[pos] == '*' && m_buffer[pos + 1] == '/') {
|
||||
m_buffer[pos++] = ' ';
|
||||
m_buffer[pos++] = ' ';
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
if (m_buffer[pos] != '\n')
|
||||
m_buffer[pos] = ' ';
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
if (m_buffer[pos] == '"' || m_buffer[pos] == '\'')
|
||||
stringChar = m_buffer[pos];
|
||||
pos++;
|
||||
@@ -147,8 +128,7 @@ void AsmFile::RemoveComments()
|
||||
|
||||
// Checks if we're at a particular directive and if so, consumes it.
|
||||
// Returns whether the directive was found.
|
||||
bool AsmFile::CheckForDirective(std::string name)
|
||||
{
|
||||
bool AsmFile::CheckForDirective(std::string name) {
|
||||
long i;
|
||||
long length = static_cast<long>(name.length());
|
||||
|
||||
@@ -166,8 +146,7 @@ bool AsmFile::CheckForDirective(std::string name)
|
||||
|
||||
// Checks if we're at a known directive and if so, consumes it.
|
||||
// Returns which directive was found.
|
||||
Directive AsmFile::GetDirective()
|
||||
{
|
||||
Directive AsmFile::GetDirective() {
|
||||
SkipWhitespace();
|
||||
|
||||
if (CheckForDirective(".include"))
|
||||
@@ -182,21 +161,18 @@ Directive AsmFile::GetDirective()
|
||||
|
||||
// Checks if we're at label that ends with '::'.
|
||||
// Returns the name if so and an empty string if not.
|
||||
std::string AsmFile::GetGlobalLabel()
|
||||
{
|
||||
std::string AsmFile::GetGlobalLabel() {
|
||||
long start = m_pos;
|
||||
long pos = m_pos;
|
||||
|
||||
if (IsIdentifierStartingChar(m_buffer[pos]))
|
||||
{
|
||||
if (IsIdentifierStartingChar(m_buffer[pos])) {
|
||||
pos++;
|
||||
|
||||
while (IsIdentifierChar(m_buffer[pos]))
|
||||
pos++;
|
||||
}
|
||||
|
||||
if (m_buffer[pos] == ':' && m_buffer[pos + 1] == ':')
|
||||
{
|
||||
if (m_buffer[pos] == ':' && m_buffer[pos + 1] == ':') {
|
||||
m_pos = pos + 2;
|
||||
ExpectEmptyRestOfLine();
|
||||
return std::string(&m_buffer[start], pos - start);
|
||||
@@ -206,15 +182,13 @@ std::string AsmFile::GetGlobalLabel()
|
||||
}
|
||||
|
||||
// Skips tabs and spaces.
|
||||
void AsmFile::SkipWhitespace()
|
||||
{
|
||||
void AsmFile::SkipWhitespace() {
|
||||
while (m_buffer[m_pos] == '\t' || m_buffer[m_pos] == ' ')
|
||||
m_pos++;
|
||||
}
|
||||
|
||||
// Reads include path.
|
||||
std::string AsmFile::ReadPath()
|
||||
{
|
||||
std::string AsmFile::ReadPath() {
|
||||
SkipWhitespace();
|
||||
|
||||
if (m_buffer[m_pos] != '"')
|
||||
@@ -225,12 +199,10 @@ std::string AsmFile::ReadPath()
|
||||
int length = 0;
|
||||
long startPos = m_pos;
|
||||
|
||||
while (m_buffer[m_pos] != '"')
|
||||
{
|
||||
while (m_buffer[m_pos] != '"') {
|
||||
unsigned char c = m_buffer[m_pos++];
|
||||
|
||||
if (c == 0)
|
||||
{
|
||||
if (c == 0) {
|
||||
if (m_pos >= m_size)
|
||||
RaiseError("unexpected EOF in include string");
|
||||
else
|
||||
@@ -241,8 +213,7 @@ std::string AsmFile::ReadPath()
|
||||
RaiseError("unexpected character '\\x%02X' in include string", c);
|
||||
|
||||
// Don't bother allowing any escape sequences.
|
||||
if (c == '\\')
|
||||
{
|
||||
if (c == '\\') {
|
||||
c = m_buffer[m_pos];
|
||||
RaiseError("unexpected escape '\\%c' in include string", c);
|
||||
}
|
||||
@@ -261,31 +232,23 @@ std::string AsmFile::ReadPath()
|
||||
}
|
||||
|
||||
// Reads a charmap string.
|
||||
int AsmFile::ReadString(unsigned char* s)
|
||||
{
|
||||
int AsmFile::ReadString(unsigned char* s) {
|
||||
SkipWhitespace();
|
||||
|
||||
int length;
|
||||
StringParser stringParser(m_buffer, m_size);
|
||||
|
||||
try
|
||||
{
|
||||
try {
|
||||
m_pos += stringParser.ParseString(m_pos, s, length);
|
||||
}
|
||||
catch (std::runtime_error& e)
|
||||
{
|
||||
RaiseError(e.what());
|
||||
}
|
||||
} catch (std::runtime_error& e) { RaiseError(e.what()); }
|
||||
|
||||
SkipWhitespace();
|
||||
|
||||
if (ConsumeComma())
|
||||
{
|
||||
if (ConsumeComma()) {
|
||||
SkipWhitespace();
|
||||
int padLength = ReadPadLength();
|
||||
|
||||
while (length < padLength)
|
||||
{
|
||||
while (length < padLength) {
|
||||
s[length++] = 0;
|
||||
}
|
||||
}
|
||||
@@ -295,40 +258,13 @@ int AsmFile::ReadString(unsigned char* s)
|
||||
return length;
|
||||
}
|
||||
|
||||
int AsmFile::ReadBraille(unsigned char* s)
|
||||
{
|
||||
static std::map<char, unsigned char> encoding =
|
||||
{
|
||||
{ 'A', 0x01 },
|
||||
{ 'B', 0x05 },
|
||||
{ 'C', 0x03 },
|
||||
{ 'D', 0x0B },
|
||||
{ 'E', 0x09 },
|
||||
{ 'F', 0x07 },
|
||||
{ 'G', 0x0F },
|
||||
{ 'H', 0x0D },
|
||||
{ 'I', 0x06 },
|
||||
{ 'J', 0x0E },
|
||||
{ 'K', 0x11 },
|
||||
{ 'L', 0x15 },
|
||||
{ 'M', 0x13 },
|
||||
{ 'N', 0x1B },
|
||||
{ 'O', 0x19 },
|
||||
{ 'P', 0x17 },
|
||||
{ 'Q', 0x1F },
|
||||
{ 'R', 0x1D },
|
||||
{ 'S', 0x16 },
|
||||
{ 'T', 0x1E },
|
||||
{ 'U', 0x31 },
|
||||
{ 'V', 0x35 },
|
||||
{ 'W', 0x2E },
|
||||
{ 'X', 0x33 },
|
||||
{ 'Y', 0x3B },
|
||||
{ 'Z', 0x39 },
|
||||
{ ' ', 0x00 },
|
||||
{ ',', 0x04 },
|
||||
{ '.', 0x2C },
|
||||
{ '$', 0xFF },
|
||||
int AsmFile::ReadBraille(unsigned char* s) {
|
||||
static std::map<char, unsigned char> encoding = {
|
||||
{ 'A', 0x01 }, { 'B', 0x05 }, { 'C', 0x03 }, { 'D', 0x0B }, { 'E', 0x09 }, { 'F', 0x07 },
|
||||
{ 'G', 0x0F }, { 'H', 0x0D }, { 'I', 0x06 }, { 'J', 0x0E }, { 'K', 0x11 }, { 'L', 0x15 },
|
||||
{ 'M', 0x13 }, { 'N', 0x1B }, { 'O', 0x19 }, { 'P', 0x17 }, { 'Q', 0x1F }, { 'R', 0x1D },
|
||||
{ 'S', 0x16 }, { 'T', 0x1E }, { 'U', 0x31 }, { 'V', 0x35 }, { 'W', 0x2E }, { 'X', 0x33 },
|
||||
{ 'Y', 0x3B }, { 'Z', 0x39 }, { ' ', 0x00 }, { ',', 0x04 }, { '.', 0x2C }, { '$', 0xFF },
|
||||
};
|
||||
|
||||
SkipWhitespace();
|
||||
@@ -340,22 +276,17 @@ int AsmFile::ReadBraille(unsigned char* s)
|
||||
|
||||
m_pos++;
|
||||
|
||||
while (m_buffer[m_pos] != '"')
|
||||
{
|
||||
while (m_buffer[m_pos] != '"') {
|
||||
if (length == kMaxStringLength)
|
||||
RaiseError("mapped string longer than %d bytes", kMaxStringLength);
|
||||
|
||||
if (m_buffer[m_pos] == '\\' && m_buffer[m_pos + 1] == 'n')
|
||||
{
|
||||
if (m_buffer[m_pos] == '\\' && m_buffer[m_pos + 1] == 'n') {
|
||||
s[length++] = 0xFE;
|
||||
m_pos += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
char c = m_buffer[m_pos];
|
||||
|
||||
if (encoding.count(c) == 0)
|
||||
{
|
||||
if (encoding.count(c) == 0) {
|
||||
if (IsAsciiPrintable(c))
|
||||
RaiseError("character '%c' not valid in braille string", m_buffer[m_pos]);
|
||||
else
|
||||
@@ -376,10 +307,8 @@ int AsmFile::ReadBraille(unsigned char* s)
|
||||
|
||||
// If we're at a comma, consumes it.
|
||||
// Returns whether a comma was found.
|
||||
bool AsmFile::ConsumeComma()
|
||||
{
|
||||
if (m_buffer[m_pos] == ',')
|
||||
{
|
||||
bool AsmFile::ConsumeComma() {
|
||||
if (m_buffer[m_pos] == ',') {
|
||||
m_pos++;
|
||||
return true;
|
||||
}
|
||||
@@ -388,8 +317,7 @@ bool AsmFile::ConsumeComma()
|
||||
}
|
||||
|
||||
// Converts digit character to numerical value.
|
||||
static int ConvertDigit(char c, int radix)
|
||||
{
|
||||
static int ConvertDigit(char c, int radix) {
|
||||
int digit;
|
||||
|
||||
if (c >= '0' && c <= '9')
|
||||
@@ -405,15 +333,13 @@ static int ConvertDigit(char c, int radix)
|
||||
}
|
||||
|
||||
// Reads an integer. If the integer is greater than maxValue, it returns -1.
|
||||
int AsmFile::ReadPadLength()
|
||||
{
|
||||
int AsmFile::ReadPadLength() {
|
||||
if (!IsAsciiDigit(m_buffer[m_pos]))
|
||||
RaiseError("expected integer");
|
||||
|
||||
int radix = 10;
|
||||
|
||||
if (m_buffer[m_pos] == '0' && m_buffer[m_pos + 1] == 'x')
|
||||
{
|
||||
if (m_buffer[m_pos] == '0' && m_buffer[m_pos + 1] == 'x') {
|
||||
radix = 16;
|
||||
m_pos += 2;
|
||||
}
|
||||
@@ -421,8 +347,7 @@ int AsmFile::ReadPadLength()
|
||||
unsigned n = 0;
|
||||
int digit;
|
||||
|
||||
while ((digit = ConvertDigit(m_buffer[m_pos], radix)) != -1)
|
||||
{
|
||||
while ((digit = ConvertDigit(m_buffer[m_pos], radix)) != -1) {
|
||||
n = n * radix + digit;
|
||||
|
||||
if (n > kMaxStringLength)
|
||||
@@ -435,25 +360,18 @@ int AsmFile::ReadPadLength()
|
||||
}
|
||||
|
||||
// Outputs the current line and moves to the next one.
|
||||
void AsmFile::OutputLine()
|
||||
{
|
||||
void AsmFile::OutputLine() {
|
||||
while (m_buffer[m_pos] != '\n' && m_buffer[m_pos] != 0)
|
||||
m_pos++;
|
||||
|
||||
if (m_buffer[m_pos] == 0)
|
||||
{
|
||||
if (m_pos >= m_size)
|
||||
{
|
||||
if (m_buffer[m_pos] == 0) {
|
||||
if (m_pos >= m_size) {
|
||||
RaiseWarning("file doesn't end with newline");
|
||||
puts(&m_buffer[m_lineStart]);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
RaiseError("unexpected null character");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
m_buffer[m_pos] = 0;
|
||||
puts(&m_buffer[m_lineStart]);
|
||||
m_buffer[m_pos] = '\n';
|
||||
@@ -464,72 +382,58 @@ void AsmFile::OutputLine()
|
||||
}
|
||||
|
||||
// Asserts that the rest of the line is empty and moves to the next one.
|
||||
void AsmFile::ExpectEmptyRestOfLine()
|
||||
{
|
||||
void AsmFile::ExpectEmptyRestOfLine() {
|
||||
SkipWhitespace();
|
||||
|
||||
if (m_buffer[m_pos] == 0)
|
||||
{
|
||||
if (m_buffer[m_pos] == 0) {
|
||||
if (m_pos >= m_size)
|
||||
RaiseWarning("file doesn't end with newline");
|
||||
else
|
||||
RaiseError("unexpected null character");
|
||||
}
|
||||
else if (m_buffer[m_pos] == '\n')
|
||||
{
|
||||
} else if (m_buffer[m_pos] == '\n') {
|
||||
m_pos++;
|
||||
m_lineStart = m_pos;
|
||||
m_lineNum++;
|
||||
}
|
||||
else if (m_buffer[m_pos] == '\r')
|
||||
{
|
||||
} else if (m_buffer[m_pos] == '\r') {
|
||||
RaiseError("only Unix-style LF newlines are supported");
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
RaiseError("junk at end of line");
|
||||
}
|
||||
}
|
||||
|
||||
// Checks if we're at the end of the file.
|
||||
bool AsmFile::IsAtEnd()
|
||||
{
|
||||
bool AsmFile::IsAtEnd() {
|
||||
return (m_pos >= m_size);
|
||||
}
|
||||
|
||||
// Output the current location to set gas's logical file and line numbers.
|
||||
void AsmFile::OutputLocation()
|
||||
{
|
||||
void AsmFile::OutputLocation() {
|
||||
std::printf("# %ld \"%s\"\n", m_lineNum, m_filename.c_str());
|
||||
}
|
||||
|
||||
// Reports a diagnostic message.
|
||||
void AsmFile::ReportDiagnostic(const char* type, const char* format, std::va_list args)
|
||||
{
|
||||
void AsmFile::ReportDiagnostic(const char* type, const char* format, std::va_list args) {
|
||||
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);
|
||||
}
|
||||
|
||||
#define DO_REPORT(type) \
|
||||
do \
|
||||
{ \
|
||||
std::va_list args; \
|
||||
va_start(args, format); \
|
||||
ReportDiagnostic(type, format, args); \
|
||||
va_end(args); \
|
||||
} while (0)
|
||||
#define DO_REPORT(type) \
|
||||
do { \
|
||||
std::va_list args; \
|
||||
va_start(args, format); \
|
||||
ReportDiagnostic(type, format, args); \
|
||||
va_end(args); \
|
||||
} while (0)
|
||||
|
||||
// Reports an error diagnostic and terminates the program.
|
||||
void AsmFile::RaiseError(const char* format, ...)
|
||||
{
|
||||
void AsmFile::RaiseError(const char* format, ...) {
|
||||
DO_REPORT("error");
|
||||
std::exit(1);
|
||||
}
|
||||
|
||||
// Reports a warning diagnostic.
|
||||
void AsmFile::RaiseWarning(const char* format, ...)
|
||||
{
|
||||
void AsmFile::RaiseWarning(const char* format, ...) {
|
||||
DO_REPORT("warning");
|
||||
}
|
||||
|
||||
Executable → Regular
+4
-11
@@ -26,17 +26,10 @@
|
||||
#include <string>
|
||||
#include "preproc.h"
|
||||
|
||||
enum class Directive
|
||||
{
|
||||
Include,
|
||||
String,
|
||||
Braille,
|
||||
Unknown
|
||||
};
|
||||
enum class Directive { Include, String, Braille, Unknown };
|
||||
|
||||
class AsmFile
|
||||
{
|
||||
public:
|
||||
class AsmFile {
|
||||
public:
|
||||
AsmFile(std::string filename);
|
||||
AsmFile(AsmFile&& other);
|
||||
AsmFile(const AsmFile&) = delete;
|
||||
@@ -50,7 +43,7 @@ public:
|
||||
void OutputLine();
|
||||
void OutputLocation();
|
||||
|
||||
private:
|
||||
private:
|
||||
char* m_buffer;
|
||||
long m_pos;
|
||||
long m_size;
|
||||
|
||||
Executable → Regular
+58
-111
@@ -29,9 +29,8 @@
|
||||
#include "utf8.h"
|
||||
#include "string_parser.h"
|
||||
|
||||
CFile::CFile(std::string filename) : m_filename(filename)
|
||||
{
|
||||
FILE *fp = std::fopen(filename.c_str(), "rb");
|
||||
CFile::CFile(std::string filename) : m_filename(filename) {
|
||||
FILE* fp = std::fopen(filename.c_str(), "rb");
|
||||
|
||||
if (fp == NULL)
|
||||
FATAL_ERROR("Failed to open \"%s\" for reading.\n", filename.c_str());
|
||||
@@ -58,8 +57,7 @@ CFile::CFile(std::string filename) : m_filename(filename)
|
||||
m_lineNum = 1;
|
||||
}
|
||||
|
||||
CFile::CFile(CFile&& other) : m_filename(std::move(other.m_filename))
|
||||
{
|
||||
CFile::CFile(CFile&& other) : m_filename(std::move(other.m_filename)) {
|
||||
m_buffer = other.m_buffer;
|
||||
m_pos = other.m_pos;
|
||||
m_size = other.m_size;
|
||||
@@ -68,41 +66,30 @@ CFile::CFile(CFile&& other) : m_filename(std::move(other.m_filename))
|
||||
other.m_buffer = nullptr;
|
||||
}
|
||||
|
||||
CFile::~CFile()
|
||||
{
|
||||
CFile::~CFile() {
|
||||
delete[] m_buffer;
|
||||
}
|
||||
|
||||
void CFile::Preproc()
|
||||
{
|
||||
void CFile::Preproc() {
|
||||
char stringChar = 0;
|
||||
|
||||
while (m_pos < m_size)
|
||||
{
|
||||
if (stringChar)
|
||||
{
|
||||
if (m_buffer[m_pos] == stringChar)
|
||||
{
|
||||
while (m_pos < m_size) {
|
||||
if (stringChar) {
|
||||
if (m_buffer[m_pos] == stringChar) {
|
||||
std::putchar(stringChar);
|
||||
m_pos++;
|
||||
stringChar = 0;
|
||||
}
|
||||
else if (m_buffer[m_pos] == '\\' && m_buffer[m_pos + 1] == stringChar)
|
||||
{
|
||||
} else if (m_buffer[m_pos] == '\\' && m_buffer[m_pos + 1] == stringChar) {
|
||||
std::putchar('\\');
|
||||
std::putchar(stringChar);
|
||||
m_pos += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
if (m_buffer[m_pos] == '\n')
|
||||
m_lineNum++;
|
||||
std::putchar(m_buffer[m_pos]);
|
||||
m_pos++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
TryConvertString();
|
||||
TryConvertIncbin();
|
||||
|
||||
@@ -123,10 +110,8 @@ void CFile::Preproc()
|
||||
}
|
||||
}
|
||||
|
||||
bool CFile::ConsumeHorizontalWhitespace()
|
||||
{
|
||||
if (m_buffer[m_pos] == '\t' || m_buffer[m_pos] == ' ')
|
||||
{
|
||||
bool CFile::ConsumeHorizontalWhitespace() {
|
||||
if (m_buffer[m_pos] == '\t' || m_buffer[m_pos] == ' ') {
|
||||
m_pos++;
|
||||
return true;
|
||||
}
|
||||
@@ -134,18 +119,15 @@ bool CFile::ConsumeHorizontalWhitespace()
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CFile::ConsumeNewline()
|
||||
{
|
||||
if (m_buffer[m_pos] == '\r' && m_buffer[m_pos + 1] == '\n')
|
||||
{
|
||||
bool CFile::ConsumeNewline() {
|
||||
if (m_buffer[m_pos] == '\r' && m_buffer[m_pos + 1] == '\n') {
|
||||
m_pos += 2;
|
||||
m_lineNum++;
|
||||
std::putchar('\n');
|
||||
return true;
|
||||
}
|
||||
|
||||
if (m_buffer[m_pos] == '\n')
|
||||
{
|
||||
if (m_buffer[m_pos] == '\n') {
|
||||
m_pos++;
|
||||
m_lineNum++;
|
||||
std::putchar('\n');
|
||||
@@ -155,14 +137,12 @@ bool CFile::ConsumeNewline()
|
||||
return false;
|
||||
}
|
||||
|
||||
void CFile::SkipWhitespace()
|
||||
{
|
||||
void CFile::SkipWhitespace() {
|
||||
while (ConsumeHorizontalWhitespace() || ConsumeNewline())
|
||||
;
|
||||
}
|
||||
|
||||
void CFile::TryConvertString()
|
||||
{
|
||||
void CFile::TryConvertString() {
|
||||
long oldPos = m_pos;
|
||||
long oldLineNum = m_lineNum;
|
||||
bool noTerminator = false;
|
||||
@@ -172,16 +152,14 @@ void CFile::TryConvertString()
|
||||
|
||||
m_pos++;
|
||||
|
||||
if (m_buffer[m_pos] == '_')
|
||||
{
|
||||
if (m_buffer[m_pos] == '_') {
|
||||
noTerminator = true;
|
||||
m_pos++;
|
||||
}
|
||||
|
||||
SkipWhitespace();
|
||||
|
||||
if (m_buffer[m_pos] != '(')
|
||||
{
|
||||
if (m_buffer[m_pos] != '(') {
|
||||
m_pos = oldPos;
|
||||
m_lineNum = oldLineNum;
|
||||
return;
|
||||
@@ -193,35 +171,24 @@ void CFile::TryConvertString()
|
||||
|
||||
std::printf("{ ");
|
||||
|
||||
while (1)
|
||||
{
|
||||
while (1) {
|
||||
SkipWhitespace();
|
||||
|
||||
if (m_buffer[m_pos] == '"')
|
||||
{
|
||||
if (m_buffer[m_pos] == '"') {
|
||||
unsigned char s[kMaxStringLength];
|
||||
int length;
|
||||
StringParser stringParser(m_buffer, m_size);
|
||||
|
||||
try
|
||||
{
|
||||
try {
|
||||
m_pos += stringParser.ParseString(m_pos, s, length);
|
||||
}
|
||||
catch (std::runtime_error& e)
|
||||
{
|
||||
RaiseError(e.what());
|
||||
}
|
||||
} catch (std::runtime_error& e) { RaiseError(e.what()); }
|
||||
|
||||
for (int i = 0; i < length; i++)
|
||||
printf("0x%02X, ", s[i]);
|
||||
}
|
||||
else if (m_buffer[m_pos] == ')')
|
||||
{
|
||||
} else if (m_buffer[m_pos] == ')') {
|
||||
m_pos++;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
if (m_pos >= m_size)
|
||||
RaiseError("unexpected EOF");
|
||||
if (IsAsciiPrintable(m_buffer[m_pos]))
|
||||
@@ -237,8 +204,7 @@ void CFile::TryConvertString()
|
||||
std::printf("0xFF }");
|
||||
}
|
||||
|
||||
bool CFile::CheckIdentifier(const std::string& ident)
|
||||
{
|
||||
bool CFile::CheckIdentifier(const std::string& ident) {
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ident.length() && m_pos + i < (unsigned)m_size; i++)
|
||||
@@ -248,8 +214,7 @@ bool CFile::CheckIdentifier(const std::string& ident)
|
||||
return (i == ident.length());
|
||||
}
|
||||
|
||||
std::unique_ptr<unsigned char[]> CFile::ReadWholeFile(const std::string& path, int& size)
|
||||
{
|
||||
std::unique_ptr<unsigned char[]> CFile::ReadWholeFile(const std::string& path, int& size) {
|
||||
FILE* fp = std::fopen(path.c_str(), "rb");
|
||||
|
||||
if (fp == nullptr)
|
||||
@@ -271,34 +236,25 @@ std::unique_ptr<unsigned char[]> CFile::ReadWholeFile(const std::string& path, i
|
||||
return buffer;
|
||||
}
|
||||
|
||||
int ExtractData(const std::unique_ptr<unsigned char[]>& buffer, int offset, int size)
|
||||
{
|
||||
switch (size)
|
||||
{
|
||||
case 1:
|
||||
return buffer[offset];
|
||||
case 2:
|
||||
return (buffer[offset + 1] << 8)
|
||||
| buffer[offset];
|
||||
case 4:
|
||||
return (buffer[offset + 3] << 24)
|
||||
| (buffer[offset + 2] << 16)
|
||||
| (buffer[offset + 1] << 8)
|
||||
| buffer[offset];
|
||||
default:
|
||||
FATAL_ERROR("Invalid size passed to ExtractData.\n");
|
||||
int ExtractData(const std::unique_ptr<unsigned char[]>& buffer, int offset, int size) {
|
||||
switch (size) {
|
||||
case 1:
|
||||
return buffer[offset];
|
||||
case 2:
|
||||
return (buffer[offset + 1] << 8) | buffer[offset];
|
||||
case 4:
|
||||
return (buffer[offset + 3] << 24) | (buffer[offset + 2] << 16) | (buffer[offset + 1] << 8) | buffer[offset];
|
||||
default:
|
||||
FATAL_ERROR("Invalid size passed to ExtractData.\n");
|
||||
}
|
||||
}
|
||||
|
||||
void CFile::TryConvertIncbin()
|
||||
{
|
||||
void CFile::TryConvertIncbin() {
|
||||
std::string idents[6] = { "INCBIN_S8", "INCBIN_U8", "INCBIN_S16", "INCBIN_U16", "INCBIN_S32", "INCBIN_U32" };
|
||||
int incbinType = -1;
|
||||
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
if (CheckIdentifier(idents[i]))
|
||||
{
|
||||
for (int i = 0; i < 6; i++) {
|
||||
if (CheckIdentifier(idents[i])) {
|
||||
incbinType = i;
|
||||
break;
|
||||
}
|
||||
@@ -317,8 +273,7 @@ void CFile::TryConvertIncbin()
|
||||
|
||||
SkipWhitespace();
|
||||
|
||||
if (m_buffer[m_pos] != '(')
|
||||
{
|
||||
if (m_buffer[m_pos] != '(') {
|
||||
m_pos = oldPos;
|
||||
m_lineNum = oldLineNum;
|
||||
return;
|
||||
@@ -328,8 +283,7 @@ void CFile::TryConvertIncbin()
|
||||
|
||||
std::printf("{");
|
||||
|
||||
while (true)
|
||||
{
|
||||
while (true) {
|
||||
SkipWhitespace();
|
||||
|
||||
if (m_buffer[m_pos] != '"')
|
||||
@@ -339,10 +293,8 @@ void CFile::TryConvertIncbin()
|
||||
|
||||
int startPos = m_pos;
|
||||
|
||||
while (m_buffer[m_pos] != '"')
|
||||
{
|
||||
if (m_buffer[m_pos] == 0)
|
||||
{
|
||||
while (m_buffer[m_pos] != '"') {
|
||||
if (m_buffer[m_pos] == 0) {
|
||||
if (m_pos >= m_size)
|
||||
RaiseError("unexpected EOF in path string");
|
||||
else
|
||||
@@ -354,7 +306,7 @@ void CFile::TryConvertIncbin()
|
||||
|
||||
if (m_buffer[m_pos] == '\\')
|
||||
RaiseError("unexpected escape in path string");
|
||||
|
||||
|
||||
m_pos++;
|
||||
}
|
||||
|
||||
@@ -371,8 +323,7 @@ void CFile::TryConvertIncbin()
|
||||
int count = fileSize / size;
|
||||
int offset = 0;
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
for (int i = 0; i < count; i++) {
|
||||
int data = ExtractData(buffer, offset, size);
|
||||
offset += size;
|
||||
|
||||
@@ -389,7 +340,7 @@ void CFile::TryConvertIncbin()
|
||||
|
||||
m_pos++;
|
||||
}
|
||||
|
||||
|
||||
if (m_buffer[m_pos] != ')')
|
||||
RaiseError("expected ')'");
|
||||
|
||||
@@ -399,32 +350,28 @@ void CFile::TryConvertIncbin()
|
||||
}
|
||||
|
||||
// Reports a diagnostic message.
|
||||
void CFile::ReportDiagnostic(const char* type, const char* format, std::va_list args)
|
||||
{
|
||||
void CFile::ReportDiagnostic(const char* type, const char* format, std::va_list args) {
|
||||
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);
|
||||
}
|
||||
|
||||
#define DO_REPORT(type) \
|
||||
do \
|
||||
{ \
|
||||
std::va_list args; \
|
||||
va_start(args, format); \
|
||||
ReportDiagnostic(type, format, args); \
|
||||
va_end(args); \
|
||||
} while (0)
|
||||
#define DO_REPORT(type) \
|
||||
do { \
|
||||
std::va_list args; \
|
||||
va_start(args, format); \
|
||||
ReportDiagnostic(type, format, args); \
|
||||
va_end(args); \
|
||||
} while (0)
|
||||
|
||||
// Reports an error diagnostic and terminates the program.
|
||||
void CFile::RaiseError(const char* format, ...)
|
||||
{
|
||||
void CFile::RaiseError(const char* format, ...) {
|
||||
DO_REPORT("error");
|
||||
std::exit(1);
|
||||
}
|
||||
|
||||
// Reports a warning diagnostic.
|
||||
void CFile::RaiseWarning(const char* format, ...)
|
||||
{
|
||||
void CFile::RaiseWarning(const char* format, ...) {
|
||||
DO_REPORT("warning");
|
||||
}
|
||||
|
||||
Executable → Regular
+3
-4
@@ -27,16 +27,15 @@
|
||||
#include <memory>
|
||||
#include "preproc.h"
|
||||
|
||||
class CFile
|
||||
{
|
||||
public:
|
||||
class CFile {
|
||||
public:
|
||||
CFile(std::string filename);
|
||||
CFile(CFile&& other);
|
||||
CFile(const CFile&) = delete;
|
||||
~CFile();
|
||||
void Preproc();
|
||||
|
||||
private:
|
||||
private:
|
||||
char* m_buffer;
|
||||
long m_pos;
|
||||
long m_size;
|
||||
|
||||
Executable → Regular
+9
-19
@@ -24,47 +24,37 @@
|
||||
#include <cstdint>
|
||||
#include <cassert>
|
||||
|
||||
inline bool IsAscii(unsigned char c)
|
||||
{
|
||||
inline bool IsAscii(unsigned char c) {
|
||||
return (c < 128);
|
||||
}
|
||||
|
||||
inline bool IsAsciiAlpha(unsigned char c)
|
||||
{
|
||||
inline bool IsAsciiAlpha(unsigned char c) {
|
||||
return ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'));
|
||||
}
|
||||
|
||||
inline bool IsAsciiDigit(unsigned char c)
|
||||
{
|
||||
inline bool IsAsciiDigit(unsigned char c) {
|
||||
return (c >= '0' && c <= '9');
|
||||
}
|
||||
|
||||
inline bool IsAsciiHexDigit(unsigned char c)
|
||||
{
|
||||
return ((c >= '0' && c <= '9')
|
||||
|| (c >= 'a' && c <= 'f')
|
||||
|| (c >= 'A' && c <= 'F'));
|
||||
inline bool IsAsciiHexDigit(unsigned char c) {
|
||||
return ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'));
|
||||
}
|
||||
|
||||
inline bool IsAsciiAlphanum(unsigned char c)
|
||||
{
|
||||
inline bool IsAsciiAlphanum(unsigned char c) {
|
||||
return (IsAsciiAlpha(c) || IsAsciiDigit(c));
|
||||
}
|
||||
|
||||
inline bool IsAsciiPrintable(unsigned char c)
|
||||
{
|
||||
inline bool IsAsciiPrintable(unsigned char c) {
|
||||
return (c >= ' ' && c <= '~');
|
||||
}
|
||||
|
||||
// Returns whether the character can start a C identifier or the identifier of a "{FOO}" constant in strings.
|
||||
inline bool IsIdentifierStartingChar(unsigned char c)
|
||||
{
|
||||
inline bool IsIdentifierStartingChar(unsigned char c) {
|
||||
return IsAsciiAlpha(c) || c == '_';
|
||||
}
|
||||
|
||||
// Returns whether the character can be used in a C identifier or the identifier of a "{FOO}" constant in strings.
|
||||
inline bool IsIdentifierChar(unsigned char c)
|
||||
{
|
||||
inline bool IsIdentifierChar(unsigned char c) {
|
||||
return IsAsciiAlphanum(c) || c == '_';
|
||||
}
|
||||
|
||||
|
||||
Executable → Regular
+73
-133
@@ -26,24 +26,16 @@
|
||||
#include "char_util.h"
|
||||
#include "utf8.h"
|
||||
|
||||
enum LhsType
|
||||
{
|
||||
Char,
|
||||
Escape,
|
||||
Constant,
|
||||
None
|
||||
};
|
||||
enum LhsType { Char, Escape, Constant, None };
|
||||
|
||||
struct Lhs
|
||||
{
|
||||
struct Lhs {
|
||||
LhsType type;
|
||||
std::string name;
|
||||
std::int32_t code;
|
||||
};
|
||||
|
||||
class CharmapReader
|
||||
{
|
||||
public:
|
||||
class CharmapReader {
|
||||
public:
|
||||
CharmapReader(std::string filename);
|
||||
CharmapReader(const CharmapReader&) = delete;
|
||||
~CharmapReader();
|
||||
@@ -53,7 +45,7 @@ public:
|
||||
void ExpectEmptyRestOfLine();
|
||||
void RaiseError(const char* format, ...);
|
||||
|
||||
private:
|
||||
private:
|
||||
char* m_buffer;
|
||||
long m_pos;
|
||||
long m_size;
|
||||
@@ -65,17 +57,15 @@ private:
|
||||
void SkipWhitespace();
|
||||
};
|
||||
|
||||
CharmapReader::CharmapReader(std::string filename) : m_filename(filename)
|
||||
{
|
||||
if (filename == "")
|
||||
{
|
||||
CharmapReader::CharmapReader(std::string filename) : m_filename(filename) {
|
||||
if (filename == "") {
|
||||
m_pos = 0;
|
||||
m_size = 0;
|
||||
m_buffer = new char[1] {};
|
||||
m_buffer = new char[1]{};
|
||||
return;
|
||||
}
|
||||
|
||||
FILE *fp = std::fopen(filename.c_str(), "rb");
|
||||
FILE* fp = std::fopen(filename.c_str(), "rb");
|
||||
|
||||
if (fp == NULL)
|
||||
FATAL_ERROR("Failed to open \"%s\" for reading.\n", filename.c_str());
|
||||
@@ -104,45 +94,36 @@ CharmapReader::CharmapReader(std::string filename) : m_filename(filename)
|
||||
RemoveComments();
|
||||
}
|
||||
|
||||
CharmapReader::~CharmapReader()
|
||||
{
|
||||
CharmapReader::~CharmapReader() {
|
||||
delete[] m_buffer;
|
||||
}
|
||||
|
||||
Lhs CharmapReader::ReadLhs()
|
||||
{
|
||||
Lhs CharmapReader::ReadLhs() {
|
||||
Lhs lhs;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
for (;;) {
|
||||
SkipWhitespace();
|
||||
|
||||
if (m_buffer[m_pos] == '\n')
|
||||
{
|
||||
if (m_buffer[m_pos] == '\n') {
|
||||
m_pos++;
|
||||
m_lineNum++;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_buffer[m_pos] == '\'')
|
||||
{
|
||||
|
||||
if (m_buffer[m_pos] == '\'') {
|
||||
m_pos++;
|
||||
|
||||
bool isEscape = (m_buffer[m_pos] == '\\');
|
||||
|
||||
if (isEscape)
|
||||
{
|
||||
if (isEscape) {
|
||||
m_pos++;
|
||||
}
|
||||
|
||||
unsigned char c = m_buffer[m_pos];
|
||||
|
||||
if (c == 0)
|
||||
{
|
||||
if (c == 0) {
|
||||
if (m_pos >= m_size)
|
||||
RaiseError("unexpected EOF in UTF-8 character literal");
|
||||
else
|
||||
@@ -167,58 +148,45 @@ Lhs CharmapReader::ReadLhs()
|
||||
|
||||
lhs.code = code;
|
||||
|
||||
if (isEscape)
|
||||
{
|
||||
if (isEscape) {
|
||||
if (code >= 128)
|
||||
RaiseError("escapes using non-ASCII characters are invalid");
|
||||
|
||||
switch (code)
|
||||
{
|
||||
case '\'':
|
||||
lhs.type = LhsType::Char;
|
||||
break;
|
||||
case '\\':
|
||||
lhs.type = LhsType::Char;
|
||||
case '"':
|
||||
RaiseError("cannot escape double quote");
|
||||
break;
|
||||
default:
|
||||
lhs.type = LhsType::Escape;
|
||||
switch (code) {
|
||||
case '\'':
|
||||
lhs.type = LhsType::Char;
|
||||
break;
|
||||
case '\\':
|
||||
lhs.type = LhsType::Char;
|
||||
case '"':
|
||||
RaiseError("cannot escape double quote");
|
||||
break;
|
||||
default:
|
||||
lhs.type = LhsType::Escape;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
if (code == '\'')
|
||||
RaiseError("empty character literal");
|
||||
|
||||
lhs.type = LhsType::Char;
|
||||
}
|
||||
}
|
||||
else if (IsIdentifierStartingChar(m_buffer[m_pos]))
|
||||
{
|
||||
} else if (IsIdentifierStartingChar(m_buffer[m_pos])) {
|
||||
lhs.type = LhsType::Constant;
|
||||
lhs.name = ReadConstant();
|
||||
}
|
||||
else if (m_buffer[m_pos] == '\r')
|
||||
{
|
||||
} else if (m_buffer[m_pos] == '\r') {
|
||||
RaiseError("only Unix-style LF newlines are supported");
|
||||
}
|
||||
else if (m_buffer[m_pos] == 0)
|
||||
{
|
||||
} else if (m_buffer[m_pos] == 0) {
|
||||
if (m_pos < m_size)
|
||||
RaiseError("unexpected null character");
|
||||
lhs.type = LhsType::None;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
RaiseError("junk at start of line");
|
||||
}
|
||||
|
||||
return lhs;
|
||||
}
|
||||
|
||||
void CharmapReader::ExpectEqualsSign()
|
||||
{
|
||||
void CharmapReader::ExpectEqualsSign() {
|
||||
SkipWhitespace();
|
||||
|
||||
if (m_buffer[m_pos] != '=')
|
||||
@@ -227,8 +195,7 @@ void CharmapReader::ExpectEqualsSign()
|
||||
m_pos++;
|
||||
}
|
||||
|
||||
static unsigned int ConvertHexDigit(char c)
|
||||
{
|
||||
static unsigned int ConvertHexDigit(char c) {
|
||||
unsigned int digit = 0;
|
||||
|
||||
if (c >= '0' && c <= '9')
|
||||
@@ -241,16 +208,14 @@ static unsigned int ConvertHexDigit(char c)
|
||||
return digit;
|
||||
}
|
||||
|
||||
std::string CharmapReader::ReadSequence()
|
||||
{
|
||||
std::string CharmapReader::ReadSequence() {
|
||||
SkipWhitespace();
|
||||
|
||||
long startPos = m_pos;
|
||||
|
||||
unsigned int length = 0;
|
||||
|
||||
while (IsAsciiHexDigit(m_buffer[m_pos]) && IsAsciiHexDigit(m_buffer[m_pos + 1]))
|
||||
{
|
||||
while (IsAsciiHexDigit(m_buffer[m_pos]) && IsAsciiHexDigit(m_buffer[m_pos + 1])) {
|
||||
m_pos += 2;
|
||||
length++;
|
||||
|
||||
@@ -271,8 +236,7 @@ std::string CharmapReader::ReadSequence()
|
||||
|
||||
m_pos = startPos;
|
||||
|
||||
for (unsigned int i = 0; i < length; i++)
|
||||
{
|
||||
for (unsigned int i = 0; i < length; i++) {
|
||||
unsigned int digit1 = ConvertHexDigit(m_buffer[m_pos]);
|
||||
unsigned int digit2 = ConvertHexDigit(m_buffer[m_pos + 1]);
|
||||
unsigned char byte = digit1 * 16 + digit2;
|
||||
@@ -285,32 +249,23 @@ std::string CharmapReader::ReadSequence()
|
||||
return sequence;
|
||||
}
|
||||
|
||||
void CharmapReader::ExpectEmptyRestOfLine()
|
||||
{
|
||||
void CharmapReader::ExpectEmptyRestOfLine() {
|
||||
SkipWhitespace();
|
||||
|
||||
if (m_buffer[m_pos] == 0)
|
||||
{
|
||||
if (m_buffer[m_pos] == 0) {
|
||||
if (m_pos < m_size)
|
||||
RaiseError("unexpected null character");
|
||||
}
|
||||
else if (m_buffer[m_pos] == '\n')
|
||||
{
|
||||
} else if (m_buffer[m_pos] == '\n') {
|
||||
m_pos++;
|
||||
m_lineNum++;
|
||||
}
|
||||
else if (m_buffer[m_pos] == '\r')
|
||||
{
|
||||
} else if (m_buffer[m_pos] == '\r') {
|
||||
RaiseError("only Unix-style LF newlines are supported");
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
RaiseError("junk at end of line");
|
||||
}
|
||||
}
|
||||
|
||||
void CharmapReader::RaiseError(const char* format, ...)
|
||||
{
|
||||
void CharmapReader::RaiseError(const char* format, ...) {
|
||||
const int bufferSize = 1024;
|
||||
char buffer[bufferSize];
|
||||
|
||||
@@ -324,36 +279,26 @@ void CharmapReader::RaiseError(const char* format, ...)
|
||||
std::exit(1);
|
||||
}
|
||||
|
||||
void CharmapReader::RemoveComments()
|
||||
{
|
||||
void CharmapReader::RemoveComments() {
|
||||
long pos = 0;
|
||||
bool inString = false;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
for (;;) {
|
||||
if (m_buffer[pos] == 0)
|
||||
return;
|
||||
|
||||
if (inString)
|
||||
{
|
||||
if (m_buffer[pos] == '\\' && m_buffer[pos + 1] == '\'')
|
||||
{
|
||||
if (inString) {
|
||||
if (m_buffer[pos] == '\\' && m_buffer[pos + 1] == '\'') {
|
||||
pos += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
if (m_buffer[pos] == '\'')
|
||||
inString = false;
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
else if (m_buffer[pos] == '@')
|
||||
{
|
||||
} else if (m_buffer[pos] == '@') {
|
||||
while (m_buffer[pos] != '\n' && m_buffer[pos] != 0)
|
||||
m_buffer[pos++] = ' ';
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
if (m_buffer[pos] == '\'')
|
||||
inString = true;
|
||||
pos++;
|
||||
@@ -361,8 +306,7 @@ void CharmapReader::RemoveComments()
|
||||
}
|
||||
}
|
||||
|
||||
std::string CharmapReader::ReadConstant()
|
||||
{
|
||||
std::string CharmapReader::ReadConstant() {
|
||||
long startPos = m_pos;
|
||||
|
||||
while (IsIdentifierChar(m_buffer[m_pos]))
|
||||
@@ -371,18 +315,15 @@ std::string CharmapReader::ReadConstant()
|
||||
return std::string(&m_buffer[startPos], m_pos - startPos);
|
||||
}
|
||||
|
||||
void CharmapReader::SkipWhitespace()
|
||||
{
|
||||
void CharmapReader::SkipWhitespace() {
|
||||
while (m_buffer[m_pos] == '\t' || m_buffer[m_pos] == ' ')
|
||||
m_pos++;
|
||||
}
|
||||
|
||||
Charmap::Charmap(std::string filename)
|
||||
{
|
||||
Charmap::Charmap(std::string filename) {
|
||||
CharmapReader reader(filename);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
for (;;) {
|
||||
Lhs lhs = reader.ReadLhs();
|
||||
|
||||
if (lhs.type == LhsType::None)
|
||||
@@ -392,23 +333,22 @@ Charmap::Charmap(std::string filename)
|
||||
|
||||
std::string sequence = reader.ReadSequence();
|
||||
|
||||
switch (lhs.type)
|
||||
{
|
||||
case LhsType::Char:
|
||||
if (m_chars.find(lhs.code) != m_chars.end())
|
||||
reader.RaiseError("redefining char");
|
||||
m_chars[lhs.code] = sequence;
|
||||
break;
|
||||
case LhsType::Escape:
|
||||
if (m_escapes[lhs.code].length() != 0)
|
||||
reader.RaiseError("redefining escape");
|
||||
m_escapes[lhs.code] = sequence;
|
||||
break;
|
||||
case LhsType::Constant:
|
||||
if (m_constants.find(lhs.name) != m_constants.end())
|
||||
reader.RaiseError("redefining constant");
|
||||
m_constants[lhs.name] = sequence;
|
||||
break;
|
||||
switch (lhs.type) {
|
||||
case LhsType::Char:
|
||||
if (m_chars.find(lhs.code) != m_chars.end())
|
||||
reader.RaiseError("redefining char");
|
||||
m_chars[lhs.code] = sequence;
|
||||
break;
|
||||
case LhsType::Escape:
|
||||
if (m_escapes[lhs.code].length() != 0)
|
||||
reader.RaiseError("redefining escape");
|
||||
m_escapes[lhs.code] = sequence;
|
||||
break;
|
||||
case LhsType::Constant:
|
||||
if (m_constants.find(lhs.name) != m_constants.end())
|
||||
reader.RaiseError("redefining constant");
|
||||
m_constants[lhs.name] = sequence;
|
||||
break;
|
||||
}
|
||||
|
||||
reader.ExpectEmptyRestOfLine();
|
||||
|
||||
Executable → Regular
+7
-10
@@ -26,13 +26,11 @@
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
class Charmap
|
||||
{
|
||||
public:
|
||||
class Charmap {
|
||||
public:
|
||||
Charmap(std::string filename);
|
||||
|
||||
std::string Char(std::int32_t code)
|
||||
{
|
||||
std::string Char(std::int32_t code) {
|
||||
auto it = m_chars.find(code);
|
||||
|
||||
if (it == m_chars.end())
|
||||
@@ -41,13 +39,11 @@ public:
|
||||
return it->second;
|
||||
}
|
||||
|
||||
std::string Escape(unsigned char code)
|
||||
{
|
||||
std::string Escape(unsigned char code) {
|
||||
return m_escapes[code];
|
||||
}
|
||||
|
||||
std::string Constant(std::string identifier)
|
||||
{
|
||||
std::string Constant(std::string identifier) {
|
||||
auto it = m_constants.find(identifier);
|
||||
|
||||
if (it == m_constants.end())
|
||||
@@ -55,7 +51,8 @@ public:
|
||||
|
||||
return it->second;
|
||||
}
|
||||
private:
|
||||
|
||||
private:
|
||||
std::map<std::int32_t, std::string> m_chars;
|
||||
std::string m_escapes[128];
|
||||
std::map<std::string, std::string> m_constants;
|
||||
|
||||
Executable → Regular
+36
-53
@@ -28,13 +28,10 @@
|
||||
Charmap* g_charmap;
|
||||
std::string g_buildName;
|
||||
|
||||
void PrintAsmBytes(unsigned char *s, int length)
|
||||
{
|
||||
if (length > 0)
|
||||
{
|
||||
void PrintAsmBytes(unsigned char* s, int length) {
|
||||
if (length > 0) {
|
||||
std::printf("\t.byte ");
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
for (int i = 0; i < length; i++) {
|
||||
std::printf("0x%02X", s[i]);
|
||||
|
||||
if (i < length - 1)
|
||||
@@ -44,16 +41,13 @@ void PrintAsmBytes(unsigned char *s, int length)
|
||||
}
|
||||
}
|
||||
|
||||
void PreprocAsmFile(std::string filename)
|
||||
{
|
||||
void PreprocAsmFile(std::string filename) {
|
||||
std::stack<AsmFile> stack;
|
||||
|
||||
stack.push(AsmFile(filename));
|
||||
|
||||
for (;;)
|
||||
{
|
||||
while (stack.top().IsAtEnd())
|
||||
{
|
||||
for (;;) {
|
||||
while (stack.top().IsAtEnd()) {
|
||||
stack.pop();
|
||||
|
||||
if (stack.empty())
|
||||
@@ -64,54 +58,45 @@ void PreprocAsmFile(std::string filename)
|
||||
|
||||
Directive directive = stack.top().GetDirective();
|
||||
|
||||
switch (directive)
|
||||
{
|
||||
case Directive::Include:
|
||||
stack.push(AsmFile(stack.top().ReadPath()));
|
||||
stack.top().OutputLocation();
|
||||
break;
|
||||
case Directive::String:
|
||||
{
|
||||
unsigned char s[kMaxStringLength];
|
||||
int length = stack.top().ReadString(s);
|
||||
PrintAsmBytes(s, length);
|
||||
break;
|
||||
}
|
||||
case Directive::Braille:
|
||||
{
|
||||
unsigned char s[kMaxStringLength];
|
||||
int length = stack.top().ReadBraille(s);
|
||||
PrintAsmBytes(s, length);
|
||||
break;
|
||||
}
|
||||
case Directive::Unknown:
|
||||
{
|
||||
std::string globalLabel = stack.top().GetGlobalLabel();
|
||||
|
||||
if (globalLabel.length() != 0)
|
||||
{
|
||||
const char *s = globalLabel.c_str();
|
||||
std::printf("%s: ; .global %s\n", s, s);
|
||||
switch (directive) {
|
||||
case Directive::Include:
|
||||
stack.push(AsmFile(stack.top().ReadPath()));
|
||||
stack.top().OutputLocation();
|
||||
break;
|
||||
case Directive::String: {
|
||||
unsigned char s[kMaxStringLength];
|
||||
int length = stack.top().ReadString(s);
|
||||
PrintAsmBytes(s, length);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
stack.top().OutputLine();
|
||||
case Directive::Braille: {
|
||||
unsigned char s[kMaxStringLength];
|
||||
int length = stack.top().ReadBraille(s);
|
||||
PrintAsmBytes(s, length);
|
||||
break;
|
||||
}
|
||||
case Directive::Unknown: {
|
||||
std::string globalLabel = stack.top().GetGlobalLabel();
|
||||
|
||||
break;
|
||||
}
|
||||
if (globalLabel.length() != 0) {
|
||||
const char* s = globalLabel.c_str();
|
||||
std::printf("%s: ; .global %s\n", s, s);
|
||||
} else {
|
||||
stack.top().OutputLine();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PreprocCFile(std::string filename)
|
||||
{
|
||||
void PreprocCFile(std::string filename) {
|
||||
CFile cFile(filename);
|
||||
cFile.Preproc();
|
||||
}
|
||||
|
||||
char* GetFileExtension(char* filename)
|
||||
{
|
||||
char* GetFileExtension(char* filename) {
|
||||
char* extension = filename;
|
||||
|
||||
while (*extension != 0)
|
||||
@@ -131,10 +116,8 @@ char* GetFileExtension(char* filename)
|
||||
return extension;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc != 4 && argc != 3)
|
||||
{
|
||||
int main(int argc, char** argv) {
|
||||
if (argc != 4 && argc != 3) {
|
||||
std::fprintf(stderr, "Usage: %s BUILD_NAME SRC_FILE CHARMAP_FILE", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
Executable → Regular
+10
-12
@@ -27,21 +27,19 @@
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
#define FATAL_ERROR(format, ...) \
|
||||
do \
|
||||
{ \
|
||||
std::fprintf(stderr, format, __VA_ARGS__); \
|
||||
std::exit(1); \
|
||||
} while (0)
|
||||
#define FATAL_ERROR(format, ...) \
|
||||
do { \
|
||||
std::fprintf(stderr, format, __VA_ARGS__); \
|
||||
std::exit(1); \
|
||||
} while (0)
|
||||
|
||||
#else
|
||||
|
||||
#define FATAL_ERROR(format, ...) \
|
||||
do \
|
||||
{ \
|
||||
std::fprintf(stderr, format, ##__VA_ARGS__); \
|
||||
std::exit(1); \
|
||||
} while (0)
|
||||
#define FATAL_ERROR(format, ...) \
|
||||
do { \
|
||||
std::fprintf(stderr, format, ##__VA_ARGS__); \
|
||||
std::exit(1); \
|
||||
} while (0)
|
||||
|
||||
#endif // _MSC_VER
|
||||
|
||||
|
||||
Executable → Regular
+62
-103
@@ -27,27 +27,22 @@
|
||||
#include "utf8.h"
|
||||
|
||||
// Reads a charmap char or escape sequence.
|
||||
std::string StringParser::ReadCharOrEscape()
|
||||
{
|
||||
std::string StringParser::ReadCharOrEscape() {
|
||||
std::string sequence;
|
||||
|
||||
bool isEscape = (m_buffer[m_pos] == '\\');
|
||||
|
||||
if (isEscape)
|
||||
{
|
||||
if (isEscape) {
|
||||
m_pos++;
|
||||
|
||||
if (m_buffer[m_pos] == '"')
|
||||
{
|
||||
if (m_buffer[m_pos] == '"') {
|
||||
sequence = g_charmap->Char('"');
|
||||
|
||||
if (sequence.length() == 0)
|
||||
RaiseError("no mapping exists for double quote");
|
||||
|
||||
return sequence;
|
||||
}
|
||||
else if (m_buffer[m_pos] == '\\')
|
||||
{
|
||||
} else if (m_buffer[m_pos] == '\\') {
|
||||
sequence = g_charmap->Char('\\');
|
||||
|
||||
if (sequence.length() == 0)
|
||||
@@ -59,8 +54,7 @@ std::string StringParser::ReadCharOrEscape()
|
||||
|
||||
unsigned char c = m_buffer[m_pos];
|
||||
|
||||
if (c == 0)
|
||||
{
|
||||
if (c == 0) {
|
||||
if (m_pos >= m_size)
|
||||
RaiseError("unexpected EOF in UTF-8 string");
|
||||
else
|
||||
@@ -82,8 +76,7 @@ std::string StringParser::ReadCharOrEscape()
|
||||
|
||||
sequence = isEscape ? g_charmap->Escape(code) : g_charmap->Char(code);
|
||||
|
||||
if (sequence.length() == 0)
|
||||
{
|
||||
if (sequence.length() == 0) {
|
||||
if (isEscape)
|
||||
RaiseError("unknown escape '\\%c'", code);
|
||||
else
|
||||
@@ -94,18 +87,15 @@ std::string StringParser::ReadCharOrEscape()
|
||||
}
|
||||
|
||||
// Reads a charmap constant, i.e. "{FOO}".
|
||||
std::string StringParser::ReadBracketedConstants()
|
||||
{
|
||||
std::string StringParser::ReadBracketedConstants() {
|
||||
std::string totalSequence;
|
||||
|
||||
m_pos++; // Assume we're on the left curly bracket.
|
||||
|
||||
while (m_buffer[m_pos] != '}')
|
||||
{
|
||||
while (m_buffer[m_pos] != '}') {
|
||||
SkipWhitespace();
|
||||
|
||||
if (IsIdentifierStartingChar(m_buffer[m_pos]))
|
||||
{
|
||||
if (IsIdentifierStartingChar(m_buffer[m_pos])) {
|
||||
long startPos = m_pos;
|
||||
|
||||
m_pos++;
|
||||
@@ -115,44 +105,36 @@ std::string StringParser::ReadBracketedConstants()
|
||||
|
||||
std::string sequence = g_charmap->Constant(std::string(&m_buffer[startPos], m_pos - startPos));
|
||||
|
||||
if (sequence.length() == 0)
|
||||
{
|
||||
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]))
|
||||
{
|
||||
} else if (IsAsciiDigit(m_buffer[m_pos])) {
|
||||
Integer integer = ReadInteger();
|
||||
|
||||
switch (integer.size)
|
||||
{
|
||||
case 1:
|
||||
totalSequence += (unsigned char)integer.value;
|
||||
break;
|
||||
case 2:
|
||||
totalSequence += (unsigned char)integer.value;
|
||||
totalSequence += (unsigned char)(integer.value >> 8);
|
||||
break;
|
||||
case 4:
|
||||
totalSequence += (unsigned char)integer.value;
|
||||
totalSequence += (unsigned char)(integer.value >> 8);
|
||||
totalSequence += (unsigned char)(integer.value >> 16);
|
||||
totalSequence += (unsigned char)(integer.value >> 24);
|
||||
break;
|
||||
switch (integer.size) {
|
||||
case 1:
|
||||
totalSequence += (unsigned char)integer.value;
|
||||
break;
|
||||
case 2:
|
||||
totalSequence += (unsigned char)integer.value;
|
||||
totalSequence += (unsigned char)(integer.value >> 8);
|
||||
break;
|
||||
case 4:
|
||||
totalSequence += (unsigned char)integer.value;
|
||||
totalSequence += (unsigned char)(integer.value >> 8);
|
||||
totalSequence += (unsigned char)(integer.value >> 16);
|
||||
totalSequence += (unsigned char)(integer.value >> 24);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (m_buffer[m_pos] == 0)
|
||||
{
|
||||
} else if (m_buffer[m_pos] == 0) {
|
||||
if (m_pos >= m_size)
|
||||
RaiseError("unexpected EOF after left curly bracket");
|
||||
else
|
||||
RaiseError("unexpected null character within curly brackets");
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
if (IsAsciiPrintable(m_buffer[m_pos]))
|
||||
RaiseError("unexpected character '%c' within curly brackets", m_buffer[m_pos]);
|
||||
else
|
||||
@@ -166,8 +148,7 @@ std::string StringParser::ReadBracketedConstants()
|
||||
}
|
||||
|
||||
// Reads a charmap string.
|
||||
int StringParser::ParseString(long srcPos, unsigned char* dest, int& destLength)
|
||||
{
|
||||
int StringParser::ParseString(long srcPos, unsigned char* dest, int& destLength) {
|
||||
m_pos = srcPos;
|
||||
|
||||
if (m_buffer[m_pos] != '"')
|
||||
@@ -179,12 +160,10 @@ int StringParser::ParseString(long srcPos, unsigned char* dest, int& destLength)
|
||||
|
||||
destLength = 0;
|
||||
|
||||
while (m_buffer[m_pos] != '"')
|
||||
{
|
||||
while (m_buffer[m_pos] != '"') {
|
||||
std::string sequence = (m_buffer[m_pos] == '{') ? ReadBracketedConstants() : ReadCharOrEscape();
|
||||
|
||||
for (const char& c : sequence)
|
||||
{
|
||||
for (const char& c : sequence) {
|
||||
if (destLength == kMaxStringLength)
|
||||
RaiseError("mapped string longer than %d bytes", kMaxStringLength);
|
||||
|
||||
@@ -197,8 +176,7 @@ int StringParser::ParseString(long srcPos, unsigned char* dest, int& destLength)
|
||||
return m_pos - start;
|
||||
}
|
||||
|
||||
void StringParser::RaiseError(const char* format, ...)
|
||||
{
|
||||
void StringParser::RaiseError(const char* format, ...) {
|
||||
const int bufferSize = 1024;
|
||||
char buffer[bufferSize];
|
||||
|
||||
@@ -211,8 +189,7 @@ void StringParser::RaiseError(const char* format, ...)
|
||||
}
|
||||
|
||||
// Converts digit character to numerical value.
|
||||
static int ConvertDigit(char c, int radix)
|
||||
{
|
||||
static int ConvertDigit(char c, int radix) {
|
||||
int digit;
|
||||
|
||||
if (c >= '0' && c <= '9')
|
||||
@@ -227,26 +204,22 @@ static int ConvertDigit(char c, int radix)
|
||||
return (digit < radix) ? digit : -1;
|
||||
}
|
||||
|
||||
void StringParser::SkipRestOfInteger(int radix)
|
||||
{
|
||||
void StringParser::SkipRestOfInteger(int radix) {
|
||||
while (ConvertDigit(m_buffer[m_pos], radix) != -1)
|
||||
m_pos++;
|
||||
}
|
||||
|
||||
StringParser::Integer StringParser::ReadDecimal()
|
||||
{
|
||||
StringParser::Integer StringParser::ReadDecimal() {
|
||||
const int radix = 10;
|
||||
std::uint64_t n = 0;
|
||||
int digit;
|
||||
std::uint64_t max = UINT32_MAX;
|
||||
long startPos = m_pos;
|
||||
|
||||
while ((digit = ConvertDigit(m_buffer[m_pos], radix)) != -1)
|
||||
{
|
||||
while ((digit = ConvertDigit(m_buffer[m_pos], radix)) != -1) {
|
||||
n = n * radix + digit;
|
||||
|
||||
if (n >= max)
|
||||
{
|
||||
if (n >= max) {
|
||||
SkipRestOfInteger(radix);
|
||||
|
||||
std::string intLiteral(m_buffer + startPos, m_pos - startPos);
|
||||
@@ -258,23 +231,17 @@ StringParser::Integer StringParser::ReadDecimal()
|
||||
|
||||
int size;
|
||||
|
||||
if (m_buffer[m_pos] == 'H')
|
||||
{
|
||||
if (n >= 0x10000)
|
||||
{
|
||||
if (m_buffer[m_pos] == 'H') {
|
||||
if (n >= 0x10000) {
|
||||
RaiseError("%lu is too large to be a halfword", (unsigned long)n);
|
||||
}
|
||||
|
||||
size = 2;
|
||||
m_pos++;
|
||||
}
|
||||
else if (m_buffer[m_pos] == 'W')
|
||||
{
|
||||
} else if (m_buffer[m_pos] == 'W') {
|
||||
size = 4;
|
||||
m_pos++;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
if (n >= 0x10000)
|
||||
size = 4;
|
||||
else if (n >= 0x100)
|
||||
@@ -283,23 +250,20 @@ StringParser::Integer StringParser::ReadDecimal()
|
||||
size = 1;
|
||||
}
|
||||
|
||||
return{ static_cast<std::uint32_t>(n), size };
|
||||
return { static_cast<std::uint32_t>(n), size };
|
||||
}
|
||||
|
||||
StringParser::Integer StringParser::ReadHex()
|
||||
{
|
||||
StringParser::Integer StringParser::ReadHex() {
|
||||
const int radix = 16;
|
||||
std::uint64_t n = 0;
|
||||
int digit;
|
||||
std::uint64_t max = UINT32_MAX;
|
||||
long startPos = m_pos;
|
||||
|
||||
while ((digit = ConvertDigit(m_buffer[m_pos], radix)) != -1)
|
||||
{
|
||||
while ((digit = ConvertDigit(m_buffer[m_pos], radix)) != -1) {
|
||||
n = n * radix + digit;
|
||||
|
||||
if (n >= max)
|
||||
{
|
||||
if (n >= max) {
|
||||
SkipRestOfInteger(radix);
|
||||
|
||||
std::string intLiteral(m_buffer + startPos, m_pos - startPos);
|
||||
@@ -312,34 +276,30 @@ StringParser::Integer StringParser::ReadHex()
|
||||
int length = m_pos - startPos;
|
||||
int size = 0;
|
||||
|
||||
switch (length)
|
||||
{
|
||||
case 2:
|
||||
size = 1;
|
||||
break;
|
||||
case 4:
|
||||
size = 2;
|
||||
break;
|
||||
case 8:
|
||||
size = 4;
|
||||
break;
|
||||
default:
|
||||
{
|
||||
std::string intLiteral(m_buffer + startPos, m_pos - startPos);
|
||||
RaiseError("hex integer literal \"0x%s\" doesn't have length of 2, 4, or 8 digits", intLiteral.c_str());
|
||||
}
|
||||
switch (length) {
|
||||
case 2:
|
||||
size = 1;
|
||||
break;
|
||||
case 4:
|
||||
size = 2;
|
||||
break;
|
||||
case 8:
|
||||
size = 4;
|
||||
break;
|
||||
default: {
|
||||
std::string intLiteral(m_buffer + startPos, m_pos - startPos);
|
||||
RaiseError("hex integer literal \"0x%s\" doesn't have length of 2, 4, or 8 digits", intLiteral.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
return{ static_cast<std::uint32_t>(n), size };
|
||||
return { static_cast<std::uint32_t>(n), size };
|
||||
}
|
||||
|
||||
StringParser::Integer StringParser::ReadInteger()
|
||||
{
|
||||
StringParser::Integer StringParser::ReadInteger() {
|
||||
if (!IsAsciiDigit(m_buffer[m_pos]))
|
||||
RaiseError("expected integer");
|
||||
|
||||
if (m_buffer[m_pos] == '0' && m_buffer[m_pos + 1] == 'x')
|
||||
{
|
||||
if (m_buffer[m_pos] == '0' && m_buffer[m_pos + 1] == 'x') {
|
||||
m_pos += 2;
|
||||
return ReadHex();
|
||||
}
|
||||
@@ -348,8 +308,7 @@ StringParser::Integer StringParser::ReadInteger()
|
||||
}
|
||||
|
||||
// Skips tabs and spaces.
|
||||
void StringParser::SkipWhitespace()
|
||||
{
|
||||
void StringParser::SkipWhitespace() {
|
||||
while (m_buffer[m_pos] == '\t' || m_buffer[m_pos] == ' ')
|
||||
m_pos++;
|
||||
}
|
||||
|
||||
Executable → Regular
+7
-8
@@ -25,15 +25,14 @@
|
||||
#include <string>
|
||||
#include "preproc.h"
|
||||
|
||||
class StringParser
|
||||
{
|
||||
public:
|
||||
StringParser(char* buffer, long size) : m_buffer(buffer), m_size(size), m_pos(0) {}
|
||||
int ParseString(long srcPos, unsigned char* dest, int &destLength);
|
||||
class StringParser {
|
||||
public:
|
||||
StringParser(char* buffer, long size) : m_buffer(buffer), m_size(size), m_pos(0) {
|
||||
}
|
||||
int ParseString(long srcPos, unsigned char* dest, int& destLength);
|
||||
|
||||
private:
|
||||
struct Integer
|
||||
{
|
||||
private:
|
||||
struct Integer {
|
||||
std::uint32_t value;
|
||||
int size;
|
||||
};
|
||||
|
||||
Executable → Regular
+30
-28
@@ -24,17 +24,23 @@
|
||||
#include <cstdint>
|
||||
#include "utf8.h"
|
||||
|
||||
static const unsigned char s_byteTypeTable[] =
|
||||
{
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 00..1f
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 20..3f
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 40..5f
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 60..7f
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, // 80..9f
|
||||
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, // a0..bf
|
||||
8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // c0..df
|
||||
0xa,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x4,0x3,0x3, // e0..ef
|
||||
0xb,0x6,0x6,0x6,0x5,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8, // f0..ff
|
||||
static const unsigned char s_byteTypeTable[] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00..1f
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20..3f
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40..5f
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 60..7f
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, // 80..9f
|
||||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
||||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // a0..bf
|
||||
8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // c0..df
|
||||
0xa, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // e0..ef
|
||||
0xb, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // f0..ff
|
||||
};
|
||||
|
||||
const unsigned char s0 = 0 * 12;
|
||||
@@ -47,28 +53,25 @@ const unsigned char s6 = 6 * 12;
|
||||
const unsigned char s7 = 7 * 12;
|
||||
const unsigned char s8 = 8 * 12;
|
||||
|
||||
static const unsigned char s_transitionTable[] =
|
||||
{
|
||||
s0,s1,s2,s3,s5,s8,s7,s1,s1,s1,s4,s6, // s0
|
||||
s1,s1,s1,s1,s1,s1,s1,s1,s1,s1,s1,s1, // s1
|
||||
s1,s0,s1,s1,s1,s1,s1,s0,s1,s0,s1,s1, // s2
|
||||
s1,s2,s1,s1,s1,s1,s1,s2,s1,s2,s1,s1, // s3
|
||||
s1,s1,s1,s1,s1,s1,s1,s2,s1,s1,s1,s1, // s4
|
||||
s1,s2,s1,s1,s1,s1,s1,s1,s1,s2,s1,s1, // s5
|
||||
s1,s1,s1,s1,s1,s1,s1,s3,s1,s3,s1,s1, // s6
|
||||
s1,s3,s1,s1,s1,s1,s1,s3,s1,s3,s1,s1, // s7
|
||||
s1,s3,s1,s1,s1,s1,s1,s1,s1,s1,s1,s1, // s8
|
||||
static const unsigned char s_transitionTable[] = {
|
||||
s0, s1, s2, s3, s5, s8, s7, s1, s1, s1, s4, s6, // s0
|
||||
s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, // s1
|
||||
s1, s0, s1, s1, s1, s1, s1, s0, s1, s0, s1, s1, // s2
|
||||
s1, s2, s1, s1, s1, s1, s1, s2, s1, s2, s1, s1, // s3
|
||||
s1, s1, s1, s1, s1, s1, s1, s2, s1, s1, s1, s1, // s4
|
||||
s1, s2, s1, s1, s1, s1, s1, s1, s1, s2, s1, s1, // s5
|
||||
s1, s1, s1, s1, s1, s1, s1, s3, s1, s3, s1, s1, // s6
|
||||
s1, s3, s1, s1, s1, s1, s1, s3, s1, s3, s1, s1, // s7
|
||||
s1, s3, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, // s8
|
||||
};
|
||||
|
||||
// Decodes UTF-8 encoded Unicode code point at "s".
|
||||
UnicodeChar DecodeUtf8(const char* s)
|
||||
{
|
||||
UnicodeChar DecodeUtf8(const char* s) {
|
||||
UnicodeChar unicodeChar;
|
||||
int state = s0;
|
||||
auto start = s;
|
||||
|
||||
do
|
||||
{
|
||||
do {
|
||||
unsigned char byte = *s++;
|
||||
int type = s_byteTypeTable[byte];
|
||||
|
||||
@@ -79,8 +82,7 @@ UnicodeChar DecodeUtf8(const char* s)
|
||||
|
||||
state = s_transitionTable[state + type];
|
||||
|
||||
if (state == s1)
|
||||
{
|
||||
if (state == s1) {
|
||||
unicodeChar.code = -1;
|
||||
return unicodeChar;
|
||||
}
|
||||
|
||||
Executable → Regular
+1
-2
@@ -23,8 +23,7 @@
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
struct UnicodeChar
|
||||
{
|
||||
struct UnicodeChar {
|
||||
std::int32_t code;
|
||||
int encodingLength;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user