]>
Commit | Line | Data |
---|---|---|
beb47437 JS |
1 | #include "cache.h" |
2 | #include "parse-options.h" | |
c8ba1639 | 3 | #include "string-list.h" |
beb47437 JS |
4 | |
5 | static int boolean = 0; | |
c4aca9cc | 6 | static int integer = 0; |
2a514ed8 | 7 | static unsigned long magnitude = 0; |
dddbad72 | 8 | static timestamp_t timestamp; |
010a2dac | 9 | static int abbrev = 7; |
e0070e8b PB |
10 | static int verbose = -1; /* unspecified */ |
11 | static int dry_run = 0, quiet = 0; | |
beb47437 | 12 | static char *string = NULL; |
df217ed6 | 13 | static char *file = NULL; |
6bbfd1fa | 14 | static int ambiguous; |
2721ce21 | 15 | static struct string_list list = STRING_LIST_INIT_NODUP; |
beb47437 | 16 | |
accac419 JH |
17 | static struct { |
18 | int called; | |
19 | const char *arg; | |
20 | int unset; | |
21 | } length_cb; | |
22 | ||
2af202be | 23 | static int length_callback(const struct option *opt, const char *arg, int unset) |
010a2dac | 24 | { |
accac419 JH |
25 | length_cb.called = 1; |
26 | length_cb.arg = arg; | |
27 | length_cb.unset = unset; | |
28 | ||
010a2dac SB |
29 | if (unset) |
30 | return 1; /* do not support unset */ | |
31 | ||
8caa3acf | 32 | *(int *)opt->value = strlen(arg); |
010a2dac SB |
33 | return 0; |
34 | } | |
35 | ||
2af202be | 36 | static int number_callback(const struct option *opt, const char *arg, int unset) |
e0319ff5 RS |
37 | { |
38 | *(int *)opt->value = strtol(arg, NULL, 10); | |
39 | return 0; | |
40 | } | |
41 | ||
ab6b28b0 JH |
42 | static int collect_expect(const struct option *opt, const char *arg, int unset) |
43 | { | |
44 | struct string_list *expect; | |
45 | struct string_list_item *item; | |
46 | struct strbuf label = STRBUF_INIT; | |
47 | const char *colon; | |
48 | ||
49 | if (!arg || unset) | |
50 | die("malformed --expect option"); | |
51 | ||
52 | expect = (struct string_list *)opt->value; | |
53 | colon = strchr(arg, ':'); | |
54 | if (!colon) | |
55 | die("malformed --expect option, lacking a colon"); | |
56 | strbuf_add(&label, arg, colon - arg); | |
57 | item = string_list_insert(expect, strbuf_detach(&label, NULL)); | |
58 | if (item->util) | |
59 | die("malformed --expect option, duplicate %s", label.buf); | |
60 | item->util = (void *)arg; | |
61 | return 0; | |
62 | } | |
63 | ||
64 | __attribute__((format (printf,3,4))) | |
65 | static void show(struct string_list *expect, int *status, const char *fmt, ...) | |
66 | { | |
67 | struct string_list_item *item; | |
68 | struct strbuf buf = STRBUF_INIT; | |
69 | va_list args; | |
70 | ||
71 | va_start(args, fmt); | |
72 | strbuf_vaddf(&buf, fmt, args); | |
73 | va_end(args); | |
74 | ||
75 | if (!expect->nr) | |
76 | printf("%s\n", buf.buf); | |
77 | else { | |
78 | char *colon = strchr(buf.buf, ':'); | |
79 | if (!colon) | |
80 | die("malformed output format, output lacking colon: %s", fmt); | |
81 | *colon = '\0'; | |
82 | item = string_list_lookup(expect, buf.buf); | |
83 | *colon = ':'; | |
84 | if (!item) | |
85 | ; /* not among entries being checked */ | |
86 | else { | |
87 | if (strcmp((const char *)item->util, buf.buf)) { | |
88 | printf("-%s\n", (char *)item->util); | |
89 | printf("+%s\n", buf.buf); | |
90 | *status = 1; | |
91 | } | |
92 | } | |
93 | } | |
94 | strbuf_release(&buf); | |
95 | } | |
96 | ||
3f2e2297 | 97 | int cmd_main(int argc, const char **argv) |
beb47437 | 98 | { |
df217ed6 | 99 | const char *prefix = "prefix/"; |
beb47437 JS |
100 | const char *usage[] = { |
101 | "test-parse-options <options>", | |
c97ee171 BC |
102 | "", |
103 | "A helper function for the parse-options API.", | |
beb47437 JS |
104 | NULL |
105 | }; | |
ab6b28b0 | 106 | struct string_list expect = STRING_LIST_INIT_NODUP; |
beb47437 | 107 | struct option options[] = { |
b9e63ddd RS |
108 | OPT_BOOL(0, "yes", &boolean, "get a boolean"), |
109 | OPT_BOOL('D', "no-doubt", &boolean, "begins with 'no-'"), | |
110 | { OPTION_SET_INT, 'B', "no-fear", &boolean, NULL, | |
111 | "be brave", PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, 1 }, | |
112 | OPT_COUNTUP('b', "boolean", &boolean, "increment by one"), | |
010a2dac SB |
113 | OPT_BIT('4', "or4", &boolean, |
114 | "bitwise-or boolean with ...0100", 4), | |
2f4b97f9 | 115 | OPT_NEGBIT(0, "neg-or4", &boolean, "same as --no-or4", 4), |
010a2dac | 116 | OPT_GROUP(""), |
beb47437 JS |
117 | OPT_INTEGER('i', "integer", &integer, "get a integer"), |
118 | OPT_INTEGER('j', NULL, &integer, "get a integer, too"), | |
2a514ed8 | 119 | OPT_MAGNITUDE('m', "magnitude", &magnitude, "get a magnitude"), |
010a2dac | 120 | OPT_SET_INT(0, "set23", &integer, "set integer to 23", 23), |
c4aca9cc | 121 | OPT_DATE('t', NULL, ×tamp, "get timestamp of <time>"), |
010a2dac SB |
122 | OPT_CALLBACK('L', "length", &integer, "str", |
123 | "get length of <str>", length_callback), | |
41dbcd45 | 124 | OPT_FILENAME('F', "file", &file, "set file to <file>"), |
010a2dac | 125 | OPT_GROUP("String options"), |
beb47437 JS |
126 | OPT_STRING('s', "string", &string, "string", "get a string"), |
127 | OPT_STRING(0, "string2", &string, "str", "get another string"), | |
243e0614 | 128 | OPT_STRING(0, "st", &string, "st", "get another string (pervert ordering)"), |
3a9f0f41 | 129 | OPT_STRING('o', NULL, &string, "str", "get another string"), |
6acec038 | 130 | OPT_NOOP_NOARG(0, "obsolete"), |
c8ba1639 | 131 | OPT_STRING_LIST(0, "list", &list, "str", "add str to list"), |
010a2dac | 132 | OPT_GROUP("Magic arguments"), |
580d5bff | 133 | OPT_ARGUMENT("quux", "means --quux"), |
e0319ff5 RS |
134 | OPT_NUMBER_CALLBACK(&integer, "set integer to NUM", |
135 | number_callback), | |
b9e63ddd | 136 | { OPTION_COUNTUP, '+', NULL, &boolean, NULL, "same as -b", |
51a9949e | 137 | PARSE_OPT_NOARG | PARSE_OPT_NONEG | PARSE_OPT_NODASH }, |
b9e63ddd | 138 | { OPTION_COUNTUP, 0, "ambiguous", &ambiguous, NULL, |
6bbfd1fa | 139 | "positive ambiguity", PARSE_OPT_NOARG | PARSE_OPT_NONEG }, |
b9e63ddd | 140 | { OPTION_COUNTUP, 0, "no-ambiguous", &ambiguous, NULL, |
6bbfd1fa | 141 | "negative ambiguity", PARSE_OPT_NOARG | PARSE_OPT_NONEG }, |
010a2dac SB |
142 | OPT_GROUP("Standard options"), |
143 | OPT__ABBREV(&abbrev), | |
fd03881a | 144 | OPT__VERBOSE(&verbose, "be verbose"), |
e21adb8c | 145 | OPT__DRY_RUN(&dry_run, "dry run"), |
d52ee6e6 | 146 | OPT__QUIET(&quiet, "be quiet"), |
ab6b28b0 JH |
147 | OPT_CALLBACK(0, "expect", &expect, "string", |
148 | "expected output in the variable dump", | |
149 | collect_expect), | |
beb47437 JS |
150 | OPT_END(), |
151 | }; | |
152 | int i; | |
ab6b28b0 | 153 | int ret = 0; |
beb47437 | 154 | |
84d32bf7 | 155 | argc = parse_options(argc, (const char **)argv, prefix, options, usage, 0); |
beb47437 | 156 | |
accac419 JH |
157 | if (length_cb.called) { |
158 | const char *arg = length_cb.arg; | |
159 | int unset = length_cb.unset; | |
ab6b28b0 JH |
160 | show(&expect, &ret, "Callback: \"%s\", %d", |
161 | (arg ? arg : "not set"), unset); | |
accac419 | 162 | } |
ab6b28b0 JH |
163 | show(&expect, &ret, "boolean: %d", boolean); |
164 | show(&expect, &ret, "integer: %d", integer); | |
165 | show(&expect, &ret, "magnitude: %lu", magnitude); | |
cb71f8bd | 166 | show(&expect, &ret, "timestamp: %"PRItime, timestamp); |
ab6b28b0 JH |
167 | show(&expect, &ret, "string: %s", string ? string : "(not set)"); |
168 | show(&expect, &ret, "abbrev: %d", abbrev); | |
169 | show(&expect, &ret, "verbose: %d", verbose); | |
170 | show(&expect, &ret, "quiet: %d", quiet); | |
171 | show(&expect, &ret, "dry run: %s", dry_run ? "yes" : "no"); | |
172 | show(&expect, &ret, "file: %s", file ? file : "(not set)"); | |
beb47437 | 173 | |
c8ba1639 | 174 | for (i = 0; i < list.nr; i++) |
ab6b28b0 | 175 | show(&expect, &ret, "list: %s", list.items[i].string); |
c8ba1639 | 176 | |
beb47437 | 177 | for (i = 0; i < argc; i++) |
ab6b28b0 | 178 | show(&expect, &ret, "arg %02d: %s", i, argv[i]); |
beb47437 | 179 | |
ab6b28b0 | 180 | return ret; |
beb47437 | 181 | } |