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