Kconfig updates for v4.16

A pretty big batch of Kconfig updates. I have to mention the lexer
 and parser of Kconfig are now built from real .l and .y sources.
 So, flex and bison are the requirement for building the kernel.
 Both of them (unlike gperf) have been stable for a long time. This
 change has been tested several weeks in linux-next, and I did not
 receive any problem report about this.
 
 Summary:
 
 - Add checks for mistakes, like the choice default is not in
   choice, help is doubled
 
 - Document data structure and complex code
 
 - Fix various memory leaks
 
 - Change Makefile to build lexer and parser instead of using
   pre-generated C files
 
 - Drop 'boolean' keyword, which is equivalent to 'bool'
 
 - Use default 'yy' prefix and remove unneeded Make variables
 
 - Fix gettext() check for xconfig
 
 - Announce that oldnoconfig will be finally removed
 
 - Make 'Selected by:' and 'Implied by' readable in help and
   search result
 
 - Hide silentoldconfig from 'make help' to stop confusing people
 
 - Fix misc things and cleanups
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQIcBAABAgAGBQJac0O7AAoJED2LAQed4NsGxRQQAKiDkBmJUKzJykEr3BhEsCW1
 1cKwsaCFSKQJZde+Edn14gqBQY3qvQVaWfnQpoBC69IOlMlVQyKqqdtjIUxmGTem
 +age94JvgPT3oj7ELigUsL5bFL8CEZYpjwAVkO+Zd+7jPxlM4glNl9F3coTp9ZAl
 kaFxnch8qPT3fb6xYSwTpkk28RFNfT8ixwImj0CH6wlwxI635o9wpqAmHCMD5Yid
 wBlEB0I0aw9xVx/D2FAh1ZJ+fyOtPLotRTtUQ1kdlDyk98V6EJRfyh1XWF0xE/gH
 WR7MAuBNXC6Uu1KqXLTJRWWE4NjBmW8e7OLTaoFQFXdnz/Rgd6gbPXuiiyKR6PUc
 mA3h6F8uPDpoRpqOrn6pdu269n1ObuZuC1XZ3MVSXtW3OzLbUk/2GpHPVX8mrep5
 SBGsfq4JYtQkgz9/wBrWpdAjl2QbtPJbM/izCbEWk7pod18dVnyHpo3i3YjsaSQf
 piDK5JGKsHEisAzp6Onhc9EPeBLAjG236+LvBruaqjJNySXyT0S2kOwV0AMOD1yC
 ave8ZQA0QxP7sV/s5DXGkFx5Nt/1LE8JWvcRN0+juavnkUklWfFfnk7epAnFfRPi
 HCGfeQSzIQxQ+JV7/vlJ95FWvLZz+KzQ49X5aoYCVcEiFf2MV7RkDHSp5mPE4DnO
 5JeHnTBpuvw4mnrZ6UNj
 =rsi/
 -----END PGP SIGNATURE-----

Merge tag 'kconfig-v4.16' of git://git.kernel.org/pub/scm/linux/kernel/git/masahiroy/linux-kbuild

Pull Kconfig updates from Masahiro Yamada:
 "A pretty big batch of Kconfig updates.

  I have to mention the lexer and parser of Kconfig are now built from
  real .l and .y sources. So, flex and bison are the requirement for
  building the kernel. Both of them (unlike gperf) have been stable for
  a long time. This change has been tested several weeks in linux-next,
  and I did not receive any problem report about this.

  Summary:

   - add checks for mistakes, like the choice default is not in choice,
     help is doubled

   - document data structure and complex code

   - fix various memory leaks

   - change Makefile to build lexer and parser instead of using
     pre-generated C files

   - drop 'boolean' keyword, which is equivalent to 'bool'

   - use default 'yy' prefix and remove unneeded Make variables

   - fix gettext() check for xconfig

   - announce that oldnoconfig will be finally removed

   - make 'Selected by:' and 'Implied by' readable in help and search
     result

   - hide silentoldconfig from 'make help' to stop confusing people

   - fix misc things and cleanups"

* tag 'kconfig-v4.16' of git://git.kernel.org/pub/scm/linux/kernel/git/masahiroy/linux-kbuild: (37 commits)
  kconfig: Remove silentoldconfig from help and docs; fix kconfig/conf's help
  kconfig: make "Selected by:" and "Implied by:" readable
  kconfig: announce removal of oldnoconfig if used
  kconfig: fix make xconfig when gettext is missing
  kconfig: Clarify menu and 'if' dependency propagation
  kconfig: Document 'if' flattening logic
  kconfig: Clarify choice dependency propagation
  kconfig: Document SYMBOL_OPTIONAL logic
  kbuild: remove unnecessary LEX_PREFIX and YACC_PREFIX
  kconfig: use default 'yy' prefix for lexer and parser
  kconfig: make conf_unsaved a local variable of conf_read()
  kconfig: make xfgets() really static
  kconfig: make input_mode static
  kconfig: Warn if there is more than one help text
  kconfig: drop 'boolean' keyword
  kconfig: use bool instead of boolean for type definition attributes, again
  kconfig: Remove menu_end_entry()
  kconfig: Document important expression functions
  kconfig: Document automatic submenu creation code
  kconfig: Fix choice symbol expression leak
  ...
This commit is contained in:
Linus Torvalds 2018-02-01 11:45:49 -08:00
commit 562f36ed28
20 changed files with 548 additions and 5065 deletions

View file

@ -113,7 +113,7 @@ void expr_free(struct expr *e)
break;
case E_NOT:
expr_free(e->left.expr);
return;
break;
case E_EQUAL:
case E_GEQ:
case E_GTH:
@ -138,8 +138,18 @@ static int trans_count;
#define e1 (*ep1)
#define e2 (*ep2)
/*
* expr_eliminate_eq() helper.
*
* Walks the two expression trees given in 'ep1' and 'ep2'. Any node that does
* not have type 'type' (E_OR/E_AND) is considered a leaf, and is compared
* against all other leaves. Two equal leaves are both replaced with either 'y'
* or 'n' as appropriate for 'type', to be eliminated later.
*/
static void __expr_eliminate_eq(enum expr_type type, struct expr **ep1, struct expr **ep2)
{
/* Recurse down to leaves */
if (e1->type == type) {
__expr_eliminate_eq(type, &e1->left.expr, &e2);
__expr_eliminate_eq(type, &e1->right.expr, &e2);
@ -150,12 +160,18 @@ static void __expr_eliminate_eq(enum expr_type type, struct expr **ep1, struct e
__expr_eliminate_eq(type, &e1, &e2->right.expr);
return;
}
/* e1 and e2 are leaves. Compare them. */
if (e1->type == E_SYMBOL && e2->type == E_SYMBOL &&
e1->left.sym == e2->left.sym &&
(e1->left.sym == &symbol_yes || e1->left.sym == &symbol_no))
return;
if (!expr_eq(e1, e2))
return;
/* e1 and e2 are equal leaves. Prepare them for elimination. */
trans_count++;
expr_free(e1); expr_free(e2);
switch (type) {
@ -172,6 +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)
{
if (!e1 || !e2)
@ -197,6 +242,12 @@ void expr_eliminate_eq(struct expr **ep1, struct expr **ep2)
#undef e1
#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)
{
int res, old_count;
@ -243,6 +294,17 @@ static int expr_eq(struct expr *e1, struct expr *e2)
return 0;
}
/*
* Recursively performs the following simplifications in-place (as well as the
* corresponding simplifications with swapped operands):
*
* expr && n -> n
* expr && y -> expr
* expr || n -> expr
* expr || y -> y
*
* Returns the optimized expression.
*/
static struct expr *expr_eliminate_yn(struct expr *e)
{
struct expr *tmp;
@ -516,12 +578,21 @@ static struct expr *expr_join_and(struct expr *e1, struct expr *e2)
return NULL;
}
/*
* expr_eliminate_dups() helper.
*
* Walks the two expression trees given in 'ep1' and 'ep2'. Any node that does
* not have type 'type' (E_OR/E_AND) is considered a leaf, and is compared
* against all other leaves to look for simplifications.
*/
static void expr_eliminate_dups1(enum expr_type type, struct expr **ep1, struct expr **ep2)
{
#define e1 (*ep1)
#define e2 (*ep2)
struct expr *tmp;
/* Recurse down to leaves */
if (e1->type == type) {
expr_eliminate_dups1(type, &e1->left.expr, &e2);
expr_eliminate_dups1(type, &e1->right.expr, &e2);
@ -532,6 +603,9 @@ static void expr_eliminate_dups1(enum expr_type type, struct expr **ep1, struct
expr_eliminate_dups1(type, &e1, &e2->right.expr);
return;
}
/* e1 and e2 are leaves. Compare and process them. */
if (e1 == e2)
return;
@ -568,6 +642,17 @@ static void expr_eliminate_dups1(enum expr_type type, struct expr **ep1, struct
#undef e2
}
/*
* Rewrites 'e' in-place to remove ("join") duplicate and other redundant
* operands.
*
* Example simplifications:
*
* A || B || A -> A || B
* A && B && A=y -> A=y && B
*
* Returns the deduplicated expression.
*/
struct expr *expr_eliminate_dups(struct expr *e)
{
int oldcount;
@ -584,6 +669,7 @@ struct expr *expr_eliminate_dups(struct expr *e)
;
}
if (!trans_count)
/* No simplifications done in this pass. We're done */
break;
e = expr_eliminate_yn(e);
}
@ -591,6 +677,12 @@ struct expr *expr_eliminate_dups(struct expr *e)
return e;
}
/*
* Performs various simplifications involving logical operators and
* comparisons.
*
* Allocates and returns a new expression.
*/
struct expr *expr_transform(struct expr *e)
{
struct expr *tmp;
@ -805,6 +897,20 @@ bool expr_depends_symbol(struct expr *dep, struct symbol *sym)
return false;
}
/*
* Inserts explicit comparisons of type 'type' to symbol 'sym' into the
* expression 'e'.
*
* Examples transformations for type == E_UNEQUAL, sym == &symbol_no:
*
* A -> A!=n
* !A -> A=n
* A && B -> !(A=n || B=n)
* A || B -> !(A=n && B=n)
* A && (B || C) -> !(A=n || (B=n && C=n))
*
* Allocates and returns a new expression.
*/
struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym)
{
struct expr *e1, *e2;
@ -1073,7 +1179,7 @@ struct expr *expr_simplify_unmet_dep(struct expr *e1, struct expr *e2)
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) {
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);
break;
case E_OR:
expr_print(e->left.expr, fn, data, E_OR);
fn(data, NULL, " || ");
expr_print(e->right.expr, fn, data, 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);
break;
case 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, ")");
}
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);
@ -1207,3 +1323,13 @@ void expr_gstr_print(struct expr *e, struct gstr *gs)
{
expr_print(e, expr_print_gstr_helper, gs, E_NONE);
}
/*
* Transform the top level "||" tokens into newlines and prepend each
* line with a minus. This makes expressions much easier to read.
* Suitable for reverse dependency expressions.
*/
void expr_gstr_print_revdep(struct expr *e, struct gstr *gs)
{
__expr_print(e, expr_print_gstr_helper, gs, E_NONE, true);
}