Skip to content

.importsym #224

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open

.importsym #224

wants to merge 6 commits into from

Conversation

Prof9
Copy link
Contributor

@Prof9 Prof9 commented May 25, 2022

This adds the .importsym directive which lets you import a pre-existing symfile. This is pretty useful when you have a base symfile for a game and you want to merge all your new labels into it.

Currently this enforces No$gba semantics where each address must be exactly 8 characters. I'm not sure if sym2 format symfiles allow for different lengths; if so, the restriction could probably be removed.

Also, this doesn't remove or change any data in the output symfile that's overwritten by armips. E.g., you have a memory region that's defined as a data pool and you write a function in there instead, the original data pool definition will be copied to the output symfile as-is (in addition to any new labels you placed in that region). I don't think this is a big problem, though.

.importsym SymFile

Imports all symbols from the existing symfile specified by SymFile. For any symbols in SymFile not starting with ., @ or @@, a global label will be created, which can be used like any other label. Regardless of prefix, all symbols and directives in SymFile are also written to the main output symfile for this run of armips, if symfile writing is enabled. This directive terminates the scope for local labels and equs.

lineEnd = std::min(line.find_first_of(";\r\x1A"),lineEnd);
if (lineEnd != std::string::npos && lineEnd > 0)
{
lineEnd = std::max(line.find_last_not_of(" \t",lineEnd-1)+1,(size_t)0);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is std::max here needed? If you compare against std::string::npos in the if below you should be able to just take the result of find_last_not_of.

This block could probably also be extracted into a trim utility function (e.g. in a local namespace).

{
public:
CDirectiveSymImport(const fs::path& fileName);
~CDirectiveSymImport() { };
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can omit the destructor if it doesn't do any custom logic. If you want to make that explicit, override = default.

return;
}

fs::ifstream file(this->fileName,fs::ifstream::in|fs::ifstream::binary);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why binary? Also, why not use TextFile? That also comes with a utility function to read all lines, which would make the loop below simpler.


// 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))
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Symbols can contain periods (see SymbolTable::isValidSymbolName) - but they can't contain colons, which .sym uses inside of its directives. So perhaps:

if (name.find(':') == std::string::npos && Global.symbolTable.isValidSymbolName(identifier) && Global.symbolTable.isGlobalSymbol(identifier))

This would make the nullptr check below redundant, however, so the check against isValidSymbolName could be used there instead too.

Copy link
Contributor Author

@Prof9 Prof9 May 27, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should still prohibit symbols starting with a period. Not all symfile directives use colons; e.g. .arm, .thumb and .pool do not, and I don't think it makes sense to create a label named .pool. It's also easier to understand.

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);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This works for no$gba .sym files (or -sym output), but not for files generated by -sym2 (if .func was used, at least). Anything after a comma should also be removed from the identifier.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants