linux conf.c,scripts/kconfig/conf.c · liang/linux - Gitee.com

/*

* Copyright (C) 2002 Roman Zippel

* Released under the terms of the GNU GPL v2.0.

*/

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include "lkc.h"

static void conf(struct menu *menu);

static void check_conf(struct menu *menu);

static void xfgets(char *str, int size, FILE *in);

enum input_mode {

oldaskconfig,

silentoldconfig,

oldconfig,

allnoconfig,

allyesconfig,

allmodconfig,

alldefconfig,

randconfig,

defconfig,

savedefconfig,

listnewconfig,

olddefconfig,

} input_mode = oldaskconfig;

static int indent = 1;

static int tty_stdio;

static int valid_stdin = 1;

static int sync_kconfig;

static int conf_cnt;

static char line[PATH_MAX];

static struct menu *rootEntry;

static void print_help(struct menu *menu)

{

struct gstr help = str_new();

menu_get_ext_help(menu, &help);

printf("\n%s\n", str_get(&help));

str_free(&help);

}

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) {

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);

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 oldconfig:

case silentoldconfig:

if (sym_has_value(sym)) {

printf("%s\n", def);

return 0;

}

check_stdin();

/* fall through */

case oldaskconfig:

fflush(stdout);

xfgets(line, sizeof(line), stdin);

if (!tty_stdio)

printf("\n");

return 1;

default:

break;

}

switch (type) {

case S_INT:

case S_HEX:

case S_STRING:

printf("%s\n", def);

return 1;

default:

;

}

printf("%s", line);

return 1;

}

static 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') {

print_help(menu);

def = NULL;

break;

}

/* fall through */

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) {

printf("%*s%s ", indent - 1, "", _(menu->prompt->text));

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");

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:

print_help(menu);

}

}

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:

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 oldconfig:

case silentoldconfig:

if (!is_new) {

cnt = def;

printf("%d\n", cnt);

break;

}

check_stdin();

/* fall through */

case oldaskconfig:

fflush(stdout);

xfgets(line, sizeof(line), stdin);

strip(line);

if (line[0] == '?') {

print_help(menu);

continue;

}

if (!line[0])

cnt = def;

else if (isdigit(line[0]))

cnt = atoi(line);

else

continue;

break;

default:

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[0] && line[strlen(line) - 1] == '?') {

print_help(child);

continue;

}

sym_set_choice_value(sym, child->sym);

for (child = child->list; child; child = child->next) {

indent += 2;

conf(child);

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 == silentoldconfig ||

input_mode == listnewconfig ||

input_mode == olddefconfig) &&

rootEntry != menu) {

check_conf(menu);

return;

}

/* fall through */

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 (input_mode == listnewconfig) {

if (sym->name && !sym_is_choice_value(sym)) {

printf("%s%s\n", CONFIG_, sym->name);

}

} else if (input_mode != olddefconfig) {

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);

}

static struct option long_opts[] = {

{"oldaskconfig", no_argument, NULL, oldaskconfig},

{"oldconfig", no_argument, NULL, oldconfig},

{"silentoldconfig", no_argument, NULL, silentoldconfig},

{"defconfig", optional_argument, NULL, defconfig},

{"savedefconfig", required_argument, NULL, savedefconfig},

{"allnoconfig", no_argument, NULL, allnoconfig},

{"allyesconfig", no_argument, NULL, allyesconfig},

{"allmodconfig", no_argument, NULL, allmodconfig},

{"alldefconfig", no_argument, NULL, alldefconfig},

{"randconfig", no_argument, NULL, randconfig},

{"listnewconfig", no_argument, NULL, listnewconfig},

{"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},

{NULL, 0, NULL, 0}

};

static void conf_usage(const char *progname)

{

printf("Usage: %s [-s] [option] \n", progname);

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");

printf(" --silentoldconfig Same as oldconfig, but quietly, additionally update deps\n");

printf(" --olddefconfig Same as silentoldconfig but sets new symbols to their default value\n");

printf(" --oldnoconfig An alias of olddefconfig\n");

printf(" --defconfig New config with default defined in \n");

printf(" --savedefconfig Save the minimal current configuration to \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");

}

int main(int ac, char **av)

{

const char *progname = av[0];

int opt;

const char *name, *defconfig_file = NULL /* gcc uninit */;

struct stat tmpstat;

setlocale(LC_ALL, "");

bindtextdomain(PACKAGE, LOCALEDIR);

textdomain(PACKAGE);

tty_stdio = isatty(0) && isatty(1) && isatty(2);

while ((opt = getopt_long(ac, av, "s", long_opts, NULL)) != -1) {

if (opt == 's') {

conf_set_message_callback(NULL);

continue;

}

input_mode = (enum input_mode)opt;

switch (opt) {

case silentoldconfig:

sync_kconfig = 1;

break;

case defconfig:

case savedefconfig:

defconfig_file = optarg;

break;

case randconfig:

{

struct timeval now;

unsigned int seed;

char *seed_env;

/*

* 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));

seed_env = getenv("KCONFIG_SEED");

if( seed_env && *seed_env ) {

char *endp;

int tmp = (int)strtol(seed_env, &endp, 0);

if (*endp == '\0') {

seed = tmp;

}

}

fprintf( stderr, "KCONFIG_SEED=0x%X\n", seed );

srand(seed);

break;

}

case oldaskconfig:

case oldconfig:

case allnoconfig:

case allyesconfig:

case allmodconfig:

case alldefconfig:

case listnewconfig:

case olddefconfig:

break;

case '?':

conf_usage(progname);

exit(1);

break;

}

}

if (ac == optind) {

printf(_("%s: Kconfig file missing\n"), av[0]);

conf_usage(progname);

exit(1);

}

name = av[optind];

conf_parse(name);

//zconfdump(stdout);

if (sync_kconfig) {

name = conf_get_configname();

if (stat(name, &tmpstat)) {

fprintf(stderr, _("***\n"

"*** Configuration file \"%s\" not found!\n"

"***\n"

"*** Please run some configurator (e.g. \"make oldconfig\" or\n"

"*** \"make menuconfig\" or \"make xconfig\").\n"

"***\n"), name);

exit(1);

}

}

switch (input_mode) {

case defconfig:

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 savedefconfig:

case silentoldconfig:

case oldaskconfig:

case oldconfig:

case listnewconfig:

case olddefconfig:

conf_read(NULL);

break;

case allnoconfig:

case allyesconfig:

case allmodconfig:

case alldefconfig:

case randconfig:

name = getenv("KCONFIG_ALLCONFIG");

if (!name)

break;

if ((strcmp(name, "") != 0) && (strcmp(name, "1") != 0)) {

if (conf_read_simple(name, S_DEF_USER)) {

fprintf(stderr,

_("*** Can't read seed configuration \"%s\"!\n"),

name);

exit(1);

}

break;

}

switch (input_mode) {

case allnoconfig:name = "allno.config"; break;

case allyesconfig:name = "allyes.config"; break;

case allmodconfig:name = "allmod.config"; break;

case alldefconfig:name = "alldef.config"; break;

case randconfig:name = "allrandom.config"; break;

default: break;

}

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);

}

break;

default:

break;

}

if (sync_kconfig) {

if (conf_get_changed()) {

name = getenv("KCONFIG_NOSILENTUPDATE");

if (name && *name) {

fprintf(stderr,

_("\n*** The configuration requires explicit update.\n\n"));

return 1;

}

}

valid_stdin = tty_stdio;

}

switch (input_mode) {

case allnoconfig:

conf_set_all_new_symbols(def_no);

break;

case allyesconfig:

conf_set_all_new_symbols(def_yes);

break;

case allmodconfig:

conf_set_all_new_symbols(def_mod);

break;

case alldefconfig:

conf_set_all_new_symbols(def_default);

break;

case randconfig:

/* Really nothing to do in this loop */

while (conf_set_all_new_symbols(def_random)) ;

break;

case defconfig:

conf_set_all_new_symbols(def_default);

break;

case savedefconfig:

break;

case oldaskconfig:

rootEntry = &rootmenu;

conf(&rootmenu);

input_mode = silentoldconfig;

/* fall through */

case oldconfig:

case listnewconfig:

case olddefconfig:

case silentoldconfig:

/* Update until a loop caused no more changes */

do {

conf_cnt = 0;

check_conf(&rootmenu);

} while (conf_cnt &&

(input_mode != listnewconfig &&

input_mode != olddefconfig));

break;

}

if (sync_kconfig) {

/* silentoldconfig is used during the build so we shall update autoconf.

* All other commands are only used to generate a config.

*/

if (conf_get_changed() && conf_write(NULL)) {

fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n"));

exit(1);

}

if (conf_write_autoconf()) {

fprintf(stderr, _("\n*** Error during update of the configuration.\n\n"));

return 1;

}

} else if (input_mode == savedefconfig) {

if (conf_write_defconfig(defconfig_file)) {

fprintf(stderr, _("n*** Error while saving defconfig to: %s\n\n"),

defconfig_file);

return 1;

}

} else if (input_mode != listnewconfig) {

if (conf_write(NULL)) {

fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n"));

exit(1);

}

}

return 0;

}

/*

* Helper function to facilitate fgets() by Jean Sacren.

*/

void xfgets(char *str, int size, FILE *in)

{

if (fgets(str, size, in) == NULL)

fprintf(stderr, "\nError in reading or end of file.\n");

}

一键复制

编辑

Web IDE

原始数据

按行查看

历史

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值