diff options
author | Bryan Hundven <bryanhundven@gmail.com> | 2015-09-01 16:11:30 -0700 |
---|---|---|
committer | Bryan Hundven <bryanhundven@gmail.com> | 2015-09-03 19:00:28 -0700 |
commit | 0cffa79d9fb3d5476d7a1dbeda617aea7a6851b2 (patch) | |
tree | 7339c7fff49ed2cd2e06c042bc1bc35a20f5a381 /kconfig/confdata.c | |
parent | 74b09f9c4a07a8f561001f4a727259b2d5eced77 (diff) | |
download | crosstool-ng-0cffa79d9fb3d5476d7a1dbeda617aea7a6851b2.tar.gz crosstool-ng-0cffa79d9fb3d5476d7a1dbeda617aea7a6851b2.tar.bz2 crosstool-ng-0cffa79d9fb3d5476d7a1dbeda617aea7a6851b2.zip |
kconfig: Update kconfig. Sync with Linux-4.2
This change updates the kconfig utility to what is shipped with 4.2.0.
Signed-off-by: Bryan Hundven <bryanhundven@gmail.com>
Diffstat (limited to 'kconfig/confdata.c')
-rw-r--r-- | kconfig/confdata.c | 497 |
1 files changed, 348 insertions, 149 deletions
diff --git a/kconfig/confdata.c b/kconfig/confdata.c index 9cb97b62..c814f576 100644 --- a/kconfig/confdata.c +++ b/kconfig/confdata.c @@ -7,15 +7,20 @@ #include <ctype.h> #include <errno.h> #include <fcntl.h> +#include <stdarg.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include <unistd.h> -#define LKC_DIRECT_LINK #include "lkc.h" +struct conf_printer { + void (*print_symbol)(FILE *, struct symbol *, const char *, void *); + void (*print_comment)(FILE *, const char *, void *); +}; + static void conf_warning(const char *fmt, ...) __attribute__ ((format (printf, 1, 2))); @@ -59,6 +64,7 @@ static void conf_message(const char *fmt, ...) va_start(ap, fmt); if (conf_message_callback) conf_message_callback(fmt, ap); + va_end(ap); } const char *conf_get_configname(void) @@ -128,6 +134,7 @@ static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p) sym->flags |= def_flags; break; } + /* fall through */ case S_BOOLEAN: if (p[0] == 'y') { sym->def[def].tri = yes; @@ -139,8 +146,10 @@ static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p) sym->flags |= def_flags; break; } - conf_warning("symbol value '%s' invalid for %s", p, sym->name); - break; + if (def != S_DEF_AUTO) + conf_warning("symbol value '%s' invalid for %s", + p, sym->name); + return 1; case S_OTHER: if (*p != '"') { for (p2 = p; *p2 && !isspace(*p2); p2++) @@ -148,6 +157,7 @@ static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p) sym->type = S_STRING; goto done; } + /* fall through */ case S_STRING: if (*p++ != '"') break; @@ -159,9 +169,11 @@ static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p) memmove(p2, p2 + 1, strlen(p2)); } if (!p2) { - conf_warning("invalid string found"); + if (def != S_DEF_AUTO) + conf_warning("invalid string found"); return 1; } + /* fall through */ case S_INT: case S_HEX: done: @@ -169,7 +181,9 @@ static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p) sym->def[def].val = strdup(p); sym->flags |= def_flags; } else { - conf_warning("symbol value '%s' invalid for %s", p, sym->name); + if (def != S_DEF_AUTO) + conf_warning("symbol value '%s' invalid for %s", + p, sym->name); return 1; } break; @@ -179,10 +193,66 @@ static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p) return 0; } +#define LINE_GROWTH 16 +static int add_byte(int c, char **lineptr, size_t slen, size_t *n) +{ + char *nline; + size_t new_size = slen + 1; + if (new_size > *n) { + new_size += LINE_GROWTH - 1; + new_size *= 2; + nline = realloc(*lineptr, new_size); + if (!nline) + return -1; + + *lineptr = nline; + *n = new_size; + } + + (*lineptr)[slen] = c; + + return 0; +} + +static ssize_t compat_getline(char **lineptr, size_t *n, FILE *stream) +{ + char *line = *lineptr; + size_t slen = 0; + + for (;;) { + int c = getc(stream); + + switch (c) { + case '\n': + if (add_byte(c, &line, slen, n) < 0) + goto e_out; + slen++; + /* fall through */ + case EOF: + if (add_byte('\0', &line, slen, n) < 0) + goto e_out; + *lineptr = line; + if (slen == 0) + return -1; + return slen; + default: + if (add_byte(c, &line, slen, n) < 0) + goto e_out; + slen++; + } + } + +e_out: + line[slen-1] = '\0'; + *lineptr = line; + return -1; +} + int conf_read_simple(const char *name, int def) { FILE *in = NULL; - char line[1024]; + char *line = NULL; + size_t line_asize = 0; char *p, *p2; struct symbol *sym; int i, def_flags; @@ -237,13 +307,14 @@ load: case S_STRING: if (sym->def[def].val) free(sym->def[def].val); + /* fall through */ default: sym->def[def].val = NULL; sym->def[def].tri = no; } } - while (fgets(line, sizeof(line), in)) { + while (compat_getline(&line, &line_asize, in) != -1) { conf_lineno++; sym = NULL; if (line[0] == '#') { @@ -331,6 +402,7 @@ setsym: cs->def[def].tri = EXPR_OR(cs->def[def].tri, sym->def[def].tri); } } + free(line); fclose(in); if (modules_sym) @@ -340,10 +412,8 @@ setsym: int conf_read(const char *name) { - struct symbol *sym, *choice_sym; - struct property *prop; - struct expr *e; - int i, flags; + struct symbol *sym; + int i; sym_set_change_count(0); @@ -353,7 +423,7 @@ int conf_read(const char *name) for_all_symbols(i, sym) { sym_calc_value(sym); if (sym_is_choice(sym) || (sym->flags & SYMBOL_AUTO)) - goto sym_ok; + continue; if (sym_has_value(sym) && (sym->flags & SYMBOL_WRITE)) { /* check that calculated value agrees with saved value */ switch (sym->type) { @@ -362,29 +432,18 @@ int conf_read(const char *name) if (sym->def[S_DEF_USER].tri != sym_get_tristate_value(sym)) break; if (!sym_is_choice(sym)) - goto sym_ok; + continue; + /* fall through */ default: if (!strcmp(sym->curr.val, sym->def[S_DEF_USER].val)) - goto sym_ok; + continue; break; } } else if (!sym_has_value(sym) && !(sym->flags & SYMBOL_WRITE)) /* no previous value and not saved */ - goto sym_ok; + continue; conf_unsaved++; /* maybe print value in verbose mode... */ - sym_ok: - if (!sym_is_choice(sym)) - continue; - /* The choice symbol only has a set value (and thus is not new) - * if all its visible childs have values. - */ - prop = sym_get_choice_prop(sym); - flags = sym->flags; - expr_list_for_each_sym(prop->expr, e, choice_sym) - if (choice_sym->visible != no) - flags &= choice_sym->flags; - sym->flags &= flags | ~SYMBOL_DEF_USER; } for_all_symbols(i, sym) { @@ -417,64 +476,191 @@ int conf_read(const char *name) return 0; } -/* Write a S_STRING */ -static void conf_write_string(bool headerfile, const char *name, - const char *str, FILE *out) +/* + * Kconfig configuration printer + * + * This printer is used when generating the resulting configuration after + * kconfig invocation and `defconfig' files. Unset symbol might be omitted by + * passing a non-NULL argument to the printer. + * + */ +static void +kconfig_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg) +{ + + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: + if (*value == 'n') { + bool skip_unset = (arg != NULL); + + if (!skip_unset) + fprintf(fp, "# %s%s is not set\n", + CONFIG_, sym->name); + return; + } + break; + default: + break; + } + + fprintf(fp, "%s%s=%s\n", CONFIG_, sym->name, value); +} + +static void +kconfig_print_comment(FILE *fp, const char *value, void *arg) { - int l; - if (headerfile) - fprintf(out, "#define %s%s \"", CONFIG_, name); - else - fprintf(out, "%s%s=\"", CONFIG_, name); - - while (1) { - l = strcspn(str, "\"\\"); + const char *p = value; + size_t l; + + for (;;) { + l = strcspn(p, "\n"); + fprintf(fp, "#"); if (l) { - xfwrite(str, l, 1, out); - str += l; + fprintf(fp, " "); + xfwrite(p, l, 1, fp); + p += l; } - if (!*str) + fprintf(fp, "\n"); + if (*p++ == '\0') break; - fprintf(out, "\\%c", *str++); } - fputs("\"\n", out); } -static void conf_write_symbol(struct symbol *sym, FILE *out, bool write_no) +static struct conf_printer kconfig_printer_cb = +{ + .print_symbol = kconfig_print_symbol, + .print_comment = kconfig_print_comment, +}; + +/* + * Header printer + * + * This printer is used when generating the `include/generated/autoconf.h' file. + */ +static void +header_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg) { - const char *str; switch (sym->type) { case S_BOOLEAN: - case S_TRISTATE: - switch (sym_get_tristate_value(sym)) { - case no: - if (write_no) - fprintf(out, "# %s%s is not set\n", - CONFIG_, sym->name); - break; - case mod: - fprintf(out, "%s%s=m\n", CONFIG_, sym->name); - break; - case yes: - fprintf(out, "%s%s=y\n", CONFIG_, sym->name); + case S_TRISTATE: { + const char *suffix = ""; + + switch (*value) { + case 'n': break; + case 'm': + suffix = "_MODULE"; + /* fall through */ + default: + fprintf(fp, "#define %s%s%s 1\n", + CONFIG_, sym->name, suffix); } break; - case S_STRING: - conf_write_string(false, sym->name, sym_get_string_value(sym), out); + } + case S_HEX: { + const char *prefix = ""; + + if (value[0] != '0' || (value[1] != 'x' && value[1] != 'X')) + prefix = "0x"; + fprintf(fp, "#define %s%s %s%s\n", + CONFIG_, sym->name, prefix, value); break; - case S_HEX: + } + case S_STRING: case S_INT: - str = sym_get_string_value(sym); - fprintf(out, "%s%s=%s\n", CONFIG_, sym->name, str); + fprintf(fp, "#define %s%s %s\n", + CONFIG_, sym->name, value); break; + default: + break; + } + +} + +static void +header_print_comment(FILE *fp, const char *value, void *arg) +{ + const char *p = value; + size_t l; + + fprintf(fp, "/*\n"); + for (;;) { + l = strcspn(p, "\n"); + fprintf(fp, " *"); + if (l) { + fprintf(fp, " "); + xfwrite(p, l, 1, fp); + p += l; + } + fprintf(fp, "\n"); + if (*p++ == '\0') + break; + } + fprintf(fp, " */\n"); +} + +static struct conf_printer header_printer_cb = +{ + .print_symbol = header_print_symbol, + .print_comment = header_print_comment, +}; + +/* + * Tristate printer + * + * This printer is used when generating the `include/config/tristate.conf' file. + */ +static void +tristate_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg) +{ + + if (sym->type == S_TRISTATE && *value != 'n') + fprintf(fp, "%s%s=%c\n", CONFIG_, sym->name, (char)toupper(*value)); +} + +static struct conf_printer tristate_printer_cb = +{ + .print_symbol = tristate_print_symbol, + .print_comment = kconfig_print_comment, +}; + +static void conf_write_symbol(FILE *fp, struct symbol *sym, + struct conf_printer *printer, void *printer_arg) +{ + const char *str; + + switch (sym->type) { case S_OTHER: case S_UNKNOWN: break; + case S_STRING: + str = sym_get_string_value(sym); + str = sym_escape_string_value(str); + printer->print_symbol(fp, sym, str, printer_arg); + free((void *)str); + break; + default: + str = sym_get_string_value(sym); + printer->print_symbol(fp, sym, str, printer_arg); } } +static void +conf_write_heading(FILE *fp, struct conf_printer *printer, void *printer_arg) +{ + char buf[256]; + + snprintf(buf, sizeof(buf), + "\n" + "Automatically generated file; DO NOT EDIT.\n" + "%s\n", + rootmenu.prompt->text); + + printer->print_comment(fp, buf, printer_arg); +} + /* * Write out a minimal config. * All values that has default values are skipped as this is redundant. @@ -531,7 +717,7 @@ int conf_write_defconfig(const char *filename) goto next_menu; } } - conf_write_symbol(sym, out, true); + conf_write_symbol(out, sym, &kconfig_printer_cb, NULL); } next_menu: if (menu->list != NULL) { @@ -560,8 +746,6 @@ int conf_write(const char *name) const char *basename; const char *str; char dirname[PATH_MAX+1], tmpname[PATH_MAX+1], newname[PATH_MAX+1]; - time_t now; - int use_timestamp = 1; char *env; dirname[0] = 0; @@ -598,19 +782,7 @@ int conf_write(const char *name) if (!out) return 1; - time(&now); - env = getenv("KCONFIG_NOTIMESTAMP"); - if (env && *env) - use_timestamp = 0; - - fprintf(out, _("#\n" - "# Automatically generated make config: don't edit\n" - "# %s\n" - "%s%s" - "#\n"), - rootmenu.prompt->text, - use_timestamp ? "# " : "", - use_timestamp ? ctime(&now) : ""); + conf_write_heading(out, &kconfig_printer_cb, NULL); if (!conf_get_changed()) sym_clear_all_valid(); @@ -631,8 +803,8 @@ int conf_write(const char *name) if (!(sym->flags & SYMBOL_WRITE)) goto next; sym->flags &= ~SYMBOL_WRITE; - /* Write config symbol to file */ - conf_write_symbol(sym, out, true); + + conf_write_symbol(out, sym, &kconfig_printer_cb, NULL); } next: @@ -659,7 +831,7 @@ next: return 1; } - conf_message(_("configuration saved")); + conf_message(_("configuration written to %s"), newname); sym_set_change_count(0); @@ -781,7 +953,6 @@ out: int conf_write_autoconf(void) { struct symbol *sym; - const char *str; const char *name; FILE *out, *tristate, *out_h; int i; @@ -810,68 +981,23 @@ int conf_write_autoconf(void) return 1; } - fprintf(out, "#\n" - "# Automatically generated make config: don't edit\n" - "# %s\n" - "#\n", - rootmenu.prompt->text); - fprintf(tristate, "#\n" - "# Automatically generated - do not edit\n" - "\n"); - fprintf(out_h, "/*\n" - " * Automatically generated C config: don't edit\n" - " * %s\n" - " */\n", - rootmenu.prompt->text); + conf_write_heading(out, &kconfig_printer_cb, NULL); + + conf_write_heading(tristate, &tristate_printer_cb, NULL); + + conf_write_heading(out_h, &header_printer_cb, NULL); for_all_symbols(i, sym) { sym_calc_value(sym); if (!(sym->flags & SYMBOL_WRITE) || !sym->name) continue; - /* write symbol to config file */ - conf_write_symbol(sym, out, false); + /* write symbol to auto.conf, tristate and header files */ + conf_write_symbol(out, sym, &kconfig_printer_cb, (void *)1); - /* update autoconf and tristate files */ - switch (sym->type) { - case S_BOOLEAN: - case S_TRISTATE: - switch (sym_get_tristate_value(sym)) { - case no: - break; - case mod: - fprintf(tristate, "%s%s=M\n", - CONFIG_, sym->name); - fprintf(out_h, "#define %s%s_MODULE 1\n", - CONFIG_, sym->name); - break; - case yes: - if (sym->type == S_TRISTATE) - fprintf(tristate,"%s%s=Y\n", - CONFIG_, sym->name); - fprintf(out_h, "#define %s%s 1\n", - CONFIG_, sym->name); - break; - } - break; - case S_STRING: - conf_write_string(true, sym->name, sym_get_string_value(sym), out_h); - break; - case S_HEX: - str = sym_get_string_value(sym); - if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) { - fprintf(out_h, "#define %s%s 0x%s\n", - CONFIG_, sym->name, str); - break; - } - case S_INT: - str = sym_get_string_value(sym); - fprintf(out_h, "#define %s%s %s\n", - CONFIG_, sym->name, str); - break; - default: - break; - } + conf_write_symbol(tristate, sym, &tristate_printer_cb, (void *)1); + + conf_write_symbol(out_h, sym, &header_printer_cb, NULL); } fclose(out); fclose(tristate); @@ -925,7 +1051,7 @@ void conf_set_changed_callback(void (*fn)(void)) conf_changed_callback = fn; } -static void randomize_choice_values(struct symbol *csym) +static bool randomize_choice_values(struct symbol *csym) { struct property *prop; struct symbol *sym; @@ -938,7 +1064,7 @@ static void randomize_choice_values(struct symbol *csym) * In both cases stop. */ if (csym->curr.tri != yes) - return; + return false; prop = sym_get_choice_prop(csym); @@ -962,13 +1088,18 @@ static void randomize_choice_values(struct symbol *csym) else { sym->def[S_DEF_USER].tri = no; } + sym->flags |= SYMBOL_DEF_USER; + /* clear VALID to get value calculated */ + sym->flags &= ~SYMBOL_VALID; } csym->flags |= SYMBOL_DEF_USER; /* clear VALID to get value calculated */ csym->flags &= ~(SYMBOL_VALID); + + return true; } -static void set_all_choice_values(struct symbol *csym) +void set_all_choice_values(struct symbol *csym) { struct property *prop; struct symbol *sym; @@ -985,20 +1116,66 @@ static void set_all_choice_values(struct symbol *csym) } csym->flags |= SYMBOL_DEF_USER; /* clear VALID to get value calculated */ - csym->flags &= ~(SYMBOL_VALID); + csym->flags &= ~(SYMBOL_VALID | SYMBOL_NEED_SET_CHOICE_VALUES); } -void conf_set_all_new_symbols(enum conf_def_mode mode) +bool conf_set_all_new_symbols(enum conf_def_mode mode) { struct symbol *sym, *csym; - int i, cnt; + int i, cnt, pby, pty, ptm; /* pby: probability of boolean = y + * pty: probability of tristate = y + * ptm: probability of tristate = m + */ + + pby = 50; pty = ptm = 33; /* can't go as the default in switch-case + * below, otherwise gcc whines about + * -Wmaybe-uninitialized */ + if (mode == def_random) { + int n, p[3]; + char *env = getenv("KCONFIG_PROBABILITY"); + n = 0; + while( env && *env ) { + char *endp; + int tmp = strtol( env, &endp, 10 ); + if( tmp >= 0 && tmp <= 100 ) { + p[n++] = tmp; + } else { + errno = ERANGE; + perror( "KCONFIG_PROBABILITY" ); + exit( 1 ); + } + env = (*endp == ':') ? endp+1 : endp; + if( n >=3 ) { + break; + } + } + switch( n ) { + case 1: + pby = p[0]; ptm = pby/2; pty = pby-ptm; + break; + case 2: + pty = p[0]; ptm = p[1]; pby = pty + ptm; + break; + case 3: + pby = p[0]; pty = p[1]; ptm = p[2]; + break; + } + + if( pty+ptm > 100 ) { + errno = ERANGE; + perror( "KCONFIG_PROBABILITY" ); + exit( 1 ); + } + } + bool has_changed = false; for_all_symbols(i, sym) { - if (sym_has_value(sym)) + if (sym_has_value(sym) || (sym->flags & SYMBOL_VALID)) continue; switch (sym_get_type(sym)) { case S_BOOLEAN: case S_TRISTATE: + has_changed = true; switch (mode) { case def_yes: sym->def[S_DEF_USER].tri = yes; @@ -1007,11 +1184,21 @@ void conf_set_all_new_symbols(enum conf_def_mode mode) sym->def[S_DEF_USER].tri = mod; break; case def_no: - sym->def[S_DEF_USER].tri = no; + if (sym->flags & SYMBOL_ALLNOCONFIG_Y) + sym->def[S_DEF_USER].tri = yes; + else + sym->def[S_DEF_USER].tri = no; break; case def_random: - cnt = sym_get_type(sym) == S_TRISTATE ? 3 : 2; - sym->def[S_DEF_USER].tri = (tristate)(rand() % cnt); + sym->def[S_DEF_USER].tri = no; + cnt = rand() % 100; + if (sym->type == S_TRISTATE) { + if (cnt < pty) + sym->def[S_DEF_USER].tri = yes; + else if (cnt < (pty+ptm)) + sym->def[S_DEF_USER].tri = mod; + } else if (cnt < pby) + sym->def[S_DEF_USER].tri = yes; break; default: continue; @@ -1036,14 +1223,26 @@ void conf_set_all_new_symbols(enum conf_def_mode mode) * selected in a choice block and we set it to yes, * and the rest to no. */ + if (mode != def_random) { + for_all_symbols(i, csym) { + if ((sym_is_choice(csym) && !sym_has_value(csym)) || + sym_is_choice_value(csym)) + csym->flags |= SYMBOL_NEED_SET_CHOICE_VALUES; + } + } + for_all_symbols(i, csym) { if (sym_has_value(csym) || !sym_is_choice(csym)) continue; sym_calc_value(csym); if (mode == def_random) - randomize_choice_values(csym); - else + has_changed = randomize_choice_values(csym); + else { set_all_choice_values(csym); + has_changed = true; + } } + + return has_changed; } |