added pragma support to build_segment tool
This commit is contained in:
1 parent
41c94e0577
commit
73f05a13c8
5 files changed
+131
-24
No files matched your search
+97
-6
@@ -79,9 +79,14 @@ class SourceFile
|
||||
public:
|
||||
SourceFile(const std::string &fileName, const std::string &dirName);
|
||||
|
||||
void preprocess();
|
||||
bool preprocessLine(const std::string &line);
|
||||
bool nameMatch(const std::string &token, const std::string &name);
|
||||
|
||||
std::string fileName;
|
||||
std::string dirName;
|
||||
|
||||
bool ignore;
|
||||
bool floating;
|
||||
std::vector<char> content;
|
||||
|
||||
@@ -120,7 +125,7 @@ public:
|
||||
class Solver
|
||||
{
|
||||
public:
|
||||
Solver(BinningProblem &problem) : problem(problem), logOutput(logFile, std::cout) {}
|
||||
explicit Solver(BinningProblem &problem) : problem(problem), logOutput(logFile, std::cout) {}
|
||||
|
||||
void run();
|
||||
|
||||
@@ -164,7 +169,7 @@ void parseCommandLine(int argc, char **argv)
|
||||
case 'd': CMD_outDir = optarg; break;
|
||||
case 's': CMD_segName = optarg; break;
|
||||
case 'i': CMD_segInfo = optarg; break;
|
||||
case 'r': CMD_romLayout = optarg; break;
|
||||
case 'r': CMD_romLayout = optarg; break;
|
||||
case 'l': CMD_loAddress = strtol(optarg, nullptr ,16); break;
|
||||
case 'h': CMD_hiAddress = strtol(optarg, nullptr ,16); break;
|
||||
default: printUsage(); ERROR();
|
||||
@@ -196,7 +201,7 @@ void readSourceFiles()
|
||||
// This is a regular file
|
||||
|
||||
char *tmp1 = strdup(objName.c_str());
|
||||
char *tmp2 = strdup(objName.c_str());
|
||||
char *tmp2 = strdup(objName.c_str());
|
||||
|
||||
std::string dirName = dirname(tmp1);
|
||||
std::string fileName = basename(tmp2);
|
||||
@@ -235,6 +240,11 @@ void readSourceFiles()
|
||||
closedir(dirHandle);
|
||||
}
|
||||
|
||||
// Filter-out files marked as ignored
|
||||
|
||||
GLOBAL_sourceFiles.erase(std::remove_if(GLOBAL_sourceFiles.begin(), GLOBAL_sourceFiles.end(),
|
||||
[](const SourceFile &sourceFile) -> bool { return sourceFile.ignore; }), GLOBAL_sourceFiles.end());
|
||||
|
||||
if (GLOBAL_sourceFiles.empty()) ERROR("no source files found");
|
||||
|
||||
// Sort the file list by name, to provide deterministic results
|
||||
@@ -485,7 +495,7 @@ void compileSegment()
|
||||
", outBin=\"" << CMD_outFile << "\", fill]" <<
|
||||
"\n";
|
||||
outFile << "#define SEGMENT_" << CMD_segName << "\n";
|
||||
outFile << "#define ROM_LAYOUT_" << CMD_romLayout << "\n";
|
||||
outFile << "#define ROM_LAYOUT_" << CMD_romLayout << "\n";
|
||||
outFile << ".namespace " << CMD_segName << " {" << "\n\n";
|
||||
|
||||
// Write files which only contain definitions (no routines)
|
||||
@@ -557,6 +567,7 @@ int main(int argc, char **argv)
|
||||
SourceFile::SourceFile(const std::string &fileName, const std::string &dirName) :
|
||||
fileName(fileName),
|
||||
dirName(dirName),
|
||||
ignore(false),
|
||||
floating(false),
|
||||
startAddr(-1),
|
||||
codeLength(-1),
|
||||
@@ -607,6 +618,10 @@ SourceFile::SourceFile(const std::string &fileName, const std::string &dirName)
|
||||
startAddr = strtol(fileName.substr(0, 4).c_str(), nullptr ,16);
|
||||
}
|
||||
|
||||
// Preprocess the file (apply settings from the content)
|
||||
|
||||
preprocess();
|
||||
|
||||
// Generate KickAss compatible label from the file name
|
||||
|
||||
label = fileName.substr(0, fileName.length() - 2);
|
||||
@@ -615,6 +630,82 @@ SourceFile::SourceFile(const std::string &fileName, const std::string &dirName)
|
||||
std::replace(label.begin(), label.end(), ',', '_');
|
||||
}
|
||||
|
||||
void SourceFile::preprocess()
|
||||
{
|
||||
std::string contentStr(content.begin(), content.end());
|
||||
std::istringstream stream(contentStr);
|
||||
std::string line;
|
||||
|
||||
while (std::getline(stream, line))
|
||||
{
|
||||
if (line.empty()) continue;
|
||||
std::replace(std::begin(line), std::end(line), '\t', ' ');
|
||||
if (!preprocessLine(line)) break;
|
||||
}
|
||||
}
|
||||
|
||||
bool SourceFile::preprocessLine(const std::string &line)
|
||||
{
|
||||
// Split the line into tokens
|
||||
|
||||
std::list<std::string> tokens;
|
||||
|
||||
std::istringstream stream(line);
|
||||
std::string token;
|
||||
while(std::getline(stream, token, ' '))
|
||||
{
|
||||
if (token.empty()) continue;
|
||||
tokens.push_back(token);
|
||||
}
|
||||
if (tokens.empty()) return true;
|
||||
|
||||
// Now preprocess line using the token list
|
||||
|
||||
auto iter = tokens.begin();
|
||||
|
||||
// Injest the comment token
|
||||
|
||||
if ((iter++)->compare("//") != 0 || iter == tokens.end()) return true;
|
||||
|
||||
// Check if supported directive
|
||||
|
||||
if ((iter++)->compare("#LAYOUT#") != 0) return true;
|
||||
|
||||
// Check if segment name and rom layout match
|
||||
|
||||
if (iter == tokens.end()) ERROR("syntax error, missing segment name in '#LAYOUT#'");
|
||||
if (!nameMatch(*(iter++), CMD_segName)) return true;
|
||||
|
||||
if (iter == tokens.end()) ERROR("syntax error, missing rom layout in '#LAYOUT#'");
|
||||
if (!nameMatch(*(iter++), CMD_romLayout)) return true;
|
||||
|
||||
// Retrieve and apply action
|
||||
|
||||
if (iter == tokens.end()) ERROR("syntax error, missing action in '#LAYOUT#'");
|
||||
|
||||
if (iter->compare("#IGNORE") == 0)
|
||||
{
|
||||
ignore = true;
|
||||
}
|
||||
else if (iter->compare("#TAKE-FLOAT") == 0)
|
||||
{
|
||||
floating = true;
|
||||
}
|
||||
else if (iter->compare("#TAKE") != 0)
|
||||
{
|
||||
ERROR("syntax error, unsupported action in '#LAYOUT#'");
|
||||
}
|
||||
|
||||
// Tell the caller to finish processing the file
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SourceFile::nameMatch(const std::string &token, const std::string &name)
|
||||
{
|
||||
return (token.compare("*") == 0) || (token.compare(name) == 0);
|
||||
}
|
||||
|
||||
//
|
||||
// Class 'BinningProblem'
|
||||
//
|
||||
@@ -630,7 +721,7 @@ BinningProblem::BinningProblem(int loAddress, int hiAddress)
|
||||
|
||||
gaps[loAddress] = hiAddress - loAddress + 1;
|
||||
|
||||
// Initial value of statistics
|
||||
// Initial value of statistics
|
||||
|
||||
statSize = gaps[loAddress];
|
||||
statFree = gaps[loAddress];
|
||||
@@ -672,7 +763,7 @@ void BinningProblem::addToProblem(SourceFile *routine)
|
||||
// Put the routine into the gap, possibly removing it or splitting into two
|
||||
|
||||
fixedRoutines[routine->startAddr] = routine;
|
||||
statFree -= routine->codeLength;
|
||||
statFree -= routine->codeLength;
|
||||
|
||||
// Calculate possible new gap after the routine
|
||||
|
||||
|
||||
Reference in new issue
Block a user