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