Skip to content

Commit

Permalink
[preproc] parse enum only in 2nd pass
Browse files Browse the repository at this point in the history
fix: usage_and_exit -> UsageAndExit
  • Loading branch information
mrgriffin authored and phil committed Jul 9, 2024
1 parent aef6170 commit 41eaf11
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 48 deletions.
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
35 changes: 22 additions & 13 deletions tools/preproc/asm_file.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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();
Expand All @@ -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();
Expand Down
3 changes: 2 additions & 1 deletion tools/preproc/asm_file.h
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -54,6 +54,7 @@ class AsmFile

private:
char* m_buffer;
bool m_doEnum;
long m_pos;
long m_size;
long m_lineNum;
Expand Down
97 changes: 65 additions & 32 deletions tools/preproc/preproc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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<AsmFile> stack;

stack.push(AsmFile(filename, isStdin));
stack.push(AsmFile(filename, isStdin, doEnum));
std::printf("# 1 \"%s\"\n", filename.c_str());

for (;;)
Expand All @@ -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:
Expand Down Expand Up @@ -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++;
Expand All @@ -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;
}

0 comments on commit 41eaf11

Please sign in to comment.