summaryrefslogtreecommitdiff
path: root/scripts/kconfig
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/kconfig')
-rw-r--r--scripts/kconfig/Makefile4
-rw-r--r--scripts/kconfig/array_size.h11
-rw-r--r--scripts/kconfig/conf.c237
-rw-r--r--scripts/kconfig/confdata.c157
-rw-r--r--scripts/kconfig/expr.c583
-rw-r--r--scripts/kconfig/expr.h66
-rwxr-xr-xscripts/kconfig/gconf-cfg.sh13
-rw-r--r--scripts/kconfig/gconf.c1699
-rw-r--r--scripts/kconfig/gconf.ui (renamed from scripts/kconfig/gconf.glade)361
-rw-r--r--scripts/kconfig/hashtable.h48
-rw-r--r--scripts/kconfig/internal.h8
-rw-r--r--scripts/kconfig/lexer.l2
-rw-r--r--scripts/kconfig/list.h256
-rw-r--r--scripts/kconfig/list_types.h17
-rw-r--r--scripts/kconfig/lkc.h44
-rw-r--r--scripts/kconfig/lkc_proto.h17
-rw-r--r--scripts/kconfig/lxdialog/inputbox.c6
-rw-r--r--scripts/kconfig/lxdialog/menubox.c2
-rw-r--r--scripts/kconfig/lxdialog/util.c3
-rwxr-xr-xscripts/kconfig/mconf-cfg.sh2
-rw-r--r--scripts/kconfig/mconf.c42
-rw-r--r--scripts/kconfig/menu.c237
-rwxr-xr-xscripts/kconfig/merge_config.sh6
-rw-r--r--scripts/kconfig/mnconf-common.c2
-rw-r--r--scripts/kconfig/mnconf-common.h2
-rwxr-xr-xscripts/kconfig/nconf-cfg.sh2
-rw-r--r--scripts/kconfig/nconf.c46
-rw-r--r--scripts/kconfig/nconf.gui.c19
-rw-r--r--scripts/kconfig/parser.y145
-rw-r--r--scripts/kconfig/preprocess.c5
-rwxr-xr-xscripts/kconfig/qconf-cfg.sh2
-rw-r--r--scripts/kconfig/qconf.cc283
-rw-r--r--scripts/kconfig/qconf.h22
-rwxr-xr-xscripts/kconfig/streamline_config.pl18
-rw-r--r--scripts/kconfig/symbol.c425
-rw-r--r--scripts/kconfig/tests/choice/Kconfig17
-rw-r--r--scripts/kconfig/tests/choice/__init__.py10
-rw-r--r--scripts/kconfig/tests/choice/alldef_expected_config3
-rw-r--r--scripts/kconfig/tests/choice/allmod_expected_config3
-rw-r--r--scripts/kconfig/tests/choice/allno_expected_config3
-rw-r--r--scripts/kconfig/tests/choice/allyes_expected_config3
-rw-r--r--scripts/kconfig/tests/choice/oldask0_expected_stdout4
-rw-r--r--scripts/kconfig/tests/choice/oldask1_config1
-rw-r--r--scripts/kconfig/tests/choice/oldask1_expected_stdout9
-rw-r--r--scripts/kconfig/tests/choice_value_with_m_dep/Kconfig21
-rw-r--r--scripts/kconfig/tests/choice_value_with_m_dep/__init__.py16
-rw-r--r--scripts/kconfig/tests/choice_value_with_m_dep/config2
-rw-r--r--scripts/kconfig/tests/choice_value_with_m_dep/expected_config3
-rw-r--r--scripts/kconfig/tests/choice_value_with_m_dep/expected_stdout4
-rw-r--r--scripts/kconfig/tests/conftest.py17
-rw-r--r--scripts/kconfig/tests/err_recursive_dep/expected_stderr36
-rw-r--r--scripts/kconfig/tests/err_transitional/Kconfig52
-rw-r--r--scripts/kconfig/tests/err_transitional/__init__.py14
-rw-r--r--scripts/kconfig/tests/err_transitional/expected_stderr7
-rw-r--r--scripts/kconfig/tests/inter_choice/Kconfig25
-rw-r--r--scripts/kconfig/tests/inter_choice/__init__.py15
-rw-r--r--scripts/kconfig/tests/inter_choice/defconfig1
-rw-r--r--scripts/kconfig/tests/inter_choice/expected_config4
-rw-r--r--scripts/kconfig/tests/transitional/Kconfig132
-rw-r--r--scripts/kconfig/tests/transitional/__init__.py25
-rw-r--r--scripts/kconfig/tests/transitional/expected_config15
-rw-r--r--scripts/kconfig/tests/transitional/expected_stdout1
-rw-r--r--scripts/kconfig/tests/transitional/initial_config20
-rw-r--r--scripts/kconfig/util.c67
64 files changed, 2342 insertions, 2980 deletions
diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile
index a0a0be38cbdc..fb50bd4f4103 100644
--- a/scripts/kconfig/Makefile
+++ b/scripts/kconfig/Makefile
@@ -105,9 +105,11 @@ configfiles = $(wildcard $(srctree)/kernel/configs/$(1) $(srctree)/arch/$(SRCARC
all-config-fragments = $(call configfiles,*.config)
config-fragments = $(call configfiles,$@)
+cmd_merge_fragments = $(srctree)/scripts/kconfig/merge_config.sh -m $(KCONFIG_CONFIG) $(config-fragments)
+
%.config: $(obj)/conf
$(if $(config-fragments),, $(error $@ fragment does not exists on this architecture))
- $(Q)$(CONFIG_SHELL) $(srctree)/scripts/kconfig/merge_config.sh -m $(KCONFIG_CONFIG) $(config-fragments)
+ $(call cmd,merge_fragments)
$(Q)$(MAKE) -f $(srctree)/Makefile olddefconfig
PHONY += tinyconfig
diff --git a/scripts/kconfig/array_size.h b/scripts/kconfig/array_size.h
deleted file mode 100644
index 26ba78d867d1..000000000000
--- a/scripts/kconfig/array_size.h
+++ /dev/null
@@ -1,11 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef ARRAY_SIZE_H
-#define ARRAY_SIZE_H
-
-/**
- * ARRAY_SIZE - get the number of elements in array @arr
- * @arr: array to be sized
- */
-#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
-
-#endif /* ARRAY_SIZE_H */
diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c
index 8ad2c52d9b1f..a7b44cd8ae14 100644
--- a/scripts/kconfig/conf.c
+++ b/scripts/kconfig/conf.c
@@ -114,51 +114,54 @@ static void set_randconfig_seed(void)
srand(seed);
}
-static bool randomize_choice_values(struct symbol *csym)
+/**
+ * randomize_choice_values - randomize choice block
+ *
+ * @choice: menu entry for the choice
+ */
+static void randomize_choice_values(struct menu *choice)
{
- struct property *prop;
- struct symbol *sym;
- struct expr *e;
- int cnt, def;
+ struct menu *menu;
+ int x;
+ int cnt = 0;
/*
- * If choice is mod then we may have more items selected
- * and if no then no-one.
- * In both cases stop.
+ * First, count the number of symbols to randomize. If sym_has_value()
+ * is true, it was specified by KCONFIG_ALLCONFIG. It needs to be
+ * respected.
*/
- if (csym->curr.tri != yes)
- return false;
+ menu_for_each_sub_entry(menu, choice) {
+ struct symbol *sym = menu->sym;
- prop = sym_get_choice_prop(csym);
+ if (sym && !sym_has_value(sym))
+ cnt++;
+ }
- /* count entries in choice block */
- cnt = 0;
- expr_list_for_each_sym(prop->expr, e, sym)
- cnt++;
+ while (cnt > 0) {
+ x = rand() % cnt;
- /*
- * find a random value and set it to yes,
- * set the rest to no so we have only one set
- */
- def = rand() % cnt;
-
- cnt = 0;
- expr_list_for_each_sym(prop->expr, e, sym) {
- if (def == cnt++) {
- sym->def[S_DEF_USER].tri = yes;
- csym->def[S_DEF_USER].val = sym;
- } else {
- sym->def[S_DEF_USER].tri = no;
+ menu_for_each_sub_entry(menu, choice) {
+ struct symbol *sym = menu->sym;
+
+ if (sym && !sym_has_value(sym))
+ x--;
+
+ if (x < 0) {
+ sym->def[S_DEF_USER].tri = yes;
+ sym->flags |= SYMBOL_DEF_USER;
+ /*
+ * Move the selected item to the _tail_ because
+ * this needs to have a lower priority than the
+ * user input from KCONFIG_ALLCONFIG.
+ */
+ list_move_tail(&sym->choice_link,
+ &choice->choice_members);
+
+ break;
+ }
}
- sym->flags |= SYMBOL_DEF_USER;
- /* clear VALID to get value calculated */
- sym->flags &= ~SYMBOL_VALID;
+ cnt--;
}
- csym->flags |= SYMBOL_DEF_USER;
- /* clear VALID to get value calculated */
- csym->flags &= ~SYMBOL_VALID;
-
- return true;
}
enum conf_def_mode {
@@ -169,9 +172,9 @@ enum conf_def_mode {
def_random
};
-static bool conf_set_all_new_symbols(enum conf_def_mode mode)
+static void conf_set_all_new_symbols(enum conf_def_mode mode)
{
- struct symbol *sym, *csym;
+ struct menu *menu;
int cnt;
/*
* can't go as the default in switch-case below, otherwise gcc whines
@@ -180,7 +183,6 @@ static bool conf_set_all_new_symbols(enum conf_def_mode mode)
int pby = 50; /* probability of bool = y */
int pty = 33; /* probability of tristate = y */
int ptm = 33; /* probability of tristate = m */
- bool has_changed = false;
if (mode == def_random) {
int n, p[3];
@@ -227,79 +229,51 @@ static bool conf_set_all_new_symbols(enum conf_def_mode mode)
}
}
- for_all_symbols(sym) {
- if (sym_has_value(sym) || sym->flags & SYMBOL_VALID)
- continue;
- switch (sym_get_type(sym)) {
- case S_BOOLEAN:
- case S_TRISTATE:
- has_changed = true;
- switch (mode) {
- case def_yes:
- sym->def[S_DEF_USER].tri = yes;
- break;
- case def_mod:
- sym->def[S_DEF_USER].tri = mod;
- break;
- case def_no:
- sym->def[S_DEF_USER].tri = no;
- break;
- case def_random:
- sym->def[S_DEF_USER].tri = no;
- cnt = rand() % 100;
- if (sym->type == S_TRISTATE) {
- if (cnt < pty)
- sym->def[S_DEF_USER].tri = yes;
- else if (cnt < pty + ptm)
- sym->def[S_DEF_USER].tri = mod;
- } else if (cnt < pby)
- sym->def[S_DEF_USER].tri = yes;
- break;
- default:
- continue;
- }
- if (!(sym_is_choice(sym) && mode == def_random))
- sym->flags |= SYMBOL_DEF_USER;
- break;
- default:
- break;
- }
-
- }
+ menu_for_each_entry(menu) {
+ struct symbol *sym = menu->sym;
+ tristate val;
- sym_clear_all_valid();
+ if (!sym || !menu->prompt || sym_has_value(sym) ||
+ (sym->type != S_BOOLEAN && sym->type != S_TRISTATE) ||
+ sym_is_choice_value(sym))
+ continue;
- /*
- * We have different type of choice blocks.
- * 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 equals yes then only one symbol can be
- * selected in a choice block and we set it to yes,
- * and the rest to no.
- */
- if (mode != def_random) {
- for_all_symbols(csym) {
- if ((sym_is_choice(csym) && !sym_has_value(csym)) ||
- sym_is_choice_value(csym))
- csym->flags |= SYMBOL_NEED_SET_CHOICE_VALUES;
+ if (sym_is_choice(sym)) {
+ if (mode == def_random)
+ randomize_choice_values(menu);
+ continue;
}
- }
- for_all_symbols(csym) {
- if (sym_has_value(csym) || !sym_is_choice(csym))
+ switch (mode) {
+ case def_yes:
+ val = yes;
+ break;
+ case def_mod:
+ val = mod;
+ break;
+ case def_no:
+ val = no;
+ break;
+ case def_random:
+ val = no;
+ cnt = rand() % 100;
+ if (sym->type == S_TRISTATE) {
+ if (cnt < pty)
+ val = yes;
+ else if (cnt < pty + ptm)
+ val = mod;
+ } else if (cnt < pby) {
+ val = yes;
+ }
+ break;
+ default:
continue;
-
- sym_calc_value(csym);
- if (mode == def_random)
- has_changed |= randomize_choice_values(csym);
- else {
- set_all_choice_values(csym);
- has_changed = true;
}
+ sym->def[S_DEF_USER].tri = val;
+ sym->flags |= SYMBOL_DEF_USER;
}
- return has_changed;
+ sym_clear_all_valid();
}
static void conf_rewrite_tristates(tristate old_val, tristate new_val)
@@ -448,39 +422,15 @@ help:
static void conf_choice(struct menu *menu)
{
- struct symbol *sym, *def_sym;
+ struct symbol *def_sym;
struct menu *child;
- bool is_new;
-
- sym = menu->sym;
- is_new = !sym_has_value(sym);
- if (sym_is_changeable(sym)) {
- conf_sym(menu);
- sym_calc_value(sym);
- switch (sym_get_tristate_value(sym)) {
- case no:
- case mod:
- return;
- case yes:
- break;
- }
- } else {
- switch (sym_get_tristate_value(sym)) {
- case no:
- return;
- case mod:
- printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu));
- return;
- case yes:
- break;
- }
- }
+ bool is_new = false;
while (1) {
int cnt, def;
printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu));
- def_sym = sym_get_choice_value(sym);
+ def_sym = sym_calc_choice(menu);
cnt = def = 0;
line[0] = 0;
for (child = menu->list; child; child = child->next) {
@@ -498,8 +448,10 @@ static void conf_choice(struct menu *menu)
printf("%*c", indent, ' ');
printf(" %d. %s (%s)", cnt, menu_get_prompt(child),
child->sym->name);
- if (!sym_has_value(child->sym))
+ if (!sym_has_value(child->sym)) {
+ is_new = true;
printf(" (NEW)");
+ }
printf("\n");
}
printf("%*schoice", indent - 1, "");
@@ -549,7 +501,7 @@ static void conf_choice(struct menu *menu)
print_help(child);
continue;
}
- sym_set_tristate_value(child->sym, yes);
+ choice_set_value(menu, child->sym);
return;
}
}
@@ -596,9 +548,7 @@ static void conf(struct menu *menu)
if (sym_is_choice(sym)) {
conf_choice(menu);
- if (sym->curr.tri != mod)
- return;
- goto conf_childs;
+ return;
}
switch (sym->type) {
@@ -630,10 +580,7 @@ static void check_conf(struct menu *menu)
return;
sym = menu->sym;
- if (sym && !sym_has_value(sym) &&
- (sym_is_changeable(sym) ||
- (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes))) {
-
+ if (sym && !sym_has_value(sym) && sym_is_changeable(sym)) {
switch (input_mode) {
case listnewconfig:
if (sym->name)
@@ -647,7 +594,7 @@ static void check_conf(struct menu *menu)
default:
if (!conf_cnt++)
printf("*\n* Restart config...\n*\n");
- rootEntry = menu_get_parent_menu(menu);
+ rootEntry = menu_get_menu_or_parent_menu(menu);
conf(rootEntry);
break;
}
@@ -681,7 +628,7 @@ static const struct option long_opts[] = {
static void conf_usage(const char *progname)
{
- printf("Usage: %s [options] <kconfig-file>\n", progname);
+ printf("Usage: %s [options] kconfig_file\n", progname);
printf("\n");
printf("Generic options:\n");
printf(" -h, --help Print this message and exit.\n");
@@ -706,6 +653,9 @@ static void conf_usage(const char *progname)
printf(" --mod2yesconfig Change answers from mod to yes if possible\n");
printf(" --mod2noconfig Change answers from mod to no if possible\n");
printf(" (If none of the above is given, --oldaskconfig is the default)\n");
+ printf("\n");
+ printf("Arguments:\n");
+ printf(" kconfig_file Top-level Kconfig file.\n");
}
int main(int ac, char **av)
@@ -849,8 +799,7 @@ int main(int ac, char **av)
conf_set_all_new_symbols(def_default);
break;
case randconfig:
- /* Really nothing to do in this loop */
- while (conf_set_all_new_symbols(def_random)) ;
+ conf_set_all_new_symbols(def_random);
break;
case defconfig:
conf_set_all_new_symbols(def_default);
diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c
index 85b53069ba7a..9599a0408862 100644
--- a/scripts/kconfig/confdata.c
+++ b/scripts/kconfig/confdata.c
@@ -18,6 +18,7 @@
#include <time.h>
#include <unistd.h>
+#include <xalloc.h>
#include "internal.h"
#include "lkc.h"
@@ -76,7 +77,7 @@ static bool is_same(const char *file1, const char *file2)
if (map2 == MAP_FAILED)
goto close2;
- if (bcmp(map1, map2, st1.st_size))
+ if (memcmp(map1, map2, st1.st_size))
goto close2;
ret = true;
@@ -359,10 +360,12 @@ int conf_read_simple(const char *name, int def)
*p = '\0';
- in = zconf_fopen(env);
+ name = env;
+
+ in = zconf_fopen(name);
if (in) {
conf_message("using defaults found in %s",
- env);
+ name);
goto load;
}
@@ -382,10 +385,7 @@ load:
def_flags = SYMBOL_DEF << def;
for_all_symbols(sym) {
- sym->flags |= SYMBOL_CHANGED;
- sym->flags &= ~(def_flags|SYMBOL_VALID);
- if (sym_is_choice(sym))
- sym->flags |= def_flags;
+ sym->flags &= ~def_flags;
switch (sym->type) {
case S_INT:
case S_HEX:
@@ -398,7 +398,15 @@ load:
}
}
+ if (def == S_DEF_USER) {
+ for_all_symbols(sym)
+ sym->flags &= ~SYMBOL_VALID;
+ expr_invalidate_all();
+ }
+
while (getline_stripped(&line, &line_asize, in) != -1) {
+ struct menu *choice;
+
conf_lineno++;
if (!line[0]) /* blank line */
@@ -460,25 +468,17 @@ load:
if (conf_set_sym_val(sym, def, def_flags, val))
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 (def != S_DEF_USER)
+ 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);
@@ -489,7 +489,6 @@ load:
int conf_read(const char *name)
{
struct symbol *sym;
- int conf_unsaved = 0;
conf_set_changed(false);
@@ -520,23 +519,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(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;
- }
- }
-
- if (conf_warnings || conf_unsaved)
+ if (conf_warnings)
conf_set_changed(true);
return 0;
@@ -784,35 +771,31 @@ int conf_write_defconfig(const char *filename)
struct menu *choice;
sym = menu->sym;
- if (sym && !sym_is_choice(sym)) {
- sym_calc_value(sym);
- if (!(sym->flags & SYMBOL_WRITE))
- continue;
- sym->flags &= ~SYMBOL_WRITE;
- /* If we cannot change the symbol - skip */
- if (!sym_is_changeable(sym))
- continue;
- /* If symbol equals to default value - skip */
- if (strcmp(sym_get_string_value(sym), sym_get_string_default(sym)) == 0)
- continue;
- /*
- * If symbol is a choice value and equals to the
- * default for a choice - skip.
- */
- choice = sym_get_choice_menu(sym);
- if (choice) {
- struct symbol *ds;
-
- ds = sym_choice_default(choice->sym);
- if (sym == ds) {
- if ((sym->type == S_BOOLEAN) &&
- sym_get_tristate_value(sym) == yes)
- continue;
- }
- }
- print_symbol_for_dotconfig(out, sym);
+ 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;
@@ -991,10 +974,8 @@ static int conf_touch_deps(void)
depfile_path[depfile_prefix_len] = 0;
conf_read_simple(name, S_DEF_AUTO);
- sym_calc_value(modules_sym);
for_all_symbols(sym) {
- sym_calc_value(sym);
if (sym_is_choice(sym))
continue;
if (sym->flags & SYMBOL_WRITE) {
@@ -1108,12 +1089,12 @@ int conf_write_autoconf(int overwrite)
if (ret)
return -1;
- if (conf_touch_deps())
- return 1;
-
for_all_symbols(sym)
sym_calc_value(sym);
+ if (conf_touch_deps())
+ return 1;
+
ret = __conf_write_autoconf(conf_get_autoheader_name(),
print_symbol_for_c,
&comment_style_c);
@@ -1141,16 +1122,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)
@@ -1158,27 +1137,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);
-}
diff --git a/scripts/kconfig/expr.c b/scripts/kconfig/expr.c
index fcc190b67b6f..16f92c4a775a 100644
--- a/scripts/kconfig/expr.c
+++ b/scripts/kconfig/expr.c
@@ -9,44 +9,69 @@
#include <stdlib.h>
#include <string.h>
+#include <hash.h>
+#include <xalloc.h>
+#include "internal.h"
#include "lkc.h"
#define DEBUG_EXPR 0
+HASHTABLE_DEFINE(expr_hashtable, EXPR_HASHSIZE);
+
static struct expr *expr_eliminate_yn(struct expr *e);
-struct expr *expr_alloc_symbol(struct symbol *sym)
+/**
+ * expr_lookup - return the expression with the given type and sub-nodes
+ * This looks up an expression with the specified type and sub-nodes. If such
+ * an expression is found in the hash table, it is returned. Otherwise, a new
+ * expression node is allocated and added to the hash table.
+ * @type: expression type
+ * @l: left node
+ * @r: right node
+ * return: expression
+ */
+static struct expr *expr_lookup(enum expr_type type, void *l, void *r)
{
- struct expr *e = xcalloc(1, sizeof(*e));
- e->type = E_SYMBOL;
- e->left.sym = sym;
+ struct expr *e;
+ int hash;
+
+ hash = hash_32((unsigned int)type ^ hash_ptr(l) ^ hash_ptr(r));
+
+ hash_for_each_possible(expr_hashtable, e, node, hash) {
+ if (e->type == type && e->left._initdata == l &&
+ e->right._initdata == r)
+ return e;
+ }
+
+ e = xmalloc(sizeof(*e));
+ e->type = type;
+ e->left._initdata = l;
+ e->right._initdata = r;
+ e->val_is_valid = false;
+
+ hash_add(expr_hashtable, &e->node, hash);
+
return e;
}
+struct expr *expr_alloc_symbol(struct symbol *sym)
+{
+ return expr_lookup(E_SYMBOL, sym, NULL);
+}
+
struct expr *expr_alloc_one(enum expr_type type, struct expr *ce)
{
- struct expr *e = xcalloc(1, sizeof(*e));
- e->type = type;
- e->left.expr = ce;
- return e;
+ return expr_lookup(type, ce, NULL);
}
struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e2)
{
- struct expr *e = xcalloc(1, sizeof(*e));
- e->type = type;
- e->left.expr = e1;
- e->right.expr = e2;
- return e;
+ return expr_lookup(type, e1, e2);
}
struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2)
{
- struct expr *e = xcalloc(1, sizeof(*e));
- e->type = type;
- e->left.sym = s1;
- e->right.sym = s2;
- return e;
+ return expr_lookup(type, s1, s2);
}
struct expr *expr_alloc_and(struct expr *e1, struct expr *e2)
@@ -63,82 +88,8 @@ struct expr *expr_alloc_or(struct expr *e1, struct expr *e2)
return e2 ? expr_alloc_two(E_OR, e1, e2) : e1;
}
-struct expr *expr_copy(const struct expr *org)
-{
- struct expr *e;
-
- if (!org)
- return NULL;
-
- e = xmalloc(sizeof(*org));
- memcpy(e, org, sizeof(*org));
- switch (org->type) {
- case E_SYMBOL:
- e->left = org->left;
- break;
- case E_NOT:
- e->left.expr = expr_copy(org->left.expr);
- break;
- case E_EQUAL:
- case E_GEQ:
- case E_GTH:
- case E_LEQ:
- case E_LTH:
- case E_UNEQUAL:
- e->left.sym = org->left.sym;
- e->right.sym = org->right.sym;
- break;
- case E_AND:
- case E_OR:
- case E_LIST:
- e->left.expr = expr_copy(org->left.expr);
- e->right.expr = expr_copy(org->right.expr);
- break;
- default:
- fprintf(stderr, "can't copy type %d\n", e->type);
- free(e);
- e = NULL;
- break;
- }
-
- return e;
-}
-
-void expr_free(struct expr *e)
-{
- if (!e)
- return;
-
- switch (e->type) {
- case E_SYMBOL:
- break;
- case E_NOT:
- expr_free(e->left.expr);
- break;
- case E_EQUAL:
- case E_GEQ:
- case E_GTH:
- case E_LEQ:
- case E_LTH:
- case E_UNEQUAL:
- break;
- case E_OR:
- case E_AND:
- expr_free(e->left.expr);
- expr_free(e->right.expr);
- break;
- default:
- fprintf(stderr, "how to free type %d?\n", e->type);
- break;
- }
- free(e);
-}
-
static int trans_count;
-#define e1 (*ep1)
-#define e2 (*ep2)
-
/*
* expr_eliminate_eq() helper.
*
@@ -149,40 +100,47 @@ static int trans_count;
*/
static void __expr_eliminate_eq(enum expr_type type, struct expr **ep1, struct expr **ep2)
{
+ struct expr *l, *r;
+
/* Recurse down to leaves */
- if (e1->type == type) {
- __expr_eliminate_eq(type, &e1->left.expr, &e2);
- __expr_eliminate_eq(type, &e1->right.expr, &e2);
+ if ((*ep1)->type == type) {
+ l = (*ep1)->left.expr;
+ r = (*ep1)->right.expr;
+ __expr_eliminate_eq(type, &l, ep2);
+ __expr_eliminate_eq(type, &r, ep2);
+ *ep1 = expr_alloc_two(type, l, r);
return;
}
- if (e2->type == type) {
- __expr_eliminate_eq(type, &e1, &e2->left.expr);
- __expr_eliminate_eq(type, &e1, &e2->right.expr);
+ if ((*ep2)->type == type) {
+ l = (*ep2)->left.expr;
+ r = (*ep2)->right.expr;
+ __expr_eliminate_eq(type, ep1, &l);
+ __expr_eliminate_eq(type, ep1, &r);
+ *ep2 = expr_alloc_two(type, l, r);
return;
}
- /* e1 and e2 are leaves. Compare them. */
+ /* *ep1 and *ep2 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))
+ if ((*ep1)->type == E_SYMBOL && (*ep2)->type == E_SYMBOL &&
+ (*ep1)->left.sym == (*ep2)->left.sym &&
+ ((*ep1)->left.sym == &symbol_yes || (*ep1)->left.sym == &symbol_no))
return;
- if (!expr_eq(e1, e2))
+ if (!expr_eq(*ep1, *ep2))
return;
- /* e1 and e2 are equal leaves. Prepare them for elimination. */
+ /* *ep1 and *ep2 are equal leaves. Prepare them for elimination. */
trans_count++;
- expr_free(e1); expr_free(e2);
switch (type) {
case E_OR:
- e1 = expr_alloc_symbol(&symbol_no);
- e2 = expr_alloc_symbol(&symbol_no);
+ *ep1 = expr_alloc_symbol(&symbol_no);
+ *ep2 = expr_alloc_symbol(&symbol_no);
break;
case E_AND:
- e1 = expr_alloc_symbol(&symbol_yes);
- e2 = expr_alloc_symbol(&symbol_yes);
+ *ep1 = expr_alloc_symbol(&symbol_yes);
+ *ep2 = expr_alloc_symbol(&symbol_yes);
break;
default:
;
@@ -220,38 +178,36 @@ static void __expr_eliminate_eq(enum expr_type type, struct expr **ep1, struct e
*/
void expr_eliminate_eq(struct expr **ep1, struct expr **ep2)
{
- if (!e1 || !e2)
+ if (!*ep1 || !*ep2)
return;
- switch (e1->type) {
+ switch ((*ep1)->type) {
case E_OR:
case E_AND:
- __expr_eliminate_eq(e1->type, ep1, ep2);
+ __expr_eliminate_eq((*ep1)->type, ep1, ep2);
default:
;
}
- if (e1->type != e2->type) switch (e2->type) {
+ if ((*ep1)->type != (*ep2)->type) switch ((*ep2)->type) {
case E_OR:
case E_AND:
- __expr_eliminate_eq(e2->type, ep1, ep2);
+ __expr_eliminate_eq((*ep2)->type, ep1, ep2);
default:
;
}
- e1 = expr_eliminate_yn(e1);
- e2 = expr_eliminate_yn(e2);
+ *ep1 = expr_eliminate_yn(*ep1);
+ *ep2 = expr_eliminate_yn(*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.
*/
-int expr_eq(struct expr *e1, struct expr *e2)
+bool expr_eq(struct expr *e1, struct expr *e2)
{
- int res, old_count;
+ int old_count;
+ bool res;
/*
* A NULL expr is taken to be yes, but there's also a different way to
@@ -261,7 +217,7 @@ int expr_eq(struct expr *e1, struct expr *e2)
return expr_is_yes(e1) && expr_is_yes(e2);
if (e1->type != e2->type)
- return 0;
+ return false;
switch (e1->type) {
case E_EQUAL:
case E_GEQ:
@@ -276,17 +232,12 @@ int expr_eq(struct expr *e1, struct expr *e2)
return expr_eq(e1->left.expr, e2->left.expr);
case E_AND:
case E_OR:
- e1 = expr_copy(e1);
- e2 = expr_copy(e2);
old_count = trans_count;
expr_eliminate_eq(&e1, &e2);
res = (e1->type == E_SYMBOL && e2->type == E_SYMBOL &&
e1->left.sym == e2->left.sym);
- expr_free(e1);
- expr_free(e2);
trans_count = old_count;
return res;
- case E_LIST:
case E_RANGE:
case E_NONE:
/* panic */;
@@ -299,11 +250,11 @@ int expr_eq(struct expr *e1, struct expr *e2)
printf(" ?\n");
}
- return 0;
+ return false;
}
/*
- * Recursively performs the following simplifications in-place (as well as the
+ * Recursively performs the following simplifications (as well as the
* corresponding simplifications with swapped operands):
*
* expr && n -> n
@@ -315,79 +266,39 @@ int expr_eq(struct expr *e1, struct expr *e2)
*/
static struct expr *expr_eliminate_yn(struct expr *e)
{
- struct expr *tmp;
+ struct expr *l, *r;
if (e) switch (e->type) {
case E_AND:
- e->left.expr = expr_eliminate_yn(e->left.expr);
- e->right.expr = expr_eliminate_yn(e->right.expr);
- if (e->left.expr->type == E_SYMBOL) {
- if (e->left.expr->left.sym == &symbol_no) {
- expr_free(e->left.expr);
- expr_free(e->right.expr);
- e->type = E_SYMBOL;
- e->left.sym = &symbol_no;
- e->right.expr = NULL;
- return e;
- } else if (e->left.expr->left.sym == &symbol_yes) {
- free(e->left.expr);
- tmp = e->right.expr;
- *e = *(e->right.expr);
- free(tmp);
- return e;
- }
+ l = expr_eliminate_yn(e->left.expr);
+ r = expr_eliminate_yn(e->right.expr);
+ if (l->type == E_SYMBOL) {
+ if (l->left.sym == &symbol_no)
+ return l;
+ else if (l->left.sym == &symbol_yes)
+ return r;
}
- if (e->right.expr->type == E_SYMBOL) {
- if (e->right.expr->left.sym == &symbol_no) {
- expr_free(e->left.expr);
- expr_free(e->right.expr);
- e->type = E_SYMBOL;
- e->left.sym = &symbol_no;
- e->right.expr = NULL;
- return e;
- } else if (e->right.expr->left.sym == &symbol_yes) {
- free(e->right.expr);
- tmp = e->left.expr;
- *e = *(e->left.expr);
- free(tmp);
- return e;
- }
+ if (r->type == E_SYMBOL) {
+ if (r->left.sym == &symbol_no)
+ return r;
+ else if (r->left.sym == &symbol_yes)
+ return l;
}
break;
case E_OR:
- e->left.expr = expr_eliminate_yn(e->left.expr);
- e->right.expr = expr_eliminate_yn(e->right.expr);
- if (e->left.expr->type == E_SYMBOL) {
- if (e->left.expr->left.sym == &symbol_no) {
- free(e->left.expr);
- tmp = e->right.expr;
- *e = *(e->right.expr);
- free(tmp);
- return e;
- } else if (e->left.expr->left.sym == &symbol_yes) {
- expr_free(e->left.expr);
- expr_free(e->right.expr);
- e->type = E_SYMBOL;
- e->left.sym = &symbol_yes;
- e->right.expr = NULL;
- return e;
- }
+ l = expr_eliminate_yn(e->left.expr);
+ r = expr_eliminate_yn(e->right.expr);
+ if (l->type == E_SYMBOL) {
+ if (l->left.sym == &symbol_no)
+ return r;
+ else if (l->left.sym == &symbol_yes)
+ return l;
}
- if (e->right.expr->type == E_SYMBOL) {
- if (e->right.expr->left.sym == &symbol_no) {
- free(e->right.expr);
- tmp = e->left.expr;
- *e = *(e->left.expr);
- free(tmp);
- return e;
- } else if (e->right.expr->left.sym == &symbol_yes) {
- expr_free(e->left.expr);
- expr_free(e->right.expr);
- e->type = E_SYMBOL;
- e->left.sym = &symbol_yes;
- e->right.expr = NULL;
- return e;
- }
+ if (r->type == E_SYMBOL) {
+ if (r->left.sym == &symbol_no)
+ return l;
+ else if (r->left.sym == &symbol_yes)
+ return r;
}
break;
default:
@@ -405,7 +316,7 @@ static struct expr *expr_join_or(struct expr *e1, struct expr *e2)
struct symbol *sym1, *sym2;
if (expr_eq(e1, e2))
- return expr_copy(e1);
+ return e1;
if (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT)
return NULL;
if (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT)
@@ -448,6 +359,7 @@ static struct expr *expr_join_or(struct expr *e1, struct expr *e2)
}
}
if (sym1->type == S_BOOLEAN) {
+ // a || !a -> y
if ((e1->type == E_NOT && e1->left.expr->type == E_SYMBOL && e2->type == E_SYMBOL) ||
(e2->type == E_NOT && e2->left.expr->type == E_SYMBOL && e1->type == E_SYMBOL))
return expr_alloc_symbol(&symbol_yes);
@@ -469,7 +381,7 @@ static struct expr *expr_join_and(struct expr *e1, struct expr *e2)
struct symbol *sym1, *sym2;
if (expr_eq(e1, e2))
- return expr_copy(e1);
+ return e1;
if (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT)
return NULL;
if (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT)
@@ -566,59 +478,49 @@ static struct expr *expr_join_and(struct expr *e1, struct expr *e2)
*/
static void expr_eliminate_dups1(enum expr_type type, struct expr **ep1, struct expr **ep2)
{
-#define e1 (*ep1)
-#define e2 (*ep2)
- struct expr *tmp;
+ struct expr *tmp, *l, *r;
/* Recurse down to leaves */
- if (e1->type == type) {
- expr_eliminate_dups1(type, &e1->left.expr, &e2);
- expr_eliminate_dups1(type, &e1->right.expr, &e2);
+ if ((*ep1)->type == type) {
+ l = (*ep1)->left.expr;
+ r = (*ep1)->right.expr;
+ expr_eliminate_dups1(type, &l, ep2);
+ expr_eliminate_dups1(type, &r, ep2);
+ *ep1 = expr_alloc_two(type, l, r);
return;
}
- if (e2->type == type) {
- expr_eliminate_dups1(type, &e1, &e2->left.expr);
- expr_eliminate_dups1(type, &e1, &e2->right.expr);
+ if ((*ep2)->type == type) {
+ l = (*ep2)->left.expr;
+ r = (*ep2)->right.expr;
+ expr_eliminate_dups1(type, ep1, &l);
+ expr_eliminate_dups1(type, ep1, &r);
+ *ep2 = expr_alloc_two(type, l, r);
return;
}
- /* e1 and e2 are leaves. Compare and process them. */
-
- if (e1 == e2)
- return;
-
- switch (e1->type) {
- case E_OR: case E_AND:
- expr_eliminate_dups1(e1->type, &e1, &e1);
- default:
- ;
- }
+ /* *ep1 and *ep2 are leaves. Compare and process them. */
switch (type) {
case E_OR:
- tmp = expr_join_or(e1, e2);
+ tmp = expr_join_or(*ep1, *ep2);
if (tmp) {
- expr_free(e1); expr_free(e2);
- e1 = expr_alloc_symbol(&symbol_no);
- e2 = tmp;
+ *ep1 = expr_alloc_symbol(&symbol_no);
+ *ep2 = tmp;
trans_count++;
}
break;
case E_AND:
- tmp = expr_join_and(e1, e2);
+ tmp = expr_join_and(*ep1, *ep2);
if (tmp) {
- expr_free(e1); expr_free(e2);
- e1 = expr_alloc_symbol(&symbol_yes);
- e2 = tmp;
+ *ep1 = expr_alloc_symbol(&symbol_yes);
+ *ep2 = tmp;
trans_count++;
}
break;
default:
;
}
-#undef e1
-#undef e2
}
/*
@@ -639,19 +541,21 @@ struct expr *expr_eliminate_dups(struct expr *e)
return e;
oldcount = trans_count;
- while (1) {
+ do {
+ struct expr *l, *r;
+
trans_count = 0;
switch (e->type) {
case E_OR: case E_AND:
- expr_eliminate_dups1(e->type, &e, &e);
+ l = expr_eliminate_dups(e->left.expr);
+ r = expr_eliminate_dups(e->right.expr);
+ expr_eliminate_dups1(e->type, &l, &r);
+ e = expr_alloc_two(e->type, l, r);
default:
;
}
- if (!trans_count)
- /* No simplifications done in this pass. We're done */
- break;
e = expr_eliminate_yn(e);
- }
+ } while (trans_count); /* repeat until we get no more simplifications */
trans_count = oldcount;
return e;
}
@@ -660,12 +564,34 @@ struct expr *expr_eliminate_dups(struct expr *e)
* Performs various simplifications involving logical operators and
* comparisons.
*
+ * For bool type:
+ * A=n -> !A
+ * A=m -> n
+ * A=y -> A
+ * A!=n -> A
+ * A!=m -> y
+ * A!=y -> !A
+ *
+ * For any type:
+ * !!A -> A
+ * !(A=B) -> A!=B
+ * !(A!=B) -> A=B
+ * !(A<=B) -> A>B
+ * !(A>=B) -> A<B
+ * !(A<B) -> A>=B
+ * !(A>B) -> A<=B
+ * !(A || B) -> !A && !B
+ * !(A && B) -> !A || !B
+ *
+ * For constant:
+ * !y -> n
+ * !m -> m
+ * !n -> y
+ *
* Allocates and returns a new expression.
*/
struct expr *expr_transform(struct expr *e)
{
- struct expr *tmp;
-
if (!e)
return NULL;
switch (e->type) {
@@ -676,11 +602,11 @@ struct expr *expr_transform(struct expr *e)
case E_LTH:
case E_UNEQUAL:
case E_SYMBOL:
- case E_LIST:
break;
default:
- e->left.expr = expr_transform(e->left.expr);
- e->right.expr = expr_transform(e->right.expr);
+ e = expr_alloc_two(e->type,
+ expr_transform(e->left.expr),
+ expr_transform(e->right.expr));
}
switch (e->type) {
@@ -688,21 +614,19 @@ struct expr *expr_transform(struct expr *e)
if (e->left.sym->type != S_BOOLEAN)
break;
if (e->right.sym == &symbol_no) {
- e->type = E_NOT;
- e->left.expr = expr_alloc_symbol(e->left.sym);
- e->right.sym = NULL;
+ // A=n -> !A
+ e = expr_alloc_one(E_NOT, expr_alloc_symbol(e->left.sym));
break;
}
if (e->right.sym == &symbol_mod) {
+ // A=m -> n
printf("boolean symbol %s tested for 'm'? test forced to 'n'\n", e->left.sym->name);
- e->type = E_SYMBOL;
- e->left.sym = &symbol_no;
- e->right.sym = NULL;
+ e = expr_alloc_symbol(&symbol_no);
break;
}
if (e->right.sym == &symbol_yes) {
- e->type = E_SYMBOL;
- e->right.sym = NULL;
+ // A=y -> A
+ e = expr_alloc_symbol(e->left.sym);
break;
}
break;
@@ -710,104 +634,71 @@ struct expr *expr_transform(struct expr *e)
if (e->left.sym->type != S_BOOLEAN)
break;
if (e->right.sym == &symbol_no) {
- e->type = E_SYMBOL;
- e->right.sym = NULL;
+ // A!=n -> A
+ e = expr_alloc_symbol(e->left.sym);
break;
}
if (e->right.sym == &symbol_mod) {
+ // A!=m -> y
printf("boolean symbol %s tested for 'm'? test forced to 'y'\n", e->left.sym->name);
- e->type = E_SYMBOL;
- e->left.sym = &symbol_yes;
- e->right.sym = NULL;
+ e = expr_alloc_symbol(&symbol_yes);
break;
}
if (e->right.sym == &symbol_yes) {
- e->type = E_NOT;
- e->left.expr = expr_alloc_symbol(e->left.sym);
- e->right.sym = NULL;
+ // A!=y -> !A
+ e = expr_alloc_one(E_NOT, e->left.expr);
break;
}
break;
case E_NOT:
switch (e->left.expr->type) {
case E_NOT:
- // !!a -> a
- tmp = e->left.expr->left.expr;
- free(e->left.expr);
- free(e);
- e = tmp;
- e = expr_transform(e);
+ // !!A -> A
+ e = e->left.expr->left.expr;
break;
case E_EQUAL:
case E_UNEQUAL:
- // !a='x' -> a!='x'
- tmp = e->left.expr;
- free(e);
- e = tmp;
- e->type = e->type == E_EQUAL ? E_UNEQUAL : E_EQUAL;
+ // !(A=B) -> A!=B
+ e = expr_alloc_comp(e->left.expr->type == E_EQUAL ? E_UNEQUAL : E_EQUAL,
+ e->left.expr->left.sym,
+ e->left.expr->right.sym);
break;
case E_LEQ:
case E_GEQ:
- // !a<='x' -> a>'x'
- tmp = e->left.expr;
- free(e);
- e = tmp;
- e->type = e->type == E_LEQ ? E_GTH : E_LTH;
+ // !(A<=B) -> A>B
+ e = expr_alloc_comp(e->left.expr->type == E_LEQ ? E_GTH : E_LTH,
+ e->left.expr->left.sym,
+ e->left.expr->right.sym);
break;
case E_LTH:
case E_GTH:
- // !a<'x' -> a>='x'
- tmp = e->left.expr;
- free(e);
- e = tmp;
- e->type = e->type == E_LTH ? E_GEQ : E_LEQ;
+ // !(A<B) -> A>=B
+ e = expr_alloc_comp(e->left.expr->type == E_LTH ? E_GEQ : E_LEQ,
+ e->left.expr->left.sym,
+ e->left.expr->right.sym);
break;
case E_OR:
- // !(a || b) -> !a && !b
- tmp = e->left.expr;
- e->type = E_AND;
- e->right.expr = expr_alloc_one(E_NOT, tmp->right.expr);
- tmp->type = E_NOT;
- tmp->right.expr = NULL;
+ // !(A || B) -> !A && !B
+ e = expr_alloc_and(expr_alloc_one(E_NOT, e->left.expr->left.expr),
+ expr_alloc_one(E_NOT, e->left.expr->right.expr));
e = expr_transform(e);
break;
case E_AND:
- // !(a && b) -> !a || !b
- tmp = e->left.expr;
- e->type = E_OR;
- e->right.expr = expr_alloc_one(E_NOT, tmp->right.expr);
- tmp->type = E_NOT;
- tmp->right.expr = NULL;
+ // !(A && B) -> !A || !B
+ e = expr_alloc_or(expr_alloc_one(E_NOT, e->left.expr->left.expr),
+ expr_alloc_one(E_NOT, e->left.expr->right.expr));
e = expr_transform(e);
break;
case E_SYMBOL:
- if (e->left.expr->left.sym == &symbol_yes) {
+ if (e->left.expr->left.sym == &symbol_yes)
// !'y' -> 'n'
- tmp = e->left.expr;
- free(e);
- e = tmp;
- e->type = E_SYMBOL;
- e->left.sym = &symbol_no;
- break;
- }
- if (e->left.expr->left.sym == &symbol_mod) {
+ e = expr_alloc_symbol(&symbol_no);
+ else if (e->left.expr->left.sym == &symbol_mod)
// !'m' -> 'm'
- tmp = e->left.expr;
- free(e);
- e = tmp;
- e->type = E_SYMBOL;
- e->left.sym = &symbol_mod;
- break;
- }
- if (e->left.expr->left.sym == &symbol_no) {
+ e = expr_alloc_symbol(&symbol_mod);
+ else if (e->left.expr->left.sym == &symbol_no)
// !'n' -> 'y'
- tmp = e->left.expr;
- free(e);
- e = tmp;
- e->type = E_SYMBOL;
- e->left.sym = &symbol_yes;
- break;
- }
+ e = expr_alloc_symbol(&symbol_yes);
break;
default:
;
@@ -819,10 +710,10 @@ struct expr *expr_transform(struct expr *e)
return e;
}
-int expr_contains_symbol(struct expr *dep, struct symbol *sym)
+bool expr_contains_symbol(struct expr *dep, struct symbol *sym)
{
if (!dep)
- return 0;
+ return false;
switch (dep->type) {
case E_AND:
@@ -844,7 +735,7 @@ int expr_contains_symbol(struct expr *dep, struct symbol *sym)
default:
;
}
- return 0;
+ return false;
}
bool expr_depends_symbol(struct expr *dep, struct symbol *sym)
@@ -931,23 +822,22 @@ struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symb
case E_EQUAL:
if (type == E_EQUAL) {
if (sym == &symbol_yes)
- return expr_copy(e);
+ return e;
if (sym == &symbol_mod)
return expr_alloc_symbol(&symbol_no);
if (sym == &symbol_no)
- return expr_alloc_one(E_NOT, expr_copy(e));
+ return expr_alloc_one(E_NOT, e);
} else {
if (sym == &symbol_yes)
- return expr_alloc_one(E_NOT, expr_copy(e));
+ return expr_alloc_one(E_NOT, e);
if (sym == &symbol_mod)
return expr_alloc_symbol(&symbol_yes);
if (sym == &symbol_no)
- return expr_copy(e);
+ return e;
}
break;
case E_SYMBOL:
return expr_alloc_comp(type, e->left.sym, sym);
- case E_LIST:
case E_RANGE:
case E_NONE:
/* panic */;
@@ -998,7 +888,7 @@ static enum string_value_kind expr_parse_string(const char *str,
? kind : k_string;
}
-tristate expr_calc_value(struct expr *e)
+static tristate __expr_calc_value(struct expr *e)
{
tristate val1, val2;
const char *str1, *str2;
@@ -1006,9 +896,6 @@ tristate expr_calc_value(struct expr *e)
union string_value lval = {}, rval = {};
int res;
- if (!e)
- return yes;
-
switch (e->type) {
case E_SYMBOL:
sym_calc_value(e->left.sym);
@@ -1072,6 +959,35 @@ tristate expr_calc_value(struct expr *e)
}
}
+/**
+ * expr_calc_value - return the tristate value of the given expression
+ * @e: expression
+ * return: tristate value of the expression
+ */
+tristate expr_calc_value(struct expr *e)
+{
+ if (!e)
+ return yes;
+
+ if (!e->val_is_valid) {
+ e->val = __expr_calc_value(e);
+ e->val_is_valid = true;
+ }
+
+ return e->val;
+}
+
+/**
+ * expr_invalidate_all - invalidate all cached expression values
+ */
+void expr_invalidate_all(void)
+{
+ struct expr *e;
+
+ hash_for_each(expr_hashtable, e, node)
+ e->val_is_valid = false;
+}
+
static int expr_compare_type(enum expr_type t1, enum expr_type t2)
{
if (t1 == t2)
@@ -1083,29 +999,27 @@ static int expr_compare_type(enum expr_type t1, enum expr_type t2)
case E_GTH:
if (t2 == E_EQUAL || t2 == E_UNEQUAL)
return 1;
+ /* fallthrough */
case E_EQUAL:
case E_UNEQUAL:
if (t2 == E_NOT)
return 1;
+ /* fallthrough */
case E_NOT:
if (t2 == E_AND)
return 1;
+ /* fallthrough */
case E_AND:
if (t2 == E_OR)
return 1;
- case E_OR:
- if (t2 == E_LIST)
- return 1;
- case E_LIST:
- if (t2 == 0)
- return 1;
+ /* fallthrough */
default:
- return -1;
+ break;
}
return 0;
}
-void expr_print(struct expr *e,
+void expr_print(const struct expr *e,
void (*fn)(void *, struct symbol *, const char *),
void *data, int prevtoken)
{
@@ -1171,13 +1085,6 @@ void expr_print(struct expr *e,
fn(data, NULL, " && ");
expr_print(e->right.expr, fn, data, E_AND);
break;
- case E_LIST:
- fn(data, e->right.sym, e->right.sym->name);
- if (e->left.expr) {
- fn(data, NULL, " ^ ");
- expr_print(e->left.expr, fn, data, E_LIST);
- }
- break;
case E_RANGE:
fn(data, NULL, "[");
fn(data, e->left.sym, e->left.sym->name);
@@ -1237,7 +1144,7 @@ static void expr_print_gstr_helper(void *data, struct symbol *sym, const char *s
str_printf(gs, " [=%s]", sym_str);
}
-void expr_gstr_print(struct expr *e, struct gstr *gs)
+void expr_gstr_print(const struct expr *e, struct gstr *gs)
{
expr_print(e, expr_print_gstr_helper, gs, E_NONE);
}
diff --git a/scripts/kconfig/expr.h b/scripts/kconfig/expr.h
index 7c0c242318bc..5f900d18dae0 100644
--- a/scripts/kconfig/expr.h
+++ b/scripts/kconfig/expr.h
@@ -12,12 +12,11 @@ extern "C" {
#include <assert.h>
#include <stdio.h>
-#include "list_types.h"
#ifndef __cplusplus
#include <stdbool.h>
#endif
-#include "list_types.h"
+#include <list_types.h>
typedef enum tristate {
no, mod, yes
@@ -26,16 +25,30 @@ typedef enum tristate {
enum expr_type {
E_NONE, E_OR, E_AND, E_NOT,
E_EQUAL, E_UNEQUAL, E_LTH, E_LEQ, E_GTH, E_GEQ,
- E_LIST, E_SYMBOL, E_RANGE
+ E_SYMBOL, E_RANGE
};
union expr_data {
- struct expr *expr;
- struct symbol *sym;
+ struct expr * const expr;
+ struct symbol * const sym;
+ void *_initdata;
};
+/**
+ * struct expr - expression
+ *
+ * @node: link node for the hash table
+ * @type: expressoin type
+ * @val: calculated tristate value
+ * @val_is_valid: indicate whether the value is valid
+ * @left: left node
+ * @right: right node
+ */
struct expr {
+ struct hlist_node node;
enum expr_type type;
+ tristate val;
+ bool val_is_valid;
union expr_data left, right;
};
@@ -43,9 +56,6 @@ struct expr {
#define EXPR_AND(dep1, dep2) (((dep1)<(dep2))?(dep1):(dep2))
#define EXPR_NOT(dep) (2-(dep))
-#define expr_list_for_each_sym(l, e, s) \
- for (e = (l); e && (s = e->right.sym); e = e->left.expr)
-
struct expr_value {
struct expr *expr;
tristate tri;
@@ -73,6 +83,8 @@ enum {
* Represents a configuration symbol.
*
* Choices are represented as a special kind of symbol with null name.
+ *
+ * @choice_link: linked to menu::choice_members
*/
struct symbol {
/* link node for the hash table */
@@ -110,6 +122,8 @@ struct symbol {
/* config entries associated with this symbol */
struct list_head menus;
+ struct list_head choice_link;
+
/* SYMBOL_* flags */
int flags;
@@ -130,10 +144,9 @@ struct symbol {
#define SYMBOL_CONST 0x0001 /* symbol is const */
#define SYMBOL_CHECK 0x0008 /* used during dependency checking */
-#define SYMBOL_CHOICEVAL 0x0020 /* used as a value in a choice block */
#define SYMBOL_VALID 0x0080 /* set when symbol.curr is calculated */
+#define SYMBOL_TRANS 0x0100 /* symbol is transitional only (not visible)*/
#define SYMBOL_WRITE 0x0200 /* write symbol to file (KCONFIG_CONFIG) */
-#define SYMBOL_CHANGED 0x0400 /* ? */
#define SYMBOL_WRITTEN 0x0800 /* track info to avoid double-write to .config */
#define SYMBOL_CHECKED 0x2000 /* used during dependency checking */
#define SYMBOL_WARNED 0x8000 /* warning has been issued */
@@ -145,9 +158,6 @@ struct symbol {
#define SYMBOL_DEF3 0x40000 /* symbol.def[S_DEF_3] is valid */
#define SYMBOL_DEF4 0x80000 /* symbol.def[S_DEF_4] is valid */
-/* choice values need to be set before calculating this symbol value */
-#define SYMBOL_NEED_SET_CHOICE_VALUES 0x100000
-
#define SYMBOL_MAXLENGTH 256
/* A property represent the config options that can be associated
@@ -170,11 +180,9 @@ enum prop_type {
P_COMMENT, /* text associated with a comment */
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_SYMBOL, /* where a symbol is defined */
};
struct property {
@@ -184,7 +192,7 @@ struct property {
struct expr_value visible;
struct expr *expr; /* the optional conditional part of the property */
struct menu *menu; /* the menu the property are associated with
- * valid for: P_SELECT, P_RANGE, P_CHOICE,
+ * valid for: P_SELECT, P_RANGE,
* P_PROMPT, P_DEFAULT, P_MENU, P_COMMENT */
const char *filename; /* what file was this property defined */
int lineno; /* what lineno was this property defined */
@@ -194,18 +202,30 @@ struct property {
for (st = sym->prop; st; st = st->next) \
if (st->type == (tok))
#define for_all_defaults(sym, st) for_all_properties(sym, st, P_DEFAULT)
-#define for_all_choices(sym, st) for_all_properties(sym, st, P_CHOICE)
#define for_all_prompts(sym, st) \
for (st = sym->prop; st; st = st->next) \
if (st->text)
+enum menu_type {
+ M_CHOICE, // "choice"
+ M_COMMENT, // "comment"
+ M_IF, // "if"
+ M_MENU, // "mainmenu", "menu", "menuconfig"
+ M_NORMAL, // others, i.e., "config"
+};
+
/*
* 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.
+ *
+ * @type: type of the menu entry
+ * @choice_members: list of choice members with priority.
*/
struct menu {
+ enum menu_type type;
+
/* The next menu node at the same level */
struct menu *next;
@@ -223,6 +243,8 @@ struct menu {
struct list_head link; /* link to symbol::menus */
+ struct list_head choice_members;
+
/*
* 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
@@ -279,24 +301,22 @@ struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *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(const struct expr *org);
-void expr_free(struct expr *e);
void expr_eliminate_eq(struct expr **ep1, struct expr **ep2);
-int expr_eq(struct expr *e1, struct expr *e2);
+bool expr_eq(struct expr *e1, struct expr *e2);
tristate expr_calc_value(struct expr *e);
struct expr *expr_eliminate_dups(struct expr *e);
struct expr *expr_transform(struct expr *e);
-int expr_contains_symbol(struct expr *dep, struct symbol *sym);
+bool 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);
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(const 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)
+static inline bool expr_is_yes(const struct expr *e)
{
return !e || (e->type == E_SYMBOL && e->left.sym == &symbol_yes);
}
diff --git a/scripts/kconfig/gconf-cfg.sh b/scripts/kconfig/gconf-cfg.sh
index 040d8f338820..856c692f480c 100755
--- a/scripts/kconfig/gconf-cfg.sh
+++ b/scripts/kconfig/gconf-cfg.sh
@@ -1,10 +1,12 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
+set -eu
+
cflags=$1
libs=$2
-PKG="gtk+-2.0 gmodule-2.0 libglade-2.0"
+PKG=gtk+-3.0
if [ -z "$(command -v ${HOSTPKG_CONFIG})" ]; then
echo >&2 "*"
@@ -16,18 +18,11 @@ fi
if ! ${HOSTPKG_CONFIG} --exists $PKG; then
echo >&2 "*"
echo >&2 "* Unable to find the GTK+ installation. Please make sure that"
- echo >&2 "* the GTK+ 2.0 development package is correctly installed."
+ echo >&2 "* the GTK 3 development package is correctly installed."
echo >&2 "* You need $PKG"
echo >&2 "*"
exit 1
fi
-if ! ${HOSTPKG_CONFIG} --atleast-version=2.0.0 gtk+-2.0; then
- echo >&2 "*"
- echo >&2 "* GTK+ is present but version >= 2.0.0 is required."
- echo >&2 "*"
- exit 1
-fi
-
${HOSTPKG_CONFIG} --cflags ${PKG} > ${cflags}
${HOSTPKG_CONFIG} --libs ${PKG} > ${libs}
diff --git a/scripts/kconfig/gconf.c b/scripts/kconfig/gconf.c
index e04dbafd3add..8b164ccfa008 100644
--- a/scripts/kconfig/gconf.c
+++ b/scripts/kconfig/gconf.c
@@ -7,10 +7,7 @@
#include "lkc.h"
#include "images.h"
-#include <glade/glade.h>
#include <gtk/gtk.h>
-#include <glib.h>
-#include <gdk/gdkkeysyms.h>
#include <stdio.h>
#include <string.h>
@@ -18,7 +15,7 @@
#include <unistd.h>
#include <time.h>
-enum {
+enum view_mode {
SINGLE_VIEW, SPLIT_VIEW, FULL_VIEW
};
@@ -30,29 +27,24 @@ static gint view_mode = FULL_VIEW;
static gboolean show_name = TRUE;
static gboolean show_range = TRUE;
static gboolean show_value = TRUE;
-static gboolean resizeable = FALSE;
static int opt_mode = OPT_NORMAL;
-GtkWidget *main_wnd = NULL;
-GtkWidget *tree1_w = NULL; // left frame
-GtkWidget *tree2_w = NULL; // right frame
-GtkWidget *text_w = NULL;
-GtkWidget *hpaned = NULL;
-GtkWidget *vpaned = NULL;
-GtkWidget *back_btn = NULL;
-GtkWidget *save_btn = NULL;
-GtkWidget *save_menu_item = NULL;
+static GtkWidget *main_wnd;
+static GtkWidget *tree1_w; // left frame
+static GtkWidget *tree2_w; // right frame
+static GtkWidget *text_w;
+static GtkWidget *hpaned;
+static GtkWidget *vpaned;
+static GtkWidget *back_btn, *save_btn, *single_btn, *split_btn, *full_btn;
+static GtkWidget *save_menu_item;
-GtkTextTag *tag1, *tag2;
-GdkColor color;
+static GtkTextTag *tag1, *tag2;
-GtkTreeStore *tree1, *tree2, *tree;
-GtkTreeModel *model1, *model2;
-static GtkTreeIter *parents[256];
-static gint indent;
+static GtkTreeStore *tree1, *tree2;
+static GdkPixbuf *pix_menu;
-static struct menu *current; // current node for SINGLE view
-static struct menu *browsed; // browsed node for SPLIT view
+static struct menu *browsed; // browsed menu for SINGLE/SPLIT view
+static struct menu *selected; // selected entry
enum {
COL_OPTION, COL_NAME, COL_NO, COL_MOD, COL_YES, COL_VALUE,
@@ -61,491 +53,382 @@ enum {
COL_NUMBER
};
-static void display_list(void);
-static void display_tree(struct menu *menu);
-static void display_tree_part(void);
-static void update_tree(struct menu *src, GtkTreeIter * dst);
-static void set_node(GtkTreeIter * node, struct menu *menu, gchar ** row);
-static gchar **fill_row(struct menu *menu);
-static void conf_changed(void);
+static void display_tree(GtkTreeStore *store, struct menu *menu);
+static void recreate_tree(void);
-static void replace_button_icon(GladeXML *xml, GdkDrawable *window,
- GtkStyle *style, gchar *btn_name, gchar **xpm)
+static void conf_changed(bool dirty)
{
- GdkPixmap *pixmap;
- GdkBitmap *mask;
- GtkToolButton *button;
- GtkWidget *image;
-
- pixmap = gdk_pixmap_create_from_xpm_d(window, &mask,
- &style->bg[GTK_STATE_NORMAL],
- xpm);
-
- button = GTK_TOOL_BUTTON(glade_xml_get_widget(xml, btn_name));
- image = gtk_image_new_from_pixmap(pixmap, mask);
- gtk_widget_show(image);
- gtk_tool_button_set_icon_widget(button, image);
+ gtk_widget_set_sensitive(save_btn, dirty);
+ gtk_widget_set_sensitive(save_menu_item, dirty);
}
-/* Main Window Initialization */
-static void init_main_window(const gchar *glade_file)
+/* Utility Functions */
+
+static void text_insert_msg(const char *title, const char *msg)
{
- GladeXML *xml;
- GtkWidget *widget;
- GtkTextBuffer *txtbuf;
- GtkStyle *style;
+ GtkTextBuffer *buffer;
+ GtkTextIter start, end;
- xml = glade_xml_new(glade_file, "window1", NULL);
- if (!xml)
- g_error("GUI loading failed !\n");
- glade_xml_signal_autoconnect(xml);
+ buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w));
+ gtk_text_buffer_get_bounds(buffer, &start, &end);
+ gtk_text_buffer_delete(buffer, &start, &end);
+ gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_w), 15);
- main_wnd = glade_xml_get_widget(xml, "window1");
- hpaned = glade_xml_get_widget(xml, "hpaned1");
- vpaned = glade_xml_get_widget(xml, "vpaned1");
- tree1_w = glade_xml_get_widget(xml, "treeview1");
- tree2_w = glade_xml_get_widget(xml, "treeview2");
- text_w = glade_xml_get_widget(xml, "textview3");
+ gtk_text_buffer_get_end_iter(buffer, &end);
+ gtk_text_buffer_insert_with_tags(buffer, &end, title, -1, tag1,
+ NULL);
+ gtk_text_buffer_insert_at_cursor(buffer, "\n\n", 2);
+ gtk_text_buffer_get_end_iter(buffer, &end);
+ gtk_text_buffer_insert_with_tags(buffer, &end, msg, -1, tag2,
+ NULL);
+}
- back_btn = glade_xml_get_widget(xml, "button1");
- gtk_widget_set_sensitive(back_btn, FALSE);
+static void text_insert_help(struct menu *menu)
+{
+ struct gstr help = str_new();
- widget = glade_xml_get_widget(xml, "show_name1");
- gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,
- show_name);
+ menu_get_ext_help(menu, &help);
+ text_insert_msg(menu_get_prompt(menu), str_get(&help));
+ str_free(&help);
+}
- widget = glade_xml_get_widget(xml, "show_range1");
- gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,
- show_range);
+static void _select_menu(GtkTreeView *view, GtkTreeModel *model,
+ GtkTreeIter *parent, struct menu *match)
+{
+ GtkTreeIter iter;
+ gboolean valid;
- widget = glade_xml_get_widget(xml, "show_data1");
- gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,
- show_value);
+ valid = gtk_tree_model_iter_children(model, &iter, parent);
+ while (valid) {
+ struct menu *menu;
- save_btn = glade_xml_get_widget(xml, "button3");
- save_menu_item = glade_xml_get_widget(xml, "save1");
- conf_set_changed_callback(conf_changed);
+ gtk_tree_model_get(model, &iter, COL_MENU, &menu, -1);
- style = gtk_widget_get_style(main_wnd);
- widget = glade_xml_get_widget(xml, "toolbar1");
+ if (menu == match) {
+ GtkTreeSelection *selection;
+ GtkTreePath *path;
- replace_button_icon(xml, main_wnd->window, style,
- "button4", (gchar **) xpm_single_view);
- replace_button_icon(xml, main_wnd->window, style,
- "button5", (gchar **) xpm_split_view);
- replace_button_icon(xml, main_wnd->window, style,
- "button6", (gchar **) xpm_tree_view);
+ /*
+ * Expand parents to reflect the selection, and
+ * scroll down to it.
+ */
+ path = gtk_tree_model_get_path(model, &iter);
+ gtk_tree_view_expand_to_path(view, path);
+ gtk_tree_view_scroll_to_cell(view, path, NULL, TRUE,
+ 0.5, 0.0);
+ gtk_tree_path_free(path);
- txtbuf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w));
- tag1 = gtk_text_buffer_create_tag(txtbuf, "mytag1",
- "foreground", "red",
- "weight", PANGO_WEIGHT_BOLD,
- NULL);
- tag2 = gtk_text_buffer_create_tag(txtbuf, "mytag2",
- /*"style", PANGO_STYLE_OBLIQUE, */
- NULL);
+ selection = gtk_tree_view_get_selection(view);
+ gtk_tree_selection_select_iter(selection, &iter);
- gtk_window_set_title(GTK_WINDOW(main_wnd), rootmenu.prompt->text);
+ text_insert_help(menu);
+ }
+
+ _select_menu(view, model, &iter, match);
- gtk_widget_show(main_wnd);
+ valid = gtk_tree_model_iter_next(model, &iter);
+ }
}
-static void init_tree_model(void)
+static void select_menu(GtkTreeView *view, struct menu *match)
{
- gint i;
-
- tree = tree2 = gtk_tree_store_new(COL_NUMBER,
- G_TYPE_STRING, G_TYPE_STRING,
- G_TYPE_STRING, G_TYPE_STRING,
- G_TYPE_STRING, G_TYPE_STRING,
- G_TYPE_POINTER, GDK_TYPE_COLOR,
- G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF,
- G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
- G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
- G_TYPE_BOOLEAN);
- model2 = GTK_TREE_MODEL(tree2);
-
- for (parents[0] = NULL, i = 1; i < 256; i++)
- parents[i] = (GtkTreeIter *) g_malloc(sizeof(GtkTreeIter));
-
- tree1 = gtk_tree_store_new(COL_NUMBER,
- G_TYPE_STRING, G_TYPE_STRING,
- G_TYPE_STRING, G_TYPE_STRING,
- G_TYPE_STRING, G_TYPE_STRING,
- G_TYPE_POINTER, GDK_TYPE_COLOR,
- G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF,
- G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
- G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
- G_TYPE_BOOLEAN);
- model1 = GTK_TREE_MODEL(tree1);
+ _select_menu(view, gtk_tree_view_get_model(view), NULL, match);
}
-static void init_left_tree(void)
+static void _update_row_visibility(GtkTreeView *view)
{
- GtkTreeView *view = GTK_TREE_VIEW(tree1_w);
- GtkCellRenderer *renderer;
- GtkTreeSelection *sel;
- GtkTreeViewColumn *column;
-
- gtk_tree_view_set_model(view, model1);
- gtk_tree_view_set_headers_visible(view, TRUE);
- gtk_tree_view_set_rules_hint(view, TRUE);
-
- column = gtk_tree_view_column_new();
- gtk_tree_view_append_column(view, column);
- gtk_tree_view_column_set_title(column, "Options");
-
- renderer = gtk_cell_renderer_toggle_new();
- gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
- renderer, FALSE);
- gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
- renderer,
- "active", COL_BTNACT,
- "inconsistent", COL_BTNINC,
- "visible", COL_BTNVIS,
- "radio", COL_BTNRAD, NULL);
- renderer = gtk_cell_renderer_text_new();
- gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
- renderer, FALSE);
- gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
- renderer,
- "text", COL_OPTION,
- "foreground-gdk",
- COL_COLOR, NULL);
+ GtkTreeModelFilter *filter = GTK_TREE_MODEL_FILTER(gtk_tree_view_get_model(view));
- sel = gtk_tree_view_get_selection(view);
- gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE);
- gtk_widget_realize(tree1_w);
+ gtk_tree_model_filter_refilter(filter);
}
-static void renderer_edited(GtkCellRendererText * cell,
- const gchar * path_string,
- const gchar * new_text, gpointer user_data);
+static void update_row_visibility(void)
+{
+ if (view_mode == SPLIT_VIEW)
+ _update_row_visibility(GTK_TREE_VIEW(tree1_w));
+ _update_row_visibility(GTK_TREE_VIEW(tree2_w));
+}
-static void init_right_tree(void)
+static void set_node(GtkTreeStore *tree, GtkTreeIter *node, struct menu *menu)
{
- GtkTreeView *view = GTK_TREE_VIEW(tree2_w);
- GtkCellRenderer *renderer;
- GtkTreeSelection *sel;
- GtkTreeViewColumn *column;
- gint i;
+ struct symbol *sym = menu->sym;
+ tristate val;
+ gchar *option;
+ const gchar *_no = "";
+ const gchar *_mod = "";
+ const gchar *_yes = "";
+ const gchar *value = "";
+ GdkRGBA color;
+ gboolean editable = FALSE;
+ gboolean btnvis = FALSE;
+
+ option = g_strdup_printf("%s %s %s %s",
+ menu->type == M_COMMENT ? "***" : "",
+ menu_get_prompt(menu),
+ menu->type == M_COMMENT ? "***" : "",
+ sym && !sym_has_value(sym) ? "(NEW)" : "");
+
+ gdk_rgba_parse(&color, menu_is_visible(menu) ? "Black" : "DarkGray");
- gtk_tree_view_set_model(view, model2);
- gtk_tree_view_set_headers_visible(view, TRUE);
- gtk_tree_view_set_rules_hint(view, TRUE);
+ if (!sym)
+ goto set;
- column = gtk_tree_view_column_new();
- gtk_tree_view_append_column(view, column);
- gtk_tree_view_column_set_title(column, "Options");
+ sym_calc_value(sym);
- renderer = gtk_cell_renderer_pixbuf_new();
- gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
- renderer, FALSE);
- gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
- renderer,
- "pixbuf", COL_PIXBUF,
- "visible", COL_PIXVIS, NULL);
- renderer = gtk_cell_renderer_toggle_new();
- gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
- renderer, FALSE);
- gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
- renderer,
- "active", COL_BTNACT,
- "inconsistent", COL_BTNINC,
- "visible", COL_BTNVIS,
- "radio", COL_BTNRAD, NULL);
- renderer = gtk_cell_renderer_text_new();
- gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
- renderer, FALSE);
- gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
- renderer,
- "text", COL_OPTION,
- "foreground-gdk",
- COL_COLOR, NULL);
+ if (menu->type == M_CHOICE) { // parse children to get a final value
+ struct symbol *def_sym = sym_calc_choice(menu);
+ struct menu *def_menu = NULL;
- renderer = gtk_cell_renderer_text_new();
- gtk_tree_view_insert_column_with_attributes(view, -1,
- "Name", renderer,
- "text", COL_NAME,
- "foreground-gdk",
- COL_COLOR, NULL);
- renderer = gtk_cell_renderer_text_new();
- gtk_tree_view_insert_column_with_attributes(view, -1,
- "N", renderer,
- "text", COL_NO,
- "foreground-gdk",
- COL_COLOR, NULL);
- renderer = gtk_cell_renderer_text_new();
- gtk_tree_view_insert_column_with_attributes(view, -1,
- "M", renderer,
- "text", COL_MOD,
- "foreground-gdk",
- COL_COLOR, NULL);
- renderer = gtk_cell_renderer_text_new();
- gtk_tree_view_insert_column_with_attributes(view, -1,
- "Y", renderer,
- "text", COL_YES,
- "foreground-gdk",
- COL_COLOR, NULL);
- renderer = gtk_cell_renderer_text_new();
- gtk_tree_view_insert_column_with_attributes(view, -1,
- "Value", renderer,
- "text", COL_VALUE,
- "editable",
- COL_EDIT,
- "foreground-gdk",
- COL_COLOR, NULL);
- g_signal_connect(G_OBJECT(renderer), "edited",
- G_CALLBACK(renderer_edited), NULL);
-
- column = gtk_tree_view_get_column(view, COL_NAME);
- gtk_tree_view_column_set_visible(column, show_name);
- column = gtk_tree_view_get_column(view, COL_NO);
- gtk_tree_view_column_set_visible(column, show_range);
- column = gtk_tree_view_get_column(view, COL_MOD);
- gtk_tree_view_column_set_visible(column, show_range);
- column = gtk_tree_view_get_column(view, COL_YES);
- gtk_tree_view_column_set_visible(column, show_range);
- column = gtk_tree_view_get_column(view, COL_VALUE);
- gtk_tree_view_column_set_visible(column, show_value);
-
- if (resizeable) {
- for (i = 0; i < COL_VALUE; i++) {
- column = gtk_tree_view_get_column(view, i);
- gtk_tree_view_column_set_resizable(column, TRUE);
+ for (struct menu *child = menu->list; child; child = child->next) {
+ if (menu_is_visible(child) && child->sym == def_sym)
+ def_menu = child;
}
- }
- sel = gtk_tree_view_get_selection(view);
- gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE);
-}
+ if (def_menu)
+ value = menu_get_prompt(def_menu);
+ goto set;
+ }
-/* Utility Functions */
+ switch (sym_get_type(sym)) {
+ case S_BOOLEAN:
+ case S_TRISTATE:
+ btnvis = TRUE;
-static void text_insert_help(struct menu *menu)
-{
- GtkTextBuffer *buffer;
- GtkTextIter start, end;
- const char *prompt = menu_get_prompt(menu);
- struct gstr help = str_new();
+ val = sym_get_tristate_value(sym);
+ switch (val) {
+ case no:
+ _no = "N";
+ value = "N";
+ break;
+ case mod:
+ _mod = "M";
+ value = "M";
+ break;
+ case yes:
+ _yes = "Y";
+ value = "Y";
+ break;
+ }
- menu_get_ext_help(menu, &help);
+ if (val != no && sym_tristate_within_range(sym, no))
+ _no = "_";
+ if (val != mod && sym_tristate_within_range(sym, mod))
+ _mod = "_";
+ if (val != yes && sym_tristate_within_range(sym, yes))
+ _yes = "_";
+ break;
+ default:
+ value = sym_get_string_value(sym);
+ editable = TRUE;
+ break;
+ }
- buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w));
- gtk_text_buffer_get_bounds(buffer, &start, &end);
- gtk_text_buffer_delete(buffer, &start, &end);
- gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_w), 15);
+set:
+ gtk_tree_store_set(tree, node,
+ COL_OPTION, option,
+ COL_NAME, sym ? sym->name : "",
+ COL_NO, _no,
+ COL_MOD, _mod,
+ COL_YES, _yes,
+ COL_VALUE, value,
+ COL_MENU, (gpointer) menu,
+ COL_COLOR, &color,
+ COL_EDIT, editable,
+ COL_PIXBUF, pix_menu,
+ COL_PIXVIS, view_mode == SINGLE_VIEW && menu->type == M_MENU,
+ COL_BTNVIS, btnvis,
+ COL_BTNACT, _yes[0] == 'Y',
+ COL_BTNINC, _mod[0] == 'M',
+ COL_BTNRAD, sym && sym_is_choice_value(sym),
+ -1);
- gtk_text_buffer_get_end_iter(buffer, &end);
- gtk_text_buffer_insert_with_tags(buffer, &end, prompt, -1, tag1,
- NULL);
- gtk_text_buffer_insert_at_cursor(buffer, "\n\n", 2);
- gtk_text_buffer_get_end_iter(buffer, &end);
- gtk_text_buffer_insert_with_tags(buffer, &end, str_get(&help), -1, tag2,
- NULL);
- str_free(&help);
+ g_free(option);
}
-
-static void text_insert_msg(const char *title, const char *message)
+static void _update_tree(GtkTreeStore *store, GtkTreeIter *parent)
{
- GtkTextBuffer *buffer;
- GtkTextIter start, end;
- const char *msg = message;
+ GtkTreeModel *model = GTK_TREE_MODEL(store);
+ GtkTreeIter iter;
+ gboolean valid;
- buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w));
- gtk_text_buffer_get_bounds(buffer, &start, &end);
- gtk_text_buffer_delete(buffer, &start, &end);
- gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_w), 15);
+ valid = gtk_tree_model_iter_children(model, &iter, parent);
+ while (valid) {
+ struct menu *menu;
- gtk_text_buffer_get_end_iter(buffer, &end);
- gtk_text_buffer_insert_with_tags(buffer, &end, title, -1, tag1,
- NULL);
- gtk_text_buffer_insert_at_cursor(buffer, "\n\n", 2);
- gtk_text_buffer_get_end_iter(buffer, &end);
- gtk_text_buffer_insert_with_tags(buffer, &end, msg, -1, tag2,
- NULL);
-}
+ gtk_tree_model_get(model, &iter, COL_MENU, &menu, -1);
+ if (menu)
+ set_node(store, &iter, menu);
-/* Main Windows Callbacks */
+ _update_tree(store, &iter);
-void on_save_activate(GtkMenuItem * menuitem, gpointer user_data);
-gboolean on_window1_delete_event(GtkWidget * widget, GdkEvent * event,
- gpointer user_data)
+ valid = gtk_tree_model_iter_next(model, &iter);
+ }
+}
+
+static void update_tree(GtkTreeStore *store)
{
- GtkWidget *dialog, *label;
- gint result;
+ _update_tree(store, NULL);
+ update_row_visibility();
+}
- if (!conf_get_changed())
- return FALSE;
+static void update_trees(void)
+{
+ if (view_mode == SPLIT_VIEW)
+ update_tree(tree1);
+ update_tree(tree2);
+}
- dialog = gtk_dialog_new_with_buttons("Warning !",
- GTK_WINDOW(main_wnd),
- (GtkDialogFlags)
- (GTK_DIALOG_MODAL |
- GTK_DIALOG_DESTROY_WITH_PARENT),
- GTK_STOCK_OK,
- GTK_RESPONSE_YES,
- GTK_STOCK_NO,
- GTK_RESPONSE_NO,
- GTK_STOCK_CANCEL,
- GTK_RESPONSE_CANCEL, NULL);
- gtk_dialog_set_default_response(GTK_DIALOG(dialog),
- GTK_RESPONSE_CANCEL);
+static void set_view_mode(enum view_mode mode)
+{
+ view_mode = mode;
- label = gtk_label_new("\nSave configuration ?\n");
- gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), label);
- gtk_widget_show(label);
+ if (mode == SPLIT_VIEW) { // two panes
+ gint w;
- result = gtk_dialog_run(GTK_DIALOG(dialog));
- switch (result) {
- case GTK_RESPONSE_YES:
- on_save_activate(NULL, NULL);
- return FALSE;
- case GTK_RESPONSE_NO:
- return FALSE;
- case GTK_RESPONSE_CANCEL:
- case GTK_RESPONSE_DELETE_EVENT:
- default:
- gtk_widget_destroy(dialog);
- return TRUE;
+ gtk_widget_show(tree1_w);
+ gtk_window_get_default_size(GTK_WINDOW(main_wnd), &w, NULL);
+ gtk_paned_set_position(GTK_PANED(hpaned), w / 2);
+ } else {
+ gtk_widget_hide(tree1_w);
+ gtk_paned_set_position(GTK_PANED(hpaned), 0);
}
- return FALSE;
-}
+ gtk_widget_set_sensitive(single_btn, TRUE);
+ gtk_widget_set_sensitive(split_btn, TRUE);
+ gtk_widget_set_sensitive(full_btn, TRUE);
+ switch (mode) {
+ case SINGLE_VIEW:
+ if (selected)
+ browsed = menu_get_parent_menu(selected) ?: &rootmenu;
+ else
+ browsed = &rootmenu;
+ recreate_tree();
+ text_insert_msg("", "");
+ select_menu(GTK_TREE_VIEW(tree2_w), selected);
+ gtk_widget_set_sensitive(single_btn, FALSE);
+ break;
+ case SPLIT_VIEW:
+ browsed = selected;
+ while (browsed && !(browsed->flags & MENU_ROOT))
+ browsed = browsed->parent;
+ gtk_tree_store_clear(tree1);
+ display_tree(tree1, &rootmenu);
+ gtk_tree_view_expand_all(GTK_TREE_VIEW(tree1_w));
+ gtk_tree_store_clear(tree2);
+ if (browsed)
+ display_tree(tree2, browsed);
+ text_insert_msg("", "");
+ select_menu(GTK_TREE_VIEW(tree1_w), browsed);
+ select_menu(GTK_TREE_VIEW(tree2_w), selected);
+ gtk_widget_set_sensitive(split_btn, FALSE);
+ break;
+ case FULL_VIEW:
+ gtk_tree_store_clear(tree2);
+ display_tree(tree2, &rootmenu);
+ text_insert_msg("", "");
+ select_menu(GTK_TREE_VIEW(tree2_w), selected);
+ gtk_widget_set_sensitive(full_btn, FALSE);
+ break;
+ }
-void on_window1_destroy(GtkObject * object, gpointer user_data)
-{
- gtk_main_quit();
+ gtk_widget_set_sensitive(back_btn,
+ mode == SINGLE_VIEW && browsed != &rootmenu);
}
+/* Menu & Toolbar Callbacks */
-void
-on_window1_size_request(GtkWidget * widget,
- GtkRequisition * requisition, gpointer user_data)
+static void on_load1_activate(GtkMenuItem *menuitem, gpointer user_data)
{
- static gint old_h;
- gint w, h;
-
- if (widget->window == NULL)
- gtk_window_get_default_size(GTK_WINDOW(main_wnd), &w, &h);
- else
- gdk_window_get_size(widget->window, &w, &h);
-
- if (h == old_h)
- return;
- old_h = h;
-
- gtk_paned_set_position(GTK_PANED(vpaned), 2 * h / 3);
-}
+ GtkWidget *dialog;
+ GtkFileChooser *chooser;
+ gint res;
+ dialog = gtk_file_chooser_dialog_new("Load file...",
+ GTK_WINDOW(user_data),
+ GTK_FILE_CHOOSER_ACTION_OPEN,
+ "_Cancel", GTK_RESPONSE_CANCEL,
+ "_Open", GTK_RESPONSE_ACCEPT,
+ NULL);
-/* Menu & Toolbar Callbacks */
+ chooser = GTK_FILE_CHOOSER(dialog);
+ gtk_file_chooser_set_filename(chooser, conf_get_configname());
+ res = gtk_dialog_run(GTK_DIALOG(dialog));
+ if (res == GTK_RESPONSE_ACCEPT) {
+ char *filename;
-static void
-load_filename(GtkFileSelection * file_selector, gpointer user_data)
-{
- const gchar *fn;
+ filename = gtk_file_chooser_get_filename(chooser);
- fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION
- (user_data));
+ if (conf_read(filename))
+ text_insert_msg("Error",
+ "Unable to load configuration!");
+ else
+ update_trees();
- if (conf_read(fn))
- text_insert_msg("Error", "Unable to load configuration !");
- else
- display_tree_part();
-}
+ g_free(filename);
+ }
-void on_load1_activate(GtkMenuItem * menuitem, gpointer user_data)
-{
- GtkWidget *fs;
-
- fs = gtk_file_selection_new("Load file...");
- g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button),
- "clicked",
- G_CALLBACK(load_filename), (gpointer) fs);
- g_signal_connect_swapped(GTK_OBJECT
- (GTK_FILE_SELECTION(fs)->ok_button),
- "clicked", G_CALLBACK(gtk_widget_destroy),
- (gpointer) fs);
- g_signal_connect_swapped(GTK_OBJECT
- (GTK_FILE_SELECTION(fs)->cancel_button),
- "clicked", G_CALLBACK(gtk_widget_destroy),
- (gpointer) fs);
- gtk_widget_show(fs);
+ gtk_widget_destroy(GTK_WIDGET(dialog));
}
-
-void on_save_activate(GtkMenuItem * menuitem, gpointer user_data)
+static void on_save_activate(GtkMenuItem *menuitem, gpointer user_data)
{
if (conf_write(NULL))
text_insert_msg("Error", "Unable to save configuration !");
conf_write_autoconf(0);
}
-
-static void
-store_filename(GtkFileSelection * file_selector, gpointer user_data)
+static void on_save_as1_activate(GtkMenuItem *menuitem, gpointer user_data)
{
- const gchar *fn;
+ GtkWidget *dialog;
+ GtkFileChooser *chooser;
+ gint res;
- fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION
- (user_data));
+ dialog = gtk_file_chooser_dialog_new("Save file as...",
+ GTK_WINDOW(user_data),
+ GTK_FILE_CHOOSER_ACTION_SAVE,
+ "_Cancel", GTK_RESPONSE_CANCEL,
+ "_Save", GTK_RESPONSE_ACCEPT,
+ NULL);
- if (conf_write(fn))
- text_insert_msg("Error", "Unable to save configuration !");
+ chooser = GTK_FILE_CHOOSER(dialog);
+ gtk_file_chooser_set_filename(chooser, conf_get_configname());
- gtk_widget_destroy(GTK_WIDGET(user_data));
-}
+ res = gtk_dialog_run(GTK_DIALOG(dialog));
+ if (res == GTK_RESPONSE_ACCEPT) {
+ char *filename;
-void on_save_as1_activate(GtkMenuItem * menuitem, gpointer user_data)
-{
- GtkWidget *fs;
-
- fs = gtk_file_selection_new("Save file as...");
- g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button),
- "clicked",
- G_CALLBACK(store_filename), (gpointer) fs);
- g_signal_connect_swapped(GTK_OBJECT
- (GTK_FILE_SELECTION(fs)->ok_button),
- "clicked", G_CALLBACK(gtk_widget_destroy),
- (gpointer) fs);
- g_signal_connect_swapped(GTK_OBJECT
- (GTK_FILE_SELECTION(fs)->cancel_button),
- "clicked", G_CALLBACK(gtk_widget_destroy),
- (gpointer) fs);
- gtk_widget_show(fs);
-}
+ filename = gtk_file_chooser_get_filename(chooser);
+ if (conf_write(filename))
+ text_insert_msg("Error",
+ "Unable to save configuration !");
-void on_quit1_activate(GtkMenuItem * menuitem, gpointer user_data)
-{
- if (!on_window1_delete_event(NULL, NULL, NULL))
- gtk_widget_destroy(GTK_WIDGET(main_wnd));
-}
+ g_free(filename);
+ }
+ gtk_widget_destroy(dialog);
+}
-void on_show_name1_activate(GtkMenuItem * menuitem, gpointer user_data)
+static void on_show_name1_activate(GtkMenuItem *menuitem, gpointer user_data)
{
GtkTreeViewColumn *col;
- show_name = GTK_CHECK_MENU_ITEM(menuitem)->active;
+ show_name = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem));
col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_NAME);
if (col)
gtk_tree_view_column_set_visible(col, show_name);
}
-
-void on_show_range1_activate(GtkMenuItem * menuitem, gpointer user_data)
+static void on_show_range1_activate(GtkMenuItem *menuitem, gpointer user_data)
{
GtkTreeViewColumn *col;
- show_range = GTK_CHECK_MENU_ITEM(menuitem)->active;
+ show_range = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem));
col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_NO);
if (col)
gtk_tree_view_column_set_visible(col, show_range);
@@ -558,46 +441,38 @@ void on_show_range1_activate(GtkMenuItem * menuitem, gpointer user_data)
}
-
-void on_show_data1_activate(GtkMenuItem * menuitem, gpointer user_data)
+static void on_show_data1_activate(GtkMenuItem *menuitem, gpointer user_data)
{
GtkTreeViewColumn *col;
- show_value = GTK_CHECK_MENU_ITEM(menuitem)->active;
+ show_value = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem));
col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_VALUE);
if (col)
gtk_tree_view_column_set_visible(col, show_value);
}
-
-void
-on_set_option_mode1_activate(GtkMenuItem *menuitem, gpointer user_data)
+static void on_set_option_mode1_activate(GtkMenuItem *menuitem,
+ gpointer user_data)
{
opt_mode = OPT_NORMAL;
- gtk_tree_store_clear(tree2);
- display_tree(&rootmenu); /* instead of update_tree to speed-up */
+ update_row_visibility();
}
-
-void
-on_set_option_mode2_activate(GtkMenuItem *menuitem, gpointer user_data)
+static void on_set_option_mode2_activate(GtkMenuItem *menuitem,
+ gpointer user_data)
{
opt_mode = OPT_ALL;
- gtk_tree_store_clear(tree2);
- display_tree(&rootmenu); /* instead of update_tree to speed-up */
+ update_row_visibility();
}
-
-void
-on_set_option_mode3_activate(GtkMenuItem *menuitem, gpointer user_data)
+static void on_set_option_mode3_activate(GtkMenuItem *menuitem,
+ gpointer user_data)
{
opt_mode = OPT_PROMPT;
- gtk_tree_store_clear(tree2);
- display_tree(&rootmenu); /* instead of update_tree to speed-up */
+ update_row_visibility();
}
-
-void on_introduction1_activate(GtkMenuItem * menuitem, gpointer user_data)
+static void on_introduction1_activate(GtkMenuItem *menuitem, gpointer user_data)
{
GtkWidget *dialog;
const gchar *intro_text =
@@ -618,14 +493,11 @@ void on_introduction1_activate(GtkMenuItem * menuitem, gpointer user_data)
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_INFO,
GTK_BUTTONS_CLOSE, "%s", intro_text);
- g_signal_connect_swapped(GTK_OBJECT(dialog), "response",
- G_CALLBACK(gtk_widget_destroy),
- GTK_OBJECT(dialog));
- gtk_widget_show_all(dialog);
+ gtk_dialog_run(GTK_DIALOG(dialog));
+ gtk_widget_destroy(dialog);
}
-
-void on_about1_activate(GtkMenuItem * menuitem, gpointer user_data)
+static void on_about1_activate(GtkMenuItem *menuitem, gpointer user_data)
{
GtkWidget *dialog;
const gchar *about_text =
@@ -635,15 +507,16 @@ void on_about1_activate(GtkMenuItem * menuitem, gpointer user_data)
dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_INFO,
- GTK_BUTTONS_CLOSE, "%s", about_text);
- g_signal_connect_swapped(GTK_OBJECT(dialog), "response",
- G_CALLBACK(gtk_widget_destroy),
- GTK_OBJECT(dialog));
- gtk_widget_show_all(dialog);
+ GTK_BUTTONS_CLOSE, "%s\nGTK version: %d.%d.%d",
+ about_text,
+ gtk_get_major_version(),
+ gtk_get_minor_version(),
+ gtk_get_micro_version());
+ gtk_dialog_run(GTK_DIALOG(dialog));
+ gtk_widget_destroy(dialog);
}
-
-void on_license1_activate(GtkMenuItem * menuitem, gpointer user_data)
+static void on_license1_activate(GtkMenuItem *menuitem, gpointer user_data)
{
GtkWidget *dialog;
const gchar *license_text =
@@ -655,81 +528,127 @@ void on_license1_activate(GtkMenuItem * menuitem, gpointer user_data)
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_INFO,
GTK_BUTTONS_CLOSE, "%s", license_text);
- g_signal_connect_swapped(GTK_OBJECT(dialog), "response",
- G_CALLBACK(gtk_widget_destroy),
- GTK_OBJECT(dialog));
- gtk_widget_show_all(dialog);
+ gtk_dialog_run(GTK_DIALOG(dialog));
+ gtk_widget_destroy(dialog);
}
-
-void on_back_clicked(GtkButton * button, gpointer user_data)
+/* toolbar handlers */
+static void on_back_clicked(GtkButton *button, gpointer user_data)
{
- enum prop_type ptype;
+ browsed = menu_get_parent_menu(browsed) ?: &rootmenu;
- current = current->parent;
- ptype = current->prompt ? current->prompt->type : P_UNKNOWN;
- if (ptype != P_MENU)
- current = current->parent;
- display_tree_part();
+ recreate_tree();
- if (current == &rootmenu)
+ if (browsed == &rootmenu)
gtk_widget_set_sensitive(back_btn, FALSE);
}
-
-void on_load_clicked(GtkButton * button, gpointer user_data)
+static void on_load_clicked(GtkButton *button, gpointer user_data)
{
on_load1_activate(NULL, user_data);
}
-
-void on_single_clicked(GtkButton * button, gpointer user_data)
+static void on_save_clicked(GtkButton *button, gpointer user_data)
{
- view_mode = SINGLE_VIEW;
- gtk_widget_hide(tree1_w);
- current = &rootmenu;
- display_tree_part();
+ on_save_activate(NULL, user_data);
}
+static void on_single_clicked(GtkButton *button, gpointer user_data)
+{
+ set_view_mode(SINGLE_VIEW);
+}
-void on_split_clicked(GtkButton * button, gpointer user_data)
+static void on_split_clicked(GtkButton *button, gpointer user_data)
{
- gint w, h;
- view_mode = SPLIT_VIEW;
- gtk_widget_show(tree1_w);
- gtk_window_get_default_size(GTK_WINDOW(main_wnd), &w, &h);
- gtk_paned_set_position(GTK_PANED(hpaned), w / 2);
- if (tree2)
- gtk_tree_store_clear(tree2);
- display_list();
+ set_view_mode(SPLIT_VIEW);
+}
- /* Disable back btn, like in full mode. */
- gtk_widget_set_sensitive(back_btn, FALSE);
+static void on_full_clicked(GtkButton *button, gpointer user_data)
+{
+ set_view_mode(FULL_VIEW);
}
+static void on_collapse_clicked(GtkButton *button, gpointer user_data)
+{
+ gtk_tree_view_collapse_all(GTK_TREE_VIEW(tree2_w));
+}
-void on_full_clicked(GtkButton * button, gpointer user_data)
+static void on_expand_clicked(GtkButton *button, gpointer user_data)
{
- view_mode = FULL_VIEW;
- gtk_widget_hide(tree1_w);
- if (tree2)
- gtk_tree_store_clear(tree2);
- display_tree(&rootmenu);
- gtk_widget_set_sensitive(back_btn, FALSE);
+ gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w));
}
+/* Main Windows Callbacks */
-void on_collapse_clicked(GtkButton * button, gpointer user_data)
+static void on_window1_destroy(GtkWidget *widget, gpointer user_data)
{
- gtk_tree_view_collapse_all(GTK_TREE_VIEW(tree2_w));
+ gtk_main_quit();
}
+static gboolean on_window1_configure(GtkWidget *self,
+ GdkEventConfigure *event,
+ gpointer user_data)
+{
+ gtk_paned_set_position(GTK_PANED(vpaned), 2 * event->height / 3);
+ return FALSE;
+}
-void on_expand_clicked(GtkButton * button, gpointer user_data)
+static gboolean on_window1_delete_event(GtkWidget *widget, GdkEvent *event,
+ gpointer user_data)
{
- gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w));
+ GtkWidget *dialog, *label, *content_area;
+ gint result;
+ gint ret = FALSE;
+
+ if (!conf_get_changed())
+ return FALSE;
+
+ dialog = gtk_dialog_new_with_buttons("Warning !",
+ GTK_WINDOW(main_wnd),
+ (GtkDialogFlags)
+ (GTK_DIALOG_MODAL |
+ GTK_DIALOG_DESTROY_WITH_PARENT),
+ "_OK",
+ GTK_RESPONSE_YES,
+ "_No",
+ GTK_RESPONSE_NO,
+ "_Cancel",
+ GTK_RESPONSE_CANCEL, NULL);
+ gtk_dialog_set_default_response(GTK_DIALOG(dialog),
+ GTK_RESPONSE_CANCEL);
+
+ label = gtk_label_new("\nSave configuration ?\n");
+ content_area = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
+ gtk_container_add(GTK_CONTAINER(content_area), label);
+ gtk_widget_show(label);
+
+ result = gtk_dialog_run(GTK_DIALOG(dialog));
+ switch (result) {
+ case GTK_RESPONSE_YES:
+ on_save_activate(NULL, NULL);
+ break;
+ case GTK_RESPONSE_NO:
+ break;
+ case GTK_RESPONSE_CANCEL:
+ case GTK_RESPONSE_DELETE_EVENT:
+ default:
+ ret = TRUE;
+ break;
+ }
+
+ gtk_widget_destroy(dialog);
+
+ if (!ret)
+ g_object_unref(pix_menu);
+
+ return ret;
}
+static void on_quit1_activate(GtkMenuItem *menuitem, gpointer user_data)
+{
+ if (!on_window1_delete_event(NULL, NULL, NULL))
+ gtk_widget_destroy(GTK_WIDGET(main_wnd));
+}
/* CTree Callbacks */
@@ -738,25 +657,28 @@ static void renderer_edited(GtkCellRendererText * cell,
const gchar * path_string,
const gchar * new_text, gpointer user_data)
{
+ GtkTreeView *view = GTK_TREE_VIEW(user_data);
+ GtkTreeModel *model = gtk_tree_view_get_model(view);
GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
GtkTreeIter iter;
const char *old_def, *new_def;
struct menu *menu;
struct symbol *sym;
- if (!gtk_tree_model_get_iter(model2, &iter, path))
- return;
+ if (!gtk_tree_model_get_iter(model, &iter, path))
+ goto free;
- gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
+ gtk_tree_model_get(model, &iter, COL_MENU, &menu, -1);
sym = menu->sym;
- gtk_tree_model_get(model2, &iter, COL_VALUE, &old_def, -1);
+ gtk_tree_model_get(model, &iter, COL_VALUE, &old_def, -1);
new_def = new_text;
sym_set_string_value(sym, new_def);
- update_tree(&rootmenu, NULL);
+ update_trees();
+free:
gtk_tree_path_free(path);
}
@@ -784,14 +706,7 @@ static void change_sym_value(struct menu *menu, gint col)
if (!sym_tristate_within_range(sym, newval))
newval = yes;
sym_set_tristate_value(sym, newval);
- if (view_mode == FULL_VIEW)
- update_tree(&rootmenu, NULL);
- else if (view_mode == SPLIT_VIEW) {
- update_tree(browsed, NULL);
- display_list();
- }
- else if (view_mode == SINGLE_VIEW)
- display_tree_part(); //fixme: keep exp/coll
+ update_trees();
break;
case S_INT:
case S_HEX:
@@ -807,14 +722,7 @@ static void toggle_sym_value(struct menu *menu)
return;
sym_toggle_tristate_value(menu->sym);
- if (view_mode == FULL_VIEW)
- update_tree(&rootmenu, NULL);
- else if (view_mode == SPLIT_VIEW) {
- update_tree(browsed, NULL);
- display_list();
- }
- else if (view_mode == SINGLE_VIEW)
- display_tree_part(); //fixme: keep exp/coll
+ update_trees();
}
static gint column2index(GtkTreeViewColumn * column)
@@ -834,43 +742,39 @@ static gint column2index(GtkTreeViewColumn * column)
/* User click: update choice (full) or goes down (single) */
-gboolean
-on_treeview2_button_press_event(GtkWidget * widget,
- GdkEventButton * event, gpointer user_data)
+static gboolean on_treeview2_button_press_event(GtkWidget *widget,
+ GdkEventButton *event,
+ gpointer user_data)
{
GtkTreeView *view = GTK_TREE_VIEW(widget);
+ GtkTreeModel *model = gtk_tree_view_get_model(view);
GtkTreePath *path;
GtkTreeViewColumn *column;
GtkTreeIter iter;
struct menu *menu;
gint col;
-
-#if GTK_CHECK_VERSION(2,1,4) // bug in ctree with earlier version of GTK
gint tx = (gint) event->x;
gint ty = (gint) event->y;
- gint cx, cy;
- gtk_tree_view_get_path_at_pos(view, tx, ty, &path, &column, &cx,
- &cy);
-#else
- gtk_tree_view_get_cursor(view, &path, &column);
-#endif
+ gtk_tree_view_get_path_at_pos(view, tx, ty, &path, &column, NULL, NULL);
if (path == NULL)
return FALSE;
- if (!gtk_tree_model_get_iter(model2, &iter, path))
+ if (!gtk_tree_model_get_iter(model, &iter, path))
return FALSE;
- gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
+ gtk_tree_model_get(model, &iter, COL_MENU, &menu, -1);
+
+ selected = menu;
col = column2index(column);
if (event->type == GDK_2BUTTON_PRESS) {
enum prop_type ptype;
ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
- if (ptype == P_MENU && view_mode != FULL_VIEW && col == COL_OPTION) {
+ if (ptype == P_MENU && view_mode == SINGLE_VIEW && col == COL_OPTION) {
// goes down into menu
- current = menu;
- display_tree_part();
+ browsed = menu;
+ recreate_tree();
gtk_widget_set_sensitive(back_btn, TRUE);
} else if (col == COL_OPTION) {
toggle_sym_value(menu);
@@ -891,35 +795,31 @@ on_treeview2_button_press_event(GtkWidget * widget,
}
/* Key pressed: update choice */
-gboolean
-on_treeview2_key_press_event(GtkWidget * widget,
- GdkEventKey * event, gpointer user_data)
+static gboolean on_treeview2_key_press_event(GtkWidget *widget,
+ GdkEventKey *event,
+ gpointer user_data)
{
GtkTreeView *view = GTK_TREE_VIEW(widget);
+ GtkTreeModel *model = gtk_tree_view_get_model(view);
GtkTreePath *path;
- GtkTreeViewColumn *column;
GtkTreeIter iter;
struct menu *menu;
gint col;
- gtk_tree_view_get_cursor(view, &path, &column);
+ gtk_tree_view_get_cursor(view, &path, NULL);
if (path == NULL)
return FALSE;
- if (event->keyval == GDK_space) {
+ if (event->keyval == GDK_KEY_space) {
if (gtk_tree_view_row_expanded(view, path))
gtk_tree_view_collapse_row(view, path);
else
gtk_tree_view_expand_row(view, path, FALSE);
return TRUE;
}
- if (event->keyval == GDK_KP_Enter) {
- }
- if (widget == tree1_w)
- return FALSE;
- gtk_tree_model_get_iter(model2, &iter, path);
- gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
+ gtk_tree_model_get_iter(model, &iter, path);
+ gtk_tree_model_get(model, &iter, COL_MENU, &menu, -1);
if (!strcasecmp(event->string, "n"))
col = COL_NO;
@@ -936,450 +836,449 @@ on_treeview2_key_press_event(GtkWidget * widget,
/* Row selection changed: update help */
-void
-on_treeview2_cursor_changed(GtkTreeView * treeview, gpointer user_data)
+static void on_treeview2_cursor_changed(GtkTreeView *treeview,
+ gpointer user_data)
{
+ GtkTreeModel *model = gtk_tree_view_get_model(treeview);
GtkTreeSelection *selection;
GtkTreeIter iter;
struct menu *menu;
selection = gtk_tree_view_get_selection(treeview);
- if (gtk_tree_selection_get_selected(selection, &model2, &iter)) {
- gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
+ if (gtk_tree_selection_get_selected(selection, &model, &iter)) {
+ gtk_tree_model_get(model, &iter, COL_MENU, &menu, -1);
text_insert_help(menu);
}
}
/* User click: display sub-tree in the right frame. */
-gboolean
-on_treeview1_button_press_event(GtkWidget * widget,
- GdkEventButton * event, gpointer user_data)
+static gboolean on_treeview1_button_press_event(GtkWidget *widget,
+ GdkEventButton *event,
+ gpointer user_data)
{
GtkTreeView *view = GTK_TREE_VIEW(widget);
+ GtkTreeModel *model = gtk_tree_view_get_model(view);
GtkTreePath *path;
- GtkTreeViewColumn *column;
GtkTreeIter iter;
struct menu *menu;
-
gint tx = (gint) event->x;
gint ty = (gint) event->y;
- gint cx, cy;
- gtk_tree_view_get_path_at_pos(view, tx, ty, &path, &column, &cx,
- &cy);
+ gtk_tree_view_get_path_at_pos(view, tx, ty, &path, NULL, NULL, NULL);
if (path == NULL)
return FALSE;
- gtk_tree_model_get_iter(model1, &iter, path);
- gtk_tree_model_get(model1, &iter, COL_MENU, &menu, -1);
+ gtk_tree_model_get_iter(model, &iter, path);
+ gtk_tree_model_get(model, &iter, COL_MENU, &menu, -1);
- if (event->type == GDK_2BUTTON_PRESS) {
+ if (event->type == GDK_2BUTTON_PRESS)
toggle_sym_value(menu);
- current = menu;
- display_tree_part();
- } else {
+
+ selected = menu;
+
+ if (menu->type == M_MENU) {
browsed = menu;
- display_tree_part();
+ recreate_tree();
}
- gtk_widget_realize(tree2_w);
gtk_tree_view_set_cursor(view, path, NULL, FALSE);
gtk_widget_grab_focus(tree2_w);
return FALSE;
}
-
-/* Fill a row of strings */
-static gchar **fill_row(struct menu *menu)
+/* Display the whole tree (single/split/full view) */
+static void _display_tree(GtkTreeStore *tree, struct menu *menu,
+ GtkTreeIter *parent)
{
- static gchar *row[COL_NUMBER];
- struct symbol *sym = menu->sym;
- const char *def;
- int stype;
- tristate val;
- enum prop_type ptype;
- int i;
-
- for (i = COL_OPTION; i <= COL_COLOR; i++)
- g_free(row[i]);
- bzero(row, sizeof(row));
-
- ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
-
- row[COL_OPTION] =
- g_strdup_printf("%s %s %s %s",
- ptype == P_COMMENT ? "***" : "",
- menu_get_prompt(menu),
- ptype == P_COMMENT ? "***" : "",
- sym && !sym_has_value(sym) ? "(NEW)" : "");
-
- if (opt_mode == OPT_ALL && !menu_is_visible(menu))
- row[COL_COLOR] = g_strdup("DarkGray");
- else if (opt_mode == OPT_PROMPT &&
- menu_has_prompt(menu) && !menu_is_visible(menu))
- row[COL_COLOR] = g_strdup("DarkGray");
- else
- row[COL_COLOR] = g_strdup("Black");
-
- switch (ptype) {
- case P_MENU:
- row[COL_PIXBUF] = (gchar *) xpm_menu;
- if (view_mode == SINGLE_VIEW)
- row[COL_PIXVIS] = GINT_TO_POINTER(TRUE);
- row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
- break;
- case P_COMMENT:
- row[COL_PIXBUF] = (gchar *) xpm_void;
- row[COL_PIXVIS] = GINT_TO_POINTER(FALSE);
- row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
- break;
- default:
- row[COL_PIXBUF] = (gchar *) xpm_void;
- row[COL_PIXVIS] = GINT_TO_POINTER(FALSE);
- row[COL_BTNVIS] = GINT_TO_POINTER(TRUE);
- break;
- }
-
- if (!sym)
- return row;
- row[COL_NAME] = g_strdup(sym->name);
-
- sym_calc_value(sym);
- menu->flags &= ~MENU_CHANGED;
-
- if (sym_is_choice(sym)) { // parse childs for getting final value
- struct menu *child;
- struct symbol *def_sym = sym_get_choice_value(sym);
- struct menu *def_menu = NULL;
+ struct menu *child;
+ GtkTreeIter iter;
- for (child = menu->list; child; child = child->next) {
- if (menu_is_visible(child)
- && child->sym == def_sym)
- def_menu = child;
- }
+ for (child = menu->list; child; child = child->next) {
+ /*
+ * REVISIT:
+ * menu_finalize() creates empty "if" entries.
+ * Do not confuse gtk_tree_model_get(), which would otherwise
+ * return "if" menu entry.
+ */
+ if (child->type == M_IF)
+ continue;
- if (def_menu)
- row[COL_VALUE] =
- g_strdup(menu_get_prompt(def_menu));
+ if ((view_mode == SPLIT_VIEW)
+ && !(child->flags & MENU_ROOT) && (tree == tree1))
+ continue;
- if (sym_get_type(sym) == S_BOOLEAN) {
- row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
- return row;
- }
- }
- if (sym->flags & SYMBOL_CHOICEVAL)
- row[COL_BTNRAD] = GINT_TO_POINTER(TRUE);
+ if ((view_mode == SPLIT_VIEW) && (child->flags & MENU_ROOT)
+ && (tree == tree2))
+ continue;
- stype = sym_get_type(sym);
- switch (stype) {
- case S_BOOLEAN:
- case S_TRISTATE:
- val = sym_get_tristate_value(sym);
- switch (val) {
- case no:
- row[COL_NO] = g_strdup("N");
- row[COL_VALUE] = g_strdup("N");
- row[COL_BTNACT] = GINT_TO_POINTER(FALSE);
- row[COL_BTNINC] = GINT_TO_POINTER(FALSE);
- break;
- case mod:
- row[COL_MOD] = g_strdup("M");
- row[COL_VALUE] = g_strdup("M");
- row[COL_BTNINC] = GINT_TO_POINTER(TRUE);
- break;
- case yes:
- row[COL_YES] = g_strdup("Y");
- row[COL_VALUE] = g_strdup("Y");
- row[COL_BTNACT] = GINT_TO_POINTER(TRUE);
- row[COL_BTNINC] = GINT_TO_POINTER(FALSE);
- break;
- }
+ gtk_tree_store_append(tree, &iter, parent);
+ set_node(tree, &iter, child);
- if (val != no && sym_tristate_within_range(sym, no))
- row[COL_NO] = g_strdup("_");
- if (val != mod && sym_tristate_within_range(sym, mod))
- row[COL_MOD] = g_strdup("_");
- if (val != yes && sym_tristate_within_range(sym, yes))
- row[COL_YES] = g_strdup("_");
- break;
- case S_INT:
- case S_HEX:
- case S_STRING:
- def = sym_get_string_value(sym);
- row[COL_VALUE] = g_strdup(def);
- row[COL_EDIT] = GINT_TO_POINTER(TRUE);
- row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
- break;
+ if (view_mode != SINGLE_VIEW || child->type != M_MENU)
+ _display_tree(tree, child, &iter);
}
+}
- return row;
+static void display_tree(GtkTreeStore *store, struct menu *menu)
+{
+ _display_tree(store, menu, NULL);
}
+/* Recreate the tree store starting at 'browsed' node */
+static void recreate_tree(void)
+{
+ gtk_tree_store_clear(tree2);
+ display_tree(tree2, browsed);
+ gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w));
+}
-/* Set the node content with a row of strings */
-static void set_node(GtkTreeIter * node, struct menu *menu, gchar ** row)
+static void fixup_rootmenu(struct menu *menu)
{
- GdkColor color;
- gboolean success;
- GdkPixbuf *pix;
+ struct menu *child;
+ static int menu_cnt = 0;
- pix = gdk_pixbuf_new_from_xpm_data((const char **)
- row[COL_PIXBUF]);
+ menu->flags |= MENU_ROOT;
+ for (child = menu->list; child; child = child->next) {
+ if (child->prompt && child->prompt->type == P_MENU) {
+ menu_cnt++;
+ fixup_rootmenu(child);
+ menu_cnt--;
+ } else if (!menu_cnt)
+ fixup_rootmenu(child);
+ }
+}
- gdk_color_parse(row[COL_COLOR], &color);
- gdk_colormap_alloc_colors(gdk_colormap_get_system(), &color, 1,
- FALSE, FALSE, &success);
+/* Main Window Initialization */
+static void replace_button_icon(GtkWidget *widget, const char * const xpm[])
+{
+ GdkPixbuf *pixbuf;
+ GtkWidget *image;
- gtk_tree_store_set(tree, node,
- COL_OPTION, row[COL_OPTION],
- COL_NAME, row[COL_NAME],
- COL_NO, row[COL_NO],
- COL_MOD, row[COL_MOD],
- COL_YES, row[COL_YES],
- COL_VALUE, row[COL_VALUE],
- COL_MENU, (gpointer) menu,
- COL_COLOR, &color,
- COL_EDIT, GPOINTER_TO_INT(row[COL_EDIT]),
- COL_PIXBUF, pix,
- COL_PIXVIS, GPOINTER_TO_INT(row[COL_PIXVIS]),
- COL_BTNVIS, GPOINTER_TO_INT(row[COL_BTNVIS]),
- COL_BTNACT, GPOINTER_TO_INT(row[COL_BTNACT]),
- COL_BTNINC, GPOINTER_TO_INT(row[COL_BTNINC]),
- COL_BTNRAD, GPOINTER_TO_INT(row[COL_BTNRAD]),
- -1);
+ pixbuf = gdk_pixbuf_new_from_xpm_data((const char **)xpm);
+ image = gtk_image_new_from_pixbuf(pixbuf);
+ g_object_unref(pixbuf);
- g_object_unref(pix);
+ gtk_widget_show(image);
+ gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(widget), image);
}
-
-/* Add a node to the tree */
-static void place_node(struct menu *menu, char **row)
+static void init_main_window(const gchar *glade_file)
{
- GtkTreeIter *parent = parents[indent - 1];
- GtkTreeIter *node = parents[indent];
+ GtkBuilder *builder;
+ GtkWidget *widget;
+ GtkTextBuffer *txtbuf;
- gtk_tree_store_append(tree, node, parent);
- set_node(node, menu, row);
-}
+ builder = gtk_builder_new_from_file(glade_file);
+ if (!builder)
+ g_error("GUI loading failed !\n");
+ main_wnd = GTK_WIDGET(gtk_builder_get_object(builder, "window1"));
+ g_signal_connect(main_wnd, "destroy",
+ G_CALLBACK(on_window1_destroy), NULL);
+ g_signal_connect(main_wnd, "configure-event",
+ G_CALLBACK(on_window1_configure), NULL);
+ g_signal_connect(main_wnd, "delete-event",
+ G_CALLBACK(on_window1_delete_event), NULL);
+
+ hpaned = GTK_WIDGET(gtk_builder_get_object(builder, "hpaned1"));
+ vpaned = GTK_WIDGET(gtk_builder_get_object(builder, "vpaned1"));
+ tree1_w = GTK_WIDGET(gtk_builder_get_object(builder, "treeview1"));
+ g_signal_connect(tree1_w, "cursor-changed",
+ G_CALLBACK(on_treeview2_cursor_changed), NULL);
+ g_signal_connect(tree1_w, "button-press-event",
+ G_CALLBACK(on_treeview1_button_press_event), NULL);
+ g_signal_connect(tree1_w, "key-press-event",
+ G_CALLBACK(on_treeview2_key_press_event), NULL);
+
+ tree2_w = GTK_WIDGET(gtk_builder_get_object(builder, "treeview2"));
+ g_signal_connect(tree2_w, "cursor-changed",
+ G_CALLBACK(on_treeview2_cursor_changed), NULL);
+ g_signal_connect(tree2_w, "button-press-event",
+ G_CALLBACK(on_treeview2_button_press_event), NULL);
+ g_signal_connect(tree2_w, "key-press-event",
+ G_CALLBACK(on_treeview2_key_press_event), NULL);
+
+ text_w = GTK_WIDGET(gtk_builder_get_object(builder, "textview3"));
+
+ /* menubar */
+ widget = GTK_WIDGET(gtk_builder_get_object(builder, "load1"));
+ g_signal_connect(widget, "activate",
+ G_CALLBACK(on_load1_activate), NULL);
+
+ save_menu_item = GTK_WIDGET(gtk_builder_get_object(builder, "save1"));
+ g_signal_connect(save_menu_item, "activate",
+ G_CALLBACK(on_save_activate), NULL);
+
+ widget = GTK_WIDGET(gtk_builder_get_object(builder, "save_as1"));
+ g_signal_connect(widget, "activate",
+ G_CALLBACK(on_save_as1_activate), NULL);
+
+ widget = GTK_WIDGET(gtk_builder_get_object(builder, "quit1"));
+ g_signal_connect(widget, "activate",
+ G_CALLBACK(on_quit1_activate), NULL);
+
+ widget = GTK_WIDGET(gtk_builder_get_object(builder, "show_name1"));
+ g_signal_connect(widget, "activate",
+ G_CALLBACK(on_show_name1_activate), NULL);
+ gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,
+ show_name);
-/* Find a node in the GTK+ tree */
-static GtkTreeIter found;
+ widget = GTK_WIDGET(gtk_builder_get_object(builder, "show_range1"));
+ g_signal_connect(widget, "activate",
+ G_CALLBACK(on_show_range1_activate), NULL);
+ gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,
+ show_range);
-/*
- * Find a menu in the GtkTree starting at parent.
- */
-static GtkTreeIter *gtktree_iter_find_node(GtkTreeIter *parent,
- struct menu *tofind)
-{
- GtkTreeIter iter;
- GtkTreeIter *child = &iter;
- gboolean valid;
- GtkTreeIter *ret;
+ widget = GTK_WIDGET(gtk_builder_get_object(builder, "show_data1"));
+ g_signal_connect(widget, "activate",
+ G_CALLBACK(on_show_data1_activate), NULL);
+ gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,
+ show_value);
- valid = gtk_tree_model_iter_children(model2, child, parent);
- while (valid) {
- struct menu *menu;
+ widget = GTK_WIDGET(gtk_builder_get_object(builder, "set_option_mode1"));
+ g_signal_connect(widget, "activate",
+ G_CALLBACK(on_set_option_mode1_activate), NULL);
- gtk_tree_model_get(model2, child, 6, &menu, -1);
+ widget = GTK_WIDGET(gtk_builder_get_object(builder, "set_option_mode2"));
+ g_signal_connect(widget, "activate",
+ G_CALLBACK(on_set_option_mode2_activate), NULL);
- if (menu == tofind) {
- memcpy(&found, child, sizeof(GtkTreeIter));
- return &found;
- }
+ widget = GTK_WIDGET(gtk_builder_get_object(builder, "set_option_mode3"));
+ g_signal_connect(widget, "activate",
+ G_CALLBACK(on_set_option_mode3_activate), NULL);
- ret = gtktree_iter_find_node(child, tofind);
- if (ret)
- return ret;
+ widget = GTK_WIDGET(gtk_builder_get_object(builder, "introduction1"));
+ g_signal_connect(widget, "activate",
+ G_CALLBACK(on_introduction1_activate), NULL);
- valid = gtk_tree_model_iter_next(model2, child);
- }
+ widget = GTK_WIDGET(gtk_builder_get_object(builder, "about1"));
+ g_signal_connect(widget, "activate",
+ G_CALLBACK(on_about1_activate), NULL);
- return NULL;
-}
+ widget = GTK_WIDGET(gtk_builder_get_object(builder, "license1"));
+ g_signal_connect(widget, "activate",
+ G_CALLBACK(on_license1_activate), NULL);
+ /* toolbar */
+ back_btn = GTK_WIDGET(gtk_builder_get_object(builder, "button1"));
+ g_signal_connect(back_btn, "clicked",
+ G_CALLBACK(on_back_clicked), NULL);
+ gtk_widget_set_sensitive(back_btn, FALSE);
-/*
- * Update the tree by adding/removing entries
- * Does not change other nodes
- */
-static void update_tree(struct menu *src, GtkTreeIter * dst)
-{
- struct menu *child1;
- GtkTreeIter iter, tmp;
- GtkTreeIter *child2 = &iter;
- gboolean valid;
- GtkTreeIter *sibling;
- struct symbol *sym;
- struct menu *menu1, *menu2;
+ widget = GTK_WIDGET(gtk_builder_get_object(builder, "button2"));
+ g_signal_connect(widget, "clicked",
+ G_CALLBACK(on_load_clicked), NULL);
- if (src == &rootmenu)
- indent = 1;
+ save_btn = GTK_WIDGET(gtk_builder_get_object(builder, "button3"));
+ g_signal_connect(save_btn, "clicked",
+ G_CALLBACK(on_save_clicked), NULL);
- valid = gtk_tree_model_iter_children(model2, child2, dst);
- for (child1 = src->list; child1; child1 = child1->next) {
+ single_btn = GTK_WIDGET(gtk_builder_get_object(builder, "button4"));
+ g_signal_connect(single_btn, "clicked",
+ G_CALLBACK(on_single_clicked), NULL);
+ replace_button_icon(single_btn, xpm_single_view);
- sym = child1->sym;
+ split_btn = GTK_WIDGET(gtk_builder_get_object(builder, "button5"));
+ g_signal_connect(split_btn, "clicked",
+ G_CALLBACK(on_split_clicked), NULL);
+ replace_button_icon(split_btn, xpm_split_view);
- reparse:
- menu1 = child1;
- if (valid)
- gtk_tree_model_get(model2, child2, COL_MENU,
- &menu2, -1);
- else
- menu2 = NULL; // force adding of a first child
-
- if ((opt_mode == OPT_NORMAL && !menu_is_visible(child1)) ||
- (opt_mode == OPT_PROMPT && !menu_has_prompt(child1)) ||
- (opt_mode == OPT_ALL && !menu_get_prompt(child1))) {
-
- /* remove node */
- if (gtktree_iter_find_node(dst, menu1) != NULL) {
- memcpy(&tmp, child2, sizeof(GtkTreeIter));
- valid = gtk_tree_model_iter_next(model2,
- child2);
- gtk_tree_store_remove(tree2, &tmp);
- if (!valid)
- return; /* next parent */
- else
- goto reparse; /* next child */
- } else
- continue;
- }
+ full_btn = GTK_WIDGET(gtk_builder_get_object(builder, "button6"));
+ g_signal_connect(full_btn, "clicked",
+ G_CALLBACK(on_full_clicked), NULL);
+ replace_button_icon(full_btn, xpm_tree_view);
- if (menu1 != menu2) {
- if (gtktree_iter_find_node(dst, menu1) == NULL) { // add node
- if (!valid && !menu2)
- sibling = NULL;
- else
- sibling = child2;
- gtk_tree_store_insert_before(tree2,
- child2,
- dst, sibling);
- set_node(child2, menu1, fill_row(menu1));
- if (menu2 == NULL)
- valid = TRUE;
- } else { // remove node
- memcpy(&tmp, child2, sizeof(GtkTreeIter));
- valid = gtk_tree_model_iter_next(model2,
- child2);
- gtk_tree_store_remove(tree2, &tmp);
- if (!valid)
- return; // next parent
- else
- goto reparse; // next child
- }
- } else if (sym && (child1->flags & MENU_CHANGED)) {
- set_node(child2, menu1, fill_row(menu1));
- }
+ widget = GTK_WIDGET(gtk_builder_get_object(builder, "button7"));
+ g_signal_connect(widget, "clicked",
+ G_CALLBACK(on_collapse_clicked), NULL);
- indent++;
- update_tree(child1, child2);
- indent--;
+ widget = GTK_WIDGET(gtk_builder_get_object(builder, "button8"));
+ g_signal_connect(widget, "clicked",
+ G_CALLBACK(on_expand_clicked), NULL);
- valid = gtk_tree_model_iter_next(model2, child2);
- }
-}
+ txtbuf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w));
+ tag1 = gtk_text_buffer_create_tag(txtbuf, "mytag1",
+ "foreground", "red",
+ "weight", PANGO_WEIGHT_BOLD,
+ NULL);
+ tag2 = gtk_text_buffer_create_tag(txtbuf, "mytag2",
+ /*"style", PANGO_STYLE_OBLIQUE, */
+ NULL);
+ gtk_window_set_title(GTK_WINDOW(main_wnd), rootmenu.prompt->text);
-/* Display the whole tree (single/split/full view) */
-static void display_tree(struct menu *menu)
+ gtk_widget_show_all(main_wnd);
+
+ g_object_unref(builder);
+
+ conf_set_changed_callback(conf_changed);
+}
+
+static gboolean visible_func(GtkTreeModel *model, GtkTreeIter *iter,
+ gpointer data)
{
- struct property *prop;
- struct menu *child;
- enum prop_type ptype;
+ struct menu *menu;
- if (menu == &rootmenu) {
- indent = 1;
- current = &rootmenu;
- }
+ gtk_tree_model_get(model, iter, COL_MENU, &menu, -1);
- for (child = menu->list; child; child = child->next) {
- prop = child->prompt;
- ptype = prop ? prop->type : P_UNKNOWN;
+ if (!menu)
+ return FALSE;
- menu->flags &= ~MENU_CHANGED;
+ return menu_is_visible(menu) || opt_mode == OPT_ALL ||
+ (opt_mode == OPT_PROMPT && menu_has_prompt(menu));
+}
- if ((view_mode == SPLIT_VIEW)
- && !(child->flags & MENU_ROOT) && (tree == tree1))
- continue;
+static void init_left_tree(void)
+{
+ GtkTreeView *view = GTK_TREE_VIEW(tree1_w);
+ GtkCellRenderer *renderer;
+ GtkTreeSelection *sel;
+ GtkTreeViewColumn *column;
+ GtkTreeModel *filter;
- if ((view_mode == SPLIT_VIEW) && (child->flags & MENU_ROOT)
- && (tree == tree2))
- continue;
+ tree1 = gtk_tree_store_new(COL_NUMBER,
+ G_TYPE_STRING, G_TYPE_STRING,
+ G_TYPE_STRING, G_TYPE_STRING,
+ G_TYPE_STRING, G_TYPE_STRING,
+ G_TYPE_POINTER, GDK_TYPE_RGBA,
+ G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF,
+ G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
+ G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
+ G_TYPE_BOOLEAN);
- if ((opt_mode == OPT_NORMAL && menu_is_visible(child)) ||
- (opt_mode == OPT_PROMPT && menu_has_prompt(child)) ||
- (opt_mode == OPT_ALL && menu_get_prompt(child)))
- place_node(child, fill_row(child));
+ filter = gtk_tree_model_filter_new(GTK_TREE_MODEL(tree1), NULL);
- if ((view_mode != FULL_VIEW) && (ptype == P_MENU)
- && (tree == tree2))
- continue;
-/*
- if (((menu != &rootmenu) && !(menu->flags & MENU_ROOT))
- || (view_mode == FULL_VIEW)
- || (view_mode == SPLIT_VIEW))*/
+ gtk_tree_model_filter_set_visible_func(GTK_TREE_MODEL_FILTER(filter),
+ visible_func, NULL, NULL);
+ gtk_tree_view_set_model(view, filter);
- /* Change paned position if the view is not in 'split mode' */
- if (view_mode == SINGLE_VIEW || view_mode == FULL_VIEW) {
- gtk_paned_set_position(GTK_PANED(hpaned), 0);
- }
+ column = gtk_tree_view_column_new();
+ gtk_tree_view_append_column(view, column);
+ gtk_tree_view_column_set_title(column, "Options");
- if (((view_mode == SINGLE_VIEW) && (menu->flags & MENU_ROOT))
- || (view_mode == FULL_VIEW)
- || (view_mode == SPLIT_VIEW)) {
- indent++;
- display_tree(child);
- indent--;
- }
- }
-}
+ renderer = gtk_cell_renderer_toggle_new();
+ gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
+ renderer, FALSE);
+ gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
+ renderer,
+ "active", COL_BTNACT,
+ "inconsistent", COL_BTNINC,
+ "visible", COL_BTNVIS,
+ "radio", COL_BTNRAD, NULL);
+ renderer = gtk_cell_renderer_text_new();
+ gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
+ renderer, FALSE);
+ gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
+ renderer,
+ "text", COL_OPTION,
+ "foreground-rgba",
+ COL_COLOR, NULL);
-/* Display a part of the tree starting at current node (single/split view) */
-static void display_tree_part(void)
-{
- if (tree2)
- gtk_tree_store_clear(tree2);
- if (view_mode == SINGLE_VIEW)
- display_tree(current);
- else if (view_mode == SPLIT_VIEW)
- display_tree(browsed);
- else if (view_mode == FULL_VIEW)
- display_tree(&rootmenu);
- gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w));
+ sel = gtk_tree_view_get_selection(view);
+ gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE);
}
-/* Display the list in the left frame (split view) */
-static void display_list(void)
+static void init_right_tree(void)
{
- if (tree1)
- gtk_tree_store_clear(tree1);
+ GtkTreeView *view = GTK_TREE_VIEW(tree2_w);
+ GtkCellRenderer *renderer;
+ GtkTreeSelection *sel;
+ GtkTreeViewColumn *column;
+ GtkTreeModel *filter;
+ gint i;
- tree = tree1;
- display_tree(&rootmenu);
- gtk_tree_view_expand_all(GTK_TREE_VIEW(tree1_w));
- tree = tree2;
-}
+ tree2 = gtk_tree_store_new(COL_NUMBER,
+ G_TYPE_STRING, G_TYPE_STRING,
+ G_TYPE_STRING, G_TYPE_STRING,
+ G_TYPE_STRING, G_TYPE_STRING,
+ G_TYPE_POINTER, GDK_TYPE_RGBA,
+ G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF,
+ G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
+ G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
+ G_TYPE_BOOLEAN);
-static void fixup_rootmenu(struct menu *menu)
-{
- struct menu *child;
- static int menu_cnt = 0;
+ filter = gtk_tree_model_filter_new(GTK_TREE_MODEL(tree2), NULL);
- menu->flags |= MENU_ROOT;
- for (child = menu->list; child; child = child->next) {
- if (child->prompt && child->prompt->type == P_MENU) {
- menu_cnt++;
- fixup_rootmenu(child);
- menu_cnt--;
- } else if (!menu_cnt)
- fixup_rootmenu(child);
+ gtk_tree_model_filter_set_visible_func(GTK_TREE_MODEL_FILTER(filter),
+ visible_func, NULL, NULL);
+ gtk_tree_view_set_model(view, filter);
+
+ column = gtk_tree_view_column_new();
+ gtk_tree_view_append_column(view, column);
+ gtk_tree_view_column_set_title(column, "Options");
+
+ renderer = gtk_cell_renderer_pixbuf_new();
+ gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
+ renderer, FALSE);
+ gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
+ renderer,
+ "pixbuf", COL_PIXBUF,
+ "visible", COL_PIXVIS, NULL);
+ renderer = gtk_cell_renderer_toggle_new();
+ gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
+ renderer, FALSE);
+ gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
+ renderer,
+ "active", COL_BTNACT,
+ "inconsistent", COL_BTNINC,
+ "visible", COL_BTNVIS,
+ "radio", COL_BTNRAD, NULL);
+ renderer = gtk_cell_renderer_text_new();
+ gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
+ renderer, FALSE);
+ gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
+ renderer,
+ "text", COL_OPTION,
+ "foreground-rgba",
+ COL_COLOR, NULL);
+
+ renderer = gtk_cell_renderer_text_new();
+ gtk_tree_view_insert_column_with_attributes(view, -1,
+ "Name", renderer,
+ "text", COL_NAME,
+ "foreground-rgba",
+ COL_COLOR, NULL);
+ renderer = gtk_cell_renderer_text_new();
+ gtk_tree_view_insert_column_with_attributes(view, -1,
+ "N", renderer,
+ "text", COL_NO,
+ "foreground-rgba",
+ COL_COLOR, NULL);
+ renderer = gtk_cell_renderer_text_new();
+ gtk_tree_view_insert_column_with_attributes(view, -1,
+ "M", renderer,
+ "text", COL_MOD,
+ "foreground-rgba",
+ COL_COLOR, NULL);
+ renderer = gtk_cell_renderer_text_new();
+ gtk_tree_view_insert_column_with_attributes(view, -1,
+ "Y", renderer,
+ "text", COL_YES,
+ "foreground-rgba",
+ COL_COLOR, NULL);
+ renderer = gtk_cell_renderer_text_new();
+ gtk_tree_view_insert_column_with_attributes(view, -1,
+ "Value", renderer,
+ "text", COL_VALUE,
+ "editable",
+ COL_EDIT,
+ "foreground-rgba",
+ COL_COLOR, NULL);
+ g_signal_connect(G_OBJECT(renderer), "edited",
+ G_CALLBACK(renderer_edited), tree2_w);
+
+ pix_menu = gdk_pixbuf_new_from_xpm_data((const char **)xpm_menu);
+
+ for (i = 0; i < COL_VALUE; i++) {
+ column = gtk_tree_view_get_column(view, i);
+ gtk_tree_view_column_set_resizable(column, TRUE);
}
-}
+ sel = gtk_tree_view_get_selection(view);
+ gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE);
+}
/* Main */
int main(int ac, char *av[])
@@ -1389,18 +1288,16 @@ int main(int ac, char *av[])
gchar *glade_file;
/* GTK stuffs */
- gtk_set_locale();
gtk_init(&ac, &av);
- glade_init();
/* Determine GUI path */
env = getenv(SRCTREE);
if (env)
- glade_file = g_strconcat(env, "/scripts/kconfig/gconf.glade", NULL);
+ glade_file = g_strconcat(env, "/scripts/kconfig/gconf.ui", NULL);
else if (av[0][0] == '/')
- glade_file = g_strconcat(av[0], ".glade", NULL);
+ glade_file = g_strconcat(av[0], ".ui", NULL);
else
- glade_file = g_strconcat(g_get_current_dir(), "/", av[0], ".glade", NULL);
+ glade_file = g_strconcat(g_get_current_dir(), "/", av[0], ".ui", NULL);
/* Conf stuffs */
if (ac > 1 && av[1][0] == '-') {
@@ -1425,32 +1322,14 @@ int main(int ac, char *av[])
/* Load the interface and connect signals */
init_main_window(glade_file);
- init_tree_model();
init_left_tree();
init_right_tree();
conf_read(NULL);
- switch (view_mode) {
- case SINGLE_VIEW:
- display_tree_part();
- break;
- case SPLIT_VIEW:
- display_list();
- break;
- case FULL_VIEW:
- display_tree(&rootmenu);
- break;
- }
+ set_view_mode(view_mode);
gtk_main();
return 0;
}
-
-static void conf_changed(void)
-{
- bool changed = conf_get_changed();
- gtk_widget_set_sensitive(save_btn, changed);
- gtk_widget_set_sensitive(save_menu_item, changed);
-}
diff --git a/scripts/kconfig/gconf.glade b/scripts/kconfig/gconf.ui
index aa483cb32755..ab4431255fa7 100644
--- a/scripts/kconfig/gconf.glade
+++ b/scripts/kconfig/gconf.ui
@@ -1,8 +1,8 @@
<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
-<glade-interface>
+<interface>
-<widget class="GtkWindow" id="window1">
+<object class="GtkWindow" id="window1">
<property name="visible">True</property>
<property name="title" translatable="yes">Gtk Kernel Configurator</property>
<property name="type">GTK_WINDOW_TOPLEVEL</property>
@@ -17,295 +17,196 @@
<property name="skip_pager_hint">False</property>
<property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property>
<property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
- <signal name="destroy" handler="on_window1_destroy" object="window1"/>
- <signal name="size_request" handler="on_window1_size_request" object="vpaned1" last_modification_time="Fri, 11 Jan 2002 16:17:11 GMT"/>
- <signal name="delete_event" handler="on_window1_delete_event" object="window1" last_modification_time="Sun, 09 Mar 2003 19:42:46 GMT"/>
<child>
- <widget class="GtkVBox" id="vbox1">
+ <object class="GtkBox" id="vbox1">
+ <property name="orientation">vertical</property>
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">0</property>
<child>
- <widget class="GtkMenuBar" id="menubar1">
+ <object class="GtkMenuBar" id="menubar1">
<property name="visible">True</property>
<child>
- <widget class="GtkMenuItem" id="file1">
+ <object class="GtkMenuItem" id="file1">
<property name="visible">True</property>
<property name="label" translatable="yes">_File</property>
<property name="use_underline">True</property>
- <child>
- <widget class="GtkMenu" id="file1_menu">
+ <child type="submenu">
+ <object class="GtkMenu" id="file1_menu">
<child>
- <widget class="GtkImageMenuItem" id="load1">
+ <object class="GtkMenuItem" id="load1">
<property name="visible">True</property>
- <property name="tooltip" translatable="yes">Load a config file</property>
+ <property name="tooltip-text" translatable="yes">Load a config file</property>
<property name="label" translatable="yes">_Load</property>
<property name="use_underline">True</property>
- <signal name="activate" handler="on_load1_activate"/>
<accelerator key="L" modifiers="GDK_CONTROL_MASK" signal="activate"/>
-
- <child internal-child="image">
- <widget class="GtkImage" id="image39">
- <property name="visible">True</property>
- <property name="stock">gtk-open</property>
- <property name="icon_size">1</property>
- <property name="xalign">0.5</property>
- <property name="yalign">0.5</property>
- <property name="xpad">0</property>
- <property name="ypad">0</property>
- </widget>
- </child>
- </widget>
+ </object>
</child>
<child>
- <widget class="GtkImageMenuItem" id="save1">
+ <object class="GtkMenuItem" id="save1">
<property name="visible">True</property>
- <property name="tooltip" translatable="yes">Save the config in .config</property>
+ <property name="tooltip-text" translatable="yes">Save the config in .config</property>
<property name="label" translatable="yes">_Save</property>
<property name="use_underline">True</property>
- <signal name="activate" handler="on_save_activate"/>
<accelerator key="S" modifiers="GDK_CONTROL_MASK" signal="activate"/>
-
- <child internal-child="image">
- <widget class="GtkImage" id="image40">
- <property name="visible">True</property>
- <property name="stock">gtk-save</property>
- <property name="icon_size">1</property>
- <property name="xalign">0.5</property>
- <property name="yalign">0.5</property>
- <property name="xpad">0</property>
- <property name="ypad">0</property>
- </widget>
- </child>
- </widget>
+ </object>
</child>
<child>
- <widget class="GtkImageMenuItem" id="save_as1">
+ <object class="GtkMenuItem" id="save_as1">
<property name="visible">True</property>
- <property name="tooltip" translatable="yes">Save the config in a file</property>
+ <property name="tooltip-text" translatable="yes">Save the config in a file</property>
<property name="label" translatable="yes">Save _as</property>
<property name="use_underline">True</property>
- <signal name="activate" handler="on_save_as1_activate"/>
-
- <child internal-child="image">
- <widget class="GtkImage" id="image41">
- <property name="visible">True</property>
- <property name="stock">gtk-save-as</property>
- <property name="icon_size">1</property>
- <property name="xalign">0.5</property>
- <property name="yalign">0.5</property>
- <property name="xpad">0</property>
- <property name="ypad">0</property>
- </widget>
- </child>
- </widget>
+ </object>
</child>
<child>
- <widget class="GtkSeparatorMenuItem" id="separator1">
+ <object class="GtkSeparatorMenuItem" id="separator1">
<property name="visible">True</property>
- </widget>
+ </object>
</child>
<child>
- <widget class="GtkImageMenuItem" id="quit1">
+ <object class="GtkMenuItem" id="quit1">
<property name="visible">True</property>
<property name="label" translatable="yes">_Quit</property>
<property name="use_underline">True</property>
- <signal name="activate" handler="on_quit1_activate"/>
<accelerator key="Q" modifiers="GDK_CONTROL_MASK" signal="activate"/>
-
- <child internal-child="image">
- <widget class="GtkImage" id="image42">
- <property name="visible">True</property>
- <property name="stock">gtk-quit</property>
- <property name="icon_size">1</property>
- <property name="xalign">0.5</property>
- <property name="yalign">0.5</property>
- <property name="xpad">0</property>
- <property name="ypad">0</property>
- </widget>
- </child>
- </widget>
+ </object>
</child>
- </widget>
+ </object>
</child>
- </widget>
+ </object>
</child>
<child>
- <widget class="GtkMenuItem" id="options1">
+ <object class="GtkMenuItem" id="options1">
<property name="visible">True</property>
<property name="label" translatable="yes">_Options</property>
<property name="use_underline">True</property>
- <child>
- <widget class="GtkMenu" id="options1_menu">
+ <child type="submenu">
+ <object class="GtkMenu" id="options1_menu">
<child>
- <widget class="GtkCheckMenuItem" id="show_name1">
+ <object class="GtkCheckMenuItem" id="show_name1">
<property name="visible">True</property>
- <property name="tooltip" translatable="yes">Show name</property>
+ <property name="tooltip-text" translatable="yes">Show name</property>
<property name="label" translatable="yes">Show _name</property>
<property name="use_underline">True</property>
<property name="active">False</property>
- <signal name="activate" handler="on_show_name1_activate"/>
- </widget>
+ </object>
</child>
<child>
- <widget class="GtkCheckMenuItem" id="show_range1">
+ <object class="GtkCheckMenuItem" id="show_range1">
<property name="visible">True</property>
- <property name="tooltip" translatable="yes">Show range (Y/M/N)</property>
+ <property name="tooltip-text" translatable="yes">Show range (Y/M/N)</property>
<property name="label" translatable="yes">Show _range</property>
<property name="use_underline">True</property>
<property name="active">False</property>
- <signal name="activate" handler="on_show_range1_activate"/>
- </widget>
+ </object>
</child>
<child>
- <widget class="GtkCheckMenuItem" id="show_data1">
+ <object class="GtkCheckMenuItem" id="show_data1">
<property name="visible">True</property>
- <property name="tooltip" translatable="yes">Show value of the option</property>
+ <property name="tooltip-text" translatable="yes">Show value of the option</property>
<property name="label" translatable="yes">Show _data</property>
<property name="use_underline">True</property>
<property name="active">False</property>
- <signal name="activate" handler="on_show_data1_activate"/>
- </widget>
+ </object>
</child>
<child>
- <widget class="GtkSeparatorMenuItem" id="separator2">
+ <object class="GtkSeparatorMenuItem" id="separator2">
<property name="visible">True</property>
- </widget>
+ </object>
</child>
<child>
- <widget class="GtkRadioMenuItem" id="set_option_mode1">
+ <object class="GtkRadioMenuItem" id="set_option_mode1">
<property name="visible">True</property>
- <property name="tooltip" translatable="yes">Show normal options</property>
+ <property name="tooltip-text" translatable="yes">Show normal options</property>
<property name="label" translatable="yes">Show normal options</property>
<property name="use_underline">True</property>
<property name="active">True</property>
- <signal name="activate" handler="on_set_option_mode1_activate"/>
- </widget>
+ </object>
</child>
<child>
- <widget class="GtkRadioMenuItem" id="set_option_mode2">
+ <object class="GtkRadioMenuItem" id="set_option_mode2">
<property name="visible">True</property>
- <property name="tooltip" translatable="yes">Show all options</property>
+ <property name="tooltip-text" translatable="yes">Show all options</property>
<property name="label" translatable="yes">Show all _options</property>
<property name="use_underline">True</property>
<property name="active">False</property>
<property name="group">set_option_mode1</property>
- <signal name="activate" handler="on_set_option_mode2_activate"/>
- </widget>
+ </object>
</child>
<child>
- <widget class="GtkRadioMenuItem" id="set_option_mode3">
+ <object class="GtkRadioMenuItem" id="set_option_mode3">
<property name="visible">True</property>
- <property name="tooltip" translatable="yes">Show all options with prompts</property>
+ <property name="tooltip-text" translatable="yes">Show all options with prompts</property>
<property name="label" translatable="yes">Show all prompt options</property>
<property name="use_underline">True</property>
<property name="active">False</property>
<property name="group">set_option_mode1</property>
- <signal name="activate" handler="on_set_option_mode3_activate"/>
- </widget>
+ </object>
</child>
- </widget>
+ </object>
</child>
- </widget>
+ </object>
</child>
<child>
- <widget class="GtkMenuItem" id="help1">
+ <object class="GtkMenuItem" id="help1">
<property name="visible">True</property>
<property name="label" translatable="yes">_Help</property>
<property name="use_underline">True</property>
- <child>
- <widget class="GtkMenu" id="help1_menu">
+ <child type="submenu">
+ <object class="GtkMenu" id="help1_menu">
<child>
- <widget class="GtkImageMenuItem" id="introduction1">
+ <object class="GtkMenuItem" id="introduction1">
<property name="visible">True</property>
<property name="label" translatable="yes">_Introduction</property>
<property name="use_underline">True</property>
- <signal name="activate" handler="on_introduction1_activate" last_modification_time="Fri, 15 Nov 2002 20:26:30 GMT"/>
<accelerator key="I" modifiers="GDK_CONTROL_MASK" signal="activate"/>
-
- <child internal-child="image">
- <widget class="GtkImage" id="image43">
- <property name="visible">True</property>
- <property name="stock">gtk-dialog-question</property>
- <property name="icon_size">1</property>
- <property name="xalign">0.5</property>
- <property name="yalign">0.5</property>
- <property name="xpad">0</property>
- <property name="ypad">0</property>
- </widget>
- </child>
- </widget>
+ </object>
</child>
<child>
- <widget class="GtkImageMenuItem" id="about1">
+ <object class="GtkMenuItem" id="about1">
<property name="visible">True</property>
<property name="label" translatable="yes">_About</property>
<property name="use_underline">True</property>
- <signal name="activate" handler="on_about1_activate" last_modification_time="Fri, 15 Nov 2002 20:26:30 GMT"/>
<accelerator key="A" modifiers="GDK_CONTROL_MASK" signal="activate"/>
-
- <child internal-child="image">
- <widget class="GtkImage" id="image44">
- <property name="visible">True</property>
- <property name="stock">gtk-properties</property>
- <property name="icon_size">1</property>
- <property name="xalign">0.5</property>
- <property name="yalign">0.5</property>
- <property name="xpad">0</property>
- <property name="ypad">0</property>
- </widget>
- </child>
- </widget>
+ </object>
</child>
<child>
- <widget class="GtkImageMenuItem" id="license1">
+ <object class="GtkMenuItem" id="license1">
<property name="visible">True</property>
<property name="label" translatable="yes">_License</property>
<property name="use_underline">True</property>
- <signal name="activate" handler="on_license1_activate" last_modification_time="Fri, 15 Nov 2002 20:26:30 GMT"/>
-
- <child internal-child="image">
- <widget class="GtkImage" id="image45">
- <property name="visible">True</property>
- <property name="stock">gtk-justify-fill</property>
- <property name="icon_size">1</property>
- <property name="xalign">0.5</property>
- <property name="yalign">0.5</property>
- <property name="xpad">0</property>
- <property name="ypad">0</property>
- </widget>
- </child>
- </widget>
+ </object>
</child>
- </widget>
+ </object>
</child>
- </widget>
+ </object>
</child>
- </widget>
+ </object>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
@@ -314,32 +215,23 @@
</child>
<child>
- <widget class="GtkHandleBox" id="handlebox1">
- <property name="visible">True</property>
- <property name="shadow_type">GTK_SHADOW_OUT</property>
- <property name="handle_position">GTK_POS_LEFT</property>
- <property name="snap_edge">GTK_POS_TOP</property>
-
- <child>
- <widget class="GtkToolbar" id="toolbar1">
+ <object class="GtkToolbar" id="toolbar1">
<property name="visible">True</property>
<property name="orientation">GTK_ORIENTATION_HORIZONTAL</property>
<property name="toolbar_style">GTK_TOOLBAR_BOTH</property>
- <property name="tooltips">True</property>
<property name="show_arrow">True</property>
<child>
- <widget class="GtkToolButton" id="button1">
+ <object class="GtkToolButton" id="button1">
<property name="visible">True</property>
- <property name="tooltip" translatable="yes">Goes up of one level (single view)</property>
+ <property name="tooltip-text" translatable="yes">Goes up one level (single view)</property>
<property name="label" translatable="yes">Back</property>
<property name="use_underline">True</property>
<property name="stock_id">gtk-undo</property>
<property name="visible_horizontal">True</property>
<property name="visible_vertical">True</property>
<property name="is_important">False</property>
- <signal name="clicked" handler="on_back_clicked"/>
- </widget>
+ </object>
<packing>
<property name="expand">False</property>
<property name="homogeneous">True</property>
@@ -347,18 +239,18 @@
</child>
<child>
- <widget class="GtkToolItem" id="toolitem1">
+ <object class="GtkToolItem" id="toolitem1">
<property name="visible">True</property>
<property name="visible_horizontal">True</property>
<property name="visible_vertical">True</property>
<property name="is_important">False</property>
<child>
- <widget class="GtkVSeparator" id="vseparator1">
+ <object class="GtkVSeparator" id="vseparator1">
<property name="visible">True</property>
- </widget>
+ </object>
</child>
- </widget>
+ </object>
<packing>
<property name="expand">False</property>
<property name="homogeneous">False</property>
@@ -366,17 +258,16 @@
</child>
<child>
- <widget class="GtkToolButton" id="button2">
+ <object class="GtkToolButton" id="button2">
<property name="visible">True</property>
- <property name="tooltip" translatable="yes">Load a config file</property>
+ <property name="tooltip-text" translatable="yes">Load a config file</property>
<property name="label" translatable="yes">Load</property>
<property name="use_underline">True</property>
<property name="stock_id">gtk-open</property>
<property name="visible_horizontal">True</property>
<property name="visible_vertical">True</property>
<property name="is_important">False</property>
- <signal name="clicked" handler="on_load_clicked"/>
- </widget>
+ </object>
<packing>
<property name="expand">False</property>
<property name="homogeneous">True</property>
@@ -384,17 +275,16 @@
</child>
<child>
- <widget class="GtkToolButton" id="button3">
+ <object class="GtkToolButton" id="button3">
<property name="visible">True</property>
- <property name="tooltip" translatable="yes">Save a config file</property>
+ <property name="tooltip-text" translatable="yes">Save a config file</property>
<property name="label" translatable="yes">Save</property>
<property name="use_underline">True</property>
<property name="stock_id">gtk-save</property>
<property name="visible_horizontal">True</property>
<property name="visible_vertical">True</property>
<property name="is_important">False</property>
- <signal name="clicked" handler="on_save_activate"/>
- </widget>
+ </object>
<packing>
<property name="expand">False</property>
<property name="homogeneous">True</property>
@@ -402,18 +292,18 @@
</child>
<child>
- <widget class="GtkToolItem" id="toolitem2">
+ <object class="GtkToolItem" id="toolitem2">
<property name="visible">True</property>
<property name="visible_horizontal">True</property>
<property name="visible_vertical">True</property>
<property name="is_important">False</property>
<child>
- <widget class="GtkVSeparator" id="vseparator2">
+ <object class="GtkVSeparator" id="vseparator2">
<property name="visible">True</property>
- </widget>
+ </object>
</child>
- </widget>
+ </object>
<packing>
<property name="expand">False</property>
<property name="homogeneous">False</property>
@@ -421,17 +311,16 @@
</child>
<child>
- <widget class="GtkToolButton" id="button4">
+ <object class="GtkToolButton" id="button4">
<property name="visible">True</property>
- <property name="tooltip" translatable="yes">Single view</property>
+ <property name="tooltip-text" translatable="yes">Single view</property>
<property name="label" translatable="yes">Single</property>
<property name="use_underline">True</property>
<property name="stock_id">gtk-missing-image</property>
<property name="visible_horizontal">True</property>
<property name="visible_vertical">True</property>
<property name="is_important">False</property>
- <signal name="clicked" handler="on_single_clicked" last_modification_time="Sun, 12 Jan 2003 14:28:39 GMT"/>
- </widget>
+ </object>
<packing>
<property name="expand">False</property>
<property name="homogeneous">True</property>
@@ -439,17 +328,16 @@
</child>
<child>
- <widget class="GtkToolButton" id="button5">
+ <object class="GtkToolButton" id="button5">
<property name="visible">True</property>
- <property name="tooltip" translatable="yes">Split view</property>
+ <property name="tooltip-text" translatable="yes">Split view</property>
<property name="label" translatable="yes">Split</property>
<property name="use_underline">True</property>
<property name="stock_id">gtk-missing-image</property>
<property name="visible_horizontal">True</property>
<property name="visible_vertical">True</property>
<property name="is_important">False</property>
- <signal name="clicked" handler="on_split_clicked" last_modification_time="Sun, 12 Jan 2003 14:28:45 GMT"/>
- </widget>
+ </object>
<packing>
<property name="expand">False</property>
<property name="homogeneous">True</property>
@@ -457,17 +345,16 @@
</child>
<child>
- <widget class="GtkToolButton" id="button6">
+ <object class="GtkToolButton" id="button6">
<property name="visible">True</property>
- <property name="tooltip" translatable="yes">Full view</property>
+ <property name="tooltip-text" translatable="yes">Full view</property>
<property name="label" translatable="yes">Full</property>
<property name="use_underline">True</property>
<property name="stock_id">gtk-missing-image</property>
<property name="visible_horizontal">True</property>
<property name="visible_vertical">True</property>
<property name="is_important">False</property>
- <signal name="clicked" handler="on_full_clicked" last_modification_time="Sun, 12 Jan 2003 14:28:50 GMT"/>
- </widget>
+ </object>
<packing>
<property name="expand">False</property>
<property name="homogeneous">True</property>
@@ -475,18 +362,18 @@
</child>
<child>
- <widget class="GtkToolItem" id="toolitem3">
+ <object class="GtkToolItem" id="toolitem3">
<property name="visible">True</property>
<property name="visible_horizontal">True</property>
<property name="visible_vertical">True</property>
<property name="is_important">False</property>
<child>
- <widget class="GtkVSeparator" id="vseparator3">
+ <object class="GtkVSeparator" id="vseparator3">
<property name="visible">True</property>
- </widget>
+ </object>
</child>
- </widget>
+ </object>
<packing>
<property name="expand">False</property>
<property name="homogeneous">False</property>
@@ -494,17 +381,16 @@
</child>
<child>
- <widget class="GtkToolButton" id="button7">
+ <object class="GtkToolButton" id="button7">
<property name="visible">True</property>
- <property name="tooltip" translatable="yes">Collapse the whole tree in the right frame</property>
+ <property name="tooltip-text" translatable="yes">Collapse the whole tree in the right frame</property>
<property name="label" translatable="yes">Collapse</property>
<property name="use_underline">True</property>
<property name="stock_id">gtk-remove</property>
<property name="visible_horizontal">True</property>
<property name="visible_vertical">True</property>
<property name="is_important">False</property>
- <signal name="clicked" handler="on_collapse_clicked"/>
- </widget>
+ </object>
<packing>
<property name="expand">False</property>
<property name="homogeneous">True</property>
@@ -512,25 +398,22 @@
</child>
<child>
- <widget class="GtkToolButton" id="button8">
+ <object class="GtkToolButton" id="button8">
<property name="visible">True</property>
- <property name="tooltip" translatable="yes">Expand the whole tree in the right frame</property>
+ <property name="tooltip-text" translatable="yes">Expand the whole tree in the right frame</property>
<property name="label" translatable="yes">Expand</property>
<property name="use_underline">True</property>
<property name="stock_id">gtk-add</property>
<property name="visible_horizontal">True</property>
<property name="visible_vertical">True</property>
<property name="is_important">False</property>
- <signal name="clicked" handler="on_expand_clicked"/>
- </widget>
+ </object>
<packing>
<property name="expand">False</property>
<property name="homogeneous">True</property>
</packing>
</child>
- </widget>
- </child>
- </widget>
+ </object>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
@@ -539,14 +422,13 @@
</child>
<child>
- <widget class="GtkHPaned" id="hpaned1">
+ <object class="GtkPaned" id="hpaned1">
<property name="width_request">1</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
- <property name="position">0</property>
<child>
- <widget class="GtkScrolledWindow" id="scrolledwindow1">
+ <object class="GtkScrolledWindow" id="scrolledwindow1">
<property name="visible">True</property>
<property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
@@ -554,19 +436,16 @@
<property name="window_placement">GTK_CORNER_TOP_LEFT</property>
<child>
- <widget class="GtkTreeView" id="treeview1">
+ <object class="GtkTreeView" id="treeview1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="headers_visible">True</property>
<property name="rules_hint">False</property>
<property name="reorderable">False</property>
<property name="enable_search">False</property>
- <signal name="cursor_changed" handler="on_treeview2_cursor_changed" last_modification_time="Sun, 12 Jan 2003 15:58:22 GMT"/>
- <signal name="button_press_event" handler="on_treeview1_button_press_event" last_modification_time="Sun, 12 Jan 2003 16:03:52 GMT"/>
- <signal name="key_press_event" handler="on_treeview2_key_press_event" last_modification_time="Sun, 12 Jan 2003 16:11:44 GMT"/>
- </widget>
+ </object>
</child>
- </widget>
+ </object>
<packing>
<property name="shrink">True</property>
<property name="resize">False</property>
@@ -574,13 +453,13 @@
</child>
<child>
- <widget class="GtkVPaned" id="vpaned1">
+ <object class="GtkPaned" id="vpaned1">
+ <property name="orientation">vertical</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
- <property name="position">0</property>
<child>
- <widget class="GtkScrolledWindow" id="scrolledwindow2">
+ <object class="GtkScrolledWindow" id="scrolledwindow2">
<property name="visible">True</property>
<property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
@@ -588,7 +467,7 @@
<property name="window_placement">GTK_CORNER_TOP_LEFT</property>
<child>
- <widget class="GtkTreeView" id="treeview2">
+ <object class="GtkTreeView" id="treeview2">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="has_focus">True</property>
@@ -596,12 +475,9 @@
<property name="rules_hint">False</property>
<property name="reorderable">False</property>
<property name="enable_search">False</property>
- <signal name="cursor_changed" handler="on_treeview2_cursor_changed" last_modification_time="Sun, 12 Jan 2003 15:57:55 GMT"/>
- <signal name="button_press_event" handler="on_treeview2_button_press_event" last_modification_time="Sun, 12 Jan 2003 15:57:58 GMT"/>
- <signal name="key_press_event" handler="on_treeview2_key_press_event" last_modification_time="Sun, 12 Jan 2003 15:58:01 GMT"/>
- </widget>
+ </object>
</child>
- </widget>
+ </object>
<packing>
<property name="shrink">True</property>
<property name="resize">False</property>
@@ -609,7 +485,7 @@
</child>
<child>
- <widget class="GtkScrolledWindow" id="scrolledwindow3">
+ <object class="GtkScrolledWindow" id="scrolledwindow3">
<property name="visible">True</property>
<property name="hscrollbar_policy">GTK_POLICY_NEVER</property>
<property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
@@ -617,7 +493,7 @@
<property name="window_placement">GTK_CORNER_TOP_LEFT</property>
<child>
- <widget class="GtkTextView" id="textview3">
+ <object class="GtkTextView" id="textview3">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="editable">False</property>
@@ -632,30 +508,29 @@
<property name="left_margin">0</property>
<property name="right_margin">0</property>
<property name="indent">0</property>
- <property name="text" translatable="yes">Sorry, no help available for this option yet.</property>
- </widget>
+ </object>
</child>
- </widget>
+ </object>
<packing>
<property name="shrink">True</property>
<property name="resize">True</property>
</packing>
</child>
- </widget>
+ </object>
<packing>
<property name="shrink">True</property>
<property name="resize">True</property>
</packing>
</child>
- </widget>
+ </object>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
- </widget>
+ </object>
</child>
-</widget>
+</object>
-</glade-interface>
+</interface>
diff --git a/scripts/kconfig/hashtable.h b/scripts/kconfig/hashtable.h
deleted file mode 100644
index a0a2c8f5f639..000000000000
--- a/scripts/kconfig/hashtable.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-#ifndef HASHTABLE_H
-#define HASHTABLE_H
-
-#include "array_size.h"
-#include "list.h"
-
-#define HASH_SIZE(name) (ARRAY_SIZE(name))
-
-#define HASHTABLE_DECLARE(name, size) struct hlist_head name[size]
-
-#define HASHTABLE_DEFINE(name, size) \
- HASHTABLE_DECLARE(name, size) = \
- { [0 ... ((size) - 1)] = HLIST_HEAD_INIT }
-
-#define hash_head(table, key) (&(table)[(key) % HASH_SIZE(table)])
-
-/**
- * hash_add - add an object to a hashtable
- * @table: hashtable to add to
- * @node: the &struct hlist_node of the object to be added
- * @key: the key of the object to be added
- */
-#define hash_add(table, node, key) \
- hlist_add_head(node, hash_head(table, key))
-
-/**
- * hash_for_each - iterate over a hashtable
- * @table: hashtable to iterate
- * @obj: the type * to use as a loop cursor for each entry
- * @member: the name of the hlist_node within the struct
- */
-#define hash_for_each(table, obj, member) \
- for (int _bkt = 0; _bkt < HASH_SIZE(table); _bkt++) \
- hlist_for_each_entry(obj, &table[_bkt], member)
-
-/**
- * hash_for_each_possible - iterate over all possible objects hashing to the
- * same bucket
- * @table: hashtable to iterate
- * @obj: the type * to use as a loop cursor for each entry
- * @member: the name of the hlist_node within the struct
- * @key: the key of the objects to iterate over
- */
-#define hash_for_each_possible(table, obj, member, key) \
- hlist_for_each_entry(obj, hash_head(table, key), member)
-
-#endif /* HASHTABLE_H */
diff --git a/scripts/kconfig/internal.h b/scripts/kconfig/internal.h
index 6c721c4cfd72..d0ffce2dfbba 100644
--- a/scripts/kconfig/internal.h
+++ b/scripts/kconfig/internal.h
@@ -2,7 +2,7 @@
#ifndef INTERNAL_H
#define INTERNAL_H
-#include "hashtable.h"
+#include <hashtable.h>
#define SYMBOL_HASHSIZE (1U << 14)
@@ -11,6 +11,12 @@ extern HASHTABLE_DECLARE(sym_hashtable, SYMBOL_HASHSIZE);
#define for_all_symbols(sym) \
hash_for_each(sym_hashtable, sym, node)
+#define EXPR_HASHSIZE (1U << 14)
+
+extern HASHTABLE_DECLARE(expr_hashtable, EXPR_HASHSIZE);
+
+void expr_invalidate_all(void);
+
struct menu;
extern struct menu *current_menu, *current_entry;
diff --git a/scripts/kconfig/lexer.l b/scripts/kconfig/lexer.l
index 8dd597c4710d..6d2c92c6095d 100644
--- a/scripts/kconfig/lexer.l
+++ b/scripts/kconfig/lexer.l
@@ -13,6 +13,7 @@
#include <stdlib.h>
#include <string.h>
+#include <xalloc.h>
#include "lkc.h"
#include "preprocess.h"
@@ -125,6 +126,7 @@ n [A-Za-z0-9_-]
"select" return T_SELECT;
"source" return T_SOURCE;
"string" return T_STRING;
+"transitional" return T_TRANSITIONAL;
"tristate" return T_TRISTATE;
"visible" return T_VISIBLE;
"||" return T_OR;
diff --git a/scripts/kconfig/list.h b/scripts/kconfig/list.h
deleted file mode 100644
index 882859ddf9f4..000000000000
--- a/scripts/kconfig/list.h
+++ /dev/null
@@ -1,256 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef LIST_H
-#define LIST_H
-
-#include <stddef.h>
-
-#include "list_types.h"
-
-/* Are two types/vars the same type (ignoring qualifiers)? */
-#define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
-
-/**
- * container_of - cast a member of a structure out to the containing structure
- * @ptr: the pointer to the member.
- * @type: the type of the container struct this is embedded in.
- * @member: the name of the member within the struct.
- *
- */
-#define container_of(ptr, type, member) ({ \
- void *__mptr = (void *)(ptr); \
- _Static_assert(__same_type(*(ptr), ((type *)0)->member) || \
- __same_type(*(ptr), void), \
- "pointer type mismatch in container_of()"); \
- ((type *)(__mptr - offsetof(type, member))); })
-
-#define LIST_POISON1 ((void *) 0x100)
-#define LIST_POISON2 ((void *) 0x122)
-
-/*
- * Circular doubly linked list implementation.
- *
- * Some of the internal functions ("__xxx") are useful when
- * manipulating whole lists rather than single entries, as
- * sometimes we already know the next/prev entries and we can
- * generate better code by using them directly rather than
- * using the generic single-entry routines.
- */
-
-#define LIST_HEAD_INIT(name) { &(name), &(name) }
-
-#define LIST_HEAD(name) \
- struct list_head name = LIST_HEAD_INIT(name)
-
-/**
- * INIT_LIST_HEAD - Initialize a list_head structure
- * @list: list_head structure to be initialized.
- *
- * Initializes the list_head to point to itself. If it is a list header,
- * the result is an empty list.
- */
-static inline void INIT_LIST_HEAD(struct list_head *list)
-{
- list->next = list;
- list->prev = list;
-}
-
-/*
- * Insert a new entry between two known consecutive entries.
- *
- * This is only for internal list manipulation where we know
- * the prev/next entries already!
- */
-static inline void __list_add(struct list_head *new,
- struct list_head *prev,
- struct list_head *next)
-{
- next->prev = new;
- new->next = next;
- new->prev = prev;
- prev->next = new;
-}
-
-/**
- * list_add - add a new entry
- * @new: new entry to be added
- * @head: list head to add it after
- *
- * Insert a new entry after the specified head.
- * This is good for implementing stacks.
- */
-static inline void list_add(struct list_head *new, struct list_head *head)
-{
- __list_add(new, head, head->next);
-}
-
-/**
- * list_add_tail - add a new entry
- * @new: new entry to be added
- * @head: list head to add it before
- *
- * Insert a new entry before the specified head.
- * This is useful for implementing queues.
- */
-static inline void list_add_tail(struct list_head *new, struct list_head *head)
-{
- __list_add(new, head->prev, head);
-}
-
-/*
- * Delete a list entry by making the prev/next entries
- * point to each other.
- *
- * This is only for internal list manipulation where we know
- * the prev/next entries already!
- */
-static inline void __list_del(struct list_head *prev, struct list_head *next)
-{
- next->prev = prev;
- prev->next = next;
-}
-
-static inline void __list_del_entry(struct list_head *entry)
-{
- __list_del(entry->prev, entry->next);
-}
-
-/**
- * list_del - deletes entry from list.
- * @entry: the element to delete from the list.
- * Note: list_empty() on entry does not return true after this, the entry is
- * in an undefined state.
- */
-static inline void list_del(struct list_head *entry)
-{
- __list_del_entry(entry);
- entry->next = LIST_POISON1;
- entry->prev = LIST_POISON2;
-}
-
-/**
- * list_is_head - tests whether @list is the list @head
- * @list: the entry to test
- * @head: the head of the list
- */
-static inline int list_is_head(const struct list_head *list, const struct list_head *head)
-{
- return list == head;
-}
-
-/**
- * list_empty - tests whether a list is empty
- * @head: the list to test.
- */
-static inline int list_empty(const struct list_head *head)
-{
- return head->next == head;
-}
-
-/**
- * list_entry - get the struct for this entry
- * @ptr: the &struct list_head pointer.
- * @type: the type of the struct this is embedded in.
- * @member: the name of the list_head within the struct.
- */
-#define list_entry(ptr, type, member) \
- container_of(ptr, type, member)
-
-/**
- * list_first_entry - get the first element from a list
- * @ptr: the list head to take the element from.
- * @type: the type of the struct this is embedded in.
- * @member: the name of the list_head within the struct.
- *
- * Note, that list is expected to be not empty.
- */
-#define list_first_entry(ptr, type, member) \
- list_entry((ptr)->next, type, member)
-
-/**
- * list_next_entry - get the next element in list
- * @pos: the type * to cursor
- * @member: the name of the list_head within the struct.
- */
-#define list_next_entry(pos, member) \
- list_entry((pos)->member.next, typeof(*(pos)), member)
-
-/**
- * list_entry_is_head - test if the entry points to the head of the list
- * @pos: the type * to cursor
- * @head: the head for your list.
- * @member: the name of the list_head within the struct.
- */
-#define list_entry_is_head(pos, head, member) \
- (&pos->member == (head))
-
-/**
- * list_for_each_entry - iterate over list of given type
- * @pos: the type * to use as a loop cursor.
- * @head: the head for your list.
- * @member: the name of the list_head within the struct.
- */
-#define list_for_each_entry(pos, head, member) \
- for (pos = list_first_entry(head, typeof(*pos), member); \
- !list_entry_is_head(pos, head, member); \
- pos = list_next_entry(pos, member))
-
-/**
- * list_for_each_entry_safe - iterate over list of given type. Safe against removal of list entry
- * @pos: the type * to use as a loop cursor.
- * @n: another type * to use as temporary storage
- * @head: the head for your list.
- * @member: the name of the list_head within the struct.
- */
-#define list_for_each_entry_safe(pos, n, head, member) \
- for (pos = list_first_entry(head, typeof(*pos), member), \
- n = list_next_entry(pos, member); \
- !list_entry_is_head(pos, head, member); \
- pos = n, n = list_next_entry(n, member))
-
-/*
- * Double linked lists with a single pointer list head.
- * Mostly useful for hash tables where the two pointer list head is
- * too wasteful.
- * You lose the ability to access the tail in O(1).
- */
-
-#define HLIST_HEAD_INIT { .first = NULL }
-
-/**
- * hlist_add_head - add a new entry at the beginning of the hlist
- * @n: new entry to be added
- * @h: hlist head to add it after
- *
- * Insert a new entry after the specified head.
- * This is good for implementing stacks.
- */
-static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
-{
- struct hlist_node *first = h->first;
-
- n->next = first;
- if (first)
- first->pprev = &n->next;
- h->first = n;
- n->pprev = &h->first;
-}
-
-#define hlist_entry(ptr, type, member) container_of(ptr, type, member)
-
-#define hlist_entry_safe(ptr, type, member) \
- ({ typeof(ptr) ____ptr = (ptr); \
- ____ptr ? hlist_entry(____ptr, type, member) : NULL; \
- })
-
-/**
- * hlist_for_each_entry - iterate over list of given type
- * @pos: the type * to use as a loop cursor.
- * @head: the head for your list.
- * @member: the name of the hlist_node within the struct.
- */
-#define hlist_for_each_entry(pos, head, member) \
- for (pos = hlist_entry_safe((head)->first, typeof(*(pos)), member);\
- pos; \
- pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member))
-
-#endif /* LIST_H */
diff --git a/scripts/kconfig/list_types.h b/scripts/kconfig/list_types.h
deleted file mode 100644
index d935b7c5aa81..000000000000
--- a/scripts/kconfig/list_types.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef LIST_TYPES_H
-#define LIST_TYPES_H
-
-struct list_head {
- struct list_head *next, *prev;
-};
-
-struct hlist_head {
- struct hlist_node *first;
-};
-
-struct hlist_node {
- struct hlist_node *next, **pprev;
-};
-
-#endif /* LIST_TYPES_H */
diff --git a/scripts/kconfig/lkc.h b/scripts/kconfig/lkc.h
index 64dfc354dd5c..56548efc14d7 100644
--- a/scripts/kconfig/lkc.h
+++ b/scripts/kconfig/lkc.h
@@ -40,7 +40,6 @@ void zconf_nextfile(const char *name);
/* confdata.c */
extern struct gstr autoconf_cmd;
const char *conf_get_configname(void);
-void set_all_choice_values(struct symbol *csym);
/* confdata.c and expr.c */
static inline void xfwrite(const void *str, size_t len, size_t count, FILE *out)
@@ -52,13 +51,7 @@ static inline void xfwrite(const void *str, size_t len, size_t count, FILE *out)
}
/* util.c */
-unsigned int strhash(const char *s);
const char *file_lookup(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);
/* lexer.l */
int yylex(void);
@@ -76,7 +69,7 @@ struct gstr str_new(void);
void str_free(struct gstr *gs);
void str_append(struct gstr *gs, const char *s);
void str_printf(struct gstr *gs, const char *fmt, ...);
-char *str_get(struct gstr *gs);
+char *str_get(const struct gstr *gs);
/* menu.c */
struct menu *menu_next(struct menu *menu, struct menu *root);
@@ -85,13 +78,14 @@ struct menu *menu_next(struct menu *menu, struct menu *root);
#define menu_for_each_entry(menu) \
menu_for_each_sub_entry(menu, &rootmenu)
void _menu_init(void);
-void menu_warn(struct menu *menu, const char *fmt, ...);
+void menu_warn(const 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_add_entry(struct symbol *sym, enum menu_type type);
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);
+struct property *menu_add_prompt(enum prop_type type, const 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_finalize(void);
@@ -101,44 +95,38 @@ extern struct menu rootmenu;
bool menu_is_empty(struct menu *menu);
bool menu_is_visible(struct menu *menu);
-bool menu_has_prompt(struct menu *menu);
-const char *menu_get_prompt(struct menu *menu);
+bool menu_has_prompt(const struct menu *menu);
+const char *menu_get_prompt(const struct menu *menu);
struct menu *menu_get_parent_menu(struct menu *menu);
+struct menu *menu_get_menu_or_parent_menu(struct menu *menu);
int get_jump_key_char(void);
struct gstr get_relations_str(struct symbol **sym_arr, struct list_head *head);
void menu_get_ext_help(struct menu *menu, struct gstr *help);
+void menu_dump(void);
/* symbol.c */
void sym_clear_all_valid(void);
-struct symbol *sym_choice_default(struct symbol *sym);
+struct symbol *sym_choice_default(struct menu *choice);
+struct symbol *sym_calc_choice(struct menu *choice);
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 symbol *prop_get_symbol(struct property *prop);
+struct symbol *prop_get_symbol(const struct property *prop);
-static inline tristate sym_get_tristate_value(struct symbol *sym)
+static inline tristate sym_get_tristate_value(const struct symbol *sym)
{
return sym->curr.tri;
}
-
-static inline struct symbol *sym_get_choice_value(struct symbol *sym)
-{
- return (struct symbol *)sym->curr.val;
-}
-
-static inline bool sym_is_choice(struct symbol *sym)
+static inline bool sym_is_choice(const struct symbol *sym)
{
/* A choice is a symbol with no name */
return sym->name == NULL;
}
-static inline bool sym_is_choice_value(struct symbol *sym)
-{
- return sym->flags & SYMBOL_CHOICEVAL ? true : false;
-}
+bool sym_is_choice_value(const struct symbol *sym);
-static inline bool sym_has_value(struct symbol *sym)
+static inline bool sym_has_value(const struct symbol *sym)
{
return sym->flags & SYMBOL_DEF_USER ? true : false;
}
diff --git a/scripts/kconfig/lkc_proto.h b/scripts/kconfig/lkc_proto.h
index d76aaf4ea117..8914b4e8f2a8 100644
--- a/scripts/kconfig/lkc_proto.h
+++ b/scripts/kconfig/lkc_proto.h
@@ -13,7 +13,7 @@ int conf_write(const char *name);
int conf_write_autoconf(int overwrite);
void conf_set_changed(bool val);
bool conf_get_changed(void);
-void conf_set_changed_callback(void (*fn)(void));
+void conf_set_changed_callback(void (*fn)(bool));
void conf_set_message_callback(void (*fn)(const char *s));
bool conf_errors(void);
@@ -25,21 +25,24 @@ struct symbol ** sym_re_search(const char *pattern);
const char * sym_type_name(enum symbol_type type);
void sym_calc_value(struct symbol *sym);
bool sym_dep_errors(void);
-enum symbol_type sym_get_type(struct symbol *sym);
-bool sym_tristate_within_range(struct symbol *sym,tristate tri);
+enum symbol_type sym_get_type(const struct symbol *sym);
+bool sym_tristate_within_range(const struct symbol *sym, tristate tri);
bool sym_set_tristate_value(struct symbol *sym,tristate tri);
+void choice_set_value(struct menu *choice, struct symbol *sym);
tristate sym_toggle_tristate_value(struct symbol *sym);
bool sym_string_valid(struct symbol *sym, const char *newval);
bool sym_string_within_range(struct symbol *sym, const char *str);
bool sym_set_string_value(struct symbol *sym, const char *newval);
-bool sym_is_changeable(struct symbol *sym);
-struct property * sym_get_choice_prop(struct symbol *sym);
-struct menu *sym_get_choice_menu(struct symbol *sym);
+bool sym_is_changeable(const struct symbol *sym);
+struct menu *sym_get_prompt_menu(const struct symbol *sym);
+struct menu *sym_get_choice_menu(const struct symbol *sym);
const char * sym_get_string_value(struct symbol *sym);
const char * prop_get_type_name(enum prop_type type);
/* expr.c */
-void expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken);
+void expr_print(const struct expr *e,
+ void (*fn)(void *, struct symbol *, const char *),
+ void *data, int prevtoken);
#endif /* LKC_PROTO_H */
diff --git a/scripts/kconfig/lxdialog/inputbox.c b/scripts/kconfig/lxdialog/inputbox.c
index 3c6e24b20f5b..5e4a131724f2 100644
--- a/scripts/kconfig/lxdialog/inputbox.c
+++ b/scripts/kconfig/lxdialog/inputbox.c
@@ -39,8 +39,10 @@ int dialog_inputbox(const char *title, const char *prompt, int height, int width
if (!init)
instr[0] = '\0';
- else
- strcpy(instr, init);
+ else {
+ strncpy(instr, init, sizeof(dialog_input_result) - 1);
+ instr[sizeof(dialog_input_result) - 1] = '\0';
+ }
do_resize:
if (getmaxy(stdscr) <= (height - INPUTBOX_HEIGHT_MIN))
diff --git a/scripts/kconfig/lxdialog/menubox.c b/scripts/kconfig/lxdialog/menubox.c
index 6e6244df0c56..d4c19b7beebb 100644
--- a/scripts/kconfig/lxdialog/menubox.c
+++ b/scripts/kconfig/lxdialog/menubox.c
@@ -264,7 +264,7 @@ do_resize:
if (key < 256 && isalpha(key))
key = tolower(key);
- if (strchr("ynmh", key))
+ if (strchr("ynmh ", key))
i = max_choice;
else {
for (i = choice + 1; i < max_choice; i++) {
diff --git a/scripts/kconfig/lxdialog/util.c b/scripts/kconfig/lxdialog/util.c
index 964139c87fcb..b34000beb294 100644
--- a/scripts/kconfig/lxdialog/util.c
+++ b/scripts/kconfig/lxdialog/util.c
@@ -345,8 +345,7 @@ void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x)
int prompt_len, room, wlen;
char tempstr[MAX_LEN + 1], *word, *sp, *sp2, *newline_separator = 0;
- strcpy(tempstr, prompt);
-
+ snprintf(tempstr, sizeof(tempstr), "%s", prompt);
prompt_len = strlen(tempstr);
if (prompt_len <= width - x * 2) { /* If prompt is short */
diff --git a/scripts/kconfig/mconf-cfg.sh b/scripts/kconfig/mconf-cfg.sh
index 1e61f50a5905..1bc304dc2f7d 100755
--- a/scripts/kconfig/mconf-cfg.sh
+++ b/scripts/kconfig/mconf-cfg.sh
@@ -1,6 +1,8 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
+set -eu
+
cflags=$1
libs=$2
diff --git a/scripts/kconfig/mconf.c b/scripts/kconfig/mconf.c
index d6a61ca1a984..b8b7bba84a65 100644
--- a/scripts/kconfig/mconf.c
+++ b/scripts/kconfig/mconf.c
@@ -12,6 +12,7 @@
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
+#include <locale.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
@@ -19,7 +20,8 @@
#include <signal.h>
#include <unistd.h>
-#include "list.h"
+#include <list.h>
+#include <xalloc.h>
#include "lkc.h"
#include "lxdialog/dialog.h"
#include "mnconf-common.h"
@@ -514,7 +516,7 @@ static void build_conf(struct menu *menu)
type = sym_get_type(sym);
if (sym_is_choice(sym)) {
- struct symbol *def_sym = sym_get_choice_value(sym);
+ struct symbol *def_sym = sym_calc_choice(menu);
struct menu *def_menu = NULL;
child_count++;
@@ -523,28 +525,14 @@ static void build_conf(struct menu *menu)
def_menu = child;
}
- val = sym_get_tristate_value(sym);
- if (sym_is_changeable(sym)) {
- switch (val) {
- case yes: ch = '*'; break;
- case mod: ch = 'M'; break;
- default: ch = ' '; break;
- }
- item_make("<%c>", ch);
- item_set_tag('t');
- item_set_data(menu);
- } else {
- item_make(" ");
- item_set_tag(def_menu ? 't' : ':');
- item_set_data(menu);
- }
+ item_make(" ");
+ item_set_tag(def_menu ? 't' : ':');
+ item_set_data(menu);
item_add_str("%*c%s", indent + 1, ' ', menu_get_prompt(menu));
- if (val == yes) {
- if (def_menu)
- item_add_str(" (%s) --->", menu_get_prompt(def_menu));
- return;
- }
+ if (def_menu)
+ item_add_str(" (%s) --->", menu_get_prompt(def_menu));
+ return;
} else {
if (menu == current_menu) {
item_make("---%*c%s", indent + 1, ' ', menu_get_prompt(menu));
@@ -614,7 +602,7 @@ static void conf_choice(struct menu *menu)
struct menu *child;
struct symbol *active;
- active = sym_get_choice_value(menu->sym);
+ active = sym_calc_choice(menu);
while (1) {
int res;
int selected;
@@ -633,7 +621,7 @@ static void conf_choice(struct menu *menu)
item_set_data(child);
if (child->sym == active)
item_set_selected(1);
- if (child->sym == sym_get_choice_value(menu->sym))
+ if (child->sym == sym_calc_choice(menu))
item_set_tag('X');
}
dialog_clear();
@@ -650,7 +638,7 @@ static void conf_choice(struct menu *menu)
if (!child->sym)
break;
- sym_set_tristate_value(child->sym, yes);
+ choice_set_value(menu, child->sym);
}
return;
case 1:
@@ -814,7 +802,7 @@ static void conf(struct menu *menu, struct menu *active_menu)
conf(submenu, NULL);
break;
case 't':
- if (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)
+ if (sym_is_choice(sym))
conf_choice(submenu);
else if (submenu->prompt->type == P_MENU)
conf(submenu, NULL);
@@ -944,6 +932,8 @@ int main(int ac, char **av)
signal(SIGINT, sig_handler);
+ setlocale(LC_ALL, "");
+
if (ac > 1 && strcmp(av[1], "-s") == 0) {
silent = 1;
/* Silence conf_read() until the real callback is set up */
diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c
index eef9b63cdf11..0f1a6513987c 100644
--- a/scripts/kconfig/menu.c
+++ b/scripts/kconfig/menu.c
@@ -8,13 +8,14 @@
#include <stdlib.h>
#include <string.h>
+#include <list.h>
+#include <xalloc.h>
#include "lkc.h"
#include "internal.h"
-#include "list.h"
static const char nohelp_text[] = "There is no help available for this option.";
-struct menu rootmenu;
+struct menu rootmenu = { .type = M_MENU };
static struct menu **last_entry_ptr;
/**
@@ -38,7 +39,7 @@ struct menu *menu_next(struct menu *menu, struct menu *root)
return menu->next;
}
-void menu_warn(struct menu *menu, const char *fmt, ...)
+void menu_warn(const struct menu *menu, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
@@ -48,7 +49,7 @@ void menu_warn(struct menu *menu, const char *fmt, ...)
va_end(ap);
}
-static void prop_warn(struct property *prop, const char *fmt, ...)
+static void prop_warn(const struct property *prop, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
@@ -64,12 +65,13 @@ void _menu_init(void)
last_entry_ptr = &rootmenu.list;
}
-void menu_add_entry(struct symbol *sym)
+void menu_add_entry(struct symbol *sym, enum menu_type type)
{
struct menu *menu;
menu = xmalloc(sizeof(*menu));
memset(menu, 0, sizeof(*menu));
+ menu->type = type;
menu->sym = sym;
menu->parent = current_menu;
menu->filename = cur_filename;
@@ -78,10 +80,8 @@ void menu_add_entry(struct symbol *sym)
*last_entry_ptr = menu;
last_entry_ptr = &menu->next;
current_entry = menu;
- if (sym) {
- menu_add_symbol(P_SYMBOL, sym, NULL);
+ if (sym)
list_add_tail(&menu->link, &sym->menus);
- }
}
struct menu *menu_add_menu(void)
@@ -108,12 +108,13 @@ static struct expr *rewrite_m(struct expr *e)
switch (e->type) {
case E_NOT:
- e->left.expr = rewrite_m(e->left.expr);
+ e = expr_alloc_one(E_NOT, rewrite_m(e->left.expr));
break;
case E_OR:
case E_AND:
- e->left.expr = rewrite_m(e->left.expr);
- e->right.expr = rewrite_m(e->right.expr);
+ e = expr_alloc_two(e->type,
+ rewrite_m(e->left.expr),
+ rewrite_m(e->right.expr));
break;
case E_SYMBOL:
/* change 'm' into 'm' && MODULES */
@@ -175,7 +176,7 @@ static struct property *menu_add_prop(enum prop_type type, struct expr *expr,
return prop;
}
-struct property *menu_add_prompt(enum prop_type type, char *prompt,
+struct property *menu_add_prompt(enum prop_type type, const char *prompt,
struct expr *dep)
{
struct property *prop = menu_add_prop(type, NULL, dep);
@@ -193,21 +194,11 @@ struct property *menu_add_prompt(enum prop_type type, char *prompt,
struct menu *menu = current_entry;
while ((menu = menu->parent) != NULL) {
- struct expr *dup_expr;
if (!menu->visibility)
continue;
- /*
- * Do not add a reference to the menu's visibility
- * expression but use a copy of it. Otherwise the
- * expression reduction functions will modify
- * expressions that have multiple references which
- * can cause unwanted side effects.
- */
- dup_expr = expr_copy(menu->visibility);
-
prop->visible.expr = expr_alloc_and(prop->visible.expr,
- dup_expr);
+ menu->visibility);
}
}
@@ -306,7 +297,7 @@ static void _menu_finalize(struct menu *parent, bool inside_choice)
struct menu *menu, *last_menu;
struct symbol *sym;
struct property *prop;
- struct expr *parentdep, *basedep, *dep, *dep2, **ep;
+ struct expr *basedep, *dep, *dep2;
sym = parent->sym;
if (parent->list) {
@@ -315,35 +306,6 @@ static void _menu_finalize(struct menu *parent, bool inside_choice)
* and propagate parent dependencies before moving on.
*/
- bool is_choice = false;
-
- if (sym && sym_is_choice(sym))
- is_choice = true;
-
- if (is_choice) {
- if (sym->type == S_UNKNOWN) {
- /* find the first choice value to find out choice type */
- current_entry = parent;
- for (menu = parent->list; menu; menu = menu->next) {
- if (menu->sym && menu->sym->type != S_UNKNOWN) {
- menu_set_type(menu->sym->type);
- break;
- }
- }
- }
-
- /*
- * 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 {
- /* Menu node for 'menu', 'if' */
- parentdep = parent->dep;
- }
-
/* For each child menu node... */
for (menu = parent->list; menu; menu = menu->next) {
/*
@@ -352,7 +314,7 @@ static void _menu_finalize(struct menu *parent, bool inside_choice)
*/
basedep = rewrite_m(menu->dep);
basedep = expr_transform(basedep);
- basedep = expr_alloc_and(expr_copy(parentdep), basedep);
+ basedep = expr_alloc_and(parent->dep, basedep);
basedep = expr_eliminate_dups(basedep);
menu->dep = basedep;
@@ -396,7 +358,7 @@ static void _menu_finalize(struct menu *parent, bool inside_choice)
*/
dep = rewrite_m(prop->visible.expr);
dep = expr_transform(dep);
- dep = expr_alloc_and(expr_copy(basedep), dep);
+ dep = expr_alloc_and(basedep, dep);
dep = expr_eliminate_dups(dep);
prop->visible.expr = dep;
@@ -407,24 +369,21 @@ static void _menu_finalize(struct menu *parent, bool inside_choice)
if (prop->type == P_SELECT) {
struct symbol *es = prop_get_symbol(prop);
es->rev_dep.expr = expr_alloc_or(es->rev_dep.expr,
- expr_alloc_and(expr_alloc_symbol(menu->sym), expr_copy(dep)));
+ expr_alloc_and(expr_alloc_symbol(menu->sym), dep));
} else if (prop->type == P_IMPLY) {
struct symbol *es = prop_get_symbol(prop);
es->implied.expr = expr_alloc_or(es->implied.expr,
- expr_alloc_and(expr_alloc_symbol(menu->sym), expr_copy(dep)));
+ expr_alloc_and(expr_alloc_symbol(menu->sym), dep));
}
}
}
- if (is_choice)
- expr_free(parentdep);
-
/*
* Recursively process children in the same fashion before
* moving on
*/
for (menu = parent->list; menu; menu = menu->next)
- _menu_finalize(menu, is_choice);
+ _menu_finalize(menu, sym && sym_is_choice(sym));
} else if (!inside_choice && sym) {
/*
* Automatic submenu creation. If sym is a symbol and A, B, C,
@@ -474,22 +433,18 @@ static void _menu_finalize(struct menu *parent, bool inside_choice)
*/
dep = expr_trans_compare(dep, E_UNEQUAL, &symbol_no);
dep = expr_eliminate_dups(expr_transform(dep));
- dep2 = expr_copy(basedep);
+ dep2 = 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, false);
menu->parent = parent;
last_menu = menu;
}
- expr_free(basedep);
if (last_menu) {
parent->list = parent->next;
parent->next = last_menu->next;
@@ -499,34 +454,6 @@ static void _menu_finalize(struct menu *parent, bool inside_choice)
sym->dir_dep.expr = expr_alloc_or(sym->dir_dep.expr, parent->dep);
}
for (menu = parent->list; menu; menu = menu->next) {
- if (sym && sym_is_choice(sym) &&
- menu->sym && !sym_is_choice_value(menu->sym)) {
- current_entry = menu;
- menu->sym->flags |= SYMBOL_CHOICEVAL;
- /* Non-tristate choice values of tristate choices must
- * depend on the choice being set to Y. The choice
- * values' dependencies were propagated to their
- * properties above, so the change here must be re-
- * propagated.
- */
- if (sym->type == S_TRISTATE && menu->sym->type != S_TRISTATE) {
- basedep = expr_alloc_comp(E_EQUAL, sym, &symbol_yes);
- menu->dep = expr_alloc_and(basedep, menu->dep);
- for (prop = menu->sym->prop; prop; prop = prop->next) {
- if (prop->menu != menu)
- continue;
- prop->visible.expr = expr_alloc_and(expr_copy(basedep),
- prop->visible.expr);
- }
- }
- menu_add_symbol(P_CHOICE, sym, NULL);
- prop = sym_get_choice_prop(sym);
- for (ep = &prop->expr; *ep; ep = &(*ep)->left.expr)
- ;
- *ep = expr_alloc_one(E_LIST, NULL);
- (*ep)->right.sym = menu->sym;
- }
-
/*
* This code serves two purposes:
*
@@ -575,17 +502,6 @@ static void _menu_finalize(struct menu *parent, bool inside_choice)
sym_check_prop(sym);
sym->flags |= SYMBOL_WARNED;
}
-
- /*
- * For 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.
- */
- if (sym && sym_is_choice(sym) && parent->prompt) {
- sym->rev_dep.expr = expr_alloc_or(sym->rev_dep.expr,
- expr_alloc_and(parent->prompt->visible.expr,
- expr_alloc_symbol(&symbol_mod)));
- }
}
void menu_finalize(void)
@@ -593,7 +509,7 @@ void menu_finalize(void)
_menu_finalize(&rootmenu, false);
}
-bool menu_has_prompt(struct menu *menu)
+bool menu_has_prompt(const struct menu *menu)
{
if (!menu->prompt)
return false;
@@ -643,18 +559,14 @@ bool menu_is_visible(struct menu *menu)
if (!sym || sym_get_tristate_value(menu->sym) == no)
return false;
- for (child = menu->list; child; child = child->next) {
- if (menu_is_visible(child)) {
- if (sym)
- sym->flags |= SYMBOL_DEF_USER;
+ for (child = menu->list; child; child = child->next)
+ if (menu_is_visible(child))
return true;
- }
- }
return false;
}
-const char *menu_get_prompt(struct menu *menu)
+const char *menu_get_prompt(const struct menu *menu)
{
if (menu->prompt)
return menu->prompt->text;
@@ -663,8 +575,28 @@ const char *menu_get_prompt(struct menu *menu)
return NULL;
}
+/**
+ * menu_get_parent_menu - return the parent menu or NULL
+ * @menu: pointer to the menu
+ * return: the parent menu, or NULL if there is no parent.
+ */
struct menu *menu_get_parent_menu(struct menu *menu)
{
+ for (menu = menu->parent; menu; menu = menu->parent)
+ if (menu->type == M_MENU)
+ return menu;
+
+ return NULL;
+}
+
+/**
+ * menu_get_menu_or_parent_menu - return the parent menu or the menu itself
+ * @menu: pointer to the menu
+ * return: the parent menu. If the given argument is already a menu, return
+ * itself.
+ */
+struct menu *menu_get_menu_or_parent_menu(struct menu *menu)
+{
enum prop_type type;
for (; menu != &rootmenu; menu = menu->parent) {
@@ -675,13 +607,14 @@ struct menu *menu_get_parent_menu(struct menu *menu)
return menu;
}
-static void get_def_str(struct gstr *r, struct menu *menu)
+static void get_def_str(struct gstr *r, const struct menu *menu)
{
str_printf(r, "Defined at %s:%d\n",
menu->filename, menu->lineno);
}
-static void get_dep_str(struct gstr *r, struct expr *expr, const char *prefix)
+static void get_dep_str(struct gstr *r, const struct expr *expr,
+ const char *prefix)
{
if (!expr_is_yes(expr)) {
str_append(r, prefix);
@@ -855,3 +788,77 @@ void menu_get_ext_help(struct menu *menu, struct gstr *help)
if (sym)
get_symbol_str(help, sym, NULL);
}
+
+/**
+ * menu_dump - dump all menu entries in a tree-like format
+ */
+void menu_dump(void)
+{
+ struct menu *menu = &rootmenu;
+ unsigned long long bits = 0;
+ int indent = 0;
+
+ while (menu) {
+
+ for (int i = indent - 1; i >= 0; i--) {
+ if (bits & (1ULL << i)) {
+ if (i > 0)
+ printf("| ");
+ else
+ printf("|-- ");
+ } else {
+ if (i > 0)
+ printf(" ");
+ else
+ printf("`-- ");
+ }
+ }
+
+ switch (menu->type) {
+ case M_CHOICE:
+ printf("choice \"%s\"\n", menu->prompt->text);
+ break;
+ case M_COMMENT:
+ printf("comment \"%s\"\n", menu->prompt->text);
+ break;
+ case M_IF:
+ printf("if\n");
+ break;
+ case M_MENU:
+ printf("menu \"%s\"", menu->prompt->text);
+ if (!menu->sym) {
+ printf("\n");
+ break;
+ }
+ printf(" + ");
+ /* fallthrough */
+ case M_NORMAL:
+ printf("symbol %s\n", menu->sym->name);
+ break;
+ }
+ if (menu->list) {
+ bits <<= 1;
+ menu = menu->list;
+ if (menu->next)
+ bits |= 1;
+ else
+ bits &= ~1;
+ indent++;
+ continue;
+ }
+
+ while (menu && !menu->next) {
+ menu = menu->parent;
+ bits >>= 1;
+ indent--;
+ }
+
+ if (menu) {
+ menu = menu->next;
+ if (menu->next)
+ bits |= 1;
+ else
+ bits &= ~1;
+ }
+ }
+}
diff --git a/scripts/kconfig/merge_config.sh b/scripts/kconfig/merge_config.sh
index 902eb429b9db..79c09b378be8 100755
--- a/scripts/kconfig/merge_config.sh
+++ b/scripts/kconfig/merge_config.sh
@@ -112,8 +112,8 @@ INITFILE=$1
shift;
if [ ! -r "$INITFILE" ]; then
- echo "The base file '$INITFILE' does not exist. Exit." >&2
- exit 1
+ echo "The base file '$INITFILE' does not exist. Creating one..." >&2
+ touch "$INITFILE"
fi
MERGE_LIST=$*
@@ -167,6 +167,8 @@ for ORIG_MERGE_FILE in $MERGE_LIST ; do
sed -i "/$CFG[ =]/d" $MERGE_FILE
fi
done
+ # In case the previous file lacks a new line at the end
+ echo >> $TMP_FILE
cat $MERGE_FILE >> $TMP_FILE
done
diff --git a/scripts/kconfig/mnconf-common.c b/scripts/kconfig/mnconf-common.c
index 18cb9a6c5aaa..8e24b07121df 100644
--- a/scripts/kconfig/mnconf-common.c
+++ b/scripts/kconfig/mnconf-common.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
+#include <list.h>
#include "expr.h"
-#include "list.h"
#include "mnconf-common.h"
int jump_key_char;
diff --git a/scripts/kconfig/mnconf-common.h b/scripts/kconfig/mnconf-common.h
index ab6292cc4bf2..53bd7292e931 100644
--- a/scripts/kconfig/mnconf-common.h
+++ b/scripts/kconfig/mnconf-common.h
@@ -4,6 +4,8 @@
#include <stddef.h>
+#include <list_types.h>
+
struct search_data {
struct list_head *head;
struct menu *target;
diff --git a/scripts/kconfig/nconf-cfg.sh b/scripts/kconfig/nconf-cfg.sh
index f871a2160e36..a20290b1a37d 100755
--- a/scripts/kconfig/nconf-cfg.sh
+++ b/scripts/kconfig/nconf-cfg.sh
@@ -1,6 +1,8 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
+set -eu
+
cflags=$1
libs=$2
diff --git a/scripts/kconfig/nconf.c b/scripts/kconfig/nconf.c
index e1cb09418cbe..521700ed7152 100644
--- a/scripts/kconfig/nconf.c
+++ b/scripts/kconfig/nconf.c
@@ -7,11 +7,13 @@
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
+#include <locale.h>
#include <string.h>
#include <strings.h>
#include <stdlib.h>
-#include "list.h"
+#include <list.h>
+#include <xalloc.h>
#include "lkc.h"
#include "mnconf-common.h"
#include "nconf.h"
@@ -466,7 +468,7 @@ static void handle_f9(int *key, struct menu *current_item)
return;
}
-/* return != 0 to indicate the key was handles */
+/* return != 0 to indicate the key was handled */
static int process_special_keys(int *key, struct menu *menu)
{
int i;
@@ -592,6 +594,8 @@ static void item_add_str(const char *fmt, ...)
tmp_str,
sizeof(k_menu_items[index].str));
+ k_menu_items[index].str[sizeof(k_menu_items[index].str) - 1] = '\0';
+
free_item(curses_menu_items[index]);
curses_menu_items[index] = new_item(
k_menu_items[index].str,
@@ -815,7 +819,7 @@ static void build_conf(struct menu *menu)
type = sym_get_type(sym);
if (sym_is_choice(sym)) {
- struct symbol *def_sym = sym_get_choice_value(sym);
+ struct symbol *def_sym = sym_calc_choice(menu);
struct menu *def_menu = NULL;
child_count++;
@@ -825,30 +829,13 @@ static void build_conf(struct menu *menu)
}
val = sym_get_tristate_value(sym);
- if (sym_is_changeable(sym)) {
- switch (val) {
- case yes:
- ch = '*';
- break;
- case mod:
- ch = 'M';
- break;
- default:
- ch = ' ';
- break;
- }
- item_make(menu, 't', "<%c>", ch);
- } else {
- item_make(menu, def_menu ? 't' : ':', " ");
- }
+ item_make(menu, def_menu ? 't' : ':', " ");
item_add_str("%*c%s", indent + 1,
' ', menu_get_prompt(menu));
- if (val == yes) {
- if (def_menu)
- item_add_str(" (%s) --->", menu_get_prompt(def_menu));
- return;
- }
+ if (def_menu)
+ item_add_str(" (%s) --->", menu_get_prompt(def_menu));
+ return;
} else {
if (menu == current_menu) {
item_make(menu, ':',
@@ -1191,8 +1178,7 @@ static void selected_conf(struct menu *menu, struct menu *active_menu)
conf(submenu);
break;
case 't':
- if (sym_is_choice(sym) &&
- sym_get_tristate_value(sym) == yes)
+ if (sym_is_choice(sym))
conf_choice(submenu);
else if (submenu->prompt &&
submenu->prompt->type == P_MENU)
@@ -1257,7 +1243,7 @@ static void conf_choice(struct menu *menu)
.pattern = "",
};
- active = sym_get_choice_value(menu->sym);
+ active = sym_calc_choice(menu);
/* this is mostly duplicated from the conf() function. */
while (!global_exit) {
reset_menu();
@@ -1266,7 +1252,7 @@ static void conf_choice(struct menu *menu)
if (!show_all_items && !menu_is_visible(child))
continue;
- if (child->sym == sym_get_choice_value(menu->sym))
+ if (child->sym == sym_calc_choice(menu))
item_make(child, ':', "<X> %s",
menu_get_prompt(child));
else if (child->sym)
@@ -1349,7 +1335,7 @@ static void conf_choice(struct menu *menu)
case ' ':
case 10:
case KEY_RIGHT:
- sym_set_tristate_value(child->sym, yes);
+ choice_set_value(menu, child->sym);
return;
case 'h':
case '?':
@@ -1493,6 +1479,8 @@ int main(int ac, char **av)
int lines, columns;
char *mode;
+ setlocale(LC_ALL, "");
+
if (ac > 1 && strcmp(av[1], "-s") == 0) {
/* Silence conf_read() until the real callback is set up */
conf_set_message_callback(NULL);
diff --git a/scripts/kconfig/nconf.gui.c b/scripts/kconfig/nconf.gui.c
index 25a7263ef3c8..2d097bc7ef1a 100644
--- a/scripts/kconfig/nconf.gui.c
+++ b/scripts/kconfig/nconf.gui.c
@@ -4,6 +4,7 @@
*
* Derived from menuconfig.
*/
+#include <xalloc.h>
#include "nconf.h"
#include "lkc.h"
@@ -172,12 +173,10 @@ void fill_window(WINDOW *win, const char *text)
/* do not go over end of line */
total_lines = min(total_lines, y);
for (i = 0; i < total_lines; i++) {
- char tmp[x+10];
const char *line = get_line(text, i);
- int len = get_line_length(line);
- strncpy(tmp, line, min(len, x));
- tmp[len] = '\0';
- mvwprintw(win, i, 0, "%s", tmp);
+ int len = min(get_line_length(line), x);
+
+ mvwprintw(win, i, 0, "%.*s", len, line);
}
}
@@ -276,6 +275,15 @@ int btn_dialog(WINDOW *main_window, const char *msg, int btn_num, ...)
case KEY_RIGHT:
menu_driver(menu, REQ_RIGHT_ITEM);
break;
+ case 9: /* TAB */
+ if (btn_num > 1) {
+ /* cycle through buttons */
+ if (item_index(current_item(menu)) == btn_num - 1)
+ menu_driver(menu, REQ_FIRST_ITEM);
+ else
+ menu_driver(menu, REQ_NEXT_ITEM);
+ }
+ break;
case 10: /* ENTER */
case 27: /* ESCAPE */
case ' ':
@@ -349,6 +357,7 @@ int dialog_inputbox(WINDOW *main_window,
x = (columns-win_cols)/2;
strncpy(result, init, *result_len);
+ result[*result_len - 1] = '\0';
/* create the windows */
win = newwin(win_lines, win_cols, y, x);
diff --git a/scripts/kconfig/parser.y b/scripts/kconfig/parser.y
index ff709001b1f0..49b79dde1725 100644
--- a/scripts/kconfig/parser.y
+++ b/scripts/kconfig/parser.y
@@ -11,6 +11,7 @@
#include <string.h>
#include <stdbool.h>
+#include <xalloc.h>
#include "lkc.h"
#include "internal.h"
#include "preprocess.h"
@@ -23,14 +24,11 @@
int cdebug = PRINTD;
static void yyerror(const char *err);
-static void zconfprint(const char *err, ...);
static void zconf_error(const char *err, ...);
static bool zconf_endtoken(const char *tokenname,
const char *expected_tokenname);
-struct menu *current_menu, *current_entry;
-
-static bool inside_choice = false;
+struct menu *current_menu, *current_entry, *current_choice;
%}
@@ -77,6 +75,7 @@ static bool inside_choice = false;
%token T_SELECT
%token T_SOURCE
%token T_STRING
+%token T_TRANSITIONAL
%token T_TRISTATE
%token T_VISIBLE
%token T_EOL
@@ -90,7 +89,7 @@ static bool inside_choice = false;
%type <symbol> nonconst_symbol
%type <symbol> symbol
-%type <type> type logic_type default
+%type <type> type default
%type <expr> expr
%type <expr> if_expr
%type <string> end
@@ -141,18 +140,33 @@ stmt_list_in_choice:
config_entry_start: T_CONFIG nonconst_symbol T_EOL
{
- menu_add_entry($2);
+ menu_add_entry($2, M_NORMAL);
printd(DEBUG_PARSE, "%s:%d:config %s\n", cur_filename, cur_lineno, $2->name);
};
config_stmt: config_entry_start config_option_list
{
- if (inside_choice) {
+ if (current_choice) {
if (!current_entry->prompt) {
fprintf(stderr, "%s:%d: error: choice member must have a prompt\n",
current_entry->filename, current_entry->lineno);
yynerrs++;
}
+
+ if (current_entry->sym->type != S_BOOLEAN) {
+ fprintf(stderr, "%s:%d: error: choice member must be bool\n",
+ current_entry->filename, current_entry->lineno);
+ yynerrs++;
+ }
+
+ /*
+ * If the same symbol appears twice in a choice block, the list
+ * node would be added twice, leading to a broken linked list.
+ * list_empty() ensures that this symbol has not yet added.
+ */
+ if (list_empty(&current_entry->sym->choice_link))
+ list_add_tail(&current_entry->sym->choice_link,
+ &current_choice->choice_members);
}
printd(DEBUG_PARSE, "%s:%d:endconfig\n", cur_filename, cur_lineno);
@@ -160,7 +174,7 @@ config_stmt: config_entry_start config_option_list
menuconfig_entry_start: T_MENUCONFIG nonconst_symbol T_EOL
{
- menu_add_entry($2);
+ menu_add_entry($2, M_MENU);
printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", cur_filename, cur_lineno, $2->name);
};
@@ -169,7 +183,7 @@ menuconfig_stmt: menuconfig_entry_start config_option_list
if (current_entry->prompt)
current_entry->prompt->type = P_MENU;
else
- zconfprint("warning: menuconfig statement without prompt");
+ zconf_error("menuconfig statement without prompt");
printd(DEBUG_PARSE, "%s:%d:endconfig\n", cur_filename, cur_lineno);
};
@@ -192,6 +206,12 @@ config_option: T_PROMPT T_WORD_QUOTE if_expr T_EOL
printd(DEBUG_PARSE, "%s:%d:prompt\n", cur_filename, cur_lineno);
};
+config_option: T_TRANSITIONAL T_EOL
+{
+ current_entry->sym->flags |= SYMBOL_TRANS;
+ printd(DEBUG_PARSE, "%s:%d:transitional\n", cur_filename, cur_lineno);
+};
+
config_option: default expr if_expr T_EOL
{
menu_add_expr(P_DEFAULT, $2, $3);
@@ -233,8 +253,10 @@ choice: T_CHOICE T_EOL
{
struct symbol *sym = sym_lookup(NULL, 0);
- menu_add_entry(sym);
- menu_add_expr(P_CHOICE, NULL, NULL);
+ menu_add_entry(sym, M_CHOICE);
+ menu_set_type(S_BOOLEAN);
+ INIT_LIST_HEAD(&current_entry->choice_members);
+
printd(DEBUG_PARSE, "%s:%d:choice\n", cur_filename, cur_lineno);
};
@@ -248,12 +270,12 @@ choice_entry: choice choice_option_list
$$ = menu_add_menu();
- inside_choice = true;
+ current_choice = current_entry;
};
choice_end: end
{
- inside_choice = false;
+ current_choice = NULL;
if (zconf_endtoken($1, "choice")) {
menu_end_menu();
@@ -277,12 +299,6 @@ choice_option: T_PROMPT T_WORD_QUOTE if_expr T_EOL
printd(DEBUG_PARSE, "%s:%d:prompt\n", cur_filename, cur_lineno);
};
-choice_option: logic_type prompt_stmt_opt T_EOL
-{
- menu_set_type($1);
- printd(DEBUG_PARSE, "%s:%d:type(%u)\n", cur_filename, cur_lineno, $1);
-};
-
choice_option: T_DEFAULT nonconst_symbol if_expr T_EOL
{
menu_add_symbol(P_DEFAULT, $2, $3);
@@ -290,15 +306,12 @@ choice_option: T_DEFAULT nonconst_symbol if_expr T_EOL
};
type:
- logic_type
+ T_BOOL { $$ = S_BOOLEAN; }
+ | T_TRISTATE { $$ = S_TRISTATE; }
| 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; }
@@ -309,7 +322,7 @@ default:
if_entry: T_IF expr T_EOL
{
printd(DEBUG_PARSE, "%s:%d:if\n", cur_filename, cur_lineno);
- menu_add_entry(NULL);
+ menu_add_entry(NULL, M_IF);
menu_add_dep($2);
$$ = menu_add_menu();
};
@@ -332,7 +345,7 @@ if_stmt_in_choice: if_entry stmt_list_in_choice if_end
menu: T_MENU T_WORD_QUOTE T_EOL
{
- menu_add_entry(NULL);
+ menu_add_entry(NULL, M_MENU);
menu_add_prompt(P_MENU, $2, NULL);
printd(DEBUG_PARSE, "%s:%d:menu\n", cur_filename, cur_lineno);
};
@@ -370,7 +383,7 @@ source_stmt: T_SOURCE T_WORD_QUOTE T_EOL
comment: T_COMMENT T_WORD_QUOTE T_EOL
{
- menu_add_entry(NULL);
+ menu_add_entry(NULL, M_COMMENT);
menu_add_prompt(P_COMMENT, $2, NULL);
printd(DEBUG_PARSE, "%s:%d:comment\n", cur_filename, cur_lineno);
};
@@ -395,14 +408,14 @@ 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>");
+ zconf_error("'%s' defined with more than one help text",
+ 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>");
+ zconf_error("'%s' defined with blank help text",
+ current_entry->sym->name ?: "<choice>");
current_entry->help = $2;
};
@@ -477,13 +490,50 @@ assign_val:
%%
/**
+ * transitional_check_sanity - check transitional symbols have no other
+ * properties
+ *
+ * @menu: menu of the potentially transitional symbol
+ *
+ * Return: -1 if an error is found, 0 otherwise.
+ */
+static int transitional_check_sanity(const struct menu *menu)
+{
+ struct property *prop;
+
+ if (!menu->sym || !(menu->sym->flags & SYMBOL_TRANS))
+ return 0;
+
+ /* Check for depends and visible conditions. */
+ if ((menu->dep && !expr_is_yes(menu->dep)) ||
+ (menu->visibility && !expr_is_yes(menu->visibility))) {
+ fprintf(stderr, "%s:%d: error: %s",
+ menu->filename, menu->lineno,
+ "transitional symbols can only have help sections\n");
+ return -1;
+ }
+
+ /* Check for any property other than "help". */
+ for (prop = menu->sym->prop; prop; prop = prop->next) {
+ if (prop->type != P_COMMENT) {
+ fprintf(stderr, "%s:%d: error: %s",
+ prop->filename, prop->lineno,
+ "transitional symbols can only have help sections\n");
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+/**
* choice_check_sanity - check sanity of a choice member
*
* @menu: menu of the choice member
*
* Return: -1 if an error is found, 0 otherwise.
*/
-static int choice_check_sanity(struct menu *menu)
+static int choice_check_sanity(const struct menu *menu)
{
struct property *prop;
int ret = 0;
@@ -524,14 +574,6 @@ void conf_parse(const char *name)
yydebug = 1;
yyparse();
- /*
- * FIXME:
- * cur_filename and cur_lineno are used even after yyparse();
- * menu_finalize() calls menu_add_symbol(). This should be fixed.
- */
- cur_filename = "<none>";
- cur_lineno = 0;
-
str_printf(&autoconf_cmd,
"\n"
"$(autoconfig): $(deps_config)\n"
@@ -560,6 +602,9 @@ void conf_parse(const char *name)
if (menu->sym && sym_check_deps(menu->sym))
yynerrs++;
+ if (transitional_check_sanity(menu))
+ yynerrs++;
+
if (menu->sym && sym_is_choice(menu->sym)) {
menu_for_each_sub_entry(child, menu)
if (child->sym && choice_check_sanity(child))
@@ -593,17 +638,6 @@ static bool zconf_endtoken(const char *tokenname,
return true;
}
-static void zconfprint(const char *err, ...)
-{
- va_list ap;
-
- fprintf(stderr, "%s:%d: ", cur_filename, cur_lineno);
- va_start(ap, err);
- vfprintf(stderr, err, ap);
- va_end(ap);
- fprintf(stderr, "\n");
-}
-
static void zconf_error(const char *err, ...)
{
va_list ap;
@@ -638,7 +672,7 @@ static void print_quoted_string(FILE *out, const char *str)
putc('"', out);
}
-static void print_symbol(FILE *out, struct menu *menu)
+static void print_symbol(FILE *out, const struct menu *menu)
{
struct symbol *sym = menu->sym;
struct property *prop;
@@ -689,9 +723,6 @@ static void print_symbol(FILE *out, struct menu *menu)
}
fputc('\n', out);
break;
- case P_CHOICE:
- fputs(" #choice value\n", out);
- break;
case P_SELECT:
fputs( " select ", out);
expr_fprint(prop->expr, out);
@@ -712,10 +743,6 @@ 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->menu->sym->name);
- break;
default:
fprintf(out, " unknown prop %d!\n", prop->type);
break;
diff --git a/scripts/kconfig/preprocess.c b/scripts/kconfig/preprocess.c
index f0a4a218c4a5..783abcaa5cc5 100644
--- a/scripts/kconfig/preprocess.c
+++ b/scripts/kconfig/preprocess.c
@@ -9,9 +9,10 @@
#include <stdlib.h>
#include <string.h>
-#include "array_size.h"
+#include <array_size.h>
+#include <list.h>
+#include <xalloc.h>
#include "internal.h"
-#include "list.h"
#include "lkc.h"
#include "preprocess.h"
diff --git a/scripts/kconfig/qconf-cfg.sh b/scripts/kconfig/qconf-cfg.sh
index 0e113b0f2455..bb2df66363a8 100755
--- a/scripts/kconfig/qconf-cfg.sh
+++ b/scripts/kconfig/qconf-cfg.sh
@@ -1,6 +1,8 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
+set -eu
+
cflags=$1
libs=$2
bin=$3
diff --git a/scripts/kconfig/qconf.cc b/scripts/kconfig/qconf.cc
index c6c42c0f4e5d..b84c9f2485d1 100644
--- a/scripts/kconfig/qconf.cc
+++ b/scripts/kconfig/qconf.cc
@@ -22,6 +22,7 @@
#include <stdlib.h>
+#include <xalloc.h>
#include "lkc.h"
#include "qconf.h"
@@ -36,6 +37,12 @@ QAction *ConfigMainWindow::saveAction;
ConfigSettings::ConfigSettings()
: QSettings("kernel.org", "qconf")
{
+ beginGroup("/kconfig/qconf");
+}
+
+ConfigSettings::~ConfigSettings()
+{
+ endGroup();
}
/**
@@ -91,7 +98,6 @@ void ConfigItem::updateMenu(void)
{
ConfigList* list;
struct symbol* sym;
- struct property *prop;
QString prompt;
int type;
tristate expr;
@@ -104,12 +110,11 @@ void ConfigItem::updateMenu(void)
}
sym = menu->sym;
- prop = menu->prompt;
prompt = menu_get_prompt(menu);
- if (prop) switch (prop->type) {
- case P_MENU:
- if (list->mode == singleMode || list->mode == symbolMode) {
+ switch (menu->type) {
+ case M_MENU:
+ if (list->mode == singleMode) {
/* a menuconfig entry is displayed differently
* depending whether it's at the view root or a child.
*/
@@ -122,10 +127,16 @@ void ConfigItem::updateMenu(void)
setIcon(promptColIdx, QIcon());
}
goto set_prompt;
- case P_COMMENT:
+ case M_COMMENT:
setIcon(promptColIdx, QIcon());
prompt = "*** " + prompt + " ***";
goto set_prompt;
+ case M_CHOICE:
+ setIcon(promptColIdx, QIcon());
+ sym = sym_calc_choice(menu);
+ if (sym)
+ setText(dataColIdx, sym->name);
+ goto set_prompt;
default:
;
}
@@ -147,7 +158,7 @@ void ConfigItem::updateMenu(void)
expr = sym_get_tristate_value(sym);
switch (expr) {
case yes:
- if (sym_is_choice_value(sym) && type == S_BOOLEAN)
+ if (sym_is_choice_value(sym))
setIcon(promptColIdx, choiceYesIcon);
else
setIcon(promptColIdx, symbolYesIcon);
@@ -158,7 +169,7 @@ void ConfigItem::updateMenu(void)
ch = 'M';
break;
default:
- if (sym_is_choice_value(sym) && type == S_BOOLEAN)
+ if (sym_is_choice_value(sym))
setIcon(promptColIdx, choiceNoIcon);
else
setIcon(promptColIdx, symbolNoIcon);
@@ -174,21 +185,24 @@ void ConfigItem::updateMenu(void)
setText(dataColIdx, sym_get_string_value(sym));
break;
}
- if (!sym_has_value(sym) && visible)
+ if (!sym_has_value(sym))
prompt += " (NEW)";
set_prompt:
setText(promptColIdx, prompt);
}
-void ConfigItem::testUpdateMenu(bool v)
+void ConfigItem::testUpdateMenu(void)
{
ConfigItem* i;
- visible = v;
if (!menu)
return;
- sym_calc_value(menu->sym);
+ if (menu->type == M_CHOICE)
+ sym_calc_choice(menu);
+ else
+ sym_calc_value(menu->sym);
+
if (menu->flags & MENU_CHANGED) {
/* the menu entry changed, so update all list items */
menu->flags &= ~MENU_CHANGED;
@@ -306,7 +320,6 @@ ConfigList::ConfigList(QWidget *parent, const char *name)
{
setObjectName(name);
setSortingEnabled(false);
- setRootIsDecorated(true);
setVerticalScrollMode(ScrollPerPixel);
setHorizontalScrollMode(ScrollPerPixel);
@@ -429,27 +442,26 @@ void ConfigList::updateList()
item = (ConfigItem*)(*it);
if (!item->menu)
continue;
- item->testUpdateMenu(menu_is_visible(item->menu));
+ item->testUpdateMenu();
++it;
}
return;
}
- if (rootEntry != &rootmenu && (mode == singleMode ||
- (mode == symbolMode && rootEntry->parent != &rootmenu))) {
+ if (rootEntry != &rootmenu && mode == singleMode) {
item = (ConfigItem *)topLevelItem(0);
if (!item)
- item = new ConfigItem(this, 0, true);
+ item = new ConfigItem(this, 0);
last = item;
}
if ((mode == singleMode || (mode == symbolMode && !(rootEntry->flags & MENU_ROOT))) &&
rootEntry->sym && rootEntry->prompt) {
item = last ? last->nextSibling() : nullptr;
if (!item)
- item = new ConfigItem(this, last, rootEntry, true);
+ item = new ConfigItem(this, last, rootEntry);
else
- item->testUpdateMenu(true);
+ item->testUpdateMenu();
updateMenuList(item, rootEntry);
update();
@@ -480,7 +492,7 @@ void ConfigList::updateListAllForAll()
while (it.hasNext()) {
ConfigList *list = it.next();
- list->updateList();
+ list->updateListAll();
}
}
@@ -571,7 +583,7 @@ void ConfigList::setParentMenu(void)
oldroot = rootEntry;
if (rootEntry == &rootmenu)
return;
- setRootMenu(menu_get_parent_menu(rootEntry->parent));
+ setRootMenu(menu_get_menu_or_parent_menu(rootEntry->parent));
QTreeWidgetItemIterator it(this);
while (*it) {
@@ -598,7 +610,6 @@ void ConfigList::updateMenuList(ConfigItem *parent, struct menu* menu)
struct menu* child;
ConfigItem* item;
ConfigItem* last;
- bool visible;
enum prop_type type;
if (!menu) {
@@ -630,14 +641,13 @@ void ConfigList::updateMenuList(ConfigItem *parent, struct menu* menu)
break;
}
- visible = menu_is_visible(child);
if (!menuSkip(child)) {
if (!child->sym && !child->list && !child->prompt)
continue;
if (!item || item->menu != child)
- item = new ConfigItem(parent, last, child, visible);
+ item = new ConfigItem(parent, last, child);
else
- item->testUpdateMenu(visible);
+ item->testUpdateMenu();
if (mode == fullMode || mode == menuMode || type != P_MENU)
updateMenuList(item, child);
@@ -663,7 +673,6 @@ void ConfigList::updateMenuList(struct menu *menu)
struct menu* child;
ConfigItem* item;
ConfigItem* last;
- bool visible;
enum prop_type type;
if (!menu) {
@@ -695,14 +704,13 @@ void ConfigList::updateMenuList(struct menu *menu)
break;
}
- visible = menu_is_visible(child);
if (!menuSkip(child)) {
if (!child->sym && !child->list && !child->prompt)
continue;
if (!item || item->menu != child)
- item = new ConfigItem(this, last, child, visible);
+ item = new ConfigItem(this, last, child);
else
- item->testUpdateMenu(visible);
+ item->testUpdateMenu();
if (mode == fullMode || mode == menuMode || type != P_MENU)
updateMenuList(item, child);
@@ -730,7 +738,7 @@ void ConfigList::keyPressEvent(QKeyEvent* ev)
struct menu *menu;
enum prop_type type;
- if (ev->key() == Qt::Key_Escape && mode != fullMode && mode != listMode) {
+ if (ev->key() == Qt::Key_Escape && mode == singleMode) {
emit parentSelected();
ev->accept();
return;
@@ -780,13 +788,6 @@ void ConfigList::keyPressEvent(QKeyEvent* ev)
ev->accept();
}
-void ConfigList::mousePressEvent(QMouseEvent* e)
-{
- //QPoint p(contentsToViewport(e->pos()));
- //printf("contentsMousePressEvent: %d,%d\n", p.x(), p.y());
- Parent::mousePressEvent(e);
-}
-
void ConfigList::mouseReleaseEvent(QMouseEvent* e)
{
QPoint p = e->pos();
@@ -833,13 +834,6 @@ skip:
Parent::mouseReleaseEvent(e);
}
-void ConfigList::mouseMoveEvent(QMouseEvent* e)
-{
- //QPoint p(contentsToViewport(e->pos()));
- //printf("contentsMouseMoveEvent: %d,%d\n", p.x(), p.y());
- Parent::mouseMoveEvent(e);
-}
-
void ConfigList::mouseDoubleClickEvent(QMouseEvent* e)
{
QPoint p = e->pos();
@@ -1021,7 +1015,7 @@ void ConfigInfoView::menuInfo(void)
if (sym->name) {
stream << " (";
if (showDebug())
- stream << "<a href=\"s" << sym->name << "\">";
+ stream << "<a href=\"" << sym->name << "\">";
stream << print_filter(sym->name);
if (showDebug())
stream << "</a>";
@@ -1030,7 +1024,7 @@ void ConfigInfoView::menuInfo(void)
} else if (sym->name) {
stream << "<big><b>";
if (showDebug())
- stream << "<a href=\"s" << sym->name << "\">";
+ stream << "<a href=\"" << sym->name << "\">";
stream << print_filter(sym->name);
if (showDebug())
stream << "</a>";
@@ -1085,30 +1079,21 @@ QString ConfigInfoView::debug_info(struct symbol *sym)
switch (prop->type) {
case P_PROMPT:
case P_MENU:
- stream << "prompt: <a href=\"m" << sym->name << "\">";
+ stream << "prompt: ";
stream << print_filter(prop->text);
- stream << "</a><br>";
+ stream << "<br>";
break;
case P_DEFAULT:
case P_SELECT:
case P_RANGE:
case P_COMMENT:
case P_IMPLY:
- case P_SYMBOL:
stream << prop_get_type_name(prop->type);
stream << ": ";
expr_print(prop->expr, expr_print_help,
&stream, E_NONE);
stream << "<br>";
break;
- case P_CHOICE:
- if (sym_is_choice(sym)) {
- stream << "choice: ";
- expr_print(prop->expr, expr_print_help,
- &stream, E_NONE);
- stream << "<br>";
- }
- break;
default:
stream << "unknown property: ";
stream << prop_get_type_name(prop->type);
@@ -1130,28 +1115,19 @@ QString ConfigInfoView::print_filter(const QString &str)
{
QRegularExpression re("[<>&\"\\n]");
QString res = str;
+
+ QHash<QChar, QString> patterns;
+ patterns['<'] = "&lt;";
+ patterns['>'] = "&gt;";
+ patterns['&'] = "&amp;";
+ patterns['"'] = "&quot;";
+ patterns['\n'] = "<br>";
+
for (int i = 0; (i = res.indexOf(re, i)) >= 0;) {
- switch (res[i].toLatin1()) {
- case '<':
- res.replace(i, 1, "&lt;");
- i += 4;
- break;
- case '>':
- res.replace(i, 1, "&gt;");
- i += 4;
- break;
- case '&':
- res.replace(i, 1, "&amp;");
- i += 5;
- break;
- case '"':
- res.replace(i, 1, "&quot;");
- i += 6;
- break;
- case '\n':
- res.replace(i, 1, "<br>");
- i += 4;
- break;
+ const QString n = patterns.value(res[i], QString());
+ if (!n.isEmpty()) {
+ res.replace(i, 1, n);
+ i += n.length();
}
}
return res;
@@ -1162,7 +1138,7 @@ void ConfigInfoView::expr_print_help(void *data, struct symbol *sym, const char
QTextStream *stream = reinterpret_cast<QTextStream *>(data);
if (sym && sym->name && !(sym->flags & SYMBOL_CONST)) {
- *stream << "<a href=\"s" << sym->name << "\">";
+ *stream << "<a href=\"" << sym->name << "\">";
*stream << print_filter(str);
*stream << "</a>";
} else {
@@ -1172,39 +1148,11 @@ void ConfigInfoView::expr_print_help(void *data, struct symbol *sym, const char
void ConfigInfoView::clicked(const QUrl &url)
{
- QByteArray str = url.toEncoded();
- const std::size_t count = str.size();
- char *data = new char[count + 1];
- struct symbol **result;
- struct menu *m = NULL;
-
- if (count < 1) {
- delete[] data;
- return;
- }
-
- memcpy(data, str.constData(), count);
- data[count] = '\0';
-
- /* Seek for exact match */
- data[0] = '^';
- strcat(data, "$");
- result = sym_re_search(data);
- if (!result) {
- delete[] data;
- return;
- }
+ struct menu *m;
- sym = *result;
-
- /* Seek for the menu which holds the symbol */
- for (struct property *prop = sym->prop; prop; prop = prop->next) {
- if (prop->type != P_PROMPT && prop->type != P_MENU)
- continue;
- m = prop->menu;
- break;
- }
+ sym = sym_find(url.toEncoded().constData());
+ m = sym_get_prompt_menu(sym);
if (!m) {
/* Symbol is not visible as a menu */
symbolInfo();
@@ -1212,9 +1160,6 @@ void ConfigInfoView::clicked(const QUrl &url)
} else {
emit menuSelected(m);
}
-
- free(result);
- delete[] data;
}
void ConfigInfoView::contextMenuEvent(QContextMenuEvent *event)
@@ -1248,8 +1193,7 @@ ConfigSearchWindow::ConfigSearchWindow(ConfigMainWindow *parent)
layout2->addWidget(searchButton);
layout1->addLayout(layout2);
- split = new QSplitter(this);
- split->setOrientation(Qt::Vertical);
+ split = new QSplitter(Qt::Vertical, this);
list = new ConfigList(split, "search");
list->mode = listMode;
info = new ConfigInfoView(split, "search");
@@ -1308,8 +1252,7 @@ void ConfigSearchWindow::search(void)
return;
for (p = result; *p; p++) {
for_all_prompts((*p), prop)
- lastItem = new ConfigItem(list, lastItem, prop->menu,
- menu_is_visible(prop->menu));
+ lastItem = new ConfigItem(list, lastItem, prop->menu);
}
}
@@ -1349,63 +1292,56 @@ ConfigMainWindow::ConfigMainWindow(void)
ConfigItem::menubackIcon = QIcon(QPixmap(xpm_menuback));
QWidget *widget = new QWidget(this);
- QVBoxLayout *layout = new QVBoxLayout(widget);
setCentralWidget(widget);
- split1 = new QSplitter(widget);
- split1->setOrientation(Qt::Horizontal);
- split1->setChildrenCollapsible(false);
-
- menuList = new ConfigList(widget, "menu");
+ QVBoxLayout *layout = new QVBoxLayout(widget);
- split2 = new QSplitter(widget);
+ split2 = new QSplitter(Qt::Vertical, widget);
+ layout->addWidget(split2);
split2->setChildrenCollapsible(false);
- split2->setOrientation(Qt::Vertical);
- // create config tree
- configList = new ConfigList(widget, "config");
+ split1 = new QSplitter(Qt::Horizontal, split2);
+ split1->setChildrenCollapsible(false);
- helpText = new ConfigInfoView(widget, "help");
+ configList = new ConfigList(split1, "config");
- layout->addWidget(split2);
- split2->addWidget(split1);
- split1->addWidget(configList);
- split1->addWidget(menuList);
- split2->addWidget(helpText);
+ menuList = new ConfigList(split1, "menu");
+ helpText = new ConfigInfoView(split2, "help");
setTabOrder(configList, helpText);
+
configList->setFocus();
backAction = new QAction(QPixmap(xpm_back), "Back", this);
+ backAction->setShortcut(QKeySequence::Back);
connect(backAction, &QAction::triggered,
this, &ConfigMainWindow::goBack);
QAction *quitAction = new QAction("&Quit", this);
- quitAction->setShortcut(Qt::CTRL | Qt::Key_Q);
+ quitAction->setShortcut(QKeySequence::Quit);
connect(quitAction, &QAction::triggered,
this, &ConfigMainWindow::close);
- QAction *loadAction = new QAction(QPixmap(xpm_load), "&Load", this);
- loadAction->setShortcut(Qt::CTRL | Qt::Key_L);
+ QAction *loadAction = new QAction(QPixmap(xpm_load), "&Open", this);
+ loadAction->setShortcut(QKeySequence::Open);
connect(loadAction, &QAction::triggered,
this, &ConfigMainWindow::loadConfig);
saveAction = new QAction(QPixmap(xpm_save), "&Save", this);
- saveAction->setShortcut(Qt::CTRL | Qt::Key_S);
+ saveAction->setShortcut(QKeySequence::Save);
connect(saveAction, &QAction::triggered,
this, &ConfigMainWindow::saveConfig);
conf_set_changed_callback(conf_changed);
- // Set saveAction's initial state
- conf_changed();
- configname = xstrdup(conf_get_configname());
+ configname = conf_get_configname();
QAction *saveAsAction = new QAction("Save &As...", this);
+ saveAsAction->setShortcut(QKeySequence::SaveAs);
connect(saveAsAction, &QAction::triggered,
this, &ConfigMainWindow::saveConfigAs);
QAction *searchAction = new QAction("&Find", this);
- searchAction->setShortcut(Qt::CTRL | Qt::Key_F);
+ searchAction->setShortcut(QKeySequence::Find);
connect(searchAction, &QAction::triggered,
this, &ConfigMainWindow::searchConfig);
singleViewAction = new QAction(QPixmap(xpm_single_view), "Single View", this);
@@ -1441,6 +1377,19 @@ ConfigMainWindow::ConfigMainWindow(void)
ConfigList::showPromptAction = new QAction("Show Prompt Options", optGroup);
ConfigList::showPromptAction->setCheckable(true);
+ switch (configList->optMode) {
+ case allOpt:
+ ConfigList::showAllAction->setChecked(true);
+ break;
+ case promptOpt:
+ ConfigList::showPromptAction->setChecked(true);
+ break;
+ case normalOpt:
+ default:
+ ConfigList::showNormalAction->setChecked(true);
+ break;
+ }
+
QAction *showDebugAction = new QAction("Show Debug Info", this);
showDebugAction->setCheckable(true);
connect(showDebugAction, &QAction::toggled,
@@ -1515,6 +1464,11 @@ ConfigMainWindow::ConfigMainWindow(void)
connect(helpText, &ConfigInfoView::menuSelected,
this, &ConfigMainWindow::setMenuLink);
+ connect(configApp, &QApplication::aboutToQuit,
+ this, &ConfigMainWindow::saveSettings);
+
+ conf_read(NULL);
+
QString listMode = configSettings->value("/listMode", "symbol").toString();
if (listMode == "single")
showSingleView();
@@ -1536,28 +1490,22 @@ ConfigMainWindow::ConfigMainWindow(void)
void ConfigMainWindow::loadConfig(void)
{
QString str;
- QByteArray ba;
- const char *name;
- str = QFileDialog::getOpenFileName(this, "", configname);
- if (str.isNull())
+ str = QFileDialog::getOpenFileName(this, QString(), configname);
+ if (str.isEmpty())
return;
- ba = str.toLocal8Bit();
- name = ba.data();
-
- if (conf_read(name))
+ if (conf_read(str.toLocal8Bit().constData()))
QMessageBox::information(this, "qconf", "Unable to load configuration!");
- free(configname);
- configname = xstrdup(name);
+ configname = str;
ConfigList::updateListAllForAll();
}
bool ConfigMainWindow::saveConfig(void)
{
- if (conf_write(configname)) {
+ if (conf_write(configname.toLocal8Bit().constData())) {
QMessageBox::information(this, "qconf", "Unable to save configuration!");
return false;
}
@@ -1569,23 +1517,17 @@ bool ConfigMainWindow::saveConfig(void)
void ConfigMainWindow::saveConfigAs(void)
{
QString str;
- QByteArray ba;
- const char *name;
- str = QFileDialog::getSaveFileName(this, "", configname);
- if (str.isNull())
+ str = QFileDialog::getSaveFileName(this, QString(), configname);
+ if (str.isEmpty())
return;
- ba = str.toLocal8Bit();
- name = ba.data();
-
- if (conf_write(name)) {
+ if (conf_write(str.toLocal8Bit().constData())) {
QMessageBox::information(this, "qconf", "Unable to save configuration!");
}
conf_write_autoconf(0);
- free(configname);
- configname = xstrdup(name);
+ configname = str;
}
void ConfigMainWindow::searchConfig(void)
@@ -1617,7 +1559,7 @@ void ConfigMainWindow::setMenuLink(struct menu *menu)
switch (configList->mode) {
case singleMode:
list = configList;
- parent = menu_get_parent_menu(menu);
+ parent = menu_get_menu_or_parent_menu(menu);
if (!parent)
return;
list->setRootMenu(parent);
@@ -1628,7 +1570,7 @@ void ConfigMainWindow::setMenuLink(struct menu *menu)
configList->clearSelection();
list = configList;
} else {
- parent = menu_get_parent_menu(menu->parent);
+ parent = menu_get_menu_or_parent_menu(menu->parent);
if (!parent)
return;
@@ -1670,9 +1612,6 @@ void ConfigMainWindow::listFocusChanged(void)
void ConfigMainWindow::goBack(void)
{
- if (configList->rootEntry == &rootmenu)
- return;
-
configList->setParentMenu();
}
@@ -1851,10 +1790,10 @@ void ConfigMainWindow::saveSettings(void)
configSettings->writeSizes("/split2", split2->sizes());
}
-void ConfigMainWindow::conf_changed(void)
+void ConfigMainWindow::conf_changed(bool dirty)
{
if (saveAction)
- saveAction->setEnabled(conf_get_changed());
+ saveAction->setEnabled(dirty);
}
void fixup_rootmenu(struct menu *menu)
@@ -1904,22 +1843,18 @@ int main(int ac, char** av)
conf_parse(name);
fixup_rootmenu(&rootmenu);
- conf_read(NULL);
//zconfdump(stdout);
configApp = new QApplication(ac, av);
configSettings = new ConfigSettings();
- configSettings->beginGroup("/kconfig/qconf");
v = new ConfigMainWindow();
//zconfdump(stdout);
- configApp->connect(configApp, SIGNAL(lastWindowClosed()), SLOT(quit()));
- configApp->connect(configApp, SIGNAL(aboutToQuit()), v, SLOT(saveSettings()));
+
v->show();
configApp->exec();
- configSettings->endGroup();
delete configSettings;
delete v;
delete configApp;
diff --git a/scripts/kconfig/qconf.h b/scripts/kconfig/qconf.h
index 78b0a1dfcd53..ab4e51f12914 100644
--- a/scripts/kconfig/qconf.h
+++ b/scripts/kconfig/qconf.h
@@ -24,6 +24,7 @@ class ConfigMainWindow;
class ConfigSettings : public QSettings {
public:
ConfigSettings();
+ ~ConfigSettings(void);
QList<int> readSizes(const QString& key, bool *ok);
bool writeSizes(const QString& key, const QList<int>& value);
};
@@ -55,9 +56,7 @@ public:
protected:
void keyPressEvent(QKeyEvent *e);
- void mousePressEvent(QMouseEvent *e);
void mouseReleaseEvent(QMouseEvent *e);
- void mouseMoveEvent(QMouseEvent *e);
void mouseDoubleClickEvent(QMouseEvent *e);
void focusInEvent(QFocusEvent *e);
void contextMenuEvent(QContextMenuEvent *e);
@@ -116,25 +115,25 @@ public:
class ConfigItem : public QTreeWidgetItem {
typedef class QTreeWidgetItem Parent;
public:
- ConfigItem(ConfigList *parent, ConfigItem *after, struct menu *m, bool v)
- : Parent(parent, after), nextItem(0), menu(m), visible(v), goParent(false)
+ ConfigItem(ConfigList *parent, ConfigItem *after, struct menu *m)
+ : Parent(parent, after), nextItem(0), menu(m), goParent(false)
{
init();
}
- ConfigItem(ConfigItem *parent, ConfigItem *after, struct menu *m, bool v)
- : Parent(parent, after), nextItem(0), menu(m), visible(v), goParent(false)
+ ConfigItem(ConfigItem *parent, ConfigItem *after, struct menu *m)
+ : Parent(parent, after), nextItem(0), menu(m), goParent(false)
{
init();
}
- ConfigItem(ConfigList *parent, ConfigItem *after, bool v)
- : Parent(parent, after), nextItem(0), menu(0), visible(v), goParent(true)
+ ConfigItem(ConfigList *parent, ConfigItem *after)
+ : Parent(parent, after), nextItem(0), menu(0), goParent(true)
{
init();
}
~ConfigItem(void);
void init(void);
void updateMenu(void);
- void testUpdateMenu(bool v);
+ void testUpdateMenu(void);
ConfigList* listView() const
{
return (ConfigList*)Parent::treeWidget();
@@ -161,7 +160,6 @@ public:
ConfigItem* nextItem;
struct menu *menu;
- bool visible;
bool goParent;
static QIcon symbolYesIcon, symbolModIcon, symbolNoIcon;
@@ -237,9 +235,9 @@ protected:
class ConfigMainWindow : public QMainWindow {
Q_OBJECT
- char *configname;
+ QString configname;
static QAction *saveAction;
- static void conf_changed(void);
+ static void conf_changed(bool);
public:
ConfigMainWindow(void);
public slots:
diff --git a/scripts/kconfig/streamline_config.pl b/scripts/kconfig/streamline_config.pl
index d51cd7ac15d2..8e23faab5d22 100755
--- a/scripts/kconfig/streamline_config.pl
+++ b/scripts/kconfig/streamline_config.pl
@@ -144,6 +144,7 @@ my %selects;
my %prompts;
my %objects;
my %config2kfile;
+my %defaults;
my $var;
my $iflevel = 0;
my @ifdeps;
@@ -220,8 +221,9 @@ sub read_kconfig {
$depends{$config} = $1;
} elsif ($state eq "DEP" && /^\s*depends\s+on\s+(.*)$/) {
$depends{$config} .= " " . $1;
- } elsif ($state eq "DEP" && /^\s*def(_(bool|tristate)|ault)\s+(\S.*)$/) {
+ } elsif ($state ne "NONE" && /^\s*def(_(bool|tristate)|ault)\s+(\S.*)$/) {
my $dep = $3;
+ $defaults{$config} = 1;
if ($dep !~ /^\s*(y|m|n)\s*$/) {
$dep =~ s/.*\sif\s+//;
$depends{$config} .= " " . $dep;
@@ -503,7 +505,7 @@ sub parse_config_selects
# Check if something other than a module selects this config
if (defined($orig_configs{$conf}) && $orig_configs{$conf} ne "m") {
- dprint "$conf (non module) selects config, we are good\n";
+ dprint "$conf (non module) selects $config, we are good\n";
# we are good with this
return;
}
@@ -523,8 +525,16 @@ sub parse_config_selects
# If no possible config selected this, then something happened.
if (!defined($next_config)) {
- print STDERR "WARNING: $config is required, but nothing in the\n";
- print STDERR " current config selects it.\n";
+
+ # Some config options have no prompt, and nothing selects them, but
+ # they stay turned on once the final checks for the configs
+ # are done. These configs have a default option, so turn off the
+ # warnings for configs with default options.
+ if (!defined($defaults{$config})) {
+ print STDERR "WARNING: $config is required, but nothing in the\n";
+ print STDERR " current config selects it.\n";
+ }
+
return;
}
diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c
index 0e439d3d48d1..7e81b3676ee9 100644
--- a/scripts/kconfig/symbol.c
+++ b/scripts/kconfig/symbol.c
@@ -9,6 +9,8 @@
#include <string.h>
#include <regex.h>
+#include <hash.h>
+#include <xalloc.h>
#include "internal.h"
#include "lkc.h"
@@ -40,16 +42,12 @@ struct symbol *modules_sym;
static tristate modules_val;
static int sym_warnings;
-enum symbol_type sym_get_type(struct symbol *sym)
+enum symbol_type sym_get_type(const struct symbol *sym)
{
enum symbol_type type = sym->type;
- if (type == S_TRISTATE) {
- if (sym_is_choice_value(sym) && sym->visible == yes)
- type = S_BOOLEAN;
- else if (modules_val == no)
- type = S_BOOLEAN;
- }
+ if (type == S_TRISTATE && modules_val == no)
+ type = S_BOOLEAN;
return type;
}
@@ -72,12 +70,21 @@ const char *sym_type_name(enum symbol_type type)
return "???";
}
-struct property *sym_get_choice_prop(struct symbol *sym)
+/**
+ * sym_get_prompt_menu - get the menu entry with a prompt
+ *
+ * @sym: a symbol pointer
+ *
+ * Return: the menu entry with a prompt.
+ */
+struct menu *sym_get_prompt_menu(const struct symbol *sym)
{
- struct property *prop;
+ struct menu *m;
+
+ list_for_each_entry(m, &sym->menus, link)
+ if (m->prompt)
+ return m;
- for_all_choices(sym, prop)
- return prop;
return NULL;
}
@@ -88,21 +95,15 @@ struct property *sym_get_choice_prop(struct symbol *sym)
*
* Return: a choice menu if this function is called against a choice member.
*/
-struct menu *sym_get_choice_menu(struct symbol *sym)
+struct menu *sym_get_choice_menu(const struct symbol *sym)
{
struct menu *menu = NULL;
- struct menu *m;
/*
* Choice members must have a prompt. Find a menu entry with a prompt,
* and assume it resides inside a choice block.
*/
- list_for_each_entry(m, &sym->menus, link)
- if (m->prompt) {
- menu = m;
- break;
- }
-
+ menu = sym_get_prompt_menu(sym);
if (!menu)
return NULL;
@@ -192,9 +193,12 @@ static void sym_set_changed(struct symbol *sym)
{
struct menu *menu;
- sym->flags |= SYMBOL_CHANGED;
list_for_each_entry(menu, &sym->menus, link)
menu->flags |= MENU_CHANGED;
+
+ menu = sym_get_choice_menu(sym);
+ if (menu)
+ menu->flags |= MENU_CHANGED;
}
static void sym_set_all_changed(void)
@@ -208,26 +212,17 @@ static void sym_set_all_changed(void)
static void sym_calc_visibility(struct symbol *sym)
{
struct property *prop;
- struct symbol *choice_sym = NULL;
tristate tri;
+ if (sym->flags & SYMBOL_TRANS) {
+ sym->visible = yes;
+ return;
+ }
+
/* any prompt visible? */
tri = no;
-
- if (sym_is_choice_value(sym))
- choice_sym = prop_get_symbol(sym_get_choice_prop(sym));
-
for_all_prompts(sym, prop) {
prop->visible.tri = expr_calc_value(prop->visible.expr);
- /*
- * Tristate choice_values with visibility 'mod' are
- * not visible if the corresponding choice's value is
- * 'yes'.
- */
- if (choice_sym && sym->type == S_TRISTATE &&
- prop->visible.tri == mod && choice_sym->curr.tri == yes)
- prop->visible.tri = no;
-
tri = EXPR_OR(tri, prop->visible.tri);
}
if (tri == mod && (sym->type != S_TRISTATE || modules_val == no))
@@ -274,14 +269,14 @@ static void sym_calc_visibility(struct symbol *sym)
* Next locate the first visible choice value
* Return NULL if none was found
*/
-struct symbol *sym_choice_default(struct symbol *sym)
+struct symbol *sym_choice_default(struct menu *choice)
{
+ struct menu *menu;
struct symbol *def_sym;
struct property *prop;
- struct expr *e;
/* any of the defaults visible? */
- for_all_defaults(sym, prop) {
+ for_all_defaults(choice->sym, prop) {
prop->visible.tri = expr_calc_value(prop->visible.expr);
if (prop->visible.tri == no)
continue;
@@ -291,48 +286,99 @@ struct symbol *sym_choice_default(struct symbol *sym)
}
/* just get the first visible value */
- prop = sym_get_choice_prop(sym);
- expr_list_for_each_sym(prop->expr, e, def_sym)
- if (def_sym->visible != no)
- return def_sym;
+ menu_for_each_sub_entry(menu, choice)
+ if (menu->sym && menu->sym->visible != no)
+ return menu->sym;
/* failed to locate any defaults */
return NULL;
}
-static struct symbol *sym_calc_choice(struct symbol *sym)
+/*
+ * sym_calc_choice - calculate symbol values in a choice
+ *
+ * @choice: a menu of the choice
+ *
+ * Return: a chosen symbol
+ */
+struct symbol *sym_calc_choice(struct menu *choice)
{
- struct symbol *def_sym;
- struct property *prop;
- struct expr *e;
- int flags;
-
- /* first calculate all choice values' visibilities */
- flags = sym->flags;
- prop = sym_get_choice_prop(sym);
- expr_list_for_each_sym(prop->expr, e, def_sym) {
- sym_calc_visibility(def_sym);
- if (def_sym->visible != no)
- flags &= def_sym->flags;
+ struct symbol *res = NULL;
+ struct symbol *sym;
+ struct menu *menu;
+
+ /* Traverse the list of choice members in the priority order. */
+ list_for_each_entry(sym, &choice->choice_members, choice_link) {
+ sym_calc_visibility(sym);
+ if (sym->visible == no)
+ continue;
+
+ /* The first visible symble with the user value 'y'. */
+ if (sym_has_value(sym) && sym->def[S_DEF_USER].tri == yes) {
+ res = sym;
+ break;
+ }
}
- sym->flags &= flags | ~SYMBOL_DEF_USER;
+ /*
+ * If 'y' is not found in the user input, use the default, unless it is
+ * explicitly set to 'n'.
+ */
+ if (!res) {
+ res = sym_choice_default(choice);
+ if (res && sym_has_value(res) && res->def[S_DEF_USER].tri == no)
+ res = NULL;
+ }
- /* is the user choice visible? */
- def_sym = sym->def[S_DEF_USER].val;
- if (def_sym && def_sym->visible != no)
- return def_sym;
+ /* Still not found. Pick up the first visible, user-unspecified symbol. */
+ if (!res) {
+ menu_for_each_sub_entry(menu, choice) {
+ sym = menu->sym;
- def_sym = sym_choice_default(sym);
+ if (!sym || sym->visible == no || sym_has_value(sym))
+ continue;
- if (def_sym == NULL)
- /* no choice? reset tristate value */
- sym->curr.tri = no;
+ res = sym;
+ break;
+ }
+ }
+
+ /*
+ * Still not found. Traverse the linked list in the _reverse_ order to
+ * pick up the least prioritized 'n'.
+ */
+ if (!res) {
+ list_for_each_entry_reverse(sym, &choice->choice_members,
+ choice_link) {
+ if (sym->visible == no)
+ continue;
+
+ res = sym;
+ break;
+ }
+ }
+
+ menu_for_each_sub_entry(menu, choice) {
+ tristate val;
+
+ sym = menu->sym;
+
+ if (!sym || sym->visible == no)
+ continue;
- return def_sym;
+ val = sym == res ? yes : no;
+
+ if (sym->curr.tri != val)
+ sym_set_changed(sym);
+
+ sym->curr.tri = val;
+ sym->flags |= SYMBOL_VALID | SYMBOL_WRITE;
+ }
+
+ return res;
}
-static void sym_warn_unmet_dep(struct symbol *sym)
+static void sym_warn_unmet_dep(const struct symbol *sym)
{
struct gstr gs = str_new();
@@ -351,6 +397,7 @@ static void sym_warn_unmet_dep(struct symbol *sym)
" Selected by [m]:\n");
fputs(str_get(&gs), stderr);
+ str_free(&gs);
sym_warnings++;
}
@@ -364,8 +411,8 @@ bool sym_dep_errors(void)
void sym_calc_value(struct symbol *sym)
{
struct symbol_value newval, oldval;
- struct property *prop;
- struct expr *e;
+ struct property *prop = NULL;
+ struct menu *choice_menu;
if (!sym)
return;
@@ -373,13 +420,6 @@ void sym_calc_value(struct symbol *sym)
if (sym->flags & SYMBOL_VALID)
return;
- if (sym_is_choice_value(sym) &&
- sym->flags & SYMBOL_NEED_SET_CHOICE_VALUES) {
- sym->flags &= ~SYMBOL_NEED_SET_CHOICE_VALUES;
- prop = sym_get_choice_prop(sym);
- sym_calc_value(prop_get_symbol(prop));
- }
-
sym->flags |= SYMBOL_VALID;
oldval = sym->curr;
@@ -418,9 +458,11 @@ void sym_calc_value(struct symbol *sym)
switch (sym_get_type(sym)) {
case S_BOOLEAN:
case S_TRISTATE:
- if (sym_is_choice_value(sym) && sym->visible == yes) {
- prop = sym_get_choice_prop(sym);
- newval.tri = (prop_get_symbol(prop)->curr.val == sym) ? yes : no;
+ choice_menu = sym_get_choice_menu(sym);
+
+ if (choice_menu) {
+ sym_calc_choice(choice_menu);
+ newval.tri = sym->curr.tri;
} else {
if (sym->visible != no) {
/* if the symbol is visible use the user value
@@ -478,9 +520,20 @@ void sym_calc_value(struct symbol *sym)
;
}
+ /*
+ * If the symbol lacks a user value but its value comes from a
+ * single transitional symbol with an existing user value, mark
+ * this symbol as having a user value to avoid prompting.
+ */
+ if (prop && !sym_has_value(sym)) {
+ struct symbol *ds = prop_get_symbol(prop);
+ if (ds && (ds->flags & SYMBOL_TRANS) && sym_has_value(ds)) {
+ sym->def[S_DEF_USER] = newval;
+ sym->flags |= SYMBOL_DEF_USER;
+ }
+ }
+
sym->curr = newval;
- if (sym_is_choice(sym) && newval.tri == yes)
- sym->curr.val = sym_calc_choice(sym);
sym_validate_range(sym);
if (memcmp(&oldval, &sym->curr, sizeof(oldval))) {
@@ -491,23 +544,8 @@ void sym_calc_value(struct symbol *sym)
}
}
- if (sym_is_choice(sym)) {
- struct symbol *choice_sym;
-
- prop = sym_get_choice_prop(sym);
- expr_list_for_each_sym(prop->expr, e, choice_sym) {
- if ((sym->flags & SYMBOL_WRITE) &&
- choice_sym->visible != no)
- choice_sym->flags |= SYMBOL_WRITE;
- if (sym->flags & SYMBOL_CHANGED)
- sym_set_changed(choice_sym);
- }
-
+ if (sym_is_choice(sym) || sym->flags & SYMBOL_TRANS)
sym->flags &= ~SYMBOL_WRITE;
- }
-
- if (sym->flags & SYMBOL_NEED_SET_CHOICE_VALUES)
- set_all_choice_values(sym);
}
void sym_clear_all_valid(void)
@@ -516,11 +554,12 @@ void sym_clear_all_valid(void)
for_all_symbols(sym)
sym->flags &= ~SYMBOL_VALID;
+ expr_invalidate_all();
conf_set_changed(true);
sym_calc_value(modules_sym);
}
-bool sym_tristate_within_range(struct symbol *sym, tristate val)
+bool sym_tristate_within_range(const struct symbol *sym, tristate val)
{
int type = sym_get_type(sym);
@@ -534,8 +573,6 @@ bool sym_tristate_within_range(struct symbol *sym, tristate val)
return false;
if (sym->visible <= sym->rev_dep.tri)
return false;
- if (sym_is_choice_value(sym) && sym->visible == yes)
- return val == yes;
return val >= sym->rev_dep.tri && val <= sym->visible;
}
@@ -543,42 +580,75 @@ bool sym_set_tristate_value(struct symbol *sym, tristate val)
{
tristate oldval = sym_get_tristate_value(sym);
- if (oldval != val && !sym_tristate_within_range(sym, val))
+ if (!sym_tristate_within_range(sym, val))
return false;
- if (!(sym->flags & SYMBOL_DEF_USER)) {
+ if (!(sym->flags & SYMBOL_DEF_USER) || sym->def[S_DEF_USER].tri != val) {
+ sym->def[S_DEF_USER].tri = val;
sym->flags |= SYMBOL_DEF_USER;
sym_set_changed(sym);
}
- /*
- * setting a choice value also resets the new flag of the choice
- * symbol and all other choice values.
- */
- if (sym_is_choice_value(sym) && val == yes) {
- struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
- struct property *prop;
- struct expr *e;
-
- cs->def[S_DEF_USER].val = sym;
- cs->flags |= SYMBOL_DEF_USER;
- prop = sym_get_choice_prop(cs);
- for (e = prop->expr; e; e = e->left.expr) {
- if (e->right.sym->visible != no)
- e->right.sym->flags |= SYMBOL_DEF_USER;
- }
- }
- sym->def[S_DEF_USER].tri = val;
if (oldval != val)
sym_clear_all_valid();
return true;
}
+/**
+ * choice_set_value - set the user input to a choice
+ *
+ * @choice: menu entry for the choice
+ * @sym: selected symbol
+ */
+void choice_set_value(struct menu *choice, struct symbol *sym)
+{
+ struct menu *menu;
+ bool changed = false;
+
+ menu_for_each_sub_entry(menu, choice) {
+ tristate val;
+
+ if (!menu->sym)
+ continue;
+
+ if (menu->sym->visible == no)
+ continue;
+
+ val = menu->sym == sym ? yes : no;
+
+ if (menu->sym->curr.tri != val)
+ changed = true;
+
+ menu->sym->def[S_DEF_USER].tri = val;
+ menu->sym->flags |= SYMBOL_DEF_USER;
+
+ /*
+ * Now, the user has explicitly enabled or disabled this symbol,
+ * it should be given the highest priority. We are possibly
+ * setting multiple symbols to 'n', where the first symbol is
+ * given the least prioritized 'n'. This works well when the
+ * choice block ends up with selecting 'n' symbol.
+ * (see sym_calc_choice())
+ */
+ list_move(&menu->sym->choice_link, &choice->choice_members);
+ }
+
+ if (changed)
+ sym_clear_all_valid();
+}
+
tristate sym_toggle_tristate_value(struct symbol *sym)
{
+ struct menu *choice;
tristate oldval, newval;
+ choice = sym_get_choice_menu(sym);
+ if (choice) {
+ choice_set_value(choice, sym);
+ return yes;
+ }
+
oldval = newval = sym_get_tristate_value(sym);
do {
switch (newval) {
@@ -831,12 +901,17 @@ const char *sym_get_string_value(struct symbol *sym)
default:
;
}
- return (const char *)sym->curr.val;
+ return sym->curr.val;
}
-bool sym_is_changeable(struct symbol *sym)
+bool sym_is_changeable(const struct symbol *sym)
{
- return sym->visible > sym->rev_dep.tri;
+ return !sym_is_choice(sym) && sym->visible > sym->rev_dep.tri;
+}
+
+bool sym_is_choice_value(const struct symbol *sym)
+{
+ return !list_empty(&sym->choice_link);
}
HASHTABLE_DEFINE(sym_hashtable, SYMBOL_HASHSIZE);
@@ -855,7 +930,7 @@ struct symbol *sym_lookup(const char *name, int flags)
case 'n': return &symbol_no;
}
}
- hash = strhash(name);
+ hash = hash_str(name);
hash_for_each_possible(sym_hashtable, symbol, node, hash) {
if (symbol->name &&
@@ -876,6 +951,7 @@ struct symbol *sym_lookup(const char *name, int flags)
symbol->type = S_UNKNOWN;
symbol->flags = flags;
INIT_LIST_HEAD(&symbol->menus);
+ INIT_LIST_HEAD(&symbol->choice_link);
hash_add(sym_hashtable, &symbol->node, hash);
@@ -897,7 +973,7 @@ struct symbol *sym_find(const char *name)
case 'n': return &symbol_no;
}
}
- hash = strhash(name);
+ hash = hash_str(name);
hash_for_each_possible(sym_hashtable, symbol, node, hash) {
if (symbol->name &&
@@ -1036,13 +1112,14 @@ static void sym_check_print_recursive(struct symbol *last_sym)
{
struct dep_stack *stack;
struct symbol *sym, *next_sym;
- struct menu *menu = NULL;
- struct property *prop;
+ struct menu *choice;
struct dep_stack cv_stack;
+ enum prop_type type;
- if (sym_is_choice_value(last_sym)) {
+ choice = sym_get_choice_menu(last_sym);
+ if (choice) {
dep_stack_insert(&cv_stack, last_sym);
- last_sym = prop_get_symbol(sym_get_choice_prop(last_sym));
+ last_sym = choice->sym;
}
for (stack = check_top; stack != NULL; stack = stack->prev)
@@ -1056,59 +1133,37 @@ static void sym_check_print_recursive(struct symbol *last_sym)
for (; stack; stack = stack->next) {
sym = stack->sym;
next_sym = stack->next ? stack->next->sym : last_sym;
- prop = stack->prop;
- if (prop == NULL)
- prop = stack->sym->prop;
-
- /* for choice values find the menu entry (used below) */
- if (sym_is_choice(sym) || sym_is_choice_value(sym)) {
- for (prop = sym->prop; prop; prop = prop->next) {
- menu = prop->menu;
- if (prop->menu)
- break;
- }
- }
+ type = stack->prop ? stack->prop->type : P_UNKNOWN;
+
if (stack->sym == last_sym)
- fprintf(stderr, "%s:%d:error: recursive dependency detected!\n",
- prop->filename, prop->lineno);
+ fprintf(stderr, "error: recursive dependency detected!\n");
- if (sym_is_choice(sym)) {
- fprintf(stderr, "%s:%d:\tchoice %s contains symbol %s\n",
- menu->filename, menu->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->filename, menu->lineno,
+ if (sym_is_choice(next_sym)) {
+ choice = list_first_entry(&next_sym->menus, struct menu, link);
+
+ fprintf(stderr, "\tsymbol %s is part of choice block at %s:%d\n",
sym->name ? sym->name : "<choice>",
- next_sym->name ? next_sym->name : "<choice>");
+ choice->filename, choice->lineno);
} else if (stack->expr == &sym->dir_dep.expr) {
- fprintf(stderr, "%s:%d:\tsymbol %s depends on %s\n",
- prop->filename, prop->lineno,
+ fprintf(stderr, "\tsymbol %s depends on %s\n",
sym->name ? sym->name : "<choice>",
- next_sym->name ? next_sym->name : "<choice>");
+ next_sym->name);
} else if (stack->expr == &sym->rev_dep.expr) {
- fprintf(stderr, "%s:%d:\tsymbol %s is selected by %s\n",
- prop->filename, prop->lineno,
- sym->name ? sym->name : "<choice>",
- next_sym->name ? next_sym->name : "<choice>");
+ fprintf(stderr, "\tsymbol %s is selected by %s\n",
+ sym->name, next_sym->name);
} else if (stack->expr == &sym->implied.expr) {
- fprintf(stderr, "%s:%d:\tsymbol %s is implied by %s\n",
- prop->filename, prop->lineno,
- sym->name ? sym->name : "<choice>",
- next_sym->name ? next_sym->name : "<choice>");
+ fprintf(stderr, "\tsymbol %s is implied by %s\n",
+ sym->name, next_sym->name);
} else if (stack->expr) {
- fprintf(stderr, "%s:%d:\tsymbol %s %s value contains %s\n",
- prop->filename, prop->lineno,
+ fprintf(stderr, "\tsymbol %s %s value contains %s\n",
sym->name ? sym->name : "<choice>",
- prop_get_type_name(prop->type),
- next_sym->name ? next_sym->name : "<choice>");
+ prop_get_type_name(type),
+ next_sym->name);
} else {
- fprintf(stderr, "%s:%d:\tsymbol %s %s is visible depending on %s\n",
- prop->filename, prop->lineno,
+ fprintf(stderr, "\tsymbol %s %s is visible depending on %s\n",
sym->name ? sym->name : "<choice>",
- prop_get_type_name(prop->type),
- next_sym->name ? next_sym->name : "<choice>");
+ prop_get_type_name(type),
+ next_sym->name);
}
}
@@ -1121,7 +1176,7 @@ static void sym_check_print_recursive(struct symbol *last_sym)
dep_stack_remove();
}
-static struct symbol *sym_check_expr_deps(struct expr *e)
+static struct symbol *sym_check_expr_deps(const struct expr *e)
{
struct symbol *sym;
@@ -1182,8 +1237,7 @@ static struct symbol *sym_check_sym_deps(struct symbol *sym)
stack.expr = NULL;
for (prop = sym->prop; prop; prop = prop->next) {
- if (prop->type == P_CHOICE || prop->type == P_SELECT ||
- prop->type == P_IMPLY)
+ if (prop->type == P_SELECT || prop->type == P_IMPLY)
continue;
stack.prop = prop;
sym2 = sym_check_expr_deps(prop->visible.expr);
@@ -1237,9 +1291,13 @@ out:
if (menu->sym)
menu->sym->flags &= ~SYMBOL_CHECK;
- if (sym2 && sym_is_choice_value(sym2) &&
- prop_get_symbol(sym_get_choice_prop(sym2)) == choice)
- sym2 = choice;
+ if (sym2) {
+ struct menu *choice_menu2;
+
+ choice_menu2 = sym_get_choice_menu(sym2);
+ if (choice_menu2 == choice_menu)
+ sym2 = choice;
+ }
dep_stack_remove();
@@ -1248,8 +1306,8 @@ out:
struct symbol *sym_check_deps(struct symbol *sym)
{
+ struct menu *choice;
struct symbol *sym2;
- struct property *prop;
if (sym->flags & SYMBOL_CHECK) {
sym_check_print_recursive(sym);
@@ -1258,13 +1316,13 @@ struct symbol *sym_check_deps(struct symbol *sym)
if (sym->flags & SYMBOL_CHECKED)
return NULL;
- if (sym_is_choice_value(sym)) {
+ choice = sym_get_choice_menu(sym);
+ if (choice) {
struct dep_stack stack;
/* for choice groups start the check with main choice symbol */
dep_stack_insert(&stack, sym);
- prop = sym_get_choice_prop(sym);
- sym2 = sym_check_deps(prop_get_symbol(prop));
+ sym2 = sym_check_deps(choice->sym);
dep_stack_remove();
} else if (sym_is_choice(sym)) {
sym2 = sym_check_choice_deps(sym);
@@ -1277,10 +1335,9 @@ struct symbol *sym_check_deps(struct symbol *sym)
return sym2;
}
-struct symbol *prop_get_symbol(struct property *prop)
+struct symbol *prop_get_symbol(const struct property *prop)
{
- if (prop->expr && (prop->expr->type == E_SYMBOL ||
- prop->expr->type == E_LIST))
+ if (prop->expr && prop->expr->type == E_SYMBOL)
return prop->expr->left.sym;
return NULL;
}
@@ -1296,16 +1353,12 @@ const char *prop_get_type_name(enum prop_type type)
return "menu";
case P_DEFAULT:
return "default";
- case P_CHOICE:
- return "choice";
case P_SELECT:
return "select";
case P_IMPLY:
return "imply";
case P_RANGE:
return "range";
- case P_SYMBOL:
- return "symbol";
case P_UNKNOWN:
break;
}
diff --git a/scripts/kconfig/tests/choice/Kconfig b/scripts/kconfig/tests/choice/Kconfig
index 8cdda40868a1..cd252579a623 100644
--- a/scripts/kconfig/tests/choice/Kconfig
+++ b/scripts/kconfig/tests/choice/Kconfig
@@ -1,10 +1,5 @@
# SPDX-License-Identifier: GPL-2.0
-config MODULES
- bool "Enable loadable module support"
- modules
- default y
-
choice
prompt "boolean choice"
default BOOL_CHOICE1
@@ -16,15 +11,3 @@ config BOOL_CHOICE1
bool "choice 1"
endchoice
-
-choice
- prompt "tristate choice"
- default TRI_CHOICE1
-
-config TRI_CHOICE0
- tristate "choice 0"
-
-config TRI_CHOICE1
- tristate "choice 1"
-
-endchoice
diff --git a/scripts/kconfig/tests/choice/__init__.py b/scripts/kconfig/tests/choice/__init__.py
index 05e162220085..0fc7bf9b5c78 100644
--- a/scripts/kconfig/tests/choice/__init__.py
+++ b/scripts/kconfig/tests/choice/__init__.py
@@ -1,11 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
"""
Basic choice tests.
-
-The handling of 'choice' is a bit complicated part in Kconfig.
-
-The behavior of 'y' choice is intuitive. If choice values are tristate,
-the choice can be 'm' where each value can be enabled independently.
"""
@@ -14,11 +9,6 @@ def test_oldask0(conf):
assert conf.stdout_contains('oldask0_expected_stdout')
-def test_oldask1(conf):
- assert conf.oldaskconfig('oldask1_config') == 0
- assert conf.stdout_contains('oldask1_expected_stdout')
-
-
def test_allyes(conf):
assert conf.allyesconfig() == 0
assert conf.config_contains('allyes_expected_config')
diff --git a/scripts/kconfig/tests/choice/alldef_expected_config b/scripts/kconfig/tests/choice/alldef_expected_config
index 7a754bf4be94..b359a2e6493e 100644
--- a/scripts/kconfig/tests/choice/alldef_expected_config
+++ b/scripts/kconfig/tests/choice/alldef_expected_config
@@ -1,5 +1,2 @@
-CONFIG_MODULES=y
# CONFIG_BOOL_CHOICE0 is not set
CONFIG_BOOL_CHOICE1=y
-# CONFIG_TRI_CHOICE0 is not set
-# CONFIG_TRI_CHOICE1 is not set
diff --git a/scripts/kconfig/tests/choice/allmod_expected_config b/scripts/kconfig/tests/choice/allmod_expected_config
index d1f51651740c..b359a2e6493e 100644
--- a/scripts/kconfig/tests/choice/allmod_expected_config
+++ b/scripts/kconfig/tests/choice/allmod_expected_config
@@ -1,5 +1,2 @@
-CONFIG_MODULES=y
# CONFIG_BOOL_CHOICE0 is not set
CONFIG_BOOL_CHOICE1=y
-CONFIG_TRI_CHOICE0=m
-CONFIG_TRI_CHOICE1=m
diff --git a/scripts/kconfig/tests/choice/allno_expected_config b/scripts/kconfig/tests/choice/allno_expected_config
index b88ee7a43136..b359a2e6493e 100644
--- a/scripts/kconfig/tests/choice/allno_expected_config
+++ b/scripts/kconfig/tests/choice/allno_expected_config
@@ -1,5 +1,2 @@
-# CONFIG_MODULES is not set
# CONFIG_BOOL_CHOICE0 is not set
CONFIG_BOOL_CHOICE1=y
-# CONFIG_TRI_CHOICE0 is not set
-CONFIG_TRI_CHOICE1=y
diff --git a/scripts/kconfig/tests/choice/allyes_expected_config b/scripts/kconfig/tests/choice/allyes_expected_config
index 8a76c1816893..b359a2e6493e 100644
--- a/scripts/kconfig/tests/choice/allyes_expected_config
+++ b/scripts/kconfig/tests/choice/allyes_expected_config
@@ -1,5 +1,2 @@
-CONFIG_MODULES=y
# CONFIG_BOOL_CHOICE0 is not set
CONFIG_BOOL_CHOICE1=y
-# CONFIG_TRI_CHOICE0 is not set
-CONFIG_TRI_CHOICE1=y
diff --git a/scripts/kconfig/tests/choice/oldask0_expected_stdout b/scripts/kconfig/tests/choice/oldask0_expected_stdout
index d2257db46423..80ec34c61ebc 100644
--- a/scripts/kconfig/tests/choice/oldask0_expected_stdout
+++ b/scripts/kconfig/tests/choice/oldask0_expected_stdout
@@ -1,8 +1,4 @@
-Enable loadable module support (MODULES) [Y/n/?] (NEW)
boolean choice
1. choice 0 (BOOL_CHOICE0) (NEW)
> 2. choice 1 (BOOL_CHOICE1) (NEW)
choice[1-2?]:
-tristate choice [M/y/?] (NEW)
- choice 0 (TRI_CHOICE0) [N/m/?] (NEW)
- choice 1 (TRI_CHOICE1) [N/m/?] (NEW)
diff --git a/scripts/kconfig/tests/choice/oldask1_config b/scripts/kconfig/tests/choice/oldask1_config
deleted file mode 100644
index 0f417856c81c..000000000000
--- a/scripts/kconfig/tests/choice/oldask1_config
+++ /dev/null
@@ -1 +0,0 @@
-# CONFIG_MODULES is not set
diff --git a/scripts/kconfig/tests/choice/oldask1_expected_stdout b/scripts/kconfig/tests/choice/oldask1_expected_stdout
deleted file mode 100644
index ffa20ad7f38e..000000000000
--- a/scripts/kconfig/tests/choice/oldask1_expected_stdout
+++ /dev/null
@@ -1,9 +0,0 @@
-Enable loadable module support (MODULES) [N/y/?]
-boolean choice
- 1. choice 0 (BOOL_CHOICE0) (NEW)
-> 2. choice 1 (BOOL_CHOICE1) (NEW)
-choice[1-2?]:
-tristate choice
- 1. choice 0 (TRI_CHOICE0) (NEW)
-> 2. choice 1 (TRI_CHOICE1) (NEW)
-choice[1-2?]:
diff --git a/scripts/kconfig/tests/choice_value_with_m_dep/Kconfig b/scripts/kconfig/tests/choice_value_with_m_dep/Kconfig
deleted file mode 100644
index bd970cec07d6..000000000000
--- a/scripts/kconfig/tests/choice_value_with_m_dep/Kconfig
+++ /dev/null
@@ -1,21 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-config MODULES
- def_bool y
- modules
-
-config DEP
- tristate
- default m
-
-choice
- prompt "Tristate Choice"
-
-config CHOICE0
- tristate "Choice 0"
-
-config CHOICE1
- tristate "Choice 1"
- depends on DEP
-
-endchoice
diff --git a/scripts/kconfig/tests/choice_value_with_m_dep/__init__.py b/scripts/kconfig/tests/choice_value_with_m_dep/__init__.py
deleted file mode 100644
index 075b4e08696e..000000000000
--- a/scripts/kconfig/tests/choice_value_with_m_dep/__init__.py
+++ /dev/null
@@ -1,16 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-"""
-Hide tristate choice values with mod dependency in y choice.
-
-If tristate choice values depend on symbols set to 'm', they should be
-hidden when the choice containing them is changed from 'm' to 'y'
-(i.e. exclusive choice).
-
-Related Linux commit: fa64e5f6a35efd5e77d639125d973077ca506074
-"""
-
-
-def test(conf):
- assert conf.oldaskconfig('config', 'y') == 0
- assert conf.config_contains('expected_config')
- assert conf.stdout_contains('expected_stdout')
diff --git a/scripts/kconfig/tests/choice_value_with_m_dep/config b/scripts/kconfig/tests/choice_value_with_m_dep/config
deleted file mode 100644
index 3a126b7a2546..000000000000
--- a/scripts/kconfig/tests/choice_value_with_m_dep/config
+++ /dev/null
@@ -1,2 +0,0 @@
-CONFIG_CHOICE0=m
-CONFIG_CHOICE1=m
diff --git a/scripts/kconfig/tests/choice_value_with_m_dep/expected_config b/scripts/kconfig/tests/choice_value_with_m_dep/expected_config
deleted file mode 100644
index 4d07b449540e..000000000000
--- a/scripts/kconfig/tests/choice_value_with_m_dep/expected_config
+++ /dev/null
@@ -1,3 +0,0 @@
-CONFIG_MODULES=y
-CONFIG_DEP=m
-CONFIG_CHOICE0=y
diff --git a/scripts/kconfig/tests/choice_value_with_m_dep/expected_stdout b/scripts/kconfig/tests/choice_value_with_m_dep/expected_stdout
deleted file mode 100644
index 2b50ab65c86a..000000000000
--- a/scripts/kconfig/tests/choice_value_with_m_dep/expected_stdout
+++ /dev/null
@@ -1,4 +0,0 @@
-Tristate Choice [M/y/?] y
-Tristate Choice
-> 1. Choice 0 (CHOICE0)
-choice[1]: 1
diff --git a/scripts/kconfig/tests/conftest.py b/scripts/kconfig/tests/conftest.py
index 2a2a7e2da060..d94b79e012c0 100644
--- a/scripts/kconfig/tests/conftest.py
+++ b/scripts/kconfig/tests/conftest.py
@@ -81,7 +81,22 @@ class Conf:
# For interactive modes such as oldaskconfig, oldconfig,
# send 'Enter' key until the program finishes.
if interactive:
- ps.stdin.write(b'\n')
+ try:
+ ps.stdin.write(b'\n')
+ ps.stdin.flush()
+ except (BrokenPipeError, OSError):
+ # Process has exited, stop sending input
+ break
+
+ # Close stdin gracefully
+ try:
+ ps.stdin.close()
+ except (BrokenPipeError, OSError):
+ # Ignore broken pipe on close
+ pass
+
+ # Wait for process to complete
+ ps.wait()
self.retcode = ps.returncode
self.stdout = ps.stdout.read().decode()
diff --git a/scripts/kconfig/tests/err_recursive_dep/expected_stderr b/scripts/kconfig/tests/err_recursive_dep/expected_stderr
index 05d4ced70320..fc2e860af082 100644
--- a/scripts/kconfig/tests/err_recursive_dep/expected_stderr
+++ b/scripts/kconfig/tests/err_recursive_dep/expected_stderr
@@ -1,38 +1,38 @@
-Kconfig:5:error: recursive dependency detected!
-Kconfig:5: symbol A depends on A
+error: recursive dependency detected!
+ symbol A depends on A
For a resolution refer to Documentation/kbuild/kconfig-language.rst
subsection "Kconfig recursive dependency limitations"
-Kconfig:11:error: recursive dependency detected!
-Kconfig:11: symbol B is selected by B
+error: recursive dependency detected!
+ symbol B is selected by B
For a resolution refer to Documentation/kbuild/kconfig-language.rst
subsection "Kconfig recursive dependency limitations"
-Kconfig:17:error: recursive dependency detected!
-Kconfig:17: symbol C1 depends on C2
-Kconfig:21: symbol C2 depends on C1
+error: recursive dependency detected!
+ symbol C1 depends on C2
+ symbol C2 depends on C1
For a resolution refer to Documentation/kbuild/kconfig-language.rst
subsection "Kconfig recursive dependency limitations"
-Kconfig:27:error: recursive dependency detected!
-Kconfig:27: symbol D1 depends on D2
-Kconfig:32: symbol D2 is selected by D1
+error: recursive dependency detected!
+ symbol D1 depends on D2
+ symbol D2 is selected by D1
For a resolution refer to Documentation/kbuild/kconfig-language.rst
subsection "Kconfig recursive dependency limitations"
-Kconfig:37:error: recursive dependency detected!
-Kconfig:37: symbol E1 depends on E2
-Kconfig:42: symbol E2 is implied by E1
+error: recursive dependency detected!
+ symbol E1 depends on E2
+ symbol E2 is implied by E1
For a resolution refer to Documentation/kbuild/kconfig-language.rst
subsection "Kconfig recursive dependency limitations"
-Kconfig:49:error: recursive dependency detected!
-Kconfig:49: symbol F1 default value contains F2
-Kconfig:51: symbol F2 depends on F1
+error: recursive dependency detected!
+ symbol F1 default value contains F2
+ symbol F2 depends on F1
For a resolution refer to Documentation/kbuild/kconfig-language.rst
subsection "Kconfig recursive dependency limitations"
-Kconfig:60:error: recursive dependency detected!
-Kconfig:60: symbol G depends on G
+error: recursive dependency detected!
+ symbol G depends on G
For a resolution refer to Documentation/kbuild/kconfig-language.rst
subsection "Kconfig recursive dependency limitations"
diff --git a/scripts/kconfig/tests/err_transitional/Kconfig b/scripts/kconfig/tests/err_transitional/Kconfig
new file mode 100644
index 000000000000..a75ed3b2fe5e
--- /dev/null
+++ b/scripts/kconfig/tests/err_transitional/Kconfig
@@ -0,0 +1,52 @@
+# SPDX-License-Identifier: GPL-2.0
+# Test that transitional symbols cannot have properties other than help
+
+config BAD_DEFAULT
+ bool
+ transitional
+ default y
+ help
+ This transitional symbol illegally has a default property.
+
+config BAD_PROMPT
+ bool
+ transitional
+ prompt "Bad prompt"
+ help
+ This transitional symbol illegally has a prompt.
+
+config BAD_SELECT
+ bool
+ transitional
+ select OTHER_SYMBOL
+ help
+ This transitional symbol illegally has a select.
+
+config BAD_IMPLY
+ bool
+ transitional
+ imply OTHER_SYMBOL
+ help
+ This transitional symbol illegally has an imply.
+
+config BAD_DEPENDS
+ bool
+ transitional
+ depends on OTHER_SYMBOL
+ help
+ This transitional symbol illegally has a depends.
+
+config BAD_RANGE
+ int
+ transitional
+ range 1 10
+ help
+ This transitional symbol illegally has a range.
+
+config BAD_NO_TYPE
+ transitional
+ help
+ This transitional symbol illegally has no type specified.
+
+config OTHER_SYMBOL
+ bool
diff --git a/scripts/kconfig/tests/err_transitional/__init__.py b/scripts/kconfig/tests/err_transitional/__init__.py
new file mode 100644
index 000000000000..7dffb5b0833f
--- /dev/null
+++ b/scripts/kconfig/tests/err_transitional/__init__.py
@@ -0,0 +1,14 @@
+# SPDX-License-Identifier: GPL-2.0
+"""
+Test that transitional symbols with invalid properties are rejected.
+
+Transitional symbols can only have help sections. Any other properties
+(default, select, depends, etc.) should cause a parser error.
+"""
+
+def test(conf):
+ # This should fail with exit code 1 due to invalid transitional symbol
+ assert conf.olddefconfig() == 1
+
+ # Check that the error message is about transitional symbols
+ assert conf.stderr_contains('expected_stderr')
diff --git a/scripts/kconfig/tests/err_transitional/expected_stderr b/scripts/kconfig/tests/err_transitional/expected_stderr
new file mode 100644
index 000000000000..b52db4f680f4
--- /dev/null
+++ b/scripts/kconfig/tests/err_transitional/expected_stderr
@@ -0,0 +1,7 @@
+Kconfig:46:warning: config symbol defined without type
+Kconfig:7: error: transitional symbols can only have help sections
+Kconfig:14: error: transitional symbols can only have help sections
+Kconfig:21: error: transitional symbols can only have help sections
+Kconfig:28: error: transitional symbols can only have help sections
+Kconfig:32: error: transitional symbols can only have help sections
+Kconfig:42: error: transitional symbols can only have help sections
diff --git a/scripts/kconfig/tests/inter_choice/Kconfig b/scripts/kconfig/tests/inter_choice/Kconfig
deleted file mode 100644
index 26c25f68695b..000000000000
--- a/scripts/kconfig/tests/inter_choice/Kconfig
+++ /dev/null
@@ -1,25 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-config MODULES
- def_bool y
- modules
-
-choice
- prompt "Choice"
-
-config CHOICE_VAL0
- tristate "Choice 0"
-
-config CHOIVE_VAL1
- tristate "Choice 1"
-
-endchoice
-
-choice
- prompt "Another choice"
- depends on CHOICE_VAL0
-
-config DUMMY
- bool "dummy"
-
-endchoice
diff --git a/scripts/kconfig/tests/inter_choice/__init__.py b/scripts/kconfig/tests/inter_choice/__init__.py
deleted file mode 100644
index ffea6b1148a6..000000000000
--- a/scripts/kconfig/tests/inter_choice/__init__.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-"""
-Do not affect user-assigned choice value by another choice.
-
-Handling of state flags for choices is complecated. In old days,
-the defconfig result of a choice could be affected by another choice
-if those choices interact by 'depends on', 'select', etc.
-
-Related Linux commit: fbe98bb9ed3dae23e320c6b113e35f129538d14a
-"""
-
-
-def test(conf):
- assert conf.defconfig('defconfig') == 0
- assert conf.config_contains('expected_config')
diff --git a/scripts/kconfig/tests/inter_choice/defconfig b/scripts/kconfig/tests/inter_choice/defconfig
deleted file mode 100644
index 162c4148e2a5..000000000000
--- a/scripts/kconfig/tests/inter_choice/defconfig
+++ /dev/null
@@ -1 +0,0 @@
-CONFIG_CHOICE_VAL0=y
diff --git a/scripts/kconfig/tests/inter_choice/expected_config b/scripts/kconfig/tests/inter_choice/expected_config
deleted file mode 100644
index 5dceefb054e3..000000000000
--- a/scripts/kconfig/tests/inter_choice/expected_config
+++ /dev/null
@@ -1,4 +0,0 @@
-CONFIG_MODULES=y
-CONFIG_CHOICE_VAL0=y
-# CONFIG_CHOIVE_VAL1 is not set
-CONFIG_DUMMY=y
diff --git a/scripts/kconfig/tests/transitional/Kconfig b/scripts/kconfig/tests/transitional/Kconfig
new file mode 100644
index 000000000000..faa4d396f828
--- /dev/null
+++ b/scripts/kconfig/tests/transitional/Kconfig
@@ -0,0 +1,132 @@
+# SPDX-License-Identifier: GPL-2.0
+# Test transitional symbols for config migration with all Kconfig types
+
+# Enable module support for tristate testing
+config MODULES
+ bool "Enable loadable module support"
+ modules
+ default y
+
+# Basic migration tests for all types
+config NEW_BOOL
+ bool "New bool option"
+ default OLD_BOOL
+
+config OLD_BOOL
+ bool
+ transitional
+
+config NEW_TRISTATE
+ tristate "New tristate option"
+ default OLD_TRISTATE
+
+config OLD_TRISTATE
+ tristate
+ transitional
+
+config NEW_STRING
+ string "New string option"
+ default OLD_STRING
+
+config OLD_STRING
+ string
+ transitional
+
+config NEW_HEX
+ hex "New hex option"
+ default OLD_HEX
+
+config OLD_HEX
+ hex
+ transitional
+
+config NEW_INT
+ int "New int option"
+ default OLD_INT
+
+config OLD_INT
+ int
+ transitional
+
+# Precedence tests for all types
+config NEW_BOOL_PRECEDENCE
+ bool "New bool option with precedence"
+ default OLD_BOOL_PRECEDENCE
+
+config OLD_BOOL_PRECEDENCE
+ bool
+ transitional
+
+config NEW_STRING_PRECEDENCE
+ string "New string option with precedence"
+ default OLD_STRING_PRECEDENCE
+
+config OLD_STRING_PRECEDENCE
+ string
+ transitional
+
+config NEW_TRISTATE_PRECEDENCE
+ tristate "New tristate option with precedence"
+ default OLD_TRISTATE_PRECEDENCE
+
+config OLD_TRISTATE_PRECEDENCE
+ tristate
+ transitional
+
+config NEW_HEX_PRECEDENCE
+ hex "New hex option with precedence"
+ default OLD_HEX_PRECEDENCE
+
+config OLD_HEX_PRECEDENCE
+ hex
+ transitional
+
+config NEW_INT_PRECEDENCE
+ int "New int option with precedence"
+ default OLD_INT_PRECEDENCE
+
+config OLD_INT_PRECEDENCE
+ int
+ transitional
+
+# Test that help sections are allowed for transitional symbols
+config OLD_WITH_HELP
+ bool
+ transitional
+ help
+ This transitional symbol has a help section to validate that help is allowed.
+
+# Test that we can set something to =n via transitional symbol
+config NEW_DISABLED
+ tristate "Check for setting to disabled"
+ default OLD_DISABLED
+
+config OLD_DISABLED
+ tristate
+ transitional
+
+# Test that a potential new value disappears if it lacks a prompt
+config NEW_DISABLED_UNSAVED
+ tristate
+ default OLD_DISABLED
+
+config OLD_DISABLED_UNSAVED
+ tristate
+ transitional
+
+# Test conditional default: transitional value should not prevent prompting
+# when default visibility makes the expression evaluate to 'no'
+config DEPENDENCY_TEST
+ bool "Dependency for testing"
+ default n
+
+config NEW_CONDITIONAL_DEFAULT
+ bool "New option with conditional default"
+ default OLD_CONDITIONAL_DEFAULT if DEPENDENCY_TEST
+
+config OLD_CONDITIONAL_DEFAULT
+ bool
+ transitional
+
+config REGULAR_OPTION
+ bool "Regular option"
diff --git a/scripts/kconfig/tests/transitional/__init__.py b/scripts/kconfig/tests/transitional/__init__.py
new file mode 100644
index 000000000000..b50ba2397548
--- /dev/null
+++ b/scripts/kconfig/tests/transitional/__init__.py
@@ -0,0 +1,25 @@
+# SPDX-License-Identifier: GPL-2.0
+"""
+Test transitional symbol migration functionality for all Kconfig types.
+
+This tests that:
+- OLD_* options in existing .config cause NEW_* options to be set
+- OLD_* options are not written to the new .config file
+- NEW_* options appear in the new .config file with correct values
+- NEW_* options with defaults from transitional symbols are not prompted
+- All Kconfig types work correctly: bool, tristate, string, hex, int
+- User-set NEW values take precedence over conflicting OLD transitional values
+"""
+
+def test(conf):
+ # Run olddefconfig to process the migration with the initial config
+ assert conf.olddefconfig(dot_config='initial_config') == 0
+
+ # Check that the configuration matches expected output
+ assert conf.config_contains('expected_config')
+
+ # Test oldconfig to ensure symbols with transitional defaults are not prompted
+ assert conf.oldconfig(dot_config='initial_config', in_keys='n\n') == 0
+
+ # Except for when conditional default evaluates to 'no'
+ assert conf.stdout_contains('expected_stdout')
diff --git a/scripts/kconfig/tests/transitional/expected_config b/scripts/kconfig/tests/transitional/expected_config
new file mode 100644
index 000000000000..e01f5f070a26
--- /dev/null
+++ b/scripts/kconfig/tests/transitional/expected_config
@@ -0,0 +1,15 @@
+CONFIG_MODULES=y
+CONFIG_NEW_BOOL=y
+CONFIG_NEW_TRISTATE=m
+CONFIG_NEW_STRING="test string"
+CONFIG_NEW_HEX=0x1234
+CONFIG_NEW_INT=42
+# CONFIG_NEW_BOOL_PRECEDENCE is not set
+CONFIG_NEW_STRING_PRECEDENCE="user value"
+CONFIG_NEW_TRISTATE_PRECEDENCE=y
+CONFIG_NEW_HEX_PRECEDENCE=0xABCD
+CONFIG_NEW_INT_PRECEDENCE=100
+# CONFIG_NEW_DISABLED is not set
+# CONFIG_DEPENDENCY_TEST is not set
+# CONFIG_NEW_CONDITIONAL_DEFAULT is not set
+# CONFIG_REGULAR_OPTION is not set
diff --git a/scripts/kconfig/tests/transitional/expected_stdout b/scripts/kconfig/tests/transitional/expected_stdout
new file mode 100644
index 000000000000..6f0b285d6469
--- /dev/null
+++ b/scripts/kconfig/tests/transitional/expected_stdout
@@ -0,0 +1 @@
+New option with conditional default (NEW_CONDITIONAL_DEFAULT) [N/y/?] (NEW) n
diff --git a/scripts/kconfig/tests/transitional/initial_config b/scripts/kconfig/tests/transitional/initial_config
new file mode 100644
index 000000000000..68b7da672426
--- /dev/null
+++ b/scripts/kconfig/tests/transitional/initial_config
@@ -0,0 +1,20 @@
+CONFIG_MODULES=y
+CONFIG_OLD_BOOL=y
+CONFIG_OLD_TRISTATE=m
+CONFIG_OLD_STRING="test string"
+CONFIG_OLD_HEX=0x1234
+CONFIG_OLD_INT=42
+# CONFIG_NEW_BOOL_PRECEDENCE is not set
+CONFIG_OLD_BOOL_PRECEDENCE=y
+CONFIG_NEW_STRING_PRECEDENCE="user value"
+CONFIG_OLD_STRING_PRECEDENCE="old value"
+CONFIG_NEW_TRISTATE_PRECEDENCE=y
+CONFIG_OLD_TRISTATE_PRECEDENCE=m
+CONFIG_NEW_HEX_PRECEDENCE=0xABCD
+CONFIG_OLD_HEX_PRECEDENCE=0x5678
+CONFIG_NEW_INT_PRECEDENCE=100
+CONFIG_OLD_INT_PRECEDENCE=200
+# CONFIG_OLD_DISABLED is not set
+# CONFIG_OLD_DISABLED_UNSAVED is not set
+# CONFIG_DEPENDENCY_TEST is not set
+CONFIG_OLD_CONDITIONAL_DEFAULT=y
diff --git a/scripts/kconfig/util.c b/scripts/kconfig/util.c
index 439c131b424e..5cdcee144b58 100644
--- a/scripts/kconfig/util.c
+++ b/scripts/kconfig/util.c
@@ -8,19 +8,11 @@
#include <stdlib.h>
#include <string.h>
-#include "hashtable.h"
+#include <hash.h>
+#include <hashtable.h>
+#include <xalloc.h>
#include "lkc.h"
-unsigned int strhash(const char *s)
-{
- /* fnv32 hash */
- unsigned int hash = 2166136261U;
-
- for (; *s; s++)
- hash = (hash ^ *s) * 0x01000193;
- return hash;
-}
-
/* hash table of all parsed Kconfig files */
static HASHTABLE_DEFINE(file_hashtable, 1U << 11);
@@ -34,7 +26,7 @@ const char *file_lookup(const char *name)
{
struct file *file;
size_t len;
- int hash = strhash(name);
+ int hash = hash_str(name);
hash_for_each_possible(file_hashtable, file, node, hash)
if (!strcmp(name, file->name))
@@ -98,56 +90,7 @@ void str_printf(struct gstr *gs, const char *fmt, ...)
}
/* Retrieve value of growable string */
-char *str_get(struct gstr *gs)
+char *str_get(const struct gstr *gs)
{
return gs->s;
}
-
-void *xmalloc(size_t size)
-{
- void *p = malloc(size);
- if (p)
- return p;
- fprintf(stderr, "Out of memory.\n");
- exit(1);
-}
-
-void *xcalloc(size_t nmemb, size_t size)
-{
- void *p = calloc(nmemb, size);
- if (p)
- return p;
- 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);
-}