LibC: getopt() and getopt_long() shouldn't modify argv

This commit is contained in:
Gunnar Beutner 2021-04-11 06:47:47 +02:00 committed by Andreas Kling
parent 6e51ea1e2e
commit 64740a0214
Notes: sideshowbarker 2024-07-18 20:32:49 +09:00
3 changed files with 14 additions and 7 deletions

View file

@ -61,7 +61,8 @@ namespace {
class OptionParser { class OptionParser {
public: public:
OptionParser(int argc, char** argv, const StringView& short_options, const option* long_options, int* out_long_option_index = nullptr); OptionParser(int argc, char* const* argv, const StringView& short_options, const option* long_options, int* out_long_option_index = nullptr);
~OptionParser();
int getopt(); int getopt();
private: private:
@ -85,13 +86,14 @@ private:
size_t m_consumed_args { 0 }; size_t m_consumed_args { 0 };
}; };
OptionParser::OptionParser(int argc, char** argv, const StringView& short_options, const option* long_options, int* out_long_option_index) OptionParser::OptionParser(int argc, char* const* argv, const StringView& short_options, const option* long_options, int* out_long_option_index)
: m_argc(argc) : m_argc(argc)
, m_argv(argv)
, m_short_options(short_options) , m_short_options(short_options)
, m_long_options(long_options) , m_long_options(long_options)
, m_out_long_option_index(out_long_option_index) , m_out_long_option_index(out_long_option_index)
{ {
m_argv = new char*[m_argc + 1];
memmove(m_argv, argv, sizeof(char*) * (m_argc + 1));
// In the following case: // In the following case:
// $ foo bar -o baz // $ foo bar -o baz
// we want to parse the option (-o baz) first, and leave the argument (bar) // we want to parse the option (-o baz) first, and leave the argument (bar)
@ -112,6 +114,11 @@ OptionParser::OptionParser(int argc, char** argv, const StringView& short_option
optarg = nullptr; optarg = nullptr;
} }
OptionParser::~OptionParser()
{
delete[] m_argv;
}
int OptionParser::getopt() int OptionParser::getopt()
{ {
bool should_reorder_argv = !m_stop_on_first_non_option; bool should_reorder_argv = !m_stop_on_first_non_option;
@ -355,14 +362,14 @@ bool OptionParser::find_next_option()
} }
int getopt(int argc, char** argv, const char* short_options) int getopt(int argc, char* const* argv, const char* short_options)
{ {
option dummy { nullptr, 0, nullptr, 0 }; option dummy { nullptr, 0, nullptr, 0 };
OptionParser parser { argc, argv, short_options, &dummy }; OptionParser parser { argc, argv, short_options, &dummy };
return parser.getopt(); return parser.getopt();
} }
int getopt_long(int argc, char** argv, const char* short_options, const struct option* long_options, int* out_long_option_index) int getopt_long(int argc, char* const* argv, const char* short_options, const struct option* long_options, int* out_long_option_index)
{ {
OptionParser parser { argc, argv, short_options, long_options, out_long_option_index }; OptionParser parser { argc, argv, short_options, long_options, out_long_option_index };
return parser.getopt(); return parser.getopt();

View file

@ -46,6 +46,6 @@ extern int optopt;
extern int optind; extern int optind;
extern int optreset; extern int optreset;
extern char* optarg; extern char* optarg;
int getopt_long(int argc, char** argv, const char* short_options, const struct option* long_options, int* out_long_option_index); int getopt_long(int argc, char* const* argv, const char* short_options, const struct option* long_options, int* out_long_option_index);
__END_DECLS __END_DECLS

View file

@ -212,6 +212,6 @@ extern int optreset;
// value. // value.
extern char* optarg; extern char* optarg;
int getopt(int argc, char** argv, const char* short_options); int getopt(int argc, char* const* argv, const char* short_options);
__END_DECLS __END_DECLS