diff options
Diffstat (limited to 'libre/linux-libre-firmware/0001-Update-carl9170-to-latest-upstream.patch')
-rw-r--r-- | libre/linux-libre-firmware/0001-Update-carl9170-to-latest-upstream.patch | 4982 |
1 files changed, 0 insertions, 4982 deletions
diff --git a/libre/linux-libre-firmware/0001-Update-carl9170-to-latest-upstream.patch b/libre/linux-libre-firmware/0001-Update-carl9170-to-latest-upstream.patch deleted file mode 100644 index e56707e4c..000000000 --- a/libre/linux-libre-firmware/0001-Update-carl9170-to-latest-upstream.patch +++ /dev/null @@ -1,4982 +0,0 @@ -From c164bf7f87f9081fee7e1a186dd7a87a9a020b9e Mon Sep 17 00:00:00 2001 -From: Jason Self <j@jxself.org> -Date: Thu, 4 Jul 2019 15:12:33 -0700 -Subject: [PATCH 1/8] Update carl9170 to latest upstream - -Based on commit 001384147050b9cd9daadb4d3115cc0f13f5b319 -Dated May 5 2019. ---- - WHENCE | 4 +- - carl9170fw/carlfw/include/wl.h | 2 +- - carl9170fw/carlfw/src/hostif.c | 8 +- - carl9170fw/carlfw/src/printf.c | 0 - carl9170fw/carlfw/src/wlantx.c | 5 +- - carl9170fw/config/CMakeLists.txt | 6 +- - carl9170fw/config/conf.c | 210 ++++++---- - carl9170fw/config/confdata.c | 329 +++++++++------ - carl9170fw/config/expr.c | 206 +++++++--- - carl9170fw/config/expr.h | 105 ++++- - carl9170fw/config/kconf_id.c | 54 --- - carl9170fw/config/lkc.h | 50 +-- - carl9170fw/config/lkc_proto.h | 19 +- - carl9170fw/config/menu.c | 259 +++++++++--- - carl9170fw/config/preprocess.c | 573 +++++++++++++++++++++++++++ - carl9170fw/config/symbol.c | 255 ++++-------- - carl9170fw/config/util.c | 86 ++-- - carl9170fw/config/zconf.l | 336 ++++++++++------ - carl9170fw/config/zconf.y | 403 +++++++++---------- - carl9170fw/include/linux/ieee80211.h | 24 +- - carl9170fw/include/shared/wlan.h | 2 +- - carl9170fw/toolchain/Makefile | 8 +- - carl9170fw/toolchain/SHA256SUMS | 18 +- - 23 files changed, 1942 insertions(+), 1020 deletions(-) - mode change 100755 => 100644 carl9170fw/carlfw/src/printf.c - delete mode 100644 carl9170fw/config/kconf_id.c - create mode 100644 carl9170fw/config/preprocess.c - -diff --git a/WHENCE b/WHENCE -index dd8ec20..2932155 100644 ---- a/WHENCE -+++ b/WHENCE -@@ -142,8 +142,8 @@ From https://git.kernel.org/pub/scm/utils/cis-tools/cis-tools.git - - Driver: carl9170 -- Atheros AR9170 802.11 draft-n USB driver - --Version: Based on commit 370b7919114a02149088c482c8709cafb9bf7478 --dated May 2 2018. -+Version: Based on commit 001384147050b9cd9daadb4d3115cc0f13f5b319 -+dated May 5 2019. - - Licence: GPLv2 or later. - -diff --git a/carl9170fw/carlfw/include/wl.h b/carl9170fw/carlfw/include/wl.h -index 8499ca2..5566be4 100644 ---- a/carl9170fw/carlfw/include/wl.h -+++ b/carl9170fw/carlfw/include/wl.h -@@ -237,7 +237,7 @@ static inline __inline void unhide_super(struct dma_desc *desc) - desc->totalLen += sizeof(struct carl9170_tx_superdesc); - } - --static inline __inline __hot void read_tsf(uint32_t *tsf) -+static inline __inline __hot void read_tsf(uint32_t tsf[static 2]) - { - /* - * "According to the [hardware] documentation: -diff --git a/carl9170fw/carlfw/src/hostif.c b/carl9170fw/carlfw/src/hostif.c -index 73e89c7..06726db 100644 ---- a/carl9170fw/carlfw/src/hostif.c -+++ b/carl9170fw/carlfw/src/hostif.c -@@ -213,10 +213,14 @@ void handle_cmd(struct carl9170_rsp *resp) - fw.reboot = 1; - break; - -- case CARL9170_CMD_READ_TSF: -+ case CARL9170_CMD_READ_TSF: { -+ uint32_t tmptsf[2]; -+ -+ read_tsf(tmptsf); - resp->hdr.len = 8; -- read_tsf((uint32_t *)resp->tsf.tsf); -+ memcpy(resp->tsf.tsf, tmptsf, sizeof(tmptsf)); - break; -+ } - - case CARL9170_CMD_RX_FILTER: - resp->hdr.len = 0; -diff --git a/carl9170fw/carlfw/src/printf.c b/carl9170fw/carlfw/src/printf.c -old mode 100755 -new mode 100644 -diff --git a/carl9170fw/carlfw/src/wlantx.c b/carl9170fw/carlfw/src/wlantx.c -index 474c040..a8d0952 100644 ---- a/carl9170fw/carlfw/src/wlantx.c -+++ b/carl9170fw/carlfw/src/wlantx.c -@@ -260,7 +260,7 @@ static void __wlan_tx(struct dma_desc *desc) - - if (unlikely(super->s.fill_in_tsf)) { - struct ieee80211_mgmt *mgmt = (void *) &super->f.data.i3e; -- uint32_t *tsf = (uint32_t *) &mgmt->u.probe_resp.timestamp; -+ uint32_t tmptsf[2]; - - /* - * Truth be told: this is a hack. -@@ -272,7 +272,8 @@ static void __wlan_tx(struct dma_desc *desc) - * (even, if it's got an accurate atomic clock source). - */ - -- read_tsf(tsf); -+ read_tsf(tmptsf); -+ memcpy(&mgmt->u.probe_resp.timestamp, tmptsf, sizeof(tmptsf)); - } - - wlan_tx_ampdu(super); -diff --git a/carl9170fw/config/CMakeLists.txt b/carl9170fw/config/CMakeLists.txt -index 0a96a82..23e7218 100644 ---- a/carl9170fw/config/CMakeLists.txt -+++ b/carl9170fw/config/CMakeLists.txt -@@ -11,13 +11,13 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}) - - file(MAKE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../include/generated") - --BISON_TARGET(zconf zconf.y zconf.tab.c COMPILE_FLAGS "-l -b zconf -p zconf -t") --FLEX_TARGET(zconfscan zconf.l zconf.lex.c COMPILE_FLAGS "-Pzconf -L") -+BISON_TARGET(zconf zconf.y zconf.tab.c COMPILE_FLAGS "-l -b zconf -p yy -t") -+FLEX_TARGET(zconfscan zconf.l zconf.lex.c COMPILE_FLAGS "-Pyy -L") - - SET(zconf_deps ${FLEX_zconfscan_OUTPUTS}) - SET_SOURCE_FILES_PROPERTIES(${BISON_zconf_OUTPUTS} - PROPERTIES OBJECT_DEPENDS "${zconf_deps}") - --set(conf_src conf.c ${BISON_zconf_OUTPUTS}) -+set(conf_src conf.c symbol.c confdata.c expr.c preprocess.c ${BISON_zconf_OUTPUTS} ${FLEX_zconfscan_OUTPUTS}) - - add_executable(conf ${conf_src}) -diff --git a/carl9170fw/config/conf.c b/carl9170fw/config/conf.c -index 6be6143..2949b7d 100644 ---- a/carl9170fw/config/conf.c -+++ b/carl9170fw/config/conf.c -@@ -1,9 +1,8 @@ -+// SPDX-License-Identifier: GPL-2.0 - /* - * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> -- * Released under the terms of the GNU GPL v2.0. - */ - --#include <locale.h> - #include <ctype.h> - #include <limits.h> - #include <stdio.h> -@@ -20,10 +19,10 @@ - - 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, -+ syncconfig, - oldconfig, - allnoconfig, - allyesconfig, -@@ -33,12 +32,13 @@ enum input_mode { - defconfig, - savedefconfig, - listnewconfig, -- oldnoconfig, --} input_mode = oldaskconfig; -+ olddefconfig, -+}; -+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]; - static struct menu *rootEntry; -@@ -70,14 +70,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) { -- printf(_("aborted!\n\n")); -- printf(_("Console input/output is redirected. ")); -- printf(_("Run 'make config' to update configuration.\n\n")); -- exit(1); -- } -+ 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) -@@ -85,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; -@@ -99,17 +99,15 @@ static int conf_askvalue(struct symbol *sym, const char *def) - - switch (input_mode) { - case oldconfig: -+ case syncconfig: - if (sym_has_value(sym)) { - 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; -@@ -134,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)) -@@ -167,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('['); -@@ -189,9 +187,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); -@@ -254,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; -@@ -264,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; -@@ -272,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++; -@@ -281,30 +277,27 @@ 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; - } -- printf("[1-%d", cnt); -- if (menu_has_help(menu)) -- printf("?"); -- printf("]: "); -+ printf("[1-%d?]: ", cnt); - switch (input_mode) { - case oldconfig: -+ case syncconfig: - if (!is_new) { - cnt = def; - printf("%d\n", cnt); - break; - } -- check_stdin(); - /* fall through */ - case oldaskconfig: - fflush(stdout); -@@ -364,9 +357,11 @@ static void conf(struct menu *menu) - - switch (prop->type) { - case P_MENU: -- if ((input_mode == listnewconfig || -- input_mode == oldnoconfig) && -- rootEntry != menu) { -+ /* -+ * Except in oldaskconfig mode, we show only menus that -+ * contain new symbols. -+ */ -+ if (input_mode != oldaskconfig && rootEntry != menu) { - check_conf(menu); - return; - } -@@ -376,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: - ; -@@ -426,12 +421,22 @@ 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 != oldnoconfig) { -+ } else { - if (!conf_cnt++) -- printf(_("*\n* Restart config...\n*\n")); -+ printf("*\n* Restart config...\n*\n"); - rootEntry = menu_get_parent_menu(menu); - conf(rootEntry); - } -@@ -443,8 +448,9 @@ static void check_conf(struct menu *menu) - } - - static struct option long_opts[] = { -- {"askconfig", no_argument, NULL, oldaskconfig}, -- {"config", no_argument, NULL, oldconfig}, -+ {"oldaskconfig", no_argument, NULL, oldaskconfig}, -+ {"oldconfig", no_argument, NULL, oldconfig}, -+ {"syncconfig", no_argument, NULL, syncconfig}, - {"defconfig", optional_argument, NULL, defconfig}, - {"savedefconfig", required_argument, NULL, savedefconfig}, - {"allnoconfig", no_argument, NULL, allnoconfig}, -@@ -453,7 +459,7 @@ static struct option long_opts[] = { - {"alldefconfig", no_argument, NULL, alldefconfig}, - {"randconfig", no_argument, NULL, randconfig}, - {"listnewconfig", no_argument, NULL, listnewconfig}, -- {"noconfig", no_argument, NULL, oldnoconfig}, -+ {"olddefconfig", no_argument, NULL, olddefconfig}, - {NULL, 0, NULL, 0} - }; - -@@ -463,10 +469,11 @@ static void conf_usage(const char *progname) - printf("Usage: %s [-s] [option] <kconfig-file>\n", progname); - printf("[option] is _one_ of the following:\n"); - printf(" --listnewconfig List new options\n"); -- printf(" --askconfig Start a new configuration using a line-oriented program\n"); -- printf(" --config Update a configuration using a provided .config as base\n"); -- printf(" --silentconfig Same as config, but quietly, additionally update deps\n"); -- printf(" --noconfig Same as silentconfig but set new symbols to no\n"); -+ printf(" --oldaskconfig Start a new configuration using a line-oriented program\n"); -+ printf(" --oldconfig Update a configuration using a provided .config as base\n"); -+ printf(" --syncconfig Similar to oldconfig but generates configuration in\n" -+ " include/{generated/,config/}\n"); -+ printf(" --olddefconfig Same as oldconfig but sets new symbols to their default value\n"); - printf(" --defconfig <file> New config with default defined in <file>\n"); - printf(" --savedefconfig <file> Save the minimal current configuration to <file>\n"); - printf(" --allnoconfig New config where all options are answered with no\n"); -@@ -482,12 +489,9 @@ int main(int ac, char **av) - int opt; - const char *name, *defconfig_file = NULL /* gcc uninit */; - struct stat tmpstat; -+ int no_conf_write = 0; - -- setlocale(LC_ALL, ""); -- 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') { -@@ -496,6 +500,14 @@ 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: - case savedefconfig: - defconfig_file = optarg; -@@ -532,7 +544,7 @@ int main(int ac, char **av) - case allmodconfig: - case alldefconfig: - case listnewconfig: -- case oldnoconfig: -+ case olddefconfig: - break; - case '?': - conf_usage(progname); -@@ -541,30 +553,45 @@ 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]); - conf_usage(progname); - exit(1); - } - 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 run some configurator (e.g. \"make oldconfig\" or\n" -+ "*** \"make menuconfig\" or \"make xconfig\").\n" -+ "***\n", name); -+ exit(1); -+ } -+ } - - switch (input_mode) { - case defconfig: - 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; - case savedefconfig: -+ case syncconfig: - case oldaskconfig: - case oldconfig: - case listnewconfig: -- case oldnoconfig: -+ case olddefconfig: - conf_read(NULL); - break; - case allnoconfig: -@@ -578,7 +605,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); - } -@@ -595,7 +622,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); - } -@@ -604,7 +631,17 @@ int main(int ac, char **av) - break; - } - -- valid_stdin = tty_stdio; -+ if (sync_kconfig) { -+ 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; -+ } -+ } - - switch (input_mode) { - case allnoconfig: -@@ -635,44 +672,51 @@ int main(int ac, char **av) - /* fall through */ - case oldconfig: - case listnewconfig: -- case oldnoconfig: -+ 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 != oldnoconfig)); -+ } while (conf_cnt); -+ break; -+ case olddefconfig: -+ default: - break; - } - - 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) { -- /* -- * build so we shall update autoconf. -- */ -- if (conf_write(NULL)) { -- fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n")); -+ if (!no_conf_write && conf_write(NULL)) { -+ fprintf(stderr, "\n*** Error during writing of the configuration.\n\n"); - exit(1); - } -- if (conf_write_autoconf()) { -- fprintf(stderr, _("\n*** Error during update of the configuration.\n\n")); -+ -+ /* -+ * Create auto.conf if it does not exist. -+ * This prevents GNU Make 4.1 or older from emitting -+ * "include/generated/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 our cmake case, we always want to update the autogenerated -+ * files. -+ */ -+ sync_kconfig = 1; -+ -+ if (conf_write_autoconf(sync_kconfig) && sync_kconfig) { -+ fprintf(stderr, -+ "\n*** Error during sync of the configuration.\n\n"); - return 1; - } - } - 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/carl9170fw/config/confdata.c b/carl9170fw/config/confdata.c -index e606f06..d67695d 100644 ---- a/carl9170fw/config/confdata.c -+++ b/carl9170fw/config/confdata.c -@@ -1,12 +1,13 @@ -+// SPDX-License-Identifier: GPL-2.0 - /* - * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> -- * Released under the terms of the GNU GPL v2.0. - */ - - #include <sys/stat.h> - #include <ctype.h> - #include <errno.h> - #include <fcntl.h> -+#include <limits.h> - #include <stdarg.h> - #include <stdio.h> - #include <stdlib.h> -@@ -16,6 +17,105 @@ - - #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; -+} -+ -+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 *); -@@ -28,7 +128,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[] = "include/generated/defconfig"; - -@@ -43,16 +143,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 +160,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); - } - -@@ -81,43 +186,16 @@ const char *conf_get_autoconfig_name(void) - return name ? name : "include/generated/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); -- if (!stat(fullname, &buf)) -+ if (is_present(fullname)) - return fullname; - } - return name; -@@ -150,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; -@@ -176,9 +246,8 @@ 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 = strdup(p); -+ sym->def[def].val = xstrdup(p); - sym->flags |= def_flags; - } else { - if (def != S_DEF_AUTO) -@@ -201,7 +270,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; - -@@ -274,10 +343,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; - } -@@ -290,7 +360,6 @@ load: - conf_filename = name; - conf_lineno = 0; - conf_warnings = 0; -- conf_unsaved = 0; - - def_flags = SYMBOL_DEF << def; - for_all_symbols(i, sym) { -@@ -327,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); -@@ -357,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); - } -@@ -380,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) { -@@ -409,6 +483,7 @@ setsym: - int conf_read(const char *name) - { - struct symbol *sym; -+ int conf_unsaved = 0; - int i; - - sym_set_change_count(0); -@@ -422,7 +497,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 */ -@@ -678,7 +753,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: -@@ -791,15 +865,14 @@ 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; - 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(); -@@ -877,33 +950,61 @@ next: - return 1; - } - -- conf_message(_("configuration written to %s"), newname); -+ conf_message("configuration written to %s", newname); - - sym_set_change_count(0); - - return 0; - } - --static int conf_split_config(void) -+/* 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_touch_deps(void) - { - const char *name; -- char path[PATH_MAX+1]; -- char *s, *d, c; - struct symbol *sym; -- struct stat sb; -- int res, i, fd; -+ int res, i; -+ -+ strcpy(depfile_path, "include/generated/"); -+ depfile_prefix_len = strlen(depfile_path); - - name = conf_get_autoconfig_name(); - conf_read_simple(name, S_DEF_AUTO); - sym_calc_value(modules_sym); - -- if (chdir("include/generated")) -- 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) { -@@ -952,63 +1053,30 @@ 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; -- } -- /* -- * 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++ = '/'; -- } -- /* 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(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, *out_c; - int i; - -+ if (!overwrite && is_present(autoconf_name)) -+ return 0; -+ - sym_clear_all_valid(); - -- file_write_dep("include/generated/auto.conf.cmd"); -+ conf_write_dep("include/generated/auto.conf.cmd"); - -- if (conf_split_config()) -+ if (conf_touch_deps()) - return 1; - - out = fopen(".tmpconfig", "w"); -@@ -1065,24 +1133,35 @@ 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/generated/tristate.conf"; -+ if (make_parent_dir(name)) -+ return 1; - if (rename(".tmpconfig_tristate", name)) - return 1; -+ -+ if (make_parent_dir(autoconf_name)) -+ return 1; -+ - name = getenv("KCONFIG_CMAKE"); - if (!name) - name = "config.cmake"; -+ if (make_parent_dir(name)) -+ return 1; - if (rename(".tmpconfig.cmake", name)) - return 1; -- name = conf_get_autoconfig_name(); -+ - /* - * 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; -@@ -1186,7 +1265,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/carl9170fw/config/expr.c b/carl9170fw/config/expr.c -index 8cee597..77ffff3 100644 ---- a/carl9170fw/config/expr.c -+++ b/carl9170fw/config/expr.c -@@ -1,8 +1,10 @@ -+// SPDX-License-Identifier: GPL-2.0 - /* - * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> -- * Released under the terms of the GNU GPL v2.0. - */ - -+#include <ctype.h> -+#include <errno.h> - #include <stdio.h> - #include <stdlib.h> - #include <string.h> -@@ -94,7 +96,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 +115,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 +129,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 +140,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 +162,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 +190,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 +244,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 +296,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 +580,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 +605,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 +644,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 +671,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 +679,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 +899,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; -@@ -874,7 +982,6 @@ enum string_value_kind { - k_string, - k_signed, - k_unsigned, -- k_invalid - }; - - union string_value { -@@ -905,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; -@@ -967,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); -@@ -1031,49 +1129,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); --} -- --void expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken) -+void expr_print(struct expr *e, -+ void (*fn)(void *, struct symbol *, const char *), -+ void *data, int prevtoken) - { - if (!e) { - fn(data, NULL, "y"); -@@ -1207,3 +1265,33 @@ 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. -+ */ -+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_revdep(e, expr_print_gstr_helper, gs, pr_type, &title); -+} -diff --git a/carl9170fw/config/expr.h b/carl9170fw/config/expr.h -index a73f762..999edb6 100644 ---- a/carl9170fw/config/expr.h -+++ b/carl9170fw/config/expr.h -@@ -1,6 +1,6 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ - /* - * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> -- * 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[] */ -@@ -74,21 +74,64 @@ 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; - }; - --#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 */ -@@ -98,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 */ - -@@ -128,18 +171,20 @@ 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, - 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 */ - 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 */ - }; - -@@ -166,22 +211,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 { -@@ -217,11 +307,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, -+ tristate pr_type, const char *title); - - static inline int expr_is_yes(struct expr *e) - { -diff --git a/carl9170fw/config/kconf_id.c b/carl9170fw/config/kconf_id.c -deleted file mode 100644 -index 5abbc72..0000000 ---- a/carl9170fw/config/kconf_id.c -+++ /dev/null -@@ -1,54 +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 }, -- { "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 }, -- { "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 }, -- { "env", T_OPT_ENV, 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/carl9170fw/config/lkc.h b/carl9170fw/config/lkc.h -index cdcbe43..531ff7c 100644 ---- a/carl9170fw/config/lkc.h -+++ b/carl9170fw/config/lkc.h -@@ -1,6 +1,6 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ - /* - * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> -- * Released under the terms of the GNU GPL v2.0. - */ - - #ifndef LKC_H -@@ -8,15 +8,6 @@ - - #include "expr.h" - --#ifndef KBUILD_NO_NLS --# include <libintl.h> --#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 -@@ -44,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, -@@ -56,18 +38,7 @@ enum conf_def_mode { - def_random - }; - --#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 { -- const char *name; -- int token; -- unsigned int flags; -- enum symbol_type stype; --}; -- -+extern int yylineno; - void zconfdump(FILE *out); - void zconf_starthelp(void); - FILE *zconf_fopen(const char *name); -@@ -100,21 +71,27 @@ 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); - 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); - - /* 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); -+char *xstrdup(const char *s); -+char *xstrndup(const char *s, size_t n); -+ -+/* zconf.l */ -+int yylex(void); - - struct gstr { - size_t len; -@@ -132,16 +109,13 @@ 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); -+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); --struct property *sym_get_env_prop(struct symbol *sym); - - static inline tristate sym_get_tristate_value(struct symbol *sym) - { -diff --git a/carl9170fw/config/lkc_proto.h b/carl9170fw/config/lkc_proto.h -index 5d86e2d..86c2675 100644 ---- a/carl9170fw/config/lkc_proto.h -+++ b/carl9170fw/config/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; -@@ -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); --const 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/carl9170fw/config/menu.c b/carl9170fw/config/menu.c -index e935793..d9d1646 100644 ---- a/carl9170fw/config/menu.c -+++ b/carl9170fw/config/menu.c -@@ -1,6 +1,6 @@ -+// SPDX-License-Identifier: GPL-2.0 - /* - * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> -- * Released under the terms of the GNU GPL v2.0. - */ - - #include <ctype.h> -@@ -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) { - if (isspace(*prompt)) { -@@ -196,31 +195,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"); -- break; -- case T_OPT_ENV: -- prop_add_env(arg); -- 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) -@@ -252,6 +246,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: -@@ -260,13 +264,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: -@@ -292,6 +296,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 */ -@@ -309,30 +318,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, -@@ -344,34 +406,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; -@@ -420,6 +529,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; -@@ -444,6 +582,15 @@ void menu_finalize(struct menu *parent) - sym->flags |= SYMBOL_WARNED; - } - -+ /* -+ * For non-optional choices, add a reverse dependency (corresponding to -+ * a select) of '<visibility> && m'. This prevents the user from -+ * setting the choice mode to 'n' when the choice is visible. -+ * -+ * This would also work for non-choice symbols, but only non-optional -+ * choices clear SYMBOL_OPTIONAL as of writing. Choices are implemented -+ * as a type of symbol. -+ */ - if (sym && !sym_is_optional(sym) && parent->prompt) { - sym->rev_dep.expr = expr_alloc_or(sym->rev_dep.expr, - expr_alloc_and(parent->prompt->visible.expr, -@@ -558,7 +705,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); -@@ -591,16 +738,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 : _("<choice>"), -+ menu->sym->name : "<choice>", - sym_get_string_value(menu->sym)); - } - str_append(r, "\n"); -@@ -664,27 +811,27 @@ 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) { -- str_append(r, _(" Selected by: ")); -- expr_gstr_print(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: ")); -+ 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); -- 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"); -@@ -699,7 +846,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; - } - -@@ -714,7 +861,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/carl9170fw/config/preprocess.c b/carl9170fw/config/preprocess.c -new file mode 100644 -index 0000000..592dfbf ---- /dev/null -+++ b/carl9170fw/config/preprocess.c -@@ -0,0 +1,573 @@ -+// SPDX-License-Identifier: GPL-2.0 -+// -+// Copyright (C) 2018 Masahiro Yamada <yamada.masahiro@socionext.com> -+ -+#include <ctype.h> -+#include <stdarg.h> -+#include <stdbool.h> -+#include <stdio.h> -+#include <stdlib.h> -+#include <string.h> -+ -+#include "list.h" -+#include "lkc.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) -+{ -+ return !(isalnum(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/carl9170fw/config/symbol.c b/carl9170fw/config/symbol.c -index 3c8bd9b..1f9266d 100644 ---- a/carl9170fw/config/symbol.c -+++ b/carl9170fw/config/symbol.c -@@ -1,6 +1,6 @@ -+// SPDX-License-Identifier: GPL-2.0 - /* - * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> -- * Released under the terms of the GNU GPL v2.0. - */ - - #include <ctype.h> -@@ -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; -@@ -77,7 +50,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: -@@ -88,8 +61,6 @@ const char *sym_type_name(enum symbol_type type) - return "string"; - case S_UNKNOWN: - return "unknown"; -- case S_OTHER: -- break; - } - return "???"; - } -@@ -103,15 +74,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; -@@ -124,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; - -@@ -183,7 +145,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) -@@ -243,7 +205,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 +295,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; -@@ -371,11 +354,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 +375,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); -@@ -402,9 +386,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; -@@ -412,18 +397,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 && -@@ -433,12 +408,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) { -@@ -480,7 +452,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) -@@ -783,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; - } -@@ -851,7 +822,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; -@@ -896,55 +867,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. -- */ --const char *sym_expand_string_value(const char *in) --{ -- const char *src; -- char *res; -- size_t reslen; -- -- 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 = realloc(res, reslen); -- } -- -- strcat(res, symval); -- in = src; -- } -- strcat(res, in); -- -- return res; --} -- - const char *sym_escape_string_value(const char *in) - { - const char *p; -@@ -1086,7 +1008,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) -@@ -1150,37 +1072,52 @@ static void sym_check_print_recursive(struct symbol *last_sym) - if (stack->sym == last_sym) - fprintf(stderr, "%s:%d:error: recursive dependency detected!\n", - prop->file->name, prop->lineno); -- fprintf(stderr, "For a resolution refer to Documentation/kbuild/kconfig-language.txt\n"); -- fprintf(stderr, "subsection \"Kconfig recursive dependency limitations\"\n"); -- 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 : "<choice>", -- prop_get_type_name(prop->type), - next_sym->name ? next_sym->name : "<choice>"); -- } else if (stack->prop) { -+ } 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 : "<choice>", -+ next_sym->name ? next_sym->name : "<choice>"); -+ } 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 : "<choice>", - next_sym->name ? next_sym->name : "<choice>"); -- } 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 : "<choice>", - next_sym->name ? next_sym->name : "<choice>"); -- } 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 : "<choice>", -+ next_sym->name ? next_sym->name : "<choice>"); -+ } else if (stack->expr) { -+ fprintf(stderr, "%s:%d:\tsymbol %s %s value contains %s\n", -+ prop->file->name, prop->lineno, - sym->name ? sym->name : "<choice>", -+ prop_get_type_name(prop->type), - next_sym->name ? next_sym->name : "<choice>"); - } 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 : "<choice>", -+ prop_get_type_name(prop->type), - next_sym->name ? next_sym->name : "<choice>"); - } - } - -+ fprintf(stderr, -+ "For a resolution refer to Documentation/kbuild/kconfig-language.txt\n" -+ "subsection \"Kconfig recursive dependency limitations\"\n" -+ "\n"); -+ - if (check_top == &cv_stack) - dep_stack_remove(); - } -@@ -1215,7 +1152,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; - } - -@@ -1228,12 +1165,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); -@@ -1241,7 +1192,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; -@@ -1319,9 +1270,6 @@ struct symbol *sym_check_deps(struct symbol *sym) - sym->flags &= ~SYMBOL_CHECK; - } - -- if (sym2 && sym2 == sym) -- sym2 = NULL; -- - return sym2; - } - -@@ -1360,8 +1308,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: -@@ -1383,32 +1329,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/carl9170fw/config/util.c b/carl9170fw/config/util.c -index 0e76042..2958539 100644 ---- a/carl9170fw/config/util.c -+++ b/carl9170fw/config/util.c -@@ -1,8 +1,7 @@ -+// SPDX-License-Identifier: GPL-2.0 - /* - * Copyright (C) 2002-2005 Roman Zippel <zippel@linux-m68k.org> - * Copyright (C) 2002-2005 Sam Ravnborg <sam@ravnborg.org> -- * -- * Released under the terms of the GNU GPL v2.0. - */ - - #include <stdarg.h> -@@ -14,69 +13,21 @@ - struct file *file_lookup(const char *name) - { - struct file *file; -- const 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); - 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; - } - --/* 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; -- -- 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()); -- -- 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"); -- } -- -- fprintf(out, "\n$(deps_config): ;\n"); -- fclose(out); -- rename("..config.tmp", name); -- return 0; --} -- -- - /* Allocate initial growable string */ - struct gstr str_new(void) - { -@@ -104,7 +55,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 +96,34 @@ 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); -+} -+ -+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/carl9170fw/config/zconf.l b/carl9170fw/config/zconf.l -index 9720530..c52cce8 100644 ---- a/carl9170fw/config/zconf.l -+++ b/carl9170fw/config/zconf.l -@@ -1,13 +1,13 @@ --%option nostdinit noyywrap never-interactive full ecs --%option 8bit nodefault perf-report perf-report --%option noinput --%x COMMAND HELP STRING PARAM --%{ -+/* SPDX-License-Identifier: GPL-2.0 */ - /* - * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> -- * 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 <assert.h> - #include <limits.h> - #include <stdio.h> - #include <stdlib.h> -@@ -15,6 +15,9 @@ - #include <unistd.h> - - #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; - -@@ -35,6 +40,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); - -@@ -52,7 +59,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); -@@ -71,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); - } - %} - -@@ -81,116 +88,113 @@ n [A-Za-z0-9_-] - int str = 0; - int ts, i; - --[ \t]*#.*\n | --[ \t]*\n { -- current_file->lineno++; -- return T_EOL; --} --[ \t]*#.* -- -- --[ \t]+ { -- BEGIN(COMMAND); --} -- --. { -- unput(yytext[0]); -- BEGIN(COMMAND); --} -- -- --<COMMAND>{ -- {n}+ { -- const struct kconf_id *id = kconf_id_lookup(yytext, yyleng); -- BEGIN(PARAM); -- current_pos.file = current_file; -- current_pos.lineno = current_file->lineno; -- if (id && id->flags & TF_COMMAND) { -- zconflval.id = id; -- return id->token; -- } -- alloc_string(yytext, yyleng); -- zconflval.string = text; -- return T_WORD; -- } -- . warn_ignored_character(*yytext); -- \n { -- BEGIN(INITIAL); -- current_file->lineno++; -- 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); - --<PARAM>{ -- "&&" 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); current_file->lineno++; return T_EOL; -- ({n}|[/.])+ { -- const struct kconf_id *id = kconf_id_lookup(yytext, yyleng); -- if (id && id->flags & TF_PARAM) { -- zconflval.id = id; -- return id->token; -- } -+<ASSIGN_VAL>{ -+ [^[:blank:]\n]+.* { - alloc_string(yytext, yyleng); -- zconflval.string = text; -- return T_WORD; -- } -- #.* /* comment */ -- \\\n current_file->lineno++; -- [[:blank:]]+ -- . warn_ignored_character(*yytext); -- <<EOF>> { -- BEGIN(INITIAL); -+ yylval.string = text; -+ return T_ASSIGN_VAL; - } -+ \n { BEGIN(INITIAL); return T_EOL; } -+ . - } - - <STRING>{ -- [^'"\\\n]+/\n { -- append_string(yytext, yyleng); -- zconflval.string = text; -- return T_WORD_QUOTE; -- } -- [^'"\\\n]+ { -+ "$".* append_expanded_string(yytext); -+ [^$'"\\\n]+ { - append_string(yytext, yyleng); - } -- \\.?/\n { -- append_string(yytext + 1, yyleng - 1); -- zconflval.string = text; -- return T_WORD_QUOTE; -- } - \\.? { - append_string(yytext + 1, yyleng - 1); - } - \'|\" { - if (str == yytext[0]) { -- BEGIN(PARAM); -- zconflval.string = text; -+ BEGIN(INITIAL); -+ 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()); -- current_file->lineno++; -+ 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; - } - <<EOF>> { - BEGIN(INITIAL); -+ yylval.string = text; -+ return T_WORD_QUOTE; - } - } - -@@ -218,12 +222,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].* { -@@ -243,6 +245,12 @@ n [A-Za-z0-9_-] - } - - <<EOF>> { -+ 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; -@@ -252,6 +260,93 @@ 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; -+ 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(); -@@ -261,7 +356,7 @@ void zconf_starthelp(void) - - static void zconf_endhelp(void) - { -- zconflval.string = text; -+ yylval.string = text; - BEGIN(INITIAL); - } - -@@ -294,7 +389,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); - } - -@@ -302,7 +397,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) -@@ -315,35 +410,34 @@ 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)); - buf->parent = current_buf; - current_buf = buf; - -- 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); -+ 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; -- } -- 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, file->name)); - exit(1); - } - } -- file->lineno = 1; -- file->parent = current_file; -+ -+ yylineno = 1; - current_file = file; - } - -@@ -352,6 +446,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) { -diff --git a/carl9170fw/config/zconf.y b/carl9170fw/config/zconf.y -index 79c4f04..60936c7 100644 ---- a/carl9170fw/config/zconf.y -+++ b/carl9170fw/config/zconf.y -@@ -1,8 +1,8 @@ --%{ -+/* SPDX-License-Identifier: GPL-2.0 */ - /* - * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> -- * Released under the terms of the GNU GPL v2.0. - */ -+%{ - - #include <ctype.h> - #include <stdarg.h> -@@ -20,63 +20,69 @@ - - int cdebug = PRINTD; - --extern int zconflex(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); -+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 32 - - %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 <id>T_MAINMENU --%token <id>T_MENU --%token <id>T_ENDMENU --%token <id>T_SOURCE --%token <id>T_CHOICE --%token <id>T_ENDCHOICE --%token <id>T_COMMENT --%token <id>T_CONFIG --%token <id>T_MENUCONFIG --%token <id>T_HELP - %token <string> T_HELPTEXT --%token <id>T_IF --%token <id>T_ENDIF --%token <id>T_DEPENDS --%token <id>T_OPTIONAL --%token <id>T_PROMPT --%token <id>T_TYPE --%token <id>T_DEFAULT --%token <id>T_SELECT --%token <id>T_IMPLY --%token <id>T_RANGE --%token <id>T_VISIBLE --%token <id>T_OPTION --%token <id>T_ON - %token <string> T_WORD - %token <string> 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 <string> T_ASSIGN_VAL - - %left T_OR - %left T_AND -@@ -85,13 +91,15 @@ static struct menu *current_menu, *current_entry; - %nonassoc T_NOT - - %type <string> prompt -+%type <symbol> nonconst_symbol - %type <symbol> symbol -+%type <type> type logic_type default - %type <expr> expr - %type <expr> if_expr --%type <id> end --%type <id> option_name -+%type <string> end - %type <menu> if_entry menu_entry choice_entry --%type <string> symbol_option_arg word_opt -+%type <string> word_opt assign_val -+%type <flavor> assign_op - - %destructor { - fprintf(stderr, "%s:%d: missing end statement for this entry\n", -@@ -100,71 +108,53 @@ static struct menu *current_menu, *current_entry; - menu_end_menu(); - } if_entry menu_entry choice_entry - --%{ --/* Include zconf_id.c here so it can see the token constants. */ --#include "kconf_id.c" --%} -- - %% --input: nl start | start; -+input: mainmenu_stmt stmt_list | stmt_list; - --start: 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 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 - | source_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 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,26 +163,22 @@ 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()); - }; - - 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 -@@ -201,25 +187,25 @@ 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 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()); - }; - -@@ -229,34 +215,30 @@ 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); -- 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 */ - - 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); - printd(DEBUG_PARSE, "%s:%d:choice\n", zconf_curname(), zconf_lineno()); - }; - -@@ -267,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()); - } -@@ -281,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 -@@ -291,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 -@@ -308,16 +284,28 @@ 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); -- 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 -@@ -325,7 +313,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); -@@ -335,29 +323,15 @@ if_entry: T_IF expr nl - - 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_stmt: if_entry stmt_list if_end - ; - --if_block: -- /* empty */ -- | if_block common_stmt -- | if_block menu_stmt -- | 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 -@@ -367,33 +341,33 @@ 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 - { - printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), $2); - zconf_nextfile($2); -+ free($2); - }; - - /* comment entry */ -@@ -405,10 +379,13 @@ comment: T_COMMENT prompt T_EOL - printd(DEBUG_PARSE, "%s:%d:comment\n", zconf_curname(), zconf_lineno()); - }; - --comment_stmt: comment depends_list --{ -- menu_end_entry(); --}; -+comment_stmt: comment comment_option_list -+; -+ -+comment_option_list: -+ /* empty */ -+ | comment_option_list depends -+; - - /* help option */ - -@@ -420,18 +397,22 @@ 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 ?: "<choice>"); -+ } -+ -+ /* Is the help text empty or all whitespace? */ -+ if ($2[strspn($2, " \f\n\r\t\v")] == '\0') -+ zconfprint("warning: '%s' defined with blank help text", -+ current_entry->sym->name ?: "<choice>"); -+ - current_entry->help = $2; - }; - - /* 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); -@@ -439,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); - }; -@@ -464,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; } -@@ -491,13 +460,31 @@ 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); } - ; - - 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) -@@ -507,61 +494,51 @@ void conf_parse(const char *name) - - zconf_initscan(name); - -- sym_init(); - _menu_init(); -- rootmenu.prompt = menu_add_prompt(P_MENU, "CARL9170 Firmware Configuration", NULL); - - if (getenv("ZCONF_DEBUG")) -- zconfdebug = 1; -- zconfparse(); -- if (zconfnerrs) -+ 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" ); - -- rootmenu.prompt->text = _(rootmenu.prompt->text); -- rootmenu.prompt->text = sym_expand_string_value(rootmenu.prompt->text); -+ 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)) -- zconfnerrs++; -+ yynerrs++; - } -- if (zconfnerrs) -+ if (yynerrs) - exit(1); - 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 "<token>"; --} -- --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)); -- zconfnerrs++; -+ 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)); -- zconfnerrs++; -+ expected_tokenname); -+ yynerrs++; - return false; - } - return true; -@@ -582,7 +559,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); -@@ -590,7 +567,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); - } -@@ -623,7 +600,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); -@@ -686,6 +663,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; -@@ -746,9 +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" -diff --git a/carl9170fw/include/linux/ieee80211.h b/carl9170fw/include/linux/ieee80211.h -index 31c59ea..46ce6cf 100644 ---- a/carl9170fw/include/linux/ieee80211.h -+++ b/carl9170fw/include/linux/ieee80211.h -@@ -897,33 +897,33 @@ struct ieee80211_mgmt { - __le16 status_code; - /* possibly followed by Challenge text */ - u8 variable[0]; -- } __packed auth; -+ } __packed __aligned(4) auth; - struct { - __le16 reason_code; -- } __packed deauth; -+ } __packed __aligned(4) deauth; - struct { - __le16 capab_info; - __le16 listen_interval; - /* followed by SSID and Supported rates */ - u8 variable[0]; -- } __packed assoc_req; -+ } __packed __aligned(4) assoc_req; - struct { - __le16 capab_info; - __le16 status_code; - __le16 aid; - /* followed by Supported rates */ - u8 variable[0]; -- } __packed assoc_resp, reassoc_resp; -+ } __packed __aligned(4) assoc_resp, reassoc_resp; - struct { - __le16 capab_info; - __le16 listen_interval; - u8 current_ap[6]; - /* followed by SSID and Supported rates */ - u8 variable[0]; -- } __packed reassoc_req; -+ } __packed __aligned(4) reassoc_req; - struct { - __le16 reason_code; -- } __packed disassoc; -+ } __packed __aligned(4) disassoc; - struct { - __le64 timestamp; - __le16 beacon_int; -@@ -931,11 +931,11 @@ struct ieee80211_mgmt { - /* followed by some of SSID, Supported rates, - * FH Params, DS Params, CF Params, IBSS Params, TIM */ - u8 variable[0]; -- } __packed beacon; -+ } __packed __aligned(4) beacon; - struct { - /* only variable items: SSID, Supported rates */ - u8 variable[0]; -- } __packed probe_req; -+ } __packed __aligned(4) probe_req; - struct { - __le64 timestamp; - __le16 beacon_int; -@@ -943,7 +943,7 @@ struct ieee80211_mgmt { - /* followed by some of SSID, Supported rates, - * FH Params, DS Params, CF Params, IBSS Params */ - u8 variable[0]; -- } __packed probe_resp; -+ } __packed __aligned(4) probe_resp; - struct { - u8 category; - union { -@@ -1041,8 +1041,8 @@ struct ieee80211_mgmt { - u8 variable[0]; - } __packed ftm; - } u; -- } __packed action; -- } u; -+ } __packed __aligned(4) action; -+ } u __aligned(2); - } __packed __aligned(2); - - /* Supported rates membership selectors */ -@@ -1245,7 +1245,7 @@ struct ieee80211_bar { - __u8 ta[6]; - __le16 control; - __le16 start_seq_num; --} __packed __aligned(4); -+} __packed __aligned(2); - - /* 802.11 BA(R) control masks */ - #define IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL 0x0000 -diff --git a/carl9170fw/include/shared/wlan.h b/carl9170fw/include/shared/wlan.h -index 9c6b7ff..117f005 100644 ---- a/carl9170fw/include/shared/wlan.h -+++ b/carl9170fw/include/shared/wlan.h -@@ -273,7 +273,7 @@ struct ar9170_tx_frame { - struct ieee80211_hdr i3e; - u8 payload[0]; - } data; --} __packed; -+} __packed __aligned(4); - - struct carl9170_tx_superframe { - struct carl9170_tx_superdesc s; -diff --git a/carl9170fw/toolchain/Makefile b/carl9170fw/toolchain/Makefile -index 11db906..43e546d 100644 ---- a/carl9170fw/toolchain/Makefile -+++ b/carl9170fw/toolchain/Makefile -@@ -1,16 +1,16 @@ --BINUTILS_VER=2.31.1 -+BINUTILS_VER=2.32 - BINUTILS_TAR=binutils-$(BINUTILS_VER).tar.xz - BINUTILS_URL="https://ftp.gnu.org/gnu/binutils/$(BINUTILS_TAR)" - --NEWLIB_VER=3.0.0 -+NEWLIB_VER=3.1.0 - NEWLIB_TAR=newlib-$(NEWLIB_VER).tar.gz - NEWLIB_URL="ftp://sourceware.org/pub/newlib/$(NEWLIB_TAR)" - --GCC_VER=8.2.0 -+GCC_VER=9.1.0 - GCC_TAR=gcc-$(GCC_VER).tar.xz - GCC_URL="https://ftp.gnu.org/gnu/gcc/gcc-$(GCC_VER)/$(GCC_TAR)" - --MPFR_VER=4.0.1 -+MPFR_VER=4.0.2 - MPFR_TAR=mpfr-$(MPFR_VER).tar.xz - MPFR_URL="https://ftp.gnu.org/gnu/mpfr/$(MPFR_TAR)" - -diff --git a/carl9170fw/toolchain/SHA256SUMS b/carl9170fw/toolchain/SHA256SUMS -index 1b65040..3a53959 100644 ---- a/carl9170fw/toolchain/SHA256SUMS -+++ b/carl9170fw/toolchain/SHA256SUMS -@@ -1,16 +1,6 @@ --1cf7adf8ff4b5aa49041c8734bbcf1ad18cc4c94d0029aae0f4e48841088479a src/gcc-7.2.0.tar.xz --5b76a9b97c9464209772ed25ce55181a7bb144a66e5669aaec945aa64da3189b src/newlib-2.5.0.tar.gz --0b871e271c4c620444f8264f72143b4d224aa305306d85dd77ab8dce785b1e85 src/binutils-2.29.tar.xz - 87b565e89a9a684fe4ebeeddb8399dce2599f9c9049854ca8c0dfbdea0e21912 src/gmp-6.1.2.tar.xz --617decc6ea09889fb08ede330917a00b16809b8db88c29c31bfbb49cbf88ecc3 src/mpc-1.0.3.tar.gz --7a62ac1a04408614fccdc506e4844b10cf0ad2c2b1677097f8f35d3a1344a950 src/mpfr-3.1.6.tar.xz - 6985c538143c1208dcb1ac42cedad6ff52e267b47e5f970183a3e75125b43c2e src/mpc-1.1.0.tar.gz --fbe2cd1418b321f5c899ce4f0f0f4e73f5ecc7d02145b0e1fd096f5c3afb8a1d src/mpfr-4.0.0.tar.xz --c8566335ee74e5fcaeb8595b4ebd0400c4b043d6acb3263ecb1314f8f5501332 src/newlib-3.0.0.tar.gz --832ca6ae04636adbb430e865a1451adf6979ab44ca1c8374f61fba65645ce15c src/gcc-7.3.0.tar.xz --e7010a46969f9d3e53b650a518663f98a5dde3c3ae21b7d71e5e6803bc36b577 src/binutils-2.29.1.tar.xz --67874a60826303ee2fb6affc6dc0ddd3e749e9bfcb4c8655e3953d0458a6e16e src/mpfr-4.0.1.tar.xz --6e46b8aeae2f727a36f0bd9505e405768a72218f1796f0d09757d45209871ae6 src/binutils-2.30.tar.xz --1d1866f992626e61349a1ccd0b8d5253816222cdc13390dcfaa74b093aa2b153 src/gcc-8.1.0.tar.xz --5d20086ecf5752cc7d9134246e9588fa201740d540f7eb84d795b1f7a93bca86 src/binutils-2.31.1.tar.xz --196c3c04ba2613f893283977e6011b2345d1cd1af9abeac58e916b1aab3e0080 src/gcc-8.2.0.tar.xz -\ No newline at end of file -+fb4fa1cc21e9060719208300a61420e4089d6de6ef59cf533b57fe74801d102a src/newlib-3.1.0.tar.gz -+1d3be708604eae0e42d578ba93b390c2a145f17743a744d8f3f8c2ad5855a38a src/mpfr-4.0.2.tar.xz -+0ab6c55dd86a92ed561972ba15b9b70a8b9f75557f896446c82e8b36e473ee04 src/binutils-2.32.tar.xz -+79a66834e96a6050d8fe78db2c3b32fb285b230b855d0a66288235bc04b327a0 src/gcc-9.1.0.tar.xz --- -2.26.0 - |