10a9064fbSMasahiro Yamada /* 20a9064fbSMasahiro Yamada * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> 30a9064fbSMasahiro Yamada * Released under the terms of the GNU GPL v2.0. 40a9064fbSMasahiro Yamada */ 50a9064fbSMasahiro Yamada 60a9064fbSMasahiro Yamada #include <sys/stat.h> 70a9064fbSMasahiro Yamada #include <ctype.h> 80a9064fbSMasahiro Yamada #include <errno.h> 90a9064fbSMasahiro Yamada #include <fcntl.h> 100a9064fbSMasahiro Yamada #include <stdarg.h> 110a9064fbSMasahiro Yamada #include <stdio.h> 120a9064fbSMasahiro Yamada #include <stdlib.h> 130a9064fbSMasahiro Yamada #include <string.h> 140a9064fbSMasahiro Yamada #include <time.h> 150a9064fbSMasahiro Yamada #include <unistd.h> 160a9064fbSMasahiro Yamada 170a9064fbSMasahiro Yamada #include "lkc.h" 180a9064fbSMasahiro Yamada 190a9064fbSMasahiro Yamada static void conf_warning(const char *fmt, ...) 200a9064fbSMasahiro Yamada __attribute__ ((format (printf, 1, 2))); 210a9064fbSMasahiro Yamada 220a9064fbSMasahiro Yamada static void conf_message(const char *fmt, ...) 230a9064fbSMasahiro Yamada __attribute__ ((format (printf, 1, 2))); 240a9064fbSMasahiro Yamada 250a9064fbSMasahiro Yamada static const char *conf_filename; 260a9064fbSMasahiro Yamada static int conf_lineno, conf_warnings, conf_unsaved; 270a9064fbSMasahiro Yamada 280a9064fbSMasahiro Yamada const char conf_defname[] = "arch/$ARCH/defconfig"; 290a9064fbSMasahiro Yamada 300a9064fbSMasahiro Yamada static void conf_warning(const char *fmt, ...) 310a9064fbSMasahiro Yamada { 320a9064fbSMasahiro Yamada va_list ap; 330a9064fbSMasahiro Yamada va_start(ap, fmt); 340a9064fbSMasahiro Yamada fprintf(stderr, "%s:%d:warning: ", conf_filename, conf_lineno); 350a9064fbSMasahiro Yamada vfprintf(stderr, fmt, ap); 360a9064fbSMasahiro Yamada fprintf(stderr, "\n"); 370a9064fbSMasahiro Yamada va_end(ap); 380a9064fbSMasahiro Yamada conf_warnings++; 390a9064fbSMasahiro Yamada } 400a9064fbSMasahiro Yamada 410a9064fbSMasahiro Yamada static void conf_default_message_callback(const char *fmt, va_list ap) 420a9064fbSMasahiro Yamada { 430a9064fbSMasahiro Yamada printf("#\n# "); 440a9064fbSMasahiro Yamada vprintf(fmt, ap); 450a9064fbSMasahiro Yamada printf("\n#\n"); 460a9064fbSMasahiro Yamada } 470a9064fbSMasahiro Yamada 480a9064fbSMasahiro Yamada static void (*conf_message_callback) (const char *fmt, va_list ap) = 490a9064fbSMasahiro Yamada conf_default_message_callback; 500a9064fbSMasahiro Yamada void conf_set_message_callback(void (*fn) (const char *fmt, va_list ap)) 510a9064fbSMasahiro Yamada { 520a9064fbSMasahiro Yamada conf_message_callback = fn; 530a9064fbSMasahiro Yamada } 540a9064fbSMasahiro Yamada 550a9064fbSMasahiro Yamada static void conf_message(const char *fmt, ...) 560a9064fbSMasahiro Yamada { 570a9064fbSMasahiro Yamada va_list ap; 580a9064fbSMasahiro Yamada 590a9064fbSMasahiro Yamada va_start(ap, fmt); 600a9064fbSMasahiro Yamada if (conf_message_callback) 610a9064fbSMasahiro Yamada conf_message_callback(fmt, ap); 620a9064fbSMasahiro Yamada } 630a9064fbSMasahiro Yamada 640a9064fbSMasahiro Yamada const char *conf_get_configname(void) 650a9064fbSMasahiro Yamada { 660a9064fbSMasahiro Yamada char *name = getenv("KCONFIG_CONFIG"); 670a9064fbSMasahiro Yamada 680a9064fbSMasahiro Yamada return name ? name : ".config"; 690a9064fbSMasahiro Yamada } 700a9064fbSMasahiro Yamada 710a9064fbSMasahiro Yamada const char *conf_get_autoconfig_name(void) 720a9064fbSMasahiro Yamada { 730a9064fbSMasahiro Yamada char *name = getenv("KCONFIG_AUTOCONFIG"); 740a9064fbSMasahiro Yamada 750a9064fbSMasahiro Yamada return name ? name : "include/config/auto.conf"; 760a9064fbSMasahiro Yamada } 770a9064fbSMasahiro Yamada 780a9064fbSMasahiro Yamada static char *conf_expand_value(const char *in) 790a9064fbSMasahiro Yamada { 800a9064fbSMasahiro Yamada struct symbol *sym; 810a9064fbSMasahiro Yamada const char *src; 820a9064fbSMasahiro Yamada static char res_value[SYMBOL_MAXLENGTH]; 830a9064fbSMasahiro Yamada char *dst, name[SYMBOL_MAXLENGTH]; 840a9064fbSMasahiro Yamada 850a9064fbSMasahiro Yamada res_value[0] = 0; 860a9064fbSMasahiro Yamada dst = name; 870a9064fbSMasahiro Yamada while ((src = strchr(in, '$'))) { 880a9064fbSMasahiro Yamada strncat(res_value, in, src - in); 890a9064fbSMasahiro Yamada src++; 900a9064fbSMasahiro Yamada dst = name; 910a9064fbSMasahiro Yamada while (isalnum(*src) || *src == '_') 920a9064fbSMasahiro Yamada *dst++ = *src++; 930a9064fbSMasahiro Yamada *dst = 0; 940a9064fbSMasahiro Yamada sym = sym_lookup(name, 0); 950a9064fbSMasahiro Yamada sym_calc_value(sym); 960a9064fbSMasahiro Yamada strcat(res_value, sym_get_string_value(sym)); 970a9064fbSMasahiro Yamada in = src; 980a9064fbSMasahiro Yamada } 990a9064fbSMasahiro Yamada strcat(res_value, in); 1000a9064fbSMasahiro Yamada 1010a9064fbSMasahiro Yamada return res_value; 1020a9064fbSMasahiro Yamada } 1030a9064fbSMasahiro Yamada 1040a9064fbSMasahiro Yamada char *conf_get_default_confname(void) 1050a9064fbSMasahiro Yamada { 1060a9064fbSMasahiro Yamada struct stat buf; 1070a9064fbSMasahiro Yamada static char fullname[PATH_MAX+1]; 1080a9064fbSMasahiro Yamada char *env, *name; 1090a9064fbSMasahiro Yamada 1100a9064fbSMasahiro Yamada name = conf_expand_value(conf_defname); 1110a9064fbSMasahiro Yamada env = getenv(SRCTREE); 1120a9064fbSMasahiro Yamada if (env) { 1130a9064fbSMasahiro Yamada sprintf(fullname, "%s/%s", env, name); 1140a9064fbSMasahiro Yamada if (!stat(fullname, &buf)) 1150a9064fbSMasahiro Yamada return fullname; 1160a9064fbSMasahiro Yamada } 1170a9064fbSMasahiro Yamada return name; 1180a9064fbSMasahiro Yamada } 1190a9064fbSMasahiro Yamada 1200a9064fbSMasahiro Yamada static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p) 1210a9064fbSMasahiro Yamada { 1220a9064fbSMasahiro Yamada char *p2; 1230a9064fbSMasahiro Yamada 1240a9064fbSMasahiro Yamada switch (sym->type) { 1250a9064fbSMasahiro Yamada case S_TRISTATE: 1260a9064fbSMasahiro Yamada if (p[0] == 'm') { 1270a9064fbSMasahiro Yamada sym->def[def].tri = mod; 1280a9064fbSMasahiro Yamada sym->flags |= def_flags; 1290a9064fbSMasahiro Yamada break; 1300a9064fbSMasahiro Yamada } 1310a9064fbSMasahiro Yamada /* fall through */ 1320a9064fbSMasahiro Yamada case S_BOOLEAN: 1330a9064fbSMasahiro Yamada if (p[0] == 'y') { 1340a9064fbSMasahiro Yamada sym->def[def].tri = yes; 1350a9064fbSMasahiro Yamada sym->flags |= def_flags; 1360a9064fbSMasahiro Yamada break; 1370a9064fbSMasahiro Yamada } 1380a9064fbSMasahiro Yamada if (p[0] == 'n') { 1390a9064fbSMasahiro Yamada sym->def[def].tri = no; 1400a9064fbSMasahiro Yamada sym->flags |= def_flags; 1410a9064fbSMasahiro Yamada break; 1420a9064fbSMasahiro Yamada } 1430a9064fbSMasahiro Yamada if (def != S_DEF_AUTO) 1440a9064fbSMasahiro Yamada conf_warning("symbol value '%s' invalid for %s", 1450a9064fbSMasahiro Yamada p, sym->name); 1460a9064fbSMasahiro Yamada return 1; 1470a9064fbSMasahiro Yamada case S_OTHER: 1480a9064fbSMasahiro Yamada if (*p != '"') { 1490a9064fbSMasahiro Yamada for (p2 = p; *p2 && !isspace(*p2); p2++) 1500a9064fbSMasahiro Yamada ; 1510a9064fbSMasahiro Yamada sym->type = S_STRING; 1520a9064fbSMasahiro Yamada goto done; 1530a9064fbSMasahiro Yamada } 1540a9064fbSMasahiro Yamada /* fall through */ 1550a9064fbSMasahiro Yamada case S_STRING: 1560a9064fbSMasahiro Yamada if (*p++ != '"') 1570a9064fbSMasahiro Yamada break; 158*20c20826SStefan Roese /* Last char has to be a '"' */ 159*20c20826SStefan Roese if (p[strlen(p) - 1] != '"') { 1600a9064fbSMasahiro Yamada if (def != S_DEF_AUTO) 1610a9064fbSMasahiro Yamada conf_warning("invalid string found"); 1620a9064fbSMasahiro Yamada return 1; 1630a9064fbSMasahiro Yamada } 164*20c20826SStefan Roese /* Overwrite '"' with \0 for string termination */ 165*20c20826SStefan Roese p[strlen(p) - 1] = 0; 1660a9064fbSMasahiro Yamada /* fall through */ 1670a9064fbSMasahiro Yamada case S_INT: 1680a9064fbSMasahiro Yamada case S_HEX: 1690a9064fbSMasahiro Yamada done: 1700a9064fbSMasahiro Yamada if (sym_string_valid(sym, p)) { 1710a9064fbSMasahiro Yamada sym->def[def].val = strdup(p); 1720a9064fbSMasahiro Yamada sym->flags |= def_flags; 1730a9064fbSMasahiro Yamada } else { 1740a9064fbSMasahiro Yamada if (def != S_DEF_AUTO) 1750a9064fbSMasahiro Yamada conf_warning("symbol value '%s' invalid for %s", 1760a9064fbSMasahiro Yamada p, sym->name); 1770a9064fbSMasahiro Yamada return 1; 1780a9064fbSMasahiro Yamada } 1790a9064fbSMasahiro Yamada break; 1800a9064fbSMasahiro Yamada default: 1810a9064fbSMasahiro Yamada ; 1820a9064fbSMasahiro Yamada } 1830a9064fbSMasahiro Yamada return 0; 1840a9064fbSMasahiro Yamada } 1850a9064fbSMasahiro Yamada 1860a9064fbSMasahiro Yamada #define LINE_GROWTH 16 1870a9064fbSMasahiro Yamada static int add_byte(int c, char **lineptr, size_t slen, size_t *n) 1880a9064fbSMasahiro Yamada { 1890a9064fbSMasahiro Yamada char *nline; 1900a9064fbSMasahiro Yamada size_t new_size = slen + 1; 1910a9064fbSMasahiro Yamada if (new_size > *n) { 1920a9064fbSMasahiro Yamada new_size += LINE_GROWTH - 1; 1930a9064fbSMasahiro Yamada new_size *= 2; 1940a9064fbSMasahiro Yamada nline = realloc(*lineptr, new_size); 1950a9064fbSMasahiro Yamada if (!nline) 1960a9064fbSMasahiro Yamada return -1; 1970a9064fbSMasahiro Yamada 1980a9064fbSMasahiro Yamada *lineptr = nline; 1990a9064fbSMasahiro Yamada *n = new_size; 2000a9064fbSMasahiro Yamada } 2010a9064fbSMasahiro Yamada 2020a9064fbSMasahiro Yamada (*lineptr)[slen] = c; 2030a9064fbSMasahiro Yamada 2040a9064fbSMasahiro Yamada return 0; 2050a9064fbSMasahiro Yamada } 2060a9064fbSMasahiro Yamada 2070a9064fbSMasahiro Yamada static ssize_t compat_getline(char **lineptr, size_t *n, FILE *stream) 2080a9064fbSMasahiro Yamada { 2090a9064fbSMasahiro Yamada char *line = *lineptr; 2100a9064fbSMasahiro Yamada size_t slen = 0; 2110a9064fbSMasahiro Yamada 2120a9064fbSMasahiro Yamada for (;;) { 2130a9064fbSMasahiro Yamada int c = getc(stream); 2140a9064fbSMasahiro Yamada 2150a9064fbSMasahiro Yamada switch (c) { 2160a9064fbSMasahiro Yamada case '\n': 2170a9064fbSMasahiro Yamada if (add_byte(c, &line, slen, n) < 0) 2180a9064fbSMasahiro Yamada goto e_out; 2190a9064fbSMasahiro Yamada slen++; 2200a9064fbSMasahiro Yamada /* fall through */ 2210a9064fbSMasahiro Yamada case EOF: 2220a9064fbSMasahiro Yamada if (add_byte('\0', &line, slen, n) < 0) 2230a9064fbSMasahiro Yamada goto e_out; 2240a9064fbSMasahiro Yamada *lineptr = line; 2250a9064fbSMasahiro Yamada if (slen == 0) 2260a9064fbSMasahiro Yamada return -1; 2270a9064fbSMasahiro Yamada return slen; 2280a9064fbSMasahiro Yamada default: 2290a9064fbSMasahiro Yamada if (add_byte(c, &line, slen, n) < 0) 2300a9064fbSMasahiro Yamada goto e_out; 2310a9064fbSMasahiro Yamada slen++; 2320a9064fbSMasahiro Yamada } 2330a9064fbSMasahiro Yamada } 2340a9064fbSMasahiro Yamada 2350a9064fbSMasahiro Yamada e_out: 2360a9064fbSMasahiro Yamada line[slen-1] = '\0'; 2370a9064fbSMasahiro Yamada *lineptr = line; 2380a9064fbSMasahiro Yamada return -1; 2390a9064fbSMasahiro Yamada } 2400a9064fbSMasahiro Yamada 2410a9064fbSMasahiro Yamada int conf_read_simple(const char *name, int def) 2420a9064fbSMasahiro Yamada { 2430a9064fbSMasahiro Yamada FILE *in = NULL; 2440a9064fbSMasahiro Yamada char *line = NULL; 2450a9064fbSMasahiro Yamada size_t line_asize = 0; 2460a9064fbSMasahiro Yamada char *p, *p2; 2470a9064fbSMasahiro Yamada struct symbol *sym; 2480a9064fbSMasahiro Yamada int i, def_flags; 2490a9064fbSMasahiro Yamada 2500a9064fbSMasahiro Yamada if (name) { 2510a9064fbSMasahiro Yamada in = zconf_fopen(name); 2520a9064fbSMasahiro Yamada } else { 2530a9064fbSMasahiro Yamada struct property *prop; 2540a9064fbSMasahiro Yamada 2550a9064fbSMasahiro Yamada name = conf_get_configname(); 2560a9064fbSMasahiro Yamada in = zconf_fopen(name); 2570a9064fbSMasahiro Yamada if (in) 2580a9064fbSMasahiro Yamada goto load; 2590a9064fbSMasahiro Yamada sym_add_change_count(1); 2600a9064fbSMasahiro Yamada if (!sym_defconfig_list) { 2610a9064fbSMasahiro Yamada if (modules_sym) 2620a9064fbSMasahiro Yamada sym_calc_value(modules_sym); 2630a9064fbSMasahiro Yamada return 1; 2640a9064fbSMasahiro Yamada } 2650a9064fbSMasahiro Yamada 2660a9064fbSMasahiro Yamada for_all_defaults(sym_defconfig_list, prop) { 2670a9064fbSMasahiro Yamada if (expr_calc_value(prop->visible.expr) == no || 2680a9064fbSMasahiro Yamada prop->expr->type != E_SYMBOL) 2690a9064fbSMasahiro Yamada continue; 2700a9064fbSMasahiro Yamada name = conf_expand_value(prop->expr->left.sym->name); 2710a9064fbSMasahiro Yamada in = zconf_fopen(name); 2720a9064fbSMasahiro Yamada if (in) { 2730a9064fbSMasahiro Yamada conf_message(_("using defaults found in %s"), 2740a9064fbSMasahiro Yamada name); 2750a9064fbSMasahiro Yamada goto load; 2760a9064fbSMasahiro Yamada } 2770a9064fbSMasahiro Yamada } 2780a9064fbSMasahiro Yamada } 2790a9064fbSMasahiro Yamada if (!in) 2800a9064fbSMasahiro Yamada return 1; 2810a9064fbSMasahiro Yamada 2820a9064fbSMasahiro Yamada load: 2830a9064fbSMasahiro Yamada conf_filename = name; 2840a9064fbSMasahiro Yamada conf_lineno = 0; 2850a9064fbSMasahiro Yamada conf_warnings = 0; 2860a9064fbSMasahiro Yamada conf_unsaved = 0; 2870a9064fbSMasahiro Yamada 2880a9064fbSMasahiro Yamada def_flags = SYMBOL_DEF << def; 2890a9064fbSMasahiro Yamada for_all_symbols(i, sym) { 2900a9064fbSMasahiro Yamada sym->flags |= SYMBOL_CHANGED; 2910a9064fbSMasahiro Yamada sym->flags &= ~(def_flags|SYMBOL_VALID); 2920a9064fbSMasahiro Yamada if (sym_is_choice(sym)) 2930a9064fbSMasahiro Yamada sym->flags |= def_flags; 2940a9064fbSMasahiro Yamada switch (sym->type) { 2950a9064fbSMasahiro Yamada case S_INT: 2960a9064fbSMasahiro Yamada case S_HEX: 2970a9064fbSMasahiro Yamada case S_STRING: 2980a9064fbSMasahiro Yamada if (sym->def[def].val) 2990a9064fbSMasahiro Yamada free(sym->def[def].val); 3000a9064fbSMasahiro Yamada /* fall through */ 3010a9064fbSMasahiro Yamada default: 3020a9064fbSMasahiro Yamada sym->def[def].val = NULL; 3030a9064fbSMasahiro Yamada sym->def[def].tri = no; 3040a9064fbSMasahiro Yamada } 3050a9064fbSMasahiro Yamada } 3060a9064fbSMasahiro Yamada 3070a9064fbSMasahiro Yamada while (compat_getline(&line, &line_asize, in) != -1) { 3080a9064fbSMasahiro Yamada conf_lineno++; 3090a9064fbSMasahiro Yamada sym = NULL; 3100a9064fbSMasahiro Yamada if (line[0] == '#') { 3110a9064fbSMasahiro Yamada if (memcmp(line + 2, CONFIG_, strlen(CONFIG_))) 3120a9064fbSMasahiro Yamada continue; 3130a9064fbSMasahiro Yamada p = strchr(line + 2 + strlen(CONFIG_), ' '); 3140a9064fbSMasahiro Yamada if (!p) 3150a9064fbSMasahiro Yamada continue; 3160a9064fbSMasahiro Yamada *p++ = 0; 3170a9064fbSMasahiro Yamada if (strncmp(p, "is not set", 10)) 3180a9064fbSMasahiro Yamada continue; 3190a9064fbSMasahiro Yamada if (def == S_DEF_USER) { 3200a9064fbSMasahiro Yamada sym = sym_find(line + 2 + strlen(CONFIG_)); 3210a9064fbSMasahiro Yamada if (!sym) { 3220a9064fbSMasahiro Yamada sym_add_change_count(1); 3230a9064fbSMasahiro Yamada goto setsym; 3240a9064fbSMasahiro Yamada } 3250a9064fbSMasahiro Yamada } else { 3260a9064fbSMasahiro Yamada sym = sym_lookup(line + 2 + strlen(CONFIG_), 0); 3270a9064fbSMasahiro Yamada if (sym->type == S_UNKNOWN) 3280a9064fbSMasahiro Yamada sym->type = S_BOOLEAN; 3290a9064fbSMasahiro Yamada } 3300a9064fbSMasahiro Yamada if (sym->flags & def_flags) { 3310a9064fbSMasahiro Yamada conf_warning("override: reassigning to symbol %s", sym->name); 3320a9064fbSMasahiro Yamada } 3330a9064fbSMasahiro Yamada switch (sym->type) { 3340a9064fbSMasahiro Yamada case S_BOOLEAN: 3350a9064fbSMasahiro Yamada case S_TRISTATE: 3360a9064fbSMasahiro Yamada sym->def[def].tri = no; 3370a9064fbSMasahiro Yamada sym->flags |= def_flags; 3380a9064fbSMasahiro Yamada break; 3390a9064fbSMasahiro Yamada default: 3400a9064fbSMasahiro Yamada ; 3410a9064fbSMasahiro Yamada } 3420a9064fbSMasahiro Yamada } else if (memcmp(line, CONFIG_, strlen(CONFIG_)) == 0) { 3430a9064fbSMasahiro Yamada p = strchr(line + strlen(CONFIG_), '='); 3440a9064fbSMasahiro Yamada if (!p) 3450a9064fbSMasahiro Yamada continue; 3460a9064fbSMasahiro Yamada *p++ = 0; 3470a9064fbSMasahiro Yamada p2 = strchr(p, '\n'); 3480a9064fbSMasahiro Yamada if (p2) { 3490a9064fbSMasahiro Yamada *p2-- = 0; 3500a9064fbSMasahiro Yamada if (*p2 == '\r') 3510a9064fbSMasahiro Yamada *p2 = 0; 3520a9064fbSMasahiro Yamada } 3530a9064fbSMasahiro Yamada if (def == S_DEF_USER) { 3540a9064fbSMasahiro Yamada sym = sym_find(line + strlen(CONFIG_)); 3550a9064fbSMasahiro Yamada if (!sym) { 3560a9064fbSMasahiro Yamada sym_add_change_count(1); 3570a9064fbSMasahiro Yamada goto setsym; 3580a9064fbSMasahiro Yamada } 3590a9064fbSMasahiro Yamada } else { 3600a9064fbSMasahiro Yamada sym = sym_lookup(line + strlen(CONFIG_), 0); 3610a9064fbSMasahiro Yamada if (sym->type == S_UNKNOWN) 3620a9064fbSMasahiro Yamada sym->type = S_OTHER; 3630a9064fbSMasahiro Yamada } 3640a9064fbSMasahiro Yamada if (sym->flags & def_flags) { 3650a9064fbSMasahiro Yamada conf_warning("override: reassigning to symbol %s", sym->name); 3660a9064fbSMasahiro Yamada } 3670a9064fbSMasahiro Yamada if (conf_set_sym_val(sym, def, def_flags, p)) 3680a9064fbSMasahiro Yamada continue; 3690a9064fbSMasahiro Yamada } else { 3700a9064fbSMasahiro Yamada if (line[0] != '\r' && line[0] != '\n') 3710a9064fbSMasahiro Yamada conf_warning("unexpected data"); 3720a9064fbSMasahiro Yamada continue; 3730a9064fbSMasahiro Yamada } 3740a9064fbSMasahiro Yamada setsym: 3750a9064fbSMasahiro Yamada if (sym && sym_is_choice_value(sym)) { 3760a9064fbSMasahiro Yamada struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym)); 3770a9064fbSMasahiro Yamada switch (sym->def[def].tri) { 3780a9064fbSMasahiro Yamada case no: 3790a9064fbSMasahiro Yamada break; 3800a9064fbSMasahiro Yamada case mod: 3810a9064fbSMasahiro Yamada if (cs->def[def].tri == yes) { 3820a9064fbSMasahiro Yamada conf_warning("%s creates inconsistent choice state", sym->name); 3830a9064fbSMasahiro Yamada cs->flags &= ~def_flags; 3840a9064fbSMasahiro Yamada } 3850a9064fbSMasahiro Yamada break; 3860a9064fbSMasahiro Yamada case yes: 3870a9064fbSMasahiro Yamada if (cs->def[def].tri != no) 3880a9064fbSMasahiro Yamada conf_warning("override: %s changes choice state", sym->name); 3890a9064fbSMasahiro Yamada cs->def[def].val = sym; 3900a9064fbSMasahiro Yamada break; 3910a9064fbSMasahiro Yamada } 3920a9064fbSMasahiro Yamada cs->def[def].tri = EXPR_OR(cs->def[def].tri, sym->def[def].tri); 3930a9064fbSMasahiro Yamada } 3940a9064fbSMasahiro Yamada } 3950a9064fbSMasahiro Yamada free(line); 3960a9064fbSMasahiro Yamada fclose(in); 3970a9064fbSMasahiro Yamada 3980a9064fbSMasahiro Yamada if (modules_sym) 3990a9064fbSMasahiro Yamada sym_calc_value(modules_sym); 4000a9064fbSMasahiro Yamada return 0; 4010a9064fbSMasahiro Yamada } 4020a9064fbSMasahiro Yamada 4030a9064fbSMasahiro Yamada int conf_read(const char *name) 4040a9064fbSMasahiro Yamada { 4050a9064fbSMasahiro Yamada struct symbol *sym; 4060a9064fbSMasahiro Yamada int i; 4070a9064fbSMasahiro Yamada 4080a9064fbSMasahiro Yamada sym_set_change_count(0); 4090a9064fbSMasahiro Yamada 4100a9064fbSMasahiro Yamada if (conf_read_simple(name, S_DEF_USER)) 4110a9064fbSMasahiro Yamada return 1; 4120a9064fbSMasahiro Yamada 4130a9064fbSMasahiro Yamada for_all_symbols(i, sym) { 4140a9064fbSMasahiro Yamada sym_calc_value(sym); 4150a9064fbSMasahiro Yamada if (sym_is_choice(sym) || (sym->flags & SYMBOL_AUTO)) 4160a9064fbSMasahiro Yamada continue; 4170a9064fbSMasahiro Yamada if (sym_has_value(sym) && (sym->flags & SYMBOL_WRITE)) { 4180a9064fbSMasahiro Yamada /* check that calculated value agrees with saved value */ 4190a9064fbSMasahiro Yamada switch (sym->type) { 4200a9064fbSMasahiro Yamada case S_BOOLEAN: 4210a9064fbSMasahiro Yamada case S_TRISTATE: 4220a9064fbSMasahiro Yamada if (sym->def[S_DEF_USER].tri != sym_get_tristate_value(sym)) 4230a9064fbSMasahiro Yamada break; 4240a9064fbSMasahiro Yamada if (!sym_is_choice(sym)) 4250a9064fbSMasahiro Yamada continue; 4260a9064fbSMasahiro Yamada /* fall through */ 4270a9064fbSMasahiro Yamada default: 4280a9064fbSMasahiro Yamada if (!strcmp(sym->curr.val, sym->def[S_DEF_USER].val)) 4290a9064fbSMasahiro Yamada continue; 4300a9064fbSMasahiro Yamada break; 4310a9064fbSMasahiro Yamada } 4320a9064fbSMasahiro Yamada } else if (!sym_has_value(sym) && !(sym->flags & SYMBOL_WRITE)) 4330a9064fbSMasahiro Yamada /* no previous value and not saved */ 4340a9064fbSMasahiro Yamada continue; 4350a9064fbSMasahiro Yamada conf_unsaved++; 4360a9064fbSMasahiro Yamada /* maybe print value in verbose mode... */ 4370a9064fbSMasahiro Yamada } 4380a9064fbSMasahiro Yamada 4390a9064fbSMasahiro Yamada for_all_symbols(i, sym) { 4400a9064fbSMasahiro Yamada if (sym_has_value(sym) && !sym_is_choice_value(sym)) { 4410a9064fbSMasahiro Yamada /* Reset values of generates values, so they'll appear 4420a9064fbSMasahiro Yamada * as new, if they should become visible, but that 4430a9064fbSMasahiro Yamada * doesn't quite work if the Kconfig and the saved 4440a9064fbSMasahiro Yamada * configuration disagree. 4450a9064fbSMasahiro Yamada */ 4460a9064fbSMasahiro Yamada if (sym->visible == no && !conf_unsaved) 4470a9064fbSMasahiro Yamada sym->flags &= ~SYMBOL_DEF_USER; 4480a9064fbSMasahiro Yamada switch (sym->type) { 4490a9064fbSMasahiro Yamada case S_STRING: 4500a9064fbSMasahiro Yamada case S_INT: 4510a9064fbSMasahiro Yamada case S_HEX: 4520a9064fbSMasahiro Yamada /* Reset a string value if it's out of range */ 4530a9064fbSMasahiro Yamada if (sym_string_within_range(sym, sym->def[S_DEF_USER].val)) 4540a9064fbSMasahiro Yamada break; 4550a9064fbSMasahiro Yamada sym->flags &= ~(SYMBOL_VALID|SYMBOL_DEF_USER); 4560a9064fbSMasahiro Yamada conf_unsaved++; 4570a9064fbSMasahiro Yamada break; 4580a9064fbSMasahiro Yamada default: 4590a9064fbSMasahiro Yamada break; 4600a9064fbSMasahiro Yamada } 4610a9064fbSMasahiro Yamada } 4620a9064fbSMasahiro Yamada } 4630a9064fbSMasahiro Yamada 4640a9064fbSMasahiro Yamada sym_add_change_count(conf_warnings || conf_unsaved); 4650a9064fbSMasahiro Yamada 4660a9064fbSMasahiro Yamada return 0; 4670a9064fbSMasahiro Yamada } 4680a9064fbSMasahiro Yamada 4690a9064fbSMasahiro Yamada /* 4700a9064fbSMasahiro Yamada * Kconfig configuration printer 4710a9064fbSMasahiro Yamada * 4720a9064fbSMasahiro Yamada * This printer is used when generating the resulting configuration after 4730a9064fbSMasahiro Yamada * kconfig invocation and `defconfig' files. Unset symbol might be omitted by 4740a9064fbSMasahiro Yamada * passing a non-NULL argument to the printer. 4750a9064fbSMasahiro Yamada * 4760a9064fbSMasahiro Yamada */ 4770a9064fbSMasahiro Yamada static void 4780a9064fbSMasahiro Yamada kconfig_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg) 4790a9064fbSMasahiro Yamada { 4800a9064fbSMasahiro Yamada 4810a9064fbSMasahiro Yamada switch (sym->type) { 4820a9064fbSMasahiro Yamada case S_BOOLEAN: 4830a9064fbSMasahiro Yamada case S_TRISTATE: 4840a9064fbSMasahiro Yamada if (*value == 'n') { 4850a9064fbSMasahiro Yamada bool skip_unset = (arg != NULL); 4860a9064fbSMasahiro Yamada 4870a9064fbSMasahiro Yamada if (!skip_unset) 4880a9064fbSMasahiro Yamada fprintf(fp, "# %s%s is not set\n", 4890a9064fbSMasahiro Yamada CONFIG_, sym->name); 4900a9064fbSMasahiro Yamada return; 4910a9064fbSMasahiro Yamada } 4920a9064fbSMasahiro Yamada break; 4930a9064fbSMasahiro Yamada default: 4940a9064fbSMasahiro Yamada break; 4950a9064fbSMasahiro Yamada } 4960a9064fbSMasahiro Yamada 4970a9064fbSMasahiro Yamada fprintf(fp, "%s%s=%s\n", CONFIG_, sym->name, value); 4980a9064fbSMasahiro Yamada } 4990a9064fbSMasahiro Yamada 5000a9064fbSMasahiro Yamada static void 5010a9064fbSMasahiro Yamada kconfig_print_comment(FILE *fp, const char *value, void *arg) 5020a9064fbSMasahiro Yamada { 5030a9064fbSMasahiro Yamada const char *p = value; 5040a9064fbSMasahiro Yamada size_t l; 5050a9064fbSMasahiro Yamada 5060a9064fbSMasahiro Yamada for (;;) { 5070a9064fbSMasahiro Yamada l = strcspn(p, "\n"); 5080a9064fbSMasahiro Yamada fprintf(fp, "#"); 5090a9064fbSMasahiro Yamada if (l) { 5100a9064fbSMasahiro Yamada fprintf(fp, " "); 5110a9064fbSMasahiro Yamada xfwrite(p, l, 1, fp); 5120a9064fbSMasahiro Yamada p += l; 5130a9064fbSMasahiro Yamada } 5140a9064fbSMasahiro Yamada fprintf(fp, "\n"); 5150a9064fbSMasahiro Yamada if (*p++ == '\0') 5160a9064fbSMasahiro Yamada break; 5170a9064fbSMasahiro Yamada } 5180a9064fbSMasahiro Yamada } 5190a9064fbSMasahiro Yamada 5200a9064fbSMasahiro Yamada static struct conf_printer kconfig_printer_cb = 5210a9064fbSMasahiro Yamada { 5220a9064fbSMasahiro Yamada .print_symbol = kconfig_print_symbol, 5230a9064fbSMasahiro Yamada .print_comment = kconfig_print_comment, 5240a9064fbSMasahiro Yamada }; 5250a9064fbSMasahiro Yamada 5260a9064fbSMasahiro Yamada /* 5270a9064fbSMasahiro Yamada * Header printer 5280a9064fbSMasahiro Yamada * 5290a9064fbSMasahiro Yamada * This printer is used when generating the `include/generated/autoconf.h' file. 5300a9064fbSMasahiro Yamada */ 5310a9064fbSMasahiro Yamada static void 5320a9064fbSMasahiro Yamada header_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg) 5330a9064fbSMasahiro Yamada { 5340a9064fbSMasahiro Yamada 5350a9064fbSMasahiro Yamada switch (sym->type) { 5360a9064fbSMasahiro Yamada case S_BOOLEAN: 5370a9064fbSMasahiro Yamada case S_TRISTATE: { 5380a9064fbSMasahiro Yamada const char *suffix = ""; 5390a9064fbSMasahiro Yamada 5400a9064fbSMasahiro Yamada switch (*value) { 5410a9064fbSMasahiro Yamada case 'n': 5420a9064fbSMasahiro Yamada break; 5430a9064fbSMasahiro Yamada case 'm': 5440a9064fbSMasahiro Yamada suffix = "_MODULE"; 5450a9064fbSMasahiro Yamada /* fall through */ 5460a9064fbSMasahiro Yamada default: 5470a9064fbSMasahiro Yamada fprintf(fp, "#define %s%s%s 1\n", 5480a9064fbSMasahiro Yamada CONFIG_, sym->name, suffix); 5490a9064fbSMasahiro Yamada } 5500a9064fbSMasahiro Yamada break; 5510a9064fbSMasahiro Yamada } 5520a9064fbSMasahiro Yamada case S_HEX: { 5530a9064fbSMasahiro Yamada const char *prefix = ""; 5540a9064fbSMasahiro Yamada 5550a9064fbSMasahiro Yamada if (value[0] != '0' || (value[1] != 'x' && value[1] != 'X')) 5560a9064fbSMasahiro Yamada prefix = "0x"; 5570a9064fbSMasahiro Yamada fprintf(fp, "#define %s%s %s%s\n", 5580a9064fbSMasahiro Yamada CONFIG_, sym->name, prefix, value); 5590a9064fbSMasahiro Yamada break; 5600a9064fbSMasahiro Yamada } 5610a9064fbSMasahiro Yamada case S_STRING: 5620a9064fbSMasahiro Yamada case S_INT: 5630a9064fbSMasahiro Yamada fprintf(fp, "#define %s%s %s\n", 5640a9064fbSMasahiro Yamada CONFIG_, sym->name, value); 5650a9064fbSMasahiro Yamada break; 5660a9064fbSMasahiro Yamada default: 5670a9064fbSMasahiro Yamada break; 5680a9064fbSMasahiro Yamada } 5690a9064fbSMasahiro Yamada 5700a9064fbSMasahiro Yamada } 5710a9064fbSMasahiro Yamada 5720a9064fbSMasahiro Yamada static void 5730a9064fbSMasahiro Yamada header_print_comment(FILE *fp, const char *value, void *arg) 5740a9064fbSMasahiro Yamada { 5750a9064fbSMasahiro Yamada const char *p = value; 5760a9064fbSMasahiro Yamada size_t l; 5770a9064fbSMasahiro Yamada 5780a9064fbSMasahiro Yamada fprintf(fp, "/*\n"); 5790a9064fbSMasahiro Yamada for (;;) { 5800a9064fbSMasahiro Yamada l = strcspn(p, "\n"); 5810a9064fbSMasahiro Yamada fprintf(fp, " *"); 5820a9064fbSMasahiro Yamada if (l) { 5830a9064fbSMasahiro Yamada fprintf(fp, " "); 5840a9064fbSMasahiro Yamada xfwrite(p, l, 1, fp); 5850a9064fbSMasahiro Yamada p += l; 5860a9064fbSMasahiro Yamada } 5870a9064fbSMasahiro Yamada fprintf(fp, "\n"); 5880a9064fbSMasahiro Yamada if (*p++ == '\0') 5890a9064fbSMasahiro Yamada break; 5900a9064fbSMasahiro Yamada } 5910a9064fbSMasahiro Yamada fprintf(fp, " */\n"); 5920a9064fbSMasahiro Yamada } 5930a9064fbSMasahiro Yamada 5940a9064fbSMasahiro Yamada static struct conf_printer header_printer_cb = 5950a9064fbSMasahiro Yamada { 5960a9064fbSMasahiro Yamada .print_symbol = header_print_symbol, 5970a9064fbSMasahiro Yamada .print_comment = header_print_comment, 5980a9064fbSMasahiro Yamada }; 5990a9064fbSMasahiro Yamada 6000a9064fbSMasahiro Yamada /* 6010a9064fbSMasahiro Yamada * Tristate printer 6020a9064fbSMasahiro Yamada * 6030a9064fbSMasahiro Yamada * This printer is used when generating the `include/config/tristate.conf' file. 6040a9064fbSMasahiro Yamada */ 6050a9064fbSMasahiro Yamada static void 6060a9064fbSMasahiro Yamada tristate_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg) 6070a9064fbSMasahiro Yamada { 6080a9064fbSMasahiro Yamada 6090a9064fbSMasahiro Yamada if (sym->type == S_TRISTATE && *value != 'n') 6100a9064fbSMasahiro Yamada fprintf(fp, "%s%s=%c\n", CONFIG_, sym->name, (char)toupper(*value)); 6110a9064fbSMasahiro Yamada } 6120a9064fbSMasahiro Yamada 6130a9064fbSMasahiro Yamada static struct conf_printer tristate_printer_cb = 6140a9064fbSMasahiro Yamada { 6150a9064fbSMasahiro Yamada .print_symbol = tristate_print_symbol, 6160a9064fbSMasahiro Yamada .print_comment = kconfig_print_comment, 6170a9064fbSMasahiro Yamada }; 6180a9064fbSMasahiro Yamada 6190a9064fbSMasahiro Yamada static void conf_write_symbol(FILE *fp, struct symbol *sym, 6200a9064fbSMasahiro Yamada struct conf_printer *printer, void *printer_arg) 6210a9064fbSMasahiro Yamada { 6220a9064fbSMasahiro Yamada const char *str; 623*20c20826SStefan Roese char *str2; 6240a9064fbSMasahiro Yamada 6250a9064fbSMasahiro Yamada switch (sym->type) { 6260a9064fbSMasahiro Yamada case S_OTHER: 6270a9064fbSMasahiro Yamada case S_UNKNOWN: 6280a9064fbSMasahiro Yamada break; 6290a9064fbSMasahiro Yamada case S_STRING: 6300a9064fbSMasahiro Yamada str = sym_get_string_value(sym); 631*20c20826SStefan Roese str2 = xmalloc(strlen(str) + 3); 632*20c20826SStefan Roese sprintf(str2, "\"%s\"", str); 633*20c20826SStefan Roese printer->print_symbol(fp, sym, str2, printer_arg); 634*20c20826SStefan Roese free((void *)str2); 6350a9064fbSMasahiro Yamada break; 6360a9064fbSMasahiro Yamada default: 6370a9064fbSMasahiro Yamada str = sym_get_string_value(sym); 6380a9064fbSMasahiro Yamada printer->print_symbol(fp, sym, str, printer_arg); 6390a9064fbSMasahiro Yamada } 6400a9064fbSMasahiro Yamada } 6410a9064fbSMasahiro Yamada 6420a9064fbSMasahiro Yamada static void 6430a9064fbSMasahiro Yamada conf_write_heading(FILE *fp, struct conf_printer *printer, void *printer_arg) 6440a9064fbSMasahiro Yamada { 6450a9064fbSMasahiro Yamada char buf[256]; 6460a9064fbSMasahiro Yamada 6470a9064fbSMasahiro Yamada snprintf(buf, sizeof(buf), 6480a9064fbSMasahiro Yamada "\n" 6490a9064fbSMasahiro Yamada "Automatically generated file; DO NOT EDIT.\n" 6500a9064fbSMasahiro Yamada "%s\n", 6510a9064fbSMasahiro Yamada rootmenu.prompt->text); 6520a9064fbSMasahiro Yamada 6530a9064fbSMasahiro Yamada printer->print_comment(fp, buf, printer_arg); 6540a9064fbSMasahiro Yamada } 6550a9064fbSMasahiro Yamada 6560a9064fbSMasahiro Yamada /* 6570a9064fbSMasahiro Yamada * Write out a minimal config. 6580a9064fbSMasahiro Yamada * All values that has default values are skipped as this is redundant. 6590a9064fbSMasahiro Yamada */ 6600a9064fbSMasahiro Yamada int conf_write_defconfig(const char *filename) 6610a9064fbSMasahiro Yamada { 6620a9064fbSMasahiro Yamada struct symbol *sym; 6630a9064fbSMasahiro Yamada struct menu *menu; 6640a9064fbSMasahiro Yamada FILE *out; 6650a9064fbSMasahiro Yamada 6660a9064fbSMasahiro Yamada out = fopen(filename, "w"); 6670a9064fbSMasahiro Yamada if (!out) 6680a9064fbSMasahiro Yamada return 1; 6690a9064fbSMasahiro Yamada 6700a9064fbSMasahiro Yamada sym_clear_all_valid(); 6710a9064fbSMasahiro Yamada 6720a9064fbSMasahiro Yamada /* Traverse all menus to find all relevant symbols */ 6730a9064fbSMasahiro Yamada menu = rootmenu.list; 6740a9064fbSMasahiro Yamada 6750a9064fbSMasahiro Yamada while (menu != NULL) 6760a9064fbSMasahiro Yamada { 6770a9064fbSMasahiro Yamada sym = menu->sym; 6780a9064fbSMasahiro Yamada if (sym == NULL) { 6790a9064fbSMasahiro Yamada if (!menu_is_visible(menu)) 6800a9064fbSMasahiro Yamada goto next_menu; 6810a9064fbSMasahiro Yamada } else if (!sym_is_choice(sym)) { 6820a9064fbSMasahiro Yamada sym_calc_value(sym); 6830a9064fbSMasahiro Yamada if (!(sym->flags & SYMBOL_WRITE)) 6840a9064fbSMasahiro Yamada goto next_menu; 6850a9064fbSMasahiro Yamada sym->flags &= ~SYMBOL_WRITE; 6860a9064fbSMasahiro Yamada /* If we cannot change the symbol - skip */ 6870a9064fbSMasahiro Yamada if (!sym_is_changable(sym)) 6880a9064fbSMasahiro Yamada goto next_menu; 6890a9064fbSMasahiro Yamada /* If symbol equals to default value - skip */ 6900a9064fbSMasahiro Yamada if (strcmp(sym_get_string_value(sym), sym_get_string_default(sym)) == 0) 6910a9064fbSMasahiro Yamada goto next_menu; 6920a9064fbSMasahiro Yamada 6930a9064fbSMasahiro Yamada /* 6940a9064fbSMasahiro Yamada * If symbol is a choice value and equals to the 6950a9064fbSMasahiro Yamada * default for a choice - skip. 6960a9064fbSMasahiro Yamada * But only if value is bool and equal to "y" and 6970a9064fbSMasahiro Yamada * choice is not "optional". 6980a9064fbSMasahiro Yamada * (If choice is "optional" then all values can be "n") 6990a9064fbSMasahiro Yamada */ 7000a9064fbSMasahiro Yamada if (sym_is_choice_value(sym)) { 7010a9064fbSMasahiro Yamada struct symbol *cs; 7020a9064fbSMasahiro Yamada struct symbol *ds; 7030a9064fbSMasahiro Yamada 7040a9064fbSMasahiro Yamada cs = prop_get_symbol(sym_get_choice_prop(sym)); 7050a9064fbSMasahiro Yamada ds = sym_choice_default(cs); 7060a9064fbSMasahiro Yamada if (!sym_is_optional(cs) && sym == ds) { 7070a9064fbSMasahiro Yamada if ((sym->type == S_BOOLEAN) && 7080a9064fbSMasahiro Yamada sym_get_tristate_value(sym) == yes) 7090a9064fbSMasahiro Yamada goto next_menu; 7100a9064fbSMasahiro Yamada } 7110a9064fbSMasahiro Yamada } 7120a9064fbSMasahiro Yamada conf_write_symbol(out, sym, &kconfig_printer_cb, NULL); 7130a9064fbSMasahiro Yamada } 7140a9064fbSMasahiro Yamada next_menu: 7150a9064fbSMasahiro Yamada if (menu->list != NULL) { 7160a9064fbSMasahiro Yamada menu = menu->list; 7170a9064fbSMasahiro Yamada } 7180a9064fbSMasahiro Yamada else if (menu->next != NULL) { 7190a9064fbSMasahiro Yamada menu = menu->next; 7200a9064fbSMasahiro Yamada } else { 7210a9064fbSMasahiro Yamada while ((menu = menu->parent)) { 7220a9064fbSMasahiro Yamada if (menu->next != NULL) { 7230a9064fbSMasahiro Yamada menu = menu->next; 7240a9064fbSMasahiro Yamada break; 7250a9064fbSMasahiro Yamada } 7260a9064fbSMasahiro Yamada } 7270a9064fbSMasahiro Yamada } 7280a9064fbSMasahiro Yamada } 7290a9064fbSMasahiro Yamada fclose(out); 7300a9064fbSMasahiro Yamada return 0; 7310a9064fbSMasahiro Yamada } 7320a9064fbSMasahiro Yamada 7330a9064fbSMasahiro Yamada int conf_write(const char *name) 7340a9064fbSMasahiro Yamada { 7350a9064fbSMasahiro Yamada FILE *out; 7360a9064fbSMasahiro Yamada struct symbol *sym; 7370a9064fbSMasahiro Yamada struct menu *menu; 7380a9064fbSMasahiro Yamada const char *basename; 7390a9064fbSMasahiro Yamada const char *str; 7400a9064fbSMasahiro Yamada char dirname[PATH_MAX+1], tmpname[PATH_MAX+1], newname[PATH_MAX+1]; 7410a9064fbSMasahiro Yamada char *env; 7420a9064fbSMasahiro Yamada 7430a9064fbSMasahiro Yamada dirname[0] = 0; 7440a9064fbSMasahiro Yamada if (name && name[0]) { 7450a9064fbSMasahiro Yamada struct stat st; 7460a9064fbSMasahiro Yamada char *slash; 7470a9064fbSMasahiro Yamada 7480a9064fbSMasahiro Yamada if (!stat(name, &st) && S_ISDIR(st.st_mode)) { 7490a9064fbSMasahiro Yamada strcpy(dirname, name); 7500a9064fbSMasahiro Yamada strcat(dirname, "/"); 7510a9064fbSMasahiro Yamada basename = conf_get_configname(); 7520a9064fbSMasahiro Yamada } else if ((slash = strrchr(name, '/'))) { 7530a9064fbSMasahiro Yamada int size = slash - name + 1; 7540a9064fbSMasahiro Yamada memcpy(dirname, name, size); 7550a9064fbSMasahiro Yamada dirname[size] = 0; 7560a9064fbSMasahiro Yamada if (slash[1]) 7570a9064fbSMasahiro Yamada basename = slash + 1; 7580a9064fbSMasahiro Yamada else 7590a9064fbSMasahiro Yamada basename = conf_get_configname(); 7600a9064fbSMasahiro Yamada } else 7610a9064fbSMasahiro Yamada basename = name; 7620a9064fbSMasahiro Yamada } else 7630a9064fbSMasahiro Yamada basename = conf_get_configname(); 7640a9064fbSMasahiro Yamada 7650a9064fbSMasahiro Yamada sprintf(newname, "%s%s", dirname, basename); 7660a9064fbSMasahiro Yamada env = getenv("KCONFIG_OVERWRITECONFIG"); 7670a9064fbSMasahiro Yamada if (!env || !*env) { 7680a9064fbSMasahiro Yamada sprintf(tmpname, "%s.tmpconfig.%d", dirname, (int)getpid()); 7690a9064fbSMasahiro Yamada out = fopen(tmpname, "w"); 7700a9064fbSMasahiro Yamada } else { 7710a9064fbSMasahiro Yamada *tmpname = 0; 7720a9064fbSMasahiro Yamada out = fopen(newname, "w"); 7730a9064fbSMasahiro Yamada } 7740a9064fbSMasahiro Yamada if (!out) 7750a9064fbSMasahiro Yamada return 1; 7760a9064fbSMasahiro Yamada 7770a9064fbSMasahiro Yamada conf_write_heading(out, &kconfig_printer_cb, NULL); 7780a9064fbSMasahiro Yamada 7790a9064fbSMasahiro Yamada if (!conf_get_changed()) 7800a9064fbSMasahiro Yamada sym_clear_all_valid(); 7810a9064fbSMasahiro Yamada 7820a9064fbSMasahiro Yamada menu = rootmenu.list; 7830a9064fbSMasahiro Yamada while (menu) { 7840a9064fbSMasahiro Yamada sym = menu->sym; 7850a9064fbSMasahiro Yamada if (!sym) { 7860a9064fbSMasahiro Yamada if (!menu_is_visible(menu)) 7870a9064fbSMasahiro Yamada goto next; 7880a9064fbSMasahiro Yamada str = menu_get_prompt(menu); 7890a9064fbSMasahiro Yamada fprintf(out, "\n" 7900a9064fbSMasahiro Yamada "#\n" 7910a9064fbSMasahiro Yamada "# %s\n" 7920a9064fbSMasahiro Yamada "#\n", str); 7930a9064fbSMasahiro Yamada } else if (!(sym->flags & SYMBOL_CHOICE)) { 7940a9064fbSMasahiro Yamada sym_calc_value(sym); 7950a9064fbSMasahiro Yamada if (!(sym->flags & SYMBOL_WRITE)) 7960a9064fbSMasahiro Yamada goto next; 7970a9064fbSMasahiro Yamada sym->flags &= ~SYMBOL_WRITE; 7980a9064fbSMasahiro Yamada 7990a9064fbSMasahiro Yamada conf_write_symbol(out, sym, &kconfig_printer_cb, NULL); 8000a9064fbSMasahiro Yamada } 8010a9064fbSMasahiro Yamada 8020a9064fbSMasahiro Yamada next: 8030a9064fbSMasahiro Yamada if (menu->list) { 8040a9064fbSMasahiro Yamada menu = menu->list; 8050a9064fbSMasahiro Yamada continue; 8060a9064fbSMasahiro Yamada } 8070a9064fbSMasahiro Yamada if (menu->next) 8080a9064fbSMasahiro Yamada menu = menu->next; 8090a9064fbSMasahiro Yamada else while ((menu = menu->parent)) { 8100a9064fbSMasahiro Yamada if (menu->next) { 8110a9064fbSMasahiro Yamada menu = menu->next; 8120a9064fbSMasahiro Yamada break; 8130a9064fbSMasahiro Yamada } 8140a9064fbSMasahiro Yamada } 8150a9064fbSMasahiro Yamada } 8160a9064fbSMasahiro Yamada fclose(out); 8170a9064fbSMasahiro Yamada 8180a9064fbSMasahiro Yamada if (*tmpname) { 8190a9064fbSMasahiro Yamada strcat(dirname, basename); 8200a9064fbSMasahiro Yamada strcat(dirname, ".old"); 8210a9064fbSMasahiro Yamada rename(newname, dirname); 8220a9064fbSMasahiro Yamada if (rename(tmpname, newname)) 8230a9064fbSMasahiro Yamada return 1; 8240a9064fbSMasahiro Yamada } 8250a9064fbSMasahiro Yamada 8260a9064fbSMasahiro Yamada conf_message(_("configuration written to %s"), newname); 8270a9064fbSMasahiro Yamada 8280a9064fbSMasahiro Yamada sym_set_change_count(0); 8290a9064fbSMasahiro Yamada 8300a9064fbSMasahiro Yamada return 0; 8310a9064fbSMasahiro Yamada } 8320a9064fbSMasahiro Yamada 8330a9064fbSMasahiro Yamada static int conf_split_config(void) 8340a9064fbSMasahiro Yamada { 8350a9064fbSMasahiro Yamada const char *name; 8360a9064fbSMasahiro Yamada char path[PATH_MAX+1]; 8370a9064fbSMasahiro Yamada char *s, *d, c; 8380a9064fbSMasahiro Yamada struct symbol *sym; 8390a9064fbSMasahiro Yamada struct stat sb; 8400a9064fbSMasahiro Yamada int res, i, fd; 8410a9064fbSMasahiro Yamada 8420a9064fbSMasahiro Yamada name = conf_get_autoconfig_name(); 8430a9064fbSMasahiro Yamada conf_read_simple(name, S_DEF_AUTO); 8440a9064fbSMasahiro Yamada 8450a9064fbSMasahiro Yamada if (chdir("include/config")) 8460a9064fbSMasahiro Yamada return 1; 8470a9064fbSMasahiro Yamada 8480a9064fbSMasahiro Yamada res = 0; 8490a9064fbSMasahiro Yamada for_all_symbols(i, sym) { 8500a9064fbSMasahiro Yamada sym_calc_value(sym); 8510a9064fbSMasahiro Yamada if ((sym->flags & SYMBOL_AUTO) || !sym->name) 8520a9064fbSMasahiro Yamada continue; 8530a9064fbSMasahiro Yamada if (sym->flags & SYMBOL_WRITE) { 8540a9064fbSMasahiro Yamada if (sym->flags & SYMBOL_DEF_AUTO) { 8550a9064fbSMasahiro Yamada /* 8560a9064fbSMasahiro Yamada * symbol has old and new value, 8570a9064fbSMasahiro Yamada * so compare them... 8580a9064fbSMasahiro Yamada */ 8590a9064fbSMasahiro Yamada switch (sym->type) { 8600a9064fbSMasahiro Yamada case S_BOOLEAN: 8610a9064fbSMasahiro Yamada case S_TRISTATE: 8620a9064fbSMasahiro Yamada if (sym_get_tristate_value(sym) == 8630a9064fbSMasahiro Yamada sym->def[S_DEF_AUTO].tri) 8640a9064fbSMasahiro Yamada continue; 8650a9064fbSMasahiro Yamada break; 8660a9064fbSMasahiro Yamada case S_STRING: 8670a9064fbSMasahiro Yamada case S_HEX: 8680a9064fbSMasahiro Yamada case S_INT: 8690a9064fbSMasahiro Yamada if (!strcmp(sym_get_string_value(sym), 8700a9064fbSMasahiro Yamada sym->def[S_DEF_AUTO].val)) 8710a9064fbSMasahiro Yamada continue; 8720a9064fbSMasahiro Yamada break; 8730a9064fbSMasahiro Yamada default: 8740a9064fbSMasahiro Yamada break; 8750a9064fbSMasahiro Yamada } 8760a9064fbSMasahiro Yamada } else { 8770a9064fbSMasahiro Yamada /* 8780a9064fbSMasahiro Yamada * If there is no old value, only 'no' (unset) 8790a9064fbSMasahiro Yamada * is allowed as new value. 8800a9064fbSMasahiro Yamada */ 8810a9064fbSMasahiro Yamada switch (sym->type) { 8820a9064fbSMasahiro Yamada case S_BOOLEAN: 8830a9064fbSMasahiro Yamada case S_TRISTATE: 8840a9064fbSMasahiro Yamada if (sym_get_tristate_value(sym) == no) 8850a9064fbSMasahiro Yamada continue; 8860a9064fbSMasahiro Yamada break; 8870a9064fbSMasahiro Yamada default: 8880a9064fbSMasahiro Yamada break; 8890a9064fbSMasahiro Yamada } 8900a9064fbSMasahiro Yamada } 8910a9064fbSMasahiro Yamada } else if (!(sym->flags & SYMBOL_DEF_AUTO)) 8920a9064fbSMasahiro Yamada /* There is neither an old nor a new value. */ 8930a9064fbSMasahiro Yamada continue; 8940a9064fbSMasahiro Yamada /* else 8950a9064fbSMasahiro Yamada * There is an old value, but no new value ('no' (unset) 8960a9064fbSMasahiro Yamada * isn't saved in auto.conf, so the old value is always 8970a9064fbSMasahiro Yamada * different from 'no'). 8980a9064fbSMasahiro Yamada */ 8990a9064fbSMasahiro Yamada 9000a9064fbSMasahiro Yamada /* Replace all '_' and append ".h" */ 9010a9064fbSMasahiro Yamada s = sym->name; 9020a9064fbSMasahiro Yamada d = path; 9030a9064fbSMasahiro Yamada while ((c = *s++)) { 9040a9064fbSMasahiro Yamada c = tolower(c); 9050a9064fbSMasahiro Yamada *d++ = (c == '_') ? '/' : c; 9060a9064fbSMasahiro Yamada } 9070a9064fbSMasahiro Yamada strcpy(d, ".h"); 9080a9064fbSMasahiro Yamada 9090a9064fbSMasahiro Yamada /* Assume directory path already exists. */ 9100a9064fbSMasahiro Yamada fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644); 9110a9064fbSMasahiro Yamada if (fd == -1) { 9120a9064fbSMasahiro Yamada if (errno != ENOENT) { 9130a9064fbSMasahiro Yamada res = 1; 9140a9064fbSMasahiro Yamada break; 9150a9064fbSMasahiro Yamada } 9160a9064fbSMasahiro Yamada /* 9170a9064fbSMasahiro Yamada * Create directory components, 9180a9064fbSMasahiro Yamada * unless they exist already. 9190a9064fbSMasahiro Yamada */ 9200a9064fbSMasahiro Yamada d = path; 9210a9064fbSMasahiro Yamada while ((d = strchr(d, '/'))) { 9220a9064fbSMasahiro Yamada *d = 0; 9230a9064fbSMasahiro Yamada if (stat(path, &sb) && mkdir(path, 0755)) { 9240a9064fbSMasahiro Yamada res = 1; 9250a9064fbSMasahiro Yamada goto out; 9260a9064fbSMasahiro Yamada } 9270a9064fbSMasahiro Yamada *d++ = '/'; 9280a9064fbSMasahiro Yamada } 9290a9064fbSMasahiro Yamada /* Try it again. */ 9300a9064fbSMasahiro Yamada fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644); 9310a9064fbSMasahiro Yamada if (fd == -1) { 9320a9064fbSMasahiro Yamada res = 1; 9330a9064fbSMasahiro Yamada break; 9340a9064fbSMasahiro Yamada } 9350a9064fbSMasahiro Yamada } 9360a9064fbSMasahiro Yamada close(fd); 9370a9064fbSMasahiro Yamada } 9380a9064fbSMasahiro Yamada out: 9390a9064fbSMasahiro Yamada if (chdir("../..")) 9400a9064fbSMasahiro Yamada return 1; 9410a9064fbSMasahiro Yamada 9420a9064fbSMasahiro Yamada return res; 9430a9064fbSMasahiro Yamada } 9440a9064fbSMasahiro Yamada 9450a9064fbSMasahiro Yamada int conf_write_autoconf(void) 9460a9064fbSMasahiro Yamada { 9470a9064fbSMasahiro Yamada struct symbol *sym; 9480a9064fbSMasahiro Yamada const char *name; 9490a9064fbSMasahiro Yamada FILE *out, *tristate, *out_h; 9500a9064fbSMasahiro Yamada int i; 9510a9064fbSMasahiro Yamada 9520a9064fbSMasahiro Yamada sym_clear_all_valid(); 9530a9064fbSMasahiro Yamada 9540a9064fbSMasahiro Yamada file_write_dep("include/config/auto.conf.cmd"); 9550a9064fbSMasahiro Yamada 9560a9064fbSMasahiro Yamada if (conf_split_config()) 9570a9064fbSMasahiro Yamada return 1; 9580a9064fbSMasahiro Yamada 9590a9064fbSMasahiro Yamada out = fopen(".tmpconfig", "w"); 9600a9064fbSMasahiro Yamada if (!out) 9610a9064fbSMasahiro Yamada return 1; 9620a9064fbSMasahiro Yamada 9630a9064fbSMasahiro Yamada tristate = fopen(".tmpconfig_tristate", "w"); 9640a9064fbSMasahiro Yamada if (!tristate) { 9650a9064fbSMasahiro Yamada fclose(out); 9660a9064fbSMasahiro Yamada return 1; 9670a9064fbSMasahiro Yamada } 9680a9064fbSMasahiro Yamada 9690a9064fbSMasahiro Yamada out_h = fopen(".tmpconfig.h", "w"); 9700a9064fbSMasahiro Yamada if (!out_h) { 9710a9064fbSMasahiro Yamada fclose(out); 9720a9064fbSMasahiro Yamada fclose(tristate); 9730a9064fbSMasahiro Yamada return 1; 9740a9064fbSMasahiro Yamada } 9750a9064fbSMasahiro Yamada 9760a9064fbSMasahiro Yamada conf_write_heading(out, &kconfig_printer_cb, NULL); 9770a9064fbSMasahiro Yamada 9780a9064fbSMasahiro Yamada conf_write_heading(tristate, &tristate_printer_cb, NULL); 9790a9064fbSMasahiro Yamada 9800a9064fbSMasahiro Yamada conf_write_heading(out_h, &header_printer_cb, NULL); 9810a9064fbSMasahiro Yamada 9820a9064fbSMasahiro Yamada for_all_symbols(i, sym) { 9830a9064fbSMasahiro Yamada sym_calc_value(sym); 9840a9064fbSMasahiro Yamada if (!(sym->flags & SYMBOL_WRITE) || !sym->name) 9850a9064fbSMasahiro Yamada continue; 9860a9064fbSMasahiro Yamada 9870a9064fbSMasahiro Yamada /* write symbol to auto.conf, tristate and header files */ 9880a9064fbSMasahiro Yamada conf_write_symbol(out, sym, &kconfig_printer_cb, (void *)1); 9890a9064fbSMasahiro Yamada 9900a9064fbSMasahiro Yamada conf_write_symbol(tristate, sym, &tristate_printer_cb, (void *)1); 9910a9064fbSMasahiro Yamada 9920a9064fbSMasahiro Yamada conf_write_symbol(out_h, sym, &header_printer_cb, NULL); 9930a9064fbSMasahiro Yamada } 9940a9064fbSMasahiro Yamada fclose(out); 9950a9064fbSMasahiro Yamada fclose(tristate); 9960a9064fbSMasahiro Yamada fclose(out_h); 9970a9064fbSMasahiro Yamada 9980a9064fbSMasahiro Yamada name = getenv("KCONFIG_AUTOHEADER"); 9990a9064fbSMasahiro Yamada if (!name) 10000a9064fbSMasahiro Yamada name = "include/generated/autoconf.h"; 10010a9064fbSMasahiro Yamada if (rename(".tmpconfig.h", name)) 10020a9064fbSMasahiro Yamada return 1; 10030a9064fbSMasahiro Yamada name = getenv("KCONFIG_TRISTATE"); 10040a9064fbSMasahiro Yamada if (!name) 10050a9064fbSMasahiro Yamada name = "include/config/tristate.conf"; 10060a9064fbSMasahiro Yamada if (rename(".tmpconfig_tristate", name)) 10070a9064fbSMasahiro Yamada return 1; 10080a9064fbSMasahiro Yamada name = conf_get_autoconfig_name(); 10090a9064fbSMasahiro Yamada /* 10100a9064fbSMasahiro Yamada * This must be the last step, kbuild has a dependency on auto.conf 10110a9064fbSMasahiro Yamada * and this marks the successful completion of the previous steps. 10120a9064fbSMasahiro Yamada */ 10130a9064fbSMasahiro Yamada if (rename(".tmpconfig", name)) 10140a9064fbSMasahiro Yamada return 1; 10150a9064fbSMasahiro Yamada 10160a9064fbSMasahiro Yamada return 0; 10170a9064fbSMasahiro Yamada } 10180a9064fbSMasahiro Yamada 10190a9064fbSMasahiro Yamada static int sym_change_count; 10200a9064fbSMasahiro Yamada static void (*conf_changed_callback)(void); 10210a9064fbSMasahiro Yamada 10220a9064fbSMasahiro Yamada void sym_set_change_count(int count) 10230a9064fbSMasahiro Yamada { 10240a9064fbSMasahiro Yamada int _sym_change_count = sym_change_count; 10250a9064fbSMasahiro Yamada sym_change_count = count; 10260a9064fbSMasahiro Yamada if (conf_changed_callback && 10270a9064fbSMasahiro Yamada (bool)_sym_change_count != (bool)count) 10280a9064fbSMasahiro Yamada conf_changed_callback(); 10290a9064fbSMasahiro Yamada } 10300a9064fbSMasahiro Yamada 10310a9064fbSMasahiro Yamada void sym_add_change_count(int count) 10320a9064fbSMasahiro Yamada { 10330a9064fbSMasahiro Yamada sym_set_change_count(count + sym_change_count); 10340a9064fbSMasahiro Yamada } 10350a9064fbSMasahiro Yamada 10360a9064fbSMasahiro Yamada bool conf_get_changed(void) 10370a9064fbSMasahiro Yamada { 10380a9064fbSMasahiro Yamada return sym_change_count; 10390a9064fbSMasahiro Yamada } 10400a9064fbSMasahiro Yamada 10410a9064fbSMasahiro Yamada void conf_set_changed_callback(void (*fn)(void)) 10420a9064fbSMasahiro Yamada { 10430a9064fbSMasahiro Yamada conf_changed_callback = fn; 10440a9064fbSMasahiro Yamada } 10450a9064fbSMasahiro Yamada 10460a9064fbSMasahiro Yamada static bool randomize_choice_values(struct symbol *csym) 10470a9064fbSMasahiro Yamada { 10480a9064fbSMasahiro Yamada struct property *prop; 10490a9064fbSMasahiro Yamada struct symbol *sym; 10500a9064fbSMasahiro Yamada struct expr *e; 10510a9064fbSMasahiro Yamada int cnt, def; 10520a9064fbSMasahiro Yamada 10530a9064fbSMasahiro Yamada /* 10540a9064fbSMasahiro Yamada * If choice is mod then we may have more items selected 10550a9064fbSMasahiro Yamada * and if no then no-one. 10560a9064fbSMasahiro Yamada * In both cases stop. 10570a9064fbSMasahiro Yamada */ 10580a9064fbSMasahiro Yamada if (csym->curr.tri != yes) 10590a9064fbSMasahiro Yamada return false; 10600a9064fbSMasahiro Yamada 10610a9064fbSMasahiro Yamada prop = sym_get_choice_prop(csym); 10620a9064fbSMasahiro Yamada 10630a9064fbSMasahiro Yamada /* count entries in choice block */ 10640a9064fbSMasahiro Yamada cnt = 0; 10650a9064fbSMasahiro Yamada expr_list_for_each_sym(prop->expr, e, sym) 10660a9064fbSMasahiro Yamada cnt++; 10670a9064fbSMasahiro Yamada 10680a9064fbSMasahiro Yamada /* 10690a9064fbSMasahiro Yamada * find a random value and set it to yes, 10700a9064fbSMasahiro Yamada * set the rest to no so we have only one set 10710a9064fbSMasahiro Yamada */ 10720a9064fbSMasahiro Yamada def = (rand() % cnt); 10730a9064fbSMasahiro Yamada 10740a9064fbSMasahiro Yamada cnt = 0; 10750a9064fbSMasahiro Yamada expr_list_for_each_sym(prop->expr, e, sym) { 10760a9064fbSMasahiro Yamada if (def == cnt++) { 10770a9064fbSMasahiro Yamada sym->def[S_DEF_USER].tri = yes; 10780a9064fbSMasahiro Yamada csym->def[S_DEF_USER].val = sym; 10790a9064fbSMasahiro Yamada } 10800a9064fbSMasahiro Yamada else { 10810a9064fbSMasahiro Yamada sym->def[S_DEF_USER].tri = no; 10820a9064fbSMasahiro Yamada } 10830a9064fbSMasahiro Yamada sym->flags |= SYMBOL_DEF_USER; 10840a9064fbSMasahiro Yamada /* clear VALID to get value calculated */ 10850a9064fbSMasahiro Yamada sym->flags &= ~SYMBOL_VALID; 10860a9064fbSMasahiro Yamada } 10870a9064fbSMasahiro Yamada csym->flags |= SYMBOL_DEF_USER; 10880a9064fbSMasahiro Yamada /* clear VALID to get value calculated */ 10890a9064fbSMasahiro Yamada csym->flags &= ~(SYMBOL_VALID); 10900a9064fbSMasahiro Yamada 10910a9064fbSMasahiro Yamada return true; 10920a9064fbSMasahiro Yamada } 10930a9064fbSMasahiro Yamada 10940a9064fbSMasahiro Yamada void set_all_choice_values(struct symbol *csym) 10950a9064fbSMasahiro Yamada { 10960a9064fbSMasahiro Yamada struct property *prop; 10970a9064fbSMasahiro Yamada struct symbol *sym; 10980a9064fbSMasahiro Yamada struct expr *e; 10990a9064fbSMasahiro Yamada 11000a9064fbSMasahiro Yamada prop = sym_get_choice_prop(csym); 11010a9064fbSMasahiro Yamada 11020a9064fbSMasahiro Yamada /* 11030a9064fbSMasahiro Yamada * Set all non-assinged choice values to no 11040a9064fbSMasahiro Yamada */ 11050a9064fbSMasahiro Yamada expr_list_for_each_sym(prop->expr, e, sym) { 11060a9064fbSMasahiro Yamada if (!sym_has_value(sym)) 11070a9064fbSMasahiro Yamada sym->def[S_DEF_USER].tri = no; 11080a9064fbSMasahiro Yamada } 11090a9064fbSMasahiro Yamada csym->flags |= SYMBOL_DEF_USER; 11100a9064fbSMasahiro Yamada /* clear VALID to get value calculated */ 11110a9064fbSMasahiro Yamada csym->flags &= ~(SYMBOL_VALID | SYMBOL_NEED_SET_CHOICE_VALUES); 11120a9064fbSMasahiro Yamada } 11130a9064fbSMasahiro Yamada 11140a9064fbSMasahiro Yamada bool conf_set_all_new_symbols(enum conf_def_mode mode) 11150a9064fbSMasahiro Yamada { 11160a9064fbSMasahiro Yamada struct symbol *sym, *csym; 11170a9064fbSMasahiro Yamada int i, cnt, pby, pty, ptm; /* pby: probability of boolean = y 11180a9064fbSMasahiro Yamada * pty: probability of tristate = y 11190a9064fbSMasahiro Yamada * ptm: probability of tristate = m 11200a9064fbSMasahiro Yamada */ 11210a9064fbSMasahiro Yamada 11220a9064fbSMasahiro Yamada pby = 50; pty = ptm = 33; /* can't go as the default in switch-case 11230a9064fbSMasahiro Yamada * below, otherwise gcc whines about 11240a9064fbSMasahiro Yamada * -Wmaybe-uninitialized */ 11250a9064fbSMasahiro Yamada if (mode == def_random) { 11260a9064fbSMasahiro Yamada int n, p[3]; 11270a9064fbSMasahiro Yamada char *env = getenv("KCONFIG_PROBABILITY"); 11280a9064fbSMasahiro Yamada n = 0; 11290a9064fbSMasahiro Yamada while( env && *env ) { 11300a9064fbSMasahiro Yamada char *endp; 11310a9064fbSMasahiro Yamada int tmp = strtol( env, &endp, 10 ); 11320a9064fbSMasahiro Yamada if( tmp >= 0 && tmp <= 100 ) { 11330a9064fbSMasahiro Yamada p[n++] = tmp; 11340a9064fbSMasahiro Yamada } else { 11350a9064fbSMasahiro Yamada errno = ERANGE; 11360a9064fbSMasahiro Yamada perror( "KCONFIG_PROBABILITY" ); 11370a9064fbSMasahiro Yamada exit( 1 ); 11380a9064fbSMasahiro Yamada } 11390a9064fbSMasahiro Yamada env = (*endp == ':') ? endp+1 : endp; 11400a9064fbSMasahiro Yamada if( n >=3 ) { 11410a9064fbSMasahiro Yamada break; 11420a9064fbSMasahiro Yamada } 11430a9064fbSMasahiro Yamada } 11440a9064fbSMasahiro Yamada switch( n ) { 11450a9064fbSMasahiro Yamada case 1: 11460a9064fbSMasahiro Yamada pby = p[0]; ptm = pby/2; pty = pby-ptm; 11470a9064fbSMasahiro Yamada break; 11480a9064fbSMasahiro Yamada case 2: 11490a9064fbSMasahiro Yamada pty = p[0]; ptm = p[1]; pby = pty + ptm; 11500a9064fbSMasahiro Yamada break; 11510a9064fbSMasahiro Yamada case 3: 11520a9064fbSMasahiro Yamada pby = p[0]; pty = p[1]; ptm = p[2]; 11530a9064fbSMasahiro Yamada break; 11540a9064fbSMasahiro Yamada } 11550a9064fbSMasahiro Yamada 11560a9064fbSMasahiro Yamada if( pty+ptm > 100 ) { 11570a9064fbSMasahiro Yamada errno = ERANGE; 11580a9064fbSMasahiro Yamada perror( "KCONFIG_PROBABILITY" ); 11590a9064fbSMasahiro Yamada exit( 1 ); 11600a9064fbSMasahiro Yamada } 11610a9064fbSMasahiro Yamada } 11620a9064fbSMasahiro Yamada bool has_changed = false; 11630a9064fbSMasahiro Yamada 11640a9064fbSMasahiro Yamada for_all_symbols(i, sym) { 11650a9064fbSMasahiro Yamada if (sym_has_value(sym) || (sym->flags & SYMBOL_VALID)) 11660a9064fbSMasahiro Yamada continue; 11670a9064fbSMasahiro Yamada switch (sym_get_type(sym)) { 11680a9064fbSMasahiro Yamada case S_BOOLEAN: 11690a9064fbSMasahiro Yamada case S_TRISTATE: 11700a9064fbSMasahiro Yamada has_changed = true; 11710a9064fbSMasahiro Yamada switch (mode) { 11720a9064fbSMasahiro Yamada case def_yes: 11730a9064fbSMasahiro Yamada sym->def[S_DEF_USER].tri = yes; 11740a9064fbSMasahiro Yamada break; 11750a9064fbSMasahiro Yamada case def_mod: 11760a9064fbSMasahiro Yamada sym->def[S_DEF_USER].tri = mod; 11770a9064fbSMasahiro Yamada break; 11780a9064fbSMasahiro Yamada case def_no: 11790a9064fbSMasahiro Yamada if (sym->flags & SYMBOL_ALLNOCONFIG_Y) 11800a9064fbSMasahiro Yamada sym->def[S_DEF_USER].tri = yes; 11810a9064fbSMasahiro Yamada else 11820a9064fbSMasahiro Yamada sym->def[S_DEF_USER].tri = no; 11830a9064fbSMasahiro Yamada break; 11840a9064fbSMasahiro Yamada case def_random: 11850a9064fbSMasahiro Yamada sym->def[S_DEF_USER].tri = no; 11860a9064fbSMasahiro Yamada cnt = rand() % 100; 11870a9064fbSMasahiro Yamada if (sym->type == S_TRISTATE) { 11880a9064fbSMasahiro Yamada if (cnt < pty) 11890a9064fbSMasahiro Yamada sym->def[S_DEF_USER].tri = yes; 11900a9064fbSMasahiro Yamada else if (cnt < (pty+ptm)) 11910a9064fbSMasahiro Yamada sym->def[S_DEF_USER].tri = mod; 11920a9064fbSMasahiro Yamada } else if (cnt < pby) 11930a9064fbSMasahiro Yamada sym->def[S_DEF_USER].tri = yes; 11940a9064fbSMasahiro Yamada break; 11950a9064fbSMasahiro Yamada default: 11960a9064fbSMasahiro Yamada continue; 11970a9064fbSMasahiro Yamada } 11980a9064fbSMasahiro Yamada if (!(sym_is_choice(sym) && mode == def_random)) 11990a9064fbSMasahiro Yamada sym->flags |= SYMBOL_DEF_USER; 12000a9064fbSMasahiro Yamada break; 12010a9064fbSMasahiro Yamada default: 12020a9064fbSMasahiro Yamada break; 12030a9064fbSMasahiro Yamada } 12040a9064fbSMasahiro Yamada 12050a9064fbSMasahiro Yamada } 12060a9064fbSMasahiro Yamada 12070a9064fbSMasahiro Yamada sym_clear_all_valid(); 12080a9064fbSMasahiro Yamada 12090a9064fbSMasahiro Yamada /* 12100a9064fbSMasahiro Yamada * We have different type of choice blocks. 12110a9064fbSMasahiro Yamada * If curr.tri equals to mod then we can select several 12120a9064fbSMasahiro Yamada * choice symbols in one block. 12130a9064fbSMasahiro Yamada * In this case we do nothing. 12140a9064fbSMasahiro Yamada * If curr.tri equals yes then only one symbol can be 12150a9064fbSMasahiro Yamada * selected in a choice block and we set it to yes, 12160a9064fbSMasahiro Yamada * and the rest to no. 12170a9064fbSMasahiro Yamada */ 12180a9064fbSMasahiro Yamada if (mode != def_random) { 12190a9064fbSMasahiro Yamada for_all_symbols(i, csym) { 12200a9064fbSMasahiro Yamada if ((sym_is_choice(csym) && !sym_has_value(csym)) || 12210a9064fbSMasahiro Yamada sym_is_choice_value(csym)) 12220a9064fbSMasahiro Yamada csym->flags |= SYMBOL_NEED_SET_CHOICE_VALUES; 12230a9064fbSMasahiro Yamada } 12240a9064fbSMasahiro Yamada } 12250a9064fbSMasahiro Yamada 12260a9064fbSMasahiro Yamada for_all_symbols(i, csym) { 12270a9064fbSMasahiro Yamada if (sym_has_value(csym) || !sym_is_choice(csym)) 12280a9064fbSMasahiro Yamada continue; 12290a9064fbSMasahiro Yamada 12300a9064fbSMasahiro Yamada sym_calc_value(csym); 12310a9064fbSMasahiro Yamada if (mode == def_random) 12320a9064fbSMasahiro Yamada has_changed = randomize_choice_values(csym); 12330a9064fbSMasahiro Yamada else { 12340a9064fbSMasahiro Yamada set_all_choice_values(csym); 12350a9064fbSMasahiro Yamada has_changed = true; 12360a9064fbSMasahiro Yamada } 12370a9064fbSMasahiro Yamada } 12380a9064fbSMasahiro Yamada 12390a9064fbSMasahiro Yamada return has_changed; 12400a9064fbSMasahiro Yamada } 1241