The current option parse code is clumsy. The 's' option is separately handled in an if-conditional due to the following code: input_mode = (enum input_mode)opt; If 's' is moved to the switch statement, the invalid value 's' would be assigned to the input_mode. Another potential problem is that we are mixing 'enum input_mode' and ASCII characters. They could overwrap if we add more input modes. To separate them out, set the flag field of long options to a pointer of input_mode_opt. For mode select options, getopt_long() returns 0, which never causes overwrap with ASCII characters that represent short options.
Unified · Split
| @@ -37,7 +37,7 @@ enum input_mode { · 36 unmodified lines | |||
| 37 | mod2yesconfig, | 37 | mod2yesconfig, |
| 38 | }; | 38 | }; |
| 39 | static enum input_mode input_mode = oldaskconfig; | 39 | static enum input_mode input_mode = oldaskconfig; |
| 40 | 40 | static int input_mode_opt; | |
| 41 | static int indent = 1; | 41 | static int indent = 1; |
| 42 | static int tty_stdio; | 42 | static int tty_stdio; |
| 43 | static int sync_kconfig; | 43 | static int sync_kconfig; |
| @@ -474,21 +474,21 @@ static void check_conf(struct menu *menu) · 430 unmodified lines | |||
| 474 | } | 474 | } |
| 475 | 475 | ||
| 476 | static struct option long_opts[] = { | 476 | static struct option long_opts[] = { |
| 477 | {"oldaskconfig", no_argument, NULL, oldaskconfig}, | 477 | {"oldaskconfig", no_argument, &input_mode_opt, oldaskconfig}, |
| 478 | {"oldconfig", no_argument, NULL, oldconfig}, | 478 | {"oldconfig", no_argument, &input_mode_opt, oldconfig}, |
| 479 | {"syncconfig", no_argument, NULL, syncconfig}, | 479 | {"syncconfig", no_argument, &input_mode_opt, syncconfig}, |
| 480 | {"defconfig", required_argument, NULL, defconfig}, | 480 | {"defconfig", required_argument, &input_mode_opt, defconfig}, |
| 481 | {"savedefconfig", required_argument, NULL, savedefconfig}, | 481 | {"savedefconfig", required_argument, &input_mode_opt, savedefconfig}, |
| 482 | {"allnoconfig", no_argument, NULL, allnoconfig}, | 482 | {"allnoconfig", no_argument, &input_mode_opt, allnoconfig}, |
| 483 | {"allyesconfig", no_argument, NULL, allyesconfig}, | 483 | {"allyesconfig", no_argument, &input_mode_opt, allyesconfig}, |
| 484 | {"allmodconfig", no_argument, NULL, allmodconfig}, | 484 | {"allmodconfig", no_argument, &input_mode_opt, allmodconfig}, |
| 485 | {"alldefconfig", no_argument, NULL, alldefconfig}, | 485 | {"alldefconfig", no_argument, &input_mode_opt, alldefconfig}, |
| 486 | {"randconfig", no_argument, NULL, randconfig}, | 486 | {"randconfig", no_argument, &input_mode_opt, randconfig}, |
| 487 | {"listnewconfig", no_argument, NULL, listnewconfig}, | 487 | {"listnewconfig", no_argument, &input_mode_opt, listnewconfig}, |
| 488 | {"helpnewconfig", no_argument, NULL, helpnewconfig}, | 488 | {"helpnewconfig", no_argument, &input_mode_opt, helpnewconfig}, |
| 489 | {"olddefconfig", no_argument, NULL, olddefconfig}, | 489 | {"olddefconfig", no_argument, &input_mode_opt, olddefconfig}, |
| 490 | {"yes2modconfig", no_argument, NULL, yes2modconfig}, | 490 | {"yes2modconfig", no_argument, &input_mode_opt, yes2modconfig}, |
| 491 | {"mod2yesconfig", no_argument, NULL, mod2yesconfig}, | 491 | {"mod2yesconfig", no_argument, &input_mode_opt, mod2yesconfig}, |
| 492 | {NULL, 0, NULL, 0} | 492 | {NULL, 0, NULL, 0} |
| 493 | }; | 493 | }; |
| 494 | 494 | ||
| @@ -526,43 +526,38 @@ int main(int ac, char **av) · 31 unmodified lines | |||
| 526 | tty_stdio = isatty(0) && isatty(1); | 526 | tty_stdio = isatty(0) && isatty(1); |
| 527 | 527 | ||
| 528 | while ((opt = getopt_long(ac, av, "hs", long_opts, NULL)) != -1) { | 528 | while ((opt = getopt_long(ac, av, "hs", long_opts, NULL)) != -1) { |
| 529 | if (opt == 's') { | ||
| 530 | conf_set_message_callback(NULL); | ||
| 531 | continue; | ||
| 532 | } | ||
| 533 | input_mode = (enum input_mode)opt; | ||
| 534 | switch (opt) { | 529 | switch (opt) { |
| 535 | case syncconfig: | ||
| 536 | /* | ||
| 537 | * syncconfig is invoked during the build stage. | ||
| 538 | * Suppress distracting "configuration written to ..." | ||
| 539 | */ | ||
| 540 | conf_set_message_callback(NULL); | ||
| 541 | sync_kconfig = 1; | ||
| 542 | break; | ||
| 543 | case defconfig: | ||
| 544 | case savedefconfig: | ||
| 545 | defconfig_file = optarg; | ||
| 546 | break; | ||
| 547 | case randconfig: | ||
| 548 | set_randconfig_seed(); | ||
| 549 | break; | ||
| 550 | case oldaskconfig: | ||
| 551 | case oldconfig: | ||
| 552 | case allnoconfig: | ||
| 553 | case allyesconfig: | ||
| 554 | case allmodconfig: | ||
| 555 | case alldefconfig: | ||
| 556 | case listnewconfig: | ||
| 557 | case helpnewconfig: | ||
| 558 | case olddefconfig: | ||
| 559 | case yes2modconfig: | ||
| 560 | case mod2yesconfig: | ||
| 561 | break; | ||
| 562 | case 'h': | 530 | case 'h': |
| 563 | conf_usage(progname); | 531 | conf_usage(progname); |
| 564 | exit(1); | 532 | exit(1); |
| 565 | break; | 533 | break; |
| 534 | case 's': | ||
| 535 | conf_set_message_callback(NULL); | ||
| 536 | break; | ||
| 537 | case 0: | ||
| 538 | input_mode = input_mode_opt; | ||
| 539 | switch (input_mode) { | ||
| 540 | case syncconfig: | ||
| 541 | /* | ||
| 542 | * syncconfig is invoked during the build stage. | ||
| 543 | * Suppress distracting | ||
| 544 | * "configuration written to ..." | ||
| 545 | */ | ||
| 546 | conf_set_message_callback(NULL); | ||
| 547 | sync_kconfig = 1; | ||
| 548 | break; | ||
| 549 | case defconfig: | ||
| 550 | case savedefconfig: | ||
| 551 | defconfig_file = optarg; | ||
| 552 | break; | ||
| 553 | case randconfig: | ||
| 554 | set_randconfig_seed(); | ||
| 555 | break; | ||
| 556 | default: | ||
| 557 | break; | ||
| 558 | } | ||
| 559 | default: | ||
| 560 | break; | ||
| 566 | } | 561 | } |
| 567 | } | 562 | } |
| 568 | if (ac == optind) { | 563 | if (ac == optind) { |