linux/scripts/kconfig/conf.c
Sam Ravnborg 6840999b19 x86: simplify "make ARCH=x86" and fix kconfig all.config
Simplify "make ARCH=x86" and fix kconfig so we again can set 64BIT in
all.config.

For a fix the diffstat is nice:
 6 files changed, 3 insertions(+), 36 deletions(-)

The patch reverts these commits:
 - 0f855aa64b ("kconfig: add helper to set
   config symbol from environment variable")
 - 2a113281f5 ("kconfig: use $K64BIT to
   set 64BIT with all*config targets")

Roman Zippel pointed out that kconfig supported string compares so
the additional complexity introduced by the above two patches were
not needed.

With this patch we have following behaviour:

  # make {allno,allyes,allmod,rand}config [ARCH=...]
  option \ host arch      | 32bit         | 64bit
  =====================================================
  ./.                     | 32bit         | 64bit
  ARCH=x86                | 32bit         | 32bit
  ARCH=i386               | 32bit         | 32bit
  ARCH=x86_64             | 64bit         | 64bit

The general rule are that ARCH= and native architecture takes
precedence over the configuration.

So make ARCH=i386 [whatever] will always build a 32-bit kernel
no matter what the configuration says.  The configuration will
be updated to 32-bit if it was configured to 64-bit and the
other way around.

This behaviour is consistent with previous behaviour so no
suprises here.

make ARCH=x86 will per default result in a 32-bit kernel but as
the only ARCH= value x86 allow the user to select between 32-bit
and 64-bit using menuconfig.

Signed-off-by: Sam Ravnborg <sam@ravnborg.org>
Cc: Roman Zippel <zippel@linux-m68k.org>
Cc: Andreas Herrmann <aherrman@arcor.de>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2007-11-17 08:35:43 -08:00

631 lines
12 KiB
C

/*
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
* Released under the terms of the GNU GPL v2.0.
*/
#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <sys/stat.h>
#define LKC_DIRECT_LINK
#include "lkc.h"
static void conf(struct menu *menu);
static void check_conf(struct menu *menu);
enum {
ask_all,
ask_new,
ask_silent,
set_default,
set_yes,
set_mod,
set_no,
set_random
} input_mode = ask_all;
char *defconfig_file;
static int indent = 1;
static int valid_stdin = 1;
static int conf_cnt;
static char line[128];
static struct menu *rootEntry;
static char nohelp_text[] = N_("Sorry, no help available for this option yet.\n");
static const char *get_help(struct menu *menu)
{
if (menu_has_help(menu))
return menu_get_help(menu);
else
return nohelp_text;
}
static void strip(char *str)
{
char *p = str;
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;
}
static void check_stdin(void)
{
if (!valid_stdin && input_mode == ask_silent) {
printf(_("aborted!\n\n"));
printf(_("Console input/output is redirected. "));
printf(_("Run 'make oldconfig' to update configuration.\n\n"));
exit(1);
}
}
static int conf_askvalue(struct symbol *sym, const char *def)
{
enum symbol_type type = sym_get_type(sym);
tristate val;
if (!sym_has_value(sym))
printf("(NEW) ");
line[0] = '\n';
line[1] = 0;
if (!sym_is_changable(sym)) {
printf("%s\n", def);
line[0] = '\n';
line[1] = 0;
return 0;
}
switch (input_mode) {
case set_no:
case set_mod:
case set_yes:
case set_random:
if (sym_has_value(sym)) {
printf("%s\n", def);
return 0;
}
break;
case ask_new:
case ask_silent:
if (sym_has_value(sym)) {
printf("%s\n", def);
return 0;
}
check_stdin();
case ask_all:
fflush(stdout);
fgets(line, 128, stdin);
return 1;
case set_default:
printf("%s\n", def);
return 1;
default:
break;
}
switch (type) {
case S_INT:
case S_HEX:
case S_STRING:
printf("%s\n", def);
return 1;
default:
;
}
switch (input_mode) {
case set_yes:
if (sym_tristate_within_range(sym, yes)) {
line[0] = 'y';
line[1] = '\n';
line[2] = 0;
break;
}
case set_mod:
if (type == S_TRISTATE) {
if (sym_tristate_within_range(sym, mod)) {
line[0] = 'm';
line[1] = '\n';
line[2] = 0;
break;
}
} else {
if (sym_tristate_within_range(sym, yes)) {
line[0] = 'y';
line[1] = '\n';
line[2] = 0;
break;
}
}
case set_no:
if (sym_tristate_within_range(sym, no)) {
line[0] = 'n';
line[1] = '\n';
line[2] = 0;
break;
}
case set_random:
do {
val = (tristate)(random() % 3);
} while (!sym_tristate_within_range(sym, val));
switch (val) {
case no: line[0] = 'n'; break;
case mod: line[0] = 'm'; break;
case yes: line[0] = 'y'; break;
}
line[1] = '\n';
line[2] = 0;
break;
default:
break;
}
printf("%s", line);
return 1;
}
int conf_string(struct menu *menu)
{
struct symbol *sym = menu->sym;
const char *def;
while (1) {
printf("%*s%s ", indent - 1, "", menu->prompt->text);
printf("(%s) ", sym->name);
def = sym_get_string_value(sym);
if (sym_get_string_value(sym))
printf("[%s] ", def);
if (!conf_askvalue(sym, def))
return 0;
switch (line[0]) {
case '\n':
break;
case '?':
/* print help */
if (line[1] == '\n') {
printf("\n%s\n", get_help(menu));
def = NULL;
break;
}
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;
int type;
tristate oldval, newval;
while (1) {
printf("%*s%s ", indent - 1, "", menu->prompt->text);
if (sym->name)
printf("(%s) ", sym->name);
type = sym_get_type(sym);
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");
if (menu_has_help(menu))
printf("/?");
printf("] ");
if (!conf_askvalue(sym, sym_get_string_value(sym)))
return 0;
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:
printf("\n%s\n", get_help(menu));
}
}
static int conf_choice(struct menu *menu)
{
struct symbol *sym, *def_sym;
struct menu *child;
int type;
bool is_new;
sym = menu->sym;
type = sym_get_type(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:
printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu));
return 0;
case yes:
break;
}
}
while (1) {
int cnt, def;
printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu));
def_sym = sym_get_choice_value(sym);
cnt = def = 0;
line[0] = 0;
for (child = menu->list; child; child = child->next) {
if (!menu_is_visible(child))
continue;
if (!child->sym) {
printf("%*c %s\n", indent, '*', menu_get_prompt(child));
continue;
}
cnt++;
if (child->sym == def_sym) {
def = cnt;
printf("%*c", indent, '>');
} else
printf("%*c", indent, ' ');
printf(" %d. %s", cnt, menu_get_prompt(child));
if (child->sym->name)
printf(" (%s)", child->sym->name);
if (!sym_has_value(child->sym))
printf(" (NEW)");
printf("\n");
}
printf("%*schoice", indent - 1, "");
if (cnt == 1) {
printf("[1]: 1\n");
goto conf_childs;
}
printf("[1-%d", cnt);
if (menu_has_help(menu))
printf("?");
printf("]: ");
switch (input_mode) {
case ask_new:
case ask_silent:
if (!is_new) {
cnt = def;
printf("%d\n", cnt);
break;
}
check_stdin();
case ask_all:
fflush(stdout);
fgets(line, 128, stdin);
strip(line);
if (line[0] == '?') {
printf("\n%s\n", get_help(menu));
continue;
}
if (!line[0])
cnt = def;
else if (isdigit(line[0]))
cnt = atoi(line);
else
continue;
break;
case set_random:
def = (random() % cnt) + 1;
case set_default:
case set_yes:
case set_mod:
case set_no:
cnt = def;
printf("%d\n", cnt);
break;
}
conf_childs:
for (child = menu->list; child; child = child->next) {
if (!child->sym || !menu_is_visible(child))
continue;
if (!--cnt)
break;
}
if (!child)
continue;
if (line[strlen(line) - 1] == '?') {
printf("\n%s\n", get_help(child));
continue;
}
sym_set_choice_value(sym, child->sym);
if (child->list) {
indent += 2;
conf(child->list);
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:
if (input_mode == ask_silent && rootEntry != menu) {
check_conf(menu);
return;
}
case P_COMMENT:
prompt = menu_get_prompt(menu);
if (prompt)
printf("%*c\n%*c %s\n%*c\n",
indent, '*',
indent, '*', prompt,
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;
if (sym && !sym_has_value(sym)) {
if (sym_is_changable(sym) ||
(sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)) {
if (!conf_cnt++)
printf(_("*\n* Restart config...\n*\n"));
rootEntry = menu_get_parent_menu(menu);
conf(rootEntry);
}
}
for (child = menu->list; child; child = child->next)
check_conf(child);
}
int main(int ac, char **av)
{
int i = 1;
const char *name;
struct stat tmpstat;
if (ac > i && av[i][0] == '-') {
switch (av[i++][1]) {
case 'o':
input_mode = ask_new;
break;
case 's':
input_mode = ask_silent;
valid_stdin = isatty(0) && isatty(1) && isatty(2);
break;
case 'd':
input_mode = set_default;
break;
case 'D':
input_mode = set_default;
defconfig_file = av[i++];
if (!defconfig_file) {
printf(_("%s: No default config file specified\n"),
av[0]);
exit(1);
}
break;
case 'n':
input_mode = set_no;
break;
case 'm':
input_mode = set_mod;
break;
case 'y':
input_mode = set_yes;
break;
case 'r':
input_mode = set_random;
srandom(time(NULL));
break;
case 'h':
case '?':
fprintf(stderr, "See README for usage info\n");
exit(0);
}
}
name = av[i];
if (!name) {
printf(_("%s: Kconfig file missing\n"), av[0]);
exit(1);
}
conf_parse(name);
//zconfdump(stdout);
switch (input_mode) {
case set_default:
if (!defconfig_file)
defconfig_file = conf_get_default_confname();
if (conf_read(defconfig_file)) {
printf("***\n"
"*** Can't find default configuration \"%s\"!\n"
"***\n", defconfig_file);
exit(1);
}
break;
case ask_silent:
if (stat(".config", &tmpstat)) {
printf(_("***\n"
"*** You have not yet configured your kernel!\n"
"*** (missing kernel .config file)\n"
"***\n"
"*** Please run some configurator (e.g. \"make oldconfig\" or\n"
"*** \"make menuconfig\" or \"make xconfig\").\n"
"***\n"));
exit(1);
}
case ask_all:
case ask_new:
conf_read(NULL);
break;
case set_no:
case set_mod:
case set_yes:
case set_random:
name = getenv("KCONFIG_ALLCONFIG");
if (name && !stat(name, &tmpstat)) {
conf_read_simple(name, S_DEF_USER);
break;
}
switch (input_mode) {
case set_no: name = "allno.config"; break;
case set_mod: name = "allmod.config"; break;
case set_yes: name = "allyes.config"; break;
case set_random: name = "allrandom.config"; break;
default: break;
}
if (!stat(name, &tmpstat))
conf_read_simple(name, S_DEF_USER);
else if (!stat("all.config", &tmpstat))
conf_read_simple("all.config", S_DEF_USER);
break;
default:
break;
}
if (input_mode != ask_silent) {
rootEntry = &rootmenu;
conf(&rootmenu);
if (input_mode == ask_all) {
input_mode = ask_silent;
valid_stdin = 1;
}
} else if (conf_get_changed()) {
name = getenv("KCONFIG_NOSILENTUPDATE");
if (name && *name) {
fprintf(stderr, _("\n*** Kernel configuration requires explicit update.\n\n"));
return 1;
}
} else
goto skip_check;
do {
conf_cnt = 0;
check_conf(&rootmenu);
} while (conf_cnt);
if (conf_write(NULL)) {
fprintf(stderr, _("\n*** Error during writing of the kernel configuration.\n\n"));
return 1;
}
skip_check:
if (input_mode == ask_silent && conf_write_autoconf()) {
fprintf(stderr, _("\n*** Error during writing of the kernel configuration.\n\n"));
return 1;
}
return 0;
}