www.delorie.com/gnu/docs/avl/libavl_274.html   search  
 
Buy GNU books!


GNU libavl 2.0.1

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

B.1 Option Parser

The BST test program contains an option parser for handling command-line options. See section 5.14.5 User Interaction, for an introduction to its public interface. This section describes the option parser's implementation.

The option parsing state is kept in struct option_state:

 
/* Option parsing state. */
struct option_state 
{ const struct option *options; /* List of options. */ char **arg_next; /* Remaining arguments. */ char *short_next; /* When non-null, unparsed short options. */ };
See also @refalso{587 This code is included in @refalso{97

The initialization function just creates and returns one of these structures:

 
/* Creates and returns a command-line options parser.  
   args is a null-terminated array of command-line arguments, not
   including program name. */
static struct option_state *
option_init (const struct option *options, char **args)
{ struct option_state *state; assert (options != NULL && args != NULL); state = xmalloc (sizeof *state); state-&#62;options = options; state-&#62;arg_next = args; state-&#62;short_next = NULL; return state; }

The option retrieval function uses a couple of helper functions. The code is lengthy, but not complicated:

 
/* Parses a short option whose single-character name is pointed to by
   state-&#62;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-&#62;short_next != NULL && *state-&#62;short_next != '\0' && state-&#62;options != NULL); /* Find option in o. */ for (o = state-&#62;options; ; o++) if (o-&#62;long_name == NULL) fail ("unknownoption`-%c';use--helpforhelp", *state-&#62;short_next); else if (o-&#62;short_name == *state-&#62;short_next) break; state-&#62;short_next++; /* Handle argument. */ if (o-&#62;has_arg)
{ if (*state-&#62;arg_next == NULL || **state-&#62;arg_next == '-') fail ("`-%c'requiresanargument;use--helpforhelp"); *argp = *state-&#62;arg_next++; } return o-&#62;short_name; } /* Parses a long option whose command-line argument is pointed to by *state-&#62;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-&#62;arg_next != NULL && *state-&#62;arg_next != NULL && state-&#62;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-&#62;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-&#62;options; ; o++) if (o-&#62;long_name == NULL) fail ("unknownoption--%s;use--helpforhelp", name); else if (!strcmp (name, o-&#62;long_name)) break; /* Make sure option has an argument if it should. */ if ((arg != NULL) != (o-&#62;has_arg != 0))
{ if (arg != NULL) fail ("--%scan'ttakeanargument;use--helpforhelp", name); else
fail ("--%srequiresanargument;use--helpforhelp", name); } /* Advance and return. */ state-&#62;arg_next++; *argp = (char *) arg; return o-&#62;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-&#62;short_next != NULL)
{ if (*state-&#62;short_next != '\0') return handle_short_option (state, argp); else
state-&#62;short_next = NULL; } /* Out of options? */ if (*state-&#62;arg_next == NULL)
{ free (state); return -1; } /* Non-option arguments not supported. */ if ((*state-&#62;arg_next)[0] != '-') fail ("non-optionargumentsencountered;use--helpforhelp"); if ((*state-&#62;arg_next)[1] == '\0') fail ("unknownoption`-';use--helpforhelp"); /* Handle the option. */ if ((*state-&#62;arg_next)[1] == '-') return handle_long_option (state, argp); else
{ state-&#62;short_next = *state-&#62;arg_next + 1; state-&#62;arg_next++; return handle_short_option (state, argp); } }


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

  webmaster   donations   bookstore     delorie software   privacy  
  Copyright 2003   by The Free Software Foundation     Updated Jun 2003