summaryrefslogtreecommitdiff
path: root/scripts/kconfig/confdata.c
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/kconfig/confdata.c')
-rw-r--r--scripts/kconfig/confdata.c391
1 files changed, 131 insertions, 260 deletions
diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c
index 992575f1e976..4286d5e7f95d 100644
--- a/scripts/kconfig/confdata.c
+++ b/scripts/kconfig/confdata.c
@@ -18,8 +18,12 @@
#include <time.h>
#include <unistd.h>
+#include <xalloc.h>
+#include "internal.h"
#include "lkc.h"
+struct gstr autoconf_cmd;
+
/* return true if 'path' exists, false otherwise */
static bool is_present(const char *path)
{
@@ -155,6 +159,13 @@ static void conf_message(const char *fmt, ...)
static const char *conf_filename;
static int conf_lineno, conf_warnings;
+bool conf_errors(void)
+{
+ if (conf_warnings)
+ return getenv("KCONFIG_WERROR");
+ return false;
+}
+
static void conf_warning(const char *fmt, ...)
{
va_list ap;
@@ -286,59 +297,24 @@ static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
return 0;
}
-#define LINE_GROWTH 16
-static int add_byte(int c, char **lineptr, size_t slen, size_t *n)
+/* like getline(), but the newline character is stripped away */
+static ssize_t getline_stripped(char **lineptr, size_t *n, FILE *stream)
{
- char *nline;
- size_t new_size = slen + 1;
- if (new_size > *n) {
- new_size += LINE_GROWTH - 1;
- new_size *= 2;
- nline = xrealloc(*lineptr, new_size);
- if (!nline)
- return -1;
-
- *lineptr = nline;
- *n = new_size;
- }
+ ssize_t len;
- (*lineptr)[slen] = c;
+ len = getline(lineptr, n, stream);
- return 0;
-}
-
-static ssize_t compat_getline(char **lineptr, size_t *n, FILE *stream)
-{
- char *line = *lineptr;
- size_t slen = 0;
+ if (len > 0 && (*lineptr)[len - 1] == '\n') {
+ len--;
+ (*lineptr)[len] = '\0';
- for (;;) {
- int c = getc(stream);
-
- switch (c) {
- case '\n':
- if (add_byte(c, &line, slen, n) < 0)
- goto e_out;
- slen++;
- /* fall through */
- case EOF:
- if (add_byte('\0', &line, slen, n) < 0)
- goto e_out;
- *lineptr = line;
- if (slen == 0)
- return -1;
- return slen;
- default:
- if (add_byte(c, &line, slen, n) < 0)
- goto e_out;
- slen++;
+ if (len > 0 && (*lineptr)[len - 1] == '\r') {
+ len--;
+ (*lineptr)[len] = '\0';
}
}
-e_out:
- line[slen-1] = '\0';
- *lineptr = line;
- return -1;
+ return len;
}
int conf_read_simple(const char *name, int def)
@@ -346,10 +322,12 @@ int conf_read_simple(const char *name, int def)
FILE *in = NULL;
char *line = NULL;
size_t line_asize = 0;
- char *p, *p2;
+ char *p, *val;
struct symbol *sym;
- int i, def_flags;
+ int def_flags;
+ const char *warn_unknown, *sym_name;
+ warn_unknown = getenv("KCONFIG_WARN_UNKNOWN_SYMBOLS");
if (name) {
in = zconf_fopen(name);
} else {
@@ -404,17 +382,13 @@ load:
conf_warnings = 0;
def_flags = SYMBOL_DEF << def;
- for_all_symbols(i, sym) {
- sym->flags |= SYMBOL_CHANGED;
+ for_all_symbols(sym) {
sym->flags &= ~(def_flags|SYMBOL_VALID);
- if (sym_is_choice(sym))
- sym->flags |= def_flags;
switch (sym->type) {
case S_INT:
case S_HEX:
case S_STRING:
- if (sym->def[def].val)
- free(sym->def[def].val);
+ free(sym->def[def].val);
/* fall through */
default:
sym->def[def].val = NULL;
@@ -422,111 +396,90 @@ load:
}
}
- while (compat_getline(&line, &line_asize, in) != -1) {
+ expr_invalidate_all();
+
+ while (getline_stripped(&line, &line_asize, in) != -1) {
+ struct menu *choice;
+
conf_lineno++;
- sym = NULL;
+
+ if (!line[0]) /* blank line */
+ continue;
+
if (line[0] == '#') {
- if (memcmp(line + 2, CONFIG_, strlen(CONFIG_)))
+ if (line[1] != ' ')
continue;
- p = strchr(line + 2 + strlen(CONFIG_), ' ');
+ p = line + 2;
+ if (memcmp(p, CONFIG_, strlen(CONFIG_)))
+ continue;
+ sym_name = p + strlen(CONFIG_);
+ p = strchr(sym_name, ' ');
if (!p)
continue;
*p++ = 0;
- if (strncmp(p, "is not set", 10))
+ if (strcmp(p, "is not set"))
continue;
- if (def == S_DEF_USER) {
- sym = sym_find(line + 2 + strlen(CONFIG_));
- if (!sym) {
- conf_set_changed(true);
- continue;
- }
- } else {
- sym = sym_lookup(line + 2 + strlen(CONFIG_), 0);
- if (sym->type == S_UNKNOWN)
- sym->type = S_BOOLEAN;
- }
- if (sym->flags & def_flags) {
- conf_warning("override: reassigning to symbol %s", sym->name);
- }
- switch (sym->type) {
- case S_BOOLEAN:
- case S_TRISTATE:
- sym->def[def].tri = no;
- sym->flags |= def_flags;
- break;
- default:
- ;
- }
- } else if (memcmp(line, CONFIG_, strlen(CONFIG_)) == 0) {
- p = strchr(line + strlen(CONFIG_), '=');
- if (!p)
+
+ val = "n";
+ } else {
+ if (memcmp(line, CONFIG_, strlen(CONFIG_))) {
+ conf_warning("unexpected data: %s", line);
continue;
- *p++ = 0;
- p2 = strchr(p, '\n');
- if (p2) {
- *p2-- = 0;
- if (*p2 == '\r')
- *p2 = 0;
}
- 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 must be touched.
- */
- conf_touch_dep(line + strlen(CONFIG_));
- else
- conf_set_changed(true);
+ sym_name = line + strlen(CONFIG_);
+ p = strchr(sym_name, '=');
+ if (!p) {
+ conf_warning("unexpected data: %s", line);
continue;
}
+ *p = 0;
+ val = p + 1;
+ }
- if (sym->flags & def_flags) {
- conf_warning("override: reassigning to symbol %s", sym->name);
- }
- if (conf_set_sym_val(sym, def, def_flags, p))
- continue;
- } else {
- if (line[0] != '\r' && line[0] != '\n')
- conf_warning("unexpected data: %.*s",
- (int)strcspn(line, "\r\n"), line);
+ sym = sym_find(sym_name);
+ 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
+ * must be touched.
+ */
+ conf_touch_dep(sym_name);
+ } else {
+ if (warn_unknown)
+ conf_warning("unknown symbol: %s", sym_name);
+ conf_set_changed(true);
+ }
continue;
}
- if (sym && sym_is_choice_value(sym)) {
- struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
- switch (sym->def[def].tri) {
- case no:
- break;
- case mod:
- if (cs->def[def].tri == yes) {
- conf_warning("%s creates inconsistent choice state", sym->name);
- cs->flags &= ~def_flags;
- }
- break;
- case yes:
- if (cs->def[def].tri != no)
- conf_warning("override: %s changes choice state", sym->name);
- cs->def[def].val = sym;
- break;
- }
- cs->def[def].tri = EXPR_OR(cs->def[def].tri, sym->def[def].tri);
- }
+ if (sym->flags & def_flags)
+ conf_warning("override: reassigning to symbol %s", sym->name);
+
+ if (conf_set_sym_val(sym, def, def_flags, val))
+ continue;
+
+ /*
+ * If this is a choice member, give it the highest priority.
+ * If conflicting CONFIG options are given from an input file,
+ * the last one wins.
+ */
+ choice = sym_get_choice_menu(sym);
+ if (choice)
+ list_move(&sym->choice_link, &choice->choice_members);
}
free(line);
fclose(in);
+
return 0;
}
int conf_read(const char *name)
{
struct symbol *sym;
- int conf_unsaved = 0;
- int i;
conf_set_changed(false);
@@ -537,9 +490,9 @@ int conf_read(const char *name)
sym_calc_value(modules_sym);
- for_all_symbols(i, sym) {
+ for_all_symbols(sym) {
sym_calc_value(sym);
- if (sym_is_choice(sym) || (sym->flags & SYMBOL_NO_WRITE))
+ if (sym_is_choice(sym))
continue;
if (sym_has_value(sym) && (sym->flags & SYMBOL_WRITE)) {
/* check that calculated value agrees with saved value */
@@ -557,36 +510,11 @@ int conf_read(const char *name)
} else if (!sym_has_value(sym) && !(sym->flags & SYMBOL_WRITE))
/* no previous value and not saved */
continue;
- conf_unsaved++;
+ conf_set_changed(true);
/* maybe print value in verbose mode... */
}
- for_all_symbols(i, sym) {
- if (sym_has_value(sym) && !sym_is_choice_value(sym)) {
- /* Reset values of generates values, so they'll appear
- * as new, if they should become visible, but that
- * doesn't quite work if the Kconfig and the saved
- * configuration disagree.
- */
- if (sym->visible == no && !conf_unsaved)
- sym->flags &= ~SYMBOL_DEF_USER;
- switch (sym->type) {
- case S_STRING:
- case S_INT:
- case S_HEX:
- /* Reset a string value if it's out of range */
- if (sym_string_within_range(sym, sym->def[S_DEF_USER].val))
- break;
- sym->flags &= ~(SYMBOL_VALID|SYMBOL_DEF_USER);
- conf_unsaved++;
- break;
- default:
- break;
- }
- }
- }
-
- if (conf_warnings || conf_unsaved)
+ if (conf_warnings)
conf_set_changed(true);
return 0;
@@ -830,62 +758,35 @@ int conf_write_defconfig(const char *filename)
sym_clear_all_valid();
- /* Traverse all menus to find all relevant symbols */
- menu = rootmenu.list;
+ menu_for_each_entry(menu) {
+ struct menu *choice;
- while (menu != NULL)
- {
sym = menu->sym;
- if (sym == NULL) {
- if (!menu_is_visible(menu))
- goto next_menu;
- } else if (!sym_is_choice(sym)) {
- sym_calc_value(sym);
- if (!(sym->flags & SYMBOL_WRITE))
- goto next_menu;
- sym->flags &= ~SYMBOL_WRITE;
- /* If we cannot change the symbol - skip */
- if (!sym_is_changeable(sym))
- goto next_menu;
- /* If symbol equals to default value - skip */
- if (strcmp(sym_get_string_value(sym), sym_get_string_default(sym)) == 0)
- goto next_menu;
-
- /*
- * If symbol is a choice value and equals to the
- * default for a choice - skip.
- * But only if value is bool and equal to "y" and
- * choice is not "optional".
- * (If choice is "optional" then all values can be "n")
- */
- if (sym_is_choice_value(sym)) {
- struct symbol *cs;
- struct symbol *ds;
-
- cs = prop_get_symbol(sym_get_choice_prop(sym));
- ds = sym_choice_default(cs);
- if (!sym_is_optional(cs) && sym == ds) {
- if ((sym->type == S_BOOLEAN) &&
- sym_get_tristate_value(sym) == yes)
- goto next_menu;
- }
- }
- print_symbol_for_dotconfig(out, sym);
- }
-next_menu:
- if (menu->list != NULL) {
- menu = menu->list;
- }
- else if (menu->next != NULL) {
- menu = menu->next;
- } else {
- while ((menu = menu->parent)) {
- if (menu->next != NULL) {
- menu = menu->next;
- break;
- }
- }
+
+ if (!sym || sym_is_choice(sym))
+ continue;
+
+ sym_calc_value(sym);
+ if (!(sym->flags & SYMBOL_WRITE))
+ continue;
+ sym->flags &= ~SYMBOL_WRITE;
+ /* Skip unchangeable symbols */
+ if (!sym_is_changeable(sym))
+ continue;
+ /* Skip symbols that are equal to the default */
+ if (!strcmp(sym_get_string_value(sym), sym_get_string_default(sym)))
+ continue;
+
+ /* Skip choice values that are equal to the default */
+ choice = sym_get_choice_menu(sym);
+ if (choice) {
+ struct symbol *ds;
+
+ ds = sym_choice_default(choice);
+ if (sym == ds && sym_get_tristate_value(sym) == yes)
+ continue;
}
+ print_symbol_for_dotconfig(out, sym);
}
fclose(out);
return 0;
@@ -899,7 +800,6 @@ int conf_write(const char *name)
const char *str;
char tmpname[PATH_MAX + 1], oldname[PATH_MAX + 1];
char *env;
- int i;
bool need_newline = false;
if (!name)
@@ -947,7 +847,7 @@ int conf_write(const char *name)
"# %s\n"
"#\n", str);
need_newline = false;
- } else if (!(sym->flags & SYMBOL_CHOICE) &&
+ } else if (!sym_is_choice(sym) &&
!(sym->flags & SYMBOL_WRITTEN)) {
sym_calc_value(sym);
if (!(sym->flags & SYMBOL_WRITE))
@@ -983,7 +883,7 @@ end_check:
}
fclose(out);
- for_all_symbols(i, sym)
+ for_all_symbols(sym)
sym->flags &= ~SYMBOL_WRITTEN;
if (*tmpname) {
@@ -1011,7 +911,6 @@ end_check:
static int conf_write_autoconf_cmd(const char *autoconf_name)
{
char name[PATH_MAX], tmp[PATH_MAX];
- struct file *file;
FILE *out;
int ret;
@@ -1032,15 +931,9 @@ static int conf_write_autoconf_cmd(const char *autoconf_name)
return -1;
}
- fprintf(out, "deps_config := \\\n");
- for (file = file_list; file; file = file->next)
- fprintf(out, "\t%s \\\n", file->name);
-
- fprintf(out, "\n%s: $(deps_config)\n\n", autoconf_name);
-
- env_write_dep(out, autoconf_name);
+ fprintf(out, "autoconfig := %s\n", autoconf_name);
- fprintf(out, "\n$(deps_config): ;\n");
+ fputs(str_get(&autoconf_cmd), out);
fflush(out);
ret = ferror(out); /* error check for all fprintf() calls */
@@ -1060,7 +953,7 @@ static int conf_touch_deps(void)
{
const char *name, *tmp;
struct symbol *sym;
- int res, i;
+ int res;
name = conf_get_autoconfig_name();
tmp = strrchr(name, '/');
@@ -1074,9 +967,9 @@ static int conf_touch_deps(void)
conf_read_simple(name, S_DEF_AUTO);
sym_calc_value(modules_sym);
- for_all_symbols(i, sym) {
+ for_all_symbols(sym) {
sym_calc_value(sym);
- if ((sym->flags & SYMBOL_NO_WRITE) || !sym->name)
+ if (sym_is_choice(sym))
continue;
if (sym->flags & SYMBOL_WRITE) {
if (sym->flags & SYMBOL_DEF_AUTO) {
@@ -1140,7 +1033,7 @@ static int __conf_write_autoconf(const char *filename,
char tmp[PATH_MAX];
FILE *file;
struct symbol *sym;
- int ret, i;
+ int ret;
if (make_parent_dir(filename))
return -1;
@@ -1157,7 +1050,7 @@ static int __conf_write_autoconf(const char *filename,
conf_write_heading(file, comment_style);
- for_all_symbols(i, sym)
+ for_all_symbols(sym)
if ((sym->flags & SYMBOL_WRITE) && sym->name)
print_symbol(file, sym);
@@ -1180,7 +1073,7 @@ int conf_write_autoconf(int overwrite)
{
struct symbol *sym;
const char *autoconf_name = conf_get_autoconfig_name();
- int ret, i;
+ int ret;
if (!overwrite && is_present(autoconf_name))
return 0;
@@ -1192,7 +1085,7 @@ int conf_write_autoconf(int overwrite)
if (conf_touch_deps())
return 1;
- for_all_symbols(i, sym)
+ for_all_symbols(sym)
sym_calc_value(sym);
ret = __conf_write_autoconf(conf_get_autoheader_name(),
@@ -1222,16 +1115,14 @@ int conf_write_autoconf(int overwrite)
}
static bool conf_changed;
-static void (*conf_changed_callback)(void);
+static void (*conf_changed_callback)(bool);
void conf_set_changed(bool val)
{
- bool changed = conf_changed != val;
+ if (conf_changed_callback && conf_changed != val)
+ conf_changed_callback(val);
conf_changed = val;
-
- if (conf_changed_callback && changed)
- conf_changed_callback();
}
bool conf_get_changed(void)
@@ -1239,27 +1130,7 @@ bool conf_get_changed(void)
return conf_changed;
}
-void conf_set_changed_callback(void (*fn)(void))
+void conf_set_changed_callback(void (*fn)(bool))
{
conf_changed_callback = fn;
}
-
-void set_all_choice_values(struct symbol *csym)
-{
- struct property *prop;
- struct symbol *sym;
- struct expr *e;
-
- prop = sym_get_choice_prop(csym);
-
- /*
- * Set all non-assinged choice values to no
- */
- expr_list_for_each_sym(prop->expr, e, sym) {
- if (!sym_has_value(sym))
- sym->def[S_DEF_USER].tri = no;
- }
- csym->flags |= SYMBOL_DEF_USER;
- /* clear VALID to get value calculated */
- csym->flags &= ~(SYMBOL_VALID | SYMBOL_NEED_SET_CHOICE_VALUES);
-}