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@2448: #include yann@1: #include yann@2448: #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@2448: enum input_mode { yann@2448: oldaskconfig, yann@2448: silentoldconfig, yann@2448: oldconfig, yann@2448: allnoconfig, yann@2448: allyesconfig, yann@2448: allmodconfig, yann@2448: alldefconfig, yann@2448: randconfig, yann@2448: defconfig, yann@2448: savedefconfig, yann@2448: listnewconfig, yann@2448: oldnoconfig, yann@2448: } input_mode = oldaskconfig; yann@2448: 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@2448: static void print_help(struct menu *menu) yann@2448: { yann@2448: struct gstr help = str_new(); yann@1: yann@2448: menu_get_ext_help(menu, &help); yann@2448: yann@2448: printf("\n%s\n", str_get(&help)); yann@2448: str_free(&help); 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@1524: /* For crosstool-NG, we don't care if stdin/stdout got redirected. yann@1524: * In this case, just printf a cariage return, for pretty output. yann@1524: */ yann@1524: printf("\n"); 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@2448: case oldconfig: yann@2448: case silentoldconfig: yann@1: if (sym_has_value(sym)) { yann@1: printf("%s\n", def); yann@943: return 0; yann@1: } yann@1: check_stdin(); yann@2448: case oldaskconfig: yann@1: fflush(stdout); yann@2448: xfgets(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@2448: static 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@2448: print_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: 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: 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@2448: print_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: bool is_new; yann@1: yann@1: sym = menu->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@2448: case oldconfig: yann@2448: case silentoldconfig: 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@2448: case oldaskconfig: yann@1: fflush(stdout); yann@2448: xfgets(line, 128, stdin); yann@1: strip(line); yann@1: if (line[0] == '?') { yann@2448: print_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@2448: if (line[0] && line[strlen(line) - 1] == '?') { yann@2448: print_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@2448: if ((input_mode == silentoldconfig || yann@2448: input_mode == listnewconfig || yann@2448: input_mode == oldnoconfig) && yann@2448: 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@2448: if (input_mode == listnewconfig) { yann@2448: if (sym->name && !sym_is_choice_value(sym)) { yann@2448: printf("%s%s\n", CONFIG_, sym->name); yann@2448: } yann@2448: } else if (input_mode != oldnoconfig) { yann@2448: if (!conf_cnt++) yann@2448: printf(_("*\n* Restart config...\n*\n")); yann@2448: rootEntry = menu_get_parent_menu(menu); yann@2448: conf(rootEntry); yann@2448: } 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@2448: static struct option long_opts[] = { yann@2448: {"oldaskconfig", no_argument, NULL, oldaskconfig}, yann@2448: {"oldconfig", no_argument, NULL, oldconfig}, yann@2448: {"silentoldconfig", no_argument, NULL, silentoldconfig}, yann@2448: {"defconfig", optional_argument, NULL, defconfig}, yann@2448: {"savedefconfig", required_argument, NULL, savedefconfig}, yann@2448: {"allnoconfig", no_argument, NULL, allnoconfig}, yann@2448: {"allyesconfig", no_argument, NULL, allyesconfig}, yann@2448: {"allmodconfig", no_argument, NULL, allmodconfig}, yann@2448: {"alldefconfig", no_argument, NULL, alldefconfig}, yann@2448: {"randconfig", no_argument, NULL, randconfig}, yann@2448: {"listnewconfig", no_argument, NULL, listnewconfig}, yann@2448: {"oldnoconfig", no_argument, NULL, oldnoconfig}, yann@2448: {NULL, 0, NULL, 0} yann@2448: }; yann@2448: 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@2448: while ((opt = getopt_long(ac, av, "", long_opts, NULL)) != -1) { yann@2448: input_mode = (enum input_mode)opt; yann@943: switch (opt) { yann@2448: case silentoldconfig: yann@943: sync_kconfig = 1; yann@1: break; yann@2448: case defconfig: yann@2448: case savedefconfig: yann@943: defconfig_file = optarg; yann@1: break; yann@2448: case randconfig: yann@2448: { yann@2448: struct timeval now; yann@2448: unsigned int seed; yann@2448: yann@2448: /* yann@2448: * Use microseconds derived seed, yann@2448: * compensate for systems where it may be zero yann@2448: */ yann@2448: gettimeofday(&now, NULL); yann@2448: yann@2448: seed = (unsigned int)((now.tv_sec + 1) * (now.tv_usec + 1)); yann@2448: srand(seed); yann@1: break; yann@2448: } yann@2448: case '?': yann@943: fprintf(stderr, _("See README for usage info\n")); yann@943: exit(1); yann@2448: break; 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@2448: name = conf_get_configname(); yann@2448: if (stat(name, &tmpstat)) { yann@943: fprintf(stderr, _("***\n" yann@2448: "*** Configuration file \"%s\" not found!\n" yann@2448: "***\n" yann@2452: "*** Please configure with \"menuconfig\", or use a\n" yann@2452: "*** pre-existing sample (see list with \"list-samples\").\n" yann@2448: "***\n"), name); yann@943: exit(1); yann@943: } yann@943: } yann@943: yann@1: switch (input_mode) { yann@2448: case defconfig: 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@2448: case savedefconfig: yann@2448: case silentoldconfig: yann@2448: case oldaskconfig: yann@2448: case oldconfig: yann@2448: case listnewconfig: yann@2448: case oldnoconfig: yann@1: conf_read(NULL); yann@1: break; yann@2448: case allnoconfig: yann@2448: case allyesconfig: yann@2448: case allmodconfig: yann@2448: case alldefconfig: yann@2448: case randconfig: 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@2448: case allnoconfig: name = "allno.config"; break; yann@2448: case allyesconfig: name = "allyes.config"; break; yann@2448: case allmodconfig: name = "allmod.config"; break; yann@2448: case alldefconfig: name = "alldef.config"; break; yann@2448: case randconfig: 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@2448: _("\n*** The 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@2448: case allnoconfig: yann@943: conf_set_all_new_symbols(def_no); yann@943: break; yann@2448: case allyesconfig: yann@943: conf_set_all_new_symbols(def_yes); yann@943: break; yann@2448: case allmodconfig: yann@943: conf_set_all_new_symbols(def_mod); yann@943: break; yann@2448: case alldefconfig: yann@2448: conf_set_all_new_symbols(def_default); yann@2448: break; yann@2448: case randconfig: yann@943: conf_set_all_new_symbols(def_random); yann@943: break; yann@2448: case defconfig: yann@943: conf_set_all_new_symbols(def_default); yann@943: break; yann@2448: case savedefconfig: yann@2448: break; yann@2448: case oldaskconfig: yann@1: rootEntry = &rootmenu; yann@1: conf(&rootmenu); yann@2448: input_mode = silentoldconfig; yann@943: /* fall through */ yann@2448: case oldconfig: yann@2448: case listnewconfig: yann@2448: case oldnoconfig: yann@2448: case silentoldconfig: yann@943: /* Update until a loop caused no more changes */ yann@943: do { yann@943: conf_cnt = 0; yann@943: check_conf(&rootmenu); yann@2448: } while (conf_cnt && yann@2448: (input_mode != listnewconfig && yann@2448: input_mode != oldnoconfig)); 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@2448: /* In crosstool-NG, we do not use the autoconf stuff */ yann@2448: } else if (input_mode == savedefconfig) { yann@2448: if (conf_write_defconfig(defconfig_file)) { yann@2448: fprintf(stderr, _("n*** Error while saving defconfig to: %s\n\n"), yann@2448: defconfig_file); yann@2448: return 1; yann@2448: } yann@2448: } else if (input_mode != listnewconfig) { 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: } yann@2448: /* yann@2448: * Helper function to facilitate fgets() by Jean Sacren. yann@2448: */ yann@2448: void xfgets(str, size, in) yann@2448: char *str; yann@2448: int size; yann@2448: FILE *in; yann@2448: { yann@2448: if (fgets(str, size, in) == NULL) yann@2448: fprintf(stderr, "\nError in reading or end of file.\n"); yann@2448: }