| xf.li | bdd93d5 | 2023-05-12 07:10:14 -0700 | [diff] [blame] | 1 | /* Test program for argp argument parser | 
 | 2 |    Copyright (C) 1997-2016 Free Software Foundation, Inc. | 
 | 3 |    This file is part of the GNU C Library. | 
 | 4 |    Written by Miles Bader <miles@gnu.ai.mit.edu>. | 
 | 5 |  | 
 | 6 |    The GNU C Library is free software; you can redistribute it and/or | 
 | 7 |    modify it under the terms of the GNU Lesser General Public | 
 | 8 |    License as published by the Free Software Foundation; either | 
 | 9 |    version 2.1 of the License, or (at your option) any later version. | 
 | 10 |  | 
 | 11 |    The GNU C Library is distributed in the hope that it will be useful, | 
 | 12 |    but WITHOUT ANY WARRANTY; without even the implied warranty of | 
 | 13 |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
 | 14 |    Lesser General Public License for more details. | 
 | 15 |  | 
 | 16 |    You should have received a copy of the GNU Lesser General Public | 
 | 17 |    License along with the GNU C Library; if not, see | 
 | 18 |    <http://www.gnu.org/licenses/>.  */ | 
 | 19 |  | 
 | 20 | #ifdef HAVE_CONFIG_H | 
 | 21 | #include <config.h> | 
 | 22 | #endif | 
 | 23 |  | 
 | 24 | #include <stdlib.h> | 
 | 25 | #include <time.h> | 
 | 26 | #include <string.h> | 
 | 27 | #include <argp.h> | 
 | 28 |  | 
 | 29 | const char *argp_program_version = "argp-test 1.0"; | 
 | 30 |  | 
 | 31 | struct argp_option sub_options[] = | 
 | 32 | { | 
 | 33 |   {"subopt1",       's',     0,  0, "Nested option 1"}, | 
 | 34 |   {"subopt2",       'S',     0,  0, "Nested option 2"}, | 
 | 35 |  | 
 | 36 |   { 0, 0, 0, 0, "Some more nested options:", 10}, | 
 | 37 |   {"subopt3",       'p',     0,  0, "Nested option 3"}, | 
 | 38 |  | 
 | 39 |   {"subopt4",       'q',     0,  0, "Nested option 4", 1}, | 
 | 40 |  | 
 | 41 |   {0} | 
 | 42 | }; | 
 | 43 |  | 
 | 44 | static const char sub_args_doc[] = "STRING...\n-"; | 
 | 45 | static const char sub_doc[] = "\vThis is the doc string from the sub-arg-parser."; | 
 | 46 |  | 
 | 47 | static error_t | 
 | 48 | sub_parse_opt (int key, char *arg, struct argp_state *state) | 
 | 49 | { | 
 | 50 |   switch (key) | 
 | 51 |     { | 
 | 52 |     case ARGP_KEY_NO_ARGS: | 
 | 53 |       printf ("NO SUB ARGS\n"); | 
 | 54 |       break; | 
 | 55 |     case ARGP_KEY_ARG: | 
 | 56 |       printf ("SUB ARG: %s\n", arg); | 
 | 57 |       break; | 
 | 58 |  | 
 | 59 |     case 's' : case 'S': case 'p': case 'q': | 
 | 60 |       printf ("SUB KEY %c\n", key); | 
 | 61 |       break; | 
 | 62 |  | 
 | 63 |     default: | 
 | 64 |       return ARGP_ERR_UNKNOWN; | 
 | 65 |     } | 
 | 66 |   return 0; | 
 | 67 | } | 
 | 68 |  | 
 | 69 | static char * | 
 | 70 | sub_help_filter (int key, const char *text, void *input) | 
 | 71 | { | 
 | 72 |   if (key == ARGP_KEY_HELP_EXTRA) | 
 | 73 |     return strdup ("This is some extra text from the sub parser (note that it \ | 
 | 74 | is preceded by a blank line)."); | 
 | 75 |   else | 
 | 76 |     return (char *)text; | 
 | 77 | } | 
 | 78 |  | 
 | 79 | static struct argp sub_argp = { | 
 | 80 |   sub_options, sub_parse_opt, sub_args_doc, sub_doc, 0, sub_help_filter | 
 | 81 | }; | 
 | 82 |  | 
 | 83 | /* Structure used to communicate with the parsing functions.  */ | 
 | 84 | struct params | 
 | 85 | { | 
 | 86 |   unsigned foonly;		/* Value parsed for foonly.  */ | 
 | 87 |   unsigned foonly_default;	/* Default value for it.  */ | 
 | 88 | }; | 
 | 89 |  | 
 | 90 | #define OPT_PGRP 1 | 
 | 91 | #define OPT_SESS 2 | 
 | 92 |  | 
 | 93 | struct argp_option options[] = | 
 | 94 | { | 
 | 95 |   {"pid",       'p',     "PID", 0, "List the process PID"}, | 
 | 96 |   {"pgrp",      OPT_PGRP,"PGRP",0, "List processes in the process group PGRP"}, | 
 | 97 |   {"no-parent", 'P',	 0,     0, "Include processes without parents"}, | 
 | 98 |   {0,           'x',     0,     OPTION_ALIAS}, | 
 | 99 |   {"all-fields",'Q',     0,     0, "Don't elide unusable fields (normally" | 
 | 100 | 				   " if there's some reason ps can't" | 
 | 101 | 				   " print a field for any process, it's" | 
 | 102 | 				   " removed from the output entirely)" }, | 
 | 103 |   {"reverse",   'r',    0,      0, "Reverse the order of any sort"}, | 
 | 104 |   {"gratuitously-long-reverse-option", 0, 0, OPTION_ALIAS}, | 
 | 105 |   {"session",  OPT_SESS,"SID",  OPTION_ARG_OPTIONAL, | 
 | 106 | 				   "Add the processes from the session" | 
 | 107 | 				   " SID (which defaults to the sid of" | 
 | 108 | 				   " the current process)" }, | 
 | 109 |  | 
 | 110 |   {0,0,0,0, "Here are some more options:"}, | 
 | 111 |   {"foonly", 'f', "ZOT", OPTION_ARG_OPTIONAL, "Glork a foonly"}, | 
 | 112 |   {"zaza", 'z', 0, 0, "Snit a zar"}, | 
 | 113 |  | 
 | 114 |   {0} | 
 | 115 | }; | 
 | 116 |  | 
 | 117 | static const char args_doc[] = "STRING"; | 
 | 118 | static const char doc[] = "Test program for argp." | 
 | 119 |  "\vThis doc string comes after the options." | 
 | 120 |  "\nHey!  Some manual formatting!" | 
 | 121 |  "\nThe current time is: %s"; | 
 | 122 |  | 
 | 123 | static void | 
 | 124 | popt (int key, char *arg) | 
 | 125 | { | 
 | 126 |   char buf[10]; | 
 | 127 |   if (isprint (key)) | 
 | 128 |     sprintf (buf, "%c", key); | 
 | 129 |   else | 
 | 130 |     sprintf (buf, "%d", key); | 
 | 131 |   if (arg) | 
 | 132 |     printf ("KEY %s: %s\n", buf, arg); | 
 | 133 |   else | 
 | 134 |     printf ("KEY %s\n", buf); | 
 | 135 | } | 
 | 136 |  | 
 | 137 | static error_t | 
 | 138 | parse_opt (int key, char *arg, struct argp_state *state) | 
 | 139 | { | 
 | 140 |   struct params *params = state->input; | 
 | 141 |  | 
 | 142 |   switch (key) | 
 | 143 |     { | 
 | 144 |     case ARGP_KEY_NO_ARGS: | 
 | 145 |       printf ("NO ARGS\n"); | 
 | 146 |       break; | 
 | 147 |  | 
 | 148 |     case ARGP_KEY_ARG: | 
 | 149 |       if (state->arg_num > 0) | 
 | 150 | 	return ARGP_ERR_UNKNOWN; /* Leave it for the sub-arg parser.  */ | 
 | 151 |       printf ("ARG: %s\n", arg); | 
 | 152 |       break; | 
 | 153 |  | 
 | 154 |     case 'f': | 
 | 155 |       if (arg) | 
 | 156 | 	params->foonly = atoi (arg); | 
 | 157 |       else | 
 | 158 | 	params->foonly = params->foonly_default; | 
 | 159 |       popt (key, arg); | 
 | 160 |       break; | 
 | 161 |  | 
 | 162 |     case 'p': case 'P': case OPT_PGRP: case 'x': case 'Q': | 
 | 163 |     case 'r': case OPT_SESS: case 'z': | 
 | 164 |       popt (key, arg); | 
 | 165 |       break; | 
 | 166 |  | 
 | 167 |     default: | 
 | 168 |       return ARGP_ERR_UNKNOWN; | 
 | 169 |     } | 
 | 170 |   return 0; | 
 | 171 | } | 
 | 172 |  | 
 | 173 | static char * | 
 | 174 | help_filter (int key, const char *text, void *input) | 
 | 175 | { | 
 | 176 |   char *new_text; | 
 | 177 |   struct params *params = input; | 
 | 178 |  | 
 | 179 |   if (key == ARGP_KEY_HELP_POST_DOC && text) | 
 | 180 |     { | 
 | 181 |       time_t now = time (0); | 
 | 182 |       asprintf (&new_text, text, ctime (&now)); | 
 | 183 |     } | 
 | 184 |   else if (key == 'f') | 
 | 185 |     /* Show the default for the --foonly option.  */ | 
 | 186 |     asprintf (&new_text, "%s (ZOT defaults to %x)", | 
 | 187 | 	      text, params->foonly_default); | 
 | 188 |   else | 
 | 189 |     new_text = (char *)text; | 
 | 190 |  | 
 | 191 |   return new_text; | 
 | 192 | } | 
 | 193 |  | 
 | 194 | static struct argp_child argp_children[] = { { &sub_argp }, { 0 } }; | 
 | 195 | static struct argp argp = { | 
 | 196 |   options, parse_opt, args_doc, doc, argp_children, help_filter | 
 | 197 | }; | 
 | 198 |  | 
 | 199 | int | 
 | 200 | main (int argc, char **argv) | 
 | 201 | { | 
 | 202 |   struct params params; | 
 | 203 |   params.foonly = 0; | 
 | 204 |   params.foonly_default = random (); | 
 | 205 |   argp_parse (&argp, argc, argv, 0, 0, ¶ms); | 
 | 206 |   printf ("After parsing: foonly = %x\n", params.foonly); | 
 | 207 |   return 0; | 
 | 208 | } |