mirror of
https://github.com/crosstool-ng/crosstool-ng.git
synced 2025-02-22 17:42:40 +00:00
commit
5b0e0127e1
@ -596,6 +596,8 @@ enter_fork()
|
||||
info[repository_url]=${info[repository]#* }
|
||||
fi
|
||||
|
||||
info[mirrors]=${info[mirrors]//$\(/\\$\(}
|
||||
|
||||
versions=`cd packages/${fork} && \
|
||||
for f in */version.desc; do [ -r "${f}" ] && echo "${f%/version.desc}"; done`
|
||||
versions=`sort_versions ${versions}`
|
||||
|
@ -382,7 +382,7 @@ choice CC_GCC_DEC_FLOATS_CHOICE
|
||||
|
||||
The default is to let ./configure decide.
|
||||
|
||||
config CC_GCC_DEC_FLOAT_AUTO
|
||||
config CC_GCC_DEC_FLOATS_AUTO
|
||||
bool "auto"
|
||||
help
|
||||
Let ./configure decide. If you say 'y' here, gcc will default to:
|
||||
@ -390,12 +390,12 @@ config CC_GCC_DEC_FLOAT_AUTO
|
||||
- 'dpd' for powerpc
|
||||
- 'no' for the other architectures
|
||||
|
||||
config CC_GCC_DEC_FLOAT_BID
|
||||
config CC_GCC_DEC_FLOATS_BID
|
||||
bool "bid"
|
||||
help
|
||||
Use the 'binary integer decimal' format for decimal floats.
|
||||
|
||||
config CC_GCC_DEC_FLOAT_DPD
|
||||
config CC_GCC_DEC_FLOATS_DPD
|
||||
bool "dpd"
|
||||
help
|
||||
Use the 'densely packed decimal' for decimal floats.
|
||||
|
@ -1,4 +1,4 @@
|
||||
mainmenu "crosstool-NG $CT_VERSION Configuration"
|
||||
mainmenu "crosstool-NG $(CT_VERSION) Configuration"
|
||||
source "config/configure.in"
|
||||
source "config/global.in"
|
||||
source "config/target.in"
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
config VERSION
|
||||
string
|
||||
option env="CT_VERSION"
|
||||
default "$(CT_VERSION)"
|
||||
|
||||
# Config version checking framework. If CONFIG_VERSION is unset in the current .config
|
||||
# or defconfig, it is loaded as 0 (possibly triggering a user prompt during 'ct-ng oldconfig').
|
||||
@ -16,13 +16,13 @@ config VERSION
|
||||
# i.e. 'ct-ng saveconfig' or 'ct-ng savedefconfig'.
|
||||
config VCHECK
|
||||
string
|
||||
option env="CT_VCHECK"
|
||||
default "$(CT_VCHECK)"
|
||||
|
||||
# Kconfig's idiosynchrasy: it does not output the config settings declared with 'option env'
|
||||
# to the generated .config file. Must use one extra level of indirection.
|
||||
config CONFIG_VERSION_ENV
|
||||
string
|
||||
option env="CT_CONFIG_VERSION_CURRENT"
|
||||
default "$(CT_CONFIG_VERSION_CURRENT)"
|
||||
|
||||
# Up-to-date version of the configuration file. If saving a defconfig, choose a default that
|
||||
# is guaranteed not to match - so that kconfig saves the value to .config.
|
||||
|
@ -18,6 +18,7 @@ AC_CONFIG_MACRO_DIR([m4])
|
||||
# - Object files are generated in a subdirectory (new default in automake)
|
||||
# - Request new tar format (old, tar-v7, breaks on long paths we have)
|
||||
AM_INIT_AUTOMAKE([-Wall -Werror foreign no-dist-gzip dist-xz dist-bzip2 subdir-objects tar-pax])
|
||||
AM_SILENT_RULES([yes])
|
||||
|
||||
# To avoid stubbing autotools with missing script
|
||||
AM_MAINTAINER_MODE([enable])
|
||||
|
19
kconfig/.gitignore
vendored
19
kconfig/.gitignore
vendored
@ -1,9 +1,14 @@
|
||||
conf
|
||||
?conf
|
||||
*.o
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
#
|
||||
# Generated files
|
||||
#
|
||||
.deps
|
||||
zconf.c
|
||||
zconf.lex.c
|
||||
*.exe
|
||||
Makefile
|
||||
.dirstamp
|
||||
|
||||
#
|
||||
# configuration programs
|
||||
#
|
||||
conf
|
||||
mconf
|
||||
nconf
|
||||
|
@ -5,26 +5,27 @@ transform = s,x,x,
|
||||
|
||||
pkglibexec_PROGRAMS = conf nconf mconf
|
||||
|
||||
EXTRA_DIST = zconf.y zconf.l \
|
||||
EXTRA_DIST = parser.y lexer.l \
|
||||
expr.h list.h lkc.h lkc_proto.h nconf.h lxdialog/dialog.h \
|
||||
confdata.c expr.c kconf_id.c menu.c symbol.c util.c
|
||||
|
||||
CLEANFILES = zconf.lex.c zconf.c
|
||||
BUILT_SOURCES = zconf.c zconf.lex.c
|
||||
CLEANFILES = lexer.lex.c parser.tab.c parser.tab.h
|
||||
BUILT_SOURCES = lexer.lex.c parser.tab.c
|
||||
|
||||
AM_LFLAGS = -L -Pzconf
|
||||
AM_YFLAGS = -l -b zconf -p zconf
|
||||
AM_LFLAGS = -L
|
||||
AM_YFLAGS = -t -l
|
||||
AM_CPPFLAGS = -include config.h -DCONFIG_=\"CT_\"
|
||||
AM_LIBTOOLFLAGS = --tag CC
|
||||
|
||||
conf_SOURCES = conf.c zconf.c
|
||||
conf_SOURCES = conf.c confdata.c expr.c symbol.c preprocess.c util.c lexer.lex.c parser.tab.c
|
||||
conf_LDADD = $(LIBINTL)
|
||||
|
||||
nconf_SOURCES = nconf.c nconf.gui.c zconf.c
|
||||
nconf_SOURCES = nconf.c nconf.gui.c confdata.c expr.c symbol.c preprocess.c util.c lexer.lex.c parser.tab.c
|
||||
nconf_CFLAGS = $(CURSES_CFLAGS)
|
||||
nconf_LDADD = $(MENU_LIBS) $(PANEL_LIBS) $(CURSES_LIBS) $(LIBINTL)
|
||||
|
||||
mconf_SOURCES = mconf.c zconf.c lxdialog/checklist.c lxdialog/inputbox.c \
|
||||
mconf_SOURCES = mconf.c confdata.c expr.c symbol.c preprocess.c util.c lexer.lex.c parser.tab.c \
|
||||
lxdialog/checklist.c lxdialog/inputbox.c \
|
||||
lxdialog/menubox.c lxdialog/textbox.c lxdialog/util.c \
|
||||
lxdialog/yesno.c
|
||||
mconf_LDADD = $(CURSES_LIBS) $(LIBINTL)
|
||||
@ -42,8 +43,8 @@ AM_V_LEX = $(am__v_LEX_@AM_V@)
|
||||
am__v_LEX_ = $(am__v_LEX_@AM_DEFAULT_V@)
|
||||
am__v_LEX_0 = @echo " LEX " $@;
|
||||
|
||||
zconf.c: zconf.y
|
||||
$(AM_V_YACC)$(YACCCOMPILE) -o$@ $<
|
||||
parser.tab.c: parser.y
|
||||
$(AM_V_YACC)$(YACCCOMPILE) -o$@ --defines=parser.tab.h $<
|
||||
|
||||
zconf.lex.c: zconf.l
|
||||
lexer.lex.c: lexer.l
|
||||
$(AM_V_LEX)$(LEXCOMPILE) -o$@ $<
|
||||
|
@ -1,14 +0,0 @@
|
||||
#!/bin/sh
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
# Needed for systems without gettext
|
||||
$* -x c -o /dev/null - > /dev/null 2>&1 << EOF
|
||||
#include <libintl.h>
|
||||
int main()
|
||||
{
|
||||
gettext("");
|
||||
return 0;
|
||||
}
|
||||
EOF
|
||||
if [ ! "$?" -eq "0" ]; then
|
||||
echo -DKBUILD_NO_NLS;
|
||||
fi
|
247
kconfig/conf.c
247
kconfig/conf.c
@ -1,9 +1,8 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
|
||||
* Released under the terms of the GNU GPL v2.0.
|
||||
*/
|
||||
|
||||
#include <locale.h>
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
@ -20,11 +19,10 @@
|
||||
|
||||
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,
|
||||
syncconfig,
|
||||
oldconfig,
|
||||
allnoconfig,
|
||||
allyesconfig,
|
||||
@ -34,12 +32,15 @@ enum input_mode {
|
||||
defconfig,
|
||||
savedefconfig,
|
||||
listnewconfig,
|
||||
helpnewconfig,
|
||||
olddefconfig,
|
||||
} input_mode = oldaskconfig;
|
||||
yes2modconfig,
|
||||
mod2yesconfig,
|
||||
};
|
||||
static enum input_mode 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];
|
||||
@ -72,14 +73,14 @@ static void strip(char *str)
|
||||
*p-- = 0;
|
||||
}
|
||||
|
||||
static void check_stdin(void)
|
||||
/* Helper function to facilitate fgets() by Jean Sacren. */
|
||||
static void xfgets(char *str, int size, FILE *in)
|
||||
{
|
||||
if (!valid_stdin) {
|
||||
/* For crosstool-NG, we don't care if stdin/stdout got redirected.
|
||||
* In this case, just printf a cariage return, for pretty output.
|
||||
*/
|
||||
printf("\n");
|
||||
}
|
||||
if (!fgets(str, size, in))
|
||||
fprintf(stderr, "\nError in reading or end of file.\n");
|
||||
|
||||
if (!tty_stdio)
|
||||
printf("%s", str);
|
||||
}
|
||||
|
||||
static int conf_askvalue(struct symbol *sym, const char *def)
|
||||
@ -87,12 +88,12 @@ 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) "));
|
||||
printf("(NEW) ");
|
||||
|
||||
line[0] = '\n';
|
||||
line[1] = 0;
|
||||
|
||||
if (!sym_is_changable(sym)) {
|
||||
if (!sym_is_changeable(sym)) {
|
||||
printf("%s\n", def);
|
||||
line[0] = '\n';
|
||||
line[1] = 0;
|
||||
@ -101,18 +102,15 @@ static int conf_askvalue(struct symbol *sym, const char *def)
|
||||
|
||||
switch (input_mode) {
|
||||
case oldconfig:
|
||||
case silentoldconfig:
|
||||
case syncconfig:
|
||||
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;
|
||||
@ -137,7 +135,7 @@ static int conf_string(struct menu *menu)
|
||||
const char *def;
|
||||
|
||||
while (1) {
|
||||
printf("%*s%s ", indent - 1, "", _(menu->prompt->text));
|
||||
printf("%*s%s ", indent - 1, "", menu->prompt->text);
|
||||
printf("(%s) ", sym->name);
|
||||
def = sym_get_string_value(sym);
|
||||
if (sym_get_string_value(sym))
|
||||
@ -170,7 +168,7 @@ static int conf_sym(struct menu *menu)
|
||||
tristate oldval, newval;
|
||||
|
||||
while (1) {
|
||||
printf("%*s%s ", indent - 1, "", _(menu->prompt->text));
|
||||
printf("%*s%s ", indent - 1, "", menu->prompt->text);
|
||||
if (sym->name)
|
||||
printf("(%s) ", sym->name);
|
||||
putchar('[');
|
||||
@ -192,9 +190,7 @@ static int conf_sym(struct menu *menu)
|
||||
printf("/m");
|
||||
if (oldval != yes && sym_tristate_within_range(sym, yes))
|
||||
printf("/y");
|
||||
if (menu_has_help(menu))
|
||||
printf("/?");
|
||||
printf("] ");
|
||||
printf("/?] ");
|
||||
if (!conf_askvalue(sym, sym_get_string_value(sym)))
|
||||
return 0;
|
||||
strip(line);
|
||||
@ -241,7 +237,7 @@ static int conf_choice(struct menu *menu)
|
||||
|
||||
sym = menu->sym;
|
||||
is_new = !sym_has_value(sym);
|
||||
if (sym_is_changable(sym)) {
|
||||
if (sym_is_changeable(sym)) {
|
||||
conf_sym(menu);
|
||||
sym_calc_value(sym);
|
||||
switch (sym_get_tristate_value(sym)) {
|
||||
@ -257,7 +253,7 @@ static int conf_choice(struct menu *menu)
|
||||
case no:
|
||||
return 1;
|
||||
case mod:
|
||||
printf("%*s%s\n", indent - 1, "", _(menu_get_prompt(menu)));
|
||||
printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu));
|
||||
return 0;
|
||||
case yes:
|
||||
break;
|
||||
@ -267,7 +263,7 @@ static int conf_choice(struct menu *menu)
|
||||
while (1) {
|
||||
int cnt, def;
|
||||
|
||||
printf("%*s%s\n", indent - 1, "", _(menu_get_prompt(menu)));
|
||||
printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu));
|
||||
def_sym = sym_get_choice_value(sym);
|
||||
cnt = def = 0;
|
||||
line[0] = 0;
|
||||
@ -275,7 +271,7 @@ static int conf_choice(struct menu *menu)
|
||||
if (!menu_is_visible(child))
|
||||
continue;
|
||||
if (!child->sym) {
|
||||
printf("%*c %s\n", indent, '*', _(menu_get_prompt(child)));
|
||||
printf("%*c %s\n", indent, '*', menu_get_prompt(child));
|
||||
continue;
|
||||
}
|
||||
cnt++;
|
||||
@ -284,31 +280,27 @@ static int conf_choice(struct menu *menu)
|
||||
printf("%*c", indent, '>');
|
||||
} else
|
||||
printf("%*c", indent, ' ');
|
||||
printf(" %d. %s", cnt, _(menu_get_prompt(child)));
|
||||
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(" (NEW)");
|
||||
printf("\n");
|
||||
}
|
||||
printf(_("%*schoice"), indent - 1, "");
|
||||
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("]: ");
|
||||
printf("[1-%d?]: ", cnt);
|
||||
switch (input_mode) {
|
||||
case oldconfig:
|
||||
case silentoldconfig:
|
||||
case syncconfig:
|
||||
if (!is_new) {
|
||||
cnt = def;
|
||||
printf("%d\n", cnt);
|
||||
break;
|
||||
}
|
||||
check_stdin();
|
||||
/* fall through */
|
||||
case oldaskconfig:
|
||||
fflush(stdout);
|
||||
@ -368,10 +360,11 @@ static void conf(struct menu *menu)
|
||||
|
||||
switch (prop->type) {
|
||||
case P_MENU:
|
||||
if ((input_mode == silentoldconfig ||
|
||||
input_mode == listnewconfig ||
|
||||
input_mode == olddefconfig) &&
|
||||
rootEntry != menu) {
|
||||
/*
|
||||
* Except in oldaskconfig mode, we show only menus that
|
||||
* contain new symbols.
|
||||
*/
|
||||
if (input_mode != oldaskconfig && rootEntry != menu) {
|
||||
check_conf(menu);
|
||||
return;
|
||||
}
|
||||
@ -381,7 +374,7 @@ static void conf(struct menu *menu)
|
||||
if (prompt)
|
||||
printf("%*c\n%*c %s\n%*c\n",
|
||||
indent, '*',
|
||||
indent, '*', _(prompt),
|
||||
indent, '*', prompt,
|
||||
indent, '*');
|
||||
default:
|
||||
;
|
||||
@ -428,15 +421,30 @@ static void check_conf(struct menu *menu)
|
||||
|
||||
sym = menu->sym;
|
||||
if (sym && !sym_has_value(sym)) {
|
||||
if (sym_is_changable(sym) ||
|
||||
if (sym_is_changeable(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);
|
||||
if (sym->name) {
|
||||
const char *str;
|
||||
|
||||
if (sym->type == S_STRING) {
|
||||
str = sym_get_string_value(sym);
|
||||
str = sym_escape_string_value(str);
|
||||
printf("%s%s=%s\n", CONFIG_, sym->name, str);
|
||||
free((void *)str);
|
||||
} else {
|
||||
str = sym_get_string_value(sym);
|
||||
printf("%s%s=%s\n", CONFIG_, sym->name, str);
|
||||
}
|
||||
}
|
||||
} else if (input_mode != olddefconfig) {
|
||||
} else if (input_mode == helpnewconfig) {
|
||||
printf("-----\n");
|
||||
print_help(menu);
|
||||
printf("-----\n");
|
||||
|
||||
} else {
|
||||
if (!conf_cnt++)
|
||||
printf(_("*\n* Restart config...\n*\n"));
|
||||
printf("*\n* Restart config...\n*\n");
|
||||
rootEntry = menu_get_parent_menu(menu);
|
||||
conf(rootEntry);
|
||||
}
|
||||
@ -450,8 +458,8 @@ static void check_conf(struct menu *menu)
|
||||
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},
|
||||
{"syncconfig", no_argument, NULL, syncconfig},
|
||||
{"defconfig", required_argument, NULL, defconfig},
|
||||
{"savedefconfig", required_argument, NULL, savedefconfig},
|
||||
{"allnoconfig", no_argument, NULL, allnoconfig},
|
||||
{"allyesconfig", no_argument, NULL, allyesconfig},
|
||||
@ -459,13 +467,10 @@ static struct option long_opts[] = {
|
||||
{"alldefconfig", no_argument, NULL, alldefconfig},
|
||||
{"randconfig", no_argument, NULL, randconfig},
|
||||
{"listnewconfig", no_argument, NULL, listnewconfig},
|
||||
{"helpnewconfig", no_argument, NULL, helpnewconfig},
|
||||
{"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},
|
||||
{"yes2modconfig", no_argument, NULL, yes2modconfig},
|
||||
{"mod2yesconfig", no_argument, NULL, mod2yesconfig},
|
||||
{NULL, 0, NULL, 0}
|
||||
};
|
||||
|
||||
@ -474,13 +479,9 @@ int main(int ac, char **av)
|
||||
const char *progname = av[0];
|
||||
int opt;
|
||||
const char *name, *defconfig_file = NULL /* gcc uninit */;
|
||||
struct stat tmpstat;
|
||||
int no_conf_write = 0;
|
||||
|
||||
setlocale(LC_ALL, "");
|
||||
bindtextdomain(PACKAGE, LOCALEDIR);
|
||||
textdomain(PACKAGE);
|
||||
|
||||
tty_stdio = isatty(0) && isatty(1) && isatty(2);
|
||||
tty_stdio = isatty(0) && isatty(1);
|
||||
|
||||
while ((opt = getopt_long(ac, av, "s", long_opts, NULL)) != -1) {
|
||||
if (opt == 's') {
|
||||
@ -489,7 +490,12 @@ int main(int ac, char **av)
|
||||
}
|
||||
input_mode = (enum input_mode)opt;
|
||||
switch (opt) {
|
||||
case silentoldconfig:
|
||||
case syncconfig:
|
||||
/*
|
||||
* syncconfig is invoked during the build stage.
|
||||
* Suppress distracting "configuration written to ..."
|
||||
*/
|
||||
conf_set_message_callback(NULL);
|
||||
sync_kconfig = 1;
|
||||
break;
|
||||
case defconfig:
|
||||
@ -528,52 +534,46 @@ int main(int ac, char **av)
|
||||
case allmodconfig:
|
||||
case alldefconfig:
|
||||
case listnewconfig:
|
||||
case helpnewconfig:
|
||||
case olddefconfig:
|
||||
case yes2modconfig:
|
||||
case mod2yesconfig:
|
||||
break;
|
||||
case '?':
|
||||
fprintf(stderr, _("See README for usage info\n"));
|
||||
fprintf(stderr, "See README for usage info\n");
|
||||
exit(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ac == optind) {
|
||||
printf(_("%s: Kconfig file missing\n"), av[0]);
|
||||
fprintf(stderr, _("See README for usage info\n"));
|
||||
fprintf(stderr, "%s: Kconfig file missing\n", av[0]);
|
||||
fprintf(stderr, "See README for usage info\n");
|
||||
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 configure with \"menuconfig\", or use a\n"
|
||||
"*** pre-existing sample (see list with \"list-samples\").\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);
|
||||
fprintf(stderr,
|
||||
"***\n"
|
||||
"*** Can't find default configuration \"%s\"!\n"
|
||||
"***\n",
|
||||
defconfig_file);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case savedefconfig:
|
||||
case silentoldconfig:
|
||||
case syncconfig:
|
||||
case oldaskconfig:
|
||||
case oldconfig:
|
||||
case listnewconfig:
|
||||
case helpnewconfig:
|
||||
case olddefconfig:
|
||||
case yes2modconfig:
|
||||
case mod2yesconfig:
|
||||
conf_read(NULL);
|
||||
break;
|
||||
case allnoconfig:
|
||||
@ -587,7 +587,7 @@ int main(int ac, char **av)
|
||||
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"),
|
||||
"*** Can't read seed configuration \"%s\"!\n",
|
||||
name);
|
||||
exit(1);
|
||||
}
|
||||
@ -604,7 +604,7 @@ int main(int ac, char **av)
|
||||
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"),
|
||||
"*** KCONFIG_ALLCONFIG set, but no \"%s\" or \"all.config\" file found\n",
|
||||
name);
|
||||
exit(1);
|
||||
}
|
||||
@ -614,15 +614,15 @@ int main(int ac, char **av)
|
||||
}
|
||||
|
||||
if (sync_kconfig) {
|
||||
if (conf_get_changed()) {
|
||||
name = getenv("KCONFIG_NOSILENTUPDATE");
|
||||
if (name && *name) {
|
||||
name = getenv("KCONFIG_NOSILENTUPDATE");
|
||||
if (name && *name) {
|
||||
if (conf_get_changed()) {
|
||||
fprintf(stderr,
|
||||
_("\n*** The configuration requires explicit update.\n\n"));
|
||||
"\n*** The configuration requires explicit update.\n\n");
|
||||
return 1;
|
||||
}
|
||||
no_conf_write = 1;
|
||||
}
|
||||
valid_stdin = tty_stdio;
|
||||
}
|
||||
|
||||
switch (input_mode) {
|
||||
@ -647,58 +647,59 @@ int main(int ac, char **av)
|
||||
break;
|
||||
case savedefconfig:
|
||||
break;
|
||||
case yes2modconfig:
|
||||
conf_rewrite_mod_or_yes(def_y2m);
|
||||
break;
|
||||
case mod2yesconfig:
|
||||
conf_rewrite_mod_or_yes(def_m2y);
|
||||
break;
|
||||
case oldaskconfig:
|
||||
rootEntry = &rootmenu;
|
||||
conf(&rootmenu);
|
||||
input_mode = silentoldconfig;
|
||||
input_mode = oldconfig;
|
||||
/* fall through */
|
||||
case oldconfig:
|
||||
case listnewconfig:
|
||||
case olddefconfig:
|
||||
case silentoldconfig:
|
||||
case helpnewconfig:
|
||||
case syncconfig:
|
||||
/* Update until a loop caused no more changes */
|
||||
do {
|
||||
conf_cnt = 0;
|
||||
check_conf(&rootmenu);
|
||||
} while (conf_cnt &&
|
||||
(input_mode != listnewconfig &&
|
||||
input_mode != olddefconfig));
|
||||
} while (conf_cnt);
|
||||
break;
|
||||
case olddefconfig:
|
||||
default:
|
||||
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);
|
||||
}
|
||||
/* In crosstool-NG, we do not use the autoconf stuff
|
||||
if (conf_write_autoconf()) {
|
||||
fprintf(stderr, _("\n*** Error during update of the configuration.\n\n"));
|
||||
return 1;
|
||||
} */
|
||||
} else if (input_mode == savedefconfig) {
|
||||
if (input_mode == savedefconfig) {
|
||||
if (conf_write_defconfig(defconfig_file)) {
|
||||
fprintf(stderr, _("n*** Error while saving defconfig to: %s\n\n"),
|
||||
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"));
|
||||
} else if (input_mode != listnewconfig && input_mode != helpnewconfig) {
|
||||
if (!no_conf_write && conf_write(NULL)) {
|
||||
fprintf(stderr, "\n*** Error during writing of the configuration.\n\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Create auto.conf if it does not exist.
|
||||
* This prevents GNU Make 4.1 or older from emitting
|
||||
* "include/config/auto.conf: No such file or directory"
|
||||
* in the top-level Makefile
|
||||
*
|
||||
* syncconfig always creates or updates auto.conf because it is
|
||||
* used during the build.
|
||||
*/
|
||||
/* In crosstool-NG, we do not use the autoconf stuff
|
||||
if (conf_write_autoconf(sync_kconfig) && sync_kconfig) {
|
||||
fprintf(stderr,
|
||||
"\n*** Error during sync of the configuration.\n\n");
|
||||
return 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");
|
||||
}
|
||||
|
@ -1,12 +1,14 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
|
||||
* Released under the terms of the GNU GPL v2.0.
|
||||
*/
|
||||
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@ -16,6 +18,151 @@
|
||||
|
||||
#include "lkc.h"
|
||||
|
||||
/* return true if 'path' exists, false otherwise */
|
||||
static bool is_present(const char *path)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
return !stat(path, &st);
|
||||
}
|
||||
|
||||
/* return true if 'path' exists and it is a directory, false otherwise */
|
||||
static bool is_dir(const char *path)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
if (stat(path, &st))
|
||||
return 0;
|
||||
|
||||
return S_ISDIR(st.st_mode);
|
||||
}
|
||||
|
||||
/* return true if the given two files are the same, false otherwise */
|
||||
static bool is_same(const char *file1, const char *file2)
|
||||
{
|
||||
int fd1, fd2;
|
||||
struct stat st1, st2;
|
||||
void *map1, *map2;
|
||||
bool ret = false;
|
||||
|
||||
fd1 = open(file1, O_RDONLY);
|
||||
if (fd1 < 0)
|
||||
return ret;
|
||||
|
||||
fd2 = open(file2, O_RDONLY);
|
||||
if (fd2 < 0)
|
||||
goto close1;
|
||||
|
||||
ret = fstat(fd1, &st1);
|
||||
if (ret)
|
||||
goto close2;
|
||||
ret = fstat(fd2, &st2);
|
||||
if (ret)
|
||||
goto close2;
|
||||
|
||||
if (st1.st_size != st2.st_size)
|
||||
goto close2;
|
||||
|
||||
map1 = mmap(NULL, st1.st_size, PROT_READ, MAP_PRIVATE, fd1, 0);
|
||||
if (map1 == MAP_FAILED)
|
||||
goto close2;
|
||||
|
||||
map2 = mmap(NULL, st2.st_size, PROT_READ, MAP_PRIVATE, fd2, 0);
|
||||
if (map2 == MAP_FAILED)
|
||||
goto close2;
|
||||
|
||||
if (bcmp(map1, map2, st1.st_size))
|
||||
goto close2;
|
||||
|
||||
ret = true;
|
||||
close2:
|
||||
close(fd2);
|
||||
close1:
|
||||
close(fd1);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create the parent directory of the given path.
|
||||
*
|
||||
* For example, if 'include/config/auto.conf' is given, create 'include/config'.
|
||||
*/
|
||||
static int make_parent_dir(const char *path)
|
||||
{
|
||||
char tmp[PATH_MAX + 1];
|
||||
char *p;
|
||||
|
||||
strncpy(tmp, path, sizeof(tmp));
|
||||
tmp[sizeof(tmp) - 1] = 0;
|
||||
|
||||
/* Remove the base name. Just return if nothing is left */
|
||||
p = strrchr(tmp, '/');
|
||||
if (!p)
|
||||
return 0;
|
||||
*(p + 1) = 0;
|
||||
|
||||
/* Just in case it is an absolute path */
|
||||
p = tmp;
|
||||
while (*p == '/')
|
||||
p++;
|
||||
|
||||
while ((p = strchr(p, '/'))) {
|
||||
*p = 0;
|
||||
|
||||
/* skip if the directory exists */
|
||||
if (!is_dir(tmp) && mkdir(tmp, 0755))
|
||||
return -1;
|
||||
|
||||
*p = '/';
|
||||
while (*p == '/')
|
||||
p++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char depfile_path[PATH_MAX];
|
||||
static size_t depfile_prefix_len;
|
||||
|
||||
/* touch depfile for symbol 'name' */
|
||||
static int conf_touch_dep(const char *name)
|
||||
{
|
||||
int fd, ret;
|
||||
const char *s;
|
||||
char *d, c;
|
||||
|
||||
/* check overflow: prefix + name + ".h" + '\0' must fit in buffer. */
|
||||
if (depfile_prefix_len + strlen(name) + 3 > sizeof(depfile_path))
|
||||
return -1;
|
||||
|
||||
d = depfile_path + depfile_prefix_len;
|
||||
s = name;
|
||||
|
||||
while ((c = *s++))
|
||||
*d++ = (c == '_') ? '/' : tolower(c);
|
||||
strcpy(d, ".h");
|
||||
|
||||
/* Assume directory path already exists. */
|
||||
fd = open(depfile_path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
||||
if (fd == -1) {
|
||||
if (errno != ENOENT)
|
||||
return -1;
|
||||
|
||||
ret = make_parent_dir(depfile_path);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Try it again. */
|
||||
fd = open(depfile_path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
||||
if (fd == -1)
|
||||
return -1;
|
||||
}
|
||||
close(fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct conf_printer {
|
||||
void (*print_symbol)(FILE *, struct symbol *, const char *, void *);
|
||||
void (*print_comment)(FILE *, const char *, void *);
|
||||
@ -28,9 +175,7 @@ static void conf_message(const char *fmt, ...)
|
||||
__attribute__ ((format (printf, 1, 2)));
|
||||
|
||||
static const char *conf_filename;
|
||||
static int conf_lineno, conf_warnings, conf_unsaved;
|
||||
|
||||
const char conf_defname[] = "arch/$ARCH/defconfig";
|
||||
static int conf_lineno, conf_warnings;
|
||||
|
||||
static void conf_warning(const char *fmt, ...)
|
||||
{
|
||||
@ -43,16 +188,16 @@ static void conf_warning(const char *fmt, ...)
|
||||
conf_warnings++;
|
||||
}
|
||||
|
||||
static void conf_default_message_callback(const char *fmt, va_list ap)
|
||||
static void conf_default_message_callback(const char *s)
|
||||
{
|
||||
printf("#\n# ");
|
||||
vprintf(fmt, ap);
|
||||
printf("%s", s);
|
||||
printf("\n#\n");
|
||||
}
|
||||
|
||||
static void (*conf_message_callback) (const char *fmt, va_list ap) =
|
||||
static void (*conf_message_callback)(const char *s) =
|
||||
conf_default_message_callback;
|
||||
void conf_set_message_callback(void (*fn) (const char *fmt, va_list ap))
|
||||
void conf_set_message_callback(void (*fn)(const char *s))
|
||||
{
|
||||
conf_message_callback = fn;
|
||||
}
|
||||
@ -60,10 +205,15 @@ void conf_set_message_callback(void (*fn) (const char *fmt, va_list ap))
|
||||
static void conf_message(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char buf[4096];
|
||||
|
||||
if (!conf_message_callback)
|
||||
return;
|
||||
|
||||
va_start(ap, fmt);
|
||||
if (conf_message_callback)
|
||||
conf_message_callback(fmt, ap);
|
||||
|
||||
vsnprintf(buf, sizeof(buf), fmt, ap);
|
||||
conf_message_callback(buf);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
@ -74,55 +224,13 @@ const char *conf_get_configname(void)
|
||||
return name ? name : ".config";
|
||||
}
|
||||
|
||||
const char *conf_get_autoconfig_name(void)
|
||||
static const char *conf_get_autoconfig_name(void)
|
||||
{
|
||||
char *name = getenv("KCONFIG_AUTOCONFIG");
|
||||
|
||||
return name ? name : "include/config/auto.conf";
|
||||
}
|
||||
|
||||
static char *conf_expand_value(const char *in)
|
||||
{
|
||||
struct symbol *sym;
|
||||
const char *src;
|
||||
static char res_value[SYMBOL_MAXLENGTH];
|
||||
char *dst, name[SYMBOL_MAXLENGTH];
|
||||
|
||||
res_value[0] = 0;
|
||||
dst = name;
|
||||
while ((src = strchr(in, '$'))) {
|
||||
strncat(res_value, in, src - in);
|
||||
src++;
|
||||
dst = name;
|
||||
while (isalnum(*src) || *src == '_')
|
||||
*dst++ = *src++;
|
||||
*dst = 0;
|
||||
sym = sym_lookup(name, 0);
|
||||
sym_calc_value(sym);
|
||||
strcat(res_value, sym_get_string_value(sym));
|
||||
in = src;
|
||||
}
|
||||
strcat(res_value, in);
|
||||
|
||||
return res_value;
|
||||
}
|
||||
|
||||
char *conf_get_default_confname(void)
|
||||
{
|
||||
struct stat buf;
|
||||
static char fullname[PATH_MAX+1];
|
||||
char *env, *name;
|
||||
|
||||
name = conf_expand_value(conf_defname);
|
||||
env = getenv(SRCTREE);
|
||||
if (env) {
|
||||
sprintf(fullname, "%s/%s", env, name);
|
||||
if (!stat(fullname, &buf))
|
||||
return fullname;
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
|
||||
{
|
||||
char *p2;
|
||||
@ -150,14 +258,6 @@ static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
|
||||
conf_warning("symbol value '%s' invalid for %s",
|
||||
p, sym->name);
|
||||
return 1;
|
||||
case S_OTHER:
|
||||
if (*p != '"') {
|
||||
for (p2 = p; *p2 && !isspace(*p2); p2++)
|
||||
;
|
||||
sym->type = S_STRING;
|
||||
goto done;
|
||||
}
|
||||
/* fall through */
|
||||
case S_STRING:
|
||||
if (*p++ != '"')
|
||||
break;
|
||||
@ -176,9 +276,8 @@ static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
|
||||
/* fall through */
|
||||
case S_INT:
|
||||
case S_HEX:
|
||||
done:
|
||||
if (sym_string_valid(sym, p)) {
|
||||
sym->def[def].val = strdup(p);
|
||||
sym->def[def].val = xstrdup(p);
|
||||
sym->flags |= def_flags;
|
||||
} else {
|
||||
if (def != S_DEF_AUTO)
|
||||
@ -201,7 +300,7 @@ static int add_byte(int c, char **lineptr, size_t slen, size_t *n)
|
||||
if (new_size > *n) {
|
||||
new_size += LINE_GROWTH - 1;
|
||||
new_size *= 2;
|
||||
nline = realloc(*lineptr, new_size);
|
||||
nline = xrealloc(*lineptr, new_size);
|
||||
if (!nline)
|
||||
return -1;
|
||||
|
||||
@ -274,10 +373,11 @@ int conf_read_simple(const char *name, int def)
|
||||
if (expr_calc_value(prop->visible.expr) == no ||
|
||||
prop->expr->type != E_SYMBOL)
|
||||
continue;
|
||||
name = conf_expand_value(prop->expr->left.sym->name);
|
||||
sym_calc_value(prop->expr->left.sym);
|
||||
name = sym_get_string_value(prop->expr->left.sym);
|
||||
in = zconf_fopen(name);
|
||||
if (in) {
|
||||
conf_message(_("using defaults found in %s"),
|
||||
conf_message("using defaults found in %s",
|
||||
name);
|
||||
goto load;
|
||||
}
|
||||
@ -290,7 +390,6 @@ load:
|
||||
conf_filename = name;
|
||||
conf_lineno = 0;
|
||||
conf_warnings = 0;
|
||||
conf_unsaved = 0;
|
||||
|
||||
def_flags = SYMBOL_DEF << def;
|
||||
for_all_symbols(i, sym) {
|
||||
@ -327,7 +426,7 @@ load:
|
||||
sym = sym_find(line + 2 + strlen(CONFIG_));
|
||||
if (!sym) {
|
||||
sym_add_change_count(1);
|
||||
goto setsym;
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
sym = sym_lookup(line + 2 + strlen(CONFIG_), 0);
|
||||
@ -357,17 +456,22 @@ load:
|
||||
if (*p2 == '\r')
|
||||
*p2 = 0;
|
||||
}
|
||||
if (def == S_DEF_USER) {
|
||||
sym = sym_find(line + strlen(CONFIG_));
|
||||
if (!sym) {
|
||||
|
||||
sym = sym_find(line + strlen(CONFIG_));
|
||||
if (!sym) {
|
||||
if (def == S_DEF_AUTO)
|
||||
/*
|
||||
* Reading from include/config/auto.conf
|
||||
* If CONFIG_FOO previously existed in
|
||||
* auto.conf but it is missing now,
|
||||
* include/config/foo.h must be touched.
|
||||
*/
|
||||
conf_touch_dep(line + strlen(CONFIG_));
|
||||
else
|
||||
sym_add_change_count(1);
|
||||
goto setsym;
|
||||
}
|
||||
} else {
|
||||
sym = sym_lookup(line + strlen(CONFIG_), 0);
|
||||
if (sym->type == S_UNKNOWN)
|
||||
sym->type = S_OTHER;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (sym->flags & def_flags) {
|
||||
conf_warning("override: reassigning to symbol %s", sym->name);
|
||||
}
|
||||
@ -380,7 +484,7 @@ load:
|
||||
|
||||
continue;
|
||||
}
|
||||
setsym:
|
||||
|
||||
if (sym && sym_is_choice_value(sym)) {
|
||||
struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
|
||||
switch (sym->def[def].tri) {
|
||||
@ -409,6 +513,7 @@ setsym:
|
||||
int conf_read(const char *name)
|
||||
{
|
||||
struct symbol *sym;
|
||||
int conf_unsaved = 0;
|
||||
int i;
|
||||
|
||||
sym_set_change_count(0);
|
||||
@ -422,18 +527,16 @@ int conf_read(const char *name)
|
||||
|
||||
for_all_symbols(i, sym) {
|
||||
sym_calc_value(sym);
|
||||
if (sym_is_choice(sym) || (sym->flags & SYMBOL_AUTO))
|
||||
if (sym_is_choice(sym) || (sym->flags & SYMBOL_NO_WRITE))
|
||||
continue;
|
||||
if (sym_has_value(sym) && (sym->flags & SYMBOL_WRITE)) {
|
||||
/* check that calculated value agrees with saved value */
|
||||
switch (sym->type) {
|
||||
case S_BOOLEAN:
|
||||
case S_TRISTATE:
|
||||
if (sym->def[S_DEF_USER].tri != sym_get_tristate_value(sym))
|
||||
break;
|
||||
if (!sym_is_choice(sym))
|
||||
if (sym->def[S_DEF_USER].tri == sym_get_tristate_value(sym))
|
||||
continue;
|
||||
/* fall through */
|
||||
break;
|
||||
default:
|
||||
if (!strcmp(sym->curr.val, sym->def[S_DEF_USER].val))
|
||||
continue;
|
||||
@ -607,32 +710,12 @@ static struct conf_printer header_printer_cb =
|
||||
.print_comment = header_print_comment,
|
||||
};
|
||||
|
||||
/*
|
||||
* Tristate printer
|
||||
*
|
||||
* This printer is used when generating the `include/config/tristate.conf' file.
|
||||
*/
|
||||
static void
|
||||
tristate_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg)
|
||||
{
|
||||
|
||||
if (sym->type == S_TRISTATE && *value != 'n')
|
||||
fprintf(fp, "%s%s=%c\n", CONFIG_, sym->name, (char)toupper(*value));
|
||||
}
|
||||
|
||||
static struct conf_printer tristate_printer_cb =
|
||||
{
|
||||
.print_symbol = tristate_print_symbol,
|
||||
.print_comment = kconfig_print_comment,
|
||||
};
|
||||
|
||||
static void conf_write_symbol(FILE *fp, struct symbol *sym,
|
||||
struct conf_printer *printer, void *printer_arg)
|
||||
{
|
||||
const char *str;
|
||||
|
||||
switch (sym->type) {
|
||||
case S_OTHER:
|
||||
case S_UNKNOWN:
|
||||
break;
|
||||
case S_STRING:
|
||||
@ -692,7 +775,7 @@ int conf_write_defconfig(const char *filename)
|
||||
goto next_menu;
|
||||
sym->flags &= ~SYMBOL_WRITE;
|
||||
/* If we cannot change the symbol - skip */
|
||||
if (!sym_is_changable(sym))
|
||||
if (!sym_is_changeable(sym))
|
||||
goto next_menu;
|
||||
/* If symbol equals to default value - skip */
|
||||
if (strcmp(sym_get_string_value(sym), sym_get_string_default(sym)) == 0)
|
||||
@ -743,41 +826,36 @@ int conf_write(const char *name)
|
||||
FILE *out;
|
||||
struct symbol *sym;
|
||||
struct menu *menu;
|
||||
const char *basename;
|
||||
const char *str;
|
||||
char dirname[PATH_MAX+1], tmpname[PATH_MAX+1], newname[PATH_MAX+1];
|
||||
char tmpname[PATH_MAX + 1], oldname[PATH_MAX + 1];
|
||||
char *env;
|
||||
int i;
|
||||
bool need_newline = false;
|
||||
|
||||
dirname[0] = 0;
|
||||
if (name && name[0]) {
|
||||
struct stat st;
|
||||
char *slash;
|
||||
if (!name)
|
||||
name = conf_get_configname();
|
||||
|
||||
if (!stat(name, &st) && S_ISDIR(st.st_mode)) {
|
||||
strcpy(dirname, name);
|
||||
strcat(dirname, "/");
|
||||
basename = conf_get_configname();
|
||||
} else if ((slash = strrchr(name, '/'))) {
|
||||
int size = slash - name + 1;
|
||||
memcpy(dirname, name, size);
|
||||
dirname[size] = 0;
|
||||
if (slash[1])
|
||||
basename = slash + 1;
|
||||
else
|
||||
basename = conf_get_configname();
|
||||
} else
|
||||
basename = name;
|
||||
} else
|
||||
basename = conf_get_configname();
|
||||
if (!*name) {
|
||||
fprintf(stderr, "config name is empty\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (is_dir(name)) {
|
||||
fprintf(stderr, "%s: Is a directory\n", name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (make_parent_dir(name))
|
||||
return -1;
|
||||
|
||||
sprintf(newname, "%s%s", dirname, basename);
|
||||
env = getenv("KCONFIG_OVERWRITECONFIG");
|
||||
if (!env || !*env) {
|
||||
sprintf(tmpname, "%s.tmpconfig.%d", dirname, (int)getpid());
|
||||
out = fopen(tmpname, "w");
|
||||
} else {
|
||||
if (env && *env) {
|
||||
*tmpname = 0;
|
||||
out = fopen(newname, "w");
|
||||
out = fopen(name, "w");
|
||||
} else {
|
||||
snprintf(tmpname, sizeof(tmpname), "%s.%d.tmp",
|
||||
name, (int)getpid());
|
||||
out = fopen(tmpname, "w");
|
||||
}
|
||||
if (!out)
|
||||
return 1;
|
||||
@ -798,12 +876,17 @@ int conf_write(const char *name)
|
||||
"#\n"
|
||||
"# %s\n"
|
||||
"#\n", str);
|
||||
} else if (!(sym->flags & SYMBOL_CHOICE)) {
|
||||
need_newline = false;
|
||||
} else if (!(sym->flags & SYMBOL_CHOICE) &&
|
||||
!(sym->flags & SYMBOL_WRITTEN)) {
|
||||
sym_calc_value(sym);
|
||||
if (!(sym->flags & SYMBOL_WRITE))
|
||||
goto next;
|
||||
sym->flags &= ~SYMBOL_WRITE;
|
||||
|
||||
if (need_newline) {
|
||||
fprintf(out, "\n");
|
||||
need_newline = false;
|
||||
}
|
||||
sym->flags |= SYMBOL_WRITTEN;
|
||||
conf_write_symbol(out, sym, &kconfig_printer_cb, NULL);
|
||||
}
|
||||
|
||||
@ -815,6 +898,12 @@ next:
|
||||
if (menu->next)
|
||||
menu = menu->next;
|
||||
else while ((menu = menu->parent)) {
|
||||
if (!menu->sym && menu_is_visible(menu) &&
|
||||
menu != &rootmenu) {
|
||||
str = menu_get_prompt(menu);
|
||||
fprintf(out, "# end of %s\n", str);
|
||||
need_newline = true;
|
||||
}
|
||||
if (menu->next) {
|
||||
menu = menu->next;
|
||||
break;
|
||||
@ -823,41 +912,76 @@ next:
|
||||
}
|
||||
fclose(out);
|
||||
|
||||
for_all_symbols(i, sym)
|
||||
sym->flags &= ~SYMBOL_WRITTEN;
|
||||
|
||||
if (*tmpname) {
|
||||
strcat(dirname, basename);
|
||||
strcat(dirname, ".old");
|
||||
rename(newname, dirname);
|
||||
if (rename(tmpname, newname))
|
||||
if (is_same(name, tmpname)) {
|
||||
conf_message("No change to %s", name);
|
||||
unlink(tmpname);
|
||||
sym_set_change_count(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
snprintf(oldname, sizeof(oldname), "%s.old", name);
|
||||
rename(name, oldname);
|
||||
if (rename(tmpname, name))
|
||||
return 1;
|
||||
}
|
||||
|
||||
conf_message(_("configuration written to %s"), newname);
|
||||
conf_message("configuration written to %s", name);
|
||||
|
||||
sym_set_change_count(0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int conf_split_config(void)
|
||||
/* write a dependency file as used by kbuild to track dependencies */
|
||||
static int conf_write_dep(const char *name)
|
||||
{
|
||||
struct file *file;
|
||||
FILE *out;
|
||||
|
||||
out = fopen("..config.tmp", "w");
|
||||
if (!out)
|
||||
return 1;
|
||||
fprintf(out, "deps_config := \\\n");
|
||||
for (file = file_list; file; file = file->next) {
|
||||
if (file->next)
|
||||
fprintf(out, "\t%s \\\n", file->name);
|
||||
else
|
||||
fprintf(out, "\t%s\n", file->name);
|
||||
}
|
||||
fprintf(out, "\n%s: \\\n"
|
||||
"\t$(deps_config)\n\n", conf_get_autoconfig_name());
|
||||
|
||||
env_write_dep(out, conf_get_autoconfig_name());
|
||||
|
||||
fprintf(out, "\n$(deps_config): ;\n");
|
||||
fclose(out);
|
||||
|
||||
if (make_parent_dir(name))
|
||||
return 1;
|
||||
rename("..config.tmp", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int conf_touch_deps(void)
|
||||
{
|
||||
const char *name;
|
||||
char path[PATH_MAX+1];
|
||||
char *s, *d, c;
|
||||
struct symbol *sym;
|
||||
struct stat sb;
|
||||
int res, i, fd;
|
||||
int res, i;
|
||||
|
||||
strcpy(depfile_path, "include/config/");
|
||||
depfile_prefix_len = strlen(depfile_path);
|
||||
|
||||
name = conf_get_autoconfig_name();
|
||||
conf_read_simple(name, S_DEF_AUTO);
|
||||
sym_calc_value(modules_sym);
|
||||
|
||||
if (chdir("include/config"))
|
||||
return 1;
|
||||
|
||||
res = 0;
|
||||
for_all_symbols(i, sym) {
|
||||
sym_calc_value(sym);
|
||||
if ((sym->flags & SYMBOL_AUTO) || !sym->name)
|
||||
if ((sym->flags & SYMBOL_NO_WRITE) || !sym->name)
|
||||
continue;
|
||||
if (sym->flags & SYMBOL_WRITE) {
|
||||
if (sym->flags & SYMBOL_DEF_AUTO) {
|
||||
@ -906,86 +1030,41 @@ static int conf_split_config(void)
|
||||
* different from 'no').
|
||||
*/
|
||||
|
||||
/* Replace all '_' and append ".h" */
|
||||
s = sym->name;
|
||||
d = path;
|
||||
while ((c = *s++)) {
|
||||
c = tolower(c);
|
||||
*d++ = (c == '_') ? '/' : c;
|
||||
}
|
||||
strcpy(d, ".h");
|
||||
|
||||
/* Assume directory path already exists. */
|
||||
fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
||||
if (fd == -1) {
|
||||
if (errno != ENOENT) {
|
||||
res = 1;
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* Create directory components,
|
||||
* unless they exist already.
|
||||
*/
|
||||
d = path;
|
||||
while ((d = strchr(d, '/'))) {
|
||||
*d = 0;
|
||||
if (stat(path, &sb) && mkdir(path, 0755)) {
|
||||
res = 1;
|
||||
goto out;
|
||||
}
|
||||
*d++ = '/';
|
||||
}
|
||||
/* Try it again. */
|
||||
fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
||||
if (fd == -1) {
|
||||
res = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
close(fd);
|
||||
res = conf_touch_dep(sym->name);
|
||||
if (res)
|
||||
return res;
|
||||
}
|
||||
out:
|
||||
if (chdir("../.."))
|
||||
return 1;
|
||||
|
||||
return res;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int conf_write_autoconf(void)
|
||||
int conf_write_autoconf(int overwrite)
|
||||
{
|
||||
struct symbol *sym;
|
||||
const char *name;
|
||||
FILE *out, *tristate, *out_h;
|
||||
const char *autoconf_name = conf_get_autoconfig_name();
|
||||
FILE *out, *out_h;
|
||||
int i;
|
||||
|
||||
sym_clear_all_valid();
|
||||
if (!overwrite && is_present(autoconf_name))
|
||||
return 0;
|
||||
|
||||
file_write_dep("include/config/auto.conf.cmd");
|
||||
conf_write_dep("include/config/auto.conf.cmd");
|
||||
|
||||
if (conf_split_config())
|
||||
if (conf_touch_deps())
|
||||
return 1;
|
||||
|
||||
out = fopen(".tmpconfig", "w");
|
||||
if (!out)
|
||||
return 1;
|
||||
|
||||
tristate = fopen(".tmpconfig_tristate", "w");
|
||||
if (!tristate) {
|
||||
fclose(out);
|
||||
return 1;
|
||||
}
|
||||
|
||||
out_h = fopen(".tmpconfig.h", "w");
|
||||
if (!out_h) {
|
||||
fclose(out);
|
||||
fclose(tristate);
|
||||
return 1;
|
||||
}
|
||||
|
||||
conf_write_heading(out, &kconfig_printer_cb, NULL);
|
||||
|
||||
conf_write_heading(tristate, &tristate_printer_cb, NULL);
|
||||
|
||||
conf_write_heading(out_h, &header_printer_cb, NULL);
|
||||
|
||||
for_all_symbols(i, sym) {
|
||||
@ -993,33 +1072,28 @@ int conf_write_autoconf(void)
|
||||
if (!(sym->flags & SYMBOL_WRITE) || !sym->name)
|
||||
continue;
|
||||
|
||||
/* write symbol to auto.conf, tristate and header files */
|
||||
/* write symbols to auto.conf and autoconf.h */
|
||||
conf_write_symbol(out, sym, &kconfig_printer_cb, (void *)1);
|
||||
|
||||
conf_write_symbol(tristate, sym, &tristate_printer_cb, (void *)1);
|
||||
|
||||
conf_write_symbol(out_h, sym, &header_printer_cb, NULL);
|
||||
}
|
||||
fclose(out);
|
||||
fclose(tristate);
|
||||
fclose(out_h);
|
||||
|
||||
name = getenv("KCONFIG_AUTOHEADER");
|
||||
if (!name)
|
||||
name = "include/generated/autoconf.h";
|
||||
if (make_parent_dir(name))
|
||||
return 1;
|
||||
if (rename(".tmpconfig.h", name))
|
||||
return 1;
|
||||
name = getenv("KCONFIG_TRISTATE");
|
||||
if (!name)
|
||||
name = "include/config/tristate.conf";
|
||||
if (rename(".tmpconfig_tristate", name))
|
||||
|
||||
if (make_parent_dir(autoconf_name))
|
||||
return 1;
|
||||
name = conf_get_autoconfig_name();
|
||||
/*
|
||||
* This must be the last step, kbuild has a dependency on auto.conf
|
||||
* and this marks the successful completion of the previous steps.
|
||||
*/
|
||||
if (rename(".tmpconfig", name))
|
||||
if (rename(".tmpconfig", autoconf_name))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
@ -1123,7 +1197,7 @@ void set_all_choice_values(struct symbol *csym)
|
||||
bool conf_set_all_new_symbols(enum conf_def_mode mode)
|
||||
{
|
||||
struct symbol *sym, *csym;
|
||||
int i, cnt, pby, pty, ptm; /* pby: probability of boolean = y
|
||||
int i, cnt, pby, pty, ptm; /* pby: probability of bool = y
|
||||
* pty: probability of tristate = y
|
||||
* ptm: probability of tristate = m
|
||||
*/
|
||||
@ -1238,7 +1312,7 @@ bool conf_set_all_new_symbols(enum conf_def_mode mode)
|
||||
|
||||
sym_calc_value(csym);
|
||||
if (mode == def_random)
|
||||
has_changed = randomize_choice_values(csym);
|
||||
has_changed |= randomize_choice_values(csym);
|
||||
else {
|
||||
set_all_choice_values(csym);
|
||||
has_changed = true;
|
||||
@ -1247,3 +1321,18 @@ bool conf_set_all_new_symbols(enum conf_def_mode mode)
|
||||
|
||||
return has_changed;
|
||||
}
|
||||
|
||||
void conf_rewrite_mod_or_yes(enum conf_def_mode mode)
|
||||
{
|
||||
struct symbol *sym;
|
||||
int i;
|
||||
tristate old_val = (mode == def_y2m) ? yes : mod;
|
||||
tristate new_val = (mode == def_y2m) ? mod : yes;
|
||||
|
||||
for_all_symbols(i, sym) {
|
||||
if (sym_get_type(sym) == S_TRISTATE &&
|
||||
sym->def[S_DEF_USER].tri == old_val)
|
||||
sym->def[S_DEF_USER].tri = new_val;
|
||||
}
|
||||
sym_clear_all_valid();
|
||||
}
|
||||
|
216
kconfig/expr.c
216
kconfig/expr.c
@ -1,8 +1,10 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
|
||||
* Released under the terms of the GNU GPL v2.0.
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -11,7 +13,6 @@
|
||||
|
||||
#define DEBUG_EXPR 0
|
||||
|
||||
static int expr_eq(struct expr *e1, struct expr *e2);
|
||||
static struct expr *expr_eliminate_yn(struct expr *e);
|
||||
|
||||
struct expr *expr_alloc_symbol(struct symbol *sym)
|
||||
@ -94,7 +95,7 @@ struct expr *expr_copy(const struct expr *org)
|
||||
e->right.expr = expr_copy(org->right.expr);
|
||||
break;
|
||||
default:
|
||||
printf("can't copy type %d\n", e->type);
|
||||
fprintf(stderr, "can't copy type %d\n", e->type);
|
||||
free(e);
|
||||
e = NULL;
|
||||
break;
|
||||
@ -113,7 +114,7 @@ void expr_free(struct expr *e)
|
||||
break;
|
||||
case E_NOT:
|
||||
expr_free(e->left.expr);
|
||||
return;
|
||||
break;
|
||||
case E_EQUAL:
|
||||
case E_GEQ:
|
||||
case E_GTH:
|
||||
@ -127,7 +128,7 @@ void expr_free(struct expr *e)
|
||||
expr_free(e->right.expr);
|
||||
break;
|
||||
default:
|
||||
printf("how to free type %d?\n", e->type);
|
||||
fprintf(stderr, "how to free type %d?\n", e->type);
|
||||
break;
|
||||
}
|
||||
free(e);
|
||||
@ -138,8 +139,18 @@ static int trans_count;
|
||||
#define e1 (*ep1)
|
||||
#define e2 (*ep2)
|
||||
|
||||
/*
|
||||
* expr_eliminate_eq() helper.
|
||||
*
|
||||
* Walks the two expression trees given in 'ep1' and 'ep2'. Any node that does
|
||||
* not have type 'type' (E_OR/E_AND) is considered a leaf, and is compared
|
||||
* against all other leaves. Two equal leaves are both replaced with either 'y'
|
||||
* or 'n' as appropriate for 'type', to be eliminated later.
|
||||
*/
|
||||
static void __expr_eliminate_eq(enum expr_type type, struct expr **ep1, struct expr **ep2)
|
||||
{
|
||||
/* Recurse down to leaves */
|
||||
|
||||
if (e1->type == type) {
|
||||
__expr_eliminate_eq(type, &e1->left.expr, &e2);
|
||||
__expr_eliminate_eq(type, &e1->right.expr, &e2);
|
||||
@ -150,12 +161,18 @@ static void __expr_eliminate_eq(enum expr_type type, struct expr **ep1, struct e
|
||||
__expr_eliminate_eq(type, &e1, &e2->right.expr);
|
||||
return;
|
||||
}
|
||||
|
||||
/* e1 and e2 are leaves. Compare them. */
|
||||
|
||||
if (e1->type == E_SYMBOL && e2->type == E_SYMBOL &&
|
||||
e1->left.sym == e2->left.sym &&
|
||||
(e1->left.sym == &symbol_yes || e1->left.sym == &symbol_no))
|
||||
return;
|
||||
if (!expr_eq(e1, e2))
|
||||
return;
|
||||
|
||||
/* e1 and e2 are equal leaves. Prepare them for elimination. */
|
||||
|
||||
trans_count++;
|
||||
expr_free(e1); expr_free(e2);
|
||||
switch (type) {
|
||||
@ -172,6 +189,35 @@ static void __expr_eliminate_eq(enum expr_type type, struct expr **ep1, struct e
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Rewrites the expressions 'ep1' and 'ep2' to remove operands common to both.
|
||||
* Example reductions:
|
||||
*
|
||||
* ep1: A && B -> ep1: y
|
||||
* ep2: A && B && C -> ep2: C
|
||||
*
|
||||
* ep1: A || B -> ep1: n
|
||||
* ep2: A || B || C -> ep2: C
|
||||
*
|
||||
* ep1: A && (B && FOO) -> ep1: FOO
|
||||
* ep2: (BAR && B) && A -> ep2: BAR
|
||||
*
|
||||
* ep1: A && (B || C) -> ep1: y
|
||||
* ep2: (C || B) && A -> ep2: y
|
||||
*
|
||||
* Comparisons are done between all operands at the same "level" of && or ||.
|
||||
* For example, in the expression 'e1 && (e2 || e3) && (e4 || e5)', the
|
||||
* following operands will be compared:
|
||||
*
|
||||
* - 'e1', 'e2 || e3', and 'e4 || e5', against each other
|
||||
* - e2 against e3
|
||||
* - e4 against e5
|
||||
*
|
||||
* Parentheses are irrelevant within a single level. 'e1 && (e2 && e3)' and
|
||||
* '(e1 && e2) && e3' are both a single level.
|
||||
*
|
||||
* See __expr_eliminate_eq() as well.
|
||||
*/
|
||||
void expr_eliminate_eq(struct expr **ep1, struct expr **ep2)
|
||||
{
|
||||
if (!e1 || !e2)
|
||||
@ -197,10 +243,23 @@ void expr_eliminate_eq(struct expr **ep1, struct expr **ep2)
|
||||
#undef e1
|
||||
#undef e2
|
||||
|
||||
static int expr_eq(struct expr *e1, struct expr *e2)
|
||||
/*
|
||||
* Returns true if 'e1' and 'e2' are equal, after minor simplification. Two
|
||||
* &&/|| expressions are considered equal if every operand in one expression
|
||||
* equals some operand in the other (operands do not need to appear in the same
|
||||
* order), recursively.
|
||||
*/
|
||||
int expr_eq(struct expr *e1, struct expr *e2)
|
||||
{
|
||||
int res, old_count;
|
||||
|
||||
/*
|
||||
* A NULL expr is taken to be yes, but there's also a different way to
|
||||
* represent yes. expr_is_yes() checks for either representation.
|
||||
*/
|
||||
if (!e1 || !e2)
|
||||
return expr_is_yes(e1) && expr_is_yes(e2);
|
||||
|
||||
if (e1->type != e2->type)
|
||||
return 0;
|
||||
switch (e1->type) {
|
||||
@ -243,6 +302,17 @@ static int expr_eq(struct expr *e1, struct expr *e2)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Recursively performs the following simplifications in-place (as well as the
|
||||
* corresponding simplifications with swapped operands):
|
||||
*
|
||||
* expr && n -> n
|
||||
* expr && y -> expr
|
||||
* expr || n -> expr
|
||||
* expr || y -> y
|
||||
*
|
||||
* Returns the optimized expression.
|
||||
*/
|
||||
static struct expr *expr_eliminate_yn(struct expr *e)
|
||||
{
|
||||
struct expr *tmp;
|
||||
@ -516,12 +586,21 @@ static struct expr *expr_join_and(struct expr *e1, struct expr *e2)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* expr_eliminate_dups() helper.
|
||||
*
|
||||
* Walks the two expression trees given in 'ep1' and 'ep2'. Any node that does
|
||||
* not have type 'type' (E_OR/E_AND) is considered a leaf, and is compared
|
||||
* against all other leaves to look for simplifications.
|
||||
*/
|
||||
static void expr_eliminate_dups1(enum expr_type type, struct expr **ep1, struct expr **ep2)
|
||||
{
|
||||
#define e1 (*ep1)
|
||||
#define e2 (*ep2)
|
||||
struct expr *tmp;
|
||||
|
||||
/* Recurse down to leaves */
|
||||
|
||||
if (e1->type == type) {
|
||||
expr_eliminate_dups1(type, &e1->left.expr, &e2);
|
||||
expr_eliminate_dups1(type, &e1->right.expr, &e2);
|
||||
@ -532,6 +611,9 @@ static void expr_eliminate_dups1(enum expr_type type, struct expr **ep1, struct
|
||||
expr_eliminate_dups1(type, &e1, &e2->right.expr);
|
||||
return;
|
||||
}
|
||||
|
||||
/* e1 and e2 are leaves. Compare and process them. */
|
||||
|
||||
if (e1 == e2)
|
||||
return;
|
||||
|
||||
@ -568,6 +650,17 @@ static void expr_eliminate_dups1(enum expr_type type, struct expr **ep1, struct
|
||||
#undef e2
|
||||
}
|
||||
|
||||
/*
|
||||
* Rewrites 'e' in-place to remove ("join") duplicate and other redundant
|
||||
* operands.
|
||||
*
|
||||
* Example simplifications:
|
||||
*
|
||||
* A || B || A -> A || B
|
||||
* A && B && A=y -> A=y && B
|
||||
*
|
||||
* Returns the deduplicated expression.
|
||||
*/
|
||||
struct expr *expr_eliminate_dups(struct expr *e)
|
||||
{
|
||||
int oldcount;
|
||||
@ -584,6 +677,7 @@ struct expr *expr_eliminate_dups(struct expr *e)
|
||||
;
|
||||
}
|
||||
if (!trans_count)
|
||||
/* No simplifications done in this pass. We're done */
|
||||
break;
|
||||
e = expr_eliminate_yn(e);
|
||||
}
|
||||
@ -591,6 +685,12 @@ struct expr *expr_eliminate_dups(struct expr *e)
|
||||
return e;
|
||||
}
|
||||
|
||||
/*
|
||||
* Performs various simplifications involving logical operators and
|
||||
* comparisons.
|
||||
*
|
||||
* Allocates and returns a new expression.
|
||||
*/
|
||||
struct expr *expr_transform(struct expr *e)
|
||||
{
|
||||
struct expr *tmp;
|
||||
@ -805,6 +905,20 @@ bool expr_depends_symbol(struct expr *dep, struct symbol *sym)
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Inserts explicit comparisons of type 'type' to symbol 'sym' into the
|
||||
* expression 'e'.
|
||||
*
|
||||
* Examples transformations for type == E_UNEQUAL, sym == &symbol_no:
|
||||
*
|
||||
* A -> A!=n
|
||||
* !A -> A=n
|
||||
* A && B -> !(A=n || B=n)
|
||||
* A || B -> !(A=n && B=n)
|
||||
* A && (B || C) -> !(A=n || (B=n && C=n))
|
||||
*
|
||||
* Allocates and returns a new expression.
|
||||
*/
|
||||
struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym)
|
||||
{
|
||||
struct expr *e1, *e2;
|
||||
@ -874,7 +988,6 @@ enum string_value_kind {
|
||||
k_string,
|
||||
k_signed,
|
||||
k_unsigned,
|
||||
k_invalid
|
||||
};
|
||||
|
||||
union string_value {
|
||||
@ -905,13 +1018,10 @@ static enum string_value_kind expr_parse_string(const char *str,
|
||||
val->u = strtoull(str, &tail, 16);
|
||||
kind = k_unsigned;
|
||||
break;
|
||||
case S_STRING:
|
||||
case S_UNKNOWN:
|
||||
default:
|
||||
val->s = strtoll(str, &tail, 0);
|
||||
kind = k_signed;
|
||||
break;
|
||||
default:
|
||||
return k_invalid;
|
||||
}
|
||||
return !errno && !*tail && tail > str && isxdigit(tail[-1])
|
||||
? kind : k_string;
|
||||
@ -967,13 +1077,7 @@ tristate expr_calc_value(struct expr *e)
|
||||
|
||||
if (k1 == k_string || k2 == k_string)
|
||||
res = strcmp(str1, str2);
|
||||
else if (k1 == k_invalid || k2 == k_invalid) {
|
||||
if (e->type != E_EQUAL && e->type != E_UNEQUAL) {
|
||||
printf("Cannot compare \"%s\" and \"%s\"\n", str1, str2);
|
||||
return no;
|
||||
}
|
||||
res = strcmp(str1, str2);
|
||||
} else if (k1 == k_unsigned || k2 == k_unsigned)
|
||||
else if (k1 == k_unsigned || k2 == k_unsigned)
|
||||
res = (lval.u > rval.u) - (lval.u < rval.u);
|
||||
else /* if (k1 == k_signed && k2 == k_signed) */
|
||||
res = (lval.s > rval.s) - (lval.s < rval.s);
|
||||
@ -1031,49 +1135,9 @@ static int expr_compare_type(enum expr_type t1, enum expr_type t2)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline struct expr *
|
||||
expr_get_leftmost_symbol(const struct expr *e)
|
||||
{
|
||||
|
||||
if (e == NULL)
|
||||
return NULL;
|
||||
|
||||
while (e->type != E_SYMBOL)
|
||||
e = e->left.expr;
|
||||
|
||||
return expr_copy(e);
|
||||
}
|
||||
|
||||
/*
|
||||
* Given expression `e1' and `e2', returns the leaf of the longest
|
||||
* sub-expression of `e1' not containing 'e2.
|
||||
*/
|
||||
struct expr *expr_simplify_unmet_dep(struct expr *e1, struct expr *e2)
|
||||
{
|
||||
struct expr *ret;
|
||||
|
||||
switch (e1->type) {
|
||||
case E_OR:
|
||||
return expr_alloc_and(
|
||||
expr_simplify_unmet_dep(e1->left.expr, e2),
|
||||
expr_simplify_unmet_dep(e1->right.expr, e2));
|
||||
case E_AND: {
|
||||
struct expr *e;
|
||||
e = expr_alloc_and(expr_copy(e1), expr_copy(e2));
|
||||
e = expr_eliminate_dups(e);
|
||||
ret = (!expr_eq(e, e1)) ? e1 : NULL;
|
||||
expr_free(e);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ret = e1;
|
||||
break;
|
||||
}
|
||||
|
||||
return expr_get_leftmost_symbol(ret);
|
||||
}
|
||||
|
||||
void expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken)
|
||||
void expr_print(struct expr *e,
|
||||
void (*fn)(void *, struct symbol *, const char *),
|
||||
void *data, int prevtoken)
|
||||
{
|
||||
if (!e) {
|
||||
fn(data, NULL, "y");
|
||||
@ -1207,3 +1271,33 @@ void expr_gstr_print(struct expr *e, struct gstr *gs)
|
||||
{
|
||||
expr_print(e, expr_print_gstr_helper, gs, E_NONE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Transform the top level "||" tokens into newlines and prepend each
|
||||
* line with a minus. This makes expressions much easier to read.
|
||||
* Suitable for reverse dependency expressions.
|
||||
*/
|
||||
static void expr_print_revdep(struct expr *e,
|
||||
void (*fn)(void *, struct symbol *, const char *),
|
||||
void *data, tristate pr_type, const char **title)
|
||||
{
|
||||
if (e->type == E_OR) {
|
||||
expr_print_revdep(e->left.expr, fn, data, pr_type, title);
|
||||
expr_print_revdep(e->right.expr, fn, data, pr_type, title);
|
||||
} else if (expr_calc_value(e) == pr_type) {
|
||||
if (*title) {
|
||||
fn(data, NULL, *title);
|
||||
*title = NULL;
|
||||
}
|
||||
|
||||
fn(data, NULL, " - ");
|
||||
expr_print(e, fn, data, E_NONE);
|
||||
fn(data, NULL, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
void expr_gstr_print_revdep(struct expr *e, struct gstr *gs,
|
||||
tristate pr_type, const char *title)
|
||||
{
|
||||
expr_print_revdep(e, expr_print_gstr_helper, gs, pr_type, &title);
|
||||
}
|
||||
|
108
kconfig/expr.h
108
kconfig/expr.h
@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
|
||||
* Released under the terms of the GNU GPL v2.0.
|
||||
*/
|
||||
|
||||
#ifndef EXPR_H
|
||||
@ -62,7 +62,7 @@ struct symbol_value {
|
||||
};
|
||||
|
||||
enum symbol_type {
|
||||
S_UNKNOWN, S_BOOLEAN, S_TRISTATE, S_INT, S_HEX, S_STRING, S_OTHER
|
||||
S_UNKNOWN, S_BOOLEAN, S_TRISTATE, S_INT, S_HEX, S_STRING
|
||||
};
|
||||
|
||||
/* enum values are used as index to symbol.def[] */
|
||||
@ -74,21 +74,64 @@ enum {
|
||||
S_DEF_COUNT
|
||||
};
|
||||
|
||||
/*
|
||||
* Represents a configuration symbol.
|
||||
*
|
||||
* Choices are represented as a special kind of symbol and have the
|
||||
* SYMBOL_CHOICE bit set in 'flags'.
|
||||
*/
|
||||
struct symbol {
|
||||
/* The next symbol in the same bucket in the symbol hash table */
|
||||
struct symbol *next;
|
||||
|
||||
/* The name of the symbol, e.g. "FOO" for 'config FOO' */
|
||||
char *name;
|
||||
|
||||
/* S_BOOLEAN, S_TRISTATE, ... */
|
||||
enum symbol_type type;
|
||||
|
||||
/*
|
||||
* The calculated value of the symbol. The SYMBOL_VALID bit is set in
|
||||
* 'flags' when this is up to date. Note that this value might differ
|
||||
* from the user value set in e.g. a .config file, due to visibility.
|
||||
*/
|
||||
struct symbol_value curr;
|
||||
|
||||
/*
|
||||
* Values for the symbol provided from outside. def[S_DEF_USER] holds
|
||||
* the .config value.
|
||||
*/
|
||||
struct symbol_value def[S_DEF_COUNT];
|
||||
|
||||
/*
|
||||
* An upper bound on the tristate value the user can set for the symbol
|
||||
* if it is a boolean or tristate. Calculated from prompt dependencies,
|
||||
* which also inherit dependencies from enclosing menus, choices, and
|
||||
* ifs. If 'n', the user value will be ignored.
|
||||
*
|
||||
* Symbols lacking prompts always have visibility 'n'.
|
||||
*/
|
||||
tristate visible;
|
||||
|
||||
/* SYMBOL_* flags */
|
||||
int flags;
|
||||
|
||||
/* List of properties. See prop_type. */
|
||||
struct property *prop;
|
||||
|
||||
/* Dependencies from enclosing menus, choices, and ifs */
|
||||
struct expr_value dir_dep;
|
||||
|
||||
/* Reverse dependencies through being selected by other symbols */
|
||||
struct expr_value rev_dep;
|
||||
|
||||
/*
|
||||
* "Weak" reverse dependencies through being implied by other symbols
|
||||
*/
|
||||
struct expr_value implied;
|
||||
};
|
||||
|
||||
#define for_all_symbols(i, sym) for (i = 0; i < SYMBOL_HASHSIZE; i++) for (sym = symbol_hash[i]; sym; sym = sym->next) if (sym->type != S_OTHER)
|
||||
#define for_all_symbols(i, sym) for (i = 0; i < SYMBOL_HASHSIZE; i++) for (sym = symbol_hash[i]; sym; sym = sym->next)
|
||||
|
||||
#define SYMBOL_CONST 0x0001 /* symbol is const */
|
||||
#define SYMBOL_CHECK 0x0008 /* used during dependency checking */
|
||||
@ -98,7 +141,8 @@ struct symbol {
|
||||
#define SYMBOL_OPTIONAL 0x0100 /* choice is optional - values can be 'n' */
|
||||
#define SYMBOL_WRITE 0x0200 /* write symbol to file (KCONFIG_CONFIG) */
|
||||
#define SYMBOL_CHANGED 0x0400 /* ? */
|
||||
#define SYMBOL_AUTO 0x1000 /* value from environment variable */
|
||||
#define SYMBOL_WRITTEN 0x0800 /* track info to avoid double-write to .config */
|
||||
#define SYMBOL_NO_WRITE 0x1000 /* Symbol for internal use only; it will not be written */
|
||||
#define SYMBOL_CHECKED 0x2000 /* used during dependency checking */
|
||||
#define SYMBOL_WARNED 0x8000 /* warning has been issued */
|
||||
|
||||
@ -128,24 +172,25 @@ struct symbol {
|
||||
* config BAZ
|
||||
* int "BAZ Value"
|
||||
* range 1..255
|
||||
*
|
||||
* Please, also check parser.y:print_symbol() when modifying the
|
||||
* list of property types!
|
||||
*/
|
||||
enum prop_type {
|
||||
P_UNKNOWN,
|
||||
P_PROMPT, /* prompt "foo prompt" or "BAZ Value" */
|
||||
P_COMMENT, /* text associated with a comment */
|
||||
P_MENU, /* prompt associated with a menuconfig option */
|
||||
P_MENU, /* prompt associated with a menu or menuconfig symbol */
|
||||
P_DEFAULT, /* default y */
|
||||
P_CHOICE, /* choice value */
|
||||
P_SELECT, /* select BAR */
|
||||
P_IMPLY, /* imply BAR */
|
||||
P_RANGE, /* range 7..100 (for a symbol) */
|
||||
P_ENV, /* value from environment variable */
|
||||
P_SYMBOL, /* where a symbol is defined */
|
||||
};
|
||||
|
||||
struct property {
|
||||
struct property *next; /* next property - null if last */
|
||||
struct symbol *sym; /* the symbol for which the property is associated */
|
||||
enum prop_type type; /* type of property */
|
||||
const char *text; /* the prompt value - P_PROMPT, P_MENU, P_COMMENT */
|
||||
struct expr_value visible;
|
||||
@ -166,22 +211,67 @@ struct property {
|
||||
for (st = sym->prop; st; st = st->next) \
|
||||
if (st->text)
|
||||
|
||||
/*
|
||||
* Represents a node in the menu tree, as seen in e.g. menuconfig (though used
|
||||
* for all front ends). Each symbol, menu, etc. defined in the Kconfig files
|
||||
* gets a node. A symbol defined in multiple locations gets one node at each
|
||||
* location.
|
||||
*/
|
||||
struct menu {
|
||||
/* The next menu node at the same level */
|
||||
struct menu *next;
|
||||
|
||||
/* The parent menu node, corresponding to e.g. a menu or choice */
|
||||
struct menu *parent;
|
||||
|
||||
/* The first child menu node, for e.g. menus and choices */
|
||||
struct menu *list;
|
||||
|
||||
/*
|
||||
* The symbol associated with the menu node. Choices are implemented as
|
||||
* a special kind of symbol. NULL for menus, comments, and ifs.
|
||||
*/
|
||||
struct symbol *sym;
|
||||
|
||||
/*
|
||||
* The prompt associated with the node. This holds the prompt for a
|
||||
* symbol as well as the text for a menu or comment, along with the
|
||||
* type (P_PROMPT, P_MENU, etc.)
|
||||
*/
|
||||
struct property *prompt;
|
||||
|
||||
/*
|
||||
* 'visible if' dependencies. If more than one is given, they will be
|
||||
* ANDed together.
|
||||
*/
|
||||
struct expr *visibility;
|
||||
|
||||
/*
|
||||
* Ordinary dependencies from e.g. 'depends on' and 'if', ANDed
|
||||
* together
|
||||
*/
|
||||
struct expr *dep;
|
||||
|
||||
/* MENU_* flags */
|
||||
unsigned int flags;
|
||||
|
||||
/* Any help text associated with the node */
|
||||
char *help;
|
||||
|
||||
/* The location where the menu node appears in the Kconfig files */
|
||||
struct file *file;
|
||||
int lineno;
|
||||
|
||||
/* For use by front ends that need to store auxiliary data */
|
||||
void *data;
|
||||
};
|
||||
|
||||
/*
|
||||
* Set on a menu node when the corresponding symbol changes state in some way.
|
||||
* Can be checked by front ends.
|
||||
*/
|
||||
#define MENU_CHANGED 0x0001
|
||||
|
||||
#define MENU_ROOT 0x0002
|
||||
|
||||
struct jump_key {
|
||||
@ -210,6 +300,7 @@ struct expr *expr_alloc_or(struct expr *e1, struct expr *e2);
|
||||
struct expr *expr_copy(const struct expr *org);
|
||||
void expr_free(struct expr *e);
|
||||
void expr_eliminate_eq(struct expr **ep1, struct expr **ep2);
|
||||
int expr_eq(struct expr *e1, struct expr *e2);
|
||||
tristate expr_calc_value(struct expr *e);
|
||||
struct expr *expr_trans_bool(struct expr *e);
|
||||
struct expr *expr_eliminate_dups(struct expr *e);
|
||||
@ -217,11 +308,12 @@ struct expr *expr_transform(struct expr *e);
|
||||
int expr_contains_symbol(struct expr *dep, struct symbol *sym);
|
||||
bool expr_depends_symbol(struct expr *dep, struct symbol *sym);
|
||||
struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym);
|
||||
struct expr *expr_simplify_unmet_dep(struct expr *e1, struct expr *e2);
|
||||
|
||||
void expr_fprint(struct expr *e, FILE *out);
|
||||
struct gstr; /* forward */
|
||||
void expr_gstr_print(struct expr *e, struct gstr *gs);
|
||||
void expr_gstr_print_revdep(struct expr *e, struct gstr *gs,
|
||||
tristate pr_type, const char *title);
|
||||
|
||||
static inline int expr_is_yes(struct expr *e)
|
||||
{
|
||||
|
@ -1,54 +0,0 @@
|
||||
|
||||
static struct kconf_id kconf_id_array[] = {
|
||||
{ "mainmenu", T_MAINMENU, TF_COMMAND },
|
||||
{ "menu", T_MENU, TF_COMMAND },
|
||||
{ "endmenu", T_ENDMENU, TF_COMMAND },
|
||||
{ "source", T_SOURCE, TF_COMMAND },
|
||||
{ "choice", T_CHOICE, TF_COMMAND },
|
||||
{ "endchoice", T_ENDCHOICE, TF_COMMAND },
|
||||
{ "comment", T_COMMENT, TF_COMMAND },
|
||||
{ "config", T_CONFIG, TF_COMMAND },
|
||||
{ "menuconfig", T_MENUCONFIG, TF_COMMAND },
|
||||
{ "help", T_HELP, TF_COMMAND },
|
||||
{ "---help---", T_HELP, TF_COMMAND },
|
||||
{ "if", T_IF, TF_COMMAND|TF_PARAM },
|
||||
{ "endif", T_ENDIF, TF_COMMAND },
|
||||
{ "depends", T_DEPENDS, TF_COMMAND },
|
||||
{ "optional", T_OPTIONAL, TF_COMMAND },
|
||||
{ "default", T_DEFAULT, TF_COMMAND, S_UNKNOWN },
|
||||
{ "prompt", T_PROMPT, TF_COMMAND },
|
||||
{ "tristate", T_TYPE, TF_COMMAND, S_TRISTATE },
|
||||
{ "def_tristate", T_DEFAULT, TF_COMMAND, S_TRISTATE },
|
||||
{ "bool", T_TYPE, TF_COMMAND, S_BOOLEAN },
|
||||
{ "boolean", T_TYPE, TF_COMMAND, S_BOOLEAN },
|
||||
{ "def_bool", T_DEFAULT, TF_COMMAND, S_BOOLEAN },
|
||||
{ "int", T_TYPE, TF_COMMAND, S_INT },
|
||||
{ "hex", T_TYPE, TF_COMMAND, S_HEX },
|
||||
{ "string", T_TYPE, TF_COMMAND, S_STRING },
|
||||
{ "select", T_SELECT, TF_COMMAND },
|
||||
{ "imply", T_IMPLY, TF_COMMAND },
|
||||
{ "range", T_RANGE, TF_COMMAND },
|
||||
{ "visible", T_VISIBLE, TF_COMMAND },
|
||||
{ "option", T_OPTION, TF_COMMAND },
|
||||
{ "on", T_ON, TF_PARAM },
|
||||
{ "modules", T_OPT_MODULES, TF_OPTION },
|
||||
{ "defconfig_list", T_OPT_DEFCONFIG_LIST, TF_OPTION },
|
||||
{ "env", T_OPT_ENV, TF_OPTION },
|
||||
{ "allnoconfig_y", T_OPT_ALLNOCONFIG_Y, TF_OPTION },
|
||||
};
|
||||
|
||||
#define KCONF_ID_ARRAY_SIZE (sizeof(kconf_id_array)/sizeof(struct kconf_id))
|
||||
|
||||
static const struct kconf_id *kconf_id_lookup(register const char *str, register unsigned int len)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < KCONF_ID_ARRAY_SIZE; i++) {
|
||||
struct kconf_id *id = kconf_id_array+i;
|
||||
int l = strlen(id->name);
|
||||
|
||||
if (len == l && !memcmp(str, id->name, len))
|
||||
return id;
|
||||
}
|
||||
return NULL;
|
||||
}
|
471
kconfig/lexer.l
Normal file
471
kconfig/lexer.l
Normal file
@ -0,0 +1,471 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
|
||||
*/
|
||||
%option nostdinit noyywrap never-interactive full ecs
|
||||
%option 8bit nodefault yylineno
|
||||
%x ASSIGN_VAL HELP STRING
|
||||
%{
|
||||
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "lkc.h"
|
||||
#include "parser.tab.h"
|
||||
|
||||
#define YY_DECL static int yylex1(void)
|
||||
|
||||
#define START_STRSIZE 16
|
||||
|
||||
static struct {
|
||||
struct file *file;
|
||||
int lineno;
|
||||
} current_pos;
|
||||
|
||||
static int prev_prev_token = T_EOL;
|
||||
static int prev_token = T_EOL;
|
||||
static char *text;
|
||||
static int text_size, text_asize;
|
||||
|
||||
struct buffer {
|
||||
struct buffer *parent;
|
||||
YY_BUFFER_STATE state;
|
||||
};
|
||||
|
||||
static struct buffer *current_buf;
|
||||
|
||||
static int last_ts, first_ts;
|
||||
|
||||
static char *expand_token(const char *in, size_t n);
|
||||
static void append_expanded_string(const char *in);
|
||||
static void zconf_endhelp(void);
|
||||
static void zconf_endfile(void);
|
||||
|
||||
static void new_string(void)
|
||||
{
|
||||
text = xmalloc(START_STRSIZE);
|
||||
text_asize = START_STRSIZE;
|
||||
text_size = 0;
|
||||
*text = 0;
|
||||
}
|
||||
|
||||
static void append_string(const char *str, int size)
|
||||
{
|
||||
int new_size = text_size + size + 1;
|
||||
if (new_size > text_asize) {
|
||||
new_size += START_STRSIZE - 1;
|
||||
new_size &= -START_STRSIZE;
|
||||
text = xrealloc(text, new_size);
|
||||
text_asize = new_size;
|
||||
}
|
||||
memcpy(text + text_size, str, size);
|
||||
text_size += size;
|
||||
text[text_size] = 0;
|
||||
}
|
||||
|
||||
static void alloc_string(const char *str, int size)
|
||||
{
|
||||
text = xmalloc(size + 1);
|
||||
memcpy(text, str, size);
|
||||
text[size] = 0;
|
||||
}
|
||||
|
||||
static void warn_ignored_character(char chr)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"%s:%d:warning: ignoring unsupported character '%c'\n",
|
||||
current_file->name, yylineno, chr);
|
||||
}
|
||||
%}
|
||||
|
||||
n [A-Za-z0-9_-]
|
||||
|
||||
%%
|
||||
int str = 0;
|
||||
int ts, i;
|
||||
|
||||
#.* /* ignore comment */
|
||||
[ \t]* /* whitespaces */
|
||||
\\\n /* escaped new line */
|
||||
\n return T_EOL;
|
||||
"allnoconfig_y" return T_ALLNOCONFIG_Y;
|
||||
"bool" return T_BOOL;
|
||||
"choice" return T_CHOICE;
|
||||
"comment" return T_COMMENT;
|
||||
"config" return T_CONFIG;
|
||||
"def_bool" return T_DEF_BOOL;
|
||||
"def_tristate" return T_DEF_TRISTATE;
|
||||
"default" return T_DEFAULT;
|
||||
"defconfig_list" return T_DEFCONFIG_LIST;
|
||||
"depends" return T_DEPENDS;
|
||||
"endchoice" return T_ENDCHOICE;
|
||||
"endif" return T_ENDIF;
|
||||
"endmenu" return T_ENDMENU;
|
||||
"help" return T_HELP;
|
||||
"hex" return T_HEX;
|
||||
"if" return T_IF;
|
||||
"imply" return T_IMPLY;
|
||||
"int" return T_INT;
|
||||
"mainmenu" return T_MAINMENU;
|
||||
"menu" return T_MENU;
|
||||
"menuconfig" return T_MENUCONFIG;
|
||||
"modules" return T_MODULES;
|
||||
"on" return T_ON;
|
||||
"option" return T_OPTION;
|
||||
"optional" return T_OPTIONAL;
|
||||
"prompt" return T_PROMPT;
|
||||
"range" return T_RANGE;
|
||||
"select" return T_SELECT;
|
||||
"source" return T_SOURCE;
|
||||
"string" return T_STRING;
|
||||
"tristate" return T_TRISTATE;
|
||||
"visible" return T_VISIBLE;
|
||||
"||" return T_OR;
|
||||
"&&" return T_AND;
|
||||
"=" return T_EQUAL;
|
||||
"!=" return T_UNEQUAL;
|
||||
"<" return T_LESS;
|
||||
"<=" return T_LESS_EQUAL;
|
||||
">" return T_GREATER;
|
||||
">=" return T_GREATER_EQUAL;
|
||||
"!" return T_NOT;
|
||||
"(" return T_OPEN_PAREN;
|
||||
")" return T_CLOSE_PAREN;
|
||||
":=" return T_COLON_EQUAL;
|
||||
"+=" return T_PLUS_EQUAL;
|
||||
\"|\' {
|
||||
str = yytext[0];
|
||||
new_string();
|
||||
BEGIN(STRING);
|
||||
}
|
||||
{n}+ {
|
||||
alloc_string(yytext, yyleng);
|
||||
yylval.string = text;
|
||||
return T_WORD;
|
||||
}
|
||||
({n}|$)+ {
|
||||
/* this token includes at least one '$' */
|
||||
yylval.string = expand_token(yytext, yyleng);
|
||||
if (strlen(yylval.string))
|
||||
return T_WORD;
|
||||
free(yylval.string);
|
||||
}
|
||||
. warn_ignored_character(*yytext);
|
||||
|
||||
<ASSIGN_VAL>{
|
||||
[^[:blank:]\n]+.* {
|
||||
alloc_string(yytext, yyleng);
|
||||
yylval.string = text;
|
||||
return T_ASSIGN_VAL;
|
||||
}
|
||||
\n { BEGIN(INITIAL); return T_EOL; }
|
||||
.
|
||||
}
|
||||
|
||||
<STRING>{
|
||||
"$".* append_expanded_string(yytext);
|
||||
[^$'"\\\n]+ {
|
||||
append_string(yytext, yyleng);
|
||||
}
|
||||
\\.? {
|
||||
append_string(yytext + 1, yyleng - 1);
|
||||
}
|
||||
\'|\" {
|
||||
if (str == yytext[0]) {
|
||||
BEGIN(INITIAL);
|
||||
yylval.string = text;
|
||||
return T_WORD_QUOTE;
|
||||
} else
|
||||
append_string(yytext, 1);
|
||||
}
|
||||
\n {
|
||||
fprintf(stderr,
|
||||
"%s:%d:warning: multi-line strings not supported\n",
|
||||
zconf_curname(), zconf_lineno());
|
||||
unput('\n');
|
||||
BEGIN(INITIAL);
|
||||
yylval.string = text;
|
||||
return T_WORD_QUOTE;
|
||||
}
|
||||
<<EOF>> {
|
||||
BEGIN(INITIAL);
|
||||
yylval.string = text;
|
||||
return T_WORD_QUOTE;
|
||||
}
|
||||
}
|
||||
|
||||
<HELP>{
|
||||
[ \t]+ {
|
||||
ts = 0;
|
||||
for (i = 0; i < yyleng; i++) {
|
||||
if (yytext[i] == '\t')
|
||||
ts = (ts & ~7) + 8;
|
||||
else
|
||||
ts++;
|
||||
}
|
||||
last_ts = ts;
|
||||
if (first_ts) {
|
||||
if (ts < first_ts) {
|
||||
zconf_endhelp();
|
||||
return T_HELPTEXT;
|
||||
}
|
||||
ts -= first_ts;
|
||||
while (ts > 8) {
|
||||
append_string(" ", 8);
|
||||
ts -= 8;
|
||||
}
|
||||
append_string(" ", ts);
|
||||
}
|
||||
}
|
||||
[ \t]*\n/[^ \t\n] {
|
||||
zconf_endhelp();
|
||||
return T_HELPTEXT;
|
||||
}
|
||||
[ \t]*\n {
|
||||
append_string("\n", 1);
|
||||
}
|
||||
[^ \t\n].* {
|
||||
while (yyleng) {
|
||||
if ((yytext[yyleng-1] != ' ') && (yytext[yyleng-1] != '\t'))
|
||||
break;
|
||||
yyleng--;
|
||||
}
|
||||
append_string(yytext, yyleng);
|
||||
if (!first_ts)
|
||||
first_ts = last_ts;
|
||||
}
|
||||
<<EOF>> {
|
||||
zconf_endhelp();
|
||||
return T_HELPTEXT;
|
||||
}
|
||||
}
|
||||
|
||||
<<EOF>> {
|
||||
BEGIN(INITIAL);
|
||||
|
||||
if (prev_token != T_EOL && prev_token != T_HELPTEXT)
|
||||
fprintf(stderr, "%s:%d:warning: no new line at end of file\n",
|
||||
current_file->name, yylineno);
|
||||
|
||||
if (current_file) {
|
||||
zconf_endfile();
|
||||
return T_EOL;
|
||||
}
|
||||
fclose(yyin);
|
||||
yyterminate();
|
||||
}
|
||||
|
||||
%%
|
||||
|
||||
/* second stage lexer */
|
||||
int yylex(void)
|
||||
{
|
||||
int token;
|
||||
|
||||
repeat:
|
||||
token = yylex1();
|
||||
|
||||
if (prev_token == T_EOL || prev_token == T_HELPTEXT) {
|
||||
if (token == T_EOL) {
|
||||
/* Do not pass unneeded T_EOL to the parser. */
|
||||
goto repeat;
|
||||
} else {
|
||||
/*
|
||||
* For the parser, update file/lineno at the first token
|
||||
* of each statement. Generally, \n is a statement
|
||||
* terminator in Kconfig, but it is not always true
|
||||
* because \n could be escaped by a backslash.
|
||||
*/
|
||||
current_pos.file = current_file;
|
||||
current_pos.lineno = yylineno;
|
||||
}
|
||||
}
|
||||
|
||||
if (prev_prev_token == T_EOL && prev_token == T_WORD &&
|
||||
(token == T_EQUAL || token == T_COLON_EQUAL || token == T_PLUS_EQUAL))
|
||||
BEGIN(ASSIGN_VAL);
|
||||
|
||||
prev_prev_token = prev_token;
|
||||
prev_token = token;
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
static char *expand_token(const char *in, size_t n)
|
||||
{
|
||||
char *out;
|
||||
int c;
|
||||
char c2;
|
||||
const char *rest, *end;
|
||||
|
||||
new_string();
|
||||
append_string(in, n);
|
||||
|
||||
/* get the whole line because we do not know the end of token. */
|
||||
while ((c = input()) != EOF) {
|
||||
if (c == '\n') {
|
||||
unput(c);
|
||||
break;
|
||||
}
|
||||
c2 = c;
|
||||
append_string(&c2, 1);
|
||||
}
|
||||
|
||||
rest = text;
|
||||
out = expand_one_token(&rest);
|
||||
|
||||
/* push back unused characters to the input stream */
|
||||
end = rest + strlen(rest);
|
||||
while (end > rest)
|
||||
unput(*--end);
|
||||
|
||||
free(text);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
static void append_expanded_string(const char *str)
|
||||
{
|
||||
const char *end;
|
||||
char *res;
|
||||
|
||||
str++;
|
||||
|
||||
res = expand_dollar(&str);
|
||||
|
||||
/* push back unused characters to the input stream */
|
||||
end = str + strlen(str);
|
||||
while (end > str)
|
||||
unput(*--end);
|
||||
|
||||
append_string(res, strlen(res));
|
||||
|
||||
free(res);
|
||||
}
|
||||
|
||||
void zconf_starthelp(void)
|
||||
{
|
||||
new_string();
|
||||
last_ts = first_ts = 0;
|
||||
BEGIN(HELP);
|
||||
}
|
||||
|
||||
static void zconf_endhelp(void)
|
||||
{
|
||||
yylval.string = text;
|
||||
BEGIN(INITIAL);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Try to open specified file with following names:
|
||||
* ./name
|
||||
* $(srctree)/name
|
||||
* The latter is used when srctree is separate from objtree
|
||||
* when compiling the kernel.
|
||||
* Return NULL if file is not found.
|
||||
*/
|
||||
FILE *zconf_fopen(const char *name)
|
||||
{
|
||||
char *env, fullname[PATH_MAX+1];
|
||||
FILE *f;
|
||||
|
||||
f = fopen(name, "r");
|
||||
if (!f && name != NULL && name[0] != '/') {
|
||||
env = getenv(SRCTREE);
|
||||
if (env) {
|
||||
snprintf(fullname, sizeof(fullname),
|
||||
"%s/%s", env, name);
|
||||
f = fopen(fullname, "r");
|
||||
}
|
||||
}
|
||||
return f;
|
||||
}
|
||||
|
||||
void zconf_initscan(const char *name)
|
||||
{
|
||||
yyin = zconf_fopen(name);
|
||||
if (!yyin) {
|
||||
fprintf(stderr, "can't find file %s\n", name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
current_buf = xmalloc(sizeof(*current_buf));
|
||||
memset(current_buf, 0, sizeof(*current_buf));
|
||||
|
||||
current_file = file_lookup(name);
|
||||
yylineno = 1;
|
||||
}
|
||||
|
||||
void zconf_nextfile(const char *name)
|
||||
{
|
||||
struct file *iter;
|
||||
struct file *file = file_lookup(name);
|
||||
struct buffer *buf = xmalloc(sizeof(*buf));
|
||||
memset(buf, 0, sizeof(*buf));
|
||||
|
||||
current_buf->state = YY_CURRENT_BUFFER;
|
||||
yyin = zconf_fopen(file->name);
|
||||
if (!yyin) {
|
||||
fprintf(stderr, "%s:%d: can't open file \"%s\"\n",
|
||||
zconf_curname(), zconf_lineno(), file->name);
|
||||
exit(1);
|
||||
}
|
||||
yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
|
||||
buf->parent = current_buf;
|
||||
current_buf = buf;
|
||||
|
||||
current_file->lineno = yylineno;
|
||||
file->parent = current_file;
|
||||
|
||||
for (iter = current_file; iter; iter = iter->parent) {
|
||||
if (!strcmp(iter->name, file->name)) {
|
||||
fprintf(stderr,
|
||||
"Recursive inclusion detected.\n"
|
||||
"Inclusion path:\n"
|
||||
" current file : %s\n", file->name);
|
||||
iter = file;
|
||||
do {
|
||||
iter = iter->parent;
|
||||
fprintf(stderr, " included from: %s:%d\n",
|
||||
iter->name, iter->lineno - 1);
|
||||
} while (strcmp(iter->name, file->name));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
yylineno = 1;
|
||||
current_file = file;
|
||||
}
|
||||
|
||||
static void zconf_endfile(void)
|
||||
{
|
||||
struct buffer *parent;
|
||||
|
||||
current_file = current_file->parent;
|
||||
if (current_file)
|
||||
yylineno = current_file->lineno;
|
||||
|
||||
parent = current_buf->parent;
|
||||
if (parent) {
|
||||
fclose(yyin);
|
||||
yy_delete_buffer(YY_CURRENT_BUFFER);
|
||||
yy_switch_to_buffer(parent->state);
|
||||
}
|
||||
free(current_buf);
|
||||
current_buf = parent;
|
||||
}
|
||||
|
||||
int zconf_lineno(void)
|
||||
{
|
||||
return current_pos.lineno;
|
||||
}
|
||||
|
||||
const char *zconf_curname(void)
|
||||
{
|
||||
return current_pos.file ? current_pos.file->name : "<none>";
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
|
||||
* Released under the terms of the GNU GPL v2.0.
|
||||
*/
|
||||
|
||||
#ifndef LKC_H
|
||||
@ -8,15 +8,6 @@
|
||||
|
||||
#include "expr.h"
|
||||
|
||||
#ifndef KBUILD_NO_NLS
|
||||
# include <libintl.h>
|
||||
#else
|
||||
static inline const char *gettext(const char *txt) { return txt; }
|
||||
static inline void textdomain(const char *domainname) {}
|
||||
static inline void bindtextdomain(const char *name, const char *dir) {}
|
||||
static inline char *bind_textdomain_codeset(const char *dn, char *c) { return c; }
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@ -29,11 +20,6 @@ extern "C" {
|
||||
#define PACKAGE "linux"
|
||||
#endif
|
||||
|
||||
#define LOCALEDIR "/usr/share/locale"
|
||||
|
||||
#define _(text) gettext(text)
|
||||
#define N_(text) (text)
|
||||
|
||||
#ifndef CONFIG_
|
||||
#define CONFIG_ "CONFIG_"
|
||||
#endif
|
||||
@ -44,30 +30,17 @@ static inline const char *CONFIG_prefix(void)
|
||||
#undef CONFIG_
|
||||
#define CONFIG_ CONFIG_prefix()
|
||||
|
||||
#define TF_COMMAND 0x0001
|
||||
#define TF_PARAM 0x0002
|
||||
#define TF_OPTION 0x0004
|
||||
|
||||
enum conf_def_mode {
|
||||
def_default,
|
||||
def_yes,
|
||||
def_mod,
|
||||
def_y2m,
|
||||
def_m2y,
|
||||
def_no,
|
||||
def_random
|
||||
};
|
||||
|
||||
#define T_OPT_MODULES 1
|
||||
#define T_OPT_DEFCONFIG_LIST 2
|
||||
#define T_OPT_ENV 3
|
||||
#define T_OPT_ALLNOCONFIG_Y 4
|
||||
|
||||
struct kconf_id {
|
||||
const char *name;
|
||||
int token;
|
||||
unsigned int flags;
|
||||
enum symbol_type stype;
|
||||
};
|
||||
|
||||
extern int yylineno;
|
||||
void zconfdump(FILE *out);
|
||||
void zconf_starthelp(void);
|
||||
FILE *zconf_fopen(const char *name);
|
||||
@ -78,11 +51,10 @@ const char *zconf_curname(void);
|
||||
|
||||
/* confdata.c */
|
||||
const char *conf_get_configname(void);
|
||||
const char *conf_get_autoconfig_name(void);
|
||||
char *conf_get_default_confname(void);
|
||||
void sym_set_change_count(int count);
|
||||
void sym_add_change_count(int count);
|
||||
bool conf_set_all_new_symbols(enum conf_def_mode mode);
|
||||
void conf_rewrite_mod_or_yes(enum conf_def_mode mode);
|
||||
void set_all_choice_values(struct symbol *csym);
|
||||
|
||||
/* confdata.c and expr.c */
|
||||
@ -94,27 +66,16 @@ static inline void xfwrite(const void *str, size_t len, size_t count, FILE *out)
|
||||
fprintf(stderr, "Error in writing or end of file.\n");
|
||||
}
|
||||
|
||||
/* menu.c */
|
||||
void _menu_init(void);
|
||||
void menu_warn(struct menu *menu, const char *fmt, ...);
|
||||
struct menu *menu_add_menu(void);
|
||||
void menu_end_menu(void);
|
||||
void menu_add_entry(struct symbol *sym);
|
||||
void menu_end_entry(void);
|
||||
void menu_add_dep(struct expr *dep);
|
||||
void menu_add_visibility(struct expr *dep);
|
||||
struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep);
|
||||
void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep);
|
||||
void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep);
|
||||
void menu_add_option(int token, char *arg);
|
||||
void menu_finalize(struct menu *parent);
|
||||
void menu_set_type(int type);
|
||||
|
||||
/* util.c */
|
||||
struct file *file_lookup(const char *name);
|
||||
int file_write_dep(const char *name);
|
||||
void *xmalloc(size_t size);
|
||||
void *xcalloc(size_t nmemb, size_t size);
|
||||
void *xrealloc(void *p, size_t size);
|
||||
char *xstrdup(const char *s);
|
||||
char *xstrndup(const char *s, size_t n);
|
||||
|
||||
/* lexer.l */
|
||||
int yylex(void);
|
||||
|
||||
struct gstr {
|
||||
size_t len;
|
||||
@ -131,17 +92,43 @@ void str_append(struct gstr *gs, const char *s);
|
||||
void str_printf(struct gstr *gs, const char *fmt, ...);
|
||||
const char *str_get(struct gstr *gs);
|
||||
|
||||
/* symbol.c */
|
||||
extern struct expr *sym_env_list;
|
||||
/* menu.c */
|
||||
void _menu_init(void);
|
||||
void menu_warn(struct menu *menu, const char *fmt, ...);
|
||||
struct menu *menu_add_menu(void);
|
||||
void menu_end_menu(void);
|
||||
void menu_add_entry(struct symbol *sym);
|
||||
void menu_add_dep(struct expr *dep);
|
||||
void menu_add_visibility(struct expr *dep);
|
||||
struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep);
|
||||
void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep);
|
||||
void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep);
|
||||
void menu_add_option_modules(void);
|
||||
void menu_add_option_defconfig_list(void);
|
||||
void menu_add_option_allnoconfig_y(void);
|
||||
void menu_finalize(struct menu *parent);
|
||||
void menu_set_type(int type);
|
||||
|
||||
void sym_init(void);
|
||||
extern struct menu rootmenu;
|
||||
|
||||
bool menu_is_empty(struct menu *menu);
|
||||
bool menu_is_visible(struct menu *menu);
|
||||
bool menu_has_prompt(struct menu *menu);
|
||||
const char *menu_get_prompt(struct menu *menu);
|
||||
struct menu *menu_get_root_menu(struct menu *menu);
|
||||
struct menu *menu_get_parent_menu(struct menu *menu);
|
||||
bool menu_has_help(struct menu *menu);
|
||||
const char *menu_get_help(struct menu *menu);
|
||||
struct gstr get_relations_str(struct symbol **sym_arr, struct list_head *head);
|
||||
void menu_get_ext_help(struct menu *menu, struct gstr *help);
|
||||
|
||||
/* symbol.c */
|
||||
void sym_clear_all_valid(void);
|
||||
struct symbol *sym_choice_default(struct symbol *sym);
|
||||
struct property *sym_get_range_prop(struct symbol *sym);
|
||||
const char *sym_get_string_default(struct symbol *sym);
|
||||
struct symbol *sym_check_deps(struct symbol *sym);
|
||||
struct property *prop_alloc(enum prop_type type, struct symbol *sym);
|
||||
struct symbol *prop_get_symbol(struct property *prop);
|
||||
struct property *sym_get_env_prop(struct symbol *sym);
|
||||
|
||||
static inline tristate sym_get_tristate_value(struct symbol *sym)
|
||||
{
|
||||
|
@ -7,31 +7,16 @@ int conf_read(const char *name);
|
||||
int conf_read_simple(const char *name, int);
|
||||
int conf_write_defconfig(const char *name);
|
||||
int conf_write(const char *name);
|
||||
int conf_write_autoconf(void);
|
||||
int conf_write_autoconf(int overwrite);
|
||||
bool conf_get_changed(void);
|
||||
void conf_set_changed_callback(void (*fn)(void));
|
||||
void conf_set_message_callback(void (*fn)(const char *fmt, va_list ap));
|
||||
|
||||
/* menu.c */
|
||||
extern struct menu rootmenu;
|
||||
|
||||
bool menu_is_empty(struct menu *menu);
|
||||
bool menu_is_visible(struct menu *menu);
|
||||
bool menu_has_prompt(struct menu *menu);
|
||||
const char * menu_get_prompt(struct menu *menu);
|
||||
struct menu * menu_get_root_menu(struct menu *menu);
|
||||
struct menu * menu_get_parent_menu(struct menu *menu);
|
||||
bool menu_has_help(struct menu *menu);
|
||||
const char * menu_get_help(struct menu *menu);
|
||||
struct gstr get_relations_str(struct symbol **sym_arr, struct list_head *head);
|
||||
void menu_get_ext_help(struct menu *menu, struct gstr *help);
|
||||
void conf_set_message_callback(void (*fn)(const char *s));
|
||||
|
||||
/* symbol.c */
|
||||
extern struct symbol * symbol_hash[SYMBOL_HASHSIZE];
|
||||
|
||||
struct symbol * sym_lookup(const char *name, int flags);
|
||||
struct symbol * sym_find(const char *name);
|
||||
const char * sym_expand_string_value(const char *in);
|
||||
const char * sym_escape_string_value(const char *in);
|
||||
struct symbol ** sym_re_search(const char *pattern);
|
||||
const char * sym_type_name(enum symbol_type type);
|
||||
@ -43,11 +28,24 @@ tristate sym_toggle_tristate_value(struct symbol *sym);
|
||||
bool sym_string_valid(struct symbol *sym, const char *newval);
|
||||
bool sym_string_within_range(struct symbol *sym, const char *str);
|
||||
bool sym_set_string_value(struct symbol *sym, const char *newval);
|
||||
bool sym_is_changable(struct symbol *sym);
|
||||
bool sym_is_changeable(struct symbol *sym);
|
||||
struct property * sym_get_choice_prop(struct symbol *sym);
|
||||
const char * sym_get_string_value(struct symbol *sym);
|
||||
|
||||
const char * prop_get_type_name(enum prop_type type);
|
||||
|
||||
/* preprocess.c */
|
||||
enum variable_flavor {
|
||||
VAR_SIMPLE,
|
||||
VAR_RECURSIVE,
|
||||
VAR_APPEND,
|
||||
};
|
||||
void env_write_dep(FILE *f, const char *auto_conf_name);
|
||||
void variable_add(const char *name, const char *value,
|
||||
enum variable_flavor flavor);
|
||||
void variable_all_del(void);
|
||||
char *expand_dollar(const char **str);
|
||||
char *expand_one_token(const char **str);
|
||||
|
||||
/* expr.c */
|
||||
void expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken);
|
||||
|
@ -1,4 +1,4 @@
|
||||
This is NOT the official version of dialog. This version has been
|
||||
significantly modified from the original. It is for use by the Linux
|
||||
kernel configuration script. Please do not bother Savio Lam with
|
||||
kernel configuration script. Please do not bother Savio Lam with
|
||||
questions about this program.
|
||||
|
@ -1,92 +0,0 @@
|
||||
#!/bin/sh
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
# Check ncurses compatibility
|
||||
|
||||
# What library to link
|
||||
ldflags()
|
||||
{
|
||||
pkg-config --libs ncursesw 2>/dev/null && exit
|
||||
pkg-config --libs ncurses 2>/dev/null && exit
|
||||
for ext in so a dll.a dylib ; do
|
||||
for lib in ncursesw ncurses curses ; do
|
||||
$cc -print-file-name=lib${lib}.${ext} | grep -q /
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "-l${lib}"
|
||||
exit
|
||||
fi
|
||||
done
|
||||
done
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Where is ncurses.h?
|
||||
ccflags()
|
||||
{
|
||||
if pkg-config --cflags ncursesw 2>/dev/null; then
|
||||
echo '-DCURSES_LOC="<ncurses.h>" -DNCURSES_WIDECHAR=1'
|
||||
elif pkg-config --cflags ncurses 2>/dev/null; then
|
||||
echo '-DCURSES_LOC="<ncurses.h>"'
|
||||
elif [ -f /usr/include/ncursesw/curses.h ]; then
|
||||
echo '-I/usr/include/ncursesw -DCURSES_LOC="<curses.h>"'
|
||||
echo ' -DNCURSES_WIDECHAR=1'
|
||||
elif [ -f /usr/include/ncurses/ncurses.h ]; then
|
||||
echo '-I/usr/include/ncurses -DCURSES_LOC="<ncurses.h>"'
|
||||
elif [ -f /usr/include/ncurses/curses.h ]; then
|
||||
echo '-I/usr/include/ncurses -DCURSES_LOC="<curses.h>"'
|
||||
elif [ -f /usr/include/ncurses.h ]; then
|
||||
echo '-DCURSES_LOC="<ncurses.h>"'
|
||||
else
|
||||
echo '-DCURSES_LOC="<curses.h>"'
|
||||
fi
|
||||
}
|
||||
|
||||
# Temp file, try to clean up after us
|
||||
tmp=.lxdialog.tmp
|
||||
trap "rm -f $tmp" 0 1 2 3 15
|
||||
|
||||
# Check if we can link to ncurses
|
||||
check() {
|
||||
$cc -x c - -o $tmp 2>/dev/null <<'EOF'
|
||||
#include CURSES_LOC
|
||||
main() {}
|
||||
EOF
|
||||
if [ $? != 0 ]; then
|
||||
echo " *** Unable to find the ncurses libraries or the" 1>&2
|
||||
echo " *** required header files." 1>&2
|
||||
echo " *** 'make menuconfig' requires the ncurses libraries." 1>&2
|
||||
echo " *** " 1>&2
|
||||
echo " *** Install ncurses (ncurses-devel) and try again." 1>&2
|
||||
echo " *** " 1>&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
usage() {
|
||||
printf "Usage: $0 [-check compiler options|-ccflags|-ldflags compiler options]\n"
|
||||
}
|
||||
|
||||
if [ $# -eq 0 ]; then
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cc=""
|
||||
case "$1" in
|
||||
"-check")
|
||||
shift
|
||||
cc="$@"
|
||||
check
|
||||
;;
|
||||
"-ccflags")
|
||||
ccflags
|
||||
;;
|
||||
"-ldflags")
|
||||
shift
|
||||
cc="$@"
|
||||
ldflags
|
||||
;;
|
||||
"*")
|
||||
usage
|
||||
exit 1
|
||||
;;
|
||||
esac
|
@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* checklist.c -- implements the checklist box
|
||||
*
|
||||
@ -5,20 +6,6 @@
|
||||
* Stuart Herbert - S.Herbert@sheffield.ac.uk: radiolist extension
|
||||
* Alessandro Rubini - rubini@ipvvis.unipv.it: merged the two
|
||||
* MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "dialog.h"
|
||||
@ -103,8 +90,8 @@ static void print_buttons(WINDOW * dialog, int height, int width, int selected)
|
||||
int x = width / 2 - 11;
|
||||
int y = height - 2;
|
||||
|
||||
print_button(dialog, gettext("Select"), y, x, selected == 0);
|
||||
print_button(dialog, gettext(" Help "), y, x + 14, selected == 1);
|
||||
print_button(dialog, "Select", y, x, selected == 0);
|
||||
print_button(dialog, " Help ", y, x + 14, selected == 1);
|
||||
|
||||
wmove(dialog, y, x + 1 + 14 * selected);
|
||||
wrefresh(dialog);
|
||||
|
@ -1,21 +1,8 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* dialog.h -- common declarations for all dialog modules
|
||||
*
|
||||
* AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
@ -26,16 +13,10 @@
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifndef KBUILD_NO_NLS
|
||||
# include <libintl.h>
|
||||
#else
|
||||
# define gettext(Msgid) ((const char *) (Msgid))
|
||||
#endif
|
||||
|
||||
#ifdef __sun__
|
||||
#define CURS_MACROS
|
||||
#endif
|
||||
#include CURSES_LOC
|
||||
#include <ncurses.h>
|
||||
|
||||
/*
|
||||
* Colors in ncurses 1.9.9e do not work properly since foreground and
|
||||
|
@ -1,22 +1,9 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* inputbox.c -- implements the input box
|
||||
*
|
||||
* ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
|
||||
* MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "dialog.h"
|
||||
@ -31,8 +18,8 @@ static void print_buttons(WINDOW * dialog, int height, int width, int selected)
|
||||
int x = width / 2 - 11;
|
||||
int y = height - 2;
|
||||
|
||||
print_button(dialog, gettext(" Ok "), y, x, selected == 0);
|
||||
print_button(dialog, gettext(" Help "), y, x + 14, selected == 1);
|
||||
print_button(dialog, " Ok ", y, x, selected == 0);
|
||||
print_button(dialog, " Help ", y, x + 14, selected == 1);
|
||||
|
||||
wmove(dialog, y, x + 1 + 14 * selected);
|
||||
wrefresh(dialog);
|
||||
@ -126,7 +113,8 @@ do_resize:
|
||||
case KEY_DOWN:
|
||||
break;
|
||||
case KEY_BACKSPACE:
|
||||
case 127:
|
||||
case 8: /* ^H */
|
||||
case 127: /* ^? */
|
||||
if (pos) {
|
||||
wattrset(dialog, dlg.inputbox.atr);
|
||||
if (input_x == 0) {
|
||||
|
@ -1,22 +1,9 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* menubox.c -- implements the menu box
|
||||
*
|
||||
* ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
|
||||
* MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcapw@cfw.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -157,11 +144,11 @@ static void print_buttons(WINDOW * win, int height, int width, int selected)
|
||||
int x = width / 2 - 28;
|
||||
int y = height - 2;
|
||||
|
||||
print_button(win, gettext("Select"), y, x, selected == 0);
|
||||
print_button(win, gettext(" Exit "), y, x + 12, selected == 1);
|
||||
print_button(win, gettext(" Help "), y, x + 24, selected == 2);
|
||||
print_button(win, gettext(" Save "), y, x + 36, selected == 3);
|
||||
print_button(win, gettext(" Load "), y, x + 48, selected == 4);
|
||||
print_button(win, "Select", y, x, selected == 0);
|
||||
print_button(win, " Exit ", y, x + 12, selected == 1);
|
||||
print_button(win, " Help ", y, x + 24, selected == 2);
|
||||
print_button(win, " Save ", y, x + 36, selected == 3);
|
||||
print_button(win, " Load ", y, x + 48, selected == 4);
|
||||
|
||||
wmove(win, y, x + 1 + 12 * selected);
|
||||
wrefresh(win);
|
||||
|
@ -1,22 +1,9 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* textbox.c -- implements the text box
|
||||
*
|
||||
* ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
|
||||
* MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "dialog.h"
|
||||
@ -129,7 +116,7 @@ do_resize:
|
||||
|
||||
print_title(dialog, title, width);
|
||||
|
||||
print_button(dialog, gettext(" Exit "), height - 2, width / 2 - 4, TRUE);
|
||||
print_button(dialog, " Exit ", height - 2, width / 2 - 4, TRUE);
|
||||
wnoutrefresh(dialog);
|
||||
getyx(dialog, cur_y, cur_x); /* Save cursor position */
|
||||
|
||||
|
@ -1,22 +1,9 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* util.c
|
||||
*
|
||||
* ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
|
||||
* MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
|
@ -1,22 +1,9 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* yesno.c -- implements the yes/no box
|
||||
*
|
||||
* ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
|
||||
* MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "dialog.h"
|
||||
@ -29,8 +16,8 @@ static void print_buttons(WINDOW * dialog, int height, int width, int selected)
|
||||
int x = width / 2 - 10;
|
||||
int y = height - 2;
|
||||
|
||||
print_button(dialog, gettext(" Yes "), y, x, selected == 0);
|
||||
print_button(dialog, gettext(" No "), y, x + 13, selected == 1);
|
||||
print_button(dialog, " Yes ", y, x, selected == 0);
|
||||
print_button(dialog, " No ", y, x + 13, selected == 1);
|
||||
|
||||
wmove(dialog, y, x + 1 + 13 * selected);
|
||||
wrefresh(dialog);
|
||||
|
165
kconfig/mconf.c
165
kconfig/mconf.c
@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
|
||||
* Released under the terms of the GNU GPL v2.0.
|
||||
*
|
||||
* Introduced single menu mode (show all sub-menus in one large tree).
|
||||
* 2002-11-06 Petr Baudis <pasky@ucw.cz>
|
||||
@ -15,14 +15,14 @@
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <locale.h>
|
||||
|
||||
#include "lkc.h"
|
||||
#include "lxdialog/dialog.h"
|
||||
|
||||
static const char mconf_readme[] = N_(
|
||||
static const char mconf_readme[] =
|
||||
"Overview\n"
|
||||
"--------\n"
|
||||
"This interface lets you select features and parameters for the build.\n"
|
||||
@ -171,37 +171,37 @@ static const char mconf_readme[] = N_(
|
||||
" blackbg => selects a color scheme with black background\n"
|
||||
" classic => theme with blue background. The classic look\n"
|
||||
" bluetitle => an LCD friendly version of classic. (default)\n"
|
||||
"\n"),
|
||||
menu_instructions[] = N_(
|
||||
"\n",
|
||||
menu_instructions[] =
|
||||
"Arrow keys navigate the menu. "
|
||||
"<Enter> selects submenus ---> (or empty submenus ----). "
|
||||
"Highlighted letters are hotkeys. "
|
||||
"Pressing <Y> includes, <N> excludes, <M> modularizes features. "
|
||||
"Press <Esc><Esc> to exit, <?> for Help, </> for Search. "
|
||||
"Legend: [*] built-in [ ] excluded <M> module < > module capable"),
|
||||
radiolist_instructions[] = N_(
|
||||
"Legend: [*] built-in [ ] excluded <M> module < > module capable",
|
||||
radiolist_instructions[] =
|
||||
"Use the arrow keys to navigate this window or "
|
||||
"press the hotkey of the item you wish to select "
|
||||
"followed by the <SPACE BAR>. "
|
||||
"Press <?> for additional information about this option."),
|
||||
inputbox_instructions_int[] = N_(
|
||||
"Press <?> for additional information about this option.",
|
||||
inputbox_instructions_int[] =
|
||||
"Please enter a decimal value. "
|
||||
"Fractions will not be accepted. "
|
||||
"Use the <TAB> key to move from the input field to the buttons below it."),
|
||||
inputbox_instructions_hex[] = N_(
|
||||
"Use the <TAB> key to move from the input field to the buttons below it.",
|
||||
inputbox_instructions_hex[] =
|
||||
"Please enter a hexadecimal value. "
|
||||
"Use the <TAB> key to move from the input field to the buttons below it."),
|
||||
inputbox_instructions_string[] = N_(
|
||||
"Use the <TAB> key to move from the input field to the buttons below it.",
|
||||
inputbox_instructions_string[] =
|
||||
"Please enter a string value. "
|
||||
"Use the <TAB> key to move from the input field to the buttons below it."),
|
||||
setmod_text[] = N_(
|
||||
"Use the <TAB> key to move from the input field to the buttons below it.",
|
||||
setmod_text[] =
|
||||
"This feature depends on another which has been configured as a module.\n"
|
||||
"As a result, this feature will be built as a module."),
|
||||
load_config_text[] = N_(
|
||||
"As a result, this feature will be built as a module.",
|
||||
load_config_text[] =
|
||||
"Enter the name of the configuration file you wish to load. "
|
||||
"Accept the name shown to restore the configuration you "
|
||||
"last retrieved. Leave blank to abort."),
|
||||
load_config_help[] = N_(
|
||||
"last retrieved. Leave blank to abort.",
|
||||
load_config_help[] =
|
||||
"\n"
|
||||
"For various reasons, one may wish to keep several different\n"
|
||||
"configurations available on a single machine.\n"
|
||||
@ -211,11 +211,11 @@ load_config_help[] = N_(
|
||||
"configuration.\n"
|
||||
"\n"
|
||||
"If you are uncertain, then you have probably never used alternate\n"
|
||||
"configuration files. You should therefore leave this blank to abort.\n"),
|
||||
save_config_text[] = N_(
|
||||
"configuration files. You should therefore leave this blank to abort.\n",
|
||||
save_config_text[] =
|
||||
"Enter a filename to which this configuration should be saved "
|
||||
"as an alternate. Leave blank to abort."),
|
||||
save_config_help[] = N_(
|
||||
"as an alternate. Leave blank to abort.",
|
||||
save_config_help[] =
|
||||
"\n"
|
||||
"For various reasons, one may wish to keep different configurations\n"
|
||||
"available on a single machine.\n"
|
||||
@ -225,8 +225,8 @@ save_config_help[] = N_(
|
||||
"configuration options you have selected at that time.\n"
|
||||
"\n"
|
||||
"If you are uncertain what all this means then you should probably\n"
|
||||
"leave this blank.\n"),
|
||||
search_help[] = N_(
|
||||
"leave this blank.\n",
|
||||
search_help[] =
|
||||
"\n"
|
||||
"Search for symbols and display their relations.\n"
|
||||
"Regular expressions are allowed.\n"
|
||||
@ -246,7 +246,7 @@ search_help[] = N_(
|
||||
" Selected by: BAR [=n]\n"
|
||||
"-----------------------------------------------------------------\n"
|
||||
"o The line 'Type:' shows the type of the configuration option for\n"
|
||||
" this symbol (boolean, tristate, string, ...)\n"
|
||||
" this symbol (bool, tristate, string, ...)\n"
|
||||
"o The line 'Prompt:' shows the text used in the menu structure for\n"
|
||||
" this symbol\n"
|
||||
"o The 'Defined at' line tells at what file / line number the symbol\n"
|
||||
@ -271,7 +271,7 @@ search_help[] = N_(
|
||||
"Examples: USB => find all symbols containing USB\n"
|
||||
" ^USB => find all symbols starting with USB\n"
|
||||
" USB$ => find all symbols ending with USB\n"
|
||||
"\n");
|
||||
"\n";
|
||||
|
||||
static int indent;
|
||||
static struct menu *current_menu;
|
||||
@ -400,19 +400,19 @@ static void search_conf(void)
|
||||
struct subtitle_part stpart;
|
||||
|
||||
title = str_new();
|
||||
str_printf( &title, _("Enter (sub)string or regexp to search for "
|
||||
"(with or without \"%s\")"), CONFIG_);
|
||||
str_printf( &title, "Enter (sub)string or regexp to search for "
|
||||
"(with or without \"%s\")", CONFIG_);
|
||||
|
||||
again:
|
||||
dialog_clear();
|
||||
dres = dialog_inputbox(_("Search Configuration Parameter"),
|
||||
dres = dialog_inputbox("Search Configuration Parameter",
|
||||
str_get(&title),
|
||||
10, 75, "");
|
||||
switch (dres) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
show_helptext(_("Search Configuration"), search_help);
|
||||
show_helptext("Search Configuration", search_help);
|
||||
goto again;
|
||||
default:
|
||||
str_free(&title);
|
||||
@ -443,7 +443,7 @@ again:
|
||||
|
||||
res = get_relations_str(sym_arr, &head);
|
||||
set_subtitle();
|
||||
dres = show_textbox_ext(_("Search Results"), (char *)
|
||||
dres = show_textbox_ext("Search Results", (char *)
|
||||
str_get(&res), 0, 0, keys, &vscroll,
|
||||
&hscroll, &update_text, (void *)
|
||||
&data);
|
||||
@ -491,7 +491,6 @@ static void build_conf(struct menu *menu)
|
||||
switch (prop->type) {
|
||||
case P_MENU:
|
||||
child_count++;
|
||||
prompt = _(prompt);
|
||||
if (single_menu_mode) {
|
||||
item_make("%s%*c%s",
|
||||
menu->data ? "-->" : "++>",
|
||||
@ -508,7 +507,7 @@ static void build_conf(struct menu *menu)
|
||||
case P_COMMENT:
|
||||
if (prompt) {
|
||||
child_count++;
|
||||
item_make(" %*c*** %s ***", indent + 1, ' ', _(prompt));
|
||||
item_make(" %*c*** %s ***", indent + 1, ' ', prompt);
|
||||
item_set_tag(':');
|
||||
item_set_data(menu);
|
||||
}
|
||||
@ -516,7 +515,7 @@ static void build_conf(struct menu *menu)
|
||||
default:
|
||||
if (prompt) {
|
||||
child_count++;
|
||||
item_make("---%*c%s", indent + 1, ' ', _(prompt));
|
||||
item_make("---%*c%s", indent + 1, ' ', prompt);
|
||||
item_set_tag(':');
|
||||
item_set_data(menu);
|
||||
}
|
||||
@ -538,7 +537,7 @@ static void build_conf(struct menu *menu)
|
||||
}
|
||||
|
||||
val = sym_get_tristate_value(sym);
|
||||
if (sym_is_changable(sym)) {
|
||||
if (sym_is_changeable(sym)) {
|
||||
switch (type) {
|
||||
case S_BOOLEAN:
|
||||
item_make("[%c]", val == no ? ' ' : '*');
|
||||
@ -560,10 +559,10 @@ static void build_conf(struct menu *menu)
|
||||
item_set_data(menu);
|
||||
}
|
||||
|
||||
item_add_str("%*c%s", indent + 1, ' ', _(menu_get_prompt(menu)));
|
||||
item_add_str("%*c%s", indent + 1, ' ', menu_get_prompt(menu));
|
||||
if (val == yes) {
|
||||
if (def_menu) {
|
||||
item_add_str(" (%s)", _(menu_get_prompt(def_menu)));
|
||||
item_add_str(" (%s)", menu_get_prompt(def_menu));
|
||||
item_add_str(" --->");
|
||||
if (def_menu->list) {
|
||||
indent += 2;
|
||||
@ -575,7 +574,7 @@ static void build_conf(struct menu *menu)
|
||||
}
|
||||
} else {
|
||||
if (menu == current_menu) {
|
||||
item_make("---%*c%s", indent + 1, ' ', _(menu_get_prompt(menu)));
|
||||
item_make("---%*c%s", indent + 1, ' ', menu_get_prompt(menu));
|
||||
item_set_tag(':');
|
||||
item_set_data(menu);
|
||||
goto conf_childs;
|
||||
@ -589,7 +588,7 @@ static void build_conf(struct menu *menu)
|
||||
} else {
|
||||
switch (type) {
|
||||
case S_BOOLEAN:
|
||||
if (sym_is_changable(sym))
|
||||
if (sym_is_changeable(sym))
|
||||
item_make("[%c]", val == no ? ' ' : '*');
|
||||
else
|
||||
item_make("-%c-", val == no ? ' ' : '*');
|
||||
@ -602,7 +601,7 @@ static void build_conf(struct menu *menu)
|
||||
case mod: ch = 'M'; break;
|
||||
default: ch = ' '; break;
|
||||
}
|
||||
if (sym_is_changable(sym)) {
|
||||
if (sym_is_changeable(sym)) {
|
||||
if (sym->rev_dep.tri == mod)
|
||||
item_make("{%c}", ch);
|
||||
else
|
||||
@ -618,17 +617,17 @@ static void build_conf(struct menu *menu)
|
||||
tmp = indent - tmp + 4;
|
||||
if (tmp < 0)
|
||||
tmp = 0;
|
||||
item_add_str("%*c%s%s", tmp, ' ', _(menu_get_prompt(menu)),
|
||||
(sym_has_value(sym) || !sym_is_changable(sym)) ?
|
||||
"" : _(" (NEW)"));
|
||||
item_add_str("%*c%s%s", tmp, ' ', menu_get_prompt(menu),
|
||||
(sym_has_value(sym) || !sym_is_changeable(sym)) ?
|
||||
"" : " (NEW)");
|
||||
item_set_tag('s');
|
||||
item_set_data(menu);
|
||||
goto conf_childs;
|
||||
}
|
||||
}
|
||||
item_add_str("%*c%s%s", indent + 1, ' ', _(menu_get_prompt(menu)),
|
||||
(sym_has_value(sym) || !sym_is_changable(sym)) ?
|
||||
"" : _(" (NEW)"));
|
||||
item_add_str("%*c%s%s", indent + 1, ' ', menu_get_prompt(menu),
|
||||
(sym_has_value(sym) || !sym_is_changeable(sym)) ?
|
||||
"" : " (NEW)");
|
||||
if (menu->prompt->type == P_MENU) {
|
||||
item_add_str(" %s", menu_is_empty(menu) ? "----" : "--->");
|
||||
return;
|
||||
@ -665,8 +664,8 @@ static void conf(struct menu *menu, struct menu *active_menu)
|
||||
break;
|
||||
set_subtitle();
|
||||
dialog_clear();
|
||||
res = dialog_menu(prompt ? _(prompt) : _("Main Menu"),
|
||||
_(menu_instructions),
|
||||
res = dialog_menu(prompt ? prompt : "Main Menu",
|
||||
menu_instructions,
|
||||
active_menu, &s_scroll);
|
||||
if (res == 1 || res == KEY_ESC || res == -ERRDISPLAYTOOSMALL)
|
||||
break;
|
||||
@ -708,7 +707,7 @@ static void conf(struct menu *menu, struct menu *active_menu)
|
||||
show_help(submenu);
|
||||
else {
|
||||
reset_subtitle();
|
||||
show_helptext(_("README"), _(mconf_readme));
|
||||
show_helptext("README", mconf_readme);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
@ -773,16 +772,13 @@ static void show_helptext(const char *title, const char *text)
|
||||
show_textbox(title, text, 0, 0);
|
||||
}
|
||||
|
||||
static void conf_message_callback(const char *fmt, va_list ap)
|
||||
static void conf_message_callback(const char *s)
|
||||
{
|
||||
char buf[PATH_MAX+1];
|
||||
|
||||
vsnprintf(buf, sizeof(buf), fmt, ap);
|
||||
if (save_and_exit) {
|
||||
if (!silent)
|
||||
printf("%s", buf);
|
||||
printf("%s", s);
|
||||
} else {
|
||||
show_textbox(NULL, buf, 6, 60);
|
||||
show_textbox(NULL, s, 6, 60);
|
||||
}
|
||||
}
|
||||
|
||||
@ -793,13 +789,13 @@ static void show_help(struct menu *menu)
|
||||
help.max_width = getmaxx(stdscr) - 10;
|
||||
menu_get_ext_help(menu, &help);
|
||||
|
||||
show_helptext(_(menu_get_prompt(menu)), str_get(&help));
|
||||
show_helptext(menu_get_prompt(menu), str_get(&help));
|
||||
str_free(&help);
|
||||
}
|
||||
|
||||
static void conf_choice(struct menu *menu)
|
||||
{
|
||||
const char *prompt = _(menu_get_prompt(menu));
|
||||
const char *prompt = menu_get_prompt(menu);
|
||||
struct menu *child;
|
||||
struct symbol *active;
|
||||
|
||||
@ -814,9 +810,9 @@ static void conf_choice(struct menu *menu)
|
||||
if (!menu_is_visible(child))
|
||||
continue;
|
||||
if (child->sym)
|
||||
item_make("%s", _(menu_get_prompt(child)));
|
||||
item_make("%s", menu_get_prompt(child));
|
||||
else {
|
||||
item_make("*** %s ***", _(menu_get_prompt(child)));
|
||||
item_make("*** %s ***", menu_get_prompt(child));
|
||||
item_set_tag(':');
|
||||
}
|
||||
item_set_data(child);
|
||||
@ -826,8 +822,8 @@ static void conf_choice(struct menu *menu)
|
||||
item_set_tag('X');
|
||||
}
|
||||
dialog_clear();
|
||||
res = dialog_checklist(prompt ? _(prompt) : _("Main Menu"),
|
||||
_(radiolist_instructions),
|
||||
res = dialog_checklist(prompt ? prompt : "Main Menu",
|
||||
radiolist_instructions,
|
||||
MENUBOX_HEIGTH_MIN,
|
||||
MENUBOX_WIDTH_MIN,
|
||||
CHECKLIST_HEIGTH_MIN);
|
||||
@ -868,26 +864,26 @@ static void conf_string(struct menu *menu)
|
||||
|
||||
switch (sym_get_type(menu->sym)) {
|
||||
case S_INT:
|
||||
heading = _(inputbox_instructions_int);
|
||||
heading = inputbox_instructions_int;
|
||||
break;
|
||||
case S_HEX:
|
||||
heading = _(inputbox_instructions_hex);
|
||||
heading = inputbox_instructions_hex;
|
||||
break;
|
||||
case S_STRING:
|
||||
heading = _(inputbox_instructions_string);
|
||||
heading = inputbox_instructions_string;
|
||||
break;
|
||||
default:
|
||||
heading = _("Internal mconf error!");
|
||||
heading = "Internal mconf error!";
|
||||
}
|
||||
dialog_clear();
|
||||
res = dialog_inputbox(prompt ? _(prompt) : _("Main Menu"),
|
||||
res = dialog_inputbox(prompt ? prompt : "Main Menu",
|
||||
heading, 10, 75,
|
||||
sym_get_string_value(menu->sym));
|
||||
switch (res) {
|
||||
case 0:
|
||||
if (sym_set_string_value(menu->sym, dialog_input_result))
|
||||
return;
|
||||
show_textbox(NULL, _("You have made an invalid entry."), 5, 43);
|
||||
show_textbox(NULL, "You have made an invalid entry.", 5, 43);
|
||||
break;
|
||||
case 1:
|
||||
show_help(menu);
|
||||
@ -915,10 +911,10 @@ static void conf_load(void)
|
||||
sym_set_change_count(1);
|
||||
return;
|
||||
}
|
||||
show_textbox(NULL, _("File does not exist!"), 5, 38);
|
||||
show_textbox(NULL, "File does not exist!", 5, 38);
|
||||
break;
|
||||
case 1:
|
||||
show_helptext(_("Load Alternate Configuration"), load_config_help);
|
||||
show_helptext("Load Alternate Configuration", load_config_help);
|
||||
break;
|
||||
case KEY_ESC:
|
||||
return;
|
||||
@ -941,10 +937,10 @@ static void conf_save(void)
|
||||
set_config_filename(dialog_input_result);
|
||||
return;
|
||||
}
|
||||
show_textbox(NULL, _("Can't create file! Probably a nonexistent directory."), 5, 60);
|
||||
show_textbox(NULL, "Can't create file!", 5, 60);
|
||||
break;
|
||||
case 1:
|
||||
show_helptext(_("Save Alternate Configuration"), save_config_help);
|
||||
show_helptext("Save Alternate Configuration", save_config_help);
|
||||
break;
|
||||
case KEY_ESC:
|
||||
return;
|
||||
@ -961,8 +957,8 @@ static int handle_exit(void)
|
||||
dialog_clear();
|
||||
if (conf_get_changed())
|
||||
res = dialog_yesno(NULL,
|
||||
_("Do you wish to save your new configuration?\n"
|
||||
"(Press <ESC><ESC> to continue Crosstool-NG configuration.)"),
|
||||
"Do you wish to save your new configuration?\n"
|
||||
"(Press <ESC><ESC> to continue Crosstool-NG configuration.)",
|
||||
6, 60);
|
||||
else
|
||||
res = -1;
|
||||
@ -972,26 +968,27 @@ static int handle_exit(void)
|
||||
switch (res) {
|
||||
case 0:
|
||||
if (conf_write(filename)) {
|
||||
fprintf(stderr, _("\n\n"
|
||||
fprintf(stderr, "\n\n"
|
||||
"Error while writing of the configuration.\n"
|
||||
"Your configuration changes were NOT saved."
|
||||
"\n\n"));
|
||||
"\n\n");
|
||||
return 1;
|
||||
}
|
||||
conf_write_autoconf(0);
|
||||
/* fall through */
|
||||
case -1:
|
||||
if (!silent)
|
||||
printf(_("\n\n"
|
||||
printf("\n\n"
|
||||
"*** End of the configuration.\n"
|
||||
"*** Execute 'ct-ng build' to start the build or try 'ct-ng help'."
|
||||
"\n\n"));
|
||||
"\n\n");
|
||||
res = 0;
|
||||
break;
|
||||
default:
|
||||
if (!silent)
|
||||
fprintf(stderr, _("\n\n"
|
||||
fprintf(stderr, "\n\n"
|
||||
"Your configuration changes were NOT saved."
|
||||
"\n\n"));
|
||||
"\n\n");
|
||||
if (res != KEY_ESC)
|
||||
res = 0;
|
||||
}
|
||||
@ -1009,10 +1006,6 @@ int main(int ac, char **av)
|
||||
char *mode;
|
||||
int res;
|
||||
|
||||
setlocale(LC_ALL, "");
|
||||
bindtextdomain(PACKAGE, LOCALEDIR);
|
||||
textdomain(PACKAGE);
|
||||
|
||||
signal(SIGINT, sig_handler);
|
||||
|
||||
if (ac > 1 && strcmp(av[1], "-s") == 0) {
|
||||
@ -1031,8 +1024,8 @@ int main(int ac, char **av)
|
||||
}
|
||||
|
||||
if (init_dialog(NULL)) {
|
||||
fprintf(stderr, N_("Your display is too small to run Menuconfig!\n"));
|
||||
fprintf(stderr, N_("It must be at least 19 lines by 80 columns.\n"));
|
||||
fprintf(stderr, "Your display is too small to run Menuconfig!\n");
|
||||
fprintf(stderr, "It must be at least 19 lines by 80 columns.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
435
kconfig/menu.c
435
kconfig/menu.c
@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
|
||||
* Released under the terms of the GNU GPL v2.0.
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
@ -62,15 +62,11 @@ void menu_add_entry(struct symbol *sym)
|
||||
menu_add_symbol(P_SYMBOL, sym, NULL);
|
||||
}
|
||||
|
||||
void menu_end_entry(void)
|
||||
{
|
||||
}
|
||||
|
||||
struct menu *menu_add_menu(void)
|
||||
{
|
||||
menu_end_entry();
|
||||
last_entry_ptr = ¤t_entry->list;
|
||||
return current_menu = current_entry;
|
||||
current_menu = current_entry;
|
||||
return current_menu;
|
||||
}
|
||||
|
||||
void menu_end_menu(void)
|
||||
@ -79,19 +75,23 @@ void menu_end_menu(void)
|
||||
current_menu = current_menu->parent;
|
||||
}
|
||||
|
||||
static struct expr *menu_check_dep(struct expr *e)
|
||||
/*
|
||||
* Rewrites 'm' to 'm' && MODULES, so that it evaluates to 'n' when running
|
||||
* without modules
|
||||
*/
|
||||
static struct expr *rewrite_m(struct expr *e)
|
||||
{
|
||||
if (!e)
|
||||
return e;
|
||||
|
||||
switch (e->type) {
|
||||
case E_NOT:
|
||||
e->left.expr = menu_check_dep(e->left.expr);
|
||||
e->left.expr = rewrite_m(e->left.expr);
|
||||
break;
|
||||
case E_OR:
|
||||
case E_AND:
|
||||
e->left.expr = menu_check_dep(e->left.expr);
|
||||
e->right.expr = menu_check_dep(e->right.expr);
|
||||
e->left.expr = rewrite_m(e->left.expr);
|
||||
e->right.expr = rewrite_m(e->right.expr);
|
||||
break;
|
||||
case E_SYMBOL:
|
||||
/* change 'm' into 'm' && MODULES */
|
||||
@ -106,7 +106,7 @@ static struct expr *menu_check_dep(struct expr *e)
|
||||
|
||||
void menu_add_dep(struct expr *dep)
|
||||
{
|
||||
current_entry->dep = expr_alloc_and(current_entry->dep, menu_check_dep(dep));
|
||||
current_entry->dep = expr_alloc_and(current_entry->dep, dep);
|
||||
}
|
||||
|
||||
void menu_set_type(int type)
|
||||
@ -125,65 +125,74 @@ void menu_set_type(int type)
|
||||
sym_type_name(sym->type), sym_type_name(type));
|
||||
}
|
||||
|
||||
static struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep)
|
||||
static struct property *menu_add_prop(enum prop_type type, struct expr *expr,
|
||||
struct expr *dep)
|
||||
{
|
||||
struct property *prop = prop_alloc(type, current_entry->sym);
|
||||
struct property *prop;
|
||||
|
||||
prop = xmalloc(sizeof(*prop));
|
||||
memset(prop, 0, sizeof(*prop));
|
||||
prop->type = type;
|
||||
prop->file = current_file;
|
||||
prop->lineno = zconf_lineno();
|
||||
prop->menu = current_entry;
|
||||
prop->expr = expr;
|
||||
prop->visible.expr = menu_check_dep(dep);
|
||||
prop->visible.expr = dep;
|
||||
|
||||
if (prompt) {
|
||||
/* For crostool-NG, a leading pipe followed with spaces
|
||||
* means that pipe shall be removed, and the spaces should
|
||||
* not be trimmed.
|
||||
*/
|
||||
if (*prompt == '|')
|
||||
prompt++;
|
||||
else if (isspace(*prompt)) {
|
||||
prop_warn(prop, "leading whitespace ignored");
|
||||
while (isspace(*prompt))
|
||||
prompt++;
|
||||
}
|
||||
if (current_entry->prompt && current_entry != &rootmenu)
|
||||
prop_warn(prop, "prompt redefined");
|
||||
/* append property to the prop list of symbol */
|
||||
if (current_entry->sym) {
|
||||
struct property **propp;
|
||||
|
||||
/* Apply all upper menus' visibilities to actual prompts. */
|
||||
if(type == P_PROMPT) {
|
||||
struct menu *menu = current_entry;
|
||||
|
||||
while ((menu = menu->parent) != NULL) {
|
||||
struct expr *dup_expr;
|
||||
|
||||
if (!menu->visibility)
|
||||
continue;
|
||||
/*
|
||||
* Do not add a reference to the
|
||||
* menu's visibility expression but
|
||||
* use a copy of it. Otherwise the
|
||||
* expression reduction functions
|
||||
* will modify expressions that have
|
||||
* multiple references which can
|
||||
* cause unwanted side effects.
|
||||
*/
|
||||
dup_expr = expr_copy(menu->visibility);
|
||||
|
||||
prop->visible.expr
|
||||
= expr_alloc_and(prop->visible.expr,
|
||||
dup_expr);
|
||||
}
|
||||
}
|
||||
|
||||
current_entry->prompt = prop;
|
||||
for (propp = ¤t_entry->sym->prop;
|
||||
*propp;
|
||||
propp = &(*propp)->next)
|
||||
;
|
||||
*propp = prop;
|
||||
}
|
||||
prop->text = prompt;
|
||||
|
||||
return prop;
|
||||
}
|
||||
|
||||
struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep)
|
||||
struct property *menu_add_prompt(enum prop_type type, char *prompt,
|
||||
struct expr *dep)
|
||||
{
|
||||
return menu_add_prop(type, prompt, NULL, dep);
|
||||
struct property *prop = menu_add_prop(type, NULL, dep);
|
||||
|
||||
if (isspace(*prompt)) {
|
||||
prop_warn(prop, "leading whitespace ignored");
|
||||
while (isspace(*prompt))
|
||||
prompt++;
|
||||
}
|
||||
if (current_entry->prompt)
|
||||
prop_warn(prop, "prompt redefined");
|
||||
|
||||
/* Apply all upper menus' visibilities to actual prompts. */
|
||||
if (type == P_PROMPT) {
|
||||
struct menu *menu = current_entry;
|
||||
|
||||
while ((menu = menu->parent) != NULL) {
|
||||
struct expr *dup_expr;
|
||||
|
||||
if (!menu->visibility)
|
||||
continue;
|
||||
/*
|
||||
* Do not add a reference to the menu's visibility
|
||||
* expression but use a copy of it. Otherwise the
|
||||
* expression reduction functions will modify
|
||||
* expressions that have multiple references which
|
||||
* can cause unwanted side effects.
|
||||
*/
|
||||
dup_expr = expr_copy(menu->visibility);
|
||||
|
||||
prop->visible.expr = expr_alloc_and(prop->visible.expr,
|
||||
dup_expr);
|
||||
}
|
||||
}
|
||||
|
||||
current_entry->prompt = prop;
|
||||
prop->text = prompt;
|
||||
|
||||
return prop;
|
||||
}
|
||||
|
||||
void menu_add_visibility(struct expr *expr)
|
||||
@ -194,39 +203,34 @@ void menu_add_visibility(struct expr *expr)
|
||||
|
||||
void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep)
|
||||
{
|
||||
menu_add_prop(type, NULL, expr, dep);
|
||||
menu_add_prop(type, expr, dep);
|
||||
}
|
||||
|
||||
void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep)
|
||||
{
|
||||
menu_add_prop(type, NULL, expr_alloc_symbol(sym), dep);
|
||||
menu_add_prop(type, expr_alloc_symbol(sym), dep);
|
||||
}
|
||||
|
||||
void menu_add_option(int token, char *arg)
|
||||
void menu_add_option_modules(void)
|
||||
{
|
||||
switch (token) {
|
||||
case T_OPT_MODULES:
|
||||
if (modules_sym)
|
||||
zconf_error("symbol '%s' redefines option 'modules'"
|
||||
" already defined by symbol '%s'",
|
||||
current_entry->sym->name,
|
||||
modules_sym->name
|
||||
);
|
||||
modules_sym = current_entry->sym;
|
||||
break;
|
||||
case T_OPT_DEFCONFIG_LIST:
|
||||
if (!sym_defconfig_list)
|
||||
sym_defconfig_list = current_entry->sym;
|
||||
else if (sym_defconfig_list != current_entry->sym)
|
||||
zconf_error("trying to redefine defconfig symbol");
|
||||
break;
|
||||
case T_OPT_ENV:
|
||||
prop_add_env(arg);
|
||||
break;
|
||||
case T_OPT_ALLNOCONFIG_Y:
|
||||
current_entry->sym->flags |= SYMBOL_ALLNOCONFIG_Y;
|
||||
break;
|
||||
}
|
||||
if (modules_sym)
|
||||
zconf_error("symbol '%s' redefines option 'modules' already defined by symbol '%s'",
|
||||
current_entry->sym->name, modules_sym->name);
|
||||
modules_sym = current_entry->sym;
|
||||
}
|
||||
|
||||
void menu_add_option_defconfig_list(void)
|
||||
{
|
||||
if (!sym_defconfig_list)
|
||||
sym_defconfig_list = current_entry->sym;
|
||||
else if (sym_defconfig_list != current_entry->sym)
|
||||
zconf_error("trying to redefine defconfig symbol");
|
||||
sym_defconfig_list->flags |= SYMBOL_NO_WRITE;
|
||||
}
|
||||
|
||||
void menu_add_option_allnoconfig_y(void)
|
||||
{
|
||||
current_entry->sym->flags |= SYMBOL_ALLNOCONFIG_Y;
|
||||
}
|
||||
|
||||
static int menu_validate_number(struct symbol *sym, struct symbol *sym2)
|
||||
@ -258,6 +262,16 @@ static void sym_check_prop(struct symbol *sym)
|
||||
"'%s': number is invalid",
|
||||
sym->name);
|
||||
}
|
||||
if (sym_is_choice(sym)) {
|
||||
struct property *choice_prop =
|
||||
sym_get_choice_prop(sym2);
|
||||
|
||||
if (!choice_prop ||
|
||||
prop_get_symbol(choice_prop) != sym)
|
||||
prop_warn(prop,
|
||||
"choice default symbol '%s' is not contained in the choice",
|
||||
sym2->name);
|
||||
}
|
||||
break;
|
||||
case P_SELECT:
|
||||
case P_IMPLY:
|
||||
@ -266,13 +280,13 @@ static void sym_check_prop(struct symbol *sym)
|
||||
if (sym->type != S_BOOLEAN && sym->type != S_TRISTATE)
|
||||
prop_warn(prop,
|
||||
"config symbol '%s' uses %s, but is "
|
||||
"not boolean or tristate", sym->name, use);
|
||||
"not bool or tristate", sym->name, use);
|
||||
else if (sym2->type != S_UNKNOWN &&
|
||||
sym2->type != S_BOOLEAN &&
|
||||
sym2->type != S_TRISTATE)
|
||||
prop_warn(prop,
|
||||
"'%s' has wrong type. '%s' only "
|
||||
"accept arguments of boolean and "
|
||||
"accept arguments of bool and "
|
||||
"tristate type", sym2->name, use);
|
||||
break;
|
||||
case P_RANGE:
|
||||
@ -298,6 +312,11 @@ void menu_finalize(struct menu *parent)
|
||||
|
||||
sym = parent->sym;
|
||||
if (parent->list) {
|
||||
/*
|
||||
* This menu node has children. We (recursively) process them
|
||||
* and propagate parent dependencies before moving on.
|
||||
*/
|
||||
|
||||
if (sym && sym_is_choice(sym)) {
|
||||
if (sym->type == S_UNKNOWN) {
|
||||
/* find the first choice value to find out choice type */
|
||||
@ -315,30 +334,81 @@ void menu_finalize(struct menu *parent)
|
||||
if (menu->sym && menu->sym->type == S_UNKNOWN)
|
||||
menu_set_type(sym->type);
|
||||
}
|
||||
parentdep = expr_alloc_symbol(sym);
|
||||
} else if (parent->prompt)
|
||||
parentdep = parent->prompt->visible.expr;
|
||||
else
|
||||
parentdep = parent->dep;
|
||||
|
||||
/*
|
||||
* Use the choice itself as the parent dependency of
|
||||
* the contained items. This turns the mode of the
|
||||
* choice into an upper bound on the visibility of the
|
||||
* choice value symbols.
|
||||
*/
|
||||
parentdep = expr_alloc_symbol(sym);
|
||||
} else {
|
||||
/* Menu node for 'menu', 'if' */
|
||||
parentdep = parent->dep;
|
||||
}
|
||||
|
||||
/* For each child menu node... */
|
||||
for (menu = parent->list; menu; menu = menu->next) {
|
||||
basedep = expr_transform(menu->dep);
|
||||
/*
|
||||
* Propagate parent dependencies to the child menu
|
||||
* node, also rewriting and simplifying expressions
|
||||
*/
|
||||
basedep = rewrite_m(menu->dep);
|
||||
basedep = expr_transform(basedep);
|
||||
basedep = expr_alloc_and(expr_copy(parentdep), basedep);
|
||||
basedep = expr_eliminate_dups(basedep);
|
||||
menu->dep = basedep;
|
||||
|
||||
if (menu->sym)
|
||||
/*
|
||||
* Note: For symbols, all prompts are included
|
||||
* too in the symbol's own property list
|
||||
*/
|
||||
prop = menu->sym->prop;
|
||||
else
|
||||
/*
|
||||
* For non-symbol menu nodes, we just need to
|
||||
* handle the prompt
|
||||
*/
|
||||
prop = menu->prompt;
|
||||
|
||||
/* For each property... */
|
||||
for (; prop; prop = prop->next) {
|
||||
if (prop->menu != menu)
|
||||
/*
|
||||
* Two possibilities:
|
||||
*
|
||||
* 1. The property lacks dependencies
|
||||
* and so isn't location-specific,
|
||||
* e.g. an 'option'
|
||||
*
|
||||
* 2. The property belongs to a symbol
|
||||
* defined in multiple locations and
|
||||
* is from some other location. It
|
||||
* will be handled there in that
|
||||
* case.
|
||||
*
|
||||
* Skip the property.
|
||||
*/
|
||||
continue;
|
||||
dep = expr_transform(prop->visible.expr);
|
||||
|
||||
/*
|
||||
* Propagate parent dependencies to the
|
||||
* property's condition, rewriting and
|
||||
* simplifying expressions at the same time
|
||||
*/
|
||||
dep = rewrite_m(prop->visible.expr);
|
||||
dep = expr_transform(dep);
|
||||
dep = expr_alloc_and(expr_copy(basedep), dep);
|
||||
dep = expr_eliminate_dups(dep);
|
||||
if (menu->sym && menu->sym->type != S_TRISTATE)
|
||||
dep = expr_trans_bool(dep);
|
||||
prop->visible.expr = dep;
|
||||
|
||||
/*
|
||||
* Handle selects and implies, which modify the
|
||||
* dependencies of the selected/implied symbol
|
||||
*/
|
||||
if (prop->type == P_SELECT) {
|
||||
struct symbol *es = prop_get_symbol(prop);
|
||||
es->rev_dep.expr = expr_alloc_or(es->rev_dep.expr,
|
||||
@ -350,34 +420,81 @@ void menu_finalize(struct menu *parent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (sym && sym_is_choice(sym))
|
||||
expr_free(parentdep);
|
||||
|
||||
/*
|
||||
* Recursively process children in the same fashion before
|
||||
* moving on
|
||||
*/
|
||||
for (menu = parent->list; menu; menu = menu->next)
|
||||
menu_finalize(menu);
|
||||
} else if (sym) {
|
||||
/*
|
||||
* Automatic submenu creation. If sym is a symbol and A, B, C,
|
||||
* ... are consecutive items (symbols, menus, ifs, etc.) that
|
||||
* all depend on sym, then the following menu structure is
|
||||
* created:
|
||||
*
|
||||
* sym
|
||||
* +-A
|
||||
* +-B
|
||||
* +-C
|
||||
* ...
|
||||
*
|
||||
* This also works recursively, giving the following structure
|
||||
* if A is a symbol and B depends on A:
|
||||
*
|
||||
* sym
|
||||
* +-A
|
||||
* | +-B
|
||||
* +-C
|
||||
* ...
|
||||
*/
|
||||
|
||||
basedep = parent->prompt ? parent->prompt->visible.expr : NULL;
|
||||
basedep = expr_trans_compare(basedep, E_UNEQUAL, &symbol_no);
|
||||
basedep = expr_eliminate_dups(expr_transform(basedep));
|
||||
|
||||
/* Examine consecutive elements after sym */
|
||||
last_menu = NULL;
|
||||
for (menu = parent->next; menu; menu = menu->next) {
|
||||
dep = menu->prompt ? menu->prompt->visible.expr : menu->dep;
|
||||
if (!expr_contains_symbol(dep, sym))
|
||||
/* No dependency, quit */
|
||||
break;
|
||||
if (expr_depends_symbol(dep, sym))
|
||||
/* Absolute dependency, put in submenu */
|
||||
goto next;
|
||||
|
||||
/*
|
||||
* Also consider it a dependency on sym if our
|
||||
* dependencies contain sym and are a "superset" of
|
||||
* sym's dependencies, e.g. '(sym || Q) && R' when sym
|
||||
* depends on R.
|
||||
*
|
||||
* Note that 'R' might be from an enclosing menu or if,
|
||||
* making this a more common case than it might seem.
|
||||
*/
|
||||
dep = expr_trans_compare(dep, E_UNEQUAL, &symbol_no);
|
||||
dep = expr_eliminate_dups(expr_transform(dep));
|
||||
dep2 = expr_copy(basedep);
|
||||
expr_eliminate_eq(&dep, &dep2);
|
||||
expr_free(dep);
|
||||
if (!expr_is_yes(dep2)) {
|
||||
/* Not superset, quit */
|
||||
expr_free(dep2);
|
||||
break;
|
||||
}
|
||||
/* Superset, put in submenu */
|
||||
expr_free(dep2);
|
||||
next:
|
||||
menu_finalize(menu);
|
||||
menu->parent = parent;
|
||||
last_menu = menu;
|
||||
}
|
||||
expr_free(basedep);
|
||||
if (last_menu) {
|
||||
parent->list = parent->next;
|
||||
parent->next = last_menu->next;
|
||||
@ -426,6 +543,35 @@ void menu_finalize(struct menu *parent)
|
||||
*ep = expr_alloc_one(E_LIST, NULL);
|
||||
(*ep)->right.sym = menu->sym;
|
||||
}
|
||||
|
||||
/*
|
||||
* This code serves two purposes:
|
||||
*
|
||||
* (1) Flattening 'if' blocks, which do not specify a submenu
|
||||
* and only add dependencies.
|
||||
*
|
||||
* (Automatic submenu creation might still create a submenu
|
||||
* from an 'if' before this code runs.)
|
||||
*
|
||||
* (2) "Undoing" any automatic submenus created earlier below
|
||||
* promptless symbols.
|
||||
*
|
||||
* Before:
|
||||
*
|
||||
* A
|
||||
* if ... (or promptless symbol)
|
||||
* +-B
|
||||
* +-C
|
||||
* D
|
||||
*
|
||||
* After:
|
||||
*
|
||||
* A
|
||||
* if ... (or promptless symbol)
|
||||
* B
|
||||
* C
|
||||
* D
|
||||
*/
|
||||
if (menu->list && (!menu->prompt || !menu->prompt->text)) {
|
||||
for (last_menu = menu->list; ; last_menu = last_menu->next) {
|
||||
last_menu->parent = parent;
|
||||
@ -450,6 +596,15 @@ void menu_finalize(struct menu *parent)
|
||||
sym->flags |= SYMBOL_WARNED;
|
||||
}
|
||||
|
||||
/*
|
||||
* For non-optional choices, add a reverse dependency (corresponding to
|
||||
* a select) of '<visibility> && m'. This prevents the user from
|
||||
* setting the choice mode to 'n' when the choice is visible.
|
||||
*
|
||||
* This would also work for non-choice symbols, but only non-optional
|
||||
* choices clear SYMBOL_OPTIONAL as of writing. Choices are implemented
|
||||
* as a type of symbol.
|
||||
*/
|
||||
if (sym && !sym_is_optional(sym) && parent->prompt) {
|
||||
sym->rev_dep.expr = expr_alloc_or(sym->rev_dep.expr,
|
||||
expr_alloc_and(parent->prompt->visible.expr,
|
||||
@ -557,6 +712,21 @@ const char *menu_get_help(struct menu *menu)
|
||||
return "";
|
||||
}
|
||||
|
||||
static void get_def_str(struct gstr *r, struct menu *menu)
|
||||
{
|
||||
str_printf(r, "Defined at %s:%d\n",
|
||||
menu->file->name, menu->lineno);
|
||||
}
|
||||
|
||||
static void get_dep_str(struct gstr *r, struct expr *expr, const char *prefix)
|
||||
{
|
||||
if (!expr_is_yes(expr)) {
|
||||
str_append(r, prefix);
|
||||
expr_gstr_print(expr, r);
|
||||
str_append(r, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void get_prompt_str(struct gstr *r, struct property *prop,
|
||||
struct list_head *head)
|
||||
{
|
||||
@ -564,7 +734,20 @@ static void get_prompt_str(struct gstr *r, struct property *prop,
|
||||
struct menu *submenu[8], *menu, *location = NULL;
|
||||
struct jump_key *jump = NULL;
|
||||
|
||||
str_printf(r, _("Prompt: %s\n"), _(prop->text));
|
||||
str_printf(r, " Prompt: %s\n", prop->text);
|
||||
|
||||
get_dep_str(r, prop->menu->dep, " Depends on: ");
|
||||
/*
|
||||
* Most prompts in Linux have visibility that exactly matches their
|
||||
* dependencies. For these, we print only the dependencies to improve
|
||||
* readability. However, prompts with inline "if" expressions and
|
||||
* prompts with a parent that has a "visible if" expression have
|
||||
* differing dependencies and visibility. In these rare cases, we
|
||||
* print both.
|
||||
*/
|
||||
if (!expr_eq(prop->menu->dep, prop->visible.expr))
|
||||
get_dep_str(r, prop->visible.expr, " Visible if: ");
|
||||
|
||||
menu = prop->menu->parent;
|
||||
for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent) {
|
||||
bool accessible = menu_is_visible(menu);
|
||||
@ -597,16 +780,16 @@ static void get_prompt_str(struct gstr *r, struct property *prop,
|
||||
}
|
||||
|
||||
if (i > 0) {
|
||||
str_printf(r, _(" Location:\n"));
|
||||
str_printf(r, " Location:\n");
|
||||
for (j = 4; --i >= 0; j += 2) {
|
||||
menu = submenu[i];
|
||||
if (jump && menu == location)
|
||||
jump->offset = strlen(r->s);
|
||||
str_printf(r, "%*c-> %s", j, ' ',
|
||||
_(menu_get_prompt(menu)));
|
||||
menu_get_prompt(menu));
|
||||
if (menu->sym) {
|
||||
str_printf(r, " (%s [=%s])", menu->sym->name ?
|
||||
menu->sym->name : _("<choice>"),
|
||||
menu->sym->name : "<choice>",
|
||||
sym_get_string_value(menu->sym));
|
||||
}
|
||||
str_append(r, "\n");
|
||||
@ -614,18 +797,6 @@ static void get_prompt_str(struct gstr *r, struct property *prop,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* get property of type P_SYMBOL
|
||||
*/
|
||||
static struct property *get_symbol_prop(struct symbol *sym)
|
||||
{
|
||||
struct property *prop = NULL;
|
||||
|
||||
for_all_properties(sym, prop, P_SYMBOL)
|
||||
break;
|
||||
return prop;
|
||||
}
|
||||
|
||||
static void get_symbol_props_str(struct gstr *r, struct symbol *sym,
|
||||
enum prop_type tok, const char *prefix)
|
||||
{
|
||||
@ -665,32 +836,34 @@ static void get_symbol_str(struct gstr *r, struct symbol *sym,
|
||||
}
|
||||
}
|
||||
}
|
||||
for_all_prompts(sym, prop)
|
||||
get_prompt_str(r, prop, head);
|
||||
|
||||
prop = get_symbol_prop(sym);
|
||||
if (prop) {
|
||||
str_printf(r, _(" Defined at %s:%d\n"), prop->menu->file->name,
|
||||
prop->menu->lineno);
|
||||
if (!expr_is_yes(prop->visible.expr)) {
|
||||
str_append(r, _(" Depends on: "));
|
||||
expr_gstr_print(prop->visible.expr, r);
|
||||
str_append(r, "\n");
|
||||
/* Print the definitions with prompts before the ones without */
|
||||
for_all_properties(sym, prop, P_SYMBOL) {
|
||||
if (prop->menu->prompt) {
|
||||
get_def_str(r, prop->menu);
|
||||
get_prompt_str(r, prop->menu->prompt, head);
|
||||
}
|
||||
}
|
||||
|
||||
get_symbol_props_str(r, sym, P_SELECT, _(" Selects: "));
|
||||
if (sym->rev_dep.expr) {
|
||||
str_append(r, _(" Selected by: "));
|
||||
expr_gstr_print(sym->rev_dep.expr, r);
|
||||
str_append(r, "\n");
|
||||
for_all_properties(sym, prop, P_SYMBOL) {
|
||||
if (!prop->menu->prompt) {
|
||||
get_def_str(r, prop->menu);
|
||||
get_dep_str(r, prop->menu->dep, " Depends on: ");
|
||||
}
|
||||
}
|
||||
|
||||
get_symbol_props_str(r, sym, P_IMPLY, _(" Implies: "));
|
||||
get_symbol_props_str(r, sym, P_SELECT, "Selects: ");
|
||||
if (sym->rev_dep.expr) {
|
||||
expr_gstr_print_revdep(sym->rev_dep.expr, r, yes, "Selected by [y]:\n");
|
||||
expr_gstr_print_revdep(sym->rev_dep.expr, r, mod, "Selected by [m]:\n");
|
||||
expr_gstr_print_revdep(sym->rev_dep.expr, r, no, "Selected by [n]:\n");
|
||||
}
|
||||
|
||||
get_symbol_props_str(r, sym, P_IMPLY, "Implies: ");
|
||||
if (sym->implied.expr) {
|
||||
str_append(r, _(" Implied by: "));
|
||||
expr_gstr_print(sym->implied.expr, r);
|
||||
str_append(r, "\n");
|
||||
expr_gstr_print_revdep(sym->implied.expr, r, yes, "Implied by [y]:\n");
|
||||
expr_gstr_print_revdep(sym->implied.expr, r, mod, "Implied by [m]:\n");
|
||||
expr_gstr_print_revdep(sym->implied.expr, r, no, "Implied by [n]:\n");
|
||||
}
|
||||
|
||||
str_append(r, "\n\n");
|
||||
@ -705,7 +878,7 @@ struct gstr get_relations_str(struct symbol **sym_arr, struct list_head *head)
|
||||
for (i = 0; sym_arr && (sym = sym_arr[i]); i++)
|
||||
get_symbol_str(&res, sym, head);
|
||||
if (!i)
|
||||
str_append(&res, _("No matches found.\n"));
|
||||
str_append(&res, "No matches found.\n");
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -720,7 +893,7 @@ void menu_get_ext_help(struct menu *menu, struct gstr *help)
|
||||
str_printf(help, "%s%s:\n\n", CONFIG_, sym->name);
|
||||
help_text = menu_get_help(menu);
|
||||
}
|
||||
str_printf(help, "%s\n", _(help_text));
|
||||
str_printf(help, "%s\n", help_text);
|
||||
if (sym)
|
||||
get_symbol_str(help, sym, NULL);
|
||||
}
|
||||
|
172
kconfig/nconf.c
172
kconfig/nconf.c
@ -1,21 +1,21 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (C) 2008 Nir Tzachar <nir.tzachar@gmail.com?
|
||||
* Released under the terms of the GNU GPL v2.0.
|
||||
* Copyright (C) 2008 Nir Tzachar <nir.tzachar@gmail.com>
|
||||
*
|
||||
* Derived from menuconfig.
|
||||
*
|
||||
*/
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "lkc.h"
|
||||
#include "nconf.h"
|
||||
#include <ctype.h>
|
||||
|
||||
static const char nconf_global_help[] = N_(
|
||||
static const char nconf_global_help[] =
|
||||
"Help windows\n"
|
||||
"------------\n"
|
||||
"o Global help: Unless in a data entry window, pressing <F1> will give \n"
|
||||
@ -133,8 +133,8 @@ static const char nconf_global_help[] = N_(
|
||||
"\n"
|
||||
"Note that this mode can eventually be a little more CPU expensive than\n"
|
||||
"the default mode, especially with a larger number of unfolded submenus.\n"
|
||||
"\n"),
|
||||
menu_no_f_instructions[] = N_(
|
||||
"\n",
|
||||
menu_no_f_instructions[] =
|
||||
"Legend: [*] built-in [ ] excluded <M> automatic < > automatic capable.\n"
|
||||
"Submenus are designated by a trailing \"--->\", empty ones by \"----\".\n"
|
||||
"\n"
|
||||
@ -150,8 +150,8 @@ menu_no_f_instructions[] = N_(
|
||||
"You do not have function keys support.\n"
|
||||
"Press <1> instead of <F1>, <2> instead of <F2>, etc.\n"
|
||||
"For verbose global help use key <1>.\n"
|
||||
"For help related to the current menu entry press <?> or <h>.\n"),
|
||||
menu_instructions[] = N_(
|
||||
"For help related to the current menu entry press <?> or <h>.\n",
|
||||
menu_instructions[] =
|
||||
"Legend: [*] built-in [ ] excluded <M> automatic < > automatic capable.\n"
|
||||
"Submenus are designated by a trailing \"--->\", empty ones by \"----\".\n"
|
||||
"\n"
|
||||
@ -166,30 +166,30 @@ menu_instructions[] = N_(
|
||||
"\n"
|
||||
"Pressing <1> may be used instead of <F1>, <2> instead of <F2>, etc.\n"
|
||||
"For verbose global help press <F1>.\n"
|
||||
"For help related to the current menu entry press <?> or <h>.\n"),
|
||||
radiolist_instructions[] = N_(
|
||||
"For help related to the current menu entry press <?> or <h>.\n",
|
||||
radiolist_instructions[] =
|
||||
"Press <Up>, <Down>, <Home> or <End> to navigate a radiolist, select\n"
|
||||
"with <Space>.\n"
|
||||
"For help related to the current entry press <?> or <h>.\n"
|
||||
"For global help press <F1>.\n"),
|
||||
inputbox_instructions_int[] = N_(
|
||||
"For global help press <F1>.\n",
|
||||
inputbox_instructions_int[] =
|
||||
"Please enter a decimal value.\n"
|
||||
"Fractions will not be accepted.\n"
|
||||
"Press <Enter> to apply, <Esc> to cancel."),
|
||||
inputbox_instructions_hex[] = N_(
|
||||
"Press <Enter> to apply, <Esc> to cancel.",
|
||||
inputbox_instructions_hex[] =
|
||||
"Please enter a hexadecimal value.\n"
|
||||
"Press <Enter> to apply, <Esc> to cancel."),
|
||||
inputbox_instructions_string[] = N_(
|
||||
"Press <Enter> to apply, <Esc> to cancel.",
|
||||
inputbox_instructions_string[] =
|
||||
"Please enter a string value.\n"
|
||||
"Press <Enter> to apply, <Esc> to cancel."),
|
||||
setmod_text[] = N_(
|
||||
"Press <Enter> to apply, <Esc> to cancel.",
|
||||
setmod_text[] =
|
||||
"This feature depends on another feature which has been configured as\n"
|
||||
"automatic. As a result, the current feature will be built as automatic too."),
|
||||
load_config_text[] = N_(
|
||||
"automatic. As a result, the current feature will be built as automatic too.",
|
||||
load_config_text[] =
|
||||
"Enter the name of the configuration file you wish to load.\n"
|
||||
"Accept the name shown to restore the configuration you last\n"
|
||||
"retrieved. Leave empty to abort."),
|
||||
load_config_help[] = N_(
|
||||
"retrieved. Leave empty to abort.",
|
||||
load_config_help[] =
|
||||
"For various reasons, one may wish to keep several different\n"
|
||||
"configurations available on a single machine.\n"
|
||||
"\n"
|
||||
@ -197,11 +197,11 @@ load_config_help[] = N_(
|
||||
"default one, entering its name here will allow you to load and modify\n"
|
||||
"that configuration.\n"
|
||||
"\n"
|
||||
"Leave empty to abort.\n"),
|
||||
save_config_text[] = N_(
|
||||
"Leave empty to abort.\n",
|
||||
save_config_text[] =
|
||||
"Enter a filename to which this configuration should be saved\n"
|
||||
"as an alternate. Leave empty to abort."),
|
||||
save_config_help[] = N_(
|
||||
"as an alternate. Leave empty to abort.",
|
||||
save_config_help[] =
|
||||
"For various reasons, one may wish to keep several different\n"
|
||||
"configurations available on a single machine.\n"
|
||||
"\n"
|
||||
@ -209,8 +209,8 @@ save_config_help[] = N_(
|
||||
"and use the current configuration as an alternate to whatever\n"
|
||||
"configuration options you have selected at that time.\n"
|
||||
"\n"
|
||||
"Leave empty to abort.\n"),
|
||||
search_help[] = N_(
|
||||
"Leave empty to abort.\n",
|
||||
search_help[] =
|
||||
"Search for symbols (configuration variable names CONFIG_*) and display\n"
|
||||
"their relations. Regular expressions are supported.\n"
|
||||
"Example: Search for \"^FOO\".\n"
|
||||
@ -247,7 +247,7 @@ search_help[] = N_(
|
||||
"USB => find all symbols containing USB\n"
|
||||
"^USB => find all symbols starting with USB\n"
|
||||
"USB$ => find all symbols ending with USB\n"
|
||||
"\n");
|
||||
"\n";
|
||||
|
||||
struct mitem {
|
||||
char str[256];
|
||||
@ -391,7 +391,7 @@ static void print_function_line(void)
|
||||
static void handle_f1(int *key, struct menu *current_item)
|
||||
{
|
||||
show_scroll_win(main_window,
|
||||
_("Global help"), _(nconf_global_help));
|
||||
"Global help", nconf_global_help);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -406,8 +406,8 @@ static void handle_f2(int *key, struct menu *current_item)
|
||||
static void handle_f3(int *key, struct menu *current_item)
|
||||
{
|
||||
show_scroll_win(main_window,
|
||||
_("Short help"),
|
||||
_(current_instructions));
|
||||
"Short help",
|
||||
current_instructions);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -415,7 +415,7 @@ static void handle_f3(int *key, struct menu *current_item)
|
||||
static void handle_f4(int *key, struct menu *current_item)
|
||||
{
|
||||
int res = btn_dialog(main_window,
|
||||
_("Show all symbols?"),
|
||||
"Show all symbols?",
|
||||
2,
|
||||
" <Show All> ",
|
||||
"<Don't show all>");
|
||||
@ -656,8 +656,8 @@ static int do_exit(void)
|
||||
return 0;
|
||||
}
|
||||
res = btn_dialog(main_window,
|
||||
_("Do you wish to save your new configuration?\n"
|
||||
"<ESC> to cancel and resume nconfig."),
|
||||
"Do you wish to save your new configuration?\n"
|
||||
"<ESC> to cancel and resume nconfig.",
|
||||
2,
|
||||
" <save> ",
|
||||
"<don't save>");
|
||||
@ -673,15 +673,16 @@ static int do_exit(void)
|
||||
if (res)
|
||||
btn_dialog(
|
||||
main_window,
|
||||
_("Error during writing of configuration.\n"
|
||||
"Your configuration changes were NOT saved."),
|
||||
"Error during writing of configuration.\n"
|
||||
"Your configuration changes were NOT saved.",
|
||||
1,
|
||||
"<OK>");
|
||||
conf_write_autoconf(0);
|
||||
break;
|
||||
default:
|
||||
btn_dialog(
|
||||
main_window,
|
||||
_("Your configuration changes were NOT saved."),
|
||||
"Your configuration changes were NOT saved.",
|
||||
1,
|
||||
"<OK>");
|
||||
break;
|
||||
@ -700,12 +701,12 @@ static void search_conf(void)
|
||||
int dres;
|
||||
|
||||
title = str_new();
|
||||
str_printf( &title, _("Enter (sub)string or regexp to search for "
|
||||
"(with or without \"%s\")"), CONFIG_);
|
||||
str_printf( &title, "Enter (sub)string or regexp to search for "
|
||||
"(with or without \"%s\")", CONFIG_);
|
||||
|
||||
again:
|
||||
dres = dialog_inputbox(main_window,
|
||||
_("Search Configuration Parameter"),
|
||||
"Search Configuration Parameter",
|
||||
str_get(&title),
|
||||
"", &dialog_input_result, &dialog_input_result_len);
|
||||
switch (dres) {
|
||||
@ -713,7 +714,7 @@ again:
|
||||
break;
|
||||
case 1:
|
||||
show_scroll_win(main_window,
|
||||
_("Search Configuration"), search_help);
|
||||
"Search Configuration", search_help);
|
||||
goto again;
|
||||
default:
|
||||
str_free(&title);
|
||||
@ -729,7 +730,7 @@ again:
|
||||
res = get_relations_str(sym_arr, NULL);
|
||||
free(sym_arr);
|
||||
show_scroll_win(main_window,
|
||||
_("Search Results"), str_get(&res));
|
||||
"Search Results", str_get(&res));
|
||||
str_free(&res);
|
||||
str_free(&title);
|
||||
}
|
||||
@ -757,7 +758,6 @@ static void build_conf(struct menu *menu)
|
||||
switch (ptype) {
|
||||
case P_MENU:
|
||||
child_count++;
|
||||
prompt = _(prompt);
|
||||
if (single_menu_mode) {
|
||||
item_make(menu, 'm',
|
||||
"%s%*c%s",
|
||||
@ -778,7 +778,7 @@ static void build_conf(struct menu *menu)
|
||||
item_make(menu, ':',
|
||||
" %*c*** %s ***",
|
||||
indent + 1, ' ',
|
||||
_(prompt));
|
||||
prompt);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@ -786,7 +786,7 @@ static void build_conf(struct menu *menu)
|
||||
child_count++;
|
||||
item_make(menu, ':', "---%*c%s",
|
||||
indent + 1, ' ',
|
||||
_(prompt));
|
||||
prompt);
|
||||
}
|
||||
}
|
||||
} else
|
||||
@ -806,7 +806,7 @@ static void build_conf(struct menu *menu)
|
||||
}
|
||||
|
||||
val = sym_get_tristate_value(sym);
|
||||
if (sym_is_changable(sym)) {
|
||||
if (sym_is_changeable(sym)) {
|
||||
switch (type) {
|
||||
case S_BOOLEAN:
|
||||
item_make(menu, 't', "[%c]",
|
||||
@ -832,11 +832,11 @@ static void build_conf(struct menu *menu)
|
||||
}
|
||||
|
||||
item_add_str("%*c%s", indent + 1,
|
||||
' ', _(menu_get_prompt(menu)));
|
||||
' ', menu_get_prompt(menu));
|
||||
if (val == yes) {
|
||||
if (def_menu) {
|
||||
item_add_str(" (%s)",
|
||||
_(menu_get_prompt(def_menu)));
|
||||
menu_get_prompt(def_menu));
|
||||
item_add_str(" --->");
|
||||
if (def_menu->list) {
|
||||
indent += 2;
|
||||
@ -850,7 +850,7 @@ static void build_conf(struct menu *menu)
|
||||
if (menu == current_menu) {
|
||||
item_make(menu, ':',
|
||||
"---%*c%s", indent + 1,
|
||||
' ', _(menu_get_prompt(menu)));
|
||||
' ', menu_get_prompt(menu));
|
||||
goto conf_childs;
|
||||
}
|
||||
child_count++;
|
||||
@ -860,7 +860,7 @@ static void build_conf(struct menu *menu)
|
||||
} else {
|
||||
switch (type) {
|
||||
case S_BOOLEAN:
|
||||
if (sym_is_changable(sym))
|
||||
if (sym_is_changeable(sym))
|
||||
item_make(menu, 't', "[%c]",
|
||||
val == no ? ' ' : '*');
|
||||
else
|
||||
@ -879,7 +879,7 @@ static void build_conf(struct menu *menu)
|
||||
ch = ' ';
|
||||
break;
|
||||
}
|
||||
if (sym_is_changable(sym)) {
|
||||
if (sym_is_changeable(sym)) {
|
||||
if (sym->rev_dep.tri == mod)
|
||||
item_make(menu,
|
||||
't', "{%c}", ch);
|
||||
@ -897,17 +897,17 @@ static void build_conf(struct menu *menu)
|
||||
if (tmp < 0)
|
||||
tmp = 0;
|
||||
item_add_str("%*c%s%s", tmp, ' ',
|
||||
_(menu_get_prompt(menu)),
|
||||
menu_get_prompt(menu),
|
||||
(sym_has_value(sym) ||
|
||||
!sym_is_changable(sym)) ? "" :
|
||||
_(" (NEW)"));
|
||||
!sym_is_changeable(sym)) ? "" :
|
||||
" (NEW)");
|
||||
goto conf_childs;
|
||||
}
|
||||
}
|
||||
item_add_str("%*c%s%s", indent + 1, ' ',
|
||||
_(menu_get_prompt(menu)),
|
||||
(sym_has_value(sym) || !sym_is_changable(sym)) ?
|
||||
"" : _(" (NEW)"));
|
||||
menu_get_prompt(menu),
|
||||
(sym_has_value(sym) || !sym_is_changeable(sym)) ?
|
||||
"" : " (NEW)");
|
||||
if (menu->prompt && menu->prompt->type == P_MENU) {
|
||||
item_add_str(" %s", menu_is_empty(menu) ? "----" : "--->");
|
||||
return;
|
||||
@ -1051,7 +1051,7 @@ static int do_match(int key, struct match_state *state, int *ans)
|
||||
state->match_direction = FIND_NEXT_MATCH_UP;
|
||||
*ans = get_mext_match(state->pattern,
|
||||
state->match_direction);
|
||||
} else if (key == KEY_BACKSPACE || key == 127) {
|
||||
} else if (key == KEY_BACKSPACE || key == 8 || key == 127) {
|
||||
state->pattern[strlen(state->pattern)-1] = '\0';
|
||||
adj_match_dir(&state->match_direction);
|
||||
} else
|
||||
@ -1089,8 +1089,8 @@ static void conf(struct menu *menu)
|
||||
if (!child_count)
|
||||
break;
|
||||
|
||||
show_menu(prompt ? _(prompt) : _("Main Menu"),
|
||||
_(menu_instructions),
|
||||
show_menu(prompt ? prompt : "Main Menu",
|
||||
menu_instructions,
|
||||
current_index, &last_top_row);
|
||||
keypad((menu_win(curses_menu)), TRUE);
|
||||
while (!global_exit) {
|
||||
@ -1213,12 +1213,9 @@ static void conf(struct menu *menu)
|
||||
}
|
||||
}
|
||||
|
||||
static void conf_message_callback(const char *fmt, va_list ap)
|
||||
static void conf_message_callback(const char *s)
|
||||
{
|
||||
char buf[1024];
|
||||
|
||||
vsnprintf(buf, sizeof(buf), fmt, ap);
|
||||
btn_dialog(main_window, buf, 1, "<OK>");
|
||||
btn_dialog(main_window, s, 1, "<OK>");
|
||||
}
|
||||
|
||||
static void show_help(struct menu *menu)
|
||||
@ -1230,13 +1227,13 @@ static void show_help(struct menu *menu)
|
||||
|
||||
help = str_new();
|
||||
menu_get_ext_help(menu, &help);
|
||||
show_scroll_win(main_window, _(menu_get_prompt(menu)), str_get(&help));
|
||||
show_scroll_win(main_window, menu_get_prompt(menu), str_get(&help));
|
||||
str_free(&help);
|
||||
}
|
||||
|
||||
static void conf_choice(struct menu *menu)
|
||||
{
|
||||
const char *prompt = _(menu_get_prompt(menu));
|
||||
const char *prompt = menu_get_prompt(menu);
|
||||
struct menu *child = NULL;
|
||||
struct symbol *active;
|
||||
int selected_index = 0;
|
||||
@ -1259,13 +1256,13 @@ static void conf_choice(struct menu *menu)
|
||||
|
||||
if (child->sym == sym_get_choice_value(menu->sym))
|
||||
item_make(child, ':', "<X> %s",
|
||||
_(menu_get_prompt(child)));
|
||||
menu_get_prompt(child));
|
||||
else if (child->sym)
|
||||
item_make(child, ':', " %s",
|
||||
_(menu_get_prompt(child)));
|
||||
menu_get_prompt(child));
|
||||
else
|
||||
item_make(child, ':', "*** %s ***",
|
||||
_(menu_get_prompt(child)));
|
||||
menu_get_prompt(child));
|
||||
|
||||
if (child->sym == active){
|
||||
last_top_row = top_row(curses_menu);
|
||||
@ -1273,8 +1270,8 @@ static void conf_choice(struct menu *menu)
|
||||
}
|
||||
i++;
|
||||
}
|
||||
show_menu(prompt ? _(prompt) : _("Choice Menu"),
|
||||
_(radiolist_instructions),
|
||||
show_menu(prompt ? prompt : "Choice Menu",
|
||||
radiolist_instructions,
|
||||
selected_index,
|
||||
&last_top_row);
|
||||
while (!global_exit) {
|
||||
@ -1361,19 +1358,19 @@ static void conf_string(struct menu *menu)
|
||||
|
||||
switch (sym_get_type(menu->sym)) {
|
||||
case S_INT:
|
||||
heading = _(inputbox_instructions_int);
|
||||
heading = inputbox_instructions_int;
|
||||
break;
|
||||
case S_HEX:
|
||||
heading = _(inputbox_instructions_hex);
|
||||
heading = inputbox_instructions_hex;
|
||||
break;
|
||||
case S_STRING:
|
||||
heading = _(inputbox_instructions_string);
|
||||
heading = inputbox_instructions_string;
|
||||
break;
|
||||
default:
|
||||
heading = _("Internal nconf error!");
|
||||
heading = "Internal nconf error!";
|
||||
}
|
||||
res = dialog_inputbox(main_window,
|
||||
prompt ? _(prompt) : _("Main Menu"),
|
||||
prompt ? prompt : "Main Menu",
|
||||
heading,
|
||||
sym_get_string_value(menu->sym),
|
||||
&dialog_input_result,
|
||||
@ -1384,7 +1381,7 @@ static void conf_string(struct menu *menu)
|
||||
dialog_input_result))
|
||||
return;
|
||||
btn_dialog(main_window,
|
||||
_("You have made an invalid entry."), 0);
|
||||
"You have made an invalid entry.", 0);
|
||||
break;
|
||||
case 1:
|
||||
show_help(menu);
|
||||
@ -1413,11 +1410,11 @@ static void conf_load(void)
|
||||
sym_set_change_count(1);
|
||||
return;
|
||||
}
|
||||
btn_dialog(main_window, _("File does not exist!"), 0);
|
||||
btn_dialog(main_window, "File does not exist!", 0);
|
||||
break;
|
||||
case 1:
|
||||
show_scroll_win(main_window,
|
||||
_("Load Alternate Configuration"),
|
||||
"Load Alternate Configuration",
|
||||
load_config_help);
|
||||
break;
|
||||
case KEY_EXIT:
|
||||
@ -1444,13 +1441,12 @@ static void conf_save(void)
|
||||
set_config_filename(dialog_input_result);
|
||||
return;
|
||||
}
|
||||
btn_dialog(main_window, _("Can't create file! "
|
||||
"Probably a nonexistent directory."),
|
||||
btn_dialog(main_window, "Can't create file!",
|
||||
1, "<OK>");
|
||||
break;
|
||||
case 1:
|
||||
show_scroll_win(main_window,
|
||||
_("Save Alternate Configuration"),
|
||||
"Save Alternate Configuration",
|
||||
save_config_help);
|
||||
break;
|
||||
case KEY_EXIT:
|
||||
@ -1483,10 +1479,6 @@ int main(int ac, char **av)
|
||||
int lines, columns;
|
||||
char *mode;
|
||||
|
||||
setlocale(LC_ALL, "");
|
||||
bindtextdomain(PACKAGE, LOCALEDIR);
|
||||
textdomain(PACKAGE);
|
||||
|
||||
if (ac > 1 && strcmp(av[1], "-s") == 0) {
|
||||
/* Silence conf_read() until the real callback is set up */
|
||||
conf_set_message_callback(NULL);
|
||||
@ -1544,8 +1536,8 @@ int main(int ac, char **av)
|
||||
/* check for KEY_FUNC(1) */
|
||||
if (has_key(KEY_F(1)) == FALSE) {
|
||||
show_scroll_win(main_window,
|
||||
_("Instructions"),
|
||||
_(menu_no_f_instructions));
|
||||
"Instructions",
|
||||
menu_no_f_instructions);
|
||||
}
|
||||
|
||||
conf_set_message_callback(conf_message_callback);
|
||||
|
@ -1,11 +1,11 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (C) 2008 Nir Tzachar <nir.tzachar@gmail.com?
|
||||
* Released under the terms of the GNU GPL v2.0.
|
||||
* Copyright (C) 2008 Nir Tzachar <nir.tzachar@gmail.com>
|
||||
*
|
||||
* Derived from menuconfig.
|
||||
*
|
||||
*/
|
||||
#include "nconf.h"
|
||||
#include "lkc.h"
|
||||
|
||||
/* a list of all the different widgets we use */
|
||||
attributes_t attributes[ATTR_MAX+1] = {0};
|
||||
@ -374,7 +374,7 @@ int dialog_inputbox(WINDOW *main_window,
|
||||
|
||||
if (strlen(init)+1 > *result_len) {
|
||||
*result_len = strlen(init)+1;
|
||||
*resultp = result = realloc(result, *result_len);
|
||||
*resultp = result = xrealloc(result, *result_len);
|
||||
}
|
||||
|
||||
/* find the widest line of msg: */
|
||||
@ -439,7 +439,8 @@ int dialog_inputbox(WINDOW *main_window,
|
||||
case KEY_F(F_EXIT):
|
||||
case KEY_F(F_BACK):
|
||||
break;
|
||||
case 127:
|
||||
case 8: /* ^H */
|
||||
case 127: /* ^? */
|
||||
case KEY_BACKSPACE:
|
||||
if (cursor_position > 0) {
|
||||
memmove(&result[cursor_position-1],
|
||||
|
@ -1,9 +1,8 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2008 Nir Tzachar <nir.tzachar@gmail.com?
|
||||
* Released under the terms of the GNU GPL v2.0.
|
||||
* Copyright (C) 2008 Nir Tzachar <nir.tzachar@gmail.com>
|
||||
*
|
||||
* Derived from menuconfig.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
@ -14,8 +13,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <locale.h>
|
||||
#include <curses.h>
|
||||
#include <ncurses.h>
|
||||
#include <menu.h>
|
||||
#include <panel.h>
|
||||
#include <form.h>
|
||||
@ -24,8 +22,6 @@
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include "ncurses.h"
|
||||
|
||||
#define max(a, b) ({\
|
||||
typeof(a) _a = a;\
|
||||
typeof(b) _b = b;\
|
||||
|
@ -1,8 +1,8 @@
|
||||
%{
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
|
||||
* Released under the terms of the GNU GPL v2.0.
|
||||
*/
|
||||
%{
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdarg.h>
|
||||
@ -20,63 +20,69 @@
|
||||
|
||||
int cdebug = PRINTD;
|
||||
|
||||
extern int zconflex(void);
|
||||
static void yyerror(const char *err);
|
||||
static void zconfprint(const char *err, ...);
|
||||
static void zconf_error(const char *err, ...);
|
||||
static void zconferror(const char *err);
|
||||
static bool zconf_endtoken(const struct kconf_id *id, int starttoken, int endtoken);
|
||||
static bool zconf_endtoken(const char *tokenname,
|
||||
const char *expected_tokenname);
|
||||
|
||||
struct symbol *symbol_hash[SYMBOL_HASHSIZE];
|
||||
|
||||
static struct menu *current_menu, *current_entry;
|
||||
|
||||
%}
|
||||
%expect 32
|
||||
|
||||
%union
|
||||
{
|
||||
char *string;
|
||||
struct file *file;
|
||||
struct symbol *symbol;
|
||||
struct expr *expr;
|
||||
struct menu *menu;
|
||||
const struct kconf_id *id;
|
||||
enum symbol_type type;
|
||||
enum variable_flavor flavor;
|
||||
}
|
||||
|
||||
%token <id>T_MAINMENU
|
||||
%token <id>T_MENU
|
||||
%token <id>T_ENDMENU
|
||||
%token <id>T_SOURCE
|
||||
%token <id>T_CHOICE
|
||||
%token <id>T_ENDCHOICE
|
||||
%token <id>T_COMMENT
|
||||
%token <id>T_CONFIG
|
||||
%token <id>T_MENUCONFIG
|
||||
%token <id>T_HELP
|
||||
%token <string> T_HELPTEXT
|
||||
%token <id>T_IF
|
||||
%token <id>T_ENDIF
|
||||
%token <id>T_DEPENDS
|
||||
%token <id>T_OPTIONAL
|
||||
%token <id>T_PROMPT
|
||||
%token <id>T_TYPE
|
||||
%token <id>T_DEFAULT
|
||||
%token <id>T_SELECT
|
||||
%token <id>T_IMPLY
|
||||
%token <id>T_RANGE
|
||||
%token <id>T_VISIBLE
|
||||
%token <id>T_OPTION
|
||||
%token <id>T_ON
|
||||
%token <string> T_WORD
|
||||
%token <string> T_WORD_QUOTE
|
||||
%token T_UNEQUAL
|
||||
%token T_LESS
|
||||
%token T_LESS_EQUAL
|
||||
%token T_GREATER
|
||||
%token T_GREATER_EQUAL
|
||||
%token T_ALLNOCONFIG_Y
|
||||
%token T_BOOL
|
||||
%token T_CHOICE
|
||||
%token T_CLOSE_PAREN
|
||||
%token T_COLON_EQUAL
|
||||
%token T_COMMENT
|
||||
%token T_CONFIG
|
||||
%token T_DEFAULT
|
||||
%token T_DEFCONFIG_LIST
|
||||
%token T_DEF_BOOL
|
||||
%token T_DEF_TRISTATE
|
||||
%token T_DEPENDS
|
||||
%token T_ENDCHOICE
|
||||
%token T_ENDIF
|
||||
%token T_ENDMENU
|
||||
%token T_HELP
|
||||
%token T_HEX
|
||||
%token T_IF
|
||||
%token T_IMPLY
|
||||
%token T_INT
|
||||
%token T_MAINMENU
|
||||
%token T_MENU
|
||||
%token T_MENUCONFIG
|
||||
%token T_MODULES
|
||||
%token T_ON
|
||||
%token T_OPEN_PAREN
|
||||
%token T_OPTION
|
||||
%token T_OPTIONAL
|
||||
%token T_PLUS_EQUAL
|
||||
%token T_PROMPT
|
||||
%token T_RANGE
|
||||
%token T_SELECT
|
||||
%token T_SOURCE
|
||||
%token T_STRING
|
||||
%token T_TRISTATE
|
||||
%token T_VISIBLE
|
||||
%token T_EOL
|
||||
%token <string> T_ASSIGN_VAL
|
||||
|
||||
%left T_OR
|
||||
%left T_AND
|
||||
@ -84,14 +90,15 @@ static struct menu *current_menu, *current_entry;
|
||||
%left T_LESS T_LESS_EQUAL T_GREATER T_GREATER_EQUAL
|
||||
%nonassoc T_NOT
|
||||
|
||||
%type <string> prompt
|
||||
%type <symbol> nonconst_symbol
|
||||
%type <symbol> symbol
|
||||
%type <type> type logic_type default
|
||||
%type <expr> expr
|
||||
%type <expr> if_expr
|
||||
%type <id> end
|
||||
%type <id> option_name
|
||||
%type <string> end
|
||||
%type <menu> if_entry menu_entry choice_entry
|
||||
%type <string> symbol_option_arg word_opt
|
||||
%type <string> word_opt assign_val
|
||||
%type <flavor> assign_op
|
||||
|
||||
%destructor {
|
||||
fprintf(stderr, "%s:%d: missing end statement for this entry\n",
|
||||
@ -100,71 +107,57 @@ static struct menu *current_menu, *current_entry;
|
||||
menu_end_menu();
|
||||
} if_entry menu_entry choice_entry
|
||||
|
||||
%{
|
||||
/* Include zconf_id.c here so it can see the token constants. */
|
||||
#include "kconf_id.c"
|
||||
%}
|
||||
|
||||
%%
|
||||
input: nl start | start;
|
||||
input: mainmenu_stmt stmt_list | stmt_list;
|
||||
|
||||
start: mainmenu_stmt stmt_list | stmt_list;
|
||||
/* mainmenu entry */
|
||||
|
||||
mainmenu_stmt: T_MAINMENU T_WORD_QUOTE T_EOL
|
||||
{
|
||||
menu_add_prompt(P_MENU, $2, NULL);
|
||||
};
|
||||
|
||||
stmt_list:
|
||||
/* empty */
|
||||
| stmt_list common_stmt
|
||||
| stmt_list assignment_stmt
|
||||
| stmt_list choice_stmt
|
||||
| stmt_list comment_stmt
|
||||
| stmt_list config_stmt
|
||||
| stmt_list if_stmt
|
||||
| stmt_list menu_stmt
|
||||
| stmt_list end { zconf_error("unexpected end statement"); }
|
||||
| stmt_list menuconfig_stmt
|
||||
| stmt_list source_stmt
|
||||
| stmt_list T_WORD error T_EOL { zconf_error("unknown statement \"%s\"", $2); }
|
||||
| stmt_list option_name error T_EOL
|
||||
{
|
||||
zconf_error("unexpected option \"%s\"", $2->name);
|
||||
}
|
||||
| stmt_list error T_EOL { zconf_error("invalid statement"); }
|
||||
;
|
||||
|
||||
option_name:
|
||||
T_DEPENDS | T_PROMPT | T_TYPE | T_SELECT | T_IMPLY | T_OPTIONAL | T_RANGE | T_DEFAULT | T_VISIBLE
|
||||
stmt_list_in_choice:
|
||||
/* empty */
|
||||
| stmt_list_in_choice comment_stmt
|
||||
| stmt_list_in_choice config_stmt
|
||||
| stmt_list_in_choice if_stmt_in_choice
|
||||
| stmt_list_in_choice error T_EOL { zconf_error("invalid statement"); }
|
||||
;
|
||||
|
||||
common_stmt:
|
||||
T_EOL
|
||||
| if_stmt
|
||||
| comment_stmt
|
||||
| config_stmt
|
||||
| menuconfig_stmt
|
||||
| source_stmt
|
||||
;
|
||||
|
||||
option_error:
|
||||
T_WORD error T_EOL { zconf_error("unknown option \"%s\"", $1); }
|
||||
| error T_EOL { zconf_error("invalid option"); }
|
||||
;
|
||||
|
||||
|
||||
/* config/menuconfig entry */
|
||||
|
||||
config_entry_start: T_CONFIG T_WORD T_EOL
|
||||
config_entry_start: T_CONFIG nonconst_symbol T_EOL
|
||||
{
|
||||
struct symbol *sym = sym_lookup($2, 0);
|
||||
sym->flags |= SYMBOL_OPTIONAL;
|
||||
menu_add_entry(sym);
|
||||
printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), $2);
|
||||
$2->flags |= SYMBOL_OPTIONAL;
|
||||
menu_add_entry($2);
|
||||
printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), $2->name);
|
||||
};
|
||||
|
||||
config_stmt: config_entry_start config_option_list
|
||||
{
|
||||
menu_end_entry();
|
||||
printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno());
|
||||
};
|
||||
|
||||
menuconfig_entry_start: T_MENUCONFIG T_WORD T_EOL
|
||||
menuconfig_entry_start: T_MENUCONFIG nonconst_symbol T_EOL
|
||||
{
|
||||
struct symbol *sym = sym_lookup($2, 0);
|
||||
sym->flags |= SYMBOL_OPTIONAL;
|
||||
menu_add_entry(sym);
|
||||
printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), $2);
|
||||
$2->flags |= SYMBOL_OPTIONAL;
|
||||
menu_add_entry($2);
|
||||
printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), $2->name);
|
||||
};
|
||||
|
||||
menuconfig_stmt: menuconfig_entry_start config_option_list
|
||||
@ -173,53 +166,49 @@ menuconfig_stmt: menuconfig_entry_start config_option_list
|
||||
current_entry->prompt->type = P_MENU;
|
||||
else
|
||||
zconfprint("warning: menuconfig statement without prompt");
|
||||
menu_end_entry();
|
||||
printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno());
|
||||
};
|
||||
|
||||
config_option_list:
|
||||
/* empty */
|
||||
| config_option_list config_option
|
||||
| config_option_list symbol_option
|
||||
| config_option_list depends
|
||||
| config_option_list help
|
||||
| config_option_list option_error
|
||||
| config_option_list T_EOL
|
||||
;
|
||||
|
||||
config_option: T_TYPE prompt_stmt_opt T_EOL
|
||||
config_option: type prompt_stmt_opt T_EOL
|
||||
{
|
||||
menu_set_type($1->stype);
|
||||
menu_set_type($1);
|
||||
printd(DEBUG_PARSE, "%s:%d:type(%u)\n",
|
||||
zconf_curname(), zconf_lineno(),
|
||||
$1->stype);
|
||||
$1);
|
||||
};
|
||||
|
||||
config_option: T_PROMPT prompt if_expr T_EOL
|
||||
config_option: T_PROMPT T_WORD_QUOTE if_expr T_EOL
|
||||
{
|
||||
menu_add_prompt(P_PROMPT, $2, $3);
|
||||
printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
|
||||
};
|
||||
|
||||
config_option: T_DEFAULT expr if_expr T_EOL
|
||||
config_option: default expr if_expr T_EOL
|
||||
{
|
||||
menu_add_expr(P_DEFAULT, $2, $3);
|
||||
if ($1->stype != S_UNKNOWN)
|
||||
menu_set_type($1->stype);
|
||||
if ($1 != S_UNKNOWN)
|
||||
menu_set_type($1);
|
||||
printd(DEBUG_PARSE, "%s:%d:default(%u)\n",
|
||||
zconf_curname(), zconf_lineno(),
|
||||
$1->stype);
|
||||
$1);
|
||||
};
|
||||
|
||||
config_option: T_SELECT T_WORD if_expr T_EOL
|
||||
config_option: T_SELECT nonconst_symbol if_expr T_EOL
|
||||
{
|
||||
menu_add_symbol(P_SELECT, sym_lookup($2, 0), $3);
|
||||
menu_add_symbol(P_SELECT, $2, $3);
|
||||
printd(DEBUG_PARSE, "%s:%d:select\n", zconf_curname(), zconf_lineno());
|
||||
};
|
||||
|
||||
config_option: T_IMPLY T_WORD if_expr T_EOL
|
||||
config_option: T_IMPLY nonconst_symbol if_expr T_EOL
|
||||
{
|
||||
menu_add_symbol(P_IMPLY, sym_lookup($2, 0), $3);
|
||||
menu_add_symbol(P_IMPLY, $2, $3);
|
||||
printd(DEBUG_PARSE, "%s:%d:imply\n", zconf_curname(), zconf_lineno());
|
||||
};
|
||||
|
||||
@ -229,34 +218,30 @@ config_option: T_RANGE symbol symbol if_expr T_EOL
|
||||
printd(DEBUG_PARSE, "%s:%d:range\n", zconf_curname(), zconf_lineno());
|
||||
};
|
||||
|
||||
symbol_option: T_OPTION symbol_option_list T_EOL
|
||||
;
|
||||
|
||||
symbol_option_list:
|
||||
/* empty */
|
||||
| symbol_option_list T_WORD symbol_option_arg
|
||||
config_option: T_OPTION T_MODULES T_EOL
|
||||
{
|
||||
const struct kconf_id *id = kconf_id_lookup($2, strlen($2));
|
||||
if (id && id->flags & TF_OPTION)
|
||||
menu_add_option(id->token, $3);
|
||||
else
|
||||
zconfprint("warning: ignoring unknown option %s", $2);
|
||||
free($2);
|
||||
menu_add_option_modules();
|
||||
};
|
||||
|
||||
symbol_option_arg:
|
||||
/* empty */ { $$ = NULL; }
|
||||
| T_EQUAL prompt { $$ = $2; }
|
||||
;
|
||||
config_option: T_OPTION T_DEFCONFIG_LIST T_EOL
|
||||
{
|
||||
menu_add_option_defconfig_list();
|
||||
};
|
||||
|
||||
config_option: T_OPTION T_ALLNOCONFIG_Y T_EOL
|
||||
{
|
||||
menu_add_option_allnoconfig_y();
|
||||
};
|
||||
|
||||
/* choice entry */
|
||||
|
||||
choice: T_CHOICE word_opt T_EOL
|
||||
{
|
||||
struct symbol *sym = sym_lookup($2, SYMBOL_CHOICE);
|
||||
sym->flags |= SYMBOL_AUTO;
|
||||
sym->flags |= SYMBOL_NO_WRITE;
|
||||
menu_add_entry(sym);
|
||||
menu_add_expr(P_CHOICE, NULL, NULL);
|
||||
free($2);
|
||||
printd(DEBUG_PARSE, "%s:%d:choice\n", zconf_curname(), zconf_lineno());
|
||||
};
|
||||
|
||||
@ -267,13 +252,13 @@ choice_entry: choice choice_option_list
|
||||
|
||||
choice_end: end
|
||||
{
|
||||
if (zconf_endtoken($1, T_CHOICE, T_ENDCHOICE)) {
|
||||
if (zconf_endtoken($1, "choice")) {
|
||||
menu_end_menu();
|
||||
printd(DEBUG_PARSE, "%s:%d:endchoice\n", zconf_curname(), zconf_lineno());
|
||||
}
|
||||
};
|
||||
|
||||
choice_stmt: choice_entry choice_block choice_end
|
||||
choice_stmt: choice_entry stmt_list_in_choice choice_end
|
||||
;
|
||||
|
||||
choice_option_list:
|
||||
@ -281,25 +266,19 @@ choice_option_list:
|
||||
| choice_option_list choice_option
|
||||
| choice_option_list depends
|
||||
| choice_option_list help
|
||||
| choice_option_list T_EOL
|
||||
| choice_option_list option_error
|
||||
;
|
||||
|
||||
choice_option: T_PROMPT prompt if_expr T_EOL
|
||||
choice_option: T_PROMPT T_WORD_QUOTE if_expr T_EOL
|
||||
{
|
||||
menu_add_prompt(P_PROMPT, $2, $3);
|
||||
printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
|
||||
};
|
||||
|
||||
choice_option: T_TYPE prompt_stmt_opt T_EOL
|
||||
choice_option: logic_type prompt_stmt_opt T_EOL
|
||||
{
|
||||
if ($1->stype == S_BOOLEAN || $1->stype == S_TRISTATE) {
|
||||
menu_set_type($1->stype);
|
||||
printd(DEBUG_PARSE, "%s:%d:type(%u)\n",
|
||||
zconf_curname(), zconf_lineno(),
|
||||
$1->stype);
|
||||
} else
|
||||
YYERROR;
|
||||
menu_set_type($1);
|
||||
printd(DEBUG_PARSE, "%s:%d:type(%u)\n",
|
||||
zconf_curname(), zconf_lineno(), $1);
|
||||
};
|
||||
|
||||
choice_option: T_OPTIONAL T_EOL
|
||||
@ -308,24 +287,31 @@ choice_option: T_OPTIONAL T_EOL
|
||||
printd(DEBUG_PARSE, "%s:%d:optional\n", zconf_curname(), zconf_lineno());
|
||||
};
|
||||
|
||||
choice_option: T_DEFAULT T_WORD if_expr T_EOL
|
||||
choice_option: T_DEFAULT nonconst_symbol if_expr T_EOL
|
||||
{
|
||||
if ($1->stype == S_UNKNOWN) {
|
||||
menu_add_symbol(P_DEFAULT, sym_lookup($2, 0), $3);
|
||||
printd(DEBUG_PARSE, "%s:%d:default\n",
|
||||
zconf_curname(), zconf_lineno());
|
||||
} else
|
||||
YYERROR;
|
||||
menu_add_symbol(P_DEFAULT, $2, $3);
|
||||
printd(DEBUG_PARSE, "%s:%d:default\n",
|
||||
zconf_curname(), zconf_lineno());
|
||||
};
|
||||
|
||||
choice_block:
|
||||
/* empty */
|
||||
| choice_block common_stmt
|
||||
;
|
||||
type:
|
||||
logic_type
|
||||
| T_INT { $$ = S_INT; }
|
||||
| T_HEX { $$ = S_HEX; }
|
||||
| T_STRING { $$ = S_STRING; }
|
||||
|
||||
logic_type:
|
||||
T_BOOL { $$ = S_BOOLEAN; }
|
||||
| T_TRISTATE { $$ = S_TRISTATE; }
|
||||
|
||||
default:
|
||||
T_DEFAULT { $$ = S_UNKNOWN; }
|
||||
| T_DEF_BOOL { $$ = S_BOOLEAN; }
|
||||
| T_DEF_TRISTATE { $$ = S_TRISTATE; }
|
||||
|
||||
/* if entry */
|
||||
|
||||
if_entry: T_IF expr nl
|
||||
if_entry: T_IF expr T_EOL
|
||||
{
|
||||
printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno());
|
||||
menu_add_entry(NULL);
|
||||
@ -335,80 +321,72 @@ if_entry: T_IF expr nl
|
||||
|
||||
if_end: end
|
||||
{
|
||||
if (zconf_endtoken($1, T_IF, T_ENDIF)) {
|
||||
if (zconf_endtoken($1, "if")) {
|
||||
menu_end_menu();
|
||||
printd(DEBUG_PARSE, "%s:%d:endif\n", zconf_curname(), zconf_lineno());
|
||||
}
|
||||
};
|
||||
|
||||
if_stmt: if_entry if_block if_end
|
||||
if_stmt: if_entry stmt_list if_end
|
||||
;
|
||||
|
||||
if_block:
|
||||
/* empty */
|
||||
| if_block common_stmt
|
||||
| if_block menu_stmt
|
||||
| if_block choice_stmt
|
||||
if_stmt_in_choice: if_entry stmt_list_in_choice if_end
|
||||
;
|
||||
|
||||
/* mainmenu entry */
|
||||
|
||||
mainmenu_stmt: T_MAINMENU prompt nl
|
||||
{
|
||||
menu_add_prompt(P_MENU, $2, NULL);
|
||||
};
|
||||
|
||||
/* menu entry */
|
||||
|
||||
menu: T_MENU prompt T_EOL
|
||||
menu: T_MENU T_WORD_QUOTE T_EOL
|
||||
{
|
||||
menu_add_entry(NULL);
|
||||
menu_add_prompt(P_MENU, $2, NULL);
|
||||
printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno());
|
||||
};
|
||||
|
||||
menu_entry: menu visibility_list depends_list
|
||||
menu_entry: menu menu_option_list
|
||||
{
|
||||
$$ = menu_add_menu();
|
||||
};
|
||||
|
||||
menu_end: end
|
||||
{
|
||||
if (zconf_endtoken($1, T_MENU, T_ENDMENU)) {
|
||||
if (zconf_endtoken($1, "menu")) {
|
||||
menu_end_menu();
|
||||
printd(DEBUG_PARSE, "%s:%d:endmenu\n", zconf_curname(), zconf_lineno());
|
||||
}
|
||||
};
|
||||
|
||||
menu_stmt: menu_entry menu_block menu_end
|
||||
menu_stmt: menu_entry stmt_list menu_end
|
||||
;
|
||||
|
||||
menu_block:
|
||||
menu_option_list:
|
||||
/* empty */
|
||||
| menu_block common_stmt
|
||||
| menu_block menu_stmt
|
||||
| menu_block choice_stmt
|
||||
| menu_option_list visible
|
||||
| menu_option_list depends
|
||||
;
|
||||
|
||||
source_stmt: T_SOURCE prompt T_EOL
|
||||
source_stmt: T_SOURCE T_WORD_QUOTE T_EOL
|
||||
{
|
||||
printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), $2);
|
||||
zconf_nextfile($2);
|
||||
free($2);
|
||||
};
|
||||
|
||||
/* comment entry */
|
||||
|
||||
comment: T_COMMENT prompt T_EOL
|
||||
comment: T_COMMENT T_WORD_QUOTE T_EOL
|
||||
{
|
||||
menu_add_entry(NULL);
|
||||
menu_add_prompt(P_COMMENT, $2, NULL);
|
||||
printd(DEBUG_PARSE, "%s:%d:comment\n", zconf_curname(), zconf_lineno());
|
||||
};
|
||||
|
||||
comment_stmt: comment depends_list
|
||||
{
|
||||
menu_end_entry();
|
||||
};
|
||||
comment_stmt: comment comment_option_list
|
||||
;
|
||||
|
||||
comment_option_list:
|
||||
/* empty */
|
||||
| comment_option_list depends
|
||||
;
|
||||
|
||||
/* help option */
|
||||
|
||||
@ -420,18 +398,22 @@ help_start: T_HELP T_EOL
|
||||
|
||||
help: help_start T_HELPTEXT
|
||||
{
|
||||
if (current_entry->help) {
|
||||
free(current_entry->help);
|
||||
zconfprint("warning: '%s' defined with more than one help text -- only the last one will be used",
|
||||
current_entry->sym->name ?: "<choice>");
|
||||
}
|
||||
|
||||
/* Is the help text empty or all whitespace? */
|
||||
if ($2[strspn($2, " \f\n\r\t\v")] == '\0')
|
||||
zconfprint("warning: '%s' defined with blank help text",
|
||||
current_entry->sym->name ?: "<choice>");
|
||||
|
||||
current_entry->help = $2;
|
||||
};
|
||||
|
||||
/* depends option */
|
||||
|
||||
depends_list:
|
||||
/* empty */
|
||||
| depends_list depends
|
||||
| depends_list T_EOL
|
||||
| depends_list option_error
|
||||
;
|
||||
|
||||
depends: T_DEPENDS T_ON expr T_EOL
|
||||
{
|
||||
menu_add_dep($3);
|
||||
@ -439,14 +421,7 @@ depends: T_DEPENDS T_ON expr T_EOL
|
||||
};
|
||||
|
||||
/* visibility option */
|
||||
|
||||
visibility_list:
|
||||
/* empty */
|
||||
| visibility_list visible
|
||||
| visibility_list T_EOL
|
||||
;
|
||||
|
||||
visible: T_VISIBLE if_expr
|
||||
visible: T_VISIBLE if_expr T_EOL
|
||||
{
|
||||
menu_add_visibility($2);
|
||||
};
|
||||
@ -455,23 +430,14 @@ visible: T_VISIBLE if_expr
|
||||
|
||||
prompt_stmt_opt:
|
||||
/* empty */
|
||||
| prompt if_expr
|
||||
| T_WORD_QUOTE if_expr
|
||||
{
|
||||
menu_add_prompt(P_PROMPT, $1, $2);
|
||||
};
|
||||
|
||||
prompt: T_WORD
|
||||
| T_WORD_QUOTE
|
||||
;
|
||||
|
||||
end: T_ENDMENU T_EOL { $$ = $1; }
|
||||
| T_ENDCHOICE T_EOL { $$ = $1; }
|
||||
| T_ENDIF T_EOL { $$ = $1; }
|
||||
;
|
||||
|
||||
nl:
|
||||
T_EOL
|
||||
| nl T_EOL
|
||||
end: T_ENDMENU T_EOL { $$ = "menu"; }
|
||||
| T_ENDCHOICE T_EOL { $$ = "choice"; }
|
||||
| T_ENDIF T_EOL { $$ = "if"; }
|
||||
;
|
||||
|
||||
if_expr: /* empty */ { $$ = NULL; }
|
||||
@ -491,13 +457,31 @@ expr: symbol { $$ = expr_alloc_symbol($1); }
|
||||
| expr T_AND expr { $$ = expr_alloc_two(E_AND, $1, $3); }
|
||||
;
|
||||
|
||||
symbol: T_WORD { $$ = sym_lookup($1, 0); free($1); }
|
||||
/* For symbol definitions, selects, etc., where quotes are not accepted */
|
||||
nonconst_symbol: T_WORD { $$ = sym_lookup($1, 0); free($1); };
|
||||
|
||||
symbol: nonconst_symbol
|
||||
| T_WORD_QUOTE { $$ = sym_lookup($1, SYMBOL_CONST); free($1); }
|
||||
;
|
||||
|
||||
word_opt: /* empty */ { $$ = NULL; }
|
||||
| T_WORD
|
||||
|
||||
/* assignment statement */
|
||||
|
||||
assignment_stmt: T_WORD assign_op assign_val T_EOL { variable_add($1, $3, $2); free($1); free($3); }
|
||||
|
||||
assign_op:
|
||||
T_EQUAL { $$ = VAR_RECURSIVE; }
|
||||
| T_COLON_EQUAL { $$ = VAR_SIMPLE; }
|
||||
| T_PLUS_EQUAL { $$ = VAR_APPEND; }
|
||||
;
|
||||
|
||||
assign_val:
|
||||
/* empty */ { $$ = xstrdup(""); };
|
||||
| T_ASSIGN_VAL
|
||||
;
|
||||
|
||||
%%
|
||||
|
||||
void conf_parse(const char *name)
|
||||
@ -507,63 +491,51 @@ void conf_parse(const char *name)
|
||||
|
||||
zconf_initscan(name);
|
||||
|
||||
sym_init();
|
||||
_menu_init();
|
||||
rootmenu.prompt = menu_add_prompt(P_MENU, "Crosstool-NG Configuration", NULL);
|
||||
|
||||
#if YYDEBUG
|
||||
if (getenv("ZCONF_DEBUG"))
|
||||
zconfdebug = 1;
|
||||
#endif
|
||||
zconfparse();
|
||||
if (zconfnerrs)
|
||||
yydebug = 1;
|
||||
yyparse();
|
||||
|
||||
/* Variables are expanded in the parse phase. We can free them here. */
|
||||
variable_all_del();
|
||||
|
||||
if (yynerrs)
|
||||
exit(1);
|
||||
if (!modules_sym)
|
||||
modules_sym = sym_find( "n" );
|
||||
|
||||
rootmenu.prompt->text = _(rootmenu.prompt->text);
|
||||
rootmenu.prompt->text = sym_expand_string_value(rootmenu.prompt->text);
|
||||
if (!menu_has_prompt(&rootmenu)) {
|
||||
current_entry = &rootmenu;
|
||||
menu_add_prompt(P_MENU, "Main menu", NULL);
|
||||
}
|
||||
|
||||
menu_finalize(&rootmenu);
|
||||
for_all_symbols(i, sym) {
|
||||
if (sym_check_deps(sym))
|
||||
zconfnerrs++;
|
||||
yynerrs++;
|
||||
}
|
||||
if (zconfnerrs)
|
||||
if (yynerrs)
|
||||
exit(1);
|
||||
sym_set_change_count(1);
|
||||
}
|
||||
|
||||
static const char *zconf_tokenname(int token)
|
||||
static bool zconf_endtoken(const char *tokenname,
|
||||
const char *expected_tokenname)
|
||||
{
|
||||
switch (token) {
|
||||
case T_MENU: return "menu";
|
||||
case T_ENDMENU: return "endmenu";
|
||||
case T_CHOICE: return "choice";
|
||||
case T_ENDCHOICE: return "endchoice";
|
||||
case T_IF: return "if";
|
||||
case T_ENDIF: return "endif";
|
||||
case T_DEPENDS: return "depends";
|
||||
case T_VISIBLE: return "visible";
|
||||
}
|
||||
return "<token>";
|
||||
}
|
||||
|
||||
static bool zconf_endtoken(const struct kconf_id *id, int starttoken, int endtoken)
|
||||
{
|
||||
if (id->token != endtoken) {
|
||||
if (strcmp(tokenname, expected_tokenname)) {
|
||||
zconf_error("unexpected '%s' within %s block",
|
||||
id->name, zconf_tokenname(starttoken));
|
||||
zconfnerrs++;
|
||||
tokenname, expected_tokenname);
|
||||
yynerrs++;
|
||||
return false;
|
||||
}
|
||||
if (current_menu->file != current_file) {
|
||||
zconf_error("'%s' in different file than '%s'",
|
||||
id->name, zconf_tokenname(starttoken));
|
||||
tokenname, expected_tokenname);
|
||||
fprintf(stderr, "%s:%d: location of the '%s'\n",
|
||||
current_menu->file->name, current_menu->lineno,
|
||||
zconf_tokenname(starttoken));
|
||||
zconfnerrs++;
|
||||
expected_tokenname);
|
||||
yynerrs++;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@ -584,7 +556,7 @@ static void zconf_error(const char *err, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
zconfnerrs++;
|
||||
yynerrs++;
|
||||
fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno());
|
||||
va_start(ap, err);
|
||||
vfprintf(stderr, err, ap);
|
||||
@ -592,7 +564,7 @@ static void zconf_error(const char *err, ...)
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
static void zconferror(const char *err)
|
||||
static void yyerror(const char *err)
|
||||
{
|
||||
fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno() + 1, err);
|
||||
}
|
||||
@ -625,7 +597,7 @@ static void print_symbol(FILE *out, struct menu *menu)
|
||||
fprintf(out, "\nconfig %s\n", sym->name);
|
||||
switch (sym->type) {
|
||||
case S_BOOLEAN:
|
||||
fputs(" boolean\n", out);
|
||||
fputs(" bool\n", out);
|
||||
break;
|
||||
case S_TRISTATE:
|
||||
fputs(" tristate\n", out);
|
||||
@ -688,6 +660,10 @@ static void print_symbol(FILE *out, struct menu *menu)
|
||||
print_quoted_string(out, prop->text);
|
||||
fputc('\n', out);
|
||||
break;
|
||||
case P_SYMBOL:
|
||||
fputs( " symbol ", out);
|
||||
fprintf(out, "%s\n", prop->menu->sym->name);
|
||||
break;
|
||||
default:
|
||||
fprintf(out, " unknown prop %d!\n", prop->type);
|
||||
break;
|
||||
@ -748,9 +724,4 @@ void zconfdump(FILE *out)
|
||||
}
|
||||
}
|
||||
|
||||
#include "zconf.lex.c"
|
||||
#include "util.c"
|
||||
#include "confdata.c"
|
||||
#include "expr.c"
|
||||
#include "symbol.c"
|
||||
#include "menu.c"
|
574
kconfig/preprocess.c
Normal file
574
kconfig/preprocess.c
Normal file
@ -0,0 +1,574 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
//
|
||||
// Copyright (C) 2018 Masahiro Yamada <yamada.masahiro@socionext.com>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "list.h"
|
||||
#include "lkc.h"
|
||||
|
||||
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
|
||||
|
||||
static char *expand_string_with_args(const char *in, int argc, char *argv[]);
|
||||
static char *expand_string(const char *in);
|
||||
|
||||
static void __attribute__((noreturn)) pperror(const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
fprintf(stderr, "%s:%d: ", current_file->name, yylineno);
|
||||
va_start(ap, format);
|
||||
vfprintf(stderr, format, ap);
|
||||
va_end(ap);
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Environment variables
|
||||
*/
|
||||
static LIST_HEAD(env_list);
|
||||
|
||||
struct env {
|
||||
char *name;
|
||||
char *value;
|
||||
struct list_head node;
|
||||
};
|
||||
|
||||
static void env_add(const char *name, const char *value)
|
||||
{
|
||||
struct env *e;
|
||||
|
||||
e = xmalloc(sizeof(*e));
|
||||
e->name = xstrdup(name);
|
||||
e->value = xstrdup(value);
|
||||
|
||||
list_add_tail(&e->node, &env_list);
|
||||
}
|
||||
|
||||
static void env_del(struct env *e)
|
||||
{
|
||||
list_del(&e->node);
|
||||
free(e->name);
|
||||
free(e->value);
|
||||
free(e);
|
||||
}
|
||||
|
||||
/* The returned pointer must be freed when done */
|
||||
static char *env_expand(const char *name)
|
||||
{
|
||||
struct env *e;
|
||||
const char *value;
|
||||
|
||||
if (!*name)
|
||||
return NULL;
|
||||
|
||||
list_for_each_entry(e, &env_list, node) {
|
||||
if (!strcmp(name, e->name))
|
||||
return xstrdup(e->value);
|
||||
}
|
||||
|
||||
value = getenv(name);
|
||||
if (!value)
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* We need to remember all referenced environment variables.
|
||||
* They will be written out to include/config/auto.conf.cmd
|
||||
*/
|
||||
env_add(name, value);
|
||||
|
||||
return xstrdup(value);
|
||||
}
|
||||
|
||||
void env_write_dep(FILE *f, const char *autoconfig_name)
|
||||
{
|
||||
struct env *e, *tmp;
|
||||
|
||||
list_for_each_entry_safe(e, tmp, &env_list, node) {
|
||||
fprintf(f, "ifneq \"$(%s)\" \"%s\"\n", e->name, e->value);
|
||||
fprintf(f, "%s: FORCE\n", autoconfig_name);
|
||||
fprintf(f, "endif\n");
|
||||
env_del(e);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Built-in functions
|
||||
*/
|
||||
struct function {
|
||||
const char *name;
|
||||
unsigned int min_args;
|
||||
unsigned int max_args;
|
||||
char *(*func)(int argc, char *argv[]);
|
||||
};
|
||||
|
||||
static char *do_error_if(int argc, char *argv[])
|
||||
{
|
||||
if (!strcmp(argv[0], "y"))
|
||||
pperror("%s", argv[1]);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static char *do_filename(int argc, char *argv[])
|
||||
{
|
||||
return xstrdup(current_file->name);
|
||||
}
|
||||
|
||||
static char *do_info(int argc, char *argv[])
|
||||
{
|
||||
printf("%s\n", argv[0]);
|
||||
|
||||
return xstrdup("");
|
||||
}
|
||||
|
||||
static char *do_lineno(int argc, char *argv[])
|
||||
{
|
||||
char buf[16];
|
||||
|
||||
sprintf(buf, "%d", yylineno);
|
||||
|
||||
return xstrdup(buf);
|
||||
}
|
||||
|
||||
static char *do_shell(int argc, char *argv[])
|
||||
{
|
||||
FILE *p;
|
||||
char buf[256];
|
||||
char *cmd;
|
||||
size_t nread;
|
||||
int i;
|
||||
|
||||
cmd = argv[0];
|
||||
|
||||
p = popen(cmd, "r");
|
||||
if (!p) {
|
||||
perror(cmd);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
nread = fread(buf, 1, sizeof(buf), p);
|
||||
if (nread == sizeof(buf))
|
||||
nread--;
|
||||
|
||||
/* remove trailing new lines */
|
||||
while (nread > 0 && buf[nread - 1] == '\n')
|
||||
nread--;
|
||||
|
||||
buf[nread] = 0;
|
||||
|
||||
/* replace a new line with a space */
|
||||
for (i = 0; i < nread; i++) {
|
||||
if (buf[i] == '\n')
|
||||
buf[i] = ' ';
|
||||
}
|
||||
|
||||
if (pclose(p) == -1) {
|
||||
perror(cmd);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return xstrdup(buf);
|
||||
}
|
||||
|
||||
static char *do_warning_if(int argc, char *argv[])
|
||||
{
|
||||
if (!strcmp(argv[0], "y"))
|
||||
fprintf(stderr, "%s:%d: %s\n",
|
||||
current_file->name, yylineno, argv[1]);
|
||||
|
||||
return xstrdup("");
|
||||
}
|
||||
|
||||
static const struct function function_table[] = {
|
||||
/* Name MIN MAX Function */
|
||||
{ "error-if", 2, 2, do_error_if },
|
||||
{ "filename", 0, 0, do_filename },
|
||||
{ "info", 1, 1, do_info },
|
||||
{ "lineno", 0, 0, do_lineno },
|
||||
{ "shell", 1, 1, do_shell },
|
||||
{ "warning-if", 2, 2, do_warning_if },
|
||||
};
|
||||
|
||||
#define FUNCTION_MAX_ARGS 16
|
||||
|
||||
static char *function_expand(const char *name, int argc, char *argv[])
|
||||
{
|
||||
const struct function *f;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(function_table); i++) {
|
||||
f = &function_table[i];
|
||||
if (strcmp(f->name, name))
|
||||
continue;
|
||||
|
||||
if (argc < f->min_args)
|
||||
pperror("too few function arguments passed to '%s'",
|
||||
name);
|
||||
|
||||
if (argc > f->max_args)
|
||||
pperror("too many function arguments passed to '%s'",
|
||||
name);
|
||||
|
||||
return f->func(argc, argv);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Variables (and user-defined functions)
|
||||
*/
|
||||
static LIST_HEAD(variable_list);
|
||||
|
||||
struct variable {
|
||||
char *name;
|
||||
char *value;
|
||||
enum variable_flavor flavor;
|
||||
int exp_count;
|
||||
struct list_head node;
|
||||
};
|
||||
|
||||
static struct variable *variable_lookup(const char *name)
|
||||
{
|
||||
struct variable *v;
|
||||
|
||||
list_for_each_entry(v, &variable_list, node) {
|
||||
if (!strcmp(name, v->name))
|
||||
return v;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static char *variable_expand(const char *name, int argc, char *argv[])
|
||||
{
|
||||
struct variable *v;
|
||||
char *res;
|
||||
|
||||
v = variable_lookup(name);
|
||||
if (!v)
|
||||
return NULL;
|
||||
|
||||
if (argc == 0 && v->exp_count)
|
||||
pperror("Recursive variable '%s' references itself (eventually)",
|
||||
name);
|
||||
|
||||
if (v->exp_count > 1000)
|
||||
pperror("Too deep recursive expansion");
|
||||
|
||||
v->exp_count++;
|
||||
|
||||
if (v->flavor == VAR_RECURSIVE)
|
||||
res = expand_string_with_args(v->value, argc, argv);
|
||||
else
|
||||
res = xstrdup(v->value);
|
||||
|
||||
v->exp_count--;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void variable_add(const char *name, const char *value,
|
||||
enum variable_flavor flavor)
|
||||
{
|
||||
struct variable *v;
|
||||
char *new_value;
|
||||
bool append = false;
|
||||
|
||||
v = variable_lookup(name);
|
||||
if (v) {
|
||||
/* For defined variables, += inherits the existing flavor */
|
||||
if (flavor == VAR_APPEND) {
|
||||
flavor = v->flavor;
|
||||
append = true;
|
||||
} else {
|
||||
free(v->value);
|
||||
}
|
||||
} else {
|
||||
/* For undefined variables, += assumes the recursive flavor */
|
||||
if (flavor == VAR_APPEND)
|
||||
flavor = VAR_RECURSIVE;
|
||||
|
||||
v = xmalloc(sizeof(*v));
|
||||
v->name = xstrdup(name);
|
||||
v->exp_count = 0;
|
||||
list_add_tail(&v->node, &variable_list);
|
||||
}
|
||||
|
||||
v->flavor = flavor;
|
||||
|
||||
if (flavor == VAR_SIMPLE)
|
||||
new_value = expand_string(value);
|
||||
else
|
||||
new_value = xstrdup(value);
|
||||
|
||||
if (append) {
|
||||
v->value = xrealloc(v->value,
|
||||
strlen(v->value) + strlen(new_value) + 2);
|
||||
strcat(v->value, " ");
|
||||
strcat(v->value, new_value);
|
||||
free(new_value);
|
||||
} else {
|
||||
v->value = new_value;
|
||||
}
|
||||
}
|
||||
|
||||
static void variable_del(struct variable *v)
|
||||
{
|
||||
list_del(&v->node);
|
||||
free(v->name);
|
||||
free(v->value);
|
||||
free(v);
|
||||
}
|
||||
|
||||
void variable_all_del(void)
|
||||
{
|
||||
struct variable *v, *tmp;
|
||||
|
||||
list_for_each_entry_safe(v, tmp, &variable_list, node)
|
||||
variable_del(v);
|
||||
}
|
||||
|
||||
/*
|
||||
* Evaluate a clause with arguments. argc/argv are arguments from the upper
|
||||
* function call.
|
||||
*
|
||||
* Returned string must be freed when done
|
||||
*/
|
||||
static char *eval_clause(const char *str, size_t len, int argc, char *argv[])
|
||||
{
|
||||
char *tmp, *name, *res, *endptr, *prev, *p;
|
||||
int new_argc = 0;
|
||||
char *new_argv[FUNCTION_MAX_ARGS];
|
||||
int nest = 0;
|
||||
int i;
|
||||
unsigned long n;
|
||||
|
||||
tmp = xstrndup(str, len);
|
||||
|
||||
/*
|
||||
* If variable name is '1', '2', etc. It is generally an argument
|
||||
* from a user-function call (i.e. local-scope variable). If not
|
||||
* available, then look-up global-scope variables.
|
||||
*/
|
||||
n = strtoul(tmp, &endptr, 10);
|
||||
if (!*endptr && n > 0 && n <= argc) {
|
||||
res = xstrdup(argv[n - 1]);
|
||||
goto free_tmp;
|
||||
}
|
||||
|
||||
prev = p = tmp;
|
||||
|
||||
/*
|
||||
* Split into tokens
|
||||
* The function name and arguments are separated by a comma.
|
||||
* For example, if the function call is like this:
|
||||
* $(foo,$(x),$(y))
|
||||
*
|
||||
* The input string for this helper should be:
|
||||
* foo,$(x),$(y)
|
||||
*
|
||||
* and split into:
|
||||
* new_argv[0] = 'foo'
|
||||
* new_argv[1] = '$(x)'
|
||||
* new_argv[2] = '$(y)'
|
||||
*/
|
||||
while (*p) {
|
||||
if (nest == 0 && *p == ',') {
|
||||
*p = 0;
|
||||
if (new_argc >= FUNCTION_MAX_ARGS)
|
||||
pperror("too many function arguments");
|
||||
new_argv[new_argc++] = prev;
|
||||
prev = p + 1;
|
||||
} else if (*p == '(') {
|
||||
nest++;
|
||||
} else if (*p == ')') {
|
||||
nest--;
|
||||
}
|
||||
|
||||
p++;
|
||||
}
|
||||
new_argv[new_argc++] = prev;
|
||||
|
||||
/*
|
||||
* Shift arguments
|
||||
* new_argv[0] represents a function name or a variable name. Put it
|
||||
* into 'name', then shift the rest of the arguments. This simplifies
|
||||
* 'const' handling.
|
||||
*/
|
||||
name = expand_string_with_args(new_argv[0], argc, argv);
|
||||
new_argc--;
|
||||
for (i = 0; i < new_argc; i++)
|
||||
new_argv[i] = expand_string_with_args(new_argv[i + 1],
|
||||
argc, argv);
|
||||
|
||||
/* Search for variables */
|
||||
res = variable_expand(name, new_argc, new_argv);
|
||||
if (res)
|
||||
goto free;
|
||||
|
||||
/* Look for built-in functions */
|
||||
res = function_expand(name, new_argc, new_argv);
|
||||
if (res)
|
||||
goto free;
|
||||
|
||||
/* Last, try environment variable */
|
||||
if (new_argc == 0) {
|
||||
res = env_expand(name);
|
||||
if (res)
|
||||
goto free;
|
||||
}
|
||||
|
||||
res = xstrdup("");
|
||||
free:
|
||||
for (i = 0; i < new_argc; i++)
|
||||
free(new_argv[i]);
|
||||
free(name);
|
||||
free_tmp:
|
||||
free(tmp);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Expand a string that follows '$'
|
||||
*
|
||||
* For example, if the input string is
|
||||
* ($(FOO)$($(BAR)))$(BAZ)
|
||||
* this helper evaluates
|
||||
* $($(FOO)$($(BAR)))
|
||||
* and returns a new string containing the expansion (note that the string is
|
||||
* recursively expanded), also advancing 'str' to point to the next character
|
||||
* after the corresponding closing parenthesis, in this case, *str will be
|
||||
* $(BAR)
|
||||
*/
|
||||
static char *expand_dollar_with_args(const char **str, int argc, char *argv[])
|
||||
{
|
||||
const char *p = *str;
|
||||
const char *q;
|
||||
int nest = 0;
|
||||
|
||||
/*
|
||||
* In Kconfig, variable/function references always start with "$(".
|
||||
* Neither single-letter variables as in $A nor curly braces as in ${CC}
|
||||
* are supported. '$' not followed by '(' loses its special meaning.
|
||||
*/
|
||||
if (*p != '(') {
|
||||
*str = p;
|
||||
return xstrdup("$");
|
||||
}
|
||||
|
||||
p++;
|
||||
q = p;
|
||||
while (*q) {
|
||||
if (*q == '(') {
|
||||
nest++;
|
||||
} else if (*q == ')') {
|
||||
if (nest-- == 0)
|
||||
break;
|
||||
}
|
||||
q++;
|
||||
}
|
||||
|
||||
if (!*q)
|
||||
pperror("unterminated reference to '%s': missing ')'", p);
|
||||
|
||||
/* Advance 'str' to after the expanded initial portion of the string */
|
||||
*str = q + 1;
|
||||
|
||||
return eval_clause(p, q - p, argc, argv);
|
||||
}
|
||||
|
||||
char *expand_dollar(const char **str)
|
||||
{
|
||||
return expand_dollar_with_args(str, 0, NULL);
|
||||
}
|
||||
|
||||
static char *__expand_string(const char **str, bool (*is_end)(char c),
|
||||
int argc, char *argv[])
|
||||
{
|
||||
const char *in, *p;
|
||||
char *expansion, *out;
|
||||
size_t in_len, out_len;
|
||||
|
||||
out = xmalloc(1);
|
||||
*out = 0;
|
||||
out_len = 1;
|
||||
|
||||
p = in = *str;
|
||||
|
||||
while (1) {
|
||||
if (*p == '$') {
|
||||
in_len = p - in;
|
||||
p++;
|
||||
expansion = expand_dollar_with_args(&p, argc, argv);
|
||||
out_len += in_len + strlen(expansion);
|
||||
out = xrealloc(out, out_len);
|
||||
strncat(out, in, in_len);
|
||||
strcat(out, expansion);
|
||||
free(expansion);
|
||||
in = p;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (is_end(*p))
|
||||
break;
|
||||
|
||||
p++;
|
||||
}
|
||||
|
||||
in_len = p - in;
|
||||
out_len += in_len;
|
||||
out = xrealloc(out, out_len);
|
||||
strncat(out, in, in_len);
|
||||
|
||||
/* Advance 'str' to the end character */
|
||||
*str = p;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
static bool is_end_of_str(char c)
|
||||
{
|
||||
return !c;
|
||||
}
|
||||
|
||||
/*
|
||||
* Expand variables and functions in the given string. Undefined variables
|
||||
* expand to an empty string.
|
||||
* The returned string must be freed when done.
|
||||
*/
|
||||
static char *expand_string_with_args(const char *in, int argc, char *argv[])
|
||||
{
|
||||
return __expand_string(&in, is_end_of_str, argc, argv);
|
||||
}
|
||||
|
||||
static char *expand_string(const char *in)
|
||||
{
|
||||
return expand_string_with_args(in, 0, NULL);
|
||||
}
|
||||
|
||||
static bool is_end_of_token(char c)
|
||||
{
|
||||
return !(isalnum(c) || c == '_' || c == '-');
|
||||
}
|
||||
|
||||
/*
|
||||
* Expand variables in a token. The parsing stops when a token separater
|
||||
* (in most cases, it is a whitespace) is encountered. 'str' is updated to
|
||||
* point to the next character.
|
||||
*
|
||||
* The returned string must be freed when done.
|
||||
*/
|
||||
char *expand_one_token(const char **str)
|
||||
{
|
||||
return __expand_string(str, is_end_of_token, 0, NULL);
|
||||
}
|
300
kconfig/symbol.c
300
kconfig/symbol.c
@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
|
||||
* Released under the terms of the GNU GPL v2.0.
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
@ -15,15 +15,21 @@ struct symbol symbol_yes = {
|
||||
.name = "y",
|
||||
.curr = { "y", yes },
|
||||
.flags = SYMBOL_CONST|SYMBOL_VALID,
|
||||
}, symbol_mod = {
|
||||
};
|
||||
|
||||
struct symbol symbol_mod = {
|
||||
.name = "m",
|
||||
.curr = { "m", mod },
|
||||
.flags = SYMBOL_CONST|SYMBOL_VALID,
|
||||
}, symbol_no = {
|
||||
};
|
||||
|
||||
struct symbol symbol_no = {
|
||||
.name = "n",
|
||||
.curr = { "n", no },
|
||||
.flags = SYMBOL_CONST|SYMBOL_VALID,
|
||||
}, symbol_empty = {
|
||||
};
|
||||
|
||||
static struct symbol symbol_empty = {
|
||||
.name = "",
|
||||
.curr = { "", no },
|
||||
.flags = SYMBOL_VALID,
|
||||
@ -31,34 +37,7 @@ struct symbol symbol_yes = {
|
||||
|
||||
struct symbol *sym_defconfig_list;
|
||||
struct symbol *modules_sym;
|
||||
tristate modules_val;
|
||||
|
||||
struct expr *sym_env_list;
|
||||
|
||||
static void sym_add_default(struct symbol *sym, const char *def)
|
||||
{
|
||||
struct property *prop = prop_alloc(P_DEFAULT, sym);
|
||||
|
||||
prop->expr = expr_alloc_symbol(sym_lookup(def, SYMBOL_CONST));
|
||||
}
|
||||
|
||||
void sym_init(void)
|
||||
{
|
||||
struct symbol *sym;
|
||||
struct utsname uts;
|
||||
static bool inited = false;
|
||||
|
||||
if (inited)
|
||||
return;
|
||||
inited = true;
|
||||
|
||||
uname(&uts);
|
||||
|
||||
sym = sym_lookup("UNAME_RELEASE", 0);
|
||||
sym->type = S_STRING;
|
||||
sym->flags |= SYMBOL_AUTO;
|
||||
sym_add_default(sym, uts.release);
|
||||
}
|
||||
static tristate modules_val;
|
||||
|
||||
enum symbol_type sym_get_type(struct symbol *sym)
|
||||
{
|
||||
@ -77,7 +56,7 @@ const char *sym_type_name(enum symbol_type type)
|
||||
{
|
||||
switch (type) {
|
||||
case S_BOOLEAN:
|
||||
return "boolean";
|
||||
return "bool";
|
||||
case S_TRISTATE:
|
||||
return "tristate";
|
||||
case S_INT:
|
||||
@ -88,8 +67,6 @@ const char *sym_type_name(enum symbol_type type)
|
||||
return "string";
|
||||
case S_UNKNOWN:
|
||||
return "unknown";
|
||||
case S_OTHER:
|
||||
break;
|
||||
}
|
||||
return "???";
|
||||
}
|
||||
@ -103,15 +80,6 @@ struct property *sym_get_choice_prop(struct symbol *sym)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct property *sym_get_env_prop(struct symbol *sym)
|
||||
{
|
||||
struct property *prop;
|
||||
|
||||
for_all_properties(sym, prop, P_ENV)
|
||||
return prop;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct property *sym_get_default_prop(struct symbol *sym)
|
||||
{
|
||||
struct property *prop;
|
||||
@ -124,7 +92,7 @@ static struct property *sym_get_default_prop(struct symbol *sym)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct property *sym_get_range_prop(struct symbol *sym)
|
||||
struct property *sym_get_range_prop(struct symbol *sym)
|
||||
{
|
||||
struct property *prop;
|
||||
|
||||
@ -183,7 +151,7 @@ static void sym_validate_range(struct symbol *sym)
|
||||
sprintf(str, "%lld", val2);
|
||||
else
|
||||
sprintf(str, "0x%llx", val2);
|
||||
sym->curr.val = strdup(str);
|
||||
sym->curr.val = xstrdup(str);
|
||||
}
|
||||
|
||||
static void sym_set_changed(struct symbol *sym)
|
||||
@ -243,7 +211,7 @@ static void sym_calc_visibility(struct symbol *sym)
|
||||
tri = yes;
|
||||
if (sym->dir_dep.expr)
|
||||
tri = expr_calc_value(sym->dir_dep.expr);
|
||||
if (tri == mod)
|
||||
if (tri == mod && sym_get_type(sym) == S_BOOLEAN)
|
||||
tri = yes;
|
||||
if (sym->dir_dep.tri != tri) {
|
||||
sym->dir_dep.tri = tri;
|
||||
@ -259,7 +227,7 @@ static void sym_calc_visibility(struct symbol *sym)
|
||||
sym_set_changed(sym);
|
||||
}
|
||||
tri = no;
|
||||
if (sym->implied.expr && sym->dir_dep.tri != no)
|
||||
if (sym->implied.expr)
|
||||
tri = expr_calc_value(sym->implied.expr);
|
||||
if (tri == mod && sym_get_type(sym) == S_BOOLEAN)
|
||||
tri = yes;
|
||||
@ -333,6 +301,27 @@ static struct symbol *sym_calc_choice(struct symbol *sym)
|
||||
return def_sym;
|
||||
}
|
||||
|
||||
static void sym_warn_unmet_dep(struct symbol *sym)
|
||||
{
|
||||
struct gstr gs = str_new();
|
||||
|
||||
str_printf(&gs,
|
||||
"\nWARNING: unmet direct dependencies detected for %s\n",
|
||||
sym->name);
|
||||
str_printf(&gs,
|
||||
" Depends on [%c]: ",
|
||||
sym->dir_dep.tri == mod ? 'm' : 'n');
|
||||
expr_gstr_print(sym->dir_dep.expr, &gs);
|
||||
str_printf(&gs, "\n");
|
||||
|
||||
expr_gstr_print_revdep(sym->rev_dep.expr, &gs, yes,
|
||||
" Selected by [y]:\n");
|
||||
expr_gstr_print_revdep(sym->rev_dep.expr, &gs, mod,
|
||||
" Selected by [m]:\n");
|
||||
|
||||
fputs(str_get(&gs), stderr);
|
||||
}
|
||||
|
||||
void sym_calc_value(struct symbol *sym)
|
||||
{
|
||||
struct symbol_value newval, oldval;
|
||||
@ -371,11 +360,13 @@ void sym_calc_value(struct symbol *sym)
|
||||
sym->curr.tri = no;
|
||||
return;
|
||||
}
|
||||
if (!sym_is_choice_value(sym))
|
||||
sym->flags &= ~SYMBOL_WRITE;
|
||||
sym->flags &= ~SYMBOL_WRITE;
|
||||
|
||||
sym_calc_visibility(sym);
|
||||
|
||||
if (sym->visible != no)
|
||||
sym->flags |= SYMBOL_WRITE;
|
||||
|
||||
/* set default if recursively called */
|
||||
sym->curr = newval;
|
||||
|
||||
@ -390,7 +381,6 @@ void sym_calc_value(struct symbol *sym)
|
||||
/* if the symbol is visible use the user value
|
||||
* if available, otherwise try the default value
|
||||
*/
|
||||
sym->flags |= SYMBOL_WRITE;
|
||||
if (sym_has_value(sym)) {
|
||||
newval.tri = EXPR_AND(sym->def[S_DEF_USER].tri,
|
||||
sym->visible);
|
||||
@ -402,43 +392,32 @@ void sym_calc_value(struct symbol *sym)
|
||||
if (!sym_is_choice(sym)) {
|
||||
prop = sym_get_default_prop(sym);
|
||||
if (prop) {
|
||||
sym->flags |= SYMBOL_WRITE;
|
||||
newval.tri = EXPR_AND(expr_calc_value(prop->expr),
|
||||
prop->visible.tri);
|
||||
if (newval.tri != no)
|
||||
sym->flags |= SYMBOL_WRITE;
|
||||
}
|
||||
if (sym->implied.tri != no) {
|
||||
sym->flags |= SYMBOL_WRITE;
|
||||
newval.tri = EXPR_OR(newval.tri, sym->implied.tri);
|
||||
newval.tri = EXPR_AND(newval.tri,
|
||||
sym->dir_dep.tri);
|
||||
}
|
||||
}
|
||||
calc_newval:
|
||||
if (sym->dir_dep.tri == no && sym->rev_dep.tri != no) {
|
||||
struct expr *e;
|
||||
e = expr_simplify_unmet_dep(sym->rev_dep.expr,
|
||||
sym->dir_dep.expr);
|
||||
fprintf(stderr, "warning: (");
|
||||
expr_fprint(e, stderr);
|
||||
fprintf(stderr, ") selects %s which has unmet direct dependencies (",
|
||||
sym->name);
|
||||
expr_fprint(sym->dir_dep.expr, stderr);
|
||||
fprintf(stderr, ")\n");
|
||||
expr_free(e);
|
||||
}
|
||||
if (sym->dir_dep.tri < sym->rev_dep.tri)
|
||||
sym_warn_unmet_dep(sym);
|
||||
newval.tri = EXPR_OR(newval.tri, sym->rev_dep.tri);
|
||||
}
|
||||
if (newval.tri == mod &&
|
||||
(sym_get_type(sym) == S_BOOLEAN || sym->implied.tri == yes))
|
||||
if (newval.tri == mod && sym_get_type(sym) == S_BOOLEAN)
|
||||
newval.tri = yes;
|
||||
break;
|
||||
case S_STRING:
|
||||
case S_HEX:
|
||||
case S_INT:
|
||||
if (sym->visible != no) {
|
||||
sym->flags |= SYMBOL_WRITE;
|
||||
if (sym_has_value(sym)) {
|
||||
newval.val = sym->def[S_DEF_USER].val;
|
||||
break;
|
||||
}
|
||||
if (sym->visible != no && sym_has_value(sym)) {
|
||||
newval.val = sym->def[S_DEF_USER].val;
|
||||
break;
|
||||
}
|
||||
prop = sym_get_default_prop(sym);
|
||||
if (prop) {
|
||||
@ -480,7 +459,7 @@ void sym_calc_value(struct symbol *sym)
|
||||
}
|
||||
}
|
||||
|
||||
if (sym->flags & SYMBOL_AUTO)
|
||||
if (sym->flags & SYMBOL_NO_WRITE)
|
||||
sym->flags &= ~SYMBOL_WRITE;
|
||||
|
||||
if (sym->flags & SYMBOL_NEED_SET_CHOICE_VALUES)
|
||||
@ -512,8 +491,6 @@ bool sym_tristate_within_range(struct symbol *sym, tristate val)
|
||||
return false;
|
||||
if (sym->visible <= sym->rev_dep.tri)
|
||||
return false;
|
||||
if (sym->implied.tri == yes && val == mod)
|
||||
return false;
|
||||
if (sym_is_choice_value(sym) && sym->visible == yes)
|
||||
return val == yes;
|
||||
return val >= sym->rev_dep.tri && val <= sym->visible;
|
||||
@ -783,7 +760,6 @@ const char *sym_get_string_default(struct symbol *sym)
|
||||
return str;
|
||||
case S_STRING:
|
||||
return str;
|
||||
case S_OTHER:
|
||||
case S_UNKNOWN:
|
||||
break;
|
||||
}
|
||||
@ -814,7 +790,7 @@ const char *sym_get_string_value(struct symbol *sym)
|
||||
return (const char *)sym->curr.val;
|
||||
}
|
||||
|
||||
bool sym_is_changable(struct symbol *sym)
|
||||
bool sym_is_changeable(struct symbol *sym)
|
||||
{
|
||||
return sym->visible > sym->rev_dep.tri;
|
||||
}
|
||||
@ -851,7 +827,7 @@ struct symbol *sym_lookup(const char *name, int flags)
|
||||
: !(symbol->flags & (SYMBOL_CONST|SYMBOL_CHOICE))))
|
||||
return symbol;
|
||||
}
|
||||
new_name = strdup(name);
|
||||
new_name = xstrdup(name);
|
||||
} else {
|
||||
new_name = NULL;
|
||||
hash = 0;
|
||||
@ -861,7 +837,7 @@ struct symbol *sym_lookup(const char *name, int flags)
|
||||
memset(symbol, 0, sizeof(*symbol));
|
||||
symbol->name = new_name;
|
||||
symbol->type = S_UNKNOWN;
|
||||
symbol->flags |= flags;
|
||||
symbol->flags = flags;
|
||||
|
||||
symbol->next = symbol_hash[hash];
|
||||
symbol_hash[hash] = symbol;
|
||||
@ -896,55 +872,6 @@ struct symbol *sym_find(const char *name)
|
||||
return symbol;
|
||||
}
|
||||
|
||||
/*
|
||||
* Expand symbol's names embedded in the string given in argument. Symbols'
|
||||
* name to be expanded shall be prefixed by a '$'. Unknown symbol expands to
|
||||
* the empty string.
|
||||
*/
|
||||
const char *sym_expand_string_value(const char *in)
|
||||
{
|
||||
const char *src;
|
||||
char *res;
|
||||
size_t reslen;
|
||||
|
||||
reslen = strlen(in) + 1;
|
||||
res = xmalloc(reslen);
|
||||
res[0] = '\0';
|
||||
|
||||
while ((src = strchr(in, '$'))) {
|
||||
char *p, name[SYMBOL_MAXLENGTH];
|
||||
const char *symval = "";
|
||||
struct symbol *sym;
|
||||
size_t newlen;
|
||||
|
||||
strncat(res, in, src - in);
|
||||
src++;
|
||||
|
||||
p = name;
|
||||
while (isalnum(*src) || *src == '_')
|
||||
*p++ = *src++;
|
||||
*p = '\0';
|
||||
|
||||
sym = sym_find(name);
|
||||
if (sym != NULL) {
|
||||
sym_calc_value(sym);
|
||||
symval = sym_get_string_value(sym);
|
||||
}
|
||||
|
||||
newlen = strlen(res) + strlen(symval) + strlen(src) + 1;
|
||||
if (newlen > reslen) {
|
||||
reslen = newlen;
|
||||
res = realloc(res, reslen);
|
||||
}
|
||||
|
||||
strcat(res, symval);
|
||||
in = src;
|
||||
}
|
||||
strcat(res, in);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
const char *sym_escape_string_value(const char *in)
|
||||
{
|
||||
const char *p;
|
||||
@ -1086,7 +1013,7 @@ static struct dep_stack {
|
||||
struct dep_stack *prev, *next;
|
||||
struct symbol *sym;
|
||||
struct property *prop;
|
||||
struct expr *expr;
|
||||
struct expr **expr;
|
||||
} *check_top;
|
||||
|
||||
static void dep_stack_insert(struct dep_stack *stack, struct symbol *sym)
|
||||
@ -1151,18 +1078,7 @@ static void sym_check_print_recursive(struct symbol *last_sym)
|
||||
fprintf(stderr, "%s:%d:error: recursive dependency detected!\n",
|
||||
prop->file->name, prop->lineno);
|
||||
|
||||
if (stack->expr) {
|
||||
fprintf(stderr, "%s:%d:\tsymbol %s %s value contains %s\n",
|
||||
prop->file->name, prop->lineno,
|
||||
sym->name ? sym->name : "<choice>",
|
||||
prop_get_type_name(prop->type),
|
||||
next_sym->name ? next_sym->name : "<choice>");
|
||||
} else if (stack->prop) {
|
||||
fprintf(stderr, "%s:%d:\tsymbol %s depends on %s\n",
|
||||
prop->file->name, prop->lineno,
|
||||
sym->name ? sym->name : "<choice>",
|
||||
next_sym->name ? next_sym->name : "<choice>");
|
||||
} else if (sym_is_choice(sym)) {
|
||||
if (sym_is_choice(sym)) {
|
||||
fprintf(stderr, "%s:%d:\tchoice %s contains symbol %s\n",
|
||||
menu->file->name, menu->lineno,
|
||||
sym->name ? sym->name : "<choice>",
|
||||
@ -1172,16 +1088,38 @@ static void sym_check_print_recursive(struct symbol *last_sym)
|
||||
menu->file->name, menu->lineno,
|
||||
sym->name ? sym->name : "<choice>",
|
||||
next_sym->name ? next_sym->name : "<choice>");
|
||||
} else {
|
||||
} else if (stack->expr == &sym->dir_dep.expr) {
|
||||
fprintf(stderr, "%s:%d:\tsymbol %s depends on %s\n",
|
||||
prop->file->name, prop->lineno,
|
||||
sym->name ? sym->name : "<choice>",
|
||||
next_sym->name ? next_sym->name : "<choice>");
|
||||
} else if (stack->expr == &sym->rev_dep.expr) {
|
||||
fprintf(stderr, "%s:%d:\tsymbol %s is selected by %s\n",
|
||||
prop->file->name, prop->lineno,
|
||||
sym->name ? sym->name : "<choice>",
|
||||
next_sym->name ? next_sym->name : "<choice>");
|
||||
} else if (stack->expr == &sym->implied.expr) {
|
||||
fprintf(stderr, "%s:%d:\tsymbol %s is implied by %s\n",
|
||||
prop->file->name, prop->lineno,
|
||||
sym->name ? sym->name : "<choice>",
|
||||
next_sym->name ? next_sym->name : "<choice>");
|
||||
} else if (stack->expr) {
|
||||
fprintf(stderr, "%s:%d:\tsymbol %s %s value contains %s\n",
|
||||
prop->file->name, prop->lineno,
|
||||
sym->name ? sym->name : "<choice>",
|
||||
prop_get_type_name(prop->type),
|
||||
next_sym->name ? next_sym->name : "<choice>");
|
||||
} else {
|
||||
fprintf(stderr, "%s:%d:\tsymbol %s %s is visible depending on %s\n",
|
||||
prop->file->name, prop->lineno,
|
||||
sym->name ? sym->name : "<choice>",
|
||||
prop_get_type_name(prop->type),
|
||||
next_sym->name ? next_sym->name : "<choice>");
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr,
|
||||
"For a resolution refer to Documentation/kbuild/kconfig-language.txt\n"
|
||||
"For a resolution refer to Documentation/kbuild/kconfig-language.rst\n"
|
||||
"subsection \"Kconfig recursive dependency limitations\"\n"
|
||||
"\n");
|
||||
|
||||
@ -1219,7 +1157,7 @@ static struct symbol *sym_check_expr_deps(struct expr *e)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
printf("Oops! How to check %d?\n", e->type);
|
||||
fprintf(stderr, "Oops! How to check %d?\n", e->type);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -1232,12 +1170,26 @@ static struct symbol *sym_check_sym_deps(struct symbol *sym)
|
||||
|
||||
dep_stack_insert(&stack, sym);
|
||||
|
||||
stack.expr = &sym->dir_dep.expr;
|
||||
sym2 = sym_check_expr_deps(sym->dir_dep.expr);
|
||||
if (sym2)
|
||||
goto out;
|
||||
|
||||
stack.expr = &sym->rev_dep.expr;
|
||||
sym2 = sym_check_expr_deps(sym->rev_dep.expr);
|
||||
if (sym2)
|
||||
goto out;
|
||||
|
||||
stack.expr = &sym->implied.expr;
|
||||
sym2 = sym_check_expr_deps(sym->implied.expr);
|
||||
if (sym2)
|
||||
goto out;
|
||||
|
||||
stack.expr = NULL;
|
||||
|
||||
for (prop = sym->prop; prop; prop = prop->next) {
|
||||
if (prop->type == P_CHOICE || prop->type == P_SELECT)
|
||||
if (prop->type == P_CHOICE || prop->type == P_SELECT ||
|
||||
prop->type == P_IMPLY)
|
||||
continue;
|
||||
stack.prop = prop;
|
||||
sym2 = sym_check_expr_deps(prop->visible.expr);
|
||||
@ -1245,7 +1197,7 @@ static struct symbol *sym_check_sym_deps(struct symbol *sym)
|
||||
break;
|
||||
if (prop->type != P_DEFAULT || sym_is_choice(sym))
|
||||
continue;
|
||||
stack.expr = prop->expr;
|
||||
stack.expr = &prop->expr;
|
||||
sym2 = sym_check_expr_deps(prop->expr);
|
||||
if (sym2)
|
||||
break;
|
||||
@ -1323,34 +1275,9 @@ struct symbol *sym_check_deps(struct symbol *sym)
|
||||
sym->flags &= ~SYMBOL_CHECK;
|
||||
}
|
||||
|
||||
if (sym2 && sym2 == sym)
|
||||
sym2 = NULL;
|
||||
|
||||
return sym2;
|
||||
}
|
||||
|
||||
struct property *prop_alloc(enum prop_type type, struct symbol *sym)
|
||||
{
|
||||
struct property *prop;
|
||||
struct property **propp;
|
||||
|
||||
prop = xmalloc(sizeof(*prop));
|
||||
memset(prop, 0, sizeof(*prop));
|
||||
prop->type = type;
|
||||
prop->sym = sym;
|
||||
prop->file = current_file;
|
||||
prop->lineno = zconf_lineno();
|
||||
|
||||
/* append property to the prop list of symbol */
|
||||
if (sym) {
|
||||
for (propp = &sym->prop; *propp; propp = &(*propp)->next)
|
||||
;
|
||||
*propp = prop;
|
||||
}
|
||||
|
||||
return prop;
|
||||
}
|
||||
|
||||
struct symbol *prop_get_symbol(struct property *prop)
|
||||
{
|
||||
if (prop->expr && (prop->expr->type == E_SYMBOL ||
|
||||
@ -1364,8 +1291,6 @@ const char *prop_get_type_name(enum prop_type type)
|
||||
switch (type) {
|
||||
case P_PROMPT:
|
||||
return "prompt";
|
||||
case P_ENV:
|
||||
return "env";
|
||||
case P_COMMENT:
|
||||
return "comment";
|
||||
case P_MENU:
|
||||
@ -1387,32 +1312,3 @@ const char *prop_get_type_name(enum prop_type type)
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
static void prop_add_env(const char *env)
|
||||
{
|
||||
struct symbol *sym, *sym2;
|
||||
struct property *prop;
|
||||
char *p;
|
||||
|
||||
sym = current_entry->sym;
|
||||
sym->flags |= SYMBOL_AUTO;
|
||||
for_all_properties(sym, prop, P_ENV) {
|
||||
sym2 = prop_get_symbol(prop);
|
||||
if (strcmp(sym2->name, env))
|
||||
menu_warn(current_entry, "redefining environment symbol from %s",
|
||||
sym2->name);
|
||||
return;
|
||||
}
|
||||
|
||||
prop = prop_alloc(P_ENV, sym);
|
||||
prop->expr = expr_alloc_symbol(sym_lookup(env, SYMBOL_CONST));
|
||||
|
||||
sym_env_list = expr_alloc_one(E_LIST, sym_env_list);
|
||||
sym_env_list->right.sym = sym;
|
||||
|
||||
p = getenv(env);
|
||||
if (p)
|
||||
sym_add_default(sym, p);
|
||||
else
|
||||
menu_warn(current_entry, "environment variable %s undefined", env);
|
||||
}
|
||||
|
@ -1,8 +1,7 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (C) 2002-2005 Roman Zippel <zippel@linux-m68k.org>
|
||||
* Copyright (C) 2002-2005 Sam Ravnborg <sam@ravnborg.org>
|
||||
*
|
||||
* Released under the terms of the GNU GPL v2.0.
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
@ -14,69 +13,21 @@
|
||||
struct file *file_lookup(const char *name)
|
||||
{
|
||||
struct file *file;
|
||||
const char *file_name = sym_expand_string_value(name);
|
||||
|
||||
for (file = file_list; file; file = file->next) {
|
||||
if (!strcmp(name, file->name)) {
|
||||
free((void *)file_name);
|
||||
return file;
|
||||
}
|
||||
}
|
||||
|
||||
file = xmalloc(sizeof(*file));
|
||||
memset(file, 0, sizeof(*file));
|
||||
file->name = file_name;
|
||||
file->name = xstrdup(name);
|
||||
file->next = file_list;
|
||||
file_list = file;
|
||||
return file;
|
||||
}
|
||||
|
||||
/* write a dependency file as used by kbuild to track dependencies */
|
||||
int file_write_dep(const char *name)
|
||||
{
|
||||
struct symbol *sym, *env_sym;
|
||||
struct expr *e;
|
||||
struct file *file;
|
||||
FILE *out;
|
||||
|
||||
if (!name)
|
||||
name = ".kconfig.d";
|
||||
out = fopen("..config.tmp", "w");
|
||||
if (!out)
|
||||
return 1;
|
||||
fprintf(out, "deps_config := \\\n");
|
||||
for (file = file_list; file; file = file->next) {
|
||||
if (file->next)
|
||||
fprintf(out, "\t%s \\\n", file->name);
|
||||
else
|
||||
fprintf(out, "\t%s\n", file->name);
|
||||
}
|
||||
fprintf(out, "\n%s: \\\n"
|
||||
"\t$(deps_config)\n\n", conf_get_autoconfig_name());
|
||||
|
||||
expr_list_for_each_sym(sym_env_list, e, sym) {
|
||||
struct property *prop;
|
||||
const char *value;
|
||||
|
||||
prop = sym_get_env_prop(sym);
|
||||
env_sym = prop_get_symbol(prop);
|
||||
if (!env_sym)
|
||||
continue;
|
||||
value = getenv(env_sym->name);
|
||||
if (!value)
|
||||
value = "";
|
||||
fprintf(out, "ifneq \"$(%s)\" \"%s\"\n", env_sym->name, value);
|
||||
fprintf(out, "%s: FORCE\n", conf_get_autoconfig_name());
|
||||
fprintf(out, "endif\n");
|
||||
}
|
||||
|
||||
fprintf(out, "\n$(deps_config): ;\n");
|
||||
fclose(out);
|
||||
rename("..config.tmp", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Allocate initial growable string */
|
||||
struct gstr str_new(void)
|
||||
{
|
||||
@ -104,7 +55,7 @@ void str_append(struct gstr *gs, const char *s)
|
||||
if (s) {
|
||||
l = strlen(gs->s) + strlen(s) + 1;
|
||||
if (l > gs->len) {
|
||||
gs->s = realloc(gs->s, l);
|
||||
gs->s = xrealloc(gs->s, l);
|
||||
gs->len = l;
|
||||
}
|
||||
strcat(gs->s, s);
|
||||
@ -145,3 +96,34 @@ void *xcalloc(size_t nmemb, size_t size)
|
||||
fprintf(stderr, "Out of memory.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void *xrealloc(void *p, size_t size)
|
||||
{
|
||||
p = realloc(p, size);
|
||||
if (p)
|
||||
return p;
|
||||
fprintf(stderr, "Out of memory.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
char *xstrdup(const char *s)
|
||||
{
|
||||
char *p;
|
||||
|
||||
p = strdup(s);
|
||||
if (p)
|
||||
return p;
|
||||
fprintf(stderr, "Out of memory.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
char *xstrndup(const char *s, size_t n)
|
||||
{
|
||||
char *p;
|
||||
|
||||
p = strndup(s, n);
|
||||
if (p)
|
||||
return p;
|
||||
fprintf(stderr, "Out of memory.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
374
kconfig/zconf.l
374
kconfig/zconf.l
@ -1,374 +0,0 @@
|
||||
%option nostdinit noyywrap never-interactive full ecs
|
||||
%option 8bit nodefault perf-report perf-report
|
||||
%option noinput
|
||||
%x COMMAND HELP STRING PARAM
|
||||
%{
|
||||
/*
|
||||
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
|
||||
* Released under the terms of the GNU GPL v2.0.
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "lkc.h"
|
||||
|
||||
#define START_STRSIZE 16
|
||||
|
||||
static struct {
|
||||
struct file *file;
|
||||
int lineno;
|
||||
} current_pos;
|
||||
|
||||
static char *text;
|
||||
static int text_size, text_asize;
|
||||
|
||||
struct buffer {
|
||||
struct buffer *parent;
|
||||
YY_BUFFER_STATE state;
|
||||
};
|
||||
|
||||
struct buffer *current_buf;
|
||||
|
||||
static int last_ts, first_ts;
|
||||
|
||||
static void zconf_endhelp(void);
|
||||
static void zconf_endfile(void);
|
||||
|
||||
static void new_string(void)
|
||||
{
|
||||
text = xmalloc(START_STRSIZE);
|
||||
text_asize = START_STRSIZE;
|
||||
text_size = 0;
|
||||
*text = 0;
|
||||
}
|
||||
|
||||
static void append_string(const char *str, int size)
|
||||
{
|
||||
int new_size = text_size + size + 1;
|
||||
if (new_size > text_asize) {
|
||||
new_size += START_STRSIZE - 1;
|
||||
new_size &= -START_STRSIZE;
|
||||
text = realloc(text, new_size);
|
||||
text_asize = new_size;
|
||||
}
|
||||
memcpy(text + text_size, str, size);
|
||||
text_size += size;
|
||||
text[text_size] = 0;
|
||||
}
|
||||
|
||||
static void alloc_string(const char *str, int size)
|
||||
{
|
||||
text = xmalloc(size + 1);
|
||||
memcpy(text, str, size);
|
||||
text[size] = 0;
|
||||
}
|
||||
|
||||
static void warn_ignored_character(char chr)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"%s:%d:warning: ignoring unsupported character '%c'\n",
|
||||
zconf_curname(), zconf_lineno(), chr);
|
||||
}
|
||||
%}
|
||||
|
||||
n [A-Za-z0-9_-]
|
||||
|
||||
%%
|
||||
int str = 0;
|
||||
int ts, i;
|
||||
|
||||
[ \t]*#.*\n |
|
||||
[ \t]*\n {
|
||||
current_file->lineno++;
|
||||
return T_EOL;
|
||||
}
|
||||
[ \t]*#.*
|
||||
|
||||
|
||||
[ \t]+ {
|
||||
BEGIN(COMMAND);
|
||||
}
|
||||
|
||||
. {
|
||||
unput(yytext[0]);
|
||||
BEGIN(COMMAND);
|
||||
}
|
||||
|
||||
|
||||
<COMMAND>{
|
||||
{n}+ {
|
||||
const struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
|
||||
BEGIN(PARAM);
|
||||
current_pos.file = current_file;
|
||||
current_pos.lineno = current_file->lineno;
|
||||
if (id && id->flags & TF_COMMAND) {
|
||||
zconflval.id = id;
|
||||
return id->token;
|
||||
}
|
||||
alloc_string(yytext, yyleng);
|
||||
zconflval.string = text;
|
||||
return T_WORD;
|
||||
}
|
||||
. warn_ignored_character(*yytext);
|
||||
\n {
|
||||
BEGIN(INITIAL);
|
||||
current_file->lineno++;
|
||||
return T_EOL;
|
||||
}
|
||||
}
|
||||
|
||||
<PARAM>{
|
||||
"&&" return T_AND;
|
||||
"||" return T_OR;
|
||||
"(" return T_OPEN_PAREN;
|
||||
")" return T_CLOSE_PAREN;
|
||||
"!" return T_NOT;
|
||||
"=" return T_EQUAL;
|
||||
"!=" return T_UNEQUAL;
|
||||
"<=" return T_LESS_EQUAL;
|
||||
">=" return T_GREATER_EQUAL;
|
||||
"<" return T_LESS;
|
||||
">" return T_GREATER;
|
||||
\"|\' {
|
||||
str = yytext[0];
|
||||
new_string();
|
||||
BEGIN(STRING);
|
||||
}
|
||||
\n BEGIN(INITIAL); current_file->lineno++; return T_EOL;
|
||||
({n}|[/.])+ {
|
||||
const struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
|
||||
if (id && id->flags & TF_PARAM) {
|
||||
zconflval.id = id;
|
||||
return id->token;
|
||||
}
|
||||
alloc_string(yytext, yyleng);
|
||||
zconflval.string = text;
|
||||
return T_WORD;
|
||||
}
|
||||
#.* /* comment */
|
||||
\\\n current_file->lineno++;
|
||||
[[:blank:]]+
|
||||
. warn_ignored_character(*yytext);
|
||||
<<EOF>> {
|
||||
BEGIN(INITIAL);
|
||||
}
|
||||
}
|
||||
|
||||
<STRING>{
|
||||
[^'"\\\n]+/\n {
|
||||
append_string(yytext, yyleng);
|
||||
zconflval.string = text;
|
||||
return T_WORD_QUOTE;
|
||||
}
|
||||
[^'"\\\n]+ {
|
||||
append_string(yytext, yyleng);
|
||||
}
|
||||
\\.?/\n {
|
||||
append_string(yytext + 1, yyleng - 1);
|
||||
zconflval.string = text;
|
||||
return T_WORD_QUOTE;
|
||||
}
|
||||
\\.? {
|
||||
append_string(yytext + 1, yyleng - 1);
|
||||
}
|
||||
\'|\" {
|
||||
if (str == yytext[0]) {
|
||||
BEGIN(PARAM);
|
||||
zconflval.string = text;
|
||||
return T_WORD_QUOTE;
|
||||
} else
|
||||
append_string(yytext, 1);
|
||||
}
|
||||
\n {
|
||||
printf("%s:%d:warning: multi-line strings not supported\n", zconf_curname(), zconf_lineno());
|
||||
current_file->lineno++;
|
||||
BEGIN(INITIAL);
|
||||
return T_EOL;
|
||||
}
|
||||
<<EOF>> {
|
||||
BEGIN(INITIAL);
|
||||
}
|
||||
}
|
||||
|
||||
<HELP>{
|
||||
[ \t]+ {
|
||||
ts = 0;
|
||||
for (i = 0; i < yyleng; i++) {
|
||||
if (yytext[i] == '\t')
|
||||
ts = (ts & ~7) + 8;
|
||||
else
|
||||
ts++;
|
||||
}
|
||||
last_ts = ts;
|
||||
if (first_ts) {
|
||||
if (ts < first_ts) {
|
||||
zconf_endhelp();
|
||||
return T_HELPTEXT;
|
||||
}
|
||||
ts -= first_ts;
|
||||
while (ts > 8) {
|
||||
append_string(" ", 8);
|
||||
ts -= 8;
|
||||
}
|
||||
append_string(" ", ts);
|
||||
}
|
||||
}
|
||||
[ \t]*\n/[^ \t\n] {
|
||||
current_file->lineno++;
|
||||
zconf_endhelp();
|
||||
return T_HELPTEXT;
|
||||
}
|
||||
[ \t]*\n {
|
||||
current_file->lineno++;
|
||||
append_string("\n", 1);
|
||||
}
|
||||
[^ \t\n].* {
|
||||
while (yyleng) {
|
||||
if ((yytext[yyleng-1] != ' ') && (yytext[yyleng-1] != '\t'))
|
||||
break;
|
||||
yyleng--;
|
||||
}
|
||||
append_string(yytext, yyleng);
|
||||
if (!first_ts)
|
||||
first_ts = last_ts;
|
||||
}
|
||||
<<EOF>> {
|
||||
zconf_endhelp();
|
||||
return T_HELPTEXT;
|
||||
}
|
||||
}
|
||||
|
||||
<<EOF>> {
|
||||
if (current_file) {
|
||||
zconf_endfile();
|
||||
return T_EOL;
|
||||
}
|
||||
fclose(yyin);
|
||||
yyterminate();
|
||||
}
|
||||
|
||||
%%
|
||||
void zconf_starthelp(void)
|
||||
{
|
||||
new_string();
|
||||
last_ts = first_ts = 0;
|
||||
BEGIN(HELP);
|
||||
}
|
||||
|
||||
static void zconf_endhelp(void)
|
||||
{
|
||||
zconflval.string = text;
|
||||
BEGIN(INITIAL);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Try to open specified file with following names:
|
||||
* ./name
|
||||
* $(srctree)/name
|
||||
* The latter is used when srctree is separate from objtree
|
||||
* when compiling the kernel.
|
||||
* Return NULL if file is not found.
|
||||
*/
|
||||
FILE *zconf_fopen(const char *name)
|
||||
{
|
||||
char *env, fullname[PATH_MAX+1];
|
||||
FILE *f;
|
||||
|
||||
f = fopen(name, "r");
|
||||
if (!f && name != NULL && name[0] != '/') {
|
||||
env = getenv(SRCTREE);
|
||||
if (env) {
|
||||
sprintf(fullname, "%s/%s", env, name);
|
||||
f = fopen(fullname, "r");
|
||||
}
|
||||
}
|
||||
return f;
|
||||
}
|
||||
|
||||
void zconf_initscan(const char *name)
|
||||
{
|
||||
yyin = zconf_fopen(name);
|
||||
if (!yyin) {
|
||||
printf("can't find file %s\n", name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
current_buf = xmalloc(sizeof(*current_buf));
|
||||
memset(current_buf, 0, sizeof(*current_buf));
|
||||
|
||||
current_file = file_lookup(name);
|
||||
current_file->lineno = 1;
|
||||
}
|
||||
|
||||
void zconf_nextfile(const char *name)
|
||||
{
|
||||
struct file *iter;
|
||||
struct file *file = file_lookup(name);
|
||||
struct buffer *buf = xmalloc(sizeof(*buf));
|
||||
memset(buf, 0, sizeof(*buf));
|
||||
|
||||
current_buf->state = YY_CURRENT_BUFFER;
|
||||
yyin = zconf_fopen(file->name);
|
||||
if (!yyin) {
|
||||
printf("%s:%d: can't open file \"%s\"\n",
|
||||
zconf_curname(), zconf_lineno(), file->name);
|
||||
exit(1);
|
||||
}
|
||||
yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
|
||||
buf->parent = current_buf;
|
||||
current_buf = buf;
|
||||
|
||||
for (iter = current_file->parent; iter; iter = iter->parent ) {
|
||||
if (!strcmp(current_file->name,iter->name) ) {
|
||||
printf("%s:%d: recursive inclusion detected. "
|
||||
"Inclusion path:\n current file : '%s'\n",
|
||||
zconf_curname(), zconf_lineno(),
|
||||
zconf_curname());
|
||||
iter = current_file->parent;
|
||||
while (iter && \
|
||||
strcmp(iter->name,current_file->name)) {
|
||||
printf(" included from: '%s:%d'\n",
|
||||
iter->name, iter->lineno-1);
|
||||
iter = iter->parent;
|
||||
}
|
||||
if (iter)
|
||||
printf(" included from: '%s:%d'\n",
|
||||
iter->name, iter->lineno+1);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
file->lineno = 1;
|
||||
file->parent = current_file;
|
||||
current_file = file;
|
||||
}
|
||||
|
||||
static void zconf_endfile(void)
|
||||
{
|
||||
struct buffer *parent;
|
||||
|
||||
current_file = current_file->parent;
|
||||
|
||||
parent = current_buf->parent;
|
||||
if (parent) {
|
||||
fclose(yyin);
|
||||
yy_delete_buffer(YY_CURRENT_BUFFER);
|
||||
yy_switch_to_buffer(parent->state);
|
||||
}
|
||||
free(current_buf);
|
||||
current_buf = parent;
|
||||
}
|
||||
|
||||
int zconf_lineno(void)
|
||||
{
|
||||
return current_pos.lineno;
|
||||
}
|
||||
|
||||
const char *zconf_curname(void)
|
||||
{
|
||||
return current_pos.file ? current_pos.file->name : "<none>";
|
||||
}
|
@ -11,7 +11,9 @@ config @@dir|@@_@@choice|@@
|
||||
#!foreach dependency
|
||||
@@depline@@
|
||||
#!end-foreach
|
||||
#!if [ -n "@@*help@@" ]
|
||||
help
|
||||
#!end-if
|
||||
#!foreach help
|
||||
@@helpline@@
|
||||
#!end-foreach
|
||||
|
@ -8,7 +8,9 @@ menuconfig @@dir|@@_@@choice|@@
|
||||
#!foreach dependency
|
||||
@@depline@@
|
||||
#!end-foreach
|
||||
#!if [ -n "@@*help@@" ]
|
||||
help
|
||||
#!end-if
|
||||
#!foreach help
|
||||
@@helpline@@
|
||||
#!end-foreach
|
||||
|
@ -68,6 +68,8 @@ config @@fork|@@_SRC_DEVEL
|
||||
Default is the vendor repository at @@repository_url@@
|
||||
#!end-if
|
||||
|
||||
endchoice
|
||||
|
||||
if @@fork|@@_SRC_DEVEL
|
||||
|
||||
choice
|
||||
@ -176,8 +178,6 @@ config @@fork|@@_CUSTOM_LOCATION
|
||||
|
||||
endif
|
||||
|
||||
endchoice
|
||||
|
||||
if EXPERIMENTAL
|
||||
choice
|
||||
bool "@@pkg_label@@ patches origin"
|
||||
|
Loading…
x
Reference in New Issue
Block a user