(root)/
glibc-2.38/
manual/
examples/
argp-ex4.c
       1  /* Argp example #4 -- a program with somewhat more complicated options
       2     Copyright (C) 1991-2023 Free Software Foundation, Inc.
       3  
       4     This program is free software; you can redistribute it and/or
       5     modify it under the terms of the GNU General Public License
       6     as published by the Free Software Foundation; either version 2
       7     of the License, or (at your option) any later version.
       8  
       9     This program is distributed in the hope that it will be useful,
      10     but WITHOUT ANY WARRANTY; without even the implied warranty of
      11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12     GNU General Public License for more details.
      13  
      14     You should have received a copy of the GNU General Public License
      15     along with this program; if not, see <https://www.gnu.org/licenses/>.
      16  */
      17  
      18  /* This program uses the same features as example 3, but has more
      19     options, and somewhat more structure in the -help output.  It
      20     also shows how you can `steal' the remainder of the input
      21     arguments past a certain point, for programs that accept a
      22     list of items.  It also shows the special argp KEY value
      23     ARGP_KEY_NO_ARGS, which is only given if no non-option
      24     arguments were supplied to the program.
      25  
      26     For structuring the help output, two features are used,
      27     *headers* which are entries in the options vector with the
      28     first four fields being zero, and a two part documentation
      29     string (in the variable DOC), which allows documentation both
      30     before and after the options; the two parts of DOC are
      31     separated by a vertical-tab character ('\v', or '\013').  By
      32     convention, the documentation before the options is just a
      33     short string saying what the program does, and that afterwards
      34     is longer, describing the behavior in more detail.  All
      35     documentation strings are automatically filled for output,
      36     although newlines may be included to force a line break at a
      37     particular point.  All documentation strings are also passed to
      38     the `gettext' function, for possible translation into the
      39     current locale.  */
      40  
      41  #include <stdlib.h>
      42  #include <error.h>
      43  #include <argp.h>
      44  
      45  const char *argp_program_version =
      46    "argp-ex4 1.0";
      47  const char *argp_program_bug_address =
      48    "<bug-gnu-utils@@prep.ai.mit.edu>";
      49  
      50  /* Program documentation.  */
      51  static char doc[] =
      52    "Argp example #4 -- a program with somewhat more complicated\
      53  options\
      54  \vThis part of the documentation comes *after* the options;\
      55   note that the text is automatically filled, but it's possible\
      56   to force a line-break, e.g.\n<-- here.";
      57  
      58  /* A description of the arguments we accept.  */
      59  static char args_doc[] = "ARG1 [STRING...]";
      60  
      61  /* Keys for options without short-options.  */
      62  #define OPT_ABORT  1		/* --abort */
      63  
      64  /* The options we understand.  */
      65  static struct argp_option options[] = {
      66    {"verbose",  'v', 0,       0, "Produce verbose output" },
      67    {"quiet",    'q', 0,       0, "Don't produce any output" },
      68    {"silent",   's', 0,       OPTION_ALIAS },
      69    {"output",   'o', "FILE",  0,
      70     "Output to FILE instead of standard output" },
      71  
      72    {0,0,0,0, "The following options should be grouped together:" },
      73    {"repeat",   'r', "COUNT", OPTION_ARG_OPTIONAL,
      74     "Repeat the output COUNT (default 10) times"},
      75    {"abort",    OPT_ABORT, 0, 0, "Abort before showing any output"},
      76  
      77    { 0 }
      78  };
      79  
      80  /* Used by @code{main} to communicate with @code{parse_opt}.  */
      81  struct arguments
      82  {
      83    char *arg1;			/* @var{arg1} */
      84    char **strings;		/* [@var{string}@dots{}] */
      85    int silent, verbose, abort;	/* @samp{-s}, @samp{-v}, @samp{--abort} */
      86    char *output_file;		/* @var{file} arg to @samp{--output} */
      87    int repeat_count;		/* @var{count} arg to @samp{--repeat} */
      88  };
      89  
      90  /* Parse a single option.  */
      91  static error_t
      92  parse_opt (int key, char *arg, struct argp_state *state)
      93  {
      94    /* Get the @code{input} argument from @code{argp_parse}, which we
      95       know is a pointer to our arguments structure.  */
      96    struct arguments *arguments = state->input;
      97  
      98    switch (key)
      99      {
     100      case 'q': case 's':
     101        arguments->silent = 1;
     102        break;
     103      case 'v':
     104        arguments->verbose = 1;
     105        break;
     106      case 'o':
     107        arguments->output_file = arg;
     108        break;
     109      case 'r':
     110        arguments->repeat_count = arg ? atoi (arg) : 10;
     111        break;
     112      case OPT_ABORT:
     113        arguments->abort = 1;
     114        break;
     115  
     116      case ARGP_KEY_NO_ARGS:
     117        argp_usage (state);
     118  
     119      case ARGP_KEY_ARG:
     120        /* Here we know that @code{state->arg_num == 0}, since we
     121  	 force argument parsing to end before any more arguments can
     122  	 get here.  */
     123        arguments->arg1 = arg;
     124  
     125        /* Now we consume all the rest of the arguments.
     126  	 @code{state->next} is the index in @code{state->argv} of the
     127  	 next argument to be parsed, which is the first @var{string}
     128  	 we're interested in, so we can just use
     129  	 @code{&state->argv[state->next]} as the value for
     130  	 arguments->strings.
     131  
     132  	 @emph{In addition}, by setting @code{state->next} to the end
     133  	 of the arguments, we can force argp to stop parsing here and
     134  	 return.  */
     135        arguments->strings = &state->argv[state->next];
     136        state->next = state->argc;
     137  
     138        break;
     139  
     140      default:
     141        return ARGP_ERR_UNKNOWN;
     142      }
     143    return 0;
     144  }
     145  
     146  /* Our argp parser.  */
     147  static struct argp argp = { options, parse_opt, args_doc, doc };
     148  
     149  int
     150  main (int argc, char **argv)
     151  {
     152    int i, j;
     153    struct arguments arguments;
     154  
     155    /* Default values.  */
     156    arguments.silent = 0;
     157    arguments.verbose = 0;
     158    arguments.output_file = "-";
     159    arguments.repeat_count = 1;
     160    arguments.abort = 0;
     161  
     162    /* Parse our arguments; every option seen by @code{parse_opt} will be
     163       reflected in @code{arguments}.  */
     164    argp_parse (&argp, argc, argv, 0, 0, &arguments);
     165  
     166    if (arguments.abort)
     167      error (10, 0, "ABORTED");
     168  
     169    for (i = 0; i < arguments.repeat_count; i++)
     170      {
     171        printf ("ARG1 = %s\n", arguments.arg1);
     172        printf ("STRINGS = ");
     173        for (j = 0; arguments.strings[j]; j++)
     174  	printf (j == 0 ? "%s" : ", %s", arguments.strings[j]);
     175        printf ("\n");
     176        printf ("OUTPUT_FILE = %s\nVERBOSE = %s\nSILENT = %s\n",
     177  	      arguments.output_file,
     178  	      arguments.verbose ? "yes" : "no",
     179  	      arguments.silent ? "yes" : "no");
     180      }
     181  
     182    exit (0);
     183  }