xref: /linux/scripts/kconfig/confdata.c (revision 40d3057ac036f2501c1930728a6179be4fca577b)
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 					break;
227 			} else {
228 				sym = sym_lookup(line + 9, 0);
229 				if (sym->type == S_UNKNOWN)
230 					sym->type = S_BOOLEAN;
231 			}
232 			if (sym->flags & def_flags) {
233 				conf_warning("override: reassigning to symbol %s", sym->name);
234 			}
235 			switch (sym->type) {
236 			case S_BOOLEAN:
237 			case S_TRISTATE:
238 				sym->def[def].tri = no;
239 				sym->flags |= def_flags;
240 				break;
241 			default:
242 				;
243 			}
244 			break;
245 		case 'C':
246 			if (memcmp(line, "CONFIG_", 7)) {
247 				conf_warning("unexpected data");
248 				continue;
249 			}
250 			p = strchr(line + 7, '=');
251 			if (!p)
252 				continue;
253 			*p++ = 0;
254 			p2 = strchr(p, '\n');
255 			if (p2) {
256 				*p2-- = 0;
257 				if (*p2 == '\r')
258 					*p2 = 0;
259 			}
260 			if (def == S_DEF_USER) {
261 				sym = sym_find(line + 7);
262 				if (!sym)
263 					break;
264 			} else {
265 				sym = sym_lookup(line + 7, 0);
266 				if (sym->type == S_UNKNOWN)
267 					sym->type = S_OTHER;
268 			}
269 			if (sym->flags & def_flags) {
270 				conf_warning("override: reassigning to symbol %s", sym->name);
271 			}
272 			if (conf_set_sym_val(sym, def, def_flags, p))
273 				continue;
274 			break;
275 		case '\r':
276 		case '\n':
277 			break;
278 		default:
279 			conf_warning("unexpected data");
280 			continue;
281 		}
282 		if (sym && sym_is_choice_value(sym)) {
283 			struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
284 			switch (sym->def[def].tri) {
285 			case no:
286 				break;
287 			case mod:
288 				if (cs->def[def].tri == yes) {
289 					conf_warning("%s creates inconsistent choice state", sym->name);
290 					cs->flags &= ~def_flags;
291 				}
292 				break;
293 			case yes:
294 				if (cs->def[def].tri != no)
295 					conf_warning("override: %s changes choice state", sym->name);
296 				cs->def[def].val = sym;
297 				break;
298 			}
299 			cs->def[def].tri = EXPR_OR(cs->def[def].tri, sym->def[def].tri);
300 		}
301 	}
302 	fclose(in);
303 
304 	if (modules_sym)
305 		sym_calc_value(modules_sym);
306 	return 0;
307 }
308 
309 int conf_read(const char *name)
310 {
311 	struct symbol *sym, *choice_sym;
312 	struct property *prop;
313 	struct expr *e;
314 	int i, flags;
315 
316 	sym_set_change_count(0);
317 
318 	if (conf_read_simple(name, S_DEF_USER))
319 		return 1;
320 
321 	for_all_symbols(i, sym) {
322 		sym_calc_value(sym);
323 		if (sym_is_choice(sym) || (sym->flags & SYMBOL_AUTO))
324 			goto sym_ok;
325 		if (sym_has_value(sym) && (sym->flags & SYMBOL_WRITE)) {
326 			/* check that calculated value agrees with saved value */
327 			switch (sym->type) {
328 			case S_BOOLEAN:
329 			case S_TRISTATE:
330 				if (sym->def[S_DEF_USER].tri != sym_get_tristate_value(sym))
331 					break;
332 				if (!sym_is_choice(sym))
333 					goto sym_ok;
334 			default:
335 				if (!strcmp(sym->curr.val, sym->def[S_DEF_USER].val))
336 					goto sym_ok;
337 				break;
338 			}
339 		} else if (!sym_has_value(sym) && !(sym->flags & SYMBOL_WRITE))
340 			/* no previous value and not saved */
341 			goto sym_ok;
342 		conf_unsaved++;
343 		/* maybe print value in verbose mode... */
344 	sym_ok:
345 		if (!sym_is_choice(sym))
346 			continue;
347 		/* The choice symbol only has a set value (and thus is not new)
348 		 * if all its visible childs have values.
349 		 */
350 		prop = sym_get_choice_prop(sym);
351 		flags = sym->flags;
352 		expr_list_for_each_sym(prop->expr, e, choice_sym)
353 			if (choice_sym->visible != no)
354 				flags &= choice_sym->flags;
355 		sym->flags &= flags | ~SYMBOL_DEF_USER;
356 	}
357 
358 	for_all_symbols(i, sym) {
359 		if (sym_has_value(sym) && !sym_is_choice_value(sym)) {
360 			/* Reset values of generates values, so they'll appear
361 			 * as new, if they should become visible, but that
362 			 * doesn't quite work if the Kconfig and the saved
363 			 * configuration disagree.
364 			 */
365 			if (sym->visible == no && !conf_unsaved)
366 				sym->flags &= ~SYMBOL_DEF_USER;
367 			switch (sym->type) {
368 			case S_STRING:
369 			case S_INT:
370 			case S_HEX:
371 				/* Reset a string value if it's out of range */
372 				if (sym_string_within_range(sym, sym->def[S_DEF_USER].val))
373 					break;
374 				sym->flags &= ~(SYMBOL_VALID|SYMBOL_DEF_USER);
375 				conf_unsaved++;
376 				break;
377 			default:
378 				break;
379 			}
380 		}
381 	}
382 
383 	sym_add_change_count(conf_warnings || conf_unsaved);
384 
385 	return 0;
386 }
387 
388 int conf_write(const char *name)
389 {
390 	FILE *out;
391 	struct symbol *sym;
392 	struct menu *menu;
393 	const char *basename;
394 	char dirname[128], tmpname[128], newname[128];
395 	int type, l;
396 	const char *str;
397 	time_t now;
398 	int use_timestamp = 1;
399 	char *env;
400 
401 	dirname[0] = 0;
402 	if (name && name[0]) {
403 		struct stat st;
404 		char *slash;
405 
406 		if (!stat(name, &st) && S_ISDIR(st.st_mode)) {
407 			strcpy(dirname, name);
408 			strcat(dirname, "/");
409 			basename = conf_get_configname();
410 		} else if ((slash = strrchr(name, '/'))) {
411 			int size = slash - name + 1;
412 			memcpy(dirname, name, size);
413 			dirname[size] = 0;
414 			if (slash[1])
415 				basename = slash + 1;
416 			else
417 				basename = conf_get_configname();
418 		} else
419 			basename = name;
420 	} else
421 		basename = conf_get_configname();
422 
423 	sprintf(newname, "%s%s", dirname, basename);
424 	env = getenv("KCONFIG_OVERWRITECONFIG");
425 	if (!env || !*env) {
426 		sprintf(tmpname, "%s.tmpconfig.%d", dirname, (int)getpid());
427 		out = fopen(tmpname, "w");
428 	} else {
429 		*tmpname = 0;
430 		out = fopen(newname, "w");
431 	}
432 	if (!out)
433 		return 1;
434 
435 	sym = sym_lookup("KERNELVERSION", 0);
436 	sym_calc_value(sym);
437 	time(&now);
438 	env = getenv("KCONFIG_NOTIMESTAMP");
439 	if (env && *env)
440 		use_timestamp = 0;
441 
442 	fprintf(out, _("#\n"
443 		       "# Automatically generated make config: don't edit\n"
444 		       "# Linux kernel version: %s\n"
445 		       "%s%s"
446 		       "#\n"),
447 		     sym_get_string_value(sym),
448 		     use_timestamp ? "# " : "",
449 		     use_timestamp ? ctime(&now) : "");
450 
451 	if (!conf_get_changed())
452 		sym_clear_all_valid();
453 
454 	menu = rootmenu.list;
455 	while (menu) {
456 		sym = menu->sym;
457 		if (!sym) {
458 			if (!menu_is_visible(menu))
459 				goto next;
460 			str = menu_get_prompt(menu);
461 			fprintf(out, "\n"
462 				     "#\n"
463 				     "# %s\n"
464 				     "#\n", str);
465 		} else if (!(sym->flags & SYMBOL_CHOICE)) {
466 			sym_calc_value(sym);
467 			if (!(sym->flags & SYMBOL_WRITE))
468 				goto next;
469 			sym->flags &= ~SYMBOL_WRITE;
470 			type = sym->type;
471 			if (type == S_TRISTATE) {
472 				sym_calc_value(modules_sym);
473 				if (modules_sym->curr.tri == no)
474 					type = S_BOOLEAN;
475 			}
476 			switch (type) {
477 			case S_BOOLEAN:
478 			case S_TRISTATE:
479 				switch (sym_get_tristate_value(sym)) {
480 				case no:
481 					fprintf(out, "# CONFIG_%s is not set\n", sym->name);
482 					break;
483 				case mod:
484 					fprintf(out, "CONFIG_%s=m\n", sym->name);
485 					break;
486 				case yes:
487 					fprintf(out, "CONFIG_%s=y\n", sym->name);
488 					break;
489 				}
490 				break;
491 			case S_STRING:
492 				str = sym_get_string_value(sym);
493 				fprintf(out, "CONFIG_%s=\"", sym->name);
494 				while (1) {
495 					l = strcspn(str, "\"\\");
496 					if (l) {
497 						fwrite(str, l, 1, out);
498 						str += l;
499 					}
500 					if (!*str)
501 						break;
502 					fprintf(out, "\\%c", *str++);
503 				}
504 				fputs("\"\n", out);
505 				break;
506 			case S_HEX:
507 				str = sym_get_string_value(sym);
508 				if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) {
509 					fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
510 					break;
511 				}
512 			case S_INT:
513 				str = sym_get_string_value(sym);
514 				fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
515 				break;
516 			}
517 		}
518 
519 	next:
520 		if (menu->list) {
521 			menu = menu->list;
522 			continue;
523 		}
524 		if (menu->next)
525 			menu = menu->next;
526 		else while ((menu = menu->parent)) {
527 			if (menu->next) {
528 				menu = menu->next;
529 				break;
530 			}
531 		}
532 	}
533 	fclose(out);
534 
535 	if (*tmpname) {
536 		strcat(dirname, basename);
537 		strcat(dirname, ".old");
538 		rename(newname, dirname);
539 		if (rename(tmpname, newname))
540 			return 1;
541 	}
542 
543 	printf(_("#\n"
544 		 "# configuration written to %s\n"
545 		 "#\n"), newname);
546 
547 	sym_set_change_count(0);
548 
549 	return 0;
550 }
551 
552 int conf_split_config(void)
553 {
554 	char *name, path[128];
555 	char *s, *d, c;
556 	struct symbol *sym;
557 	struct stat sb;
558 	int res, i, fd;
559 
560 	name = getenv("KCONFIG_AUTOCONFIG");
561 	if (!name)
562 		name = "include/config/auto.conf";
563 	conf_read_simple(name, S_DEF_AUTO);
564 
565 	if (chdir("include/config"))
566 		return 1;
567 
568 	res = 0;
569 	for_all_symbols(i, sym) {
570 		sym_calc_value(sym);
571 		if ((sym->flags & SYMBOL_AUTO) || !sym->name)
572 			continue;
573 		if (sym->flags & SYMBOL_WRITE) {
574 			if (sym->flags & SYMBOL_DEF_AUTO) {
575 				/*
576 				 * symbol has old and new value,
577 				 * so compare them...
578 				 */
579 				switch (sym->type) {
580 				case S_BOOLEAN:
581 				case S_TRISTATE:
582 					if (sym_get_tristate_value(sym) ==
583 					    sym->def[S_DEF_AUTO].tri)
584 						continue;
585 					break;
586 				case S_STRING:
587 				case S_HEX:
588 				case S_INT:
589 					if (!strcmp(sym_get_string_value(sym),
590 						    sym->def[S_DEF_AUTO].val))
591 						continue;
592 					break;
593 				default:
594 					break;
595 				}
596 			} else {
597 				/*
598 				 * If there is no old value, only 'no' (unset)
599 				 * is allowed as new value.
600 				 */
601 				switch (sym->type) {
602 				case S_BOOLEAN:
603 				case S_TRISTATE:
604 					if (sym_get_tristate_value(sym) == no)
605 						continue;
606 					break;
607 				default:
608 					break;
609 				}
610 			}
611 		} else if (!(sym->flags & SYMBOL_DEF_AUTO))
612 			/* There is neither an old nor a new value. */
613 			continue;
614 		/* else
615 		 *	There is an old value, but no new value ('no' (unset)
616 		 *	isn't saved in auto.conf, so the old value is always
617 		 *	different from 'no').
618 		 */
619 
620 		/* Replace all '_' and append ".h" */
621 		s = sym->name;
622 		d = path;
623 		while ((c = *s++)) {
624 			c = tolower(c);
625 			*d++ = (c == '_') ? '/' : c;
626 		}
627 		strcpy(d, ".h");
628 
629 		/* Assume directory path already exists. */
630 		fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
631 		if (fd == -1) {
632 			if (errno != ENOENT) {
633 				res = 1;
634 				break;
635 			}
636 			/*
637 			 * Create directory components,
638 			 * unless they exist already.
639 			 */
640 			d = path;
641 			while ((d = strchr(d, '/'))) {
642 				*d = 0;
643 				if (stat(path, &sb) && mkdir(path, 0755)) {
644 					res = 1;
645 					goto out;
646 				}
647 				*d++ = '/';
648 			}
649 			/* Try it again. */
650 			fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
651 			if (fd == -1) {
652 				res = 1;
653 				break;
654 			}
655 		}
656 		close(fd);
657 	}
658 out:
659 	if (chdir("../.."))
660 		return 1;
661 
662 	return res;
663 }
664 
665 int conf_write_autoconf(void)
666 {
667 	struct symbol *sym;
668 	const char *str;
669 	char *name;
670 	FILE *out, *out_h;
671 	time_t now;
672 	int i, l;
673 
674 	sym_clear_all_valid();
675 
676 	file_write_dep("include/config/auto.conf.cmd");
677 
678 	if (conf_split_config())
679 		return 1;
680 
681 	out = fopen(".tmpconfig", "w");
682 	if (!out)
683 		return 1;
684 
685 	out_h = fopen(".tmpconfig.h", "w");
686 	if (!out_h) {
687 		fclose(out);
688 		return 1;
689 	}
690 
691 	sym = sym_lookup("KERNELVERSION", 0);
692 	sym_calc_value(sym);
693 	time(&now);
694 	fprintf(out, "#\n"
695 		     "# Automatically generated make config: don't edit\n"
696 		     "# Linux kernel version: %s\n"
697 		     "# %s"
698 		     "#\n",
699 		     sym_get_string_value(sym), ctime(&now));
700 	fprintf(out_h, "/*\n"
701 		       " * Automatically generated C config: don't edit\n"
702 		       " * Linux kernel version: %s\n"
703 		       " * %s"
704 		       " */\n"
705 		       "#define AUTOCONF_INCLUDED\n",
706 		       sym_get_string_value(sym), ctime(&now));
707 
708 	for_all_symbols(i, sym) {
709 		sym_calc_value(sym);
710 		if (!(sym->flags & SYMBOL_WRITE) || !sym->name)
711 			continue;
712 		switch (sym->type) {
713 		case S_BOOLEAN:
714 		case S_TRISTATE:
715 			switch (sym_get_tristate_value(sym)) {
716 			case no:
717 				break;
718 			case mod:
719 				fprintf(out, "CONFIG_%s=m\n", sym->name);
720 				fprintf(out_h, "#define CONFIG_%s_MODULE 1\n", sym->name);
721 				break;
722 			case yes:
723 				fprintf(out, "CONFIG_%s=y\n", sym->name);
724 				fprintf(out_h, "#define CONFIG_%s 1\n", sym->name);
725 				break;
726 			}
727 			break;
728 		case S_STRING:
729 			str = sym_get_string_value(sym);
730 			fprintf(out, "CONFIG_%s=\"", sym->name);
731 			fprintf(out_h, "#define CONFIG_%s \"", sym->name);
732 			while (1) {
733 				l = strcspn(str, "\"\\");
734 				if (l) {
735 					fwrite(str, l, 1, out);
736 					fwrite(str, l, 1, out_h);
737 					str += l;
738 				}
739 				if (!*str)
740 					break;
741 				fprintf(out, "\\%c", *str);
742 				fprintf(out_h, "\\%c", *str);
743 				str++;
744 			}
745 			fputs("\"\n", out);
746 			fputs("\"\n", out_h);
747 			break;
748 		case S_HEX:
749 			str = sym_get_string_value(sym);
750 			if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) {
751 				fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
752 				fprintf(out_h, "#define CONFIG_%s 0x%s\n", sym->name, str);
753 				break;
754 			}
755 		case S_INT:
756 			str = sym_get_string_value(sym);
757 			fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
758 			fprintf(out_h, "#define CONFIG_%s %s\n", sym->name, str);
759 			break;
760 		default:
761 			break;
762 		}
763 	}
764 	fclose(out);
765 	fclose(out_h);
766 
767 	name = getenv("KCONFIG_AUTOHEADER");
768 	if (!name)
769 		name = "include/linux/autoconf.h";
770 	if (rename(".tmpconfig.h", name))
771 		return 1;
772 	name = getenv("KCONFIG_AUTOCONFIG");
773 	if (!name)
774 		name = "include/config/auto.conf";
775 	/*
776 	 * This must be the last step, kbuild has a dependency on auto.conf
777 	 * and this marks the successful completion of the previous steps.
778 	 */
779 	if (rename(".tmpconfig", name))
780 		return 1;
781 
782 	return 0;
783 }
784 
785 static int sym_change_count;
786 static void (*conf_changed_callback)(void);
787 
788 void sym_set_change_count(int count)
789 {
790 	int _sym_change_count = sym_change_count;
791 	sym_change_count = count;
792 	if (conf_changed_callback &&
793 	    (bool)_sym_change_count != (bool)count)
794 		conf_changed_callback();
795 }
796 
797 void sym_add_change_count(int count)
798 {
799 	sym_set_change_count(count + sym_change_count);
800 }
801 
802 bool conf_get_changed(void)
803 {
804 	return sym_change_count;
805 }
806 
807 void conf_set_changed_callback(void (*fn)(void))
808 {
809 	conf_changed_callback = fn;
810 }
811 
812 
813 void conf_set_all_new_symbols(enum conf_def_mode mode)
814 {
815 	struct symbol *sym, *csym;
816 	struct property *prop;
817 	struct expr *e;
818 	int i, cnt, def;
819 
820 	for_all_symbols(i, sym) {
821 		if (sym_has_value(sym))
822 			continue;
823 		switch (sym_get_type(sym)) {
824 		case S_BOOLEAN:
825 		case S_TRISTATE:
826 			switch (mode) {
827 			case def_yes:
828 				sym->def[S_DEF_USER].tri = yes;
829 				break;
830 			case def_mod:
831 				sym->def[S_DEF_USER].tri = mod;
832 				break;
833 			case def_no:
834 				sym->def[S_DEF_USER].tri = no;
835 				break;
836 			case def_random:
837 				sym->def[S_DEF_USER].tri = (tristate)(rand() % 3);
838 				break;
839 			default:
840 				continue;
841 			}
842 			if (!sym_is_choice(sym) || mode != def_random)
843 				sym->flags |= SYMBOL_DEF_USER;
844 			break;
845 		default:
846 			break;
847 		}
848 
849 	}
850 
851 	if (modules_sym)
852 		sym_calc_value(modules_sym);
853 
854 	if (mode != def_random)
855 		return;
856 
857 	for_all_symbols(i, csym) {
858 		if (sym_has_value(csym) || !sym_is_choice(csym))
859 			continue;
860 
861 		sym_calc_value(csym);
862 		prop = sym_get_choice_prop(csym);
863 		def = -1;
864 		while (1) {
865 			cnt = 0;
866 			expr_list_for_each_sym(prop->expr, e, sym) {
867 				if (sym->visible == no)
868 					continue;
869 				if (def == cnt++) {
870 					csym->def[S_DEF_USER].val = sym;
871 					break;
872 				}
873 			}
874 			if (def >= 0 || cnt < 2)
875 				break;
876 			def = (rand() % cnt) + 1;
877 		}
878 		csym->flags |= SYMBOL_DEF_USER;
879 	}
880 }
881