yann@1: /* yann@1: * Copyright (C) 2002 Roman Zippel yann@1: * Released under the terms of the GNU GPL v2.0. yann@1: */ yann@1: yann@1: #include yann@1: #include yann@1: #include yann@1: #include yann@1: #include yann@1: #include yann@1: #include yann@1: #include yann@1: yann@1: #define LKC_DIRECT_LINK yann@1: #include "lkc.h" yann@1: yann@1: static void conf_warning(const char *fmt, ...) yann@1: __attribute__ ((format (printf, 1, 2))); yann@1: yann@1: static const char *conf_filename; yann@1: static int conf_lineno, conf_warnings, conf_unsaved; yann@1: yann@1: const char conf_defname[] = "arch/$ARCH/defconfig"; yann@1: yann@1: static void conf_warning(const char *fmt, ...) yann@1: { yann@1: va_list ap; yann@1: va_start(ap, fmt); yann@1: fprintf(stderr, "%s:%d:warning: ", conf_filename, conf_lineno); yann@1: vfprintf(stderr, fmt, ap); yann@1: fprintf(stderr, "\n"); yann@1: va_end(ap); yann@1: conf_warnings++; yann@1: } yann@1: yann@1: const char *conf_get_configname(void) yann@1: { yann@1: char *name = getenv("KCONFIG_CONFIG"); yann@1: yann@1: return name ? name : ".config"; yann@1: } yann@1: yann@1: static char *conf_expand_value(const char *in) yann@1: { yann@1: struct symbol *sym; yann@1: const char *src; yann@1: static char res_value[SYMBOL_MAXLENGTH]; yann@1: char *dst, name[SYMBOL_MAXLENGTH]; yann@1: yann@1: res_value[0] = 0; yann@1: dst = name; yann@1: while ((src = strchr(in, '$'))) { yann@1: strncat(res_value, in, src - in); yann@1: src++; yann@1: dst = name; yann@1: while (isalnum(*src) || *src == '_') yann@1: *dst++ = *src++; yann@1: *dst = 0; yann@1: sym = sym_lookup(name, 0); yann@1: sym_calc_value(sym); yann@1: strcat(res_value, sym_get_string_value(sym)); yann@1: in = src; yann@1: } yann@1: strcat(res_value, in); yann@1: yann@1: return res_value; yann@1: } yann@1: yann@1: char *conf_get_default_confname(void) yann@1: { yann@1: struct stat buf; yann@1: static char fullname[PATH_MAX+1]; yann@1: char *env, *name; yann@1: yann@1: name = conf_expand_value(conf_defname); yann@1: env = getenv(SRCTREE); yann@1: if (env) { yann@1: sprintf(fullname, "%s/%s", env, name); yann@1: if (!stat(fullname, &buf)) yann@1: return fullname; yann@1: } yann@1: return name; yann@1: } yann@1: yann@943: static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p) yann@943: { yann@943: char *p2; yann@943: yann@943: switch (sym->type) { yann@943: case S_TRISTATE: yann@943: if (p[0] == 'm') { yann@943: sym->def[def].tri = mod; yann@943: sym->flags |= def_flags; yann@943: break; yann@943: } yann@943: case S_BOOLEAN: yann@943: if (p[0] == 'y') { yann@943: sym->def[def].tri = yes; yann@943: sym->flags |= def_flags; yann@943: break; yann@943: } yann@943: if (p[0] == 'n') { yann@943: sym->def[def].tri = no; yann@943: sym->flags |= def_flags; yann@943: break; yann@943: } yann@943: conf_warning("symbol value '%s' invalid for %s", p, sym->name); yann@943: break; yann@943: case S_OTHER: yann@943: if (*p != '"') { yann@943: for (p2 = p; *p2 && !isspace(*p2); p2++) yann@943: ; yann@943: sym->type = S_STRING; yann@943: goto done; yann@943: } yann@943: case S_STRING: yann@943: if (*p++ != '"') yann@943: break; yann@943: for (p2 = p; (p2 = strpbrk(p2, "\"\\")); p2++) { yann@943: if (*p2 == '"') { yann@943: *p2 = 0; yann@943: break; yann@943: } yann@943: memmove(p2, p2 + 1, strlen(p2)); yann@943: } yann@943: if (!p2) { yann@943: conf_warning("invalid string found"); yann@943: return 1; yann@943: } yann@943: case S_INT: yann@943: case S_HEX: yann@943: done: yann@943: if (sym_string_valid(sym, p)) { yann@943: sym->def[def].val = strdup(p); yann@943: sym->flags |= def_flags; yann@943: } else { yann@943: conf_warning("symbol value '%s' invalid for %s", p, sym->name); yann@943: return 1; yann@943: } yann@943: break; yann@943: default: yann@943: ; yann@943: } yann@943: return 0; yann@943: } yann@943: yann@1: int conf_read_simple(const char *name, int def) yann@1: { yann@1: FILE *in = NULL; yann@1: char line[1024]; yann@1: char *p, *p2; yann@1: struct symbol *sym; yann@1: int i, def_flags; yann@1: yann@1: if (name) { yann@1: in = zconf_fopen(name); yann@1: } else { yann@1: struct property *prop; yann@1: yann@1: name = conf_get_configname(); yann@1: in = zconf_fopen(name); yann@1: if (in) yann@1: goto load; yann@39: sym_add_change_count(1); yann@1: if (!sym_defconfig_list) yann@1: return 1; yann@1: yann@1: for_all_defaults(sym_defconfig_list, prop) { yann@1: if (expr_calc_value(prop->visible.expr) == no || yann@1: prop->expr->type != E_SYMBOL) yann@1: continue; yann@1: name = conf_expand_value(prop->expr->left.sym->name); yann@1: in = zconf_fopen(name); yann@1: if (in) { yann@1: printf(_("#\n" yann@1: "# using defaults found in %s\n" yann@1: "#\n"), name); yann@1: goto load; yann@1: } yann@1: } yann@1: } yann@1: if (!in) yann@1: return 1; yann@1: yann@1: load: yann@1: conf_filename = name; yann@1: conf_lineno = 0; yann@1: conf_warnings = 0; yann@1: conf_unsaved = 0; yann@1: yann@1: def_flags = SYMBOL_DEF << def; yann@1: for_all_symbols(i, sym) { yann@1: sym->flags |= SYMBOL_CHANGED; yann@1: sym->flags &= ~(def_flags|SYMBOL_VALID); yann@1: if (sym_is_choice(sym)) yann@1: sym->flags |= def_flags; yann@1: switch (sym->type) { yann@1: case S_INT: yann@1: case S_HEX: yann@1: case S_STRING: yann@1: if (sym->def[def].val) yann@1: free(sym->def[def].val); yann@1: default: yann@1: sym->def[def].val = NULL; yann@1: sym->def[def].tri = no; yann@1: } yann@1: } yann@1: yann@1: while (fgets(line, sizeof(line), in)) { yann@1: conf_lineno++; yann@1: sym = NULL; yann@1: switch (line[0]) { yann@1: case '#': yann@1: if (memcmp(line + 2, "CT_", 3)) yann@1: continue; yann@1: p = strchr(line + 5, ' '); yann@1: if (!p) yann@1: continue; yann@1: *p++ = 0; yann@1: if (strncmp(p, "is not set", 10)) yann@1: continue; yann@1: if (def == S_DEF_USER) { yann@1: sym = sym_find(line + 5); yann@1: if (!sym) { yann@943: sym_add_change_count(1); yann@1: break; yann@1: } yann@1: } else { yann@1: sym = sym_lookup(line + 5, 0); yann@1: if (sym->type == S_UNKNOWN) yann@1: sym->type = S_BOOLEAN; yann@1: } yann@1: if (sym->flags & def_flags) { yann@943: conf_warning("override: reassigning to symbol %s", sym->name); yann@1: } yann@1: switch (sym->type) { yann@1: case S_BOOLEAN: yann@1: case S_TRISTATE: yann@1: sym->def[def].tri = no; yann@1: sym->flags |= def_flags; yann@1: break; yann@1: default: yann@1: ; yann@1: } yann@1: break; yann@1: case 'C': yann@1: if (memcmp(line, "CT_", 3)) { yann@1: conf_warning("unexpected data"); yann@1: continue; yann@1: } yann@1: p = strchr(line + 3, '='); yann@1: if (!p) yann@1: continue; yann@1: *p++ = 0; yann@1: p2 = strchr(p, '\n'); yann@1: if (p2) { yann@1: *p2-- = 0; yann@1: if (*p2 == '\r') yann@1: *p2 = 0; yann@1: } yann@1: if (def == S_DEF_USER) { yann@1: sym = sym_find(line + 3); yann@1: if (!sym) { yann@943: sym_add_change_count(1); yann@1: break; yann@1: } yann@1: } else { yann@1: sym = sym_lookup(line + 3, 0); yann@1: if (sym->type == S_UNKNOWN) yann@1: sym->type = S_OTHER; yann@1: } yann@1: if (sym->flags & def_flags) { yann@943: conf_warning("override: reassigning to symbol %s", sym->name); yann@1: } yann@943: if (conf_set_sym_val(sym, def, def_flags, p)) yann@943: continue; yann@1: break; yann@1: case '\r': yann@1: case '\n': yann@1: break; yann@1: default: yann@1: conf_warning("unexpected data"); yann@1: continue; yann@1: } yann@1: if (sym && sym_is_choice_value(sym)) { yann@1: struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym)); yann@1: switch (sym->def[def].tri) { yann@1: case no: yann@1: break; yann@1: case mod: yann@1: if (cs->def[def].tri == yes) { yann@1: conf_warning("%s creates inconsistent choice state", sym->name); yann@1: cs->flags &= ~def_flags; yann@1: } yann@1: break; yann@1: case yes: yann@943: if (cs->def[def].tri != no) yann@943: conf_warning("override: %s changes choice state", sym->name); yann@943: cs->def[def].val = sym; yann@1: break; yann@1: } yann@943: cs->def[def].tri = EXPR_OR(cs->def[def].tri, sym->def[def].tri); yann@1: } yann@1: } yann@1: fclose(in); yann@1: yann@1: if (modules_sym) yann@1: sym_calc_value(modules_sym); yann@1: return 0; yann@1: } yann@1: yann@1: int conf_read(const char *name) yann@1: { yann@943: struct symbol *sym, *choice_sym; yann@1: struct property *prop; yann@1: struct expr *e; yann@1: int i, flags; yann@1: yann@39: sym_set_change_count(0); yann@1: yann@1: if (conf_read_simple(name, S_DEF_USER)) yann@1: return 1; yann@1: yann@1: for_all_symbols(i, sym) { yann@1: sym_calc_value(sym); yann@1: if (sym_is_choice(sym) || (sym->flags & SYMBOL_AUTO)) yann@1: goto sym_ok; yann@1: if (sym_has_value(sym) && (sym->flags & SYMBOL_WRITE)) { yann@1: /* check that calculated value agrees with saved value */ yann@1: switch (sym->type) { yann@1: case S_BOOLEAN: yann@1: case S_TRISTATE: yann@1: if (sym->def[S_DEF_USER].tri != sym_get_tristate_value(sym)) yann@1: break; yann@1: if (!sym_is_choice(sym)) yann@1: goto sym_ok; yann@1: default: yann@1: if (!strcmp(sym->curr.val, sym->def[S_DEF_USER].val)) yann@1: goto sym_ok; yann@1: break; yann@1: } yann@1: } else if (!sym_has_value(sym) && !(sym->flags & SYMBOL_WRITE)) yann@1: /* no previous value and not saved */ yann@1: goto sym_ok; yann@1: conf_unsaved++; yann@1: /* maybe print value in verbose mode... */ yann@1: sym_ok: yann@943: if (!sym_is_choice(sym)) yann@943: continue; yann@943: /* The choice symbol only has a set value (and thus is not new) yann@943: * if all its visible childs have values. yann@943: */ yann@943: prop = sym_get_choice_prop(sym); yann@943: flags = sym->flags; yann@943: expr_list_for_each_sym(prop->expr, e, choice_sym) yann@943: if (choice_sym->visible != no) yann@943: flags &= choice_sym->flags; yann@943: sym->flags &= flags | ~SYMBOL_DEF_USER; yann@943: } yann@943: yann@943: for_all_symbols(i, sym) { yann@1: if (sym_has_value(sym) && !sym_is_choice_value(sym)) { yann@943: /* Reset values of generates values, so they'll appear yann@943: * as new, if they should become visible, but that yann@943: * doesn't quite work if the Kconfig and the saved yann@943: * configuration disagree. yann@943: */ yann@943: if (sym->visible == no && !conf_unsaved) yann@1: sym->flags &= ~SYMBOL_DEF_USER; yann@1: switch (sym->type) { yann@1: case S_STRING: yann@1: case S_INT: yann@1: case S_HEX: yann@943: /* Reset a string value if it's out of range */ yann@943: if (sym_string_within_range(sym, sym->def[S_DEF_USER].val)) yann@943: break; yann@943: sym->flags &= ~(SYMBOL_VALID|SYMBOL_DEF_USER); yann@943: conf_unsaved++; yann@943: break; yann@1: default: yann@1: break; yann@1: } yann@1: } yann@1: } yann@1: yann@39: sym_add_change_count(conf_warnings || conf_unsaved); yann@1: yann@1: return 0; yann@1: } yann@1: yann@1: int conf_write(const char *name) yann@1: { yann@1: FILE *out; yann@1: struct symbol *sym; yann@1: struct menu *menu; yann@1: const char *basename; yann@1: char dirname[128], tmpname[128], newname[128]; yann@39: int type, l; yann@1: const char *str; yann@1: time_t now; yann@1: int use_timestamp = 1; yann@1: char *env; yann@1: yann@1: dirname[0] = 0; yann@1: if (name && name[0]) { yann@1: struct stat st; yann@1: char *slash; yann@1: yann@1: if (!stat(name, &st) && S_ISDIR(st.st_mode)) { yann@1: strcpy(dirname, name); yann@1: strcat(dirname, "/"); yann@1: basename = conf_get_configname(); yann@1: } else if ((slash = strrchr(name, '/'))) { yann@1: int size = slash - name + 1; yann@1: memcpy(dirname, name, size); yann@1: dirname[size] = 0; yann@1: if (slash[1]) yann@1: basename = slash + 1; yann@1: else yann@1: basename = conf_get_configname(); yann@1: } else yann@1: basename = name; yann@1: } else yann@1: basename = conf_get_configname(); yann@1: yann@1: sprintf(newname, "%s%s", dirname, basename); yann@1: env = getenv("KCONFIG_OVERWRITECONFIG"); yann@1: if (!env || !*env) { yann@1: sprintf(tmpname, "%s.tmpconfig.%d", dirname, (int)getpid()); yann@1: out = fopen(tmpname, "w"); yann@1: } else { yann@1: *tmpname = 0; yann@1: out = fopen(newname, "w"); yann@1: } yann@1: if (!out) yann@1: return 1; yann@1: yann@1: sym = sym_lookup("PROJECTVERSION", 0); yann@1: sym_calc_value(sym); yann@1: time(&now); yann@1: env = getenv("KCONFIG_NOTIMESTAMP"); yann@1: if (env && *env) yann@1: use_timestamp = 0; yann@1: yann@1: fprintf(out, _("#\n" yann@1: "# Automatically generated make config: don't edit\n" yann@943: "# " PACKAGE " version: %s\n" yann@1: "%s%s" yann@1: "#\n"), yann@1: sym_get_string_value(sym), yann@1: use_timestamp ? "# " : "", yann@1: use_timestamp ? ctime(&now) : ""); yann@1: yann@39: if (!conf_get_changed()) yann@1: sym_clear_all_valid(); yann@1: yann@1: menu = rootmenu.list; yann@1: while (menu) { yann@1: sym = menu->sym; yann@1: if (!sym) { yann@1: if (!menu_is_visible(menu)) yann@1: goto next; yann@1: str = menu_get_prompt(menu); yann@1: fprintf(out, "\n" yann@1: "#\n" yann@1: "# %s\n" yann@1: "#\n", str); yann@1: } else if (!(sym->flags & SYMBOL_CHOICE)) { yann@1: sym_calc_value(sym); yann@39: if (!(sym->flags & SYMBOL_WRITE)) yann@1: goto next; yann@39: sym->flags &= ~SYMBOL_WRITE; yann@1: type = sym->type; yann@1: if (type == S_TRISTATE) { yann@1: sym_calc_value(modules_sym); yann@1: if (modules_sym->curr.tri == no) yann@1: type = S_BOOLEAN; yann@1: } yann@1: switch (type) { yann@1: case S_BOOLEAN: yann@1: case S_TRISTATE: yann@1: switch (sym_get_tristate_value(sym)) { yann@1: case no: yann@1: fprintf(out, "# CT_%s is not set\n", sym->name); yann@1: break; yann@1: case mod: yann@1: fprintf(out, "CT_%s=m\n", sym->name); yann@1: break; yann@1: case yes: yann@1: fprintf(out, "CT_%s=y\n", sym->name); yann@1: break; yann@1: } yann@1: break; yann@1: case S_STRING: yann@1: str = sym_get_string_value(sym); yann@1: fprintf(out, "CT_%s=\"", sym->name); yann@1: while (1) { yann@1: l = strcspn(str, "\"\\"); yann@1: if (l) { yann@1: fwrite(str, l, 1, out); yann@1: str += l; yann@1: } yann@1: if (!*str) yann@1: break; yann@1: fprintf(out, "\\%c", *str++); yann@1: } yann@1: fputs("\"\n", out); yann@1: break; yann@1: case S_HEX: yann@1: str = sym_get_string_value(sym); yann@1: if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) { yann@39: fprintf(out, "CT_%s=%s\n", sym->name, str); yann@1: break; yann@1: } yann@1: case S_INT: yann@1: str = sym_get_string_value(sym); yann@39: fprintf(out, "CT_%s=%s\n", sym->name, str); yann@1: break; yann@1: } yann@1: } yann@1: yann@1: next: yann@39: if (menu->list) { yann@39: menu = menu->list; yann@39: continue; yann@39: } yann@39: if (menu->next) yann@39: menu = menu->next; yann@39: else while ((menu = menu->parent)) { yann@39: if (menu->next) { yann@39: menu = menu->next; yann@39: break; yann@1: } yann@39: } yann@1: } yann@1: fclose(out); yann@1: yann@1: if (*tmpname) { yann@1: strcat(dirname, basename); yann@1: strcat(dirname, ".old"); yann@1: rename(newname, dirname); yann@1: if (rename(tmpname, newname)) yann@1: return 1; yann@1: } yann@1: yann@39: sym_set_change_count(0); yann@1: yann@1: return 0; yann@1: } yann@1: yann@1: int conf_split_config(void) yann@1: { yann@1: char *name, path[128]; yann@1: char *s, *d, c; yann@1: struct symbol *sym; yann@1: struct stat sb; yann@1: int res, i, fd; yann@1: yann@1: name = getenv("KCONFIG_AUTOCONFIG"); yann@1: if (!name) yann@1: name = "include/config/auto.conf"; yann@1: conf_read_simple(name, S_DEF_AUTO); yann@1: yann@1: if (chdir("include/config")) yann@1: return 1; yann@1: yann@1: res = 0; yann@1: for_all_symbols(i, sym) { yann@1: sym_calc_value(sym); yann@1: if ((sym->flags & SYMBOL_AUTO) || !sym->name) yann@1: continue; yann@1: if (sym->flags & SYMBOL_WRITE) { yann@1: if (sym->flags & SYMBOL_DEF_AUTO) { yann@1: /* yann@1: * symbol has old and new value, yann@1: * so compare them... yann@1: */ yann@1: switch (sym->type) { yann@1: case S_BOOLEAN: yann@1: case S_TRISTATE: yann@1: if (sym_get_tristate_value(sym) == yann@1: sym->def[S_DEF_AUTO].tri) yann@1: continue; yann@1: break; yann@1: case S_STRING: yann@1: case S_HEX: yann@1: case S_INT: yann@1: if (!strcmp(sym_get_string_value(sym), yann@1: sym->def[S_DEF_AUTO].val)) yann@1: continue; yann@1: break; yann@1: default: yann@1: break; yann@1: } yann@1: } else { yann@1: /* yann@1: * If there is no old value, only 'no' (unset) yann@1: * is allowed as new value. yann@1: */ yann@1: switch (sym->type) { yann@1: case S_BOOLEAN: yann@1: case S_TRISTATE: yann@1: if (sym_get_tristate_value(sym) == no) yann@1: continue; yann@1: break; yann@1: default: yann@1: break; yann@1: } yann@1: } yann@1: } else if (!(sym->flags & SYMBOL_DEF_AUTO)) yann@1: /* There is neither an old nor a new value. */ yann@1: continue; yann@1: /* else yann@1: * There is an old value, but no new value ('no' (unset) yann@1: * isn't saved in auto.conf, so the old value is always yann@1: * different from 'no'). yann@1: */ yann@1: yann@1: /* Replace all '_' and append ".h" */ yann@1: s = sym->name; yann@1: d = path; yann@1: while ((c = *s++)) { yann@1: c = tolower(c); yann@1: *d++ = (c == '_') ? '/' : c; yann@1: } yann@1: strcpy(d, ".h"); yann@1: yann@1: /* Assume directory path already exists. */ yann@1: fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644); yann@1: if (fd == -1) { yann@1: if (errno != ENOENT) { yann@1: res = 1; yann@1: break; yann@1: } yann@1: /* yann@1: * Create directory components, yann@1: * unless they exist already. yann@1: */ yann@1: d = path; yann@1: while ((d = strchr(d, '/'))) { yann@1: *d = 0; yann@1: if (stat(path, &sb) && mkdir(path, 0755)) { yann@1: res = 1; yann@1: goto out; yann@1: } yann@1: *d++ = '/'; yann@1: } yann@1: /* Try it again. */ yann@1: fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644); yann@1: if (fd == -1) { yann@1: res = 1; yann@1: break; yann@1: } yann@1: } yann@1: close(fd); yann@1: } yann@1: out: yann@1: if (chdir("../..")) yann@1: return 1; yann@1: yann@1: return res; yann@1: } yann@1: yann@1: int conf_write_autoconf(void) yann@1: { yann@1: struct symbol *sym; yann@1: const char *str; yann@1: char *name; yann@1: FILE *out, *out_h; yann@1: time_t now; yann@1: int i, l; yann@1: yann@1: sym_clear_all_valid(); yann@1: yann@1: file_write_dep("include/config/auto.conf.cmd"); yann@1: yann@1: if (conf_split_config()) yann@1: return 1; yann@1: yann@1: out = fopen(".tmpconfig", "w"); yann@1: if (!out) yann@1: return 1; yann@1: yann@1: out_h = fopen(".tmpconfig.h", "w"); yann@1: if (!out_h) { yann@1: fclose(out); yann@1: return 1; yann@1: } yann@1: yann@1: sym = sym_lookup("PROJECTVERSION", 0); yann@1: sym_calc_value(sym); yann@1: time(&now); yann@1: fprintf(out, "#\n" yann@1: "# Automatically generated make config: don't edit\n" yann@943: "# " PACKAGE " version: %s\n" yann@1: "# %s" yann@1: "#\n", yann@1: sym_get_string_value(sym), ctime(&now)); yann@1: fprintf(out_h, "/*\n" yann@1: " * Automatically generated C config: don't edit\n" yann@943: " * " PACKAGE " version: %s\n" yann@1: " * %s" yann@1: " */\n" yann@1: "#define AUTOCONF_INCLUDED\n", yann@1: sym_get_string_value(sym), ctime(&now)); yann@1: yann@1: for_all_symbols(i, sym) { yann@1: sym_calc_value(sym); yann@1: if (!(sym->flags & SYMBOL_WRITE) || !sym->name) yann@1: continue; yann@1: switch (sym->type) { yann@1: case S_BOOLEAN: yann@1: case S_TRISTATE: yann@1: switch (sym_get_tristate_value(sym)) { yann@1: case no: yann@1: break; yann@1: case mod: yann@1: fprintf(out, "CT_%s=m\n", sym->name); yann@1: fprintf(out_h, "#define CT_%s_MODULE 1\n", sym->name); yann@1: break; yann@1: case yes: yann@1: fprintf(out, "CT_%s=y\n", sym->name); yann@1: fprintf(out_h, "#define CT_%s 1\n", sym->name); yann@1: break; yann@1: } yann@1: break; yann@1: case S_STRING: yann@1: str = sym_get_string_value(sym); yann@1: fprintf(out, "CT_%s=\"", sym->name); yann@1: fprintf(out_h, "#define CT_%s \"", sym->name); yann@1: while (1) { yann@1: l = strcspn(str, "\"\\"); yann@1: if (l) { yann@1: fwrite(str, l, 1, out); yann@1: fwrite(str, l, 1, out_h); yann@1: str += l; yann@1: } yann@1: if (!*str) yann@1: break; yann@1: fprintf(out, "\\%c", *str); yann@1: fprintf(out_h, "\\%c", *str); yann@1: str++; yann@1: } yann@1: fputs("\"\n", out); yann@1: fputs("\"\n", out_h); yann@1: break; yann@1: case S_HEX: yann@1: str = sym_get_string_value(sym); yann@1: if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) { yann@1: fprintf(out, "CT_%s=%s\n", sym->name, str); yann@1: fprintf(out_h, "#define CT_%s 0x%s\n", sym->name, str); yann@1: break; yann@1: } yann@1: case S_INT: yann@1: str = sym_get_string_value(sym); yann@1: fprintf(out, "CT_%s=%s\n", sym->name, str); yann@1: fprintf(out_h, "#define CT_%s %s\n", sym->name, str); yann@1: break; yann@1: default: yann@1: break; yann@1: } yann@1: } yann@1: fclose(out); yann@1: fclose(out_h); yann@1: yann@1: name = getenv("KCONFIG_AUTOHEADER"); yann@1: if (!name) yann@1: name = "include/linux/autoconf.h"; yann@1: if (rename(".tmpconfig.h", name)) yann@1: return 1; yann@1: name = getenv("KCONFIG_AUTOCONFIG"); yann@1: if (!name) yann@1: name = "include/config/auto.conf"; yann@1: /* yann@1: * This must be the last step, kbuild has a dependency on auto.conf yann@1: * and this marks the successful completion of the previous steps. yann@1: */ yann@1: if (rename(".tmpconfig", name)) yann@1: return 1; yann@1: yann@1: return 0; yann@1: } yann@39: yann@39: static int sym_change_count; yann@39: static void (*conf_changed_callback)(void); yann@39: yann@39: void sym_set_change_count(int count) yann@39: { yann@39: int _sym_change_count = sym_change_count; yann@39: sym_change_count = count; yann@39: if (conf_changed_callback && yann@39: (bool)_sym_change_count != (bool)count) yann@39: conf_changed_callback(); yann@39: } yann@39: yann@39: void sym_add_change_count(int count) yann@39: { yann@39: sym_set_change_count(count + sym_change_count); yann@39: } yann@39: yann@39: bool conf_get_changed(void) yann@39: { yann@39: return sym_change_count; yann@39: } yann@39: yann@39: void conf_set_changed_callback(void (*fn)(void)) yann@39: { yann@39: conf_changed_callback = fn; yann@39: } yann@943: yann@943: yann@943: void conf_set_all_new_symbols(enum conf_def_mode mode) yann@943: { yann@943: struct symbol *sym, *csym; yann@943: struct property *prop; yann@943: struct expr *e; yann@943: int i, cnt, def; yann@943: yann@943: for_all_symbols(i, sym) { yann@943: if (sym_has_value(sym)) yann@943: continue; yann@943: switch (sym_get_type(sym)) { yann@943: case S_BOOLEAN: yann@943: case S_TRISTATE: yann@943: switch (mode) { yann@943: case def_yes: yann@943: sym->def[S_DEF_USER].tri = yes; yann@943: break; yann@943: case def_mod: yann@943: sym->def[S_DEF_USER].tri = mod; yann@943: break; yann@943: case def_no: yann@943: sym->def[S_DEF_USER].tri = no; yann@943: break; yann@943: case def_random: yann@943: sym->def[S_DEF_USER].tri = (tristate)(rand() % 3); yann@943: break; yann@943: default: yann@943: continue; yann@943: } yann@943: if (!sym_is_choice(sym) || mode != def_random) yann@943: sym->flags |= SYMBOL_DEF_USER; yann@943: break; yann@943: default: yann@943: break; yann@943: } yann@943: yann@943: } yann@943: yann@1228: sym_clear_all_valid(); yann@943: yann@943: if (mode != def_random) yann@943: return; yann@943: yann@943: for_all_symbols(i, csym) { yann@943: if (sym_has_value(csym) || !sym_is_choice(csym)) yann@943: continue; yann@943: yann@943: sym_calc_value(csym); yann@943: prop = sym_get_choice_prop(csym); yann@943: def = -1; yann@943: while (1) { yann@943: cnt = 0; yann@943: expr_list_for_each_sym(prop->expr, e, sym) { yann@943: if (sym->visible == no) yann@943: continue; yann@943: if (def == cnt++) { yann@943: csym->def[S_DEF_USER].val = sym; yann@943: break; yann@943: } yann@943: } yann@943: if (def >= 0 || cnt < 2) yann@943: break; yann@943: def = (rand() % cnt) + 1; yann@943: } yann@943: csym->flags |= SYMBOL_DEF_USER; yann@943: } yann@943: }