1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 01:17:35 +00:00

find: Use a Vector for parsing instead of moving optind

This commit is contained in:
Tim Schumacher 2021-11-23 18:43:59 +01:00 committed by Andreas Kling
parent 4ca35ac1b8
commit 5a21c3b389

View file

@ -364,36 +364,37 @@ private:
NonnullOwnPtr<Command> m_rhs; NonnullOwnPtr<Command> m_rhs;
}; };
static OwnPtr<Command> parse_complex_command(char* argv[]); static OwnPtr<Command> parse_complex_command(Vector<char*>& args);
// Parse a simple command starting at optind; leave optind at its the last // Parse a simple command starting at optind; leave optind at its the last
// argument. Return nullptr if we reach the end of arguments. // argument. Return nullptr if we reach the end of arguments.
static OwnPtr<Command> parse_simple_command(char* argv[]) static OwnPtr<Command> parse_simple_command(Vector<char*>& args)
{ {
StringView arg = argv[optind]; if (args.is_empty())
if (arg.is_null()) {
return {}; return {};
} else if (arg == "(") {
optind++; char* raw_arg = args.take_first();
auto command = parse_complex_command(argv); StringView arg = raw_arg;
if (command && argv[optind] && StringView(argv[++optind]) == ")")
if (arg == "(") {
auto command = parse_complex_command(args);
if (command && !args.is_empty() && StringView(args.first()) == ")")
return command; return command;
fatal_error("Unmatched \033[1m("); fatal_error("Unmatched \033[1m(");
} else if (arg == "-type") { } else if (arg == "-type") {
return make<TypeCommand>(argv[++optind]); return make<TypeCommand>(args.take_first());
} else if (arg == "-links") { } else if (arg == "-links") {
return make<LinksCommand>(argv[++optind]); return make<LinksCommand>(args.take_first());
} else if (arg == "-user") { } else if (arg == "-user") {
return make<UserCommand>(argv[++optind]); return make<UserCommand>(args.take_first());
} else if (arg == "-group") { } else if (arg == "-group") {
return make<GroupCommand>(argv[++optind]); return make<GroupCommand>(args.take_first());
} else if (arg == "-size") { } else if (arg == "-size") {
return make<SizeCommand>(argv[++optind]); return make<SizeCommand>(args.take_first());
} else if (arg == "-name") { } else if (arg == "-name") {
return make<NameCommand>(argv[++optind], CaseSensitivity::CaseSensitive); return make<NameCommand>(args.take_first(), CaseSensitivity::CaseSensitive);
} else if (arg == "-iname") { } else if (arg == "-iname") {
return make<NameCommand>(argv[++optind], CaseSensitivity::CaseInsensitive); return make<NameCommand>(args.take_first(), CaseSensitivity::CaseInsensitive);
} else if (arg == "-print") { } else if (arg == "-print") {
g_have_seen_action_command = true; g_have_seen_action_command = true;
return make<PrintCommand>(); return make<PrintCommand>();
@ -403,20 +404,25 @@ static OwnPtr<Command> parse_simple_command(char* argv[])
} else if (arg == "-exec") { } else if (arg == "-exec") {
g_have_seen_action_command = true; g_have_seen_action_command = true;
Vector<char*> command_argv; Vector<char*> command_argv;
while (argv[++optind] && StringView(argv[optind]) != ";") while (!args.is_empty()) {
command_argv.append(argv[optind]); char* next = args.take_first();
if (next[0] == ';')
break;
command_argv.append(next);
}
return make<ExecCommand>(move(command_argv)); return make<ExecCommand>(move(command_argv));
} else { } else {
fatal_error("Unsupported command \033[1m{}", argv[optind]); fatal_error("Unsupported command \033[1m{}", arg);
} }
} }
static OwnPtr<Command> parse_complex_command(char* argv[]) static OwnPtr<Command> parse_complex_command(Vector<char*>& args)
{ {
auto command = parse_simple_command(argv); auto command = parse_simple_command(args);
while (command && argv[optind] && argv[optind + 1]) { while (command && !args.is_empty()) {
StringView arg = argv[++optind]; char* raw_arg = args.take_first();
StringView arg = raw_arg;
enum { enum {
And, And,
@ -424,21 +430,20 @@ static OwnPtr<Command> parse_complex_command(char* argv[])
} binary_operation { And }; } binary_operation { And };
if (arg == "-a") { if (arg == "-a") {
optind++;
binary_operation = And; binary_operation = And;
} else if (arg == "-o") { } else if (arg == "-o") {
optind++;
binary_operation = Or; binary_operation = Or;
} else if (arg == ")") { } else if (arg == ")") {
// Ooops, looked too far. // Ooops, looked too far.
optind--; args.prepend(raw_arg);
return command; return command;
} else { } else {
// Juxtaposition is an And too, and there's nothing to skip. // Juxtaposition is an And too, and there's nothing to skip.
args.prepend(raw_arg);
binary_operation = And; binary_operation = And;
} }
auto rhs = parse_complex_command(argv); auto rhs = parse_complex_command(args);
if (!rhs) if (!rhs)
fatal_error("Missing right-hand side"); fatal_error("Missing right-hand side");
@ -451,9 +456,9 @@ static OwnPtr<Command> parse_complex_command(char* argv[])
return command; return command;
} }
static NonnullOwnPtr<Command> parse_all_commands(char* argv[]) static NonnullOwnPtr<Command> parse_all_commands(Vector<char*>& args)
{ {
auto command = parse_complex_command(argv); auto command = parse_complex_command(args);
if (g_have_seen_action_command) { if (g_have_seen_action_command) {
VERIFY(command); VERIFY(command);
@ -467,41 +472,6 @@ static NonnullOwnPtr<Command> parse_all_commands(char* argv[])
return make<AndCommand>(command.release_nonnull(), make<PrintCommand>()); return make<AndCommand>(command.release_nonnull(), make<PrintCommand>());
} }
static const char* parse_options(int argc, char* argv[])
{
// Sadly, we can't use Core::ArgsParser, because find accepts arguments in
// an extremely unusual format. We're going to try to use getopt(), though.
opterr = 0;
while (true) {
int opt = getopt(argc, argv, "+L");
switch (opt) {
case -1: {
// No more options.
StringView arg = argv[optind];
if (!arg.is_null() && !arg.starts_with('-')) {
// It's our root path!
return argv[optind++];
} else {
// It's a part of the script, and our root path is the current
// directory by default.
return ".";
}
}
case '?':
// Some error. Most likely, it's getopt() getting confused about
// what it thought was an option, but is actually a command. Return
// the default path, and hope the command parsing logic deals with
// this.
return ".";
case 'L':
g_follow_symlinks = true;
break;
default:
VERIFY_NOT_REACHED();
}
}
}
static void walk_tree(FileData& root_data, Command& command) static void walk_tree(FileData& root_data, Command& command)
{ {
command.evaluate(root_data); command.evaluate(root_data);
@ -567,7 +537,29 @@ static void walk_tree(FileData& root_data, Command& command)
ErrorOr<int> serenity_main(Main::Arguments arguments) ErrorOr<int> serenity_main(Main::Arguments arguments)
{ {
LexicalPath root_path(parse_options(arguments.argc, arguments.argv)); Vector<char*> args;
args.append(arguments.argv + 1, arguments.argc - 1);
OwnPtr<Command> command;
LexicalPath root_path = LexicalPath(".");
while (!args.is_empty()) {
char* raw_arg = args.take_first();
StringView arg = raw_arg;
if (arg == "-L") {
g_follow_symlinks = true;
} else if (!arg.starts_with('-')) {
root_path = LexicalPath(arg);
} else {
// No special case, so add back the argument and try to parse a command.
args.prepend(raw_arg);
command = parse_all_commands(args);
}
}
if (!command)
command = make<PrintCommand>();
String dirname = root_path.dirname(); String dirname = root_path.dirname();
String basename = root_path.basename(); String basename = root_path.basename();
@ -581,8 +573,8 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
false, false,
DT_UNKNOWN, DT_UNKNOWN,
}; };
auto command = parse_all_commands(arguments.argv);
walk_tree(file_data, *command); walk_tree(file_data, *command);
close(dirfd); close(dirfd);
return g_there_was_an_error ? 1 : 0; return g_there_was_an_error ? 1 : 0;
} }