kconfig/confdata.c
author "Yann E. MORIN" <yann.morin.1998@anciens.enib.fr>
Sun Jul 13 10:32:38 2008 +0000 (2008-07-13)
changeset 645 8e58024f8e37
parent 39 af42eec9d383
child 943 1cca90ce0481
permissions -rw-r--r--
Ioannis E. VENETIS <venetis@mail.capsl.udel.edu> pointed out that GMP and MPFR were not used by gcc.
Turned out that none could use GMP and MPFR as the config option changed its name, but the change was not propagated to all users.

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