📄 symbol.c
字号:
/* * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> * Released under the terms of the GNU GPL v2.0. */#include <ctype.h>#include <stdlib.h>#include <string.h>#include <regex.h>#include <sys/utsname.h>#define LKC_DIRECT_LINK#include "lkc.h"struct symbol symbol_yes = { .name = "y", .curr = { "y", yes }, .flags = SYMBOL_YES|SYMBOL_VALID,}, symbol_mod = { .name = "m", .curr = { "m", mod }, .flags = SYMBOL_MOD|SYMBOL_VALID,}, symbol_no = { .name = "n", .curr = { "n", no }, .flags = SYMBOL_NO|SYMBOL_VALID,}, symbol_empty = { .name = "", .curr = { "", no }, .flags = SYMBOL_VALID,};int sym_change_count;struct symbol *modules_sym;tristate modules_val;void sym_add_default(struct symbol *sym, const char *def){ struct property *prop = prop_alloc(P_DEFAULT, sym); prop->expr = expr_alloc_symbol(sym_lookup(def, 1));}void sym_init(void){ struct symbol *sym; struct utsname uts; char *p; static bool inited = false; if (inited) return; inited = true; uname(&uts); sym = sym_lookup("ARCH", 0); sym->type = S_STRING; sym->flags |= SYMBOL_AUTO; p = getenv("ARCH"); if (p) sym_add_default(sym, p); sym = sym_lookup("KERNELVERSION", 0); sym->type = S_STRING; sym->flags |= SYMBOL_AUTO; p = getenv("KERNELVERSION"); if (p) sym_add_default(sym, p); sym = sym_lookup("UNAME_RELEASE", 0); sym->type = S_STRING; sym->flags |= SYMBOL_AUTO; sym_add_default(sym, uts.release);}enum symbol_type sym_get_type(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; } return type;}const char *sym_type_name(enum symbol_type type){ switch (type) { case S_BOOLEAN: return "boolean"; case S_TRISTATE: return "tristate"; case S_INT: return "integer"; case S_HEX: return "hex"; case S_STRING: return "string"; case S_UNKNOWN: return "unknown"; case S_OTHER: break; } return "???";}struct property *sym_get_choice_prop(struct symbol *sym){ struct property *prop; for_all_choices(sym, prop) return prop; return NULL;}struct property *sym_get_default_prop(struct symbol *sym){ struct property *prop; for_all_defaults(sym, prop) { prop->visible.tri = expr_calc_value(prop->visible.expr); if (prop->visible.tri != no) return prop; } return NULL;}struct property *sym_get_range_prop(struct symbol *sym){ struct property *prop; for_all_properties(sym, prop, P_RANGE) { prop->visible.tri = expr_calc_value(prop->visible.expr); if (prop->visible.tri != no) return prop; } return NULL;}static int sym_get_range_val(struct symbol *sym, int base){ sym_calc_value(sym); switch (sym->type) { case S_INT: base = 10; break; case S_HEX: base = 16; break; default: break; } return strtol(sym->curr.val, NULL, base);}static void sym_validate_range(struct symbol *sym){ struct property *prop; int base, val, val2; char str[64]; switch (sym->type) { case S_INT: base = 10; break; case S_HEX: base = 16; break; default: return; } prop = sym_get_range_prop(sym); if (!prop) return; val = strtol(sym->curr.val, NULL, base); val2 = sym_get_range_val(prop->expr->left.sym, base); if (val >= val2) { val2 = sym_get_range_val(prop->expr->right.sym, base); if (val <= val2) return; } if (sym->type == S_INT) sprintf(str, "%d", val2); else sprintf(str, "0x%x", val2); sym->curr.val = strdup(str);}static void sym_calc_visibility(struct symbol *sym){ struct property *prop; tristate tri; /* any prompt visible? */ tri = no; for_all_prompts(sym, prop) { prop->visible.tri = expr_calc_value(prop->visible.expr); tri = E_OR(tri, prop->visible.tri); } if (tri == mod && (sym->type != S_TRISTATE || modules_val == no)) tri = yes; if (sym->visible != tri) { sym->visible = tri; sym_set_changed(sym); } if (sym_is_choice_value(sym)) return; tri = no; if (sym->rev_dep.expr) tri = expr_calc_value(sym->rev_dep.expr); if (tri == mod && sym_get_type(sym) == S_BOOLEAN) tri = yes; if (sym->rev_dep.tri != tri) { sym->rev_dep.tri = tri; sym_set_changed(sym); }}static struct symbol *sym_calc_choice(struct symbol *sym){ struct symbol *def_sym; struct property *prop; struct expr *e; /* is the user choice visible? */ def_sym = sym->user.val; if (def_sym) { sym_calc_visibility(def_sym); if (def_sym->visible != no) return def_sym; } /* any of the defaults visible? */ for_all_defaults(sym, prop) { prop->visible.tri = expr_calc_value(prop->visible.expr); if (prop->visible.tri == no) continue; def_sym = prop_get_symbol(prop); sym_calc_visibility(def_sym); if (def_sym->visible != no) return def_sym; } /* just get the first visible value */ prop = sym_get_choice_prop(sym); for (e = prop->expr; e; e = e->left.expr) { def_sym = e->right.sym; sym_calc_visibility(def_sym); if (def_sym->visible != no) return def_sym; } /* no choice? reset tristate value */ sym->curr.tri = no; return NULL;}void sym_calc_value(struct symbol *sym){ struct symbol_value newval, oldval; struct property *prop; struct expr *e; if (!sym) return; if (sym->flags & SYMBOL_VALID) return; sym->flags |= SYMBOL_VALID; oldval = sym->curr; switch (sym->type) { case S_INT: case S_HEX: case S_STRING: newval = symbol_empty.curr; break; case S_BOOLEAN: case S_TRISTATE: newval = symbol_no.curr; break; default: sym->curr.val = sym->name; sym->curr.tri = no; return; } if (!sym_is_choice_value(sym)) sym->flags &= ~SYMBOL_WRITE; sym_calc_visibility(sym); /* set default if recursively called */ sym->curr = newval; 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; } else if (E_OR(sym->visible, sym->rev_dep.tri) != no) { sym->flags |= SYMBOL_WRITE; if (sym_has_value(sym)) newval.tri = sym->user.tri; else if (!sym_is_choice(sym)) { prop = sym_get_default_prop(sym); if (prop) newval.tri = expr_calc_value(prop->expr); } newval.tri = E_OR(E_AND(newval.tri, sym->visible), sym->rev_dep.tri); } else if (!sym_is_choice(sym)) { prop = sym_get_default_prop(sym); if (prop) { sym->flags |= SYMBOL_WRITE; newval.tri = expr_calc_value(prop->expr); } } if (newval.tri == mod && sym_get_type(sym) == S_BOOLEAN) newval.tri = yes; break; case S_STRING: case S_HEX: case S_INT: if (sym->visible != no) { sym->flags |= SYMBOL_WRITE; if (sym_has_value(sym)) { newval.val = sym->user.val; break; } } prop = sym_get_default_prop(sym); if (prop) { struct symbol *ds = prop_get_symbol(prop); if (ds) { sym->flags |= SYMBOL_WRITE; sym_calc_value(ds); newval.val = ds->curr.val; } } break; default: ; } 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))) sym_set_changed(sym); if (modules_sym == sym) modules_val = modules_sym->curr.tri; if (sym_is_choice(sym)) { int flags = sym->flags & (SYMBOL_CHANGED | SYMBOL_WRITE); prop = sym_get_choice_prop(sym); for (e = prop->expr; e; e = e->left.expr) { e->right.sym->flags |= flags; if (flags & SYMBOL_CHANGED) sym_set_changed(e->right.sym); } }}void sym_clear_all_valid(void){ struct symbol *sym; int i; for_all_symbols(i, sym) sym->flags &= ~SYMBOL_VALID; sym_change_count++; if (modules_sym) sym_calc_value(modules_sym);}void sym_set_changed(struct symbol *sym){ struct property *prop; sym->flags |= SYMBOL_CHANGED; for (prop = sym->prop; prop; prop = prop->next) { if (prop->menu) prop->menu->flags |= MENU_CHANGED; }}void sym_set_all_changed(void){ struct symbol *sym; int i; for_all_symbols(i, sym) sym_set_changed(sym);}bool sym_tristate_within_range(struct symbol *sym, tristate val){ int type = sym_get_type(sym); if (sym->visible == no) return false; if (type != S_BOOLEAN && type != S_TRISTATE) return false; if (type == S_BOOLEAN && val == mod) 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;}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)) return false; if (sym->flags & SYMBOL_NEW) { sym->flags &= ~SYMBOL_NEW; 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->user.val = sym;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -