6840999b19
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>
630 lines
12 KiB
C
630 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;
|
|
}
|