-
Notifications
You must be signed in to change notification settings - Fork 121
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
Remove cpp-optparse from the rest of our project #4072
Remove cpp-optparse from the rest of our project #4072
Conversation
6d8a867
to
488a472
Compare
Doesn't remove it from the full project since three tools still use it. FEXLoader argument loader is fairly special since we have a generator tied to it. This generator lets us have some niceties where everything ends up being a string literal without any sort of dynamic requirements. cpp-optparse has a systemic issue where it makes deep copies of /everything/ all the time. This means it has huge runtime costs and huge stack usage (4992 bytes). The new implementation uses 608 bytes of stack space (plus 640 if it actually parses a strenum). When profiling cpp-optparse with FEXLoader's argument it takes ~2,039,307 ns to parse the arguments! As a direct comparison this new implementation takes ~56,885 ns. Both sides not getting passed /any/ arguments, really shows how spicy this library is.
Fits our needs and /only/ our needs.
488a472
to
3f36125
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adding more comments here, most of which I think already apply to 4070.
} | ||
}; | ||
|
||
bool NeedsArg(const OptionDetails* Details) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Global functions used only locally should be static
.
}; | ||
|
||
void ParseArgument(std::string_view Arg, std::string_view SecondArg, const OptionDetails* Details) { | ||
std::invoke(Parser[FEXCore::ToUnderlying(Details->ParseType)], this, Arg, SecondArg, Details); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not just call the member pointer directly?
std::invoke(Parser[FEXCore::ToUnderlying(Details->ParseType)], this, Arg, SecondArg, Details); | |
(this->*Parser[FEXCore::ToUnderlying(Details->ParseType)])(Arg, SecondArg, Details); |
_exit(1); | ||
} | ||
|
||
class ArgParser final { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This needs some documentation to explain why it exists and what's the difference from the confusingly similarly named ArgLoader.
} | ||
|
||
void MicroArgParser::PrintHelp(char** argv, std::span<ParseMember> ParseList) { | ||
fextl::fmt::print("Usage: {} [options]\n", argv[0]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This does not seem to handle line wrapping, e.g. FEXpidof
now prints very long lines
-q Do not display matched PIDs to stdout. Simply exit with status of true or false if a PID was found
-z Try to detect zombie processes - Usually zombie processes are skipped
instead of
-q Do not display matched PIDs to stdout. Simply exit
with status of true or false if a PID was found
-z Try to detect zombie processes - Usually zombie
processes are skipped
(Also note the extra spaces on the left. Not sure where those are coming from. Both versions seem overly padding-happy, not sure if there's some sort of standard that says there should be at least N characters of whitespace here. Conversely, FEXRootFSFetcher --help
doesn't vertically align the option descriptions for the lengthy --force-ui=[default,tty,zenity]
, though that seems to be the only setting with that issue.)
{FEX::MicroArgParser::ParseMember::Type::Bool, {}, "--current-rootfs", "Print the directory that contains the FEX rootfs. Mounted in the case of squashfs", "0"}, | ||
{FEX::MicroArgParser::ParseMember::Type::Bool, {}, "--tso-emulation-info", "Print how FEX is emulating the x86-TSO memory model.", "0"}, | ||
// Defaults | ||
{FEX::MicroArgParser::ParseMember::Type::Bool, "-v", "--version", "show program's verison number and exit", "0"}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
verison is spelt wrong here and in a couple of other places.
{FEX::MicroArgParser::ParseMember::Type::StringArray, "-o", {}, "Ignore processes with matched pids", {}}, | ||
|
||
// Defaults | ||
{FEX::MicroArgParser::ParseMember::Type::Bool, "-v", "--version", "show program's verison number and exit", "0"}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
show
should be spelt Show
for consistency with other descriptions.
} | ||
} | ||
|
||
ExitWithError(fextl::fmt::format("'{}' Not in list of choices '{}'\n", Arg, Member->Choices)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ExitWithError(fextl::fmt::format("'{}' Not in list of choices '{}'\n", Arg, Member->Choices)); | |
ExitWithError(fextl::fmt::format("Invalid argument '{}'. Valid choices are '{}'\n", Arg, Member->Choices)); |
or better yet:
ExitWithError(fextl::fmt::format("'{}' Not in list of choices '{}'\n", Arg, Member->Choices)); | |
ExitWithError(fextl::fmt::format("Invalid argument '{}' for --TODO. Valid choices are '{}'\n", Arg, Member->Choices)); |
ExitWithError(fextl::fmt::format("'{}' Not in list of choices '{}'\n", Arg, Member->Choices)); | ||
} | ||
|
||
void MicroArgParser::Parse(int argc, char** argv) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Invoking multiple short options at once seems broken now:
./Bin/FEXpidof -sq
Error: Unknown argument: -sq
} | ||
|
||
private: | ||
fextl::vector<std::string_view> _Value; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Identifiers starting with an underscore look out of place here.
Also, this can be an std::optional<vector<string_view>>
instead to avoid having two variables to manage the same state.
{FEX::MicroArgParser::ParseMember::Type::StringArray, "-o", {}, "Ignore processes with matched pids", {}}, | ||
|
||
// Defaults | ||
{FEX::MicroArgParser::ParseMember::Type::Bool, "-v", "--version", "show program's verison number and exit", "0"}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The apostrophe s isn't needed here (and actually sounds slightly wrong to me due to lack of preceding article):
program's version -> program version
if (Arg == "--") { | ||
// Special case break. Remaining arguments get passed to guest. | ||
++ArgParsed; | ||
break; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For tools other than FEXLoader, are we checking and failing if "--" is used by accident (e.g. by slipping in a space)?
Based on #4070
First step: add an argument parser that handles /only/ what FEX needs for its tools.
Second step: Move everything over to that.
Third step: Delete cpp-optparse.
FEXLoader using the generated loader still.