2005-04-17 06:20:36 +08:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
|
|
|
|
* Released under the terms of the GNU GPL v2.0.
|
|
|
|
*/
|
|
|
|
|
2008-01-12 06:44:39 +08:00
|
|
|
#include <locale.h>
|
2005-04-17 06:20:36 +08:00
|
|
|
#include <ctype.h>
|
2015-12-10 06:56:12 +08:00
|
|
|
#include <limits.h>
|
2006-04-19 13:21:53 +08:00
|
|
|
#include <stdio.h>
|
2008-01-09 23:36:19 +08:00
|
|
|
#include <stdlib.h>
|
2005-04-17 06:20:36 +08:00
|
|
|
#include <string.h>
|
|
|
|
#include <time.h>
|
2008-01-09 23:36:19 +08:00
|
|
|
#include <unistd.h>
|
2010-08-01 05:35:26 +08:00
|
|
|
#include <getopt.h>
|
2005-04-17 06:20:36 +08:00
|
|
|
#include <sys/stat.h>
|
2009-03-12 22:15:31 +08:00
|
|
|
#include <sys/time.h>
|
2013-04-14 04:49:13 +08:00
|
|
|
#include <errno.h>
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
#include "lkc.h"
|
|
|
|
|
|
|
|
static void conf(struct menu *menu);
|
|
|
|
static void check_conf(struct menu *menu);
|
|
|
|
|
2010-08-01 05:35:26 +08:00
|
|
|
enum input_mode {
|
|
|
|
oldaskconfig,
|
2018-03-01 14:34:37 +08:00
|
|
|
syncconfig,
|
2010-08-01 05:35:26 +08:00
|
|
|
oldconfig,
|
|
|
|
allnoconfig,
|
|
|
|
allyesconfig,
|
|
|
|
allmodconfig,
|
2010-08-01 05:35:31 +08:00
|
|
|
alldefconfig,
|
2010-08-01 05:35:26 +08:00
|
|
|
randconfig,
|
|
|
|
defconfig,
|
2010-08-01 05:35:34 +08:00
|
|
|
savedefconfig,
|
2010-08-01 05:35:28 +08:00
|
|
|
listnewconfig,
|
2012-09-01 01:05:17 +08:00
|
|
|
olddefconfig,
|
2018-01-11 21:39:39 +08:00
|
|
|
};
|
|
|
|
static enum input_mode input_mode = oldaskconfig;
|
2010-08-01 05:35:26 +08:00
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
static int indent = 1;
|
2013-02-19 08:24:26 +08:00
|
|
|
static int tty_stdio;
|
2008-09-29 11:27:10 +08:00
|
|
|
static int sync_kconfig;
|
2005-04-17 06:20:36 +08:00
|
|
|
static int conf_cnt;
|
2015-12-10 06:56:12 +08:00
|
|
|
static char line[PATH_MAX];
|
2005-04-17 06:20:36 +08:00
|
|
|
static struct menu *rootEntry;
|
|
|
|
|
2009-07-12 16:11:48 +08:00
|
|
|
static void print_help(struct menu *menu)
|
2007-07-21 06:00:36 +08:00
|
|
|
{
|
2009-07-12 16:11:48 +08:00
|
|
|
struct gstr help = str_new();
|
|
|
|
|
|
|
|
menu_get_ext_help(menu, &help);
|
|
|
|
|
|
|
|
printf("\n%s\n", str_get(&help));
|
|
|
|
str_free(&help);
|
2007-07-21 06:00:36 +08:00
|
|
|
}
|
|
|
|
|
2005-06-26 05:59:22 +08:00
|
|
|
static void strip(char *str)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2005-06-26 05:59:22 +08:00
|
|
|
char *p = str;
|
2005-04-17 06:20:36 +08:00
|
|
|
int l;
|
|
|
|
|
|
|
|
while ((isspace(*p)))
|
|
|
|
p++;
|
|
|
|
l = strlen(p);
|
|
|
|
if (p != str)
|
|
|
|
memmove(str, p, l + 1);
|
|
|
|
if (!l)
|
|
|
|
return;
|
|
|
|
p = str + l - 1;
|
|
|
|
while ((isspace(*p)))
|
|
|
|
*p-- = 0;
|
|
|
|
}
|
|
|
|
|
2018-01-11 21:39:40 +08:00
|
|
|
/* Helper function to facilitate fgets() by Jean Sacren. */
|
|
|
|
static void xfgets(char *str, int size, FILE *in)
|
|
|
|
{
|
|
|
|
if (!fgets(str, size, in))
|
|
|
|
fprintf(stderr, "\nError in reading or end of file.\n");
|
2018-02-08 13:56:40 +08:00
|
|
|
|
|
|
|
if (!tty_stdio)
|
|
|
|
printf("%s", str);
|
2018-01-11 21:39:40 +08:00
|
|
|
}
|
|
|
|
|
2007-08-30 11:06:17 +08:00
|
|
|
static int conf_askvalue(struct symbol *sym, const char *def)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
enum symbol_type type = sym_get_type(sym);
|
|
|
|
|
|
|
|
if (!sym_has_value(sym))
|
2008-01-12 06:44:39 +08:00
|
|
|
printf(_("(NEW) "));
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
line[0] = '\n';
|
|
|
|
line[1] = 0;
|
|
|
|
|
|
|
|
if (!sym_is_changable(sym)) {
|
|
|
|
printf("%s\n", def);
|
|
|
|
line[0] = '\n';
|
|
|
|
line[1] = 0;
|
2007-08-30 11:06:17 +08:00
|
|
|
return 0;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
switch (input_mode) {
|
2010-08-01 05:35:26 +08:00
|
|
|
case oldconfig:
|
2018-03-01 14:34:37 +08:00
|
|
|
case syncconfig:
|
2005-04-17 06:20:36 +08:00
|
|
|
if (sym_has_value(sym)) {
|
|
|
|
printf("%s\n", def);
|
2007-08-30 11:06:17 +08:00
|
|
|
return 0;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
2011-06-01 00:30:26 +08:00
|
|
|
/* fall through */
|
2010-08-01 05:35:26 +08:00
|
|
|
case oldaskconfig:
|
2005-04-17 06:20:36 +08:00
|
|
|
fflush(stdout);
|
2015-12-10 06:56:12 +08:00
|
|
|
xfgets(line, sizeof(line), stdin);
|
2007-08-30 11:06:17 +08:00
|
|
|
return 1;
|
2005-04-17 06:20:36 +08:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
case S_INT:
|
|
|
|
case S_HEX:
|
|
|
|
case S_STRING:
|
|
|
|
printf("%s\n", def);
|
2007-08-30 11:06:17 +08:00
|
|
|
return 1;
|
2005-04-17 06:20:36 +08:00
|
|
|
default:
|
|
|
|
;
|
|
|
|
}
|
|
|
|
printf("%s", line);
|
2007-08-30 11:06:17 +08:00
|
|
|
return 1;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2009-09-19 03:49:23 +08:00
|
|
|
static int conf_string(struct menu *menu)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
struct symbol *sym = menu->sym;
|
2007-07-21 06:00:36 +08:00
|
|
|
const char *def;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
while (1) {
|
2008-01-12 06:44:39 +08:00
|
|
|
printf("%*s%s ", indent - 1, "", _(menu->prompt->text));
|
2005-04-17 06:20:36 +08:00
|
|
|
printf("(%s) ", sym->name);
|
|
|
|
def = sym_get_string_value(sym);
|
|
|
|
if (sym_get_string_value(sym))
|
|
|
|
printf("[%s] ", def);
|
2007-08-30 11:06:17 +08:00
|
|
|
if (!conf_askvalue(sym, def))
|
|
|
|
return 0;
|
2005-04-17 06:20:36 +08:00
|
|
|
switch (line[0]) {
|
|
|
|
case '\n':
|
|
|
|
break;
|
|
|
|
case '?':
|
|
|
|
/* print help */
|
|
|
|
if (line[1] == '\n') {
|
2009-07-12 16:11:48 +08:00
|
|
|
print_help(menu);
|
2005-04-17 06:20:36 +08:00
|
|
|
def = NULL;
|
|
|
|
break;
|
|
|
|
}
|
2011-06-01 00:30:26 +08:00
|
|
|
/* fall through */
|
2005-04-17 06:20:36 +08:00
|
|
|
default:
|
|
|
|
line[strlen(line)-1] = 0;
|
|
|
|
def = line;
|
|
|
|
}
|
|
|
|
if (def && sym_set_string_value(sym, def))
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int conf_sym(struct menu *menu)
|
|
|
|
{
|
|
|
|
struct symbol *sym = menu->sym;
|
|
|
|
tristate oldval, newval;
|
|
|
|
|
|
|
|
while (1) {
|
2008-01-12 06:44:39 +08:00
|
|
|
printf("%*s%s ", indent - 1, "", _(menu->prompt->text));
|
2005-04-17 06:20:36 +08:00
|
|
|
if (sym->name)
|
|
|
|
printf("(%s) ", sym->name);
|
|
|
|
putchar('[');
|
|
|
|
oldval = sym_get_tristate_value(sym);
|
|
|
|
switch (oldval) {
|
|
|
|
case no:
|
|
|
|
putchar('N');
|
|
|
|
break;
|
|
|
|
case mod:
|
|
|
|
putchar('M');
|
|
|
|
break;
|
|
|
|
case yes:
|
|
|
|
putchar('Y');
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (oldval != no && sym_tristate_within_range(sym, no))
|
|
|
|
printf("/n");
|
|
|
|
if (oldval != mod && sym_tristate_within_range(sym, mod))
|
|
|
|
printf("/m");
|
|
|
|
if (oldval != yes && sym_tristate_within_range(sym, yes))
|
|
|
|
printf("/y");
|
2018-02-06 08:34:43 +08:00
|
|
|
printf("/?] ");
|
2007-08-30 11:06:17 +08:00
|
|
|
if (!conf_askvalue(sym, sym_get_string_value(sym)))
|
|
|
|
return 0;
|
2005-04-17 06:20:36 +08:00
|
|
|
strip(line);
|
|
|
|
|
|
|
|
switch (line[0]) {
|
|
|
|
case 'n':
|
|
|
|
case 'N':
|
|
|
|
newval = no;
|
|
|
|
if (!line[1] || !strcmp(&line[1], "o"))
|
|
|
|
break;
|
|
|
|
continue;
|
|
|
|
case 'm':
|
|
|
|
case 'M':
|
|
|
|
newval = mod;
|
|
|
|
if (!line[1])
|
|
|
|
break;
|
|
|
|
continue;
|
|
|
|
case 'y':
|
|
|
|
case 'Y':
|
|
|
|
newval = yes;
|
|
|
|
if (!line[1] || !strcmp(&line[1], "es"))
|
|
|
|
break;
|
|
|
|
continue;
|
|
|
|
case 0:
|
|
|
|
newval = oldval;
|
|
|
|
break;
|
|
|
|
case '?':
|
|
|
|
goto help;
|
|
|
|
default:
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (sym_set_tristate_value(sym, newval))
|
|
|
|
return 0;
|
|
|
|
help:
|
2009-07-12 16:11:48 +08:00
|
|
|
print_help(menu);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int conf_choice(struct menu *menu)
|
|
|
|
{
|
|
|
|
struct symbol *sym, *def_sym;
|
|
|
|
struct menu *child;
|
|
|
|
bool is_new;
|
|
|
|
|
|
|
|
sym = menu->sym;
|
|
|
|
is_new = !sym_has_value(sym);
|
|
|
|
if (sym_is_changable(sym)) {
|
|
|
|
conf_sym(menu);
|
|
|
|
sym_calc_value(sym);
|
|
|
|
switch (sym_get_tristate_value(sym)) {
|
|
|
|
case no:
|
|
|
|
return 1;
|
|
|
|
case mod:
|
|
|
|
return 0;
|
|
|
|
case yes:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
switch (sym_get_tristate_value(sym)) {
|
|
|
|
case no:
|
|
|
|
return 1;
|
|
|
|
case mod:
|
2008-01-12 06:44:39 +08:00
|
|
|
printf("%*s%s\n", indent - 1, "", _(menu_get_prompt(menu)));
|
2005-04-17 06:20:36 +08:00
|
|
|
return 0;
|
|
|
|
case yes:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
int cnt, def;
|
|
|
|
|
2008-01-12 06:44:39 +08:00
|
|
|
printf("%*s%s\n", indent - 1, "", _(menu_get_prompt(menu)));
|
2005-04-17 06:20:36 +08:00
|
|
|
def_sym = sym_get_choice_value(sym);
|
|
|
|
cnt = def = 0;
|
2006-04-09 23:26:39 +08:00
|
|
|
line[0] = 0;
|
2005-04-17 06:20:36 +08:00
|
|
|
for (child = menu->list; child; child = child->next) {
|
|
|
|
if (!menu_is_visible(child))
|
|
|
|
continue;
|
|
|
|
if (!child->sym) {
|
2008-01-12 06:44:39 +08:00
|
|
|
printf("%*c %s\n", indent, '*', _(menu_get_prompt(child)));
|
2005-04-17 06:20:36 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
cnt++;
|
|
|
|
if (child->sym == def_sym) {
|
|
|
|
def = cnt;
|
|
|
|
printf("%*c", indent, '>');
|
|
|
|
} else
|
|
|
|
printf("%*c", indent, ' ');
|
2008-01-12 06:44:39 +08:00
|
|
|
printf(" %d. %s", cnt, _(menu_get_prompt(child)));
|
2005-04-17 06:20:36 +08:00
|
|
|
if (child->sym->name)
|
|
|
|
printf(" (%s)", child->sym->name);
|
|
|
|
if (!sym_has_value(child->sym))
|
2008-01-12 06:44:39 +08:00
|
|
|
printf(_(" (NEW)"));
|
2005-04-17 06:20:36 +08:00
|
|
|
printf("\n");
|
|
|
|
}
|
2008-01-12 06:44:39 +08:00
|
|
|
printf(_("%*schoice"), indent - 1, "");
|
2005-04-17 06:20:36 +08:00
|
|
|
if (cnt == 1) {
|
|
|
|
printf("[1]: 1\n");
|
|
|
|
goto conf_childs;
|
|
|
|
}
|
2018-02-06 08:34:43 +08:00
|
|
|
printf("[1-%d?]: ", cnt);
|
2005-04-17 06:20:36 +08:00
|
|
|
switch (input_mode) {
|
2010-08-01 05:35:26 +08:00
|
|
|
case oldconfig:
|
2018-03-01 14:34:37 +08:00
|
|
|
case syncconfig:
|
2005-04-17 06:20:36 +08:00
|
|
|
if (!is_new) {
|
|
|
|
cnt = def;
|
|
|
|
printf("%d\n", cnt);
|
|
|
|
break;
|
|
|
|
}
|
2011-06-01 00:30:26 +08:00
|
|
|
/* fall through */
|
2010-08-01 05:35:26 +08:00
|
|
|
case oldaskconfig:
|
2005-04-17 06:20:36 +08:00
|
|
|
fflush(stdout);
|
2015-12-10 06:56:12 +08:00
|
|
|
xfgets(line, sizeof(line), stdin);
|
2005-04-17 06:20:36 +08:00
|
|
|
strip(line);
|
|
|
|
if (line[0] == '?') {
|
2009-07-12 16:11:48 +08:00
|
|
|
print_help(menu);
|
2005-04-17 06:20:36 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (!line[0])
|
|
|
|
cnt = def;
|
|
|
|
else if (isdigit(line[0]))
|
|
|
|
cnt = atoi(line);
|
|
|
|
else
|
|
|
|
continue;
|
|
|
|
break;
|
2008-07-01 04:45:38 +08:00
|
|
|
default:
|
|
|
|
break;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
conf_childs:
|
|
|
|
for (child = menu->list; child; child = child->next) {
|
|
|
|
if (!child->sym || !menu_is_visible(child))
|
|
|
|
continue;
|
|
|
|
if (!--cnt)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (!child)
|
|
|
|
continue;
|
2011-04-24 01:42:56 +08:00
|
|
|
if (line[0] && line[strlen(line) - 1] == '?') {
|
2009-07-12 16:11:48 +08:00
|
|
|
print_help(child);
|
2005-04-17 06:20:36 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
sym_set_choice_value(sym, child->sym);
|
2008-01-24 19:54:23 +08:00
|
|
|
for (child = child->list; child; child = child->next) {
|
2005-04-17 06:20:36 +08:00
|
|
|
indent += 2;
|
2008-01-24 19:54:23 +08:00
|
|
|
conf(child);
|
2005-04-17 06:20:36 +08:00
|
|
|
indent -= 2;
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void conf(struct menu *menu)
|
|
|
|
{
|
|
|
|
struct symbol *sym;
|
|
|
|
struct property *prop;
|
|
|
|
struct menu *child;
|
|
|
|
|
|
|
|
if (!menu_is_visible(menu))
|
|
|
|
return;
|
|
|
|
|
|
|
|
sym = menu->sym;
|
|
|
|
prop = menu->prompt;
|
|
|
|
if (prop) {
|
|
|
|
const char *prompt;
|
|
|
|
|
|
|
|
switch (prop->type) {
|
|
|
|
case P_MENU:
|
kconfig: hide irrelevant sub-menus for oldconfig
Historically, "make oldconfig" has changed its behavior several times,
quieter or louder. (I attached the history below.) Currently, it is
not as quiet as it should be. This commit addresses it.
Test Case
---------
---------------------------(Kconfig)----------------------------
menu "menu"
config FOO
bool "foo"
menu "sub menu"
config BAR
bool "bar"
endmenu
endmenu
menu "sibling menu"
config BAZ
bool "baz"
endmenu
----------------------------------------------------------------
---------------------------(.config)----------------------------
CONFIG_BAR=y
CONFIG_BAZ=y
----------------------------------------------------------------
With the Kconfig and .config above, "make silentoldconfig" and
"make oldconfig" work differently, like follows:
$ make silentoldconfig
scripts/kconfig/conf --silentoldconfig Kconfig
*
* Restart config...
*
*
* menu
*
foo (FOO) [N/y/?] (NEW) y
#
# configuration written to .config
#
$ make oldconfig
scripts/kconfig/conf --oldconfig Kconfig
*
* Restart config...
*
*
* menu
*
foo (FOO) [N/y/?] (NEW) y
*
* sub menu
*
bar (BAR) [Y/n/?] y
#
# configuration written to .config
#
Both hide "sibling node" since it is irrelevant. The difference is
that silentoldconfig hides "sub menu" whereas oldconfig does not.
The behavior of silentoldconfig is preferred since the "sub menu"
does not contain any new symbol.
The root cause is in conf(). There are three input modes that can
call conf(); oldaskconfig, oldconfig, and silentoldconfig.
Everytime conf() encounters a menu entry, it calls check_conf() to
check if it contains new symbols. If no new symbol is found, the
menu is just skipped.
Currently, this happens only when input_mode == silentoldconfig.
The oldaskconfig enters into the check_conf() loop as silentoldconfig,
so oldaskconfig works likewise for the second loop or later, but it
never happens for oldconfig. So, irrelevant sub-menus are shown for
oldconfig.
Change the test condition to "input_mode != oldaskconfig". This is
false only for the first loop of oldaskconfig; it must ask the user
all symbols, so no need to call check_conf().
History of oldconfig
--------------------
[0] Originally, "make oldconfig" was as loud as "make config" (It
showed the entire .config file)
[1] Commit cd9140e1e73a ("kconfig: make oldconfig is now less chatty")
made oldconfig quieter, but it was still less quieter than
silentoldconfig. (oldconfig did not hide sub-menus)
[2] Commit 204c96f60904 ("kconfig: fix silentoldconfig") changed
the input_mode of oldconfig to "ask_silent" from "ask_new".
So, oldconfig really became as quiet as silentoldconfig.
(oldconfig hided irrelevant sub-menus)
[3] Commit 4062f1a4c030 ("kconfig: use long options in conf") made
oldconfig as loud as [0] due to misconversion.
[4] Commit 14828349719a ("kconfig: fix make oldconfig") addressed
the misconversion of [3], but it made oldconfig quieter only to
the same level as [1], not [2].
This commit is restoring the behavior of [2].
Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
Reviewed-by: Ulf Magnusson <ulfalizer@gmail.com>
2018-02-28 08:15:24 +08:00
|
|
|
/*
|
|
|
|
* Except in oldaskconfig mode, we show only menus that
|
|
|
|
* contain new symbols.
|
|
|
|
*/
|
|
|
|
if (input_mode != oldaskconfig && rootEntry != menu) {
|
2005-04-17 06:20:36 +08:00
|
|
|
check_conf(menu);
|
|
|
|
return;
|
|
|
|
}
|
2011-06-01 00:30:26 +08:00
|
|
|
/* fall through */
|
2005-04-17 06:20:36 +08:00
|
|
|
case P_COMMENT:
|
|
|
|
prompt = menu_get_prompt(menu);
|
|
|
|
if (prompt)
|
|
|
|
printf("%*c\n%*c %s\n%*c\n",
|
|
|
|
indent, '*',
|
2008-01-12 06:44:39 +08:00
|
|
|
indent, '*', _(prompt),
|
2005-04-17 06:20:36 +08:00
|
|
|
indent, '*');
|
|
|
|
default:
|
|
|
|
;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!sym)
|
|
|
|
goto conf_childs;
|
|
|
|
|
|
|
|
if (sym_is_choice(sym)) {
|
|
|
|
conf_choice(menu);
|
|
|
|
if (sym->curr.tri != mod)
|
|
|
|
return;
|
|
|
|
goto conf_childs;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (sym->type) {
|
|
|
|
case S_INT:
|
|
|
|
case S_HEX:
|
|
|
|
case S_STRING:
|
|
|
|
conf_string(menu);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
conf_sym(menu);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
conf_childs:
|
|
|
|
if (sym)
|
|
|
|
indent += 2;
|
|
|
|
for (child = menu->list; child; child = child->next)
|
|
|
|
conf(child);
|
|
|
|
if (sym)
|
|
|
|
indent -= 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void check_conf(struct menu *menu)
|
|
|
|
{
|
|
|
|
struct symbol *sym;
|
|
|
|
struct menu *child;
|
|
|
|
|
|
|
|
if (!menu_is_visible(menu))
|
|
|
|
return;
|
|
|
|
|
|
|
|
sym = menu->sym;
|
2005-11-09 13:34:48 +08:00
|
|
|
if (sym && !sym_has_value(sym)) {
|
|
|
|
if (sym_is_changable(sym) ||
|
|
|
|
(sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)) {
|
2010-08-01 05:35:28 +08:00
|
|
|
if (input_mode == listnewconfig) {
|
2018-04-12 03:15:37 +08:00
|
|
|
if (sym->name) {
|
|
|
|
const char *str;
|
|
|
|
|
|
|
|
if (sym->type == S_STRING) {
|
|
|
|
str = sym_get_string_value(sym);
|
|
|
|
str = sym_escape_string_value(str);
|
|
|
|
printf("%s%s=%s\n", CONFIG_, sym->name, str);
|
|
|
|
free((void *)str);
|
|
|
|
} else {
|
|
|
|
str = sym_get_string_value(sym);
|
|
|
|
printf("%s%s=%s\n", CONFIG_, sym->name, str);
|
|
|
|
}
|
2010-05-07 00:48:34 +08:00
|
|
|
}
|
2018-02-28 08:15:21 +08:00
|
|
|
} else {
|
2010-05-07 00:48:34 +08:00
|
|
|
if (!conf_cnt++)
|
|
|
|
printf(_("*\n* Restart config...\n*\n"));
|
|
|
|
rootEntry = menu_get_parent_menu(menu);
|
|
|
|
conf(rootEntry);
|
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (child = menu->list; child; child = child->next)
|
|
|
|
check_conf(child);
|
|
|
|
}
|
|
|
|
|
2010-08-01 05:35:26 +08:00
|
|
|
static struct option long_opts[] = {
|
|
|
|
{"oldaskconfig", no_argument, NULL, oldaskconfig},
|
|
|
|
{"oldconfig", no_argument, NULL, oldconfig},
|
2018-03-01 14:34:37 +08:00
|
|
|
{"syncconfig", no_argument, NULL, syncconfig},
|
2010-08-01 05:35:26 +08:00
|
|
|
{"defconfig", optional_argument, NULL, defconfig},
|
2010-08-01 05:35:34 +08:00
|
|
|
{"savedefconfig", required_argument, NULL, savedefconfig},
|
2010-08-01 05:35:26 +08:00
|
|
|
{"allnoconfig", no_argument, NULL, allnoconfig},
|
|
|
|
{"allyesconfig", no_argument, NULL, allyesconfig},
|
|
|
|
{"allmodconfig", no_argument, NULL, allmodconfig},
|
2010-08-01 05:35:31 +08:00
|
|
|
{"alldefconfig", no_argument, NULL, alldefconfig},
|
2010-08-01 05:35:26 +08:00
|
|
|
{"randconfig", no_argument, NULL, randconfig},
|
2010-08-01 05:35:28 +08:00
|
|
|
{"listnewconfig", no_argument, NULL, listnewconfig},
|
2012-09-01 01:05:17 +08:00
|
|
|
{"olddefconfig", no_argument, NULL, olddefconfig},
|
|
|
|
/*
|
|
|
|
* oldnoconfig is an alias of olddefconfig, because people already
|
|
|
|
* are dependent on its behavior(sets new symbols to their default
|
|
|
|
* value but not 'n') with the counter-intuitive name.
|
|
|
|
*/
|
|
|
|
{"oldnoconfig", no_argument, NULL, olddefconfig},
|
2010-08-01 05:35:26 +08:00
|
|
|
{NULL, 0, NULL, 0}
|
|
|
|
};
|
|
|
|
|
2010-11-02 12:26:33 +08:00
|
|
|
static void conf_usage(const char *progname)
|
|
|
|
{
|
|
|
|
|
2015-04-08 19:30:42 +08:00
|
|
|
printf("Usage: %s [-s] [option] <kconfig-file>\n", progname);
|
2010-11-02 12:26:33 +08:00
|
|
|
printf("[option] is _one_ of the following:\n");
|
|
|
|
printf(" --listnewconfig List new options\n");
|
|
|
|
printf(" --oldaskconfig Start a new configuration using a line-oriented program\n");
|
|
|
|
printf(" --oldconfig Update a configuration using a provided .config as base\n");
|
2018-03-01 14:34:37 +08:00
|
|
|
printf(" --syncconfig Similar to oldconfig but generates configuration in\n"
|
|
|
|
" include/{generated/,config/}\n");
|
2018-01-27 06:59:00 +08:00
|
|
|
printf(" --olddefconfig Same as oldconfig but sets new symbols to their default value\n");
|
2012-09-01 01:05:17 +08:00
|
|
|
printf(" --oldnoconfig An alias of olddefconfig\n");
|
2010-11-02 12:26:33 +08:00
|
|
|
printf(" --defconfig <file> New config with default defined in <file>\n");
|
|
|
|
printf(" --savedefconfig <file> Save the minimal current configuration to <file>\n");
|
|
|
|
printf(" --allnoconfig New config where all options are answered with no\n");
|
|
|
|
printf(" --allyesconfig New config where all options are answered with yes\n");
|
|
|
|
printf(" --allmodconfig New config where all options are answered with mod\n");
|
|
|
|
printf(" --alldefconfig New config with all symbols set to default\n");
|
|
|
|
printf(" --randconfig New config with random answer to all options\n");
|
|
|
|
}
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
int main(int ac, char **av)
|
|
|
|
{
|
2010-11-02 12:26:33 +08:00
|
|
|
const char *progname = av[0];
|
2007-12-17 14:34:58 +08:00
|
|
|
int opt;
|
2010-10-14 08:43:28 +08:00
|
|
|
const char *name, *defconfig_file = NULL /* gcc uninit */;
|
2005-04-17 06:20:36 +08:00
|
|
|
struct stat tmpstat;
|
|
|
|
|
2008-01-12 06:44:39 +08:00
|
|
|
setlocale(LC_ALL, "");
|
|
|
|
bindtextdomain(PACKAGE, LOCALEDIR);
|
|
|
|
textdomain(PACKAGE);
|
|
|
|
|
2018-02-08 13:56:40 +08:00
|
|
|
tty_stdio = isatty(0) && isatty(1);
|
2013-02-19 08:24:26 +08:00
|
|
|
|
2015-04-08 19:30:42 +08:00
|
|
|
while ((opt = getopt_long(ac, av, "s", long_opts, NULL)) != -1) {
|
|
|
|
if (opt == 's') {
|
|
|
|
conf_set_message_callback(NULL);
|
|
|
|
continue;
|
|
|
|
}
|
2010-08-01 05:35:26 +08:00
|
|
|
input_mode = (enum input_mode)opt;
|
2007-12-17 14:34:58 +08:00
|
|
|
switch (opt) {
|
2018-03-01 14:34:37 +08:00
|
|
|
case syncconfig:
|
2008-09-29 11:27:10 +08:00
|
|
|
sync_kconfig = 1;
|
2005-04-17 06:20:36 +08:00
|
|
|
break;
|
2010-08-01 05:35:26 +08:00
|
|
|
case defconfig:
|
2010-08-01 05:35:34 +08:00
|
|
|
case savedefconfig:
|
2007-12-17 14:34:58 +08:00
|
|
|
defconfig_file = optarg;
|
2005-04-17 06:20:36 +08:00
|
|
|
break;
|
2010-08-01 05:35:26 +08:00
|
|
|
case randconfig:
|
2009-03-12 22:15:31 +08:00
|
|
|
{
|
|
|
|
struct timeval now;
|
|
|
|
unsigned int seed;
|
2013-04-14 04:49:13 +08:00
|
|
|
char *seed_env;
|
2009-03-12 22:15:31 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Use microseconds derived seed,
|
|
|
|
* compensate for systems where it may be zero
|
|
|
|
*/
|
|
|
|
gettimeofday(&now, NULL);
|
|
|
|
seed = (unsigned int)((now.tv_sec + 1) * (now.tv_usec + 1));
|
2013-04-14 04:49:13 +08:00
|
|
|
|
|
|
|
seed_env = getenv("KCONFIG_SEED");
|
|
|
|
if( seed_env && *seed_env ) {
|
|
|
|
char *endp;
|
2013-05-21 05:17:34 +08:00
|
|
|
int tmp = (int)strtol(seed_env, &endp, 0);
|
2013-04-14 04:49:13 +08:00
|
|
|
if (*endp == '\0') {
|
|
|
|
seed = tmp;
|
|
|
|
}
|
|
|
|
}
|
2013-05-21 05:09:03 +08:00
|
|
|
fprintf( stderr, "KCONFIG_SEED=0x%X\n", seed );
|
2009-03-12 22:15:31 +08:00
|
|
|
srand(seed);
|
2005-04-17 06:20:36 +08:00
|
|
|
break;
|
2009-03-12 22:15:31 +08:00
|
|
|
}
|
2010-11-02 12:26:33 +08:00
|
|
|
case oldaskconfig:
|
|
|
|
case oldconfig:
|
|
|
|
case allnoconfig:
|
|
|
|
case allyesconfig:
|
|
|
|
case allmodconfig:
|
|
|
|
case alldefconfig:
|
|
|
|
case listnewconfig:
|
2012-09-01 01:05:17 +08:00
|
|
|
case olddefconfig:
|
2010-11-02 12:26:33 +08:00
|
|
|
break;
|
2010-08-01 05:35:26 +08:00
|
|
|
case '?':
|
2010-11-02 12:26:33 +08:00
|
|
|
conf_usage(progname);
|
2007-12-17 14:34:58 +08:00
|
|
|
exit(1);
|
2010-08-01 05:35:26 +08:00
|
|
|
break;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
}
|
2007-12-17 14:34:58 +08:00
|
|
|
if (ac == optind) {
|
2018-02-06 08:34:41 +08:00
|
|
|
fprintf(stderr, _("%s: Kconfig file missing\n"), av[0]);
|
2010-11-02 12:26:33 +08:00
|
|
|
conf_usage(progname);
|
2006-06-09 13:12:50 +08:00
|
|
|
exit(1);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
2007-12-17 14:34:58 +08:00
|
|
|
name = av[optind];
|
2005-04-17 06:20:36 +08:00
|
|
|
conf_parse(name);
|
|
|
|
//zconfdump(stdout);
|
2008-09-29 11:27:10 +08:00
|
|
|
if (sync_kconfig) {
|
2009-05-18 07:36:53 +08:00
|
|
|
name = conf_get_configname();
|
|
|
|
if (stat(name, &tmpstat)) {
|
2008-09-29 11:27:10 +08:00
|
|
|
fprintf(stderr, _("***\n"
|
2010-08-15 11:51:40 +08:00
|
|
|
"*** Configuration file \"%s\" not found!\n"
|
2008-09-29 11:27:10 +08:00
|
|
|
"***\n"
|
|
|
|
"*** Please run some configurator (e.g. \"make oldconfig\" or\n"
|
|
|
|
"*** \"make menuconfig\" or \"make xconfig\").\n"
|
2009-05-18 07:36:53 +08:00
|
|
|
"***\n"), name);
|
2008-09-29 11:27:10 +08:00
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
switch (input_mode) {
|
2010-08-01 05:35:26 +08:00
|
|
|
case defconfig:
|
2005-04-17 06:20:36 +08:00
|
|
|
if (!defconfig_file)
|
|
|
|
defconfig_file = conf_get_default_confname();
|
|
|
|
if (conf_read(defconfig_file)) {
|
2018-02-06 08:34:41 +08:00
|
|
|
fprintf(stderr,
|
|
|
|
_("***\n"
|
|
|
|
"*** Can't find default configuration \"%s\"!\n"
|
|
|
|
"***\n"),
|
|
|
|
defconfig_file);
|
2005-04-17 06:20:36 +08:00
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
break;
|
2010-08-01 05:35:34 +08:00
|
|
|
case savedefconfig:
|
2018-03-01 14:34:37 +08:00
|
|
|
case syncconfig:
|
2010-08-01 05:35:26 +08:00
|
|
|
case oldaskconfig:
|
|
|
|
case oldconfig:
|
2010-08-01 05:35:28 +08:00
|
|
|
case listnewconfig:
|
2012-09-01 01:05:17 +08:00
|
|
|
case olddefconfig:
|
2005-04-17 06:20:36 +08:00
|
|
|
conf_read(NULL);
|
|
|
|
break;
|
2010-08-01 05:35:26 +08:00
|
|
|
case allnoconfig:
|
|
|
|
case allyesconfig:
|
|
|
|
case allmodconfig:
|
2010-08-01 05:35:31 +08:00
|
|
|
case alldefconfig:
|
2010-08-01 05:35:26 +08:00
|
|
|
case randconfig:
|
2005-11-09 13:34:49 +08:00
|
|
|
name = getenv("KCONFIG_ALLCONFIG");
|
2012-05-07 20:37:45 +08:00
|
|
|
if (!name)
|
|
|
|
break;
|
|
|
|
if ((strcmp(name, "") != 0) && (strcmp(name, "1") != 0)) {
|
2012-04-26 16:51:32 +08:00
|
|
|
if (conf_read_simple(name, S_DEF_USER)) {
|
|
|
|
fprintf(stderr,
|
|
|
|
_("*** Can't read seed configuration \"%s\"!\n"),
|
|
|
|
name);
|
|
|
|
exit(1);
|
|
|
|
}
|
2005-11-09 13:34:49 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
switch (input_mode) {
|
2010-08-01 05:35:26 +08:00
|
|
|
case allnoconfig: name = "allno.config"; break;
|
|
|
|
case allyesconfig: name = "allyes.config"; break;
|
|
|
|
case allmodconfig: name = "allmod.config"; break;
|
2010-08-01 05:35:31 +08:00
|
|
|
case alldefconfig: name = "alldef.config"; break;
|
2010-08-01 05:35:26 +08:00
|
|
|
case randconfig: name = "allrandom.config"; break;
|
2005-11-09 13:34:49 +08:00
|
|
|
default: break;
|
|
|
|
}
|
2012-04-26 16:51:32 +08:00
|
|
|
if (conf_read_simple(name, S_DEF_USER) &&
|
|
|
|
conf_read_simple("all.config", S_DEF_USER)) {
|
|
|
|
fprintf(stderr,
|
|
|
|
_("*** KCONFIG_ALLCONFIG set, but no \"%s\" or \"all.config\" file found\n"),
|
|
|
|
name);
|
|
|
|
exit(1);
|
|
|
|
}
|
2005-11-09 13:34:49 +08:00
|
|
|
break;
|
2005-04-17 06:20:36 +08:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2008-09-29 11:27:10 +08:00
|
|
|
|
|
|
|
if (sync_kconfig) {
|
|
|
|
if (conf_get_changed()) {
|
|
|
|
name = getenv("KCONFIG_NOSILENTUPDATE");
|
|
|
|
if (name && *name) {
|
|
|
|
fprintf(stderr,
|
2010-08-15 11:51:40 +08:00
|
|
|
_("\n*** The configuration requires explicit update.\n\n"));
|
2008-09-29 11:27:10 +08:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-07-01 04:45:38 +08:00
|
|
|
switch (input_mode) {
|
2010-08-01 05:35:26 +08:00
|
|
|
case allnoconfig:
|
2008-07-01 04:45:38 +08:00
|
|
|
conf_set_all_new_symbols(def_no);
|
|
|
|
break;
|
2010-08-01 05:35:26 +08:00
|
|
|
case allyesconfig:
|
2008-07-01 04:45:38 +08:00
|
|
|
conf_set_all_new_symbols(def_yes);
|
|
|
|
break;
|
2010-08-01 05:35:26 +08:00
|
|
|
case allmodconfig:
|
2008-07-01 04:45:38 +08:00
|
|
|
conf_set_all_new_symbols(def_mod);
|
|
|
|
break;
|
2010-08-01 05:35:31 +08:00
|
|
|
case alldefconfig:
|
|
|
|
conf_set_all_new_symbols(def_default);
|
|
|
|
break;
|
2010-08-01 05:35:26 +08:00
|
|
|
case randconfig:
|
2013-04-29 04:36:38 +08:00
|
|
|
/* Really nothing to do in this loop */
|
|
|
|
while (conf_set_all_new_symbols(def_random)) ;
|
2008-07-01 04:45:38 +08:00
|
|
|
break;
|
2010-08-01 05:35:26 +08:00
|
|
|
case defconfig:
|
2008-07-01 05:02:59 +08:00
|
|
|
conf_set_all_new_symbols(def_default);
|
|
|
|
break;
|
2010-08-01 05:35:34 +08:00
|
|
|
case savedefconfig:
|
|
|
|
break;
|
2010-08-01 05:35:26 +08:00
|
|
|
case oldaskconfig:
|
2008-09-29 11:27:10 +08:00
|
|
|
rootEntry = &rootmenu;
|
|
|
|
conf(&rootmenu);
|
kconfig: hide irrelevant sub-menus for oldconfig
Historically, "make oldconfig" has changed its behavior several times,
quieter or louder. (I attached the history below.) Currently, it is
not as quiet as it should be. This commit addresses it.
Test Case
---------
---------------------------(Kconfig)----------------------------
menu "menu"
config FOO
bool "foo"
menu "sub menu"
config BAR
bool "bar"
endmenu
endmenu
menu "sibling menu"
config BAZ
bool "baz"
endmenu
----------------------------------------------------------------
---------------------------(.config)----------------------------
CONFIG_BAR=y
CONFIG_BAZ=y
----------------------------------------------------------------
With the Kconfig and .config above, "make silentoldconfig" and
"make oldconfig" work differently, like follows:
$ make silentoldconfig
scripts/kconfig/conf --silentoldconfig Kconfig
*
* Restart config...
*
*
* menu
*
foo (FOO) [N/y/?] (NEW) y
#
# configuration written to .config
#
$ make oldconfig
scripts/kconfig/conf --oldconfig Kconfig
*
* Restart config...
*
*
* menu
*
foo (FOO) [N/y/?] (NEW) y
*
* sub menu
*
bar (BAR) [Y/n/?] y
#
# configuration written to .config
#
Both hide "sibling node" since it is irrelevant. The difference is
that silentoldconfig hides "sub menu" whereas oldconfig does not.
The behavior of silentoldconfig is preferred since the "sub menu"
does not contain any new symbol.
The root cause is in conf(). There are three input modes that can
call conf(); oldaskconfig, oldconfig, and silentoldconfig.
Everytime conf() encounters a menu entry, it calls check_conf() to
check if it contains new symbols. If no new symbol is found, the
menu is just skipped.
Currently, this happens only when input_mode == silentoldconfig.
The oldaskconfig enters into the check_conf() loop as silentoldconfig,
so oldaskconfig works likewise for the second loop or later, but it
never happens for oldconfig. So, irrelevant sub-menus are shown for
oldconfig.
Change the test condition to "input_mode != oldaskconfig". This is
false only for the first loop of oldaskconfig; it must ask the user
all symbols, so no need to call check_conf().
History of oldconfig
--------------------
[0] Originally, "make oldconfig" was as loud as "make config" (It
showed the entire .config file)
[1] Commit cd9140e1e73a ("kconfig: make oldconfig is now less chatty")
made oldconfig quieter, but it was still less quieter than
silentoldconfig. (oldconfig did not hide sub-menus)
[2] Commit 204c96f60904 ("kconfig: fix silentoldconfig") changed
the input_mode of oldconfig to "ask_silent" from "ask_new".
So, oldconfig really became as quiet as silentoldconfig.
(oldconfig hided irrelevant sub-menus)
[3] Commit 4062f1a4c030 ("kconfig: use long options in conf") made
oldconfig as loud as [0] due to misconversion.
[4] Commit 14828349719a ("kconfig: fix make oldconfig") addressed
the misconversion of [3], but it made oldconfig quieter only to
the same level as [1], not [2].
This commit is restoring the behavior of [2].
Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
Reviewed-by: Ulf Magnusson <ulfalizer@gmail.com>
2018-02-28 08:15:24 +08:00
|
|
|
input_mode = oldconfig;
|
2008-09-29 11:27:10 +08:00
|
|
|
/* fall through */
|
2010-08-06 13:13:54 +08:00
|
|
|
case oldconfig:
|
2010-08-01 05:35:28 +08:00
|
|
|
case listnewconfig:
|
2018-03-01 14:34:37 +08:00
|
|
|
case syncconfig:
|
2008-09-29 11:27:10 +08:00
|
|
|
/* Update until a loop caused no more changes */
|
|
|
|
do {
|
|
|
|
conf_cnt = 0;
|
|
|
|
check_conf(&rootmenu);
|
2018-02-28 08:15:23 +08:00
|
|
|
} while (conf_cnt);
|
2018-02-28 08:15:21 +08:00
|
|
|
break;
|
|
|
|
case olddefconfig:
|
|
|
|
default:
|
2008-07-01 04:45:38 +08:00
|
|
|
break;
|
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2008-09-29 11:27:10 +08:00
|
|
|
if (sync_kconfig) {
|
2018-03-01 14:34:37 +08:00
|
|
|
/* syncconfig is used during the build so we shall update autoconf.
|
2008-09-29 11:27:10 +08:00
|
|
|
* All other commands are only used to generate a config.
|
|
|
|
*/
|
|
|
|
if (conf_get_changed() && conf_write(NULL)) {
|
2010-08-15 11:51:40 +08:00
|
|
|
fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n"));
|
2008-09-29 11:27:10 +08:00
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
if (conf_write_autoconf()) {
|
2010-08-15 11:51:40 +08:00
|
|
|
fprintf(stderr, _("\n*** Error during update of the configuration.\n\n"));
|
2008-09-29 11:27:10 +08:00
|
|
|
return 1;
|
|
|
|
}
|
2010-08-01 05:35:34 +08:00
|
|
|
} else if (input_mode == savedefconfig) {
|
|
|
|
if (conf_write_defconfig(defconfig_file)) {
|
|
|
|
fprintf(stderr, _("n*** Error while saving defconfig to: %s\n\n"),
|
2014-06-10 18:08:13 +08:00
|
|
|
defconfig_file);
|
2010-08-01 05:35:34 +08:00
|
|
|
return 1;
|
|
|
|
}
|
2010-08-01 05:35:28 +08:00
|
|
|
} else if (input_mode != listnewconfig) {
|
2008-09-29 11:27:10 +08:00
|
|
|
if (conf_write(NULL)) {
|
2010-08-15 11:51:40 +08:00
|
|
|
fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n"));
|
2008-09-29 11:27:10 +08:00
|
|
|
exit(1);
|
|
|
|
}
|
2006-06-09 13:12:39 +08:00
|
|
|
}
|
2010-08-01 05:35:28 +08:00
|
|
|
return 0;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|