1.1 --- a/kconfig/symbol.c Sun Apr 15 16:45:11 2007 +0000
1.2 +++ b/kconfig/symbol.c Mon Oct 20 09:50:45 2008 +0000
1.3 @@ -34,19 +34,21 @@
1.4 struct symbol *modules_sym;
1.5 tristate modules_val;
1.6
1.7 +struct expr *sym_env_list;
1.8 +
1.9 void sym_add_default(struct symbol *sym, const char *def)
1.10 {
1.11 struct property *prop = prop_alloc(P_DEFAULT, sym);
1.12
1.13 - prop->expr = expr_alloc_symbol(sym_lookup(def, 1));
1.14 + prop->expr = expr_alloc_symbol(sym_lookup(def, SYMBOL_CONST));
1.15 }
1.16
1.17 void sym_init(void)
1.18 {
1.19 struct symbol *sym;
1.20 struct utsname uts;
1.21 - char *p;
1.22 static bool inited = false;
1.23 + char* p;
1.24
1.25 if (inited)
1.26 return;
1.27 @@ -54,12 +56,10 @@
1.28
1.29 uname(&uts);
1.30
1.31 - sym = sym_lookup("ARCH", 0);
1.32 + sym = sym_lookup("UNAME_RELEASE", 0);
1.33 sym->type = S_STRING;
1.34 sym->flags |= SYMBOL_AUTO;
1.35 - p = getenv("ARCH");
1.36 - if (p)
1.37 - sym_add_default(sym, p);
1.38 + sym_add_default(sym, uts.release);
1.39
1.40 sym = sym_lookup("PROJECTVERSION", 0);
1.41 sym->type = S_STRING;
1.42 @@ -67,11 +67,6 @@
1.43 p = getenv("PROJECTVERSION");
1.44 if (p)
1.45 sym_add_default(sym, p);
1.46 -
1.47 - sym = sym_lookup("UNAME_RELEASE", 0);
1.48 - sym->type = S_STRING;
1.49 - sym->flags |= SYMBOL_AUTO;
1.50 - sym_add_default(sym, uts.release);
1.51 }
1.52
1.53 enum symbol_type sym_get_type(struct symbol *sym)
1.54 @@ -117,6 +112,15 @@
1.55 return NULL;
1.56 }
1.57
1.58 +struct property *sym_get_env_prop(struct symbol *sym)
1.59 +{
1.60 + struct property *prop;
1.61 +
1.62 + for_all_properties(sym, prop, P_ENV)
1.63 + return prop;
1.64 + return NULL;
1.65 +}
1.66 +
1.67 struct property *sym_get_default_prop(struct symbol *sym)
1.68 {
1.69 struct property *prop;
1.70 @@ -199,7 +203,7 @@
1.71 tri = no;
1.72 for_all_prompts(sym, prop) {
1.73 prop->visible.tri = expr_calc_value(prop->visible.expr);
1.74 - tri = E_OR(tri, prop->visible.tri);
1.75 + tri = EXPR_OR(tri, prop->visible.tri);
1.76 }
1.77 if (tri == mod && (sym->type != S_TRISTATE || modules_val == no))
1.78 tri = yes;
1.79 @@ -247,8 +251,7 @@
1.80
1.81 /* just get the first visible value */
1.82 prop = sym_get_choice_prop(sym);
1.83 - for (e = prop->expr; e; e = e->left.expr) {
1.84 - def_sym = e->right.sym;
1.85 + expr_list_for_each_sym(prop->expr, e, def_sym) {
1.86 sym_calc_visibility(def_sym);
1.87 if (def_sym->visible != no)
1.88 return def_sym;
1.89 @@ -303,22 +306,30 @@
1.90 if (sym_is_choice_value(sym) && sym->visible == yes) {
1.91 prop = sym_get_choice_prop(sym);
1.92 newval.tri = (prop_get_symbol(prop)->curr.val == sym) ? yes : no;
1.93 - } else if (E_OR(sym->visible, sym->rev_dep.tri) != no) {
1.94 - sym->flags |= SYMBOL_WRITE;
1.95 - if (sym_has_value(sym))
1.96 - newval.tri = sym->def[S_DEF_USER].tri;
1.97 - else if (!sym_is_choice(sym)) {
1.98 + } else {
1.99 + if (sym->visible != no) {
1.100 + /* if the symbol is visible use the user value
1.101 + * if available, otherwise try the default value
1.102 + */
1.103 + sym->flags |= SYMBOL_WRITE;
1.104 + if (sym_has_value(sym)) {
1.105 + newval.tri = EXPR_AND(sym->def[S_DEF_USER].tri,
1.106 + sym->visible);
1.107 + goto calc_newval;
1.108 + }
1.109 + }
1.110 + if (sym->rev_dep.tri != no)
1.111 + sym->flags |= SYMBOL_WRITE;
1.112 + if (!sym_is_choice(sym)) {
1.113 prop = sym_get_default_prop(sym);
1.114 - if (prop)
1.115 - newval.tri = expr_calc_value(prop->expr);
1.116 + if (prop) {
1.117 + sym->flags |= SYMBOL_WRITE;
1.118 + newval.tri = EXPR_AND(expr_calc_value(prop->expr),
1.119 + prop->visible.tri);
1.120 + }
1.121 }
1.122 - newval.tri = E_OR(E_AND(newval.tri, sym->visible), sym->rev_dep.tri);
1.123 - } else if (!sym_is_choice(sym)) {
1.124 - prop = sym_get_default_prop(sym);
1.125 - if (prop) {
1.126 - sym->flags |= SYMBOL_WRITE;
1.127 - newval.tri = expr_calc_value(prop->expr);
1.128 - }
1.129 + calc_newval:
1.130 + newval.tri = EXPR_OR(newval.tri, sym->rev_dep.tri);
1.131 }
1.132 if (newval.tri == mod && sym_get_type(sym) == S_BOOLEAN)
1.133 newval.tri = yes;
1.134 @@ -361,14 +372,19 @@
1.135 }
1.136
1.137 if (sym_is_choice(sym)) {
1.138 + struct symbol *choice_sym;
1.139 int flags = sym->flags & (SYMBOL_CHANGED | SYMBOL_WRITE);
1.140 +
1.141 prop = sym_get_choice_prop(sym);
1.142 - for (e = prop->expr; e; e = e->left.expr) {
1.143 - e->right.sym->flags |= flags;
1.144 + expr_list_for_each_sym(prop->expr, e, choice_sym) {
1.145 + choice_sym->flags |= flags;
1.146 if (flags & SYMBOL_CHANGED)
1.147 - sym_set_changed(e->right.sym);
1.148 + sym_set_changed(choice_sym);
1.149 }
1.150 }
1.151 +
1.152 + if (sym->flags & SYMBOL_AUTO)
1.153 + sym->flags &= ~SYMBOL_WRITE;
1.154 }
1.155
1.156 void sym_clear_all_valid(void)
1.157 @@ -643,7 +659,7 @@
1.158 return sym->visible > sym->rev_dep.tri;
1.159 }
1.160
1.161 -struct symbol *sym_lookup(const char *name, int isconst)
1.162 +struct symbol *sym_lookup(const char *name, int flags)
1.163 {
1.164 struct symbol *symbol;
1.165 const char *ptr;
1.166 @@ -663,11 +679,10 @@
1.167 hash &= 0xff;
1.168
1.169 for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
1.170 - if (!strcmp(symbol->name, name)) {
1.171 - if ((isconst && symbol->flags & SYMBOL_CONST) ||
1.172 - (!isconst && !(symbol->flags & SYMBOL_CONST)))
1.173 - return symbol;
1.174 - }
1.175 + if (!strcmp(symbol->name, name) &&
1.176 + (flags ? symbol->flags & flags
1.177 + : !(symbol->flags & (SYMBOL_CONST|SYMBOL_CHOICE))))
1.178 + return symbol;
1.179 }
1.180 new_name = strdup(name);
1.181 } else {
1.182 @@ -679,8 +694,7 @@
1.183 memset(symbol, 0, sizeof(*symbol));
1.184 symbol->name = new_name;
1.185 symbol->type = S_UNKNOWN;
1.186 - if (isconst)
1.187 - symbol->flags |= SYMBOL_CONST;
1.188 + symbol->flags |= flags;
1.189
1.190 symbol->next = symbol_hash[hash];
1.191 symbol_hash[hash] = symbol;
1.192 @@ -754,8 +768,6 @@
1.193 }
1.194
1.195
1.196 -struct symbol *sym_check_deps(struct symbol *sym);
1.197 -
1.198 static struct symbol *sym_check_expr_deps(struct expr *e)
1.199 {
1.200 struct symbol *sym;
1.201 @@ -786,44 +798,101 @@
1.202 return NULL;
1.203 }
1.204
1.205 +/* return NULL when dependencies are OK */
1.206 +static struct symbol *sym_check_sym_deps(struct symbol *sym)
1.207 +{
1.208 + struct symbol *sym2;
1.209 + struct property *prop;
1.210 +
1.211 + sym2 = sym_check_expr_deps(sym->rev_dep.expr);
1.212 + if (sym2)
1.213 + return sym2;
1.214 +
1.215 + for (prop = sym->prop; prop; prop = prop->next) {
1.216 + if (prop->type == P_CHOICE || prop->type == P_SELECT)
1.217 + continue;
1.218 + sym2 = sym_check_expr_deps(prop->visible.expr);
1.219 + if (sym2)
1.220 + break;
1.221 + if (prop->type != P_DEFAULT || sym_is_choice(sym))
1.222 + continue;
1.223 + sym2 = sym_check_expr_deps(prop->expr);
1.224 + if (sym2)
1.225 + break;
1.226 + }
1.227 +
1.228 + return sym2;
1.229 +}
1.230 +
1.231 +static struct symbol *sym_check_choice_deps(struct symbol *choice)
1.232 +{
1.233 + struct symbol *sym, *sym2;
1.234 + struct property *prop;
1.235 + struct expr *e;
1.236 +
1.237 + prop = sym_get_choice_prop(choice);
1.238 + expr_list_for_each_sym(prop->expr, e, sym)
1.239 + sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);
1.240 +
1.241 + choice->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);
1.242 + sym2 = sym_check_sym_deps(choice);
1.243 + choice->flags &= ~SYMBOL_CHECK;
1.244 + if (sym2)
1.245 + goto out;
1.246 +
1.247 + expr_list_for_each_sym(prop->expr, e, sym) {
1.248 + sym2 = sym_check_sym_deps(sym);
1.249 + if (sym2) {
1.250 + fprintf(stderr, " -> %s", sym->name);
1.251 + break;
1.252 + }
1.253 + }
1.254 +out:
1.255 + expr_list_for_each_sym(prop->expr, e, sym)
1.256 + sym->flags &= ~SYMBOL_CHECK;
1.257 +
1.258 + if (sym2 && sym_is_choice_value(sym2) &&
1.259 + prop_get_symbol(sym_get_choice_prop(sym2)) == choice)
1.260 + sym2 = choice;
1.261 +
1.262 + return sym2;
1.263 +}
1.264 +
1.265 struct symbol *sym_check_deps(struct symbol *sym)
1.266 {
1.267 struct symbol *sym2;
1.268 struct property *prop;
1.269
1.270 if (sym->flags & SYMBOL_CHECK) {
1.271 - printf("Warning! Found recursive dependency: %s", sym->name);
1.272 + fprintf(stderr, "%s:%d:error: found recursive dependency: %s",
1.273 + sym->prop->file->name, sym->prop->lineno,
1.274 + sym->name ? sym->name : "<choice>");
1.275 return sym;
1.276 }
1.277 if (sym->flags & SYMBOL_CHECKED)
1.278 return NULL;
1.279
1.280 - sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);
1.281 - sym2 = sym_check_expr_deps(sym->rev_dep.expr);
1.282 - if (sym2)
1.283 - goto out;
1.284 + if (sym_is_choice_value(sym)) {
1.285 + /* for choice groups start the check with main choice symbol */
1.286 + prop = sym_get_choice_prop(sym);
1.287 + sym2 = sym_check_deps(prop_get_symbol(prop));
1.288 + } else if (sym_is_choice(sym)) {
1.289 + sym2 = sym_check_choice_deps(sym);
1.290 + } else {
1.291 + sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);
1.292 + sym2 = sym_check_sym_deps(sym);
1.293 + sym->flags &= ~SYMBOL_CHECK;
1.294 + }
1.295
1.296 - for (prop = sym->prop; prop; prop = prop->next) {
1.297 - if (prop->type == P_CHOICE || prop->type == P_SELECT)
1.298 - continue;
1.299 - sym2 = sym_check_expr_deps(prop->visible.expr);
1.300 - if (sym2)
1.301 - goto out;
1.302 - if (prop->type != P_DEFAULT || sym_is_choice(sym))
1.303 - continue;
1.304 - sym2 = sym_check_expr_deps(prop->expr);
1.305 - if (sym2)
1.306 - goto out;
1.307 - }
1.308 -out:
1.309 if (sym2) {
1.310 - printf(" %s", sym->name);
1.311 + fprintf(stderr, " -> %s", sym->name ? sym->name : "<choice>");
1.312 if (sym2 == sym) {
1.313 - printf("\n");
1.314 + fprintf(stderr, "\n");
1.315 + zconfnerrs++;
1.316 sym2 = NULL;
1.317 }
1.318 }
1.319 - sym->flags &= ~SYMBOL_CHECK;
1.320 +
1.321 return sym2;
1.322 }
1.323
1.324 @@ -852,7 +921,7 @@
1.325 struct symbol *prop_get_symbol(struct property *prop)
1.326 {
1.327 if (prop->expr && (prop->expr->type == E_SYMBOL ||
1.328 - prop->expr->type == E_CHOICE))
1.329 + prop->expr->type == E_LIST))
1.330 return prop->expr->left.sym;
1.331 return NULL;
1.332 }
1.333 @@ -862,6 +931,8 @@
1.334 switch (type) {
1.335 case P_PROMPT:
1.336 return "prompt";
1.337 + case P_ENV:
1.338 + return "env";
1.339 case P_COMMENT:
1.340 return "comment";
1.341 case P_MENU:
1.342 @@ -879,3 +950,32 @@
1.343 }
1.344 return "unknown";
1.345 }
1.346 +
1.347 +void prop_add_env(const char *env)
1.348 +{
1.349 + struct symbol *sym, *sym2;
1.350 + struct property *prop;
1.351 + char *p;
1.352 +
1.353 + sym = current_entry->sym;
1.354 + sym->flags |= SYMBOL_AUTO;
1.355 + for_all_properties(sym, prop, P_ENV) {
1.356 + sym2 = prop_get_symbol(prop);
1.357 + if (strcmp(sym2->name, env))
1.358 + menu_warn(current_entry, "redefining environment symbol from %s",
1.359 + sym2->name);
1.360 + return;
1.361 + }
1.362 +
1.363 + prop = prop_alloc(P_ENV, sym);
1.364 + prop->expr = expr_alloc_symbol(sym_lookup(env, SYMBOL_CONST));
1.365 +
1.366 + sym_env_list = expr_alloc_one(E_LIST, sym_env_list);
1.367 + sym_env_list->right.sym = sym;
1.368 +
1.369 + p = getenv(env);
1.370 + if (p)
1.371 + sym_add_default(sym, p);
1.372 + else
1.373 + menu_warn(current_entry, "environment variable %s undefined", env);
1.374 +}