cregit-Linux how code gets into the kernel

Release 4.15 scripts/kconfig/symbol.c

Directory: scripts/kconfig
/*
 * 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

PersonTokensPropCommitsCommitProp
Roman Zippel4197.62%375.00%
Trevor Keith12.38%125.00%
Total42100.00%4100.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

PersonTokensPropCommitsCommitProp
Roman Zippel67100.00%1100.00%
Total67100.00%1100.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

PersonTokensPropCommitsCommitProp
Roman Zippel5696.55%266.67%
Andrew Morton23.45%133.33%
Total58100.00%3100.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

PersonTokensPropCommitsCommitProp
Roman Zippel60100.00%2100.00%
Total60100.00%2100.00%


struct property *sym_get_choice_prop(struct symbol *sym) { struct property *prop; for_all_choices(sym, prop) return prop; return NULL; }

Contributors

PersonTokensPropCommitsCommitProp
Roman Zippel29100.00%1100.00%
Total29100.00%1100.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

PersonTokensPropCommitsCommitProp
Roman Zippel31100.00%1100.00%
Total31100.00%1100.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

PersonTokensPropCommitsCommitProp
Roman Zippel5698.25%266.67%
Michal Marek11.75%133.33%
Total57100.00%3100.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

PersonTokensPropCommitsCommitProp
Roman Zippel5898.31%150.00%
Trevor Keith11.69%150.00%
Total59100.00%2100.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

PersonTokensPropCommitsCommitProp
Roman Zippel5795.00%133.33%
Kees Cook35.00%266.67%
Total60100.00%3100.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

PersonTokensPropCommitsCommitProp
Roman Zippel16195.83%150.00%
Kees Cook74.17%150.00%
Total168100.00%2100.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

PersonTokensPropCommitsCommitProp
Michal Marek54100.00%1100.00%
Total54100.00%1100.00%


static void sym_set_all_changed(void) { struct symbol *sym; int i; for_all_symbols(i, sym) sym_set_changed(sym); }

Contributors

PersonTokensPropCommitsCommitProp
Michal Marek27100.00%1100.00%
Total27100.00%1100.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

PersonTokensPropCommitsCommitProp
Roman Zippel13637.06%550.00%
Nico Pitre7319.89%110.00%
Dirk Gouders5916.08%110.00%
Catalin Marinas5916.08%110.00%
Andrew Morton3910.63%110.00%
Sam Ravnborg10.27%110.00%
Total367100.00%10100.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

PersonTokensPropCommitsCommitProp
Roman Zippel10594.59%266.67%
Sam Ravnborg65.41%133.33%
Total111100.00%3100.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

PersonTokensPropCommitsCommitProp
Sam Ravnborg8765.41%125.00%
Arnaud Lacombe3425.56%125.00%
Roman Zippel129.02%250.00%
Total133100.00%4100.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

PersonTokensPropCommitsCommitProp
Roman Zippel57571.96%1470.00%
Michal Marek627.76%15.00%
Arve Hjönnevåg506.26%15.00%
Nico Pitre455.63%15.00%
Arnaud Lacombe283.50%15.00%
Andrew Morton202.50%15.00%
Jan Beulich192.38%15.00%
Total799100.00%20100.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

PersonTokensPropCommitsCommitProp
Roman Zippel2976.32%133.33%
Andrew Morton513.16%133.33%
Karsten Wiese410.53%133.33%
Total38100.00%3100.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

PersonTokensPropCommitsCommitProp
Roman Zippel10686.18%266.67%
Nico Pitre1713.82%133.33%
Total123100.00%3100.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

PersonTokensPropCommitsCommitProp
Roman Zippel188100.00%7100.00%
Total188100.00%7100.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

PersonTokensPropCommitsCommitProp
Roman Zippel77100.00%1100.00%
Total77100.00%1100.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