2 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
3 * Released under the terms of the GNU GPL v2.0.
9 #include <sys/utsname.h>
11 #define LKC_DIRECT_LINK
14 struct symbol symbol_yes = {
17 flags: SYMBOL_YES|SYMBOL_VALID,
21 flags: SYMBOL_MOD|SYMBOL_VALID,
25 flags: SYMBOL_NO|SYMBOL_VALID,
33 struct symbol *modules_sym;
35 void sym_add_default(struct symbol *sym, const char *def)
37 struct property *prop = create_prop(P_DEFAULT);
38 struct property **propp;
41 prop->def = sym_lookup(def, 1);
43 /* append property to the prop list of symbol */
45 for (propp = &prop->sym->prop; *propp; propp = &(*propp)->next)
56 static bool inited = false;
65 sym = sym_lookup("ARCH", 0);
67 sym->flags |= SYMBOL_AUTO;
70 sym_add_default(sym, p);
73 sym = sym_lookup("VERSION", 0);
75 sym->flags |= SYMBOL_AUTO;
76 p = getenv("VERSION");
78 sym_add_default(sym, p);
81 sym = sym_lookup("UNAME_RELEASE", 0);
83 sym->flags |= SYMBOL_AUTO;
84 sym_add_default(sym, uts.release);
87 sym = sym_lookup("TARGET_ARCH", 0);
89 sym->flags |= SYMBOL_AUTO;
90 p = getenv("TARGET_ARCH");
92 sym_add_default(sym, p);
95 int sym_get_type(struct symbol *sym)
98 if (type == S_TRISTATE) {
99 if (sym_is_choice_value(sym) && sym->visible == yes)
102 sym_calc_value(modules_sym);
103 if (S_TRI(modules_sym->curr) == no)
110 const char *sym_type_name(int type)
129 struct property *sym_get_choice_prop(struct symbol *sym)
131 struct property *prop;
133 for_all_choices(sym, prop)
138 struct property *sym_get_default_prop(struct symbol *sym)
140 struct property *prop;
143 for_all_defaults(sym, prop) {
144 visible = E_CALC(prop->visible);
151 void sym_calc_visibility(struct symbol *sym)
153 struct property *prop;
154 tristate visible, oldvisible;
156 /* any prompt visible? */
157 oldvisible = sym->visible;
159 for_all_prompts(sym, prop)
160 visible = E_OR(visible, E_CALC(prop->visible));
161 if (oldvisible != visible) {
162 sym->visible = visible;
163 sym->flags |= SYMBOL_CHANGED;
167 void sym_calc_value(struct symbol *sym)
169 struct symbol_value newval, oldval;
170 struct property *prop, *def_prop;
171 struct symbol *def_sym;
174 if (sym->flags & SYMBOL_VALID)
183 newval = symbol_empty.curr;
187 newval = symbol_no.curr;
190 S_VAL(newval) = sym->name;
192 if (sym->flags & SYMBOL_CONST) {
195 //newval = symbol_empty.curr;
196 // generate warning somewhere here later
197 //S_TRI(newval) = yes;
200 sym->flags |= SYMBOL_VALID;
201 if (!sym_is_choice_value(sym))
202 sym->flags &= ~SYMBOL_WRITE;
204 sym_calc_visibility(sym);
206 /* set default if recursively called */
209 if (sym->visible != no) {
210 sym->flags |= SYMBOL_WRITE;
211 if (!sym_has_value(sym)) {
212 if (!sym_is_choice(sym)) {
213 prop = sym_get_default_prop(sym);
215 sym_calc_value(prop->def);
216 newval = prop->def->curr;
222 S_TRI(newval) = E_AND(S_TRI(newval), sym->visible);
223 /* if the symbol is visible and not optionial,
224 * possibly ignore old user choice. */
225 if (!sym_is_optional(sym) && S_TRI(newval) == no)
226 S_TRI(newval) = sym->visible;
227 if (sym_is_choice_value(sym) && sym->visible == yes) {
228 prop = sym_get_choice_prop(sym);
229 S_TRI(newval) = (S_VAL(prop->def->curr) == sym) ? yes : no;
232 prop = sym_get_default_prop(sym);
234 sym->flags |= SYMBOL_WRITE;
235 sym_calc_value(prop->def);
236 newval = prop->def->curr;
240 switch (sym_get_type(sym)) {
242 if (S_TRI(newval) != mod)
244 sym_calc_value(modules_sym);
245 if (S_TRI(modules_sym->curr) == no)
249 if (S_TRI(newval) == mod)
256 if (sym_is_choice(sym) && S_TRI(newval) == yes) {
257 def_sym = S_VAL(sym->def);
259 sym_calc_visibility(def_sym);
260 if (def_sym->visible == no)
264 for_all_defaults(sym, def_prop) {
265 if (E_CALC(def_prop->visible) == no)
267 sym_calc_visibility(def_prop->def);
268 if (def_prop->def->visible != no) {
269 def_sym = def_prop->def;
276 prop = sym_get_choice_prop(sym);
277 for (e = prop->dep; e; e = e->left.expr) {
278 sym_calc_visibility(e->right.sym);
279 if (e->right.sym->visible != no) {
280 def_sym = e->right.sym;
286 S_VAL(newval) = def_sym;
289 if (memcmp(&oldval, &newval, sizeof(newval)))
290 sym->flags |= SYMBOL_CHANGED;
293 if (sym_is_choice(sym)) {
294 int flags = sym->flags & (SYMBOL_CHANGED | SYMBOL_WRITE);
295 prop = sym_get_choice_prop(sym);
296 for (e = prop->dep; e; e = e->left.expr)
297 e->right.sym->flags |= flags;
301 void sym_clear_all_valid(void)
306 for_all_symbols(i, sym)
307 sym->flags &= ~SYMBOL_VALID;
311 void sym_set_all_changed(void)
316 for_all_symbols(i, sym)
317 sym->flags |= SYMBOL_CHANGED;
320 bool sym_tristate_within_range(struct symbol *sym, tristate val)
322 int type = sym_get_type(sym);
324 if (sym->visible == no)
327 if (type != S_BOOLEAN && type != S_TRISTATE)
332 if (sym_is_choice_value(sym) && sym->visible == yes)
334 return sym_is_optional(sym);
336 if (sym_is_choice_value(sym) && sym->visible == yes)
338 return type == S_TRISTATE;
340 return type == S_BOOLEAN || sym->visible == yes;
345 bool sym_set_tristate_value(struct symbol *sym, tristate val)
347 tristate oldval = sym_get_tristate_value(sym);
349 if (oldval != val && !sym_tristate_within_range(sym, val))
352 if (sym->flags & SYMBOL_NEW) {
353 sym->flags &= ~SYMBOL_NEW;
354 sym->flags |= SYMBOL_CHANGED;
356 if (sym_is_choice_value(sym) && val == yes) {
357 struct property *prop = sym_get_choice_prop(sym);
359 S_VAL(prop->def->def) = sym;
360 prop->def->flags &= ~SYMBOL_NEW;
363 S_TRI(sym->def) = val;
365 sym_clear_all_valid();
366 if (sym == modules_sym)
367 sym_set_all_changed();
373 tristate sym_toggle_tristate_value(struct symbol *sym)
375 tristate oldval, newval;
377 oldval = newval = sym_get_tristate_value(sym);
390 if (sym_set_tristate_value(sym, newval))
392 } while (oldval != newval);
396 bool sym_string_valid(struct symbol *sym, const char *str)
407 if (!isdigit((int)ch))
409 if (ch == '0' && *str != 0)
411 while ((ch = *str++)) {
412 if (!isdigit((int)ch))
417 if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
421 if (!isxdigit((int)ch))
423 } while ((ch = *str++));
430 return sym_tristate_within_range(sym, yes);
433 return sym_tristate_within_range(sym, mod);
436 return sym_tristate_within_range(sym, no);
444 bool sym_set_string_value(struct symbol *sym, const char *newval)
456 return sym_set_tristate_value(sym, yes);
459 return sym_set_tristate_value(sym, mod);
462 return sym_set_tristate_value(sym, no);
469 if (!sym_string_valid(sym, newval))
472 if (sym->flags & SYMBOL_NEW) {
473 sym->flags &= ~SYMBOL_NEW;
474 sym->flags |= SYMBOL_CHANGED;
477 oldval = S_VAL(sym->def);
478 size = strlen(newval) + 1;
479 if (sym->type == S_HEX && (newval[0] != '0' || (newval[1] != 'x' && newval[1] != 'X'))) {
481 S_VAL(sym->def) = val = malloc(size);
484 } else if (!oldval || strcmp(oldval, newval))
485 S_VAL(sym->def) = val = malloc(size);
490 free((void *)oldval);
491 sym_clear_all_valid();
496 const char *sym_get_string_value(struct symbol *sym)
503 val = sym_get_tristate_value(sym);
516 return (const char *)S_VAL(sym->curr);
519 bool sym_is_changable(struct symbol *sym)
521 if (sym->visible == no)
523 /* at least 'n' and 'y'/'m' is selectable */
524 if (sym_is_optional(sym))
526 /* no 'n', so 'y' and 'm' must be selectable */
527 if (sym_get_type(sym) == S_TRISTATE && sym->visible == yes)
532 struct symbol *sym_lookup(const char *name, int isconst)
534 struct symbol *symbol;
539 //printf("lookup: %s -> ", name);
541 if (name[0] && !name[1]) {
543 case 'y': return &symbol_yes;
544 case 'm': return &symbol_mod;
545 case 'n': return &symbol_no;
548 for (ptr = name; *ptr; ptr++)
552 for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
553 if (!strcmp(symbol->name, name)) {
554 if ((isconst && symbol->flags & SYMBOL_CONST) ||
555 (!isconst && !(symbol->flags & SYMBOL_CONST))) {
556 //printf("h:%p\n", symbol);
561 new_name = strdup(name);
567 symbol = malloc(sizeof(*symbol));
568 memset(symbol, 0, sizeof(*symbol));
569 symbol->name = new_name;
570 symbol->type = S_UNKNOWN;
571 symbol->flags = SYMBOL_NEW;
573 symbol->flags |= SYMBOL_CONST;
575 symbol->next = symbol_hash[hash];
576 symbol_hash[hash] = symbol;
578 //printf("n:%p\n", symbol);
582 struct symbol *sym_find(const char *name)
584 struct symbol *symbol = NULL;
591 if (name[0] && !name[1]) {
593 case 'y': return &symbol_yes;
594 case 'm': return &symbol_mod;
595 case 'n': return &symbol_no;
598 for (ptr = name; *ptr; ptr++)
602 for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
603 if (!strcmp(symbol->name, name) &&
604 !(symbol->flags & SYMBOL_CONST))
611 const char *prop_get_type_name(enum prop_type type)