WvStreams
|
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 <stdio.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", 0}, 00052 {"quiet", 'q', 0, 0, "Don't produce any output", 0}, 00053 {"silent", 's', 0, OPTION_ALIAS, 0, 0}, 00054 {"output", 'o', "FILE", 0, 00055 "Output to FILE instead of standard output", 0}, 00056 00057 {0,0,0,0, "The following options should be grouped together:", 0}, 00058 {"repeat", 'r', "COUNT", OPTION_ARG_OPTIONAL, 00059 "Repeat the output COUNT (default 10) times", 0}, 00060 {"abort", OPT_ABORT, 0, 0, "Abort before showing any output", 0}, 00061 00062 {0, 0, 0, 0, 0, 0} 00063 }; 00064 00065 /* Used by `main' to communicate with `parse_opt'. */ 00066 struct arguments 00067 { 00068 char *arg1; /* ARG1 */ 00069 char **strings; /* [STRING...] */ 00070 int silent, verbose, abort; /* `-s', `-v', `--abort' */ 00071 char *output_file; /* FILE arg to `--output' */ 00072 int repeat_count; /* COUNT arg to `--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 `input' argument from `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 `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 `state->next' is the index in `state->argv' of the 00112 next argument to be parsed, which is the first STRING 00113 we're interested in, so we can just use 00114 `&state->argv[state->next]' as the value for 00115 arguments->strings. 00116 00117 _In addition_, by setting `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, 0, 0, 0}; 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 `parse_opt' will be 00147 reflected in `arguments'. */ 00148 argp_parse (&argp, argc, argv, 0, 0, &arguments); 00149 00150 if (arguments.abort) 00151 { 00152 /* The glibc example used error (10, 0, "ABORTED"), but that's 00153 not portable. */ 00154 fprintf(stderr, "ex4: ABORTED\n"); 00155 exit(10); 00156 } 00157 00158 for (i = 0; i < arguments.repeat_count; i++) 00159 { 00160 printf ("ARG1 = %s\n", arguments.arg1); 00161 printf ("STRINGS = "); 00162 for (j = 0; arguments.strings[j]; j++) 00163 printf (j == 0 ? "%s" : ", %s", arguments.strings[j]); 00164 printf ("\n"); 00165 printf ("OUTPUT_FILE = %s\nVERBOSE = %s\nSILENT = %s\n", 00166 arguments.output_file, 00167 arguments.verbose ? "yes" : "no", 00168 arguments.silent ? "yes" : "no"); 00169 } 00170 00171 exit (0); 00172 }