Commit c1a0f5e3 authored by Roman Zippel's avatar Roman Zippel Committed by Linus Torvalds

[PATCH] kconfig: stricter error checking for .config

Add some more checks during the parsing of .config, so that after parsing
sym_change_count reflects the correct state whether the .config is correct and
in sync with the Kconfig or if it needs saving.
Signed-off-by: default avatarRoman Zippel <zippel@linux-m68k.org>
Cc: Sam Ravnborg <sam@ravnborg.org>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent a02f0570
...@@ -14,6 +14,12 @@ ...@@ -14,6 +14,12 @@
#define LKC_DIRECT_LINK #define LKC_DIRECT_LINK
#include "lkc.h" #include "lkc.h"
static void conf_warning(const char *fmt, ...)
__attribute__ ((format (printf, 1, 2)));
static const char *conf_filename;
static int conf_lineno, conf_warnings, conf_unsaved;
const char conf_def_filename[] = ".config"; const char conf_def_filename[] = ".config";
const char conf_defname[] = "arch/$ARCH/defconfig"; const char conf_defname[] = "arch/$ARCH/defconfig";
...@@ -27,6 +33,17 @@ const char *conf_confnames[] = { ...@@ -27,6 +33,17 @@ const char *conf_confnames[] = {
NULL, NULL,
}; };
static void conf_warning(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
fprintf(stderr, "%s:%d:warning: ", conf_filename, conf_lineno);
vfprintf(stderr, fmt, ap);
fprintf(stderr, "\n");
va_end(ap);
conf_warnings++;
}
static char *conf_expand_value(const char *in) static char *conf_expand_value(const char *in)
{ {
struct symbol *sym; struct symbol *sym;
...@@ -74,7 +91,6 @@ int conf_read_simple(const char *name) ...@@ -74,7 +91,6 @@ int conf_read_simple(const char *name)
FILE *in = NULL; FILE *in = NULL;
char line[1024]; char line[1024];
char *p, *p2; char *p, *p2;
int lineno = 0;
struct symbol *sym; struct symbol *sym;
int i; int i;
...@@ -93,12 +109,18 @@ int conf_read_simple(const char *name) ...@@ -93,12 +109,18 @@ int conf_read_simple(const char *name)
} }
} }
} }
if (!in) if (!in)
return 1; return 1;
conf_filename = name;
conf_lineno = 0;
conf_warnings = 0;
conf_unsaved = 0;
for_all_symbols(i, sym) { for_all_symbols(i, sym) {
sym->flags |= SYMBOL_NEW | SYMBOL_CHANGED; sym->flags |= SYMBOL_NEW | SYMBOL_CHANGED;
if (sym_is_choice(sym))
sym->flags &= ~SYMBOL_NEW;
sym->flags &= ~SYMBOL_VALID; sym->flags &= ~SYMBOL_VALID;
switch (sym->type) { switch (sym->type) {
case S_INT: case S_INT:
...@@ -113,7 +135,7 @@ int conf_read_simple(const char *name) ...@@ -113,7 +135,7 @@ int conf_read_simple(const char *name)
} }
while (fgets(line, sizeof(line), in)) { while (fgets(line, sizeof(line), in)) {
lineno++; conf_lineno++;
sym = NULL; sym = NULL;
switch (line[0]) { switch (line[0]) {
case '#': case '#':
...@@ -127,7 +149,10 @@ int conf_read_simple(const char *name) ...@@ -127,7 +149,10 @@ int conf_read_simple(const char *name)
continue; continue;
sym = sym_find(line + 9); sym = sym_find(line + 9);
if (!sym) { if (!sym) {
fprintf(stderr, "%s:%d: trying to assign nonexistent symbol %s\n", name, lineno, line + 9); conf_warning("trying to assign nonexistent symbol %s", line + 9);
break;
} else if (!(sym->flags & SYMBOL_NEW)) {
conf_warning("trying to reassign symbol %s", sym->name);
break; break;
} }
switch (sym->type) { switch (sym->type) {
...@@ -141,8 +166,10 @@ int conf_read_simple(const char *name) ...@@ -141,8 +166,10 @@ int conf_read_simple(const char *name)
} }
break; break;
case 'C': case 'C':
if (memcmp(line, "CONFIG_", 7)) if (memcmp(line, "CONFIG_", 7)) {
conf_warning("unexpected data");
continue; continue;
}
p = strchr(line + 7, '='); p = strchr(line + 7, '=');
if (!p) if (!p)
continue; continue;
...@@ -152,7 +179,10 @@ int conf_read_simple(const char *name) ...@@ -152,7 +179,10 @@ int conf_read_simple(const char *name)
*p2 = 0; *p2 = 0;
sym = sym_find(line + 7); sym = sym_find(line + 7);
if (!sym) { if (!sym) {
fprintf(stderr, "%s:%d: trying to assign nonexistent symbol %s\n", name, lineno, line + 7); conf_warning("trying to assign nonexistent symbol %s", line + 7);
break;
} else if (!(sym->flags & SYMBOL_NEW)) {
conf_warning("trying to reassign symbol %s", sym->name);
break; break;
} }
switch (sym->type) { switch (sym->type) {
...@@ -173,6 +203,7 @@ int conf_read_simple(const char *name) ...@@ -173,6 +203,7 @@ int conf_read_simple(const char *name)
sym->flags &= ~SYMBOL_NEW; sym->flags &= ~SYMBOL_NEW;
break; break;
} }
conf_warning("symbol value '%s' invalid for %s", p, sym->name);
break; break;
case S_STRING: case S_STRING:
if (*p++ != '"') if (*p++ != '"')
...@@ -185,8 +216,8 @@ int conf_read_simple(const char *name) ...@@ -185,8 +216,8 @@ int conf_read_simple(const char *name)
memmove(p2, p2 + 1, strlen(p2)); memmove(p2, p2 + 1, strlen(p2));
} }
if (!p2) { if (!p2) {
fprintf(stderr, "%s:%d: invalid string found\n", name, lineno); conf_warning("invalid string found");
exit(1); continue;
} }
case S_INT: case S_INT:
case S_HEX: case S_HEX:
...@@ -194,8 +225,8 @@ int conf_read_simple(const char *name) ...@@ -194,8 +225,8 @@ int conf_read_simple(const char *name)
sym->user.val = strdup(p); sym->user.val = strdup(p);
sym->flags &= ~SYMBOL_NEW; sym->flags &= ~SYMBOL_NEW;
} else { } else {
fprintf(stderr, "%s:%d: symbol value '%s' invalid for %s\n", name, lineno, p, sym->name); conf_warning("symbol value '%s' invalid for %s", p, sym->name);
exit(1); continue;
} }
break; break;
default: default:
...@@ -205,6 +236,7 @@ int conf_read_simple(const char *name) ...@@ -205,6 +236,7 @@ int conf_read_simple(const char *name)
case '\n': case '\n':
break; break;
default: default:
conf_warning("unexpected data");
continue; continue;
} }
if (sym && sym_is_choice_value(sym)) { if (sym && sym_is_choice_value(sym)) {
...@@ -213,17 +245,20 @@ int conf_read_simple(const char *name) ...@@ -213,17 +245,20 @@ int conf_read_simple(const char *name)
case no: case no:
break; break;
case mod: case mod:
if (cs->user.tri == yes) if (cs->user.tri == yes) {
/* warn? */; conf_warning("%s creates inconsistent choice state", sym->name);
cs->flags |= SYMBOL_NEW;
}
break; break;
case yes: case yes:
if (cs->user.tri != no) if (cs->user.tri != no) {
/* warn? */; conf_warning("%s creates inconsistent choice state", sym->name);
cs->user.val = sym; cs->flags |= SYMBOL_NEW;
} else
cs->user.val = sym;
break; break;
} }
cs->user.tri = E_OR(cs->user.tri, sym->user.tri); cs->user.tri = E_OR(cs->user.tri, sym->user.tri);
cs->flags &= ~SYMBOL_NEW;
} }
} }
fclose(in); fclose(in);
...@@ -245,6 +280,28 @@ int conf_read(const char *name) ...@@ -245,6 +280,28 @@ int conf_read(const char *name)
for_all_symbols(i, sym) { for_all_symbols(i, sym) {
sym_calc_value(sym); sym_calc_value(sym);
if (sym_is_choice(sym) || (sym->flags & SYMBOL_AUTO))
goto sym_ok;
if (sym_has_value(sym) && (sym->flags & SYMBOL_WRITE)) {
/* check that calculated value agrees with saved value */
switch (sym->type) {
case S_BOOLEAN:
case S_TRISTATE:
if (sym->user.tri != sym_get_tristate_value(sym))
break;
if (!sym_is_choice(sym))
goto sym_ok;
default:
if (!strcmp(sym->curr.val, sym->user.val))
goto sym_ok;
break;
}
} else if (!sym_has_value(sym) && !(sym->flags & SYMBOL_WRITE))
/* no previous value and not saved */
goto sym_ok;
conf_unsaved++;
/* maybe print value in verbose mode... */
sym_ok:
if (sym_has_value(sym) && !sym_is_choice_value(sym)) { if (sym_has_value(sym) && !sym_is_choice_value(sym)) {
if (sym->visible == no) if (sym->visible == no)
sym->flags |= SYMBOL_NEW; sym->flags |= SYMBOL_NEW;
...@@ -252,8 +309,10 @@ int conf_read(const char *name) ...@@ -252,8 +309,10 @@ int conf_read(const char *name)
case S_STRING: case S_STRING:
case S_INT: case S_INT:
case S_HEX: case S_HEX:
if (!sym_string_within_range(sym, sym->user.val)) if (!sym_string_within_range(sym, sym->user.val)) {
sym->flags |= SYMBOL_NEW; sym->flags |= SYMBOL_NEW;
sym->flags &= ~SYMBOL_VALID;
}
default: default:
break; break;
} }
...@@ -266,7 +325,7 @@ int conf_read(const char *name) ...@@ -266,7 +325,7 @@ int conf_read(const char *name)
sym->flags |= e->right.sym->flags & SYMBOL_NEW; sym->flags |= e->right.sym->flags & SYMBOL_NEW;
} }
sym_change_count = 1; sym_change_count = conf_warnings && conf_unsaved;
return 0; return 0;
} }
......
...@@ -61,7 +61,6 @@ char *zconf_curname(void); ...@@ -61,7 +61,6 @@ char *zconf_curname(void);
/* confdata.c */ /* confdata.c */
extern const char conf_def_filename[]; extern const char conf_def_filename[];
extern char conf_filename[];
char *conf_get_default_confname(void); char *conf_get_default_confname(void);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment