blob: f17a2a9562ee247db8dc9d249d4c65382dec9131 [file] [log] [blame]
Masahiro Yamada0c874102018-12-18 21:13:35 +09001// SPDX-License-Identifier: GPL-2.0
Linus Torvalds1da177e2005-04-16 15:20:36 -07002/*
3 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
Linus Torvalds1da177e2005-04-16 15:20:36 -07004 */
5
Masahiro Yamada67424f62019-05-10 15:12:05 +09006#include <sys/mman.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -07007#include <sys/stat.h>
Boris Kolpackov78cb0902020-11-23 11:38:18 +02008#include <sys/types.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -07009#include <ctype.h>
Arnaud Lacombe94bedec2010-08-17 01:40:20 -040010#include <errno.h>
Roman Zippel2e3646e2006-06-08 22:12:42 -070011#include <fcntl.h>
Masahiro Yamada558e78e2018-12-21 17:33:04 +090012#include <limits.h>
Arnaud Lacombe10a4b272011-06-01 16:00:46 -040013#include <stdarg.h>
Masahiro Yamada6ce45a92021-10-01 14:32:46 +090014#include <stdbool.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070015#include <stdio.h>
16#include <stdlib.h>
17#include <string.h>
18#include <time.h>
19#include <unistd.h>
20
Linus Torvalds1da177e2005-04-16 15:20:36 -070021#include "lkc.h"
22
Masahiro Yamada06081822018-07-20 16:46:27 +090023/* return true if 'path' exists, false otherwise */
24static bool is_present(const char *path)
25{
26 struct stat st;
27
28 return !stat(path, &st);
29}
30
31/* return true if 'path' exists and it is a directory, false otherwise */
32static bool is_dir(const char *path)
33{
34 struct stat st;
35
36 if (stat(path, &st))
Yang Lia69b1912021-03-15 14:55:44 +080037 return false;
Masahiro Yamada06081822018-07-20 16:46:27 +090038
39 return S_ISDIR(st.st_mode);
40}
41
Masahiro Yamada67424f62019-05-10 15:12:05 +090042/* return true if the given two files are the same, false otherwise */
43static bool is_same(const char *file1, const char *file2)
44{
45 int fd1, fd2;
46 struct stat st1, st2;
47 void *map1, *map2;
48 bool ret = false;
49
50 fd1 = open(file1, O_RDONLY);
51 if (fd1 < 0)
52 return ret;
53
54 fd2 = open(file2, O_RDONLY);
55 if (fd2 < 0)
56 goto close1;
57
58 ret = fstat(fd1, &st1);
59 if (ret)
60 goto close2;
61 ret = fstat(fd2, &st2);
62 if (ret)
63 goto close2;
64
65 if (st1.st_size != st2.st_size)
66 goto close2;
67
68 map1 = mmap(NULL, st1.st_size, PROT_READ, MAP_PRIVATE, fd1, 0);
69 if (map1 == MAP_FAILED)
70 goto close2;
71
72 map2 = mmap(NULL, st2.st_size, PROT_READ, MAP_PRIVATE, fd2, 0);
73 if (map2 == MAP_FAILED)
74 goto close2;
75
76 if (bcmp(map1, map2, st1.st_size))
77 goto close2;
78
79 ret = true;
80close2:
81 close(fd2);
82close1:
83 close(fd1);
84
85 return ret;
86}
87
Masahiro Yamada06081822018-07-20 16:46:27 +090088/*
89 * Create the parent directory of the given path.
90 *
91 * For example, if 'include/config/auto.conf' is given, create 'include/config'.
92 */
93static int make_parent_dir(const char *path)
94{
95 char tmp[PATH_MAX + 1];
96 char *p;
97
98 strncpy(tmp, path, sizeof(tmp));
99 tmp[sizeof(tmp) - 1] = 0;
100
101 /* Remove the base name. Just return if nothing is left */
102 p = strrchr(tmp, '/');
103 if (!p)
104 return 0;
105 *(p + 1) = 0;
106
107 /* Just in case it is an absolute path */
108 p = tmp;
109 while (*p == '/')
110 p++;
111
112 while ((p = strchr(p, '/'))) {
113 *p = 0;
114
115 /* skip if the directory exists */
116 if (!is_dir(tmp) && mkdir(tmp, 0755))
117 return -1;
118
119 *p = '/';
120 while (*p == '/')
121 p++;
122 }
123
124 return 0;
125}
126
Masahiro Yamada1508fec2018-11-30 18:15:50 +0900127static char depfile_path[PATH_MAX];
128static size_t depfile_prefix_len;
129
130/* touch depfile for symbol 'name' */
131static int conf_touch_dep(const char *name)
132{
133 int fd, ret;
Alexey Dobriyan0e0345b2021-04-15 20:36:07 +0300134 char *d;
Masahiro Yamada1508fec2018-11-30 18:15:50 +0900135
Alexey Dobriyan0e0345b2021-04-15 20:36:07 +0300136 /* check overflow: prefix + name + '\0' must fit in buffer. */
137 if (depfile_prefix_len + strlen(name) + 1 > sizeof(depfile_path))
Masahiro Yamada1508fec2018-11-30 18:15:50 +0900138 return -1;
139
140 d = depfile_path + depfile_prefix_len;
Alexey Dobriyan0e0345b2021-04-15 20:36:07 +0300141 strcpy(d, name);
Masahiro Yamada1508fec2018-11-30 18:15:50 +0900142
143 /* Assume directory path already exists. */
144 fd = open(depfile_path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
145 if (fd == -1) {
146 if (errno != ENOENT)
147 return -1;
148
149 ret = make_parent_dir(depfile_path);
150 if (ret)
151 return ret;
152
153 /* Try it again. */
154 fd = open(depfile_path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
155 if (fd == -1)
156 return -1;
157 }
158 close(fd);
159
160 return 0;
161}
162
Roman Zippelc1a0f5e2005-11-08 21:34:54 -0800163static void conf_warning(const char *fmt, ...)
164 __attribute__ ((format (printf, 1, 2)));
165
Michal Marek42368c32010-08-17 10:21:19 +0200166static void conf_message(const char *fmt, ...)
167 __attribute__ ((format (printf, 1, 2)));
168
Roman Zippelc1a0f5e2005-11-08 21:34:54 -0800169static const char *conf_filename;
Masahiro Yamada84dd95d2018-01-11 22:39:41 +0900170static int conf_lineno, conf_warnings;
Roman Zippelc1a0f5e2005-11-08 21:34:54 -0800171
Roman Zippelc1a0f5e2005-11-08 21:34:54 -0800172static void conf_warning(const char *fmt, ...)
173{
174 va_list ap;
175 va_start(ap, fmt);
176 fprintf(stderr, "%s:%d:warning: ", conf_filename, conf_lineno);
177 vfprintf(stderr, fmt, ap);
178 fprintf(stderr, "\n");
179 va_end(ap);
180 conf_warnings++;
181}
182
Masahiro Yamada5accd7f2018-07-05 11:46:12 +0900183static void conf_default_message_callback(const char *s)
Michal Marek42368c32010-08-17 10:21:19 +0200184{
185 printf("#\n# ");
Masahiro Yamada5accd7f2018-07-05 11:46:12 +0900186 printf("%s", s);
Michal Marek42368c32010-08-17 10:21:19 +0200187 printf("\n#\n");
188}
189
Masahiro Yamada5accd7f2018-07-05 11:46:12 +0900190static void (*conf_message_callback)(const char *s) =
Michal Marek42368c32010-08-17 10:21:19 +0200191 conf_default_message_callback;
Masahiro Yamada5accd7f2018-07-05 11:46:12 +0900192void conf_set_message_callback(void (*fn)(const char *s))
Michal Marek42368c32010-08-17 10:21:19 +0200193{
194 conf_message_callback = fn;
195}
196
197static void conf_message(const char *fmt, ...)
198{
199 va_list ap;
Masahiro Yamada5accd7f2018-07-05 11:46:12 +0900200 char buf[4096];
201
202 if (!conf_message_callback)
203 return;
Michal Marek42368c32010-08-17 10:21:19 +0200204
205 va_start(ap, fmt);
Masahiro Yamada5accd7f2018-07-05 11:46:12 +0900206
207 vsnprintf(buf, sizeof(buf), fmt, ap);
208 conf_message_callback(buf);
Colin Ian Kingb6a2ab22015-01-12 13:18:26 +0000209 va_end(ap);
Michal Marek42368c32010-08-17 10:21:19 +0200210}
211
Roman Zippel14cdd3c2006-06-08 22:12:51 -0700212const char *conf_get_configname(void)
213{
214 char *name = getenv("KCONFIG_CONFIG");
215
216 return name ? name : ".config";
217}
218
Masahiro Yamada9b9f5942019-05-13 01:00:53 +0900219static const char *conf_get_autoconfig_name(void)
Markus Heidelberg12122f62009-05-18 01:36:54 +0200220{
221 char *name = getenv("KCONFIG_AUTOCONFIG");
222
223 return name ? name : "include/config/auto.conf";
224}
225
Sam Ravnborg9c900a92007-11-10 20:01:56 +0100226static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
227{
228 char *p2;
229
230 switch (sym->type) {
231 case S_TRISTATE:
232 if (p[0] == 'm') {
233 sym->def[def].tri = mod;
234 sym->flags |= def_flags;
235 break;
236 }
Arnaud Lacombed8fc3202011-05-31 12:30:26 -0400237 /* fall through */
Sam Ravnborg9c900a92007-11-10 20:01:56 +0100238 case S_BOOLEAN:
239 if (p[0] == 'y') {
240 sym->def[def].tri = yes;
241 sym->flags |= def_flags;
242 break;
243 }
244 if (p[0] == 'n') {
245 sym->def[def].tri = no;
246 sym->flags |= def_flags;
247 break;
248 }
Yann E. MORIN04b19b772013-08-06 18:45:07 +0200249 if (def != S_DEF_AUTO)
250 conf_warning("symbol value '%s' invalid for %s",
251 p, sym->name);
Arnaud Lacombe75f14682011-05-31 12:31:57 -0400252 return 1;
Sam Ravnborg9c900a92007-11-10 20:01:56 +0100253 case S_STRING:
254 if (*p++ != '"')
255 break;
256 for (p2 = p; (p2 = strpbrk(p2, "\"\\")); p2++) {
257 if (*p2 == '"') {
258 *p2 = 0;
259 break;
260 }
261 memmove(p2, p2 + 1, strlen(p2));
262 }
263 if (!p2) {
Yann E. MORIN04b19b772013-08-06 18:45:07 +0200264 if (def != S_DEF_AUTO)
265 conf_warning("invalid string found");
Sam Ravnborg9c900a92007-11-10 20:01:56 +0100266 return 1;
267 }
Arnaud Lacombed8fc3202011-05-31 12:30:26 -0400268 /* fall through */
Sam Ravnborg9c900a92007-11-10 20:01:56 +0100269 case S_INT:
270 case S_HEX:
Sam Ravnborg9c900a92007-11-10 20:01:56 +0100271 if (sym_string_valid(sym, p)) {
Masahiro Yamadacd81fc82018-02-17 03:38:31 +0900272 sym->def[def].val = xstrdup(p);
Sam Ravnborg9c900a92007-11-10 20:01:56 +0100273 sym->flags |= def_flags;
274 } else {
Yann E. MORIN04b19b772013-08-06 18:45:07 +0200275 if (def != S_DEF_AUTO)
276 conf_warning("symbol value '%s' invalid for %s",
277 p, sym->name);
Sam Ravnborg9c900a92007-11-10 20:01:56 +0100278 return 1;
279 }
280 break;
281 default:
282 ;
283 }
284 return 0;
285}
286
Cody Schafer1a7a8c62012-07-13 11:27:12 -0700287#define LINE_GROWTH 16
288static int add_byte(int c, char **lineptr, size_t slen, size_t *n)
289{
290 char *nline;
291 size_t new_size = slen + 1;
292 if (new_size > *n) {
293 new_size += LINE_GROWTH - 1;
294 new_size *= 2;
Masahiro Yamadad717f242018-02-09 01:19:07 +0900295 nline = xrealloc(*lineptr, new_size);
Cody Schafer1a7a8c62012-07-13 11:27:12 -0700296 if (!nline)
297 return -1;
298
299 *lineptr = nline;
300 *n = new_size;
301 }
302
303 (*lineptr)[slen] = c;
304
305 return 0;
306}
307
308static ssize_t compat_getline(char **lineptr, size_t *n, FILE *stream)
309{
310 char *line = *lineptr;
311 size_t slen = 0;
312
313 for (;;) {
314 int c = getc(stream);
315
316 switch (c) {
317 case '\n':
318 if (add_byte(c, &line, slen, n) < 0)
319 goto e_out;
320 slen++;
321 /* fall through */
322 case EOF:
323 if (add_byte('\0', &line, slen, n) < 0)
324 goto e_out;
325 *lineptr = line;
326 if (slen == 0)
327 return -1;
328 return slen;
329 default:
330 if (add_byte(c, &line, slen, n) < 0)
331 goto e_out;
332 slen++;
333 }
334 }
335
336e_out:
337 line[slen-1] = '\0';
338 *lineptr = line;
339 return -1;
340}
341
Roman Zippel669bfad92006-06-08 22:12:42 -0700342int conf_read_simple(const char *name, int def)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700343{
344 FILE *in = NULL;
Cody Schafer1a7a8c62012-07-13 11:27:12 -0700345 char *line = NULL;
346 size_t line_asize = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700347 char *p, *p2;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700348 struct symbol *sym;
Roman Zippel669bfad92006-06-08 22:12:42 -0700349 int i, def_flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350
351 if (name) {
352 in = zconf_fopen(name);
353 } else {
Masahiro Yamadab75b0a82021-03-14 04:48:32 +0900354 char *env;
Roman Zippelface4372006-06-08 22:12:45 -0700355
Roman Zippel14cdd3c2006-06-08 22:12:51 -0700356 name = conf_get_configname();
Roman Zippelddc97ca2006-06-08 22:12:38 -0700357 in = zconf_fopen(name);
358 if (in)
359 goto load;
Masahiro Yamada5ee54652021-04-10 15:57:22 +0900360 conf_set_changed(true);
Masahiro Yamadab75b0a82021-03-14 04:48:32 +0900361
362 env = getenv("KCONFIG_DEFCONFIG_LIST");
363 if (!env)
Roman Zippelface4372006-06-08 22:12:45 -0700364 return 1;
365
Masahiro Yamadab75b0a82021-03-14 04:48:32 +0900366 while (1) {
367 bool is_last;
368
369 while (isspace(*env))
370 env++;
371
372 if (!*env)
373 break;
374
375 p = env;
376 while (*p && !isspace(*p))
377 p++;
378
379 is_last = (*p == '\0');
380
381 *p = '\0';
382
383 in = zconf_fopen(env);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384 if (in) {
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200385 conf_message("using defaults found in %s",
Masahiro Yamadab75b0a82021-03-14 04:48:32 +0900386 env);
Roman Zippelddc97ca2006-06-08 22:12:38 -0700387 goto load;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388 }
Masahiro Yamadab75b0a82021-03-14 04:48:32 +0900389
390 if (is_last)
391 break;
392
393 env = p + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700394 }
395 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396 if (!in)
397 return 1;
398
Roman Zippelddc97ca2006-06-08 22:12:38 -0700399load:
Roman Zippelc1a0f5e2005-11-08 21:34:54 -0800400 conf_filename = name;
401 conf_lineno = 0;
402 conf_warnings = 0;
Roman Zippelc1a0f5e2005-11-08 21:34:54 -0800403
Roman Zippel669bfad92006-06-08 22:12:42 -0700404 def_flags = SYMBOL_DEF << def;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700405 for_all_symbols(i, sym) {
Roman Zippel669bfad92006-06-08 22:12:42 -0700406 sym->flags |= SYMBOL_CHANGED;
407 sym->flags &= ~(def_flags|SYMBOL_VALID);
Yann E. MORIN490f1612013-06-25 23:37:44 +0200408 if (sym_is_choice(sym))
409 sym->flags |= def_flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410 switch (sym->type) {
411 case S_INT:
412 case S_HEX:
413 case S_STRING:
Roman Zippel669bfad92006-06-08 22:12:42 -0700414 if (sym->def[def].val)
415 free(sym->def[def].val);
Arnaud Lacombed8fc3202011-05-31 12:30:26 -0400416 /* fall through */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417 default:
Roman Zippel669bfad92006-06-08 22:12:42 -0700418 sym->def[def].val = NULL;
419 sym->def[def].tri = no;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420 }
421 }
422
Cody Schafer1a7a8c62012-07-13 11:27:12 -0700423 while (compat_getline(&line, &line_asize, in) != -1) {
Roman Zippelc1a0f5e2005-11-08 21:34:54 -0800424 conf_lineno++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425 sym = NULL;
Arnaud Lacombe8baefd32010-08-24 00:14:47 -0400426 if (line[0] == '#') {
Arnaud Lacombeffb59572010-08-14 23:57:43 -0400427 if (memcmp(line + 2, CONFIG_, strlen(CONFIG_)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428 continue;
Arnaud Lacombeffb59572010-08-14 23:57:43 -0400429 p = strchr(line + 2 + strlen(CONFIG_), ' ');
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430 if (!p)
431 continue;
432 *p++ = 0;
433 if (strncmp(p, "is not set", 10))
434 continue;
Roman Zippel669bfad92006-06-08 22:12:42 -0700435 if (def == S_DEF_USER) {
Arnaud Lacombeffb59572010-08-14 23:57:43 -0400436 sym = sym_find(line + 2 + strlen(CONFIG_));
zippel@linux-m68k.org661b0682008-09-29 05:27:11 +0200437 if (!sym) {
Masahiro Yamada5ee54652021-04-10 15:57:22 +0900438 conf_set_changed(true);
Masahiro Yamada75889e92018-11-30 18:15:48 +0900439 continue;
zippel@linux-m68k.org661b0682008-09-29 05:27:11 +0200440 }
Roman Zippel669bfad92006-06-08 22:12:42 -0700441 } else {
Arnaud Lacombeffb59572010-08-14 23:57:43 -0400442 sym = sym_lookup(line + 2 + strlen(CONFIG_), 0);
Roman Zippel669bfad92006-06-08 22:12:42 -0700443 if (sym->type == S_UNKNOWN)
444 sym->type = S_BOOLEAN;
445 }
446 if (sym->flags & def_flags) {
Jan Engelhardtd84876f2008-01-03 23:33:44 +0100447 conf_warning("override: reassigning to symbol %s", sym->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700448 }
449 switch (sym->type) {
450 case S_BOOLEAN:
451 case S_TRISTATE:
Roman Zippel669bfad92006-06-08 22:12:42 -0700452 sym->def[def].tri = no;
453 sym->flags |= def_flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454 break;
455 default:
456 ;
457 }
Arnaud Lacombeffb59572010-08-14 23:57:43 -0400458 } else if (memcmp(line, CONFIG_, strlen(CONFIG_)) == 0) {
459 p = strchr(line + strlen(CONFIG_), '=');
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460 if (!p)
461 continue;
462 *p++ = 0;
463 p2 = strchr(p, '\n');
Matthew Wilcoxd3660a82006-07-13 12:54:07 -0600464 if (p2) {
465 *p2-- = 0;
466 if (*p2 == '\r')
467 *p2 = 0;
468 }
Masahiro Yamada2aabbed2018-11-30 18:15:51 +0900469
470 sym = sym_find(line + strlen(CONFIG_));
471 if (!sym) {
472 if (def == S_DEF_AUTO)
473 /*
474 * Reading from include/config/auto.conf
475 * If CONFIG_FOO previously existed in
476 * auto.conf but it is missing now,
Alexey Dobriyan0e0345b2021-04-15 20:36:07 +0300477 * include/config/FOO must be touched.
Masahiro Yamada2aabbed2018-11-30 18:15:51 +0900478 */
479 conf_touch_dep(line + strlen(CONFIG_));
480 else
Masahiro Yamada5ee54652021-04-10 15:57:22 +0900481 conf_set_changed(true);
Masahiro Yamada2aabbed2018-11-30 18:15:51 +0900482 continue;
Roman Zippel669bfad92006-06-08 22:12:42 -0700483 }
Masahiro Yamada2aabbed2018-11-30 18:15:51 +0900484
Roman Zippel669bfad92006-06-08 22:12:42 -0700485 if (sym->flags & def_flags) {
Jan Engelhardtd84876f2008-01-03 23:33:44 +0100486 conf_warning("override: reassigning to symbol %s", sym->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700487 }
Sam Ravnborg9c900a92007-11-10 20:01:56 +0100488 if (conf_set_sym_val(sym, def, def_flags, p))
489 continue;
Arnaud Lacombe8baefd32010-08-24 00:14:47 -0400490 } else {
491 if (line[0] != '\r' && line[0] != '\n')
Paul Bollea4663912016-03-16 21:27:27 +0100492 conf_warning("unexpected data: %.*s",
493 (int)strcspn(line, "\r\n"), line);
494
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495 continue;
496 }
Masahiro Yamada75889e92018-11-30 18:15:48 +0900497
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498 if (sym && sym_is_choice_value(sym)) {
499 struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
Roman Zippel669bfad92006-06-08 22:12:42 -0700500 switch (sym->def[def].tri) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501 case no:
502 break;
503 case mod:
Roman Zippel669bfad92006-06-08 22:12:42 -0700504 if (cs->def[def].tri == yes) {
Roman Zippelc1a0f5e2005-11-08 21:34:54 -0800505 conf_warning("%s creates inconsistent choice state", sym->name);
Yann E. MORIN490f1612013-06-25 23:37:44 +0200506 cs->flags &= ~def_flags;
Roman Zippelc1a0f5e2005-11-08 21:34:54 -0800507 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700508 break;
509 case yes:
Jan Engelhardtd84876f2008-01-03 23:33:44 +0100510 if (cs->def[def].tri != no)
511 conf_warning("override: %s changes choice state", sym->name);
512 cs->def[def].val = sym;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513 break;
514 }
Sam Ravnborgd6ee3572008-01-07 21:09:55 +0100515 cs->def[def].tri = EXPR_OR(cs->def[def].tri, sym->def[def].tri);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700516 }
517 }
Cody Schafer1a7a8c62012-07-13 11:27:12 -0700518 free(line);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700519 fclose(in);
Roman Zippel90389162005-11-08 21:34:49 -0800520 return 0;
521}
522
523int conf_read(const char *name)
524{
Arnaud Lacombe5d095982012-01-23 17:29:05 -0500525 struct symbol *sym;
Masahiro Yamada84dd95d2018-01-11 22:39:41 +0900526 int conf_unsaved = 0;
Arnaud Lacombe5d095982012-01-23 17:29:05 -0500527 int i;
Roman Zippel90389162005-11-08 21:34:49 -0800528
Masahiro Yamada5ee54652021-04-10 15:57:22 +0900529 conf_set_changed(false);
Roman Zippelddc97ca2006-06-08 22:12:38 -0700530
Al Viro6b87b702016-01-14 18:13:49 +0000531 if (conf_read_simple(name, S_DEF_USER)) {
532 sym_calc_value(modules_sym);
Roman Zippel90389162005-11-08 21:34:49 -0800533 return 1;
Al Viro6b87b702016-01-14 18:13:49 +0000534 }
535
536 sym_calc_value(modules_sym);
Roman Zippel90389162005-11-08 21:34:49 -0800537
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538 for_all_symbols(i, sym) {
539 sym_calc_value(sym);
Dirk Gouders693359f2018-07-03 14:43:31 +0200540 if (sym_is_choice(sym) || (sym->flags & SYMBOL_NO_WRITE))
Arnaud Lacombe5d095982012-01-23 17:29:05 -0500541 continue;
Roman Zippelc1a0f5e2005-11-08 21:34:54 -0800542 if (sym_has_value(sym) && (sym->flags & SYMBOL_WRITE)) {
543 /* check that calculated value agrees with saved value */
544 switch (sym->type) {
545 case S_BOOLEAN:
546 case S_TRISTATE:
Masahiro Yamadae3cd5132019-07-11 16:33:17 +0900547 if (sym->def[S_DEF_USER].tri == sym_get_tristate_value(sym))
Arnaud Lacombe5d095982012-01-23 17:29:05 -0500548 continue;
Masahiro Yamadae3cd5132019-07-11 16:33:17 +0900549 break;
Roman Zippelc1a0f5e2005-11-08 21:34:54 -0800550 default:
Roman Zippel0c1822e2006-06-08 22:12:41 -0700551 if (!strcmp(sym->curr.val, sym->def[S_DEF_USER].val))
Arnaud Lacombe5d095982012-01-23 17:29:05 -0500552 continue;
Roman Zippelc1a0f5e2005-11-08 21:34:54 -0800553 break;
554 }
555 } else if (!sym_has_value(sym) && !(sym->flags & SYMBOL_WRITE))
556 /* no previous value and not saved */
Arnaud Lacombe5d095982012-01-23 17:29:05 -0500557 continue;
Roman Zippelc1a0f5e2005-11-08 21:34:54 -0800558 conf_unsaved++;
559 /* maybe print value in verbose mode... */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560 }
561
Roman Zippeld8982ba2007-07-09 11:43:58 -0700562 for_all_symbols(i, sym) {
563 if (sym_has_value(sym) && !sym_is_choice_value(sym)) {
564 /* Reset values of generates values, so they'll appear
565 * as new, if they should become visible, but that
566 * doesn't quite work if the Kconfig and the saved
567 * configuration disagree.
568 */
569 if (sym->visible == no && !conf_unsaved)
570 sym->flags &= ~SYMBOL_DEF_USER;
571 switch (sym->type) {
572 case S_STRING:
573 case S_INT:
574 case S_HEX:
575 /* Reset a string value if it's out of range */
576 if (sym_string_within_range(sym, sym->def[S_DEF_USER].val))
577 break;
578 sym->flags &= ~(SYMBOL_VALID|SYMBOL_DEF_USER);
579 conf_unsaved++;
580 break;
581 default:
582 break;
583 }
584 }
585 }
586
Masahiro Yamada5ee54652021-04-10 15:57:22 +0900587 if (conf_warnings || conf_unsaved)
588 conf_set_changed(true);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700589
590 return 0;
591}
592
Masahiro Yamadaca51b262021-10-01 14:32:45 +0900593struct comment_style {
594 const char *decoration;
595 const char *prefix;
596 const char *postfix;
597};
598
599static const struct comment_style comment_style_pound = {
600 .decoration = "#",
601 .prefix = "#",
602 .postfix = "#",
603};
604
605static const struct comment_style comment_style_c = {
606 .decoration = " *",
607 .prefix = "/*",
608 .postfix = " */",
609};
610
611static void conf_write_heading(FILE *fp, const struct comment_style *cs)
612{
613 fprintf(fp, "%s\n", cs->prefix);
614
615 fprintf(fp, "%s Automatically generated file; DO NOT EDIT.\n",
616 cs->decoration);
617
618 fprintf(fp, "%s %s\n", cs->decoration, rootmenu.prompt->text);
619
620 fprintf(fp, "%s\n", cs->postfix);
621}
622
Arnaud Lacombee54e6922011-05-15 23:42:09 -0400623/*
624 * Kconfig configuration printer
625 *
626 * This printer is used when generating the resulting configuration after
627 * kconfig invocation and `defconfig' files. Unset symbol might be omitted by
628 * passing a non-NULL argument to the printer.
Arnaud Lacombee54e6922011-05-15 23:42:09 -0400629 */
Masahiro Yamada6ce45a92021-10-01 14:32:46 +0900630enum output_n { OUTPUT_N, OUTPUT_N_AS_UNSET, OUTPUT_N_NONE };
Sam Ravnborg49192f22010-07-31 23:35:33 +0200631
Masahiro Yamada6ce45a92021-10-01 14:32:46 +0900632static void __print_symbol(FILE *fp, struct symbol *sym, enum output_n output_n,
633 bool escape_string)
Arnaud Lacombee54e6922011-05-15 23:42:09 -0400634{
Masahiro Yamada229d0cf2021-10-01 14:32:44 +0900635 const char *val;
636 char *escaped = NULL;
Arnaud Lacombee54e6922011-05-15 23:42:09 -0400637
Masahiro Yamada229d0cf2021-10-01 14:32:44 +0900638 if (sym->type == S_UNKNOWN)
639 return;
640
641 val = sym_get_string_value(sym);
642
Masahiro Yamada6ce45a92021-10-01 14:32:46 +0900643 if ((sym->type == S_BOOLEAN || sym->type == S_TRISTATE) &&
644 output_n != OUTPUT_N && *val == 'n') {
645 if (output_n == OUTPUT_N_AS_UNSET)
646 fprintf(fp, "# %s%s is not set\n", CONFIG_, sym->name);
647 return;
648 }
649
650 if (sym->type == S_STRING && escape_string) {
Masahiro Yamada229d0cf2021-10-01 14:32:44 +0900651 escaped = sym_escape_string_value(val);
652 val = escaped;
Sam Ravnborg49192f22010-07-31 23:35:33 +0200653 }
Masahiro Yamada229d0cf2021-10-01 14:32:44 +0900654
Masahiro Yamada6ce45a92021-10-01 14:32:46 +0900655 fprintf(fp, "%s%s=%s\n", CONFIG_, sym->name, val);
656
657 free(escaped);
658}
659
660static void print_symbol_for_dotconfig(FILE *fp, struct symbol *sym)
661{
662 __print_symbol(fp, sym, OUTPUT_N_AS_UNSET, true);
663}
664
665static void print_symbol_for_autoconf(FILE *fp, struct symbol *sym)
666{
667 __print_symbol(fp, sym, OUTPUT_N_NONE, true);
668}
669
Masahiro Yamada51d792c2021-10-01 14:32:47 +0900670void print_symbol_for_listconfig(struct symbol *sym)
671{
672 __print_symbol(stdout, sym, OUTPUT_N, true);
673}
674
Masahiro Yamada6ce45a92021-10-01 14:32:46 +0900675static void print_symbol_for_c(FILE *fp, struct symbol *sym)
676{
677 const char *val;
678 const char *sym_suffix = "";
679 const char *val_prefix = "";
680 char *escaped = NULL;
681
682 if (sym->type == S_UNKNOWN)
683 return;
684
685 val = sym_get_string_value(sym);
686
687 switch (sym->type) {
688 case S_BOOLEAN:
689 case S_TRISTATE:
690 switch (*val) {
691 case 'n':
692 return;
693 case 'm':
694 sym_suffix = "_MODULE";
695 /* fall through */
696 default:
697 val = "1";
698 }
699 break;
700 case S_HEX:
701 if (val[0] != '0' || (val[1] != 'x' && val[1] != 'X'))
702 val_prefix = "0x";
703 break;
704 case S_STRING:
705 escaped = sym_escape_string_value(val);
706 val = escaped;
707 default:
708 break;
709 }
710
711 fprintf(fp, "#define %s%s%s %s%s\n", CONFIG_, sym->name, sym_suffix,
712 val_prefix, val);
Masahiro Yamada229d0cf2021-10-01 14:32:44 +0900713
714 free(escaped);
Sam Ravnborg49192f22010-07-31 23:35:33 +0200715}
716
Sam Ravnborg7cf3d732010-07-31 23:35:34 +0200717/*
718 * Write out a minimal config.
719 * All values that has default values are skipped as this is redundant.
720 */
721int conf_write_defconfig(const char *filename)
722{
723 struct symbol *sym;
724 struct menu *menu;
725 FILE *out;
726
727 out = fopen(filename, "w");
728 if (!out)
729 return 1;
730
731 sym_clear_all_valid();
732
733 /* Traverse all menus to find all relevant symbols */
734 menu = rootmenu.list;
735
736 while (menu != NULL)
737 {
738 sym = menu->sym;
739 if (sym == NULL) {
740 if (!menu_is_visible(menu))
741 goto next_menu;
742 } else if (!sym_is_choice(sym)) {
743 sym_calc_value(sym);
744 if (!(sym->flags & SYMBOL_WRITE))
745 goto next_menu;
746 sym->flags &= ~SYMBOL_WRITE;
747 /* If we cannot change the symbol - skip */
Marco Ammonbaa23ec2019-07-04 12:50:41 +0200748 if (!sym_is_changeable(sym))
Sam Ravnborg7cf3d732010-07-31 23:35:34 +0200749 goto next_menu;
750 /* If symbol equals to default value - skip */
751 if (strcmp(sym_get_string_value(sym), sym_get_string_default(sym)) == 0)
752 goto next_menu;
753
754 /*
755 * If symbol is a choice value and equals to the
756 * default for a choice - skip.
Sam Ravnborg84062dd2010-08-14 23:22:16 +0200757 * But only if value is bool and equal to "y" and
758 * choice is not "optional".
759 * (If choice is "optional" then all values can be "n")
Sam Ravnborg7cf3d732010-07-31 23:35:34 +0200760 */
761 if (sym_is_choice_value(sym)) {
762 struct symbol *cs;
763 struct symbol *ds;
764
765 cs = prop_get_symbol(sym_get_choice_prop(sym));
766 ds = sym_choice_default(cs);
Sam Ravnborg84062dd2010-08-14 23:22:16 +0200767 if (!sym_is_optional(cs) && sym == ds) {
Sam Ravnborg801690c2010-08-12 09:11:51 +0200768 if ((sym->type == S_BOOLEAN) &&
769 sym_get_tristate_value(sym) == yes)
Sam Ravnborg7cf3d732010-07-31 23:35:34 +0200770 goto next_menu;
771 }
772 }
Masahiro Yamada6ce45a92021-10-01 14:32:46 +0900773 print_symbol_for_dotconfig(out, sym);
Sam Ravnborg7cf3d732010-07-31 23:35:34 +0200774 }
775next_menu:
776 if (menu->list != NULL) {
777 menu = menu->list;
778 }
779 else if (menu->next != NULL) {
780 menu = menu->next;
781 } else {
782 while ((menu = menu->parent)) {
783 if (menu->next != NULL) {
784 menu = menu->next;
785 break;
786 }
787 }
788 }
789 }
790 fclose(out);
791 return 0;
792}
793
Linus Torvalds1da177e2005-04-16 15:20:36 -0700794int conf_write(const char *name)
795{
Roman Zippelc955cca2006-06-08 22:12:39 -0700796 FILE *out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700797 struct symbol *sym;
798 struct menu *menu;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799 const char *str;
Masahiro Yamadaceb7f322019-05-10 15:12:04 +0900800 char tmpname[PATH_MAX + 1], oldname[PATH_MAX + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700801 char *env;
M. Vefa Bicakci0c5b6c282019-08-03 06:02:12 -0400802 int i;
Alexander Popovaff11cd2019-05-17 22:42:22 +0300803 bool need_newline = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700804
Masahiro Yamadaceb7f322019-05-10 15:12:04 +0900805 if (!name)
806 name = conf_get_configname();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700807
Masahiro Yamadaceb7f322019-05-10 15:12:04 +0900808 if (!*name) {
809 fprintf(stderr, "config name is empty\n");
810 return -1;
811 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700812
Masahiro Yamadaceb7f322019-05-10 15:12:04 +0900813 if (is_dir(name)) {
814 fprintf(stderr, "%s: Is a directory\n", name);
815 return -1;
816 }
817
Masahiro Yamada580c5b32019-05-11 01:56:01 +0900818 if (make_parent_dir(name))
819 return -1;
820
Roman Zippel14cdd3c2006-06-08 22:12:51 -0700821 env = getenv("KCONFIG_OVERWRITECONFIG");
Masahiro Yamadaceb7f322019-05-10 15:12:04 +0900822 if (env && *env) {
Roman Zippel14cdd3c2006-06-08 22:12:51 -0700823 *tmpname = 0;
Masahiro Yamadaceb7f322019-05-10 15:12:04 +0900824 out = fopen(name, "w");
825 } else {
826 snprintf(tmpname, sizeof(tmpname), "%s.%d.tmp",
827 name, (int)getpid());
828 out = fopen(tmpname, "w");
Roman Zippel14cdd3c2006-06-08 22:12:51 -0700829 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700830 if (!out)
831 return 1;
Roman Zippel14cdd3c2006-06-08 22:12:51 -0700832
Masahiro Yamadaca51b262021-10-01 14:32:45 +0900833 conf_write_heading(out, &comment_style_pound);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700834
Karsten Wieseb3214292006-12-13 00:34:06 -0800835 if (!conf_get_changed())
Linus Torvalds1da177e2005-04-16 15:20:36 -0700836 sym_clear_all_valid();
837
838 menu = rootmenu.list;
839 while (menu) {
840 sym = menu->sym;
841 if (!sym) {
842 if (!menu_is_visible(menu))
843 goto next;
844 str = menu_get_prompt(menu);
845 fprintf(out, "\n"
846 "#\n"
847 "# %s\n"
848 "#\n", str);
Alexander Popovaff11cd2019-05-17 22:42:22 +0300849 need_newline = false;
Masahiro Yamada8e2442a2019-07-12 15:07:09 +0900850 } else if (!(sym->flags & SYMBOL_CHOICE) &&
851 !(sym->flags & SYMBOL_WRITTEN)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700852 sym_calc_value(sym);
853 if (!(sym->flags & SYMBOL_WRITE))
854 goto next;
Alexander Popovaff11cd2019-05-17 22:42:22 +0300855 if (need_newline) {
856 fprintf(out, "\n");
857 need_newline = false;
858 }
Masahiro Yamada8e2442a2019-07-12 15:07:09 +0900859 sym->flags |= SYMBOL_WRITTEN;
Masahiro Yamada6ce45a92021-10-01 14:32:46 +0900860 print_symbol_for_dotconfig(out, sym);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700861 }
862
Sam Ravnborg49192f22010-07-31 23:35:33 +0200863next:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700864 if (menu->list) {
865 menu = menu->list;
866 continue;
867 }
868 if (menu->next)
869 menu = menu->next;
870 else while ((menu = menu->parent)) {
Alexander Popovaff11cd2019-05-17 22:42:22 +0300871 if (!menu->sym && menu_is_visible(menu) &&
872 menu != &rootmenu) {
873 str = menu_get_prompt(menu);
874 fprintf(out, "# end of %s\n", str);
875 need_newline = true;
876 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700877 if (menu->next) {
878 menu = menu->next;
879 break;
880 }
881 }
882 }
883 fclose(out);
Roman Zippel14cdd3c2006-06-08 22:12:51 -0700884
M. Vefa Bicakci0c5b6c282019-08-03 06:02:12 -0400885 for_all_symbols(i, sym)
886 sym->flags &= ~SYMBOL_WRITTEN;
887
Roman Zippel14cdd3c2006-06-08 22:12:51 -0700888 if (*tmpname) {
Masahiro Yamada67424f62019-05-10 15:12:05 +0900889 if (is_same(name, tmpname)) {
890 conf_message("No change to %s", name);
891 unlink(tmpname);
Masahiro Yamada5ee54652021-04-10 15:57:22 +0900892 conf_set_changed(false);
Masahiro Yamada67424f62019-05-10 15:12:05 +0900893 return 0;
894 }
895
Masahiro Yamadaceb7f322019-05-10 15:12:04 +0900896 snprintf(oldname, sizeof(oldname), "%s.old", name);
897 rename(name, oldname);
898 if (rename(tmpname, name))
Roman Zippel14cdd3c2006-06-08 22:12:51 -0700899 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700900 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901
Masahiro Yamadaceb7f322019-05-10 15:12:04 +0900902 conf_message("configuration written to %s", name);
Roman Zippelddc97ca2006-06-08 22:12:38 -0700903
Masahiro Yamada5ee54652021-04-10 15:57:22 +0900904 conf_set_changed(false);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905
906 return 0;
907}
Roman Zippelc955cca2006-06-08 22:12:39 -0700908
Masahiro Yamadaa2ff4042018-07-20 16:46:26 +0900909/* write a dependency file as used by kbuild to track dependencies */
910static int conf_write_dep(const char *name)
911{
912 struct file *file;
913 FILE *out;
914
Masahiro Yamadaa2ff4042018-07-20 16:46:26 +0900915 out = fopen("..config.tmp", "w");
916 if (!out)
917 return 1;
918 fprintf(out, "deps_config := \\\n");
919 for (file = file_list; file; file = file->next) {
920 if (file->next)
921 fprintf(out, "\t%s \\\n", file->name);
922 else
923 fprintf(out, "\t%s\n", file->name);
924 }
925 fprintf(out, "\n%s: \\\n"
926 "\t$(deps_config)\n\n", conf_get_autoconfig_name());
927
928 env_write_dep(out, conf_get_autoconfig_name());
929
930 fprintf(out, "\n$(deps_config): ;\n");
931 fclose(out);
Masahiro Yamada79123b12018-07-20 16:46:29 +0900932
933 if (make_parent_dir(name))
934 return 1;
Masahiro Yamadaa2ff4042018-07-20 16:46:26 +0900935 rename("..config.tmp", name);
936 return 0;
937}
938
Masahiro Yamada0849d212018-11-30 18:15:49 +0900939static int conf_touch_deps(void)
Roman Zippel2e3646e2006-06-08 22:12:42 -0700940{
Markus Heidelberg12122f62009-05-18 01:36:54 +0200941 const char *name;
Roman Zippel2e3646e2006-06-08 22:12:42 -0700942 struct symbol *sym;
Masahiro Yamada1508fec2018-11-30 18:15:50 +0900943 int res, i;
944
945 strcpy(depfile_path, "include/config/");
946 depfile_prefix_len = strlen(depfile_path);
Roman Zippel2e3646e2006-06-08 22:12:42 -0700947
Markus Heidelberg12122f62009-05-18 01:36:54 +0200948 name = conf_get_autoconfig_name();
Roman Zippel2e3646e2006-06-08 22:12:42 -0700949 conf_read_simple(name, S_DEF_AUTO);
Al Viro6b87b702016-01-14 18:13:49 +0000950 sym_calc_value(modules_sym);
Roman Zippel2e3646e2006-06-08 22:12:42 -0700951
Roman Zippel2e3646e2006-06-08 22:12:42 -0700952 for_all_symbols(i, sym) {
953 sym_calc_value(sym);
Dirk Gouders693359f2018-07-03 14:43:31 +0200954 if ((sym->flags & SYMBOL_NO_WRITE) || !sym->name)
Roman Zippel2e3646e2006-06-08 22:12:42 -0700955 continue;
956 if (sym->flags & SYMBOL_WRITE) {
957 if (sym->flags & SYMBOL_DEF_AUTO) {
958 /*
959 * symbol has old and new value,
960 * so compare them...
961 */
962 switch (sym->type) {
963 case S_BOOLEAN:
964 case S_TRISTATE:
965 if (sym_get_tristate_value(sym) ==
966 sym->def[S_DEF_AUTO].tri)
967 continue;
968 break;
969 case S_STRING:
970 case S_HEX:
971 case S_INT:
972 if (!strcmp(sym_get_string_value(sym),
973 sym->def[S_DEF_AUTO].val))
974 continue;
975 break;
976 default:
977 break;
978 }
979 } else {
980 /*
981 * If there is no old value, only 'no' (unset)
982 * is allowed as new value.
983 */
984 switch (sym->type) {
985 case S_BOOLEAN:
986 case S_TRISTATE:
987 if (sym_get_tristate_value(sym) == no)
988 continue;
989 break;
990 default:
991 break;
992 }
993 }
994 } else if (!(sym->flags & SYMBOL_DEF_AUTO))
995 /* There is neither an old nor a new value. */
996 continue;
997 /* else
998 * There is an old value, but no new value ('no' (unset)
999 * isn't saved in auto.conf, so the old value is always
1000 * different from 'no').
1001 */
1002
Masahiro Yamada1508fec2018-11-30 18:15:50 +09001003 res = conf_touch_dep(sym->name);
1004 if (res)
1005 return res;
Roman Zippel2e3646e2006-06-08 22:12:42 -07001006 }
Roman Zippel2e3646e2006-06-08 22:12:42 -07001007
Masahiro Yamada1508fec2018-11-30 18:15:50 +09001008 return 0;
Roman Zippel2e3646e2006-06-08 22:12:42 -07001009}
1010
Masahiro Yamada00c864f2018-07-20 16:46:31 +09001011int conf_write_autoconf(int overwrite)
Roman Zippelc955cca2006-06-08 22:12:39 -07001012{
1013 struct symbol *sym;
Markus Heidelberg12122f62009-05-18 01:36:54 +02001014 const char *name;
Masahiro Yamada00c864f2018-07-20 16:46:31 +09001015 const char *autoconf_name = conf_get_autoconfig_name();
Masahiro Yamada8b41fc42019-12-19 17:33:29 +09001016 FILE *out, *out_h;
Sam Ravnborg49192f22010-07-31 23:35:33 +02001017 int i;
Roman Zippelc955cca2006-06-08 22:12:39 -07001018
Masahiro Yamada00c864f2018-07-20 16:46:31 +09001019 if (!overwrite && is_present(autoconf_name))
1020 return 0;
1021
Masahiro Yamadaa2ff4042018-07-20 16:46:26 +09001022 conf_write_dep("include/config/auto.conf.cmd");
Roman Zippelc955cca2006-06-08 22:12:39 -07001023
Masahiro Yamada0849d212018-11-30 18:15:49 +09001024 if (conf_touch_deps())
Roman Zippel2e3646e2006-06-08 22:12:42 -07001025 return 1;
1026
Roman Zippelc955cca2006-06-08 22:12:39 -07001027 out = fopen(".tmpconfig", "w");
1028 if (!out)
1029 return 1;
1030
1031 out_h = fopen(".tmpconfig.h", "w");
1032 if (!out_h) {
1033 fclose(out);
1034 return 1;
1035 }
1036
Masahiro Yamadaca51b262021-10-01 14:32:45 +09001037 conf_write_heading(out, &comment_style_pound);
1038 conf_write_heading(out_h, &comment_style_c);
Roman Zippelc955cca2006-06-08 22:12:39 -07001039
Roman Zippelc955cca2006-06-08 22:12:39 -07001040 for_all_symbols(i, sym) {
Arnaud Lacombe953742c2011-08-16 01:20:20 -04001041 sym_calc_value(sym);
Paul Gortmakera9596132012-04-12 19:46:33 -04001042 if (!(sym->flags & SYMBOL_WRITE) || !sym->name)
Arnaud Lacombe953742c2011-08-16 01:20:20 -04001043 continue;
1044
Masahiro Yamada8b41fc42019-12-19 17:33:29 +09001045 /* write symbols to auto.conf and autoconf.h */
Masahiro Yamada6ce45a92021-10-01 14:32:46 +09001046 print_symbol_for_autoconf(out, sym);
1047 print_symbol_for_c(out_h, sym);
Roman Zippelc955cca2006-06-08 22:12:39 -07001048 }
1049 fclose(out);
1050 fclose(out_h);
1051
1052 name = getenv("KCONFIG_AUTOHEADER");
1053 if (!name)
Sam Ravnborg264a2682009-10-18 00:49:24 +02001054 name = "include/generated/autoconf.h";
Masahiro Yamada79123b12018-07-20 16:46:29 +09001055 if (make_parent_dir(name))
1056 return 1;
Roman Zippelc955cca2006-06-08 22:12:39 -07001057 if (rename(".tmpconfig.h", name))
1058 return 1;
Masahiro Yamada79123b12018-07-20 16:46:29 +09001059
Masahiro Yamada00c864f2018-07-20 16:46:31 +09001060 if (make_parent_dir(autoconf_name))
Masahiro Yamada79123b12018-07-20 16:46:29 +09001061 return 1;
Roman Zippelc955cca2006-06-08 22:12:39 -07001062 /*
1063 * This must be the last step, kbuild has a dependency on auto.conf
1064 * and this marks the successful completion of the previous steps.
1065 */
Masahiro Yamada00c864f2018-07-20 16:46:31 +09001066 if (rename(".tmpconfig", autoconf_name))
Roman Zippelc955cca2006-06-08 22:12:39 -07001067 return 1;
1068
1069 return 0;
1070}
Karsten Wieseb3214292006-12-13 00:34:06 -08001071
Masahiro Yamada5ee54652021-04-10 15:57:22 +09001072static bool conf_changed;
Karsten Wiese3b354c52006-12-13 00:34:08 -08001073static void (*conf_changed_callback)(void);
Karsten Wiesebfc10002006-12-13 00:34:07 -08001074
Masahiro Yamada5ee54652021-04-10 15:57:22 +09001075void conf_set_changed(bool val)
Karsten Wiesebfc10002006-12-13 00:34:07 -08001076{
Masahiro Yamada5ee54652021-04-10 15:57:22 +09001077 if (conf_changed_callback && conf_changed != val)
Karsten Wiese3b354c52006-12-13 00:34:08 -08001078 conf_changed_callback();
Karsten Wiesebfc10002006-12-13 00:34:07 -08001079
Masahiro Yamada5ee54652021-04-10 15:57:22 +09001080 conf_changed = val;
Karsten Wiesebfc10002006-12-13 00:34:07 -08001081}
1082
Karsten Wieseb3214292006-12-13 00:34:06 -08001083bool conf_get_changed(void)
1084{
Masahiro Yamada5ee54652021-04-10 15:57:22 +09001085 return conf_changed;
Karsten Wieseb3214292006-12-13 00:34:06 -08001086}
Karsten Wiese3b354c52006-12-13 00:34:08 -08001087
1088void conf_set_changed_callback(void (*fn)(void))
1089{
1090 conf_changed_callback = fn;
1091}
Roman Zippeldc7862e2008-05-06 04:55:55 +02001092
Arve Hjønnevågfbe98bb92013-06-06 20:37:00 -07001093void set_all_choice_values(struct symbol *csym)
Sam Ravnborga64b44e2010-08-12 09:11:52 +02001094{
1095 struct property *prop;
1096 struct symbol *sym;
1097 struct expr *e;
1098
1099 prop = sym_get_choice_prop(csym);
1100
1101 /*
1102 * Set all non-assinged choice values to no
1103 */
1104 expr_list_for_each_sym(prop->expr, e, sym) {
1105 if (!sym_has_value(sym))
1106 sym->def[S_DEF_USER].tri = no;
1107 }
1108 csym->flags |= SYMBOL_DEF_USER;
1109 /* clear VALID to get value calculated */
Arve Hjønnevågfbe98bb92013-06-06 20:37:00 -07001110 csym->flags &= ~(SYMBOL_VALID | SYMBOL_NEED_SET_CHOICE_VALUES);
Sam Ravnborga64b44e2010-08-12 09:11:52 +02001111}