yann@1: /* yann@1: * Copyright (C) 2002 Roman Zippel yann@1: * Released under the terms of the GNU GPL v2.0. yann@1: */ yann@1: yann@943: #include yann@1: #include yann@943: #include yann@1: #include yann@1: #include yann@943: #include yann@1: #include yann@1: #include yann@1: yann@1: #define LKC_DIRECT_LINK yann@1: #include "lkc.h" yann@1: yann@1: static void conf(struct menu *menu); yann@1: static void check_conf(struct menu *menu); yann@1: yann@1: enum { yann@1: ask_all, yann@1: ask_new, yann@1: ask_silent, yann@1: set_default, yann@1: set_yes, yann@1: set_mod, yann@1: set_no, yann@1: set_random yann@1: } input_mode = ask_all; yann@1: char *defconfig_file; yann@1: yann@1: static int indent = 1; yann@1: static int valid_stdin = 1; yann@943: static int sync_kconfig; yann@1: static int conf_cnt; yann@1: static char line[128]; yann@1: static struct menu *rootEntry; yann@1: yann@1: static char nohelp_text[] = N_("Sorry, no help available for this option yet.\n"); yann@1: yann@943: static const char *get_help(struct menu *menu) yann@943: { yann@943: if (menu_has_help(menu)) yann@943: return _(menu_get_help(menu)); yann@943: else yann@943: return nohelp_text; yann@943: } yann@943: yann@1: static void strip(char *str) yann@1: { yann@1: char *p = str; yann@1: int l; yann@1: yann@1: while ((isspace(*p))) yann@1: p++; yann@1: l = strlen(p); yann@1: if (p != str) yann@1: memmove(str, p, l + 1); yann@1: if (!l) yann@1: return; yann@1: p = str + l - 1; yann@1: while ((isspace(*p))) yann@1: *p-- = 0; yann@1: } yann@1: yann@1: static void check_stdin(void) yann@1: { yann@943: if (!valid_stdin) { yann@1: printf(_("aborted!\n\n")); yann@1: printf(_("Console input/output is redirected. ")); yann@1: printf(_("Run 'make oldconfig' to update configuration.\n\n")); yann@1: exit(1); yann@1: } yann@1: } yann@1: yann@943: static int conf_askvalue(struct symbol *sym, const char *def) yann@1: { yann@1: enum symbol_type type = sym_get_type(sym); yann@1: yann@1: if (!sym_has_value(sym)) yann@943: printf(_("(NEW) ")); yann@1: yann@1: line[0] = '\n'; yann@1: line[1] = 0; yann@1: yann@1: if (!sym_is_changable(sym)) { yann@1: printf("%s\n", def); yann@1: line[0] = '\n'; yann@1: line[1] = 0; yann@943: return 0; yann@1: } yann@1: yann@1: switch (input_mode) { yann@1: case ask_new: yann@1: case ask_silent: yann@1: if (sym_has_value(sym)) { yann@1: printf("%s\n", def); yann@943: return 0; yann@1: } yann@1: check_stdin(); yann@1: case ask_all: yann@1: fflush(stdout); yann@1: fgets(line, 128, stdin); yann@943: return 1; yann@1: default: yann@1: break; yann@1: } yann@1: yann@1: switch (type) { yann@1: case S_INT: yann@1: case S_HEX: yann@1: case S_STRING: yann@1: printf("%s\n", def); yann@943: return 1; yann@1: default: yann@1: ; yann@1: } yann@1: printf("%s", line); yann@943: return 1; yann@1: } yann@1: yann@1: int conf_string(struct menu *menu) yann@1: { yann@1: struct symbol *sym = menu->sym; yann@943: const char *def; yann@1: yann@1: while (1) { yann@943: printf("%*s%s ", indent - 1, "", _(menu->prompt->text)); yann@1: printf("(%s) ", sym->name); yann@1: def = sym_get_string_value(sym); yann@1: if (sym_get_string_value(sym)) yann@1: printf("[%s] ", def); yann@943: if (!conf_askvalue(sym, def)) yann@943: return 0; yann@1: switch (line[0]) { yann@1: case '\n': yann@1: break; yann@1: case '?': yann@1: /* print help */ yann@1: if (line[1] == '\n') { yann@943: printf("\n%s\n", get_help(menu)); yann@1: def = NULL; yann@1: break; yann@1: } yann@1: default: yann@1: line[strlen(line)-1] = 0; yann@1: def = line; yann@1: } yann@1: if (def && sym_set_string_value(sym, def)) yann@1: return 0; yann@1: } yann@1: } yann@1: yann@1: static int conf_sym(struct menu *menu) yann@1: { yann@1: struct symbol *sym = menu->sym; yann@1: int type; yann@1: tristate oldval, newval; yann@1: yann@1: while (1) { yann@943: printf("%*s%s ", indent - 1, "", _(menu->prompt->text)); yann@1: if (sym->name) yann@1: printf("(%s) ", sym->name); yann@1: type = sym_get_type(sym); yann@1: putchar('['); yann@1: oldval = sym_get_tristate_value(sym); yann@1: switch (oldval) { yann@1: case no: yann@1: putchar('N'); yann@1: break; yann@1: case mod: yann@1: putchar('M'); yann@1: break; yann@1: case yes: yann@1: putchar('Y'); yann@1: break; yann@1: } yann@1: if (oldval != no && sym_tristate_within_range(sym, no)) yann@1: printf("/n"); yann@1: if (oldval != mod && sym_tristate_within_range(sym, mod)) yann@1: printf("/m"); yann@1: if (oldval != yes && sym_tristate_within_range(sym, yes)) yann@1: printf("/y"); yann@943: if (menu_has_help(menu)) yann@1: printf("/?"); yann@1: printf("] "); yann@943: if (!conf_askvalue(sym, sym_get_string_value(sym))) yann@943: return 0; yann@1: strip(line); yann@1: yann@1: switch (line[0]) { yann@1: case 'n': yann@1: case 'N': yann@1: newval = no; yann@1: if (!line[1] || !strcmp(&line[1], "o")) yann@1: break; yann@1: continue; yann@1: case 'm': yann@1: case 'M': yann@1: newval = mod; yann@1: if (!line[1]) yann@1: break; yann@1: continue; yann@1: case 'y': yann@1: case 'Y': yann@1: newval = yes; yann@1: if (!line[1] || !strcmp(&line[1], "es")) yann@1: break; yann@1: continue; yann@1: case 0: yann@1: newval = oldval; yann@1: break; yann@1: case '?': yann@1: goto help; yann@1: default: yann@1: continue; yann@1: } yann@1: if (sym_set_tristate_value(sym, newval)) yann@1: return 0; yann@1: help: yann@943: printf("\n%s\n", get_help(menu)); yann@1: } yann@1: } yann@1: yann@1: static int conf_choice(struct menu *menu) yann@1: { yann@1: struct symbol *sym, *def_sym; yann@1: struct menu *child; yann@1: int type; yann@1: bool is_new; yann@1: yann@1: sym = menu->sym; yann@1: type = sym_get_type(sym); yann@1: is_new = !sym_has_value(sym); yann@1: if (sym_is_changable(sym)) { yann@1: conf_sym(menu); yann@1: sym_calc_value(sym); yann@1: switch (sym_get_tristate_value(sym)) { yann@1: case no: yann@1: return 1; yann@1: case mod: yann@1: return 0; yann@1: case yes: yann@1: break; yann@1: } yann@1: } else { yann@1: switch (sym_get_tristate_value(sym)) { yann@1: case no: yann@1: return 1; yann@1: case mod: yann@943: printf("%*s%s\n", indent - 1, "", _(menu_get_prompt(menu))); yann@1: return 0; yann@1: case yes: yann@1: break; yann@1: } yann@1: } yann@1: yann@1: while (1) { yann@1: int cnt, def; yann@1: yann@943: printf("%*s%s\n", indent - 1, "", _(menu_get_prompt(menu))); yann@1: def_sym = sym_get_choice_value(sym); yann@1: cnt = def = 0; yann@1: line[0] = 0; yann@1: for (child = menu->list; child; child = child->next) { yann@1: if (!menu_is_visible(child)) yann@1: continue; yann@1: if (!child->sym) { yann@943: printf("%*c %s\n", indent, '*', _(menu_get_prompt(child))); yann@1: continue; yann@1: } yann@1: cnt++; yann@1: if (child->sym == def_sym) { yann@1: def = cnt; yann@1: printf("%*c", indent, '>'); yann@1: } else yann@1: printf("%*c", indent, ' '); yann@943: printf(" %d. %s", cnt, _(menu_get_prompt(child))); yann@1: if (child->sym->name) yann@1: printf(" (%s)", child->sym->name); yann@1: if (!sym_has_value(child->sym)) yann@943: printf(_(" (NEW)")); yann@1: printf("\n"); yann@1: } yann@943: printf(_("%*schoice"), indent - 1, ""); yann@1: if (cnt == 1) { yann@1: printf("[1]: 1\n"); yann@1: goto conf_childs; yann@1: } yann@1: printf("[1-%d", cnt); yann@943: if (menu_has_help(menu)) yann@1: printf("?"); yann@1: printf("]: "); yann@1: switch (input_mode) { yann@1: case ask_new: yann@1: case ask_silent: yann@1: if (!is_new) { yann@1: cnt = def; yann@1: printf("%d\n", cnt); yann@1: break; yann@1: } yann@1: check_stdin(); yann@1: case ask_all: yann@1: fflush(stdout); yann@1: fgets(line, 128, stdin); yann@1: strip(line); yann@1: if (line[0] == '?') { yann@943: printf("\n%s\n", get_help(menu)); yann@1: continue; yann@1: } yann@1: if (!line[0]) yann@1: cnt = def; yann@1: else if (isdigit(line[0])) yann@1: cnt = atoi(line); yann@1: else yann@1: continue; yann@1: break; yann@943: default: yann@1: break; yann@1: } yann@1: yann@1: conf_childs: yann@1: for (child = menu->list; child; child = child->next) { yann@1: if (!child->sym || !menu_is_visible(child)) yann@1: continue; yann@1: if (!--cnt) yann@1: break; yann@1: } yann@1: if (!child) yann@1: continue; yann@1: if (line[strlen(line) - 1] == '?') { yann@943: printf("\n%s\n", get_help(child)); yann@1: continue; yann@1: } yann@1: sym_set_choice_value(sym, child->sym); yann@943: for (child = child->list; child; child = child->next) { yann@1: indent += 2; yann@943: conf(child); yann@1: indent -= 2; yann@1: } yann@1: return 1; yann@1: } yann@1: } yann@1: yann@1: static void conf(struct menu *menu) yann@1: { yann@1: struct symbol *sym; yann@1: struct property *prop; yann@1: struct menu *child; yann@1: yann@1: if (!menu_is_visible(menu)) yann@1: return; yann@1: yann@1: sym = menu->sym; yann@1: prop = menu->prompt; yann@1: if (prop) { yann@1: const char *prompt; yann@1: yann@1: switch (prop->type) { yann@1: case P_MENU: yann@1: if (input_mode == ask_silent && rootEntry != menu) { yann@1: check_conf(menu); yann@1: return; yann@1: } yann@1: case P_COMMENT: yann@1: prompt = menu_get_prompt(menu); yann@1: if (prompt) yann@1: printf("%*c\n%*c %s\n%*c\n", yann@1: indent, '*', yann@943: indent, '*', _(prompt), yann@1: indent, '*'); yann@1: default: yann@1: ; yann@1: } yann@1: } yann@1: yann@1: if (!sym) yann@1: goto conf_childs; yann@1: yann@1: if (sym_is_choice(sym)) { yann@1: conf_choice(menu); yann@1: if (sym->curr.tri != mod) yann@1: return; yann@1: goto conf_childs; yann@1: } yann@1: yann@1: switch (sym->type) { yann@1: case S_INT: yann@1: case S_HEX: yann@1: case S_STRING: yann@1: conf_string(menu); yann@1: break; yann@1: default: yann@1: conf_sym(menu); yann@1: break; yann@1: } yann@1: yann@1: conf_childs: yann@1: if (sym) yann@1: indent += 2; yann@1: for (child = menu->list; child; child = child->next) yann@1: conf(child); yann@1: if (sym) yann@1: indent -= 2; yann@1: } yann@1: yann@1: static void check_conf(struct menu *menu) yann@1: { yann@1: struct symbol *sym; yann@1: struct menu *child; yann@1: yann@1: if (!menu_is_visible(menu)) yann@1: return; yann@1: yann@1: sym = menu->sym; yann@1: if (sym && !sym_has_value(sym)) { yann@1: if (sym_is_changable(sym) || yann@1: (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)) { yann@1: if (!conf_cnt++) yann@1: printf(_("*\n* Restart config...\n*\n")); yann@1: rootEntry = menu_get_parent_menu(menu); yann@1: conf(rootEntry); yann@1: } yann@1: } yann@1: yann@1: for (child = menu->list; child; child = child->next) yann@1: check_conf(child); yann@1: } yann@1: yann@1: int main(int ac, char **av) yann@1: { yann@943: int opt; yann@1: const char *name; yann@1: struct stat tmpstat; yann@1: yann@943: setlocale(LC_ALL, ""); yann@943: bindtextdomain(PACKAGE, LOCALEDIR); yann@943: textdomain(PACKAGE); yann@943: yann@943: while ((opt = getopt(ac, av, "osdD:nmyrh")) != -1) { yann@943: switch (opt) { yann@1: case 'o': yann@943: input_mode = ask_silent; yann@1: break; yann@1: case 's': yann@1: input_mode = ask_silent; yann@943: sync_kconfig = 1; yann@1: break; yann@1: case 'd': yann@1: input_mode = set_default; yann@1: break; yann@1: case 'D': yann@1: input_mode = set_default; yann@943: defconfig_file = optarg; yann@1: break; yann@1: case 'n': yann@1: input_mode = set_no; yann@1: break; yann@1: case 'm': yann@1: input_mode = set_mod; yann@1: break; yann@1: case 'y': yann@1: input_mode = set_yes; yann@1: break; yann@1: case 'r': yann@1: input_mode = set_random; yann@943: srand(time(NULL)); yann@1: break; yann@1: case 'h': yann@943: printf(_("See README for usage info\n")); yann@1: exit(0); yann@943: break; yann@943: default: yann@943: fprintf(stderr, _("See README for usage info\n")); yann@943: exit(1); yann@1: } yann@1: } yann@943: if (ac == optind) { yann@1: printf(_("%s: Kconfig file missing\n"), av[0]); yann@1: exit(1); yann@1: } yann@943: name = av[optind]; yann@1: conf_parse(name); yann@1: //zconfdump(stdout); yann@943: if (sync_kconfig) { yann@943: if (stat(".config", &tmpstat)) { yann@943: fprintf(stderr, _("***\n" yann@943: "*** Please run some configurator (e.g. \"make menuconfig\").\n" yann@943: "***\n")); yann@943: exit(1); yann@943: } yann@943: } yann@943: yann@1: switch (input_mode) { yann@1: case set_default: yann@1: if (!defconfig_file) yann@1: defconfig_file = conf_get_default_confname(); yann@1: if (conf_read(defconfig_file)) { yann@943: printf(_("***\n" yann@1: "*** Can't find default configuration \"%s\"!\n" yann@943: "***\n"), defconfig_file); yann@1: exit(1); yann@1: } yann@1: break; yann@1: case ask_silent: yann@1: case ask_all: yann@1: case ask_new: yann@1: conf_read(NULL); yann@1: break; yann@1: case set_no: yann@1: case set_mod: yann@1: case set_yes: yann@1: case set_random: yann@1: name = getenv("KCONFIG_ALLCONFIG"); yann@1: if (name && !stat(name, &tmpstat)) { yann@1: conf_read_simple(name, S_DEF_USER); yann@1: break; yann@1: } yann@1: switch (input_mode) { yann@1: case set_no: name = "allno.config"; break; yann@1: case set_mod: name = "allmod.config"; break; yann@1: case set_yes: name = "allyes.config"; break; yann@1: case set_random: name = "allrandom.config"; break; yann@1: default: break; yann@1: } yann@1: if (!stat(name, &tmpstat)) yann@1: conf_read_simple(name, S_DEF_USER); yann@1: else if (!stat("all.config", &tmpstat)) yann@1: conf_read_simple("all.config", S_DEF_USER); yann@1: break; yann@1: default: yann@1: break; yann@1: } yann@1: yann@943: if (sync_kconfig) { yann@943: if (conf_get_changed()) { yann@943: name = getenv("KCONFIG_NOSILENTUPDATE"); yann@943: if (name && *name) { yann@943: fprintf(stderr, yann@943: _("\n*** Configuration requires explicit update.\n\n")); yann@943: return 1; yann@943: } yann@943: } yann@943: valid_stdin = isatty(0) && isatty(1) && isatty(2); yann@943: } yann@943: yann@943: switch (input_mode) { yann@943: case set_no: yann@943: conf_set_all_new_symbols(def_no); yann@943: break; yann@943: case set_yes: yann@943: conf_set_all_new_symbols(def_yes); yann@943: break; yann@943: case set_mod: yann@943: conf_set_all_new_symbols(def_mod); yann@943: break; yann@943: case set_random: yann@943: conf_set_all_new_symbols(def_random); yann@943: break; yann@943: case set_default: yann@943: conf_set_all_new_symbols(def_default); yann@943: break; yann@943: case ask_new: yann@943: case ask_all: yann@1: rootEntry = &rootmenu; yann@1: conf(&rootmenu); yann@943: input_mode = ask_silent; yann@943: /* fall through */ yann@943: case ask_silent: yann@943: /* Update until a loop caused no more changes */ yann@943: do { yann@943: conf_cnt = 0; yann@943: check_conf(&rootmenu); yann@943: } while (conf_cnt); yann@943: break; yann@943: } yann@943: yann@943: if (sync_kconfig) { yann@943: /* silentoldconfig is used during the build so we shall update autoconf. yann@943: * All other commands are only used to generate a config. yann@943: */ yann@943: if (conf_get_changed() && conf_write(NULL)) { yann@943: fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n")); yann@943: exit(1); yann@1: } yann@943: } else { yann@943: if (conf_write(NULL)) { yann@943: fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n")); yann@943: exit(1); yann@1: } yann@39: } yann@39: return 0; yann@1: }