Merge branch 'master' of https://github.com/pret/pokeemerald into pretmerge13july
This commit is contained in:
commit
50f368eceb
9 changed files with 339 additions and 103 deletions
14
Makefile
14
Makefile
|
@ -377,7 +377,7 @@ ifeq ($(NODEP),1)
|
|||
$(C_BUILDDIR)/%.o: $(C_SUBDIR)/%.c
|
||||
ifeq (,$(KEEP_TEMPS))
|
||||
@echo "$(CC1) <flags> -o $@ $<"
|
||||
@$(CPP) $(CPPFLAGS) $< | $(PREPROC) $< charmap.txt -i | $(CC1) $(CFLAGS) -o - - | cat - <(echo -e ".text\n\t.align\t2, 0") | $(AS) $(ASFLAGS) -o $@ -
|
||||
@$(CPP) $(CPPFLAGS) $< | $(PREPROC) -i $< charmap.txt | $(CC1) $(CFLAGS) -o - - | cat - <(echo -e ".text\n\t.align\t2, 0") | $(AS) $(ASFLAGS) -o $@ -
|
||||
else
|
||||
@$(CPP) $(CPPFLAGS) $< -o $(C_BUILDDIR)/$*.i
|
||||
@$(PREPROC) $(C_BUILDDIR)/$*.i charmap.txt | $(CC1) $(CFLAGS) -o $(C_BUILDDIR)/$*.s
|
||||
|
@ -389,7 +389,7 @@ define C_DEP
|
|||
$1: $2 $$(shell $(SCANINC) -I include -I tools/agbcc/include -I gflib $2)
|
||||
ifeq (,$$(KEEP_TEMPS))
|
||||
@echo "$$(CC1) <flags> -o $$@ $$<"
|
||||
@$$(CPP) $$(CPPFLAGS) $$< | $$(PREPROC) $$< charmap.txt -i | $$(CC1) $$(CFLAGS) -o - - | cat - <(echo -e ".text\n\t.align\t2, 0") | $$(AS) $$(ASFLAGS) -o $$@ -
|
||||
@$$(CPP) $$(CPPFLAGS) $$< | $$(PREPROC) -i $$< charmap.txt | $$(CC1) $$(CFLAGS) -o - - | cat - <(echo -e ".text\n\t.align\t2, 0") | $$(AS) $$(ASFLAGS) -o $$@ -
|
||||
else
|
||||
@$$(CPP) $$(CPPFLAGS) $$< -o $$(C_BUILDDIR)/$3.i
|
||||
@$$(PREPROC) $$(C_BUILDDIR)/$3.i charmap.txt | $$(CC1) $$(CFLAGS) -o $$(C_BUILDDIR)/$3.s
|
||||
|
@ -404,7 +404,7 @@ ifeq ($(NODEP),1)
|
|||
$(GFLIB_BUILDDIR)/%.o: $(GFLIB_SUBDIR)/%.c $$(c_dep)
|
||||
ifeq (,$(KEEP_TEMPS))
|
||||
@echo "$(CC1) <flags> -o $@ $<"
|
||||
@$(CPP) $(CPPFLAGS) $< | $(PREPROC) $< charmap.txt -i | $(CC1) $(CFLAGS) -o - - | cat - <(echo -e ".text\n\t.align\t2, 0") | $(AS) $(ASFLAGS) -o $@ -
|
||||
@$(CPP) $(CPPFLAGS) $< | $(PREPROC) -i $< charmap.txt | $(CC1) $(CFLAGS) -o - - | cat - <(echo -e ".text\n\t.align\t2, 0") | $(AS) $(ASFLAGS) -o $@ -
|
||||
else
|
||||
@$(CPP) $(CPPFLAGS) $< -o $(GFLIB_BUILDDIR)/$*.i
|
||||
@$(PREPROC) $(GFLIB_BUILDDIR)/$*.i charmap.txt | $(CC1) $(CFLAGS) -o $(GFLIB_BUILDDIR)/$*.s
|
||||
|
@ -416,7 +416,7 @@ define GFLIB_DEP
|
|||
$1: $2 $$(shell $(SCANINC) -I include -I tools/agbcc/include -I gflib $2)
|
||||
ifeq (,$$(KEEP_TEMPS))
|
||||
@echo "$$(CC1) <flags> -o $$@ $$<"
|
||||
@$$(CPP) $$(CPPFLAGS) $$< | $$(PREPROC) $$< charmap.txt -i | $$(CC1) $$(CFLAGS) -o - - | cat - <(echo -e ".text\n\t.align\t2, 0") | $$(AS) $$(ASFLAGS) -o $$@ -
|
||||
@$$(CPP) $$(CPPFLAGS) $$< | $$(PREPROC) -i $$< charmap.txt | $$(CC1) $$(CFLAGS) -o - - | cat - <(echo -e ".text\n\t.align\t2, 0") | $$(AS) $$(ASFLAGS) -o $$@ -
|
||||
else
|
||||
@$$(CPP) $$(CPPFLAGS) $$< -o $$(GFLIB_BUILDDIR)/$3.i
|
||||
@$$(PREPROC) $$(GFLIB_BUILDDIR)/$3.i charmap.txt | $$(CC1) $$(CFLAGS) -o $$(GFLIB_BUILDDIR)/$3.s
|
||||
|
@ -429,11 +429,11 @@ endif
|
|||
|
||||
ifeq ($(NODEP),1)
|
||||
$(C_BUILDDIR)/%.o: $(C_SUBDIR)/%.s
|
||||
$(PREPROC) $< charmap.txt | $(CPP) -I include - | $(AS) $(ASFLAGS) -o $@
|
||||
$(PREPROC) $< charmap.txt | $(CPP) -I include - | $(PREPROC) -i $$< charmap.txt | $(AS) $(ASFLAGS) -o $@
|
||||
else
|
||||
define SRC_ASM_DATA_DEP
|
||||
$1: $2 $$(shell $(SCANINC) -I include -I "" $2)
|
||||
$$(PREPROC) $$< charmap.txt | $$(CPP) -I include - | $$(AS) $$(ASFLAGS) -o $$@
|
||||
$$(PREPROC) $$< charmap.txt | $$(CPP) -I include - | $$(PREPROC) -ie $$< charmap.txt | $$(AS) $$(ASFLAGS) -o $$@
|
||||
endef
|
||||
$(foreach src, $(C_ASM_SRCS), $(eval $(call SRC_ASM_DATA_DEP,$(patsubst $(C_SUBDIR)/%.s,$(C_BUILDDIR)/%.o, $(src)),$(src))))
|
||||
endif
|
||||
|
@ -451,7 +451,7 @@ endif
|
|||
|
||||
ifeq ($(NODEP),1)
|
||||
$(DATA_ASM_BUILDDIR)/%.o: $(DATA_ASM_SUBDIR)/%.s
|
||||
$(PREPROC) $< charmap.txt | $(CPP) -I include - | $(AS) $(ASFLAGS) -o $@
|
||||
$(PREPROC) $< charmap.txt | $(CPP) -I include - | $(PREPROC) -ie $$< charmap.txt | $(AS) $(ASFLAGS) -o $@
|
||||
else
|
||||
$(foreach src, $(REGULAR_DATA_ASM_SRCS), $(eval $(call SRC_ASM_DATA_DEP,$(patsubst $(DATA_ASM_SUBDIR)/%.s,$(DATA_ASM_BUILDDIR)/%.o, $(src)),$(src))))
|
||||
endif
|
||||
|
|
|
@ -3,10 +3,10 @@ CXX ?= g++
|
|||
CXXFLAGS := -std=c++11 -O2 -Wall -Wno-switch -Werror
|
||||
|
||||
SRCS := asm_file.cpp c_file.cpp charmap.cpp preproc.cpp string_parser.cpp \
|
||||
utf8.cpp
|
||||
utf8.cpp io.cpp
|
||||
|
||||
HEADERS := asm_file.h c_file.h char_util.h charmap.h preproc.h string_parser.h \
|
||||
utf8.h
|
||||
utf8.h io.h
|
||||
|
||||
ifeq ($(OS),Windows_NT)
|
||||
EXE := .exe
|
||||
|
|
|
@ -27,33 +27,12 @@
|
|||
#include "utf8.h"
|
||||
#include "string_parser.h"
|
||||
#include "../../gflib/characters.h"
|
||||
#include "io.h"
|
||||
|
||||
AsmFile::AsmFile(std::string filename) : m_filename(filename)
|
||||
AsmFile::AsmFile(std::string filename, bool isStdin, bool doEnum) : 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());
|
||||
|
||||
std::fseek(fp, 0, SEEK_END);
|
||||
|
||||
m_size = std::ftell(fp);
|
||||
|
||||
if (m_size < 0)
|
||||
FATAL_ERROR("File size of \"%s\" is less than zero.\n", filename.c_str());
|
||||
else if (m_size == 0)
|
||||
return; // Empty file
|
||||
|
||||
m_buffer = new char[m_size + 1];
|
||||
|
||||
std::rewind(fp);
|
||||
|
||||
if (std::fread(m_buffer, m_size, 1, fp) != 1)
|
||||
FATAL_ERROR("Failed to read \"%s\".\n", filename.c_str());
|
||||
|
||||
m_buffer[m_size] = 0;
|
||||
|
||||
std::fclose(fp);
|
||||
m_buffer = ReadFileToBuffer(filename.c_str(), isStdin, &m_size);
|
||||
m_doEnum = doEnum;
|
||||
|
||||
m_pos = 0;
|
||||
m_lineNum = 1;
|
||||
|
@ -65,6 +44,7 @@ AsmFile::AsmFile(std::string filename) : m_filename(filename)
|
|||
AsmFile::AsmFile(AsmFile&& other) : m_filename(std::move(other.m_filename))
|
||||
{
|
||||
m_buffer = other.m_buffer;
|
||||
m_doEnum = other.m_doEnum;
|
||||
m_pos = other.m_pos;
|
||||
m_size = other.m_size;
|
||||
m_lineNum = other.m_lineNum;
|
||||
|
@ -174,6 +154,8 @@ Directive AsmFile::GetDirective()
|
|||
return Directive::String;
|
||||
else if (CheckForDirective(".braille"))
|
||||
return Directive::Braille;
|
||||
else if (CheckForDirective("enum"))
|
||||
return Directive::Enum;
|
||||
else
|
||||
return Directive::Unknown;
|
||||
}
|
||||
|
@ -527,6 +509,70 @@ void AsmFile::OutputLine()
|
|||
}
|
||||
}
|
||||
|
||||
// parses an assumed C `enum`. Returns false if `enum { ...` is not matched
|
||||
bool AsmFile::ParseEnum()
|
||||
{
|
||||
if (!m_doEnum)
|
||||
return false;
|
||||
|
||||
long fallbackPosition = m_pos;
|
||||
std::string headerFilename = "";
|
||||
long currentHeaderLine = SkipWhitespaceAndEol();
|
||||
std::string enumName = ReadIdentifier();
|
||||
currentHeaderLine += SkipWhitespaceAndEol();
|
||||
long enumCounter = 0;
|
||||
long symbolCount = 0;
|
||||
|
||||
if (m_buffer[m_pos] != '{') // assume assembly macro, otherwise assume enum and report errors accordingly
|
||||
{
|
||||
m_pos = fallbackPosition - 4;
|
||||
return false;
|
||||
}
|
||||
|
||||
currentHeaderLine += FindLastLineNumber(headerFilename);
|
||||
m_pos++;
|
||||
for (;;)
|
||||
{
|
||||
currentHeaderLine += SkipWhitespaceAndEol();
|
||||
std::string currentIdentName = ReadIdentifier();
|
||||
if (!currentIdentName.empty())
|
||||
{
|
||||
std::printf("# %ld \"%s\"\n", currentHeaderLine, headerFilename.c_str());
|
||||
currentHeaderLine += SkipWhitespaceAndEol();
|
||||
if (m_buffer[m_pos] == '=')
|
||||
{
|
||||
m_pos++;
|
||||
currentHeaderLine += SkipWhitespaceAndEol();
|
||||
enumCounter = ReadInteger(headerFilename, currentHeaderLine);
|
||||
currentHeaderLine += SkipWhitespaceAndEol();
|
||||
}
|
||||
std::printf(".equiv %s, %ld\n", currentIdentName.c_str(), enumCounter);
|
||||
enumCounter++;
|
||||
symbolCount++;
|
||||
}
|
||||
else if (symbolCount == 0)
|
||||
{
|
||||
RaiseError("%s:%ld: empty enum is invalid", headerFilename.c_str(), currentHeaderLine);
|
||||
}
|
||||
|
||||
if (m_buffer[m_pos] != ',')
|
||||
{
|
||||
currentHeaderLine += SkipWhitespaceAndEol();
|
||||
if (m_buffer[m_pos++] == '}' && m_buffer[m_pos++] == ';')
|
||||
{
|
||||
ExpectEmptyRestOfLine();
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
RaiseError("unterminated enum from included file %s:%ld", headerFilename.c_str(), currentHeaderLine);
|
||||
}
|
||||
}
|
||||
m_pos++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Asserts that the rest of the line is empty and moves to the next one.
|
||||
void AsmFile::ExpectEmptyRestOfLine()
|
||||
{
|
||||
|
@ -599,3 +645,130 @@ void AsmFile::RaiseWarning(const char* format, ...)
|
|||
{
|
||||
DO_REPORT("warning");
|
||||
}
|
||||
|
||||
// Skips Whitespace including newlines and returns the amount of newlines skipped
|
||||
int AsmFile::SkipWhitespaceAndEol()
|
||||
{
|
||||
int newlines = 0;
|
||||
while (m_buffer[m_pos] == '\t' || m_buffer[m_pos] == ' ' || m_buffer[m_pos] == '\n')
|
||||
{
|
||||
if (m_buffer[m_pos] == '\n')
|
||||
newlines++;
|
||||
m_pos++;
|
||||
}
|
||||
return newlines;
|
||||
}
|
||||
|
||||
// returns the last line indicator and its corresponding file name without modifying the token index
|
||||
int AsmFile::FindLastLineNumber(std::string& filename)
|
||||
{
|
||||
long pos = m_pos;
|
||||
long linebreaks = 0;
|
||||
while (m_buffer[pos] != '#' && pos >= 0)
|
||||
{
|
||||
if (m_buffer[pos] == '\n')
|
||||
linebreaks++;
|
||||
pos--;
|
||||
}
|
||||
|
||||
if (pos < 0)
|
||||
RaiseError("line indicator for header file not found before `enum`");
|
||||
|
||||
pos++;
|
||||
while (m_buffer[pos] == ' ' || m_buffer[pos] == '\t')
|
||||
pos++;
|
||||
|
||||
if (!IsAsciiDigit(m_buffer[pos]))
|
||||
RaiseError("malformatted line indicator found before `enum`, expected line number");
|
||||
|
||||
unsigned n = 0;
|
||||
int digit = 0;
|
||||
while ((digit = ConvertDigit(m_buffer[pos++], 10)) != -1)
|
||||
n = 10 * n + digit;
|
||||
|
||||
while (m_buffer[pos] == ' ' || m_buffer[pos] == '\t')
|
||||
pos++;
|
||||
|
||||
if (m_buffer[pos++] != '"')
|
||||
RaiseError("malformatted line indicator found before `enum`, expected filename");
|
||||
|
||||
while (m_buffer[pos] != '"')
|
||||
{
|
||||
unsigned char c = m_buffer[pos++];
|
||||
|
||||
if (c == 0)
|
||||
{
|
||||
if (pos >= m_size)
|
||||
RaiseError("unexpected EOF in line indicator");
|
||||
else
|
||||
RaiseError("unexpected null character in line indicator");
|
||||
}
|
||||
|
||||
if (!IsAsciiPrintable(c))
|
||||
RaiseError("unexpected character '\\x%02X' in line indicator", c);
|
||||
|
||||
if (c == '\\')
|
||||
{
|
||||
c = m_buffer[pos];
|
||||
RaiseError("unexpected escape '\\%c' in line indicator", c);
|
||||
}
|
||||
|
||||
filename += c;
|
||||
}
|
||||
|
||||
return n + linebreaks - 1;
|
||||
}
|
||||
|
||||
std::string AsmFile::ReadIdentifier()
|
||||
{
|
||||
long start = m_pos;
|
||||
if (!IsIdentifierStartingChar(m_buffer[m_pos]))
|
||||
return std::string();
|
||||
|
||||
m_pos++;
|
||||
|
||||
while (IsIdentifierChar(m_buffer[m_pos]))
|
||||
m_pos++;
|
||||
|
||||
return std::string(&m_buffer[start], m_pos - start);
|
||||
}
|
||||
|
||||
long AsmFile::ReadInteger(std::string filename, long line)
|
||||
{
|
||||
bool negate = false;
|
||||
int radix = 10;
|
||||
if (!IsAsciiDigit(m_buffer[m_pos]))
|
||||
{
|
||||
if (m_buffer[m_pos++] == '-')
|
||||
negate = true;
|
||||
else
|
||||
RaiseError("expected number in included file %s:%ld", filename.c_str(), line);
|
||||
}
|
||||
|
||||
if (m_buffer[m_pos] == '0' && m_buffer[m_pos + 1] == 'x')
|
||||
{
|
||||
radix = 16;
|
||||
m_pos += 2;
|
||||
}
|
||||
else if (m_buffer[m_pos] == '0' && m_buffer[m_pos + 1] == 'b')
|
||||
{
|
||||
radix = 2;
|
||||
m_pos += 2;
|
||||
}
|
||||
else if (m_buffer[m_pos] == '0' && IsAsciiDigit(m_buffer[m_pos+1]))
|
||||
{
|
||||
radix = 8;
|
||||
m_pos++;
|
||||
}
|
||||
|
||||
long n = 0;
|
||||
int digit;
|
||||
|
||||
while ((digit = ConvertDigit(m_buffer[m_pos], radix)) != -1)
|
||||
{
|
||||
n = n * radix + digit;
|
||||
m_pos++;
|
||||
}
|
||||
|
||||
return negate ? -n : n;
|
||||
}
|
||||
|
|
|
@ -31,13 +31,14 @@ enum class Directive
|
|||
Include,
|
||||
String,
|
||||
Braille,
|
||||
Enum,
|
||||
Unknown
|
||||
};
|
||||
|
||||
class AsmFile
|
||||
{
|
||||
public:
|
||||
AsmFile(std::string filename);
|
||||
AsmFile(std::string filename, bool isStdin, bool doEnum);
|
||||
AsmFile(AsmFile&& other);
|
||||
AsmFile(const AsmFile&) = delete;
|
||||
~AsmFile();
|
||||
|
@ -49,9 +50,11 @@ public:
|
|||
bool IsAtEnd();
|
||||
void OutputLine();
|
||||
void OutputLocation();
|
||||
bool ParseEnum();
|
||||
|
||||
private:
|
||||
char* m_buffer;
|
||||
bool m_doEnum;
|
||||
long m_pos;
|
||||
long m_size;
|
||||
long m_lineNum;
|
||||
|
@ -68,6 +71,10 @@ private:
|
|||
void RaiseError(const char* format, ...);
|
||||
void RaiseWarning(const char* format, ...);
|
||||
void VerifyStringLength(int length);
|
||||
int SkipWhitespaceAndEol();
|
||||
int FindLastLineNumber(std::string& filename);
|
||||
std::string ReadIdentifier();
|
||||
long ReadInteger(std::string filename, long line);
|
||||
};
|
||||
|
||||
#endif // ASM_FILE_H
|
||||
|
|
|
@ -30,56 +30,16 @@
|
|||
#include "char_util.h"
|
||||
#include "utf8.h"
|
||||
#include "string_parser.h"
|
||||
#include "io.h"
|
||||
|
||||
CFile::CFile(const char * filenameCStr, bool isStdin)
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
if (isStdin) {
|
||||
fp = stdin;
|
||||
if (isStdin)
|
||||
m_filename = std::string{"<stdin>/"}.append(filenameCStr);
|
||||
} else {
|
||||
fp = std::fopen(filenameCStr, "rb");
|
||||
else
|
||||
m_filename = std::string(filenameCStr);
|
||||
}
|
||||
|
||||
std::string& filename = m_filename;
|
||||
|
||||
if (fp == NULL)
|
||||
FATAL_ERROR("Failed to open \"%s\" for reading.\n", filename.c_str());
|
||||
|
||||
m_size = 0;
|
||||
m_buffer = (char *)malloc(CHUNK_SIZE + 1);
|
||||
if (m_buffer == NULL) {
|
||||
FATAL_ERROR("Failed to allocate memory to process file \"%s\"!", filename.c_str());
|
||||
}
|
||||
|
||||
std::size_t numAllocatedBytes = CHUNK_SIZE + 1;
|
||||
std::size_t bufferOffset = 0;
|
||||
std::size_t count;
|
||||
|
||||
while ((count = std::fread(m_buffer + bufferOffset, 1, CHUNK_SIZE, fp)) != 0) {
|
||||
if (!std::ferror(fp)) {
|
||||
m_size += count;
|
||||
|
||||
if (std::feof(fp)) {
|
||||
break;
|
||||
}
|
||||
|
||||
numAllocatedBytes += CHUNK_SIZE;
|
||||
bufferOffset += CHUNK_SIZE;
|
||||
m_buffer = (char *)realloc(m_buffer, numAllocatedBytes);
|
||||
if (m_buffer == NULL) {
|
||||
FATAL_ERROR("Failed to allocate memory to process file \"%s\"!", filename.c_str());
|
||||
}
|
||||
} else {
|
||||
FATAL_ERROR("Failed to read \"%s\". (error: %s)", filename.c_str(), std::strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
m_buffer[m_size] = 0;
|
||||
|
||||
std::fclose(fp);
|
||||
m_buffer = ReadFileToBuffer(filenameCStr, isStdin, &m_size);
|
||||
|
||||
m_pos = 0;
|
||||
m_lineNum = 1;
|
||||
|
|
|
@ -56,6 +56,4 @@ private:
|
|||
void RaiseWarning(const char* format, ...);
|
||||
};
|
||||
|
||||
#define CHUNK_SIZE 4096
|
||||
|
||||
#endif // C_FILE_H
|
||||
|
|
51
tools/preproc/io.cpp
Normal file
51
tools/preproc/io.cpp
Normal file
|
@ -0,0 +1,51 @@
|
|||
#include "preproc.h"
|
||||
#include "io.h"
|
||||
#include <string>
|
||||
#include <cerrno>
|
||||
#include <cstring>
|
||||
|
||||
char *ReadFileToBuffer(const char *filename, bool isStdin, long *size)
|
||||
{
|
||||
FILE *fp;
|
||||
if (isStdin)
|
||||
fp = stdin;
|
||||
else
|
||||
fp = std::fopen(filename, "rb");
|
||||
|
||||
if (fp == NULL)
|
||||
FATAL_ERROR("Failed to open \"%s\" for reading.\n", filename);
|
||||
|
||||
*size = 0;
|
||||
char *buffer = (char *)malloc(CHUNK_SIZE + 1);
|
||||
if (buffer == NULL) {
|
||||
FATAL_ERROR("Failed to allocate memory to process file \"%s\"!", filename);
|
||||
}
|
||||
|
||||
std::size_t numAllocatedBytes = CHUNK_SIZE + 1;
|
||||
std::size_t bufferOffset = 0;
|
||||
std::size_t count;
|
||||
|
||||
while ((count = std::fread(buffer + bufferOffset, 1, CHUNK_SIZE, fp)) != 0) {
|
||||
if (!std::ferror(fp)) {
|
||||
*size += count;
|
||||
|
||||
if (std::feof(fp)) {
|
||||
break;
|
||||
}
|
||||
|
||||
numAllocatedBytes += CHUNK_SIZE;
|
||||
bufferOffset += CHUNK_SIZE;
|
||||
buffer = (char *)realloc(buffer, numAllocatedBytes);
|
||||
if (buffer == NULL) {
|
||||
FATAL_ERROR("Failed to allocate memory to process file \"%s\"!", filename);
|
||||
}
|
||||
} else {
|
||||
FATAL_ERROR("Failed to read \"%s\". (error: %s)", filename, std::strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
buffer[*size] = 0;
|
||||
|
||||
std::fclose(fp);
|
||||
return buffer;
|
||||
}
|
8
tools/preproc/io.h
Normal file
8
tools/preproc/io.h
Normal file
|
@ -0,0 +1,8 @@
|
|||
#ifndef IO_H_
|
||||
#define IO_H_
|
||||
|
||||
#define CHUNK_SIZE 4096
|
||||
|
||||
char *ReadFileToBuffer(const char *filename, bool isStdin, long *size);
|
||||
|
||||
#endif // IO_H_
|
|
@ -20,11 +20,14 @@
|
|||
|
||||
#include <string>
|
||||
#include <stack>
|
||||
#include <unistd.h>
|
||||
#include "preproc.h"
|
||||
#include "asm_file.h"
|
||||
#include "c_file.h"
|
||||
#include "charmap.h"
|
||||
|
||||
static void UsageAndExit(const char *program);
|
||||
|
||||
Charmap* g_charmap;
|
||||
|
||||
void PrintAsmBytes(unsigned char *s, int length)
|
||||
|
@ -43,11 +46,12 @@ void PrintAsmBytes(unsigned char *s, int length)
|
|||
}
|
||||
}
|
||||
|
||||
void PreprocAsmFile(std::string filename)
|
||||
void PreprocAsmFile(std::string filename, bool isStdin, bool doEnum)
|
||||
{
|
||||
std::stack<AsmFile> stack;
|
||||
|
||||
stack.push(AsmFile(filename));
|
||||
stack.push(AsmFile(filename, isStdin, doEnum));
|
||||
std::printf("# 1 \"%s\"\n", filename.c_str());
|
||||
|
||||
for (;;)
|
||||
{
|
||||
|
@ -66,7 +70,7 @@ void PreprocAsmFile(std::string filename)
|
|||
switch (directive)
|
||||
{
|
||||
case Directive::Include:
|
||||
stack.push(AsmFile(stack.top().ReadPath()));
|
||||
stack.push(AsmFile(stack.top().ReadPath(), false, doEnum));
|
||||
stack.top().OutputLocation();
|
||||
break;
|
||||
case Directive::String:
|
||||
|
@ -83,6 +87,12 @@ void PreprocAsmFile(std::string filename)
|
|||
PrintAsmBytes(s, length);
|
||||
break;
|
||||
}
|
||||
case Directive::Enum:
|
||||
{
|
||||
if (!stack.top().ParseEnum())
|
||||
stack.top().OutputLine();
|
||||
break;
|
||||
}
|
||||
case Directive::Unknown:
|
||||
{
|
||||
std::string globalLabel = stack.top().GetGlobalLabel();
|
||||
|
@ -109,9 +119,9 @@ void PreprocCFile(const char * filename, bool isStdin)
|
|||
cFile.Preproc();
|
||||
}
|
||||
|
||||
char* GetFileExtension(char* filename)
|
||||
const char* GetFileExtension(const char* filename)
|
||||
{
|
||||
char* extension = filename;
|
||||
const char* extension = filename;
|
||||
|
||||
while (*extension != 0)
|
||||
extension++;
|
||||
|
@ -130,35 +140,64 @@ char* GetFileExtension(char* filename)
|
|||
return extension;
|
||||
}
|
||||
|
||||
static void UsageAndExit(const char *program)
|
||||
{
|
||||
std::fprintf(stderr, "Usage: %s [-i] [-e] SRC_FILE CHARMAP_FILE\nwhere -i denotes if input is from stdin\n -e enables enum handling\n", program);
|
||||
std::exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc < 3 || argc > 4)
|
||||
int opt;
|
||||
const char *source = NULL;
|
||||
const char *charmap = NULL;
|
||||
bool isStdin = false;
|
||||
bool doEnum = false;
|
||||
|
||||
/* preproc [-i] [-e] SRC_FILE CHARMAP_FILE */
|
||||
while ((opt = getopt(argc, argv, "ie")) != -1)
|
||||
{
|
||||
std::fprintf(stderr, "Usage: %s SRC_FILE CHARMAP_FILE [-i]\nwhere -i denotes if input is from stdin\n", argv[0]);
|
||||
return 1;
|
||||
switch (opt)
|
||||
{
|
||||
case 'i':
|
||||
isStdin = true;
|
||||
break;
|
||||
case 'e':
|
||||
doEnum = true;
|
||||
break;
|
||||
default:
|
||||
UsageAndExit(argv[0]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
g_charmap = new Charmap(argv[2]);
|
||||
if (optind + 2 != argc)
|
||||
UsageAndExit(argv[0]);
|
||||
|
||||
char* extension = GetFileExtension(argv[1]);
|
||||
source = argv[optind + 0];
|
||||
charmap = argv[optind + 1];
|
||||
|
||||
g_charmap = new Charmap(charmap);
|
||||
|
||||
const char* extension = GetFileExtension(source);
|
||||
|
||||
if (!extension)
|
||||
FATAL_ERROR("\"%s\" has no file extension.\n", argv[1]);
|
||||
|
||||
if ((extension[0] == 's') && extension[1] == 0)
|
||||
PreprocAsmFile(argv[1]);
|
||||
else if ((extension[0] == 'c' || extension[0] == 'i') && extension[1] == 0) {
|
||||
if (argc == 4) {
|
||||
if (argv[3][0] == '-' && argv[3][1] == 'i' && argv[3][2] == '\0') {
|
||||
PreprocCFile(argv[1], true);
|
||||
} else {
|
||||
FATAL_ERROR("unknown argument flag \"%s\".\n", argv[3]);
|
||||
}
|
||||
} else {
|
||||
PreprocCFile(argv[1], false);
|
||||
}
|
||||
} else
|
||||
{
|
||||
PreprocAsmFile(source, isStdin, doEnum);
|
||||
}
|
||||
else if ((extension[0] == 'c' || extension[0] == 'i') && extension[1] == 0)
|
||||
{
|
||||
if (doEnum)
|
||||
FATAL_ERROR("-e is invalid for C sources\n");
|
||||
PreprocCFile(source, isStdin);
|
||||
}
|
||||
else
|
||||
{
|
||||
FATAL_ERROR("\"%s\" has an unknown file extension of \"%s\".\n", argv[1], extension);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue