kconfig: Sync with upstream v4.17

This commit introduces the following upstream changes:

17baab68d337 kconfig: extend output of 'listnewconfig'
b23d1a241f4e kbuild: add %.lex.c and %.tab.[ch] to 'targets' automatically
9a8dfb394c04 kbuild: clean up *.lex.c and *.tab.[ch] patterns from top-level Makefile
598893002745 .gitignore: move *.lex.c *.tab.[ch] patterns to the top-level .gitignore
18492685e479 kconfig: use yylineno option instead of manual lineno increments
379a8eb8eb1a kconfig: detect recursive inclusion earlier
32a94b8b0c3e kconfig: remove duplicated file name and lineno of recursive inclusion
26561514cc9d kconfig: do not include both curses.h and ncurses.h for nconfig
f8f69dc0b4e0 kconfig: make unmet dependency warnings readable
f622f8279581 kconfig: warn unmet direct dependency of tristate symbols selected by y
e2c75e7667c7 kconfig: tests: test if recursive inclusion is detected
29c434f367ea kconfig: tests: test if recursive dependencies are detected
3e4888c2e3d7 kconfig: tests: test randconfig for choice in choice
beaaddb62540 kconfig: tests: test defconfig when two choices interact
ee236610653e kconfig: tests: check visibility of tristate choice values in y choice
930c429a656f kconfig: tests: check unneeded "is not set" with unmet dependency
b76960c0f6b2 kconfig: tests: test if new symbols in choice are asked
49ac3c0c3aa3 kconfig: tests: test automatic submenu creation
1903c5119059 kconfig: tests: add basic choice tests
022a4bf6b59d kconfig: tests: add framework for Kconfig unit testing
2a61625835c7 kconfig: remove redundant streamline_config.pl prerequisite
911a91c39cab kconfig: rename silentoldconfig to syncconfig
81d2bc227305 kconfig: invoke oldconfig instead of silentoldconfig from local*config
2aad9b896213 kconfig: hide irrelevant sub-menus for oldconfig
99f0b6578bab kconfig: remove redundant input_mode test for check_conf() loop
4bb3a5b085cd kconfig: remove unneeded input_mode test in conf()
59a80b5e892d kconfig: do not call check_conf() for olddefconfig
f467c5640c29 kconfig: only write '# CONFIG_FOO is not set' for visible symbols
d9119b5925a0 kconfig: Print reverse dependencies in groups
9a47ceec543b kconfig: clean-up reverse dependency help implementation
07a422bb213a kbuild: restore autoksyms.h touch to the top Makefile

Signed-off-by: Chris Packham <judge.packham@gmail.com>
This commit is contained in:
Chris Packham 2020-12-09 21:03:27 +13:00
parent 07ae8dd48d
commit 689dc60f21
9 changed files with 115 additions and 127 deletions

3
kconfig/.gitignore vendored
View File

@ -1,9 +1,6 @@
#
# Generated files
#
*.lex.c
*.tab.c
*.tab.h
.deps
Makefile

View File

@ -23,7 +23,7 @@ static void check_conf(struct menu *menu);
enum input_mode {
oldaskconfig,
silentoldconfig,
syncconfig,
oldconfig,
allnoconfig,
allyesconfig,
@ -100,7 +100,7 @@ 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;
@ -293,7 +293,7 @@ static int conf_choice(struct menu *menu)
printf("[1-%d?]: ", cnt);
switch (input_mode) {
case oldconfig:
case silentoldconfig:
case syncconfig:
if (!is_new) {
cnt = def;
printf("%d\n", cnt);
@ -358,10 +358,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;
}
@ -421,10 +422,20 @@ static void check_conf(struct menu *menu)
if (sym_is_changable(sym) ||
(sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)) {
if (input_mode == listnewconfig) {
if (sym->name && !sym_is_choice_value(sym)) {
printf("%s%s\n", CONFIG_, sym->name);
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 (!conf_cnt++)
printf(_("*\n* Restart config...\n*\n"));
rootEntry = menu_get_parent_menu(menu);
@ -440,7 +451,7 @@ 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},
{"syncconfig", no_argument, NULL, syncconfig},
{"defconfig", optional_argument, NULL, defconfig},
{"savedefconfig", required_argument, NULL, savedefconfig},
{"allnoconfig", no_argument, NULL, allnoconfig},
@ -479,7 +490,7 @@ int main(int ac, char **av)
}
input_mode = (enum input_mode)opt;
switch (opt) {
case silentoldconfig:
case syncconfig:
sync_kconfig = 1;
break;
case defconfig:
@ -561,7 +572,7 @@ int main(int ac, char **av)
}
break;
case savedefconfig:
case silentoldconfig:
case syncconfig:
case oldaskconfig:
case oldconfig:
case listnewconfig:
@ -641,24 +652,24 @@ int main(int ac, char **av)
case oldaskconfig:
rootEntry = &rootmenu;
conf(&rootmenu);
input_mode = silentoldconfig;
input_mode = oldconfig;
/* fall through */
case oldconfig:
case listnewconfig:
case olddefconfig:
case silentoldconfig:
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.
/* syncconfig 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)) {

View File

@ -1137,49 +1137,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);
}
static void __expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken, bool revdep)
void expr_print(struct expr *e,
void (*fn)(void *, struct symbol *, const char *),
void *data, int prevtoken)
{
if (!e) {
fn(data, NULL, "y");
@ -1234,14 +1194,9 @@ static void __expr_print(struct expr *e, void (*fn)(void *, struct symbol *, con
fn(data, e->right.sym, e->right.sym->name);
break;
case E_OR:
if (revdep && e->left.expr->type != E_OR)
fn(data, NULL, "\n - ");
__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);
expr_print(e->left.expr, fn, data, E_OR);
fn(data, NULL, " || ");
expr_print(e->right.expr, fn, data, E_OR);
break;
case E_AND:
expr_print(e->left.expr, fn, data, E_AND);
@ -1274,11 +1229,6 @@ static void __expr_print(struct expr *e, void (*fn)(void *, struct symbol *, con
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)
{
xfwrite(str, strlen(str), 1, data);
@ -1329,7 +1279,27 @@ void expr_gstr_print(struct expr *e, struct gstr *gs)
* 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)
static void expr_print_revdep(struct expr *e,
void (*fn)(void *, struct symbol *, const char *),
void *data, tristate pr_type, const char **title)
{
__expr_print(e, expr_print_gstr_helper, gs, E_NONE, true);
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);
}

View File

@ -305,12 +305,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);
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)
{

View File

@ -68,6 +68,7 @@ struct kconf_id {
enum symbol_type stype;
};
extern int yylineno;
void zconfdump(FILE *out);
void zconf_starthelp(void);
FILE *zconf_fopen(const char *name);

View File

@ -834,16 +834,16 @@ static void get_symbol_str(struct gstr *r, struct symbol *sym,
get_symbol_props_str(r, sym, P_SELECT, _(" Selects: "));
if (sym->rev_dep.expr) {
str_append(r, _(" Selected by: "));
expr_gstr_print_revdep(sym->rev_dep.expr, r);
str_append(r, "\n");
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_revdep(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");

View File

@ -15,7 +15,7 @@
#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 +24,6 @@
#include <time.h>
#include <sys/time.h>
#include "ncurses.h"
#define max(a, b) ({\
typeof(a) _a = a;\
typeof(b) _b = b;\

View File

@ -243,7 +243,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;
@ -333,6 +333,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;
@ -403,9 +424,10 @@ 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;
@ -413,18 +435,8 @@ void sym_calc_value(struct symbol *sym)
}
}
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 &&

View File

@ -1,5 +1,5 @@
%option nostdinit noyywrap never-interactive full ecs
%option 8bit nodefault perf-report perf-report
%option 8bit nodefault yylineno
%option noinput
%x COMMAND HELP STRING PARAM
%{
@ -83,7 +83,6 @@ n [A-Za-z0-9_-]
[ \t]*#.*\n |
[ \t]*\n {
current_file->lineno++;
return T_EOL;
}
[ \t]*#.*
@ -104,7 +103,7 @@ n [A-Za-z0-9_-]
const struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
BEGIN(PARAM);
current_pos.file = current_file;
current_pos.lineno = current_file->lineno;
current_pos.lineno = yylineno;
if (id && id->flags & TF_COMMAND) {
yylval.id = id;
return id->token;
@ -116,7 +115,6 @@ n [A-Za-z0-9_-]
. warn_ignored_character(*yytext);
\n {
BEGIN(INITIAL);
current_file->lineno++;
return T_EOL;
}
}
@ -138,7 +136,7 @@ n [A-Za-z0-9_-]
new_string();
BEGIN(STRING);
}
\n BEGIN(INITIAL); current_file->lineno++; return T_EOL;
\n BEGIN(INITIAL); return T_EOL;
({n}|[/.])+ {
const struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
if (id && id->flags & TF_PARAM) {
@ -150,7 +148,7 @@ n [A-Za-z0-9_-]
return T_WORD;
}
#.* /* comment */
\\\n current_file->lineno++;
\\\n ;
[[:blank:]]+
. warn_ignored_character(*yytext);
<<EOF>> {
@ -187,7 +185,6 @@ n [A-Za-z0-9_-]
fprintf(stderr,
"%s:%d:warning: multi-line strings not supported\n",
zconf_curname(), zconf_lineno());
current_file->lineno++;
BEGIN(INITIAL);
return T_EOL;
}
@ -220,12 +217,10 @@ n [A-Za-z0-9_-]
}
}
[ \t]*\n/[^ \t\n] {
current_file->lineno++;
zconf_endhelp();
return T_HELPTEXT;
}
[ \t]*\n {
current_file->lineno++;
append_string("\n", 1);
}
[^ \t\n].* {
@ -304,7 +299,7 @@ void zconf_initscan(const char *name)
memset(current_buf, 0, sizeof(*current_buf));
current_file = file_lookup(name);
current_file->lineno = 1;
yylineno = 1;
}
void zconf_nextfile(const char *name)
@ -325,24 +320,26 @@ void zconf_nextfile(const char *name)
buf->parent = current_buf;
current_buf = buf;
for (iter = current_file->parent; iter; iter = iter->parent ) {
if (!strcmp(current_file->name,iter->name) ) {
current_file->lineno = yylineno;
file->parent = current_file;
for (iter = current_file; iter; iter = iter->parent) {
if (!strcmp(iter->name, file->name)) {
fprintf(stderr,
"%s:%d: recursive inclusion detected. "
"Inclusion path:\n current file : '%s'\n",
zconf_curname(), zconf_lineno(),
zconf_curname());
iter = current_file;
"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",
fprintf(stderr, " included from: %s:%d\n",
iter->name, iter->lineno - 1);
} while (strcmp(iter->name, current_file->name));
} while (strcmp(iter->name, file->name));
exit(1);
}
}
file->lineno = 1;
file->parent = current_file;
yylineno = 1;
current_file = file;
}
@ -351,6 +348,8 @@ 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) {