1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/kconfig/symbol.c Tue Apr 10 16:07:30 2007 +0000
1.3 @@ -0,0 +1,882 @@
1.4 +/*
1.5 + * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
1.6 + * Released under the terms of the GNU GPL v2.0.
1.7 + */
1.8 +
1.9 +#include <ctype.h>
1.10 +#include <stdlib.h>
1.11 +#include <string.h>
1.12 +#include <regex.h>
1.13 +#include <sys/utsname.h>
1.14 +
1.15 +#define LKC_DIRECT_LINK
1.16 +#include "lkc.h"
1.17 +
1.18 +struct symbol symbol_yes = {
1.19 + .name = "y",
1.20 + .curr = { "y", yes },
1.21 + .flags = SYMBOL_CONST|SYMBOL_VALID,
1.22 +}, symbol_mod = {
1.23 + .name = "m",
1.24 + .curr = { "m", mod },
1.25 + .flags = SYMBOL_CONST|SYMBOL_VALID,
1.26 +}, symbol_no = {
1.27 + .name = "n",
1.28 + .curr = { "n", no },
1.29 + .flags = SYMBOL_CONST|SYMBOL_VALID,
1.30 +}, symbol_empty = {
1.31 + .name = "",
1.32 + .curr = { "", no },
1.33 + .flags = SYMBOL_VALID,
1.34 +};
1.35 +
1.36 +int sym_change_count;
1.37 +struct symbol *sym_defconfig_list;
1.38 +struct symbol *modules_sym;
1.39 +tristate modules_val;
1.40 +
1.41 +void sym_add_default(struct symbol *sym, const char *def)
1.42 +{
1.43 + struct property *prop = prop_alloc(P_DEFAULT, sym);
1.44 +
1.45 + prop->expr = expr_alloc_symbol(sym_lookup(def, 1));
1.46 +}
1.47 +
1.48 +void sym_init(void)
1.49 +{
1.50 + struct symbol *sym;
1.51 + struct utsname uts;
1.52 + char *p;
1.53 + static bool inited = false;
1.54 +
1.55 + if (inited)
1.56 + return;
1.57 + inited = true;
1.58 +
1.59 + uname(&uts);
1.60 +
1.61 + sym = sym_lookup("ARCH", 0);
1.62 + sym->type = S_STRING;
1.63 + sym->flags |= SYMBOL_AUTO;
1.64 + p = getenv("ARCH");
1.65 + if (p)
1.66 + sym_add_default(sym, p);
1.67 +
1.68 + sym = sym_lookup("PROJECTVERSION", 0);
1.69 + sym->type = S_STRING;
1.70 + sym->flags |= SYMBOL_AUTO;
1.71 + p = getenv("PROJECTVERSION");
1.72 + if (p)
1.73 + sym_add_default(sym, p);
1.74 +
1.75 + sym = sym_lookup("UNAME_RELEASE", 0);
1.76 + sym->type = S_STRING;
1.77 + sym->flags |= SYMBOL_AUTO;
1.78 + sym_add_default(sym, uts.release);
1.79 +}
1.80 +
1.81 +enum symbol_type sym_get_type(struct symbol *sym)
1.82 +{
1.83 + enum symbol_type type = sym->type;
1.84 +
1.85 + if (type == S_TRISTATE) {
1.86 + if (sym_is_choice_value(sym) && sym->visible == yes)
1.87 + type = S_BOOLEAN;
1.88 + else if (modules_val == no)
1.89 + type = S_BOOLEAN;
1.90 + }
1.91 + return type;
1.92 +}
1.93 +
1.94 +const char *sym_type_name(enum symbol_type type)
1.95 +{
1.96 + switch (type) {
1.97 + case S_BOOLEAN:
1.98 + return "boolean";
1.99 + case S_TRISTATE:
1.100 + return "tristate";
1.101 + case S_INT:
1.102 + return "integer";
1.103 + case S_HEX:
1.104 + return "hex";
1.105 + case S_STRING:
1.106 + return "string";
1.107 + case S_UNKNOWN:
1.108 + return "unknown";
1.109 + case S_OTHER:
1.110 + break;
1.111 + }
1.112 + return "???";
1.113 +}
1.114 +
1.115 +struct property *sym_get_choice_prop(struct symbol *sym)
1.116 +{
1.117 + struct property *prop;
1.118 +
1.119 + for_all_choices(sym, prop)
1.120 + return prop;
1.121 + return NULL;
1.122 +}
1.123 +
1.124 +struct property *sym_get_default_prop(struct symbol *sym)
1.125 +{
1.126 + struct property *prop;
1.127 +
1.128 + for_all_defaults(sym, prop) {
1.129 + prop->visible.tri = expr_calc_value(prop->visible.expr);
1.130 + if (prop->visible.tri != no)
1.131 + return prop;
1.132 + }
1.133 + return NULL;
1.134 +}
1.135 +
1.136 +struct property *sym_get_range_prop(struct symbol *sym)
1.137 +{
1.138 + struct property *prop;
1.139 +
1.140 + for_all_properties(sym, prop, P_RANGE) {
1.141 + prop->visible.tri = expr_calc_value(prop->visible.expr);
1.142 + if (prop->visible.tri != no)
1.143 + return prop;
1.144 + }
1.145 + return NULL;
1.146 +}
1.147 +
1.148 +static int sym_get_range_val(struct symbol *sym, int base)
1.149 +{
1.150 + sym_calc_value(sym);
1.151 + switch (sym->type) {
1.152 + case S_INT:
1.153 + base = 10;
1.154 + break;
1.155 + case S_HEX:
1.156 + base = 16;
1.157 + break;
1.158 + default:
1.159 + break;
1.160 + }
1.161 + return strtol(sym->curr.val, NULL, base);
1.162 +}
1.163 +
1.164 +static void sym_validate_range(struct symbol *sym)
1.165 +{
1.166 + struct property *prop;
1.167 + int base, val, val2;
1.168 + char str[64];
1.169 +
1.170 + switch (sym->type) {
1.171 + case S_INT:
1.172 + base = 10;
1.173 + break;
1.174 + case S_HEX:
1.175 + base = 16;
1.176 + break;
1.177 + default:
1.178 + return;
1.179 + }
1.180 + prop = sym_get_range_prop(sym);
1.181 + if (!prop)
1.182 + return;
1.183 + val = strtol(sym->curr.val, NULL, base);
1.184 + val2 = sym_get_range_val(prop->expr->left.sym, base);
1.185 + if (val >= val2) {
1.186 + val2 = sym_get_range_val(prop->expr->right.sym, base);
1.187 + if (val <= val2)
1.188 + return;
1.189 + }
1.190 + if (sym->type == S_INT)
1.191 + sprintf(str, "%d", val2);
1.192 + else
1.193 + sprintf(str, "0x%x", val2);
1.194 + sym->curr.val = strdup(str);
1.195 +}
1.196 +
1.197 +static void sym_calc_visibility(struct symbol *sym)
1.198 +{
1.199 + struct property *prop;
1.200 + tristate tri;
1.201 +
1.202 + /* any prompt visible? */
1.203 + tri = no;
1.204 + for_all_prompts(sym, prop) {
1.205 + prop->visible.tri = expr_calc_value(prop->visible.expr);
1.206 + tri = E_OR(tri, prop->visible.tri);
1.207 + }
1.208 + if (tri == mod && (sym->type != S_TRISTATE || modules_val == no))
1.209 + tri = yes;
1.210 + if (sym->visible != tri) {
1.211 + sym->visible = tri;
1.212 + sym_set_changed(sym);
1.213 + }
1.214 + if (sym_is_choice_value(sym))
1.215 + return;
1.216 + tri = no;
1.217 + if (sym->rev_dep.expr)
1.218 + tri = expr_calc_value(sym->rev_dep.expr);
1.219 + if (tri == mod && sym_get_type(sym) == S_BOOLEAN)
1.220 + tri = yes;
1.221 + if (sym->rev_dep.tri != tri) {
1.222 + sym->rev_dep.tri = tri;
1.223 + sym_set_changed(sym);
1.224 + }
1.225 +}
1.226 +
1.227 +static struct symbol *sym_calc_choice(struct symbol *sym)
1.228 +{
1.229 + struct symbol *def_sym;
1.230 + struct property *prop;
1.231 + struct expr *e;
1.232 +
1.233 + /* is the user choice visible? */
1.234 + def_sym = sym->def[S_DEF_USER].val;
1.235 + if (def_sym) {
1.236 + sym_calc_visibility(def_sym);
1.237 + if (def_sym->visible != no)
1.238 + return def_sym;
1.239 + }
1.240 +
1.241 + /* any of the defaults visible? */
1.242 + for_all_defaults(sym, prop) {
1.243 + prop->visible.tri = expr_calc_value(prop->visible.expr);
1.244 + if (prop->visible.tri == no)
1.245 + continue;
1.246 + def_sym = prop_get_symbol(prop);
1.247 + sym_calc_visibility(def_sym);
1.248 + if (def_sym->visible != no)
1.249 + return def_sym;
1.250 + }
1.251 +
1.252 + /* just get the first visible value */
1.253 + prop = sym_get_choice_prop(sym);
1.254 + for (e = prop->expr; e; e = e->left.expr) {
1.255 + def_sym = e->right.sym;
1.256 + sym_calc_visibility(def_sym);
1.257 + if (def_sym->visible != no)
1.258 + return def_sym;
1.259 + }
1.260 +
1.261 + /* no choice? reset tristate value */
1.262 + sym->curr.tri = no;
1.263 + return NULL;
1.264 +}
1.265 +
1.266 +void sym_calc_value(struct symbol *sym)
1.267 +{
1.268 + struct symbol_value newval, oldval;
1.269 + struct property *prop;
1.270 + struct expr *e;
1.271 +
1.272 + if (!sym)
1.273 + return;
1.274 +
1.275 + if (sym->flags & SYMBOL_VALID)
1.276 + return;
1.277 + sym->flags |= SYMBOL_VALID;
1.278 +
1.279 + oldval = sym->curr;
1.280 +
1.281 + switch (sym->type) {
1.282 + case S_INT:
1.283 + case S_HEX:
1.284 + case S_STRING:
1.285 + newval = symbol_empty.curr;
1.286 + break;
1.287 + case S_BOOLEAN:
1.288 + case S_TRISTATE:
1.289 + newval = symbol_no.curr;
1.290 + break;
1.291 + default:
1.292 + sym->curr.val = sym->name;
1.293 + sym->curr.tri = no;
1.294 + return;
1.295 + }
1.296 + if (!sym_is_choice_value(sym))
1.297 + sym->flags &= ~SYMBOL_WRITE;
1.298 +
1.299 + sym_calc_visibility(sym);
1.300 +
1.301 + /* set default if recursively called */
1.302 + sym->curr = newval;
1.303 +
1.304 + switch (sym_get_type(sym)) {
1.305 + case S_BOOLEAN:
1.306 + case S_TRISTATE:
1.307 + if (sym_is_choice_value(sym) && sym->visible == yes) {
1.308 + prop = sym_get_choice_prop(sym);
1.309 + newval.tri = (prop_get_symbol(prop)->curr.val == sym) ? yes : no;
1.310 + } else if (E_OR(sym->visible, sym->rev_dep.tri) != no) {
1.311 + sym->flags |= SYMBOL_WRITE;
1.312 + if (sym_has_value(sym))
1.313 + newval.tri = sym->def[S_DEF_USER].tri;
1.314 + else if (!sym_is_choice(sym)) {
1.315 + prop = sym_get_default_prop(sym);
1.316 + if (prop)
1.317 + newval.tri = expr_calc_value(prop->expr);
1.318 + }
1.319 + newval.tri = E_OR(E_AND(newval.tri, sym->visible), sym->rev_dep.tri);
1.320 + } else if (!sym_is_choice(sym)) {
1.321 + prop = sym_get_default_prop(sym);
1.322 + if (prop) {
1.323 + sym->flags |= SYMBOL_WRITE;
1.324 + newval.tri = expr_calc_value(prop->expr);
1.325 + }
1.326 + }
1.327 + if (newval.tri == mod && sym_get_type(sym) == S_BOOLEAN)
1.328 + newval.tri = yes;
1.329 + break;
1.330 + case S_STRING:
1.331 + case S_HEX:
1.332 + case S_INT:
1.333 + if (sym->visible != no) {
1.334 + sym->flags |= SYMBOL_WRITE;
1.335 + if (sym_has_value(sym)) {
1.336 + newval.val = sym->def[S_DEF_USER].val;
1.337 + break;
1.338 + }
1.339 + }
1.340 + prop = sym_get_default_prop(sym);
1.341 + if (prop) {
1.342 + struct symbol *ds = prop_get_symbol(prop);
1.343 + if (ds) {
1.344 + sym->flags |= SYMBOL_WRITE;
1.345 + sym_calc_value(ds);
1.346 + newval.val = ds->curr.val;
1.347 + }
1.348 + }
1.349 + break;
1.350 + default:
1.351 + ;
1.352 + }
1.353 +
1.354 + sym->curr = newval;
1.355 + if (sym_is_choice(sym) && newval.tri == yes)
1.356 + sym->curr.val = sym_calc_choice(sym);
1.357 + sym_validate_range(sym);
1.358 +
1.359 + if (memcmp(&oldval, &sym->curr, sizeof(oldval))) {
1.360 + sym_set_changed(sym);
1.361 + if (modules_sym == sym) {
1.362 + sym_set_all_changed();
1.363 + modules_val = modules_sym->curr.tri;
1.364 + }
1.365 + }
1.366 +
1.367 + if (sym_is_choice(sym)) {
1.368 + int flags = sym->flags & (SYMBOL_CHANGED | SYMBOL_WRITE);
1.369 + prop = sym_get_choice_prop(sym);
1.370 + for (e = prop->expr; e; e = e->left.expr) {
1.371 + e->right.sym->flags |= flags;
1.372 + if (flags & SYMBOL_CHANGED)
1.373 + sym_set_changed(e->right.sym);
1.374 + }
1.375 + }
1.376 +}
1.377 +
1.378 +void sym_clear_all_valid(void)
1.379 +{
1.380 + struct symbol *sym;
1.381 + int i;
1.382 +
1.383 + for_all_symbols(i, sym)
1.384 + sym->flags &= ~SYMBOL_VALID;
1.385 + sym_change_count++;
1.386 + if (modules_sym)
1.387 + sym_calc_value(modules_sym);
1.388 +}
1.389 +
1.390 +void sym_set_changed(struct symbol *sym)
1.391 +{
1.392 + struct property *prop;
1.393 +
1.394 + sym->flags |= SYMBOL_CHANGED;
1.395 + for (prop = sym->prop; prop; prop = prop->next) {
1.396 + if (prop->menu)
1.397 + prop->menu->flags |= MENU_CHANGED;
1.398 + }
1.399 +}
1.400 +
1.401 +void sym_set_all_changed(void)
1.402 +{
1.403 + struct symbol *sym;
1.404 + int i;
1.405 +
1.406 + for_all_symbols(i, sym)
1.407 + sym_set_changed(sym);
1.408 +}
1.409 +
1.410 +bool sym_tristate_within_range(struct symbol *sym, tristate val)
1.411 +{
1.412 + int type = sym_get_type(sym);
1.413 +
1.414 + if (sym->visible == no)
1.415 + return false;
1.416 +
1.417 + if (type != S_BOOLEAN && type != S_TRISTATE)
1.418 + return false;
1.419 +
1.420 + if (type == S_BOOLEAN && val == mod)
1.421 + return false;
1.422 + if (sym->visible <= sym->rev_dep.tri)
1.423 + return false;
1.424 + if (sym_is_choice_value(sym) && sym->visible == yes)
1.425 + return val == yes;
1.426 + return val >= sym->rev_dep.tri && val <= sym->visible;
1.427 +}
1.428 +
1.429 +bool sym_set_tristate_value(struct symbol *sym, tristate val)
1.430 +{
1.431 + tristate oldval = sym_get_tristate_value(sym);
1.432 +
1.433 + if (oldval != val && !sym_tristate_within_range(sym, val))
1.434 + return false;
1.435 +
1.436 + if (!(sym->flags & SYMBOL_DEF_USER)) {
1.437 + sym->flags |= SYMBOL_DEF_USER;
1.438 + sym_set_changed(sym);
1.439 + }
1.440 + /*
1.441 + * setting a choice value also resets the new flag of the choice
1.442 + * symbol and all other choice values.
1.443 + */
1.444 + if (sym_is_choice_value(sym) && val == yes) {
1.445 + struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
1.446 + struct property *prop;
1.447 + struct expr *e;
1.448 +
1.449 + cs->def[S_DEF_USER].val = sym;
1.450 + cs->flags |= SYMBOL_DEF_USER;
1.451 + prop = sym_get_choice_prop(cs);
1.452 + for (e = prop->expr; e; e = e->left.expr) {
1.453 + if (e->right.sym->visible != no)
1.454 + e->right.sym->flags |= SYMBOL_DEF_USER;
1.455 + }
1.456 + }
1.457 +
1.458 + sym->def[S_DEF_USER].tri = val;
1.459 + if (oldval != val)
1.460 + sym_clear_all_valid();
1.461 +
1.462 + return true;
1.463 +}
1.464 +
1.465 +tristate sym_toggle_tristate_value(struct symbol *sym)
1.466 +{
1.467 + tristate oldval, newval;
1.468 +
1.469 + oldval = newval = sym_get_tristate_value(sym);
1.470 + do {
1.471 + switch (newval) {
1.472 + case no:
1.473 + newval = mod;
1.474 + break;
1.475 + case mod:
1.476 + newval = yes;
1.477 + break;
1.478 + case yes:
1.479 + newval = no;
1.480 + break;
1.481 + }
1.482 + if (sym_set_tristate_value(sym, newval))
1.483 + break;
1.484 + } while (oldval != newval);
1.485 + return newval;
1.486 +}
1.487 +
1.488 +bool sym_string_valid(struct symbol *sym, const char *str)
1.489 +{
1.490 + signed char ch;
1.491 +
1.492 + switch (sym->type) {
1.493 + case S_STRING:
1.494 + return true;
1.495 + case S_INT:
1.496 + ch = *str++;
1.497 + if (ch == '-')
1.498 + ch = *str++;
1.499 + if (!isdigit(ch))
1.500 + return false;
1.501 + if (ch == '0' && *str != 0)
1.502 + return false;
1.503 + while ((ch = *str++)) {
1.504 + if (!isdigit(ch))
1.505 + return false;
1.506 + }
1.507 + return true;
1.508 + case S_HEX:
1.509 + if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
1.510 + str += 2;
1.511 + ch = *str++;
1.512 + do {
1.513 + if (!isxdigit(ch))
1.514 + return false;
1.515 + } while ((ch = *str++));
1.516 + return true;
1.517 + case S_BOOLEAN:
1.518 + case S_TRISTATE:
1.519 + switch (str[0]) {
1.520 + case 'y': case 'Y':
1.521 + case 'm': case 'M':
1.522 + case 'n': case 'N':
1.523 + return true;
1.524 + }
1.525 + return false;
1.526 + default:
1.527 + return false;
1.528 + }
1.529 +}
1.530 +
1.531 +bool sym_string_within_range(struct symbol *sym, const char *str)
1.532 +{
1.533 + struct property *prop;
1.534 + int val;
1.535 +
1.536 + switch (sym->type) {
1.537 + case S_STRING:
1.538 + return sym_string_valid(sym, str);
1.539 + case S_INT:
1.540 + if (!sym_string_valid(sym, str))
1.541 + return false;
1.542 + prop = sym_get_range_prop(sym);
1.543 + if (!prop)
1.544 + return true;
1.545 + val = strtol(str, NULL, 10);
1.546 + return val >= sym_get_range_val(prop->expr->left.sym, 10) &&
1.547 + val <= sym_get_range_val(prop->expr->right.sym, 10);
1.548 + case S_HEX:
1.549 + if (!sym_string_valid(sym, str))
1.550 + return false;
1.551 + prop = sym_get_range_prop(sym);
1.552 + if (!prop)
1.553 + return true;
1.554 + val = strtol(str, NULL, 16);
1.555 + return val >= sym_get_range_val(prop->expr->left.sym, 16) &&
1.556 + val <= sym_get_range_val(prop->expr->right.sym, 16);
1.557 + case S_BOOLEAN:
1.558 + case S_TRISTATE:
1.559 + switch (str[0]) {
1.560 + case 'y': case 'Y':
1.561 + return sym_tristate_within_range(sym, yes);
1.562 + case 'm': case 'M':
1.563 + return sym_tristate_within_range(sym, mod);
1.564 + case 'n': case 'N':
1.565 + return sym_tristate_within_range(sym, no);
1.566 + }
1.567 + return false;
1.568 + default:
1.569 + return false;
1.570 + }
1.571 +}
1.572 +
1.573 +bool sym_set_string_value(struct symbol *sym, const char *newval)
1.574 +{
1.575 + const char *oldval;
1.576 + char *val;
1.577 + int size;
1.578 +
1.579 + switch (sym->type) {
1.580 + case S_BOOLEAN:
1.581 + case S_TRISTATE:
1.582 + switch (newval[0]) {
1.583 + case 'y': case 'Y':
1.584 + return sym_set_tristate_value(sym, yes);
1.585 + case 'm': case 'M':
1.586 + return sym_set_tristate_value(sym, mod);
1.587 + case 'n': case 'N':
1.588 + return sym_set_tristate_value(sym, no);
1.589 + }
1.590 + return false;
1.591 + default:
1.592 + ;
1.593 + }
1.594 +
1.595 + if (!sym_string_within_range(sym, newval))
1.596 + return false;
1.597 +
1.598 + if (!(sym->flags & SYMBOL_DEF_USER)) {
1.599 + sym->flags |= SYMBOL_DEF_USER;
1.600 + sym_set_changed(sym);
1.601 + }
1.602 +
1.603 + oldval = sym->def[S_DEF_USER].val;
1.604 + size = strlen(newval) + 1;
1.605 + if (sym->type == S_HEX && (newval[0] != '0' || (newval[1] != 'x' && newval[1] != 'X'))) {
1.606 + size += 2;
1.607 + sym->def[S_DEF_USER].val = val = malloc(size);
1.608 + *val++ = '0';
1.609 + *val++ = 'x';
1.610 + } else if (!oldval || strcmp(oldval, newval))
1.611 + sym->def[S_DEF_USER].val = val = malloc(size);
1.612 + else
1.613 + return true;
1.614 +
1.615 + strcpy(val, newval);
1.616 + free((void *)oldval);
1.617 + sym_clear_all_valid();
1.618 +
1.619 + return true;
1.620 +}
1.621 +
1.622 +const char *sym_get_string_value(struct symbol *sym)
1.623 +{
1.624 + tristate val;
1.625 +
1.626 + switch (sym->type) {
1.627 + case S_BOOLEAN:
1.628 + case S_TRISTATE:
1.629 + val = sym_get_tristate_value(sym);
1.630 + switch (val) {
1.631 + case no:
1.632 + return "n";
1.633 + case mod:
1.634 + return "m";
1.635 + case yes:
1.636 + return "y";
1.637 + }
1.638 + break;
1.639 + default:
1.640 + ;
1.641 + }
1.642 + return (const char *)sym->curr.val;
1.643 +}
1.644 +
1.645 +bool sym_is_changable(struct symbol *sym)
1.646 +{
1.647 + return sym->visible > sym->rev_dep.tri;
1.648 +}
1.649 +
1.650 +struct symbol *sym_lookup(const char *name, int isconst)
1.651 +{
1.652 + struct symbol *symbol;
1.653 + const char *ptr;
1.654 + char *new_name;
1.655 + int hash = 0;
1.656 +
1.657 + if (name) {
1.658 + if (name[0] && !name[1]) {
1.659 + switch (name[0]) {
1.660 + case 'y': return &symbol_yes;
1.661 + case 'm': return &symbol_mod;
1.662 + case 'n': return &symbol_no;
1.663 + }
1.664 + }
1.665 + for (ptr = name; *ptr; ptr++)
1.666 + hash += *ptr;
1.667 + hash &= 0xff;
1.668 +
1.669 + for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
1.670 + if (!strcmp(symbol->name, name)) {
1.671 + if ((isconst && symbol->flags & SYMBOL_CONST) ||
1.672 + (!isconst && !(symbol->flags & SYMBOL_CONST)))
1.673 + return symbol;
1.674 + }
1.675 + }
1.676 + new_name = strdup(name);
1.677 + } else {
1.678 + new_name = NULL;
1.679 + hash = 256;
1.680 + }
1.681 +
1.682 + symbol = malloc(sizeof(*symbol));
1.683 + memset(symbol, 0, sizeof(*symbol));
1.684 + symbol->name = new_name;
1.685 + symbol->type = S_UNKNOWN;
1.686 + if (isconst)
1.687 + symbol->flags |= SYMBOL_CONST;
1.688 +
1.689 + symbol->next = symbol_hash[hash];
1.690 + symbol_hash[hash] = symbol;
1.691 +
1.692 + return symbol;
1.693 +}
1.694 +
1.695 +struct symbol *sym_find(const char *name)
1.696 +{
1.697 + struct symbol *symbol = NULL;
1.698 + const char *ptr;
1.699 + int hash = 0;
1.700 +
1.701 + if (!name)
1.702 + return NULL;
1.703 +
1.704 + if (name[0] && !name[1]) {
1.705 + switch (name[0]) {
1.706 + case 'y': return &symbol_yes;
1.707 + case 'm': return &symbol_mod;
1.708 + case 'n': return &symbol_no;
1.709 + }
1.710 + }
1.711 + for (ptr = name; *ptr; ptr++)
1.712 + hash += *ptr;
1.713 + hash &= 0xff;
1.714 +
1.715 + for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
1.716 + if (!strcmp(symbol->name, name) &&
1.717 + !(symbol->flags & SYMBOL_CONST))
1.718 + break;
1.719 + }
1.720 +
1.721 + return symbol;
1.722 +}
1.723 +
1.724 +struct symbol **sym_re_search(const char *pattern)
1.725 +{
1.726 + struct symbol *sym, **sym_arr = NULL;
1.727 + int i, cnt, size;
1.728 + regex_t re;
1.729 +
1.730 + cnt = size = 0;
1.731 + /* Skip if empty */
1.732 + if (strlen(pattern) == 0)
1.733 + return NULL;
1.734 + if (regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB|REG_ICASE))
1.735 + return NULL;
1.736 +
1.737 + for_all_symbols(i, sym) {
1.738 + if (sym->flags & SYMBOL_CONST || !sym->name)
1.739 + continue;
1.740 + if (regexec(&re, sym->name, 0, NULL, 0))
1.741 + continue;
1.742 + if (cnt + 1 >= size) {
1.743 + void *tmp = sym_arr;
1.744 + size += 16;
1.745 + sym_arr = realloc(sym_arr, size * sizeof(struct symbol *));
1.746 + if (!sym_arr) {
1.747 + free(tmp);
1.748 + return NULL;
1.749 + }
1.750 + }
1.751 + sym_arr[cnt++] = sym;
1.752 + }
1.753 + if (sym_arr)
1.754 + sym_arr[cnt] = NULL;
1.755 + regfree(&re);
1.756 +
1.757 + return sym_arr;
1.758 +}
1.759 +
1.760 +
1.761 +struct symbol *sym_check_deps(struct symbol *sym);
1.762 +
1.763 +static struct symbol *sym_check_expr_deps(struct expr *e)
1.764 +{
1.765 + struct symbol *sym;
1.766 +
1.767 + if (!e)
1.768 + return NULL;
1.769 + switch (e->type) {
1.770 + case E_OR:
1.771 + case E_AND:
1.772 + sym = sym_check_expr_deps(e->left.expr);
1.773 + if (sym)
1.774 + return sym;
1.775 + return sym_check_expr_deps(e->right.expr);
1.776 + case E_NOT:
1.777 + return sym_check_expr_deps(e->left.expr);
1.778 + case E_EQUAL:
1.779 + case E_UNEQUAL:
1.780 + sym = sym_check_deps(e->left.sym);
1.781 + if (sym)
1.782 + return sym;
1.783 + return sym_check_deps(e->right.sym);
1.784 + case E_SYMBOL:
1.785 + return sym_check_deps(e->left.sym);
1.786 + default:
1.787 + break;
1.788 + }
1.789 + printf("Oops! How to check %d?\n", e->type);
1.790 + return NULL;
1.791 +}
1.792 +
1.793 +struct symbol *sym_check_deps(struct symbol *sym)
1.794 +{
1.795 + struct symbol *sym2;
1.796 + struct property *prop;
1.797 +
1.798 + if (sym->flags & SYMBOL_CHECK) {
1.799 + printf("Warning! Found recursive dependency: %s", sym->name);
1.800 + return sym;
1.801 + }
1.802 + if (sym->flags & SYMBOL_CHECKED)
1.803 + return NULL;
1.804 +
1.805 + sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);
1.806 + sym2 = sym_check_expr_deps(sym->rev_dep.expr);
1.807 + if (sym2)
1.808 + goto out;
1.809 +
1.810 + for (prop = sym->prop; prop; prop = prop->next) {
1.811 + if (prop->type == P_CHOICE || prop->type == P_SELECT)
1.812 + continue;
1.813 + sym2 = sym_check_expr_deps(prop->visible.expr);
1.814 + if (sym2)
1.815 + goto out;
1.816 + if (prop->type != P_DEFAULT || sym_is_choice(sym))
1.817 + continue;
1.818 + sym2 = sym_check_expr_deps(prop->expr);
1.819 + if (sym2)
1.820 + goto out;
1.821 + }
1.822 +out:
1.823 + if (sym2) {
1.824 + printf(" %s", sym->name);
1.825 + if (sym2 == sym) {
1.826 + printf("\n");
1.827 + sym2 = NULL;
1.828 + }
1.829 + }
1.830 + sym->flags &= ~SYMBOL_CHECK;
1.831 + return sym2;
1.832 +}
1.833 +
1.834 +struct property *prop_alloc(enum prop_type type, struct symbol *sym)
1.835 +{
1.836 + struct property *prop;
1.837 + struct property **propp;
1.838 +
1.839 + prop = malloc(sizeof(*prop));
1.840 + memset(prop, 0, sizeof(*prop));
1.841 + prop->type = type;
1.842 + prop->sym = sym;
1.843 + prop->file = current_file;
1.844 + prop->lineno = zconf_lineno();
1.845 +
1.846 + /* append property to the prop list of symbol */
1.847 + if (sym) {
1.848 + for (propp = &sym->prop; *propp; propp = &(*propp)->next)
1.849 + ;
1.850 + *propp = prop;
1.851 + }
1.852 +
1.853 + return prop;
1.854 +}
1.855 +
1.856 +struct symbol *prop_get_symbol(struct property *prop)
1.857 +{
1.858 + if (prop->expr && (prop->expr->type == E_SYMBOL ||
1.859 + prop->expr->type == E_CHOICE))
1.860 + return prop->expr->left.sym;
1.861 + return NULL;
1.862 +}
1.863 +
1.864 +const char *prop_get_type_name(enum prop_type type)
1.865 +{
1.866 + switch (type) {
1.867 + case P_PROMPT:
1.868 + return "prompt";
1.869 + case P_COMMENT:
1.870 + return "comment";
1.871 + case P_MENU:
1.872 + return "menu";
1.873 + case P_DEFAULT:
1.874 + return "default";
1.875 + case P_CHOICE:
1.876 + return "choice";
1.877 + case P_SELECT:
1.878 + return "select";
1.879 + case P_RANGE:
1.880 + return "range";
1.881 + case P_UNKNOWN:
1.882 + break;
1.883 + }
1.884 + return "unknown";
1.885 +}