1*0a9064fbSMasahiro Yamada /* 2*0a9064fbSMasahiro Yamada * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> 3*0a9064fbSMasahiro Yamada * Released under the terms of the GNU GPL v2.0. 4*0a9064fbSMasahiro Yamada */ 5*0a9064fbSMasahiro Yamada 6*0a9064fbSMasahiro Yamada #include <sys/stat.h> 7*0a9064fbSMasahiro Yamada #include <ctype.h> 8*0a9064fbSMasahiro Yamada #include <errno.h> 9*0a9064fbSMasahiro Yamada #include <fcntl.h> 10*0a9064fbSMasahiro Yamada #include <stdarg.h> 11*0a9064fbSMasahiro Yamada #include <stdio.h> 12*0a9064fbSMasahiro Yamada #include <stdlib.h> 13*0a9064fbSMasahiro Yamada #include <string.h> 14*0a9064fbSMasahiro Yamada #include <time.h> 15*0a9064fbSMasahiro Yamada #include <unistd.h> 16*0a9064fbSMasahiro Yamada 17*0a9064fbSMasahiro Yamada #include "lkc.h" 18*0a9064fbSMasahiro Yamada 19*0a9064fbSMasahiro Yamada static void conf_warning(const char *fmt, ...) 20*0a9064fbSMasahiro Yamada __attribute__ ((format (printf, 1, 2))); 21*0a9064fbSMasahiro Yamada 22*0a9064fbSMasahiro Yamada static void conf_message(const char *fmt, ...) 23*0a9064fbSMasahiro Yamada __attribute__ ((format (printf, 1, 2))); 24*0a9064fbSMasahiro Yamada 25*0a9064fbSMasahiro Yamada static const char *conf_filename; 26*0a9064fbSMasahiro Yamada static int conf_lineno, conf_warnings, conf_unsaved; 27*0a9064fbSMasahiro Yamada 28*0a9064fbSMasahiro Yamada const char conf_defname[] = "arch/$ARCH/defconfig"; 29*0a9064fbSMasahiro Yamada 30*0a9064fbSMasahiro Yamada static void conf_warning(const char *fmt, ...) 31*0a9064fbSMasahiro Yamada { 32*0a9064fbSMasahiro Yamada va_list ap; 33*0a9064fbSMasahiro Yamada va_start(ap, fmt); 34*0a9064fbSMasahiro Yamada fprintf(stderr, "%s:%d:warning: ", conf_filename, conf_lineno); 35*0a9064fbSMasahiro Yamada vfprintf(stderr, fmt, ap); 36*0a9064fbSMasahiro Yamada fprintf(stderr, "\n"); 37*0a9064fbSMasahiro Yamada va_end(ap); 38*0a9064fbSMasahiro Yamada conf_warnings++; 39*0a9064fbSMasahiro Yamada } 40*0a9064fbSMasahiro Yamada 41*0a9064fbSMasahiro Yamada static void conf_default_message_callback(const char *fmt, va_list ap) 42*0a9064fbSMasahiro Yamada { 43*0a9064fbSMasahiro Yamada printf("#\n# "); 44*0a9064fbSMasahiro Yamada vprintf(fmt, ap); 45*0a9064fbSMasahiro Yamada printf("\n#\n"); 46*0a9064fbSMasahiro Yamada } 47*0a9064fbSMasahiro Yamada 48*0a9064fbSMasahiro Yamada static void (*conf_message_callback) (const char *fmt, va_list ap) = 49*0a9064fbSMasahiro Yamada conf_default_message_callback; 50*0a9064fbSMasahiro Yamada void conf_set_message_callback(void (*fn) (const char *fmt, va_list ap)) 51*0a9064fbSMasahiro Yamada { 52*0a9064fbSMasahiro Yamada conf_message_callback = fn; 53*0a9064fbSMasahiro Yamada } 54*0a9064fbSMasahiro Yamada 55*0a9064fbSMasahiro Yamada static void conf_message(const char *fmt, ...) 56*0a9064fbSMasahiro Yamada { 57*0a9064fbSMasahiro Yamada va_list ap; 58*0a9064fbSMasahiro Yamada 59*0a9064fbSMasahiro Yamada va_start(ap, fmt); 60*0a9064fbSMasahiro Yamada if (conf_message_callback) 61*0a9064fbSMasahiro Yamada conf_message_callback(fmt, ap); 62*0a9064fbSMasahiro Yamada } 63*0a9064fbSMasahiro Yamada 64*0a9064fbSMasahiro Yamada const char *conf_get_configname(void) 65*0a9064fbSMasahiro Yamada { 66*0a9064fbSMasahiro Yamada char *name = getenv("KCONFIG_CONFIG"); 67*0a9064fbSMasahiro Yamada 68*0a9064fbSMasahiro Yamada return name ? name : ".config"; 69*0a9064fbSMasahiro Yamada } 70*0a9064fbSMasahiro Yamada 71*0a9064fbSMasahiro Yamada const char *conf_get_autoconfig_name(void) 72*0a9064fbSMasahiro Yamada { 73*0a9064fbSMasahiro Yamada char *name = getenv("KCONFIG_AUTOCONFIG"); 74*0a9064fbSMasahiro Yamada 75*0a9064fbSMasahiro Yamada return name ? name : "include/config/auto.conf"; 76*0a9064fbSMasahiro Yamada } 77*0a9064fbSMasahiro Yamada 78*0a9064fbSMasahiro Yamada static char *conf_expand_value(const char *in) 79*0a9064fbSMasahiro Yamada { 80*0a9064fbSMasahiro Yamada struct symbol *sym; 81*0a9064fbSMasahiro Yamada const char *src; 82*0a9064fbSMasahiro Yamada static char res_value[SYMBOL_MAXLENGTH]; 83*0a9064fbSMasahiro Yamada char *dst, name[SYMBOL_MAXLENGTH]; 84*0a9064fbSMasahiro Yamada 85*0a9064fbSMasahiro Yamada res_value[0] = 0; 86*0a9064fbSMasahiro Yamada dst = name; 87*0a9064fbSMasahiro Yamada while ((src = strchr(in, '$'))) { 88*0a9064fbSMasahiro Yamada strncat(res_value, in, src - in); 89*0a9064fbSMasahiro Yamada src++; 90*0a9064fbSMasahiro Yamada dst = name; 91*0a9064fbSMasahiro Yamada while (isalnum(*src) || *src == '_') 92*0a9064fbSMasahiro Yamada *dst++ = *src++; 93*0a9064fbSMasahiro Yamada *dst = 0; 94*0a9064fbSMasahiro Yamada sym = sym_lookup(name, 0); 95*0a9064fbSMasahiro Yamada sym_calc_value(sym); 96*0a9064fbSMasahiro Yamada strcat(res_value, sym_get_string_value(sym)); 97*0a9064fbSMasahiro Yamada in = src; 98*0a9064fbSMasahiro Yamada } 99*0a9064fbSMasahiro Yamada strcat(res_value, in); 100*0a9064fbSMasahiro Yamada 101*0a9064fbSMasahiro Yamada return res_value; 102*0a9064fbSMasahiro Yamada } 103*0a9064fbSMasahiro Yamada 104*0a9064fbSMasahiro Yamada char *conf_get_default_confname(void) 105*0a9064fbSMasahiro Yamada { 106*0a9064fbSMasahiro Yamada struct stat buf; 107*0a9064fbSMasahiro Yamada static char fullname[PATH_MAX+1]; 108*0a9064fbSMasahiro Yamada char *env, *name; 109*0a9064fbSMasahiro Yamada 110*0a9064fbSMasahiro Yamada name = conf_expand_value(conf_defname); 111*0a9064fbSMasahiro Yamada env = getenv(SRCTREE); 112*0a9064fbSMasahiro Yamada if (env) { 113*0a9064fbSMasahiro Yamada sprintf(fullname, "%s/%s", env, name); 114*0a9064fbSMasahiro Yamada if (!stat(fullname, &buf)) 115*0a9064fbSMasahiro Yamada return fullname; 116*0a9064fbSMasahiro Yamada } 117*0a9064fbSMasahiro Yamada return name; 118*0a9064fbSMasahiro Yamada } 119*0a9064fbSMasahiro Yamada 120*0a9064fbSMasahiro Yamada static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p) 121*0a9064fbSMasahiro Yamada { 122*0a9064fbSMasahiro Yamada char *p2; 123*0a9064fbSMasahiro Yamada 124*0a9064fbSMasahiro Yamada switch (sym->type) { 125*0a9064fbSMasahiro Yamada case S_TRISTATE: 126*0a9064fbSMasahiro Yamada if (p[0] == 'm') { 127*0a9064fbSMasahiro Yamada sym->def[def].tri = mod; 128*0a9064fbSMasahiro Yamada sym->flags |= def_flags; 129*0a9064fbSMasahiro Yamada break; 130*0a9064fbSMasahiro Yamada } 131*0a9064fbSMasahiro Yamada /* fall through */ 132*0a9064fbSMasahiro Yamada case S_BOOLEAN: 133*0a9064fbSMasahiro Yamada if (p[0] == 'y') { 134*0a9064fbSMasahiro Yamada sym->def[def].tri = yes; 135*0a9064fbSMasahiro Yamada sym->flags |= def_flags; 136*0a9064fbSMasahiro Yamada break; 137*0a9064fbSMasahiro Yamada } 138*0a9064fbSMasahiro Yamada if (p[0] == 'n') { 139*0a9064fbSMasahiro Yamada sym->def[def].tri = no; 140*0a9064fbSMasahiro Yamada sym->flags |= def_flags; 141*0a9064fbSMasahiro Yamada break; 142*0a9064fbSMasahiro Yamada } 143*0a9064fbSMasahiro Yamada if (def != S_DEF_AUTO) 144*0a9064fbSMasahiro Yamada conf_warning("symbol value '%s' invalid for %s", 145*0a9064fbSMasahiro Yamada p, sym->name); 146*0a9064fbSMasahiro Yamada return 1; 147*0a9064fbSMasahiro Yamada case S_OTHER: 148*0a9064fbSMasahiro Yamada if (*p != '"') { 149*0a9064fbSMasahiro Yamada for (p2 = p; *p2 && !isspace(*p2); p2++) 150*0a9064fbSMasahiro Yamada ; 151*0a9064fbSMasahiro Yamada sym->type = S_STRING; 152*0a9064fbSMasahiro Yamada goto done; 153*0a9064fbSMasahiro Yamada } 154*0a9064fbSMasahiro Yamada /* fall through */ 155*0a9064fbSMasahiro Yamada case S_STRING: 156*0a9064fbSMasahiro Yamada if (*p++ != '"') 157*0a9064fbSMasahiro Yamada break; 158*0a9064fbSMasahiro Yamada for (p2 = p; (p2 = strpbrk(p2, "\"\\")); p2++) { 159*0a9064fbSMasahiro Yamada if (*p2 == '"') { 160*0a9064fbSMasahiro Yamada *p2 = 0; 161*0a9064fbSMasahiro Yamada break; 162*0a9064fbSMasahiro Yamada } 163*0a9064fbSMasahiro Yamada memmove(p2, p2 + 1, strlen(p2)); 164*0a9064fbSMasahiro Yamada } 165*0a9064fbSMasahiro Yamada if (!p2) { 166*0a9064fbSMasahiro Yamada if (def != S_DEF_AUTO) 167*0a9064fbSMasahiro Yamada conf_warning("invalid string found"); 168*0a9064fbSMasahiro Yamada return 1; 169*0a9064fbSMasahiro Yamada } 170*0a9064fbSMasahiro Yamada /* fall through */ 171*0a9064fbSMasahiro Yamada case S_INT: 172*0a9064fbSMasahiro Yamada case S_HEX: 173*0a9064fbSMasahiro Yamada done: 174*0a9064fbSMasahiro Yamada if (sym_string_valid(sym, p)) { 175*0a9064fbSMasahiro Yamada sym->def[def].val = strdup(p); 176*0a9064fbSMasahiro Yamada sym->flags |= def_flags; 177*0a9064fbSMasahiro Yamada } else { 178*0a9064fbSMasahiro Yamada if (def != S_DEF_AUTO) 179*0a9064fbSMasahiro Yamada conf_warning("symbol value '%s' invalid for %s", 180*0a9064fbSMasahiro Yamada p, sym->name); 181*0a9064fbSMasahiro Yamada return 1; 182*0a9064fbSMasahiro Yamada } 183*0a9064fbSMasahiro Yamada break; 184*0a9064fbSMasahiro Yamada default: 185*0a9064fbSMasahiro Yamada ; 186*0a9064fbSMasahiro Yamada } 187*0a9064fbSMasahiro Yamada return 0; 188*0a9064fbSMasahiro Yamada } 189*0a9064fbSMasahiro Yamada 190*0a9064fbSMasahiro Yamada #define LINE_GROWTH 16 191*0a9064fbSMasahiro Yamada static int add_byte(int c, char **lineptr, size_t slen, size_t *n) 192*0a9064fbSMasahiro Yamada { 193*0a9064fbSMasahiro Yamada char *nline; 194*0a9064fbSMasahiro Yamada size_t new_size = slen + 1; 195*0a9064fbSMasahiro Yamada if (new_size > *n) { 196*0a9064fbSMasahiro Yamada new_size += LINE_GROWTH - 1; 197*0a9064fbSMasahiro Yamada new_size *= 2; 198*0a9064fbSMasahiro Yamada nline = realloc(*lineptr, new_size); 199*0a9064fbSMasahiro Yamada if (!nline) 200*0a9064fbSMasahiro Yamada return -1; 201*0a9064fbSMasahiro Yamada 202*0a9064fbSMasahiro Yamada *lineptr = nline; 203*0a9064fbSMasahiro Yamada *n = new_size; 204*0a9064fbSMasahiro Yamada } 205*0a9064fbSMasahiro Yamada 206*0a9064fbSMasahiro Yamada (*lineptr)[slen] = c; 207*0a9064fbSMasahiro Yamada 208*0a9064fbSMasahiro Yamada return 0; 209*0a9064fbSMasahiro Yamada } 210*0a9064fbSMasahiro Yamada 211*0a9064fbSMasahiro Yamada static ssize_t compat_getline(char **lineptr, size_t *n, FILE *stream) 212*0a9064fbSMasahiro Yamada { 213*0a9064fbSMasahiro Yamada char *line = *lineptr; 214*0a9064fbSMasahiro Yamada size_t slen = 0; 215*0a9064fbSMasahiro Yamada 216*0a9064fbSMasahiro Yamada for (;;) { 217*0a9064fbSMasahiro Yamada int c = getc(stream); 218*0a9064fbSMasahiro Yamada 219*0a9064fbSMasahiro Yamada switch (c) { 220*0a9064fbSMasahiro Yamada case '\n': 221*0a9064fbSMasahiro Yamada if (add_byte(c, &line, slen, n) < 0) 222*0a9064fbSMasahiro Yamada goto e_out; 223*0a9064fbSMasahiro Yamada slen++; 224*0a9064fbSMasahiro Yamada /* fall through */ 225*0a9064fbSMasahiro Yamada case EOF: 226*0a9064fbSMasahiro Yamada if (add_byte('\0', &line, slen, n) < 0) 227*0a9064fbSMasahiro Yamada goto e_out; 228*0a9064fbSMasahiro Yamada *lineptr = line; 229*0a9064fbSMasahiro Yamada if (slen == 0) 230*0a9064fbSMasahiro Yamada return -1; 231*0a9064fbSMasahiro Yamada return slen; 232*0a9064fbSMasahiro Yamada default: 233*0a9064fbSMasahiro Yamada if (add_byte(c, &line, slen, n) < 0) 234*0a9064fbSMasahiro Yamada goto e_out; 235*0a9064fbSMasahiro Yamada slen++; 236*0a9064fbSMasahiro Yamada } 237*0a9064fbSMasahiro Yamada } 238*0a9064fbSMasahiro Yamada 239*0a9064fbSMasahiro Yamada e_out: 240*0a9064fbSMasahiro Yamada line[slen-1] = '\0'; 241*0a9064fbSMasahiro Yamada *lineptr = line; 242*0a9064fbSMasahiro Yamada return -1; 243*0a9064fbSMasahiro Yamada } 244*0a9064fbSMasahiro Yamada 245*0a9064fbSMasahiro Yamada int conf_read_simple(const char *name, int def) 246*0a9064fbSMasahiro Yamada { 247*0a9064fbSMasahiro Yamada FILE *in = NULL; 248*0a9064fbSMasahiro Yamada char *line = NULL; 249*0a9064fbSMasahiro Yamada size_t line_asize = 0; 250*0a9064fbSMasahiro Yamada char *p, *p2; 251*0a9064fbSMasahiro Yamada struct symbol *sym; 252*0a9064fbSMasahiro Yamada int i, def_flags; 253*0a9064fbSMasahiro Yamada 254*0a9064fbSMasahiro Yamada if (name) { 255*0a9064fbSMasahiro Yamada in = zconf_fopen(name); 256*0a9064fbSMasahiro Yamada } else { 257*0a9064fbSMasahiro Yamada struct property *prop; 258*0a9064fbSMasahiro Yamada 259*0a9064fbSMasahiro Yamada name = conf_get_configname(); 260*0a9064fbSMasahiro Yamada in = zconf_fopen(name); 261*0a9064fbSMasahiro Yamada if (in) 262*0a9064fbSMasahiro Yamada goto load; 263*0a9064fbSMasahiro Yamada sym_add_change_count(1); 264*0a9064fbSMasahiro Yamada if (!sym_defconfig_list) { 265*0a9064fbSMasahiro Yamada if (modules_sym) 266*0a9064fbSMasahiro Yamada sym_calc_value(modules_sym); 267*0a9064fbSMasahiro Yamada return 1; 268*0a9064fbSMasahiro Yamada } 269*0a9064fbSMasahiro Yamada 270*0a9064fbSMasahiro Yamada for_all_defaults(sym_defconfig_list, prop) { 271*0a9064fbSMasahiro Yamada if (expr_calc_value(prop->visible.expr) == no || 272*0a9064fbSMasahiro Yamada prop->expr->type != E_SYMBOL) 273*0a9064fbSMasahiro Yamada continue; 274*0a9064fbSMasahiro Yamada name = conf_expand_value(prop->expr->left.sym->name); 275*0a9064fbSMasahiro Yamada in = zconf_fopen(name); 276*0a9064fbSMasahiro Yamada if (in) { 277*0a9064fbSMasahiro Yamada conf_message(_("using defaults found in %s"), 278*0a9064fbSMasahiro Yamada name); 279*0a9064fbSMasahiro Yamada goto load; 280*0a9064fbSMasahiro Yamada } 281*0a9064fbSMasahiro Yamada } 282*0a9064fbSMasahiro Yamada } 283*0a9064fbSMasahiro Yamada if (!in) 284*0a9064fbSMasahiro Yamada return 1; 285*0a9064fbSMasahiro Yamada 286*0a9064fbSMasahiro Yamada load: 287*0a9064fbSMasahiro Yamada conf_filename = name; 288*0a9064fbSMasahiro Yamada conf_lineno = 0; 289*0a9064fbSMasahiro Yamada conf_warnings = 0; 290*0a9064fbSMasahiro Yamada conf_unsaved = 0; 291*0a9064fbSMasahiro Yamada 292*0a9064fbSMasahiro Yamada def_flags = SYMBOL_DEF << def; 293*0a9064fbSMasahiro Yamada for_all_symbols(i, sym) { 294*0a9064fbSMasahiro Yamada sym->flags |= SYMBOL_CHANGED; 295*0a9064fbSMasahiro Yamada sym->flags &= ~(def_flags|SYMBOL_VALID); 296*0a9064fbSMasahiro Yamada if (sym_is_choice(sym)) 297*0a9064fbSMasahiro Yamada sym->flags |= def_flags; 298*0a9064fbSMasahiro Yamada switch (sym->type) { 299*0a9064fbSMasahiro Yamada case S_INT: 300*0a9064fbSMasahiro Yamada case S_HEX: 301*0a9064fbSMasahiro Yamada case S_STRING: 302*0a9064fbSMasahiro Yamada if (sym->def[def].val) 303*0a9064fbSMasahiro Yamada free(sym->def[def].val); 304*0a9064fbSMasahiro Yamada /* fall through */ 305*0a9064fbSMasahiro Yamada default: 306*0a9064fbSMasahiro Yamada sym->def[def].val = NULL; 307*0a9064fbSMasahiro Yamada sym->def[def].tri = no; 308*0a9064fbSMasahiro Yamada } 309*0a9064fbSMasahiro Yamada } 310*0a9064fbSMasahiro Yamada 311*0a9064fbSMasahiro Yamada while (compat_getline(&line, &line_asize, in) != -1) { 312*0a9064fbSMasahiro Yamada conf_lineno++; 313*0a9064fbSMasahiro Yamada sym = NULL; 314*0a9064fbSMasahiro Yamada if (line[0] == '#') { 315*0a9064fbSMasahiro Yamada if (memcmp(line + 2, CONFIG_, strlen(CONFIG_))) 316*0a9064fbSMasahiro Yamada continue; 317*0a9064fbSMasahiro Yamada p = strchr(line + 2 + strlen(CONFIG_), ' '); 318*0a9064fbSMasahiro Yamada if (!p) 319*0a9064fbSMasahiro Yamada continue; 320*0a9064fbSMasahiro Yamada *p++ = 0; 321*0a9064fbSMasahiro Yamada if (strncmp(p, "is not set", 10)) 322*0a9064fbSMasahiro Yamada continue; 323*0a9064fbSMasahiro Yamada if (def == S_DEF_USER) { 324*0a9064fbSMasahiro Yamada sym = sym_find(line + 2 + strlen(CONFIG_)); 325*0a9064fbSMasahiro Yamada if (!sym) { 326*0a9064fbSMasahiro Yamada sym_add_change_count(1); 327*0a9064fbSMasahiro Yamada goto setsym; 328*0a9064fbSMasahiro Yamada } 329*0a9064fbSMasahiro Yamada } else { 330*0a9064fbSMasahiro Yamada sym = sym_lookup(line + 2 + strlen(CONFIG_), 0); 331*0a9064fbSMasahiro Yamada if (sym->type == S_UNKNOWN) 332*0a9064fbSMasahiro Yamada sym->type = S_BOOLEAN; 333*0a9064fbSMasahiro Yamada } 334*0a9064fbSMasahiro Yamada if (sym->flags & def_flags) { 335*0a9064fbSMasahiro Yamada conf_warning("override: reassigning to symbol %s", sym->name); 336*0a9064fbSMasahiro Yamada } 337*0a9064fbSMasahiro Yamada switch (sym->type) { 338*0a9064fbSMasahiro Yamada case S_BOOLEAN: 339*0a9064fbSMasahiro Yamada case S_TRISTATE: 340*0a9064fbSMasahiro Yamada sym->def[def].tri = no; 341*0a9064fbSMasahiro Yamada sym->flags |= def_flags; 342*0a9064fbSMasahiro Yamada break; 343*0a9064fbSMasahiro Yamada default: 344*0a9064fbSMasahiro Yamada ; 345*0a9064fbSMasahiro Yamada } 346*0a9064fbSMasahiro Yamada } else if (memcmp(line, CONFIG_, strlen(CONFIG_)) == 0) { 347*0a9064fbSMasahiro Yamada p = strchr(line + strlen(CONFIG_), '='); 348*0a9064fbSMasahiro Yamada if (!p) 349*0a9064fbSMasahiro Yamada continue; 350*0a9064fbSMasahiro Yamada *p++ = 0; 351*0a9064fbSMasahiro Yamada p2 = strchr(p, '\n'); 352*0a9064fbSMasahiro Yamada if (p2) { 353*0a9064fbSMasahiro Yamada *p2-- = 0; 354*0a9064fbSMasahiro Yamada if (*p2 == '\r') 355*0a9064fbSMasahiro Yamada *p2 = 0; 356*0a9064fbSMasahiro Yamada } 357*0a9064fbSMasahiro Yamada if (def == S_DEF_USER) { 358*0a9064fbSMasahiro Yamada sym = sym_find(line + strlen(CONFIG_)); 359*0a9064fbSMasahiro Yamada if (!sym) { 360*0a9064fbSMasahiro Yamada sym_add_change_count(1); 361*0a9064fbSMasahiro Yamada goto setsym; 362*0a9064fbSMasahiro Yamada } 363*0a9064fbSMasahiro Yamada } else { 364*0a9064fbSMasahiro Yamada sym = sym_lookup(line + strlen(CONFIG_), 0); 365*0a9064fbSMasahiro Yamada if (sym->type == S_UNKNOWN) 366*0a9064fbSMasahiro Yamada sym->type = S_OTHER; 367*0a9064fbSMasahiro Yamada } 368*0a9064fbSMasahiro Yamada if (sym->flags & def_flags) { 369*0a9064fbSMasahiro Yamada conf_warning("override: reassigning to symbol %s", sym->name); 370*0a9064fbSMasahiro Yamada } 371*0a9064fbSMasahiro Yamada if (conf_set_sym_val(sym, def, def_flags, p)) 372*0a9064fbSMasahiro Yamada continue; 373*0a9064fbSMasahiro Yamada } else { 374*0a9064fbSMasahiro Yamada if (line[0] != '\r' && line[0] != '\n') 375*0a9064fbSMasahiro Yamada conf_warning("unexpected data"); 376*0a9064fbSMasahiro Yamada continue; 377*0a9064fbSMasahiro Yamada } 378*0a9064fbSMasahiro Yamada setsym: 379*0a9064fbSMasahiro Yamada if (sym && sym_is_choice_value(sym)) { 380*0a9064fbSMasahiro Yamada struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym)); 381*0a9064fbSMasahiro Yamada switch (sym->def[def].tri) { 382*0a9064fbSMasahiro Yamada case no: 383*0a9064fbSMasahiro Yamada break; 384*0a9064fbSMasahiro Yamada case mod: 385*0a9064fbSMasahiro Yamada if (cs->def[def].tri == yes) { 386*0a9064fbSMasahiro Yamada conf_warning("%s creates inconsistent choice state", sym->name); 387*0a9064fbSMasahiro Yamada cs->flags &= ~def_flags; 388*0a9064fbSMasahiro Yamada } 389*0a9064fbSMasahiro Yamada break; 390*0a9064fbSMasahiro Yamada case yes: 391*0a9064fbSMasahiro Yamada if (cs->def[def].tri != no) 392*0a9064fbSMasahiro Yamada conf_warning("override: %s changes choice state", sym->name); 393*0a9064fbSMasahiro Yamada cs->def[def].val = sym; 394*0a9064fbSMasahiro Yamada break; 395*0a9064fbSMasahiro Yamada } 396*0a9064fbSMasahiro Yamada cs->def[def].tri = EXPR_OR(cs->def[def].tri, sym->def[def].tri); 397*0a9064fbSMasahiro Yamada } 398*0a9064fbSMasahiro Yamada } 399*0a9064fbSMasahiro Yamada free(line); 400*0a9064fbSMasahiro Yamada fclose(in); 401*0a9064fbSMasahiro Yamada 402*0a9064fbSMasahiro Yamada if (modules_sym) 403*0a9064fbSMasahiro Yamada sym_calc_value(modules_sym); 404*0a9064fbSMasahiro Yamada return 0; 405*0a9064fbSMasahiro Yamada } 406*0a9064fbSMasahiro Yamada 407*0a9064fbSMasahiro Yamada int conf_read(const char *name) 408*0a9064fbSMasahiro Yamada { 409*0a9064fbSMasahiro Yamada struct symbol *sym; 410*0a9064fbSMasahiro Yamada int i; 411*0a9064fbSMasahiro Yamada 412*0a9064fbSMasahiro Yamada sym_set_change_count(0); 413*0a9064fbSMasahiro Yamada 414*0a9064fbSMasahiro Yamada if (conf_read_simple(name, S_DEF_USER)) 415*0a9064fbSMasahiro Yamada return 1; 416*0a9064fbSMasahiro Yamada 417*0a9064fbSMasahiro Yamada for_all_symbols(i, sym) { 418*0a9064fbSMasahiro Yamada sym_calc_value(sym); 419*0a9064fbSMasahiro Yamada if (sym_is_choice(sym) || (sym->flags & SYMBOL_AUTO)) 420*0a9064fbSMasahiro Yamada continue; 421*0a9064fbSMasahiro Yamada if (sym_has_value(sym) && (sym->flags & SYMBOL_WRITE)) { 422*0a9064fbSMasahiro Yamada /* check that calculated value agrees with saved value */ 423*0a9064fbSMasahiro Yamada switch (sym->type) { 424*0a9064fbSMasahiro Yamada case S_BOOLEAN: 425*0a9064fbSMasahiro Yamada case S_TRISTATE: 426*0a9064fbSMasahiro Yamada if (sym->def[S_DEF_USER].tri != sym_get_tristate_value(sym)) 427*0a9064fbSMasahiro Yamada break; 428*0a9064fbSMasahiro Yamada if (!sym_is_choice(sym)) 429*0a9064fbSMasahiro Yamada continue; 430*0a9064fbSMasahiro Yamada /* fall through */ 431*0a9064fbSMasahiro Yamada default: 432*0a9064fbSMasahiro Yamada if (!strcmp(sym->curr.val, sym->def[S_DEF_USER].val)) 433*0a9064fbSMasahiro Yamada continue; 434*0a9064fbSMasahiro Yamada break; 435*0a9064fbSMasahiro Yamada } 436*0a9064fbSMasahiro Yamada } else if (!sym_has_value(sym) && !(sym->flags & SYMBOL_WRITE)) 437*0a9064fbSMasahiro Yamada /* no previous value and not saved */ 438*0a9064fbSMasahiro Yamada continue; 439*0a9064fbSMasahiro Yamada conf_unsaved++; 440*0a9064fbSMasahiro Yamada /* maybe print value in verbose mode... */ 441*0a9064fbSMasahiro Yamada } 442*0a9064fbSMasahiro Yamada 443*0a9064fbSMasahiro Yamada for_all_symbols(i, sym) { 444*0a9064fbSMasahiro Yamada if (sym_has_value(sym) && !sym_is_choice_value(sym)) { 445*0a9064fbSMasahiro Yamada /* Reset values of generates values, so they'll appear 446*0a9064fbSMasahiro Yamada * as new, if they should become visible, but that 447*0a9064fbSMasahiro Yamada * doesn't quite work if the Kconfig and the saved 448*0a9064fbSMasahiro Yamada * configuration disagree. 449*0a9064fbSMasahiro Yamada */ 450*0a9064fbSMasahiro Yamada if (sym->visible == no && !conf_unsaved) 451*0a9064fbSMasahiro Yamada sym->flags &= ~SYMBOL_DEF_USER; 452*0a9064fbSMasahiro Yamada switch (sym->type) { 453*0a9064fbSMasahiro Yamada case S_STRING: 454*0a9064fbSMasahiro Yamada case S_INT: 455*0a9064fbSMasahiro Yamada case S_HEX: 456*0a9064fbSMasahiro Yamada /* Reset a string value if it's out of range */ 457*0a9064fbSMasahiro Yamada if (sym_string_within_range(sym, sym->def[S_DEF_USER].val)) 458*0a9064fbSMasahiro Yamada break; 459*0a9064fbSMasahiro Yamada sym->flags &= ~(SYMBOL_VALID|SYMBOL_DEF_USER); 460*0a9064fbSMasahiro Yamada conf_unsaved++; 461*0a9064fbSMasahiro Yamada break; 462*0a9064fbSMasahiro Yamada default: 463*0a9064fbSMasahiro Yamada break; 464*0a9064fbSMasahiro Yamada } 465*0a9064fbSMasahiro Yamada } 466*0a9064fbSMasahiro Yamada } 467*0a9064fbSMasahiro Yamada 468*0a9064fbSMasahiro Yamada sym_add_change_count(conf_warnings || conf_unsaved); 469*0a9064fbSMasahiro Yamada 470*0a9064fbSMasahiro Yamada return 0; 471*0a9064fbSMasahiro Yamada } 472*0a9064fbSMasahiro Yamada 473*0a9064fbSMasahiro Yamada /* 474*0a9064fbSMasahiro Yamada * Kconfig configuration printer 475*0a9064fbSMasahiro Yamada * 476*0a9064fbSMasahiro Yamada * This printer is used when generating the resulting configuration after 477*0a9064fbSMasahiro Yamada * kconfig invocation and `defconfig' files. Unset symbol might be omitted by 478*0a9064fbSMasahiro Yamada * passing a non-NULL argument to the printer. 479*0a9064fbSMasahiro Yamada * 480*0a9064fbSMasahiro Yamada */ 481*0a9064fbSMasahiro Yamada static void 482*0a9064fbSMasahiro Yamada kconfig_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg) 483*0a9064fbSMasahiro Yamada { 484*0a9064fbSMasahiro Yamada 485*0a9064fbSMasahiro Yamada switch (sym->type) { 486*0a9064fbSMasahiro Yamada case S_BOOLEAN: 487*0a9064fbSMasahiro Yamada case S_TRISTATE: 488*0a9064fbSMasahiro Yamada if (*value == 'n') { 489*0a9064fbSMasahiro Yamada bool skip_unset = (arg != NULL); 490*0a9064fbSMasahiro Yamada 491*0a9064fbSMasahiro Yamada if (!skip_unset) 492*0a9064fbSMasahiro Yamada fprintf(fp, "# %s%s is not set\n", 493*0a9064fbSMasahiro Yamada CONFIG_, sym->name); 494*0a9064fbSMasahiro Yamada return; 495*0a9064fbSMasahiro Yamada } 496*0a9064fbSMasahiro Yamada break; 497*0a9064fbSMasahiro Yamada default: 498*0a9064fbSMasahiro Yamada break; 499*0a9064fbSMasahiro Yamada } 500*0a9064fbSMasahiro Yamada 501*0a9064fbSMasahiro Yamada fprintf(fp, "%s%s=%s\n", CONFIG_, sym->name, value); 502*0a9064fbSMasahiro Yamada } 503*0a9064fbSMasahiro Yamada 504*0a9064fbSMasahiro Yamada static void 505*0a9064fbSMasahiro Yamada kconfig_print_comment(FILE *fp, const char *value, void *arg) 506*0a9064fbSMasahiro Yamada { 507*0a9064fbSMasahiro Yamada const char *p = value; 508*0a9064fbSMasahiro Yamada size_t l; 509*0a9064fbSMasahiro Yamada 510*0a9064fbSMasahiro Yamada for (;;) { 511*0a9064fbSMasahiro Yamada l = strcspn(p, "\n"); 512*0a9064fbSMasahiro Yamada fprintf(fp, "#"); 513*0a9064fbSMasahiro Yamada if (l) { 514*0a9064fbSMasahiro Yamada fprintf(fp, " "); 515*0a9064fbSMasahiro Yamada xfwrite(p, l, 1, fp); 516*0a9064fbSMasahiro Yamada p += l; 517*0a9064fbSMasahiro Yamada } 518*0a9064fbSMasahiro Yamada fprintf(fp, "\n"); 519*0a9064fbSMasahiro Yamada if (*p++ == '\0') 520*0a9064fbSMasahiro Yamada break; 521*0a9064fbSMasahiro Yamada } 522*0a9064fbSMasahiro Yamada } 523*0a9064fbSMasahiro Yamada 524*0a9064fbSMasahiro Yamada static struct conf_printer kconfig_printer_cb = 525*0a9064fbSMasahiro Yamada { 526*0a9064fbSMasahiro Yamada .print_symbol = kconfig_print_symbol, 527*0a9064fbSMasahiro Yamada .print_comment = kconfig_print_comment, 528*0a9064fbSMasahiro Yamada }; 529*0a9064fbSMasahiro Yamada 530*0a9064fbSMasahiro Yamada /* 531*0a9064fbSMasahiro Yamada * Header printer 532*0a9064fbSMasahiro Yamada * 533*0a9064fbSMasahiro Yamada * This printer is used when generating the `include/generated/autoconf.h' file. 534*0a9064fbSMasahiro Yamada */ 535*0a9064fbSMasahiro Yamada static void 536*0a9064fbSMasahiro Yamada header_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg) 537*0a9064fbSMasahiro Yamada { 538*0a9064fbSMasahiro Yamada 539*0a9064fbSMasahiro Yamada switch (sym->type) { 540*0a9064fbSMasahiro Yamada case S_BOOLEAN: 541*0a9064fbSMasahiro Yamada case S_TRISTATE: { 542*0a9064fbSMasahiro Yamada const char *suffix = ""; 543*0a9064fbSMasahiro Yamada 544*0a9064fbSMasahiro Yamada switch (*value) { 545*0a9064fbSMasahiro Yamada case 'n': 546*0a9064fbSMasahiro Yamada break; 547*0a9064fbSMasahiro Yamada case 'm': 548*0a9064fbSMasahiro Yamada suffix = "_MODULE"; 549*0a9064fbSMasahiro Yamada /* fall through */ 550*0a9064fbSMasahiro Yamada default: 551*0a9064fbSMasahiro Yamada fprintf(fp, "#define %s%s%s 1\n", 552*0a9064fbSMasahiro Yamada CONFIG_, sym->name, suffix); 553*0a9064fbSMasahiro Yamada } 554*0a9064fbSMasahiro Yamada break; 555*0a9064fbSMasahiro Yamada } 556*0a9064fbSMasahiro Yamada case S_HEX: { 557*0a9064fbSMasahiro Yamada const char *prefix = ""; 558*0a9064fbSMasahiro Yamada 559*0a9064fbSMasahiro Yamada if (value[0] != '0' || (value[1] != 'x' && value[1] != 'X')) 560*0a9064fbSMasahiro Yamada prefix = "0x"; 561*0a9064fbSMasahiro Yamada fprintf(fp, "#define %s%s %s%s\n", 562*0a9064fbSMasahiro Yamada CONFIG_, sym->name, prefix, value); 563*0a9064fbSMasahiro Yamada break; 564*0a9064fbSMasahiro Yamada } 565*0a9064fbSMasahiro Yamada case S_STRING: 566*0a9064fbSMasahiro Yamada case S_INT: 567*0a9064fbSMasahiro Yamada fprintf(fp, "#define %s%s %s\n", 568*0a9064fbSMasahiro Yamada CONFIG_, sym->name, value); 569*0a9064fbSMasahiro Yamada break; 570*0a9064fbSMasahiro Yamada default: 571*0a9064fbSMasahiro Yamada break; 572*0a9064fbSMasahiro Yamada } 573*0a9064fbSMasahiro Yamada 574*0a9064fbSMasahiro Yamada } 575*0a9064fbSMasahiro Yamada 576*0a9064fbSMasahiro Yamada static void 577*0a9064fbSMasahiro Yamada header_print_comment(FILE *fp, const char *value, void *arg) 578*0a9064fbSMasahiro Yamada { 579*0a9064fbSMasahiro Yamada const char *p = value; 580*0a9064fbSMasahiro Yamada size_t l; 581*0a9064fbSMasahiro Yamada 582*0a9064fbSMasahiro Yamada fprintf(fp, "/*\n"); 583*0a9064fbSMasahiro Yamada for (;;) { 584*0a9064fbSMasahiro Yamada l = strcspn(p, "\n"); 585*0a9064fbSMasahiro Yamada fprintf(fp, " *"); 586*0a9064fbSMasahiro Yamada if (l) { 587*0a9064fbSMasahiro Yamada fprintf(fp, " "); 588*0a9064fbSMasahiro Yamada xfwrite(p, l, 1, fp); 589*0a9064fbSMasahiro Yamada p += l; 590*0a9064fbSMasahiro Yamada } 591*0a9064fbSMasahiro Yamada fprintf(fp, "\n"); 592*0a9064fbSMasahiro Yamada if (*p++ == '\0') 593*0a9064fbSMasahiro Yamada break; 594*0a9064fbSMasahiro Yamada } 595*0a9064fbSMasahiro Yamada fprintf(fp, " */\n"); 596*0a9064fbSMasahiro Yamada } 597*0a9064fbSMasahiro Yamada 598*0a9064fbSMasahiro Yamada static struct conf_printer header_printer_cb = 599*0a9064fbSMasahiro Yamada { 600*0a9064fbSMasahiro Yamada .print_symbol = header_print_symbol, 601*0a9064fbSMasahiro Yamada .print_comment = header_print_comment, 602*0a9064fbSMasahiro Yamada }; 603*0a9064fbSMasahiro Yamada 604*0a9064fbSMasahiro Yamada /* 605*0a9064fbSMasahiro Yamada * Tristate printer 606*0a9064fbSMasahiro Yamada * 607*0a9064fbSMasahiro Yamada * This printer is used when generating the `include/config/tristate.conf' file. 608*0a9064fbSMasahiro Yamada */ 609*0a9064fbSMasahiro Yamada static void 610*0a9064fbSMasahiro Yamada tristate_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg) 611*0a9064fbSMasahiro Yamada { 612*0a9064fbSMasahiro Yamada 613*0a9064fbSMasahiro Yamada if (sym->type == S_TRISTATE && *value != 'n') 614*0a9064fbSMasahiro Yamada fprintf(fp, "%s%s=%c\n", CONFIG_, sym->name, (char)toupper(*value)); 615*0a9064fbSMasahiro Yamada } 616*0a9064fbSMasahiro Yamada 617*0a9064fbSMasahiro Yamada static struct conf_printer tristate_printer_cb = 618*0a9064fbSMasahiro Yamada { 619*0a9064fbSMasahiro Yamada .print_symbol = tristate_print_symbol, 620*0a9064fbSMasahiro Yamada .print_comment = kconfig_print_comment, 621*0a9064fbSMasahiro Yamada }; 622*0a9064fbSMasahiro Yamada 623*0a9064fbSMasahiro Yamada static void conf_write_symbol(FILE *fp, struct symbol *sym, 624*0a9064fbSMasahiro Yamada struct conf_printer *printer, void *printer_arg) 625*0a9064fbSMasahiro Yamada { 626*0a9064fbSMasahiro Yamada const char *str; 627*0a9064fbSMasahiro Yamada 628*0a9064fbSMasahiro Yamada switch (sym->type) { 629*0a9064fbSMasahiro Yamada case S_OTHER: 630*0a9064fbSMasahiro Yamada case S_UNKNOWN: 631*0a9064fbSMasahiro Yamada break; 632*0a9064fbSMasahiro Yamada case S_STRING: 633*0a9064fbSMasahiro Yamada str = sym_get_string_value(sym); 634*0a9064fbSMasahiro Yamada str = sym_escape_string_value(str); 635*0a9064fbSMasahiro Yamada printer->print_symbol(fp, sym, str, printer_arg); 636*0a9064fbSMasahiro Yamada free((void *)str); 637*0a9064fbSMasahiro Yamada break; 638*0a9064fbSMasahiro Yamada default: 639*0a9064fbSMasahiro Yamada str = sym_get_string_value(sym); 640*0a9064fbSMasahiro Yamada printer->print_symbol(fp, sym, str, printer_arg); 641*0a9064fbSMasahiro Yamada } 642*0a9064fbSMasahiro Yamada } 643*0a9064fbSMasahiro Yamada 644*0a9064fbSMasahiro Yamada static void 645*0a9064fbSMasahiro Yamada conf_write_heading(FILE *fp, struct conf_printer *printer, void *printer_arg) 646*0a9064fbSMasahiro Yamada { 647*0a9064fbSMasahiro Yamada char buf[256]; 648*0a9064fbSMasahiro Yamada 649*0a9064fbSMasahiro Yamada snprintf(buf, sizeof(buf), 650*0a9064fbSMasahiro Yamada "\n" 651*0a9064fbSMasahiro Yamada "Automatically generated file; DO NOT EDIT.\n" 652*0a9064fbSMasahiro Yamada "%s\n", 653*0a9064fbSMasahiro Yamada rootmenu.prompt->text); 654*0a9064fbSMasahiro Yamada 655*0a9064fbSMasahiro Yamada printer->print_comment(fp, buf, printer_arg); 656*0a9064fbSMasahiro Yamada } 657*0a9064fbSMasahiro Yamada 658*0a9064fbSMasahiro Yamada /* 659*0a9064fbSMasahiro Yamada * Write out a minimal config. 660*0a9064fbSMasahiro Yamada * All values that has default values are skipped as this is redundant. 661*0a9064fbSMasahiro Yamada */ 662*0a9064fbSMasahiro Yamada int conf_write_defconfig(const char *filename) 663*0a9064fbSMasahiro Yamada { 664*0a9064fbSMasahiro Yamada struct symbol *sym; 665*0a9064fbSMasahiro Yamada struct menu *menu; 666*0a9064fbSMasahiro Yamada FILE *out; 667*0a9064fbSMasahiro Yamada 668*0a9064fbSMasahiro Yamada out = fopen(filename, "w"); 669*0a9064fbSMasahiro Yamada if (!out) 670*0a9064fbSMasahiro Yamada return 1; 671*0a9064fbSMasahiro Yamada 672*0a9064fbSMasahiro Yamada sym_clear_all_valid(); 673*0a9064fbSMasahiro Yamada 674*0a9064fbSMasahiro Yamada /* Traverse all menus to find all relevant symbols */ 675*0a9064fbSMasahiro Yamada menu = rootmenu.list; 676*0a9064fbSMasahiro Yamada 677*0a9064fbSMasahiro Yamada while (menu != NULL) 678*0a9064fbSMasahiro Yamada { 679*0a9064fbSMasahiro Yamada sym = menu->sym; 680*0a9064fbSMasahiro Yamada if (sym == NULL) { 681*0a9064fbSMasahiro Yamada if (!menu_is_visible(menu)) 682*0a9064fbSMasahiro Yamada goto next_menu; 683*0a9064fbSMasahiro Yamada } else if (!sym_is_choice(sym)) { 684*0a9064fbSMasahiro Yamada sym_calc_value(sym); 685*0a9064fbSMasahiro Yamada if (!(sym->flags & SYMBOL_WRITE)) 686*0a9064fbSMasahiro Yamada goto next_menu; 687*0a9064fbSMasahiro Yamada sym->flags &= ~SYMBOL_WRITE; 688*0a9064fbSMasahiro Yamada /* If we cannot change the symbol - skip */ 689*0a9064fbSMasahiro Yamada if (!sym_is_changable(sym)) 690*0a9064fbSMasahiro Yamada goto next_menu; 691*0a9064fbSMasahiro Yamada /* If symbol equals to default value - skip */ 692*0a9064fbSMasahiro Yamada if (strcmp(sym_get_string_value(sym), sym_get_string_default(sym)) == 0) 693*0a9064fbSMasahiro Yamada goto next_menu; 694*0a9064fbSMasahiro Yamada 695*0a9064fbSMasahiro Yamada /* 696*0a9064fbSMasahiro Yamada * If symbol is a choice value and equals to the 697*0a9064fbSMasahiro Yamada * default for a choice - skip. 698*0a9064fbSMasahiro Yamada * But only if value is bool and equal to "y" and 699*0a9064fbSMasahiro Yamada * choice is not "optional". 700*0a9064fbSMasahiro Yamada * (If choice is "optional" then all values can be "n") 701*0a9064fbSMasahiro Yamada */ 702*0a9064fbSMasahiro Yamada if (sym_is_choice_value(sym)) { 703*0a9064fbSMasahiro Yamada struct symbol *cs; 704*0a9064fbSMasahiro Yamada struct symbol *ds; 705*0a9064fbSMasahiro Yamada 706*0a9064fbSMasahiro Yamada cs = prop_get_symbol(sym_get_choice_prop(sym)); 707*0a9064fbSMasahiro Yamada ds = sym_choice_default(cs); 708*0a9064fbSMasahiro Yamada if (!sym_is_optional(cs) && sym == ds) { 709*0a9064fbSMasahiro Yamada if ((sym->type == S_BOOLEAN) && 710*0a9064fbSMasahiro Yamada sym_get_tristate_value(sym) == yes) 711*0a9064fbSMasahiro Yamada goto next_menu; 712*0a9064fbSMasahiro Yamada } 713*0a9064fbSMasahiro Yamada } 714*0a9064fbSMasahiro Yamada conf_write_symbol(out, sym, &kconfig_printer_cb, NULL); 715*0a9064fbSMasahiro Yamada } 716*0a9064fbSMasahiro Yamada next_menu: 717*0a9064fbSMasahiro Yamada if (menu->list != NULL) { 718*0a9064fbSMasahiro Yamada menu = menu->list; 719*0a9064fbSMasahiro Yamada } 720*0a9064fbSMasahiro Yamada else if (menu->next != NULL) { 721*0a9064fbSMasahiro Yamada menu = menu->next; 722*0a9064fbSMasahiro Yamada } else { 723*0a9064fbSMasahiro Yamada while ((menu = menu->parent)) { 724*0a9064fbSMasahiro Yamada if (menu->next != NULL) { 725*0a9064fbSMasahiro Yamada menu = menu->next; 726*0a9064fbSMasahiro Yamada break; 727*0a9064fbSMasahiro Yamada } 728*0a9064fbSMasahiro Yamada } 729*0a9064fbSMasahiro Yamada } 730*0a9064fbSMasahiro Yamada } 731*0a9064fbSMasahiro Yamada fclose(out); 732*0a9064fbSMasahiro Yamada return 0; 733*0a9064fbSMasahiro Yamada } 734*0a9064fbSMasahiro Yamada 735*0a9064fbSMasahiro Yamada int conf_write(const char *name) 736*0a9064fbSMasahiro Yamada { 737*0a9064fbSMasahiro Yamada FILE *out; 738*0a9064fbSMasahiro Yamada struct symbol *sym; 739*0a9064fbSMasahiro Yamada struct menu *menu; 740*0a9064fbSMasahiro Yamada const char *basename; 741*0a9064fbSMasahiro Yamada const char *str; 742*0a9064fbSMasahiro Yamada char dirname[PATH_MAX+1], tmpname[PATH_MAX+1], newname[PATH_MAX+1]; 743*0a9064fbSMasahiro Yamada char *env; 744*0a9064fbSMasahiro Yamada 745*0a9064fbSMasahiro Yamada dirname[0] = 0; 746*0a9064fbSMasahiro Yamada if (name && name[0]) { 747*0a9064fbSMasahiro Yamada struct stat st; 748*0a9064fbSMasahiro Yamada char *slash; 749*0a9064fbSMasahiro Yamada 750*0a9064fbSMasahiro Yamada if (!stat(name, &st) && S_ISDIR(st.st_mode)) { 751*0a9064fbSMasahiro Yamada strcpy(dirname, name); 752*0a9064fbSMasahiro Yamada strcat(dirname, "/"); 753*0a9064fbSMasahiro Yamada basename = conf_get_configname(); 754*0a9064fbSMasahiro Yamada } else if ((slash = strrchr(name, '/'))) { 755*0a9064fbSMasahiro Yamada int size = slash - name + 1; 756*0a9064fbSMasahiro Yamada memcpy(dirname, name, size); 757*0a9064fbSMasahiro Yamada dirname[size] = 0; 758*0a9064fbSMasahiro Yamada if (slash[1]) 759*0a9064fbSMasahiro Yamada basename = slash + 1; 760*0a9064fbSMasahiro Yamada else 761*0a9064fbSMasahiro Yamada basename = conf_get_configname(); 762*0a9064fbSMasahiro Yamada } else 763*0a9064fbSMasahiro Yamada basename = name; 764*0a9064fbSMasahiro Yamada } else 765*0a9064fbSMasahiro Yamada basename = conf_get_configname(); 766*0a9064fbSMasahiro Yamada 767*0a9064fbSMasahiro Yamada sprintf(newname, "%s%s", dirname, basename); 768*0a9064fbSMasahiro Yamada env = getenv("KCONFIG_OVERWRITECONFIG"); 769*0a9064fbSMasahiro Yamada if (!env || !*env) { 770*0a9064fbSMasahiro Yamada sprintf(tmpname, "%s.tmpconfig.%d", dirname, (int)getpid()); 771*0a9064fbSMasahiro Yamada out = fopen(tmpname, "w"); 772*0a9064fbSMasahiro Yamada } else { 773*0a9064fbSMasahiro Yamada *tmpname = 0; 774*0a9064fbSMasahiro Yamada out = fopen(newname, "w"); 775*0a9064fbSMasahiro Yamada } 776*0a9064fbSMasahiro Yamada if (!out) 777*0a9064fbSMasahiro Yamada return 1; 778*0a9064fbSMasahiro Yamada 779*0a9064fbSMasahiro Yamada conf_write_heading(out, &kconfig_printer_cb, NULL); 780*0a9064fbSMasahiro Yamada 781*0a9064fbSMasahiro Yamada if (!conf_get_changed()) 782*0a9064fbSMasahiro Yamada sym_clear_all_valid(); 783*0a9064fbSMasahiro Yamada 784*0a9064fbSMasahiro Yamada menu = rootmenu.list; 785*0a9064fbSMasahiro Yamada while (menu) { 786*0a9064fbSMasahiro Yamada sym = menu->sym; 787*0a9064fbSMasahiro Yamada if (!sym) { 788*0a9064fbSMasahiro Yamada if (!menu_is_visible(menu)) 789*0a9064fbSMasahiro Yamada goto next; 790*0a9064fbSMasahiro Yamada str = menu_get_prompt(menu); 791*0a9064fbSMasahiro Yamada fprintf(out, "\n" 792*0a9064fbSMasahiro Yamada "#\n" 793*0a9064fbSMasahiro Yamada "# %s\n" 794*0a9064fbSMasahiro Yamada "#\n", str); 795*0a9064fbSMasahiro Yamada } else if (!(sym->flags & SYMBOL_CHOICE)) { 796*0a9064fbSMasahiro Yamada sym_calc_value(sym); 797*0a9064fbSMasahiro Yamada if (!(sym->flags & SYMBOL_WRITE)) 798*0a9064fbSMasahiro Yamada goto next; 799*0a9064fbSMasahiro Yamada sym->flags &= ~SYMBOL_WRITE; 800*0a9064fbSMasahiro Yamada 801*0a9064fbSMasahiro Yamada conf_write_symbol(out, sym, &kconfig_printer_cb, NULL); 802*0a9064fbSMasahiro Yamada } 803*0a9064fbSMasahiro Yamada 804*0a9064fbSMasahiro Yamada next: 805*0a9064fbSMasahiro Yamada if (menu->list) { 806*0a9064fbSMasahiro Yamada menu = menu->list; 807*0a9064fbSMasahiro Yamada continue; 808*0a9064fbSMasahiro Yamada } 809*0a9064fbSMasahiro Yamada if (menu->next) 810*0a9064fbSMasahiro Yamada menu = menu->next; 811*0a9064fbSMasahiro Yamada else while ((menu = menu->parent)) { 812*0a9064fbSMasahiro Yamada if (menu->next) { 813*0a9064fbSMasahiro Yamada menu = menu->next; 814*0a9064fbSMasahiro Yamada break; 815*0a9064fbSMasahiro Yamada } 816*0a9064fbSMasahiro Yamada } 817*0a9064fbSMasahiro Yamada } 818*0a9064fbSMasahiro Yamada fclose(out); 819*0a9064fbSMasahiro Yamada 820*0a9064fbSMasahiro Yamada if (*tmpname) { 821*0a9064fbSMasahiro Yamada strcat(dirname, basename); 822*0a9064fbSMasahiro Yamada strcat(dirname, ".old"); 823*0a9064fbSMasahiro Yamada rename(newname, dirname); 824*0a9064fbSMasahiro Yamada if (rename(tmpname, newname)) 825*0a9064fbSMasahiro Yamada return 1; 826*0a9064fbSMasahiro Yamada } 827*0a9064fbSMasahiro Yamada 828*0a9064fbSMasahiro Yamada conf_message(_("configuration written to %s"), newname); 829*0a9064fbSMasahiro Yamada 830*0a9064fbSMasahiro Yamada sym_set_change_count(0); 831*0a9064fbSMasahiro Yamada 832*0a9064fbSMasahiro Yamada return 0; 833*0a9064fbSMasahiro Yamada } 834*0a9064fbSMasahiro Yamada 835*0a9064fbSMasahiro Yamada static int conf_split_config(void) 836*0a9064fbSMasahiro Yamada { 837*0a9064fbSMasahiro Yamada const char *name; 838*0a9064fbSMasahiro Yamada char path[PATH_MAX+1]; 839*0a9064fbSMasahiro Yamada char *s, *d, c; 840*0a9064fbSMasahiro Yamada struct symbol *sym; 841*0a9064fbSMasahiro Yamada struct stat sb; 842*0a9064fbSMasahiro Yamada int res, i, fd; 843*0a9064fbSMasahiro Yamada 844*0a9064fbSMasahiro Yamada name = conf_get_autoconfig_name(); 845*0a9064fbSMasahiro Yamada conf_read_simple(name, S_DEF_AUTO); 846*0a9064fbSMasahiro Yamada 847*0a9064fbSMasahiro Yamada if (chdir("include/config")) 848*0a9064fbSMasahiro Yamada return 1; 849*0a9064fbSMasahiro Yamada 850*0a9064fbSMasahiro Yamada res = 0; 851*0a9064fbSMasahiro Yamada for_all_symbols(i, sym) { 852*0a9064fbSMasahiro Yamada sym_calc_value(sym); 853*0a9064fbSMasahiro Yamada if ((sym->flags & SYMBOL_AUTO) || !sym->name) 854*0a9064fbSMasahiro Yamada continue; 855*0a9064fbSMasahiro Yamada if (sym->flags & SYMBOL_WRITE) { 856*0a9064fbSMasahiro Yamada if (sym->flags & SYMBOL_DEF_AUTO) { 857*0a9064fbSMasahiro Yamada /* 858*0a9064fbSMasahiro Yamada * symbol has old and new value, 859*0a9064fbSMasahiro Yamada * so compare them... 860*0a9064fbSMasahiro Yamada */ 861*0a9064fbSMasahiro Yamada switch (sym->type) { 862*0a9064fbSMasahiro Yamada case S_BOOLEAN: 863*0a9064fbSMasahiro Yamada case S_TRISTATE: 864*0a9064fbSMasahiro Yamada if (sym_get_tristate_value(sym) == 865*0a9064fbSMasahiro Yamada sym->def[S_DEF_AUTO].tri) 866*0a9064fbSMasahiro Yamada continue; 867*0a9064fbSMasahiro Yamada break; 868*0a9064fbSMasahiro Yamada case S_STRING: 869*0a9064fbSMasahiro Yamada case S_HEX: 870*0a9064fbSMasahiro Yamada case S_INT: 871*0a9064fbSMasahiro Yamada if (!strcmp(sym_get_string_value(sym), 872*0a9064fbSMasahiro Yamada sym->def[S_DEF_AUTO].val)) 873*0a9064fbSMasahiro Yamada continue; 874*0a9064fbSMasahiro Yamada break; 875*0a9064fbSMasahiro Yamada default: 876*0a9064fbSMasahiro Yamada break; 877*0a9064fbSMasahiro Yamada } 878*0a9064fbSMasahiro Yamada } else { 879*0a9064fbSMasahiro Yamada /* 880*0a9064fbSMasahiro Yamada * If there is no old value, only 'no' (unset) 881*0a9064fbSMasahiro Yamada * is allowed as new value. 882*0a9064fbSMasahiro Yamada */ 883*0a9064fbSMasahiro Yamada switch (sym->type) { 884*0a9064fbSMasahiro Yamada case S_BOOLEAN: 885*0a9064fbSMasahiro Yamada case S_TRISTATE: 886*0a9064fbSMasahiro Yamada if (sym_get_tristate_value(sym) == no) 887*0a9064fbSMasahiro Yamada continue; 888*0a9064fbSMasahiro Yamada break; 889*0a9064fbSMasahiro Yamada default: 890*0a9064fbSMasahiro Yamada break; 891*0a9064fbSMasahiro Yamada } 892*0a9064fbSMasahiro Yamada } 893*0a9064fbSMasahiro Yamada } else if (!(sym->flags & SYMBOL_DEF_AUTO)) 894*0a9064fbSMasahiro Yamada /* There is neither an old nor a new value. */ 895*0a9064fbSMasahiro Yamada continue; 896*0a9064fbSMasahiro Yamada /* else 897*0a9064fbSMasahiro Yamada * There is an old value, but no new value ('no' (unset) 898*0a9064fbSMasahiro Yamada * isn't saved in auto.conf, so the old value is always 899*0a9064fbSMasahiro Yamada * different from 'no'). 900*0a9064fbSMasahiro Yamada */ 901*0a9064fbSMasahiro Yamada 902*0a9064fbSMasahiro Yamada /* Replace all '_' and append ".h" */ 903*0a9064fbSMasahiro Yamada s = sym->name; 904*0a9064fbSMasahiro Yamada d = path; 905*0a9064fbSMasahiro Yamada while ((c = *s++)) { 906*0a9064fbSMasahiro Yamada c = tolower(c); 907*0a9064fbSMasahiro Yamada *d++ = (c == '_') ? '/' : c; 908*0a9064fbSMasahiro Yamada } 909*0a9064fbSMasahiro Yamada strcpy(d, ".h"); 910*0a9064fbSMasahiro Yamada 911*0a9064fbSMasahiro Yamada /* Assume directory path already exists. */ 912*0a9064fbSMasahiro Yamada fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644); 913*0a9064fbSMasahiro Yamada if (fd == -1) { 914*0a9064fbSMasahiro Yamada if (errno != ENOENT) { 915*0a9064fbSMasahiro Yamada res = 1; 916*0a9064fbSMasahiro Yamada break; 917*0a9064fbSMasahiro Yamada } 918*0a9064fbSMasahiro Yamada /* 919*0a9064fbSMasahiro Yamada * Create directory components, 920*0a9064fbSMasahiro Yamada * unless they exist already. 921*0a9064fbSMasahiro Yamada */ 922*0a9064fbSMasahiro Yamada d = path; 923*0a9064fbSMasahiro Yamada while ((d = strchr(d, '/'))) { 924*0a9064fbSMasahiro Yamada *d = 0; 925*0a9064fbSMasahiro Yamada if (stat(path, &sb) && mkdir(path, 0755)) { 926*0a9064fbSMasahiro Yamada res = 1; 927*0a9064fbSMasahiro Yamada goto out; 928*0a9064fbSMasahiro Yamada } 929*0a9064fbSMasahiro Yamada *d++ = '/'; 930*0a9064fbSMasahiro Yamada } 931*0a9064fbSMasahiro Yamada /* Try it again. */ 932*0a9064fbSMasahiro Yamada fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644); 933*0a9064fbSMasahiro Yamada if (fd == -1) { 934*0a9064fbSMasahiro Yamada res = 1; 935*0a9064fbSMasahiro Yamada break; 936*0a9064fbSMasahiro Yamada } 937*0a9064fbSMasahiro Yamada } 938*0a9064fbSMasahiro Yamada close(fd); 939*0a9064fbSMasahiro Yamada } 940*0a9064fbSMasahiro Yamada out: 941*0a9064fbSMasahiro Yamada if (chdir("../..")) 942*0a9064fbSMasahiro Yamada return 1; 943*0a9064fbSMasahiro Yamada 944*0a9064fbSMasahiro Yamada return res; 945*0a9064fbSMasahiro Yamada } 946*0a9064fbSMasahiro Yamada 947*0a9064fbSMasahiro Yamada int conf_write_autoconf(void) 948*0a9064fbSMasahiro Yamada { 949*0a9064fbSMasahiro Yamada struct symbol *sym; 950*0a9064fbSMasahiro Yamada const char *name; 951*0a9064fbSMasahiro Yamada FILE *out, *tristate, *out_h; 952*0a9064fbSMasahiro Yamada int i; 953*0a9064fbSMasahiro Yamada 954*0a9064fbSMasahiro Yamada sym_clear_all_valid(); 955*0a9064fbSMasahiro Yamada 956*0a9064fbSMasahiro Yamada file_write_dep("include/config/auto.conf.cmd"); 957*0a9064fbSMasahiro Yamada 958*0a9064fbSMasahiro Yamada if (conf_split_config()) 959*0a9064fbSMasahiro Yamada return 1; 960*0a9064fbSMasahiro Yamada 961*0a9064fbSMasahiro Yamada out = fopen(".tmpconfig", "w"); 962*0a9064fbSMasahiro Yamada if (!out) 963*0a9064fbSMasahiro Yamada return 1; 964*0a9064fbSMasahiro Yamada 965*0a9064fbSMasahiro Yamada tristate = fopen(".tmpconfig_tristate", "w"); 966*0a9064fbSMasahiro Yamada if (!tristate) { 967*0a9064fbSMasahiro Yamada fclose(out); 968*0a9064fbSMasahiro Yamada return 1; 969*0a9064fbSMasahiro Yamada } 970*0a9064fbSMasahiro Yamada 971*0a9064fbSMasahiro Yamada out_h = fopen(".tmpconfig.h", "w"); 972*0a9064fbSMasahiro Yamada if (!out_h) { 973*0a9064fbSMasahiro Yamada fclose(out); 974*0a9064fbSMasahiro Yamada fclose(tristate); 975*0a9064fbSMasahiro Yamada return 1; 976*0a9064fbSMasahiro Yamada } 977*0a9064fbSMasahiro Yamada 978*0a9064fbSMasahiro Yamada conf_write_heading(out, &kconfig_printer_cb, NULL); 979*0a9064fbSMasahiro Yamada 980*0a9064fbSMasahiro Yamada conf_write_heading(tristate, &tristate_printer_cb, NULL); 981*0a9064fbSMasahiro Yamada 982*0a9064fbSMasahiro Yamada conf_write_heading(out_h, &header_printer_cb, NULL); 983*0a9064fbSMasahiro Yamada 984*0a9064fbSMasahiro Yamada for_all_symbols(i, sym) { 985*0a9064fbSMasahiro Yamada sym_calc_value(sym); 986*0a9064fbSMasahiro Yamada if (!(sym->flags & SYMBOL_WRITE) || !sym->name) 987*0a9064fbSMasahiro Yamada continue; 988*0a9064fbSMasahiro Yamada 989*0a9064fbSMasahiro Yamada /* write symbol to auto.conf, tristate and header files */ 990*0a9064fbSMasahiro Yamada conf_write_symbol(out, sym, &kconfig_printer_cb, (void *)1); 991*0a9064fbSMasahiro Yamada 992*0a9064fbSMasahiro Yamada conf_write_symbol(tristate, sym, &tristate_printer_cb, (void *)1); 993*0a9064fbSMasahiro Yamada 994*0a9064fbSMasahiro Yamada conf_write_symbol(out_h, sym, &header_printer_cb, NULL); 995*0a9064fbSMasahiro Yamada } 996*0a9064fbSMasahiro Yamada fclose(out); 997*0a9064fbSMasahiro Yamada fclose(tristate); 998*0a9064fbSMasahiro Yamada fclose(out_h); 999*0a9064fbSMasahiro Yamada 1000*0a9064fbSMasahiro Yamada name = getenv("KCONFIG_AUTOHEADER"); 1001*0a9064fbSMasahiro Yamada if (!name) 1002*0a9064fbSMasahiro Yamada name = "include/generated/autoconf.h"; 1003*0a9064fbSMasahiro Yamada if (rename(".tmpconfig.h", name)) 1004*0a9064fbSMasahiro Yamada return 1; 1005*0a9064fbSMasahiro Yamada name = getenv("KCONFIG_TRISTATE"); 1006*0a9064fbSMasahiro Yamada if (!name) 1007*0a9064fbSMasahiro Yamada name = "include/config/tristate.conf"; 1008*0a9064fbSMasahiro Yamada if (rename(".tmpconfig_tristate", name)) 1009*0a9064fbSMasahiro Yamada return 1; 1010*0a9064fbSMasahiro Yamada name = conf_get_autoconfig_name(); 1011*0a9064fbSMasahiro Yamada /* 1012*0a9064fbSMasahiro Yamada * This must be the last step, kbuild has a dependency on auto.conf 1013*0a9064fbSMasahiro Yamada * and this marks the successful completion of the previous steps. 1014*0a9064fbSMasahiro Yamada */ 1015*0a9064fbSMasahiro Yamada if (rename(".tmpconfig", name)) 1016*0a9064fbSMasahiro Yamada return 1; 1017*0a9064fbSMasahiro Yamada 1018*0a9064fbSMasahiro Yamada return 0; 1019*0a9064fbSMasahiro Yamada } 1020*0a9064fbSMasahiro Yamada 1021*0a9064fbSMasahiro Yamada static int sym_change_count; 1022*0a9064fbSMasahiro Yamada static void (*conf_changed_callback)(void); 1023*0a9064fbSMasahiro Yamada 1024*0a9064fbSMasahiro Yamada void sym_set_change_count(int count) 1025*0a9064fbSMasahiro Yamada { 1026*0a9064fbSMasahiro Yamada int _sym_change_count = sym_change_count; 1027*0a9064fbSMasahiro Yamada sym_change_count = count; 1028*0a9064fbSMasahiro Yamada if (conf_changed_callback && 1029*0a9064fbSMasahiro Yamada (bool)_sym_change_count != (bool)count) 1030*0a9064fbSMasahiro Yamada conf_changed_callback(); 1031*0a9064fbSMasahiro Yamada } 1032*0a9064fbSMasahiro Yamada 1033*0a9064fbSMasahiro Yamada void sym_add_change_count(int count) 1034*0a9064fbSMasahiro Yamada { 1035*0a9064fbSMasahiro Yamada sym_set_change_count(count + sym_change_count); 1036*0a9064fbSMasahiro Yamada } 1037*0a9064fbSMasahiro Yamada 1038*0a9064fbSMasahiro Yamada bool conf_get_changed(void) 1039*0a9064fbSMasahiro Yamada { 1040*0a9064fbSMasahiro Yamada return sym_change_count; 1041*0a9064fbSMasahiro Yamada } 1042*0a9064fbSMasahiro Yamada 1043*0a9064fbSMasahiro Yamada void conf_set_changed_callback(void (*fn)(void)) 1044*0a9064fbSMasahiro Yamada { 1045*0a9064fbSMasahiro Yamada conf_changed_callback = fn; 1046*0a9064fbSMasahiro Yamada } 1047*0a9064fbSMasahiro Yamada 1048*0a9064fbSMasahiro Yamada static bool randomize_choice_values(struct symbol *csym) 1049*0a9064fbSMasahiro Yamada { 1050*0a9064fbSMasahiro Yamada struct property *prop; 1051*0a9064fbSMasahiro Yamada struct symbol *sym; 1052*0a9064fbSMasahiro Yamada struct expr *e; 1053*0a9064fbSMasahiro Yamada int cnt, def; 1054*0a9064fbSMasahiro Yamada 1055*0a9064fbSMasahiro Yamada /* 1056*0a9064fbSMasahiro Yamada * If choice is mod then we may have more items selected 1057*0a9064fbSMasahiro Yamada * and if no then no-one. 1058*0a9064fbSMasahiro Yamada * In both cases stop. 1059*0a9064fbSMasahiro Yamada */ 1060*0a9064fbSMasahiro Yamada if (csym->curr.tri != yes) 1061*0a9064fbSMasahiro Yamada return false; 1062*0a9064fbSMasahiro Yamada 1063*0a9064fbSMasahiro Yamada prop = sym_get_choice_prop(csym); 1064*0a9064fbSMasahiro Yamada 1065*0a9064fbSMasahiro Yamada /* count entries in choice block */ 1066*0a9064fbSMasahiro Yamada cnt = 0; 1067*0a9064fbSMasahiro Yamada expr_list_for_each_sym(prop->expr, e, sym) 1068*0a9064fbSMasahiro Yamada cnt++; 1069*0a9064fbSMasahiro Yamada 1070*0a9064fbSMasahiro Yamada /* 1071*0a9064fbSMasahiro Yamada * find a random value and set it to yes, 1072*0a9064fbSMasahiro Yamada * set the rest to no so we have only one set 1073*0a9064fbSMasahiro Yamada */ 1074*0a9064fbSMasahiro Yamada def = (rand() % cnt); 1075*0a9064fbSMasahiro Yamada 1076*0a9064fbSMasahiro Yamada cnt = 0; 1077*0a9064fbSMasahiro Yamada expr_list_for_each_sym(prop->expr, e, sym) { 1078*0a9064fbSMasahiro Yamada if (def == cnt++) { 1079*0a9064fbSMasahiro Yamada sym->def[S_DEF_USER].tri = yes; 1080*0a9064fbSMasahiro Yamada csym->def[S_DEF_USER].val = sym; 1081*0a9064fbSMasahiro Yamada } 1082*0a9064fbSMasahiro Yamada else { 1083*0a9064fbSMasahiro Yamada sym->def[S_DEF_USER].tri = no; 1084*0a9064fbSMasahiro Yamada } 1085*0a9064fbSMasahiro Yamada sym->flags |= SYMBOL_DEF_USER; 1086*0a9064fbSMasahiro Yamada /* clear VALID to get value calculated */ 1087*0a9064fbSMasahiro Yamada sym->flags &= ~SYMBOL_VALID; 1088*0a9064fbSMasahiro Yamada } 1089*0a9064fbSMasahiro Yamada csym->flags |= SYMBOL_DEF_USER; 1090*0a9064fbSMasahiro Yamada /* clear VALID to get value calculated */ 1091*0a9064fbSMasahiro Yamada csym->flags &= ~(SYMBOL_VALID); 1092*0a9064fbSMasahiro Yamada 1093*0a9064fbSMasahiro Yamada return true; 1094*0a9064fbSMasahiro Yamada } 1095*0a9064fbSMasahiro Yamada 1096*0a9064fbSMasahiro Yamada void set_all_choice_values(struct symbol *csym) 1097*0a9064fbSMasahiro Yamada { 1098*0a9064fbSMasahiro Yamada struct property *prop; 1099*0a9064fbSMasahiro Yamada struct symbol *sym; 1100*0a9064fbSMasahiro Yamada struct expr *e; 1101*0a9064fbSMasahiro Yamada 1102*0a9064fbSMasahiro Yamada prop = sym_get_choice_prop(csym); 1103*0a9064fbSMasahiro Yamada 1104*0a9064fbSMasahiro Yamada /* 1105*0a9064fbSMasahiro Yamada * Set all non-assinged choice values to no 1106*0a9064fbSMasahiro Yamada */ 1107*0a9064fbSMasahiro Yamada expr_list_for_each_sym(prop->expr, e, sym) { 1108*0a9064fbSMasahiro Yamada if (!sym_has_value(sym)) 1109*0a9064fbSMasahiro Yamada sym->def[S_DEF_USER].tri = no; 1110*0a9064fbSMasahiro Yamada } 1111*0a9064fbSMasahiro Yamada csym->flags |= SYMBOL_DEF_USER; 1112*0a9064fbSMasahiro Yamada /* clear VALID to get value calculated */ 1113*0a9064fbSMasahiro Yamada csym->flags &= ~(SYMBOL_VALID | SYMBOL_NEED_SET_CHOICE_VALUES); 1114*0a9064fbSMasahiro Yamada } 1115*0a9064fbSMasahiro Yamada 1116*0a9064fbSMasahiro Yamada bool conf_set_all_new_symbols(enum conf_def_mode mode) 1117*0a9064fbSMasahiro Yamada { 1118*0a9064fbSMasahiro Yamada struct symbol *sym, *csym; 1119*0a9064fbSMasahiro Yamada int i, cnt, pby, pty, ptm; /* pby: probability of boolean = y 1120*0a9064fbSMasahiro Yamada * pty: probability of tristate = y 1121*0a9064fbSMasahiro Yamada * ptm: probability of tristate = m 1122*0a9064fbSMasahiro Yamada */ 1123*0a9064fbSMasahiro Yamada 1124*0a9064fbSMasahiro Yamada pby = 50; pty = ptm = 33; /* can't go as the default in switch-case 1125*0a9064fbSMasahiro Yamada * below, otherwise gcc whines about 1126*0a9064fbSMasahiro Yamada * -Wmaybe-uninitialized */ 1127*0a9064fbSMasahiro Yamada if (mode == def_random) { 1128*0a9064fbSMasahiro Yamada int n, p[3]; 1129*0a9064fbSMasahiro Yamada char *env = getenv("KCONFIG_PROBABILITY"); 1130*0a9064fbSMasahiro Yamada n = 0; 1131*0a9064fbSMasahiro Yamada while( env && *env ) { 1132*0a9064fbSMasahiro Yamada char *endp; 1133*0a9064fbSMasahiro Yamada int tmp = strtol( env, &endp, 10 ); 1134*0a9064fbSMasahiro Yamada if( tmp >= 0 && tmp <= 100 ) { 1135*0a9064fbSMasahiro Yamada p[n++] = tmp; 1136*0a9064fbSMasahiro Yamada } else { 1137*0a9064fbSMasahiro Yamada errno = ERANGE; 1138*0a9064fbSMasahiro Yamada perror( "KCONFIG_PROBABILITY" ); 1139*0a9064fbSMasahiro Yamada exit( 1 ); 1140*0a9064fbSMasahiro Yamada } 1141*0a9064fbSMasahiro Yamada env = (*endp == ':') ? endp+1 : endp; 1142*0a9064fbSMasahiro Yamada if( n >=3 ) { 1143*0a9064fbSMasahiro Yamada break; 1144*0a9064fbSMasahiro Yamada } 1145*0a9064fbSMasahiro Yamada } 1146*0a9064fbSMasahiro Yamada switch( n ) { 1147*0a9064fbSMasahiro Yamada case 1: 1148*0a9064fbSMasahiro Yamada pby = p[0]; ptm = pby/2; pty = pby-ptm; 1149*0a9064fbSMasahiro Yamada break; 1150*0a9064fbSMasahiro Yamada case 2: 1151*0a9064fbSMasahiro Yamada pty = p[0]; ptm = p[1]; pby = pty + ptm; 1152*0a9064fbSMasahiro Yamada break; 1153*0a9064fbSMasahiro Yamada case 3: 1154*0a9064fbSMasahiro Yamada pby = p[0]; pty = p[1]; ptm = p[2]; 1155*0a9064fbSMasahiro Yamada break; 1156*0a9064fbSMasahiro Yamada } 1157*0a9064fbSMasahiro Yamada 1158*0a9064fbSMasahiro Yamada if( pty+ptm > 100 ) { 1159*0a9064fbSMasahiro Yamada errno = ERANGE; 1160*0a9064fbSMasahiro Yamada perror( "KCONFIG_PROBABILITY" ); 1161*0a9064fbSMasahiro Yamada exit( 1 ); 1162*0a9064fbSMasahiro Yamada } 1163*0a9064fbSMasahiro Yamada } 1164*0a9064fbSMasahiro Yamada bool has_changed = false; 1165*0a9064fbSMasahiro Yamada 1166*0a9064fbSMasahiro Yamada for_all_symbols(i, sym) { 1167*0a9064fbSMasahiro Yamada if (sym_has_value(sym) || (sym->flags & SYMBOL_VALID)) 1168*0a9064fbSMasahiro Yamada continue; 1169*0a9064fbSMasahiro Yamada switch (sym_get_type(sym)) { 1170*0a9064fbSMasahiro Yamada case S_BOOLEAN: 1171*0a9064fbSMasahiro Yamada case S_TRISTATE: 1172*0a9064fbSMasahiro Yamada has_changed = true; 1173*0a9064fbSMasahiro Yamada switch (mode) { 1174*0a9064fbSMasahiro Yamada case def_yes: 1175*0a9064fbSMasahiro Yamada sym->def[S_DEF_USER].tri = yes; 1176*0a9064fbSMasahiro Yamada break; 1177*0a9064fbSMasahiro Yamada case def_mod: 1178*0a9064fbSMasahiro Yamada sym->def[S_DEF_USER].tri = mod; 1179*0a9064fbSMasahiro Yamada break; 1180*0a9064fbSMasahiro Yamada case def_no: 1181*0a9064fbSMasahiro Yamada if (sym->flags & SYMBOL_ALLNOCONFIG_Y) 1182*0a9064fbSMasahiro Yamada sym->def[S_DEF_USER].tri = yes; 1183*0a9064fbSMasahiro Yamada else 1184*0a9064fbSMasahiro Yamada sym->def[S_DEF_USER].tri = no; 1185*0a9064fbSMasahiro Yamada break; 1186*0a9064fbSMasahiro Yamada case def_random: 1187*0a9064fbSMasahiro Yamada sym->def[S_DEF_USER].tri = no; 1188*0a9064fbSMasahiro Yamada cnt = rand() % 100; 1189*0a9064fbSMasahiro Yamada if (sym->type == S_TRISTATE) { 1190*0a9064fbSMasahiro Yamada if (cnt < pty) 1191*0a9064fbSMasahiro Yamada sym->def[S_DEF_USER].tri = yes; 1192*0a9064fbSMasahiro Yamada else if (cnt < (pty+ptm)) 1193*0a9064fbSMasahiro Yamada sym->def[S_DEF_USER].tri = mod; 1194*0a9064fbSMasahiro Yamada } else if (cnt < pby) 1195*0a9064fbSMasahiro Yamada sym->def[S_DEF_USER].tri = yes; 1196*0a9064fbSMasahiro Yamada break; 1197*0a9064fbSMasahiro Yamada default: 1198*0a9064fbSMasahiro Yamada continue; 1199*0a9064fbSMasahiro Yamada } 1200*0a9064fbSMasahiro Yamada if (!(sym_is_choice(sym) && mode == def_random)) 1201*0a9064fbSMasahiro Yamada sym->flags |= SYMBOL_DEF_USER; 1202*0a9064fbSMasahiro Yamada break; 1203*0a9064fbSMasahiro Yamada default: 1204*0a9064fbSMasahiro Yamada break; 1205*0a9064fbSMasahiro Yamada } 1206*0a9064fbSMasahiro Yamada 1207*0a9064fbSMasahiro Yamada } 1208*0a9064fbSMasahiro Yamada 1209*0a9064fbSMasahiro Yamada sym_clear_all_valid(); 1210*0a9064fbSMasahiro Yamada 1211*0a9064fbSMasahiro Yamada /* 1212*0a9064fbSMasahiro Yamada * We have different type of choice blocks. 1213*0a9064fbSMasahiro Yamada * If curr.tri equals to mod then we can select several 1214*0a9064fbSMasahiro Yamada * choice symbols in one block. 1215*0a9064fbSMasahiro Yamada * In this case we do nothing. 1216*0a9064fbSMasahiro Yamada * If curr.tri equals yes then only one symbol can be 1217*0a9064fbSMasahiro Yamada * selected in a choice block and we set it to yes, 1218*0a9064fbSMasahiro Yamada * and the rest to no. 1219*0a9064fbSMasahiro Yamada */ 1220*0a9064fbSMasahiro Yamada if (mode != def_random) { 1221*0a9064fbSMasahiro Yamada for_all_symbols(i, csym) { 1222*0a9064fbSMasahiro Yamada if ((sym_is_choice(csym) && !sym_has_value(csym)) || 1223*0a9064fbSMasahiro Yamada sym_is_choice_value(csym)) 1224*0a9064fbSMasahiro Yamada csym->flags |= SYMBOL_NEED_SET_CHOICE_VALUES; 1225*0a9064fbSMasahiro Yamada } 1226*0a9064fbSMasahiro Yamada } 1227*0a9064fbSMasahiro Yamada 1228*0a9064fbSMasahiro Yamada for_all_symbols(i, csym) { 1229*0a9064fbSMasahiro Yamada if (sym_has_value(csym) || !sym_is_choice(csym)) 1230*0a9064fbSMasahiro Yamada continue; 1231*0a9064fbSMasahiro Yamada 1232*0a9064fbSMasahiro Yamada sym_calc_value(csym); 1233*0a9064fbSMasahiro Yamada if (mode == def_random) 1234*0a9064fbSMasahiro Yamada has_changed = randomize_choice_values(csym); 1235*0a9064fbSMasahiro Yamada else { 1236*0a9064fbSMasahiro Yamada set_all_choice_values(csym); 1237*0a9064fbSMasahiro Yamada has_changed = true; 1238*0a9064fbSMasahiro Yamada } 1239*0a9064fbSMasahiro Yamada } 1240*0a9064fbSMasahiro Yamada 1241*0a9064fbSMasahiro Yamada return has_changed; 1242*0a9064fbSMasahiro Yamada } 1243