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