2 #include "parse-options.h"
4 #include "string-list.h"
7 static int boolean
= 0;
8 static int integer
= 0;
9 static unsigned long magnitude
= 0;
10 static timestamp_t timestamp
;
11 static int abbrev
= 7;
12 static int verbose
= -1; /* unspecified */
13 static int dry_run
= 0, quiet
= 0;
14 static char *string
= NULL
;
15 static char *file
= NULL
;
24 static int mode34_callback(const struct option
*opt
, const char *arg
, int unset
)
27 *(int *)opt
->value
= 0;
28 else if (!strcmp(arg
, "3"))
29 *(int *)opt
->value
= 3;
30 else if (!strcmp(arg
, "4"))
31 *(int *)opt
->value
= 4;
33 return error("invalid value for '%s': '%s'", "--mode34", arg
);
37 static int length_callback(const struct option
*opt
, const char *arg
, int unset
)
41 length_cb
.unset
= unset
;
44 return 1; /* do not support unset */
46 *(int *)opt
->value
= strlen(arg
);
50 static int number_callback(const struct option
*opt
, const char *arg
, int unset
)
52 BUG_ON_OPT_NEG(unset
);
53 *(int *)opt
->value
= strtol(arg
, NULL
, 10);
57 static int collect_expect(const struct option
*opt
, const char *arg
, int unset
)
59 struct string_list
*expect
;
60 struct string_list_item
*item
;
61 struct strbuf label
= STRBUF_INIT
;
65 die("malformed --expect option");
67 expect
= (struct string_list
*)opt
->value
;
68 colon
= strchr(arg
, ':');
70 die("malformed --expect option, lacking a colon");
71 strbuf_add(&label
, arg
, colon
- arg
);
72 item
= string_list_insert(expect
, strbuf_detach(&label
, NULL
));
74 die("malformed --expect option, duplicate %s", label
.buf
);
75 item
->util
= (void *)arg
;
79 __attribute__((format (printf
,3,4)))
80 static void show(struct string_list
*expect
, int *status
, const char *fmt
, ...)
82 struct string_list_item
*item
;
83 struct strbuf buf
= STRBUF_INIT
;
87 strbuf_vaddf(&buf
, fmt
, args
);
91 printf("%s\n", buf
.buf
);
93 char *colon
= strchr(buf
.buf
, ':');
95 die("malformed output format, output lacking colon: %s", fmt
);
97 item
= string_list_lookup(expect
, buf
.buf
);
100 ; /* not among entries being checked */
102 if (strcmp((const char *)item
->util
, buf
.buf
)) {
103 printf("-%s\n", (char *)item
->util
);
104 printf("+%s\n", buf
.buf
);
109 strbuf_release(&buf
);
112 int cmd__parse_options(int argc
, const char **argv
)
114 const char *prefix
= "prefix/";
115 const char *usage
[] = {
116 "test-tool parse-options <options>",
118 "A helper function for the parse-options API.",
121 struct string_list expect
= STRING_LIST_INIT_NODUP
;
122 struct string_list list
= STRING_LIST_INIT_NODUP
;
124 struct option options
[] = {
125 OPT_BOOL(0, "yes", &boolean
, "get a boolean"),
126 OPT_BOOL('D', "no-doubt", &boolean
, "begins with 'no-'"),
127 { OPTION_SET_INT
, 'B', "no-fear", &boolean
, NULL
,
128 "be brave", PARSE_OPT_NOARG
| PARSE_OPT_NONEG
, NULL
, 1 },
129 OPT_COUNTUP('b', "boolean", &boolean
, "increment by one"),
130 OPT_BIT('4', "or4", &boolean
,
131 "bitwise-or boolean with ...0100", 4),
132 OPT_NEGBIT(0, "neg-or4", &boolean
, "same as --no-or4", 4),
134 OPT_INTEGER('i', "integer", &integer
, "get a integer"),
135 OPT_INTEGER('j', NULL
, &integer
, "get a integer, too"),
136 OPT_MAGNITUDE('m', "magnitude", &magnitude
, "get a magnitude"),
137 OPT_SET_INT(0, "set23", &integer
, "set integer to 23", 23),
138 OPT_CMDMODE(0, "mode1", &integer
, "set integer to 1 (cmdmode option)", 1),
139 OPT_CMDMODE(0, "mode2", &integer
, "set integer to 2 (cmdmode option)", 2),
140 OPT_CALLBACK_F(0, "mode34", &integer
, "(3|4)",
141 "set integer to 3 or 4 (cmdmode option)",
142 PARSE_OPT_CMDMODE
, mode34_callback
),
143 OPT_CALLBACK('L', "length", &integer
, "str",
144 "get length of <str>", length_callback
),
145 OPT_FILENAME('F', "file", &file
, "set file to <file>"),
146 OPT_GROUP("String options"),
147 OPT_STRING('s', "string", &string
, "string", "get a string"),
148 OPT_STRING(0, "string2", &string
, "str", "get another string"),
149 OPT_STRING(0, "st", &string
, "st", "get another string (pervert ordering)"),
150 OPT_STRING('o', NULL
, &string
, "str", "get another string"),
151 OPT_NOOP_NOARG(0, "obsolete"),
152 OPT_SET_INT_F(0, "longhelp", &integer
, "help text of this entry\n"
153 "spans multiple lines", 0, PARSE_OPT_NONEG
),
154 OPT_STRING_LIST(0, "list", &list
, "str", "add str to list"),
155 OPT_GROUP("Magic arguments"),
156 OPT_NUMBER_CALLBACK(&integer
, "set integer to NUM",
158 { OPTION_COUNTUP
, '+', NULL
, &boolean
, NULL
, "same as -b",
159 PARSE_OPT_NOARG
| PARSE_OPT_NONEG
| PARSE_OPT_NODASH
},
160 { OPTION_COUNTUP
, 0, "ambiguous", &ambiguous
, NULL
,
161 "positive ambiguity", PARSE_OPT_NOARG
| PARSE_OPT_NONEG
},
162 { OPTION_COUNTUP
, 0, "no-ambiguous", &ambiguous
, NULL
,
163 "negative ambiguity", PARSE_OPT_NOARG
| PARSE_OPT_NONEG
},
164 OPT_GROUP("Standard options"),
165 OPT__ABBREV(&abbrev
),
166 OPT__VERBOSE(&verbose
, "be verbose"),
167 OPT__DRY_RUN(&dry_run
, "dry run"),
168 OPT__QUIET(&quiet
, "be quiet"),
169 OPT_CALLBACK(0, "expect", &expect
, "string",
170 "expected output in the variable dump",
173 OPT_STRING('A', "alias-source", &string
, "string", "get a string"),
174 OPT_ALIAS('Z', "alias-target", "alias-source"),
180 trace2_cmd_name("_parse_");
182 argc
= parse_options(argc
, (const char **)argv
, prefix
, options
, usage
, 0);
184 if (length_cb
.called
) {
185 const char *arg
= length_cb
.arg
;
186 int unset
= length_cb
.unset
;
187 show(&expect
, &ret
, "Callback: \"%s\", %d",
188 (arg
? arg
: "not set"), unset
);
190 show(&expect
, &ret
, "boolean: %d", boolean
);
191 show(&expect
, &ret
, "integer: %d", integer
);
192 show(&expect
, &ret
, "magnitude: %lu", magnitude
);
193 show(&expect
, &ret
, "timestamp: %"PRItime
, timestamp
);
194 show(&expect
, &ret
, "string: %s", string
? string
: "(not set)");
195 show(&expect
, &ret
, "abbrev: %d", abbrev
);
196 show(&expect
, &ret
, "verbose: %d", verbose
);
197 show(&expect
, &ret
, "quiet: %d", quiet
);
198 show(&expect
, &ret
, "dry run: %s", dry_run
? "yes" : "no");
199 show(&expect
, &ret
, "file: %s", file
? file
: "(not set)");
201 for (i
= 0; i
< list
.nr
; i
++)
202 show(&expect
, &ret
, "list: %s", list
.items
[i
].string
);
204 for (i
= 0; i
< argc
; i
++)
205 show(&expect
, &ret
, "arg %02d: %s", i
, argv
[i
]);
207 expect
.strdup_strings
= 1;
208 string_list_clear(&expect
, 0);
209 string_list_clear(&list
, 0);
214 static void print_args(int argc
, const char **argv
)
217 for (i
= 0; i
< argc
; i
++)
218 printf("arg %02d: %s\n", i
, argv
[i
]);
221 static int parse_options_flags__cmd(int argc
, const char **argv
,
222 enum parse_opt_flags test_flags
)
224 const char *usage
[] = {
225 "<...> cmd [options]",
229 const struct option options
[] = {
230 OPT_INTEGER('o', "opt", &opt
, "an integer option"),
234 argc
= parse_options(argc
, argv
, NULL
, options
, usage
, test_flags
);
236 printf("opt: %d\n", opt
);
237 print_args(argc
, argv
);
242 static enum parse_opt_flags test_flags
= 0;
243 static const struct option test_flag_options
[] = {
244 OPT_GROUP("flag-options:"),
245 OPT_BIT(0, "keep-dashdash", &test_flags
,
246 "pass PARSE_OPT_KEEP_DASHDASH to parse_options()",
247 PARSE_OPT_KEEP_DASHDASH
),
248 OPT_BIT(0, "stop-at-non-option", &test_flags
,
249 "pass PARSE_OPT_STOP_AT_NON_OPTION to parse_options()",
250 PARSE_OPT_STOP_AT_NON_OPTION
),
251 OPT_BIT(0, "keep-argv0", &test_flags
,
252 "pass PARSE_OPT_KEEP_ARGV0 to parse_options()",
253 PARSE_OPT_KEEP_ARGV0
),
254 OPT_BIT(0, "keep-unknown-opt", &test_flags
,
255 "pass PARSE_OPT_KEEP_UNKNOWN_OPT to parse_options()",
256 PARSE_OPT_KEEP_UNKNOWN_OPT
),
257 OPT_BIT(0, "no-internal-help", &test_flags
,
258 "pass PARSE_OPT_NO_INTERNAL_HELP to parse_options()",
259 PARSE_OPT_NO_INTERNAL_HELP
),
260 OPT_BIT(0, "subcommand-optional", &test_flags
,
261 "pass PARSE_OPT_SUBCOMMAND_OPTIONAL to parse_options()",
262 PARSE_OPT_SUBCOMMAND_OPTIONAL
),
266 int cmd__parse_options_flags(int argc
, const char **argv
)
268 const char *usage
[] = {
269 "test-tool parse-options-flags [flag-options] cmd [options]",
273 argc
= parse_options(argc
, argv
, NULL
, test_flag_options
, usage
,
274 PARSE_OPT_STOP_AT_NON_OPTION
);
276 if (!argc
|| strcmp(argv
[0], "cmd")) {
277 error("'cmd' is mandatory");
278 usage_with_options(usage
, test_flag_options
);
281 return parse_options_flags__cmd(argc
, argv
, test_flags
);
284 static int subcmd_one(int argc
, const char **argv
, const char *prefix UNUSED
)
286 printf("fn: subcmd_one\n");
287 print_args(argc
, argv
);
291 static int subcmd_two(int argc
, const char **argv
, const char *prefix UNUSED
)
293 printf("fn: subcmd_two\n");
294 print_args(argc
, argv
);
298 static int parse_subcommand__cmd(int argc
, const char **argv
,
299 enum parse_opt_flags test_flags
)
301 const char *usage
[] = {
302 "<...> cmd subcmd-one",
303 "<...> cmd subcmd-two",
306 parse_opt_subcommand_fn
*fn
= NULL
;
308 struct option options
[] = {
309 OPT_SUBCOMMAND("subcmd-one", &fn
, subcmd_one
),
310 OPT_SUBCOMMAND("subcmd-two", &fn
, subcmd_two
),
311 OPT_INTEGER('o', "opt", &opt
, "an integer option"),
315 if (test_flags
& PARSE_OPT_SUBCOMMAND_OPTIONAL
)
317 argc
= parse_options(argc
, argv
, NULL
, options
, usage
, test_flags
);
319 printf("opt: %d\n", opt
);
321 return fn(argc
, argv
, NULL
);
324 int cmd__parse_subcommand(int argc
, const char **argv
)
326 const char *usage
[] = {
327 "test-tool parse-subcommand [flag-options] cmd <subcommand>",
331 argc
= parse_options(argc
, argv
, NULL
, test_flag_options
, usage
,
332 PARSE_OPT_STOP_AT_NON_OPTION
);
334 if (!argc
|| strcmp(argv
[0], "cmd")) {
335 error("'cmd' is mandatory");
336 usage_with_options(usage
, test_flag_options
);
339 return parse_subcommand__cmd(argc
, argv
, test_flags
);