Back to index

glibc  2.9
argp-ex4.c
Go to the documentation of this file.
00001 /* Argp example #4 -- a program with somewhat more complicated options */
00002 
00003 /* This program uses the same features as example 3, but has more
00004    options, and somewhat more structure in the -help output.  It
00005    also shows how you can `steal' the remainder of the input
00006    arguments past a certain point, for programs that accept a
00007    list of items.  It also shows the special argp KEY value
00008    ARGP_KEY_NO_ARGS, which is only given if no non-option
00009    arguments were supplied to the program.
00010 
00011    For structuring the help output, two features are used,
00012    *headers* which are entries in the options vector with the
00013    first four fields being zero, and a two part documentation
00014    string (in the variable DOC), which allows documentation both
00015    before and after the options; the two parts of DOC are
00016    separated by a vertical-tab character ('\v', or '\013').  By
00017    convention, the documentation before the options is just a
00018    short string saying what the program does, and that afterwards
00019    is longer, describing the behavior in more detail.  All
00020    documentation strings are automatically filled for output,
00021    although newlines may be included to force a line break at a
00022    particular point.  All documentation strings are also passed to
00023    the `gettext' function, for possible translation into the
00024    current locale.  */
00025 
00026 #include <stdlib.h>
00027 #include <error.h>
00028 #include <argp.h>
00029 
00030 const char *argp_program_version =
00031   "argp-ex4 1.0";
00032 const char *argp_program_bug_address =
00033   "<bug-gnu-utils@@prep.ai.mit.edu>";
00034 
00035 /* Program documentation.  */
00036 static char doc[] =
00037   "Argp example #4 -- a program with somewhat more complicated\
00038 options\
00039 \vThis part of the documentation comes *after* the options;\
00040  note that the text is automatically filled, but it's possible\
00041  to force a line-break, e.g.\n<-- here.";
00042 
00043 /* A description of the arguments we accept.  */
00044 static char args_doc[] = "ARG1 [STRING...]";
00045 
00046 /* Keys for options without short-options.  */
00047 #define OPT_ABORT  1        /* --abort */
00048 
00049 /* The options we understand.  */
00050 static struct argp_option options[] = {
00051   {"verbose",  'v', 0,       0, "Produce verbose output" },
00052   {"quiet",    'q', 0,       0, "Don't produce any output" },
00053   {"silent",   's', 0,       OPTION_ALIAS },
00054   {"output",   'o', "FILE",  0,
00055    "Output to FILE instead of standard output" },
00056 
00057   {0,0,0,0, "The following options should be grouped together:" },
00058   {"repeat",   'r', "COUNT", OPTION_ARG_OPTIONAL,
00059    "Repeat the output COUNT (default 10) times"},
00060   {"abort",    OPT_ABORT, 0, 0, "Abort before showing any output"},
00061 
00062   { 0 }
00063 };
00064 
00065 /* Used by @code{main} to communicate with @code{parse_opt}.  */
00066 struct arguments
00067 {
00068   char *arg1;               /* @var{arg1} */
00069   char **strings;           /* [@var{string}@dots{}] */
00070   int silent, verbose, abort;      /* @samp{-s}, @samp{-v}, @samp{--abort} */
00071   char *output_file;        /* @var{file} arg to @samp{--output} */
00072   int repeat_count;         /* @var{count} arg to @samp{--repeat} */
00073 };
00074 
00075 /* Parse a single option.  */
00076 static error_t
00077 parse_opt (int key, char *arg, struct argp_state *state)
00078 {
00079   /* Get the @code{input} argument from @code{argp_parse}, which we
00080      know is a pointer to our arguments structure.  */
00081   struct arguments *arguments = state->input;
00082 
00083   switch (key)
00084     {
00085     case 'q': case 's':
00086       arguments->silent = 1;
00087       break;
00088     case 'v':
00089       arguments->verbose = 1;
00090       break;
00091     case 'o':
00092       arguments->output_file = arg;
00093       break;
00094     case 'r':
00095       arguments->repeat_count = arg ? atoi (arg) : 10;
00096       break;
00097     case OPT_ABORT:
00098       arguments->abort = 1;
00099       break;
00100 
00101     case ARGP_KEY_NO_ARGS:
00102       argp_usage (state);
00103 
00104     case ARGP_KEY_ARG:
00105       /* Here we know that @code{state->arg_num == 0}, since we
00106         force argument parsing to end before any more arguments can
00107         get here.  */
00108       arguments->arg1 = arg;
00109 
00110       /* Now we consume all the rest of the arguments.
00111         @code{state->next} is the index in @code{state->argv} of the
00112         next argument to be parsed, which is the first @var{string}
00113         we're interested in, so we can just use
00114         @code{&state->argv[state->next]} as the value for
00115         arguments->strings.
00116 
00117         @emph{In addition}, by setting @code{state->next} to the end
00118         of the arguments, we can force argp to stop parsing here and
00119         return.  */
00120       arguments->strings = &state->argv[state->next];
00121       state->next = state->argc;
00122 
00123       break;
00124 
00125     default:
00126       return ARGP_ERR_UNKNOWN;
00127     }
00128   return 0;
00129 }
00130 
00131 /* Our argp parser.  */
00132 static struct argp argp = { options, parse_opt, args_doc, doc };
00133 
00134 int main (int argc, char **argv)
00135 {
00136   int i, j;
00137   struct arguments arguments;
00138 
00139   /* Default values.  */
00140   arguments.silent = 0;
00141   arguments.verbose = 0;
00142   arguments.output_file = "-";
00143   arguments.repeat_count = 1;
00144   arguments.abort = 0;
00145 
00146   /* Parse our arguments; every option seen by @code{parse_opt} will be
00147      reflected in @code{arguments}.  */
00148   argp_parse (&argp, argc, argv, 0, 0, &arguments);
00149 
00150   if (arguments.abort)
00151     error (10, 0, "ABORTED");
00152 
00153   for (i = 0; i < arguments.repeat_count; i++)
00154     {
00155       printf ("ARG1 = %s\n", arguments.arg1);
00156       printf ("STRINGS = ");
00157       for (j = 0; arguments.strings[j]; j++)
00158        printf (j == 0 ? "%s" : ", %s", arguments.strings[j]);
00159       printf ("\n");
00160       printf ("OUTPUT_FILE = %s\nVERBOSE = %s\nSILENT = %s\n",
00161              arguments.output_file,
00162              arguments.verbose ? "yes" : "no",
00163              arguments.silent ? "yes" : "no");
00164     }
00165 
00166   exit (0);
00167 }