From 805fb9e1e028140d266e7ca5036bea9292545708 Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Thu, 10 Dec 2020 21:04:53 +1300 Subject: configure.ac: Silence make output when building ct-ng Set AM_SILENT_RULES([yes]) to reduce the verbosity from make by default. Signed-off-by: Chris Packham diff --git a/configure.ac b/configure.ac index 8151737..c4964df 100644 --- a/configure.ac +++ b/configure.ac @@ -18,6 +18,7 @@ AC_CONFIG_MACRO_DIR([m4]) # - Object files are generated in a subdirectory (new default in automake) # - Request new tar format (old, tar-v7, breaks on long paths we have) AM_INIT_AUTOMAKE([-Wall -Werror foreign no-dist-gzip dist-xz dist-bzip2 subdir-objects tar-pax]) +AM_SILENT_RULES([yes]) # To avoid stubbing autotools with missing script AM_MAINTAINER_MODE([enable]) -- cgit v0.10.2-6-g49f6 From 2340fa29125291b1db770616fcdc96a8ac1d103e Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Mon, 14 Dec 2020 21:44:00 +1300 Subject: Don't generate empty help Kconfig now complains when we have a help section with no text. If there is nothing in @@help@@ don't output a `help` section. Signed-off-by: Chris Packham diff --git a/maintainer/kconfig-choice.template b/maintainer/kconfig-choice.template index bd0c474..6f03707 100644 --- a/maintainer/kconfig-choice.template +++ b/maintainer/kconfig-choice.template @@ -11,7 +11,9 @@ config @@dir|@@_@@choice|@@ #!foreach dependency @@depline@@ #!end-foreach +#!if [ -n "@@*help@@" ] help +#!end-if #!foreach help @@helpline@@ #!end-foreach diff --git a/maintainer/kconfig-menu.template b/maintainer/kconfig-menu.template index 4892435..1f5e7b2 100644 --- a/maintainer/kconfig-menu.template +++ b/maintainer/kconfig-menu.template @@ -8,7 +8,9 @@ menuconfig @@dir|@@_@@choice|@@ #!foreach dependency @@depline@@ #!end-foreach +#!if [ -n "@@*help@@" ] help +#!end-if #!foreach help @@helpline@@ #!end-foreach -- cgit v0.10.2-6-g49f6 From 51cb8939f830584b5b0db4f018dfa73e311308f6 Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Tue, 2 Feb 2021 20:01:38 +1300 Subject: config/cc/gcc.in: Fix typo CC_GCC_DEC_FLOAT -> CC_GCC_DEC_FLOATS This has gone unnoticed for a while, it looks like all configurations have probably been using the default floats behaviour. Newer kconfig tells us the default value is not in the choice so lets fix this in preparation. Signed-off-by: Chris Packham diff --git a/config/cc/gcc.in b/config/cc/gcc.in index 9d9b692..21e7db0 100644 --- a/config/cc/gcc.in +++ b/config/cc/gcc.in @@ -382,7 +382,7 @@ choice CC_GCC_DEC_FLOATS_CHOICE The default is to let ./configure decide. -config CC_GCC_DEC_FLOAT_AUTO +config CC_GCC_DEC_FLOATS_AUTO bool "auto" help Let ./configure decide. If you say 'y' here, gcc will default to: @@ -390,12 +390,12 @@ config CC_GCC_DEC_FLOAT_AUTO - 'dpd' for powerpc - 'no' for the other architectures -config CC_GCC_DEC_FLOAT_BID +config CC_GCC_DEC_FLOATS_BID bool "bid" help Use the 'binary integer decimal' format for decimal floats. -config CC_GCC_DEC_FLOAT_DPD +config CC_GCC_DEC_FLOATS_DPD bool "dpd" help Use the 'densely packed decimal' for decimal floats. -- cgit v0.10.2-6-g49f6 From 07ae8dd48dfb19a7b89bc4c208bc5778c79ce446 Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Thu, 10 Dec 2020 20:33:11 +1300 Subject: 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 diff --git a/kconfig/.gitignore b/kconfig/.gitignore index 69967bc..0c8d3a2 100644 --- a/kconfig/.gitignore +++ b/kconfig/.gitignore @@ -1,9 +1,15 @@ -conf -?conf -*.o +# +# Generated files +# +*.lex.c +*.tab.c +*.tab.h .deps -zconf.c -zconf.lex.c -*.exe Makefile -.dirstamp + +# +# configuration programs +# +conf +mconf +nconf diff --git a/kconfig/check.sh b/kconfig/check.sh old mode 100644 new mode 100755 diff --git a/kconfig/conf.c b/kconfig/conf.c index df87eb4..55e4f7c 100644 --- a/kconfig/conf.c +++ b/kconfig/conf.c @@ -20,7 +20,6 @@ static void conf(struct menu *menu); static void check_conf(struct menu *menu); -static void xfgets(char *str, int size, FILE *in); enum input_mode { oldaskconfig, @@ -35,11 +34,11 @@ enum input_mode { savedefconfig, listnewconfig, olddefconfig, -} input_mode = oldaskconfig; +}; +static enum input_mode input_mode = oldaskconfig; static int indent = 1; static int tty_stdio; -static int valid_stdin = 1; static int sync_kconfig; static int conf_cnt; static char line[PATH_MAX]; @@ -72,14 +71,14 @@ static void strip(char *str) *p-- = 0; } -static void check_stdin(void) +/* Helper function to facilitate fgets() by Jean Sacren. */ +static void xfgets(char *str, int size, FILE *in) { - if (!valid_stdin) { - /* For crosstool-NG, we don't care if stdin/stdout got redirected. - * In this case, just printf a cariage return, for pretty output. - */ - printf("\n"); - } + if (!fgets(str, size, in)) + fprintf(stderr, "\nError in reading or end of file.\n"); + + if (!tty_stdio) + printf("%s", str); } static int conf_askvalue(struct symbol *sym, const char *def) @@ -106,13 +105,10 @@ static int conf_askvalue(struct symbol *sym, const char *def) printf("%s\n", def); return 0; } - check_stdin(); /* fall through */ case oldaskconfig: fflush(stdout); xfgets(line, sizeof(line), stdin); - if (!tty_stdio) - printf("\n"); return 1; default: break; @@ -192,9 +188,7 @@ static int conf_sym(struct menu *menu) printf("/m"); if (oldval != yes && sym_tristate_within_range(sym, yes)) printf("/y"); - if (menu_has_help(menu)) - printf("/?"); - printf("] "); + printf("/?] "); if (!conf_askvalue(sym, sym_get_string_value(sym))) return 0; strip(line); @@ -296,10 +290,7 @@ static int conf_choice(struct menu *menu) printf("[1]: 1\n"); goto conf_childs; } - printf("[1-%d", cnt); - if (menu_has_help(menu)) - printf("?"); - printf("]: "); + printf("[1-%d?]: ", cnt); switch (input_mode) { case oldconfig: case silentoldconfig: @@ -308,7 +299,6 @@ static int conf_choice(struct menu *menu) printf("%d\n", cnt); break; } - check_stdin(); /* fall through */ case oldaskconfig: fflush(stdout); @@ -480,7 +470,7 @@ int main(int ac, char **av) bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); - tty_stdio = isatty(0) && isatty(1) && isatty(2); + tty_stdio = isatty(0) && isatty(1); while ((opt = getopt_long(ac, av, "s", long_opts, NULL)) != -1) { if (opt == 's') { @@ -537,7 +527,7 @@ int main(int ac, char **av) } } 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")); exit(1); } @@ -562,9 +552,11 @@ int main(int ac, char **av) if (!defconfig_file) defconfig_file = conf_get_default_confname(); if (conf_read(defconfig_file)) { - printf(_("***\n" - "*** Can't find default configuration \"%s\"!\n" - "***\n"), defconfig_file); + fprintf(stderr, + _("***\n" + "*** Can't find default configuration \"%s\"!\n" + "***\n"), + defconfig_file); exit(1); } break; @@ -622,7 +614,6 @@ int main(int ac, char **av) return 1; } } - valid_stdin = tty_stdio; } switch (input_mode) { @@ -693,12 +684,3 @@ int main(int ac, char **av) } 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"); -} diff --git a/kconfig/confdata.c b/kconfig/confdata.c index 297b079..df26c7b 100644 --- a/kconfig/confdata.c +++ b/kconfig/confdata.c @@ -28,7 +28,7 @@ static void conf_message(const char *fmt, ...) __attribute__ ((format (printf, 1, 2))); static const char *conf_filename; -static int conf_lineno, conf_warnings, conf_unsaved; +static int conf_lineno, conf_warnings; 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: done: if (sym_string_valid(sym, p)) { - sym->def[def].val = strdup(p); + sym->def[def].val = xstrdup(p); sym->flags |= def_flags; } else { if (def != S_DEF_AUTO) @@ -201,7 +201,7 @@ static int add_byte(int c, char **lineptr, size_t slen, size_t *n) if (new_size > *n) { new_size += LINE_GROWTH - 1; new_size *= 2; - nline = realloc(*lineptr, new_size); + nline = xrealloc(*lineptr, new_size); if (!nline) return -1; @@ -290,7 +290,6 @@ load: conf_filename = name; conf_lineno = 0; conf_warnings = 0; - conf_unsaved = 0; def_flags = SYMBOL_DEF << def; for_all_symbols(i, sym) { @@ -409,6 +408,7 @@ setsym: int conf_read(const char *name) { struct symbol *sym; + int conf_unsaved = 0; int i; 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) { struct symbol *sym, *csym; - int i, cnt, pby, pty, ptm; /* pby: probability of boolean = y + int i, cnt, pby, pty, ptm; /* pby: probability of bool = y * pty: probability of tristate = y * ptm: probability of tristate = m */ diff --git a/kconfig/expr.c b/kconfig/expr.c index 8cee597..d453819 100644 --- a/kconfig/expr.c +++ b/kconfig/expr.c @@ -94,7 +94,7 @@ struct expr *expr_copy(const struct expr *org) e->right.expr = expr_copy(org->right.expr); break; default: - printf("can't copy type %d\n", e->type); + fprintf(stderr, "can't copy type %d\n", e->type); free(e); e = NULL; break; @@ -113,7 +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: @@ -127,7 +127,7 @@ void expr_free(struct expr *e) expr_free(e->right.expr); break; default: - printf("how to free type %d?\n", e->type); + fprintf(stderr, "how to free type %d?\n", e->type); break; } free(e); @@ -138,8 +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); +} diff --git a/kconfig/expr.h b/kconfig/expr.h index a73f762..c16e82e 100644 --- a/kconfig/expr.h +++ b/kconfig/expr.h @@ -74,17 +74,60 @@ enum { S_DEF_COUNT }; +/* + * Represents a configuration symbol. + * + * Choices are represented as a special kind of symbol and have the + * SYMBOL_CHOICE bit set in 'flags'. + */ struct symbol { + /* The next symbol in the same bucket in the symbol hash table */ struct symbol *next; + + /* The name of the symbol, e.g. "FOO" for 'config FOO' */ char *name; + + /* S_BOOLEAN, S_TRISTATE, ... */ enum symbol_type type; + + /* + * The calculated value of the symbol. The SYMBOL_VALID bit is set in + * 'flags' when this is up to date. Note that this value might differ + * from the user value set in e.g. a .config file, due to visibility. + */ struct symbol_value curr; + + /* + * Values for the symbol provided from outside. def[S_DEF_USER] holds + * the .config value. + */ struct symbol_value def[S_DEF_COUNT]; + + /* + * An upper bound on the tristate value the user can set for the symbol + * if it is a boolean or tristate. Calculated from prompt dependencies, + * which also inherit dependencies from enclosing menus, choices, and + * ifs. If 'n', the user value will be ignored. + * + * Symbols lacking prompts always have visibility 'n'. + */ tristate visible; + + /* SYMBOL_* flags */ int flags; + + /* List of properties. See prop_type. */ struct property *prop; + + /* Dependencies from enclosing menus, choices, and ifs */ struct expr_value dir_dep; + + /* Reverse dependencies through being selected by other symbols */ struct expr_value rev_dep; + + /* + * "Weak" reverse dependencies through being implied by other symbols + */ struct expr_value implied; }; @@ -133,7 +176,7 @@ enum prop_type { P_UNKNOWN, P_PROMPT, /* prompt "foo prompt" or "BAZ Value" */ P_COMMENT, /* text associated with a comment */ - P_MENU, /* prompt associated with a menuconfig option */ + P_MENU, /* prompt associated with a menu or menuconfig symbol */ P_DEFAULT, /* default y */ P_CHOICE, /* choice value */ P_SELECT, /* select BAR */ @@ -166,22 +209,67 @@ struct property { for (st = sym->prop; st; st = st->next) \ if (st->text) +/* + * Represents a node in the menu tree, as seen in e.g. menuconfig (though used + * for all front ends). Each symbol, menu, etc. defined in the Kconfig files + * gets a node. A symbol defined in multiple locations gets one node at each + * location. + */ struct menu { + /* The next menu node at the same level */ struct menu *next; + + /* The parent menu node, corresponding to e.g. a menu or choice */ struct menu *parent; + + /* The first child menu node, for e.g. menus and choices */ struct menu *list; + + /* + * The symbol associated with the menu node. Choices are implemented as + * a special kind of symbol. NULL for menus, comments, and ifs. + */ struct symbol *sym; + + /* + * The prompt associated with the node. This holds the prompt for a + * symbol as well as the text for a menu or comment, along with the + * type (P_PROMPT, P_MENU, etc.) + */ struct property *prompt; + + /* + * 'visible if' dependencies. If more than one is given, they will be + * ANDed together. + */ struct expr *visibility; + + /* + * Ordinary dependencies from e.g. 'depends on' and 'if', ANDed + * together + */ struct expr *dep; + + /* MENU_* flags */ unsigned int flags; + + /* Any help text associated with the node */ char *help; + + /* The location where the menu node appears in the Kconfig files */ struct file *file; int lineno; + + /* For use by front ends that need to store auxiliary data */ void *data; }; +/* + * Set on a menu node when the corresponding symbol changes state in some way. + * Can be checked by front ends. + */ #define MENU_CHANGED 0x0001 + #define MENU_ROOT 0x0002 struct jump_key { @@ -222,6 +310,7 @@ 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); static inline int expr_is_yes(struct expr *e) { diff --git a/kconfig/kconf_id.c b/kconfig/kconf_id.c index 5abbc72..3ea9c5f 100644 --- a/kconfig/kconf_id.c +++ b/kconfig/kconf_id.c @@ -20,7 +20,6 @@ static struct kconf_id kconf_id_array[] = { { "tristate", T_TYPE, TF_COMMAND, S_TRISTATE }, { "def_tristate", T_DEFAULT, TF_COMMAND, S_TRISTATE }, { "bool", T_TYPE, TF_COMMAND, S_BOOLEAN }, - { "boolean", T_TYPE, TF_COMMAND, S_BOOLEAN }, { "def_bool", T_DEFAULT, TF_COMMAND, S_BOOLEAN }, { "int", T_TYPE, TF_COMMAND, S_INT }, { "hex", T_TYPE, TF_COMMAND, S_HEX }, diff --git a/kconfig/lkc.h b/kconfig/lkc.h index cdcbe43..2d5ec2d 100644 --- a/kconfig/lkc.h +++ b/kconfig/lkc.h @@ -100,7 +100,6 @@ void menu_warn(struct menu *menu, const char *fmt, ...); struct menu *menu_add_menu(void); void menu_end_menu(void); void menu_add_entry(struct symbol *sym); -void menu_end_entry(void); void menu_add_dep(struct expr *dep); void menu_add_visibility(struct expr *dep); struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep); @@ -115,6 +114,8 @@ struct file *file_lookup(const char *name); int file_write_dep(const char *name); void *xmalloc(size_t size); void *xcalloc(size_t nmemb, size_t size); +void *xrealloc(void *p, size_t size); +char *xstrdup(const char *s); struct gstr { size_t len; diff --git a/kconfig/lkc_proto.h b/kconfig/lkc_proto.h index 5d86e2d..9dc8abf 100644 --- a/kconfig/lkc_proto.h +++ b/kconfig/lkc_proto.h @@ -31,7 +31,7 @@ extern struct symbol * symbol_hash[SYMBOL_HASHSIZE]; struct symbol * sym_lookup(const char *name, int flags); struct symbol * sym_find(const char *name); -const char * sym_expand_string_value(const char *in); +char *sym_expand_string_value(const char *in); const char * sym_escape_string_value(const char *in); struct symbol ** sym_re_search(const char *pattern); const char * sym_type_name(enum symbol_type type); diff --git a/kconfig/lxdialog/check-lxdialog.sh b/kconfig/lxdialog/check-lxdialog.sh old mode 100644 new mode 100755 index a10bd9d..6c0bcd9 --- a/kconfig/lxdialog/check-lxdialog.sh +++ b/kconfig/lxdialog/check-lxdialog.sh @@ -55,7 +55,8 @@ EOF echo " *** required header files." 1>&2 echo " *** 'make menuconfig' requires the ncurses libraries." 1>&2 echo " *** " 1>&2 - echo " *** Install ncurses (ncurses-devel) and try again." 1>&2 + echo " *** Install ncurses (ncurses-devel or libncurses-dev " 1>&2 + echo " *** depending on your distribution) and try again." 1>&2 echo " *** " 1>&2 exit 1 fi diff --git a/kconfig/mconf.c b/kconfig/mconf.c index dc7421c..ea50ba0 100644 --- a/kconfig/mconf.c +++ b/kconfig/mconf.c @@ -246,7 +246,7 @@ search_help[] = N_( " Selected by: BAR [=n]\n" "-----------------------------------------------------------------\n" "o The line 'Type:' shows the type of the configuration option for\n" - " this symbol (boolean, tristate, string, ...)\n" + " this symbol (bool, tristate, string, ...)\n" "o The line 'Prompt:' shows the text used in the menu structure for\n" " this symbol\n" "o The 'Defined at' line tells at what file / line number the symbol\n" diff --git a/kconfig/menu.c b/kconfig/menu.c index 1fd7b25..d5a3322 100644 --- a/kconfig/menu.c +++ b/kconfig/menu.c @@ -62,13 +62,8 @@ void menu_add_entry(struct symbol *sym) menu_add_symbol(P_SYMBOL, sym, NULL); } -void menu_end_entry(void) -{ -} - struct menu *menu_add_menu(void) { - menu_end_entry(); last_entry_ptr = ¤t_entry->list; return current_menu = current_entry; } @@ -79,19 +74,23 @@ void menu_end_menu(void) current_menu = current_menu->parent; } -static struct expr *menu_check_dep(struct expr *e) +/* + * Rewrites 'm' to 'm' && MODULES, so that it evaluates to 'n' when running + * without modules + */ +static struct expr *rewrite_m(struct expr *e) { if (!e) return e; switch (e->type) { case E_NOT: - e->left.expr = menu_check_dep(e->left.expr); + e->left.expr = rewrite_m(e->left.expr); break; case E_OR: case E_AND: - e->left.expr = menu_check_dep(e->left.expr); - e->right.expr = menu_check_dep(e->right.expr); + e->left.expr = rewrite_m(e->left.expr); + e->right.expr = rewrite_m(e->right.expr); break; case E_SYMBOL: /* change 'm' into 'm' && MODULES */ @@ -106,7 +105,7 @@ static struct expr *menu_check_dep(struct expr *e) void menu_add_dep(struct expr *dep) { - current_entry->dep = expr_alloc_and(current_entry->dep, menu_check_dep(dep)); + current_entry->dep = expr_alloc_and(current_entry->dep, dep); } void menu_set_type(int type) @@ -131,7 +130,7 @@ static struct property *menu_add_prop(enum prop_type type, char *prompt, struct prop->menu = current_entry; prop->expr = expr; - prop->visible.expr = menu_check_dep(dep); + prop->visible.expr = dep; if (prompt) { /* For crostool-NG, a leading pipe followed with spaces @@ -219,6 +218,7 @@ void menu_add_option(int token, char *arg) sym_defconfig_list = current_entry->sym; else if (sym_defconfig_list != current_entry->sym) zconf_error("trying to redefine defconfig symbol"); + sym_defconfig_list->flags |= SYMBOL_AUTO; break; case T_OPT_ENV: prop_add_env(arg); @@ -258,6 +258,16 @@ static void sym_check_prop(struct symbol *sym) "'%s': number is invalid", sym->name); } + if (sym_is_choice(sym)) { + struct property *choice_prop = + sym_get_choice_prop(sym2); + + if (!choice_prop || + prop_get_symbol(choice_prop) != sym) + prop_warn(prop, + "choice default symbol '%s' is not contained in the choice", + sym2->name); + } break; case P_SELECT: case P_IMPLY: @@ -266,13 +276,13 @@ static void sym_check_prop(struct symbol *sym) if (sym->type != S_BOOLEAN && sym->type != S_TRISTATE) prop_warn(prop, "config symbol '%s' uses %s, but is " - "not boolean or tristate", sym->name, use); + "not bool or tristate", sym->name, use); else if (sym2->type != S_UNKNOWN && sym2->type != S_BOOLEAN && sym2->type != S_TRISTATE) prop_warn(prop, "'%s' has wrong type. '%s' only " - "accept arguments of boolean and " + "accept arguments of bool and " "tristate type", sym2->name, use); break; case P_RANGE: @@ -298,6 +308,11 @@ void menu_finalize(struct menu *parent) sym = parent->sym; if (parent->list) { + /* + * This menu node has children. We (recursively) process them + * and propagate parent dependencies before moving on. + */ + if (sym && sym_is_choice(sym)) { if (sym->type == S_UNKNOWN) { /* find the first choice value to find out choice type */ @@ -315,30 +330,83 @@ void menu_finalize(struct menu *parent) if (menu->sym && menu->sym->type == S_UNKNOWN) 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); } else if (parent->prompt) + /* Menu node for 'menu' */ parentdep = parent->prompt->visible.expr; else + /* Menu node for 'if' */ parentdep = parent->dep; + /* For each child menu node... */ for (menu = parent->list; menu; menu = menu->next) { - basedep = expr_transform(menu->dep); + /* + * Propagate parent dependencies to the child menu + * node, also rewriting and simplifying expressions + */ + basedep = rewrite_m(menu->dep); + basedep = expr_transform(basedep); basedep = expr_alloc_and(expr_copy(parentdep), basedep); basedep = expr_eliminate_dups(basedep); menu->dep = basedep; + if (menu->sym) + /* + * Note: For symbols, all prompts are included + * too in the symbol's own property list + */ prop = menu->sym->prop; else + /* + * For non-symbol menu nodes, we just need to + * handle the prompt + */ prop = menu->prompt; + + /* For each property... */ for (; prop; prop = prop->next) { if (prop->menu != menu) + /* + * Two possibilities: + * + * 1. The property lacks dependencies + * and so isn't location-specific, + * e.g. an 'option' + * + * 2. The property belongs to a symbol + * defined in multiple locations and + * is from some other location. It + * will be handled there in that + * case. + * + * Skip the property. + */ continue; - dep = expr_transform(prop->visible.expr); + + /* + * Propagate parent dependencies to the + * property's condition, rewriting and + * simplifying expressions at the same time + */ + dep = rewrite_m(prop->visible.expr); + dep = expr_transform(dep); dep = expr_alloc_and(expr_copy(basedep), dep); dep = expr_eliminate_dups(dep); if (menu->sym && menu->sym->type != S_TRISTATE) dep = expr_trans_bool(dep); prop->visible.expr = dep; + + /* + * Handle selects and implies, which modify the + * dependencies of the selected/implied symbol + */ if (prop->type == P_SELECT) { struct symbol *es = prop_get_symbol(prop); es->rev_dep.expr = expr_alloc_or(es->rev_dep.expr, @@ -350,34 +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) menu_finalize(menu); } else if (sym) { + /* + * Automatic submenu creation. If sym is a symbol and A, B, C, + * ... are consecutive items (symbols, menus, ifs, etc.) that + * all depend on sym, then the following menu structure is + * created: + * + * sym + * +-A + * +-B + * +-C + * ... + * + * This also works recursively, giving the following structure + * if A is a symbol and B depends on A: + * + * sym + * +-A + * | +-B + * +-C + * ... + */ + basedep = parent->prompt ? parent->prompt->visible.expr : NULL; basedep = expr_trans_compare(basedep, E_UNEQUAL, &symbol_no); basedep = expr_eliminate_dups(expr_transform(basedep)); + + /* Examine consecutive elements after sym */ last_menu = NULL; for (menu = parent->next; menu; menu = menu->next) { dep = menu->prompt ? menu->prompt->visible.expr : menu->dep; if (!expr_contains_symbol(dep, sym)) + /* No dependency, quit */ break; if (expr_depends_symbol(dep, sym)) + /* Absolute dependency, put in submenu */ goto next; + + /* + * Also consider it a dependency on sym if our + * dependencies contain sym and are a "superset" of + * sym's dependencies, e.g. '(sym || Q) && R' when sym + * depends on R. + * + * Note that 'R' might be from an enclosing menu or if, + * making this a more common case than it might seem. + */ dep = expr_trans_compare(dep, E_UNEQUAL, &symbol_no); dep = expr_eliminate_dups(expr_transform(dep)); dep2 = expr_copy(basedep); expr_eliminate_eq(&dep, &dep2); expr_free(dep); if (!expr_is_yes(dep2)) { + /* Not superset, quit */ expr_free(dep2); break; } + /* Superset, put in submenu */ expr_free(dep2); next: menu_finalize(menu); menu->parent = parent; last_menu = menu; } + expr_free(basedep); if (last_menu) { parent->list = parent->next; parent->next = last_menu->next; @@ -426,6 +541,35 @@ void menu_finalize(struct menu *parent) *ep = expr_alloc_one(E_LIST, NULL); (*ep)->right.sym = menu->sym; } + + /* + * This code serves two purposes: + * + * (1) Flattening 'if' blocks, which do not specify a submenu + * and only add dependencies. + * + * (Automatic submenu creation might still create a submenu + * from an 'if' before this code runs.) + * + * (2) "Undoing" any automatic submenus created earlier below + * promptless symbols. + * + * Before: + * + * A + * if ... (or promptless symbol) + * +-B + * +-C + * D + * + * After: + * + * A + * if ... (or promptless symbol) + * B + * C + * D + */ if (menu->list && (!menu->prompt || !menu->prompt->text)) { for (last_menu = menu->list; ; last_menu = last_menu->next) { last_menu->parent = parent; @@ -450,6 +594,15 @@ void menu_finalize(struct menu *parent) sym->flags |= SYMBOL_WARNED; } + /* + * For non-optional choices, add a reverse dependency (corresponding to + * a select) of ' && m'. This prevents the user from + * setting the choice mode to 'n' when the choice is visible. + * + * This would also work for non-choice symbols, but only non-optional + * choices clear SYMBOL_OPTIONAL as of writing. Choices are implemented + * as a type of symbol. + */ if (sym && !sym_is_optional(sym) && parent->prompt) { sym->rev_dep.expr = expr_alloc_or(sym->rev_dep.expr, expr_alloc_and(parent->prompt->visible.expr, @@ -682,14 +835,14 @@ 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(sym->rev_dep.expr, r); + expr_gstr_print_revdep(sym->rev_dep.expr, r); str_append(r, "\n"); } get_symbol_props_str(r, sym, P_IMPLY, _(" Implies: ")); if (sym->implied.expr) { str_append(r, _(" Implied by: ")); - expr_gstr_print(sym->implied.expr, r); + expr_gstr_print_revdep(sym->implied.expr, r); str_append(r, "\n"); } diff --git a/kconfig/nconf.gui.c b/kconfig/nconf.gui.c index a64b1c3..88874ac 100644 --- a/kconfig/nconf.gui.c +++ b/kconfig/nconf.gui.c @@ -6,6 +6,7 @@ * */ #include "nconf.h" +#include "lkc.h" /* a list of all the different widgets we use */ attributes_t attributes[ATTR_MAX+1] = {0}; @@ -374,7 +375,7 @@ int dialog_inputbox(WINDOW *main_window, if (strlen(init)+1 > *result_len) { *result_len = strlen(init)+1; - *resultp = result = realloc(result, *result_len); + *resultp = result = xrealloc(result, *result_len); } /* find the widest line of msg: */ diff --git a/kconfig/symbol.c b/kconfig/symbol.c index 35e0937..2220bc4 100644 --- a/kconfig/symbol.c +++ b/kconfig/symbol.c @@ -77,7 +77,7 @@ const char *sym_type_name(enum symbol_type type) { switch (type) { case S_BOOLEAN: - return "boolean"; + return "bool"; case S_TRISTATE: return "tristate"; case S_INT: @@ -183,7 +183,7 @@ static void sym_validate_range(struct symbol *sym) sprintf(str, "%lld", val2); else sprintf(str, "0x%llx", val2); - sym->curr.val = strdup(str); + sym->curr.val = xstrdup(str); } static void sym_set_changed(struct symbol *sym) @@ -371,11 +371,13 @@ void sym_calc_value(struct symbol *sym) sym->curr.tri = no; return; } - if (!sym_is_choice_value(sym)) - sym->flags &= ~SYMBOL_WRITE; + sym->flags &= ~SYMBOL_WRITE; sym_calc_visibility(sym); + if (sym->visible != no) + sym->flags |= SYMBOL_WRITE; + /* set default if recursively called */ sym->curr = newval; @@ -390,7 +392,6 @@ void sym_calc_value(struct symbol *sym) /* if the symbol is visible use the user value * if available, otherwise try the default value */ - sym->flags |= SYMBOL_WRITE; if (sym_has_value(sym)) { newval.tri = EXPR_AND(sym->def[S_DEF_USER].tri, sym->visible); @@ -433,12 +434,9 @@ void sym_calc_value(struct symbol *sym) case S_STRING: case S_HEX: case S_INT: - if (sym->visible != no) { - sym->flags |= SYMBOL_WRITE; - if (sym_has_value(sym)) { - newval.val = sym->def[S_DEF_USER].val; - break; - } + if (sym->visible != no && sym_has_value(sym)) { + newval.val = sym->def[S_DEF_USER].val; + break; } prop = sym_get_default_prop(sym); if (prop) { @@ -851,7 +849,7 @@ struct symbol *sym_lookup(const char *name, int flags) : !(symbol->flags & (SYMBOL_CONST|SYMBOL_CHOICE)))) return symbol; } - new_name = strdup(name); + new_name = xstrdup(name); } else { new_name = NULL; hash = 0; @@ -901,12 +899,16 @@ struct symbol *sym_find(const char *name) * name to be expanded shall be prefixed by a '$'. Unknown symbol expands to * the empty string. */ -const char *sym_expand_string_value(const char *in) +char *sym_expand_string_value(const char *in) { const char *src; char *res; 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; res = xmalloc(reslen); res[0] = '\0'; @@ -934,7 +936,7 @@ const char *sym_expand_string_value(const char *in) newlen = strlen(res) + strlen(symval) + strlen(src) + 1; if (newlen > reslen) { reslen = newlen; - res = realloc(res, reslen); + res = xrealloc(res, reslen); } strcat(res, symval); @@ -1219,7 +1221,7 @@ static struct symbol *sym_check_expr_deps(struct expr *e) default: break; } - printf("Oops! How to check %d?\n", e->type); + fprintf(stderr, "Oops! How to check %d?\n", e->type); return NULL; } diff --git a/kconfig/util.c b/kconfig/util.c index 0e76042..c6f6e21 100644 --- a/kconfig/util.c +++ b/kconfig/util.c @@ -14,11 +14,11 @@ struct file *file_lookup(const char *name) { 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) { if (!strcmp(name, file->name)) { - free((void *)file_name); + free(file_name); return file; } } @@ -104,7 +104,7 @@ void str_append(struct gstr *gs, const char *s) if (s) { l = strlen(gs->s) + strlen(s) + 1; if (l > gs->len) { - gs->s = realloc(gs->s, l); + gs->s = xrealloc(gs->s, l); gs->len = l; } strcat(gs->s, s); @@ -145,3 +145,23 @@ void *xcalloc(size_t nmemb, size_t size) fprintf(stderr, "Out of memory.\n"); exit(1); } + +void *xrealloc(void *p, size_t size) +{ + p = realloc(p, size); + if (p) + return p; + fprintf(stderr, "Out of memory.\n"); + exit(1); +} + +char *xstrdup(const char *s) +{ + char *p; + + p = strdup(s); + if (p) + return p; + fprintf(stderr, "Out of memory.\n"); + exit(1); +} diff --git a/kconfig/zconf.l b/kconfig/zconf.l index c410d25..88b650e 100644 --- a/kconfig/zconf.l +++ b/kconfig/zconf.l @@ -52,7 +52,7 @@ static void append_string(const char *str, int size) if (new_size > text_asize) { new_size += START_STRSIZE - 1; new_size &= -START_STRSIZE; - text = realloc(text, new_size); + text = xrealloc(text, new_size); text_asize = new_size; } memcpy(text + text_size, str, size); @@ -106,11 +106,11 @@ n [A-Za-z0-9_-] current_pos.file = current_file; current_pos.lineno = current_file->lineno; if (id && id->flags & TF_COMMAND) { - zconflval.id = id; + yylval.id = id; return id->token; } alloc_string(yytext, yyleng); - zconflval.string = text; + yylval.string = text; return T_WORD; } . warn_ignored_character(*yytext); @@ -142,11 +142,11 @@ n [A-Za-z0-9_-] ({n}|[/.])+ { const struct kconf_id *id = kconf_id_lookup(yytext, yyleng); if (id && id->flags & TF_PARAM) { - zconflval.id = id; + yylval.id = id; return id->token; } alloc_string(yytext, yyleng); - zconflval.string = text; + yylval.string = text; return T_WORD; } #.* /* comment */ @@ -161,7 +161,7 @@ n [A-Za-z0-9_-] { [^'"\\\n]+/\n { append_string(yytext, yyleng); - zconflval.string = text; + yylval.string = text; return T_WORD_QUOTE; } [^'"\\\n]+ { @@ -169,7 +169,7 @@ n [A-Za-z0-9_-] } \\.?/\n { append_string(yytext + 1, yyleng - 1); - zconflval.string = text; + yylval.string = text; return T_WORD_QUOTE; } \\.? { @@ -178,13 +178,15 @@ n [A-Za-z0-9_-] \'|\" { if (str == yytext[0]) { BEGIN(PARAM); - zconflval.string = text; + yylval.string = text; return T_WORD_QUOTE; } else append_string(yytext, 1); } \n { - printf("%s:%d:warning: multi-line strings not supported\n", zconf_curname(), zconf_lineno()); + fprintf(stderr, + "%s:%d:warning: multi-line strings not supported\n", + zconf_curname(), zconf_lineno()); current_file->lineno++; BEGIN(INITIAL); return T_EOL; @@ -261,7 +263,7 @@ void zconf_starthelp(void) static void zconf_endhelp(void) { - zconflval.string = text; + yylval.string = text; BEGIN(INITIAL); } @@ -294,7 +296,7 @@ void zconf_initscan(const char *name) { yyin = zconf_fopen(name); if (!yyin) { - printf("can't find file %s\n", name); + fprintf(stderr, "can't find file %s\n", name); exit(1); } @@ -315,8 +317,8 @@ void zconf_nextfile(const char *name) current_buf->state = YY_CURRENT_BUFFER; yyin = zconf_fopen(file->name); if (!yyin) { - printf("%s:%d: can't open file \"%s\"\n", - zconf_curname(), zconf_lineno(), file->name); + fprintf(stderr, "%s:%d: can't open file \"%s\"\n", + zconf_curname(), zconf_lineno(), file->name); exit(1); } yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE)); @@ -325,20 +327,17 @@ void zconf_nextfile(const char *name) for (iter = current_file->parent; iter; iter = iter->parent ) { if (!strcmp(current_file->name,iter->name) ) { - printf("%s:%d: recursive inclusion detected. " - "Inclusion path:\n current file : '%s'\n", - zconf_curname(), zconf_lineno(), - zconf_curname()); - iter = current_file->parent; - while (iter && \ - strcmp(iter->name,current_file->name)) { - printf(" included from: '%s:%d'\n", - iter->name, iter->lineno-1); + fprintf(stderr, + "%s:%d: recursive inclusion detected. " + "Inclusion path:\n current file : '%s'\n", + zconf_curname(), zconf_lineno(), + zconf_curname()); + iter = current_file; + do { iter = iter->parent; - } - if (iter) - printf(" included from: '%s:%d'\n", - iter->name, iter->lineno+1); + fprintf(stderr, " included from: '%s:%d'\n", + iter->name, iter->lineno - 1); + } while (strcmp(iter->name, current_file->name)); exit(1); } } diff --git a/kconfig/zconf.y b/kconfig/zconf.y index 5edf50c..283ad36 100644 --- a/kconfig/zconf.y +++ b/kconfig/zconf.y @@ -20,10 +20,10 @@ int cdebug = PRINTD; -extern int zconflex(void); +int yylex(void); +static void yyerror(const char *err); static void zconfprint(const char *err, ...); static void zconf_error(const char *err, ...); -static void zconferror(const char *err); static bool zconf_endtoken(const struct kconf_id *id, int starttoken, int endtoken); struct symbol *symbol_hash[SYMBOL_HASHSIZE]; @@ -85,6 +85,7 @@ static struct menu *current_menu, *current_entry; %nonassoc T_NOT %type prompt +%type nonconst_symbol %type symbol %type expr %type if_expr @@ -101,14 +102,34 @@ static struct menu *current_menu, *current_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" %} %% 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: /* empty */ @@ -145,26 +166,23 @@ option_error: /* config/menuconfig entry */ -config_entry_start: T_CONFIG T_WORD T_EOL +config_entry_start: T_CONFIG nonconst_symbol T_EOL { - struct symbol *sym = sym_lookup($2, 0); - sym->flags |= SYMBOL_OPTIONAL; - menu_add_entry(sym); - printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), $2); + $2->flags |= SYMBOL_OPTIONAL; + menu_add_entry($2); + printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), $2->name); }; config_stmt: config_entry_start config_option_list { - menu_end_entry(); printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno()); }; -menuconfig_entry_start: T_MENUCONFIG T_WORD T_EOL +menuconfig_entry_start: T_MENUCONFIG nonconst_symbol T_EOL { - struct symbol *sym = sym_lookup($2, 0); - sym->flags |= SYMBOL_OPTIONAL; - menu_add_entry(sym); - printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), $2); + $2->flags |= SYMBOL_OPTIONAL; + menu_add_entry($2); + printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), $2->name); }; menuconfig_stmt: menuconfig_entry_start config_option_list @@ -173,7 +191,6 @@ menuconfig_stmt: menuconfig_entry_start config_option_list current_entry->prompt->type = P_MENU; else zconfprint("warning: menuconfig statement without prompt"); - menu_end_entry(); printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno()); }; @@ -211,15 +228,15 @@ config_option: T_DEFAULT expr if_expr T_EOL $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()); }; -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()); }; @@ -237,8 +254,10 @@ symbol_option_list: | symbol_option_list T_WORD symbol_option_arg { 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); + free($3); + } else zconfprint("warning: ignoring unknown option %s", $2); free($2); @@ -257,6 +276,7 @@ choice: T_CHOICE word_opt T_EOL sym->flags |= SYMBOL_AUTO; menu_add_entry(sym); menu_add_expr(P_CHOICE, NULL, NULL); + free($2); 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()); }; -choice_option: T_DEFAULT T_WORD if_expr T_EOL +choice_option: T_DEFAULT nonconst_symbol if_expr T_EOL { if ($1->stype == S_UNKNOWN) { - menu_add_symbol(P_DEFAULT, sym_lookup($2, 0), $3); + menu_add_symbol(P_DEFAULT, $2, $3); printd(DEBUG_PARSE, "%s:%d:default\n", zconf_curname(), zconf_lineno()); } else @@ -351,13 +371,6 @@ if_block: | if_block choice_stmt ; -/* mainmenu entry */ - -mainmenu_stmt: T_MAINMENU prompt nl -{ - menu_add_prompt(P_MENU, $2, NULL); -}; - /* menu entry */ 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); zconf_nextfile($2); + free($2); }; /* comment entry */ @@ -406,9 +420,7 @@ comment: T_COMMENT prompt T_EOL }; comment_stmt: comment depends_list -{ - menu_end_entry(); -}; +; /* help option */ @@ -420,6 +432,17 @@ help_start: T_HELP T_EOL help: help_start T_HELPTEXT { + if (current_entry->help) { + free(current_entry->help); + zconfprint("warning: '%s' defined with more than one help text -- only the last one will be used", + current_entry->sym->name ?: ""); + } + + /* 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 ?: ""); + 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); } ; -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); } ; @@ -502,6 +528,7 @@ word_opt: /* empty */ { $$ = NULL; } void conf_parse(const char *name) { + const char *tmp; struct symbol *sym; int i; @@ -509,27 +536,28 @@ void conf_parse(const char *name) sym_init(); _menu_init(); - rootmenu.prompt = menu_add_prompt(P_MENU, "Crosstool-NG Configuration", NULL); #if YYDEBUG if (getenv("ZCONF_DEBUG")) - zconfdebug = 1; + yydebug = 1; #endif - zconfparse(); - if (zconfnerrs) + yyparse(); + if (yynerrs) exit(1); if (!modules_sym) modules_sym = sym_find( "n" ); + tmp = rootmenu.prompt->text; rootmenu.prompt->text = _(rootmenu.prompt->text); rootmenu.prompt->text = sym_expand_string_value(rootmenu.prompt->text); + free((char*)tmp); menu_finalize(&rootmenu); for_all_symbols(i, sym) { if (sym_check_deps(sym)) - zconfnerrs++; + yynerrs++; } - if (zconfnerrs) + if (yynerrs) exit(1); sym_set_change_count(1); } @@ -554,7 +582,7 @@ static bool zconf_endtoken(const struct kconf_id *id, int starttoken, int endtok if (id->token != endtoken) { zconf_error("unexpected '%s' within %s block", id->name, zconf_tokenname(starttoken)); - zconfnerrs++; + yynerrs++; return false; } 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", current_menu->file->name, current_menu->lineno, zconf_tokenname(starttoken)); - zconfnerrs++; + yynerrs++; return false; } return true; @@ -584,7 +612,7 @@ static void zconf_error(const char *err, ...) { va_list ap; - zconfnerrs++; + yynerrs++; fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno()); va_start(ap, err); vfprintf(stderr, err, ap); @@ -592,7 +620,7 @@ static void zconf_error(const char *err, ...) fprintf(stderr, "\n"); } -static void zconferror(const char *err) +static void yyerror(const char *err) { fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno() + 1, err); } @@ -625,7 +653,7 @@ static void print_symbol(FILE *out, struct menu *menu) fprintf(out, "\nconfig %s\n", sym->name); switch (sym->type) { case S_BOOLEAN: - fputs(" boolean\n", out); + fputs(" bool\n", out); break; case S_TRISTATE: fputs(" tristate\n", out); -- cgit v0.10.2-6-g49f6 From 689dc60f212db105243b60290480f29475578e0d Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Wed, 9 Dec 2020 21:03:27 +1300 Subject: 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 diff --git a/kconfig/.gitignore b/kconfig/.gitignore index 0c8d3a2..1908525 100644 --- a/kconfig/.gitignore +++ b/kconfig/.gitignore @@ -1,9 +1,6 @@ # # Generated files # -*.lex.c -*.tab.c -*.tab.h .deps Makefile diff --git a/kconfig/conf.c b/kconfig/conf.c index 55e4f7c..5141be2 100644 --- a/kconfig/conf.c +++ b/kconfig/conf.c @@ -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)) { diff --git a/kconfig/expr.c b/kconfig/expr.c index d453819..e1a39e9 100644 --- a/kconfig/expr.c +++ b/kconfig/expr.c @@ -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) +{ + 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(e, expr_print_gstr_helper, gs, E_NONE, true); + expr_print_revdep(e, expr_print_gstr_helper, gs, pr_type, &title); } diff --git a/kconfig/expr.h b/kconfig/expr.h index c16e82e..94a383b 100644 --- a/kconfig/expr.h +++ b/kconfig/expr.h @@ -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) { diff --git a/kconfig/lkc.h b/kconfig/lkc.h index 2d5ec2d..f4394af 100644 --- a/kconfig/lkc.h +++ b/kconfig/lkc.h @@ -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); diff --git a/kconfig/menu.c b/kconfig/menu.c index d5a3322..53e7ad4 100644 --- a/kconfig/menu.c +++ b/kconfig/menu.c @@ -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"); diff --git a/kconfig/nconf.h b/kconfig/nconf.h index 0d52617..9f6f21d 100644 --- a/kconfig/nconf.h +++ b/kconfig/nconf.h @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include #include #include @@ -24,8 +24,6 @@ #include #include -#include "ncurses.h" - #define max(a, b) ({\ typeof(a) _a = a;\ typeof(b) _b = b;\ diff --git a/kconfig/symbol.c b/kconfig/symbol.c index 2220bc4..f0b2e3b 100644 --- a/kconfig/symbol.c +++ b/kconfig/symbol.c @@ -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 && diff --git a/kconfig/zconf.l b/kconfig/zconf.l index 88b650e..045093d 100644 --- a/kconfig/zconf.l +++ b/kconfig/zconf.l @@ -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); <> { @@ -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) { -- cgit v0.10.2-6-g49f6 From bbc4db133746d49893c3c9b70ef710747df27441 Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Wed, 9 Dec 2020 21:24:45 +1300 Subject: kconfig: Sync with upstream v4.18 This commit introduces the following upstream changes: 73d1c580f92b kconfig: loop boundary condition fix ecd53ac2f2c6 kconfig: handle P_SYMBOL in print_symbol() b2d00d7c61c8 kconfig: fix line numbers for if-entries in menu tree 8593080c0fcf kconfig: fix localmodconfig 2ae89c7a82ea kconfig: Avoid format overflow warning from GCC 8.1 bb6d83dde191 kbuild: Move last word of nconfig help to the previous line d6a0c8a1326b kconfig: Add testconfig into make help output 2bece88f89fa kconfig: test: add Kconfig macro language tests 915f64901eb3 kconfig: error out if a recursive variable references itself a702a6176e2f kconfig: add 'filename' and 'lineno' built-in variables 1d6272e6fe43 kconfig: add 'info', 'warning-if', and 'error-if' built-in functions 82bc8bd82e5c kconfig: expand lefthand side of assignment statement ed2a22f277c6 kconfig: support append assignment operator 1175c02506ff kconfig: support simply expanded variable 9ced3bddec08 kconfig: support user-defined function and recursively expanded variable 9de071536c87 kconfig: begin PARAM state only when seeing a command keyword 2fd5b09c201e kconfig: add 'shell' built-in function e298f3b49def kconfig: add built-in function support 137c0118a900 kconfig: make default prompt of mainmenu less specific 5b31a9746756 kconfig: remove sym_expand_string_value() 96d8e48da55a kconfig: remove string expansion for mainmenu after yyparse() bb222ceeb327 kconfig: remove string expansion in file_lookup() 104daea149c4 kconfig: reference environment variables directly and remove 'option env=' 694c49a7c01c kconfig: drop localization support 1c5af5cf9308 kconfig: refactor ncurses package checks for building mconf and nconf b464ef583dc7 kconfig: refactor GTK+ package checks for building gconf 0b669a5076fd kconfig: refactor Qt package checks for building qconf Signed-off-by: Chris Packham diff --git a/kconfig/check.sh b/kconfig/check.sh deleted file mode 100755 index 97f0fee..0000000 --- a/kconfig/check.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/sh -# SPDX-License-Identifier: GPL-2.0 -# Needed for systems without gettext -$* -x c -o /dev/null - > /dev/null 2>&1 << EOF -#include -int main() -{ - gettext(""); - return 0; -} -EOF -if [ ! "$?" -eq "0" ]; then - echo -DKBUILD_NO_NLS; -fi diff --git a/kconfig/conf.c b/kconfig/conf.c index 5141be2..abd5238 100644 --- a/kconfig/conf.c +++ b/kconfig/conf.c @@ -3,7 +3,6 @@ * Released under the terms of the GNU GPL v2.0. */ -#include #include #include #include @@ -86,7 +85,7 @@ static int conf_askvalue(struct symbol *sym, const char *def) enum symbol_type type = sym_get_type(sym); if (!sym_has_value(sym)) - printf(_("(NEW) ")); + printf("(NEW) "); line[0] = '\n'; line[1] = 0; @@ -133,7 +132,7 @@ static int conf_string(struct menu *menu) const char *def; while (1) { - printf("%*s%s ", indent - 1, "", _(menu->prompt->text)); + printf("%*s%s ", indent - 1, "", menu->prompt->text); printf("(%s) ", sym->name); def = sym_get_string_value(sym); if (sym_get_string_value(sym)) @@ -166,7 +165,7 @@ static int conf_sym(struct menu *menu) tristate oldval, newval; while (1) { - printf("%*s%s ", indent - 1, "", _(menu->prompt->text)); + printf("%*s%s ", indent - 1, "", menu->prompt->text); if (sym->name) printf("(%s) ", sym->name); putchar('['); @@ -251,7 +250,7 @@ static int conf_choice(struct menu *menu) case no: return 1; case mod: - printf("%*s%s\n", indent - 1, "", _(menu_get_prompt(menu))); + printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu)); return 0; case yes: break; @@ -261,7 +260,7 @@ static int conf_choice(struct menu *menu) while (1) { int cnt, def; - printf("%*s%s\n", indent - 1, "", _(menu_get_prompt(menu))); + printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu)); def_sym = sym_get_choice_value(sym); cnt = def = 0; line[0] = 0; @@ -269,7 +268,7 @@ static int conf_choice(struct menu *menu) if (!menu_is_visible(child)) continue; if (!child->sym) { - printf("%*c %s\n", indent, '*', _(menu_get_prompt(child))); + printf("%*c %s\n", indent, '*', menu_get_prompt(child)); continue; } cnt++; @@ -278,14 +277,14 @@ static int conf_choice(struct menu *menu) printf("%*c", indent, '>'); } else printf("%*c", indent, ' '); - printf(" %d. %s", cnt, _(menu_get_prompt(child))); + printf(" %d. %s", cnt, menu_get_prompt(child)); if (child->sym->name) printf(" (%s)", child->sym->name); if (!sym_has_value(child->sym)) - printf(_(" (NEW)")); + printf(" (NEW)"); printf("\n"); } - printf(_("%*schoice"), indent - 1, ""); + printf("%*schoice", indent - 1, ""); if (cnt == 1) { printf("[1]: 1\n"); goto conf_childs; @@ -372,7 +371,7 @@ static void conf(struct menu *menu) if (prompt) printf("%*c\n%*c %s\n%*c\n", indent, '*', - indent, '*', _(prompt), + indent, '*', prompt, indent, '*'); default: ; @@ -437,7 +436,7 @@ static void check_conf(struct menu *menu) } } else { if (!conf_cnt++) - printf(_("*\n* Restart config...\n*\n")); + printf("*\n* Restart config...\n*\n"); rootEntry = menu_get_parent_menu(menu); conf(rootEntry); } @@ -477,10 +476,6 @@ int main(int ac, char **av) const char *name, *defconfig_file = NULL /* gcc uninit */; struct stat tmpstat; - setlocale(LC_ALL, ""); - bindtextdomain(PACKAGE, LOCALEDIR); - textdomain(PACKAGE); - tty_stdio = isatty(0) && isatty(1); while ((opt = getopt_long(ac, av, "s", long_opts, NULL)) != -1) { @@ -532,14 +527,14 @@ int main(int ac, char **av) case olddefconfig: break; case '?': - fprintf(stderr, _("See README for usage info\n")); + fprintf(stderr, "See README for usage info\n"); exit(1); break; } } if (ac == optind) { - fprintf(stderr, _("%s: Kconfig file missing\n"), av[0]); - fprintf(stderr, _("See README for usage info\n")); + fprintf(stderr, "%s: Kconfig file missing\n", av[0]); + fprintf(stderr, "See README for usage info\n"); exit(1); } name = av[optind]; @@ -548,12 +543,12 @@ int main(int ac, char **av) if (sync_kconfig) { name = conf_get_configname(); if (stat(name, &tmpstat)) { - fprintf(stderr, _("***\n" + fprintf(stderr, "***\n" "*** Configuration file \"%s\" not found!\n" "***\n" "*** Please configure with \"menuconfig\", or use a\n" "*** pre-existing sample (see list with \"list-samples\").\n" - "***\n"), name); + "***\n", name); exit(1); } } @@ -564,9 +559,9 @@ int main(int ac, char **av) defconfig_file = conf_get_default_confname(); if (conf_read(defconfig_file)) { fprintf(stderr, - _("***\n" + "***\n" "*** Can't find default configuration \"%s\"!\n" - "***\n"), + "***\n", defconfig_file); exit(1); } @@ -590,7 +585,7 @@ int main(int ac, char **av) if ((strcmp(name, "") != 0) && (strcmp(name, "1") != 0)) { if (conf_read_simple(name, S_DEF_USER)) { fprintf(stderr, - _("*** Can't read seed configuration \"%s\"!\n"), + "*** Can't read seed configuration \"%s\"!\n", name); exit(1); } @@ -607,7 +602,7 @@ int main(int ac, char **av) if (conf_read_simple(name, S_DEF_USER) && conf_read_simple("all.config", S_DEF_USER)) { fprintf(stderr, - _("*** KCONFIG_ALLCONFIG set, but no \"%s\" or \"all.config\" file found\n"), + "*** KCONFIG_ALLCONFIG set, but no \"%s\" or \"all.config\" file found\n", name); exit(1); } @@ -621,7 +616,7 @@ int main(int ac, char **av) name = getenv("KCONFIG_NOSILENTUPDATE"); if (name && *name) { fprintf(stderr, - _("\n*** The configuration requires explicit update.\n\n")); + "\n*** The configuration requires explicit update.\n\n"); return 1; } } @@ -673,23 +668,23 @@ int main(int ac, char **av) * All other commands are only used to generate a config. */ if (conf_get_changed() && conf_write(NULL)) { - fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n")); + fprintf(stderr, "\n*** Error during writing of the configuration.\n\n"); exit(1); } /* In crosstool-NG, we do not use the autoconf stuff if (conf_write_autoconf()) { - fprintf(stderr, _("\n*** Error during update of the configuration.\n\n")); + fprintf(stderr, "\n*** Error during update of the configuration.\n\n"); return 1; } */ } else if (input_mode == savedefconfig) { if (conf_write_defconfig(defconfig_file)) { - fprintf(stderr, _("n*** Error while saving defconfig to: %s\n\n"), + fprintf(stderr, "n*** Error while saving defconfig to: %s\n\n", defconfig_file); return 1; } } else if (input_mode != listnewconfig) { if (conf_write(NULL)) { - fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n")); + fprintf(stderr, "\n*** Error during writing of the configuration.\n\n"); exit(1); } } diff --git a/kconfig/confdata.c b/kconfig/confdata.c index df26c7b..39e2097 100644 --- a/kconfig/confdata.c +++ b/kconfig/confdata.c @@ -30,7 +30,7 @@ static void conf_message(const char *fmt, ...) static const char *conf_filename; static int conf_lineno, conf_warnings; -const char conf_defname[] = "arch/$ARCH/defconfig"; +const char conf_defname[] = "arch/$(ARCH)/defconfig"; static void conf_warning(const char *fmt, ...) { @@ -81,39 +81,13 @@ const char *conf_get_autoconfig_name(void) return name ? name : "include/config/auto.conf"; } -static char *conf_expand_value(const char *in) -{ - struct symbol *sym; - const char *src; - static char res_value[SYMBOL_MAXLENGTH]; - char *dst, name[SYMBOL_MAXLENGTH]; - - res_value[0] = 0; - dst = name; - while ((src = strchr(in, '$'))) { - strncat(res_value, in, src - in); - src++; - dst = name; - while (isalnum(*src) || *src == '_') - *dst++ = *src++; - *dst = 0; - sym = sym_lookup(name, 0); - sym_calc_value(sym); - strcat(res_value, sym_get_string_value(sym)); - in = src; - } - strcat(res_value, in); - - return res_value; -} - char *conf_get_default_confname(void) { struct stat buf; static char fullname[PATH_MAX+1]; char *env, *name; - name = conf_expand_value(conf_defname); + name = expand_string(conf_defname); env = getenv(SRCTREE); if (env) { sprintf(fullname, "%s/%s", env, name); @@ -274,10 +248,11 @@ int conf_read_simple(const char *name, int def) if (expr_calc_value(prop->visible.expr) == no || prop->expr->type != E_SYMBOL) continue; - name = conf_expand_value(prop->expr->left.sym->name); + sym_calc_value(prop->expr->left.sym); + name = sym_get_string_value(prop->expr->left.sym); in = zconf_fopen(name); if (in) { - conf_message(_("using defaults found in %s"), + conf_message("using defaults found in %s", name); goto load; } @@ -745,7 +720,7 @@ int conf_write(const char *name) struct menu *menu; const char *basename; const char *str; - char dirname[PATH_MAX+1], tmpname[PATH_MAX+1], newname[PATH_MAX+1]; + char dirname[PATH_MAX+1], tmpname[PATH_MAX+22], newname[PATH_MAX+8]; char *env; dirname[0] = 0; @@ -831,7 +806,7 @@ next: return 1; } - conf_message(_("configuration written to %s"), newname); + conf_message("configuration written to %s", newname); sym_set_change_count(0); diff --git a/kconfig/expr.h b/kconfig/expr.h index 94a383b..f63b41b 100644 --- a/kconfig/expr.h +++ b/kconfig/expr.h @@ -171,6 +171,9 @@ struct symbol { * config BAZ * int "BAZ Value" * range 1..255 + * + * Please, also check zconf.y:print_symbol() when modifying the + * list of property types! */ enum prop_type { P_UNKNOWN, diff --git a/kconfig/kconf_id.c b/kconfig/kconf_id.c index 3ea9c5f..b3e0ea0 100644 --- a/kconfig/kconf_id.c +++ b/kconfig/kconf_id.c @@ -32,7 +32,6 @@ static struct kconf_id kconf_id_array[] = { { "on", T_ON, TF_PARAM }, { "modules", T_OPT_MODULES, TF_OPTION }, { "defconfig_list", T_OPT_DEFCONFIG_LIST, TF_OPTION }, - { "env", T_OPT_ENV, TF_OPTION }, { "allnoconfig_y", T_OPT_ALLNOCONFIG_Y, TF_OPTION }, }; diff --git a/kconfig/lkc.h b/kconfig/lkc.h index f4394af..ed3ff88 100644 --- a/kconfig/lkc.h +++ b/kconfig/lkc.h @@ -8,15 +8,6 @@ #include "expr.h" -#ifndef KBUILD_NO_NLS -# include -#else -static inline const char *gettext(const char *txt) { return txt; } -static inline void textdomain(const char *domainname) {} -static inline void bindtextdomain(const char *name, const char *dir) {} -static inline char *bind_textdomain_codeset(const char *dn, char *c) { return c; } -#endif - #ifdef __cplusplus extern "C" { #endif @@ -29,11 +20,6 @@ extern "C" { #define PACKAGE "linux" #endif -#define LOCALEDIR "/usr/share/locale" - -#define _(text) gettext(text) -#define N_(text) (text) - #ifndef CONFIG_ #define CONFIG_ "CONFIG_" #endif @@ -58,7 +44,6 @@ enum conf_def_mode { #define T_OPT_MODULES 1 #define T_OPT_DEFCONFIG_LIST 2 -#define T_OPT_ENV 3 #define T_OPT_ALLNOCONFIG_Y 4 struct kconf_id { @@ -117,6 +102,7 @@ void *xmalloc(size_t size); void *xcalloc(size_t nmemb, size_t size); void *xrealloc(void *p, size_t size); char *xstrdup(const char *s); +char *xstrndup(const char *s, size_t n); struct gstr { size_t len; @@ -134,9 +120,6 @@ void str_printf(struct gstr *gs, const char *fmt, ...); const char *str_get(struct gstr *gs); /* symbol.c */ -extern struct expr *sym_env_list; - -void sym_init(void); void sym_clear_all_valid(void); struct symbol *sym_choice_default(struct symbol *sym); const char *sym_get_string_default(struct symbol *sym); diff --git a/kconfig/lkc_proto.h b/kconfig/lkc_proto.h index 9dc8abf..a8b7a33 100644 --- a/kconfig/lkc_proto.h +++ b/kconfig/lkc_proto.h @@ -31,7 +31,6 @@ extern struct symbol * symbol_hash[SYMBOL_HASHSIZE]; struct symbol * sym_lookup(const char *name, int flags); struct symbol * sym_find(const char *name); -char *sym_expand_string_value(const char *in); const char * sym_escape_string_value(const char *in); struct symbol ** sym_re_search(const char *pattern); const char * sym_type_name(enum symbol_type type); @@ -49,5 +48,19 @@ const char * sym_get_string_value(struct symbol *sym); const char * prop_get_type_name(enum prop_type type); +/* preprocess.c */ +enum variable_flavor { + VAR_SIMPLE, + VAR_RECURSIVE, + VAR_APPEND, +}; +void env_write_dep(FILE *f, const char *auto_conf_name); +void variable_add(const char *name, const char *value, + enum variable_flavor flavor); +void variable_all_del(void); +char *expand_string(const char *in); +char *expand_dollar(const char **str); +char *expand_one_token(const char **str); + /* expr.c */ void expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken); diff --git a/kconfig/lxdialog/check-lxdialog.sh b/kconfig/lxdialog/check-lxdialog.sh deleted file mode 100755 index 6c0bcd9..0000000 --- a/kconfig/lxdialog/check-lxdialog.sh +++ /dev/null @@ -1,93 +0,0 @@ -#!/bin/sh -# SPDX-License-Identifier: GPL-2.0 -# Check ncurses compatibility - -# What library to link -ldflags() -{ - pkg-config --libs ncursesw 2>/dev/null && exit - pkg-config --libs ncurses 2>/dev/null && exit - for ext in so a dll.a dylib ; do - for lib in ncursesw ncurses curses ; do - $cc -print-file-name=lib${lib}.${ext} | grep -q / - if [ $? -eq 0 ]; then - echo "-l${lib}" - exit - fi - done - done - exit 1 -} - -# Where is ncurses.h? -ccflags() -{ - if pkg-config --cflags ncursesw 2>/dev/null; then - echo '-DCURSES_LOC="" -DNCURSES_WIDECHAR=1' - elif pkg-config --cflags ncurses 2>/dev/null; then - echo '-DCURSES_LOC=""' - elif [ -f /usr/include/ncursesw/curses.h ]; then - echo '-I/usr/include/ncursesw -DCURSES_LOC=""' - echo ' -DNCURSES_WIDECHAR=1' - elif [ -f /usr/include/ncurses/ncurses.h ]; then - echo '-I/usr/include/ncurses -DCURSES_LOC=""' - elif [ -f /usr/include/ncurses/curses.h ]; then - echo '-I/usr/include/ncurses -DCURSES_LOC=""' - elif [ -f /usr/include/ncurses.h ]; then - echo '-DCURSES_LOC=""' - else - echo '-DCURSES_LOC=""' - fi -} - -# Temp file, try to clean up after us -tmp=.lxdialog.tmp -trap "rm -f $tmp" 0 1 2 3 15 - -# Check if we can link to ncurses -check() { - $cc -x c - -o $tmp 2>/dev/null <<'EOF' -#include CURSES_LOC -main() {} -EOF - if [ $? != 0 ]; then - echo " *** Unable to find the ncurses libraries or the" 1>&2 - echo " *** required header files." 1>&2 - echo " *** 'make menuconfig' requires the ncurses libraries." 1>&2 - echo " *** " 1>&2 - echo " *** Install ncurses (ncurses-devel or libncurses-dev " 1>&2 - echo " *** depending on your distribution) and try again." 1>&2 - echo " *** " 1>&2 - exit 1 - fi -} - -usage() { - printf "Usage: $0 [-check compiler options|-ccflags|-ldflags compiler options]\n" -} - -if [ $# -eq 0 ]; then - usage - exit 1 -fi - -cc="" -case "$1" in - "-check") - shift - cc="$@" - check - ;; - "-ccflags") - ccflags - ;; - "-ldflags") - shift - cc="$@" - ldflags - ;; - "*") - usage - exit 1 - ;; -esac diff --git a/kconfig/lxdialog/checklist.c b/kconfig/lxdialog/checklist.c index 8d016fa..2e96323 100644 --- a/kconfig/lxdialog/checklist.c +++ b/kconfig/lxdialog/checklist.c @@ -103,8 +103,8 @@ static void print_buttons(WINDOW * dialog, int height, int width, int selected) int x = width / 2 - 11; int y = height - 2; - print_button(dialog, gettext("Select"), y, x, selected == 0); - print_button(dialog, gettext(" Help "), y, x + 14, selected == 1); + print_button(dialog, "Select", y, x, selected == 0); + print_button(dialog, " Help ", y, x + 14, selected == 1); wmove(dialog, y, x + 1 + 14 * selected); wrefresh(dialog); diff --git a/kconfig/lxdialog/dialog.h b/kconfig/lxdialog/dialog.h index fcffd5b..0b00be5 100644 --- a/kconfig/lxdialog/dialog.h +++ b/kconfig/lxdialog/dialog.h @@ -26,16 +26,10 @@ #include #include -#ifndef KBUILD_NO_NLS -# include -#else -# define gettext(Msgid) ((const char *) (Msgid)) -#endif - #ifdef __sun__ #define CURS_MACROS #endif -#include CURSES_LOC +#include /* * Colors in ncurses 1.9.9e do not work properly since foreground and diff --git a/kconfig/lxdialog/inputbox.c b/kconfig/lxdialog/inputbox.c index d58de1d..fe82ff6 100644 --- a/kconfig/lxdialog/inputbox.c +++ b/kconfig/lxdialog/inputbox.c @@ -31,8 +31,8 @@ static void print_buttons(WINDOW * dialog, int height, int width, int selected) int x = width / 2 - 11; int y = height - 2; - print_button(dialog, gettext(" Ok "), y, x, selected == 0); - print_button(dialog, gettext(" Help "), y, x + 14, selected == 1); + print_button(dialog, " Ok ", y, x, selected == 0); + print_button(dialog, " Help ", y, x + 14, selected == 1); wmove(dialog, y, x + 1 + 14 * selected); wrefresh(dialog); diff --git a/kconfig/lxdialog/menubox.c b/kconfig/lxdialog/menubox.c index 11ae9ad..d70cab3 100644 --- a/kconfig/lxdialog/menubox.c +++ b/kconfig/lxdialog/menubox.c @@ -157,11 +157,11 @@ static void print_buttons(WINDOW * win, int height, int width, int selected) int x = width / 2 - 28; int y = height - 2; - print_button(win, gettext("Select"), y, x, selected == 0); - print_button(win, gettext(" Exit "), y, x + 12, selected == 1); - print_button(win, gettext(" Help "), y, x + 24, selected == 2); - print_button(win, gettext(" Save "), y, x + 36, selected == 3); - print_button(win, gettext(" Load "), y, x + 48, selected == 4); + print_button(win, "Select", y, x, selected == 0); + print_button(win, " Exit ", y, x + 12, selected == 1); + print_button(win, " Help ", y, x + 24, selected == 2); + print_button(win, " Save ", y, x + 36, selected == 3); + print_button(win, " Load ", y, x + 48, selected == 4); wmove(win, y, x + 1 + 12 * selected); wrefresh(win); diff --git a/kconfig/lxdialog/textbox.c b/kconfig/lxdialog/textbox.c index 1773319..88d2818 100644 --- a/kconfig/lxdialog/textbox.c +++ b/kconfig/lxdialog/textbox.c @@ -129,7 +129,7 @@ do_resize: print_title(dialog, title, width); - print_button(dialog, gettext(" Exit "), height - 2, width / 2 - 4, TRUE); + print_button(dialog, " Exit ", height - 2, width / 2 - 4, TRUE); wnoutrefresh(dialog); getyx(dialog, cur_y, cur_x); /* Save cursor position */ diff --git a/kconfig/lxdialog/yesno.c b/kconfig/lxdialog/yesno.c index 676fb2f..cd1223c 100644 --- a/kconfig/lxdialog/yesno.c +++ b/kconfig/lxdialog/yesno.c @@ -29,8 +29,8 @@ static void print_buttons(WINDOW * dialog, int height, int width, int selected) int x = width / 2 - 10; int y = height - 2; - print_button(dialog, gettext(" Yes "), y, x, selected == 0); - print_button(dialog, gettext(" No "), y, x + 13, selected == 1); + print_button(dialog, " Yes ", y, x, selected == 0); + print_button(dialog, " No ", y, x + 13, selected == 1); wmove(dialog, y, x + 1 + 13 * selected); wrefresh(dialog); diff --git a/kconfig/mconf.c b/kconfig/mconf.c index ea50ba0..9890dd4 100644 --- a/kconfig/mconf.c +++ b/kconfig/mconf.c @@ -17,12 +17,11 @@ #include #include #include -#include #include "lkc.h" #include "lxdialog/dialog.h" -static const char mconf_readme[] = N_( +static const char mconf_readme[] = "Overview\n" "--------\n" "This interface lets you select features and parameters for the build.\n" @@ -171,37 +170,37 @@ static const char mconf_readme[] = N_( " blackbg => selects a color scheme with black background\n" " classic => theme with blue background. The classic look\n" " bluetitle => an LCD friendly version of classic. (default)\n" -"\n"), -menu_instructions[] = N_( +"\n", +menu_instructions[] = "Arrow keys navigate the menu. " " selects submenus ---> (or empty submenus ----). " "Highlighted letters are hotkeys. " "Pressing includes, excludes, modularizes features. " "Press to exit, for Help, for Search. " - "Legend: [*] built-in [ ] excluded module < > module capable"), -radiolist_instructions[] = N_( + "Legend: [*] built-in [ ] excluded module < > module capable", +radiolist_instructions[] = "Use the arrow keys to navigate this window or " "press the hotkey of the item you wish to select " "followed by the . " - "Press for additional information about this option."), -inputbox_instructions_int[] = N_( + "Press for additional information about this option.", +inputbox_instructions_int[] = "Please enter a decimal value. " "Fractions will not be accepted. " - "Use the key to move from the input field to the buttons below it."), -inputbox_instructions_hex[] = N_( + "Use the key to move from the input field to the buttons below it.", +inputbox_instructions_hex[] = "Please enter a hexadecimal value. " - "Use the key to move from the input field to the buttons below it."), -inputbox_instructions_string[] = N_( + "Use the key to move from the input field to the buttons below it.", +inputbox_instructions_string[] = "Please enter a string value. " - "Use the key to move from the input field to the buttons below it."), -setmod_text[] = N_( + "Use the key to move from the input field to the buttons below it.", +setmod_text[] = "This feature depends on another which has been configured as a module.\n" - "As a result, this feature will be built as a module."), -load_config_text[] = N_( + "As a result, this feature will be built as a module.", +load_config_text[] = "Enter the name of the configuration file you wish to load. " "Accept the name shown to restore the configuration you " - "last retrieved. Leave blank to abort."), -load_config_help[] = N_( + "last retrieved. Leave blank to abort.", +load_config_help[] = "\n" "For various reasons, one may wish to keep several different\n" "configurations available on a single machine.\n" @@ -211,11 +210,11 @@ load_config_help[] = N_( "configuration.\n" "\n" "If you are uncertain, then you have probably never used alternate\n" - "configuration files. You should therefore leave this blank to abort.\n"), -save_config_text[] = N_( + "configuration files. You should therefore leave this blank to abort.\n", +save_config_text[] = "Enter a filename to which this configuration should be saved " - "as an alternate. Leave blank to abort."), -save_config_help[] = N_( + "as an alternate. Leave blank to abort.", +save_config_help[] = "\n" "For various reasons, one may wish to keep different configurations\n" "available on a single machine.\n" @@ -225,8 +224,8 @@ save_config_help[] = N_( "configuration options you have selected at that time.\n" "\n" "If you are uncertain what all this means then you should probably\n" - "leave this blank.\n"), -search_help[] = N_( + "leave this blank.\n", +search_help[] = "\n" "Search for symbols and display their relations.\n" "Regular expressions are allowed.\n" @@ -271,7 +270,7 @@ search_help[] = N_( "Examples: USB => find all symbols containing USB\n" " ^USB => find all symbols starting with USB\n" " USB$ => find all symbols ending with USB\n" - "\n"); + "\n"; static int indent; static struct menu *current_menu; @@ -400,19 +399,19 @@ static void search_conf(void) struct subtitle_part stpart; title = str_new(); - str_printf( &title, _("Enter (sub)string or regexp to search for " - "(with or without \"%s\")"), CONFIG_); + str_printf( &title, "Enter (sub)string or regexp to search for " + "(with or without \"%s\")", CONFIG_); again: dialog_clear(); - dres = dialog_inputbox(_("Search Configuration Parameter"), + dres = dialog_inputbox("Search Configuration Parameter", str_get(&title), 10, 75, ""); switch (dres) { case 0: break; case 1: - show_helptext(_("Search Configuration"), search_help); + show_helptext("Search Configuration", search_help); goto again; default: str_free(&title); @@ -443,7 +442,7 @@ again: res = get_relations_str(sym_arr, &head); set_subtitle(); - dres = show_textbox_ext(_("Search Results"), (char *) + dres = show_textbox_ext("Search Results", (char *) str_get(&res), 0, 0, keys, &vscroll, &hscroll, &update_text, (void *) &data); @@ -491,7 +490,7 @@ static void build_conf(struct menu *menu) switch (prop->type) { case P_MENU: child_count++; - prompt = _(prompt); + prompt = prompt; if (single_menu_mode) { item_make("%s%*c%s", menu->data ? "-->" : "++>", @@ -508,7 +507,7 @@ static void build_conf(struct menu *menu) case P_COMMENT: if (prompt) { child_count++; - item_make(" %*c*** %s ***", indent + 1, ' ', _(prompt)); + item_make(" %*c*** %s ***", indent + 1, ' ', prompt); item_set_tag(':'); item_set_data(menu); } @@ -516,7 +515,7 @@ static void build_conf(struct menu *menu) default: if (prompt) { child_count++; - item_make("---%*c%s", indent + 1, ' ', _(prompt)); + item_make("---%*c%s", indent + 1, ' ', prompt); item_set_tag(':'); item_set_data(menu); } @@ -560,10 +559,10 @@ static void build_conf(struct menu *menu) item_set_data(menu); } - item_add_str("%*c%s", indent + 1, ' ', _(menu_get_prompt(menu))); + item_add_str("%*c%s", indent + 1, ' ', menu_get_prompt(menu)); if (val == yes) { if (def_menu) { - item_add_str(" (%s)", _(menu_get_prompt(def_menu))); + item_add_str(" (%s)", menu_get_prompt(def_menu)); item_add_str(" --->"); if (def_menu->list) { indent += 2; @@ -575,7 +574,7 @@ static void build_conf(struct menu *menu) } } else { if (menu == current_menu) { - item_make("---%*c%s", indent + 1, ' ', _(menu_get_prompt(menu))); + item_make("---%*c%s", indent + 1, ' ', menu_get_prompt(menu)); item_set_tag(':'); item_set_data(menu); goto conf_childs; @@ -618,17 +617,17 @@ static void build_conf(struct menu *menu) tmp = indent - tmp + 4; if (tmp < 0) tmp = 0; - item_add_str("%*c%s%s", tmp, ' ', _(menu_get_prompt(menu)), + item_add_str("%*c%s%s", tmp, ' ', menu_get_prompt(menu), (sym_has_value(sym) || !sym_is_changable(sym)) ? - "" : _(" (NEW)")); + "" : " (NEW)"); item_set_tag('s'); item_set_data(menu); goto conf_childs; } } - item_add_str("%*c%s%s", indent + 1, ' ', _(menu_get_prompt(menu)), + item_add_str("%*c%s%s", indent + 1, ' ', menu_get_prompt(menu), (sym_has_value(sym) || !sym_is_changable(sym)) ? - "" : _(" (NEW)")); + "" : " (NEW)"); if (menu->prompt->type == P_MENU) { item_add_str(" %s", menu_is_empty(menu) ? "----" : "--->"); return; @@ -665,8 +664,8 @@ static void conf(struct menu *menu, struct menu *active_menu) break; set_subtitle(); dialog_clear(); - res = dialog_menu(prompt ? _(prompt) : _("Main Menu"), - _(menu_instructions), + res = dialog_menu(prompt ? prompt : "Main Menu", + menu_instructions, active_menu, &s_scroll); if (res == 1 || res == KEY_ESC || res == -ERRDISPLAYTOOSMALL) break; @@ -708,7 +707,7 @@ static void conf(struct menu *menu, struct menu *active_menu) show_help(submenu); else { reset_subtitle(); - show_helptext(_("README"), _(mconf_readme)); + show_helptext("README", mconf_readme); } break; case 3: @@ -793,13 +792,13 @@ static void show_help(struct menu *menu) help.max_width = getmaxx(stdscr) - 10; menu_get_ext_help(menu, &help); - show_helptext(_(menu_get_prompt(menu)), str_get(&help)); + show_helptext(menu_get_prompt(menu), str_get(&help)); str_free(&help); } static void conf_choice(struct menu *menu) { - const char *prompt = _(menu_get_prompt(menu)); + const char *prompt = menu_get_prompt(menu); struct menu *child; struct symbol *active; @@ -814,9 +813,9 @@ static void conf_choice(struct menu *menu) if (!menu_is_visible(child)) continue; if (child->sym) - item_make("%s", _(menu_get_prompt(child))); + item_make("%s", menu_get_prompt(child)); else { - item_make("*** %s ***", _(menu_get_prompt(child))); + item_make("*** %s ***", menu_get_prompt(child)); item_set_tag(':'); } item_set_data(child); @@ -826,8 +825,8 @@ static void conf_choice(struct menu *menu) item_set_tag('X'); } dialog_clear(); - res = dialog_checklist(prompt ? _(prompt) : _("Main Menu"), - _(radiolist_instructions), + res = dialog_checklist(prompt ? prompt : "Main Menu", + radiolist_instructions, MENUBOX_HEIGTH_MIN, MENUBOX_WIDTH_MIN, CHECKLIST_HEIGTH_MIN); @@ -868,26 +867,26 @@ static void conf_string(struct menu *menu) switch (sym_get_type(menu->sym)) { case S_INT: - heading = _(inputbox_instructions_int); + heading = inputbox_instructions_int; break; case S_HEX: - heading = _(inputbox_instructions_hex); + heading = inputbox_instructions_hex; break; case S_STRING: - heading = _(inputbox_instructions_string); + heading = inputbox_instructions_string; break; default: - heading = _("Internal mconf error!"); + heading = "Internal mconf error!"; } dialog_clear(); - res = dialog_inputbox(prompt ? _(prompt) : _("Main Menu"), + res = dialog_inputbox(prompt ? prompt : "Main Menu", heading, 10, 75, sym_get_string_value(menu->sym)); switch (res) { case 0: if (sym_set_string_value(menu->sym, dialog_input_result)) return; - show_textbox(NULL, _("You have made an invalid entry."), 5, 43); + show_textbox(NULL, "You have made an invalid entry.", 5, 43); break; case 1: show_help(menu); @@ -915,10 +914,10 @@ static void conf_load(void) sym_set_change_count(1); return; } - show_textbox(NULL, _("File does not exist!"), 5, 38); + show_textbox(NULL, "File does not exist!", 5, 38); break; case 1: - show_helptext(_("Load Alternate Configuration"), load_config_help); + show_helptext("Load Alternate Configuration", load_config_help); break; case KEY_ESC: return; @@ -941,10 +940,10 @@ static void conf_save(void) set_config_filename(dialog_input_result); return; } - show_textbox(NULL, _("Can't create file! Probably a nonexistent directory."), 5, 60); + show_textbox(NULL, "Can't create file! Probably a nonexistent directory.", 5, 60); break; case 1: - show_helptext(_("Save Alternate Configuration"), save_config_help); + show_helptext("Save Alternate Configuration", save_config_help); break; case KEY_ESC: return; @@ -961,8 +960,8 @@ static int handle_exit(void) dialog_clear(); if (conf_get_changed()) res = dialog_yesno(NULL, - _("Do you wish to save your new configuration?\n" - "(Press to continue Crosstool-NG configuration.)"), + "Do you wish to save your new configuration?\n" + "(Press to continue Crosstool-NG configuration.)", 6, 60); else res = -1; @@ -972,26 +971,26 @@ static int handle_exit(void) switch (res) { case 0: if (conf_write(filename)) { - fprintf(stderr, _("\n\n" + fprintf(stderr, "\n\n" "Error while writing of the configuration.\n" "Your configuration changes were NOT saved." - "\n\n")); + "\n\n"); return 1; } /* fall through */ case -1: if (!silent) - printf(_("\n\n" + printf("\n\n" "*** End of the configuration.\n" "*** Execute 'ct-ng build' to start the build or try 'ct-ng help'." - "\n\n")); + "\n\n"); res = 0; break; default: if (!silent) - fprintf(stderr, _("\n\n" + fprintf(stderr, "\n\n" "Your configuration changes were NOT saved." - "\n\n")); + "\n\n"); if (res != KEY_ESC) res = 0; } @@ -1009,10 +1008,6 @@ int main(int ac, char **av) char *mode; int res; - setlocale(LC_ALL, ""); - bindtextdomain(PACKAGE, LOCALEDIR); - textdomain(PACKAGE); - signal(SIGINT, sig_handler); if (ac > 1 && strcmp(av[1], "-s") == 0) { @@ -1031,8 +1026,8 @@ int main(int ac, char **av) } if (init_dialog(NULL)) { - fprintf(stderr, N_("Your display is too small to run Menuconfig!\n")); - fprintf(stderr, N_("It must be at least 19 lines by 80 columns.\n")); + fprintf(stderr, "Your display is too small to run Menuconfig!\n"); + fprintf(stderr, "It must be at least 19 lines by 80 columns.\n"); return 1; } diff --git a/kconfig/menu.c b/kconfig/menu.c index 53e7ad4..fd919bd 100644 --- a/kconfig/menu.c +++ b/kconfig/menu.c @@ -220,9 +220,6 @@ void menu_add_option(int token, char *arg) zconf_error("trying to redefine defconfig symbol"); sym_defconfig_list->flags |= SYMBOL_AUTO; break; - case T_OPT_ENV: - prop_add_env(arg); - break; case T_OPT_ALLNOCONFIG_Y: current_entry->sym->flags |= SYMBOL_ALLNOCONFIG_Y; break; @@ -717,7 +714,7 @@ static void get_prompt_str(struct gstr *r, struct property *prop, struct menu *submenu[8], *menu, *location = NULL; struct jump_key *jump = NULL; - str_printf(r, _("Prompt: %s\n"), _(prop->text)); + str_printf(r, "Prompt: %s\n", prop->text); menu = prop->menu->parent; for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent) { bool accessible = menu_is_visible(menu); @@ -750,16 +747,16 @@ static void get_prompt_str(struct gstr *r, struct property *prop, } if (i > 0) { - str_printf(r, _(" Location:\n")); + str_printf(r, " Location:\n"); for (j = 4; --i >= 0; j += 2) { menu = submenu[i]; if (jump && menu == location) jump->offset = strlen(r->s); str_printf(r, "%*c-> %s", j, ' ', - _(menu_get_prompt(menu))); + menu_get_prompt(menu)); if (menu->sym) { str_printf(r, " (%s [=%s])", menu->sym->name ? - menu->sym->name : _(""), + menu->sym->name : "", sym_get_string_value(menu->sym)); } str_append(r, "\n"); @@ -823,23 +820,23 @@ static void get_symbol_str(struct gstr *r, struct symbol *sym, prop = get_symbol_prop(sym); if (prop) { - str_printf(r, _(" Defined at %s:%d\n"), prop->menu->file->name, + str_printf(r, " Defined at %s:%d\n", prop->menu->file->name, prop->menu->lineno); if (!expr_is_yes(prop->visible.expr)) { - str_append(r, _(" Depends on: ")); + str_append(r, " Depends on: "); expr_gstr_print(prop->visible.expr, r); str_append(r, "\n"); } } - get_symbol_props_str(r, sym, P_SELECT, _(" Selects: ")); + get_symbol_props_str(r, sym, P_SELECT, " Selects: "); if (sym->rev_dep.expr) { expr_gstr_print_revdep(sym->rev_dep.expr, r, yes, " Selected by [y]:\n"); expr_gstr_print_revdep(sym->rev_dep.expr, r, mod, " Selected by [m]:\n"); expr_gstr_print_revdep(sym->rev_dep.expr, r, no, " Selected by [n]:\n"); } - get_symbol_props_str(r, sym, P_IMPLY, _(" Implies: ")); + get_symbol_props_str(r, sym, P_IMPLY, " Implies: "); if (sym->implied.expr) { 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"); @@ -858,7 +855,7 @@ struct gstr get_relations_str(struct symbol **sym_arr, struct list_head *head) for (i = 0; sym_arr && (sym = sym_arr[i]); i++) get_symbol_str(&res, sym, head); if (!i) - str_append(&res, _("No matches found.\n")); + str_append(&res, "No matches found.\n"); return res; } @@ -873,7 +870,7 @@ void menu_get_ext_help(struct menu *menu, struct gstr *help) str_printf(help, "%s%s:\n\n", CONFIG_, sym->name); help_text = menu_get_help(menu); } - str_printf(help, "%s\n", _(help_text)); + str_printf(help, "%s\n", help_text); if (sym) get_symbol_str(help, sym, NULL); } diff --git a/kconfig/nconf.c b/kconfig/nconf.c index be76120..4875f5e 100644 --- a/kconfig/nconf.c +++ b/kconfig/nconf.c @@ -15,7 +15,7 @@ #include "nconf.h" #include -static const char nconf_global_help[] = N_( +static const char nconf_global_help[] = "Help windows\n" "------------\n" "o Global help: Unless in a data entry window, pressing will give \n" @@ -133,8 +133,8 @@ static const char nconf_global_help[] = N_( "\n" "Note that this mode can eventually be a little more CPU expensive than\n" "the default mode, especially with a larger number of unfolded submenus.\n" -"\n"), -menu_no_f_instructions[] = N_( +"\n", +menu_no_f_instructions[] = "Legend: [*] built-in [ ] excluded automatic < > automatic capable.\n" "Submenus are designated by a trailing \"--->\", empty ones by \"----\".\n" "\n" @@ -150,8 +150,8 @@ menu_no_f_instructions[] = N_( "You do not have function keys support.\n" "Press <1> instead of , <2> instead of , etc.\n" "For verbose global help use key <1>.\n" -"For help related to the current menu entry press or .\n"), -menu_instructions[] = N_( +"For help related to the current menu entry press or .\n", +menu_instructions[] = "Legend: [*] built-in [ ] excluded automatic < > automatic capable.\n" "Submenus are designated by a trailing \"--->\", empty ones by \"----\".\n" "\n" @@ -166,30 +166,30 @@ menu_instructions[] = N_( "\n" "Pressing <1> may be used instead of , <2> instead of , etc.\n" "For verbose global help press .\n" -"For help related to the current menu entry press or .\n"), -radiolist_instructions[] = N_( +"For help related to the current menu entry press or .\n", +radiolist_instructions[] = "Press , , or to navigate a radiolist, select\n" "with .\n" "For help related to the current entry press or .\n" -"For global help press .\n"), -inputbox_instructions_int[] = N_( +"For global help press .\n", +inputbox_instructions_int[] = "Please enter a decimal value.\n" "Fractions will not be accepted.\n" -"Press to apply, to cancel."), -inputbox_instructions_hex[] = N_( +"Press to apply, to cancel.", +inputbox_instructions_hex[] = "Please enter a hexadecimal value.\n" -"Press to apply, to cancel."), -inputbox_instructions_string[] = N_( +"Press to apply, to cancel.", +inputbox_instructions_string[] = "Please enter a string value.\n" -"Press to apply, to cancel."), -setmod_text[] = N_( +"Press to apply, to cancel.", +setmod_text[] = "This feature depends on another feature which has been configured as\n" -"automatic. As a result, the current feature will be built as automatic too."), -load_config_text[] = N_( +"automatic. As a result, the current feature will be built as automatic too.", +load_config_text[] = "Enter the name of the configuration file you wish to load.\n" "Accept the name shown to restore the configuration you last\n" -"retrieved. Leave empty to abort."), -load_config_help[] = N_( +"retrieved. Leave empty to abort.", +load_config_help[] = "For various reasons, one may wish to keep several different\n" "configurations available on a single machine.\n" "\n" @@ -197,11 +197,11 @@ load_config_help[] = N_( "default one, entering its name here will allow you to load and modify\n" "that configuration.\n" "\n" -"Leave empty to abort.\n"), -save_config_text[] = N_( +"Leave empty to abort.\n", +save_config_text[] = "Enter a filename to which this configuration should be saved\n" -"as an alternate. Leave empty to abort."), -save_config_help[] = N_( +"as an alternate. Leave empty to abort.", +save_config_help[] = "For various reasons, one may wish to keep several different\n" "configurations available on a single machine.\n" "\n" @@ -209,8 +209,8 @@ save_config_help[] = N_( "and use the current configuration as an alternate to whatever\n" "configuration options you have selected at that time.\n" "\n" -"Leave empty to abort.\n"), -search_help[] = N_( +"Leave empty to abort.\n", +search_help[] = "Search for symbols (configuration variable names CONFIG_*) and display\n" "their relations. Regular expressions are supported.\n" "Example: Search for \"^FOO\".\n" @@ -247,7 +247,7 @@ search_help[] = N_( "USB => find all symbols containing USB\n" "^USB => find all symbols starting with USB\n" "USB$ => find all symbols ending with USB\n" -"\n"); +"\n"; struct mitem { char str[256]; @@ -391,7 +391,7 @@ static void print_function_line(void) static void handle_f1(int *key, struct menu *current_item) { show_scroll_win(main_window, - _("Global help"), _(nconf_global_help)); + "Global help", nconf_global_help); return; } @@ -406,8 +406,8 @@ static void handle_f2(int *key, struct menu *current_item) static void handle_f3(int *key, struct menu *current_item) { show_scroll_win(main_window, - _("Short help"), - _(current_instructions)); + "Short help", + current_instructions); return; } @@ -415,7 +415,7 @@ static void handle_f3(int *key, struct menu *current_item) static void handle_f4(int *key, struct menu *current_item) { int res = btn_dialog(main_window, - _("Show all symbols?"), + "Show all symbols?", 2, " ", ""); @@ -656,8 +656,8 @@ static int do_exit(void) return 0; } res = btn_dialog(main_window, - _("Do you wish to save your new configuration?\n" - " to cancel and resume nconfig."), + "Do you wish to save your new configuration?\n" + " to cancel and resume nconfig.", 2, " ", ""); @@ -673,15 +673,15 @@ static int do_exit(void) if (res) btn_dialog( main_window, - _("Error during writing of configuration.\n" - "Your configuration changes were NOT saved."), + "Error during writing of configuration.\n" + "Your configuration changes were NOT saved.", 1, ""); break; default: btn_dialog( main_window, - _("Your configuration changes were NOT saved."), + "Your configuration changes were NOT saved.", 1, ""); break; @@ -700,12 +700,12 @@ static void search_conf(void) int dres; title = str_new(); - str_printf( &title, _("Enter (sub)string or regexp to search for " - "(with or without \"%s\")"), CONFIG_); + str_printf( &title, "Enter (sub)string or regexp to search for " + "(with or without \"%s\")", CONFIG_); again: dres = dialog_inputbox(main_window, - _("Search Configuration Parameter"), + "Search Configuration Parameter", str_get(&title), "", &dialog_input_result, &dialog_input_result_len); switch (dres) { @@ -713,7 +713,7 @@ again: break; case 1: show_scroll_win(main_window, - _("Search Configuration"), search_help); + "Search Configuration", search_help); goto again; default: str_free(&title); @@ -729,7 +729,7 @@ again: res = get_relations_str(sym_arr, NULL); free(sym_arr); show_scroll_win(main_window, - _("Search Results"), str_get(&res)); + "Search Results", str_get(&res)); str_free(&res); str_free(&title); } @@ -757,7 +757,7 @@ static void build_conf(struct menu *menu) switch (ptype) { case P_MENU: child_count++; - prompt = _(prompt); + prompt = prompt; if (single_menu_mode) { item_make(menu, 'm', "%s%*c%s", @@ -778,7 +778,7 @@ static void build_conf(struct menu *menu) item_make(menu, ':', " %*c*** %s ***", indent + 1, ' ', - _(prompt)); + prompt); } break; default: @@ -786,7 +786,7 @@ static void build_conf(struct menu *menu) child_count++; item_make(menu, ':', "---%*c%s", indent + 1, ' ', - _(prompt)); + prompt); } } } else @@ -832,11 +832,11 @@ static void build_conf(struct menu *menu) } item_add_str("%*c%s", indent + 1, - ' ', _(menu_get_prompt(menu))); + ' ', menu_get_prompt(menu)); if (val == yes) { if (def_menu) { item_add_str(" (%s)", - _(menu_get_prompt(def_menu))); + menu_get_prompt(def_menu)); item_add_str(" --->"); if (def_menu->list) { indent += 2; @@ -850,7 +850,7 @@ static void build_conf(struct menu *menu) if (menu == current_menu) { item_make(menu, ':', "---%*c%s", indent + 1, - ' ', _(menu_get_prompt(menu))); + ' ', menu_get_prompt(menu)); goto conf_childs; } child_count++; @@ -897,17 +897,17 @@ static void build_conf(struct menu *menu) if (tmp < 0) tmp = 0; item_add_str("%*c%s%s", tmp, ' ', - _(menu_get_prompt(menu)), + menu_get_prompt(menu), (sym_has_value(sym) || !sym_is_changable(sym)) ? "" : - _(" (NEW)")); + " (NEW)"); goto conf_childs; } } item_add_str("%*c%s%s", indent + 1, ' ', - _(menu_get_prompt(menu)), + menu_get_prompt(menu), (sym_has_value(sym) || !sym_is_changable(sym)) ? - "" : _(" (NEW)")); + "" : " (NEW)"); if (menu->prompt && menu->prompt->type == P_MENU) { item_add_str(" %s", menu_is_empty(menu) ? "----" : "--->"); return; @@ -1089,8 +1089,8 @@ static void conf(struct menu *menu) if (!child_count) break; - show_menu(prompt ? _(prompt) : _("Main Menu"), - _(menu_instructions), + show_menu(prompt ? prompt : "Main Menu", + menu_instructions, current_index, &last_top_row); keypad((menu_win(curses_menu)), TRUE); while (!global_exit) { @@ -1230,13 +1230,13 @@ static void show_help(struct menu *menu) help = str_new(); menu_get_ext_help(menu, &help); - show_scroll_win(main_window, _(menu_get_prompt(menu)), str_get(&help)); + show_scroll_win(main_window, menu_get_prompt(menu), str_get(&help)); str_free(&help); } static void conf_choice(struct menu *menu) { - const char *prompt = _(menu_get_prompt(menu)); + const char *prompt = menu_get_prompt(menu); struct menu *child = NULL; struct symbol *active; int selected_index = 0; @@ -1259,13 +1259,13 @@ static void conf_choice(struct menu *menu) if (child->sym == sym_get_choice_value(menu->sym)) item_make(child, ':', " %s", - _(menu_get_prompt(child))); + menu_get_prompt(child)); else if (child->sym) item_make(child, ':', " %s", - _(menu_get_prompt(child))); + menu_get_prompt(child)); else item_make(child, ':', "*** %s ***", - _(menu_get_prompt(child))); + menu_get_prompt(child)); if (child->sym == active){ last_top_row = top_row(curses_menu); @@ -1273,8 +1273,8 @@ static void conf_choice(struct menu *menu) } i++; } - show_menu(prompt ? _(prompt) : _("Choice Menu"), - _(radiolist_instructions), + show_menu(prompt ? prompt : "Choice Menu", + radiolist_instructions, selected_index, &last_top_row); while (!global_exit) { @@ -1361,19 +1361,19 @@ static void conf_string(struct menu *menu) switch (sym_get_type(menu->sym)) { case S_INT: - heading = _(inputbox_instructions_int); + heading = inputbox_instructions_int; break; case S_HEX: - heading = _(inputbox_instructions_hex); + heading = inputbox_instructions_hex; break; case S_STRING: - heading = _(inputbox_instructions_string); + heading = inputbox_instructions_string; break; default: - heading = _("Internal nconf error!"); + heading = "Internal nconf error!"; } res = dialog_inputbox(main_window, - prompt ? _(prompt) : _("Main Menu"), + prompt ? prompt : "Main Menu", heading, sym_get_string_value(menu->sym), &dialog_input_result, @@ -1384,7 +1384,7 @@ static void conf_string(struct menu *menu) dialog_input_result)) return; btn_dialog(main_window, - _("You have made an invalid entry."), 0); + "You have made an invalid entry.", 0); break; case 1: show_help(menu); @@ -1413,11 +1413,11 @@ static void conf_load(void) sym_set_change_count(1); return; } - btn_dialog(main_window, _("File does not exist!"), 0); + btn_dialog(main_window, "File does not exist!", 0); break; case 1: show_scroll_win(main_window, - _("Load Alternate Configuration"), + "Load Alternate Configuration", load_config_help); break; case KEY_EXIT: @@ -1444,13 +1444,13 @@ static void conf_save(void) set_config_filename(dialog_input_result); return; } - btn_dialog(main_window, _("Can't create file! " - "Probably a nonexistent directory."), + btn_dialog(main_window, "Can't create file! " + "Probably a nonexistent directory.", 1, ""); break; case 1: show_scroll_win(main_window, - _("Save Alternate Configuration"), + "Save Alternate Configuration", save_config_help); break; case KEY_EXIT: @@ -1483,10 +1483,6 @@ int main(int ac, char **av) int lines, columns; char *mode; - setlocale(LC_ALL, ""); - bindtextdomain(PACKAGE, LOCALEDIR); - textdomain(PACKAGE); - if (ac > 1 && strcmp(av[1], "-s") == 0) { /* Silence conf_read() until the real callback is set up */ conf_set_message_callback(NULL); @@ -1544,8 +1540,8 @@ int main(int ac, char **av) /* check for KEY_FUNC(1) */ if (has_key(KEY_F(1)) == FALSE) { show_scroll_win(main_window, - _("Instructions"), - _(menu_no_f_instructions)); + "Instructions", + menu_no_f_instructions); } conf_set_message_callback(conf_message_callback); diff --git a/kconfig/nconf.h b/kconfig/nconf.h index 9f6f21d..2b9e19f 100644 --- a/kconfig/nconf.h +++ b/kconfig/nconf.h @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include diff --git a/kconfig/preprocess.c b/kconfig/preprocess.c new file mode 100644 index 0000000..5ca2df7 --- /dev/null +++ b/kconfig/preprocess.c @@ -0,0 +1,572 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (C) 2018 Masahiro Yamada + +#include +#include +#include +#include +#include + +#include "list.h" + +#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) + +static char *expand_string_with_args(const char *in, int argc, char *argv[]); + +static void __attribute__((noreturn)) pperror(const char *format, ...) +{ + va_list ap; + + fprintf(stderr, "%s:%d: ", current_file->name, yylineno); + va_start(ap, format); + vfprintf(stderr, format, ap); + va_end(ap); + fprintf(stderr, "\n"); + + exit(1); +} + +/* + * Environment variables + */ +static LIST_HEAD(env_list); + +struct env { + char *name; + char *value; + struct list_head node; +}; + +static void env_add(const char *name, const char *value) +{ + struct env *e; + + e = xmalloc(sizeof(*e)); + e->name = xstrdup(name); + e->value = xstrdup(value); + + list_add_tail(&e->node, &env_list); +} + +static void env_del(struct env *e) +{ + list_del(&e->node); + free(e->name); + free(e->value); + free(e); +} + +/* The returned pointer must be freed when done */ +static char *env_expand(const char *name) +{ + struct env *e; + const char *value; + + if (!*name) + return NULL; + + list_for_each_entry(e, &env_list, node) { + if (!strcmp(name, e->name)) + return xstrdup(e->value); + } + + value = getenv(name); + if (!value) + return NULL; + + /* + * We need to remember all referenced environment variables. + * They will be written out to include/config/auto.conf.cmd + */ + env_add(name, value); + + return xstrdup(value); +} + +void env_write_dep(FILE *f, const char *autoconfig_name) +{ + struct env *e, *tmp; + + list_for_each_entry_safe(e, tmp, &env_list, node) { + fprintf(f, "ifneq \"$(%s)\" \"%s\"\n", e->name, e->value); + fprintf(f, "%s: FORCE\n", autoconfig_name); + fprintf(f, "endif\n"); + env_del(e); + } +} + +/* + * Built-in functions + */ +struct function { + const char *name; + unsigned int min_args; + unsigned int max_args; + char *(*func)(int argc, char *argv[]); +}; + +static char *do_error_if(int argc, char *argv[]) +{ + if (!strcmp(argv[0], "y")) + pperror("%s", argv[1]); + + return NULL; +} + +static char *do_filename(int argc, char *argv[]) +{ + return xstrdup(current_file->name); +} + +static char *do_info(int argc, char *argv[]) +{ + printf("%s\n", argv[0]); + + return xstrdup(""); +} + +static char *do_lineno(int argc, char *argv[]) +{ + char buf[16]; + + sprintf(buf, "%d", yylineno); + + return xstrdup(buf); +} + +static char *do_shell(int argc, char *argv[]) +{ + FILE *p; + char buf[256]; + char *cmd; + size_t nread; + int i; + + cmd = argv[0]; + + p = popen(cmd, "r"); + if (!p) { + perror(cmd); + exit(1); + } + + nread = fread(buf, 1, sizeof(buf), p); + if (nread == sizeof(buf)) + nread--; + + /* remove trailing new lines */ + while (nread > 0 && buf[nread - 1] == '\n') + nread--; + + buf[nread] = 0; + + /* replace a new line with a space */ + for (i = 0; i < nread; i++) { + if (buf[i] == '\n') + buf[i] = ' '; + } + + if (pclose(p) == -1) { + perror(cmd); + exit(1); + } + + return xstrdup(buf); +} + +static char *do_warning_if(int argc, char *argv[]) +{ + if (!strcmp(argv[0], "y")) + fprintf(stderr, "%s:%d: %s\n", + current_file->name, yylineno, argv[1]); + + return xstrdup(""); +} + +static const struct function function_table[] = { + /* Name MIN MAX Function */ + { "error-if", 2, 2, do_error_if }, + { "filename", 0, 0, do_filename }, + { "info", 1, 1, do_info }, + { "lineno", 0, 0, do_lineno }, + { "shell", 1, 1, do_shell }, + { "warning-if", 2, 2, do_warning_if }, +}; + +#define FUNCTION_MAX_ARGS 16 + +static char *function_expand(const char *name, int argc, char *argv[]) +{ + const struct function *f; + int i; + + for (i = 0; i < ARRAY_SIZE(function_table); i++) { + f = &function_table[i]; + if (strcmp(f->name, name)) + continue; + + if (argc < f->min_args) + pperror("too few function arguments passed to '%s'", + name); + + if (argc > f->max_args) + pperror("too many function arguments passed to '%s'", + name); + + return f->func(argc, argv); + } + + return NULL; +} + +/* + * Variables (and user-defined functions) + */ +static LIST_HEAD(variable_list); + +struct variable { + char *name; + char *value; + enum variable_flavor flavor; + int exp_count; + struct list_head node; +}; + +static struct variable *variable_lookup(const char *name) +{ + struct variable *v; + + list_for_each_entry(v, &variable_list, node) { + if (!strcmp(name, v->name)) + return v; + } + + return NULL; +} + +static char *variable_expand(const char *name, int argc, char *argv[]) +{ + struct variable *v; + char *res; + + v = variable_lookup(name); + if (!v) + return NULL; + + if (argc == 0 && v->exp_count) + pperror("Recursive variable '%s' references itself (eventually)", + name); + + if (v->exp_count > 1000) + pperror("Too deep recursive expansion"); + + v->exp_count++; + + if (v->flavor == VAR_RECURSIVE) + res = expand_string_with_args(v->value, argc, argv); + else + res = xstrdup(v->value); + + v->exp_count--; + + return res; +} + +void variable_add(const char *name, const char *value, + enum variable_flavor flavor) +{ + struct variable *v; + char *new_value; + bool append = false; + + v = variable_lookup(name); + if (v) { + /* For defined variables, += inherits the existing flavor */ + if (flavor == VAR_APPEND) { + flavor = v->flavor; + append = true; + } else { + free(v->value); + } + } else { + /* For undefined variables, += assumes the recursive flavor */ + if (flavor == VAR_APPEND) + flavor = VAR_RECURSIVE; + + v = xmalloc(sizeof(*v)); + v->name = xstrdup(name); + v->exp_count = 0; + list_add_tail(&v->node, &variable_list); + } + + v->flavor = flavor; + + if (flavor == VAR_SIMPLE) + new_value = expand_string(value); + else + new_value = xstrdup(value); + + if (append) { + v->value = xrealloc(v->value, + strlen(v->value) + strlen(new_value) + 2); + strcat(v->value, " "); + strcat(v->value, new_value); + free(new_value); + } else { + v->value = new_value; + } +} + +static void variable_del(struct variable *v) +{ + list_del(&v->node); + free(v->name); + free(v->value); + free(v); +} + +void variable_all_del(void) +{ + struct variable *v, *tmp; + + list_for_each_entry_safe(v, tmp, &variable_list, node) + variable_del(v); +} + +/* + * Evaluate a clause with arguments. argc/argv are arguments from the upper + * function call. + * + * Returned string must be freed when done + */ +static char *eval_clause(const char *str, size_t len, int argc, char *argv[]) +{ + char *tmp, *name, *res, *endptr, *prev, *p; + int new_argc = 0; + char *new_argv[FUNCTION_MAX_ARGS]; + int nest = 0; + int i; + unsigned long n; + + tmp = xstrndup(str, len); + + /* + * If variable name is '1', '2', etc. It is generally an argument + * from a user-function call (i.e. local-scope variable). If not + * available, then look-up global-scope variables. + */ + n = strtoul(tmp, &endptr, 10); + if (!*endptr && n > 0 && n <= argc) { + res = xstrdup(argv[n - 1]); + goto free_tmp; + } + + prev = p = tmp; + + /* + * Split into tokens + * The function name and arguments are separated by a comma. + * For example, if the function call is like this: + * $(foo,$(x),$(y)) + * + * The input string for this helper should be: + * foo,$(x),$(y) + * + * and split into: + * new_argv[0] = 'foo' + * new_argv[1] = '$(x)' + * new_argv[2] = '$(y)' + */ + while (*p) { + if (nest == 0 && *p == ',') { + *p = 0; + if (new_argc >= FUNCTION_MAX_ARGS) + pperror("too many function arguments"); + new_argv[new_argc++] = prev; + prev = p + 1; + } else if (*p == '(') { + nest++; + } else if (*p == ')') { + nest--; + } + + p++; + } + new_argv[new_argc++] = prev; + + /* + * Shift arguments + * new_argv[0] represents a function name or a variable name. Put it + * into 'name', then shift the rest of the arguments. This simplifies + * 'const' handling. + */ + name = expand_string_with_args(new_argv[0], argc, argv); + new_argc--; + for (i = 0; i < new_argc; i++) + new_argv[i] = expand_string_with_args(new_argv[i + 1], + argc, argv); + + /* Search for variables */ + res = variable_expand(name, new_argc, new_argv); + if (res) + goto free; + + /* Look for built-in functions */ + res = function_expand(name, new_argc, new_argv); + if (res) + goto free; + + /* Last, try environment variable */ + if (new_argc == 0) { + res = env_expand(name); + if (res) + goto free; + } + + res = xstrdup(""); +free: + for (i = 0; i < new_argc; i++) + free(new_argv[i]); + free(name); +free_tmp: + free(tmp); + + return res; +} + +/* + * Expand a string that follows '$' + * + * For example, if the input string is + * ($(FOO)$($(BAR)))$(BAZ) + * this helper evaluates + * $($(FOO)$($(BAR))) + * and returns a new string containing the expansion (note that the string is + * recursively expanded), also advancing 'str' to point to the next character + * after the corresponding closing parenthesis, in this case, *str will be + * $(BAR) + */ +static char *expand_dollar_with_args(const char **str, int argc, char *argv[]) +{ + const char *p = *str; + const char *q; + int nest = 0; + + /* + * In Kconfig, variable/function references always start with "$(". + * Neither single-letter variables as in $A nor curly braces as in ${CC} + * are supported. '$' not followed by '(' loses its special meaning. + */ + if (*p != '(') { + *str = p; + return xstrdup("$"); + } + + p++; + q = p; + while (*q) { + if (*q == '(') { + nest++; + } else if (*q == ')') { + if (nest-- == 0) + break; + } + q++; + } + + if (!*q) + pperror("unterminated reference to '%s': missing ')'", p); + + /* Advance 'str' to after the expanded initial portion of the string */ + *str = q + 1; + + return eval_clause(p, q - p, argc, argv); +} + +char *expand_dollar(const char **str) +{ + return expand_dollar_with_args(str, 0, NULL); +} + +static char *__expand_string(const char **str, bool (*is_end)(char c), + int argc, char *argv[]) +{ + const char *in, *p; + char *expansion, *out; + size_t in_len, out_len; + + out = xmalloc(1); + *out = 0; + out_len = 1; + + p = in = *str; + + while (1) { + if (*p == '$') { + in_len = p - in; + p++; + expansion = expand_dollar_with_args(&p, argc, argv); + out_len += in_len + strlen(expansion); + out = xrealloc(out, out_len); + strncat(out, in, in_len); + strcat(out, expansion); + free(expansion); + in = p; + continue; + } + + if (is_end(*p)) + break; + + p++; + } + + in_len = p - in; + out_len += in_len; + out = xrealloc(out, out_len); + strncat(out, in, in_len); + + /* Advance 'str' to the end character */ + *str = p; + + return out; +} + +static bool is_end_of_str(char c) +{ + return !c; +} + +/* + * Expand variables and functions in the given string. Undefined variables + * expand to an empty string. + * The returned string must be freed when done. + */ +static char *expand_string_with_args(const char *in, int argc, char *argv[]) +{ + return __expand_string(&in, is_end_of_str, argc, argv); +} + +char *expand_string(const char *in) +{ + return expand_string_with_args(in, 0, NULL); +} + +static bool is_end_of_token(char c) +{ + /* Why are '.' and '/' valid characters for symbols? */ + return !(isalnum(c) || c == '_' || c == '-' || c == '.' || c == '/'); +} + +/* + * Expand variables in a token. The parsing stops when a token separater + * (in most cases, it is a whitespace) is encountered. 'str' is updated to + * point to the next character. + * + * The returned string must be freed when done. + */ +char *expand_one_token(const char **str) +{ + return __expand_string(str, is_end_of_token, 0, NULL); +} diff --git a/kconfig/symbol.c b/kconfig/symbol.c index f0b2e3b..7c9a88e 100644 --- a/kconfig/symbol.c +++ b/kconfig/symbol.c @@ -33,33 +33,6 @@ struct symbol *sym_defconfig_list; struct symbol *modules_sym; tristate modules_val; -struct expr *sym_env_list; - -static void sym_add_default(struct symbol *sym, const char *def) -{ - struct property *prop = prop_alloc(P_DEFAULT, sym); - - prop->expr = expr_alloc_symbol(sym_lookup(def, SYMBOL_CONST)); -} - -void sym_init(void) -{ - struct symbol *sym; - struct utsname uts; - static bool inited = false; - - if (inited) - return; - inited = true; - - uname(&uts); - - sym = sym_lookup("UNAME_RELEASE", 0); - sym->type = S_STRING; - sym->flags |= SYMBOL_AUTO; - sym_add_default(sym, uts.release); -} - enum symbol_type sym_get_type(struct symbol *sym) { enum symbol_type type = sym->type; @@ -906,59 +879,6 @@ struct symbol *sym_find(const char *name) return symbol; } -/* - * Expand symbol's names embedded in the string given in argument. Symbols' - * name to be expanded shall be prefixed by a '$'. Unknown symbol expands to - * the empty string. - */ -char *sym_expand_string_value(const char *in) -{ - const char *src; - char *res; - 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; - res = xmalloc(reslen); - res[0] = '\0'; - - while ((src = strchr(in, '$'))) { - char *p, name[SYMBOL_MAXLENGTH]; - const char *symval = ""; - struct symbol *sym; - size_t newlen; - - strncat(res, in, src - in); - src++; - - p = name; - while (isalnum(*src) || *src == '_') - *p++ = *src++; - *p = '\0'; - - sym = sym_find(name); - if (sym != NULL) { - sym_calc_value(sym); - symval = sym_get_string_value(sym); - } - - newlen = strlen(res) + strlen(symval) + strlen(src) + 1; - if (newlen > reslen) { - reslen = newlen; - res = xrealloc(res, reslen); - } - - strcat(res, symval); - in = src; - } - strcat(res, in); - - return res; -} - const char *sym_escape_string_value(const char *in) { const char *p; @@ -1401,32 +1321,3 @@ const char *prop_get_type_name(enum prop_type type) } return "unknown"; } - -static void prop_add_env(const char *env) -{ - struct symbol *sym, *sym2; - struct property *prop; - char *p; - - sym = current_entry->sym; - sym->flags |= SYMBOL_AUTO; - for_all_properties(sym, prop, P_ENV) { - sym2 = prop_get_symbol(prop); - if (strcmp(sym2->name, env)) - menu_warn(current_entry, "redefining environment symbol from %s", - sym2->name); - return; - } - - prop = prop_alloc(P_ENV, sym); - prop->expr = expr_alloc_symbol(sym_lookup(env, SYMBOL_CONST)); - - sym_env_list = expr_alloc_one(E_LIST, sym_env_list); - sym_env_list->right.sym = sym; - - p = getenv(env); - if (p) - sym_add_default(sym, p); - else - menu_warn(current_entry, "environment variable %s undefined", env); -} diff --git a/kconfig/util.c b/kconfig/util.c index c6f6e21..a365594 100644 --- a/kconfig/util.c +++ b/kconfig/util.c @@ -14,18 +14,16 @@ struct file *file_lookup(const char *name) { struct file *file; - char *file_name = sym_expand_string_value(name); for (file = file_list; file; file = file->next) { if (!strcmp(name, file->name)) { - free(file_name); return file; } } file = xmalloc(sizeof(*file)); memset(file, 0, sizeof(*file)); - file->name = file_name; + file->name = xstrdup(name); file->next = file_list; file_list = file; return file; @@ -34,8 +32,6 @@ struct file *file_lookup(const char *name) /* write a dependency file as used by kbuild to track dependencies */ int file_write_dep(const char *name) { - struct symbol *sym, *env_sym; - struct expr *e; struct file *file; FILE *out; @@ -54,21 +50,7 @@ int file_write_dep(const char *name) fprintf(out, "\n%s: \\\n" "\t$(deps_config)\n\n", conf_get_autoconfig_name()); - expr_list_for_each_sym(sym_env_list, e, sym) { - struct property *prop; - const char *value; - - prop = sym_get_env_prop(sym); - env_sym = prop_get_symbol(prop); - if (!env_sym) - continue; - value = getenv(env_sym->name); - if (!value) - value = ""; - fprintf(out, "ifneq \"$(%s)\" \"%s\"\n", env_sym->name, value); - fprintf(out, "%s: FORCE\n", conf_get_autoconfig_name()); - fprintf(out, "endif\n"); - } + env_write_dep(out, conf_get_autoconfig_name()); fprintf(out, "\n$(deps_config): ;\n"); fclose(out); @@ -165,3 +147,14 @@ char *xstrdup(const char *s) fprintf(stderr, "Out of memory.\n"); exit(1); } + +char *xstrndup(const char *s, size_t n) +{ + char *p; + + p = strndup(s, n); + if (p) + return p; + fprintf(stderr, "Out of memory.\n"); + exit(1); +} diff --git a/kconfig/zconf.l b/kconfig/zconf.l index 045093d..25bd2b8 100644 --- a/kconfig/zconf.l +++ b/kconfig/zconf.l @@ -1,13 +1,13 @@ %option nostdinit noyywrap never-interactive full ecs %option 8bit nodefault yylineno -%option noinput -%x COMMAND HELP STRING PARAM +%x COMMAND HELP STRING PARAM ASSIGN_VAL %{ /* * Copyright (C) 2002 Roman Zippel * Released under the terms of the GNU GPL v2.0. */ +#include #include #include #include @@ -35,6 +35,8 @@ struct buffer *current_buf; static int last_ts, first_ts; +static char *expand_token(const char *in, size_t n); +static void append_expanded_string(const char *in); static void zconf_endhelp(void); static void zconf_endfile(void); @@ -101,17 +103,28 @@ n [A-Za-z0-9_-] { {n}+ { const struct kconf_id *id = kconf_id_lookup(yytext, yyleng); - BEGIN(PARAM); current_pos.file = current_file; current_pos.lineno = yylineno; if (id && id->flags & TF_COMMAND) { + BEGIN(PARAM); yylval.id = id; return id->token; } alloc_string(yytext, yyleng); yylval.string = text; - return T_WORD; + return T_VARIABLE; } + ({n}|$)+ { + /* this token includes at least one '$' */ + yylval.string = expand_token(yytext, yyleng); + if (strlen(yylval.string)) + return T_VARIABLE; + free(yylval.string); + } + "=" { BEGIN(ASSIGN_VAL); yylval.flavor = VAR_RECURSIVE; return T_ASSIGN; } + ":=" { BEGIN(ASSIGN_VAL); yylval.flavor = VAR_SIMPLE; return T_ASSIGN; } + "+=" { BEGIN(ASSIGN_VAL); yylval.flavor = VAR_APPEND; return T_ASSIGN; } + [[:blank:]]+ . warn_ignored_character(*yytext); \n { BEGIN(INITIAL); @@ -119,6 +132,16 @@ n [A-Za-z0-9_-] } } +{ + [^[:blank:]\n]+.* { + alloc_string(yytext, yyleng); + yylval.string = text; + return T_ASSIGN_VAL; + } + \n { BEGIN(INITIAL); return T_EOL; } + . +} + { "&&" return T_AND; "||" return T_OR; @@ -147,6 +170,13 @@ n [A-Za-z0-9_-] yylval.string = text; return T_WORD; } + ({n}|[/.$])+ { + /* this token includes at least one '$' */ + yylval.string = expand_token(yytext, yyleng); + if (strlen(yylval.string)) + return T_WORD; + free(yylval.string); + } #.* /* comment */ \\\n ; [[:blank:]]+ @@ -157,12 +187,13 @@ n [A-Za-z0-9_-] } { - [^'"\\\n]+/\n { + "$".* append_expanded_string(yytext); + [^$'"\\\n]+/\n { append_string(yytext, yyleng); yylval.string = text; return T_WORD_QUOTE; } - [^'"\\\n]+ { + [^$'"\\\n]+ { append_string(yytext, yyleng); } \\.?/\n { @@ -249,6 +280,58 @@ n [A-Za-z0-9_-] } %% +static char *expand_token(const char *in, size_t n) +{ + char *out; + int c; + char c2; + const char *rest, *end; + + new_string(); + append_string(in, n); + + /* get the whole line because we do not know the end of token. */ + while ((c = input()) != EOF) { + if (c == '\n') { + unput(c); + break; + } + c2 = c; + append_string(&c2, 1); + } + + rest = text; + out = expand_one_token(&rest); + + /* push back unused characters to the input stream */ + end = rest + strlen(rest); + while (end > rest) + unput(*--end); + + free(text); + + return out; +} + +static void append_expanded_string(const char *str) +{ + const char *end; + char *res; + + str++; + + res = expand_dollar(&str); + + /* push back unused characters to the input stream */ + end = str + strlen(str); + while (end > str) + unput(*--end); + + append_string(res, strlen(res)); + + free(res); +} + void zconf_starthelp(void) { new_string(); diff --git a/kconfig/zconf.y b/kconfig/zconf.y index 283ad36..1fd37c9 100644 --- a/kconfig/zconf.y +++ b/kconfig/zconf.y @@ -31,7 +31,7 @@ struct symbol *symbol_hash[SYMBOL_HASHSIZE]; static struct menu *current_menu, *current_entry; %} -%expect 32 +%expect 31 %union { @@ -41,6 +41,7 @@ static struct menu *current_menu, *current_entry; struct expr *expr; struct menu *menu; const struct kconf_id *id; + enum variable_flavor flavor; } %token T_MAINMENU @@ -77,6 +78,9 @@ static struct menu *current_menu, *current_entry; %token T_CLOSE_PAREN %token T_OPEN_PAREN %token T_EOL +%token T_VARIABLE +%token T_ASSIGN +%token T_ASSIGN_VAL %left T_OR %left T_AND @@ -92,7 +96,7 @@ static struct menu *current_menu, *current_entry; %type end %type option_name %type if_entry menu_entry choice_entry -%type symbol_option_arg word_opt +%type symbol_option_arg word_opt assign_val %destructor { fprintf(stderr, "%s:%d: missing end statement for this entry\n", @@ -109,7 +113,7 @@ static struct menu *current_menu, *current_entry; %% input: nl start | start; -start: mainmenu_stmt stmt_list | no_mainmenu_stmt stmt_list; +start: mainmenu_stmt stmt_list | stmt_list; /* mainmenu entry */ @@ -118,19 +122,6 @@ 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: /* empty */ | stmt_list common_stmt @@ -156,6 +147,7 @@ common_stmt: | config_stmt | menuconfig_stmt | source_stmt + | assignment_stmt ; option_error: @@ -345,7 +337,7 @@ choice_block: /* if entry */ -if_entry: T_IF expr nl +if_entry: T_IF expr T_EOL { printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno()); menu_add_entry(NULL); @@ -524,33 +516,43 @@ symbol: nonconst_symbol word_opt: /* empty */ { $$ = NULL; } | T_WORD +/* assignment statement */ + +assignment_stmt: T_VARIABLE T_ASSIGN assign_val T_EOL { variable_add($1, $3, $2); free($1); free($3); } + +assign_val: + /* empty */ { $$ = xstrdup(""); }; + | T_ASSIGN_VAL +; + %% void conf_parse(const char *name) { - const char *tmp; struct symbol *sym; int i; zconf_initscan(name); - sym_init(); _menu_init(); - #if YYDEBUG if (getenv("ZCONF_DEBUG")) yydebug = 1; #endif yyparse(); + + /* Variables are expanded in the parse phase. We can free them here. */ + variable_all_del(); + if (yynerrs) exit(1); if (!modules_sym) modules_sym = sym_find( "n" ); - tmp = rootmenu.prompt->text; - rootmenu.prompt->text = _(rootmenu.prompt->text); - rootmenu.prompt->text = sym_expand_string_value(rootmenu.prompt->text); - free((char*)tmp); + if (!menu_has_prompt(&rootmenu)) { + current_entry = &rootmenu; + menu_add_prompt(P_MENU, "Main menu", NULL); + } menu_finalize(&rootmenu); for_all_symbols(i, sym) { @@ -716,6 +718,10 @@ static void print_symbol(FILE *out, struct menu *menu) print_quoted_string(out, prop->text); fputc('\n', out); break; + case P_SYMBOL: + fputs( " symbol ", out); + fprintf(out, "%s\n", prop->sym->name); + break; default: fprintf(out, " unknown prop %d!\n", prop->type); break; @@ -782,3 +788,4 @@ void zconfdump(FILE *out) #include "expr.c" #include "symbol.c" #include "menu.c" +#include "preprocess.c" -- cgit v0.10.2-6-g49f6 From 8fbf528681d1fa64a5d6fa6286fbf6f256c10a80 Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Wed, 9 Dec 2020 21:42:54 +1300 Subject: config: Update environment variable usage Upstream changes in the way kconfig handles environment variables means we need to update our usage of them. Signed-off-by: Chris Packham diff --git a/config/config.in b/config/config.in index f941301..cc349aa 100644 --- a/config/config.in +++ b/config/config.in @@ -1,4 +1,4 @@ -mainmenu "crosstool-NG $CT_VERSION Configuration" +mainmenu "crosstool-NG $(CT_VERSION) Configuration" source "config/configure.in" source "config/global.in" source "config/target.in" diff --git a/config/global.in b/config/global.in index 94d2191..d2a5c5e 100644 --- a/config/global.in +++ b/config/global.in @@ -2,7 +2,7 @@ config VERSION string - option env="CT_VERSION" + default "$(CT_VERSION)" # Config version checking framework. If CONFIG_VERSION is unset in the current .config # or defconfig, it is loaded as 0 (possibly triggering a user prompt during 'ct-ng oldconfig'). @@ -16,13 +16,13 @@ config VERSION # i.e. 'ct-ng saveconfig' or 'ct-ng savedefconfig'. config VCHECK string - option env="CT_VCHECK" + default "$(CT_VCHECK)" # Kconfig's idiosynchrasy: it does not output the config settings declared with 'option env' # to the generated .config file. Must use one extra level of indirection. config CONFIG_VERSION_ENV string - option env="CT_CONFIG_VERSION_CURRENT" + default "$(CT_CONFIG_VERSION_CURRENT)" # Up-to-date version of the configuration file. If saving a defconfig, choose a default that # is guaranteed not to match - so that kconfig saves the value to .config. -- cgit v0.10.2-6-g49f6 From df94f6803fe17fd1030ef08ff0463e437b9323b9 Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Wed, 9 Dec 2020 21:53:59 +1300 Subject: kconfig: Sync with upstream v4.19 This commit introduces the following upstream changes: fd65465b7016 kconfig: do not require pkg-config on make {menu,n}config bc8d2e20a3eb kconfig: remove a spurious self-assignment 9a9ddcf47831 kconfig: suppress "configuration written to .config" for syncconfig 98a4afbfafd2 kconfig: fix "Can't open ..." in parallel build f498926c47aa kconfig: improve the recursive dependency report 5e8c5299d315 kconfig: report recursive dependency involving 'imply' f1575595d156 kconfig: error out when seeing recursive dependency 4bf6a9af0e91 kconfig: add build-only configurator targets 1880861226c1 kconfig: remove P_ENV property type c151272d1687 kconfig: remove unused sym_get_env_prop() function 56869d45e364 kconfig: fix the rule of mainmenu_stmt symbol 00c864f8903d kconfig: allow all config targets to write auto.conf if missing 16952b77d8b5 kconfig: make syncconfig update .config regardless of sym_change_count 79123b1389cc kconfig: create directories needed for syncconfig by itself adc18acf42a1 kconfig: remove unneeded directory generation from local*config 0608182ad542 kconfig: split out useful helpers in confdata.c a2ff4040151a kconfig: rename file_write_dep and move it to confdata.c 5accd7f3360e kconfig: handle format string before calling conf_message_callback() 693359f7ac90 kconfig: rename SYMBOL_AUTO to SYMBOL_NO_WRITE 4ab3b80159d4 kconfig: check for pkg-config on make {menu,n,g,x}config 8377bd2b9ee1 kbuild: Rename HOST_LOADLIBES to KBUILD_HOSTLDLIBS Signed-off-by: Chris Packham diff --git a/kconfig/conf.c b/kconfig/conf.c index abd5238..a0db354 100644 --- a/kconfig/conf.c +++ b/kconfig/conf.c @@ -475,6 +475,7 @@ int main(int ac, char **av) int opt; const char *name, *defconfig_file = NULL /* gcc uninit */; struct stat tmpstat; + int no_conf_write = 0; tty_stdio = isatty(0) && isatty(1); @@ -486,6 +487,11 @@ int main(int ac, char **av) input_mode = (enum input_mode)opt; switch (opt) { case syncconfig: + /* + * syncconfig is invoked during the build stage. + * Suppress distracting "configuration written to ..." + */ + conf_set_message_callback(NULL); sync_kconfig = 1; break; case defconfig: @@ -612,13 +618,14 @@ int main(int ac, char **av) } if (sync_kconfig) { - if (conf_get_changed()) { - name = getenv("KCONFIG_NOSILENTUPDATE"); - if (name && *name) { + name = getenv("KCONFIG_NOSILENTUPDATE"); + if (name && *name) { + if (conf_get_changed()) { fprintf(stderr, "\n*** The configuration requires explicit update.\n\n"); return 1; } + no_conf_write = 1; } } @@ -663,30 +670,33 @@ int main(int ac, char **av) break; } - if (sync_kconfig) { - /* 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)) { - fprintf(stderr, "\n*** Error during writing of the configuration.\n\n"); - exit(1); - } - /* In crosstool-NG, we do not use the autoconf stuff - if (conf_write_autoconf()) { - fprintf(stderr, "\n*** Error during update of the configuration.\n\n"); - return 1; - } */ - } else if (input_mode == savedefconfig) { + if (input_mode == savedefconfig) { if (conf_write_defconfig(defconfig_file)) { fprintf(stderr, "n*** Error while saving defconfig to: %s\n\n", defconfig_file); return 1; } } else if (input_mode != listnewconfig) { - if (conf_write(NULL)) { + if (!no_conf_write && conf_write(NULL)) { fprintf(stderr, "\n*** Error during writing of the configuration.\n\n"); exit(1); } + + /* + * Create auto.conf if it does not exist. + * This prevents GNU Make 4.1 or older from emitting + * "include/config/auto.conf: No such file or directory" + * in the top-level Makefile + * + * syncconfig always creates or updates auto.conf because it is + * used during the build. + */ + /* In crosstool-NG, we do not use the autoconf stuff + if (conf_write_autoconf(sync_kconfig) && sync_kconfig) { + fprintf(stderr, + "\n*** Error during sync of the configuration.\n\n"); + return 1; + }*/ } return 0; } diff --git a/kconfig/confdata.c b/kconfig/confdata.c index 39e2097..91d0a5c 100644 --- a/kconfig/confdata.c +++ b/kconfig/confdata.c @@ -16,6 +16,64 @@ #include "lkc.h" +/* return true if 'path' exists, false otherwise */ +static bool is_present(const char *path) +{ + struct stat st; + + return !stat(path, &st); +} + +/* return true if 'path' exists and it is a directory, false otherwise */ +static bool is_dir(const char *path) +{ + struct stat st; + + if (stat(path, &st)) + return 0; + + return S_ISDIR(st.st_mode); +} + +/* + * Create the parent directory of the given path. + * + * For example, if 'include/config/auto.conf' is given, create 'include/config'. + */ +static int make_parent_dir(const char *path) +{ + char tmp[PATH_MAX + 1]; + char *p; + + strncpy(tmp, path, sizeof(tmp)); + tmp[sizeof(tmp) - 1] = 0; + + /* Remove the base name. Just return if nothing is left */ + p = strrchr(tmp, '/'); + if (!p) + return 0; + *(p + 1) = 0; + + /* Just in case it is an absolute path */ + p = tmp; + while (*p == '/') + p++; + + while ((p = strchr(p, '/'))) { + *p = 0; + + /* skip if the directory exists */ + if (!is_dir(tmp) && mkdir(tmp, 0755)) + return -1; + + *p = '/'; + while (*p == '/') + p++; + } + + return 0; +} + struct conf_printer { void (*print_symbol)(FILE *, struct symbol *, const char *, void *); void (*print_comment)(FILE *, const char *, void *); @@ -43,16 +101,16 @@ static void conf_warning(const char *fmt, ...) conf_warnings++; } -static void conf_default_message_callback(const char *fmt, va_list ap) +static void conf_default_message_callback(const char *s) { printf("#\n# "); - vprintf(fmt, ap); + printf("%s", s); printf("\n#\n"); } -static void (*conf_message_callback) (const char *fmt, va_list ap) = +static void (*conf_message_callback)(const char *s) = conf_default_message_callback; -void conf_set_message_callback(void (*fn) (const char *fmt, va_list ap)) +void conf_set_message_callback(void (*fn)(const char *s)) { conf_message_callback = fn; } @@ -60,10 +118,15 @@ void conf_set_message_callback(void (*fn) (const char *fmt, va_list ap)) static void conf_message(const char *fmt, ...) { va_list ap; + char buf[4096]; + + if (!conf_message_callback) + return; va_start(ap, fmt); - if (conf_message_callback) - conf_message_callback(fmt, ap); + + vsnprintf(buf, sizeof(buf), fmt, ap); + conf_message_callback(buf); va_end(ap); } @@ -83,7 +146,6 @@ const char *conf_get_autoconfig_name(void) char *conf_get_default_confname(void) { - struct stat buf; static char fullname[PATH_MAX+1]; char *env, *name; @@ -91,7 +153,7 @@ char *conf_get_default_confname(void) env = getenv(SRCTREE); if (env) { sprintf(fullname, "%s/%s", env, name); - if (!stat(fullname, &buf)) + if (is_present(fullname)) return fullname; } return name; @@ -397,7 +459,7 @@ int conf_read(const char *name) for_all_symbols(i, sym) { sym_calc_value(sym); - if (sym_is_choice(sym) || (sym->flags & SYMBOL_AUTO)) + if (sym_is_choice(sym) || (sym->flags & SYMBOL_NO_WRITE)) continue; if (sym_has_value(sym) && (sym->flags & SYMBOL_WRITE)) { /* check that calculated value agrees with saved value */ @@ -725,10 +787,9 @@ int conf_write(const char *name) dirname[0] = 0; if (name && name[0]) { - struct stat st; char *slash; - if (!stat(name, &st) && S_ISDIR(st.st_mode)) { + if (is_dir(name)) { strcpy(dirname, name); strcat(dirname, "/"); basename = conf_get_configname(); @@ -813,26 +874,59 @@ next: return 0; } +/* write a dependency file as used by kbuild to track dependencies */ +static int conf_write_dep(const char *name) +{ + struct file *file; + FILE *out; + + if (!name) + name = ".kconfig.d"; + out = fopen("..config.tmp", "w"); + if (!out) + return 1; + fprintf(out, "deps_config := \\\n"); + for (file = file_list; file; file = file->next) { + if (file->next) + fprintf(out, "\t%s \\\n", file->name); + else + fprintf(out, "\t%s\n", file->name); + } + fprintf(out, "\n%s: \\\n" + "\t$(deps_config)\n\n", conf_get_autoconfig_name()); + + env_write_dep(out, conf_get_autoconfig_name()); + + fprintf(out, "\n$(deps_config): ;\n"); + fclose(out); + + if (make_parent_dir(name)) + return 1; + rename("..config.tmp", name); + return 0; +} + static int conf_split_config(void) { const char *name; char path[PATH_MAX+1]; char *s, *d, c; struct symbol *sym; - struct stat sb; int res, i, fd; name = conf_get_autoconfig_name(); conf_read_simple(name, S_DEF_AUTO); sym_calc_value(modules_sym); + if (make_parent_dir("include/config/foo.h")) + return 1; if (chdir("include/config")) return 1; res = 0; for_all_symbols(i, sym) { sym_calc_value(sym); - if ((sym->flags & SYMBOL_AUTO) || !sym->name) + if ((sym->flags & SYMBOL_NO_WRITE) || !sym->name) continue; if (sym->flags & SYMBOL_WRITE) { if (sym->flags & SYMBOL_DEF_AUTO) { @@ -897,19 +991,12 @@ static int conf_split_config(void) res = 1; break; } - /* - * Create directory components, - * unless they exist already. - */ - d = path; - while ((d = strchr(d, '/'))) { - *d = 0; - if (stat(path, &sb) && mkdir(path, 0755)) { - res = 1; - goto out; - } - *d++ = '/'; + + if (make_parent_dir(path)) { + res = 1; + goto out; } + /* Try it again. */ fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644); if (fd == -1) { @@ -926,16 +1013,20 @@ out: return res; } -int conf_write_autoconf(void) +int conf_write_autoconf(int overwrite) { struct symbol *sym; const char *name; + const char *autoconf_name = conf_get_autoconfig_name(); FILE *out, *tristate, *out_h; int i; + if (!overwrite && is_present(autoconf_name)) + return 0; + sym_clear_all_valid(); - file_write_dep("include/config/auto.conf.cmd"); + conf_write_dep("include/config/auto.conf.cmd"); if (conf_split_config()) return 1; @@ -982,19 +1073,26 @@ int conf_write_autoconf(void) name = getenv("KCONFIG_AUTOHEADER"); if (!name) name = "include/generated/autoconf.h"; + if (make_parent_dir(name)) + return 1; if (rename(".tmpconfig.h", name)) return 1; + name = getenv("KCONFIG_TRISTATE"); if (!name) name = "include/config/tristate.conf"; + if (make_parent_dir(name)) + return 1; if (rename(".tmpconfig_tristate", name)) return 1; - name = conf_get_autoconfig_name(); + + if (make_parent_dir(autoconf_name)) + return 1; /* * This must be the last step, kbuild has a dependency on auto.conf * and this marks the successful completion of the previous steps. */ - if (rename(".tmpconfig", name)) + if (rename(".tmpconfig", autoconf_name)) return 1; return 0; diff --git a/kconfig/expr.h b/kconfig/expr.h index f63b41b..7c329e1 100644 --- a/kconfig/expr.h +++ b/kconfig/expr.h @@ -141,7 +141,7 @@ struct symbol { #define SYMBOL_OPTIONAL 0x0100 /* choice is optional - values can be 'n' */ #define SYMBOL_WRITE 0x0200 /* write symbol to file (KCONFIG_CONFIG) */ #define SYMBOL_CHANGED 0x0400 /* ? */ -#define SYMBOL_AUTO 0x1000 /* value from environment variable */ +#define SYMBOL_NO_WRITE 0x1000 /* Symbol for internal use only; it will not be written */ #define SYMBOL_CHECKED 0x2000 /* used during dependency checking */ #define SYMBOL_WARNED 0x8000 /* warning has been issued */ @@ -185,7 +185,6 @@ enum prop_type { P_SELECT, /* select BAR */ P_IMPLY, /* imply BAR */ P_RANGE, /* range 7..100 (for a symbol) */ - P_ENV, /* value from environment variable */ P_SYMBOL, /* where a symbol is defined */ }; diff --git a/kconfig/lkc.h b/kconfig/lkc.h index ed3ff88..9eb7c83 100644 --- a/kconfig/lkc.h +++ b/kconfig/lkc.h @@ -97,7 +97,6 @@ void menu_set_type(int type); /* util.c */ struct file *file_lookup(const char *name); -int file_write_dep(const char *name); void *xmalloc(size_t size); void *xcalloc(size_t nmemb, size_t size); void *xrealloc(void *p, size_t size); @@ -126,7 +125,6 @@ const char *sym_get_string_default(struct symbol *sym); struct symbol *sym_check_deps(struct symbol *sym); struct property *prop_alloc(enum prop_type type, struct symbol *sym); struct symbol *prop_get_symbol(struct property *prop); -struct property *sym_get_env_prop(struct symbol *sym); static inline tristate sym_get_tristate_value(struct symbol *sym) { diff --git a/kconfig/lkc_proto.h b/kconfig/lkc_proto.h index a8b7a33..86c2675 100644 --- a/kconfig/lkc_proto.h +++ b/kconfig/lkc_proto.h @@ -7,10 +7,10 @@ int conf_read(const char *name); int conf_read_simple(const char *name, int); int conf_write_defconfig(const char *name); int conf_write(const char *name); -int conf_write_autoconf(void); +int conf_write_autoconf(int overwrite); bool conf_get_changed(void); void conf_set_changed_callback(void (*fn)(void)); -void conf_set_message_callback(void (*fn)(const char *fmt, va_list ap)); +void conf_set_message_callback(void (*fn)(const char *s)); /* menu.c */ extern struct menu rootmenu; diff --git a/kconfig/mconf.c b/kconfig/mconf.c index 9890dd4..c719f60 100644 --- a/kconfig/mconf.c +++ b/kconfig/mconf.c @@ -490,7 +490,6 @@ static void build_conf(struct menu *menu) switch (prop->type) { case P_MENU: child_count++; - prompt = prompt; if (single_menu_mode) { item_make("%s%*c%s", menu->data ? "-->" : "++>", @@ -772,16 +771,13 @@ static void show_helptext(const char *title, const char *text) show_textbox(title, text, 0, 0); } -static void conf_message_callback(const char *fmt, va_list ap) +static void conf_message_callback(const char *s) { - char buf[PATH_MAX+1]; - - vsnprintf(buf, sizeof(buf), fmt, ap); if (save_and_exit) { if (!silent) - printf("%s", buf); + printf("%s", s); } else { - show_textbox(NULL, buf, 6, 60); + show_textbox(NULL, s, 6, 60); } } @@ -977,6 +973,7 @@ static int handle_exit(void) "\n\n"); return 1; } + conf_write_autoconf(0); /* fall through */ case -1: if (!silent) diff --git a/kconfig/menu.c b/kconfig/menu.c index fd919bd..539ff57 100644 --- a/kconfig/menu.c +++ b/kconfig/menu.c @@ -218,7 +218,7 @@ void menu_add_option(int token, char *arg) sym_defconfig_list = current_entry->sym; else if (sym_defconfig_list != current_entry->sym) zconf_error("trying to redefine defconfig symbol"); - sym_defconfig_list->flags |= SYMBOL_AUTO; + sym_defconfig_list->flags |= SYMBOL_NO_WRITE; break; case T_OPT_ALLNOCONFIG_Y: current_entry->sym->flags |= SYMBOL_ALLNOCONFIG_Y; diff --git a/kconfig/nconf.c b/kconfig/nconf.c index 4875f5e..93d186e 100644 --- a/kconfig/nconf.c +++ b/kconfig/nconf.c @@ -677,6 +677,7 @@ static int do_exit(void) "Your configuration changes were NOT saved.", 1, ""); + conf_write_autoconf(0); break; default: btn_dialog( @@ -1213,12 +1214,9 @@ static void conf(struct menu *menu) } } -static void conf_message_callback(const char *fmt, va_list ap) +static void conf_message_callback(const char *s) { - char buf[1024]; - - vsnprintf(buf, sizeof(buf), fmt, ap); - btn_dialog(main_window, buf, 1, ""); + btn_dialog(main_window, s, 1, ""); } static void show_help(struct menu *menu) diff --git a/kconfig/symbol.c b/kconfig/symbol.c index 7c9a88e..703b9b8 100644 --- a/kconfig/symbol.c +++ b/kconfig/symbol.c @@ -76,15 +76,6 @@ struct property *sym_get_choice_prop(struct symbol *sym) return NULL; } -struct property *sym_get_env_prop(struct symbol *sym) -{ - struct property *prop; - - for_all_properties(sym, prop, P_ENV) - return prop; - return NULL; -} - static struct property *sym_get_default_prop(struct symbol *sym) { struct property *prop; @@ -463,7 +454,7 @@ void sym_calc_value(struct symbol *sym) } } - if (sym->flags & SYMBOL_AUTO) + if (sym->flags & SYMBOL_NO_WRITE) sym->flags &= ~SYMBOL_WRITE; if (sym->flags & SYMBOL_NEED_SET_CHOICE_VALUES) @@ -1020,7 +1011,7 @@ static struct dep_stack { struct dep_stack *prev, *next; struct symbol *sym; struct property *prop; - struct expr *expr; + struct expr **expr; } *check_top; static void dep_stack_insert(struct dep_stack *stack, struct symbol *sym) @@ -1085,31 +1076,42 @@ static void sym_check_print_recursive(struct symbol *last_sym) fprintf(stderr, "%s:%d:error: recursive dependency detected!\n", prop->file->name, prop->lineno); - if (stack->expr) { - fprintf(stderr, "%s:%d:\tsymbol %s %s value contains %s\n", - prop->file->name, prop->lineno, + if (sym_is_choice(sym)) { + fprintf(stderr, "%s:%d:\tchoice %s contains symbol %s\n", + menu->file->name, menu->lineno, + sym->name ? sym->name : "", + next_sym->name ? next_sym->name : ""); + } else if (sym_is_choice_value(sym)) { + fprintf(stderr, "%s:%d:\tsymbol %s is part of choice %s\n", + menu->file->name, menu->lineno, sym->name ? sym->name : "", - prop_get_type_name(prop->type), next_sym->name ? next_sym->name : ""); - } else if (stack->prop) { + } else if (stack->expr == &sym->dir_dep.expr) { fprintf(stderr, "%s:%d:\tsymbol %s depends on %s\n", prop->file->name, prop->lineno, sym->name ? sym->name : "", next_sym->name ? next_sym->name : ""); - } else if (sym_is_choice(sym)) { - fprintf(stderr, "%s:%d:\tchoice %s contains symbol %s\n", - menu->file->name, menu->lineno, + } else if (stack->expr == &sym->rev_dep.expr) { + fprintf(stderr, "%s:%d:\tsymbol %s is selected by %s\n", + prop->file->name, prop->lineno, sym->name ? sym->name : "", next_sym->name ? next_sym->name : ""); - } else if (sym_is_choice_value(sym)) { - fprintf(stderr, "%s:%d:\tsymbol %s is part of choice %s\n", - menu->file->name, menu->lineno, + } else if (stack->expr == &sym->implied.expr) { + fprintf(stderr, "%s:%d:\tsymbol %s is implied by %s\n", + prop->file->name, prop->lineno, sym->name ? sym->name : "", next_sym->name ? next_sym->name : ""); + } else if (stack->expr) { + fprintf(stderr, "%s:%d:\tsymbol %s %s value contains %s\n", + prop->file->name, prop->lineno, + sym->name ? sym->name : "", + prop_get_type_name(prop->type), + next_sym->name ? next_sym->name : ""); } else { - fprintf(stderr, "%s:%d:\tsymbol %s is selected by %s\n", + fprintf(stderr, "%s:%d:\tsymbol %s %s is visible depending on %s\n", prop->file->name, prop->lineno, sym->name ? sym->name : "", + prop_get_type_name(prop->type), next_sym->name ? next_sym->name : ""); } } @@ -1166,12 +1168,26 @@ static struct symbol *sym_check_sym_deps(struct symbol *sym) dep_stack_insert(&stack, sym); + stack.expr = &sym->dir_dep.expr; + sym2 = sym_check_expr_deps(sym->dir_dep.expr); + if (sym2) + goto out; + + stack.expr = &sym->rev_dep.expr; sym2 = sym_check_expr_deps(sym->rev_dep.expr); if (sym2) goto out; + stack.expr = &sym->implied.expr; + sym2 = sym_check_expr_deps(sym->implied.expr); + if (sym2) + goto out; + + stack.expr = NULL; + for (prop = sym->prop; prop; prop = prop->next) { - if (prop->type == P_CHOICE || prop->type == P_SELECT) + if (prop->type == P_CHOICE || prop->type == P_SELECT || + prop->type == P_IMPLY) continue; stack.prop = prop; sym2 = sym_check_expr_deps(prop->visible.expr); @@ -1179,7 +1195,7 @@ static struct symbol *sym_check_sym_deps(struct symbol *sym) break; if (prop->type != P_DEFAULT || sym_is_choice(sym)) continue; - stack.expr = prop->expr; + stack.expr = &prop->expr; sym2 = sym_check_expr_deps(prop->expr); if (sym2) break; @@ -1257,9 +1273,6 @@ struct symbol *sym_check_deps(struct symbol *sym) sym->flags &= ~SYMBOL_CHECK; } - if (sym2 && sym2 == sym) - sym2 = NULL; - return sym2; } @@ -1298,8 +1311,6 @@ const char *prop_get_type_name(enum prop_type type) switch (type) { case P_PROMPT: return "prompt"; - case P_ENV: - return "env"; case P_COMMENT: return "comment"; case P_MENU: diff --git a/kconfig/util.c b/kconfig/util.c index a365594..d999683 100644 --- a/kconfig/util.c +++ b/kconfig/util.c @@ -29,36 +29,6 @@ struct file *file_lookup(const char *name) return file; } -/* write a dependency file as used by kbuild to track dependencies */ -int file_write_dep(const char *name) -{ - struct file *file; - FILE *out; - - if (!name) - name = ".kconfig.d"; - out = fopen("..config.tmp", "w"); - if (!out) - return 1; - fprintf(out, "deps_config := \\\n"); - for (file = file_list; file; file = file->next) { - if (file->next) - fprintf(out, "\t%s \\\n", file->name); - else - fprintf(out, "\t%s\n", file->name); - } - fprintf(out, "\n%s: \\\n" - "\t$(deps_config)\n\n", conf_get_autoconfig_name()); - - env_write_dep(out, conf_get_autoconfig_name()); - - fprintf(out, "\n$(deps_config): ;\n"); - fclose(out); - rename("..config.tmp", name); - return 0; -} - - /* Allocate initial growable string */ struct gstr str_new(void) { diff --git a/kconfig/zconf.y b/kconfig/zconf.y index 1fd37c9..9d331da 100644 --- a/kconfig/zconf.y +++ b/kconfig/zconf.y @@ -31,7 +31,7 @@ struct symbol *symbol_hash[SYMBOL_HASHSIZE]; static struct menu *current_menu, *current_entry; %} -%expect 31 +%expect 30 %union { @@ -117,7 +117,7 @@ start: mainmenu_stmt stmt_list | stmt_list; /* mainmenu entry */ -mainmenu_stmt: T_MAINMENU prompt nl +mainmenu_stmt: T_MAINMENU prompt T_EOL { menu_add_prompt(P_MENU, $2, NULL); }; @@ -265,7 +265,7 @@ symbol_option_arg: choice: T_CHOICE word_opt T_EOL { struct symbol *sym = sym_lookup($2, SYMBOL_CHOICE); - sym->flags |= SYMBOL_AUTO; + sym->flags |= SYMBOL_NO_WRITE; menu_add_entry(sym); menu_add_expr(P_CHOICE, NULL, NULL); free($2); -- cgit v0.10.2-6-g49f6 From b16baed494d3c3fb66eeaaf9d8c1dbc7c6c0479f Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Wed, 9 Dec 2020 21:55:38 +1300 Subject: kconfig: Sync with upstream v4.20 6bbe4385d035 kconfig: merge_config: avoid false positive matches from comment lines 2cd3faf87d2d merge_config.sh: Allow to define config prefix 0085b4191f3e kconfig: remove silentoldconfig target 04c459d20448 kconfig: remove oldnoconfig target Signed-off-by: Chris Packham diff --git a/kconfig/conf.c b/kconfig/conf.c index a0db354..5a795c5 100644 --- a/kconfig/conf.c +++ b/kconfig/conf.c @@ -460,12 +460,6 @@ static struct option long_opts[] = { {"randconfig", no_argument, NULL, randconfig}, {"listnewconfig", no_argument, NULL, listnewconfig}, {"olddefconfig", no_argument, NULL, olddefconfig}, - /* - * oldnoconfig is an alias of olddefconfig, because people already - * are dependent on its behavior(sets new symbols to their default - * value but not 'n') with the counter-intuitive name. - */ - {"oldnoconfig", no_argument, NULL, olddefconfig}, {NULL, 0, NULL, 0} }; -- cgit v0.10.2-6-g49f6 From 21095fab6712d3a082936b14b93cb6ff29c02872 Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Wed, 9 Dec 2020 22:13:29 +1300 Subject: kconfig: Sync with upstream v5.0 This commit introduces the following upstream changes: 2648ca1859bb kconfig: clean generated *conf-cfg files d86271af6460 kconfig: rename generated .*conf-cfg to *conf-cfg ba97df45581f kbuild: use assignment instead of define ... endef for filechk_* rules a5003571e627 kconfig: remove unused "file" field of yylval union f222b7f43661 kconfig: surround dbg_sym_flags with #ifdef DEBUG to fix gconf warning 3b541978562a kconfig: split images.c out of qconf.cc/gconf.c to fix gconf warnings 9abe42371b44 kconfig: add static qualifiers to fix gconf warnings cbafbf7f551c kconfig: split the lexer out of zconf.y 558e78e3ce84 kconfig: split some C files out of zconf.y 0c874100108f kconfig: convert to SPDX License Identifier 979f2b2f7936 kconfig: remove keyword lookup table entirely 4b31a32caf0a kconfig: update current_pos in the second lexer 824fa3b3b5e3 kconfig: switch to ASSIGN_VAL state in the second lexer b3d1d9d3c362 kconfig: stop associating kconf_id with yylval caaebb3c6de3 kconfig: refactor end token rules f5451582c4e2 kconfig: stop supporting '.' and '/' in unquoted words 171a515d0803 kconfig: use T_WORD instead of T_VARIABLE for variables c3d228713b10 kconfig: use specific tokens instead of T_ASSIGN for assignments ce2164ab5831 kconfig: refactor scanning and parsing "option" properties 3c8f317d4cf1 kconfig: use distinct tokens for type and default properties a01e5d242d93 kconfig: remove redundant token defines 4b5ec81bfeda kconfig: rename depends_list to comment_option_list 1f31be9ec0a9 kconfig: loosen the order of "visible" and "depends on" in menu entry 94d4e1b6021b kconfig: remove redundant menu_block rule 4891796c6f83 kconfig: remove redundant if_block rule 2f60e46e605a kconfig: remove grammatically ambiguous option_error 6900ae9eeee3 kconfig: remove grammatically ambiguous "unexpected option" diagnostic 723679339d08 kconfig: warn no new line at end of file 0bcc547ec4b0 kconfig: clean up EOF handling in the lexer cc66bca775ee kconfig: fix ambiguous grammar in terms of new lines 21c5ecf60472 kconfig: refactor pattern matching in STRING state be3c8075978a kconfig: remove unneeded pattern matching to whitespaces 413cd19d81fd kconfig: require T_EOL to reduce visible statement fbac5977d81c kconfig: fix memory leak when EOF is encountered in quotation 77c1c0fa8b14 kconfig: fix file name and line number of warn_ignored_character() 0cbe3ac439bf kconfig: remove k_invalid from expr_parse_string() return type 2aabbed6774f kconfig: remove S_OTHER symbol type and correct dependency tracking 1508fec82e39 kconfig: split out code touching a file to conf_touch_dep() 0849d212e395 kconfig: rename conf_split_config() to conf_touch_deps() 75889e9be78f kconfig: remove unneeded setsym label in conf_read_simple() a9b722847872 scripts/kconfig/merge_config: don't redefine 'y' to 'm' Signed-off-by: Chris Packham diff --git a/kconfig/Makefile.am b/kconfig/Makefile.am index 0523ea9..8245606 100644 --- a/kconfig/Makefile.am +++ b/kconfig/Makefile.am @@ -9,22 +9,23 @@ EXTRA_DIST = zconf.y zconf.l \ expr.h list.h lkc.h lkc_proto.h nconf.h lxdialog/dialog.h \ confdata.c expr.c kconf_id.c menu.c symbol.c util.c -CLEANFILES = zconf.lex.c zconf.c -BUILT_SOURCES = zconf.c zconf.lex.c +CLEANFILES = zconf.lex.c zconf.tab.c +BUILT_SOURCES = zconf.lex.c zconf.tab.c -AM_LFLAGS = -L -Pzconf -AM_YFLAGS = -l -b zconf -p zconf +AM_LFLAGS = -L +AM_YFLAGS = -t -l AM_CPPFLAGS = -include config.h -DCONFIG_=\"CT_\" AM_LIBTOOLFLAGS = --tag CC -conf_SOURCES = conf.c zconf.c +conf_SOURCES = conf.c confdata.c expr.c symbol.c preprocess.c zconf.lex.c zconf.tab.c conf_LDADD = $(LIBINTL) -nconf_SOURCES = nconf.c nconf.gui.c zconf.c +nconf_SOURCES = nconf.c nconf.gui.c confdata.c expr.c symbol.c preprocess.c zconf.lex.c zconf.tab.c nconf_CFLAGS = $(CURSES_CFLAGS) nconf_LDADD = $(MENU_LIBS) $(PANEL_LIBS) $(CURSES_LIBS) $(LIBINTL) -mconf_SOURCES = mconf.c zconf.c lxdialog/checklist.c lxdialog/inputbox.c \ +mconf_SOURCES = mconf.c confdata.c expr.c symbol.c preprocess.c zconf.lex.c zconf.tab.c \ + lxdialog/checklist.c lxdialog/inputbox.c \ lxdialog/menubox.c lxdialog/textbox.c lxdialog/util.c \ lxdialog/yesno.c mconf_LDADD = $(CURSES_LIBS) $(LIBINTL) @@ -42,8 +43,8 @@ AM_V_LEX = $(am__v_LEX_@AM_V@) am__v_LEX_ = $(am__v_LEX_@AM_DEFAULT_V@) am__v_LEX_0 = @echo " LEX " $@; -zconf.c: zconf.y - $(AM_V_YACC)$(YACCCOMPILE) -o$@ $< +zconf.tab.c: zconf.y + $(AM_V_YACC)$(YACCCOMPILE) -o$@ --defines=zconf.tab.h $< zconf.lex.c: zconf.l $(AM_V_LEX)$(LEXCOMPILE) -o$@ $< diff --git a/kconfig/conf.c b/kconfig/conf.c index 5a795c5..b86c7de 100644 --- a/kconfig/conf.c +++ b/kconfig/conf.c @@ -1,6 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2002 Roman Zippel - * Released under the terms of the GNU GPL v2.0. */ #include diff --git a/kconfig/confdata.c b/kconfig/confdata.c index 91d0a5c..08ba146 100644 --- a/kconfig/confdata.c +++ b/kconfig/confdata.c @@ -1,12 +1,13 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2002 Roman Zippel - * Released under the terms of the GNU GPL v2.0. */ #include #include #include #include +#include #include #include #include @@ -74,6 +75,47 @@ static int make_parent_dir(const char *path) return 0; } +static char depfile_path[PATH_MAX]; +static size_t depfile_prefix_len; + +/* touch depfile for symbol 'name' */ +static int conf_touch_dep(const char *name) +{ + int fd, ret; + const char *s; + char *d, c; + + /* check overflow: prefix + name + ".h" + '\0' must fit in buffer. */ + if (depfile_prefix_len + strlen(name) + 3 > sizeof(depfile_path)) + return -1; + + d = depfile_path + depfile_prefix_len; + s = name; + + while ((c = *s++)) + *d++ = (c == '_') ? '/' : tolower(c); + strcpy(d, ".h"); + + /* Assume directory path already exists. */ + fd = open(depfile_path, O_WRONLY | O_CREAT | O_TRUNC, 0644); + if (fd == -1) { + if (errno != ENOENT) + return -1; + + ret = make_parent_dir(depfile_path); + if (ret) + return ret; + + /* Try it again. */ + fd = open(depfile_path, O_WRONLY | O_CREAT | O_TRUNC, 0644); + if (fd == -1) + return -1; + } + close(fd); + + return 0; +} + struct conf_printer { void (*print_symbol)(FILE *, struct symbol *, const char *, void *); void (*print_comment)(FILE *, const char *, void *); @@ -186,14 +228,6 @@ static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p) conf_warning("symbol value '%s' invalid for %s", p, sym->name); return 1; - case S_OTHER: - if (*p != '"') { - for (p2 = p; *p2 && !isspace(*p2); p2++) - ; - sym->type = S_STRING; - goto done; - } - /* fall through */ case S_STRING: if (*p++ != '"') break; @@ -212,7 +246,6 @@ static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p) /* fall through */ case S_INT: case S_HEX: - done: if (sym_string_valid(sym, p)) { sym->def[def].val = xstrdup(p); sym->flags |= def_flags; @@ -363,7 +396,7 @@ load: sym = sym_find(line + 2 + strlen(CONFIG_)); if (!sym) { sym_add_change_count(1); - goto setsym; + continue; } } else { sym = sym_lookup(line + 2 + strlen(CONFIG_), 0); @@ -393,17 +426,22 @@ load: if (*p2 == '\r') *p2 = 0; } - if (def == S_DEF_USER) { - sym = sym_find(line + strlen(CONFIG_)); - if (!sym) { + + sym = sym_find(line + strlen(CONFIG_)); + if (!sym) { + if (def == S_DEF_AUTO) + /* + * Reading from include/config/auto.conf + * If CONFIG_FOO previously existed in + * auto.conf but it is missing now, + * include/config/foo.h must be touched. + */ + conf_touch_dep(line + strlen(CONFIG_)); + else sym_add_change_count(1); - goto setsym; - } - } else { - sym = sym_lookup(line + strlen(CONFIG_), 0); - if (sym->type == S_UNKNOWN) - sym->type = S_OTHER; + continue; } + if (sym->flags & def_flags) { conf_warning("override: reassigning to symbol %s", sym->name); } @@ -416,7 +454,7 @@ load: continue; } -setsym: + if (sym && sym_is_choice_value(sym)) { struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym)); switch (sym->def[def].tri) { @@ -669,7 +707,6 @@ static void conf_write_symbol(FILE *fp, struct symbol *sym, const char *str; switch (sym->type) { - case S_OTHER: case S_UNKNOWN: break; case S_STRING: @@ -906,24 +943,19 @@ static int conf_write_dep(const char *name) return 0; } -static int conf_split_config(void) +static int conf_touch_deps(void) { const char *name; - char path[PATH_MAX+1]; - char *s, *d, c; struct symbol *sym; - int res, i, fd; + int res, i; + + strcpy(depfile_path, "include/config/"); + depfile_prefix_len = strlen(depfile_path); name = conf_get_autoconfig_name(); conf_read_simple(name, S_DEF_AUTO); sym_calc_value(modules_sym); - if (make_parent_dir("include/config/foo.h")) - return 1; - if (chdir("include/config")) - return 1; - - res = 0; for_all_symbols(i, sym) { sym_calc_value(sym); if ((sym->flags & SYMBOL_NO_WRITE) || !sym->name) @@ -975,42 +1007,12 @@ static int conf_split_config(void) * different from 'no'). */ - /* Replace all '_' and append ".h" */ - s = sym->name; - d = path; - while ((c = *s++)) { - c = tolower(c); - *d++ = (c == '_') ? '/' : c; - } - strcpy(d, ".h"); - - /* Assume directory path already exists. */ - fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644); - if (fd == -1) { - if (errno != ENOENT) { - res = 1; - break; - } - - if (make_parent_dir(path)) { - res = 1; - goto out; - } - - /* Try it again. */ - fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644); - if (fd == -1) { - res = 1; - break; - } - } - close(fd); + res = conf_touch_dep(sym->name); + if (res) + return res; } -out: - if (chdir("../..")) - return 1; - return res; + return 0; } int conf_write_autoconf(int overwrite) @@ -1028,7 +1030,7 @@ int conf_write_autoconf(int overwrite) conf_write_dep("include/config/auto.conf.cmd"); - if (conf_split_config()) + if (conf_touch_deps()) return 1; out = fopen(".tmpconfig", "w"); diff --git a/kconfig/expr.c b/kconfig/expr.c index e1a39e9..77ffff3 100644 --- a/kconfig/expr.c +++ b/kconfig/expr.c @@ -1,8 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2002 Roman Zippel - * Released under the terms of the GNU GPL v2.0. */ +#include +#include #include #include #include @@ -980,7 +982,6 @@ enum string_value_kind { k_string, k_signed, k_unsigned, - k_invalid }; union string_value { @@ -1011,13 +1012,10 @@ static enum string_value_kind expr_parse_string(const char *str, val->u = strtoull(str, &tail, 16); kind = k_unsigned; break; - case S_STRING: - case S_UNKNOWN: + default: val->s = strtoll(str, &tail, 0); kind = k_signed; break; - default: - return k_invalid; } return !errno && !*tail && tail > str && isxdigit(tail[-1]) ? kind : k_string; @@ -1073,13 +1071,7 @@ tristate expr_calc_value(struct expr *e) if (k1 == k_string || k2 == k_string) res = strcmp(str1, str2); - else if (k1 == k_invalid || k2 == k_invalid) { - if (e->type != E_EQUAL && e->type != E_UNEQUAL) { - printf("Cannot compare \"%s\" and \"%s\"\n", str1, str2); - return no; - } - res = strcmp(str1, str2); - } else if (k1 == k_unsigned || k2 == k_unsigned) + else if (k1 == k_unsigned || k2 == k_unsigned) res = (lval.u > rval.u) - (lval.u < rval.u); else /* if (k1 == k_signed && k2 == k_signed) */ res = (lval.s > rval.s) - (lval.s < rval.s); diff --git a/kconfig/expr.h b/kconfig/expr.h index 7c329e1..999edb6 100644 --- a/kconfig/expr.h +++ b/kconfig/expr.h @@ -1,6 +1,6 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * Copyright (C) 2002 Roman Zippel - * Released under the terms of the GNU GPL v2.0. */ #ifndef EXPR_H @@ -62,7 +62,7 @@ struct symbol_value { }; enum symbol_type { - S_UNKNOWN, S_BOOLEAN, S_TRISTATE, S_INT, S_HEX, S_STRING, S_OTHER + S_UNKNOWN, S_BOOLEAN, S_TRISTATE, S_INT, S_HEX, S_STRING }; /* enum values are used as index to symbol.def[] */ @@ -131,7 +131,7 @@ struct symbol { struct expr_value implied; }; -#define for_all_symbols(i, sym) for (i = 0; i < SYMBOL_HASHSIZE; i++) for (sym = symbol_hash[i]; sym; sym = sym->next) if (sym->type != S_OTHER) +#define for_all_symbols(i, sym) for (i = 0; i < SYMBOL_HASHSIZE; i++) for (sym = symbol_hash[i]; sym; sym = sym->next) #define SYMBOL_CONST 0x0001 /* symbol is const */ #define SYMBOL_CHECK 0x0008 /* used during dependency checking */ diff --git a/kconfig/kconf_id.c b/kconfig/kconf_id.c deleted file mode 100644 index b3e0ea0..0000000 --- a/kconfig/kconf_id.c +++ /dev/null @@ -1,52 +0,0 @@ - -static struct kconf_id kconf_id_array[] = { - { "mainmenu", T_MAINMENU, TF_COMMAND }, - { "menu", T_MENU, TF_COMMAND }, - { "endmenu", T_ENDMENU, TF_COMMAND }, - { "source", T_SOURCE, TF_COMMAND }, - { "choice", T_CHOICE, TF_COMMAND }, - { "endchoice", T_ENDCHOICE, TF_COMMAND }, - { "comment", T_COMMENT, TF_COMMAND }, - { "config", T_CONFIG, TF_COMMAND }, - { "menuconfig", T_MENUCONFIG, TF_COMMAND }, - { "help", T_HELP, TF_COMMAND }, - { "---help---", T_HELP, TF_COMMAND }, - { "if", T_IF, TF_COMMAND|TF_PARAM }, - { "endif", T_ENDIF, TF_COMMAND }, - { "depends", T_DEPENDS, TF_COMMAND }, - { "optional", T_OPTIONAL, TF_COMMAND }, - { "default", T_DEFAULT, TF_COMMAND, S_UNKNOWN }, - { "prompt", T_PROMPT, TF_COMMAND }, - { "tristate", T_TYPE, TF_COMMAND, S_TRISTATE }, - { "def_tristate", T_DEFAULT, TF_COMMAND, S_TRISTATE }, - { "bool", T_TYPE, TF_COMMAND, S_BOOLEAN }, - { "def_bool", T_DEFAULT, TF_COMMAND, S_BOOLEAN }, - { "int", T_TYPE, TF_COMMAND, S_INT }, - { "hex", T_TYPE, TF_COMMAND, S_HEX }, - { "string", T_TYPE, TF_COMMAND, S_STRING }, - { "select", T_SELECT, TF_COMMAND }, - { "imply", T_IMPLY, TF_COMMAND }, - { "range", T_RANGE, TF_COMMAND }, - { "visible", T_VISIBLE, TF_COMMAND }, - { "option", T_OPTION, TF_COMMAND }, - { "on", T_ON, TF_PARAM }, - { "modules", T_OPT_MODULES, TF_OPTION }, - { "defconfig_list", T_OPT_DEFCONFIG_LIST, TF_OPTION }, - { "allnoconfig_y", T_OPT_ALLNOCONFIG_Y, TF_OPTION }, -}; - -#define KCONF_ID_ARRAY_SIZE (sizeof(kconf_id_array)/sizeof(struct kconf_id)) - -static const struct kconf_id *kconf_id_lookup(register const char *str, register unsigned int len) -{ - int i; - - for (i = 0; i < KCONF_ID_ARRAY_SIZE; i++) { - struct kconf_id *id = kconf_id_array+i; - int l = strlen(id->name); - - if (len == l && !memcmp(str, id->name, len)) - return id; - } - return NULL; -} diff --git a/kconfig/lkc.h b/kconfig/lkc.h index 9eb7c83..531ff7c 100644 --- a/kconfig/lkc.h +++ b/kconfig/lkc.h @@ -1,6 +1,6 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * Copyright (C) 2002 Roman Zippel - * Released under the terms of the GNU GPL v2.0. */ #ifndef LKC_H @@ -30,10 +30,6 @@ static inline const char *CONFIG_prefix(void) #undef CONFIG_ #define CONFIG_ CONFIG_prefix() -#define TF_COMMAND 0x0001 -#define TF_PARAM 0x0002 -#define TF_OPTION 0x0004 - enum conf_def_mode { def_default, def_yes, @@ -42,17 +38,6 @@ enum conf_def_mode { def_random }; -#define T_OPT_MODULES 1 -#define T_OPT_DEFCONFIG_LIST 2 -#define T_OPT_ALLNOCONFIG_Y 4 - -struct kconf_id { - const char *name; - int token; - unsigned int flags; - enum symbol_type stype; -}; - extern int yylineno; void zconfdump(FILE *out); void zconf_starthelp(void); @@ -91,7 +76,9 @@ void menu_add_visibility(struct expr *dep); struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep); void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep); void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep); -void menu_add_option(int token, char *arg); +void menu_add_option_modules(void); +void menu_add_option_defconfig_list(void); +void menu_add_option_allnoconfig_y(void); void menu_finalize(struct menu *parent); void menu_set_type(int type); @@ -103,6 +90,9 @@ void *xrealloc(void *p, size_t size); char *xstrdup(const char *s); char *xstrndup(const char *s, size_t n); +/* zconf.l */ +int yylex(void); + struct gstr { size_t len; char *s; @@ -121,6 +111,7 @@ const char *str_get(struct gstr *gs); /* symbol.c */ void sym_clear_all_valid(void); struct symbol *sym_choice_default(struct symbol *sym); +struct property *sym_get_range_prop(struct symbol *sym); const char *sym_get_string_default(struct symbol *sym); struct symbol *sym_check_deps(struct symbol *sym); struct property *prop_alloc(enum prop_type type, struct symbol *sym); diff --git a/kconfig/lxdialog/checklist.c b/kconfig/lxdialog/checklist.c index 2e96323..fd161cf 100644 --- a/kconfig/lxdialog/checklist.c +++ b/kconfig/lxdialog/checklist.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * checklist.c -- implements the checklist box * @@ -5,20 +6,6 @@ * Stuart Herbert - S.Herbert@sheffield.ac.uk: radiolist extension * Alessandro Rubini - rubini@ipvvis.unipv.it: merged the two * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "dialog.h" diff --git a/kconfig/lxdialog/dialog.h b/kconfig/lxdialog/dialog.h index 0b00be5..68b565e 100644 --- a/kconfig/lxdialog/dialog.h +++ b/kconfig/lxdialog/dialog.h @@ -1,21 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * dialog.h -- common declarations for all dialog modules * * AUTHOR: Savio Lam (lam836@cs.cuhk.hk) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include diff --git a/kconfig/lxdialog/inputbox.c b/kconfig/lxdialog/inputbox.c index fe82ff6..6119456 100644 --- a/kconfig/lxdialog/inputbox.c +++ b/kconfig/lxdialog/inputbox.c @@ -1,22 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * inputbox.c -- implements the input box * * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "dialog.h" diff --git a/kconfig/lxdialog/menubox.c b/kconfig/lxdialog/menubox.c index d70cab3..58c2f8a 100644 --- a/kconfig/lxdialog/menubox.c +++ b/kconfig/lxdialog/menubox.c @@ -1,22 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * menubox.c -- implements the menu box * * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcapw@cfw.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* diff --git a/kconfig/lxdialog/textbox.c b/kconfig/lxdialog/textbox.c index 88d2818..4e339b1 100644 --- a/kconfig/lxdialog/textbox.c +++ b/kconfig/lxdialog/textbox.c @@ -1,22 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * textbox.c -- implements the text box * * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "dialog.h" diff --git a/kconfig/lxdialog/util.c b/kconfig/lxdialog/util.c index f7abdeb..1b490d4 100644 --- a/kconfig/lxdialog/util.c +++ b/kconfig/lxdialog/util.c @@ -1,22 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * util.c * * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include diff --git a/kconfig/lxdialog/yesno.c b/kconfig/lxdialog/yesno.c index cd1223c..bcaac9b 100644 --- a/kconfig/lxdialog/yesno.c +++ b/kconfig/lxdialog/yesno.c @@ -1,22 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * yesno.c -- implements the yes/no box * * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "dialog.h" diff --git a/kconfig/mconf.c b/kconfig/mconf.c index c719f60..3d4bd5e 100644 --- a/kconfig/mconf.c +++ b/kconfig/mconf.c @@ -1,6 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2002 Roman Zippel - * Released under the terms of the GNU GPL v2.0. * * Introduced single menu mode (show all sub-menus in one large tree). * 2002-11-06 Petr Baudis diff --git a/kconfig/menu.c b/kconfig/menu.c index 539ff57..264ba29 100644 --- a/kconfig/menu.c +++ b/kconfig/menu.c @@ -1,6 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2002 Roman Zippel - * Released under the terms of the GNU GPL v2.0. */ #include @@ -201,29 +201,26 @@ void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep) menu_add_prop(type, NULL, expr_alloc_symbol(sym), dep); } -void menu_add_option(int token, char *arg) +void menu_add_option_modules(void) { - switch (token) { - case T_OPT_MODULES: - if (modules_sym) - zconf_error("symbol '%s' redefines option 'modules'" - " already defined by symbol '%s'", - current_entry->sym->name, - modules_sym->name - ); - modules_sym = current_entry->sym; - break; - case T_OPT_DEFCONFIG_LIST: - if (!sym_defconfig_list) - sym_defconfig_list = current_entry->sym; - else if (sym_defconfig_list != current_entry->sym) - zconf_error("trying to redefine defconfig symbol"); - sym_defconfig_list->flags |= SYMBOL_NO_WRITE; - break; - case T_OPT_ALLNOCONFIG_Y: - current_entry->sym->flags |= SYMBOL_ALLNOCONFIG_Y; - break; - } + if (modules_sym) + zconf_error("symbol '%s' redefines option 'modules' already defined by symbol '%s'", + current_entry->sym->name, modules_sym->name); + modules_sym = current_entry->sym; +} + +void menu_add_option_defconfig_list(void) +{ + if (!sym_defconfig_list) + sym_defconfig_list = current_entry->sym; + else if (sym_defconfig_list != current_entry->sym) + zconf_error("trying to redefine defconfig symbol"); + sym_defconfig_list->flags |= SYMBOL_NO_WRITE; +} + +void menu_add_option_allnoconfig_y(void) +{ + current_entry->sym->flags |= SYMBOL_ALLNOCONFIG_Y; } static int menu_validate_number(struct symbol *sym, struct symbol *sym2) diff --git a/kconfig/nconf.c b/kconfig/nconf.c index 93d186e..fb6027a 100644 --- a/kconfig/nconf.c +++ b/kconfig/nconf.c @@ -1,9 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 /* - * Copyright (C) 2008 Nir Tzachar * * Derived from menuconfig. - * */ #ifndef _GNU_SOURCE #define _GNU_SOURCE diff --git a/kconfig/nconf.gui.c b/kconfig/nconf.gui.c index 88874ac..7be620a 100644 --- a/kconfig/nconf.gui.c +++ b/kconfig/nconf.gui.c @@ -1,9 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 /* - * Copyright (C) 2008 Nir Tzachar * * Derived from menuconfig. - * */ #include "nconf.h" #include "lkc.h" diff --git a/kconfig/nconf.h b/kconfig/nconf.h index 2b9e19f..fa5245e 100644 --- a/kconfig/nconf.h +++ b/kconfig/nconf.h @@ -1,9 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* - * Copyright (C) 2008 Nir Tzachar * * Derived from menuconfig. - * */ #include diff --git a/kconfig/preprocess.c b/kconfig/preprocess.c index 5ca2df7..592dfbf 100644 --- a/kconfig/preprocess.c +++ b/kconfig/preprocess.c @@ -2,6 +2,7 @@ // // Copyright (C) 2018 Masahiro Yamada +#include #include #include #include @@ -9,6 +10,7 @@ #include #include "list.h" +#include "lkc.h" #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) @@ -555,8 +557,7 @@ char *expand_string(const char *in) static bool is_end_of_token(char c) { - /* Why are '.' and '/' valid characters for symbols? */ - return !(isalnum(c) || c == '_' || c == '-' || c == '.' || c == '/'); + return !(isalnum(c) || c == '_' || c == '-'); } /* diff --git a/kconfig/symbol.c b/kconfig/symbol.c index 703b9b8..1f9266d 100644 --- a/kconfig/symbol.c +++ b/kconfig/symbol.c @@ -1,6 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2002 Roman Zippel - * Released under the terms of the GNU GPL v2.0. */ #include @@ -61,8 +61,6 @@ const char *sym_type_name(enum symbol_type type) return "string"; case S_UNKNOWN: return "unknown"; - case S_OTHER: - break; } return "???"; } @@ -88,7 +86,7 @@ static struct property *sym_get_default_prop(struct symbol *sym) return NULL; } -static struct property *sym_get_range_prop(struct symbol *sym) +struct property *sym_get_range_prop(struct symbol *sym) { struct property *prop; @@ -757,7 +755,6 @@ const char *sym_get_string_default(struct symbol *sym) return str; case S_STRING: return str; - case S_OTHER: case S_UNKNOWN: break; } diff --git a/kconfig/util.c b/kconfig/util.c index d999683..2958539 100644 --- a/kconfig/util.c +++ b/kconfig/util.c @@ -1,8 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2002-2005 Roman Zippel * Copyright (C) 2002-2005 Sam Ravnborg - * - * Released under the terms of the GNU GPL v2.0. */ #include diff --git a/kconfig/zconf.l b/kconfig/zconf.l index 25bd2b8..b2d0a3b 100644 --- a/kconfig/zconf.l +++ b/kconfig/zconf.l @@ -1,11 +1,11 @@ -%option nostdinit noyywrap never-interactive full ecs -%option 8bit nodefault yylineno -%x COMMAND HELP STRING PARAM ASSIGN_VAL -%{ +/* SPDX-License-Identifier: GPL-2.0 */ /* * Copyright (C) 2002 Roman Zippel - * Released under the terms of the GNU GPL v2.0. */ +%option nostdinit noyywrap never-interactive full ecs +%option 8bit nodefault yylineno +%x ASSIGN_VAL HELP STRING +%{ #include #include @@ -15,6 +15,9 @@ #include #include "lkc.h" +#include "zconf.tab.h" + +#define YY_DECL static int yylex1(void) #define START_STRSIZE 16 @@ -23,6 +26,8 @@ static struct { int lineno; } current_pos; +static int prev_prev_token = T_EOL; +static int prev_token = T_EOL; static char *text; static int text_size, text_asize; @@ -73,7 +78,7 @@ static void warn_ignored_character(char chr) { fprintf(stderr, "%s:%d:warning: ignoring unsupported character '%c'\n", - zconf_curname(), zconf_lineno(), chr); + current_file->name, yylineno, chr); } %} @@ -83,54 +88,73 @@ n [A-Za-z0-9_-] int str = 0; int ts, i; -[ \t]*#.*\n | -[ \t]*\n { - return T_EOL; -} -[ \t]*#.* - - -[ \t]+ { - BEGIN(COMMAND); -} - -. { - unput(yytext[0]); - BEGIN(COMMAND); -} - - -{ - {n}+ { - const struct kconf_id *id = kconf_id_lookup(yytext, yyleng); - current_pos.file = current_file; - current_pos.lineno = yylineno; - if (id && id->flags & TF_COMMAND) { - BEGIN(PARAM); - yylval.id = id; - return id->token; - } - alloc_string(yytext, yyleng); - yylval.string = text; - return T_VARIABLE; - } - ({n}|$)+ { - /* this token includes at least one '$' */ - yylval.string = expand_token(yytext, yyleng); - if (strlen(yylval.string)) - return T_VARIABLE; - free(yylval.string); - } - "=" { BEGIN(ASSIGN_VAL); yylval.flavor = VAR_RECURSIVE; return T_ASSIGN; } - ":=" { BEGIN(ASSIGN_VAL); yylval.flavor = VAR_SIMPLE; return T_ASSIGN; } - "+=" { BEGIN(ASSIGN_VAL); yylval.flavor = VAR_APPEND; return T_ASSIGN; } - [[:blank:]]+ - . warn_ignored_character(*yytext); - \n { - BEGIN(INITIAL); - return T_EOL; - } -} +#.* /* ignore comment */ +[ \t]* /* whitespaces */ +\\\n /* escaped new line */ +\n return T_EOL; +"allnoconfig_y" return T_ALLNOCONFIG_Y; +"bool" return T_BOOL; +"choice" return T_CHOICE; +"comment" return T_COMMENT; +"config" return T_CONFIG; +"def_bool" return T_DEF_BOOL; +"def_tristate" return T_DEF_TRISTATE; +"default" return T_DEFAULT; +"defconfig_list" return T_DEFCONFIG_LIST; +"depends" return T_DEPENDS; +"endchoice" return T_ENDCHOICE; +"endif" return T_ENDIF; +"endmenu" return T_ENDMENU; +"help"|"---help---" return T_HELP; +"hex" return T_HEX; +"if" return T_IF; +"imply" return T_IMPLY; +"int" return T_INT; +"mainmenu" return T_MAINMENU; +"menu" return T_MENU; +"menuconfig" return T_MENUCONFIG; +"modules" return T_MODULES; +"on" return T_ON; +"option" return T_OPTION; +"optional" return T_OPTIONAL; +"prompt" return T_PROMPT; +"range" return T_RANGE; +"select" return T_SELECT; +"source" return T_SOURCE; +"string" return T_STRING; +"tristate" return T_TRISTATE; +"visible" return T_VISIBLE; +"||" return T_OR; +"&&" return T_AND; +"=" return T_EQUAL; +"!=" return T_UNEQUAL; +"<" return T_LESS; +"<=" return T_LESS_EQUAL; +">" return T_GREATER; +">=" return T_GREATER_EQUAL; +"!" return T_NOT; +"(" return T_OPEN_PAREN; +")" return T_CLOSE_PAREN; +":=" return T_COLON_EQUAL; +"+=" return T_PLUS_EQUAL; +\"|\' { + str = yytext[0]; + new_string(); + BEGIN(STRING); + } +{n}+ { + alloc_string(yytext, yyleng); + yylval.string = text; + return T_WORD; + } +({n}|$)+ { + /* this token includes at least one '$' */ + yylval.string = expand_token(yytext, yyleng); + if (strlen(yylval.string)) + return T_WORD; + free(yylval.string); + } +. warn_ignored_character(*yytext); { [^[:blank:]\n]+.* { @@ -142,71 +166,17 @@ n [A-Za-z0-9_-] . } -{ - "&&" return T_AND; - "||" return T_OR; - "(" return T_OPEN_PAREN; - ")" return T_CLOSE_PAREN; - "!" return T_NOT; - "=" return T_EQUAL; - "!=" return T_UNEQUAL; - "<=" return T_LESS_EQUAL; - ">=" return T_GREATER_EQUAL; - "<" return T_LESS; - ">" return T_GREATER; - \"|\' { - str = yytext[0]; - new_string(); - BEGIN(STRING); - } - \n BEGIN(INITIAL); return T_EOL; - ({n}|[/.])+ { - const struct kconf_id *id = kconf_id_lookup(yytext, yyleng); - if (id && id->flags & TF_PARAM) { - yylval.id = id; - return id->token; - } - alloc_string(yytext, yyleng); - yylval.string = text; - return T_WORD; - } - ({n}|[/.$])+ { - /* this token includes at least one '$' */ - yylval.string = expand_token(yytext, yyleng); - if (strlen(yylval.string)) - return T_WORD; - free(yylval.string); - } - #.* /* comment */ - \\\n ; - [[:blank:]]+ - . warn_ignored_character(*yytext); - <> { - BEGIN(INITIAL); - } -} - { "$".* append_expanded_string(yytext); - [^$'"\\\n]+/\n { - append_string(yytext, yyleng); - yylval.string = text; - return T_WORD_QUOTE; - } [^$'"\\\n]+ { append_string(yytext, yyleng); } - \\.?/\n { - append_string(yytext + 1, yyleng - 1); - yylval.string = text; - return T_WORD_QUOTE; - } \\.? { append_string(yytext + 1, yyleng - 1); } \'|\" { if (str == yytext[0]) { - BEGIN(PARAM); + BEGIN(INITIAL); yylval.string = text; return T_WORD_QUOTE; } else @@ -216,11 +186,15 @@ n [A-Za-z0-9_-] fprintf(stderr, "%s:%d:warning: multi-line strings not supported\n", zconf_curname(), zconf_lineno()); + unput('\n'); BEGIN(INITIAL); - return T_EOL; + yylval.string = text; + return T_WORD_QUOTE; } <> { BEGIN(INITIAL); + yylval.string = text; + return T_WORD_QUOTE; } } @@ -271,6 +245,12 @@ n [A-Za-z0-9_-] } <> { + BEGIN(INITIAL); + + if (prev_token != T_EOL && prev_token != T_HELPTEXT) + fprintf(stderr, "%s:%d:warning: no new line at end of file\n", + current_file->name, yylineno); + if (current_file) { zconf_endfile(); return T_EOL; @@ -280,6 +260,41 @@ n [A-Za-z0-9_-] } %% + +/* second stage lexer */ +int yylex(void) +{ + int token; + +repeat: + token = yylex1(); + + if (prev_token == T_EOL || prev_token == T_HELPTEXT) { + if (token == T_EOL) { + /* Do not pass unneeded T_EOL to the parser. */ + goto repeat; + } else { + /* + * For the parser, update file/lineno at the first token + * of each statement. Generally, \n is a statement + * terminator in Kconfig, but it is not always true + * because \n could be escaped by a backslash. + */ + current_pos.file = current_file; + current_pos.lineno = yylineno; + } + } + + if (prev_prev_token == T_EOL && prev_token == T_WORD && + (token == T_EQUAL || token == T_COLON_EQUAL || token == T_PLUS_EQUAL)) + BEGIN(ASSIGN_VAL); + + prev_prev_token = prev_token; + prev_token = token; + + return token; +} + static char *expand_token(const char *in, size_t n) { char *out; diff --git a/kconfig/zconf.y b/kconfig/zconf.y index 9d331da..60936c7 100644 --- a/kconfig/zconf.y +++ b/kconfig/zconf.y @@ -1,8 +1,8 @@ -%{ +/* SPDX-License-Identifier: GPL-2.0 */ /* * Copyright (C) 2002 Roman Zippel - * Released under the terms of the GNU GPL v2.0. */ +%{ #include #include @@ -20,66 +20,68 @@ int cdebug = PRINTD; -int yylex(void); static void yyerror(const char *err); static void zconfprint(const char *err, ...); static void zconf_error(const char *err, ...); -static bool zconf_endtoken(const struct kconf_id *id, int starttoken, int endtoken); +static bool zconf_endtoken(const char *tokenname, + const char *expected_tokenname); struct symbol *symbol_hash[SYMBOL_HASHSIZE]; static struct menu *current_menu, *current_entry; %} -%expect 30 %union { char *string; - struct file *file; struct symbol *symbol; struct expr *expr; struct menu *menu; - const struct kconf_id *id; + enum symbol_type type; enum variable_flavor flavor; } -%token T_MAINMENU -%token T_MENU -%token T_ENDMENU -%token T_SOURCE -%token T_CHOICE -%token T_ENDCHOICE -%token T_COMMENT -%token T_CONFIG -%token T_MENUCONFIG -%token T_HELP %token T_HELPTEXT -%token T_IF -%token T_ENDIF -%token T_DEPENDS -%token T_OPTIONAL -%token T_PROMPT -%token T_TYPE -%token T_DEFAULT -%token T_SELECT -%token T_IMPLY -%token T_RANGE -%token T_VISIBLE -%token T_OPTION -%token T_ON %token T_WORD %token T_WORD_QUOTE -%token T_UNEQUAL -%token T_LESS -%token T_LESS_EQUAL -%token T_GREATER -%token T_GREATER_EQUAL +%token T_ALLNOCONFIG_Y +%token T_BOOL +%token T_CHOICE %token T_CLOSE_PAREN +%token T_COLON_EQUAL +%token T_COMMENT +%token T_CONFIG +%token T_DEFAULT +%token T_DEFCONFIG_LIST +%token T_DEF_BOOL +%token T_DEF_TRISTATE +%token T_DEPENDS +%token T_ENDCHOICE +%token T_ENDIF +%token T_ENDMENU +%token T_HELP +%token T_HEX +%token T_IF +%token T_IMPLY +%token T_INT +%token T_MAINMENU +%token T_MENU +%token T_MENUCONFIG +%token T_MODULES +%token T_ON %token T_OPEN_PAREN +%token T_OPTION +%token T_OPTIONAL +%token T_PLUS_EQUAL +%token T_PROMPT +%token T_RANGE +%token T_SELECT +%token T_SOURCE +%token T_STRING +%token T_TRISTATE +%token T_VISIBLE %token T_EOL -%token T_VARIABLE -%token T_ASSIGN %token T_ASSIGN_VAL %left T_OR @@ -91,12 +93,13 @@ static struct menu *current_menu, *current_entry; %type prompt %type nonconst_symbol %type symbol +%type type logic_type default %type expr %type if_expr -%type end -%type option_name +%type end %type if_entry menu_entry choice_entry -%type symbol_option_arg word_opt assign_val +%type word_opt assign_val +%type assign_op %destructor { fprintf(stderr, "%s:%d: missing end statement for this entry\n", @@ -105,15 +108,8 @@ static struct menu *current_menu, *current_entry; menu_end_menu(); } if_entry menu_entry choice_entry -%{ -/* Include kconf_id.c here so it can see the token constants. */ -#include "kconf_id.c" -%} - %% -input: nl start | start; - -start: mainmenu_stmt stmt_list | stmt_list; +input: mainmenu_stmt stmt_list | stmt_list; /* mainmenu entry */ @@ -127,22 +123,12 @@ stmt_list: | stmt_list common_stmt | stmt_list choice_stmt | stmt_list menu_stmt - | stmt_list end { zconf_error("unexpected end statement"); } | stmt_list T_WORD error T_EOL { zconf_error("unknown statement \"%s\"", $2); } - | stmt_list option_name error T_EOL -{ - zconf_error("unexpected option \"%s\"", $2->name); -} | stmt_list error T_EOL { zconf_error("invalid statement"); } ; -option_name: - T_DEPENDS | T_PROMPT | T_TYPE | T_SELECT | T_IMPLY | T_OPTIONAL | T_RANGE | T_DEFAULT | T_VISIBLE -; - common_stmt: - T_EOL - | if_stmt + if_stmt | comment_stmt | config_stmt | menuconfig_stmt @@ -150,12 +136,6 @@ common_stmt: | assignment_stmt ; -option_error: - T_WORD error T_EOL { zconf_error("unknown option \"%s\"", $1); } - | error T_EOL { zconf_error("invalid option"); } -; - - /* config/menuconfig entry */ config_entry_start: T_CONFIG nonconst_symbol T_EOL @@ -189,19 +169,16 @@ menuconfig_stmt: menuconfig_entry_start config_option_list config_option_list: /* empty */ | config_option_list config_option - | config_option_list symbol_option | config_option_list depends | config_option_list help - | config_option_list option_error - | config_option_list T_EOL ; -config_option: T_TYPE prompt_stmt_opt T_EOL +config_option: type prompt_stmt_opt T_EOL { - menu_set_type($1->stype); + menu_set_type($1); printd(DEBUG_PARSE, "%s:%d:type(%u)\n", zconf_curname(), zconf_lineno(), - $1->stype); + $1); }; config_option: T_PROMPT prompt if_expr T_EOL @@ -210,14 +187,14 @@ config_option: T_PROMPT prompt if_expr T_EOL printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno()); }; -config_option: T_DEFAULT expr if_expr T_EOL +config_option: default expr if_expr T_EOL { menu_add_expr(P_DEFAULT, $2, $3); - if ($1->stype != S_UNKNOWN) - menu_set_type($1->stype); + if ($1 != S_UNKNOWN) + menu_set_type($1); printd(DEBUG_PARSE, "%s:%d:default(%u)\n", zconf_curname(), zconf_lineno(), - $1->stype); + $1); }; config_option: T_SELECT nonconst_symbol if_expr T_EOL @@ -238,27 +215,20 @@ config_option: T_RANGE symbol symbol if_expr T_EOL printd(DEBUG_PARSE, "%s:%d:range\n", zconf_curname(), zconf_lineno()); }; -symbol_option: T_OPTION symbol_option_list T_EOL -; +config_option: T_OPTION T_MODULES T_EOL +{ + menu_add_option_modules(); +}; -symbol_option_list: - /* empty */ - | symbol_option_list T_WORD symbol_option_arg +config_option: T_OPTION T_DEFCONFIG_LIST T_EOL { - const struct kconf_id *id = kconf_id_lookup($2, strlen($2)); - if (id && id->flags & TF_OPTION) { - menu_add_option(id->token, $3); - free($3); - } - else - zconfprint("warning: ignoring unknown option %s", $2); - free($2); + menu_add_option_defconfig_list(); }; -symbol_option_arg: - /* empty */ { $$ = NULL; } - | T_EQUAL prompt { $$ = $2; } -; +config_option: T_OPTION T_ALLNOCONFIG_Y T_EOL +{ + menu_add_option_allnoconfig_y(); +}; /* choice entry */ @@ -279,7 +249,7 @@ choice_entry: choice choice_option_list choice_end: end { - if (zconf_endtoken($1, T_CHOICE, T_ENDCHOICE)) { + if (zconf_endtoken($1, "choice")) { menu_end_menu(); printd(DEBUG_PARSE, "%s:%d:endchoice\n", zconf_curname(), zconf_lineno()); } @@ -293,8 +263,6 @@ choice_option_list: | choice_option_list choice_option | choice_option_list depends | choice_option_list help - | choice_option_list T_EOL - | choice_option_list option_error ; choice_option: T_PROMPT prompt if_expr T_EOL @@ -303,15 +271,11 @@ choice_option: T_PROMPT prompt if_expr T_EOL printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno()); }; -choice_option: T_TYPE prompt_stmt_opt T_EOL +choice_option: logic_type prompt_stmt_opt T_EOL { - if ($1->stype == S_BOOLEAN || $1->stype == S_TRISTATE) { - menu_set_type($1->stype); - printd(DEBUG_PARSE, "%s:%d:type(%u)\n", - zconf_curname(), zconf_lineno(), - $1->stype); - } else - YYERROR; + menu_set_type($1); + printd(DEBUG_PARSE, "%s:%d:type(%u)\n", + zconf_curname(), zconf_lineno(), $1); }; choice_option: T_OPTIONAL T_EOL @@ -322,14 +286,26 @@ choice_option: T_OPTIONAL T_EOL choice_option: T_DEFAULT nonconst_symbol if_expr T_EOL { - if ($1->stype == S_UNKNOWN) { - menu_add_symbol(P_DEFAULT, $2, $3); - printd(DEBUG_PARSE, "%s:%d:default\n", - zconf_curname(), zconf_lineno()); - } else - YYERROR; + menu_add_symbol(P_DEFAULT, $2, $3); + printd(DEBUG_PARSE, "%s:%d:default\n", + zconf_curname(), zconf_lineno()); }; +type: + logic_type + | T_INT { $$ = S_INT; } + | T_HEX { $$ = S_HEX; } + | T_STRING { $$ = S_STRING; } + +logic_type: + T_BOOL { $$ = S_BOOLEAN; } + | T_TRISTATE { $$ = S_TRISTATE; } + +default: + T_DEFAULT { $$ = S_UNKNOWN; } + | T_DEF_BOOL { $$ = S_BOOLEAN; } + | T_DEF_TRISTATE { $$ = S_TRISTATE; } + choice_block: /* empty */ | choice_block common_stmt @@ -347,20 +323,13 @@ if_entry: T_IF expr T_EOL if_end: end { - if (zconf_endtoken($1, T_IF, T_ENDIF)) { + if (zconf_endtoken($1, "if")) { menu_end_menu(); printd(DEBUG_PARSE, "%s:%d:endif\n", zconf_curname(), zconf_lineno()); } }; -if_stmt: if_entry if_block if_end -; - -if_block: - /* empty */ - | if_block common_stmt - | if_block menu_stmt - | if_block choice_stmt +if_stmt: if_entry stmt_list if_end ; /* menu entry */ @@ -372,27 +341,26 @@ menu: T_MENU prompt T_EOL printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno()); }; -menu_entry: menu visibility_list depends_list +menu_entry: menu menu_option_list { $$ = menu_add_menu(); }; menu_end: end { - if (zconf_endtoken($1, T_MENU, T_ENDMENU)) { + if (zconf_endtoken($1, "menu")) { menu_end_menu(); printd(DEBUG_PARSE, "%s:%d:endmenu\n", zconf_curname(), zconf_lineno()); } }; -menu_stmt: menu_entry menu_block menu_end +menu_stmt: menu_entry stmt_list menu_end ; -menu_block: +menu_option_list: /* empty */ - | menu_block common_stmt - | menu_block menu_stmt - | menu_block choice_stmt + | menu_option_list visible + | menu_option_list depends ; source_stmt: T_SOURCE prompt T_EOL @@ -411,7 +379,12 @@ comment: T_COMMENT prompt T_EOL printd(DEBUG_PARSE, "%s:%d:comment\n", zconf_curname(), zconf_lineno()); }; -comment_stmt: comment depends_list +comment_stmt: comment comment_option_list +; + +comment_option_list: + /* empty */ + | comment_option_list depends ; /* help option */ @@ -440,13 +413,6 @@ help: help_start T_HELPTEXT /* depends option */ -depends_list: - /* empty */ - | depends_list depends - | depends_list T_EOL - | depends_list option_error -; - depends: T_DEPENDS T_ON expr T_EOL { menu_add_dep($3); @@ -454,14 +420,7 @@ depends: T_DEPENDS T_ON expr T_EOL }; /* visibility option */ - -visibility_list: - /* empty */ - | visibility_list visible - | visibility_list T_EOL -; - -visible: T_VISIBLE if_expr +visible: T_VISIBLE if_expr T_EOL { menu_add_visibility($2); }; @@ -479,14 +438,9 @@ prompt: T_WORD | T_WORD_QUOTE ; -end: T_ENDMENU T_EOL { $$ = $1; } - | T_ENDCHOICE T_EOL { $$ = $1; } - | T_ENDIF T_EOL { $$ = $1; } -; - -nl: - T_EOL - | nl T_EOL +end: T_ENDMENU T_EOL { $$ = "menu"; } + | T_ENDCHOICE T_EOL { $$ = "choice"; } + | T_ENDIF T_EOL { $$ = "if"; } ; if_expr: /* empty */ { $$ = NULL; } @@ -518,7 +472,13 @@ word_opt: /* empty */ { $$ = NULL; } /* assignment statement */ -assignment_stmt: T_VARIABLE T_ASSIGN assign_val T_EOL { variable_add($1, $3, $2); free($1); free($3); } +assignment_stmt: T_WORD assign_op assign_val T_EOL { variable_add($1, $3, $2); free($1); free($3); } + +assign_op: + T_EQUAL { $$ = VAR_RECURSIVE; } + | T_COLON_EQUAL { $$ = VAR_SIMPLE; } + | T_PLUS_EQUAL { $$ = VAR_APPEND; } +; assign_val: /* empty */ { $$ = xstrdup(""); }; @@ -535,10 +495,9 @@ void conf_parse(const char *name) zconf_initscan(name); _menu_init(); -#if YYDEBUG + if (getenv("ZCONF_DEBUG")) yydebug = 1; -#endif yyparse(); /* Variables are expanded in the parse phase. We can free them here. */ @@ -564,35 +523,21 @@ void conf_parse(const char *name) sym_set_change_count(1); } -static const char *zconf_tokenname(int token) -{ - switch (token) { - case T_MENU: return "menu"; - case T_ENDMENU: return "endmenu"; - case T_CHOICE: return "choice"; - case T_ENDCHOICE: return "endchoice"; - case T_IF: return "if"; - case T_ENDIF: return "endif"; - case T_DEPENDS: return "depends"; - case T_VISIBLE: return "visible"; - } - return ""; -} - -static bool zconf_endtoken(const struct kconf_id *id, int starttoken, int endtoken) +static bool zconf_endtoken(const char *tokenname, + const char *expected_tokenname) { - if (id->token != endtoken) { + if (strcmp(tokenname, expected_tokenname)) { zconf_error("unexpected '%s' within %s block", - id->name, zconf_tokenname(starttoken)); + tokenname, expected_tokenname); yynerrs++; return false; } if (current_menu->file != current_file) { zconf_error("'%s' in different file than '%s'", - id->name, zconf_tokenname(starttoken)); + tokenname, expected_tokenname); fprintf(stderr, "%s:%d: location of the '%s'\n", current_menu->file->name, current_menu->lineno, - zconf_tokenname(starttoken)); + expected_tokenname); yynerrs++; return false; } @@ -782,10 +727,5 @@ void zconfdump(FILE *out) } } -#include "zconf.lex.c" #include "util.c" -#include "confdata.c" -#include "expr.c" -#include "symbol.c" #include "menu.c" -#include "preprocess.c" -- cgit v0.10.2-6-g49f6 From d057ba5324a082ba28d3b81f90405fae860bb376 Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Wed, 9 Dec 2020 22:22:43 +1300 Subject: kconfig: Sync with upstream v5.1 This commit introduces the following upstream changes: 9c38f1f04408 kconfig/[mn]conf: handle backspace (^H) key c71bb9f86666 kconfig: remove stale lxdialog/.gitignore 8741908b3e29 kconfig: fix 'Save As' menu of xconfig 058507195b53 kbuild: move ".config not found!" message from Kconfig to Makefile 769a1c022678 kconfig: rename zconf.y to parser.y 981e545a698a kconfig: rename zconf.l to lexer.l Signed-off-by: Chris Packham diff --git a/kconfig/Makefile.am b/kconfig/Makefile.am index 8245606..2db2615 100644 --- a/kconfig/Makefile.am +++ b/kconfig/Makefile.am @@ -5,26 +5,26 @@ transform = s,x,x, pkglibexec_PROGRAMS = conf nconf mconf -EXTRA_DIST = zconf.y zconf.l \ +EXTRA_DIST = parser.y lexer.l \ expr.h list.h lkc.h lkc_proto.h nconf.h lxdialog/dialog.h \ confdata.c expr.c kconf_id.c menu.c symbol.c util.c -CLEANFILES = zconf.lex.c zconf.tab.c -BUILT_SOURCES = zconf.lex.c zconf.tab.c +CLEANFILES = lexer.lex.c parser.tab.c parser.tab.h +BUILT_SOURCES = lexer.lex.c parser.tab.c AM_LFLAGS = -L AM_YFLAGS = -t -l AM_CPPFLAGS = -include config.h -DCONFIG_=\"CT_\" AM_LIBTOOLFLAGS = --tag CC -conf_SOURCES = conf.c confdata.c expr.c symbol.c preprocess.c zconf.lex.c zconf.tab.c +conf_SOURCES = conf.c confdata.c expr.c symbol.c preprocess.c lexer.lex.c parser.tab.c conf_LDADD = $(LIBINTL) -nconf_SOURCES = nconf.c nconf.gui.c confdata.c expr.c symbol.c preprocess.c zconf.lex.c zconf.tab.c +nconf_SOURCES = nconf.c nconf.gui.c confdata.c expr.c symbol.c preprocess.c lexer.lex.c parser.tab.c nconf_CFLAGS = $(CURSES_CFLAGS) nconf_LDADD = $(MENU_LIBS) $(PANEL_LIBS) $(CURSES_LIBS) $(LIBINTL) -mconf_SOURCES = mconf.c confdata.c expr.c symbol.c preprocess.c zconf.lex.c zconf.tab.c \ +mconf_SOURCES = mconf.c confdata.c expr.c symbol.c preprocess.c lexer.lex.c parser.tab.c \ lxdialog/checklist.c lxdialog/inputbox.c \ lxdialog/menubox.c lxdialog/textbox.c lxdialog/util.c \ lxdialog/yesno.c @@ -43,8 +43,8 @@ AM_V_LEX = $(am__v_LEX_@AM_V@) am__v_LEX_ = $(am__v_LEX_@AM_DEFAULT_V@) am__v_LEX_0 = @echo " LEX " $@; -zconf.tab.c: zconf.y - $(AM_V_YACC)$(YACCCOMPILE) -o$@ --defines=zconf.tab.h $< +parser.tab.c: parser.y + $(AM_V_YACC)$(YACCCOMPILE) -o$@ --defines=parser.tab.h $< -zconf.lex.c: zconf.l +lexer.lex.c: lexer.l $(AM_V_LEX)$(LEXCOMPILE) -o$@ $< diff --git a/kconfig/conf.c b/kconfig/conf.c index b86c7de..67e3219 100644 --- a/kconfig/conf.c +++ b/kconfig/conf.c @@ -468,7 +468,6 @@ int main(int ac, char **av) const char *progname = av[0]; int opt; const char *name, *defconfig_file = NULL /* gcc uninit */; - struct stat tmpstat; int no_conf_write = 0; tty_stdio = isatty(0) && isatty(1); @@ -540,18 +539,6 @@ int main(int ac, char **av) name = av[optind]; conf_parse(name); //zconfdump(stdout); - if (sync_kconfig) { - name = conf_get_configname(); - if (stat(name, &tmpstat)) { - fprintf(stderr, "***\n" - "*** Configuration file \"%s\" not found!\n" - "***\n" - "*** Please configure with \"menuconfig\", or use a\n" - "*** pre-existing sample (see list with \"list-samples\").\n" - "***\n", name); - exit(1); - } - } switch (input_mode) { case defconfig: diff --git a/kconfig/expr.h b/kconfig/expr.h index 999edb6..8dde65b 100644 --- a/kconfig/expr.h +++ b/kconfig/expr.h @@ -172,7 +172,7 @@ struct symbol { * int "BAZ Value" * range 1..255 * - * Please, also check zconf.y:print_symbol() when modifying the + * Please, also check parser.y:print_symbol() when modifying the * list of property types! */ enum prop_type { diff --git a/kconfig/lexer.l b/kconfig/lexer.l new file mode 100644 index 0000000..c9df1c8 --- /dev/null +++ b/kconfig/lexer.l @@ -0,0 +1,470 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2002 Roman Zippel + */ +%option nostdinit noyywrap never-interactive full ecs +%option 8bit nodefault yylineno +%x ASSIGN_VAL HELP STRING +%{ + +#include +#include +#include +#include +#include +#include + +#include "lkc.h" +#include "parser.tab.h" + +#define YY_DECL static int yylex1(void) + +#define START_STRSIZE 16 + +static struct { + struct file *file; + int lineno; +} current_pos; + +static int prev_prev_token = T_EOL; +static int prev_token = T_EOL; +static char *text; +static int text_size, text_asize; + +struct buffer { + struct buffer *parent; + YY_BUFFER_STATE state; +}; + +struct buffer *current_buf; + +static int last_ts, first_ts; + +static char *expand_token(const char *in, size_t n); +static void append_expanded_string(const char *in); +static void zconf_endhelp(void); +static void zconf_endfile(void); + +static void new_string(void) +{ + text = xmalloc(START_STRSIZE); + text_asize = START_STRSIZE; + text_size = 0; + *text = 0; +} + +static void append_string(const char *str, int size) +{ + int new_size = text_size + size + 1; + if (new_size > text_asize) { + new_size += START_STRSIZE - 1; + new_size &= -START_STRSIZE; + text = xrealloc(text, new_size); + text_asize = new_size; + } + memcpy(text + text_size, str, size); + text_size += size; + text[text_size] = 0; +} + +static void alloc_string(const char *str, int size) +{ + text = xmalloc(size + 1); + memcpy(text, str, size); + text[size] = 0; +} + +static void warn_ignored_character(char chr) +{ + fprintf(stderr, + "%s:%d:warning: ignoring unsupported character '%c'\n", + current_file->name, yylineno, chr); +} +%} + +n [A-Za-z0-9_-] + +%% + int str = 0; + int ts, i; + +#.* /* ignore comment */ +[ \t]* /* whitespaces */ +\\\n /* escaped new line */ +\n return T_EOL; +"allnoconfig_y" return T_ALLNOCONFIG_Y; +"bool" return T_BOOL; +"choice" return T_CHOICE; +"comment" return T_COMMENT; +"config" return T_CONFIG; +"def_bool" return T_DEF_BOOL; +"def_tristate" return T_DEF_TRISTATE; +"default" return T_DEFAULT; +"defconfig_list" return T_DEFCONFIG_LIST; +"depends" return T_DEPENDS; +"endchoice" return T_ENDCHOICE; +"endif" return T_ENDIF; +"endmenu" return T_ENDMENU; +"help"|"---help---" return T_HELP; +"hex" return T_HEX; +"if" return T_IF; +"imply" return T_IMPLY; +"int" return T_INT; +"mainmenu" return T_MAINMENU; +"menu" return T_MENU; +"menuconfig" return T_MENUCONFIG; +"modules" return T_MODULES; +"on" return T_ON; +"option" return T_OPTION; +"optional" return T_OPTIONAL; +"prompt" return T_PROMPT; +"range" return T_RANGE; +"select" return T_SELECT; +"source" return T_SOURCE; +"string" return T_STRING; +"tristate" return T_TRISTATE; +"visible" return T_VISIBLE; +"||" return T_OR; +"&&" return T_AND; +"=" return T_EQUAL; +"!=" return T_UNEQUAL; +"<" return T_LESS; +"<=" return T_LESS_EQUAL; +">" return T_GREATER; +">=" return T_GREATER_EQUAL; +"!" return T_NOT; +"(" return T_OPEN_PAREN; +")" return T_CLOSE_PAREN; +":=" return T_COLON_EQUAL; +"+=" return T_PLUS_EQUAL; +\"|\' { + str = yytext[0]; + new_string(); + BEGIN(STRING); + } +{n}+ { + alloc_string(yytext, yyleng); + yylval.string = text; + return T_WORD; + } +({n}|$)+ { + /* this token includes at least one '$' */ + yylval.string = expand_token(yytext, yyleng); + if (strlen(yylval.string)) + return T_WORD; + free(yylval.string); + } +. warn_ignored_character(*yytext); + +{ + [^[:blank:]\n]+.* { + alloc_string(yytext, yyleng); + yylval.string = text; + return T_ASSIGN_VAL; + } + \n { BEGIN(INITIAL); return T_EOL; } + . +} + +{ + "$".* append_expanded_string(yytext); + [^$'"\\\n]+ { + append_string(yytext, yyleng); + } + \\.? { + append_string(yytext + 1, yyleng - 1); + } + \'|\" { + if (str == yytext[0]) { + BEGIN(INITIAL); + yylval.string = text; + return T_WORD_QUOTE; + } else + append_string(yytext, 1); + } + \n { + fprintf(stderr, + "%s:%d:warning: multi-line strings not supported\n", + zconf_curname(), zconf_lineno()); + unput('\n'); + BEGIN(INITIAL); + yylval.string = text; + return T_WORD_QUOTE; + } + <> { + BEGIN(INITIAL); + yylval.string = text; + return T_WORD_QUOTE; + } +} + +{ + [ \t]+ { + ts = 0; + for (i = 0; i < yyleng; i++) { + if (yytext[i] == '\t') + ts = (ts & ~7) + 8; + else + ts++; + } + last_ts = ts; + if (first_ts) { + if (ts < first_ts) { + zconf_endhelp(); + return T_HELPTEXT; + } + ts -= first_ts; + while (ts > 8) { + append_string(" ", 8); + ts -= 8; + } + append_string(" ", ts); + } + } + [ \t]*\n/[^ \t\n] { + zconf_endhelp(); + return T_HELPTEXT; + } + [ \t]*\n { + append_string("\n", 1); + } + [^ \t\n].* { + while (yyleng) { + if ((yytext[yyleng-1] != ' ') && (yytext[yyleng-1] != '\t')) + break; + yyleng--; + } + append_string(yytext, yyleng); + if (!first_ts) + first_ts = last_ts; + } + <> { + zconf_endhelp(); + return T_HELPTEXT; + } +} + +<> { + BEGIN(INITIAL); + + if (prev_token != T_EOL && prev_token != T_HELPTEXT) + fprintf(stderr, "%s:%d:warning: no new line at end of file\n", + current_file->name, yylineno); + + if (current_file) { + zconf_endfile(); + return T_EOL; + } + fclose(yyin); + yyterminate(); +} + +%% + +/* second stage lexer */ +int yylex(void) +{ + int token; + +repeat: + token = yylex1(); + + if (prev_token == T_EOL || prev_token == T_HELPTEXT) { + if (token == T_EOL) { + /* Do not pass unneeded T_EOL to the parser. */ + goto repeat; + } else { + /* + * For the parser, update file/lineno at the first token + * of each statement. Generally, \n is a statement + * terminator in Kconfig, but it is not always true + * because \n could be escaped by a backslash. + */ + current_pos.file = current_file; + current_pos.lineno = yylineno; + } + } + + if (prev_prev_token == T_EOL && prev_token == T_WORD && + (token == T_EQUAL || token == T_COLON_EQUAL || token == T_PLUS_EQUAL)) + BEGIN(ASSIGN_VAL); + + prev_prev_token = prev_token; + prev_token = token; + + return token; +} + +static char *expand_token(const char *in, size_t n) +{ + char *out; + int c; + char c2; + const char *rest, *end; + + new_string(); + append_string(in, n); + + /* get the whole line because we do not know the end of token. */ + while ((c = input()) != EOF) { + if (c == '\n') { + unput(c); + break; + } + c2 = c; + append_string(&c2, 1); + } + + rest = text; + out = expand_one_token(&rest); + + /* push back unused characters to the input stream */ + end = rest + strlen(rest); + while (end > rest) + unput(*--end); + + free(text); + + return out; +} + +static void append_expanded_string(const char *str) +{ + const char *end; + char *res; + + str++; + + res = expand_dollar(&str); + + /* push back unused characters to the input stream */ + end = str + strlen(str); + while (end > str) + unput(*--end); + + append_string(res, strlen(res)); + + free(res); +} + +void zconf_starthelp(void) +{ + new_string(); + last_ts = first_ts = 0; + BEGIN(HELP); +} + +static void zconf_endhelp(void) +{ + yylval.string = text; + BEGIN(INITIAL); +} + + +/* + * Try to open specified file with following names: + * ./name + * $(srctree)/name + * The latter is used when srctree is separate from objtree + * when compiling the kernel. + * Return NULL if file is not found. + */ +FILE *zconf_fopen(const char *name) +{ + char *env, fullname[PATH_MAX+1]; + FILE *f; + + f = fopen(name, "r"); + if (!f && name != NULL && name[0] != '/') { + env = getenv(SRCTREE); + if (env) { + sprintf(fullname, "%s/%s", env, name); + f = fopen(fullname, "r"); + } + } + return f; +} + +void zconf_initscan(const char *name) +{ + yyin = zconf_fopen(name); + if (!yyin) { + fprintf(stderr, "can't find file %s\n", name); + exit(1); + } + + current_buf = xmalloc(sizeof(*current_buf)); + memset(current_buf, 0, sizeof(*current_buf)); + + current_file = file_lookup(name); + yylineno = 1; +} + +void zconf_nextfile(const char *name) +{ + struct file *iter; + struct file *file = file_lookup(name); + struct buffer *buf = xmalloc(sizeof(*buf)); + memset(buf, 0, sizeof(*buf)); + + current_buf->state = YY_CURRENT_BUFFER; + yyin = zconf_fopen(file->name); + if (!yyin) { + fprintf(stderr, "%s:%d: can't open file \"%s\"\n", + zconf_curname(), zconf_lineno(), file->name); + exit(1); + } + yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE)); + buf->parent = current_buf; + current_buf = buf; + + current_file->lineno = yylineno; + file->parent = current_file; + + for (iter = current_file; iter; iter = iter->parent) { + if (!strcmp(iter->name, file->name)) { + fprintf(stderr, + "Recursive inclusion detected.\n" + "Inclusion path:\n" + " current file : %s\n", file->name); + iter = file; + do { + iter = iter->parent; + fprintf(stderr, " included from: %s:%d\n", + iter->name, iter->lineno - 1); + } while (strcmp(iter->name, file->name)); + exit(1); + } + } + + yylineno = 1; + current_file = file; +} + +static void zconf_endfile(void) +{ + struct buffer *parent; + + current_file = current_file->parent; + if (current_file) + yylineno = current_file->lineno; + + parent = current_buf->parent; + if (parent) { + fclose(yyin); + yy_delete_buffer(YY_CURRENT_BUFFER); + yy_switch_to_buffer(parent->state); + } + free(current_buf); + current_buf = parent; +} + +int zconf_lineno(void) +{ + return current_pos.lineno; +} + +const char *zconf_curname(void) +{ + return current_pos.file ? current_pos.file->name : ""; +} diff --git a/kconfig/lkc.h b/kconfig/lkc.h index 531ff7c..d871539 100644 --- a/kconfig/lkc.h +++ b/kconfig/lkc.h @@ -90,7 +90,7 @@ void *xrealloc(void *p, size_t size); char *xstrdup(const char *s); char *xstrndup(const char *s, size_t n); -/* zconf.l */ +/* lexer.l */ int yylex(void); struct gstr { diff --git a/kconfig/lxdialog/inputbox.c b/kconfig/lxdialog/inputbox.c index 6119456..1dcfb28 100644 --- a/kconfig/lxdialog/inputbox.c +++ b/kconfig/lxdialog/inputbox.c @@ -113,7 +113,8 @@ do_resize: case KEY_DOWN: break; case KEY_BACKSPACE: - case 127: + case 8: /* ^H */ + case 127: /* ^? */ if (pos) { wattrset(dialog, dlg.inputbox.atr); if (input_x == 0) { diff --git a/kconfig/nconf.c b/kconfig/nconf.c index fb6027a..96a6bac 100644 --- a/kconfig/nconf.c +++ b/kconfig/nconf.c @@ -1051,7 +1051,7 @@ static int do_match(int key, struct match_state *state, int *ans) state->match_direction = FIND_NEXT_MATCH_UP; *ans = get_mext_match(state->pattern, state->match_direction); - } else if (key == KEY_BACKSPACE || key == 127) { + } else if (key == KEY_BACKSPACE || key == 8 || key == 127) { state->pattern[strlen(state->pattern)-1] = '\0'; adj_match_dir(&state->match_direction); } else diff --git a/kconfig/nconf.gui.c b/kconfig/nconf.gui.c index 7be620a..77f525a 100644 --- a/kconfig/nconf.gui.c +++ b/kconfig/nconf.gui.c @@ -439,7 +439,8 @@ int dialog_inputbox(WINDOW *main_window, case KEY_F(F_EXIT): case KEY_F(F_BACK): break; - case 127: + case 8: /* ^H */ + case 127: /* ^? */ case KEY_BACKSPACE: if (cursor_position > 0) { memmove(&result[cursor_position-1], diff --git a/kconfig/parser.y b/kconfig/parser.y new file mode 100644 index 0000000..60936c7 --- /dev/null +++ b/kconfig/parser.y @@ -0,0 +1,731 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2002 Roman Zippel + */ +%{ + +#include +#include +#include +#include +#include +#include + +#include "lkc.h" + +#define printd(mask, fmt...) if (cdebug & (mask)) printf(fmt) + +#define PRINTD 0x0001 +#define DEBUG_PARSE 0x0002 + +int cdebug = PRINTD; + +static void yyerror(const char *err); +static void zconfprint(const char *err, ...); +static void zconf_error(const char *err, ...); +static bool zconf_endtoken(const char *tokenname, + const char *expected_tokenname); + +struct symbol *symbol_hash[SYMBOL_HASHSIZE]; + +static struct menu *current_menu, *current_entry; + +%} + +%union +{ + char *string; + struct symbol *symbol; + struct expr *expr; + struct menu *menu; + enum symbol_type type; + enum variable_flavor flavor; +} + +%token T_HELPTEXT +%token T_WORD +%token T_WORD_QUOTE +%token T_ALLNOCONFIG_Y +%token T_BOOL +%token T_CHOICE +%token T_CLOSE_PAREN +%token T_COLON_EQUAL +%token T_COMMENT +%token T_CONFIG +%token T_DEFAULT +%token T_DEFCONFIG_LIST +%token T_DEF_BOOL +%token T_DEF_TRISTATE +%token T_DEPENDS +%token T_ENDCHOICE +%token T_ENDIF +%token T_ENDMENU +%token T_HELP +%token T_HEX +%token T_IF +%token T_IMPLY +%token T_INT +%token T_MAINMENU +%token T_MENU +%token T_MENUCONFIG +%token T_MODULES +%token T_ON +%token T_OPEN_PAREN +%token T_OPTION +%token T_OPTIONAL +%token T_PLUS_EQUAL +%token T_PROMPT +%token T_RANGE +%token T_SELECT +%token T_SOURCE +%token T_STRING +%token T_TRISTATE +%token T_VISIBLE +%token T_EOL +%token T_ASSIGN_VAL + +%left T_OR +%left T_AND +%left T_EQUAL T_UNEQUAL +%left T_LESS T_LESS_EQUAL T_GREATER T_GREATER_EQUAL +%nonassoc T_NOT + +%type prompt +%type nonconst_symbol +%type symbol +%type type logic_type default +%type expr +%type if_expr +%type end +%type if_entry menu_entry choice_entry +%type word_opt assign_val +%type assign_op + +%destructor { + fprintf(stderr, "%s:%d: missing end statement for this entry\n", + $$->file->name, $$->lineno); + if (current_menu == $$) + menu_end_menu(); +} if_entry menu_entry choice_entry + +%% +input: mainmenu_stmt stmt_list | stmt_list; + +/* mainmenu entry */ + +mainmenu_stmt: T_MAINMENU prompt T_EOL +{ + menu_add_prompt(P_MENU, $2, NULL); +}; + +stmt_list: + /* empty */ + | stmt_list common_stmt + | stmt_list choice_stmt + | stmt_list menu_stmt + | stmt_list T_WORD error T_EOL { zconf_error("unknown statement \"%s\"", $2); } + | stmt_list error T_EOL { zconf_error("invalid statement"); } +; + +common_stmt: + if_stmt + | comment_stmt + | config_stmt + | menuconfig_stmt + | source_stmt + | assignment_stmt +; + +/* config/menuconfig entry */ + +config_entry_start: T_CONFIG nonconst_symbol T_EOL +{ + $2->flags |= SYMBOL_OPTIONAL; + menu_add_entry($2); + printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), $2->name); +}; + +config_stmt: config_entry_start config_option_list +{ + printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno()); +}; + +menuconfig_entry_start: T_MENUCONFIG nonconst_symbol T_EOL +{ + $2->flags |= SYMBOL_OPTIONAL; + menu_add_entry($2); + printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), $2->name); +}; + +menuconfig_stmt: menuconfig_entry_start config_option_list +{ + if (current_entry->prompt) + current_entry->prompt->type = P_MENU; + else + zconfprint("warning: menuconfig statement without prompt"); + printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno()); +}; + +config_option_list: + /* empty */ + | config_option_list config_option + | config_option_list depends + | config_option_list help +; + +config_option: type prompt_stmt_opt T_EOL +{ + menu_set_type($1); + printd(DEBUG_PARSE, "%s:%d:type(%u)\n", + zconf_curname(), zconf_lineno(), + $1); +}; + +config_option: T_PROMPT prompt if_expr T_EOL +{ + menu_add_prompt(P_PROMPT, $2, $3); + printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno()); +}; + +config_option: default expr if_expr T_EOL +{ + menu_add_expr(P_DEFAULT, $2, $3); + if ($1 != S_UNKNOWN) + menu_set_type($1); + printd(DEBUG_PARSE, "%s:%d:default(%u)\n", + zconf_curname(), zconf_lineno(), + $1); +}; + +config_option: T_SELECT nonconst_symbol if_expr T_EOL +{ + menu_add_symbol(P_SELECT, $2, $3); + printd(DEBUG_PARSE, "%s:%d:select\n", zconf_curname(), zconf_lineno()); +}; + +config_option: T_IMPLY nonconst_symbol if_expr T_EOL +{ + menu_add_symbol(P_IMPLY, $2, $3); + printd(DEBUG_PARSE, "%s:%d:imply\n", zconf_curname(), zconf_lineno()); +}; + +config_option: T_RANGE symbol symbol if_expr T_EOL +{ + menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,$2, $3), $4); + printd(DEBUG_PARSE, "%s:%d:range\n", zconf_curname(), zconf_lineno()); +}; + +config_option: T_OPTION T_MODULES T_EOL +{ + menu_add_option_modules(); +}; + +config_option: T_OPTION T_DEFCONFIG_LIST T_EOL +{ + menu_add_option_defconfig_list(); +}; + +config_option: T_OPTION T_ALLNOCONFIG_Y T_EOL +{ + menu_add_option_allnoconfig_y(); +}; + +/* choice entry */ + +choice: T_CHOICE word_opt T_EOL +{ + struct symbol *sym = sym_lookup($2, SYMBOL_CHOICE); + sym->flags |= SYMBOL_NO_WRITE; + menu_add_entry(sym); + menu_add_expr(P_CHOICE, NULL, NULL); + free($2); + printd(DEBUG_PARSE, "%s:%d:choice\n", zconf_curname(), zconf_lineno()); +}; + +choice_entry: choice choice_option_list +{ + $$ = menu_add_menu(); +}; + +choice_end: end +{ + if (zconf_endtoken($1, "choice")) { + menu_end_menu(); + printd(DEBUG_PARSE, "%s:%d:endchoice\n", zconf_curname(), zconf_lineno()); + } +}; + +choice_stmt: choice_entry choice_block choice_end +; + +choice_option_list: + /* empty */ + | choice_option_list choice_option + | choice_option_list depends + | choice_option_list help +; + +choice_option: T_PROMPT prompt if_expr T_EOL +{ + menu_add_prompt(P_PROMPT, $2, $3); + printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno()); +}; + +choice_option: logic_type prompt_stmt_opt T_EOL +{ + menu_set_type($1); + printd(DEBUG_PARSE, "%s:%d:type(%u)\n", + zconf_curname(), zconf_lineno(), $1); +}; + +choice_option: T_OPTIONAL T_EOL +{ + current_entry->sym->flags |= SYMBOL_OPTIONAL; + printd(DEBUG_PARSE, "%s:%d:optional\n", zconf_curname(), zconf_lineno()); +}; + +choice_option: T_DEFAULT nonconst_symbol if_expr T_EOL +{ + menu_add_symbol(P_DEFAULT, $2, $3); + printd(DEBUG_PARSE, "%s:%d:default\n", + zconf_curname(), zconf_lineno()); +}; + +type: + logic_type + | T_INT { $$ = S_INT; } + | T_HEX { $$ = S_HEX; } + | T_STRING { $$ = S_STRING; } + +logic_type: + T_BOOL { $$ = S_BOOLEAN; } + | T_TRISTATE { $$ = S_TRISTATE; } + +default: + T_DEFAULT { $$ = S_UNKNOWN; } + | T_DEF_BOOL { $$ = S_BOOLEAN; } + | T_DEF_TRISTATE { $$ = S_TRISTATE; } + +choice_block: + /* empty */ + | choice_block common_stmt +; + +/* if entry */ + +if_entry: T_IF expr T_EOL +{ + printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno()); + menu_add_entry(NULL); + menu_add_dep($2); + $$ = menu_add_menu(); +}; + +if_end: end +{ + if (zconf_endtoken($1, "if")) { + menu_end_menu(); + printd(DEBUG_PARSE, "%s:%d:endif\n", zconf_curname(), zconf_lineno()); + } +}; + +if_stmt: if_entry stmt_list if_end +; + +/* menu entry */ + +menu: T_MENU prompt T_EOL +{ + menu_add_entry(NULL); + menu_add_prompt(P_MENU, $2, NULL); + printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno()); +}; + +menu_entry: menu menu_option_list +{ + $$ = menu_add_menu(); +}; + +menu_end: end +{ + if (zconf_endtoken($1, "menu")) { + menu_end_menu(); + printd(DEBUG_PARSE, "%s:%d:endmenu\n", zconf_curname(), zconf_lineno()); + } +}; + +menu_stmt: menu_entry stmt_list menu_end +; + +menu_option_list: + /* empty */ + | menu_option_list visible + | menu_option_list depends +; + +source_stmt: T_SOURCE prompt T_EOL +{ + printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), $2); + zconf_nextfile($2); + free($2); +}; + +/* comment entry */ + +comment: T_COMMENT prompt T_EOL +{ + menu_add_entry(NULL); + menu_add_prompt(P_COMMENT, $2, NULL); + printd(DEBUG_PARSE, "%s:%d:comment\n", zconf_curname(), zconf_lineno()); +}; + +comment_stmt: comment comment_option_list +; + +comment_option_list: + /* empty */ + | comment_option_list depends +; + +/* help option */ + +help_start: T_HELP T_EOL +{ + printd(DEBUG_PARSE, "%s:%d:help\n", zconf_curname(), zconf_lineno()); + zconf_starthelp(); +}; + +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 ?: ""); + } + + /* 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 ?: ""); + + current_entry->help = $2; +}; + +/* depends option */ + +depends: T_DEPENDS T_ON expr T_EOL +{ + menu_add_dep($3); + printd(DEBUG_PARSE, "%s:%d:depends on\n", zconf_curname(), zconf_lineno()); +}; + +/* visibility option */ +visible: T_VISIBLE if_expr T_EOL +{ + menu_add_visibility($2); +}; + +/* prompt statement */ + +prompt_stmt_opt: + /* empty */ + | prompt if_expr +{ + menu_add_prompt(P_PROMPT, $1, $2); +}; + +prompt: T_WORD + | T_WORD_QUOTE +; + +end: T_ENDMENU T_EOL { $$ = "menu"; } + | T_ENDCHOICE T_EOL { $$ = "choice"; } + | T_ENDIF T_EOL { $$ = "if"; } +; + +if_expr: /* empty */ { $$ = NULL; } + | T_IF expr { $$ = $2; } +; + +expr: symbol { $$ = expr_alloc_symbol($1); } + | symbol T_LESS symbol { $$ = expr_alloc_comp(E_LTH, $1, $3); } + | symbol T_LESS_EQUAL symbol { $$ = expr_alloc_comp(E_LEQ, $1, $3); } + | symbol T_GREATER symbol { $$ = expr_alloc_comp(E_GTH, $1, $3); } + | symbol T_GREATER_EQUAL symbol { $$ = expr_alloc_comp(E_GEQ, $1, $3); } + | symbol T_EQUAL symbol { $$ = expr_alloc_comp(E_EQUAL, $1, $3); } + | symbol T_UNEQUAL symbol { $$ = expr_alloc_comp(E_UNEQUAL, $1, $3); } + | T_OPEN_PAREN expr T_CLOSE_PAREN { $$ = $2; } + | T_NOT expr { $$ = expr_alloc_one(E_NOT, $2); } + | expr T_OR expr { $$ = expr_alloc_two(E_OR, $1, $3); } + | expr T_AND expr { $$ = expr_alloc_two(E_AND, $1, $3); } +; + +/* For symbol definitions, selects, etc., where quotes are not accepted */ +nonconst_symbol: T_WORD { $$ = sym_lookup($1, 0); free($1); }; + +symbol: nonconst_symbol + | T_WORD_QUOTE { $$ = sym_lookup($1, SYMBOL_CONST); free($1); } +; + +word_opt: /* empty */ { $$ = NULL; } + | T_WORD + +/* assignment statement */ + +assignment_stmt: T_WORD assign_op assign_val T_EOL { variable_add($1, $3, $2); free($1); free($3); } + +assign_op: + T_EQUAL { $$ = VAR_RECURSIVE; } + | T_COLON_EQUAL { $$ = VAR_SIMPLE; } + | T_PLUS_EQUAL { $$ = VAR_APPEND; } +; + +assign_val: + /* empty */ { $$ = xstrdup(""); }; + | T_ASSIGN_VAL +; + +%% + +void conf_parse(const char *name) +{ + struct symbol *sym; + int i; + + zconf_initscan(name); + + _menu_init(); + + if (getenv("ZCONF_DEBUG")) + yydebug = 1; + yyparse(); + + /* Variables are expanded in the parse phase. We can free them here. */ + variable_all_del(); + + if (yynerrs) + exit(1); + if (!modules_sym) + modules_sym = sym_find( "n" ); + + if (!menu_has_prompt(&rootmenu)) { + current_entry = &rootmenu; + menu_add_prompt(P_MENU, "Main menu", NULL); + } + + menu_finalize(&rootmenu); + for_all_symbols(i, sym) { + if (sym_check_deps(sym)) + yynerrs++; + } + if (yynerrs) + exit(1); + sym_set_change_count(1); +} + +static bool zconf_endtoken(const char *tokenname, + const char *expected_tokenname) +{ + if (strcmp(tokenname, expected_tokenname)) { + zconf_error("unexpected '%s' within %s block", + tokenname, expected_tokenname); + yynerrs++; + return false; + } + if (current_menu->file != current_file) { + zconf_error("'%s' in different file than '%s'", + tokenname, expected_tokenname); + fprintf(stderr, "%s:%d: location of the '%s'\n", + current_menu->file->name, current_menu->lineno, + expected_tokenname); + yynerrs++; + return false; + } + return true; +} + +static void zconfprint(const char *err, ...) +{ + va_list ap; + + fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno()); + va_start(ap, err); + vfprintf(stderr, err, ap); + va_end(ap); + fprintf(stderr, "\n"); +} + +static void zconf_error(const char *err, ...) +{ + va_list ap; + + yynerrs++; + fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno()); + va_start(ap, err); + vfprintf(stderr, err, ap); + va_end(ap); + fprintf(stderr, "\n"); +} + +static void yyerror(const char *err) +{ + fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno() + 1, err); +} + +static void print_quoted_string(FILE *out, const char *str) +{ + const char *p; + int len; + + putc('"', out); + while ((p = strchr(str, '"'))) { + len = p - str; + if (len) + fprintf(out, "%.*s", len, str); + fputs("\\\"", out); + str = p + 1; + } + fputs(str, out); + putc('"', out); +} + +static void print_symbol(FILE *out, struct menu *menu) +{ + struct symbol *sym = menu->sym; + struct property *prop; + + if (sym_is_choice(sym)) + fprintf(out, "\nchoice\n"); + else + fprintf(out, "\nconfig %s\n", sym->name); + switch (sym->type) { + case S_BOOLEAN: + fputs(" bool\n", out); + break; + case S_TRISTATE: + fputs(" tristate\n", out); + break; + case S_STRING: + fputs(" string\n", out); + break; + case S_INT: + fputs(" integer\n", out); + break; + case S_HEX: + fputs(" hex\n", out); + break; + default: + fputs(" ???\n", out); + break; + } + for (prop = sym->prop; prop; prop = prop->next) { + if (prop->menu != menu) + continue; + switch (prop->type) { + case P_PROMPT: + fputs(" prompt ", out); + print_quoted_string(out, prop->text); + if (!expr_is_yes(prop->visible.expr)) { + fputs(" if ", out); + expr_fprint(prop->visible.expr, out); + } + fputc('\n', out); + break; + case P_DEFAULT: + fputs( " default ", out); + expr_fprint(prop->expr, out); + if (!expr_is_yes(prop->visible.expr)) { + fputs(" if ", out); + expr_fprint(prop->visible.expr, out); + } + fputc('\n', out); + break; + case P_CHOICE: + fputs(" #choice value\n", out); + break; + case P_SELECT: + fputs( " select ", out); + expr_fprint(prop->expr, out); + fputc('\n', out); + break; + case P_IMPLY: + fputs( " imply ", out); + expr_fprint(prop->expr, out); + fputc('\n', out); + break; + case P_RANGE: + fputs( " range ", out); + expr_fprint(prop->expr, out); + fputc('\n', out); + break; + case P_MENU: + fputs( " menu ", out); + print_quoted_string(out, prop->text); + fputc('\n', out); + break; + case P_SYMBOL: + fputs( " symbol ", out); + fprintf(out, "%s\n", prop->sym->name); + break; + default: + fprintf(out, " unknown prop %d!\n", prop->type); + break; + } + } + if (menu->help) { + int len = strlen(menu->help); + while (menu->help[--len] == '\n') + menu->help[len] = 0; + fprintf(out, " help\n%s\n", menu->help); + } +} + +void zconfdump(FILE *out) +{ + struct property *prop; + struct symbol *sym; + struct menu *menu; + + menu = rootmenu.list; + while (menu) { + if ((sym = menu->sym)) + print_symbol(out, menu); + else if ((prop = menu->prompt)) { + switch (prop->type) { + case P_COMMENT: + fputs("\ncomment ", out); + print_quoted_string(out, prop->text); + fputs("\n", out); + break; + case P_MENU: + fputs("\nmenu ", out); + print_quoted_string(out, prop->text); + fputs("\n", out); + break; + default: + ; + } + if (!expr_is_yes(prop->visible.expr)) { + fputs(" depends ", out); + expr_fprint(prop->visible.expr, out); + fputc('\n', out); + } + } + + if (menu->list) + menu = menu->list; + else if (menu->next) + menu = menu->next; + else while ((menu = menu->parent)) { + if (menu->prompt && menu->prompt->type == P_MENU) + fputs("\nendmenu\n", out); + if (menu->next) { + menu = menu->next; + break; + } + } + } +} + +#include "util.c" +#include "menu.c" diff --git a/kconfig/zconf.l b/kconfig/zconf.l deleted file mode 100644 index b2d0a3b..0000000 --- a/kconfig/zconf.l +++ /dev/null @@ -1,470 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright (C) 2002 Roman Zippel - */ -%option nostdinit noyywrap never-interactive full ecs -%option 8bit nodefault yylineno -%x ASSIGN_VAL HELP STRING -%{ - -#include -#include -#include -#include -#include -#include - -#include "lkc.h" -#include "zconf.tab.h" - -#define YY_DECL static int yylex1(void) - -#define START_STRSIZE 16 - -static struct { - struct file *file; - int lineno; -} current_pos; - -static int prev_prev_token = T_EOL; -static int prev_token = T_EOL; -static char *text; -static int text_size, text_asize; - -struct buffer { - struct buffer *parent; - YY_BUFFER_STATE state; -}; - -struct buffer *current_buf; - -static int last_ts, first_ts; - -static char *expand_token(const char *in, size_t n); -static void append_expanded_string(const char *in); -static void zconf_endhelp(void); -static void zconf_endfile(void); - -static void new_string(void) -{ - text = xmalloc(START_STRSIZE); - text_asize = START_STRSIZE; - text_size = 0; - *text = 0; -} - -static void append_string(const char *str, int size) -{ - int new_size = text_size + size + 1; - if (new_size > text_asize) { - new_size += START_STRSIZE - 1; - new_size &= -START_STRSIZE; - text = xrealloc(text, new_size); - text_asize = new_size; - } - memcpy(text + text_size, str, size); - text_size += size; - text[text_size] = 0; -} - -static void alloc_string(const char *str, int size) -{ - text = xmalloc(size + 1); - memcpy(text, str, size); - text[size] = 0; -} - -static void warn_ignored_character(char chr) -{ - fprintf(stderr, - "%s:%d:warning: ignoring unsupported character '%c'\n", - current_file->name, yylineno, chr); -} -%} - -n [A-Za-z0-9_-] - -%% - int str = 0; - int ts, i; - -#.* /* ignore comment */ -[ \t]* /* whitespaces */ -\\\n /* escaped new line */ -\n return T_EOL; -"allnoconfig_y" return T_ALLNOCONFIG_Y; -"bool" return T_BOOL; -"choice" return T_CHOICE; -"comment" return T_COMMENT; -"config" return T_CONFIG; -"def_bool" return T_DEF_BOOL; -"def_tristate" return T_DEF_TRISTATE; -"default" return T_DEFAULT; -"defconfig_list" return T_DEFCONFIG_LIST; -"depends" return T_DEPENDS; -"endchoice" return T_ENDCHOICE; -"endif" return T_ENDIF; -"endmenu" return T_ENDMENU; -"help"|"---help---" return T_HELP; -"hex" return T_HEX; -"if" return T_IF; -"imply" return T_IMPLY; -"int" return T_INT; -"mainmenu" return T_MAINMENU; -"menu" return T_MENU; -"menuconfig" return T_MENUCONFIG; -"modules" return T_MODULES; -"on" return T_ON; -"option" return T_OPTION; -"optional" return T_OPTIONAL; -"prompt" return T_PROMPT; -"range" return T_RANGE; -"select" return T_SELECT; -"source" return T_SOURCE; -"string" return T_STRING; -"tristate" return T_TRISTATE; -"visible" return T_VISIBLE; -"||" return T_OR; -"&&" return T_AND; -"=" return T_EQUAL; -"!=" return T_UNEQUAL; -"<" return T_LESS; -"<=" return T_LESS_EQUAL; -">" return T_GREATER; -">=" return T_GREATER_EQUAL; -"!" return T_NOT; -"(" return T_OPEN_PAREN; -")" return T_CLOSE_PAREN; -":=" return T_COLON_EQUAL; -"+=" return T_PLUS_EQUAL; -\"|\' { - str = yytext[0]; - new_string(); - BEGIN(STRING); - } -{n}+ { - alloc_string(yytext, yyleng); - yylval.string = text; - return T_WORD; - } -({n}|$)+ { - /* this token includes at least one '$' */ - yylval.string = expand_token(yytext, yyleng); - if (strlen(yylval.string)) - return T_WORD; - free(yylval.string); - } -. warn_ignored_character(*yytext); - -{ - [^[:blank:]\n]+.* { - alloc_string(yytext, yyleng); - yylval.string = text; - return T_ASSIGN_VAL; - } - \n { BEGIN(INITIAL); return T_EOL; } - . -} - -{ - "$".* append_expanded_string(yytext); - [^$'"\\\n]+ { - append_string(yytext, yyleng); - } - \\.? { - append_string(yytext + 1, yyleng - 1); - } - \'|\" { - if (str == yytext[0]) { - BEGIN(INITIAL); - yylval.string = text; - return T_WORD_QUOTE; - } else - append_string(yytext, 1); - } - \n { - fprintf(stderr, - "%s:%d:warning: multi-line strings not supported\n", - zconf_curname(), zconf_lineno()); - unput('\n'); - BEGIN(INITIAL); - yylval.string = text; - return T_WORD_QUOTE; - } - <> { - BEGIN(INITIAL); - yylval.string = text; - return T_WORD_QUOTE; - } -} - -{ - [ \t]+ { - ts = 0; - for (i = 0; i < yyleng; i++) { - if (yytext[i] == '\t') - ts = (ts & ~7) + 8; - else - ts++; - } - last_ts = ts; - if (first_ts) { - if (ts < first_ts) { - zconf_endhelp(); - return T_HELPTEXT; - } - ts -= first_ts; - while (ts > 8) { - append_string(" ", 8); - ts -= 8; - } - append_string(" ", ts); - } - } - [ \t]*\n/[^ \t\n] { - zconf_endhelp(); - return T_HELPTEXT; - } - [ \t]*\n { - append_string("\n", 1); - } - [^ \t\n].* { - while (yyleng) { - if ((yytext[yyleng-1] != ' ') && (yytext[yyleng-1] != '\t')) - break; - yyleng--; - } - append_string(yytext, yyleng); - if (!first_ts) - first_ts = last_ts; - } - <> { - zconf_endhelp(); - return T_HELPTEXT; - } -} - -<> { - BEGIN(INITIAL); - - if (prev_token != T_EOL && prev_token != T_HELPTEXT) - fprintf(stderr, "%s:%d:warning: no new line at end of file\n", - current_file->name, yylineno); - - if (current_file) { - zconf_endfile(); - return T_EOL; - } - fclose(yyin); - yyterminate(); -} - -%% - -/* second stage lexer */ -int yylex(void) -{ - int token; - -repeat: - token = yylex1(); - - if (prev_token == T_EOL || prev_token == T_HELPTEXT) { - if (token == T_EOL) { - /* Do not pass unneeded T_EOL to the parser. */ - goto repeat; - } else { - /* - * For the parser, update file/lineno at the first token - * of each statement. Generally, \n is a statement - * terminator in Kconfig, but it is not always true - * because \n could be escaped by a backslash. - */ - current_pos.file = current_file; - current_pos.lineno = yylineno; - } - } - - if (prev_prev_token == T_EOL && prev_token == T_WORD && - (token == T_EQUAL || token == T_COLON_EQUAL || token == T_PLUS_EQUAL)) - BEGIN(ASSIGN_VAL); - - prev_prev_token = prev_token; - prev_token = token; - - return token; -} - -static char *expand_token(const char *in, size_t n) -{ - char *out; - int c; - char c2; - const char *rest, *end; - - new_string(); - append_string(in, n); - - /* get the whole line because we do not know the end of token. */ - while ((c = input()) != EOF) { - if (c == '\n') { - unput(c); - break; - } - c2 = c; - append_string(&c2, 1); - } - - rest = text; - out = expand_one_token(&rest); - - /* push back unused characters to the input stream */ - end = rest + strlen(rest); - while (end > rest) - unput(*--end); - - free(text); - - return out; -} - -static void append_expanded_string(const char *str) -{ - const char *end; - char *res; - - str++; - - res = expand_dollar(&str); - - /* push back unused characters to the input stream */ - end = str + strlen(str); - while (end > str) - unput(*--end); - - append_string(res, strlen(res)); - - free(res); -} - -void zconf_starthelp(void) -{ - new_string(); - last_ts = first_ts = 0; - BEGIN(HELP); -} - -static void zconf_endhelp(void) -{ - yylval.string = text; - BEGIN(INITIAL); -} - - -/* - * Try to open specified file with following names: - * ./name - * $(srctree)/name - * The latter is used when srctree is separate from objtree - * when compiling the kernel. - * Return NULL if file is not found. - */ -FILE *zconf_fopen(const char *name) -{ - char *env, fullname[PATH_MAX+1]; - FILE *f; - - f = fopen(name, "r"); - if (!f && name != NULL && name[0] != '/') { - env = getenv(SRCTREE); - if (env) { - sprintf(fullname, "%s/%s", env, name); - f = fopen(fullname, "r"); - } - } - return f; -} - -void zconf_initscan(const char *name) -{ - yyin = zconf_fopen(name); - if (!yyin) { - fprintf(stderr, "can't find file %s\n", name); - exit(1); - } - - current_buf = xmalloc(sizeof(*current_buf)); - memset(current_buf, 0, sizeof(*current_buf)); - - current_file = file_lookup(name); - yylineno = 1; -} - -void zconf_nextfile(const char *name) -{ - struct file *iter; - struct file *file = file_lookup(name); - struct buffer *buf = xmalloc(sizeof(*buf)); - memset(buf, 0, sizeof(*buf)); - - current_buf->state = YY_CURRENT_BUFFER; - yyin = zconf_fopen(file->name); - if (!yyin) { - fprintf(stderr, "%s:%d: can't open file \"%s\"\n", - zconf_curname(), zconf_lineno(), file->name); - exit(1); - } - yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE)); - buf->parent = current_buf; - current_buf = buf; - - current_file->lineno = yylineno; - file->parent = current_file; - - for (iter = current_file; iter; iter = iter->parent) { - if (!strcmp(iter->name, file->name)) { - fprintf(stderr, - "Recursive inclusion detected.\n" - "Inclusion path:\n" - " current file : %s\n", file->name); - iter = file; - do { - iter = iter->parent; - fprintf(stderr, " included from: %s:%d\n", - iter->name, iter->lineno - 1); - } while (strcmp(iter->name, file->name)); - exit(1); - } - } - - yylineno = 1; - current_file = file; -} - -static void zconf_endfile(void) -{ - struct buffer *parent; - - current_file = current_file->parent; - if (current_file) - yylineno = current_file->lineno; - - parent = current_buf->parent; - if (parent) { - fclose(yyin); - yy_delete_buffer(YY_CURRENT_BUFFER); - yy_switch_to_buffer(parent->state); - } - free(current_buf); - current_buf = parent; -} - -int zconf_lineno(void) -{ - return current_pos.lineno; -} - -const char *zconf_curname(void) -{ - return current_pos.file ? current_pos.file->name : ""; -} diff --git a/kconfig/zconf.y b/kconfig/zconf.y deleted file mode 100644 index 60936c7..0000000 --- a/kconfig/zconf.y +++ /dev/null @@ -1,731 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright (C) 2002 Roman Zippel - */ -%{ - -#include -#include -#include -#include -#include -#include - -#include "lkc.h" - -#define printd(mask, fmt...) if (cdebug & (mask)) printf(fmt) - -#define PRINTD 0x0001 -#define DEBUG_PARSE 0x0002 - -int cdebug = PRINTD; - -static void yyerror(const char *err); -static void zconfprint(const char *err, ...); -static void zconf_error(const char *err, ...); -static bool zconf_endtoken(const char *tokenname, - const char *expected_tokenname); - -struct symbol *symbol_hash[SYMBOL_HASHSIZE]; - -static struct menu *current_menu, *current_entry; - -%} - -%union -{ - char *string; - struct symbol *symbol; - struct expr *expr; - struct menu *menu; - enum symbol_type type; - enum variable_flavor flavor; -} - -%token T_HELPTEXT -%token T_WORD -%token T_WORD_QUOTE -%token T_ALLNOCONFIG_Y -%token T_BOOL -%token T_CHOICE -%token T_CLOSE_PAREN -%token T_COLON_EQUAL -%token T_COMMENT -%token T_CONFIG -%token T_DEFAULT -%token T_DEFCONFIG_LIST -%token T_DEF_BOOL -%token T_DEF_TRISTATE -%token T_DEPENDS -%token T_ENDCHOICE -%token T_ENDIF -%token T_ENDMENU -%token T_HELP -%token T_HEX -%token T_IF -%token T_IMPLY -%token T_INT -%token T_MAINMENU -%token T_MENU -%token T_MENUCONFIG -%token T_MODULES -%token T_ON -%token T_OPEN_PAREN -%token T_OPTION -%token T_OPTIONAL -%token T_PLUS_EQUAL -%token T_PROMPT -%token T_RANGE -%token T_SELECT -%token T_SOURCE -%token T_STRING -%token T_TRISTATE -%token T_VISIBLE -%token T_EOL -%token T_ASSIGN_VAL - -%left T_OR -%left T_AND -%left T_EQUAL T_UNEQUAL -%left T_LESS T_LESS_EQUAL T_GREATER T_GREATER_EQUAL -%nonassoc T_NOT - -%type prompt -%type nonconst_symbol -%type symbol -%type type logic_type default -%type expr -%type if_expr -%type end -%type if_entry menu_entry choice_entry -%type word_opt assign_val -%type assign_op - -%destructor { - fprintf(stderr, "%s:%d: missing end statement for this entry\n", - $$->file->name, $$->lineno); - if (current_menu == $$) - menu_end_menu(); -} if_entry menu_entry choice_entry - -%% -input: mainmenu_stmt stmt_list | stmt_list; - -/* mainmenu entry */ - -mainmenu_stmt: T_MAINMENU prompt T_EOL -{ - menu_add_prompt(P_MENU, $2, NULL); -}; - -stmt_list: - /* empty */ - | stmt_list common_stmt - | stmt_list choice_stmt - | stmt_list menu_stmt - | stmt_list T_WORD error T_EOL { zconf_error("unknown statement \"%s\"", $2); } - | stmt_list error T_EOL { zconf_error("invalid statement"); } -; - -common_stmt: - if_stmt - | comment_stmt - | config_stmt - | menuconfig_stmt - | source_stmt - | assignment_stmt -; - -/* config/menuconfig entry */ - -config_entry_start: T_CONFIG nonconst_symbol T_EOL -{ - $2->flags |= SYMBOL_OPTIONAL; - menu_add_entry($2); - printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), $2->name); -}; - -config_stmt: config_entry_start config_option_list -{ - printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno()); -}; - -menuconfig_entry_start: T_MENUCONFIG nonconst_symbol T_EOL -{ - $2->flags |= SYMBOL_OPTIONAL; - menu_add_entry($2); - printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), $2->name); -}; - -menuconfig_stmt: menuconfig_entry_start config_option_list -{ - if (current_entry->prompt) - current_entry->prompt->type = P_MENU; - else - zconfprint("warning: menuconfig statement without prompt"); - printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno()); -}; - -config_option_list: - /* empty */ - | config_option_list config_option - | config_option_list depends - | config_option_list help -; - -config_option: type prompt_stmt_opt T_EOL -{ - menu_set_type($1); - printd(DEBUG_PARSE, "%s:%d:type(%u)\n", - zconf_curname(), zconf_lineno(), - $1); -}; - -config_option: T_PROMPT prompt if_expr T_EOL -{ - menu_add_prompt(P_PROMPT, $2, $3); - printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno()); -}; - -config_option: default expr if_expr T_EOL -{ - menu_add_expr(P_DEFAULT, $2, $3); - if ($1 != S_UNKNOWN) - menu_set_type($1); - printd(DEBUG_PARSE, "%s:%d:default(%u)\n", - zconf_curname(), zconf_lineno(), - $1); -}; - -config_option: T_SELECT nonconst_symbol if_expr T_EOL -{ - menu_add_symbol(P_SELECT, $2, $3); - printd(DEBUG_PARSE, "%s:%d:select\n", zconf_curname(), zconf_lineno()); -}; - -config_option: T_IMPLY nonconst_symbol if_expr T_EOL -{ - menu_add_symbol(P_IMPLY, $2, $3); - printd(DEBUG_PARSE, "%s:%d:imply\n", zconf_curname(), zconf_lineno()); -}; - -config_option: T_RANGE symbol symbol if_expr T_EOL -{ - menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,$2, $3), $4); - printd(DEBUG_PARSE, "%s:%d:range\n", zconf_curname(), zconf_lineno()); -}; - -config_option: T_OPTION T_MODULES T_EOL -{ - menu_add_option_modules(); -}; - -config_option: T_OPTION T_DEFCONFIG_LIST T_EOL -{ - menu_add_option_defconfig_list(); -}; - -config_option: T_OPTION T_ALLNOCONFIG_Y T_EOL -{ - menu_add_option_allnoconfig_y(); -}; - -/* choice entry */ - -choice: T_CHOICE word_opt T_EOL -{ - struct symbol *sym = sym_lookup($2, SYMBOL_CHOICE); - sym->flags |= SYMBOL_NO_WRITE; - menu_add_entry(sym); - menu_add_expr(P_CHOICE, NULL, NULL); - free($2); - printd(DEBUG_PARSE, "%s:%d:choice\n", zconf_curname(), zconf_lineno()); -}; - -choice_entry: choice choice_option_list -{ - $$ = menu_add_menu(); -}; - -choice_end: end -{ - if (zconf_endtoken($1, "choice")) { - menu_end_menu(); - printd(DEBUG_PARSE, "%s:%d:endchoice\n", zconf_curname(), zconf_lineno()); - } -}; - -choice_stmt: choice_entry choice_block choice_end -; - -choice_option_list: - /* empty */ - | choice_option_list choice_option - | choice_option_list depends - | choice_option_list help -; - -choice_option: T_PROMPT prompt if_expr T_EOL -{ - menu_add_prompt(P_PROMPT, $2, $3); - printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno()); -}; - -choice_option: logic_type prompt_stmt_opt T_EOL -{ - menu_set_type($1); - printd(DEBUG_PARSE, "%s:%d:type(%u)\n", - zconf_curname(), zconf_lineno(), $1); -}; - -choice_option: T_OPTIONAL T_EOL -{ - current_entry->sym->flags |= SYMBOL_OPTIONAL; - printd(DEBUG_PARSE, "%s:%d:optional\n", zconf_curname(), zconf_lineno()); -}; - -choice_option: T_DEFAULT nonconst_symbol if_expr T_EOL -{ - menu_add_symbol(P_DEFAULT, $2, $3); - printd(DEBUG_PARSE, "%s:%d:default\n", - zconf_curname(), zconf_lineno()); -}; - -type: - logic_type - | T_INT { $$ = S_INT; } - | T_HEX { $$ = S_HEX; } - | T_STRING { $$ = S_STRING; } - -logic_type: - T_BOOL { $$ = S_BOOLEAN; } - | T_TRISTATE { $$ = S_TRISTATE; } - -default: - T_DEFAULT { $$ = S_UNKNOWN; } - | T_DEF_BOOL { $$ = S_BOOLEAN; } - | T_DEF_TRISTATE { $$ = S_TRISTATE; } - -choice_block: - /* empty */ - | choice_block common_stmt -; - -/* if entry */ - -if_entry: T_IF expr T_EOL -{ - printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno()); - menu_add_entry(NULL); - menu_add_dep($2); - $$ = menu_add_menu(); -}; - -if_end: end -{ - if (zconf_endtoken($1, "if")) { - menu_end_menu(); - printd(DEBUG_PARSE, "%s:%d:endif\n", zconf_curname(), zconf_lineno()); - } -}; - -if_stmt: if_entry stmt_list if_end -; - -/* menu entry */ - -menu: T_MENU prompt T_EOL -{ - menu_add_entry(NULL); - menu_add_prompt(P_MENU, $2, NULL); - printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno()); -}; - -menu_entry: menu menu_option_list -{ - $$ = menu_add_menu(); -}; - -menu_end: end -{ - if (zconf_endtoken($1, "menu")) { - menu_end_menu(); - printd(DEBUG_PARSE, "%s:%d:endmenu\n", zconf_curname(), zconf_lineno()); - } -}; - -menu_stmt: menu_entry stmt_list menu_end -; - -menu_option_list: - /* empty */ - | menu_option_list visible - | menu_option_list depends -; - -source_stmt: T_SOURCE prompt T_EOL -{ - printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), $2); - zconf_nextfile($2); - free($2); -}; - -/* comment entry */ - -comment: T_COMMENT prompt T_EOL -{ - menu_add_entry(NULL); - menu_add_prompt(P_COMMENT, $2, NULL); - printd(DEBUG_PARSE, "%s:%d:comment\n", zconf_curname(), zconf_lineno()); -}; - -comment_stmt: comment comment_option_list -; - -comment_option_list: - /* empty */ - | comment_option_list depends -; - -/* help option */ - -help_start: T_HELP T_EOL -{ - printd(DEBUG_PARSE, "%s:%d:help\n", zconf_curname(), zconf_lineno()); - zconf_starthelp(); -}; - -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 ?: ""); - } - - /* 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 ?: ""); - - current_entry->help = $2; -}; - -/* depends option */ - -depends: T_DEPENDS T_ON expr T_EOL -{ - menu_add_dep($3); - printd(DEBUG_PARSE, "%s:%d:depends on\n", zconf_curname(), zconf_lineno()); -}; - -/* visibility option */ -visible: T_VISIBLE if_expr T_EOL -{ - menu_add_visibility($2); -}; - -/* prompt statement */ - -prompt_stmt_opt: - /* empty */ - | prompt if_expr -{ - menu_add_prompt(P_PROMPT, $1, $2); -}; - -prompt: T_WORD - | T_WORD_QUOTE -; - -end: T_ENDMENU T_EOL { $$ = "menu"; } - | T_ENDCHOICE T_EOL { $$ = "choice"; } - | T_ENDIF T_EOL { $$ = "if"; } -; - -if_expr: /* empty */ { $$ = NULL; } - | T_IF expr { $$ = $2; } -; - -expr: symbol { $$ = expr_alloc_symbol($1); } - | symbol T_LESS symbol { $$ = expr_alloc_comp(E_LTH, $1, $3); } - | symbol T_LESS_EQUAL symbol { $$ = expr_alloc_comp(E_LEQ, $1, $3); } - | symbol T_GREATER symbol { $$ = expr_alloc_comp(E_GTH, $1, $3); } - | symbol T_GREATER_EQUAL symbol { $$ = expr_alloc_comp(E_GEQ, $1, $3); } - | symbol T_EQUAL symbol { $$ = expr_alloc_comp(E_EQUAL, $1, $3); } - | symbol T_UNEQUAL symbol { $$ = expr_alloc_comp(E_UNEQUAL, $1, $3); } - | T_OPEN_PAREN expr T_CLOSE_PAREN { $$ = $2; } - | T_NOT expr { $$ = expr_alloc_one(E_NOT, $2); } - | expr T_OR expr { $$ = expr_alloc_two(E_OR, $1, $3); } - | expr T_AND expr { $$ = expr_alloc_two(E_AND, $1, $3); } -; - -/* For symbol definitions, selects, etc., where quotes are not accepted */ -nonconst_symbol: T_WORD { $$ = sym_lookup($1, 0); free($1); }; - -symbol: nonconst_symbol - | T_WORD_QUOTE { $$ = sym_lookup($1, SYMBOL_CONST); free($1); } -; - -word_opt: /* empty */ { $$ = NULL; } - | T_WORD - -/* assignment statement */ - -assignment_stmt: T_WORD assign_op assign_val T_EOL { variable_add($1, $3, $2); free($1); free($3); } - -assign_op: - T_EQUAL { $$ = VAR_RECURSIVE; } - | T_COLON_EQUAL { $$ = VAR_SIMPLE; } - | T_PLUS_EQUAL { $$ = VAR_APPEND; } -; - -assign_val: - /* empty */ { $$ = xstrdup(""); }; - | T_ASSIGN_VAL -; - -%% - -void conf_parse(const char *name) -{ - struct symbol *sym; - int i; - - zconf_initscan(name); - - _menu_init(); - - if (getenv("ZCONF_DEBUG")) - yydebug = 1; - yyparse(); - - /* Variables are expanded in the parse phase. We can free them here. */ - variable_all_del(); - - if (yynerrs) - exit(1); - if (!modules_sym) - modules_sym = sym_find( "n" ); - - if (!menu_has_prompt(&rootmenu)) { - current_entry = &rootmenu; - menu_add_prompt(P_MENU, "Main menu", NULL); - } - - menu_finalize(&rootmenu); - for_all_symbols(i, sym) { - if (sym_check_deps(sym)) - yynerrs++; - } - if (yynerrs) - exit(1); - sym_set_change_count(1); -} - -static bool zconf_endtoken(const char *tokenname, - const char *expected_tokenname) -{ - if (strcmp(tokenname, expected_tokenname)) { - zconf_error("unexpected '%s' within %s block", - tokenname, expected_tokenname); - yynerrs++; - return false; - } - if (current_menu->file != current_file) { - zconf_error("'%s' in different file than '%s'", - tokenname, expected_tokenname); - fprintf(stderr, "%s:%d: location of the '%s'\n", - current_menu->file->name, current_menu->lineno, - expected_tokenname); - yynerrs++; - return false; - } - return true; -} - -static void zconfprint(const char *err, ...) -{ - va_list ap; - - fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno()); - va_start(ap, err); - vfprintf(stderr, err, ap); - va_end(ap); - fprintf(stderr, "\n"); -} - -static void zconf_error(const char *err, ...) -{ - va_list ap; - - yynerrs++; - fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno()); - va_start(ap, err); - vfprintf(stderr, err, ap); - va_end(ap); - fprintf(stderr, "\n"); -} - -static void yyerror(const char *err) -{ - fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno() + 1, err); -} - -static void print_quoted_string(FILE *out, const char *str) -{ - const char *p; - int len; - - putc('"', out); - while ((p = strchr(str, '"'))) { - len = p - str; - if (len) - fprintf(out, "%.*s", len, str); - fputs("\\\"", out); - str = p + 1; - } - fputs(str, out); - putc('"', out); -} - -static void print_symbol(FILE *out, struct menu *menu) -{ - struct symbol *sym = menu->sym; - struct property *prop; - - if (sym_is_choice(sym)) - fprintf(out, "\nchoice\n"); - else - fprintf(out, "\nconfig %s\n", sym->name); - switch (sym->type) { - case S_BOOLEAN: - fputs(" bool\n", out); - break; - case S_TRISTATE: - fputs(" tristate\n", out); - break; - case S_STRING: - fputs(" string\n", out); - break; - case S_INT: - fputs(" integer\n", out); - break; - case S_HEX: - fputs(" hex\n", out); - break; - default: - fputs(" ???\n", out); - break; - } - for (prop = sym->prop; prop; prop = prop->next) { - if (prop->menu != menu) - continue; - switch (prop->type) { - case P_PROMPT: - fputs(" prompt ", out); - print_quoted_string(out, prop->text); - if (!expr_is_yes(prop->visible.expr)) { - fputs(" if ", out); - expr_fprint(prop->visible.expr, out); - } - fputc('\n', out); - break; - case P_DEFAULT: - fputs( " default ", out); - expr_fprint(prop->expr, out); - if (!expr_is_yes(prop->visible.expr)) { - fputs(" if ", out); - expr_fprint(prop->visible.expr, out); - } - fputc('\n', out); - break; - case P_CHOICE: - fputs(" #choice value\n", out); - break; - case P_SELECT: - fputs( " select ", out); - expr_fprint(prop->expr, out); - fputc('\n', out); - break; - case P_IMPLY: - fputs( " imply ", out); - expr_fprint(prop->expr, out); - fputc('\n', out); - break; - case P_RANGE: - fputs( " range ", out); - expr_fprint(prop->expr, out); - fputc('\n', out); - break; - case P_MENU: - fputs( " menu ", out); - print_quoted_string(out, prop->text); - fputc('\n', out); - break; - case P_SYMBOL: - fputs( " symbol ", out); - fprintf(out, "%s\n", prop->sym->name); - break; - default: - fprintf(out, " unknown prop %d!\n", prop->type); - break; - } - } - if (menu->help) { - int len = strlen(menu->help); - while (menu->help[--len] == '\n') - menu->help[len] = 0; - fprintf(out, " help\n%s\n", menu->help); - } -} - -void zconfdump(FILE *out) -{ - struct property *prop; - struct symbol *sym; - struct menu *menu; - - menu = rootmenu.list; - while (menu) { - if ((sym = menu->sym)) - print_symbol(out, menu); - else if ((prop = menu->prompt)) { - switch (prop->type) { - case P_COMMENT: - fputs("\ncomment ", out); - print_quoted_string(out, prop->text); - fputs("\n", out); - break; - case P_MENU: - fputs("\nmenu ", out); - print_quoted_string(out, prop->text); - fputs("\n", out); - break; - default: - ; - } - if (!expr_is_yes(prop->visible.expr)) { - fputs(" depends ", out); - expr_fprint(prop->visible.expr, out); - fputc('\n', out); - } - } - - if (menu->list) - menu = menu->list; - else if (menu->next) - menu = menu->next; - else while ((menu = menu->parent)) { - if (menu->prompt && menu->prompt->type == P_MENU) - fputs("\nendmenu\n", out); - if (menu->next) { - menu = menu->next; - break; - } - } - } -} - -#include "util.c" -#include "menu.c" -- cgit v0.10.2-6-g49f6 From 141f88a5f640625f63f70dad6f216a81596c42fc Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Wed, 9 Dec 2020 22:27:48 +1300 Subject: kconfig: Sync with upstream v5.2 This commit introduces the following upstream changes: 8dde5715b280 kconfig: tests: fix recursive inclusion unit test ec8f24b7faaf treewide: Add SPDX license identifier - Makefile/Kconfig fc2694ec1ab7 kconfig: use 'else ifneq' for Makefile to improve readability aff11cd983ec kconfig: Terminate menu blocks with a comment in the generated config 9cc342f6c4a0 treewide: prefix header search paths with $(srctree)/ 9b9f5948afcd kconfig: make conf_get_autoconfig_name() static b9d1a8e9302e kconfig: use snprintf for formatting pathnames 4cb726121e2c kconfig: remove useless NULL pointer check in conf_write_dep() 580c5b3e1b8b kconfig: make parent directories for the saved .config as needed 67424f61f813 kconfig: do not write .config if the content is the same ceb7f3296ea1 kconfig: do not accept a directory for configuration output 65be755a5411 kconfig: remove trailing whitespaces b63e37bc9ec4 kconfig: Make nconf-cfg.sh executable Signed-off-by: Chris Packham diff --git a/kconfig/confdata.c b/kconfig/confdata.c index 08ba146..6006154 100644 --- a/kconfig/confdata.c +++ b/kconfig/confdata.c @@ -3,6 +3,7 @@ * Copyright (C) 2002 Roman Zippel */ +#include #include #include #include @@ -36,6 +37,52 @@ static bool is_dir(const char *path) return S_ISDIR(st.st_mode); } +/* return true if the given two files are the same, false otherwise */ +static bool is_same(const char *file1, const char *file2) +{ + int fd1, fd2; + struct stat st1, st2; + void *map1, *map2; + bool ret = false; + + fd1 = open(file1, O_RDONLY); + if (fd1 < 0) + return ret; + + fd2 = open(file2, O_RDONLY); + if (fd2 < 0) + goto close1; + + ret = fstat(fd1, &st1); + if (ret) + goto close2; + ret = fstat(fd2, &st2); + if (ret) + goto close2; + + if (st1.st_size != st2.st_size) + goto close2; + + map1 = mmap(NULL, st1.st_size, PROT_READ, MAP_PRIVATE, fd1, 0); + if (map1 == MAP_FAILED) + goto close2; + + map2 = mmap(NULL, st2.st_size, PROT_READ, MAP_PRIVATE, fd2, 0); + if (map2 == MAP_FAILED) + goto close2; + + if (bcmp(map1, map2, st1.st_size)) + goto close2; + + ret = true; +close2: + close(fd2); +close1: + close(fd1); + + return ret; +} + /* * Create the parent directory of the given path. * @@ -179,7 +226,7 @@ const char *conf_get_configname(void) return name ? name : ".config"; } -const char *conf_get_autoconfig_name(void) +static const char *conf_get_autoconfig_name(void) { char *name = getenv("KCONFIG_AUTOCONFIG"); @@ -194,7 +241,7 @@ char *conf_get_default_confname(void) name = expand_string(conf_defname); env = getenv(SRCTREE); if (env) { - sprintf(fullname, "%s/%s", env, name); + snprintf(fullname, sizeof(fullname), "%s/%s", env, name); if (is_present(fullname)) return fullname; } @@ -817,40 +864,35 @@ int conf_write(const char *name) FILE *out; struct symbol *sym; struct menu *menu; - const char *basename; const char *str; - char dirname[PATH_MAX+1], tmpname[PATH_MAX+22], newname[PATH_MAX+8]; + char tmpname[PATH_MAX + 1], oldname[PATH_MAX + 1]; char *env; + bool need_newline = false; + + if (!name) + name = conf_get_configname(); + + if (!*name) { + fprintf(stderr, "config name is empty\n"); + return -1; + } + + if (is_dir(name)) { + fprintf(stderr, "%s: Is a directory\n", name); + return -1; + } + + if (make_parent_dir(name)) + return -1; - dirname[0] = 0; - if (name && name[0]) { - char *slash; - - if (is_dir(name)) { - strcpy(dirname, name); - strcat(dirname, "/"); - basename = conf_get_configname(); - } else if ((slash = strrchr(name, '/'))) { - int size = slash - name + 1; - memcpy(dirname, name, size); - dirname[size] = 0; - if (slash[1]) - basename = slash + 1; - else - basename = conf_get_configname(); - } else - basename = name; - } else - basename = conf_get_configname(); - - sprintf(newname, "%s%s", dirname, basename); env = getenv("KCONFIG_OVERWRITECONFIG"); - if (!env || !*env) { - sprintf(tmpname, "%s.tmpconfig.%d", dirname, (int)getpid()); - out = fopen(tmpname, "w"); - } else { + if (env && *env) { *tmpname = 0; - out = fopen(newname, "w"); + out = fopen(name, "w"); + } else { + snprintf(tmpname, sizeof(tmpname), "%s.%d.tmp", + name, (int)getpid()); + out = fopen(tmpname, "w"); } if (!out) return 1; @@ -871,12 +913,16 @@ int conf_write(const char *name) "#\n" "# %s\n" "#\n", str); + need_newline = false; } else if (!(sym->flags & SYMBOL_CHOICE)) { sym_calc_value(sym); if (!(sym->flags & SYMBOL_WRITE)) goto next; + if (need_newline) { + fprintf(out, "\n"); + need_newline = false; + } sym->flags &= ~SYMBOL_WRITE; - conf_write_symbol(out, sym, &kconfig_printer_cb, NULL); } @@ -888,6 +934,12 @@ next: if (menu->next) menu = menu->next; else while ((menu = menu->parent)) { + if (!menu->sym && menu_is_visible(menu) && + menu != &rootmenu) { + str = menu_get_prompt(menu); + fprintf(out, "# end of %s\n", str); + need_newline = true; + } if (menu->next) { menu = menu->next; break; @@ -897,14 +949,20 @@ next: fclose(out); if (*tmpname) { - strcat(dirname, basename); - strcat(dirname, ".old"); - rename(newname, dirname); - if (rename(tmpname, newname)) + if (is_same(name, tmpname)) { + conf_message("No change to %s", name); + unlink(tmpname); + sym_set_change_count(0); + return 0; + } + + snprintf(oldname, sizeof(oldname), "%s.old", name); + rename(name, oldname); + if (rename(tmpname, name)) return 1; } - conf_message("configuration written to %s", newname); + conf_message("configuration written to %s", name); sym_set_change_count(0); @@ -917,8 +975,6 @@ static int conf_write_dep(const char *name) struct file *file; FILE *out; - if (!name) - name = ".kconfig.d"; out = fopen("..config.tmp", "w"); if (!out) return 1; diff --git a/kconfig/lexer.l b/kconfig/lexer.l index c9df1c8..6354c90 100644 --- a/kconfig/lexer.l +++ b/kconfig/lexer.l @@ -378,7 +378,8 @@ FILE *zconf_fopen(const char *name) if (!f && name != NULL && name[0] != '/') { env = getenv(SRCTREE); if (env) { - sprintf(fullname, "%s/%s", env, name); + snprintf(fullname, sizeof(fullname), + "%s/%s", env, name); f = fopen(fullname, "r"); } } diff --git a/kconfig/lkc.h b/kconfig/lkc.h index d871539..cbc7658 100644 --- a/kconfig/lkc.h +++ b/kconfig/lkc.h @@ -49,7 +49,6 @@ const char *zconf_curname(void); /* confdata.c */ const char *conf_get_configname(void); -const char *conf_get_autoconfig_name(void); char *conf_get_default_confname(void); void sym_set_change_count(int count); void sym_add_change_count(int count); diff --git a/kconfig/lxdialog/BIG.FAT.WARNING b/kconfig/lxdialog/BIG.FAT.WARNING index a8999d8..7cb5a7e 100644 --- a/kconfig/lxdialog/BIG.FAT.WARNING +++ b/kconfig/lxdialog/BIG.FAT.WARNING @@ -1,4 +1,4 @@ This is NOT the official version of dialog. This version has been significantly modified from the original. It is for use by the Linux -kernel configuration script. Please do not bother Savio Lam with +kernel configuration script. Please do not bother Savio Lam with questions about this program. diff --git a/kconfig/mconf.c b/kconfig/mconf.c index 3d4bd5e..0d775ce 100644 --- a/kconfig/mconf.c +++ b/kconfig/mconf.c @@ -936,7 +936,7 @@ static void conf_save(void) set_config_filename(dialog_input_result); return; } - show_textbox(NULL, "Can't create file! Probably a nonexistent directory.", 5, 60); + show_textbox(NULL, "Can't create file!", 5, 60); break; case 1: show_helptext("Save Alternate Configuration", save_config_help); diff --git a/kconfig/nconf.c b/kconfig/nconf.c index 96a6bac..fca2cea 100644 --- a/kconfig/nconf.c +++ b/kconfig/nconf.c @@ -1441,8 +1441,7 @@ static void conf_save(void) set_config_filename(dialog_input_result); return; } - btn_dialog(main_window, "Can't create file! " - "Probably a nonexistent directory.", + btn_dialog(main_window, "Can't create file!", 1, ""); break; case 1: -- cgit v0.10.2-6-g49f6 From 31695dd2b00fc3daac109324992901fdcd6068e5 Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Thu, 10 Dec 2020 19:46:43 +1300 Subject: kconfig: Sync with upstream v5.3 This commit introduces the following upstream changes: 0c5b6c28ed68 kconfig: Clear "written" flag to avoid data loss 8e2442a5f86e kconfig: fix missing choice values in auto.conf 3266c806dc86 kconfig: run olddefconfig instead of oldconfig after merging fragments e3cd5136a4ec kconfig: remove meaningless if-conditional in conf_read() baa23ec86092 kconfig: Fix spelling of sym_is_changable cd238effefa2 docs: kbuild: convert docs to ReST and rename to *.rst bd305f259cd3 kconfig: make arch/*/configs/defconfig the default of KBUILD_DEFCONFIG 5533397d1ec8 kconfig: add static qualifier to expand_string() b6f7e9f7050b kconfig: require the argument of --defconfig e0a2668665a5 kconfig: remove always false ifeq ($(KBUILD_DEFCONFIG,) conditional Signed-off-by: Chris Packham diff --git a/kconfig/conf.c b/kconfig/conf.c index 67e3219..dd714b4 100644 --- a/kconfig/conf.c +++ b/kconfig/conf.c @@ -90,7 +90,7 @@ static int conf_askvalue(struct symbol *sym, const char *def) line[0] = '\n'; line[1] = 0; - if (!sym_is_changable(sym)) { + if (!sym_is_changeable(sym)) { printf("%s\n", def); line[0] = '\n'; line[1] = 0; @@ -234,7 +234,7 @@ static int conf_choice(struct menu *menu) sym = menu->sym; is_new = !sym_has_value(sym); - if (sym_is_changable(sym)) { + if (sym_is_changeable(sym)) { conf_sym(menu); sym_calc_value(sym); switch (sym_get_tristate_value(sym)) { @@ -418,7 +418,7 @@ static void check_conf(struct menu *menu) sym = menu->sym; if (sym && !sym_has_value(sym)) { - if (sym_is_changable(sym) || + if (sym_is_changeable(sym) || (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)) { if (input_mode == listnewconfig) { if (sym->name) { @@ -451,7 +451,7 @@ static struct option long_opts[] = { {"oldaskconfig", no_argument, NULL, oldaskconfig}, {"oldconfig", no_argument, NULL, oldconfig}, {"syncconfig", no_argument, NULL, syncconfig}, - {"defconfig", optional_argument, NULL, defconfig}, + {"defconfig", required_argument, NULL, defconfig}, {"savedefconfig", required_argument, NULL, savedefconfig}, {"allnoconfig", no_argument, NULL, allnoconfig}, {"allyesconfig", no_argument, NULL, allyesconfig}, @@ -542,8 +542,6 @@ int main(int ac, char **av) switch (input_mode) { case defconfig: - if (!defconfig_file) - defconfig_file = conf_get_default_confname(); if (conf_read(defconfig_file)) { fprintf(stderr, "***\n" diff --git a/kconfig/confdata.c b/kconfig/confdata.c index 6006154..3569d2d 100644 --- a/kconfig/confdata.c +++ b/kconfig/confdata.c @@ -177,8 +177,6 @@ static void conf_message(const char *fmt, ...) static const char *conf_filename; static int conf_lineno, conf_warnings; -const char conf_defname[] = "arch/$(ARCH)/defconfig"; - static void conf_warning(const char *fmt, ...) { va_list ap; @@ -233,21 +231,6 @@ static const char *conf_get_autoconfig_name(void) return name ? name : "include/config/auto.conf"; } -char *conf_get_default_confname(void) -{ - static char fullname[PATH_MAX+1]; - char *env, *name; - - name = expand_string(conf_defname); - env = getenv(SRCTREE); - if (env) { - snprintf(fullname, sizeof(fullname), "%s/%s", env, name); - if (is_present(fullname)) - return fullname; - } - return name; -} - static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p) { char *p2; @@ -551,11 +534,9 @@ int conf_read(const char *name) switch (sym->type) { case S_BOOLEAN: case S_TRISTATE: - if (sym->def[S_DEF_USER].tri != sym_get_tristate_value(sym)) - break; - if (!sym_is_choice(sym)) + if (sym->def[S_DEF_USER].tri == sym_get_tristate_value(sym)) continue; - /* fall through */ + break; default: if (!strcmp(sym->curr.val, sym->def[S_DEF_USER].val)) continue; @@ -813,7 +794,7 @@ int conf_write_defconfig(const char *filename) goto next_menu; sym->flags &= ~SYMBOL_WRITE; /* If we cannot change the symbol - skip */ - if (!sym_is_changable(sym)) + if (!sym_is_changeable(sym)) goto next_menu; /* If symbol equals to default value - skip */ if (strcmp(sym_get_string_value(sym), sym_get_string_default(sym)) == 0) @@ -867,6 +848,7 @@ int conf_write(const char *name) const char *str; char tmpname[PATH_MAX + 1], oldname[PATH_MAX + 1]; char *env; + int i; bool need_newline = false; if (!name) @@ -914,7 +896,8 @@ int conf_write(const char *name) "# %s\n" "#\n", str); need_newline = false; - } else if (!(sym->flags & SYMBOL_CHOICE)) { + } else if (!(sym->flags & SYMBOL_CHOICE) && + !(sym->flags & SYMBOL_WRITTEN)) { sym_calc_value(sym); if (!(sym->flags & SYMBOL_WRITE)) goto next; @@ -922,7 +905,7 @@ int conf_write(const char *name) fprintf(out, "\n"); need_newline = false; } - sym->flags &= ~SYMBOL_WRITE; + sym->flags |= SYMBOL_WRITTEN; conf_write_symbol(out, sym, &kconfig_printer_cb, NULL); } @@ -948,6 +931,9 @@ next: } fclose(out); + for_all_symbols(i, sym) + sym->flags &= ~SYMBOL_WRITTEN; + if (*tmpname) { if (is_same(name, tmpname)) { conf_message("No change to %s", name); @@ -1082,8 +1068,6 @@ int conf_write_autoconf(int overwrite) if (!overwrite && is_present(autoconf_name)) return 0; - sym_clear_all_valid(); - conf_write_dep("include/config/auto.conf.cmd"); if (conf_touch_deps()) diff --git a/kconfig/expr.h b/kconfig/expr.h index 8dde65b..017843c 100644 --- a/kconfig/expr.h +++ b/kconfig/expr.h @@ -141,6 +141,7 @@ struct symbol { #define SYMBOL_OPTIONAL 0x0100 /* choice is optional - values can be 'n' */ #define SYMBOL_WRITE 0x0200 /* write symbol to file (KCONFIG_CONFIG) */ #define SYMBOL_CHANGED 0x0400 /* ? */ +#define SYMBOL_WRITTEN 0x0800 /* track info to avoid double-write to .config */ #define SYMBOL_NO_WRITE 0x1000 /* Symbol for internal use only; it will not be written */ #define SYMBOL_CHECKED 0x2000 /* used during dependency checking */ #define SYMBOL_WARNED 0x8000 /* warning has been issued */ diff --git a/kconfig/lkc.h b/kconfig/lkc.h index cbc7658..4fb16f3 100644 --- a/kconfig/lkc.h +++ b/kconfig/lkc.h @@ -49,7 +49,6 @@ const char *zconf_curname(void); /* confdata.c */ const char *conf_get_configname(void); -char *conf_get_default_confname(void); void sym_set_change_count(int count); void sym_add_change_count(int count); bool conf_set_all_new_symbols(enum conf_def_mode mode); diff --git a/kconfig/lkc_proto.h b/kconfig/lkc_proto.h index 86c2675..f9ab982 100644 --- a/kconfig/lkc_proto.h +++ b/kconfig/lkc_proto.h @@ -42,7 +42,7 @@ tristate sym_toggle_tristate_value(struct symbol *sym); bool sym_string_valid(struct symbol *sym, const char *newval); bool sym_string_within_range(struct symbol *sym, const char *str); bool sym_set_string_value(struct symbol *sym, const char *newval); -bool sym_is_changable(struct symbol *sym); +bool sym_is_changeable(struct symbol *sym); struct property * sym_get_choice_prop(struct symbol *sym); const char * sym_get_string_value(struct symbol *sym); @@ -58,7 +58,6 @@ void env_write_dep(FILE *f, const char *auto_conf_name); void variable_add(const char *name, const char *value, enum variable_flavor flavor); void variable_all_del(void); -char *expand_string(const char *in); char *expand_dollar(const char **str); char *expand_one_token(const char **str); diff --git a/kconfig/mconf.c b/kconfig/mconf.c index 0d775ce..e3cb680 100644 --- a/kconfig/mconf.c +++ b/kconfig/mconf.c @@ -536,7 +536,7 @@ static void build_conf(struct menu *menu) } val = sym_get_tristate_value(sym); - if (sym_is_changable(sym)) { + if (sym_is_changeable(sym)) { switch (type) { case S_BOOLEAN: item_make("[%c]", val == no ? ' ' : '*'); @@ -587,7 +587,7 @@ static void build_conf(struct menu *menu) } else { switch (type) { case S_BOOLEAN: - if (sym_is_changable(sym)) + if (sym_is_changeable(sym)) item_make("[%c]", val == no ? ' ' : '*'); else item_make("-%c-", val == no ? ' ' : '*'); @@ -600,7 +600,7 @@ static void build_conf(struct menu *menu) case mod: ch = 'M'; break; default: ch = ' '; break; } - if (sym_is_changable(sym)) { + if (sym_is_changeable(sym)) { if (sym->rev_dep.tri == mod) item_make("{%c}", ch); else @@ -617,7 +617,7 @@ static void build_conf(struct menu *menu) if (tmp < 0) tmp = 0; item_add_str("%*c%s%s", tmp, ' ', menu_get_prompt(menu), - (sym_has_value(sym) || !sym_is_changable(sym)) ? + (sym_has_value(sym) || !sym_is_changeable(sym)) ? "" : " (NEW)"); item_set_tag('s'); item_set_data(menu); @@ -625,7 +625,7 @@ static void build_conf(struct menu *menu) } } item_add_str("%*c%s%s", indent + 1, ' ', menu_get_prompt(menu), - (sym_has_value(sym) || !sym_is_changable(sym)) ? + (sym_has_value(sym) || !sym_is_changeable(sym)) ? "" : " (NEW)"); if (menu->prompt->type == P_MENU) { item_add_str(" %s", menu_is_empty(menu) ? "----" : "--->"); diff --git a/kconfig/nconf.c b/kconfig/nconf.c index fca2cea..bee5135 100644 --- a/kconfig/nconf.c +++ b/kconfig/nconf.c @@ -806,7 +806,7 @@ static void build_conf(struct menu *menu) } val = sym_get_tristate_value(sym); - if (sym_is_changable(sym)) { + if (sym_is_changeable(sym)) { switch (type) { case S_BOOLEAN: item_make(menu, 't', "[%c]", @@ -860,7 +860,7 @@ static void build_conf(struct menu *menu) } else { switch (type) { case S_BOOLEAN: - if (sym_is_changable(sym)) + if (sym_is_changeable(sym)) item_make(menu, 't', "[%c]", val == no ? ' ' : '*'); else @@ -879,7 +879,7 @@ static void build_conf(struct menu *menu) ch = ' '; break; } - if (sym_is_changable(sym)) { + if (sym_is_changeable(sym)) { if (sym->rev_dep.tri == mod) item_make(menu, 't', "{%c}", ch); @@ -899,14 +899,14 @@ static void build_conf(struct menu *menu) item_add_str("%*c%s%s", tmp, ' ', menu_get_prompt(menu), (sym_has_value(sym) || - !sym_is_changable(sym)) ? "" : + !sym_is_changeable(sym)) ? "" : " (NEW)"); goto conf_childs; } } item_add_str("%*c%s%s", indent + 1, ' ', menu_get_prompt(menu), - (sym_has_value(sym) || !sym_is_changable(sym)) ? + (sym_has_value(sym) || !sym_is_changeable(sym)) ? "" : " (NEW)"); if (menu->prompt && menu->prompt->type == P_MENU) { item_add_str(" %s", menu_is_empty(menu) ? "----" : "--->"); diff --git a/kconfig/preprocess.c b/kconfig/preprocess.c index 592dfbf..0243086 100644 --- a/kconfig/preprocess.c +++ b/kconfig/preprocess.c @@ -15,6 +15,7 @@ #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) static char *expand_string_with_args(const char *in, int argc, char *argv[]); +static char *expand_string(const char *in); static void __attribute__((noreturn)) pperror(const char *format, ...) { @@ -550,7 +551,7 @@ static char *expand_string_with_args(const char *in, int argc, char *argv[]) return __expand_string(&in, is_end_of_str, argc, argv); } -char *expand_string(const char *in) +static char *expand_string(const char *in) { return expand_string_with_args(in, 0, NULL); } diff --git a/kconfig/symbol.c b/kconfig/symbol.c index 1f9266d..f56eec5 100644 --- a/kconfig/symbol.c +++ b/kconfig/symbol.c @@ -785,7 +785,7 @@ const char *sym_get_string_value(struct symbol *sym) return (const char *)sym->curr.val; } -bool sym_is_changable(struct symbol *sym) +bool sym_is_changeable(struct symbol *sym) { return sym->visible > sym->rev_dep.tri; } @@ -1114,7 +1114,7 @@ static void sym_check_print_recursive(struct symbol *last_sym) } fprintf(stderr, - "For a resolution refer to Documentation/kbuild/kconfig-language.txt\n" + "For a resolution refer to Documentation/kbuild/kconfig-language.rst\n" "subsection \"Kconfig recursive dependency limitations\"\n" "\n"); -- cgit v0.10.2-6-g49f6 From acce58834d83602b5c97cb01f04c9f540e40792b Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Thu, 10 Dec 2020 19:51:50 +1300 Subject: kconfig: Sync with upstream v5.5 This commit introduces the following upstream changes: 272a72103012 kconfig: don't crash on NULL expressions in expr_eq() 46b2afa6890d kconfig: be more helpful if pkg-config is missing 5d8b42aa7ccb kconfig: Add option to get the full help text with listnewconfig a64c0440dda1 kbuild: Wrap long "make help" text lines 521b29b6ff53 kconfig: split util.c out of parser.y 60bef52c7a68 merge_config.sh: ignore unwanted grep errors 54b8ae66ae1a kbuild: change *FLAGS_.o to take the path relative to $(obj) 1634f2bfdb84 kbuild: remove clean-dirs syntax cdfca821571d merge_config.sh: Check error codes from make Signed-off-by: Chris Packham diff --git a/kconfig/Makefile.am b/kconfig/Makefile.am index 2db2615..a6d47fc 100644 --- a/kconfig/Makefile.am +++ b/kconfig/Makefile.am @@ -17,14 +17,14 @@ AM_YFLAGS = -t -l AM_CPPFLAGS = -include config.h -DCONFIG_=\"CT_\" AM_LIBTOOLFLAGS = --tag CC -conf_SOURCES = conf.c confdata.c expr.c symbol.c preprocess.c lexer.lex.c parser.tab.c +conf_SOURCES = conf.c confdata.c expr.c symbol.c preprocess.c util.c lexer.lex.c parser.tab.c conf_LDADD = $(LIBINTL) -nconf_SOURCES = nconf.c nconf.gui.c confdata.c expr.c symbol.c preprocess.c lexer.lex.c parser.tab.c +nconf_SOURCES = nconf.c nconf.gui.c confdata.c expr.c symbol.c preprocess.c util.c lexer.lex.c parser.tab.c nconf_CFLAGS = $(CURSES_CFLAGS) nconf_LDADD = $(MENU_LIBS) $(PANEL_LIBS) $(CURSES_LIBS) $(LIBINTL) -mconf_SOURCES = mconf.c confdata.c expr.c symbol.c preprocess.c lexer.lex.c parser.tab.c \ +mconf_SOURCES = mconf.c confdata.c expr.c symbol.c preprocess.c util.c lexer.lex.c parser.tab.c \ lxdialog/checklist.c lxdialog/inputbox.c \ lxdialog/menubox.c lxdialog/textbox.c lxdialog/util.c \ lxdialog/yesno.c diff --git a/kconfig/conf.c b/kconfig/conf.c index dd714b4..393e96e 100644 --- a/kconfig/conf.c +++ b/kconfig/conf.c @@ -32,6 +32,7 @@ enum input_mode { defconfig, savedefconfig, listnewconfig, + helpnewconfig, olddefconfig, }; static enum input_mode input_mode = oldaskconfig; @@ -434,6 +435,11 @@ static void check_conf(struct menu *menu) printf("%s%s=%s\n", CONFIG_, sym->name, str); } } + } else if (input_mode == helpnewconfig) { + printf("-----\n"); + print_help(menu); + printf("-----\n"); + } else { if (!conf_cnt++) printf("*\n* Restart config...\n*\n"); @@ -459,6 +465,7 @@ static struct option long_opts[] = { {"alldefconfig", no_argument, NULL, alldefconfig}, {"randconfig", no_argument, NULL, randconfig}, {"listnewconfig", no_argument, NULL, listnewconfig}, + {"helpnewconfig", no_argument, NULL, helpnewconfig}, {"olddefconfig", no_argument, NULL, olddefconfig}, {NULL, 0, NULL, 0} }; @@ -523,6 +530,7 @@ int main(int ac, char **av) case allmodconfig: case alldefconfig: case listnewconfig: + case helpnewconfig: case olddefconfig: break; case '?': @@ -556,6 +564,7 @@ int main(int ac, char **av) case oldaskconfig: case oldconfig: case listnewconfig: + case helpnewconfig: case olddefconfig: conf_read(NULL); break; @@ -637,6 +646,7 @@ int main(int ac, char **av) /* fall through */ case oldconfig: case listnewconfig: + case helpnewconfig: case syncconfig: /* Update until a loop caused no more changes */ do { @@ -655,7 +665,7 @@ int main(int ac, char **av) defconfig_file); return 1; } - } else if (input_mode != listnewconfig) { + } else if (input_mode != listnewconfig && input_mode != helpnewconfig) { if (!no_conf_write && conf_write(NULL)) { fprintf(stderr, "\n*** Error during writing of the configuration.\n\n"); exit(1); diff --git a/kconfig/expr.c b/kconfig/expr.c index 77ffff3..9f1de58 100644 --- a/kconfig/expr.c +++ b/kconfig/expr.c @@ -254,6 +254,13 @@ static int expr_eq(struct expr *e1, struct expr *e2) { int res, old_count; + /* + * A NULL expr is taken to be yes, but there's also a different way to + * represent yes. expr_is_yes() checks for either representation. + */ + if (!e1 || !e2) + return expr_is_yes(e1) && expr_is_yes(e2); + if (e1->type != e2->type) return 0; switch (e1->type) { diff --git a/kconfig/parser.y b/kconfig/parser.y index 60936c7..b3eff96 100644 --- a/kconfig/parser.y +++ b/kconfig/parser.y @@ -727,5 +727,4 @@ void zconfdump(FILE *out) } } -#include "util.c" #include "menu.c" -- cgit v0.10.2-6-g49f6 From 3bf9edb36c5f1ea9715de1a2a556390540398077 Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Thu, 10 Dec 2020 19:53:19 +1300 Subject: kconfig: Sync with upstream v5.6 This commit introduces the following upstream changes: 089b7d890f97 kconfig: Invalidate all symbols after changing to y or m. 5f2fb52fac15 kbuild: rename hostprogs-y/always to hostprogs/always-y c8fb7d7e48d1 kconfig: fix broken dependency in randconfig-generated .config ba82f52e2287 kconfig: fix an "implicit declaration of function" warning a9609686042b kconfig: fix nesting of symbol help text 3460d0bc256a kconfig: distinguish between dependencies and visibility in help text edda15f21974 kconfig: list all definitions of a symbol in help text 89b9060987d9 kconfig: Add yes2modconfig and mod2yesconfig targets. c8138a57bbd1 kconfig: use $(PERL) in Makefile 1d1352373ebc kconfig: fix too deep indentation in Makefile 68f0d62746bc kconfig: localmodconfig: fix indentation for closing brace 5edcef8454a4 kconfig: localmodconfig: remove unused $config adf7c5bd0674 kconfig: squash prop_alloc() into menu_add_prop() 6397d96ba5a5 kconfig: remove sym from struct property 2ffeef615b5e kconfig: remove 'prompt' argument from menu_add_prop() 024352ff8d69 kconfig: move prompt handling to menu_add_prompt() from menu_add_prop() 1be6e791383a kconfig: remove 'prompt' symbol 801b27db4638 kconfig: drop T_WORD from the RHS of 'prompt' symbol de026ca9152c kconfig: use parent->dep as the parentdep of 'menu' f64048a20b0c kconfig: remove the rootmenu check in menu_add_prop() 8b41fc4454e3 kbuild: create modules.builtin without Makefile.modbuiltin or tristate.conf Signed-off-by: Chris Packham diff --git a/kconfig/conf.c b/kconfig/conf.c index 393e96e..422165d 100644 --- a/kconfig/conf.c +++ b/kconfig/conf.c @@ -34,6 +34,8 @@ enum input_mode { listnewconfig, helpnewconfig, olddefconfig, + yes2modconfig, + mod2yesconfig, }; static enum input_mode input_mode = oldaskconfig; @@ -467,6 +469,8 @@ static struct option long_opts[] = { {"listnewconfig", no_argument, NULL, listnewconfig}, {"helpnewconfig", no_argument, NULL, helpnewconfig}, {"olddefconfig", no_argument, NULL, olddefconfig}, + {"yes2modconfig", no_argument, NULL, yes2modconfig}, + {"mod2yesconfig", no_argument, NULL, mod2yesconfig}, {NULL, 0, NULL, 0} }; @@ -532,6 +536,8 @@ int main(int ac, char **av) case listnewconfig: case helpnewconfig: case olddefconfig: + case yes2modconfig: + case mod2yesconfig: break; case '?': fprintf(stderr, "See README for usage info\n"); @@ -566,6 +572,8 @@ int main(int ac, char **av) case listnewconfig: case helpnewconfig: case olddefconfig: + case yes2modconfig: + case mod2yesconfig: conf_read(NULL); break; case allnoconfig: @@ -639,6 +647,12 @@ int main(int ac, char **av) break; case savedefconfig: break; + case yes2modconfig: + conf_rewrite_mod_or_yes(def_y2m); + break; + case mod2yesconfig: + conf_rewrite_mod_or_yes(def_m2y); + break; case oldaskconfig: rootEntry = &rootmenu; conf(&rootmenu); diff --git a/kconfig/confdata.c b/kconfig/confdata.c index 3569d2d..a39d93e 100644 --- a/kconfig/confdata.c +++ b/kconfig/confdata.c @@ -710,25 +710,6 @@ static struct conf_printer header_printer_cb = .print_comment = header_print_comment, }; -/* - * Tristate printer - * - * This printer is used when generating the `include/config/tristate.conf' file. - */ -static void -tristate_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg) -{ - - if (sym->type == S_TRISTATE && *value != 'n') - fprintf(fp, "%s%s=%c\n", CONFIG_, sym->name, (char)toupper(*value)); -} - -static struct conf_printer tristate_printer_cb = -{ - .print_symbol = tristate_print_symbol, - .print_comment = kconfig_print_comment, -}; - static void conf_write_symbol(FILE *fp, struct symbol *sym, struct conf_printer *printer, void *printer_arg) { @@ -1062,7 +1043,7 @@ int conf_write_autoconf(int overwrite) struct symbol *sym; const char *name; const char *autoconf_name = conf_get_autoconfig_name(); - FILE *out, *tristate, *out_h; + FILE *out, *out_h; int i; if (!overwrite && is_present(autoconf_name)) @@ -1077,23 +1058,13 @@ int conf_write_autoconf(int overwrite) if (!out) return 1; - tristate = fopen(".tmpconfig_tristate", "w"); - if (!tristate) { - fclose(out); - return 1; - } - out_h = fopen(".tmpconfig.h", "w"); if (!out_h) { fclose(out); - fclose(tristate); return 1; } conf_write_heading(out, &kconfig_printer_cb, NULL); - - conf_write_heading(tristate, &tristate_printer_cb, NULL); - conf_write_heading(out_h, &header_printer_cb, NULL); for_all_symbols(i, sym) { @@ -1101,15 +1072,11 @@ int conf_write_autoconf(int overwrite) if (!(sym->flags & SYMBOL_WRITE) || !sym->name) continue; - /* write symbol to auto.conf, tristate and header files */ + /* write symbols to auto.conf and autoconf.h */ conf_write_symbol(out, sym, &kconfig_printer_cb, (void *)1); - - conf_write_symbol(tristate, sym, &tristate_printer_cb, (void *)1); - conf_write_symbol(out_h, sym, &header_printer_cb, NULL); } fclose(out); - fclose(tristate); fclose(out_h); name = getenv("KCONFIG_AUTOHEADER"); @@ -1120,14 +1087,6 @@ int conf_write_autoconf(int overwrite) if (rename(".tmpconfig.h", name)) return 1; - name = getenv("KCONFIG_TRISTATE"); - if (!name) - name = "include/config/tristate.conf"; - if (make_parent_dir(name)) - return 1; - if (rename(".tmpconfig_tristate", name)) - return 1; - if (make_parent_dir(autoconf_name)) return 1; /* @@ -1353,7 +1312,7 @@ bool conf_set_all_new_symbols(enum conf_def_mode mode) sym_calc_value(csym); if (mode == def_random) - has_changed = randomize_choice_values(csym); + has_changed |= randomize_choice_values(csym); else { set_all_choice_values(csym); has_changed = true; @@ -1362,3 +1321,18 @@ bool conf_set_all_new_symbols(enum conf_def_mode mode) return has_changed; } + +void conf_rewrite_mod_or_yes(enum conf_def_mode mode) +{ + struct symbol *sym; + int i; + tristate old_val = (mode == def_y2m) ? yes : mod; + tristate new_val = (mode == def_y2m) ? mod : yes; + + for_all_symbols(i, sym) { + if (sym_get_type(sym) == S_TRISTATE && + sym->def[S_DEF_USER].tri == old_val) + sym->def[S_DEF_USER].tri = new_val; + } + sym_clear_all_valid(); +} diff --git a/kconfig/expr.c b/kconfig/expr.c index 9f1de58..81ebf81 100644 --- a/kconfig/expr.c +++ b/kconfig/expr.c @@ -13,7 +13,6 @@ #define DEBUG_EXPR 0 -static int expr_eq(struct expr *e1, struct expr *e2); static struct expr *expr_eliminate_yn(struct expr *e); struct expr *expr_alloc_symbol(struct symbol *sym) @@ -250,7 +249,7 @@ void expr_eliminate_eq(struct expr **ep1, struct expr **ep2) * 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 expr_eq(struct expr *e1, struct expr *e2) { int res, old_count; diff --git a/kconfig/expr.h b/kconfig/expr.h index 017843c..5c34436 100644 --- a/kconfig/expr.h +++ b/kconfig/expr.h @@ -191,7 +191,6 @@ enum prop_type { struct property { struct property *next; /* next property - null if last */ - struct symbol *sym; /* the symbol for which the property is associated */ enum prop_type type; /* type of property */ const char *text; /* the prompt value - P_PROMPT, P_MENU, P_COMMENT */ struct expr_value visible; @@ -301,6 +300,7 @@ struct expr *expr_alloc_or(struct expr *e1, struct expr *e2); struct expr *expr_copy(const struct expr *org); void expr_free(struct expr *e); void expr_eliminate_eq(struct expr **ep1, struct expr **ep2); +int expr_eq(struct expr *e1, struct expr *e2); tristate expr_calc_value(struct expr *e); struct expr *expr_trans_bool(struct expr *e); struct expr *expr_eliminate_dups(struct expr *e); diff --git a/kconfig/lkc.h b/kconfig/lkc.h index 4fb16f3..d4ca829 100644 --- a/kconfig/lkc.h +++ b/kconfig/lkc.h @@ -34,6 +34,8 @@ enum conf_def_mode { def_default, def_yes, def_mod, + def_y2m, + def_m2y, def_no, def_random }; @@ -52,6 +54,7 @@ const char *conf_get_configname(void); void sym_set_change_count(int count); void sym_add_change_count(int count); bool conf_set_all_new_symbols(enum conf_def_mode mode); +void conf_rewrite_mod_or_yes(enum conf_def_mode mode); void set_all_choice_values(struct symbol *csym); /* confdata.c and expr.c */ @@ -112,7 +115,6 @@ struct symbol *sym_choice_default(struct symbol *sym); struct property *sym_get_range_prop(struct symbol *sym); const char *sym_get_string_default(struct symbol *sym); struct symbol *sym_check_deps(struct symbol *sym); -struct property *prop_alloc(enum prop_type type, struct symbol *sym); struct symbol *prop_get_symbol(struct property *prop); static inline tristate sym_get_tristate_value(struct symbol *sym) diff --git a/kconfig/mconf.c b/kconfig/mconf.c index e3cb680..2435b2b 100644 --- a/kconfig/mconf.c +++ b/kconfig/mconf.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include diff --git a/kconfig/menu.c b/kconfig/menu.c index 264ba29..bfd7800 100644 --- a/kconfig/menu.c +++ b/kconfig/menu.c @@ -124,67 +124,82 @@ void menu_set_type(int type) sym_type_name(sym->type), sym_type_name(type)); } -static struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep) +static struct property *menu_add_prop(enum prop_type type, struct expr *expr, + struct expr *dep) { - struct property *prop = prop_alloc(type, current_entry->sym); + struct property *prop; + prop = xmalloc(sizeof(*prop)); + memset(prop, 0, sizeof(*prop)); + prop->type = type; + prop->file = current_file; + prop->lineno = zconf_lineno(); prop->menu = current_entry; prop->expr = expr; prop->visible.expr = dep; - if (prompt) { - /* For crostool-NG, a leading pipe followed with spaces - * means that pipe shall be removed, and the spaces should - * not be trimmed. - */ - if (*prompt == '|') + /* append property to the prop list of symbol */ + if (current_entry->sym) { + struct property **propp; + + for (propp = ¤t_entry->sym->prop; + *propp; + propp = &(*propp)->next) + ; + *propp = prop; + } + + return prop; +} + +struct property *menu_add_prompt(enum prop_type type, char *prompt, + struct expr *dep) +{ + struct property *prop = menu_add_prop(type, NULL, dep); + + /* For crostool-NG, a leading pipe followed with spaces + * means that pipe shall be removed, and the spaces should + * not be trimmed. + */ + if (*prompt == '|') + prompt++; + else if (isspace(*prompt)) { + prop_warn(prop, "leading whitespace ignored"); + while (isspace(*prompt)) prompt++; - else if (isspace(*prompt)) { - prop_warn(prop, "leading whitespace ignored"); - while (isspace(*prompt)) - prompt++; - } - if (current_entry->prompt && current_entry != &rootmenu) - prop_warn(prop, "prompt redefined"); + } + if (current_entry->prompt) + prop_warn(prop, "prompt redefined"); - /* Apply all upper menus' visibilities to actual prompts. */ - if(type == P_PROMPT) { - struct menu *menu = current_entry; + /* Apply all upper menus' visibilities to actual prompts. */ + if (type == P_PROMPT) { + struct menu *menu = current_entry; - while ((menu = menu->parent) != NULL) { - struct expr *dup_expr; + while ((menu = menu->parent) != NULL) { + struct expr *dup_expr; - if (!menu->visibility) - continue; - /* - * Do not add a reference to the - * menu's visibility expression but - * use a copy of it. Otherwise the - * expression reduction functions - * will modify expressions that have - * multiple references which can - * cause unwanted side effects. - */ - dup_expr = expr_copy(menu->visibility); + if (!menu->visibility) + continue; + /* + * Do not add a reference to the menu's visibility + * expression but use a copy of it. Otherwise the + * expression reduction functions will modify + * expressions that have multiple references which + * can cause unwanted side effects. + */ + dup_expr = expr_copy(menu->visibility); - prop->visible.expr - = expr_alloc_and(prop->visible.expr, - dup_expr); - } + prop->visible.expr = expr_alloc_and(prop->visible.expr, + dup_expr); } - - current_entry->prompt = prop; } + + current_entry->prompt = prop; prop->text = prompt; return prop; } -struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep) -{ - return menu_add_prop(type, prompt, NULL, dep); -} - void menu_add_visibility(struct expr *expr) { current_entry->visibility = expr_alloc_and(current_entry->visibility, @@ -193,12 +208,12 @@ void menu_add_visibility(struct expr *expr) void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep) { - menu_add_prop(type, NULL, expr, dep); + menu_add_prop(type, expr, dep); } void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep) { - menu_add_prop(type, NULL, expr_alloc_symbol(sym), dep); + menu_add_prop(type, expr_alloc_symbol(sym), dep); } void menu_add_option_modules(void) @@ -332,12 +347,10 @@ void menu_finalize(struct menu *parent) * choice value symbols. */ parentdep = expr_alloc_symbol(sym); - } else if (parent->prompt) - /* Menu node for 'menu' */ - parentdep = parent->prompt->visible.expr; - else - /* Menu node for 'if' */ + } else { + /* Menu node for 'menu', 'if' */ parentdep = parent->dep; + } /* For each child menu node... */ for (menu = parent->list; menu; menu = menu->next) { @@ -704,6 +717,21 @@ const char *menu_get_help(struct menu *menu) return ""; } +static void get_def_str(struct gstr *r, struct menu *menu) +{ + str_printf(r, "Defined at %s:%d\n", + menu->file->name, menu->lineno); +} + +static void get_dep_str(struct gstr *r, struct expr *expr, const char *prefix) +{ + if (!expr_is_yes(expr)) { + str_append(r, prefix); + expr_gstr_print(expr, r); + str_append(r, "\n"); + } +} + static void get_prompt_str(struct gstr *r, struct property *prop, struct list_head *head) { @@ -711,7 +739,20 @@ static void get_prompt_str(struct gstr *r, struct property *prop, struct menu *submenu[8], *menu, *location = NULL; struct jump_key *jump = NULL; - str_printf(r, "Prompt: %s\n", prop->text); + str_printf(r, " Prompt: %s\n", prop->text); + + get_dep_str(r, prop->menu->dep, " Depends on: "); + /* + * Most prompts in Linux have visibility that exactly matches their + * dependencies. For these, we print only the dependencies to improve + * readability. However, prompts with inline "if" expressions and + * prompts with a parent that has a "visible if" expression have + * differing dependencies and visibility. In these rare cases, we + * print both. + */ + if (!expr_eq(prop->menu->dep, prop->visible.expr)) + get_dep_str(r, prop->visible.expr, " Visible if: "); + menu = prop->menu->parent; for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent) { bool accessible = menu_is_visible(menu); @@ -761,18 +802,6 @@ static void get_prompt_str(struct gstr *r, struct property *prop, } } -/* - * get property of type P_SYMBOL - */ -static struct property *get_symbol_prop(struct symbol *sym) -{ - struct property *prop = NULL; - - for_all_properties(sym, prop, P_SYMBOL) - break; - return prop; -} - static void get_symbol_props_str(struct gstr *r, struct symbol *sym, enum prop_type tok, const char *prefix) { @@ -812,32 +841,34 @@ static void get_symbol_str(struct gstr *r, struct symbol *sym, } } } - for_all_prompts(sym, prop) - get_prompt_str(r, prop, head); - - prop = get_symbol_prop(sym); - if (prop) { - str_printf(r, " Defined at %s:%d\n", prop->menu->file->name, - prop->menu->lineno); - if (!expr_is_yes(prop->visible.expr)) { - str_append(r, " Depends on: "); - expr_gstr_print(prop->visible.expr, r); - str_append(r, "\n"); + + /* Print the definitions with prompts before the ones without */ + for_all_properties(sym, prop, P_SYMBOL) { + if (prop->menu->prompt) { + get_def_str(r, prop->menu); + get_prompt_str(r, prop->menu->prompt, head); + } + } + + for_all_properties(sym, prop, P_SYMBOL) { + if (!prop->menu->prompt) { + get_def_str(r, prop->menu); + get_dep_str(r, prop->menu->dep, " Depends on: "); } } - get_symbol_props_str(r, sym, P_SELECT, " Selects: "); + get_symbol_props_str(r, sym, P_SELECT, "Selects: "); if (sym->rev_dep.expr) { - expr_gstr_print_revdep(sym->rev_dep.expr, r, yes, " Selected by [y]:\n"); - expr_gstr_print_revdep(sym->rev_dep.expr, r, mod, " Selected by [m]:\n"); - expr_gstr_print_revdep(sym->rev_dep.expr, r, no, " Selected by [n]:\n"); + 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: "); + get_symbol_props_str(r, sym, P_IMPLY, "Implies: "); if (sym->implied.expr) { - 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"); + 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"); diff --git a/kconfig/nconf.c b/kconfig/nconf.c index bee5135..49b405d 100644 --- a/kconfig/nconf.c +++ b/kconfig/nconf.c @@ -8,6 +8,7 @@ #define _GNU_SOURCE #endif #include +#include #include #include "lkc.h" diff --git a/kconfig/parser.y b/kconfig/parser.y index b3eff96..708b6c4 100644 --- a/kconfig/parser.y +++ b/kconfig/parser.y @@ -90,7 +90,6 @@ static struct menu *current_menu, *current_entry; %left T_LESS T_LESS_EQUAL T_GREATER T_GREATER_EQUAL %nonassoc T_NOT -%type prompt %type nonconst_symbol %type symbol %type type logic_type default @@ -113,7 +112,7 @@ input: mainmenu_stmt stmt_list | stmt_list; /* mainmenu entry */ -mainmenu_stmt: T_MAINMENU prompt T_EOL +mainmenu_stmt: T_MAINMENU T_WORD_QUOTE T_EOL { menu_add_prompt(P_MENU, $2, NULL); }; @@ -181,7 +180,7 @@ config_option: type prompt_stmt_opt T_EOL $1); }; -config_option: T_PROMPT prompt if_expr T_EOL +config_option: T_PROMPT T_WORD_QUOTE if_expr T_EOL { menu_add_prompt(P_PROMPT, $2, $3); printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno()); @@ -265,7 +264,7 @@ choice_option_list: | choice_option_list help ; -choice_option: T_PROMPT prompt if_expr T_EOL +choice_option: T_PROMPT T_WORD_QUOTE if_expr T_EOL { menu_add_prompt(P_PROMPT, $2, $3); printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno()); @@ -334,7 +333,7 @@ if_stmt: if_entry stmt_list if_end /* menu entry */ -menu: T_MENU prompt T_EOL +menu: T_MENU T_WORD_QUOTE T_EOL { menu_add_entry(NULL); menu_add_prompt(P_MENU, $2, NULL); @@ -363,7 +362,7 @@ menu_option_list: | menu_option_list depends ; -source_stmt: T_SOURCE prompt T_EOL +source_stmt: T_SOURCE T_WORD_QUOTE T_EOL { printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), $2); zconf_nextfile($2); @@ -372,7 +371,7 @@ source_stmt: T_SOURCE prompt T_EOL /* comment entry */ -comment: T_COMMENT prompt T_EOL +comment: T_COMMENT T_WORD_QUOTE T_EOL { menu_add_entry(NULL); menu_add_prompt(P_COMMENT, $2, NULL); @@ -429,15 +428,11 @@ visible: T_VISIBLE if_expr T_EOL prompt_stmt_opt: /* empty */ - | prompt if_expr + | T_WORD_QUOTE if_expr { menu_add_prompt(P_PROMPT, $1, $2); }; -prompt: T_WORD - | T_WORD_QUOTE -; - end: T_ENDMENU T_EOL { $$ = "menu"; } | T_ENDCHOICE T_EOL { $$ = "choice"; } | T_ENDIF T_EOL { $$ = "if"; } @@ -665,7 +660,7 @@ static void print_symbol(FILE *out, struct menu *menu) break; case P_SYMBOL: fputs( " symbol ", out); - fprintf(out, "%s\n", prop->sym->name); + fprintf(out, "%s\n", prop->menu->sym->name); break; default: fprintf(out, " unknown prop %d!\n", prop->type); diff --git a/kconfig/symbol.c b/kconfig/symbol.c index f56eec5..8d38b70 100644 --- a/kconfig/symbol.c +++ b/kconfig/symbol.c @@ -1273,28 +1273,6 @@ struct symbol *sym_check_deps(struct symbol *sym) return sym2; } -struct property *prop_alloc(enum prop_type type, struct symbol *sym) -{ - struct property *prop; - struct property **propp; - - prop = xmalloc(sizeof(*prop)); - memset(prop, 0, sizeof(*prop)); - prop->type = type; - prop->sym = sym; - prop->file = current_file; - prop->lineno = zconf_lineno(); - - /* append property to the prop list of symbol */ - if (sym) { - for (propp = &sym->prop; *propp; propp = &(*propp)->next) - ; - *propp = prop; - } - - return prop; -} - struct symbol *prop_get_symbol(struct property *prop) { if (prop->expr && (prop->expr->type == E_SYMBOL || -- cgit v0.10.2-6-g49f6 From 914c794fc2d4433b8796bd977a93afa0803ec42b Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Thu, 10 Dec 2020 19:55:15 +1300 Subject: kconfig: Sync with upstream v5.7 This commit introduces the following upstream changes: 60969f02f07a kconfig: qconf: Fix a few alignment issues e1f7769f6094 kconfig: qconf: remove some old bogus TODOs b311142fcfd3 kconfig: qconf: fix support for the split view mode cce1faba8264 kconfig: qconf: fix the content of the main widget 5752ff07fd90 kconfig: qconf: Change title for the item window cf497b922386 kconfig: qconf: clean deprecated warnings dbd35860122b kconfig: remove unused variable in qconf.cc d198b34f3855 .gitignore: add SPDX License Identifier 2985bed68083 .gitignore: remove too obvious comments 3a9dd3ecb207 kconfig: make 'imply' obey the direct dependency def2fbffe62c kconfig: allow symbols implied by y to become m 2a86f6612164 kbuild: use KBUILD_DEFCONFIG as the fallback for DEFCONFIG_LIST Signed-off-by: Chris Packham diff --git a/kconfig/.gitignore b/kconfig/.gitignore index 1908525..8886956 100644 --- a/kconfig/.gitignore +++ b/kconfig/.gitignore @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0-only + # # Generated files # diff --git a/kconfig/symbol.c b/kconfig/symbol.c index 8d38b70..3dc8139 100644 --- a/kconfig/symbol.c +++ b/kconfig/symbol.c @@ -221,7 +221,7 @@ static void sym_calc_visibility(struct symbol *sym) sym_set_changed(sym); } tri = no; - if (sym->implied.expr && sym->dir_dep.tri != no) + if (sym->implied.expr) tri = expr_calc_value(sym->implied.expr); if (tri == mod && sym_get_type(sym) == S_BOOLEAN) tri = yes; @@ -394,6 +394,8 @@ void sym_calc_value(struct symbol *sym) if (sym->implied.tri != no) { sym->flags |= SYMBOL_WRITE; newval.tri = EXPR_OR(newval.tri, sym->implied.tri); + newval.tri = EXPR_AND(newval.tri, + sym->dir_dep.tri); } } calc_newval: @@ -401,8 +403,7 @@ void sym_calc_value(struct symbol *sym) sym_warn_unmet_dep(sym); newval.tri = EXPR_OR(newval.tri, sym->rev_dep.tri); } - if (newval.tri == mod && - (sym_get_type(sym) == S_BOOLEAN || sym->implied.tri == yes)) + if (newval.tri == mod && sym_get_type(sym) == S_BOOLEAN) newval.tri = yes; break; case S_STRING: @@ -484,8 +485,6 @@ bool sym_tristate_within_range(struct symbol *sym, tristate val) return false; if (sym->visible <= sym->rev_dep.tri) return false; - if (sym->implied.tri == yes && val == mod) - return false; if (sym_is_choice_value(sym) && sym->visible == yes) return val == yes; return val >= sym->rev_dep.tri && val <= sym->visible; -- cgit v0.10.2-6-g49f6 From 7f6fe28ce013d2ea9684f781624e57b9b4dff7c7 Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Mon, 14 Dec 2020 21:43:37 +1300 Subject: bootstrap: Escape mirrors When we have mirrors set to $(CT_Mirror foo bar) we need some extra escaping so that they get interpreted correctly by kconfig. Signed-off-by: Chris Packham diff --git a/bootstrap b/bootstrap index 7015f54..79fad68 100755 --- a/bootstrap +++ b/bootstrap @@ -596,6 +596,8 @@ enter_fork() info[repository_url]=${info[repository]#* } fi + info[mirrors]=${info[mirrors]//$\(/\\$\(} + versions=`cd packages/${fork} && \ for f in */version.desc; do [ -r "${f}" ] && echo "${f%/version.desc}"; done` versions=`sort_versions ${versions}` -- cgit v0.10.2-6-g49f6 From 30bffa96b215a16c3adc88446d3d2ecc66d4450b Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Tue, 2 Feb 2021 21:25:22 +1300 Subject: don't nest choices New versions of Kconfig won't allow choices to be nested. Update the kconfig template accordingly. Signed-off-by: Chris Packham diff --git a/maintainer/kconfig-versions.template b/maintainer/kconfig-versions.template index 1969354..51bb28c 100644 --- a/maintainer/kconfig-versions.template +++ b/maintainer/kconfig-versions.template @@ -68,6 +68,8 @@ config @@fork|@@_SRC_DEVEL Default is the vendor repository at @@repository_url@@ #!end-if +endchoice + if @@fork|@@_SRC_DEVEL choice @@ -176,8 +178,6 @@ config @@fork|@@_CUSTOM_LOCATION endif -endchoice - if EXPERIMENTAL choice bool "@@pkg_label@@ patches origin" -- cgit v0.10.2-6-g49f6 From 5263bf8339a07a967f0a923d237e8a36d20439fc Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Mon, 1 Feb 2021 20:14:11 +1300 Subject: kconfig: Sync with upstream v5.8 09d5873e4d1f kconfig: allow only 'config', 'comment', and 'if' inside 'choice' 644a4b6cecc2 kconfig: do not assign a variable in the return statement cfc6eea9f6af kconfig: do not use OR-assignment for zero-cleared structure Signed-off-by: Chris Packham diff --git a/kconfig/menu.c b/kconfig/menu.c index bfd7800..a5fbd6c 100644 --- a/kconfig/menu.c +++ b/kconfig/menu.c @@ -65,7 +65,8 @@ void menu_add_entry(struct symbol *sym) struct menu *menu_add_menu(void) { last_entry_ptr = ¤t_entry->list; - return current_menu = current_entry; + current_menu = current_entry; + return current_menu; } void menu_end_menu(void) @@ -157,13 +158,7 @@ struct property *menu_add_prompt(enum prop_type type, char *prompt, { struct property *prop = menu_add_prop(type, NULL, dep); - /* For crostool-NG, a leading pipe followed with spaces - * means that pipe shall be removed, and the spaces should - * not be trimmed. - */ - if (*prompt == '|') - prompt++; - else if (isspace(*prompt)) { + if (isspace(*prompt)) { prop_warn(prop, "leading whitespace ignored"); while (isspace(*prompt)) prompt++; diff --git a/kconfig/parser.y b/kconfig/parser.y index 708b6c4..190f111 100644 --- a/kconfig/parser.y +++ b/kconfig/parser.y @@ -119,20 +119,24 @@ mainmenu_stmt: T_MAINMENU T_WORD_QUOTE T_EOL stmt_list: /* empty */ - | stmt_list common_stmt + | stmt_list assignment_stmt | stmt_list choice_stmt + | stmt_list comment_stmt + | stmt_list config_stmt + | stmt_list if_stmt | stmt_list menu_stmt + | stmt_list menuconfig_stmt + | stmt_list source_stmt | stmt_list T_WORD error T_EOL { zconf_error("unknown statement \"%s\"", $2); } | stmt_list error T_EOL { zconf_error("invalid statement"); } ; -common_stmt: - if_stmt - | comment_stmt - | config_stmt - | menuconfig_stmt - | source_stmt - | assignment_stmt +stmt_list_in_choice: + /* empty */ + | stmt_list_in_choice comment_stmt + | stmt_list_in_choice config_stmt + | stmt_list_in_choice if_stmt_in_choice + | stmt_list_in_choice error T_EOL { zconf_error("invalid statement"); } ; /* config/menuconfig entry */ @@ -254,7 +258,7 @@ choice_end: end } }; -choice_stmt: choice_entry choice_block choice_end +choice_stmt: choice_entry stmt_list_in_choice choice_end ; choice_option_list: @@ -305,11 +309,6 @@ default: | T_DEF_BOOL { $$ = S_BOOLEAN; } | T_DEF_TRISTATE { $$ = S_TRISTATE; } -choice_block: - /* empty */ - | choice_block common_stmt -; - /* if entry */ if_entry: T_IF expr T_EOL @@ -331,6 +330,9 @@ if_end: end if_stmt: if_entry stmt_list if_end ; +if_stmt_in_choice: if_entry stmt_list_in_choice if_end +; + /* menu entry */ menu: T_MENU T_WORD_QUOTE T_EOL diff --git a/kconfig/symbol.c b/kconfig/symbol.c index 3dc8139..9363e37 100644 --- a/kconfig/symbol.c +++ b/kconfig/symbol.c @@ -831,7 +831,7 @@ struct symbol *sym_lookup(const char *name, int flags) memset(symbol, 0, sizeof(*symbol)); symbol->name = new_name; symbol->type = S_UNKNOWN; - symbol->flags |= flags; + symbol->flags = flags; symbol->next = symbol_hash[hash]; symbol_hash[hash] = symbol; -- cgit v0.10.2-6-g49f6 From d0e328c8ad357a705b6218e20f74ec1ec1869e8d Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Mon, 1 Feb 2021 20:14:11 +1300 Subject: kconfig: Sync with upstream v5.9 19b835a5db93 kconfig: qconf: fix incomplete type 'struct gstr' warning 163e0c27fead kconfig: remove redundant assignment prompt = prompt d41809ff7af9 kconfig: add 'static' to some file-local data f70f74d15ca8 kconfig: remove '---help---' support Signed-off-by: Chris Packham diff --git a/kconfig/lexer.l b/kconfig/lexer.l index 6354c90..240109f 100644 --- a/kconfig/lexer.l +++ b/kconfig/lexer.l @@ -36,7 +36,7 @@ struct buffer { YY_BUFFER_STATE state; }; -struct buffer *current_buf; +static struct buffer *current_buf; static int last_ts, first_ts; @@ -105,7 +105,7 @@ n [A-Za-z0-9_-] "endchoice" return T_ENDCHOICE; "endif" return T_ENDIF; "endmenu" return T_ENDMENU; -"help"|"---help---" return T_HELP; +"help" return T_HELP; "hex" return T_HEX; "if" return T_IF; "imply" return T_IMPLY; diff --git a/kconfig/lkc.h b/kconfig/lkc.h index d4ca829..8454649 100644 --- a/kconfig/lkc.h +++ b/kconfig/lkc.h @@ -66,23 +66,6 @@ static inline void xfwrite(const void *str, size_t len, size_t count, FILE *out) fprintf(stderr, "Error in writing or end of file.\n"); } -/* menu.c */ -void _menu_init(void); -void menu_warn(struct menu *menu, const char *fmt, ...); -struct menu *menu_add_menu(void); -void menu_end_menu(void); -void menu_add_entry(struct symbol *sym); -void menu_add_dep(struct expr *dep); -void menu_add_visibility(struct expr *dep); -struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep); -void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep); -void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep); -void menu_add_option_modules(void); -void menu_add_option_defconfig_list(void); -void menu_add_option_allnoconfig_y(void); -void menu_finalize(struct menu *parent); -void menu_set_type(int type); - /* util.c */ struct file *file_lookup(const char *name); void *xmalloc(size_t size); @@ -109,6 +92,36 @@ void str_append(struct gstr *gs, const char *s); void str_printf(struct gstr *gs, const char *fmt, ...); const char *str_get(struct gstr *gs); +/* menu.c */ +void _menu_init(void); +void menu_warn(struct menu *menu, const char *fmt, ...); +struct menu *menu_add_menu(void); +void menu_end_menu(void); +void menu_add_entry(struct symbol *sym); +void menu_add_dep(struct expr *dep); +void menu_add_visibility(struct expr *dep); +struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep); +void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep); +void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep); +void menu_add_option_modules(void); +void menu_add_option_defconfig_list(void); +void menu_add_option_allnoconfig_y(void); +void menu_finalize(struct menu *parent); +void menu_set_type(int type); + +extern struct menu rootmenu; + +bool menu_is_empty(struct menu *menu); +bool menu_is_visible(struct menu *menu); +bool menu_has_prompt(struct menu *menu); +const char *menu_get_prompt(struct menu *menu); +struct menu *menu_get_root_menu(struct menu *menu); +struct menu *menu_get_parent_menu(struct menu *menu); +bool menu_has_help(struct menu *menu); +const char *menu_get_help(struct menu *menu); +struct gstr get_relations_str(struct symbol **sym_arr, struct list_head *head); +void menu_get_ext_help(struct menu *menu, struct gstr *help); + /* symbol.c */ void sym_clear_all_valid(void); struct symbol *sym_choice_default(struct symbol *sym); diff --git a/kconfig/lkc_proto.h b/kconfig/lkc_proto.h index f9ab982..9e81be3 100644 --- a/kconfig/lkc_proto.h +++ b/kconfig/lkc_proto.h @@ -12,20 +12,6 @@ bool conf_get_changed(void); void conf_set_changed_callback(void (*fn)(void)); void conf_set_message_callback(void (*fn)(const char *s)); -/* menu.c */ -extern struct menu rootmenu; - -bool menu_is_empty(struct menu *menu); -bool menu_is_visible(struct menu *menu); -bool menu_has_prompt(struct menu *menu); -const char * menu_get_prompt(struct menu *menu); -struct menu * menu_get_root_menu(struct menu *menu); -struct menu * menu_get_parent_menu(struct menu *menu); -bool menu_has_help(struct menu *menu); -const char * menu_get_help(struct menu *menu); -struct gstr get_relations_str(struct symbol **sym_arr, struct list_head *head); -void menu_get_ext_help(struct menu *menu, struct gstr *help); - /* symbol.c */ extern struct symbol * symbol_hash[SYMBOL_HASHSIZE]; diff --git a/kconfig/nconf.c b/kconfig/nconf.c index 49b405d..c1df68e 100644 --- a/kconfig/nconf.c +++ b/kconfig/nconf.c @@ -758,7 +758,6 @@ static void build_conf(struct menu *menu) switch (ptype) { case P_MENU: child_count++; - prompt = prompt; if (single_menu_mode) { item_make(menu, 'm', "%s%*c%s", diff --git a/kconfig/symbol.c b/kconfig/symbol.c index 9363e37..ffa3ec6 100644 --- a/kconfig/symbol.c +++ b/kconfig/symbol.c @@ -15,15 +15,21 @@ struct symbol symbol_yes = { .name = "y", .curr = { "y", yes }, .flags = SYMBOL_CONST|SYMBOL_VALID, -}, symbol_mod = { +}; + +struct symbol symbol_mod = { .name = "m", .curr = { "m", mod }, .flags = SYMBOL_CONST|SYMBOL_VALID, -}, symbol_no = { +}; + +struct symbol symbol_no = { .name = "n", .curr = { "n", no }, .flags = SYMBOL_CONST|SYMBOL_VALID, -}, symbol_empty = { +}; + +static struct symbol symbol_empty = { .name = "", .curr = { "", no }, .flags = SYMBOL_VALID, @@ -31,7 +37,7 @@ struct symbol symbol_yes = { struct symbol *sym_defconfig_list; struct symbol *modules_sym; -tristate modules_val; +static tristate modules_val; enum symbol_type sym_get_type(struct symbol *sym) { -- cgit v0.10.2-6-g49f6