Commit 5a1aa8a1 authored by Roman Zippel's avatar Roman Zippel Committed by Sam Ravnborg

kconfig: add named choice group

As choice dependency are now fully checked, it's quite easy to add support
for named choices. This lifts the restriction that a choice value can only
appear once, although it still has to be within the same group,
but multiple choices can be joined by giving them a name.
While at it I cleaned up a little the choice type logic to simplify it a
bit.
Signed-off-by: default avatarRoman Zippel <zippel@linux-m68k.org>
Signed-off-by: default avatarSam Ravnborg <sam@ravnborg.org>
parent 48981178
...@@ -5,25 +5,6 @@ ...@@ -5,25 +5,6 @@
/* A lexical scanner generated by flex */ /* A lexical scanner generated by flex */
#define yy_create_buffer zconf_create_buffer
#define yy_delete_buffer zconf_delete_buffer
#define yy_flex_debug zconf_flex_debug
#define yy_init_buffer zconf_init_buffer
#define yy_flush_buffer zconf_flush_buffer
#define yy_load_buffer_state zconf_load_buffer_state
#define yy_switch_to_buffer zconf_switch_to_buffer
#define yyin zconfin
#define yyleng zconfleng
#define yylex zconflex
#define yylineno zconflineno
#define yyout zconfout
#define yyrestart zconfrestart
#define yytext zconftext
#define yywrap zconfwrap
#define yyalloc zconfalloc
#define yyrealloc zconfrealloc
#define yyfree zconffree
#define FLEX_SCANNER #define FLEX_SCANNER
#define YY_FLEX_MAJOR_VERSION 2 #define YY_FLEX_MAJOR_VERSION 2
#define YY_FLEX_MINOR_VERSION 5 #define YY_FLEX_MINOR_VERSION 5
...@@ -354,7 +335,7 @@ void zconffree (void * ); ...@@ -354,7 +335,7 @@ void zconffree (void * );
/* Begin user sect3 */ /* Begin user sect3 */
#define zconfwrap(n) 1 #define zconfwrap() 1
#define YY_SKIP_YYWRAP #define YY_SKIP_YYWRAP
typedef unsigned char YY_CHAR; typedef unsigned char YY_CHAR;
...@@ -1535,7 +1516,7 @@ static int yy_get_next_buffer (void) ...@@ -1535,7 +1516,7 @@ static int yy_get_next_buffer (void)
/* Read in more data. */ /* Read in more data. */
YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
(yy_n_chars), num_to_read ); (yy_n_chars), (size_t) num_to_read );
YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
} }
...@@ -2007,7 +1988,7 @@ YY_BUFFER_STATE zconf_scan_buffer (char * base, yy_size_t size ) ...@@ -2007,7 +1988,7 @@ YY_BUFFER_STATE zconf_scan_buffer (char * base, yy_size_t size )
/** Setup the input buffer state to scan a string. The next call to zconflex() will /** Setup the input buffer state to scan a string. The next call to zconflex() will
* scan from a @e copy of @a str. * scan from a @e copy of @a str.
* @param str a NUL-terminated string to scan * @param yystr a NUL-terminated string to scan
* *
* @return the newly allocated buffer state object. * @return the newly allocated buffer state object.
* @note If you want to scan bytes that may contain NUL values, then use * @note If you want to scan bytes that may contain NUL values, then use
......
...@@ -21,7 +21,7 @@ P(menu_get_help,const char *,(struct menu *menu)); ...@@ -21,7 +21,7 @@ P(menu_get_help,const char *,(struct menu *menu));
/* symbol.c */ /* symbol.c */
P(symbol_hash,struct symbol *,[SYMBOL_HASHSIZE]); P(symbol_hash,struct symbol *,[SYMBOL_HASHSIZE]);
P(sym_lookup,struct symbol *,(const char *name, int isconst)); P(sym_lookup,struct symbol *,(const char *name, int flags));
P(sym_find,struct symbol *,(const char *name)); P(sym_find,struct symbol *,(const char *name));
P(sym_re_search,struct symbol **,(const char *pattern)); P(sym_re_search,struct symbol **,(const char *pattern));
P(sym_type_name,const char *,(enum symbol_type type)); P(sym_type_name,const char *,(enum symbol_type type));
......
...@@ -235,18 +235,22 @@ void menu_finalize(struct menu *parent) ...@@ -235,18 +235,22 @@ void menu_finalize(struct menu *parent)
sym = parent->sym; sym = parent->sym;
if (parent->list) { if (parent->list) {
if (sym && sym_is_choice(sym)) { if (sym && sym_is_choice(sym)) {
/* find the first choice value and find out choice type */ if (sym->type == S_UNKNOWN) {
for (menu = parent->list; menu; menu = menu->next) { /* find the first choice value to find out choice type */
if (menu->sym) { current_entry = parent;
current_entry = parent; for (menu = parent->list; menu; menu = menu->next) {
if (sym->type == S_UNKNOWN) if (menu->sym && menu->sym->type != S_UNKNOWN) {
menu_set_type(menu->sym->type); menu_set_type(menu->sym->type);
current_entry = menu; break;
if (menu->sym->type == S_UNKNOWN) }
menu_set_type(sym->type);
break;
} }
} }
/* set the type of the remaining choice values */
for (menu = parent->list; menu; menu = menu->next) {
current_entry = menu;
if (menu->sym && menu->sym->type == S_UNKNOWN)
menu_set_type(sym->type);
}
parentdep = expr_alloc_symbol(sym); parentdep = expr_alloc_symbol(sym);
} else if (parent->prompt) } else if (parent->prompt)
parentdep = parent->prompt->visible.expr; parentdep = parent->prompt->visible.expr;
...@@ -313,50 +317,36 @@ void menu_finalize(struct menu *parent) ...@@ -313,50 +317,36 @@ void menu_finalize(struct menu *parent)
} }
} }
for (menu = parent->list; menu; menu = menu->next) { for (menu = parent->list; menu; menu = menu->next) {
if (sym && sym_is_choice(sym) && menu->sym) { if (sym && sym_is_choice(sym) &&
menu->sym && !sym_is_choice_value(menu->sym)) {
current_entry = menu;
menu->sym->flags |= SYMBOL_CHOICEVAL; menu->sym->flags |= SYMBOL_CHOICEVAL;
if (!menu->prompt) if (!menu->prompt)
menu_warn(menu, "choice value must have a prompt"); menu_warn(menu, "choice value must have a prompt");
for (prop = menu->sym->prop; prop; prop = prop->next) { for (prop = menu->sym->prop; prop; prop = prop->next) {
if (prop->type == P_PROMPT && prop->menu != menu) {
prop_warn(prop, "choice values "
"currently only support a "
"single prompt");
}
if (prop->type == P_DEFAULT) if (prop->type == P_DEFAULT)
prop_warn(prop, "defaults for choice " prop_warn(prop, "defaults for choice "
"values not supported"); "values not supported");
if (prop->menu == menu)
continue;
if (prop->type == P_PROMPT &&
prop->menu->parent->sym != sym)
prop_warn(prop, "choice value used outside its choice group");
} }
current_entry = menu;
if (menu->sym->type == S_UNKNOWN)
menu_set_type(sym->type);
/* Non-tristate choice values of tristate choices must /* Non-tristate choice values of tristate choices must
* depend on the choice being set to Y. The choice * depend on the choice being set to Y. The choice
* values' dependencies were propagated to their * values' dependencies were propagated to their
* properties above, so the change here must be re- * properties above, so the change here must be re-
* propagated. */ * propagated.
*/
if (sym->type == S_TRISTATE && menu->sym->type != S_TRISTATE) { if (sym->type == S_TRISTATE && menu->sym->type != S_TRISTATE) {
basedep = expr_alloc_comp(E_EQUAL, sym, &symbol_yes); basedep = expr_alloc_comp(E_EQUAL, sym, &symbol_yes);
basedep = expr_alloc_and(basedep, menu->dep); menu->dep = expr_alloc_and(basedep, menu->dep);
basedep = expr_eliminate_dups(basedep);
menu->dep = basedep;
for (prop = menu->sym->prop; prop; prop = prop->next) { for (prop = menu->sym->prop; prop; prop = prop->next) {
if (prop->menu != menu) if (prop->menu != menu)
continue; continue;
dep = expr_alloc_and(expr_copy(basedep), prop->visible.expr = expr_alloc_and(expr_copy(basedep),
prop->visible.expr); prop->visible.expr);
dep = expr_eliminate_dups(dep);
dep = expr_trans_bool(dep);
prop->visible.expr = dep;
if (prop->type == P_SELECT) {
struct symbol *es = prop_get_symbol(prop);
dep2 = expr_alloc_symbol(menu->sym);
dep = expr_alloc_and(dep2,
expr_copy(dep));
dep = expr_alloc_or(es->rev_dep.expr, dep);
dep = expr_eliminate_dups(dep);
es->rev_dep.expr = dep;
}
} }
} }
menu_add_symbol(P_CHOICE, sym, NULL); menu_add_symbol(P_CHOICE, sym, NULL);
......
...@@ -40,7 +40,7 @@ void sym_add_default(struct symbol *sym, const char *def) ...@@ -40,7 +40,7 @@ void sym_add_default(struct symbol *sym, const char *def)
{ {
struct property *prop = prop_alloc(P_DEFAULT, sym); struct property *prop = prop_alloc(P_DEFAULT, sym);
prop->expr = expr_alloc_symbol(sym_lookup(def, 1)); prop->expr = expr_alloc_symbol(sym_lookup(def, SYMBOL_CONST));
} }
void sym_init(void) void sym_init(void)
...@@ -350,9 +350,6 @@ void sym_calc_value(struct symbol *sym) ...@@ -350,9 +350,6 @@ void sym_calc_value(struct symbol *sym)
; ;
} }
if (sym->flags & SYMBOL_AUTO)
sym->flags &= ~SYMBOL_WRITE;
sym->curr = newval; sym->curr = newval;
if (sym_is_choice(sym) && newval.tri == yes) if (sym_is_choice(sym) && newval.tri == yes)
sym->curr.val = sym_calc_choice(sym); sym->curr.val = sym_calc_choice(sym);
...@@ -377,6 +374,9 @@ void sym_calc_value(struct symbol *sym) ...@@ -377,6 +374,9 @@ void sym_calc_value(struct symbol *sym)
sym_set_changed(choice_sym); sym_set_changed(choice_sym);
} }
} }
if (sym->flags & SYMBOL_AUTO)
sym->flags &= ~SYMBOL_WRITE;
} }
void sym_clear_all_valid(void) void sym_clear_all_valid(void)
...@@ -651,7 +651,7 @@ bool sym_is_changable(struct symbol *sym) ...@@ -651,7 +651,7 @@ bool sym_is_changable(struct symbol *sym)
return sym->visible > sym->rev_dep.tri; return sym->visible > sym->rev_dep.tri;
} }
struct symbol *sym_lookup(const char *name, int isconst) struct symbol *sym_lookup(const char *name, int flags)
{ {
struct symbol *symbol; struct symbol *symbol;
const char *ptr; const char *ptr;
...@@ -671,11 +671,10 @@ struct symbol *sym_lookup(const char *name, int isconst) ...@@ -671,11 +671,10 @@ struct symbol *sym_lookup(const char *name, int isconst)
hash &= 0xff; hash &= 0xff;
for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) { for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
if (!strcmp(symbol->name, name)) { if (!strcmp(symbol->name, name) &&
if ((isconst && symbol->flags & SYMBOL_CONST) || (flags ? symbol->flags & flags
(!isconst && !(symbol->flags & SYMBOL_CONST))) : !(symbol->flags & (SYMBOL_CONST|SYMBOL_CHOICE))))
return symbol; return symbol;
}
} }
new_name = strdup(name); new_name = strdup(name);
} else { } else {
...@@ -687,8 +686,7 @@ struct symbol *sym_lookup(const char *name, int isconst) ...@@ -687,8 +686,7 @@ struct symbol *sym_lookup(const char *name, int isconst)
memset(symbol, 0, sizeof(*symbol)); memset(symbol, 0, sizeof(*symbol));
symbol->name = new_name; symbol->name = new_name;
symbol->type = S_UNKNOWN; symbol->type = S_UNKNOWN;
if (isconst) symbol->flags |= flags;
symbol->flags |= SYMBOL_CONST;
symbol->next = symbol_hash[hash]; symbol->next = symbol_hash[hash];
symbol_hash[hash] = symbol; symbol_hash[hash] = symbol;
...@@ -962,7 +960,7 @@ void prop_add_env(const char *env) ...@@ -962,7 +960,7 @@ void prop_add_env(const char *env)
} }
prop = prop_alloc(P_ENV, sym); prop = prop_alloc(P_ENV, sym);
prop->expr = expr_alloc_symbol(sym_lookup(env, 1)); prop->expr = expr_alloc_symbol(sym_lookup(env, SYMBOL_CONST));
sym_env_list = expr_alloc_one(E_LIST, sym_env_list); sym_env_list = expr_alloc_one(E_LIST, sym_env_list);
sym_env_list->right.sym = sym; sym_env_list->right.sym = sym;
......
This diff is collapsed.
...@@ -91,7 +91,7 @@ static struct menu *current_menu, *current_entry; ...@@ -91,7 +91,7 @@ static struct menu *current_menu, *current_entry;
%type <id> end %type <id> end
%type <id> option_name %type <id> option_name
%type <menu> if_entry menu_entry choice_entry %type <menu> if_entry menu_entry choice_entry
%type <string> symbol_option_arg %type <string> symbol_option_arg word_opt
%destructor { %destructor {
fprintf(stderr, "%s:%d: missing end statement for this entry\n", fprintf(stderr, "%s:%d: missing end statement for this entry\n",
...@@ -239,10 +239,10 @@ symbol_option_arg: ...@@ -239,10 +239,10 @@ symbol_option_arg:
/* choice entry */ /* choice entry */
choice: T_CHOICE T_EOL choice: T_CHOICE word_opt T_EOL
{ {
struct symbol *sym = sym_lookup(NULL, 0); struct symbol *sym = sym_lookup($2, SYMBOL_CHOICE);
sym->flags |= SYMBOL_CHOICE; sym->flags |= SYMBOL_AUTO;
menu_add_entry(sym); menu_add_entry(sym);
menu_add_expr(P_CHOICE, NULL, NULL); menu_add_expr(P_CHOICE, NULL, NULL);
printd(DEBUG_PARSE, "%s:%d:choice\n", zconf_curname(), zconf_lineno()); printd(DEBUG_PARSE, "%s:%d:choice\n", zconf_curname(), zconf_lineno());
...@@ -456,9 +456,12 @@ expr: symbol { $$ = expr_alloc_symbol($1); } ...@@ -456,9 +456,12 @@ expr: symbol { $$ = expr_alloc_symbol($1); }
; ;
symbol: T_WORD { $$ = sym_lookup($1, 0); free($1); } symbol: T_WORD { $$ = sym_lookup($1, 0); free($1); }
| T_WORD_QUOTE { $$ = sym_lookup($1, 1); free($1); } | T_WORD_QUOTE { $$ = sym_lookup($1, SYMBOL_CONST); free($1); }
; ;
word_opt: /* empty */ { $$ = NULL; }
| T_WORD
%% %%
void conf_parse(const char *name) void conf_parse(const char *name)
......
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