From 760e23cb0d92512bc2480d8c696301ffbde9e326 Mon Sep 17 00:00:00 2001 From: "Prof. 9" Date: Wed, 25 May 2022 19:14:51 +0200 Subject: [PATCH 1/6] Implement .importsym directive --- Commands/CDirectiveFile.cpp | 122 ++++++++++++++++++++++++++++++++++++ Commands/CDirectiveFile.h | 15 +++++ Parser/DirectivesParser.cpp | 11 ++++ Readme.md | 8 +++ 4 files changed, 156 insertions(+) diff --git a/Commands/CDirectiveFile.cpp b/Commands/CDirectiveFile.cpp index 7df4ac61..86a9f3ef 100644 --- a/Commands/CDirectiveFile.cpp +++ b/Commands/CDirectiveFile.cpp @@ -562,3 +562,125 @@ void DirectiveObjImport::writeSymData(SymbolData& symData) const rel.writeSymbols(symData); } + +// +// CDirectiveSymImport +// +CDirectiveSymImport::CDirectiveSymImport(const fs::path& fileName) +{ + // We may be adding global labels, so start a new section + updateSection(++Global.Section); + + this->fileName = getFullPathName(fileName); + if (!fs::exists(this->fileName)) + { + Logger::printError(Logger::FatalError,"File %s not found",this->fileName.u8string()); + return; + } + + fs::ifstream file(this->fileName,fs::ifstream::in|fs::ifstream::binary); + if (!file.is_open()) + { + Logger::printError(Logger::FatalError,"Could not open file %s",this->fileName.u8string()); + return; + } + + std::string line; + size_t l = 0; + while (l++, std::getline(file,line,'\n')) + { + // End line at comment (starting with ;) + // \x1A included here as well since No$gba .sym file ends with it + size_t lineEnd = line.find_first_of(";\r\x1A"); + if (lineEnd != std::string::npos && lineEnd > 0) + { + lineEnd = line.find_last_not_of(" \t",lineEnd-1); + if (lineEnd != std::string::npos) + lineEnd += 1; + } + + // Skip empty line + if (lineEnd <= 0) + continue; + line = line.substr(0,lineEnd); + + // Parse address of exactly 8 chars + const char* addressStart = line.c_str(); + char* addressEnd; + uint32_t address = strtoul(addressStart,&addressEnd,16); + if (addressEnd != addressStart+8) + { + Logger::printError(Logger::Warning,"Invalid symbol address on line %i of symbols file %s",l,this->fileName); + continue; + } + + // Skip one or more space or tabs + size_t startOfName = line.find_first_not_of(" \t",8); + if (startOfName == std::string::npos || startOfName < (8+1)) + { + Logger::printError(Logger::Warning,"Invalid symbol address on line %i of symbols file %s",l,this->fileName); + continue; + } + + // Rest of the line is the symbol name + std::string name = line.substr(startOfName); + + // Create label for this symbol, if it's not a directive and it would be a global label + const Identifier identifier = Identifier(name); + if (name.find('.') != 0 && Global.symbolTable.isGlobalSymbol(identifier)) + { + std::shared_ptr