Release 4.10 scripts/kconfig/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>
#include "lkc.h"
struct symbol symbol_yes = {
.name = "y",
.curr = { "y", yes },
.flags = SYMBOL_CONST|SYMBOL_VALID,
}
, symbol_mod = {
.name = "m",
.curr = { "m", mod },
.flags = SYMBOL_CONST|SYMBOL_VALID,
}
, symbol_no = {
.name = "n",
.curr = { "n", no },
.flags = SYMBOL_CONST|SYMBOL_VALID,
}
, symbol_empty = {
.name = "",
.curr = { "", no },
.flags = SYMBOL_VALID,
};
struct symbol *sym_defconfig_list;
struct symbol *modules_sym;
tristate modules_val;
struct expr *sym_env_list;
static 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, SYMBOL_CONST));
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
roman zippel | roman zippel | 41 | 97.62% | 3 | 75.00% |
trevor keith | trevor keith | 1 | 2.38% | 1 | 25.00% |
| Total | 42 | 100.00% | 4 | 100.00% |
void sym_init(void)
{
struct symbol *sym;
struct utsname uts;
static bool inited = false;
if (inited)
return;
inited = true;
uname(&uts);
sym = sym_lookup("UNAME_RELEASE", 0);
sym->type = S_STRING;
sym->flags |= SYMBOL_AUTO;
sym_add_default(sym, uts.release);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
roman zippel | roman zippel | 67 | 100.00% | 1 | 100.00% |
| Total | 67 | 100.00% | 1 | 100.00% |
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;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
roman zippel | roman zippel | 56 | 96.55% | 2 | 66.67% |
andrew morton | andrew morton | 2 | 3.45% | 1 | 33.33% |
| Total | 58 | 100.00% | 3 | 100.00% |
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 "???";
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
roman zippel | roman zippel | 60 | 100.00% | 2 | 100.00% |
| Total | 60 | 100.00% | 2 | 100.00% |
struct property *sym_get_choice_prop(struct symbol *sym)
{
struct property *prop;
for_all_choices(sym, prop)
return prop;
return NULL;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
roman zippel | roman zippel | 29 | 100.00% | 1 | 100.00% |
| Total | 29 | 100.00% | 1 | 100.00% |
struct property *sym_get_env_prop(struct symbol *sym)
{
struct property *prop;
for_all_properties(sym, prop, P_ENV)
return prop;
return NULL;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
roman zippel | roman zippel | 31 | 100.00% | 1 | 100.00% |
| Total | 31 | 100.00% | 1 | 100.00% |
static 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;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
roman zippel | roman zippel | 56 | 98.25% | 2 | 66.67% |
michal marek | michal marek | 1 | 1.75% | 1 | 33.33% |
| Total | 57 | 100.00% | 3 | 100.00% |
static 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;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
roman zippel | roman zippel | 58 | 98.31% | 1 | 50.00% |
trevor keith | trevor keith | 1 | 1.69% | 1 | 50.00% |
| Total | 59 | 100.00% | 2 | 100.00% |
static long long 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 strtoll(sym->curr.val, NULL, base);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
roman zippel | roman zippel | 57 | 95.00% | 1 | 33.33% |
kees cook | kees cook | 3 | 5.00% | 2 | 66.67% |
| Total | 60 | 100.00% | 3 | 100.00% |
static void sym_validate_range(struct symbol *sym)
{
struct property *prop;
int base;
long long 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 = strtoll(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, "%lld", val2);
else
sprintf(str, "0x%llx", val2);
sym->curr.val = strdup(str);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
roman zippel | roman zippel | 161 | 95.83% | 1 | 50.00% |
kees cook | kees cook | 7 | 4.17% | 1 | 50.00% |
| Total | 168 | 100.00% | 2 | 100.00% |
static 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;
}
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
michal marek | michal marek | 54 | 100.00% | 1 | 100.00% |
| Total | 54 | 100.00% | 1 | 100.00% |
static void sym_set_all_changed(void)
{
struct symbol *sym;
int i;
for_all_symbols(i, sym)
sym_set_changed(sym);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
michal marek | michal marek | 27 | 100.00% | 1 | 100.00% |
| Total | 27 | 100.00% | 1 | 100.00% |
static void sym_calc_visibility(struct symbol *sym)
{
struct property *prop;
struct symbol *choice_sym = NULL;
tristate tri;
/* any prompt visible? */
tri = no;
if (sym_is_choice_value(sym))
choice_sym = prop_get_symbol(sym_get_choice_prop(sym));
for_all_prompts(sym, prop) {
prop->visible.tri = expr_calc_value(prop->visible.expr);
/*
* Tristate choice_values with visibility 'mod' are
* not visible if the corresponding choice's value is
* 'yes'.
*/
if (choice_sym && sym->type == S_TRISTATE &&
prop->visible.tri == mod && choice_sym->curr.tri == yes)
prop->visible.tri = no;
tri = EXPR_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;
/* defaulting to "yes" if no explicit "depends on" are given */
tri = yes;
if (sym->dir_dep.expr)
tri = expr_calc_value(sym->dir_dep.expr);
if (tri == mod)
tri = yes;
if (sym->dir_dep.tri != tri) {
sym->dir_dep.tri = tri;
sym_set_changed(sym);
}
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);
}
tri = no;
if (sym->implied.expr && sym->dir_dep.tri != no)
tri = expr_calc_value(sym->implied.expr);
if (tri == mod && sym_get_type(sym) == S_BOOLEAN)
tri = yes;
if (sym->implied.tri != tri) {
sym->implied.tri = tri;
sym_set_changed(sym);
}
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
roman zippel | roman zippel | 136 | 37.06% | 5 | 50.00% |
nicolas pitre | nicolas pitre | 73 | 19.89% | 1 | 10.00% |
dirk gouders | dirk gouders | 59 | 16.08% | 1 | 10.00% |
catalin marinas | catalin marinas | 59 | 16.08% | 1 | 10.00% |
andrew morton | andrew morton | 39 | 10.63% | 1 | 10.00% |
sam ravnborg | sam ravnborg | 1 | 0.27% | 1 | 10.00% |
| Total | 367 | 100.00% | 10 | 100.00% |
/*
* Find the default symbol for a choice.
* First try the default values for the choice symbol
* Next locate the first visible choice value
* Return NULL if none was found
*/
struct symbol *sym_choice_default(struct symbol *sym)
{
struct symbol *def_sym;
struct property *prop;
struct expr *e;
/* 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);
if (def_sym->visible != no)
return def_sym;
}
/* just get the first visible value */
prop = sym_get_choice_prop(sym);
expr_list_for_each_sym(prop->expr, e, def_sym)
if (def_sym->visible != no)
return def_sym;
/* failed to locate any defaults */
return NULL;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
roman zippel | roman zippel | 105 | 94.59% | 2 | 66.67% |
sam ravnborg | sam ravnborg | 6 | 5.41% | 1 | 33.33% |
| Total | 111 | 100.00% | 3 | 100.00% |
static struct symbol *sym_calc_choice(struct symbol *sym)
{
struct symbol *def_sym;
struct property *prop;
struct expr *e;
int flags;
/* first calculate all choice values' visibilities */
flags = sym->flags;
prop = sym_get_choice_prop(sym);
expr_list_for_each_sym(prop->expr, e, def_sym) {
sym_calc_visibility(def_sym);
if (def_sym->visible != no)
flags &= def_sym->flags;
}
sym->flags &= flags | ~SYMBOL_DEF_USER;
/* is the user choice visible? */
def_sym = sym->def[S_DEF_USER].val;
if (def_sym && def_sym->visible != no)
return def_sym;
def_sym = sym_choice_default(sym);
if (def_sym == NULL)
/* no choice? reset tristate value */
sym->curr.tri = no;
return def_sym;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
sam ravnborg | sam ravnborg | 87 | 65.41% | 1 | 25.00% |
arnaud lacombe | arnaud lacombe | 34 | 25.56% | 1 | 25.00% |
roman zippel | roman zippel | 12 | 9.02% | 2 | 50.00% |
| Total | 133 | 100.00% | 4 | 100.00% |
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;
if (sym_is_choice_value(sym) &&
sym->flags & SYMBOL_NEED_SET_CHOICE_VALUES) {
sym->flags &= ~SYMBOL_NEED_SET_CHOICE_VALUES;
prop = sym_get_choice_prop(sym);
sym_calc_value(prop_get_symbol(prop));
}
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 (sym->visible != no) {
/* if the symbol is visible use the user value
* if available, otherwise try the default value
*/
sym->flags |= SYMBOL_WRITE;
if (sym_has_value(sym)) {
newval.tri = EXPR_AND(sym->def[S_DEF_USER].tri,
sym->visible);
goto calc_newval;
}
}
if (sym->rev_dep.tri != no)
sym->flags |= SYMBOL_WRITE;
if (!sym_is_choice(sym)) {
prop = sym_get_default_prop(sym);
if (prop) {
sym->flags |= SYMBOL_WRITE;
newval.tri = EXPR_AND(expr_calc_value(prop->expr),
prop->visible.tri);
}
if (sym->implied.tri != no) {
sym->flags |= SYMBOL_WRITE;
newval.tri = EXPR_OR(newval.tri, sym->implied.tri);
}
}
calc_newval:
if (sym->dir_dep.tri == no && sym->rev_dep.tri != no) {
struct expr *e;
e = expr_simplify_unmet_dep(sym->rev_dep.expr,
sym->dir_dep.expr);
fprintf(stderr, "warning: (");
expr_fprint(e, stderr);
fprintf(stderr, ") selects %s which has unmet direct dependencies (",
sym->name);
expr_fprint(sym->dir_dep.expr, stderr);
fprintf(stderr, ")\n");
expr_free(e);
}
newval.tri = EXPR_OR(newval.tri, sym->rev_dep.tri);
}
if (newval.tri == mod &&
(sym_get_type(sym) == S_BOOLEAN || sym->implied.tri == yes))
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->def[S_DEF_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) {
sym_set_all_changed();
modules_val = modules_sym->curr.tri;
}
}
if (sym_is_choice(sym)) {
struct symbol *choice_sym;
prop = sym_get_choice_prop(sym);
expr_list_for_each_sym(prop->expr, e, choice_sym) {
if ((sym->flags & SYMBOL_WRITE) &&
choice_sym->visible != no)
choice_sym->flags |= SYMBOL_WRITE;
if (sym->flags & SYMBOL_CHANGED)
sym_set_changed(choice_sym);
}
}
if (sym->flags & SYMBOL_AUTO)
sym->flags &= ~SYMBOL_WRITE;
if (sym->flags & SYMBOL_NEED_SET_CHOICE_VALUES)
set_all_choice_values(sym);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
roman zippel | roman zippel | 575 | 71.96% | 14 | 70.00% |
michal marek | michal marek | 62 | 7.76% | 1 | 5.00% |
arve hjonnevag | arve hjonnevag | 50 | 6.26% | 1 | 5.00% |
nicolas pitre | nicolas pitre | 45 | 5.63% | 1 | 5.00% |
arnaud lacombe | arnaud lacombe | 28 | 3.50% | 1 | 5.00% |
andrew morton | andrew morton | 20 | 2.50% | 1 | 5.00% |
jan beulich | jan beulich | 19 | 2.38% | 1 | 5.00% |
| Total | 799 | 100.00% | 20 | 100.00% |
void sym_clear_all_valid(void)
{
struct symbol *sym;
int i;
for_all_symbols(i, sym)
sym->flags &= ~SYMBOL_VALID;
sym_add_change_count(1);
sym_calc_value(modules_sym);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
roman zippel | roman zippel | 29 | 76.32% | 1 | 33.33% |
andrew morton | andrew morton | 5 | 13.16% | 1 | 33.33% |
karsten wiese | karsten wiese | 4 | 10.53% | 1 | 33.33% |
| Total | 38 | 100.00% | 3 | 100.00% |
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->implied.tri == yes && val == mod)
return false;
if (sym_is_choice_value(sym) && sym->visible == yes)
return val == yes;
return val >= sym->rev_dep.tri && val <= sym->visible;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
roman zippel | roman zippel | 106 | 86.18% | 2 | 66.67% |
nicolas pitre | nicolas pitre | 17 | 13.82% | 1 | 33.33% |
| Total | 123 | 100.00% | 3 | 100.00% |
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_DEF_USER)) {
sym->flags |= SYMBOL_DEF_USER;
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->def[S_DEF_USER].val = sym;
cs->flags |= SYMBOL_DEF_USER;
prop = sym_get_choice_prop(cs);
for (e = prop->expr; e; e = e->left.expr) {
if (e->right.sym->visible != no)
e->right.sym->flags |= SYMBOL_DEF_USER;
}
}
sym->def[S_DEF_USER].tri = val;
if (oldval != val)
sym_clear_all_valid();
return true;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
roman zippel | roman zippel | 188 | 100.00% | 7 | 100.00% |
| Total | 188 | 100.00% | 7 | 100.00% |
tristate sym_toggle_tristate_value(struct symbol *sym)
{
tristate oldval, newval;
oldval = newval = sym_get_tristate_value(sym);
do {
switch (newval) {
case no:
newval = mod;
break;
case mod:
newval = yes;
break;
case yes:
newval = no;
break;
}
if (sym_set_tristate_value(sym, newval))
break;
} while (oldval != newval);
return newval;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
roman zippel | roman zippel | 77 | 100.00% | 1 | 100.00% |
| Total | 77 | 100.00% | 1 | 100.00% |
bool sym_string_valid(struct symbol *sym, const char *str)
{
signed char ch;
switch (sym->type) {
case S_STRING:
return true;
case S_INT:
ch = *str++;
if (ch == '-')
ch = *str++;
if (!isdigit(ch))
return false;
if (ch == '0' && *str != 0)
return false;
while ((ch = *str++)) {
if (!isdigit(ch))
return false;
}
return true;
case S_HEX:
if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
str += 2;
ch = *str++;
do {
if (!isxdigit(ch))
return false;
} while ((ch = *str++));
return true;
case S_BOOLEAN:
case S_TRISTATE:
switch (str[0]) {
case 'y': case 'Y':
case 'm': case 'M':
case 'n': case 'N':
return true;
}
return false;
default:
return false;
}
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
roman zippel | roman zippel | 213 | 99.53% | 2 | 66.67% |
tom rini | tom rini | 1 | 0.47% | 1 | 33.33% |
| Total | 214 | 100.00% | 3 | 100.00% |
bool sym_string_within_range(struct symbol *sym, const char *str)
{
struct property *prop;
long long val;
switch (sym->type) {
case S_STRING:
return sym_string_valid(sym, str);
case S_INT:
if (!sym_string_valid(sym, str))
return false;
prop = sym_get_range_prop(sym);
if (!