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