X-Git-Url: https://jxself.org/git/?p=carl9170fw.git;a=blobdiff_plain;f=config%2Fsymbol.c;h=25cf0c2c0c795ac36658a2bfa061c9f3383630a1;hp=071f00c3046e69e77112a4e5cf56d4f686fc101f;hb=58c57a78909bcbbd4d44db4240fb544e80d6eb54;hpb=d1dbdf395b7ee5330b22008ba7c2cc704e157229 diff --git a/config/symbol.c b/config/symbol.c index 071f00c..25cf0c2 100644 --- a/config/symbol.c +++ b/config/symbol.c @@ -112,7 +112,7 @@ struct property *sym_get_env_prop(struct symbol *sym) return NULL; } -struct property *sym_get_default_prop(struct symbol *sym) +static struct property *sym_get_default_prop(struct symbol *sym) { struct property *prop; @@ -136,7 +136,7 @@ static struct property *sym_get_range_prop(struct symbol *sym) return NULL; } -static int sym_get_range_val(struct symbol *sym, int base) +static long long sym_get_range_val(struct symbol *sym, int base) { sym_calc_value(sym); switch (sym->type) { @@ -149,13 +149,14 @@ static int sym_get_range_val(struct symbol *sym, int base) default: break; } - return strtol(sym->curr.val, NULL, base); + return strtoll(sym->curr.val, NULL, base); } static void sym_validate_range(struct symbol *sym) { struct property *prop; - int base, val, val2; + int base; + long long val, val2; char str[64]; switch (sym->type) { @@ -171,7 +172,7 @@ static void sym_validate_range(struct symbol *sym) prop = sym_get_range_prop(sym); if (!prop) return; - val = strtol(sym->curr.val, NULL, base); + 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); @@ -179,12 +180,32 @@ static void sym_validate_range(struct symbol *sym) return; } if (sym->type == S_INT) - sprintf(str, "%d", val2); + sprintf(str, "%lld", val2); else - sprintf(str, "0x%x", val2); + sprintf(str, "0x%llx", val2); sym->curr.val = strdup(str); } +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; + } +} + +static void sym_set_all_changed(void) +{ + struct symbol *sym; + int i; + + for_all_symbols(i, sym) + sym_set_changed(sym); +} + static void sym_calc_visibility(struct symbol *sym) { struct property *prop; @@ -262,11 +283,18 @@ 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) + 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; @@ -293,6 +321,14 @@ void sym_calc_value(struct symbol *sym) 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; @@ -418,6 +454,9 @@ void sym_calc_value(struct symbol *sym) if (sym->flags & SYMBOL_AUTO) sym->flags &= ~SYMBOL_WRITE; + + if (sym->flags & SYMBOL_NEED_SET_CHOICE_VALUES) + set_all_choice_values(sym); } void sym_clear_all_valid(void) @@ -428,28 +467,7 @@ void sym_clear_all_valid(void) for_all_symbols(i, sym) sym->flags &= ~SYMBOL_VALID; sym_add_change_count(1); - 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); + sym_calc_value(modules_sym); } bool sym_tristate_within_range(struct symbol *sym, tristate val) @@ -576,7 +594,7 @@ bool sym_string_valid(struct symbol *sym, const char *str) bool sym_string_within_range(struct symbol *sym, const char *str) { struct property *prop; - int val; + long long val; switch (sym->type) { case S_STRING: @@ -587,7 +605,7 @@ bool sym_string_within_range(struct symbol *sym, const char *str) prop = sym_get_range_prop(sym); if (!prop) return true; - val = strtol(str, NULL, 10); + val = strtoll(str, NULL, 10); return val >= sym_get_range_val(prop->expr->left.sym, 10) && val <= sym_get_range_val(prop->expr->right.sym, 10); case S_HEX: @@ -596,7 +614,7 @@ bool sym_string_within_range(struct symbol *sym, const char *str) prop = sym_get_range_prop(sym); if (!prop) return true; - val = strtol(str, NULL, 16); + val = strtoll(str, NULL, 16); return val >= sym_get_range_val(prop->expr->left.sym, 16) && val <= sym_get_range_val(prop->expr->right.sym, 16); case S_BOOLEAN: @@ -649,11 +667,11 @@ bool sym_set_string_value(struct symbol *sym, const char *newval) size = strlen(newval) + 1; if (sym->type == S_HEX && (newval[0] != '0' || (newval[1] != 'x' && newval[1] != 'X'))) { size += 2; - sym->def[S_DEF_USER].val = val = malloc(size); + sym->def[S_DEF_USER].val = val = xmalloc(size); *val++ = '0'; *val++ = 'x'; } else if (!oldval || strcmp(oldval, newval)) - sym->def[S_DEF_USER].val = val = malloc(size); + sym->def[S_DEF_USER].val = val = xmalloc(size); else return true; @@ -805,7 +823,7 @@ struct symbol *sym_lookup(const char *name, int flags) hash = 0; } - symbol = malloc(sizeof(*symbol)); + symbol = xmalloc(sizeof(*symbol)); memset(symbol, 0, sizeof(*symbol)); symbol->name = new_name; symbol->type = S_UNKNOWN; @@ -856,7 +874,7 @@ const char *sym_expand_string_value(const char *in) size_t reslen; reslen = strlen(in) + 1; - res = malloc(reslen); + res = xmalloc(reslen); res[0] = '\0'; while ((src = strchr(in, '$'))) { @@ -914,7 +932,7 @@ const char *sym_escape_string_value(const char *in) p++; } - res = malloc(reslen); + res = xmalloc(reslen); res[0] = '\0'; strcat(res, "\""); @@ -936,38 +954,89 @@ const char *sym_escape_string_value(const char *in) return res; } +struct sym_match { + struct symbol *sym; + off_t so, eo; +}; + +/* Compare matched symbols as thus: + * - first, symbols that match exactly + * - then, alphabetical sort + */ +static int sym_rel_comp(const void *sym1, const void *sym2) +{ + const struct sym_match *s1 = sym1; + const struct sym_match *s2 = sym2; + int exact1, exact2; + + /* Exact match: + * - if matched length on symbol s1 is the length of that symbol, + * then this symbol should come first; + * - if matched length on symbol s2 is the length of that symbol, + * then this symbol should come first. + * Note: since the search can be a regexp, both symbols may match + * exactly; if this is the case, we can't decide which comes first, + * and we fallback to sorting alphabetically. + */ + exact1 = (s1->eo - s1->so) == strlen(s1->sym->name); + exact2 = (s2->eo - s2->so) == strlen(s2->sym->name); + if (exact1 && !exact2) + return -1; + if (!exact1 && exact2) + return 1; + + /* As a fallback, sort symbols alphabetically */ + return strcmp(s1->sym->name, s2->sym->name); +} + struct symbol **sym_re_search(const char *pattern) { struct symbol *sym, **sym_arr = NULL; + struct sym_match *sym_match_arr = NULL; int i, cnt, size; regex_t re; + regmatch_t match[1]; cnt = size = 0; /* Skip if empty */ if (strlen(pattern) == 0) return NULL; - if (regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB|REG_ICASE)) + if (regcomp(&re, pattern, REG_EXTENDED|REG_ICASE)) return NULL; for_all_symbols(i, sym) { if (sym->flags & SYMBOL_CONST || !sym->name) continue; - if (regexec(&re, sym->name, 0, NULL, 0)) + if (regexec(&re, sym->name, 1, match, 0)) continue; - if (cnt + 1 >= size) { - void *tmp = sym_arr; + if (cnt >= size) { + void *tmp; size += 16; - sym_arr = realloc(sym_arr, size * sizeof(struct symbol *)); - if (!sym_arr) { - free(tmp); - return NULL; - } + tmp = realloc(sym_match_arr, size * sizeof(struct sym_match)); + if (!tmp) + goto sym_re_search_free; + sym_match_arr = tmp; } sym_calc_value(sym); - sym_arr[cnt++] = sym; + /* As regexec returned 0, we know we have a match, so + * we can use match[0].rm_[se]o without further checks + */ + sym_match_arr[cnt].so = match[0].rm_so; + sym_match_arr[cnt].eo = match[0].rm_eo; + sym_match_arr[cnt++].sym = sym; } - if (sym_arr) + if (sym_match_arr) { + qsort(sym_match_arr, cnt, sizeof(struct sym_match), sym_rel_comp); + sym_arr = malloc((cnt+1) * sizeof(struct symbol)); + if (!sym_arr) + goto sym_re_search_free; + for (i = 0; i < cnt; i++) + sym_arr[i] = sym_match_arr[i].sym; sym_arr[cnt] = NULL; + } +sym_re_search_free: + /* sym_match_arr can be NULL if no match, but free(NULL) is OK */ + free(sym_match_arr); regfree(&re); return sym_arr; @@ -977,7 +1046,7 @@ struct symbol **sym_re_search(const char *pattern) * When we check for recursive dependencies we use a stack to save * current state so we can print out relevant info to user. * The entries are located on the call stack so no need to free memory. - * Note inser() remove() must always match to properly clear the stack. + * Note insert() remove() must always match to properly clear the stack. */ static struct dep_stack { struct dep_stack *prev, *next; @@ -1047,6 +1116,8 @@ static void sym_check_print_recursive(struct symbol *last_sym) if (stack->sym == last_sym) fprintf(stderr, "%s:%d:error: recursive dependency detected!\n", prop->file->name, prop->lineno); + fprintf(stderr, "For a resolution refer to Documentation/kbuild/kconfig-language.txt\n"); + fprintf(stderr, "subsection \"Kconfig recursive dependency limitations\"\n"); if (stack->expr) { fprintf(stderr, "%s:%d:\tsymbol %s %s value contains %s\n", prop->file->name, prop->lineno, @@ -1096,6 +1167,10 @@ static struct symbol *sym_check_expr_deps(struct expr *e) case E_NOT: return sym_check_expr_deps(e->left.expr); case E_EQUAL: + case E_GEQ: + case E_GTH: + case E_LEQ: + case E_LTH: case E_UNEQUAL: sym = sym_check_deps(e->left.sym); if (sym) @@ -1221,7 +1296,7 @@ struct property *prop_alloc(enum prop_type type, struct symbol *sym) struct property *prop; struct property **propp; - prop = malloc(sizeof(*prop)); + prop = xmalloc(sizeof(*prop)); memset(prop, 0, sizeof(*prop)); prop->type = type; prop->sym = sym;