18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci#include <sys/mman.h> 78c2ecf20Sopenharmony_ci#include <sys/stat.h> 88c2ecf20Sopenharmony_ci#include <ctype.h> 98c2ecf20Sopenharmony_ci#include <errno.h> 108c2ecf20Sopenharmony_ci#include <fcntl.h> 118c2ecf20Sopenharmony_ci#include <limits.h> 128c2ecf20Sopenharmony_ci#include <stdarg.h> 138c2ecf20Sopenharmony_ci#include <stdio.h> 148c2ecf20Sopenharmony_ci#include <stdlib.h> 158c2ecf20Sopenharmony_ci#include <string.h> 168c2ecf20Sopenharmony_ci#include <time.h> 178c2ecf20Sopenharmony_ci#include <unistd.h> 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci#include "lkc.h" 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci/* return true if 'path' exists, false otherwise */ 228c2ecf20Sopenharmony_cistatic bool is_present(const char *path) 238c2ecf20Sopenharmony_ci{ 248c2ecf20Sopenharmony_ci struct stat st; 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci return !stat(path, &st); 278c2ecf20Sopenharmony_ci} 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci/* return true if 'path' exists and it is a directory, false otherwise */ 308c2ecf20Sopenharmony_cistatic bool is_dir(const char *path) 318c2ecf20Sopenharmony_ci{ 328c2ecf20Sopenharmony_ci struct stat st; 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci if (stat(path, &st)) 358c2ecf20Sopenharmony_ci return 0; 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci return S_ISDIR(st.st_mode); 388c2ecf20Sopenharmony_ci} 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci/* return true if the given two files are the same, false otherwise */ 418c2ecf20Sopenharmony_cistatic bool is_same(const char *file1, const char *file2) 428c2ecf20Sopenharmony_ci{ 438c2ecf20Sopenharmony_ci int fd1, fd2; 448c2ecf20Sopenharmony_ci struct stat st1, st2; 458c2ecf20Sopenharmony_ci void *map1, *map2; 468c2ecf20Sopenharmony_ci bool ret = false; 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci fd1 = open(file1, O_RDONLY); 498c2ecf20Sopenharmony_ci if (fd1 < 0) 508c2ecf20Sopenharmony_ci return ret; 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci fd2 = open(file2, O_RDONLY); 538c2ecf20Sopenharmony_ci if (fd2 < 0) 548c2ecf20Sopenharmony_ci goto close1; 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci ret = fstat(fd1, &st1); 578c2ecf20Sopenharmony_ci if (ret) 588c2ecf20Sopenharmony_ci goto close2; 598c2ecf20Sopenharmony_ci ret = fstat(fd2, &st2); 608c2ecf20Sopenharmony_ci if (ret) 618c2ecf20Sopenharmony_ci goto close2; 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci if (st1.st_size != st2.st_size) 648c2ecf20Sopenharmony_ci goto close2; 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci map1 = mmap(NULL, st1.st_size, PROT_READ, MAP_PRIVATE, fd1, 0); 678c2ecf20Sopenharmony_ci if (map1 == MAP_FAILED) 688c2ecf20Sopenharmony_ci goto close2; 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci map2 = mmap(NULL, st2.st_size, PROT_READ, MAP_PRIVATE, fd2, 0); 718c2ecf20Sopenharmony_ci if (map2 == MAP_FAILED) 728c2ecf20Sopenharmony_ci goto close2; 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci if (bcmp(map1, map2, st1.st_size)) 758c2ecf20Sopenharmony_ci goto close2; 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci ret = true; 788c2ecf20Sopenharmony_ciclose2: 798c2ecf20Sopenharmony_ci close(fd2); 808c2ecf20Sopenharmony_ciclose1: 818c2ecf20Sopenharmony_ci close(fd1); 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci return ret; 848c2ecf20Sopenharmony_ci} 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci/* 878c2ecf20Sopenharmony_ci * Create the parent directory of the given path. 888c2ecf20Sopenharmony_ci * 898c2ecf20Sopenharmony_ci * For example, if 'include/config/auto.conf' is given, create 'include/config'. 908c2ecf20Sopenharmony_ci */ 918c2ecf20Sopenharmony_cistatic int make_parent_dir(const char *path) 928c2ecf20Sopenharmony_ci{ 938c2ecf20Sopenharmony_ci char tmp[PATH_MAX + 1]; 948c2ecf20Sopenharmony_ci char *p; 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci strncpy(tmp, path, sizeof(tmp)); 978c2ecf20Sopenharmony_ci tmp[sizeof(tmp) - 1] = 0; 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci /* Remove the base name. Just return if nothing is left */ 1008c2ecf20Sopenharmony_ci p = strrchr(tmp, '/'); 1018c2ecf20Sopenharmony_ci if (!p) 1028c2ecf20Sopenharmony_ci return 0; 1038c2ecf20Sopenharmony_ci *(p + 1) = 0; 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci /* Just in case it is an absolute path */ 1068c2ecf20Sopenharmony_ci p = tmp; 1078c2ecf20Sopenharmony_ci while (*p == '/') 1088c2ecf20Sopenharmony_ci p++; 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci while ((p = strchr(p, '/'))) { 1118c2ecf20Sopenharmony_ci *p = 0; 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci /* skip if the directory exists */ 1148c2ecf20Sopenharmony_ci if (!is_dir(tmp) && mkdir(tmp, 0755)) 1158c2ecf20Sopenharmony_ci return -1; 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci *p = '/'; 1188c2ecf20Sopenharmony_ci while (*p == '/') 1198c2ecf20Sopenharmony_ci p++; 1208c2ecf20Sopenharmony_ci } 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci return 0; 1238c2ecf20Sopenharmony_ci} 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_cistatic char depfile_path[PATH_MAX]; 1268c2ecf20Sopenharmony_cistatic size_t depfile_prefix_len; 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci/* touch depfile for symbol 'name' */ 1298c2ecf20Sopenharmony_cistatic int conf_touch_dep(const char *name) 1308c2ecf20Sopenharmony_ci{ 1318c2ecf20Sopenharmony_ci int fd, ret; 1328c2ecf20Sopenharmony_ci const char *s; 1338c2ecf20Sopenharmony_ci char *d, c; 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_ci /* check overflow: prefix + name + ".h" + '\0' must fit in buffer. */ 1368c2ecf20Sopenharmony_ci if (depfile_prefix_len + strlen(name) + 3 > sizeof(depfile_path)) 1378c2ecf20Sopenharmony_ci return -1; 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci d = depfile_path + depfile_prefix_len; 1408c2ecf20Sopenharmony_ci s = name; 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci while ((c = *s++)) 1438c2ecf20Sopenharmony_ci *d++ = (c == '_') ? '/' : tolower(c); 1448c2ecf20Sopenharmony_ci strcpy(d, ".h"); 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci /* Assume directory path already exists. */ 1478c2ecf20Sopenharmony_ci fd = open(depfile_path, O_WRONLY | O_CREAT | O_TRUNC, 0644); 1488c2ecf20Sopenharmony_ci if (fd == -1) { 1498c2ecf20Sopenharmony_ci if (errno != ENOENT) 1508c2ecf20Sopenharmony_ci return -1; 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ci ret = make_parent_dir(depfile_path); 1538c2ecf20Sopenharmony_ci if (ret) 1548c2ecf20Sopenharmony_ci return ret; 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci /* Try it again. */ 1578c2ecf20Sopenharmony_ci fd = open(depfile_path, O_WRONLY | O_CREAT | O_TRUNC, 0644); 1588c2ecf20Sopenharmony_ci if (fd == -1) 1598c2ecf20Sopenharmony_ci return -1; 1608c2ecf20Sopenharmony_ci } 1618c2ecf20Sopenharmony_ci close(fd); 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci return 0; 1648c2ecf20Sopenharmony_ci} 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_cistruct conf_printer { 1678c2ecf20Sopenharmony_ci void (*print_symbol)(FILE *, struct symbol *, const char *, void *); 1688c2ecf20Sopenharmony_ci void (*print_comment)(FILE *, const char *, void *); 1698c2ecf20Sopenharmony_ci}; 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_cistatic void conf_warning(const char *fmt, ...) 1728c2ecf20Sopenharmony_ci __attribute__ ((format (printf, 1, 2))); 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_cistatic void conf_message(const char *fmt, ...) 1758c2ecf20Sopenharmony_ci __attribute__ ((format (printf, 1, 2))); 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_cistatic const char *conf_filename; 1788c2ecf20Sopenharmony_cistatic int conf_lineno, conf_warnings; 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_cistatic void conf_warning(const char *fmt, ...) 1818c2ecf20Sopenharmony_ci{ 1828c2ecf20Sopenharmony_ci va_list ap; 1838c2ecf20Sopenharmony_ci va_start(ap, fmt); 1848c2ecf20Sopenharmony_ci fprintf(stderr, "%s:%d:warning: ", conf_filename, conf_lineno); 1858c2ecf20Sopenharmony_ci vfprintf(stderr, fmt, ap); 1868c2ecf20Sopenharmony_ci fprintf(stderr, "\n"); 1878c2ecf20Sopenharmony_ci va_end(ap); 1888c2ecf20Sopenharmony_ci conf_warnings++; 1898c2ecf20Sopenharmony_ci} 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_cistatic void conf_default_message_callback(const char *s) 1928c2ecf20Sopenharmony_ci{ 1938c2ecf20Sopenharmony_ci printf("#\n# "); 1948c2ecf20Sopenharmony_ci printf("%s", s); 1958c2ecf20Sopenharmony_ci printf("\n#\n"); 1968c2ecf20Sopenharmony_ci} 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_cistatic void (*conf_message_callback)(const char *s) = 1998c2ecf20Sopenharmony_ci conf_default_message_callback; 2008c2ecf20Sopenharmony_civoid conf_set_message_callback(void (*fn)(const char *s)) 2018c2ecf20Sopenharmony_ci{ 2028c2ecf20Sopenharmony_ci conf_message_callback = fn; 2038c2ecf20Sopenharmony_ci} 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_cistatic void conf_message(const char *fmt, ...) 2068c2ecf20Sopenharmony_ci{ 2078c2ecf20Sopenharmony_ci va_list ap; 2088c2ecf20Sopenharmony_ci char buf[4096]; 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_ci if (!conf_message_callback) 2118c2ecf20Sopenharmony_ci return; 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_ci va_start(ap, fmt); 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ci vsnprintf(buf, sizeof(buf), fmt, ap); 2168c2ecf20Sopenharmony_ci conf_message_callback(buf); 2178c2ecf20Sopenharmony_ci va_end(ap); 2188c2ecf20Sopenharmony_ci} 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ciconst char *conf_get_configname(void) 2218c2ecf20Sopenharmony_ci{ 2228c2ecf20Sopenharmony_ci char *name = getenv("KCONFIG_CONFIG"); 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_ci return name ? name : ".config"; 2258c2ecf20Sopenharmony_ci} 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_cistatic const char *conf_get_autoconfig_name(void) 2288c2ecf20Sopenharmony_ci{ 2298c2ecf20Sopenharmony_ci char *name = getenv("KCONFIG_AUTOCONFIG"); 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci return name ? name : "include/config/auto.conf"; 2328c2ecf20Sopenharmony_ci} 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_cistatic int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p) 2358c2ecf20Sopenharmony_ci{ 2368c2ecf20Sopenharmony_ci char *p2; 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ci switch (sym->type) { 2398c2ecf20Sopenharmony_ci case S_TRISTATE: 2408c2ecf20Sopenharmony_ci if (p[0] == 'm') { 2418c2ecf20Sopenharmony_ci sym->def[def].tri = mod; 2428c2ecf20Sopenharmony_ci sym->flags |= def_flags; 2438c2ecf20Sopenharmony_ci break; 2448c2ecf20Sopenharmony_ci } 2458c2ecf20Sopenharmony_ci /* fall through */ 2468c2ecf20Sopenharmony_ci case S_BOOLEAN: 2478c2ecf20Sopenharmony_ci if (p[0] == 'y') { 2488c2ecf20Sopenharmony_ci sym->def[def].tri = yes; 2498c2ecf20Sopenharmony_ci sym->flags |= def_flags; 2508c2ecf20Sopenharmony_ci break; 2518c2ecf20Sopenharmony_ci } 2528c2ecf20Sopenharmony_ci if (p[0] == 'n') { 2538c2ecf20Sopenharmony_ci sym->def[def].tri = no; 2548c2ecf20Sopenharmony_ci sym->flags |= def_flags; 2558c2ecf20Sopenharmony_ci break; 2568c2ecf20Sopenharmony_ci } 2578c2ecf20Sopenharmony_ci if (def != S_DEF_AUTO) 2588c2ecf20Sopenharmony_ci conf_warning("symbol value '%s' invalid for %s", 2598c2ecf20Sopenharmony_ci p, sym->name); 2608c2ecf20Sopenharmony_ci return 1; 2618c2ecf20Sopenharmony_ci case S_STRING: 2628c2ecf20Sopenharmony_ci if (*p++ != '"') 2638c2ecf20Sopenharmony_ci break; 2648c2ecf20Sopenharmony_ci for (p2 = p; (p2 = strpbrk(p2, "\"\\")); p2++) { 2658c2ecf20Sopenharmony_ci if (*p2 == '"') { 2668c2ecf20Sopenharmony_ci *p2 = 0; 2678c2ecf20Sopenharmony_ci break; 2688c2ecf20Sopenharmony_ci } 2698c2ecf20Sopenharmony_ci memmove(p2, p2 + 1, strlen(p2)); 2708c2ecf20Sopenharmony_ci } 2718c2ecf20Sopenharmony_ci if (!p2) { 2728c2ecf20Sopenharmony_ci if (def != S_DEF_AUTO) 2738c2ecf20Sopenharmony_ci conf_warning("invalid string found"); 2748c2ecf20Sopenharmony_ci return 1; 2758c2ecf20Sopenharmony_ci } 2768c2ecf20Sopenharmony_ci /* fall through */ 2778c2ecf20Sopenharmony_ci case S_INT: 2788c2ecf20Sopenharmony_ci case S_HEX: 2798c2ecf20Sopenharmony_ci if (sym_string_valid(sym, p)) { 2808c2ecf20Sopenharmony_ci sym->def[def].val = xstrdup(p); 2818c2ecf20Sopenharmony_ci sym->flags |= def_flags; 2828c2ecf20Sopenharmony_ci } else { 2838c2ecf20Sopenharmony_ci if (def != S_DEF_AUTO) 2848c2ecf20Sopenharmony_ci conf_warning("symbol value '%s' invalid for %s", 2858c2ecf20Sopenharmony_ci p, sym->name); 2868c2ecf20Sopenharmony_ci return 1; 2878c2ecf20Sopenharmony_ci } 2888c2ecf20Sopenharmony_ci break; 2898c2ecf20Sopenharmony_ci default: 2908c2ecf20Sopenharmony_ci ; 2918c2ecf20Sopenharmony_ci } 2928c2ecf20Sopenharmony_ci return 0; 2938c2ecf20Sopenharmony_ci} 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_ci#define LINE_GROWTH 16 2968c2ecf20Sopenharmony_cistatic int add_byte(int c, char **lineptr, size_t slen, size_t *n) 2978c2ecf20Sopenharmony_ci{ 2988c2ecf20Sopenharmony_ci char *nline; 2998c2ecf20Sopenharmony_ci size_t new_size = slen + 1; 3008c2ecf20Sopenharmony_ci if (new_size > *n) { 3018c2ecf20Sopenharmony_ci new_size += LINE_GROWTH - 1; 3028c2ecf20Sopenharmony_ci new_size *= 2; 3038c2ecf20Sopenharmony_ci nline = xrealloc(*lineptr, new_size); 3048c2ecf20Sopenharmony_ci if (!nline) 3058c2ecf20Sopenharmony_ci return -1; 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_ci *lineptr = nline; 3088c2ecf20Sopenharmony_ci *n = new_size; 3098c2ecf20Sopenharmony_ci } 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci (*lineptr)[slen] = c; 3128c2ecf20Sopenharmony_ci 3138c2ecf20Sopenharmony_ci return 0; 3148c2ecf20Sopenharmony_ci} 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_cistatic ssize_t compat_getline(char **lineptr, size_t *n, FILE *stream) 3178c2ecf20Sopenharmony_ci{ 3188c2ecf20Sopenharmony_ci char *line = *lineptr; 3198c2ecf20Sopenharmony_ci size_t slen = 0; 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci for (;;) { 3228c2ecf20Sopenharmony_ci int c = getc(stream); 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_ci switch (c) { 3258c2ecf20Sopenharmony_ci case '\n': 3268c2ecf20Sopenharmony_ci if (add_byte(c, &line, slen, n) < 0) 3278c2ecf20Sopenharmony_ci goto e_out; 3288c2ecf20Sopenharmony_ci slen++; 3298c2ecf20Sopenharmony_ci /* fall through */ 3308c2ecf20Sopenharmony_ci case EOF: 3318c2ecf20Sopenharmony_ci if (add_byte('\0', &line, slen, n) < 0) 3328c2ecf20Sopenharmony_ci goto e_out; 3338c2ecf20Sopenharmony_ci *lineptr = line; 3348c2ecf20Sopenharmony_ci if (slen == 0) 3358c2ecf20Sopenharmony_ci return -1; 3368c2ecf20Sopenharmony_ci return slen; 3378c2ecf20Sopenharmony_ci default: 3388c2ecf20Sopenharmony_ci if (add_byte(c, &line, slen, n) < 0) 3398c2ecf20Sopenharmony_ci goto e_out; 3408c2ecf20Sopenharmony_ci slen++; 3418c2ecf20Sopenharmony_ci } 3428c2ecf20Sopenharmony_ci } 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_cie_out: 3458c2ecf20Sopenharmony_ci line[slen-1] = '\0'; 3468c2ecf20Sopenharmony_ci *lineptr = line; 3478c2ecf20Sopenharmony_ci return -1; 3488c2ecf20Sopenharmony_ci} 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ciint conf_read_simple(const char *name, int def) 3518c2ecf20Sopenharmony_ci{ 3528c2ecf20Sopenharmony_ci FILE *in = NULL; 3538c2ecf20Sopenharmony_ci char *line = NULL; 3548c2ecf20Sopenharmony_ci size_t line_asize = 0; 3558c2ecf20Sopenharmony_ci char *p, *p2; 3568c2ecf20Sopenharmony_ci struct symbol *sym; 3578c2ecf20Sopenharmony_ci int i, def_flags; 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_ci if (name) { 3608c2ecf20Sopenharmony_ci in = zconf_fopen(name); 3618c2ecf20Sopenharmony_ci } else { 3628c2ecf20Sopenharmony_ci struct property *prop; 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_ci name = conf_get_configname(); 3658c2ecf20Sopenharmony_ci in = zconf_fopen(name); 3668c2ecf20Sopenharmony_ci if (in) 3678c2ecf20Sopenharmony_ci goto load; 3688c2ecf20Sopenharmony_ci sym_add_change_count(1); 3698c2ecf20Sopenharmony_ci if (!sym_defconfig_list) 3708c2ecf20Sopenharmony_ci return 1; 3718c2ecf20Sopenharmony_ci 3728c2ecf20Sopenharmony_ci for_all_defaults(sym_defconfig_list, prop) { 3738c2ecf20Sopenharmony_ci if (expr_calc_value(prop->visible.expr) == no || 3748c2ecf20Sopenharmony_ci prop->expr->type != E_SYMBOL) 3758c2ecf20Sopenharmony_ci continue; 3768c2ecf20Sopenharmony_ci sym_calc_value(prop->expr->left.sym); 3778c2ecf20Sopenharmony_ci name = sym_get_string_value(prop->expr->left.sym); 3788c2ecf20Sopenharmony_ci in = zconf_fopen(name); 3798c2ecf20Sopenharmony_ci if (in) { 3808c2ecf20Sopenharmony_ci conf_message("using defaults found in %s", 3818c2ecf20Sopenharmony_ci name); 3828c2ecf20Sopenharmony_ci goto load; 3838c2ecf20Sopenharmony_ci } 3848c2ecf20Sopenharmony_ci } 3858c2ecf20Sopenharmony_ci } 3868c2ecf20Sopenharmony_ci if (!in) 3878c2ecf20Sopenharmony_ci return 1; 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_ciload: 3908c2ecf20Sopenharmony_ci conf_filename = name; 3918c2ecf20Sopenharmony_ci conf_lineno = 0; 3928c2ecf20Sopenharmony_ci conf_warnings = 0; 3938c2ecf20Sopenharmony_ci 3948c2ecf20Sopenharmony_ci def_flags = SYMBOL_DEF << def; 3958c2ecf20Sopenharmony_ci for_all_symbols(i, sym) { 3968c2ecf20Sopenharmony_ci sym->flags |= SYMBOL_CHANGED; 3978c2ecf20Sopenharmony_ci sym->flags &= ~(def_flags|SYMBOL_VALID); 3988c2ecf20Sopenharmony_ci if (sym_is_choice(sym)) 3998c2ecf20Sopenharmony_ci sym->flags |= def_flags; 4008c2ecf20Sopenharmony_ci switch (sym->type) { 4018c2ecf20Sopenharmony_ci case S_INT: 4028c2ecf20Sopenharmony_ci case S_HEX: 4038c2ecf20Sopenharmony_ci case S_STRING: 4048c2ecf20Sopenharmony_ci if (sym->def[def].val) 4058c2ecf20Sopenharmony_ci free(sym->def[def].val); 4068c2ecf20Sopenharmony_ci /* fall through */ 4078c2ecf20Sopenharmony_ci default: 4088c2ecf20Sopenharmony_ci sym->def[def].val = NULL; 4098c2ecf20Sopenharmony_ci sym->def[def].tri = no; 4108c2ecf20Sopenharmony_ci } 4118c2ecf20Sopenharmony_ci } 4128c2ecf20Sopenharmony_ci 4138c2ecf20Sopenharmony_ci while (compat_getline(&line, &line_asize, in) != -1) { 4148c2ecf20Sopenharmony_ci conf_lineno++; 4158c2ecf20Sopenharmony_ci sym = NULL; 4168c2ecf20Sopenharmony_ci if (line[0] == '#') { 4178c2ecf20Sopenharmony_ci if (memcmp(line + 2, CONFIG_, strlen(CONFIG_))) 4188c2ecf20Sopenharmony_ci continue; 4198c2ecf20Sopenharmony_ci p = strchr(line + 2 + strlen(CONFIG_), ' '); 4208c2ecf20Sopenharmony_ci if (!p) 4218c2ecf20Sopenharmony_ci continue; 4228c2ecf20Sopenharmony_ci *p++ = 0; 4238c2ecf20Sopenharmony_ci if (strncmp(p, "is not set", 10)) 4248c2ecf20Sopenharmony_ci continue; 4258c2ecf20Sopenharmony_ci if (def == S_DEF_USER) { 4268c2ecf20Sopenharmony_ci sym = sym_find(line + 2 + strlen(CONFIG_)); 4278c2ecf20Sopenharmony_ci if (!sym) { 4288c2ecf20Sopenharmony_ci sym_add_change_count(1); 4298c2ecf20Sopenharmony_ci continue; 4308c2ecf20Sopenharmony_ci } 4318c2ecf20Sopenharmony_ci } else { 4328c2ecf20Sopenharmony_ci sym = sym_lookup(line + 2 + strlen(CONFIG_), 0); 4338c2ecf20Sopenharmony_ci if (sym->type == S_UNKNOWN) 4348c2ecf20Sopenharmony_ci sym->type = S_BOOLEAN; 4358c2ecf20Sopenharmony_ci } 4368c2ecf20Sopenharmony_ci if (sym->flags & def_flags) { 4378c2ecf20Sopenharmony_ci conf_warning("override: reassigning to symbol %s", sym->name); 4388c2ecf20Sopenharmony_ci } 4398c2ecf20Sopenharmony_ci switch (sym->type) { 4408c2ecf20Sopenharmony_ci case S_BOOLEAN: 4418c2ecf20Sopenharmony_ci case S_TRISTATE: 4428c2ecf20Sopenharmony_ci sym->def[def].tri = no; 4438c2ecf20Sopenharmony_ci sym->flags |= def_flags; 4448c2ecf20Sopenharmony_ci break; 4458c2ecf20Sopenharmony_ci default: 4468c2ecf20Sopenharmony_ci ; 4478c2ecf20Sopenharmony_ci } 4488c2ecf20Sopenharmony_ci } else if (memcmp(line, CONFIG_, strlen(CONFIG_)) == 0) { 4498c2ecf20Sopenharmony_ci p = strchr(line + strlen(CONFIG_), '='); 4508c2ecf20Sopenharmony_ci if (!p) 4518c2ecf20Sopenharmony_ci continue; 4528c2ecf20Sopenharmony_ci *p++ = 0; 4538c2ecf20Sopenharmony_ci p2 = strchr(p, '\n'); 4548c2ecf20Sopenharmony_ci if (p2) { 4558c2ecf20Sopenharmony_ci *p2-- = 0; 4568c2ecf20Sopenharmony_ci if (*p2 == '\r') 4578c2ecf20Sopenharmony_ci *p2 = 0; 4588c2ecf20Sopenharmony_ci } 4598c2ecf20Sopenharmony_ci 4608c2ecf20Sopenharmony_ci sym = sym_find(line + strlen(CONFIG_)); 4618c2ecf20Sopenharmony_ci if (!sym) { 4628c2ecf20Sopenharmony_ci if (def == S_DEF_AUTO) 4638c2ecf20Sopenharmony_ci /* 4648c2ecf20Sopenharmony_ci * Reading from include/config/auto.conf 4658c2ecf20Sopenharmony_ci * If CONFIG_FOO previously existed in 4668c2ecf20Sopenharmony_ci * auto.conf but it is missing now, 4678c2ecf20Sopenharmony_ci * include/config/foo.h must be touched. 4688c2ecf20Sopenharmony_ci */ 4698c2ecf20Sopenharmony_ci conf_touch_dep(line + strlen(CONFIG_)); 4708c2ecf20Sopenharmony_ci else 4718c2ecf20Sopenharmony_ci sym_add_change_count(1); 4728c2ecf20Sopenharmony_ci continue; 4738c2ecf20Sopenharmony_ci } 4748c2ecf20Sopenharmony_ci 4758c2ecf20Sopenharmony_ci if (sym->flags & def_flags) { 4768c2ecf20Sopenharmony_ci conf_warning("override: reassigning to symbol %s", sym->name); 4778c2ecf20Sopenharmony_ci } 4788c2ecf20Sopenharmony_ci if (conf_set_sym_val(sym, def, def_flags, p)) 4798c2ecf20Sopenharmony_ci continue; 4808c2ecf20Sopenharmony_ci } else { 4818c2ecf20Sopenharmony_ci if (line[0] != '\r' && line[0] != '\n') 4828c2ecf20Sopenharmony_ci conf_warning("unexpected data: %.*s", 4838c2ecf20Sopenharmony_ci (int)strcspn(line, "\r\n"), line); 4848c2ecf20Sopenharmony_ci 4858c2ecf20Sopenharmony_ci continue; 4868c2ecf20Sopenharmony_ci } 4878c2ecf20Sopenharmony_ci 4888c2ecf20Sopenharmony_ci if (sym && sym_is_choice_value(sym)) { 4898c2ecf20Sopenharmony_ci struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym)); 4908c2ecf20Sopenharmony_ci switch (sym->def[def].tri) { 4918c2ecf20Sopenharmony_ci case no: 4928c2ecf20Sopenharmony_ci break; 4938c2ecf20Sopenharmony_ci case mod: 4948c2ecf20Sopenharmony_ci if (cs->def[def].tri == yes) { 4958c2ecf20Sopenharmony_ci conf_warning("%s creates inconsistent choice state", sym->name); 4968c2ecf20Sopenharmony_ci cs->flags &= ~def_flags; 4978c2ecf20Sopenharmony_ci } 4988c2ecf20Sopenharmony_ci break; 4998c2ecf20Sopenharmony_ci case yes: 5008c2ecf20Sopenharmony_ci if (cs->def[def].tri != no) 5018c2ecf20Sopenharmony_ci conf_warning("override: %s changes choice state", sym->name); 5028c2ecf20Sopenharmony_ci cs->def[def].val = sym; 5038c2ecf20Sopenharmony_ci break; 5048c2ecf20Sopenharmony_ci } 5058c2ecf20Sopenharmony_ci cs->def[def].tri = EXPR_OR(cs->def[def].tri, sym->def[def].tri); 5068c2ecf20Sopenharmony_ci } 5078c2ecf20Sopenharmony_ci } 5088c2ecf20Sopenharmony_ci free(line); 5098c2ecf20Sopenharmony_ci fclose(in); 5108c2ecf20Sopenharmony_ci return 0; 5118c2ecf20Sopenharmony_ci} 5128c2ecf20Sopenharmony_ci 5138c2ecf20Sopenharmony_ciint conf_read(const char *name) 5148c2ecf20Sopenharmony_ci{ 5158c2ecf20Sopenharmony_ci struct symbol *sym; 5168c2ecf20Sopenharmony_ci int conf_unsaved = 0; 5178c2ecf20Sopenharmony_ci int i; 5188c2ecf20Sopenharmony_ci 5198c2ecf20Sopenharmony_ci sym_set_change_count(0); 5208c2ecf20Sopenharmony_ci 5218c2ecf20Sopenharmony_ci if (conf_read_simple(name, S_DEF_USER)) { 5228c2ecf20Sopenharmony_ci sym_calc_value(modules_sym); 5238c2ecf20Sopenharmony_ci return 1; 5248c2ecf20Sopenharmony_ci } 5258c2ecf20Sopenharmony_ci 5268c2ecf20Sopenharmony_ci sym_calc_value(modules_sym); 5278c2ecf20Sopenharmony_ci 5288c2ecf20Sopenharmony_ci for_all_symbols(i, sym) { 5298c2ecf20Sopenharmony_ci sym_calc_value(sym); 5308c2ecf20Sopenharmony_ci if (sym_is_choice(sym) || (sym->flags & SYMBOL_NO_WRITE)) 5318c2ecf20Sopenharmony_ci continue; 5328c2ecf20Sopenharmony_ci if (sym_has_value(sym) && (sym->flags & SYMBOL_WRITE)) { 5338c2ecf20Sopenharmony_ci /* check that calculated value agrees with saved value */ 5348c2ecf20Sopenharmony_ci switch (sym->type) { 5358c2ecf20Sopenharmony_ci case S_BOOLEAN: 5368c2ecf20Sopenharmony_ci case S_TRISTATE: 5378c2ecf20Sopenharmony_ci if (sym->def[S_DEF_USER].tri == sym_get_tristate_value(sym)) 5388c2ecf20Sopenharmony_ci continue; 5398c2ecf20Sopenharmony_ci break; 5408c2ecf20Sopenharmony_ci default: 5418c2ecf20Sopenharmony_ci if (!strcmp(sym->curr.val, sym->def[S_DEF_USER].val)) 5428c2ecf20Sopenharmony_ci continue; 5438c2ecf20Sopenharmony_ci break; 5448c2ecf20Sopenharmony_ci } 5458c2ecf20Sopenharmony_ci } else if (!sym_has_value(sym) && !(sym->flags & SYMBOL_WRITE)) 5468c2ecf20Sopenharmony_ci /* no previous value and not saved */ 5478c2ecf20Sopenharmony_ci continue; 5488c2ecf20Sopenharmony_ci conf_unsaved++; 5498c2ecf20Sopenharmony_ci /* maybe print value in verbose mode... */ 5508c2ecf20Sopenharmony_ci } 5518c2ecf20Sopenharmony_ci 5528c2ecf20Sopenharmony_ci for_all_symbols(i, sym) { 5538c2ecf20Sopenharmony_ci if (sym_has_value(sym) && !sym_is_choice_value(sym)) { 5548c2ecf20Sopenharmony_ci /* Reset values of generates values, so they'll appear 5558c2ecf20Sopenharmony_ci * as new, if they should become visible, but that 5568c2ecf20Sopenharmony_ci * doesn't quite work if the Kconfig and the saved 5578c2ecf20Sopenharmony_ci * configuration disagree. 5588c2ecf20Sopenharmony_ci */ 5598c2ecf20Sopenharmony_ci if (sym->visible == no && !conf_unsaved) 5608c2ecf20Sopenharmony_ci sym->flags &= ~SYMBOL_DEF_USER; 5618c2ecf20Sopenharmony_ci switch (sym->type) { 5628c2ecf20Sopenharmony_ci case S_STRING: 5638c2ecf20Sopenharmony_ci case S_INT: 5648c2ecf20Sopenharmony_ci case S_HEX: 5658c2ecf20Sopenharmony_ci /* Reset a string value if it's out of range */ 5668c2ecf20Sopenharmony_ci if (sym_string_within_range(sym, sym->def[S_DEF_USER].val)) 5678c2ecf20Sopenharmony_ci break; 5688c2ecf20Sopenharmony_ci sym->flags &= ~(SYMBOL_VALID|SYMBOL_DEF_USER); 5698c2ecf20Sopenharmony_ci conf_unsaved++; 5708c2ecf20Sopenharmony_ci break; 5718c2ecf20Sopenharmony_ci default: 5728c2ecf20Sopenharmony_ci break; 5738c2ecf20Sopenharmony_ci } 5748c2ecf20Sopenharmony_ci } 5758c2ecf20Sopenharmony_ci } 5768c2ecf20Sopenharmony_ci 5778c2ecf20Sopenharmony_ci sym_add_change_count(conf_warnings || conf_unsaved); 5788c2ecf20Sopenharmony_ci 5798c2ecf20Sopenharmony_ci return 0; 5808c2ecf20Sopenharmony_ci} 5818c2ecf20Sopenharmony_ci 5828c2ecf20Sopenharmony_ci/* 5838c2ecf20Sopenharmony_ci * Kconfig configuration printer 5848c2ecf20Sopenharmony_ci * 5858c2ecf20Sopenharmony_ci * This printer is used when generating the resulting configuration after 5868c2ecf20Sopenharmony_ci * kconfig invocation and `defconfig' files. Unset symbol might be omitted by 5878c2ecf20Sopenharmony_ci * passing a non-NULL argument to the printer. 5888c2ecf20Sopenharmony_ci * 5898c2ecf20Sopenharmony_ci */ 5908c2ecf20Sopenharmony_cistatic void 5918c2ecf20Sopenharmony_cikconfig_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg) 5928c2ecf20Sopenharmony_ci{ 5938c2ecf20Sopenharmony_ci 5948c2ecf20Sopenharmony_ci switch (sym->type) { 5958c2ecf20Sopenharmony_ci case S_BOOLEAN: 5968c2ecf20Sopenharmony_ci case S_TRISTATE: 5978c2ecf20Sopenharmony_ci if (*value == 'n') { 5988c2ecf20Sopenharmony_ci bool skip_unset = (arg != NULL); 5998c2ecf20Sopenharmony_ci 6008c2ecf20Sopenharmony_ci if (!skip_unset) 6018c2ecf20Sopenharmony_ci fprintf(fp, "# %s%s is not set\n", 6028c2ecf20Sopenharmony_ci CONFIG_, sym->name); 6038c2ecf20Sopenharmony_ci return; 6048c2ecf20Sopenharmony_ci } 6058c2ecf20Sopenharmony_ci break; 6068c2ecf20Sopenharmony_ci default: 6078c2ecf20Sopenharmony_ci break; 6088c2ecf20Sopenharmony_ci } 6098c2ecf20Sopenharmony_ci 6108c2ecf20Sopenharmony_ci fprintf(fp, "%s%s=%s\n", CONFIG_, sym->name, value); 6118c2ecf20Sopenharmony_ci} 6128c2ecf20Sopenharmony_ci 6138c2ecf20Sopenharmony_cistatic void 6148c2ecf20Sopenharmony_cikconfig_print_comment(FILE *fp, const char *value, void *arg) 6158c2ecf20Sopenharmony_ci{ 6168c2ecf20Sopenharmony_ci const char *p = value; 6178c2ecf20Sopenharmony_ci size_t l; 6188c2ecf20Sopenharmony_ci 6198c2ecf20Sopenharmony_ci for (;;) { 6208c2ecf20Sopenharmony_ci l = strcspn(p, "\n"); 6218c2ecf20Sopenharmony_ci fprintf(fp, "#"); 6228c2ecf20Sopenharmony_ci if (l) { 6238c2ecf20Sopenharmony_ci fprintf(fp, " "); 6248c2ecf20Sopenharmony_ci xfwrite(p, l, 1, fp); 6258c2ecf20Sopenharmony_ci p += l; 6268c2ecf20Sopenharmony_ci } 6278c2ecf20Sopenharmony_ci fprintf(fp, "\n"); 6288c2ecf20Sopenharmony_ci if (*p++ == '\0') 6298c2ecf20Sopenharmony_ci break; 6308c2ecf20Sopenharmony_ci } 6318c2ecf20Sopenharmony_ci} 6328c2ecf20Sopenharmony_ci 6338c2ecf20Sopenharmony_cistatic struct conf_printer kconfig_printer_cb = 6348c2ecf20Sopenharmony_ci{ 6358c2ecf20Sopenharmony_ci .print_symbol = kconfig_print_symbol, 6368c2ecf20Sopenharmony_ci .print_comment = kconfig_print_comment, 6378c2ecf20Sopenharmony_ci}; 6388c2ecf20Sopenharmony_ci 6398c2ecf20Sopenharmony_ci/* 6408c2ecf20Sopenharmony_ci * Header printer 6418c2ecf20Sopenharmony_ci * 6428c2ecf20Sopenharmony_ci * This printer is used when generating the `include/generated/autoconf.h' file. 6438c2ecf20Sopenharmony_ci */ 6448c2ecf20Sopenharmony_cistatic void 6458c2ecf20Sopenharmony_ciheader_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg) 6468c2ecf20Sopenharmony_ci{ 6478c2ecf20Sopenharmony_ci 6488c2ecf20Sopenharmony_ci switch (sym->type) { 6498c2ecf20Sopenharmony_ci case S_BOOLEAN: 6508c2ecf20Sopenharmony_ci case S_TRISTATE: { 6518c2ecf20Sopenharmony_ci const char *suffix = ""; 6528c2ecf20Sopenharmony_ci 6538c2ecf20Sopenharmony_ci switch (*value) { 6548c2ecf20Sopenharmony_ci case 'n': 6558c2ecf20Sopenharmony_ci break; 6568c2ecf20Sopenharmony_ci case 'm': 6578c2ecf20Sopenharmony_ci suffix = "_MODULE"; 6588c2ecf20Sopenharmony_ci /* fall through */ 6598c2ecf20Sopenharmony_ci default: 6608c2ecf20Sopenharmony_ci fprintf(fp, "#define %s%s%s 1\n", 6618c2ecf20Sopenharmony_ci CONFIG_, sym->name, suffix); 6628c2ecf20Sopenharmony_ci } 6638c2ecf20Sopenharmony_ci break; 6648c2ecf20Sopenharmony_ci } 6658c2ecf20Sopenharmony_ci case S_HEX: { 6668c2ecf20Sopenharmony_ci const char *prefix = ""; 6678c2ecf20Sopenharmony_ci 6688c2ecf20Sopenharmony_ci if (value[0] != '0' || (value[1] != 'x' && value[1] != 'X')) 6698c2ecf20Sopenharmony_ci prefix = "0x"; 6708c2ecf20Sopenharmony_ci fprintf(fp, "#define %s%s %s%s\n", 6718c2ecf20Sopenharmony_ci CONFIG_, sym->name, prefix, value); 6728c2ecf20Sopenharmony_ci break; 6738c2ecf20Sopenharmony_ci } 6748c2ecf20Sopenharmony_ci case S_STRING: 6758c2ecf20Sopenharmony_ci case S_INT: 6768c2ecf20Sopenharmony_ci fprintf(fp, "#define %s%s %s\n", 6778c2ecf20Sopenharmony_ci CONFIG_, sym->name, value); 6788c2ecf20Sopenharmony_ci break; 6798c2ecf20Sopenharmony_ci default: 6808c2ecf20Sopenharmony_ci break; 6818c2ecf20Sopenharmony_ci } 6828c2ecf20Sopenharmony_ci 6838c2ecf20Sopenharmony_ci} 6848c2ecf20Sopenharmony_ci 6858c2ecf20Sopenharmony_cistatic void 6868c2ecf20Sopenharmony_ciheader_print_comment(FILE *fp, const char *value, void *arg) 6878c2ecf20Sopenharmony_ci{ 6888c2ecf20Sopenharmony_ci const char *p = value; 6898c2ecf20Sopenharmony_ci size_t l; 6908c2ecf20Sopenharmony_ci 6918c2ecf20Sopenharmony_ci fprintf(fp, "/*\n"); 6928c2ecf20Sopenharmony_ci for (;;) { 6938c2ecf20Sopenharmony_ci l = strcspn(p, "\n"); 6948c2ecf20Sopenharmony_ci fprintf(fp, " *"); 6958c2ecf20Sopenharmony_ci if (l) { 6968c2ecf20Sopenharmony_ci fprintf(fp, " "); 6978c2ecf20Sopenharmony_ci xfwrite(p, l, 1, fp); 6988c2ecf20Sopenharmony_ci p += l; 6998c2ecf20Sopenharmony_ci } 7008c2ecf20Sopenharmony_ci fprintf(fp, "\n"); 7018c2ecf20Sopenharmony_ci if (*p++ == '\0') 7028c2ecf20Sopenharmony_ci break; 7038c2ecf20Sopenharmony_ci } 7048c2ecf20Sopenharmony_ci fprintf(fp, " */\n"); 7058c2ecf20Sopenharmony_ci} 7068c2ecf20Sopenharmony_ci 7078c2ecf20Sopenharmony_cistatic struct conf_printer header_printer_cb = 7088c2ecf20Sopenharmony_ci{ 7098c2ecf20Sopenharmony_ci .print_symbol = header_print_symbol, 7108c2ecf20Sopenharmony_ci .print_comment = header_print_comment, 7118c2ecf20Sopenharmony_ci}; 7128c2ecf20Sopenharmony_ci 7138c2ecf20Sopenharmony_cistatic void conf_write_symbol(FILE *fp, struct symbol *sym, 7148c2ecf20Sopenharmony_ci struct conf_printer *printer, void *printer_arg) 7158c2ecf20Sopenharmony_ci{ 7168c2ecf20Sopenharmony_ci const char *str; 7178c2ecf20Sopenharmony_ci 7188c2ecf20Sopenharmony_ci switch (sym->type) { 7198c2ecf20Sopenharmony_ci case S_UNKNOWN: 7208c2ecf20Sopenharmony_ci break; 7218c2ecf20Sopenharmony_ci case S_STRING: 7228c2ecf20Sopenharmony_ci str = sym_get_string_value(sym); 7238c2ecf20Sopenharmony_ci str = sym_escape_string_value(str); 7248c2ecf20Sopenharmony_ci printer->print_symbol(fp, sym, str, printer_arg); 7258c2ecf20Sopenharmony_ci free((void *)str); 7268c2ecf20Sopenharmony_ci break; 7278c2ecf20Sopenharmony_ci default: 7288c2ecf20Sopenharmony_ci str = sym_get_string_value(sym); 7298c2ecf20Sopenharmony_ci printer->print_symbol(fp, sym, str, printer_arg); 7308c2ecf20Sopenharmony_ci } 7318c2ecf20Sopenharmony_ci} 7328c2ecf20Sopenharmony_ci 7338c2ecf20Sopenharmony_cistatic void 7348c2ecf20Sopenharmony_ciconf_write_heading(FILE *fp, struct conf_printer *printer, void *printer_arg) 7358c2ecf20Sopenharmony_ci{ 7368c2ecf20Sopenharmony_ci char buf[256]; 7378c2ecf20Sopenharmony_ci 7388c2ecf20Sopenharmony_ci snprintf(buf, sizeof(buf), 7398c2ecf20Sopenharmony_ci "\n" 7408c2ecf20Sopenharmony_ci "Automatically generated file; DO NOT EDIT.\n" 7418c2ecf20Sopenharmony_ci "%s\n", 7428c2ecf20Sopenharmony_ci rootmenu.prompt->text); 7438c2ecf20Sopenharmony_ci 7448c2ecf20Sopenharmony_ci printer->print_comment(fp, buf, printer_arg); 7458c2ecf20Sopenharmony_ci} 7468c2ecf20Sopenharmony_ci 7478c2ecf20Sopenharmony_ci/* 7488c2ecf20Sopenharmony_ci * Write out a minimal config. 7498c2ecf20Sopenharmony_ci * All values that has default values are skipped as this is redundant. 7508c2ecf20Sopenharmony_ci */ 7518c2ecf20Sopenharmony_ciint conf_write_defconfig(const char *filename) 7528c2ecf20Sopenharmony_ci{ 7538c2ecf20Sopenharmony_ci struct symbol *sym; 7548c2ecf20Sopenharmony_ci struct menu *menu; 7558c2ecf20Sopenharmony_ci FILE *out; 7568c2ecf20Sopenharmony_ci 7578c2ecf20Sopenharmony_ci out = fopen(filename, "w"); 7588c2ecf20Sopenharmony_ci if (!out) 7598c2ecf20Sopenharmony_ci return 1; 7608c2ecf20Sopenharmony_ci 7618c2ecf20Sopenharmony_ci sym_clear_all_valid(); 7628c2ecf20Sopenharmony_ci 7638c2ecf20Sopenharmony_ci /* Traverse all menus to find all relevant symbols */ 7648c2ecf20Sopenharmony_ci menu = rootmenu.list; 7658c2ecf20Sopenharmony_ci 7668c2ecf20Sopenharmony_ci while (menu != NULL) 7678c2ecf20Sopenharmony_ci { 7688c2ecf20Sopenharmony_ci sym = menu->sym; 7698c2ecf20Sopenharmony_ci if (sym == NULL) { 7708c2ecf20Sopenharmony_ci if (!menu_is_visible(menu)) 7718c2ecf20Sopenharmony_ci goto next_menu; 7728c2ecf20Sopenharmony_ci } else if (!sym_is_choice(sym)) { 7738c2ecf20Sopenharmony_ci sym_calc_value(sym); 7748c2ecf20Sopenharmony_ci if (!(sym->flags & SYMBOL_WRITE)) 7758c2ecf20Sopenharmony_ci goto next_menu; 7768c2ecf20Sopenharmony_ci sym->flags &= ~SYMBOL_WRITE; 7778c2ecf20Sopenharmony_ci /* If we cannot change the symbol - skip */ 7788c2ecf20Sopenharmony_ci if (!sym_is_changeable(sym)) 7798c2ecf20Sopenharmony_ci goto next_menu; 7808c2ecf20Sopenharmony_ci /* If symbol equals to default value - skip */ 7818c2ecf20Sopenharmony_ci if (strcmp(sym_get_string_value(sym), sym_get_string_default(sym)) == 0) 7828c2ecf20Sopenharmony_ci goto next_menu; 7838c2ecf20Sopenharmony_ci 7848c2ecf20Sopenharmony_ci /* 7858c2ecf20Sopenharmony_ci * If symbol is a choice value and equals to the 7868c2ecf20Sopenharmony_ci * default for a choice - skip. 7878c2ecf20Sopenharmony_ci * But only if value is bool and equal to "y" and 7888c2ecf20Sopenharmony_ci * choice is not "optional". 7898c2ecf20Sopenharmony_ci * (If choice is "optional" then all values can be "n") 7908c2ecf20Sopenharmony_ci */ 7918c2ecf20Sopenharmony_ci if (sym_is_choice_value(sym)) { 7928c2ecf20Sopenharmony_ci struct symbol *cs; 7938c2ecf20Sopenharmony_ci struct symbol *ds; 7948c2ecf20Sopenharmony_ci 7958c2ecf20Sopenharmony_ci cs = prop_get_symbol(sym_get_choice_prop(sym)); 7968c2ecf20Sopenharmony_ci ds = sym_choice_default(cs); 7978c2ecf20Sopenharmony_ci if (!sym_is_optional(cs) && sym == ds) { 7988c2ecf20Sopenharmony_ci if ((sym->type == S_BOOLEAN) && 7998c2ecf20Sopenharmony_ci sym_get_tristate_value(sym) == yes) 8008c2ecf20Sopenharmony_ci goto next_menu; 8018c2ecf20Sopenharmony_ci } 8028c2ecf20Sopenharmony_ci } 8038c2ecf20Sopenharmony_ci conf_write_symbol(out, sym, &kconfig_printer_cb, NULL); 8048c2ecf20Sopenharmony_ci } 8058c2ecf20Sopenharmony_cinext_menu: 8068c2ecf20Sopenharmony_ci if (menu->list != NULL) { 8078c2ecf20Sopenharmony_ci menu = menu->list; 8088c2ecf20Sopenharmony_ci } 8098c2ecf20Sopenharmony_ci else if (menu->next != NULL) { 8108c2ecf20Sopenharmony_ci menu = menu->next; 8118c2ecf20Sopenharmony_ci } else { 8128c2ecf20Sopenharmony_ci while ((menu = menu->parent)) { 8138c2ecf20Sopenharmony_ci if (menu->next != NULL) { 8148c2ecf20Sopenharmony_ci menu = menu->next; 8158c2ecf20Sopenharmony_ci break; 8168c2ecf20Sopenharmony_ci } 8178c2ecf20Sopenharmony_ci } 8188c2ecf20Sopenharmony_ci } 8198c2ecf20Sopenharmony_ci } 8208c2ecf20Sopenharmony_ci fclose(out); 8218c2ecf20Sopenharmony_ci return 0; 8228c2ecf20Sopenharmony_ci} 8238c2ecf20Sopenharmony_ci 8248c2ecf20Sopenharmony_ciint conf_write(const char *name) 8258c2ecf20Sopenharmony_ci{ 8268c2ecf20Sopenharmony_ci FILE *out; 8278c2ecf20Sopenharmony_ci struct symbol *sym; 8288c2ecf20Sopenharmony_ci struct menu *menu; 8298c2ecf20Sopenharmony_ci const char *str; 8308c2ecf20Sopenharmony_ci char tmpname[PATH_MAX + 1], oldname[PATH_MAX + 1]; 8318c2ecf20Sopenharmony_ci char *env; 8328c2ecf20Sopenharmony_ci int i; 8338c2ecf20Sopenharmony_ci bool need_newline = false; 8348c2ecf20Sopenharmony_ci 8358c2ecf20Sopenharmony_ci if (!name) 8368c2ecf20Sopenharmony_ci name = conf_get_configname(); 8378c2ecf20Sopenharmony_ci 8388c2ecf20Sopenharmony_ci if (!*name) { 8398c2ecf20Sopenharmony_ci fprintf(stderr, "config name is empty\n"); 8408c2ecf20Sopenharmony_ci return -1; 8418c2ecf20Sopenharmony_ci } 8428c2ecf20Sopenharmony_ci 8438c2ecf20Sopenharmony_ci if (is_dir(name)) { 8448c2ecf20Sopenharmony_ci fprintf(stderr, "%s: Is a directory\n", name); 8458c2ecf20Sopenharmony_ci return -1; 8468c2ecf20Sopenharmony_ci } 8478c2ecf20Sopenharmony_ci 8488c2ecf20Sopenharmony_ci if (make_parent_dir(name)) 8498c2ecf20Sopenharmony_ci return -1; 8508c2ecf20Sopenharmony_ci 8518c2ecf20Sopenharmony_ci env = getenv("KCONFIG_OVERWRITECONFIG"); 8528c2ecf20Sopenharmony_ci if (env && *env) { 8538c2ecf20Sopenharmony_ci *tmpname = 0; 8548c2ecf20Sopenharmony_ci out = fopen(name, "w"); 8558c2ecf20Sopenharmony_ci } else { 8568c2ecf20Sopenharmony_ci snprintf(tmpname, sizeof(tmpname), "%s.%d.tmp", 8578c2ecf20Sopenharmony_ci name, (int)getpid()); 8588c2ecf20Sopenharmony_ci out = fopen(tmpname, "w"); 8598c2ecf20Sopenharmony_ci } 8608c2ecf20Sopenharmony_ci if (!out) 8618c2ecf20Sopenharmony_ci return 1; 8628c2ecf20Sopenharmony_ci 8638c2ecf20Sopenharmony_ci conf_write_heading(out, &kconfig_printer_cb, NULL); 8648c2ecf20Sopenharmony_ci 8658c2ecf20Sopenharmony_ci if (!conf_get_changed()) 8668c2ecf20Sopenharmony_ci sym_clear_all_valid(); 8678c2ecf20Sopenharmony_ci 8688c2ecf20Sopenharmony_ci menu = rootmenu.list; 8698c2ecf20Sopenharmony_ci while (menu) { 8708c2ecf20Sopenharmony_ci sym = menu->sym; 8718c2ecf20Sopenharmony_ci if (!sym) { 8728c2ecf20Sopenharmony_ci if (!menu_is_visible(menu)) 8738c2ecf20Sopenharmony_ci goto next; 8748c2ecf20Sopenharmony_ci str = menu_get_prompt(menu); 8758c2ecf20Sopenharmony_ci fprintf(out, "\n" 8768c2ecf20Sopenharmony_ci "#\n" 8778c2ecf20Sopenharmony_ci "# %s\n" 8788c2ecf20Sopenharmony_ci "#\n", str); 8798c2ecf20Sopenharmony_ci need_newline = false; 8808c2ecf20Sopenharmony_ci } else if (!(sym->flags & SYMBOL_CHOICE) && 8818c2ecf20Sopenharmony_ci !(sym->flags & SYMBOL_WRITTEN)) { 8828c2ecf20Sopenharmony_ci sym_calc_value(sym); 8838c2ecf20Sopenharmony_ci if (!(sym->flags & SYMBOL_WRITE)) 8848c2ecf20Sopenharmony_ci goto next; 8858c2ecf20Sopenharmony_ci if (need_newline) { 8868c2ecf20Sopenharmony_ci fprintf(out, "\n"); 8878c2ecf20Sopenharmony_ci need_newline = false; 8888c2ecf20Sopenharmony_ci } 8898c2ecf20Sopenharmony_ci sym->flags |= SYMBOL_WRITTEN; 8908c2ecf20Sopenharmony_ci conf_write_symbol(out, sym, &kconfig_printer_cb, NULL); 8918c2ecf20Sopenharmony_ci } 8928c2ecf20Sopenharmony_ci 8938c2ecf20Sopenharmony_cinext: 8948c2ecf20Sopenharmony_ci if (menu->list) { 8958c2ecf20Sopenharmony_ci menu = menu->list; 8968c2ecf20Sopenharmony_ci continue; 8978c2ecf20Sopenharmony_ci } 8988c2ecf20Sopenharmony_ci if (menu->next) 8998c2ecf20Sopenharmony_ci menu = menu->next; 9008c2ecf20Sopenharmony_ci else while ((menu = menu->parent)) { 9018c2ecf20Sopenharmony_ci if (!menu->sym && menu_is_visible(menu) && 9028c2ecf20Sopenharmony_ci menu != &rootmenu) { 9038c2ecf20Sopenharmony_ci str = menu_get_prompt(menu); 9048c2ecf20Sopenharmony_ci fprintf(out, "# end of %s\n", str); 9058c2ecf20Sopenharmony_ci need_newline = true; 9068c2ecf20Sopenharmony_ci } 9078c2ecf20Sopenharmony_ci if (menu->next) { 9088c2ecf20Sopenharmony_ci menu = menu->next; 9098c2ecf20Sopenharmony_ci break; 9108c2ecf20Sopenharmony_ci } 9118c2ecf20Sopenharmony_ci } 9128c2ecf20Sopenharmony_ci } 9138c2ecf20Sopenharmony_ci fclose(out); 9148c2ecf20Sopenharmony_ci 9158c2ecf20Sopenharmony_ci for_all_symbols(i, sym) 9168c2ecf20Sopenharmony_ci sym->flags &= ~SYMBOL_WRITTEN; 9178c2ecf20Sopenharmony_ci 9188c2ecf20Sopenharmony_ci if (*tmpname) { 9198c2ecf20Sopenharmony_ci if (is_same(name, tmpname)) { 9208c2ecf20Sopenharmony_ci conf_message("No change to %s", name); 9218c2ecf20Sopenharmony_ci unlink(tmpname); 9228c2ecf20Sopenharmony_ci sym_set_change_count(0); 9238c2ecf20Sopenharmony_ci return 0; 9248c2ecf20Sopenharmony_ci } 9258c2ecf20Sopenharmony_ci 9268c2ecf20Sopenharmony_ci snprintf(oldname, sizeof(oldname), "%s.old", name); 9278c2ecf20Sopenharmony_ci rename(name, oldname); 9288c2ecf20Sopenharmony_ci if (rename(tmpname, name)) 9298c2ecf20Sopenharmony_ci return 1; 9308c2ecf20Sopenharmony_ci } 9318c2ecf20Sopenharmony_ci 9328c2ecf20Sopenharmony_ci conf_message("configuration written to %s", name); 9338c2ecf20Sopenharmony_ci 9348c2ecf20Sopenharmony_ci sym_set_change_count(0); 9358c2ecf20Sopenharmony_ci 9368c2ecf20Sopenharmony_ci return 0; 9378c2ecf20Sopenharmony_ci} 9388c2ecf20Sopenharmony_ci 9398c2ecf20Sopenharmony_ci/* write a dependency file as used by kbuild to track dependencies */ 9408c2ecf20Sopenharmony_cistatic int conf_write_dep(const char *name) 9418c2ecf20Sopenharmony_ci{ 9428c2ecf20Sopenharmony_ci struct file *file; 9438c2ecf20Sopenharmony_ci FILE *out; 9448c2ecf20Sopenharmony_ci 9458c2ecf20Sopenharmony_ci out = fopen("..config.tmp", "w"); 9468c2ecf20Sopenharmony_ci if (!out) 9478c2ecf20Sopenharmony_ci return 1; 9488c2ecf20Sopenharmony_ci fprintf(out, "deps_config := \\\n"); 9498c2ecf20Sopenharmony_ci for (file = file_list; file; file = file->next) { 9508c2ecf20Sopenharmony_ci if (file->next) 9518c2ecf20Sopenharmony_ci fprintf(out, "\t%s \\\n", file->name); 9528c2ecf20Sopenharmony_ci else 9538c2ecf20Sopenharmony_ci fprintf(out, "\t%s\n", file->name); 9548c2ecf20Sopenharmony_ci } 9558c2ecf20Sopenharmony_ci fprintf(out, "\n%s: \\\n" 9568c2ecf20Sopenharmony_ci "\t$(deps_config)\n\n", conf_get_autoconfig_name()); 9578c2ecf20Sopenharmony_ci 9588c2ecf20Sopenharmony_ci env_write_dep(out, conf_get_autoconfig_name()); 9598c2ecf20Sopenharmony_ci 9608c2ecf20Sopenharmony_ci fprintf(out, "\n$(deps_config): ;\n"); 9618c2ecf20Sopenharmony_ci fclose(out); 9628c2ecf20Sopenharmony_ci 9638c2ecf20Sopenharmony_ci if (make_parent_dir(name)) 9648c2ecf20Sopenharmony_ci return 1; 9658c2ecf20Sopenharmony_ci rename("..config.tmp", name); 9668c2ecf20Sopenharmony_ci return 0; 9678c2ecf20Sopenharmony_ci} 9688c2ecf20Sopenharmony_ci 9698c2ecf20Sopenharmony_cistatic int conf_touch_deps(void) 9708c2ecf20Sopenharmony_ci{ 9718c2ecf20Sopenharmony_ci const char *name, *tmp; 9728c2ecf20Sopenharmony_ci struct symbol *sym; 9738c2ecf20Sopenharmony_ci int res, i; 9748c2ecf20Sopenharmony_ci 9758c2ecf20Sopenharmony_ci name = conf_get_autoconfig_name(); 9768c2ecf20Sopenharmony_ci tmp = strrchr(name, '/'); 9778c2ecf20Sopenharmony_ci depfile_prefix_len = tmp ? tmp - name + 1 : 0; 9788c2ecf20Sopenharmony_ci if (depfile_prefix_len + 1 > sizeof(depfile_path)) 9798c2ecf20Sopenharmony_ci return -1; 9808c2ecf20Sopenharmony_ci 9818c2ecf20Sopenharmony_ci strncpy(depfile_path, name, depfile_prefix_len); 9828c2ecf20Sopenharmony_ci depfile_path[depfile_prefix_len] = 0; 9838c2ecf20Sopenharmony_ci 9848c2ecf20Sopenharmony_ci conf_read_simple(name, S_DEF_AUTO); 9858c2ecf20Sopenharmony_ci sym_calc_value(modules_sym); 9868c2ecf20Sopenharmony_ci 9878c2ecf20Sopenharmony_ci for_all_symbols(i, sym) { 9888c2ecf20Sopenharmony_ci sym_calc_value(sym); 9898c2ecf20Sopenharmony_ci if ((sym->flags & SYMBOL_NO_WRITE) || !sym->name) 9908c2ecf20Sopenharmony_ci continue; 9918c2ecf20Sopenharmony_ci if (sym->flags & SYMBOL_WRITE) { 9928c2ecf20Sopenharmony_ci if (sym->flags & SYMBOL_DEF_AUTO) { 9938c2ecf20Sopenharmony_ci /* 9948c2ecf20Sopenharmony_ci * symbol has old and new value, 9958c2ecf20Sopenharmony_ci * so compare them... 9968c2ecf20Sopenharmony_ci */ 9978c2ecf20Sopenharmony_ci switch (sym->type) { 9988c2ecf20Sopenharmony_ci case S_BOOLEAN: 9998c2ecf20Sopenharmony_ci case S_TRISTATE: 10008c2ecf20Sopenharmony_ci if (sym_get_tristate_value(sym) == 10018c2ecf20Sopenharmony_ci sym->def[S_DEF_AUTO].tri) 10028c2ecf20Sopenharmony_ci continue; 10038c2ecf20Sopenharmony_ci break; 10048c2ecf20Sopenharmony_ci case S_STRING: 10058c2ecf20Sopenharmony_ci case S_HEX: 10068c2ecf20Sopenharmony_ci case S_INT: 10078c2ecf20Sopenharmony_ci if (!strcmp(sym_get_string_value(sym), 10088c2ecf20Sopenharmony_ci sym->def[S_DEF_AUTO].val)) 10098c2ecf20Sopenharmony_ci continue; 10108c2ecf20Sopenharmony_ci break; 10118c2ecf20Sopenharmony_ci default: 10128c2ecf20Sopenharmony_ci break; 10138c2ecf20Sopenharmony_ci } 10148c2ecf20Sopenharmony_ci } else { 10158c2ecf20Sopenharmony_ci /* 10168c2ecf20Sopenharmony_ci * If there is no old value, only 'no' (unset) 10178c2ecf20Sopenharmony_ci * is allowed as new value. 10188c2ecf20Sopenharmony_ci */ 10198c2ecf20Sopenharmony_ci switch (sym->type) { 10208c2ecf20Sopenharmony_ci case S_BOOLEAN: 10218c2ecf20Sopenharmony_ci case S_TRISTATE: 10228c2ecf20Sopenharmony_ci if (sym_get_tristate_value(sym) == no) 10238c2ecf20Sopenharmony_ci continue; 10248c2ecf20Sopenharmony_ci break; 10258c2ecf20Sopenharmony_ci default: 10268c2ecf20Sopenharmony_ci break; 10278c2ecf20Sopenharmony_ci } 10288c2ecf20Sopenharmony_ci } 10298c2ecf20Sopenharmony_ci } else if (!(sym->flags & SYMBOL_DEF_AUTO)) 10308c2ecf20Sopenharmony_ci /* There is neither an old nor a new value. */ 10318c2ecf20Sopenharmony_ci continue; 10328c2ecf20Sopenharmony_ci /* else 10338c2ecf20Sopenharmony_ci * There is an old value, but no new value ('no' (unset) 10348c2ecf20Sopenharmony_ci * isn't saved in auto.conf, so the old value is always 10358c2ecf20Sopenharmony_ci * different from 'no'). 10368c2ecf20Sopenharmony_ci */ 10378c2ecf20Sopenharmony_ci 10388c2ecf20Sopenharmony_ci res = conf_touch_dep(sym->name); 10398c2ecf20Sopenharmony_ci if (res) 10408c2ecf20Sopenharmony_ci return res; 10418c2ecf20Sopenharmony_ci } 10428c2ecf20Sopenharmony_ci 10438c2ecf20Sopenharmony_ci return 0; 10448c2ecf20Sopenharmony_ci} 10458c2ecf20Sopenharmony_ci 10468c2ecf20Sopenharmony_ciint conf_write_autoconf(int overwrite) 10478c2ecf20Sopenharmony_ci{ 10488c2ecf20Sopenharmony_ci struct symbol *sym; 10498c2ecf20Sopenharmony_ci const char *name; 10508c2ecf20Sopenharmony_ci const char *autoconf_name = conf_get_autoconfig_name(); 10518c2ecf20Sopenharmony_ci FILE *out, *out_h; 10528c2ecf20Sopenharmony_ci int i; 10538c2ecf20Sopenharmony_ci 10548c2ecf20Sopenharmony_ci if (!overwrite && is_present(autoconf_name)) 10558c2ecf20Sopenharmony_ci return 0; 10568c2ecf20Sopenharmony_ci 10578c2ecf20Sopenharmony_ci conf_write_dep("include/config/auto.conf.cmd"); 10588c2ecf20Sopenharmony_ci 10598c2ecf20Sopenharmony_ci if (conf_touch_deps()) 10608c2ecf20Sopenharmony_ci return 1; 10618c2ecf20Sopenharmony_ci 10628c2ecf20Sopenharmony_ci out = fopen(".tmpconfig", "w"); 10638c2ecf20Sopenharmony_ci if (!out) 10648c2ecf20Sopenharmony_ci return 1; 10658c2ecf20Sopenharmony_ci 10668c2ecf20Sopenharmony_ci out_h = fopen(".tmpconfig.h", "w"); 10678c2ecf20Sopenharmony_ci if (!out_h) { 10688c2ecf20Sopenharmony_ci fclose(out); 10698c2ecf20Sopenharmony_ci return 1; 10708c2ecf20Sopenharmony_ci } 10718c2ecf20Sopenharmony_ci 10728c2ecf20Sopenharmony_ci conf_write_heading(out, &kconfig_printer_cb, NULL); 10738c2ecf20Sopenharmony_ci conf_write_heading(out_h, &header_printer_cb, NULL); 10748c2ecf20Sopenharmony_ci 10758c2ecf20Sopenharmony_ci for_all_symbols(i, sym) { 10768c2ecf20Sopenharmony_ci sym_calc_value(sym); 10778c2ecf20Sopenharmony_ci if (!(sym->flags & SYMBOL_WRITE) || !sym->name) 10788c2ecf20Sopenharmony_ci continue; 10798c2ecf20Sopenharmony_ci 10808c2ecf20Sopenharmony_ci /* write symbols to auto.conf and autoconf.h */ 10818c2ecf20Sopenharmony_ci conf_write_symbol(out, sym, &kconfig_printer_cb, (void *)1); 10828c2ecf20Sopenharmony_ci conf_write_symbol(out_h, sym, &header_printer_cb, NULL); 10838c2ecf20Sopenharmony_ci } 10848c2ecf20Sopenharmony_ci fclose(out); 10858c2ecf20Sopenharmony_ci fclose(out_h); 10868c2ecf20Sopenharmony_ci 10878c2ecf20Sopenharmony_ci name = getenv("KCONFIG_AUTOHEADER"); 10888c2ecf20Sopenharmony_ci if (!name) 10898c2ecf20Sopenharmony_ci name = "include/generated/autoconf.h"; 10908c2ecf20Sopenharmony_ci if (make_parent_dir(name)) 10918c2ecf20Sopenharmony_ci return 1; 10928c2ecf20Sopenharmony_ci if (rename(".tmpconfig.h", name)) 10938c2ecf20Sopenharmony_ci return 1; 10948c2ecf20Sopenharmony_ci 10958c2ecf20Sopenharmony_ci if (make_parent_dir(autoconf_name)) 10968c2ecf20Sopenharmony_ci return 1; 10978c2ecf20Sopenharmony_ci /* 10988c2ecf20Sopenharmony_ci * This must be the last step, kbuild has a dependency on auto.conf 10998c2ecf20Sopenharmony_ci * and this marks the successful completion of the previous steps. 11008c2ecf20Sopenharmony_ci */ 11018c2ecf20Sopenharmony_ci if (rename(".tmpconfig", autoconf_name)) 11028c2ecf20Sopenharmony_ci return 1; 11038c2ecf20Sopenharmony_ci 11048c2ecf20Sopenharmony_ci return 0; 11058c2ecf20Sopenharmony_ci} 11068c2ecf20Sopenharmony_ci 11078c2ecf20Sopenharmony_cistatic int sym_change_count; 11088c2ecf20Sopenharmony_cistatic void (*conf_changed_callback)(void); 11098c2ecf20Sopenharmony_ci 11108c2ecf20Sopenharmony_civoid sym_set_change_count(int count) 11118c2ecf20Sopenharmony_ci{ 11128c2ecf20Sopenharmony_ci int _sym_change_count = sym_change_count; 11138c2ecf20Sopenharmony_ci sym_change_count = count; 11148c2ecf20Sopenharmony_ci if (conf_changed_callback && 11158c2ecf20Sopenharmony_ci (bool)_sym_change_count != (bool)count) 11168c2ecf20Sopenharmony_ci conf_changed_callback(); 11178c2ecf20Sopenharmony_ci} 11188c2ecf20Sopenharmony_ci 11198c2ecf20Sopenharmony_civoid sym_add_change_count(int count) 11208c2ecf20Sopenharmony_ci{ 11218c2ecf20Sopenharmony_ci sym_set_change_count(count + sym_change_count); 11228c2ecf20Sopenharmony_ci} 11238c2ecf20Sopenharmony_ci 11248c2ecf20Sopenharmony_cibool conf_get_changed(void) 11258c2ecf20Sopenharmony_ci{ 11268c2ecf20Sopenharmony_ci return sym_change_count; 11278c2ecf20Sopenharmony_ci} 11288c2ecf20Sopenharmony_ci 11298c2ecf20Sopenharmony_civoid conf_set_changed_callback(void (*fn)(void)) 11308c2ecf20Sopenharmony_ci{ 11318c2ecf20Sopenharmony_ci conf_changed_callback = fn; 11328c2ecf20Sopenharmony_ci} 11338c2ecf20Sopenharmony_ci 11348c2ecf20Sopenharmony_cistatic bool randomize_choice_values(struct symbol *csym) 11358c2ecf20Sopenharmony_ci{ 11368c2ecf20Sopenharmony_ci struct property *prop; 11378c2ecf20Sopenharmony_ci struct symbol *sym; 11388c2ecf20Sopenharmony_ci struct expr *e; 11398c2ecf20Sopenharmony_ci int cnt, def; 11408c2ecf20Sopenharmony_ci 11418c2ecf20Sopenharmony_ci /* 11428c2ecf20Sopenharmony_ci * If choice is mod then we may have more items selected 11438c2ecf20Sopenharmony_ci * and if no then no-one. 11448c2ecf20Sopenharmony_ci * In both cases stop. 11458c2ecf20Sopenharmony_ci */ 11468c2ecf20Sopenharmony_ci if (csym->curr.tri != yes) 11478c2ecf20Sopenharmony_ci return false; 11488c2ecf20Sopenharmony_ci 11498c2ecf20Sopenharmony_ci prop = sym_get_choice_prop(csym); 11508c2ecf20Sopenharmony_ci 11518c2ecf20Sopenharmony_ci /* count entries in choice block */ 11528c2ecf20Sopenharmony_ci cnt = 0; 11538c2ecf20Sopenharmony_ci expr_list_for_each_sym(prop->expr, e, sym) 11548c2ecf20Sopenharmony_ci cnt++; 11558c2ecf20Sopenharmony_ci 11568c2ecf20Sopenharmony_ci /* 11578c2ecf20Sopenharmony_ci * find a random value and set it to yes, 11588c2ecf20Sopenharmony_ci * set the rest to no so we have only one set 11598c2ecf20Sopenharmony_ci */ 11608c2ecf20Sopenharmony_ci def = (rand() % cnt); 11618c2ecf20Sopenharmony_ci 11628c2ecf20Sopenharmony_ci cnt = 0; 11638c2ecf20Sopenharmony_ci expr_list_for_each_sym(prop->expr, e, sym) { 11648c2ecf20Sopenharmony_ci if (def == cnt++) { 11658c2ecf20Sopenharmony_ci sym->def[S_DEF_USER].tri = yes; 11668c2ecf20Sopenharmony_ci csym->def[S_DEF_USER].val = sym; 11678c2ecf20Sopenharmony_ci } 11688c2ecf20Sopenharmony_ci else { 11698c2ecf20Sopenharmony_ci sym->def[S_DEF_USER].tri = no; 11708c2ecf20Sopenharmony_ci } 11718c2ecf20Sopenharmony_ci sym->flags |= SYMBOL_DEF_USER; 11728c2ecf20Sopenharmony_ci /* clear VALID to get value calculated */ 11738c2ecf20Sopenharmony_ci sym->flags &= ~SYMBOL_VALID; 11748c2ecf20Sopenharmony_ci } 11758c2ecf20Sopenharmony_ci csym->flags |= SYMBOL_DEF_USER; 11768c2ecf20Sopenharmony_ci /* clear VALID to get value calculated */ 11778c2ecf20Sopenharmony_ci csym->flags &= ~(SYMBOL_VALID); 11788c2ecf20Sopenharmony_ci 11798c2ecf20Sopenharmony_ci return true; 11808c2ecf20Sopenharmony_ci} 11818c2ecf20Sopenharmony_ci 11828c2ecf20Sopenharmony_civoid set_all_choice_values(struct symbol *csym) 11838c2ecf20Sopenharmony_ci{ 11848c2ecf20Sopenharmony_ci struct property *prop; 11858c2ecf20Sopenharmony_ci struct symbol *sym; 11868c2ecf20Sopenharmony_ci struct expr *e; 11878c2ecf20Sopenharmony_ci 11888c2ecf20Sopenharmony_ci prop = sym_get_choice_prop(csym); 11898c2ecf20Sopenharmony_ci 11908c2ecf20Sopenharmony_ci /* 11918c2ecf20Sopenharmony_ci * Set all non-assinged choice values to no 11928c2ecf20Sopenharmony_ci */ 11938c2ecf20Sopenharmony_ci expr_list_for_each_sym(prop->expr, e, sym) { 11948c2ecf20Sopenharmony_ci if (!sym_has_value(sym)) 11958c2ecf20Sopenharmony_ci sym->def[S_DEF_USER].tri = no; 11968c2ecf20Sopenharmony_ci } 11978c2ecf20Sopenharmony_ci csym->flags |= SYMBOL_DEF_USER; 11988c2ecf20Sopenharmony_ci /* clear VALID to get value calculated */ 11998c2ecf20Sopenharmony_ci csym->flags &= ~(SYMBOL_VALID | SYMBOL_NEED_SET_CHOICE_VALUES); 12008c2ecf20Sopenharmony_ci} 12018c2ecf20Sopenharmony_ci 12028c2ecf20Sopenharmony_cibool conf_set_all_new_symbols(enum conf_def_mode mode) 12038c2ecf20Sopenharmony_ci{ 12048c2ecf20Sopenharmony_ci struct symbol *sym, *csym; 12058c2ecf20Sopenharmony_ci int i, cnt, pby, pty, ptm; /* pby: probability of bool = y 12068c2ecf20Sopenharmony_ci * pty: probability of tristate = y 12078c2ecf20Sopenharmony_ci * ptm: probability of tristate = m 12088c2ecf20Sopenharmony_ci */ 12098c2ecf20Sopenharmony_ci 12108c2ecf20Sopenharmony_ci pby = 50; pty = ptm = 33; /* can't go as the default in switch-case 12118c2ecf20Sopenharmony_ci * below, otherwise gcc whines about 12128c2ecf20Sopenharmony_ci * -Wmaybe-uninitialized */ 12138c2ecf20Sopenharmony_ci if (mode == def_random) { 12148c2ecf20Sopenharmony_ci int n, p[3]; 12158c2ecf20Sopenharmony_ci char *env = getenv("KCONFIG_PROBABILITY"); 12168c2ecf20Sopenharmony_ci n = 0; 12178c2ecf20Sopenharmony_ci while( env && *env ) { 12188c2ecf20Sopenharmony_ci char *endp; 12198c2ecf20Sopenharmony_ci int tmp = strtol( env, &endp, 10 ); 12208c2ecf20Sopenharmony_ci if( tmp >= 0 && tmp <= 100 ) { 12218c2ecf20Sopenharmony_ci p[n++] = tmp; 12228c2ecf20Sopenharmony_ci } else { 12238c2ecf20Sopenharmony_ci errno = ERANGE; 12248c2ecf20Sopenharmony_ci perror( "KCONFIG_PROBABILITY" ); 12258c2ecf20Sopenharmony_ci exit( 1 ); 12268c2ecf20Sopenharmony_ci } 12278c2ecf20Sopenharmony_ci env = (*endp == ':') ? endp+1 : endp; 12288c2ecf20Sopenharmony_ci if( n >=3 ) { 12298c2ecf20Sopenharmony_ci break; 12308c2ecf20Sopenharmony_ci } 12318c2ecf20Sopenharmony_ci } 12328c2ecf20Sopenharmony_ci switch( n ) { 12338c2ecf20Sopenharmony_ci case 1: 12348c2ecf20Sopenharmony_ci pby = p[0]; ptm = pby/2; pty = pby-ptm; 12358c2ecf20Sopenharmony_ci break; 12368c2ecf20Sopenharmony_ci case 2: 12378c2ecf20Sopenharmony_ci pty = p[0]; ptm = p[1]; pby = pty + ptm; 12388c2ecf20Sopenharmony_ci break; 12398c2ecf20Sopenharmony_ci case 3: 12408c2ecf20Sopenharmony_ci pby = p[0]; pty = p[1]; ptm = p[2]; 12418c2ecf20Sopenharmony_ci break; 12428c2ecf20Sopenharmony_ci } 12438c2ecf20Sopenharmony_ci 12448c2ecf20Sopenharmony_ci if( pty+ptm > 100 ) { 12458c2ecf20Sopenharmony_ci errno = ERANGE; 12468c2ecf20Sopenharmony_ci perror( "KCONFIG_PROBABILITY" ); 12478c2ecf20Sopenharmony_ci exit( 1 ); 12488c2ecf20Sopenharmony_ci } 12498c2ecf20Sopenharmony_ci } 12508c2ecf20Sopenharmony_ci bool has_changed = false; 12518c2ecf20Sopenharmony_ci 12528c2ecf20Sopenharmony_ci for_all_symbols(i, sym) { 12538c2ecf20Sopenharmony_ci if (sym_has_value(sym) || (sym->flags & SYMBOL_VALID)) 12548c2ecf20Sopenharmony_ci continue; 12558c2ecf20Sopenharmony_ci switch (sym_get_type(sym)) { 12568c2ecf20Sopenharmony_ci case S_BOOLEAN: 12578c2ecf20Sopenharmony_ci case S_TRISTATE: 12588c2ecf20Sopenharmony_ci has_changed = true; 12598c2ecf20Sopenharmony_ci switch (mode) { 12608c2ecf20Sopenharmony_ci case def_yes: 12618c2ecf20Sopenharmony_ci sym->def[S_DEF_USER].tri = yes; 12628c2ecf20Sopenharmony_ci break; 12638c2ecf20Sopenharmony_ci case def_mod: 12648c2ecf20Sopenharmony_ci sym->def[S_DEF_USER].tri = mod; 12658c2ecf20Sopenharmony_ci break; 12668c2ecf20Sopenharmony_ci case def_no: 12678c2ecf20Sopenharmony_ci if (sym->flags & SYMBOL_ALLNOCONFIG_Y) 12688c2ecf20Sopenharmony_ci sym->def[S_DEF_USER].tri = yes; 12698c2ecf20Sopenharmony_ci else 12708c2ecf20Sopenharmony_ci sym->def[S_DEF_USER].tri = no; 12718c2ecf20Sopenharmony_ci break; 12728c2ecf20Sopenharmony_ci case def_random: 12738c2ecf20Sopenharmony_ci sym->def[S_DEF_USER].tri = no; 12748c2ecf20Sopenharmony_ci cnt = rand() % 100; 12758c2ecf20Sopenharmony_ci if (sym->type == S_TRISTATE) { 12768c2ecf20Sopenharmony_ci if (cnt < pty) 12778c2ecf20Sopenharmony_ci sym->def[S_DEF_USER].tri = yes; 12788c2ecf20Sopenharmony_ci else if (cnt < (pty+ptm)) 12798c2ecf20Sopenharmony_ci sym->def[S_DEF_USER].tri = mod; 12808c2ecf20Sopenharmony_ci } else if (cnt < pby) 12818c2ecf20Sopenharmony_ci sym->def[S_DEF_USER].tri = yes; 12828c2ecf20Sopenharmony_ci break; 12838c2ecf20Sopenharmony_ci default: 12848c2ecf20Sopenharmony_ci continue; 12858c2ecf20Sopenharmony_ci } 12868c2ecf20Sopenharmony_ci if (!(sym_is_choice(sym) && mode == def_random)) 12878c2ecf20Sopenharmony_ci sym->flags |= SYMBOL_DEF_USER; 12888c2ecf20Sopenharmony_ci break; 12898c2ecf20Sopenharmony_ci default: 12908c2ecf20Sopenharmony_ci break; 12918c2ecf20Sopenharmony_ci } 12928c2ecf20Sopenharmony_ci 12938c2ecf20Sopenharmony_ci } 12948c2ecf20Sopenharmony_ci 12958c2ecf20Sopenharmony_ci sym_clear_all_valid(); 12968c2ecf20Sopenharmony_ci 12978c2ecf20Sopenharmony_ci /* 12988c2ecf20Sopenharmony_ci * We have different type of choice blocks. 12998c2ecf20Sopenharmony_ci * If curr.tri equals to mod then we can select several 13008c2ecf20Sopenharmony_ci * choice symbols in one block. 13018c2ecf20Sopenharmony_ci * In this case we do nothing. 13028c2ecf20Sopenharmony_ci * If curr.tri equals yes then only one symbol can be 13038c2ecf20Sopenharmony_ci * selected in a choice block and we set it to yes, 13048c2ecf20Sopenharmony_ci * and the rest to no. 13058c2ecf20Sopenharmony_ci */ 13068c2ecf20Sopenharmony_ci if (mode != def_random) { 13078c2ecf20Sopenharmony_ci for_all_symbols(i, csym) { 13088c2ecf20Sopenharmony_ci if ((sym_is_choice(csym) && !sym_has_value(csym)) || 13098c2ecf20Sopenharmony_ci sym_is_choice_value(csym)) 13108c2ecf20Sopenharmony_ci csym->flags |= SYMBOL_NEED_SET_CHOICE_VALUES; 13118c2ecf20Sopenharmony_ci } 13128c2ecf20Sopenharmony_ci } 13138c2ecf20Sopenharmony_ci 13148c2ecf20Sopenharmony_ci for_all_symbols(i, csym) { 13158c2ecf20Sopenharmony_ci if (sym_has_value(csym) || !sym_is_choice(csym)) 13168c2ecf20Sopenharmony_ci continue; 13178c2ecf20Sopenharmony_ci 13188c2ecf20Sopenharmony_ci sym_calc_value(csym); 13198c2ecf20Sopenharmony_ci if (mode == def_random) 13208c2ecf20Sopenharmony_ci has_changed |= randomize_choice_values(csym); 13218c2ecf20Sopenharmony_ci else { 13228c2ecf20Sopenharmony_ci set_all_choice_values(csym); 13238c2ecf20Sopenharmony_ci has_changed = true; 13248c2ecf20Sopenharmony_ci } 13258c2ecf20Sopenharmony_ci } 13268c2ecf20Sopenharmony_ci 13278c2ecf20Sopenharmony_ci return has_changed; 13288c2ecf20Sopenharmony_ci} 13298c2ecf20Sopenharmony_ci 13308c2ecf20Sopenharmony_civoid conf_rewrite_mod_or_yes(enum conf_def_mode mode) 13318c2ecf20Sopenharmony_ci{ 13328c2ecf20Sopenharmony_ci struct symbol *sym; 13338c2ecf20Sopenharmony_ci int i; 13348c2ecf20Sopenharmony_ci tristate old_val = (mode == def_y2m) ? yes : mod; 13358c2ecf20Sopenharmony_ci tristate new_val = (mode == def_y2m) ? mod : yes; 13368c2ecf20Sopenharmony_ci 13378c2ecf20Sopenharmony_ci for_all_symbols(i, sym) { 13388c2ecf20Sopenharmony_ci if (sym_get_type(sym) == S_TRISTATE && 13398c2ecf20Sopenharmony_ci sym->def[S_DEF_USER].tri == old_val) 13408c2ecf20Sopenharmony_ci sym->def[S_DEF_USER].tri = new_val; 13418c2ecf20Sopenharmony_ci } 13428c2ecf20Sopenharmony_ci sym_clear_all_valid(); 13438c2ecf20Sopenharmony_ci} 1344