parse-opt: add PARSE_OPT_KEEP_ARGV0 parser option.
[git] / parse-options.c
1 #include "git-compat-util.h"
2 #include "parse-options.h"
3 #include "cache.h"
4
5 #define OPT_SHORT 1
6 #define OPT_UNSET 2
7
8 static inline const char *get_arg(struct parse_opt_ctx_t *p)
9 {
10         if (p->opt) {
11                 const char *res = p->opt;
12                 p->opt = NULL;
13                 return res;
14         }
15         p->argc--;
16         return *++p->argv;
17 }
18
19 static inline const char *skip_prefix(const char *str, const char *prefix)
20 {
21         size_t len = strlen(prefix);
22         return strncmp(str, prefix, len) ? NULL : str + len;
23 }
24
25 static int opterror(const struct option *opt, const char *reason, int flags)
26 {
27         if (flags & OPT_SHORT)
28                 return error("switch `%c' %s", opt->short_name, reason);
29         if (flags & OPT_UNSET)
30                 return error("option `no-%s' %s", opt->long_name, reason);
31         return error("option `%s' %s", opt->long_name, reason);
32 }
33
34 static int get_value(struct parse_opt_ctx_t *p,
35                      const struct option *opt, int flags)
36 {
37         const char *s, *arg;
38         const int unset = flags & OPT_UNSET;
39
40         if (unset && p->opt)
41                 return opterror(opt, "takes no value", flags);
42         if (unset && (opt->flags & PARSE_OPT_NONEG))
43                 return opterror(opt, "isn't available", flags);
44
45         if (!(flags & OPT_SHORT) && p->opt) {
46                 switch (opt->type) {
47                 case OPTION_CALLBACK:
48                         if (!(opt->flags & PARSE_OPT_NOARG))
49                                 break;
50                         /* FALLTHROUGH */
51                 case OPTION_BOOLEAN:
52                 case OPTION_BIT:
53                 case OPTION_SET_INT:
54                 case OPTION_SET_PTR:
55                         return opterror(opt, "takes no value", flags);
56                 default:
57                         break;
58                 }
59         }
60
61         arg = p->opt ? p->opt : (p->argc > 1 ? p->argv[1] : NULL);
62         switch (opt->type) {
63         case OPTION_BIT:
64                 if (unset)
65                         *(int *)opt->value &= ~opt->defval;
66                 else
67                         *(int *)opt->value |= opt->defval;
68                 return 0;
69
70         case OPTION_BOOLEAN:
71                 *(int *)opt->value = unset ? 0 : *(int *)opt->value + 1;
72                 return 0;
73
74         case OPTION_SET_INT:
75                 *(int *)opt->value = unset ? 0 : opt->defval;
76                 return 0;
77
78         case OPTION_SET_PTR:
79                 *(void **)opt->value = unset ? NULL : (void *)opt->defval;
80                 return 0;
81
82         case OPTION_STRING:
83                 if (unset) {
84                         *(const char **)opt->value = NULL;
85                         return 0;
86                 }
87                 if (opt->flags & PARSE_OPT_OPTARG && !p->opt) {
88                         *(const char **)opt->value = (const char *)opt->defval;
89                         return 0;
90                 }
91                 if (!arg)
92                         return opterror(opt, "requires a value", flags);
93                 *(const char **)opt->value = get_arg(p);
94                 return 0;
95
96         case OPTION_CALLBACK:
97                 if (unset)
98                         return (*opt->callback)(opt, NULL, 1) ? (-1) : 0;
99                 if (opt->flags & PARSE_OPT_NOARG)
100                         return (*opt->callback)(opt, NULL, 0) ? (-1) : 0;
101                 if (opt->flags & PARSE_OPT_OPTARG && !p->opt)
102                         return (*opt->callback)(opt, NULL, 0) ? (-1) : 0;
103                 if (!arg)
104                         return opterror(opt, "requires a value", flags);
105                 return (*opt->callback)(opt, get_arg(p), 0) ? (-1) : 0;
106
107         case OPTION_INTEGER:
108                 if (unset) {
109                         *(int *)opt->value = 0;
110                         return 0;
111                 }
112                 if (opt->flags & PARSE_OPT_OPTARG && !p->opt) {
113                         *(int *)opt->value = opt->defval;
114                         return 0;
115                 }
116                 if (!arg)
117                         return opterror(opt, "requires a value", flags);
118                 *(int *)opt->value = strtol(get_arg(p), (char **)&s, 10);
119                 if (*s)
120                         return opterror(opt, "expects a numerical value", flags);
121                 return 0;
122
123         default:
124                 die("should not happen, someone must be hit on the forehead");
125         }
126 }
127
128 static int parse_short_opt(struct parse_opt_ctx_t *p, const struct option *options)
129 {
130         for (; options->type != OPTION_END; options++) {
131                 if (options->short_name == *p->opt) {
132                         p->opt = p->opt[1] ? p->opt + 1 : NULL;
133                         return get_value(p, options, OPT_SHORT);
134                 }
135         }
136         return -2;
137 }
138
139 static int parse_long_opt(struct parse_opt_ctx_t *p, const char *arg,
140                           const struct option *options)
141 {
142         const char *arg_end = strchr(arg, '=');
143         const struct option *abbrev_option = NULL, *ambiguous_option = NULL;
144         int abbrev_flags = 0, ambiguous_flags = 0;
145
146         if (!arg_end)
147                 arg_end = arg + strlen(arg);
148
149         for (; options->type != OPTION_END; options++) {
150                 const char *rest;
151                 int flags = 0;
152
153                 if (!options->long_name)
154                         continue;
155
156                 rest = skip_prefix(arg, options->long_name);
157                 if (options->type == OPTION_ARGUMENT) {
158                         if (!rest)
159                                 continue;
160                         if (*rest == '=')
161                                 return opterror(options, "takes no value", flags);
162                         if (*rest)
163                                 continue;
164                         p->out[p->cpidx++] = arg - 2;
165                         return 0;
166                 }
167                 if (!rest) {
168                         /* abbreviated? */
169                         if (!strncmp(options->long_name, arg, arg_end - arg)) {
170 is_abbreviated:
171                                 if (abbrev_option) {
172                                         /*
173                                          * If this is abbreviated, it is
174                                          * ambiguous. So when there is no
175                                          * exact match later, we need to
176                                          * error out.
177                                          */
178                                         ambiguous_option = abbrev_option;
179                                         ambiguous_flags = abbrev_flags;
180                                 }
181                                 if (!(flags & OPT_UNSET) && *arg_end)
182                                         p->opt = arg_end + 1;
183                                 abbrev_option = options;
184                                 abbrev_flags = flags;
185                                 continue;
186                         }
187                         /* negated and abbreviated very much? */
188                         if (!prefixcmp("no-", arg)) {
189                                 flags |= OPT_UNSET;
190                                 goto is_abbreviated;
191                         }
192                         /* negated? */
193                         if (strncmp(arg, "no-", 3))
194                                 continue;
195                         flags |= OPT_UNSET;
196                         rest = skip_prefix(arg + 3, options->long_name);
197                         /* abbreviated and negated? */
198                         if (!rest && !prefixcmp(options->long_name, arg + 3))
199                                 goto is_abbreviated;
200                         if (!rest)
201                                 continue;
202                 }
203                 if (*rest) {
204                         if (*rest != '=')
205                                 continue;
206                         p->opt = rest + 1;
207                 }
208                 return get_value(p, options, flags);
209         }
210
211         if (ambiguous_option)
212                 return error("Ambiguous option: %s "
213                         "(could be --%s%s or --%s%s)",
214                         arg,
215                         (ambiguous_flags & OPT_UNSET) ?  "no-" : "",
216                         ambiguous_option->long_name,
217                         (abbrev_flags & OPT_UNSET) ?  "no-" : "",
218                         abbrev_option->long_name);
219         if (abbrev_option)
220                 return get_value(p, abbrev_option, abbrev_flags);
221         return -2;
222 }
223
224 void check_typos(const char *arg, const struct option *options)
225 {
226         if (strlen(arg) < 3)
227                 return;
228
229         if (!prefixcmp(arg, "no-")) {
230                 error ("did you mean `--%s` (with two dashes ?)", arg);
231                 exit(129);
232         }
233
234         for (; options->type != OPTION_END; options++) {
235                 if (!options->long_name)
236                         continue;
237                 if (!prefixcmp(options->long_name, arg)) {
238                         error ("did you mean `--%s` (with two dashes ?)", arg);
239                         exit(129);
240                 }
241         }
242 }
243
244 void parse_options_start(struct parse_opt_ctx_t *ctx,
245                          int argc, const char **argv, int flags)
246 {
247         memset(ctx, 0, sizeof(*ctx));
248         ctx->argc = argc - 1;
249         ctx->argv = argv + 1;
250         ctx->out  = argv;
251         ctx->cpidx = ((flags & PARSE_OPT_KEEP_ARGV0) != 0);
252         ctx->flags = flags;
253 }
254
255 static int usage_with_options_internal(const char * const *,
256                                        const struct option *, int);
257
258 int parse_options_step(struct parse_opt_ctx_t *ctx,
259                        const struct option *options,
260                        const char * const usagestr[])
261 {
262         /* we must reset ->opt, unknown short option leave it dangling */
263         ctx->opt = NULL;
264
265         for (; ctx->argc; ctx->argc--, ctx->argv++) {
266                 const char *arg = ctx->argv[0];
267
268                 if (*arg != '-' || !arg[1]) {
269                         if (ctx->flags & PARSE_OPT_STOP_AT_NON_OPTION)
270                                 break;
271                         ctx->out[ctx->cpidx++] = ctx->argv[0];
272                         continue;
273                 }
274
275                 if (arg[1] != '-') {
276                         ctx->opt = arg + 1;
277                         if (*ctx->opt == 'h')
278                                 return parse_options_usage(usagestr, options);
279                         switch (parse_short_opt(ctx, options)) {
280                         case -1:
281                                 return parse_options_usage(usagestr, options);
282                         case -2:
283                                 return PARSE_OPT_UNKNOWN;
284                         }
285                         if (ctx->opt)
286                                 check_typos(arg + 1, options);
287                         while (ctx->opt) {
288                                 if (*ctx->opt == 'h')
289                                         return parse_options_usage(usagestr, options);
290                                 switch (parse_short_opt(ctx, options)) {
291                                 case -1:
292                                         return parse_options_usage(usagestr, options);
293                                 case -2:
294                                         /* fake a short option thing to hide the fact that we may have
295                                          * started to parse aggregated stuff
296                                          *
297                                          * This is leaky, too bad.
298                                          */
299                                         ctx->argv[0] = xstrdup(ctx->opt - 1);
300                                         *(char *)ctx->argv[0] = '-';
301                                         return PARSE_OPT_UNKNOWN;
302                                 }
303                         }
304                         continue;
305                 }
306
307                 if (!arg[2]) { /* "--" */
308                         if (!(ctx->flags & PARSE_OPT_KEEP_DASHDASH)) {
309                                 ctx->argc--;
310                                 ctx->argv++;
311                         }
312                         break;
313                 }
314
315                 if (!strcmp(arg + 2, "help-all"))
316                         return usage_with_options_internal(usagestr, options, 1);
317                 if (!strcmp(arg + 2, "help"))
318                         return parse_options_usage(usagestr, options);
319                 switch (parse_long_opt(ctx, arg + 2, options)) {
320                 case -1:
321                         return parse_options_usage(usagestr, options);
322                 case -2:
323                         return PARSE_OPT_UNKNOWN;
324                 }
325         }
326         return PARSE_OPT_DONE;
327 }
328
329 int parse_options_end(struct parse_opt_ctx_t *ctx)
330 {
331         memmove(ctx->out + ctx->cpidx, ctx->argv, ctx->argc * sizeof(*ctx->out));
332         ctx->out[ctx->cpidx + ctx->argc] = NULL;
333         return ctx->cpidx + ctx->argc;
334 }
335
336 int parse_options(int argc, const char **argv, const struct option *options,
337                   const char * const usagestr[], int flags)
338 {
339         struct parse_opt_ctx_t ctx;
340
341         parse_options_start(&ctx, argc, argv, flags);
342         switch (parse_options_step(&ctx, options, usagestr)) {
343         case PARSE_OPT_HELP:
344                 exit(129);
345         case PARSE_OPT_DONE:
346                 break;
347         default: /* PARSE_OPT_UNKNOWN */
348                 if (ctx.argv[0][1] == '-') {
349                         error("unknown option `%s'", ctx.argv[0] + 2);
350                 } else {
351                         error("unknown switch `%c'", *ctx.opt);
352                 }
353                 usage_with_options(usagestr, options);
354         }
355
356         return parse_options_end(&ctx);
357 }
358
359 #define USAGE_OPTS_WIDTH 24
360 #define USAGE_GAP         2
361
362 int usage_with_options_internal(const char * const *usagestr,
363                                 const struct option *opts, int full)
364 {
365         fprintf(stderr, "usage: %s\n", *usagestr++);
366         while (*usagestr && **usagestr)
367                 fprintf(stderr, "   or: %s\n", *usagestr++);
368         while (*usagestr) {
369                 fprintf(stderr, "%s%s\n",
370                                 **usagestr ? "    " : "",
371                                 *usagestr);
372                 usagestr++;
373         }
374
375         if (opts->type != OPTION_GROUP)
376                 fputc('\n', stderr);
377
378         for (; opts->type != OPTION_END; opts++) {
379                 size_t pos;
380                 int pad;
381
382                 if (opts->type == OPTION_GROUP) {
383                         fputc('\n', stderr);
384                         if (*opts->help)
385                                 fprintf(stderr, "%s\n", opts->help);
386                         continue;
387                 }
388                 if (!full && (opts->flags & PARSE_OPT_HIDDEN))
389                         continue;
390
391                 pos = fprintf(stderr, "    ");
392                 if (opts->short_name)
393                         pos += fprintf(stderr, "-%c", opts->short_name);
394                 if (opts->long_name && opts->short_name)
395                         pos += fprintf(stderr, ", ");
396                 if (opts->long_name)
397                         pos += fprintf(stderr, "--%s", opts->long_name);
398
399                 switch (opts->type) {
400                 case OPTION_ARGUMENT:
401                         break;
402                 case OPTION_INTEGER:
403                         if (opts->flags & PARSE_OPT_OPTARG)
404                                 if (opts->long_name)
405                                         pos += fprintf(stderr, "[=<n>]");
406                                 else
407                                         pos += fprintf(stderr, "[<n>]");
408                         else
409                                 pos += fprintf(stderr, " <n>");
410                         break;
411                 case OPTION_CALLBACK:
412                         if (opts->flags & PARSE_OPT_NOARG)
413                                 break;
414                         /* FALLTHROUGH */
415                 case OPTION_STRING:
416                         if (opts->argh) {
417                                 if (opts->flags & PARSE_OPT_OPTARG)
418                                         if (opts->long_name)
419                                                 pos += fprintf(stderr, "[=<%s>]", opts->argh);
420                                         else
421                                                 pos += fprintf(stderr, "[<%s>]", opts->argh);
422                                 else
423                                         pos += fprintf(stderr, " <%s>", opts->argh);
424                         } else {
425                                 if (opts->flags & PARSE_OPT_OPTARG)
426                                         if (opts->long_name)
427                                                 pos += fprintf(stderr, "[=...]");
428                                         else
429                                                 pos += fprintf(stderr, "[...]");
430                                 else
431                                         pos += fprintf(stderr, " ...");
432                         }
433                         break;
434                 default: /* OPTION_{BIT,BOOLEAN,SET_INT,SET_PTR} */
435                         break;
436                 }
437
438                 if (pos <= USAGE_OPTS_WIDTH)
439                         pad = USAGE_OPTS_WIDTH - pos;
440                 else {
441                         fputc('\n', stderr);
442                         pad = USAGE_OPTS_WIDTH;
443                 }
444                 fprintf(stderr, "%*s%s\n", pad + USAGE_GAP, "", opts->help);
445         }
446         fputc('\n', stderr);
447
448         return PARSE_OPT_HELP;
449 }
450
451 void usage_with_options(const char * const *usagestr,
452                         const struct option *opts)
453 {
454         usage_with_options_internal(usagestr, opts, 0);
455         exit(129);
456 }
457
458 int parse_options_usage(const char * const *usagestr,
459                         const struct option *opts)
460 {
461         return usage_with_options_internal(usagestr, opts, 0);
462 }
463
464
465 /*----- some often used options -----*/
466 #include "cache.h"
467
468 int parse_opt_abbrev_cb(const struct option *opt, const char *arg, int unset)
469 {
470         int v;
471
472         if (!arg) {
473                 v = unset ? 0 : DEFAULT_ABBREV;
474         } else {
475                 v = strtol(arg, (char **)&arg, 10);
476                 if (*arg)
477                         return opterror(opt, "expects a numerical value", 0);
478                 if (v && v < MINIMUM_ABBREV)
479                         v = MINIMUM_ABBREV;
480                 else if (v > 40)
481                         v = 40;
482         }
483         *(int *)(opt->value) = v;
484         return 0;
485 }
486
487 int parse_opt_approxidate_cb(const struct option *opt, const char *arg,
488                              int unset)
489 {
490         *(unsigned long *)(opt->value) = approxidate(arg);
491         return 0;
492 }