@@ -310,6 +310,127 @@ load:
return 0;
}
+static int test_deps(struct symbol *sym)
+{
+ struct property *prop;
+ struct expr *expr;
+
+ if (sym->rev_dep.tri == no)
+ return 1;
+
+ for (prop = sym->prop; prop; prop = prop->next) {
+ if (prop->type != P_PROMPT)
+ continue;
+
+ expr = prop->visible.expr;
+ if (!expr)
+ continue;
+
+ if (expr_calc_value(expr) == no)
+ return 0;
+ }
+
+ return 1;
+}
+
+void test_select(struct symbol *sym)
+{
+ struct property *prop;
+ struct expr *expr;
+
+ for (prop = sym->prop; prop; prop = prop->next) {
+ if (prop->type != P_SELECT)
+ continue;
+
+ expr = prop->expr;
+
+ if (!expr || expr->type != E_SYMBOL ||
+ !expr->left.sym)
+ continue;
+
+ if (test_deps(expr->left.sym))
+ continue;
+
+ conf_warning("%s selects %s which fails its dependencies!",
+ sym->name, expr->left.sym->name);
+ }
+}
+
+void test_conf(void)
+{
+ struct symbol *sym, *embedded;
+ tristate embed_tri;
+ struct menu *menu;
+ int type;
+
+ /*
+ * EMBEDDED is more like an "EXPERT" option. It is OK
+ * to select it even when it does not have the proper
+ * dependencies.
+ *
+ * Find the EMBEDDED symbol.
+ * Save its state.
+ * Set it to 'yes'.
+ * Run tests.
+ * Reset the EMBEDDED symbol.
+ */
+ embedded = sym_lookup("EMBEDDED", 0);
+ embed_tri = embedded->curr.tri;
+ embedded->curr.tri = yes;
+
+ menu = rootmenu.list;
+ while (menu) {
+ sym = menu->sym;
+ if (!sym)
+ goto next;
+
+ if (!(sym->flags & SYMBOL_CHOICE)) {
+ sym_calc_value(sym);
+ if (!(sym->flags & SYMBOL_WRITE))
+ goto next;
+ type = sym->type;
+ if (type == S_TRISTATE) {
+ sym_calc_value(modules_sym);
+ if (modules_sym->curr.tri == no)
+ type = S_BOOLEAN;
+ }
+ switch (type) {
+ case S_BOOLEAN:
+ case S_TRISTATE:
+ switch (sym_get_tristate_value(sym)) {
+ case no:
+ break;
+ case mod:
+ case yes:
+ test_select(sym);
+ break;
+ }
+ break;
+ case S_STRING:
+ case S_HEX:
+ case S_INT:
+ break;
+ }
+ }
+
+ next:
+ if (menu->list) {
+ menu = menu->list;
+ continue;
+ }
+ if (menu->next)
+ menu = menu->next;
+ else while ((menu = menu->parent)) {
+ if (menu->next) {
+ menu = menu->next;
+ break;
+ }
+ }
+ }
+
+ embedded->curr.tri = embed_tri;
+}
+
int conf_read(const char *name)
{
struct symbol *sym, *choice_sym;
@@ -386,6 +507,7 @@ int conf_read(const char *name)
sym_add_change_count(conf_warnings || conf_unsaved);
+ test_conf();
return 0;
}
@@ -550,6 +672,8 @@ int conf_write(const char *name)
sym_set_change_count(0);
+ test_conf();
+
return 0;
}