Let kconfig exit with error on duplicated Kconfig file inclusion. Repeated inclusion of Kbuild files are considered bad-practise with regard to maintenance; and Kconfig language is rich enough that there should be no need for that. If repeated inclusion of Kconfig files is detected, error out with messages like: Kconfig.inc1:4: error: repeated inclusion of Kconfig.inc3 Kconfig.inc2:3: note: location of first inclusion of Kconfig.inc3 While commit f094f8a1b273 ("kconfig: allow multiple inclusion of the same file") introduced detection of recursive inclusions of Kconfig files, it explicitly allowed repeated inclusions, unfortunately w/o reasoning.
Unified · Split
| @@ -402,7 +402,7 @@ void zconf_initscan(const char *name) · 401 unmodified lines | |||
| 402 | exit(1); | 402 | exit(1); |
| 403 | } | 403 | } |
| 404 | 404 | ||
| 405 | cur_filename = file_lookup(name); | 405 | cur_filename = file_lookup(name, NULL, 0); |
| 406 | yylineno = 1; | 406 | yylineno = 1; |
| 407 | } | 407 | } |
| 408 | 408 | ||
| @@ -443,7 +443,7 @@ void zconf_nextfile(const char *name) · 34 unmodified lines | |||
| 443 | } | 443 | } |
| 444 | 444 | ||
| 445 | yylineno = 1; | 445 | yylineno = 1; |
| 446 | cur_filename = file_lookup(name); | 446 | cur_filename = file_lookup(name, cur_filename, cur_lineno); |
| 447 | } | 447 | } |
| 448 | 448 | ||
| 449 | static void zconf_endfile(void) | 449 | static void zconf_endfile(void) |
| @@ -51,7 +51,8 @@ static inline void xfwrite(const void *str, size_t len, size_t count, FILE *out) · 50 unmodified lines | |||
| 51 | } | 51 | } |
| 52 | 52 | ||
| 53 | /* util.c */ | 53 | /* util.c */ |
| 54 | const char *file_lookup(const char *name); | 54 | const char *file_lookup(const char *name, |
| 55 | const char *parent_name, int parent_lineno); | ||
| 55 | 56 | ||
| 56 | /* lexer.l */ | 57 | /* lexer.l */ |
| 57 | int yylex(void); | 58 | int yylex(void); |
| @@ -0,0 +1,3 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0-only | ||
| 2 | |||
| 3 | source "Kconfig.inc1" | ||
| @@ -0,0 +1,4 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0-only | ||
| 2 | |||
| 3 | source "Kconfig.inc2" | ||
| 4 | source "Kconfig.inc3" | ||
| @@ -0,0 +1,3 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0-only | ||
| 2 | |||
| 3 | source "Kconfig.inc3" | ||
| @@ -0,0 +1 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0-only | ||
| @@ -0,0 +1,10 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0 | ||
| 2 | """ | ||
| 3 | Detect repeated inclusion error. | ||
| 4 | |||
| 5 | If repeated inclusion is detected, it should fail with error message. | ||
| 6 | """ | ||
| 7 | |||
| 8 | def test(conf): | ||
| 9 | assert conf.oldaskconfig() != 0 | ||
| 10 | assert conf.stderr_contains('expected_stderr') | ||
| @@ -0,0 +1,2 @@ | |||
| 1 | Kconfig.inc1:4: error: Repeated inclusion of Kconfig.inc3 | ||
| 2 | Kconfig.inc2:3: note: Location of first inclusion of Kconfig.inc3 | ||
| @@ -18,25 +18,50 @@ static HASHTABLE_DEFINE(file_hashtable, 1U << 11); · 17 unmodified lines | |||
| 18 | 18 | ||
| 19 | struct file { | 19 | struct file { |
| 20 | struct hlist_node node; | 20 | struct hlist_node node; |
| 21 | struct { | ||
| 22 | const char *name; | ||
| 23 | int lineno; | ||
| 24 | } parent; | ||
| 21 | char name[]; | 25 | char name[]; |
| 22 | }; | 26 | }; |
| 23 | 27 | ||
| 28 | static void die_duplicated_include(struct file *file, | ||
| 29 | const char *parent, int lineno) | ||
| 30 | { | ||
| 31 | fprintf(stderr, | ||
| 32 | "%s:%d: error: repeated inclusion of %s\n" | ||
| 33 | "%s:%d: note: location of first inclusion of %s\n", | ||
| 34 | parent, lineno, file->name, | ||
| 35 | file->parent.name, file->parent.lineno, file->name); | ||
| 36 | exit(1); | ||
| 37 | } | ||
| 38 | |||
| 24 | /* file already present in list? If not add it */ | 39 | /* file already present in list? If not add it */ |
| 25 | const char *file_lookup(const char *name) | 40 | const char *file_lookup(const char *name, |
| 41 | const char *parent_name, int parent_lineno) | ||
| 26 | { | 42 | { |
| 43 | const char *parent = NULL; | ||
| 27 | struct file *file; | 44 | struct file *file; |
| 28 | size_t len; | 45 | size_t len; |
| 29 | int hash = hash_str(name); | 46 | int hash = hash_str(name); |
| 30 | 47 | ||
| 48 | if (parent_name) | ||
| 49 | parent = file_lookup(parent_name, NULL, 0); | ||
| 50 | |||
| 31 | hash_for_each_possible(file_hashtable, file, node, hash) | 51 | hash_for_each_possible(file_hashtable, file, node, hash) |
| 32 | if (!strcmp(name, file->name)) | 52 | if (!strcmp(name, file->name)) { |
| 33 | return file->name; | 53 | if (!parent_name) |
| 54 | return file->name; | ||
| 55 | die_duplicated_include(file, parent, parent_lineno); | ||
| 56 | } | ||
| 34 | 57 | ||
| 35 | len = strlen(name); | 58 | len = strlen(name); |
| 36 | file = xmalloc(sizeof(*file) + len + 1); | 59 | file = xmalloc(sizeof(*file) + len + 1); |
| 37 | memset(file, 0, sizeof(*file)); | 60 | memset(file, 0, sizeof(*file)); |
| 38 | memcpy(file->name, name, len); | 61 | memcpy(file->name, name, len); |
| 39 | file->name[len] = '\0'; | 62 | file->name[len] = '\0'; |
| 63 | file->parent.name = parent; | ||
| 64 | file->parent.lineno = parent_lineno; | ||
| 40 | 65 | ||
| 41 | hash_add(file_hashtable, &file->node, hash); | 66 | hash_add(file_hashtable, &file->node, hash); |
| 42 | 67 | ||