diff --git a/Makefile b/Makefile index fceee4e138f3..93448b1272c3 100644 --- a/Makefile +++ b/Makefile @@ -367,7 +367,7 @@ $(C_BUILDDIR)/%.o: $(C_SUBDIR)/%.s else define SRC_ASM_DATA_DEP $1: $2 $$(shell $(SCANINC) -I include -I "" $2) - $$(PREPROC) $$< charmap.txt | $$(CPP) -I include - | $$(PREPROC) $$< charmap.txt -i | $$(AS) $$(ASFLAGS) -o $$@ + $$(PREPROC) $$< charmap.txt | $$(CPP) -I include - | $$(PREPROC) $$< charmap.txt -i -e | $$(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 @@ -385,7 +385,7 @@ endif ifeq ($(NODEP),1) $(DATA_ASM_BUILDDIR)/%.o: $(DATA_ASM_SUBDIR)/%.s - $(PREPROC) $< charmap.txt | $(CPP) -I include - | $(PREPROC) $$< charmap.txt -i | $(AS) $(ASFLAGS) -o $@ + $(PREPROC) $< charmap.txt | $(CPP) -I include - | $(PREPROC) $$< charmap.txt -i -e | $(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 diff --git a/tools/preproc/asm_file.cpp b/tools/preproc/asm_file.cpp index 7eca0850401a..ca8b8cc4ae96 100644 --- a/tools/preproc/asm_file.cpp +++ b/tools/preproc/asm_file.cpp @@ -29,9 +29,10 @@ #include "../../gflib/characters.h" #include "io.h" -AsmFile::AsmFile(std::string filename, bool isStdin) : m_filename(filename) +AsmFile::AsmFile(std::string filename, bool isStdin, bool doEnum) : m_filename(filename) { m_buffer = ReadFileToBuffer(filename.c_str(), isStdin, &m_size); + m_doEnum = doEnum; m_pos = 0; m_lineNum = 1; @@ -43,6 +44,7 @@ AsmFile::AsmFile(std::string filename, bool isStdin) : 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; @@ -510,6 +512,9 @@ 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(); @@ -530,22 +535,26 @@ bool AsmFile::ParseEnum() { currentHeaderLine += SkipWhitespaceAndEol(); std::string currentIdentName = ReadIdentifier(); - if (currentIdentName.empty() && symbolCount == 0) + if (!currentIdentName.empty()) { - RaiseError("%s:%ld: empty enum is invalid", headerFilename.c_str(), currentHeaderLine); + 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++; } - std::printf("# %ld \"%s\"\n", currentHeaderLine, headerFilename.c_str()); - currentHeaderLine += SkipWhitespaceAndEol(); - if (m_buffer[m_pos] == '=') + else if (symbolCount == 0) { - m_pos++; - currentHeaderLine += SkipWhitespaceAndEol(); - enumCounter = ReadInteger(headerFilename, currentHeaderLine); - currentHeaderLine += SkipWhitespaceAndEol(); + RaiseError("%s:%ld: empty enum is invalid", headerFilename.c_str(), currentHeaderLine); } - - std::printf(".equiv %s, %ld\n", currentIdentName.c_str(), enumCounter); - enumCounter++; + if (m_buffer[m_pos] != ',') { currentHeaderLine += SkipWhitespaceAndEol(); diff --git a/tools/preproc/asm_file.h b/tools/preproc/asm_file.h index 83ed9c2e0deb..33e6ce5c49c1 100644 --- a/tools/preproc/asm_file.h +++ b/tools/preproc/asm_file.h @@ -38,7 +38,7 @@ enum class Directive class AsmFile { public: - AsmFile(std::string filename, bool isStdin); + AsmFile(std::string filename, bool isStdin, bool doEnum); AsmFile(AsmFile&& other); AsmFile(const AsmFile&) = delete; ~AsmFile(); @@ -54,6 +54,7 @@ class AsmFile private: char* m_buffer; + bool m_doEnum; long m_pos; long m_size; long m_lineNum; diff --git a/tools/preproc/preproc.cpp b/tools/preproc/preproc.cpp index 9926a04b812f..a6ddb53ac96f 100644 --- a/tools/preproc/preproc.cpp +++ b/tools/preproc/preproc.cpp @@ -20,11 +20,14 @@ #include #include +#include #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,11 @@ void PrintAsmBytes(unsigned char *s, int length) } } -void PreprocAsmFile(std::string filename, bool isStdin) +void PreprocAsmFile(std::string filename, bool isStdin, bool doEnum) { std::stack stack; - stack.push(AsmFile(filename, isStdin)); + stack.push(AsmFile(filename, isStdin, doEnum)); std::printf("# 1 \"%s\"\n", filename.c_str()); for (;;) @@ -67,7 +70,7 @@ void PreprocAsmFile(std::string filename, bool isStdin) switch (directive) { case Directive::Include: - stack.push(AsmFile(stack.top().ReadPath(), false)); + stack.push(AsmFile(stack.top().ReadPath(), false, doEnum)); stack.top().OutputLocation(); break; case Directive::String: @@ -116,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++; @@ -137,45 +140,75 @@ char* GetFileExtension(char* filename) return extension; } +static void UsageAndExit(const char *program) +{ + std::fprintf(stderr, "Usage: %s SRC_FILE CHARMAP_FILE [-i] [-e]\nwhere -i denotes if input is from stdin\n -e enables enum handling\n", argv0); + 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 SRC_FILE CHARMAP_FILE [-i] [-e] */ + 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 1: // positional. + switch (optind) + { + case 2: + source = optarg; + break; + case 3: + charmap = optarg; + break; + default: + UsageAndExit(argv[0]); + break; + } + break; + case 'i': + isStdin = true; + break; + case 'e': + doEnum = true; + break; + default: + UsageAndExit(argv[0]); + break; + } } - g_charmap = new Charmap(argv[2]); + if (optind != argc || !source || !charmap) + UsageAndExit(argv[0]); + + g_charmap = new Charmap(charmap); - char* extension = GetFileExtension(argv[1]); + const char* extension = GetFileExtension(source); if (!extension) FATAL_ERROR("\"%s\" has no file extension.\n", argv[1]); - if ((extension[0] == 's') && extension[1] == 0) { - if (argc == 4) { - if (argv[3][0] == '-' && argv[3][1] == 'i' && argv[3][2] == '\0') { - PreprocAsmFile(argv[1], true); - } else { - FATAL_ERROR("unknown argument flag \"%s\".\n", argv[3]); - } - } else { - PreprocAsmFile(argv[1], false); - } - + if ((extension[0] == 's') && extension[1] == 0) + { + PreprocAsmFile(source, isStdin, doEnum); } - 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 + 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; }