Fixes nconfig crash on comments within choice groups.
Signed-off-by: Peter Korsgaard <jacmet@sunsite.dk>
}
break;
case savedefconfig:
- conf_read(NULL);
- break;
case silentoldconfig:
case oldaskconfig:
case oldconfig:
fputs("\"\n", out);
}
-static void conf_write_symbol(struct symbol *sym, enum symbol_type type,
- FILE *out, bool write_no)
+static void conf_write_symbol(struct symbol *sym, FILE *out, bool write_no)
{
const char *str;
- switch (type) {
+ switch (sym->type) {
case S_BOOLEAN:
case S_TRISTATE:
switch (sym_get_tristate_value(sym)) {
goto next_menu;
}
}
- conf_write_symbol(sym, sym->type, out, true);
+ conf_write_symbol(sym, out, true);
}
next_menu:
if (menu->list != NULL) {
const char *basename;
const char *str;
char dirname[PATH_MAX+1], tmpname[PATH_MAX+1], newname[PATH_MAX+1];
- enum symbol_type type;
time_t now;
int use_timestamp = 1;
char *env;
if (!(sym->flags & SYMBOL_WRITE))
goto next;
sym->flags &= ~SYMBOL_WRITE;
- type = sym->type;
- if (type == S_TRISTATE) {
- sym_calc_value(modules_sym);
- if (modules_sym->curr.tri == no)
- type = S_BOOLEAN;
- }
/* Write config symbol to file */
- conf_write_symbol(sym, type, out, true);
+ conf_write_symbol(sym, out, true);
}
next:
continue;
/* write symbol to config file */
- conf_write_symbol(sym, sym->type, out, false);
+ conf_write_symbol(sym, out, false);
/* update autoconf and tristate files */
switch (sym->type) {
int cnt, def;
/*
- * If choice is mod then we may have more items slected
+ * If choice is mod then we may have more items selected
* and if no then no-one.
* In both cases stop.
*/
/*
* We have different type of choice blocks.
- * If curr.tri equal to mod then we can select several
+ * If curr.tri equals to mod then we can select several
* choice symbols in one block.
* In this case we do nothing.
- * If curr.tri equal yes then only one symbol can be
+ * If curr.tri equals yes then only one symbol can be
* selected in a choice block and we set it to yes,
* and the rest to no.
*/
return e2 ? expr_alloc_two(E_OR, e1, e2) : e1;
}
-struct expr *expr_copy(struct expr *org)
+struct expr *expr_copy(const struct expr *org)
{
struct expr *e;
#endif
}
+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)
{
if (!e) {
struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2);
struct expr *expr_alloc_and(struct expr *e1, struct expr *e2);
struct expr *expr_alloc_or(struct expr *e1, struct expr *e2);
-struct expr *expr_copy(struct expr *org);
+struct expr *expr_copy(const struct expr *org);
void expr_free(struct expr *e);
int expr_eq(struct expr *e1, struct expr *e2);
void expr_eliminate_eq(struct expr **ep1, struct expr **ep2);
struct expr *expr_extract_eq_or(struct expr **ep1, struct expr **ep2);
void expr_extract_eq(enum expr_type type, struct expr **ep, struct expr **ep1, struct expr **ep2);
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 */
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
enum symbol_type stype;
};
+#ifdef YYDEBUG
+extern int zconfdebug;
+#endif
+
int zconfparse(void);
void zconfdump(FILE *out);
-
-extern int zconfdebug;
void zconf_starthelp(void);
FILE *zconf_fopen(const char *name);
void zconf_initscan(const char *name);
}
}
-static int menu_range_valid_sym(struct symbol *sym, struct symbol *sym2)
+static int menu_validate_number(struct symbol *sym, struct symbol *sym2)
{
return sym2->type == S_INT || sym2->type == S_HEX ||
(sym2->type == S_UNKNOWN && sym_string_valid(sym, sym2->name));
prop_warn(prop,
"default for config symbol '%s'"
" must be a single symbol", sym->name);
+ if (prop->expr->type != E_SYMBOL)
+ break;
+ sym2 = prop_get_symbol(prop);
+ if (sym->type == S_HEX || sym->type == S_INT) {
+ if (!menu_validate_number(sym, sym2))
+ prop_warn(prop,
+ "'%s': number is invalid",
+ sym->name);
+ }
break;
case P_SELECT:
sym2 = prop_get_symbol(prop);
if (sym->type != S_INT && sym->type != S_HEX)
prop_warn(prop, "range is only allowed "
"for int or hex symbols");
- if (!menu_range_valid_sym(sym, prop->expr->left.sym) ||
- !menu_range_valid_sym(sym, prop->expr->right.sym))
+ if (!menu_validate_number(sym, prop->expr->left.sym) ||
+ !menu_validate_number(sym, prop->expr->right.sym))
prop_warn(prop, "range is invalid");
break;
default:
"Only relevant lines are shown.\n"
"\n\n"
"Search examples:\n"
-"Examples: USB = > find all symbols containing USB\n"
+"Examples: USB => find all symbols containing USB\n"
" ^USB => find all symbols starting with USB\n"
" USB$ => find all symbols ending with USB\n"
"\n");
if (child->sym == sym_get_choice_value(menu->sym))
item_make(child, ':', "<X> %s",
_(menu_get_prompt(child)));
- else
+ else if (child->sym)
item_make(child, ':', " %s",
_(menu_get_prompt(child)));
+ else
+ item_make(child, ':', "*** %s ***",
+ _(menu_get_prompt(child)));
+
if (child->sym == active){
last_top_row = top_row(curses_menu);
selected_index = i;
break;
child = item_data();
- if (!child || !menu_is_visible(child))
+ if (!child || !menu_is_visible(child) || !child->sym)
continue;
switch (res) {
case ' ':
while (1) {
l = strcspn(str, "\"\\");
-@@ -451,14 +452,14 @@
+@@ -450,14 +451,14 @@
switch (sym_get_tristate_value(sym)) {
case no:
if (write_no)
break;
}
break;
-@@ -468,7 +469,7 @@
+@@ -467,7 +468,7 @@
case S_HEX:
case S_INT:
str = sym_get_string_value(sym);
break;
case S_OTHER:
case S_UNKNOWN:
-@@ -853,17 +854,17 @@
+@@ -844,17 +845,17 @@
case no:
break;
case mod:
break;
}
break;
-@@ -873,14 +874,14 @@
+@@ -864,14 +865,14 @@
case S_HEX:
str = sym_get_string_value(sym);
if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) {
===================================================================
--- config.orig/lkc.h
+++ config/lkc.h
-@@ -41,7 +41,7 @@
+@@ -42,7 +42,7 @@
#define N_(text) (text)
#ifndef CONFIG_
===================================================================
--- config.orig/menu.c
+++ config/menu.c
-@@ -588,7 +588,7 @@
+@@ -597,7 +597,7 @@
if (menu_has_help(menu)) {
if (sym->name) {
===================================================================
--- config.orig/confdata.c
+++ config/confdata.c
-@@ -1005,7 +1005,16 @@
+@@ -996,7 +996,16 @@
void conf_set_all_new_symbols(enum conf_def_mode mode)
{
struct symbol *sym, *csym;
for_all_symbols(i, sym) {
if (sym_has_value(sym))
-@@ -1024,8 +1033,15 @@
+@@ -1015,8 +1024,15 @@
sym->def[S_DEF_USER].tri = no;
break;
case def_random:
---
conf.c | 1
- confdata.c | 65 +++++++++++++++++++++++++++++++++++++++++++++----------------
+ confdata.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++---------------
util.c | 16 +++++++++++++--
- 3 files changed, 62 insertions(+), 20 deletions(-)
+ 3 files changed, 61 insertions(+), 18 deletions(-)
Index: config/conf.c
===================================================================
}
static char *conf_expand_value(const char *in)
-@@ -567,6 +565,9 @@
+@@ -565,6 +563,9 @@
int use_timestamp = 1;
char *env;
dirname[0] = 0;
if (name && name[0]) {
struct stat st;
-@@ -679,6 +680,7 @@
+@@ -671,6 +672,7 @@
{
const char *name;
char path[PATH_MAX+1];
char *s, *d, c;
struct symbol *sym;
struct stat sb;
-@@ -687,8 +689,20 @@
+@@ -679,8 +681,20 @@
name = conf_get_autoconfig_name();
conf_read_simple(name, S_DEF_AUTO);
res = 0;
for_all_symbols(i, sym) {
-@@ -781,9 +795,11 @@
+@@ -773,9 +787,11 @@
close(fd);
}
out:
return res;
}
-@@ -795,25 +811,38 @@
+@@ -787,25 +803,38 @@
FILE *out, *tristate, *out_h;
time_t now;
int i;
if (!out_h) {
fclose(out);
fclose(tristate);
-@@ -834,8 +863,7 @@
- " * Automatically generated C config: don't edit\n"
- " * %s\n"
- " * %s"
-- " */\n"
-- "#define AUTOCONF_INCLUDED\n",
-+ " */\n",
- rootmenu.prompt->text, ctime(&now));
-
- for_all_symbols(i, sym) {
-@@ -894,19 +922,22 @@
+@@ -885,19 +914,22 @@
name = getenv("KCONFIG_AUTOHEADER");
if (!name)
name = "include/generated/autoconf.h";
}
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(sym->rev_dep.expr, stderr);
+ 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);
}
newval.tri = EXPR_OR(newval.tri, sym->rev_dep.tri);
}
switch (sym->type) {
case S_BOOLEAN:
case S_TRISTATE:
- /* The visibility imay limit the value from yes => mod */
+ /* The visibility may limit the value from yes => mod */
val = EXPR_AND(expr_calc_value(prop->expr), prop->visible.tri);
break;
default: