Blame manual/examples/argp-ex4.c

Packit 6c4009
/* Argp example #4 -- a program with somewhat more complicated options
Packit 6c4009
   Copyright (C) 1991-2018 Free Software Foundation, Inc.
Packit 6c4009
Packit 6c4009
   This program is free software; you can redistribute it and/or
Packit 6c4009
   modify it under the terms of the GNU General Public License
Packit 6c4009
   as published by the Free Software Foundation; either version 2
Packit 6c4009
   of the License, or (at your option) any later version.
Packit 6c4009
Packit 6c4009
   This program is distributed in the hope that it will be useful,
Packit 6c4009
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 6c4009
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 6c4009
   GNU General Public License for more details.
Packit 6c4009
Packit 6c4009
   You should have received a copy of the GNU General Public License
Packit 6c4009
   along with this program; if not, if not, see <http://www.gnu.org/licenses/>.
Packit 6c4009
*/
Packit 6c4009
Packit 6c4009
/* This program uses the same features as example 3, but has more
Packit 6c4009
   options, and somewhat more structure in the -help output.  It
Packit 6c4009
   also shows how you can `steal' the remainder of the input
Packit 6c4009
   arguments past a certain point, for programs that accept a
Packit 6c4009
   list of items.  It also shows the special argp KEY value
Packit 6c4009
   ARGP_KEY_NO_ARGS, which is only given if no non-option
Packit 6c4009
   arguments were supplied to the program.
Packit 6c4009
Packit 6c4009
   For structuring the help output, two features are used,
Packit 6c4009
   *headers* which are entries in the options vector with the
Packit 6c4009
   first four fields being zero, and a two part documentation
Packit 6c4009
   string (in the variable DOC), which allows documentation both
Packit 6c4009
   before and after the options; the two parts of DOC are
Packit 6c4009
   separated by a vertical-tab character ('\v', or '\013').  By
Packit 6c4009
   convention, the documentation before the options is just a
Packit 6c4009
   short string saying what the program does, and that afterwards
Packit 6c4009
   is longer, describing the behavior in more detail.  All
Packit 6c4009
   documentation strings are automatically filled for output,
Packit 6c4009
   although newlines may be included to force a line break at a
Packit 6c4009
   particular point.  All documentation strings are also passed to
Packit 6c4009
   the `gettext' function, for possible translation into the
Packit 6c4009
   current locale.  */
Packit 6c4009
Packit 6c4009
#include <stdlib.h>
Packit 6c4009
#include <error.h>
Packit 6c4009
#include <argp.h>
Packit 6c4009
Packit 6c4009
const char *argp_program_version =
Packit 6c4009
  "argp-ex4 1.0";
Packit 6c4009
const char *argp_program_bug_address =
Packit 6c4009
  "<bug-gnu-utils@@prep.ai.mit.edu>";
Packit 6c4009
Packit 6c4009
/* Program documentation.  */
Packit 6c4009
static char doc[] =
Packit 6c4009
  "Argp example #4 -- a program with somewhat more complicated\
Packit 6c4009
options\
Packit 6c4009
\vThis part of the documentation comes *after* the options;\
Packit 6c4009
 note that the text is automatically filled, but it's possible\
Packit 6c4009
 to force a line-break, e.g.\n<-- here.";
Packit 6c4009
Packit 6c4009
/* A description of the arguments we accept.  */
Packit 6c4009
static char args_doc[] = "ARG1 [STRING...]";
Packit 6c4009
Packit 6c4009
/* Keys for options without short-options.  */
Packit 6c4009
#define OPT_ABORT  1		/* --abort */
Packit 6c4009
Packit 6c4009
/* The options we understand.  */
Packit 6c4009
static struct argp_option options[] = {
Packit 6c4009
  {"verbose",  'v', 0,       0, "Produce verbose output" },
Packit 6c4009
  {"quiet",    'q', 0,       0, "Don't produce any output" },
Packit 6c4009
  {"silent",   's', 0,       OPTION_ALIAS },
Packit 6c4009
  {"output",   'o', "FILE",  0,
Packit 6c4009
   "Output to FILE instead of standard output" },
Packit 6c4009
Packit 6c4009
  {0,0,0,0, "The following options should be grouped together:" },
Packit 6c4009
  {"repeat",   'r', "COUNT", OPTION_ARG_OPTIONAL,
Packit 6c4009
   "Repeat the output COUNT (default 10) times"},
Packit 6c4009
  {"abort",    OPT_ABORT, 0, 0, "Abort before showing any output"},
Packit 6c4009
Packit 6c4009
  { 0 }
Packit 6c4009
};
Packit 6c4009
Packit 6c4009
/* Used by @code{main} to communicate with @code{parse_opt}.  */
Packit 6c4009
struct arguments
Packit 6c4009
{
Packit 6c4009
  char *arg1;			/* @var{arg1} */
Packit 6c4009
  char **strings;		/* [@var{string}@dots{}] */
Packit 6c4009
  int silent, verbose, abort;	/* @samp{-s}, @samp{-v}, @samp{--abort} */
Packit 6c4009
  char *output_file;		/* @var{file} arg to @samp{--output} */
Packit 6c4009
  int repeat_count;		/* @var{count} arg to @samp{--repeat} */
Packit 6c4009
};
Packit 6c4009
Packit 6c4009
/* Parse a single option.  */
Packit 6c4009
static error_t
Packit 6c4009
parse_opt (int key, char *arg, struct argp_state *state)
Packit 6c4009
{
Packit 6c4009
  /* Get the @code{input} argument from @code{argp_parse}, which we
Packit 6c4009
     know is a pointer to our arguments structure.  */
Packit 6c4009
  struct arguments *arguments = state->input;
Packit 6c4009
Packit 6c4009
  switch (key)
Packit 6c4009
    {
Packit 6c4009
    case 'q': case 's':
Packit 6c4009
      arguments->silent = 1;
Packit 6c4009
      break;
Packit 6c4009
    case 'v':
Packit 6c4009
      arguments->verbose = 1;
Packit 6c4009
      break;
Packit 6c4009
    case 'o':
Packit 6c4009
      arguments->output_file = arg;
Packit 6c4009
      break;
Packit 6c4009
    case 'r':
Packit 6c4009
      arguments->repeat_count = arg ? atoi (arg) : 10;
Packit 6c4009
      break;
Packit 6c4009
    case OPT_ABORT:
Packit 6c4009
      arguments->abort = 1;
Packit 6c4009
      break;
Packit 6c4009
Packit 6c4009
    case ARGP_KEY_NO_ARGS:
Packit 6c4009
      argp_usage (state);
Packit 6c4009
Packit 6c4009
    case ARGP_KEY_ARG:
Packit 6c4009
      /* Here we know that @code{state->arg_num == 0}, since we
Packit 6c4009
	 force argument parsing to end before any more arguments can
Packit 6c4009
	 get here.  */
Packit 6c4009
      arguments->arg1 = arg;
Packit 6c4009
Packit 6c4009
      /* Now we consume all the rest of the arguments.
Packit 6c4009
	 @code{state->next} is the index in @code{state->argv} of the
Packit 6c4009
	 next argument to be parsed, which is the first @var{string}
Packit 6c4009
	 we're interested in, so we can just use
Packit 6c4009
	 @code{&state->argv[state->next]} as the value for
Packit 6c4009
	 arguments->strings.
Packit 6c4009
Packit 6c4009
	 @emph{In addition}, by setting @code{state->next} to the end
Packit 6c4009
	 of the arguments, we can force argp to stop parsing here and
Packit 6c4009
	 return.  */
Packit 6c4009
      arguments->strings = &state->argv[state->next];
Packit 6c4009
      state->next = state->argc;
Packit 6c4009
Packit 6c4009
      break;
Packit 6c4009
Packit 6c4009
    default:
Packit 6c4009
      return ARGP_ERR_UNKNOWN;
Packit 6c4009
    }
Packit 6c4009
  return 0;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
/* Our argp parser.  */
Packit 6c4009
static struct argp argp = { options, parse_opt, args_doc, doc };
Packit 6c4009
Packit 6c4009
int
Packit 6c4009
main (int argc, char **argv)
Packit 6c4009
{
Packit 6c4009
  int i, j;
Packit 6c4009
  struct arguments arguments;
Packit 6c4009
Packit 6c4009
  /* Default values.  */
Packit 6c4009
  arguments.silent = 0;
Packit 6c4009
  arguments.verbose = 0;
Packit 6c4009
  arguments.output_file = "-";
Packit 6c4009
  arguments.repeat_count = 1;
Packit 6c4009
  arguments.abort = 0;
Packit 6c4009
Packit 6c4009
  /* Parse our arguments; every option seen by @code{parse_opt} will be
Packit 6c4009
     reflected in @code{arguments}.  */
Packit 6c4009
  argp_parse (&argp, argc, argv, 0, 0, &arguments);
Packit 6c4009
Packit 6c4009
  if (arguments.abort)
Packit 6c4009
    error (10, 0, "ABORTED");
Packit 6c4009
Packit 6c4009
  for (i = 0; i < arguments.repeat_count; i++)
Packit 6c4009
    {
Packit 6c4009
      printf ("ARG1 = %s\n", arguments.arg1);
Packit 6c4009
      printf ("STRINGS = ");
Packit 6c4009
      for (j = 0; arguments.strings[j]; j++)
Packit 6c4009
	printf (j == 0 ? "%s" : ", %s", arguments.strings[j]);
Packit 6c4009
      printf ("\n");
Packit 6c4009
      printf ("OUTPUT_FILE = %s\nVERBOSE = %s\nSILENT = %s\n",
Packit 6c4009
	      arguments.output_file,
Packit 6c4009
	      arguments.verbose ? "yes" : "no",
Packit 6c4009
	      arguments.silent ? "yes" : "no");
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  exit (0);
Packit 6c4009
}