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