|
|
@@ -34,15 +34,15 @@ namespace crown
|
|
|
|
|
|
enum ArgsOptionType
|
|
|
{
|
|
|
- AOT_SHORT = 1,
|
|
|
- AOT_LONG = 2,
|
|
|
- AOT_NOT_OPTION = 3
|
|
|
+ AOT_SHORT,
|
|
|
+ AOT_LONG,
|
|
|
+ AOT_NOT_OPTION
|
|
|
};
|
|
|
|
|
|
enum ArgsOptionArgument
|
|
|
{
|
|
|
- AOA_NO_ARGUMENT = 1,
|
|
|
- AOA_REQUIRED_ARGUMENT = 2
|
|
|
+ AOA_NO_ARGUMENT,
|
|
|
+ AOA_REQUIRED_ARGUMENT
|
|
|
};
|
|
|
|
|
|
struct ArgsOption
|
|
|
@@ -56,202 +56,67 @@ struct ArgsOption
|
|
|
/// Parses the command line arguments in a way very similar to GNU getopt.
|
|
|
class Args
|
|
|
{
|
|
|
-public:
|
|
|
-
|
|
|
-
|
|
|
public:
|
|
|
|
|
|
Args(int argc, char** argv, const char* shortopts, const ArgsOption* longopts);
|
|
|
~Args();
|
|
|
|
|
|
- int32_t next_option();
|
|
|
- int32_t option_index() const;
|
|
|
- const char* option_argument() const;
|
|
|
-
|
|
|
-
|
|
|
-private:
|
|
|
-
|
|
|
- // Returns the @option type
|
|
|
- // Returns AOT_SHORT if @option starts with "-"
|
|
|
- // Returns AOT_LONG if @option starts with "--"
|
|
|
- ArgsOptionType option_type(const char* option);
|
|
|
- int32_t long_option(const char* option);
|
|
|
- int32_t short_option(const char* option);
|
|
|
-
|
|
|
-private:
|
|
|
+ /// Finds the next option character and returns it.
|
|
|
+ /// If there are no more option characters, it returns -1 and optind()
|
|
|
+ /// returns the index in argv[] of the first argv-element that is not
|
|
|
+ /// an option.
|
|
|
+ /// If it finds an option that was not included in shortopts or longopts,
|
|
|
+ /// or if it finds a missing option argument, it returns '?' character.
|
|
|
+ int32_t getopt();
|
|
|
|
|
|
- int m_argc;
|
|
|
- char** m_argv;
|
|
|
- const char* m_shortopts;
|
|
|
- const ArgsOption* m_longopts;
|
|
|
-
|
|
|
- int m_current_arg;
|
|
|
-
|
|
|
- int m_option_index;
|
|
|
- char* m_option_argument;
|
|
|
-};
|
|
|
-
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
-inline 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_current_arg(1), // Do not consider argv[0]
|
|
|
- m_option_index(0),
|
|
|
- m_option_argument(NULL)
|
|
|
-{
|
|
|
- assert(argv != NULL);
|
|
|
- assert(shortopts != NULL);
|
|
|
- // longopts could be NULL
|
|
|
-}
|
|
|
-
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
-inline Args::~Args()
|
|
|
-{
|
|
|
-}
|
|
|
-
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
-inline int32_t Args::next_option()
|
|
|
-{
|
|
|
- // End of arguments
|
|
|
- if (m_current_arg >= m_argc)
|
|
|
- {
|
|
|
- return -1;
|
|
|
- }
|
|
|
+ /// Returns the index of the next argument to be processed.
|
|
|
+ int32_t optind() const;
|
|
|
|
|
|
- const char* current_arg = m_argv[m_current_arg];
|
|
|
+ /// Returns the text of the following argv-element in respect
|
|
|
+ /// to the current optind().
|
|
|
+ const char* optarg() const;
|
|
|
|
|
|
- ArgsOptionType type = option_type(current_arg);
|
|
|
|
|
|
- int32_t return_value = -1;
|
|
|
+ /// Sets the @index into argv[] from where to start option scanning.
|
|
|
+ /// If @index >= argc nothing will be scanned.
|
|
|
+ void set_optind(int32_t index);
|
|
|
|
|
|
- switch (type)
|
|
|
- {
|
|
|
- case AOT_SHORT:
|
|
|
- {
|
|
|
- return_value = short_option(current_arg);
|
|
|
- break;
|
|
|
- }
|
|
|
- case AOT_LONG:
|
|
|
- {
|
|
|
- return_value = long_option(current_arg);
|
|
|
- break;
|
|
|
- }
|
|
|
- case AOT_NOT_OPTION:
|
|
|
- {
|
|
|
- return_value = '?';
|
|
|
- break;
|
|
|
- }
|
|
|
- default:
|
|
|
- {
|
|
|
- return_value = '?';
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- m_current_arg++;
|
|
|
-
|
|
|
- return return_value;
|
|
|
-}
|
|
|
-
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
-inline int32_t Args::option_index() const
|
|
|
-{
|
|
|
- return m_option_index;
|
|
|
-}
|
|
|
-
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
-inline const char* Args::option_argument() const
|
|
|
-{
|
|
|
- return m_option_argument;
|
|
|
-}
|
|
|
-
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
-inline ArgsOptionType Args::option_type(const char* option)
|
|
|
-{
|
|
|
- size_t option_len = string::strlen(option);
|
|
|
-
|
|
|
- if (option_len > 2)
|
|
|
- {
|
|
|
- if (option[0] == '-' && option[1] == '-')
|
|
|
- {
|
|
|
- return AOT_LONG;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (option_len > 1)
|
|
|
- {
|
|
|
- if (option[0] == '-')
|
|
|
- {
|
|
|
- return AOT_SHORT;
|
|
|
- }
|
|
|
- }
|
|
|
+private:
|
|
|
|
|
|
- return AOT_NOT_OPTION;
|
|
|
-}
|
|
|
+ // Returns the @option type
|
|
|
+ // 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_NOT_OPTION in all other cases.
|
|
|
+ ArgsOptionType option_type(const char* option);
|
|
|
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
-inline int32_t Args::long_option(const char* option)
|
|
|
-{
|
|
|
- int32_t option_index = 0;
|
|
|
- const ArgsOption* current_option = m_longopts;
|
|
|
+ // Parses a long option
|
|
|
+ int32_t long_option(const char* option);
|
|
|
|
|
|
- while (1)
|
|
|
- {
|
|
|
- if (current_option->name == NULL && current_option->has_arg == 0 &&
|
|
|
- current_option->flag == NULL && current_option->val == 0)
|
|
|
- {
|
|
|
- break;
|
|
|
- }
|
|
|
+ // Parses a short option
|
|
|
+ int32_t short_option(const char* option);
|
|
|
|
|
|
- if (string::strcmp(current_option->name, &option[2]) == 0)
|
|
|
- {
|
|
|
- m_option_index = option_index;
|
|
|
+ void not_option();
|
|
|
|
|
|
- if (current_option->has_arg == AOA_REQUIRED_ARGUMENT)
|
|
|
- {
|
|
|
- if (m_argc > m_current_arg + 1)
|
|
|
- {
|
|
|
- m_option_argument = m_argv[m_current_arg + 1];
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- m_option_argument = NULL;
|
|
|
- }
|
|
|
+ // Returns whether the given option is the last one
|
|
|
+ bool end_of_longopts(const ArgsOption* option) const;
|
|
|
|
|
|
- m_current_arg += 1;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- m_option_argument = NULL;
|
|
|
- }
|
|
|
+private:
|
|
|
|
|
|
- if (current_option->flag == NULL)
|
|
|
- {
|
|
|
- return current_option->val;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- (*current_option->flag) = current_option->val;
|
|
|
+ int m_argc;
|
|
|
+ char** m_argv;
|
|
|
|
|
|
- return 0;
|
|
|
- }
|
|
|
- }
|
|
|
+ const char* m_shortopts;
|
|
|
+ const ArgsOption* m_longopts;
|
|
|
|
|
|
- option_index++;
|
|
|
- current_option++;
|
|
|
- }
|
|
|
+ // Index of the next argument to be processed
|
|
|
+ int32_t m_optind;
|
|
|
|
|
|
- return -1;
|
|
|
-}
|
|
|
+ // Number of "true" arguments
|
|
|
+ int32_t m_scope;
|
|
|
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
-inline int32_t Args::short_option(const char* option)
|
|
|
-{
|
|
|
- (void)option;
|
|
|
- return 0;
|
|
|
-}
|
|
|
+ // The text of the following argv-element to argv[optind]
|
|
|
+ char* m_optarg;
|
|
|
+};
|
|
|
|
|
|
} // namespace crown
|
|
|
|