| | /* Parses a short option whose single-character name is pointed to by
state->short_next. Advances past the option so that the next one
will be parsed in the next call to option_get(). Sets *argp to
the option's argument, if any. Returns the option's short name. */
static int handle_short_option (struct option_state *state, char **argp) {
const struct option *o;
assert (state != NULL && state->short_next != NULL && *state->short_next != '\0'
&& state->options != NULL);
/* Find option in o. */
for (o = state->options; ; o++)
if (o->long_name == NULL)
fail ("unknownoption`-%c';use--helpforhelp", *state->short_next);
else if (o->short_name == *state->short_next)
break;
state->short_next++;
/* Handle argument. */
if (o->has_arg) {
if (*state->arg_next == NULL || **state->arg_next == '-')
fail ("`-%c'requiresanargument;use--helpforhelp");
*argp = *state->arg_next++;
}
return o->short_name;
}
/* Parses a long option whose command-line argument is pointed to by
*state->arg_next. Advances past the option so that the next one
will be parsed in the next call to option_get(). Sets *argp to
the option's argument, if any. Returns the option's identifier. */
static int handle_long_option (struct option_state *state, char **argp) {
const struct option *o; /* Iterator on options. */
char name[16]; /* Option name. */
const char *arg; /* Option argument. */
assert (state != NULL && state->arg_next != NULL && *state->arg_next != NULL
&& state->options != NULL && argp != NULL);
/* Copy the option name into name
and put a pointer to its argument, or NULL if none, into arg. */
{
const char *p = *state->arg_next + 2;
const char *q = p + strcspn (p, "=");
size_t name_len = q - p;
if (name_len > (sizeof name) - 1)
name_len = (sizeof name) - 1;
memcpy (name, p, name_len);
name[name_len] = '\0';
arg = (*q == '=') ? q + 1 : NULL;
}
/* Find option in o. */
for (o = state->options; ; o++)
if (o->long_name == NULL)
fail ("unknownoption--%s;use--helpforhelp", name);
else if (!strcmp (name, o->long_name))
break;
/* Make sure option has an argument if it should. */
if ((arg != NULL) != (o->has_arg != 0)) {
if (arg != NULL)
fail ("--%scan'ttakeanargument;use--helpforhelp", name);
else fail ("--%srequiresanargument;use--helpforhelp", name);
}
/* Advance and return. */
state->arg_next++;
*argp = (char *) arg;
return o->short_name;
}
/* Retrieves the next option in the state vector state.
Returns the option's identifier, or -1 if out of options.
Stores the option's argument, or NULL if none, into *argp. */
static int option_get (struct option_state *state, char **argp) {
assert (state != NULL && argp != NULL);
/* No argument by default. */
*argp = NULL;
/* Deal with left-over short options. */
if (state->short_next != NULL) {
if (*state->short_next != '\0')
return handle_short_option (state, argp);
else state->short_next = NULL;
}
/* Out of options? */
if (*state->arg_next == NULL) {
free (state);
return -1;
}
/* Non-option arguments not supported. */
if ((*state->arg_next)[0] != '-')
fail ("non-optionargumentsencountered;use--helpforhelp");
if ((*state->arg_next)[1] == '\0')
fail ("unknownoption`-';use--helpforhelp");
/* Handle the option. */
if ((*state->arg_next)[1] == '-')
return handle_long_option (state, argp);
else {
state->short_next = *state->arg_next + 1;
state->arg_next++;
return handle_short_option (state, argp);
}
}
|