3 #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 length_callback(const struct option
*opt
, const char *arg
, int unset
)
28 length_cb
.unset
= unset
;
31 return 1; /* do not support unset */
33 *(int *)opt
->value
= strlen(arg
);
37 static int number_callback(const struct option
*opt
, const char *arg
, int unset
)
39 BUG_ON_OPT_NEG(unset
);
40 *(int *)opt
->value
= strtol(arg
, NULL
, 10);
44 static int collect_expect(const struct option
*opt
, const char *arg
, int unset
)
46 struct string_list
*expect
;
47 struct string_list_item
*item
;
48 struct strbuf label
= STRBUF_INIT
;
52 die("malformed --expect option");
54 expect
= (struct string_list
*)opt
->value
;
55 colon
= strchr(arg
, ':');
57 die("malformed --expect option, lacking a colon");
58 strbuf_add(&label
, arg
, colon
- arg
);
59 item
= string_list_insert(expect
, strbuf_detach(&label
, NULL
));
61 die("malformed --expect option, duplicate %s", label
.buf
);
62 item
->util
= (void *)arg
;
66 __attribute__((format (printf
,3,4)))
67 static void show(struct string_list
*expect
, int *status
, const char *fmt
, ...)
69 struct string_list_item
*item
;
70 struct strbuf buf
= STRBUF_INIT
;
74 strbuf_vaddf(&buf
, fmt
, args
);
78 printf("%s\n", buf
.buf
);
80 char *colon
= strchr(buf
.buf
, ':');
82 die("malformed output format, output lacking colon: %s", fmt
);
84 item
= string_list_lookup(expect
, buf
.buf
);
87 ; /* not among entries being checked */
89 if (strcmp((const char *)item
->util
, buf
.buf
)) {
90 printf("-%s\n", (char *)item
->util
);
91 printf("+%s\n", buf
.buf
);
99 int cmd__parse_options(int argc
, const char **argv
)
101 const char *prefix
= "prefix/";
102 const char *usage
[] = {
103 "test-tool parse-options <options>",
105 "A helper function for the parse-options API.",
108 struct string_list expect
= STRING_LIST_INIT_NODUP
;
109 struct string_list list
= STRING_LIST_INIT_NODUP
;
111 struct option options
[] = {
112 OPT_BOOL(0, "yes", &boolean
, "get a boolean"),
113 OPT_BOOL('D', "no-doubt", &boolean
, "begins with 'no-'"),
114 { OPTION_SET_INT
, 'B', "no-fear", &boolean
, NULL
,
115 "be brave", PARSE_OPT_NOARG
| PARSE_OPT_NONEG
, NULL
, 1 },
116 OPT_COUNTUP('b', "boolean", &boolean
, "increment by one"),
117 OPT_BIT('4', "or4", &boolean
,
118 "bitwise-or boolean with ...0100", 4),
119 OPT_NEGBIT(0, "neg-or4", &boolean
, "same as --no-or4", 4),
121 OPT_INTEGER('i', "integer", &integer
, "get a integer"),
122 OPT_INTEGER('j', NULL
, &integer
, "get a integer, too"),
123 OPT_MAGNITUDE('m', "magnitude", &magnitude
, "get a magnitude"),
124 OPT_SET_INT(0, "set23", &integer
, "set integer to 23", 23),
125 OPT_CMDMODE(0, "mode1", &integer
, "set integer to 1 (cmdmode option)", 1),
126 OPT_CMDMODE(0, "mode2", &integer
, "set integer to 2 (cmdmode option)", 2),
127 OPT_CALLBACK('L', "length", &integer
, "str",
128 "get length of <str>", length_callback
),
129 OPT_FILENAME('F', "file", &file
, "set file to <file>"),
130 OPT_GROUP("String options"),
131 OPT_STRING('s', "string", &string
, "string", "get a string"),
132 OPT_STRING(0, "string2", &string
, "str", "get another string"),
133 OPT_STRING(0, "st", &string
, "st", "get another string (pervert ordering)"),
134 OPT_STRING('o', NULL
, &string
, "str", "get another string"),
135 OPT_NOOP_NOARG(0, "obsolete"),
136 OPT_STRING_LIST(0, "list", &list
, "str", "add str to list"),
137 OPT_GROUP("Magic arguments"),
138 OPT_NUMBER_CALLBACK(&integer
, "set integer to NUM",
140 { OPTION_COUNTUP
, '+', NULL
, &boolean
, NULL
, "same as -b",
141 PARSE_OPT_NOARG
| PARSE_OPT_NONEG
| PARSE_OPT_NODASH
},
142 { OPTION_COUNTUP
, 0, "ambiguous", &ambiguous
, NULL
,
143 "positive ambiguity", PARSE_OPT_NOARG
| PARSE_OPT_NONEG
},
144 { OPTION_COUNTUP
, 0, "no-ambiguous", &ambiguous
, NULL
,
145 "negative ambiguity", PARSE_OPT_NOARG
| PARSE_OPT_NONEG
},
146 OPT_GROUP("Standard options"),
147 OPT__ABBREV(&abbrev
),
148 OPT__VERBOSE(&verbose
, "be verbose"),
149 OPT__DRY_RUN(&dry_run
, "dry run"),
150 OPT__QUIET(&quiet
, "be quiet"),
151 OPT_CALLBACK(0, "expect", &expect
, "string",
152 "expected output in the variable dump",
155 OPT_STRING('A', "alias-source", &string
, "string", "get a string"),
156 OPT_ALIAS('Z', "alias-target", "alias-source"),
162 trace2_cmd_name("_parse_");
164 argc
= parse_options(argc
, (const char **)argv
, prefix
, options
, usage
, 0);
166 if (length_cb
.called
) {
167 const char *arg
= length_cb
.arg
;
168 int unset
= length_cb
.unset
;
169 show(&expect
, &ret
, "Callback: \"%s\", %d",
170 (arg
? arg
: "not set"), unset
);
172 show(&expect
, &ret
, "boolean: %d", boolean
);
173 show(&expect
, &ret
, "integer: %d", integer
);
174 show(&expect
, &ret
, "magnitude: %lu", magnitude
);
175 show(&expect
, &ret
, "timestamp: %"PRItime
, timestamp
);
176 show(&expect
, &ret
, "string: %s", string
? string
: "(not set)");
177 show(&expect
, &ret
, "abbrev: %d", abbrev
);
178 show(&expect
, &ret
, "verbose: %d", verbose
);
179 show(&expect
, &ret
, "quiet: %d", quiet
);
180 show(&expect
, &ret
, "dry run: %s", dry_run
? "yes" : "no");
181 show(&expect
, &ret
, "file: %s", file
? file
: "(not set)");
183 for (i
= 0; i
< list
.nr
; i
++)
184 show(&expect
, &ret
, "list: %s", list
.items
[i
].string
);
186 for (i
= 0; i
< argc
; i
++)
187 show(&expect
, &ret
, "arg %02d: %s", i
, argv
[i
]);
189 expect
.strdup_strings
= 1;
190 string_list_clear(&expect
, 0);
191 string_list_clear(&list
, 0);
196 static void print_args(int argc
, const char **argv
)
199 for (i
= 0; i
< argc
; i
++)
200 printf("arg %02d: %s\n", i
, argv
[i
]);
203 static int parse_options_flags__cmd(int argc
, const char **argv
,
204 enum parse_opt_flags test_flags
)
206 const char *usage
[] = {
207 "<...> cmd [options]",
211 const struct option options
[] = {
212 OPT_INTEGER('o', "opt", &opt
, "an integer option"),
216 argc
= parse_options(argc
, argv
, NULL
, options
, usage
, test_flags
);
218 printf("opt: %d\n", opt
);
219 print_args(argc
, argv
);
224 static enum parse_opt_flags test_flags
= 0;
225 static const struct option test_flag_options
[] = {
226 OPT_GROUP("flag-options:"),
227 OPT_BIT(0, "keep-dashdash", &test_flags
,
228 "pass PARSE_OPT_KEEP_DASHDASH to parse_options()",
229 PARSE_OPT_KEEP_DASHDASH
),
230 OPT_BIT(0, "stop-at-non-option", &test_flags
,
231 "pass PARSE_OPT_STOP_AT_NON_OPTION to parse_options()",
232 PARSE_OPT_STOP_AT_NON_OPTION
),
233 OPT_BIT(0, "keep-argv0", &test_flags
,
234 "pass PARSE_OPT_KEEP_ARGV0 to parse_options()",
235 PARSE_OPT_KEEP_ARGV0
),
236 OPT_BIT(0, "keep-unknown-opt", &test_flags
,
237 "pass PARSE_OPT_KEEP_UNKNOWN_OPT to parse_options()",
238 PARSE_OPT_KEEP_UNKNOWN_OPT
),
239 OPT_BIT(0, "no-internal-help", &test_flags
,
240 "pass PARSE_OPT_NO_INTERNAL_HELP to parse_options()",
241 PARSE_OPT_NO_INTERNAL_HELP
),
242 OPT_BIT(0, "subcommand-optional", &test_flags
,
243 "pass PARSE_OPT_SUBCOMMAND_OPTIONAL to parse_options()",
244 PARSE_OPT_SUBCOMMAND_OPTIONAL
),
248 int cmd__parse_options_flags(int argc
, const char **argv
)
250 const char *usage
[] = {
251 "test-tool parse-options-flags [flag-options] cmd [options]",
255 argc
= parse_options(argc
, argv
, NULL
, test_flag_options
, usage
,
256 PARSE_OPT_STOP_AT_NON_OPTION
);
258 if (!argc
|| strcmp(argv
[0], "cmd")) {
259 error("'cmd' is mandatory");
260 usage_with_options(usage
, test_flag_options
);
263 return parse_options_flags__cmd(argc
, argv
, test_flags
);
266 static int subcmd_one(int argc
, const char **argv
, const char *prefix
)
268 printf("fn: subcmd_one\n");
269 print_args(argc
, argv
);
273 static int subcmd_two(int argc
, const char **argv
, const char *prefix
)
275 printf("fn: subcmd_two\n");
276 print_args(argc
, argv
);
280 static int parse_subcommand__cmd(int argc
, const char **argv
,
281 enum parse_opt_flags test_flags
)
283 const char *usage
[] = {
284 "<...> cmd subcmd-one",
285 "<...> cmd subcmd-two",
288 parse_opt_subcommand_fn
*fn
= NULL
;
290 struct option options
[] = {
291 OPT_SUBCOMMAND("subcmd-one", &fn
, subcmd_one
),
292 OPT_SUBCOMMAND("subcmd-two", &fn
, subcmd_two
),
293 OPT_INTEGER('o', "opt", &opt
, "an integer option"),
297 if (test_flags
& PARSE_OPT_SUBCOMMAND_OPTIONAL
)
299 argc
= parse_options(argc
, argv
, NULL
, options
, usage
, test_flags
);
301 printf("opt: %d\n", opt
);
303 return fn(argc
, argv
, NULL
);
306 int cmd__parse_subcommand(int argc
, const char **argv
)
308 const char *usage
[] = {
309 "test-tool parse-subcommand [flag-options] cmd <subcommand>",
313 argc
= parse_options(argc
, argv
, NULL
, test_flag_options
, usage
,
314 PARSE_OPT_STOP_AT_NON_OPTION
);
316 if (!argc
|| strcmp(argv
[0], "cmd")) {
317 error("'cmd' is mandatory");
318 usage_with_options(usage
, test_flag_options
);
321 return parse_subcommand__cmd(argc
, argv
, test_flags
);