kconfig/confdata.c
author "Yann E. MORIN" <yann.morin.1998@anciens.enib.fr>
Tue Jul 22 13:29:08 2008 +0000 (2008-07-22)
changeset 710 021546adce69
parent 39 af42eec9d383
child 943 1cca90ce0481
permissions -rw-r--r--
Allow selecting 'latest' snapshot, as well as 'specific' date snapshot for glibc.
Update uClibc config to commonalise some help.

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