xref: /openbmc/linux/scripts/kconfig/confdata.c (revision 058250a0d5886b4d96a195ecc7e3a75e2df5e4b1)
1 /*
2  * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
3  * Released under the terms of the GNU GPL v2.0.
4  */
5 
6 #include <sys/stat.h>
7 #include <ctype.h>
8 #include <fcntl.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <time.h>
13 #include <unistd.h>
14 
15 #define LKC_DIRECT_LINK
16 #include "lkc.h"
17 
18 static void conf_warning(const char *fmt, ...)
19 	__attribute__ ((format (printf, 1, 2)));
20 
21 static const char *conf_filename;
22 static int conf_lineno, conf_warnings, conf_unsaved;
23 
24 const char conf_defname[] = "arch/$ARCH/defconfig";
25 
26 static void conf_warning(const char *fmt, ...)
27 {
28 	va_list ap;
29 	va_start(ap, fmt);
30 	fprintf(stderr, "%s:%d:warning: ", conf_filename, conf_lineno);
31 	vfprintf(stderr, fmt, ap);
32 	fprintf(stderr, "\n");
33 	va_end(ap);
34 	conf_warnings++;
35 }
36 
37 const char *conf_get_configname(void)
38 {
39 	char *name = getenv("KCONFIG_CONFIG");
40 
41 	return name ? name : ".config";
42 }
43 
44 static char *conf_expand_value(const char *in)
45 {
46 	struct symbol *sym;
47 	const char *src;
48 	static char res_value[SYMBOL_MAXLENGTH];
49 	char *dst, name[SYMBOL_MAXLENGTH];
50 
51 	res_value[0] = 0;
52 	dst = name;
53 	while ((src = strchr(in, '$'))) {
54 		strncat(res_value, in, src - in);
55 		src++;
56 		dst = name;
57 		while (isalnum(*src) || *src == '_')
58 			*dst++ = *src++;
59 		*dst = 0;
60 		sym = sym_lookup(name, 0);
61 		sym_calc_value(sym);
62 		strcat(res_value, sym_get_string_value(sym));
63 		in = src;
64 	}
65 	strcat(res_value, in);
66 
67 	return res_value;
68 }
69 
70 char *conf_get_default_confname(void)
71 {
72 	struct stat buf;
73 	static char fullname[PATH_MAX+1];
74 	char *env, *name;
75 
76 	name = conf_expand_value(conf_defname);
77 	env = getenv(SRCTREE);
78 	if (env) {
79 		sprintf(fullname, "%s/%s", env, name);
80 		if (!stat(fullname, &buf))
81 			return fullname;
82 	}
83 	return name;
84 }
85 
86 static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
87 {
88 	char *p2;
89 
90 	switch (sym->type) {
91 	case S_TRISTATE:
92 		if (p[0] == 'm') {
93 			sym->def[def].tri = mod;
94 			sym->flags |= def_flags;
95 			break;
96 		}
97 	case S_BOOLEAN:
98 		if (p[0] == 'y') {
99 			sym->def[def].tri = yes;
100 			sym->flags |= def_flags;
101 			break;
102 		}
103 		if (p[0] == 'n') {
104 			sym->def[def].tri = no;
105 			sym->flags |= def_flags;
106 			break;
107 		}
108 		conf_warning("symbol value '%s' invalid for %s", p, sym->name);
109 		break;
110 	case S_OTHER:
111 		if (*p != '"') {
112 			for (p2 = p; *p2 && !isspace(*p2); p2++)
113 				;
114 			sym->type = S_STRING;
115 			goto done;
116 		}
117 	case S_STRING:
118 		if (*p++ != '"')
119 			break;
120 		for (p2 = p; (p2 = strpbrk(p2, "\"\\")); p2++) {
121 			if (*p2 == '"') {
122 				*p2 = 0;
123 				break;
124 			}
125 			memmove(p2, p2 + 1, strlen(p2));
126 		}
127 		if (!p2) {
128 			conf_warning("invalid string found");
129 			return 1;
130 		}
131 	case S_INT:
132 	case S_HEX:
133 	done:
134 		if (sym_string_valid(sym, p)) {
135 			sym->def[def].val = strdup(p);
136 			sym->flags |= def_flags;
137 		} else {
138 			conf_warning("symbol value '%s' invalid for %s", p, sym->name);
139 			return 1;
140 		}
141 		break;
142 	default:
143 		;
144 	}
145 	return 0;
146 }
147 
148 int conf_read_simple(const char *name, int def)
149 {
150 	FILE *in = NULL;
151 	char line[1024];
152 	char *p, *p2;
153 	struct symbol *sym;
154 	int i, def_flags;
155 
156 	if (name) {
157 		in = zconf_fopen(name);
158 	} else {
159 		struct property *prop;
160 
161 		name = conf_get_configname();
162 		in = zconf_fopen(name);
163 		if (in)
164 			goto load;
165 		sym_add_change_count(1);
166 		if (!sym_defconfig_list)
167 			return 1;
168 
169 		for_all_defaults(sym_defconfig_list, prop) {
170 			if (expr_calc_value(prop->visible.expr) == no ||
171 			    prop->expr->type != E_SYMBOL)
172 				continue;
173 			name = conf_expand_value(prop->expr->left.sym->name);
174 			in = zconf_fopen(name);
175 			if (in) {
176 				printf(_("#\n"
177 					 "# using defaults found in %s\n"
178 					 "#\n"), name);
179 				goto load;
180 			}
181 		}
182 	}
183 	if (!in)
184 		return 1;
185 
186 load:
187 	conf_filename = name;
188 	conf_lineno = 0;
189 	conf_warnings = 0;
190 	conf_unsaved = 0;
191 
192 	def_flags = SYMBOL_DEF << def;
193 	for_all_symbols(i, sym) {
194 		sym->flags |= SYMBOL_CHANGED;
195 		sym->flags &= ~(def_flags|SYMBOL_VALID);
196 		if (sym_is_choice(sym))
197 			sym->flags |= def_flags;
198 		switch (sym->type) {
199 		case S_INT:
200 		case S_HEX:
201 		case S_STRING:
202 			if (sym->def[def].val)
203 				free(sym->def[def].val);
204 		default:
205 			sym->def[def].val = NULL;
206 			sym->def[def].tri = no;
207 		}
208 	}
209 
210 	while (fgets(line, sizeof(line), in)) {
211 		conf_lineno++;
212 		sym = NULL;
213 		switch (line[0]) {
214 		case '#':
215 			if (memcmp(line + 2, "CONFIG_", 7))
216 				continue;
217 			p = strchr(line + 9, ' ');
218 			if (!p)
219 				continue;
220 			*p++ = 0;
221 			if (strncmp(p, "is not set", 10))
222 				continue;
223 			if (def == S_DEF_USER) {
224 				sym = sym_find(line + 9);
225 				if (!sym) {
226 					conf_warning("trying to assign nonexistent symbol %s", line + 9);
227 					break;
228 				}
229 			} else {
230 				sym = sym_lookup(line + 9, 0);
231 				if (sym->type == S_UNKNOWN)
232 					sym->type = S_BOOLEAN;
233 			}
234 			if (sym->flags & def_flags) {
235 				conf_warning("trying to reassign symbol %s", sym->name);
236 				break;
237 			}
238 			switch (sym->type) {
239 			case S_BOOLEAN:
240 			case S_TRISTATE:
241 				sym->def[def].tri = no;
242 				sym->flags |= def_flags;
243 				break;
244 			default:
245 				;
246 			}
247 			break;
248 		case 'C':
249 			if (memcmp(line, "CONFIG_", 7)) {
250 				conf_warning("unexpected data");
251 				continue;
252 			}
253 			p = strchr(line + 7, '=');
254 			if (!p)
255 				continue;
256 			*p++ = 0;
257 			p2 = strchr(p, '\n');
258 			if (p2) {
259 				*p2-- = 0;
260 				if (*p2 == '\r')
261 					*p2 = 0;
262 			}
263 			if (def == S_DEF_USER) {
264 				sym = sym_find(line + 7);
265 				if (!sym) {
266 					conf_warning("trying to assign nonexistent symbol %s", line + 7);
267 					break;
268 				}
269 			} else {
270 				sym = sym_lookup(line + 7, 0);
271 				if (sym->type == S_UNKNOWN)
272 					sym->type = S_OTHER;
273 			}
274 			if (sym->flags & def_flags) {
275 				conf_warning("trying to reassign symbol %s", sym->name);
276 				break;
277 			}
278 			if (conf_set_sym_val(sym, def, def_flags, p))
279 				continue;
280 			break;
281 		case '\r':
282 		case '\n':
283 			break;
284 		default:
285 			conf_warning("unexpected data");
286 			continue;
287 		}
288 		if (sym && sym_is_choice_value(sym)) {
289 			struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
290 			switch (sym->def[def].tri) {
291 			case no:
292 				break;
293 			case mod:
294 				if (cs->def[def].tri == yes) {
295 					conf_warning("%s creates inconsistent choice state", sym->name);
296 					cs->flags &= ~def_flags;
297 				}
298 				break;
299 			case yes:
300 				if (cs->def[def].tri != no) {
301 					conf_warning("%s creates inconsistent choice state", sym->name);
302 					cs->flags &= ~def_flags;
303 				} else
304 					cs->def[def].val = sym;
305 				break;
306 			}
307 			cs->def[def].tri = E_OR(cs->def[def].tri, sym->def[def].tri);
308 		}
309 	}
310 	fclose(in);
311 
312 	if (modules_sym)
313 		sym_calc_value(modules_sym);
314 	return 0;
315 }
316 
317 int conf_read(const char *name)
318 {
319 	struct symbol *sym;
320 	struct property *prop;
321 	struct expr *e;
322 	int i, flags;
323 
324 	sym_set_change_count(0);
325 
326 	if (conf_read_simple(name, S_DEF_USER))
327 		return 1;
328 
329 	for_all_symbols(i, sym) {
330 		sym_calc_value(sym);
331 		if (sym_is_choice(sym) || (sym->flags & SYMBOL_AUTO))
332 			goto sym_ok;
333 		if (sym_has_value(sym) && (sym->flags & SYMBOL_WRITE)) {
334 			/* check that calculated value agrees with saved value */
335 			switch (sym->type) {
336 			case S_BOOLEAN:
337 			case S_TRISTATE:
338 				if (sym->def[S_DEF_USER].tri != sym_get_tristate_value(sym))
339 					break;
340 				if (!sym_is_choice(sym))
341 					goto sym_ok;
342 			default:
343 				if (!strcmp(sym->curr.val, sym->def[S_DEF_USER].val))
344 					goto sym_ok;
345 				break;
346 			}
347 		} else if (!sym_has_value(sym) && !(sym->flags & SYMBOL_WRITE))
348 			/* no previous value and not saved */
349 			goto sym_ok;
350 		conf_unsaved++;
351 		/* maybe print value in verbose mode... */
352 	sym_ok:
353 		if (!sym_is_choice(sym))
354 			continue;
355 		/* The choice symbol only has a set value (and thus is not new)
356 		 * if all its visible childs have values.
357 		 */
358 		prop = sym_get_choice_prop(sym);
359 		flags = sym->flags;
360 		for (e = prop->expr; e; e = e->left.expr)
361 			if (e->right.sym->visible != no)
362 				flags &= e->right.sym->flags;
363 		sym->flags &= flags | ~SYMBOL_DEF_USER;
364 	}
365 
366 	for_all_symbols(i, sym) {
367 		if (sym_has_value(sym) && !sym_is_choice_value(sym)) {
368 			/* Reset values of generates values, so they'll appear
369 			 * as new, if they should become visible, but that
370 			 * doesn't quite work if the Kconfig and the saved
371 			 * configuration disagree.
372 			 */
373 			if (sym->visible == no && !conf_unsaved)
374 				sym->flags &= ~SYMBOL_DEF_USER;
375 			switch (sym->type) {
376 			case S_STRING:
377 			case S_INT:
378 			case S_HEX:
379 				/* Reset a string value if it's out of range */
380 				if (sym_string_within_range(sym, sym->def[S_DEF_USER].val))
381 					break;
382 				sym->flags &= ~(SYMBOL_VALID|SYMBOL_DEF_USER);
383 				conf_unsaved++;
384 				break;
385 			default:
386 				break;
387 			}
388 		}
389 	}
390 
391 	sym_add_change_count(conf_warnings || conf_unsaved);
392 
393 	return 0;
394 }
395 
396 int conf_write(const char *name)
397 {
398 	FILE *out;
399 	struct symbol *sym;
400 	struct menu *menu;
401 	const char *basename;
402 	char dirname[128], tmpname[128], newname[128];
403 	int type, l;
404 	const char *str;
405 	time_t now;
406 	int use_timestamp = 1;
407 	char *env;
408 
409 	dirname[0] = 0;
410 	if (name && name[0]) {
411 		struct stat st;
412 		char *slash;
413 
414 		if (!stat(name, &st) && S_ISDIR(st.st_mode)) {
415 			strcpy(dirname, name);
416 			strcat(dirname, "/");
417 			basename = conf_get_configname();
418 		} else if ((slash = strrchr(name, '/'))) {
419 			int size = slash - name + 1;
420 			memcpy(dirname, name, size);
421 			dirname[size] = 0;
422 			if (slash[1])
423 				basename = slash + 1;
424 			else
425 				basename = conf_get_configname();
426 		} else
427 			basename = name;
428 	} else
429 		basename = conf_get_configname();
430 
431 	sprintf(newname, "%s%s", dirname, basename);
432 	env = getenv("KCONFIG_OVERWRITECONFIG");
433 	if (!env || !*env) {
434 		sprintf(tmpname, "%s.tmpconfig.%d", dirname, (int)getpid());
435 		out = fopen(tmpname, "w");
436 	} else {
437 		*tmpname = 0;
438 		out = fopen(newname, "w");
439 	}
440 	if (!out)
441 		return 1;
442 
443 	sym = sym_lookup("KERNELVERSION", 0);
444 	sym_calc_value(sym);
445 	time(&now);
446 	env = getenv("KCONFIG_NOTIMESTAMP");
447 	if (env && *env)
448 		use_timestamp = 0;
449 
450 	fprintf(out, _("#\n"
451 		       "# Automatically generated make config: don't edit\n"
452 		       "# Linux kernel version: %s\n"
453 		       "%s%s"
454 		       "#\n"),
455 		     sym_get_string_value(sym),
456 		     use_timestamp ? "# " : "",
457 		     use_timestamp ? ctime(&now) : "");
458 
459 	if (!conf_get_changed())
460 		sym_clear_all_valid();
461 
462 	menu = rootmenu.list;
463 	while (menu) {
464 		sym = menu->sym;
465 		if (!sym) {
466 			if (!menu_is_visible(menu))
467 				goto next;
468 			str = menu_get_prompt(menu);
469 			fprintf(out, "\n"
470 				     "#\n"
471 				     "# %s\n"
472 				     "#\n", str);
473 		} else if (!(sym->flags & SYMBOL_CHOICE)) {
474 			sym_calc_value(sym);
475 			if (!(sym->flags & SYMBOL_WRITE))
476 				goto next;
477 			sym->flags &= ~SYMBOL_WRITE;
478 			type = sym->type;
479 			if (type == S_TRISTATE) {
480 				sym_calc_value(modules_sym);
481 				if (modules_sym->curr.tri == no)
482 					type = S_BOOLEAN;
483 			}
484 			switch (type) {
485 			case S_BOOLEAN:
486 			case S_TRISTATE:
487 				switch (sym_get_tristate_value(sym)) {
488 				case no:
489 					fprintf(out, "# CONFIG_%s is not set\n", sym->name);
490 					break;
491 				case mod:
492 					fprintf(out, "CONFIG_%s=m\n", sym->name);
493 					break;
494 				case yes:
495 					fprintf(out, "CONFIG_%s=y\n", sym->name);
496 					break;
497 				}
498 				break;
499 			case S_STRING:
500 				str = sym_get_string_value(sym);
501 				fprintf(out, "CONFIG_%s=\"", sym->name);
502 				while (1) {
503 					l = strcspn(str, "\"\\");
504 					if (l) {
505 						fwrite(str, l, 1, out);
506 						str += l;
507 					}
508 					if (!*str)
509 						break;
510 					fprintf(out, "\\%c", *str++);
511 				}
512 				fputs("\"\n", out);
513 				break;
514 			case S_HEX:
515 				str = sym_get_string_value(sym);
516 				if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) {
517 					fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
518 					break;
519 				}
520 			case S_INT:
521 				str = sym_get_string_value(sym);
522 				fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
523 				break;
524 			}
525 		}
526 
527 	next:
528 		if (menu->list) {
529 			menu = menu->list;
530 			continue;
531 		}
532 		if (menu->next)
533 			menu = menu->next;
534 		else while ((menu = menu->parent)) {
535 			if (menu->next) {
536 				menu = menu->next;
537 				break;
538 			}
539 		}
540 	}
541 	fclose(out);
542 
543 	if (*tmpname) {
544 		strcat(dirname, basename);
545 		strcat(dirname, ".old");
546 		rename(newname, dirname);
547 		if (rename(tmpname, newname))
548 			return 1;
549 	}
550 
551 	printf(_("#\n"
552 		 "# configuration written to %s\n"
553 		 "#\n"), newname);
554 
555 	sym_set_change_count(0);
556 
557 	return 0;
558 }
559 
560 int conf_split_config(void)
561 {
562 	char *name, path[128];
563 	char *s, *d, c;
564 	struct symbol *sym;
565 	struct stat sb;
566 	int res, i, fd;
567 
568 	name = getenv("KCONFIG_AUTOCONFIG");
569 	if (!name)
570 		name = "include/config/auto.conf";
571 	conf_read_simple(name, S_DEF_AUTO);
572 
573 	if (chdir("include/config"))
574 		return 1;
575 
576 	res = 0;
577 	for_all_symbols(i, sym) {
578 		sym_calc_value(sym);
579 		if ((sym->flags & SYMBOL_AUTO) || !sym->name)
580 			continue;
581 		if (sym->flags & SYMBOL_WRITE) {
582 			if (sym->flags & SYMBOL_DEF_AUTO) {
583 				/*
584 				 * symbol has old and new value,
585 				 * so compare them...
586 				 */
587 				switch (sym->type) {
588 				case S_BOOLEAN:
589 				case S_TRISTATE:
590 					if (sym_get_tristate_value(sym) ==
591 					    sym->def[S_DEF_AUTO].tri)
592 						continue;
593 					break;
594 				case S_STRING:
595 				case S_HEX:
596 				case S_INT:
597 					if (!strcmp(sym_get_string_value(sym),
598 						    sym->def[S_DEF_AUTO].val))
599 						continue;
600 					break;
601 				default:
602 					break;
603 				}
604 			} else {
605 				/*
606 				 * If there is no old value, only 'no' (unset)
607 				 * is allowed as new value.
608 				 */
609 				switch (sym->type) {
610 				case S_BOOLEAN:
611 				case S_TRISTATE:
612 					if (sym_get_tristate_value(sym) == no)
613 						continue;
614 					break;
615 				default:
616 					break;
617 				}
618 			}
619 		} else if (!(sym->flags & SYMBOL_DEF_AUTO))
620 			/* There is neither an old nor a new value. */
621 			continue;
622 		/* else
623 		 *	There is an old value, but no new value ('no' (unset)
624 		 *	isn't saved in auto.conf, so the old value is always
625 		 *	different from 'no').
626 		 */
627 
628 		/* Replace all '_' and append ".h" */
629 		s = sym->name;
630 		d = path;
631 		while ((c = *s++)) {
632 			c = tolower(c);
633 			*d++ = (c == '_') ? '/' : c;
634 		}
635 		strcpy(d, ".h");
636 
637 		/* Assume directory path already exists. */
638 		fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
639 		if (fd == -1) {
640 			if (errno != ENOENT) {
641 				res = 1;
642 				break;
643 			}
644 			/*
645 			 * Create directory components,
646 			 * unless they exist already.
647 			 */
648 			d = path;
649 			while ((d = strchr(d, '/'))) {
650 				*d = 0;
651 				if (stat(path, &sb) && mkdir(path, 0755)) {
652 					res = 1;
653 					goto out;
654 				}
655 				*d++ = '/';
656 			}
657 			/* Try it again. */
658 			fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
659 			if (fd == -1) {
660 				res = 1;
661 				break;
662 			}
663 		}
664 		close(fd);
665 	}
666 out:
667 	if (chdir("../.."))
668 		return 1;
669 
670 	return res;
671 }
672 
673 int conf_write_autoconf(void)
674 {
675 	struct symbol *sym;
676 	const char *str;
677 	char *name;
678 	FILE *out, *out_h;
679 	time_t now;
680 	int i, l;
681 
682 	sym_clear_all_valid();
683 
684 	file_write_dep("include/config/auto.conf.cmd");
685 
686 	if (conf_split_config())
687 		return 1;
688 
689 	out = fopen(".tmpconfig", "w");
690 	if (!out)
691 		return 1;
692 
693 	out_h = fopen(".tmpconfig.h", "w");
694 	if (!out_h) {
695 		fclose(out);
696 		return 1;
697 	}
698 
699 	sym = sym_lookup("KERNELVERSION", 0);
700 	sym_calc_value(sym);
701 	time(&now);
702 	fprintf(out, "#\n"
703 		     "# Automatically generated make config: don't edit\n"
704 		     "# Linux kernel version: %s\n"
705 		     "# %s"
706 		     "#\n",
707 		     sym_get_string_value(sym), ctime(&now));
708 	fprintf(out_h, "/*\n"
709 		       " * Automatically generated C config: don't edit\n"
710 		       " * Linux kernel version: %s\n"
711 		       " * %s"
712 		       " */\n"
713 		       "#define AUTOCONF_INCLUDED\n",
714 		       sym_get_string_value(sym), ctime(&now));
715 
716 	for_all_symbols(i, sym) {
717 		sym_calc_value(sym);
718 		if (!(sym->flags & SYMBOL_WRITE) || !sym->name)
719 			continue;
720 		switch (sym->type) {
721 		case S_BOOLEAN:
722 		case S_TRISTATE:
723 			switch (sym_get_tristate_value(sym)) {
724 			case no:
725 				break;
726 			case mod:
727 				fprintf(out, "CONFIG_%s=m\n", sym->name);
728 				fprintf(out_h, "#define CONFIG_%s_MODULE 1\n", sym->name);
729 				break;
730 			case yes:
731 				fprintf(out, "CONFIG_%s=y\n", sym->name);
732 				fprintf(out_h, "#define CONFIG_%s 1\n", sym->name);
733 				break;
734 			}
735 			break;
736 		case S_STRING:
737 			str = sym_get_string_value(sym);
738 			fprintf(out, "CONFIG_%s=\"", sym->name);
739 			fprintf(out_h, "#define CONFIG_%s \"", sym->name);
740 			while (1) {
741 				l = strcspn(str, "\"\\");
742 				if (l) {
743 					fwrite(str, l, 1, out);
744 					fwrite(str, l, 1, out_h);
745 					str += l;
746 				}
747 				if (!*str)
748 					break;
749 				fprintf(out, "\\%c", *str);
750 				fprintf(out_h, "\\%c", *str);
751 				str++;
752 			}
753 			fputs("\"\n", out);
754 			fputs("\"\n", out_h);
755 			break;
756 		case S_HEX:
757 			str = sym_get_string_value(sym);
758 			if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) {
759 				fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
760 				fprintf(out_h, "#define CONFIG_%s 0x%s\n", sym->name, str);
761 				break;
762 			}
763 		case S_INT:
764 			str = sym_get_string_value(sym);
765 			fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
766 			fprintf(out_h, "#define CONFIG_%s %s\n", sym->name, str);
767 			break;
768 		default:
769 			break;
770 		}
771 	}
772 	fclose(out);
773 	fclose(out_h);
774 
775 	name = getenv("KCONFIG_AUTOHEADER");
776 	if (!name)
777 		name = "include/linux/autoconf.h";
778 	if (rename(".tmpconfig.h", name))
779 		return 1;
780 	name = getenv("KCONFIG_AUTOCONFIG");
781 	if (!name)
782 		name = "include/config/auto.conf";
783 	/*
784 	 * This must be the last step, kbuild has a dependency on auto.conf
785 	 * and this marks the successful completion of the previous steps.
786 	 */
787 	if (rename(".tmpconfig", name))
788 		return 1;
789 
790 	return 0;
791 }
792 
793 static int sym_change_count;
794 static void (*conf_changed_callback)(void);
795 
796 void sym_set_change_count(int count)
797 {
798 	int _sym_change_count = sym_change_count;
799 	sym_change_count = count;
800 	if (conf_changed_callback &&
801 	    (bool)_sym_change_count != (bool)count)
802 		conf_changed_callback();
803 }
804 
805 void sym_add_change_count(int count)
806 {
807 	sym_set_change_count(count + sym_change_count);
808 }
809 
810 bool conf_get_changed(void)
811 {
812 	return sym_change_count;
813 }
814 
815 void conf_set_changed_callback(void (*fn)(void))
816 {
817 	conf_changed_callback = fn;
818 }
819