|
@@ -48,19 +48,30 @@ enum ArgsOptionArgument
|
|
|
|
|
|
|
|
struct ArgsOption
|
|
struct ArgsOption
|
|
|
{
|
|
{
|
|
|
- const char* name;
|
|
|
|
|
- int32_t has_arg;
|
|
|
|
|
- int32_t* flag;
|
|
|
|
|
- int32_t val;
|
|
|
|
|
|
|
+ const char* name;
|
|
|
|
|
+ int32_t has_arg;
|
|
|
|
|
+ int32_t* flag;
|
|
|
|
|
+ int32_t val;
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
/// Parses the command line arguments in a way very similar to GNU getopt.
|
|
/// Parses the command line arguments in a way very similar to GNU getopt.
|
|
|
-class CE_EXPORT Args
|
|
|
|
|
|
|
+class Args
|
|
|
{
|
|
{
|
|
|
public:
|
|
public:
|
|
|
|
|
|
|
|
- Args(int argc, char** argv, const char* shortopts, const ArgsOption* longopts);
|
|
|
|
|
- ~Args();
|
|
|
|
|
|
|
+ Args(int argc, char** argv, const char* shortopts, const ArgsOption* longopts)
|
|
|
|
|
+ : m_argc(argc)
|
|
|
|
|
+ , m_argv(argv)
|
|
|
|
|
+ , m_shortopts(shortopts)
|
|
|
|
|
+ , m_longopts(longopts)
|
|
|
|
|
+ , m_optind(1) // Do not consider argv[0]
|
|
|
|
|
+ , m_scope(argc)
|
|
|
|
|
+ , m_optarg(NULL)
|
|
|
|
|
+ {
|
|
|
|
|
+ CE_ASSERT(argv != NULL, "Argument vector must be != NULL");
|
|
|
|
|
+ CE_ASSERT(shortopts != NULL, "Short argument list must be != NULL");
|
|
|
|
|
+ // longopts could be NULL
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
/// Finds the next option character and returns it.
|
|
/// Finds the next option character and returns it.
|
|
|
/// If there are no more option characters, it returns -1 and optind()
|
|
/// If there are no more option characters, it returns -1 and optind()
|
|
@@ -68,19 +79,59 @@ public:
|
|
|
/// an option.
|
|
/// an option.
|
|
|
/// If it finds an option that was not included in shortopts or longopts,
|
|
/// If it finds an option that was not included in shortopts or longopts,
|
|
|
/// or if it finds a missing option argument, it returns '?' character.
|
|
/// or if it finds a missing option argument, it returns '?' character.
|
|
|
- int32_t getopt();
|
|
|
|
|
|
|
+ int32_t getopt()
|
|
|
|
|
+ {
|
|
|
|
|
+ // Always reset optarg
|
|
|
|
|
+ m_optarg = NULL;
|
|
|
|
|
+
|
|
|
|
|
+ // End of arguments
|
|
|
|
|
+ if (m_optind >= m_scope)
|
|
|
|
|
+ {
|
|
|
|
|
+ return -1;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ switch (option_type(m_argv[m_optind]))
|
|
|
|
|
+ {
|
|
|
|
|
+ case AOT_SHORT:
|
|
|
|
|
+ {
|
|
|
|
|
+ return short_option(m_argv[m_optind]);
|
|
|
|
|
+ }
|
|
|
|
|
+ case AOT_LONG:
|
|
|
|
|
+ {
|
|
|
|
|
+ return long_option(m_argv[m_optind]);
|
|
|
|
|
+ }
|
|
|
|
|
+ case AOT_NOT_OPTION:
|
|
|
|
|
+ {
|
|
|
|
|
+ not_option();
|
|
|
|
|
+ return getopt();
|
|
|
|
|
+ }
|
|
|
|
|
+ default:
|
|
|
|
|
+ {
|
|
|
|
|
+ return '?';
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
/// Returns the index of the next argument to be processed.
|
|
/// Returns the index of the next argument to be processed.
|
|
|
- int32_t optind() const;
|
|
|
|
|
|
|
+ int32_t optind() const
|
|
|
|
|
+ {
|
|
|
|
|
+ return m_optind;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
/// Returns the text of the following argv-element in respect
|
|
/// Returns the text of the following argv-element in respect
|
|
|
/// to the current optind().
|
|
/// to the current optind().
|
|
|
- const char* optarg() const;
|
|
|
|
|
|
|
+ const char* optarg() const
|
|
|
|
|
+ {
|
|
|
|
|
+ return m_optarg;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Sets the @a index into argv[] from where to start option scanning.
|
|
/// Sets the @a index into argv[] from where to start option scanning.
|
|
|
/// If @a index >= argc nothing will be scanned.
|
|
/// If @a index >= argc nothing will be scanned.
|
|
|
- void set_optind(int32_t index);
|
|
|
|
|
|
|
+ void set_optind(int32_t index)
|
|
|
|
|
+ {
|
|
|
|
|
+ m_optind = index;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
private:
|
|
private:
|
|
|
|
|
|
|
@@ -88,36 +139,126 @@ private:
|
|
|
// Returns AOT_SHORT if option is of the form "-x" where 'x' is the option.
|
|
// Returns AOT_SHORT if option is of the form "-x" where 'x' is the option.
|
|
|
// Returns AOT_LONG if option is of the form "--option" where "option" is the option.
|
|
// Returns AOT_LONG if option is of the form "--option" where "option" is the option.
|
|
|
// Returns AOT_NOT_OPTION in all other cases.
|
|
// Returns AOT_NOT_OPTION in all other cases.
|
|
|
- ArgsOptionType option_type(const char* option);
|
|
|
|
|
|
|
+ ArgsOptionType option_type(const char* option)
|
|
|
|
|
+ {
|
|
|
|
|
+ const size_t option_len = string::strlen(option);
|
|
|
|
|
+
|
|
|
|
|
+ if (option_len == 2 && option[0] == '-' && option[1] != '-')
|
|
|
|
|
+ {
|
|
|
|
|
+ return AOT_SHORT;
|
|
|
|
|
+ }
|
|
|
|
|
+ else if (option_len > 2 && option[0] == '-' && option[1] == '-')
|
|
|
|
|
+ {
|
|
|
|
|
+ return AOT_LONG;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return AOT_NOT_OPTION;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
|
|
|
// Parses a long option
|
|
// Parses a long option
|
|
|
- int32_t long_option(const char* option);
|
|
|
|
|
|
|
+ int32_t long_option(const char* option)
|
|
|
|
|
+ {
|
|
|
|
|
+ const ArgsOption* current_option = m_longopts;
|
|
|
|
|
+
|
|
|
|
|
+ // Loop through all the long options
|
|
|
|
|
+ while (!end_of_longopts(current_option))
|
|
|
|
|
+ {
|
|
|
|
|
+ if (string::strcmp(current_option->name, &option[2]) == 0)
|
|
|
|
|
+ {
|
|
|
|
|
+ // If the option requires an argument
|
|
|
|
|
+ if (current_option->has_arg == AOA_REQUIRED_ARGUMENT)
|
|
|
|
|
+ {
|
|
|
|
|
+ // Read the argument if it exists
|
|
|
|
|
+ if ((m_optind + 1) < m_scope)
|
|
|
|
|
+ {
|
|
|
|
|
+ // Read the argument and skip the following parameter
|
|
|
|
|
+ m_optarg = m_argv[m_optind + 1];
|
|
|
|
|
+ m_optind += 2;
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ // CE_LOGE("%s: option requires an argument -- '%s'", m_argv[0], current_option->name);
|
|
|
|
|
+
|
|
|
|
|
+ // Missing option
|
|
|
|
|
+ m_optind += 1;
|
|
|
|
|
+ return '?';
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ // If the option does not require an argument
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ m_optind++;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (current_option->flag == NULL)
|
|
|
|
|
+ {
|
|
|
|
|
+ return current_option->val;
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ (*current_option->flag) = current_option->val;
|
|
|
|
|
+
|
|
|
|
|
+ return 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ current_option++;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Found a long option but was not included in longopts
|
|
|
|
|
+ // CE_LOGE("%s: invalid option -- '%s'", m_argv[0], &option[2]);
|
|
|
|
|
+ m_optind++;
|
|
|
|
|
+ return '?';
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
// Parses a short option
|
|
// Parses a short option
|
|
|
- int32_t short_option(const char* option);
|
|
|
|
|
|
|
+ int32_t short_option(const char* option)
|
|
|
|
|
+ {
|
|
|
|
|
+ (void)option;
|
|
|
|
|
+
|
|
|
|
|
+ // CE_LOGE("%s: invalid option -- '%s'", m_argv[0], &option[1]);
|
|
|
|
|
+ m_optind++;
|
|
|
|
|
+ return '?';
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- void not_option();
|
|
|
|
|
|
|
+ void not_option()
|
|
|
|
|
+ {
|
|
|
|
|
+ char* current_option = m_argv[m_optind];
|
|
|
|
|
+
|
|
|
|
|
+ for (int32_t i = m_optind; i < (m_argc - 1); i++)
|
|
|
|
|
+ {
|
|
|
|
|
+ m_argv[i] = m_argv[i + 1];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ m_argv[m_argc - 1] = current_option;
|
|
|
|
|
+
|
|
|
|
|
+ // Reduce the number of true arguments
|
|
|
|
|
+ m_scope--;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
// Returns whether the given option is the last one
|
|
// Returns whether the given option is the last one
|
|
|
- bool end_of_longopts(const ArgsOption* option) const;
|
|
|
|
|
|
|
+ bool end_of_longopts(const ArgsOption* option) const
|
|
|
|
|
+ {
|
|
|
|
|
+ return (option->name == NULL && option->has_arg == 0 && option->flag == NULL && option->val == 0);
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
private:
|
|
private:
|
|
|
|
|
|
|
|
- int m_argc;
|
|
|
|
|
- char** m_argv;
|
|
|
|
|
|
|
+ int m_argc;
|
|
|
|
|
+ char** m_argv;
|
|
|
|
|
|
|
|
- const char* m_shortopts;
|
|
|
|
|
- const ArgsOption* m_longopts;
|
|
|
|
|
|
|
+ const char* m_shortopts;
|
|
|
|
|
+ const ArgsOption* m_longopts;
|
|
|
|
|
|
|
|
// Index of the next argument to be processed
|
|
// Index of the next argument to be processed
|
|
|
- int32_t m_optind;
|
|
|
|
|
|
|
+ int32_t m_optind;
|
|
|
|
|
|
|
|
// Number of "true" arguments
|
|
// Number of "true" arguments
|
|
|
- int32_t m_scope;
|
|
|
|
|
|
|
+ int32_t m_scope;
|
|
|
|
|
|
|
|
// The text of the following argv-element to argv[optind]
|
|
// The text of the following argv-element to argv[optind]
|
|
|
- char* m_optarg;
|
|
|
|
|
|
|
+ char* m_optarg;
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
} // namespace crown
|
|
} // namespace crown
|
|
|
-
|
|
|