mirror of
https://github.com/crosstool-ng/crosstool-ng.git
synced 2025-02-21 09:21:52 +00:00
kconfig: Sync with upstream v4.16
This commit introduces the following upstream changes: 5ae6fcc4bb82 kconfig: fix line number in recursive inclusion error message 1a90ce36c6ef kconfig: Update ncurses package names for menuconfig bf0bbdcf1003 kconfig: Don't leak choice names during parsing f4bc1eefc160 kconfig: set SYMBOL_AUTO to the symbol marked with defconfig_list cd81fc82b93f kconfig: add xstrdup() helper 523ca58b7db2 kconfig: remove const qualifier from sym_expand_string_value() d717f24d8c68 kconfig: add xrealloc() helper 9e3e10c72536 kconfig: send error messages to stderr f3ff6fb5db68 kconfig: echo stdin to stdout if either is redirected d2a04648a5db kconfig: remove check_stdin() cd58a91def2a kconfig: remove 'config*' pattern from .gitignnore 4f208f392103 kconfig: show '?' prompt even if no help text is available cb67ab2cd2b8 kconfig: do not write choice values when their dependency becomes n 1b9eda2e4892 kconfig: Warn if help text is blank cedd55d49dee kconfig: Remove silentoldconfig from help and docs; fix kconfig/conf's help 1ccb27143360 kconfig: make "Selected by:" and "Implied by:" readable 312ee68752fa kconfig: announce removal of oldnoconfig if used d0fd0428ecf0 kconfig: fix make xconfig when gettext is missing b53688014e33 kconfig: Clarify menu and 'if' dependency propagation 9d1a9e8bc18b kconfig: Document 'if' flattening logic d3465af60f44 kconfig: Clarify choice dependency propagation 3e41ba05b6d6 kconfig: Document SYMBOL_OPTIONAL logic 765f4cdef6f8 kconfig: use default 'yy' prefix for lexer and parser 84dd95d4f87a kconfig: make conf_unsaved a local variable of conf_read() 5a3dc717b3c7 kconfig: make xfgets() really static 52e58a3caeba kconfig: make input_mode static 6479f327dea6 kconfig: Warn if there is more than one help text b92d804a5179 kconfig: drop 'boolean' keyword df60f4b92d3d kconfig: Remove menu_end_entry() 0735f7e5def2 kconfig: Document important expression functions 05cccce58045 kconfig: Document automatic submenu creation code 7cf33f88e294 kconfig: Fix choice symbol expression leak 5b1374b3b3c2 kconfig: Fix expr_free() E_NOT leak ae7440ef0c80 kconfig: Fix automatic menu creation mem leak 0724a7c32a54 kconfig: Don't leak main menus during parsing bc28fe1d5ede kconfig: Don't leak 'option' arguments during parsing 24161a6711c9 kconfig: Don't leak 'source' filenames during parsing 26e47a3c11a2 kconfig: Don't leak symbol names during parsing 29c833061c1d kconfig: generate lexer and parser during build instead of shipping e3b03bf29d6b kconfig: display recursive dependency resolution hint just once f77850d3fe0c kconfig: Clean up modules handling and fix crash fa8cedaef814 kconfig: Clarify expression rewriting 9a826842ff2f kconfig: Rename menu_check_dep() to rewrite_m() c873443430eb kconfig: Sync zconf.y with zconf.tab.c_shipped 52aede4ba5ef kconfig: Document the 'symbol' struct 33ca1a248663 kconfig: Document the 'menu' struct 2c37e08464a8 kconfig: Warn if choice default is not in choice Signed-off-by: Chris Packham <judge.packham@gmail.com>
This commit is contained in:
parent
51cb8939f8
commit
07ae8dd48d
20
kconfig/.gitignore
vendored
20
kconfig/.gitignore
vendored
@ -1,9 +1,15 @@
|
|||||||
conf
|
#
|
||||||
?conf
|
# Generated files
|
||||||
*.o
|
#
|
||||||
|
*.lex.c
|
||||||
|
*.tab.c
|
||||||
|
*.tab.h
|
||||||
.deps
|
.deps
|
||||||
zconf.c
|
|
||||||
zconf.lex.c
|
|
||||||
*.exe
|
|
||||||
Makefile
|
Makefile
|
||||||
.dirstamp
|
|
||||||
|
#
|
||||||
|
# configuration programs
|
||||||
|
#
|
||||||
|
conf
|
||||||
|
mconf
|
||||||
|
nconf
|
||||||
|
0
kconfig/check.sh
Normal file → Executable file
0
kconfig/check.sh
Normal file → Executable file
@ -20,7 +20,6 @@
|
|||||||
|
|
||||||
static void conf(struct menu *menu);
|
static void conf(struct menu *menu);
|
||||||
static void check_conf(struct menu *menu);
|
static void check_conf(struct menu *menu);
|
||||||
static void xfgets(char *str, int size, FILE *in);
|
|
||||||
|
|
||||||
enum input_mode {
|
enum input_mode {
|
||||||
oldaskconfig,
|
oldaskconfig,
|
||||||
@ -35,11 +34,11 @@ enum input_mode {
|
|||||||
savedefconfig,
|
savedefconfig,
|
||||||
listnewconfig,
|
listnewconfig,
|
||||||
olddefconfig,
|
olddefconfig,
|
||||||
} input_mode = oldaskconfig;
|
};
|
||||||
|
static enum input_mode input_mode = oldaskconfig;
|
||||||
|
|
||||||
static int indent = 1;
|
static int indent = 1;
|
||||||
static int tty_stdio;
|
static int tty_stdio;
|
||||||
static int valid_stdin = 1;
|
|
||||||
static int sync_kconfig;
|
static int sync_kconfig;
|
||||||
static int conf_cnt;
|
static int conf_cnt;
|
||||||
static char line[PATH_MAX];
|
static char line[PATH_MAX];
|
||||||
@ -72,14 +71,14 @@ static void strip(char *str)
|
|||||||
*p-- = 0;
|
*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) {
|
if (!fgets(str, size, in))
|
||||||
/* For crosstool-NG, we don't care if stdin/stdout got redirected.
|
fprintf(stderr, "\nError in reading or end of file.\n");
|
||||||
* In this case, just printf a cariage return, for pretty output.
|
|
||||||
*/
|
if (!tty_stdio)
|
||||||
printf("\n");
|
printf("%s", str);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int conf_askvalue(struct symbol *sym, const char *def)
|
static int conf_askvalue(struct symbol *sym, const char *def)
|
||||||
@ -106,13 +105,10 @@ static int conf_askvalue(struct symbol *sym, const char *def)
|
|||||||
printf("%s\n", def);
|
printf("%s\n", def);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
check_stdin();
|
|
||||||
/* fall through */
|
/* fall through */
|
||||||
case oldaskconfig:
|
case oldaskconfig:
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
xfgets(line, sizeof(line), stdin);
|
xfgets(line, sizeof(line), stdin);
|
||||||
if (!tty_stdio)
|
|
||||||
printf("\n");
|
|
||||||
return 1;
|
return 1;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -192,9 +188,7 @@ static int conf_sym(struct menu *menu)
|
|||||||
printf("/m");
|
printf("/m");
|
||||||
if (oldval != yes && sym_tristate_within_range(sym, yes))
|
if (oldval != yes && sym_tristate_within_range(sym, yes))
|
||||||
printf("/y");
|
printf("/y");
|
||||||
if (menu_has_help(menu))
|
printf("/?] ");
|
||||||
printf("/?");
|
|
||||||
printf("] ");
|
|
||||||
if (!conf_askvalue(sym, sym_get_string_value(sym)))
|
if (!conf_askvalue(sym, sym_get_string_value(sym)))
|
||||||
return 0;
|
return 0;
|
||||||
strip(line);
|
strip(line);
|
||||||
@ -296,10 +290,7 @@ static int conf_choice(struct menu *menu)
|
|||||||
printf("[1]: 1\n");
|
printf("[1]: 1\n");
|
||||||
goto conf_childs;
|
goto conf_childs;
|
||||||
}
|
}
|
||||||
printf("[1-%d", cnt);
|
printf("[1-%d?]: ", cnt);
|
||||||
if (menu_has_help(menu))
|
|
||||||
printf("?");
|
|
||||||
printf("]: ");
|
|
||||||
switch (input_mode) {
|
switch (input_mode) {
|
||||||
case oldconfig:
|
case oldconfig:
|
||||||
case silentoldconfig:
|
case silentoldconfig:
|
||||||
@ -308,7 +299,6 @@ static int conf_choice(struct menu *menu)
|
|||||||
printf("%d\n", cnt);
|
printf("%d\n", cnt);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
check_stdin();
|
|
||||||
/* fall through */
|
/* fall through */
|
||||||
case oldaskconfig:
|
case oldaskconfig:
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
@ -480,7 +470,7 @@ int main(int ac, char **av)
|
|||||||
bindtextdomain(PACKAGE, LOCALEDIR);
|
bindtextdomain(PACKAGE, LOCALEDIR);
|
||||||
textdomain(PACKAGE);
|
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) {
|
while ((opt = getopt_long(ac, av, "s", long_opts, NULL)) != -1) {
|
||||||
if (opt == 's') {
|
if (opt == 's') {
|
||||||
@ -537,7 +527,7 @@ int main(int ac, char **av)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ac == optind) {
|
if (ac == optind) {
|
||||||
printf(_("%s: Kconfig file missing\n"), av[0]);
|
fprintf(stderr, _("%s: Kconfig file missing\n"), av[0]);
|
||||||
fprintf(stderr, _("See README for usage info\n"));
|
fprintf(stderr, _("See README for usage info\n"));
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
@ -562,9 +552,11 @@ int main(int ac, char **av)
|
|||||||
if (!defconfig_file)
|
if (!defconfig_file)
|
||||||
defconfig_file = conf_get_default_confname();
|
defconfig_file = conf_get_default_confname();
|
||||||
if (conf_read(defconfig_file)) {
|
if (conf_read(defconfig_file)) {
|
||||||
printf(_("***\n"
|
fprintf(stderr,
|
||||||
"*** Can't find default configuration \"%s\"!\n"
|
_("***\n"
|
||||||
"***\n"), defconfig_file);
|
"*** Can't find default configuration \"%s\"!\n"
|
||||||
|
"***\n"),
|
||||||
|
defconfig_file);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -622,7 +614,6 @@ int main(int ac, char **av)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
valid_stdin = tty_stdio;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (input_mode) {
|
switch (input_mode) {
|
||||||
@ -693,12 +684,3 @@ int main(int ac, char **av)
|
|||||||
}
|
}
|
||||||
return 0;
|
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");
|
|
||||||
}
|
|
||||||
|
@ -28,7 +28,7 @@ static void conf_message(const char *fmt, ...)
|
|||||||
__attribute__ ((format (printf, 1, 2)));
|
__attribute__ ((format (printf, 1, 2)));
|
||||||
|
|
||||||
static const char *conf_filename;
|
static const char *conf_filename;
|
||||||
static int conf_lineno, conf_warnings, conf_unsaved;
|
static int conf_lineno, conf_warnings;
|
||||||
|
|
||||||
const char conf_defname[] = "arch/$ARCH/defconfig";
|
const char conf_defname[] = "arch/$ARCH/defconfig";
|
||||||
|
|
||||||
@ -178,7 +178,7 @@ static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
|
|||||||
case S_HEX:
|
case S_HEX:
|
||||||
done:
|
done:
|
||||||
if (sym_string_valid(sym, p)) {
|
if (sym_string_valid(sym, p)) {
|
||||||
sym->def[def].val = strdup(p);
|
sym->def[def].val = xstrdup(p);
|
||||||
sym->flags |= def_flags;
|
sym->flags |= def_flags;
|
||||||
} else {
|
} else {
|
||||||
if (def != S_DEF_AUTO)
|
if (def != S_DEF_AUTO)
|
||||||
@ -201,7 +201,7 @@ static int add_byte(int c, char **lineptr, size_t slen, size_t *n)
|
|||||||
if (new_size > *n) {
|
if (new_size > *n) {
|
||||||
new_size += LINE_GROWTH - 1;
|
new_size += LINE_GROWTH - 1;
|
||||||
new_size *= 2;
|
new_size *= 2;
|
||||||
nline = realloc(*lineptr, new_size);
|
nline = xrealloc(*lineptr, new_size);
|
||||||
if (!nline)
|
if (!nline)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@ -290,7 +290,6 @@ load:
|
|||||||
conf_filename = name;
|
conf_filename = name;
|
||||||
conf_lineno = 0;
|
conf_lineno = 0;
|
||||||
conf_warnings = 0;
|
conf_warnings = 0;
|
||||||
conf_unsaved = 0;
|
|
||||||
|
|
||||||
def_flags = SYMBOL_DEF << def;
|
def_flags = SYMBOL_DEF << def;
|
||||||
for_all_symbols(i, sym) {
|
for_all_symbols(i, sym) {
|
||||||
@ -409,6 +408,7 @@ setsym:
|
|||||||
int conf_read(const char *name)
|
int conf_read(const char *name)
|
||||||
{
|
{
|
||||||
struct symbol *sym;
|
struct symbol *sym;
|
||||||
|
int conf_unsaved = 0;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
sym_set_change_count(0);
|
sym_set_change_count(0);
|
||||||
@ -1123,7 +1123,7 @@ void set_all_choice_values(struct symbol *csym)
|
|||||||
bool conf_set_all_new_symbols(enum conf_def_mode mode)
|
bool conf_set_all_new_symbols(enum conf_def_mode mode)
|
||||||
{
|
{
|
||||||
struct symbol *sym, *csym;
|
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
|
* pty: probability of tristate = y
|
||||||
* ptm: probability of tristate = m
|
* ptm: probability of tristate = m
|
||||||
*/
|
*/
|
||||||
|
140
kconfig/expr.c
140
kconfig/expr.c
@ -94,7 +94,7 @@ struct expr *expr_copy(const struct expr *org)
|
|||||||
e->right.expr = expr_copy(org->right.expr);
|
e->right.expr = expr_copy(org->right.expr);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printf("can't copy type %d\n", e->type);
|
fprintf(stderr, "can't copy type %d\n", e->type);
|
||||||
free(e);
|
free(e);
|
||||||
e = NULL;
|
e = NULL;
|
||||||
break;
|
break;
|
||||||
@ -113,7 +113,7 @@ void expr_free(struct expr *e)
|
|||||||
break;
|
break;
|
||||||
case E_NOT:
|
case E_NOT:
|
||||||
expr_free(e->left.expr);
|
expr_free(e->left.expr);
|
||||||
return;
|
break;
|
||||||
case E_EQUAL:
|
case E_EQUAL:
|
||||||
case E_GEQ:
|
case E_GEQ:
|
||||||
case E_GTH:
|
case E_GTH:
|
||||||
@ -127,7 +127,7 @@ void expr_free(struct expr *e)
|
|||||||
expr_free(e->right.expr);
|
expr_free(e->right.expr);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printf("how to free type %d?\n", e->type);
|
fprintf(stderr, "how to free type %d?\n", e->type);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
free(e);
|
free(e);
|
||||||
@ -138,8 +138,18 @@ static int trans_count;
|
|||||||
#define e1 (*ep1)
|
#define e1 (*ep1)
|
||||||
#define e2 (*ep2)
|
#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)
|
static void __expr_eliminate_eq(enum expr_type type, struct expr **ep1, struct expr **ep2)
|
||||||
{
|
{
|
||||||
|
/* Recurse down to leaves */
|
||||||
|
|
||||||
if (e1->type == type) {
|
if (e1->type == type) {
|
||||||
__expr_eliminate_eq(type, &e1->left.expr, &e2);
|
__expr_eliminate_eq(type, &e1->left.expr, &e2);
|
||||||
__expr_eliminate_eq(type, &e1->right.expr, &e2);
|
__expr_eliminate_eq(type, &e1->right.expr, &e2);
|
||||||
@ -150,12 +160,18 @@ static void __expr_eliminate_eq(enum expr_type type, struct expr **ep1, struct e
|
|||||||
__expr_eliminate_eq(type, &e1, &e2->right.expr);
|
__expr_eliminate_eq(type, &e1, &e2->right.expr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* e1 and e2 are leaves. Compare them. */
|
||||||
|
|
||||||
if (e1->type == E_SYMBOL && e2->type == E_SYMBOL &&
|
if (e1->type == E_SYMBOL && e2->type == E_SYMBOL &&
|
||||||
e1->left.sym == e2->left.sym &&
|
e1->left.sym == e2->left.sym &&
|
||||||
(e1->left.sym == &symbol_yes || e1->left.sym == &symbol_no))
|
(e1->left.sym == &symbol_yes || e1->left.sym == &symbol_no))
|
||||||
return;
|
return;
|
||||||
if (!expr_eq(e1, e2))
|
if (!expr_eq(e1, e2))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/* e1 and e2 are equal leaves. Prepare them for elimination. */
|
||||||
|
|
||||||
trans_count++;
|
trans_count++;
|
||||||
expr_free(e1); expr_free(e2);
|
expr_free(e1); expr_free(e2);
|
||||||
switch (type) {
|
switch (type) {
|
||||||
@ -172,6 +188,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)
|
void expr_eliminate_eq(struct expr **ep1, struct expr **ep2)
|
||||||
{
|
{
|
||||||
if (!e1 || !e2)
|
if (!e1 || !e2)
|
||||||
@ -197,6 +242,12 @@ void expr_eliminate_eq(struct expr **ep1, struct expr **ep2)
|
|||||||
#undef e1
|
#undef e1
|
||||||
#undef e2
|
#undef 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.
|
||||||
|
*/
|
||||||
static int expr_eq(struct expr *e1, struct expr *e2)
|
static int expr_eq(struct expr *e1, struct expr *e2)
|
||||||
{
|
{
|
||||||
int res, old_count;
|
int res, old_count;
|
||||||
@ -243,6 +294,17 @@ static int expr_eq(struct expr *e1, struct expr *e2)
|
|||||||
return 0;
|
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)
|
static struct expr *expr_eliminate_yn(struct expr *e)
|
||||||
{
|
{
|
||||||
struct expr *tmp;
|
struct expr *tmp;
|
||||||
@ -516,12 +578,21 @@ static struct expr *expr_join_and(struct expr *e1, struct expr *e2)
|
|||||||
return NULL;
|
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)
|
static void expr_eliminate_dups1(enum expr_type type, struct expr **ep1, struct expr **ep2)
|
||||||
{
|
{
|
||||||
#define e1 (*ep1)
|
#define e1 (*ep1)
|
||||||
#define e2 (*ep2)
|
#define e2 (*ep2)
|
||||||
struct expr *tmp;
|
struct expr *tmp;
|
||||||
|
|
||||||
|
/* Recurse down to leaves */
|
||||||
|
|
||||||
if (e1->type == type) {
|
if (e1->type == type) {
|
||||||
expr_eliminate_dups1(type, &e1->left.expr, &e2);
|
expr_eliminate_dups1(type, &e1->left.expr, &e2);
|
||||||
expr_eliminate_dups1(type, &e1->right.expr, &e2);
|
expr_eliminate_dups1(type, &e1->right.expr, &e2);
|
||||||
@ -532,6 +603,9 @@ static void expr_eliminate_dups1(enum expr_type type, struct expr **ep1, struct
|
|||||||
expr_eliminate_dups1(type, &e1, &e2->right.expr);
|
expr_eliminate_dups1(type, &e1, &e2->right.expr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* e1 and e2 are leaves. Compare and process them. */
|
||||||
|
|
||||||
if (e1 == e2)
|
if (e1 == e2)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -568,6 +642,17 @@ static void expr_eliminate_dups1(enum expr_type type, struct expr **ep1, struct
|
|||||||
#undef e2
|
#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)
|
struct expr *expr_eliminate_dups(struct expr *e)
|
||||||
{
|
{
|
||||||
int oldcount;
|
int oldcount;
|
||||||
@ -584,6 +669,7 @@ struct expr *expr_eliminate_dups(struct expr *e)
|
|||||||
;
|
;
|
||||||
}
|
}
|
||||||
if (!trans_count)
|
if (!trans_count)
|
||||||
|
/* No simplifications done in this pass. We're done */
|
||||||
break;
|
break;
|
||||||
e = expr_eliminate_yn(e);
|
e = expr_eliminate_yn(e);
|
||||||
}
|
}
|
||||||
@ -591,6 +677,12 @@ struct expr *expr_eliminate_dups(struct expr *e)
|
|||||||
return 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 *expr_transform(struct expr *e)
|
||||||
{
|
{
|
||||||
struct expr *tmp;
|
struct expr *tmp;
|
||||||
@ -805,6 +897,20 @@ bool expr_depends_symbol(struct expr *dep, struct symbol *sym)
|
|||||||
return false;
|
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 *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym)
|
||||||
{
|
{
|
||||||
struct expr *e1, *e2;
|
struct expr *e1, *e2;
|
||||||
@ -1073,7 +1179,7 @@ struct expr *expr_simplify_unmet_dep(struct expr *e1, struct expr *e2)
|
|||||||
return expr_get_leftmost_symbol(ret);
|
return expr_get_leftmost_symbol(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
void expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken)
|
static void __expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken, bool revdep)
|
||||||
{
|
{
|
||||||
if (!e) {
|
if (!e) {
|
||||||
fn(data, NULL, "y");
|
fn(data, NULL, "y");
|
||||||
@ -1128,9 +1234,14 @@ void expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char *
|
|||||||
fn(data, e->right.sym, e->right.sym->name);
|
fn(data, e->right.sym, e->right.sym->name);
|
||||||
break;
|
break;
|
||||||
case E_OR:
|
case E_OR:
|
||||||
expr_print(e->left.expr, fn, data, E_OR);
|
if (revdep && e->left.expr->type != E_OR)
|
||||||
fn(data, NULL, " || ");
|
fn(data, NULL, "\n - ");
|
||||||
expr_print(e->right.expr, fn, data, E_OR);
|
__expr_print(e->left.expr, fn, data, E_OR, revdep);
|
||||||
|
if (revdep)
|
||||||
|
fn(data, NULL, "\n - ");
|
||||||
|
else
|
||||||
|
fn(data, NULL, " || ");
|
||||||
|
__expr_print(e->right.expr, fn, data, E_OR, revdep);
|
||||||
break;
|
break;
|
||||||
case E_AND:
|
case E_AND:
|
||||||
expr_print(e->left.expr, fn, data, E_AND);
|
expr_print(e->left.expr, fn, data, E_AND);
|
||||||
@ -1163,6 +1274,11 @@ void expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char *
|
|||||||
fn(data, NULL, ")");
|
fn(data, NULL, ")");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken)
|
||||||
|
{
|
||||||
|
__expr_print(e, fn, data, prevtoken, false);
|
||||||
|
}
|
||||||
|
|
||||||
static void expr_print_file_helper(void *data, struct symbol *sym, const char *str)
|
static void expr_print_file_helper(void *data, struct symbol *sym, const char *str)
|
||||||
{
|
{
|
||||||
xfwrite(str, strlen(str), 1, data);
|
xfwrite(str, strlen(str), 1, data);
|
||||||
@ -1207,3 +1323,13 @@ void expr_gstr_print(struct expr *e, struct gstr *gs)
|
|||||||
{
|
{
|
||||||
expr_print(e, expr_print_gstr_helper, gs, E_NONE);
|
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.
|
||||||
|
*/
|
||||||
|
void expr_gstr_print_revdep(struct expr *e, struct gstr *gs)
|
||||||
|
{
|
||||||
|
__expr_print(e, expr_print_gstr_helper, gs, E_NONE, true);
|
||||||
|
}
|
||||||
|
@ -74,17 +74,60 @@ enum {
|
|||||||
S_DEF_COUNT
|
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 {
|
struct symbol {
|
||||||
|
/* The next symbol in the same bucket in the symbol hash table */
|
||||||
struct symbol *next;
|
struct symbol *next;
|
||||||
|
|
||||||
|
/* The name of the symbol, e.g. "FOO" for 'config FOO' */
|
||||||
char *name;
|
char *name;
|
||||||
|
|
||||||
|
/* S_BOOLEAN, S_TRISTATE, ... */
|
||||||
enum symbol_type type;
|
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;
|
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];
|
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;
|
tristate visible;
|
||||||
|
|
||||||
|
/* SYMBOL_* flags */
|
||||||
int flags;
|
int flags;
|
||||||
|
|
||||||
|
/* List of properties. See prop_type. */
|
||||||
struct property *prop;
|
struct property *prop;
|
||||||
|
|
||||||
|
/* Dependencies from enclosing menus, choices, and ifs */
|
||||||
struct expr_value dir_dep;
|
struct expr_value dir_dep;
|
||||||
|
|
||||||
|
/* Reverse dependencies through being selected by other symbols */
|
||||||
struct expr_value rev_dep;
|
struct expr_value rev_dep;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* "Weak" reverse dependencies through being implied by other symbols
|
||||||
|
*/
|
||||||
struct expr_value implied;
|
struct expr_value implied;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -133,7 +176,7 @@ enum prop_type {
|
|||||||
P_UNKNOWN,
|
P_UNKNOWN,
|
||||||
P_PROMPT, /* prompt "foo prompt" or "BAZ Value" */
|
P_PROMPT, /* prompt "foo prompt" or "BAZ Value" */
|
||||||
P_COMMENT, /* text associated with a comment */
|
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_DEFAULT, /* default y */
|
||||||
P_CHOICE, /* choice value */
|
P_CHOICE, /* choice value */
|
||||||
P_SELECT, /* select BAR */
|
P_SELECT, /* select BAR */
|
||||||
@ -166,22 +209,67 @@ struct property {
|
|||||||
for (st = sym->prop; st; st = st->next) \
|
for (st = sym->prop; st; st = st->next) \
|
||||||
if (st->text)
|
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 {
|
struct menu {
|
||||||
|
/* The next menu node at the same level */
|
||||||
struct menu *next;
|
struct menu *next;
|
||||||
|
|
||||||
|
/* The parent menu node, corresponding to e.g. a menu or choice */
|
||||||
struct menu *parent;
|
struct menu *parent;
|
||||||
|
|
||||||
|
/* The first child menu node, for e.g. menus and choices */
|
||||||
struct menu *list;
|
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;
|
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;
|
struct property *prompt;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 'visible if' dependencies. If more than one is given, they will be
|
||||||
|
* ANDed together.
|
||||||
|
*/
|
||||||
struct expr *visibility;
|
struct expr *visibility;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Ordinary dependencies from e.g. 'depends on' and 'if', ANDed
|
||||||
|
* together
|
||||||
|
*/
|
||||||
struct expr *dep;
|
struct expr *dep;
|
||||||
|
|
||||||
|
/* MENU_* flags */
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
|
|
||||||
|
/* Any help text associated with the node */
|
||||||
char *help;
|
char *help;
|
||||||
|
|
||||||
|
/* The location where the menu node appears in the Kconfig files */
|
||||||
struct file *file;
|
struct file *file;
|
||||||
int lineno;
|
int lineno;
|
||||||
|
|
||||||
|
/* For use by front ends that need to store auxiliary data */
|
||||||
void *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_CHANGED 0x0001
|
||||||
|
|
||||||
#define MENU_ROOT 0x0002
|
#define MENU_ROOT 0x0002
|
||||||
|
|
||||||
struct jump_key {
|
struct jump_key {
|
||||||
@ -222,6 +310,7 @@ struct expr *expr_simplify_unmet_dep(struct expr *e1, struct expr *e2);
|
|||||||
void expr_fprint(struct expr *e, FILE *out);
|
void expr_fprint(struct expr *e, FILE *out);
|
||||||
struct gstr; /* forward */
|
struct gstr; /* forward */
|
||||||
void expr_gstr_print(struct expr *e, struct gstr *gs);
|
void expr_gstr_print(struct expr *e, struct gstr *gs);
|
||||||
|
void expr_gstr_print_revdep(struct expr *e, struct gstr *gs);
|
||||||
|
|
||||||
static inline int expr_is_yes(struct expr *e)
|
static inline int expr_is_yes(struct expr *e)
|
||||||
{
|
{
|
||||||
|
@ -20,7 +20,6 @@ static struct kconf_id kconf_id_array[] = {
|
|||||||
{ "tristate", T_TYPE, TF_COMMAND, S_TRISTATE },
|
{ "tristate", T_TYPE, TF_COMMAND, S_TRISTATE },
|
||||||
{ "def_tristate", T_DEFAULT, TF_COMMAND, S_TRISTATE },
|
{ "def_tristate", T_DEFAULT, TF_COMMAND, S_TRISTATE },
|
||||||
{ "bool", T_TYPE, TF_COMMAND, S_BOOLEAN },
|
{ "bool", T_TYPE, TF_COMMAND, S_BOOLEAN },
|
||||||
{ "boolean", T_TYPE, TF_COMMAND, S_BOOLEAN },
|
|
||||||
{ "def_bool", T_DEFAULT, TF_COMMAND, S_BOOLEAN },
|
{ "def_bool", T_DEFAULT, TF_COMMAND, S_BOOLEAN },
|
||||||
{ "int", T_TYPE, TF_COMMAND, S_INT },
|
{ "int", T_TYPE, TF_COMMAND, S_INT },
|
||||||
{ "hex", T_TYPE, TF_COMMAND, S_HEX },
|
{ "hex", T_TYPE, TF_COMMAND, S_HEX },
|
||||||
|
@ -100,7 +100,6 @@ void menu_warn(struct menu *menu, const char *fmt, ...);
|
|||||||
struct menu *menu_add_menu(void);
|
struct menu *menu_add_menu(void);
|
||||||
void menu_end_menu(void);
|
void menu_end_menu(void);
|
||||||
void menu_add_entry(struct symbol *sym);
|
void menu_add_entry(struct symbol *sym);
|
||||||
void menu_end_entry(void);
|
|
||||||
void menu_add_dep(struct expr *dep);
|
void menu_add_dep(struct expr *dep);
|
||||||
void menu_add_visibility(struct expr *dep);
|
void menu_add_visibility(struct expr *dep);
|
||||||
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);
|
||||||
@ -115,6 +114,8 @@ struct file *file_lookup(const char *name);
|
|||||||
int file_write_dep(const char *name);
|
int file_write_dep(const char *name);
|
||||||
void *xmalloc(size_t size);
|
void *xmalloc(size_t size);
|
||||||
void *xcalloc(size_t nmemb, size_t size);
|
void *xcalloc(size_t nmemb, size_t size);
|
||||||
|
void *xrealloc(void *p, size_t size);
|
||||||
|
char *xstrdup(const char *s);
|
||||||
|
|
||||||
struct gstr {
|
struct gstr {
|
||||||
size_t len;
|
size_t len;
|
||||||
|
@ -31,7 +31,7 @@ extern struct symbol * symbol_hash[SYMBOL_HASHSIZE];
|
|||||||
|
|
||||||
struct symbol * sym_lookup(const char *name, int flags);
|
struct symbol * sym_lookup(const char *name, int flags);
|
||||||
struct symbol * sym_find(const char *name);
|
struct symbol * sym_find(const char *name);
|
||||||
const char * sym_expand_string_value(const char *in);
|
char *sym_expand_string_value(const char *in);
|
||||||
const char * sym_escape_string_value(const char *in);
|
const char * sym_escape_string_value(const char *in);
|
||||||
struct symbol ** sym_re_search(const char *pattern);
|
struct symbol ** sym_re_search(const char *pattern);
|
||||||
const char * sym_type_name(enum symbol_type type);
|
const char * sym_type_name(enum symbol_type type);
|
||||||
|
3
kconfig/lxdialog/check-lxdialog.sh
Normal file → Executable file
3
kconfig/lxdialog/check-lxdialog.sh
Normal file → Executable file
@ -55,7 +55,8 @@ EOF
|
|||||||
echo " *** required header files." 1>&2
|
echo " *** required header files." 1>&2
|
||||||
echo " *** 'make menuconfig' requires the ncurses libraries." 1>&2
|
echo " *** 'make menuconfig' requires the ncurses libraries." 1>&2
|
||||||
echo " *** " 1>&2
|
echo " *** " 1>&2
|
||||||
echo " *** Install ncurses (ncurses-devel) and try again." 1>&2
|
echo " *** Install ncurses (ncurses-devel or libncurses-dev " 1>&2
|
||||||
|
echo " *** depending on your distribution) and try again." 1>&2
|
||||||
echo " *** " 1>&2
|
echo " *** " 1>&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
@ -246,7 +246,7 @@ search_help[] = N_(
|
|||||||
" Selected by: BAR [=n]\n"
|
" Selected by: BAR [=n]\n"
|
||||||
"-----------------------------------------------------------------\n"
|
"-----------------------------------------------------------------\n"
|
||||||
"o The line 'Type:' shows the type of the configuration option for\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"
|
"o The line 'Prompt:' shows the text used in the menu structure for\n"
|
||||||
" this symbol\n"
|
" this symbol\n"
|
||||||
"o The 'Defined at' line tells at what file / line number the symbol\n"
|
"o The 'Defined at' line tells at what file / line number the symbol\n"
|
||||||
|
187
kconfig/menu.c
187
kconfig/menu.c
@ -62,13 +62,8 @@ void menu_add_entry(struct symbol *sym)
|
|||||||
menu_add_symbol(P_SYMBOL, sym, NULL);
|
menu_add_symbol(P_SYMBOL, sym, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void menu_end_entry(void)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
struct menu *menu_add_menu(void)
|
struct menu *menu_add_menu(void)
|
||||||
{
|
{
|
||||||
menu_end_entry();
|
|
||||||
last_entry_ptr = ¤t_entry->list;
|
last_entry_ptr = ¤t_entry->list;
|
||||||
return current_menu = current_entry;
|
return current_menu = current_entry;
|
||||||
}
|
}
|
||||||
@ -79,19 +74,23 @@ void menu_end_menu(void)
|
|||||||
current_menu = current_menu->parent;
|
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)
|
if (!e)
|
||||||
return e;
|
return e;
|
||||||
|
|
||||||
switch (e->type) {
|
switch (e->type) {
|
||||||
case E_NOT:
|
case E_NOT:
|
||||||
e->left.expr = menu_check_dep(e->left.expr);
|
e->left.expr = rewrite_m(e->left.expr);
|
||||||
break;
|
break;
|
||||||
case E_OR:
|
case E_OR:
|
||||||
case E_AND:
|
case E_AND:
|
||||||
e->left.expr = menu_check_dep(e->left.expr);
|
e->left.expr = rewrite_m(e->left.expr);
|
||||||
e->right.expr = menu_check_dep(e->right.expr);
|
e->right.expr = rewrite_m(e->right.expr);
|
||||||
break;
|
break;
|
||||||
case E_SYMBOL:
|
case E_SYMBOL:
|
||||||
/* change 'm' into 'm' && MODULES */
|
/* change 'm' into 'm' && MODULES */
|
||||||
@ -106,7 +105,7 @@ static struct expr *menu_check_dep(struct expr *e)
|
|||||||
|
|
||||||
void menu_add_dep(struct expr *dep)
|
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)
|
void menu_set_type(int type)
|
||||||
@ -131,7 +130,7 @@ static struct property *menu_add_prop(enum prop_type type, char *prompt, struct
|
|||||||
|
|
||||||
prop->menu = current_entry;
|
prop->menu = current_entry;
|
||||||
prop->expr = expr;
|
prop->expr = expr;
|
||||||
prop->visible.expr = menu_check_dep(dep);
|
prop->visible.expr = dep;
|
||||||
|
|
||||||
if (prompt) {
|
if (prompt) {
|
||||||
/* For crostool-NG, a leading pipe followed with spaces
|
/* For crostool-NG, a leading pipe followed with spaces
|
||||||
@ -219,6 +218,7 @@ void menu_add_option(int token, char *arg)
|
|||||||
sym_defconfig_list = current_entry->sym;
|
sym_defconfig_list = current_entry->sym;
|
||||||
else if (sym_defconfig_list != current_entry->sym)
|
else if (sym_defconfig_list != current_entry->sym)
|
||||||
zconf_error("trying to redefine defconfig symbol");
|
zconf_error("trying to redefine defconfig symbol");
|
||||||
|
sym_defconfig_list->flags |= SYMBOL_AUTO;
|
||||||
break;
|
break;
|
||||||
case T_OPT_ENV:
|
case T_OPT_ENV:
|
||||||
prop_add_env(arg);
|
prop_add_env(arg);
|
||||||
@ -258,6 +258,16 @@ static void sym_check_prop(struct symbol *sym)
|
|||||||
"'%s': number is invalid",
|
"'%s': number is invalid",
|
||||||
sym->name);
|
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;
|
break;
|
||||||
case P_SELECT:
|
case P_SELECT:
|
||||||
case P_IMPLY:
|
case P_IMPLY:
|
||||||
@ -266,13 +276,13 @@ static void sym_check_prop(struct symbol *sym)
|
|||||||
if (sym->type != S_BOOLEAN && sym->type != S_TRISTATE)
|
if (sym->type != S_BOOLEAN && sym->type != S_TRISTATE)
|
||||||
prop_warn(prop,
|
prop_warn(prop,
|
||||||
"config symbol '%s' uses %s, but is "
|
"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 &&
|
else if (sym2->type != S_UNKNOWN &&
|
||||||
sym2->type != S_BOOLEAN &&
|
sym2->type != S_BOOLEAN &&
|
||||||
sym2->type != S_TRISTATE)
|
sym2->type != S_TRISTATE)
|
||||||
prop_warn(prop,
|
prop_warn(prop,
|
||||||
"'%s' has wrong type. '%s' only "
|
"'%s' has wrong type. '%s' only "
|
||||||
"accept arguments of boolean and "
|
"accept arguments of bool and "
|
||||||
"tristate type", sym2->name, use);
|
"tristate type", sym2->name, use);
|
||||||
break;
|
break;
|
||||||
case P_RANGE:
|
case P_RANGE:
|
||||||
@ -298,6 +308,11 @@ void menu_finalize(struct menu *parent)
|
|||||||
|
|
||||||
sym = parent->sym;
|
sym = parent->sym;
|
||||||
if (parent->list) {
|
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 && sym_is_choice(sym)) {
|
||||||
if (sym->type == S_UNKNOWN) {
|
if (sym->type == S_UNKNOWN) {
|
||||||
/* find the first choice value to find out choice type */
|
/* find the first choice value to find out choice type */
|
||||||
@ -315,30 +330,83 @@ void menu_finalize(struct menu *parent)
|
|||||||
if (menu->sym && menu->sym->type == S_UNKNOWN)
|
if (menu->sym && menu->sym->type == S_UNKNOWN)
|
||||||
menu_set_type(sym->type);
|
menu_set_type(sym->type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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);
|
parentdep = expr_alloc_symbol(sym);
|
||||||
} else if (parent->prompt)
|
} else if (parent->prompt)
|
||||||
|
/* Menu node for 'menu' */
|
||||||
parentdep = parent->prompt->visible.expr;
|
parentdep = parent->prompt->visible.expr;
|
||||||
else
|
else
|
||||||
|
/* Menu node for 'if' */
|
||||||
parentdep = parent->dep;
|
parentdep = parent->dep;
|
||||||
|
|
||||||
|
/* For each child menu node... */
|
||||||
for (menu = parent->list; menu; menu = menu->next) {
|
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_alloc_and(expr_copy(parentdep), basedep);
|
||||||
basedep = expr_eliminate_dups(basedep);
|
basedep = expr_eliminate_dups(basedep);
|
||||||
menu->dep = basedep;
|
menu->dep = basedep;
|
||||||
|
|
||||||
if (menu->sym)
|
if (menu->sym)
|
||||||
|
/*
|
||||||
|
* Note: For symbols, all prompts are included
|
||||||
|
* too in the symbol's own property list
|
||||||
|
*/
|
||||||
prop = menu->sym->prop;
|
prop = menu->sym->prop;
|
||||||
else
|
else
|
||||||
|
/*
|
||||||
|
* For non-symbol menu nodes, we just need to
|
||||||
|
* handle the prompt
|
||||||
|
*/
|
||||||
prop = menu->prompt;
|
prop = menu->prompt;
|
||||||
|
|
||||||
|
/* For each property... */
|
||||||
for (; prop; prop = prop->next) {
|
for (; prop; prop = prop->next) {
|
||||||
if (prop->menu != menu)
|
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;
|
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_alloc_and(expr_copy(basedep), dep);
|
||||||
dep = expr_eliminate_dups(dep);
|
dep = expr_eliminate_dups(dep);
|
||||||
if (menu->sym && menu->sym->type != S_TRISTATE)
|
if (menu->sym && menu->sym->type != S_TRISTATE)
|
||||||
dep = expr_trans_bool(dep);
|
dep = expr_trans_bool(dep);
|
||||||
prop->visible.expr = dep;
|
prop->visible.expr = dep;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Handle selects and implies, which modify the
|
||||||
|
* dependencies of the selected/implied symbol
|
||||||
|
*/
|
||||||
if (prop->type == P_SELECT) {
|
if (prop->type == P_SELECT) {
|
||||||
struct symbol *es = prop_get_symbol(prop);
|
struct symbol *es = prop_get_symbol(prop);
|
||||||
es->rev_dep.expr = expr_alloc_or(es->rev_dep.expr,
|
es->rev_dep.expr = expr_alloc_or(es->rev_dep.expr,
|
||||||
@ -350,34 +418,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)
|
for (menu = parent->list; menu; menu = menu->next)
|
||||||
menu_finalize(menu);
|
menu_finalize(menu);
|
||||||
} else if (sym) {
|
} 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 = parent->prompt ? parent->prompt->visible.expr : NULL;
|
||||||
basedep = expr_trans_compare(basedep, E_UNEQUAL, &symbol_no);
|
basedep = expr_trans_compare(basedep, E_UNEQUAL, &symbol_no);
|
||||||
basedep = expr_eliminate_dups(expr_transform(basedep));
|
basedep = expr_eliminate_dups(expr_transform(basedep));
|
||||||
|
|
||||||
|
/* Examine consecutive elements after sym */
|
||||||
last_menu = NULL;
|
last_menu = NULL;
|
||||||
for (menu = parent->next; menu; menu = menu->next) {
|
for (menu = parent->next; menu; menu = menu->next) {
|
||||||
dep = menu->prompt ? menu->prompt->visible.expr : menu->dep;
|
dep = menu->prompt ? menu->prompt->visible.expr : menu->dep;
|
||||||
if (!expr_contains_symbol(dep, sym))
|
if (!expr_contains_symbol(dep, sym))
|
||||||
|
/* No dependency, quit */
|
||||||
break;
|
break;
|
||||||
if (expr_depends_symbol(dep, sym))
|
if (expr_depends_symbol(dep, sym))
|
||||||
|
/* Absolute dependency, put in submenu */
|
||||||
goto next;
|
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_trans_compare(dep, E_UNEQUAL, &symbol_no);
|
||||||
dep = expr_eliminate_dups(expr_transform(dep));
|
dep = expr_eliminate_dups(expr_transform(dep));
|
||||||
dep2 = expr_copy(basedep);
|
dep2 = expr_copy(basedep);
|
||||||
expr_eliminate_eq(&dep, &dep2);
|
expr_eliminate_eq(&dep, &dep2);
|
||||||
expr_free(dep);
|
expr_free(dep);
|
||||||
if (!expr_is_yes(dep2)) {
|
if (!expr_is_yes(dep2)) {
|
||||||
|
/* Not superset, quit */
|
||||||
expr_free(dep2);
|
expr_free(dep2);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
/* Superset, put in submenu */
|
||||||
expr_free(dep2);
|
expr_free(dep2);
|
||||||
next:
|
next:
|
||||||
menu_finalize(menu);
|
menu_finalize(menu);
|
||||||
menu->parent = parent;
|
menu->parent = parent;
|
||||||
last_menu = menu;
|
last_menu = menu;
|
||||||
}
|
}
|
||||||
|
expr_free(basedep);
|
||||||
if (last_menu) {
|
if (last_menu) {
|
||||||
parent->list = parent->next;
|
parent->list = parent->next;
|
||||||
parent->next = last_menu->next;
|
parent->next = last_menu->next;
|
||||||
@ -426,6 +541,35 @@ void menu_finalize(struct menu *parent)
|
|||||||
*ep = expr_alloc_one(E_LIST, NULL);
|
*ep = expr_alloc_one(E_LIST, NULL);
|
||||||
(*ep)->right.sym = menu->sym;
|
(*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)) {
|
if (menu->list && (!menu->prompt || !menu->prompt->text)) {
|
||||||
for (last_menu = menu->list; ; last_menu = last_menu->next) {
|
for (last_menu = menu->list; ; last_menu = last_menu->next) {
|
||||||
last_menu->parent = parent;
|
last_menu->parent = parent;
|
||||||
@ -450,6 +594,15 @@ void menu_finalize(struct menu *parent)
|
|||||||
sym->flags |= SYMBOL_WARNED;
|
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) {
|
if (sym && !sym_is_optional(sym) && parent->prompt) {
|
||||||
sym->rev_dep.expr = expr_alloc_or(sym->rev_dep.expr,
|
sym->rev_dep.expr = expr_alloc_or(sym->rev_dep.expr,
|
||||||
expr_alloc_and(parent->prompt->visible.expr,
|
expr_alloc_and(parent->prompt->visible.expr,
|
||||||
@ -682,14 +835,14 @@ static void get_symbol_str(struct gstr *r, struct symbol *sym,
|
|||||||
get_symbol_props_str(r, sym, P_SELECT, _(" Selects: "));
|
get_symbol_props_str(r, sym, P_SELECT, _(" Selects: "));
|
||||||
if (sym->rev_dep.expr) {
|
if (sym->rev_dep.expr) {
|
||||||
str_append(r, _(" Selected by: "));
|
str_append(r, _(" Selected by: "));
|
||||||
expr_gstr_print(sym->rev_dep.expr, r);
|
expr_gstr_print_revdep(sym->rev_dep.expr, r);
|
||||||
str_append(r, "\n");
|
str_append(r, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
get_symbol_props_str(r, sym, P_IMPLY, _(" Implies: "));
|
get_symbol_props_str(r, sym, P_IMPLY, _(" Implies: "));
|
||||||
if (sym->implied.expr) {
|
if (sym->implied.expr) {
|
||||||
str_append(r, _(" Implied by: "));
|
str_append(r, _(" Implied by: "));
|
||||||
expr_gstr_print(sym->implied.expr, r);
|
expr_gstr_print_revdep(sym->implied.expr, r);
|
||||||
str_append(r, "\n");
|
str_append(r, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#include "nconf.h"
|
#include "nconf.h"
|
||||||
|
#include "lkc.h"
|
||||||
|
|
||||||
/* a list of all the different widgets we use */
|
/* a list of all the different widgets we use */
|
||||||
attributes_t attributes[ATTR_MAX+1] = {0};
|
attributes_t attributes[ATTR_MAX+1] = {0};
|
||||||
@ -374,7 +375,7 @@ int dialog_inputbox(WINDOW *main_window,
|
|||||||
|
|
||||||
if (strlen(init)+1 > *result_len) {
|
if (strlen(init)+1 > *result_len) {
|
||||||
*result_len = strlen(init)+1;
|
*result_len = strlen(init)+1;
|
||||||
*resultp = result = realloc(result, *result_len);
|
*resultp = result = xrealloc(result, *result_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* find the widest line of msg: */
|
/* find the widest line of msg: */
|
||||||
|
@ -77,7 +77,7 @@ const char *sym_type_name(enum symbol_type type)
|
|||||||
{
|
{
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case S_BOOLEAN:
|
case S_BOOLEAN:
|
||||||
return "boolean";
|
return "bool";
|
||||||
case S_TRISTATE:
|
case S_TRISTATE:
|
||||||
return "tristate";
|
return "tristate";
|
||||||
case S_INT:
|
case S_INT:
|
||||||
@ -183,7 +183,7 @@ static void sym_validate_range(struct symbol *sym)
|
|||||||
sprintf(str, "%lld", val2);
|
sprintf(str, "%lld", val2);
|
||||||
else
|
else
|
||||||
sprintf(str, "0x%llx", val2);
|
sprintf(str, "0x%llx", val2);
|
||||||
sym->curr.val = strdup(str);
|
sym->curr.val = xstrdup(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sym_set_changed(struct symbol *sym)
|
static void sym_set_changed(struct symbol *sym)
|
||||||
@ -371,11 +371,13 @@ void sym_calc_value(struct symbol *sym)
|
|||||||
sym->curr.tri = no;
|
sym->curr.tri = no;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!sym_is_choice_value(sym))
|
sym->flags &= ~SYMBOL_WRITE;
|
||||||
sym->flags &= ~SYMBOL_WRITE;
|
|
||||||
|
|
||||||
sym_calc_visibility(sym);
|
sym_calc_visibility(sym);
|
||||||
|
|
||||||
|
if (sym->visible != no)
|
||||||
|
sym->flags |= SYMBOL_WRITE;
|
||||||
|
|
||||||
/* set default if recursively called */
|
/* set default if recursively called */
|
||||||
sym->curr = newval;
|
sym->curr = newval;
|
||||||
|
|
||||||
@ -390,7 +392,6 @@ void sym_calc_value(struct symbol *sym)
|
|||||||
/* if the symbol is visible use the user value
|
/* if the symbol is visible use the user value
|
||||||
* if available, otherwise try the default value
|
* if available, otherwise try the default value
|
||||||
*/
|
*/
|
||||||
sym->flags |= SYMBOL_WRITE;
|
|
||||||
if (sym_has_value(sym)) {
|
if (sym_has_value(sym)) {
|
||||||
newval.tri = EXPR_AND(sym->def[S_DEF_USER].tri,
|
newval.tri = EXPR_AND(sym->def[S_DEF_USER].tri,
|
||||||
sym->visible);
|
sym->visible);
|
||||||
@ -433,12 +434,9 @@ void sym_calc_value(struct symbol *sym)
|
|||||||
case S_STRING:
|
case S_STRING:
|
||||||
case S_HEX:
|
case S_HEX:
|
||||||
case S_INT:
|
case S_INT:
|
||||||
if (sym->visible != no) {
|
if (sym->visible != no && sym_has_value(sym)) {
|
||||||
sym->flags |= SYMBOL_WRITE;
|
newval.val = sym->def[S_DEF_USER].val;
|
||||||
if (sym_has_value(sym)) {
|
break;
|
||||||
newval.val = sym->def[S_DEF_USER].val;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
prop = sym_get_default_prop(sym);
|
prop = sym_get_default_prop(sym);
|
||||||
if (prop) {
|
if (prop) {
|
||||||
@ -851,7 +849,7 @@ struct symbol *sym_lookup(const char *name, int flags)
|
|||||||
: !(symbol->flags & (SYMBOL_CONST|SYMBOL_CHOICE))))
|
: !(symbol->flags & (SYMBOL_CONST|SYMBOL_CHOICE))))
|
||||||
return symbol;
|
return symbol;
|
||||||
}
|
}
|
||||||
new_name = strdup(name);
|
new_name = xstrdup(name);
|
||||||
} else {
|
} else {
|
||||||
new_name = NULL;
|
new_name = NULL;
|
||||||
hash = 0;
|
hash = 0;
|
||||||
@ -901,12 +899,16 @@ struct symbol *sym_find(const char *name)
|
|||||||
* name to be expanded shall be prefixed by a '$'. Unknown symbol expands to
|
* name to be expanded shall be prefixed by a '$'. Unknown symbol expands to
|
||||||
* the empty string.
|
* the empty string.
|
||||||
*/
|
*/
|
||||||
const char *sym_expand_string_value(const char *in)
|
char *sym_expand_string_value(const char *in)
|
||||||
{
|
{
|
||||||
const char *src;
|
const char *src;
|
||||||
char *res;
|
char *res;
|
||||||
size_t reslen;
|
size_t reslen;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Note: 'in' might come from a token that's about to be
|
||||||
|
* freed, so make sure to always allocate a new string
|
||||||
|
*/
|
||||||
reslen = strlen(in) + 1;
|
reslen = strlen(in) + 1;
|
||||||
res = xmalloc(reslen);
|
res = xmalloc(reslen);
|
||||||
res[0] = '\0';
|
res[0] = '\0';
|
||||||
@ -934,7 +936,7 @@ const char *sym_expand_string_value(const char *in)
|
|||||||
newlen = strlen(res) + strlen(symval) + strlen(src) + 1;
|
newlen = strlen(res) + strlen(symval) + strlen(src) + 1;
|
||||||
if (newlen > reslen) {
|
if (newlen > reslen) {
|
||||||
reslen = newlen;
|
reslen = newlen;
|
||||||
res = realloc(res, reslen);
|
res = xrealloc(res, reslen);
|
||||||
}
|
}
|
||||||
|
|
||||||
strcat(res, symval);
|
strcat(res, symval);
|
||||||
@ -1219,7 +1221,7 @@ static struct symbol *sym_check_expr_deps(struct expr *e)
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
printf("Oops! How to check %d?\n", e->type);
|
fprintf(stderr, "Oops! How to check %d?\n", e->type);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,11 +14,11 @@
|
|||||||
struct file *file_lookup(const char *name)
|
struct file *file_lookup(const char *name)
|
||||||
{
|
{
|
||||||
struct file *file;
|
struct file *file;
|
||||||
const char *file_name = sym_expand_string_value(name);
|
char *file_name = sym_expand_string_value(name);
|
||||||
|
|
||||||
for (file = file_list; file; file = file->next) {
|
for (file = file_list; file; file = file->next) {
|
||||||
if (!strcmp(name, file->name)) {
|
if (!strcmp(name, file->name)) {
|
||||||
free((void *)file_name);
|
free(file_name);
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -104,7 +104,7 @@ void str_append(struct gstr *gs, const char *s)
|
|||||||
if (s) {
|
if (s) {
|
||||||
l = strlen(gs->s) + strlen(s) + 1;
|
l = strlen(gs->s) + strlen(s) + 1;
|
||||||
if (l > gs->len) {
|
if (l > gs->len) {
|
||||||
gs->s = realloc(gs->s, l);
|
gs->s = xrealloc(gs->s, l);
|
||||||
gs->len = l;
|
gs->len = l;
|
||||||
}
|
}
|
||||||
strcat(gs->s, s);
|
strcat(gs->s, s);
|
||||||
@ -145,3 +145,23 @@ void *xcalloc(size_t nmemb, size_t size)
|
|||||||
fprintf(stderr, "Out of memory.\n");
|
fprintf(stderr, "Out of memory.\n");
|
||||||
exit(1);
|
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);
|
||||||
|
}
|
||||||
|
@ -52,7 +52,7 @@ static void append_string(const char *str, int size)
|
|||||||
if (new_size > text_asize) {
|
if (new_size > text_asize) {
|
||||||
new_size += START_STRSIZE - 1;
|
new_size += START_STRSIZE - 1;
|
||||||
new_size &= -START_STRSIZE;
|
new_size &= -START_STRSIZE;
|
||||||
text = realloc(text, new_size);
|
text = xrealloc(text, new_size);
|
||||||
text_asize = new_size;
|
text_asize = new_size;
|
||||||
}
|
}
|
||||||
memcpy(text + text_size, str, size);
|
memcpy(text + text_size, str, size);
|
||||||
@ -106,11 +106,11 @@ n [A-Za-z0-9_-]
|
|||||||
current_pos.file = current_file;
|
current_pos.file = current_file;
|
||||||
current_pos.lineno = current_file->lineno;
|
current_pos.lineno = current_file->lineno;
|
||||||
if (id && id->flags & TF_COMMAND) {
|
if (id && id->flags & TF_COMMAND) {
|
||||||
zconflval.id = id;
|
yylval.id = id;
|
||||||
return id->token;
|
return id->token;
|
||||||
}
|
}
|
||||||
alloc_string(yytext, yyleng);
|
alloc_string(yytext, yyleng);
|
||||||
zconflval.string = text;
|
yylval.string = text;
|
||||||
return T_WORD;
|
return T_WORD;
|
||||||
}
|
}
|
||||||
. warn_ignored_character(*yytext);
|
. warn_ignored_character(*yytext);
|
||||||
@ -142,11 +142,11 @@ n [A-Za-z0-9_-]
|
|||||||
({n}|[/.])+ {
|
({n}|[/.])+ {
|
||||||
const struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
|
const struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
|
||||||
if (id && id->flags & TF_PARAM) {
|
if (id && id->flags & TF_PARAM) {
|
||||||
zconflval.id = id;
|
yylval.id = id;
|
||||||
return id->token;
|
return id->token;
|
||||||
}
|
}
|
||||||
alloc_string(yytext, yyleng);
|
alloc_string(yytext, yyleng);
|
||||||
zconflval.string = text;
|
yylval.string = text;
|
||||||
return T_WORD;
|
return T_WORD;
|
||||||
}
|
}
|
||||||
#.* /* comment */
|
#.* /* comment */
|
||||||
@ -161,7 +161,7 @@ n [A-Za-z0-9_-]
|
|||||||
<STRING>{
|
<STRING>{
|
||||||
[^'"\\\n]+/\n {
|
[^'"\\\n]+/\n {
|
||||||
append_string(yytext, yyleng);
|
append_string(yytext, yyleng);
|
||||||
zconflval.string = text;
|
yylval.string = text;
|
||||||
return T_WORD_QUOTE;
|
return T_WORD_QUOTE;
|
||||||
}
|
}
|
||||||
[^'"\\\n]+ {
|
[^'"\\\n]+ {
|
||||||
@ -169,7 +169,7 @@ n [A-Za-z0-9_-]
|
|||||||
}
|
}
|
||||||
\\.?/\n {
|
\\.?/\n {
|
||||||
append_string(yytext + 1, yyleng - 1);
|
append_string(yytext + 1, yyleng - 1);
|
||||||
zconflval.string = text;
|
yylval.string = text;
|
||||||
return T_WORD_QUOTE;
|
return T_WORD_QUOTE;
|
||||||
}
|
}
|
||||||
\\.? {
|
\\.? {
|
||||||
@ -178,13 +178,15 @@ n [A-Za-z0-9_-]
|
|||||||
\'|\" {
|
\'|\" {
|
||||||
if (str == yytext[0]) {
|
if (str == yytext[0]) {
|
||||||
BEGIN(PARAM);
|
BEGIN(PARAM);
|
||||||
zconflval.string = text;
|
yylval.string = text;
|
||||||
return T_WORD_QUOTE;
|
return T_WORD_QUOTE;
|
||||||
} else
|
} else
|
||||||
append_string(yytext, 1);
|
append_string(yytext, 1);
|
||||||
}
|
}
|
||||||
\n {
|
\n {
|
||||||
printf("%s:%d:warning: multi-line strings not supported\n", zconf_curname(), zconf_lineno());
|
fprintf(stderr,
|
||||||
|
"%s:%d:warning: multi-line strings not supported\n",
|
||||||
|
zconf_curname(), zconf_lineno());
|
||||||
current_file->lineno++;
|
current_file->lineno++;
|
||||||
BEGIN(INITIAL);
|
BEGIN(INITIAL);
|
||||||
return T_EOL;
|
return T_EOL;
|
||||||
@ -261,7 +263,7 @@ void zconf_starthelp(void)
|
|||||||
|
|
||||||
static void zconf_endhelp(void)
|
static void zconf_endhelp(void)
|
||||||
{
|
{
|
||||||
zconflval.string = text;
|
yylval.string = text;
|
||||||
BEGIN(INITIAL);
|
BEGIN(INITIAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -294,7 +296,7 @@ void zconf_initscan(const char *name)
|
|||||||
{
|
{
|
||||||
yyin = zconf_fopen(name);
|
yyin = zconf_fopen(name);
|
||||||
if (!yyin) {
|
if (!yyin) {
|
||||||
printf("can't find file %s\n", name);
|
fprintf(stderr, "can't find file %s\n", name);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -315,8 +317,8 @@ void zconf_nextfile(const char *name)
|
|||||||
current_buf->state = YY_CURRENT_BUFFER;
|
current_buf->state = YY_CURRENT_BUFFER;
|
||||||
yyin = zconf_fopen(file->name);
|
yyin = zconf_fopen(file->name);
|
||||||
if (!yyin) {
|
if (!yyin) {
|
||||||
printf("%s:%d: can't open file \"%s\"\n",
|
fprintf(stderr, "%s:%d: can't open file \"%s\"\n",
|
||||||
zconf_curname(), zconf_lineno(), file->name);
|
zconf_curname(), zconf_lineno(), file->name);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
|
yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
|
||||||
@ -325,20 +327,17 @@ void zconf_nextfile(const char *name)
|
|||||||
|
|
||||||
for (iter = current_file->parent; iter; iter = iter->parent ) {
|
for (iter = current_file->parent; iter; iter = iter->parent ) {
|
||||||
if (!strcmp(current_file->name,iter->name) ) {
|
if (!strcmp(current_file->name,iter->name) ) {
|
||||||
printf("%s:%d: recursive inclusion detected. "
|
fprintf(stderr,
|
||||||
"Inclusion path:\n current file : '%s'\n",
|
"%s:%d: recursive inclusion detected. "
|
||||||
zconf_curname(), zconf_lineno(),
|
"Inclusion path:\n current file : '%s'\n",
|
||||||
zconf_curname());
|
zconf_curname(), zconf_lineno(),
|
||||||
iter = current_file->parent;
|
zconf_curname());
|
||||||
while (iter && \
|
iter = current_file;
|
||||||
strcmp(iter->name,current_file->name)) {
|
do {
|
||||||
printf(" included from: '%s:%d'\n",
|
|
||||||
iter->name, iter->lineno-1);
|
|
||||||
iter = iter->parent;
|
iter = iter->parent;
|
||||||
}
|
fprintf(stderr, " included from: '%s:%d'\n",
|
||||||
if (iter)
|
iter->name, iter->lineno - 1);
|
||||||
printf(" included from: '%s:%d'\n",
|
} while (strcmp(iter->name, current_file->name));
|
||||||
iter->name, iter->lineno+1);
|
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
118
kconfig/zconf.y
118
kconfig/zconf.y
@ -20,10 +20,10 @@
|
|||||||
|
|
||||||
int cdebug = PRINTD;
|
int cdebug = PRINTD;
|
||||||
|
|
||||||
extern int zconflex(void);
|
int yylex(void);
|
||||||
|
static void yyerror(const char *err);
|
||||||
static void zconfprint(const char *err, ...);
|
static void zconfprint(const char *err, ...);
|
||||||
static void zconf_error(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 struct kconf_id *id, int starttoken, int endtoken);
|
||||||
|
|
||||||
struct symbol *symbol_hash[SYMBOL_HASHSIZE];
|
struct symbol *symbol_hash[SYMBOL_HASHSIZE];
|
||||||
@ -85,6 +85,7 @@ static struct menu *current_menu, *current_entry;
|
|||||||
%nonassoc T_NOT
|
%nonassoc T_NOT
|
||||||
|
|
||||||
%type <string> prompt
|
%type <string> prompt
|
||||||
|
%type <symbol> nonconst_symbol
|
||||||
%type <symbol> symbol
|
%type <symbol> symbol
|
||||||
%type <expr> expr
|
%type <expr> expr
|
||||||
%type <expr> if_expr
|
%type <expr> if_expr
|
||||||
@ -101,14 +102,34 @@ static struct menu *current_menu, *current_entry;
|
|||||||
} if_entry menu_entry choice_entry
|
} if_entry menu_entry choice_entry
|
||||||
|
|
||||||
%{
|
%{
|
||||||
/* Include zconf_id.c here so it can see the token constants. */
|
/* Include kconf_id.c here so it can see the token constants. */
|
||||||
#include "kconf_id.c"
|
#include "kconf_id.c"
|
||||||
%}
|
%}
|
||||||
|
|
||||||
%%
|
%%
|
||||||
input: nl start | start;
|
input: nl start | start;
|
||||||
|
|
||||||
start: mainmenu_stmt stmt_list | stmt_list;
|
start: mainmenu_stmt stmt_list | no_mainmenu_stmt stmt_list;
|
||||||
|
|
||||||
|
/* mainmenu entry */
|
||||||
|
|
||||||
|
mainmenu_stmt: T_MAINMENU prompt nl
|
||||||
|
{
|
||||||
|
menu_add_prompt(P_MENU, $2, NULL);
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Default main menu, if there's no mainmenu entry */
|
||||||
|
|
||||||
|
no_mainmenu_stmt: /* empty */
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Hack: Keep the main menu title on the heap so we can safely free it
|
||||||
|
* later regardless of whether it comes from the 'prompt' in
|
||||||
|
* mainmenu_stmt or here
|
||||||
|
*/
|
||||||
|
menu_add_prompt(P_MENU, xstrdup("Linux Kernel Configuration"), NULL);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
stmt_list:
|
stmt_list:
|
||||||
/* empty */
|
/* empty */
|
||||||
@ -145,26 +166,23 @@ option_error:
|
|||||||
|
|
||||||
/* config/menuconfig entry */
|
/* 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);
|
$2->flags |= SYMBOL_OPTIONAL;
|
||||||
sym->flags |= SYMBOL_OPTIONAL;
|
menu_add_entry($2);
|
||||||
menu_add_entry(sym);
|
printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), $2->name);
|
||||||
printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), $2);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
config_stmt: config_entry_start config_option_list
|
config_stmt: config_entry_start config_option_list
|
||||||
{
|
{
|
||||||
menu_end_entry();
|
|
||||||
printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno());
|
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);
|
$2->flags |= SYMBOL_OPTIONAL;
|
||||||
sym->flags |= SYMBOL_OPTIONAL;
|
menu_add_entry($2);
|
||||||
menu_add_entry(sym);
|
printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), $2->name);
|
||||||
printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), $2);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
menuconfig_stmt: menuconfig_entry_start config_option_list
|
menuconfig_stmt: menuconfig_entry_start config_option_list
|
||||||
@ -173,7 +191,6 @@ menuconfig_stmt: menuconfig_entry_start config_option_list
|
|||||||
current_entry->prompt->type = P_MENU;
|
current_entry->prompt->type = P_MENU;
|
||||||
else
|
else
|
||||||
zconfprint("warning: menuconfig statement without prompt");
|
zconfprint("warning: menuconfig statement without prompt");
|
||||||
menu_end_entry();
|
|
||||||
printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno());
|
printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno());
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -211,15 +228,15 @@ config_option: T_DEFAULT expr if_expr T_EOL
|
|||||||
$1->stype);
|
$1->stype);
|
||||||
};
|
};
|
||||||
|
|
||||||
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());
|
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());
|
printd(DEBUG_PARSE, "%s:%d:imply\n", zconf_curname(), zconf_lineno());
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -237,8 +254,10 @@ symbol_option_list:
|
|||||||
| symbol_option_list T_WORD symbol_option_arg
|
| symbol_option_list T_WORD symbol_option_arg
|
||||||
{
|
{
|
||||||
const struct kconf_id *id = kconf_id_lookup($2, strlen($2));
|
const struct kconf_id *id = kconf_id_lookup($2, strlen($2));
|
||||||
if (id && id->flags & TF_OPTION)
|
if (id && id->flags & TF_OPTION) {
|
||||||
menu_add_option(id->token, $3);
|
menu_add_option(id->token, $3);
|
||||||
|
free($3);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
zconfprint("warning: ignoring unknown option %s", $2);
|
zconfprint("warning: ignoring unknown option %s", $2);
|
||||||
free($2);
|
free($2);
|
||||||
@ -257,6 +276,7 @@ choice: T_CHOICE word_opt T_EOL
|
|||||||
sym->flags |= SYMBOL_AUTO;
|
sym->flags |= SYMBOL_AUTO;
|
||||||
menu_add_entry(sym);
|
menu_add_entry(sym);
|
||||||
menu_add_expr(P_CHOICE, NULL, NULL);
|
menu_add_expr(P_CHOICE, NULL, NULL);
|
||||||
|
free($2);
|
||||||
printd(DEBUG_PARSE, "%s:%d:choice\n", zconf_curname(), zconf_lineno());
|
printd(DEBUG_PARSE, "%s:%d:choice\n", zconf_curname(), zconf_lineno());
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -308,10 +328,10 @@ choice_option: T_OPTIONAL T_EOL
|
|||||||
printd(DEBUG_PARSE, "%s:%d:optional\n", zconf_curname(), zconf_lineno());
|
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) {
|
if ($1->stype == S_UNKNOWN) {
|
||||||
menu_add_symbol(P_DEFAULT, sym_lookup($2, 0), $3);
|
menu_add_symbol(P_DEFAULT, $2, $3);
|
||||||
printd(DEBUG_PARSE, "%s:%d:default\n",
|
printd(DEBUG_PARSE, "%s:%d:default\n",
|
||||||
zconf_curname(), zconf_lineno());
|
zconf_curname(), zconf_lineno());
|
||||||
} else
|
} else
|
||||||
@ -351,13 +371,6 @@ if_block:
|
|||||||
| if_block choice_stmt
|
| if_block choice_stmt
|
||||||
;
|
;
|
||||||
|
|
||||||
/* mainmenu entry */
|
|
||||||
|
|
||||||
mainmenu_stmt: T_MAINMENU prompt nl
|
|
||||||
{
|
|
||||||
menu_add_prompt(P_MENU, $2, NULL);
|
|
||||||
};
|
|
||||||
|
|
||||||
/* menu entry */
|
/* menu entry */
|
||||||
|
|
||||||
menu: T_MENU prompt T_EOL
|
menu: T_MENU prompt T_EOL
|
||||||
@ -394,6 +407,7 @@ source_stmt: T_SOURCE prompt T_EOL
|
|||||||
{
|
{
|
||||||
printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), $2);
|
printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), $2);
|
||||||
zconf_nextfile($2);
|
zconf_nextfile($2);
|
||||||
|
free($2);
|
||||||
};
|
};
|
||||||
|
|
||||||
/* comment entry */
|
/* comment entry */
|
||||||
@ -406,9 +420,7 @@ comment: T_COMMENT prompt T_EOL
|
|||||||
};
|
};
|
||||||
|
|
||||||
comment_stmt: comment depends_list
|
comment_stmt: comment depends_list
|
||||||
{
|
;
|
||||||
menu_end_entry();
|
|
||||||
};
|
|
||||||
|
|
||||||
/* help option */
|
/* help option */
|
||||||
|
|
||||||
@ -420,6 +432,17 @@ help_start: T_HELP T_EOL
|
|||||||
|
|
||||||
help: help_start T_HELPTEXT
|
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;
|
current_entry->help = $2;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -491,7 +514,10 @@ expr: symbol { $$ = expr_alloc_symbol($1); }
|
|||||||
| expr T_AND expr { $$ = expr_alloc_two(E_AND, $1, $3); }
|
| 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); }
|
| T_WORD_QUOTE { $$ = sym_lookup($1, SYMBOL_CONST); free($1); }
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -502,6 +528,7 @@ word_opt: /* empty */ { $$ = NULL; }
|
|||||||
|
|
||||||
void conf_parse(const char *name)
|
void conf_parse(const char *name)
|
||||||
{
|
{
|
||||||
|
const char *tmp;
|
||||||
struct symbol *sym;
|
struct symbol *sym;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@ -509,27 +536,28 @@ void conf_parse(const char *name)
|
|||||||
|
|
||||||
sym_init();
|
sym_init();
|
||||||
_menu_init();
|
_menu_init();
|
||||||
rootmenu.prompt = menu_add_prompt(P_MENU, "Crosstool-NG Configuration", NULL);
|
|
||||||
|
|
||||||
#if YYDEBUG
|
#if YYDEBUG
|
||||||
if (getenv("ZCONF_DEBUG"))
|
if (getenv("ZCONF_DEBUG"))
|
||||||
zconfdebug = 1;
|
yydebug = 1;
|
||||||
#endif
|
#endif
|
||||||
zconfparse();
|
yyparse();
|
||||||
if (zconfnerrs)
|
if (yynerrs)
|
||||||
exit(1);
|
exit(1);
|
||||||
if (!modules_sym)
|
if (!modules_sym)
|
||||||
modules_sym = sym_find( "n" );
|
modules_sym = sym_find( "n" );
|
||||||
|
|
||||||
|
tmp = rootmenu.prompt->text;
|
||||||
rootmenu.prompt->text = _(rootmenu.prompt->text);
|
rootmenu.prompt->text = _(rootmenu.prompt->text);
|
||||||
rootmenu.prompt->text = sym_expand_string_value(rootmenu.prompt->text);
|
rootmenu.prompt->text = sym_expand_string_value(rootmenu.prompt->text);
|
||||||
|
free((char*)tmp);
|
||||||
|
|
||||||
menu_finalize(&rootmenu);
|
menu_finalize(&rootmenu);
|
||||||
for_all_symbols(i, sym) {
|
for_all_symbols(i, sym) {
|
||||||
if (sym_check_deps(sym))
|
if (sym_check_deps(sym))
|
||||||
zconfnerrs++;
|
yynerrs++;
|
||||||
}
|
}
|
||||||
if (zconfnerrs)
|
if (yynerrs)
|
||||||
exit(1);
|
exit(1);
|
||||||
sym_set_change_count(1);
|
sym_set_change_count(1);
|
||||||
}
|
}
|
||||||
@ -554,7 +582,7 @@ static bool zconf_endtoken(const struct kconf_id *id, int starttoken, int endtok
|
|||||||
if (id->token != endtoken) {
|
if (id->token != endtoken) {
|
||||||
zconf_error("unexpected '%s' within %s block",
|
zconf_error("unexpected '%s' within %s block",
|
||||||
id->name, zconf_tokenname(starttoken));
|
id->name, zconf_tokenname(starttoken));
|
||||||
zconfnerrs++;
|
yynerrs++;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (current_menu->file != current_file) {
|
if (current_menu->file != current_file) {
|
||||||
@ -563,7 +591,7 @@ static bool zconf_endtoken(const struct kconf_id *id, int starttoken, int endtok
|
|||||||
fprintf(stderr, "%s:%d: location of the '%s'\n",
|
fprintf(stderr, "%s:%d: location of the '%s'\n",
|
||||||
current_menu->file->name, current_menu->lineno,
|
current_menu->file->name, current_menu->lineno,
|
||||||
zconf_tokenname(starttoken));
|
zconf_tokenname(starttoken));
|
||||||
zconfnerrs++;
|
yynerrs++;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -584,7 +612,7 @@ static void zconf_error(const char *err, ...)
|
|||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
zconfnerrs++;
|
yynerrs++;
|
||||||
fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno());
|
fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno());
|
||||||
va_start(ap, err);
|
va_start(ap, err);
|
||||||
vfprintf(stderr, err, ap);
|
vfprintf(stderr, err, ap);
|
||||||
@ -592,7 +620,7 @@ static void zconf_error(const char *err, ...)
|
|||||||
fprintf(stderr, "\n");
|
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);
|
fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno() + 1, err);
|
||||||
}
|
}
|
||||||
@ -625,7 +653,7 @@ static void print_symbol(FILE *out, struct menu *menu)
|
|||||||
fprintf(out, "\nconfig %s\n", sym->name);
|
fprintf(out, "\nconfig %s\n", sym->name);
|
||||||
switch (sym->type) {
|
switch (sym->type) {
|
||||||
case S_BOOLEAN:
|
case S_BOOLEAN:
|
||||||
fputs(" boolean\n", out);
|
fputs(" bool\n", out);
|
||||||
break;
|
break;
|
||||||
case S_TRISTATE:
|
case S_TRISTATE:
|
||||||
fputs(" tristate\n", out);
|
fputs(" tristate\n", out);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user