kconfig/confdata.c
author "Benoît Thébaudeau" <benoit.thebaudeau@advansee.com>
Mon Apr 16 15:25:36 2012 +0200 (2012-04-16)
changeset 2941 13e40098fffc
parent 2448 a103abae1560
permissions -rw-r--r--
cc/gcc: update Linaro GCC revisions to 2012.04

Update Linaro GCC with the latest available revisions.

The 4.7 revision is also released, but the infrastructure is not yet ready for
it in CT-NG.

Signed-off-by: "Benoît Thébaudeau" <benoit.thebaudeau@advansee.com>
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@2448
     8
#include <errno.h>
yann@1
     9
#include <fcntl.h>
yann@1
    10
#include <stdio.h>
yann@1
    11
#include <stdlib.h>
yann@1
    12
#include <string.h>
yann@1
    13
#include <time.h>
yann@1
    14
#include <unistd.h>
yann@1
    15
yann@1
    16
#define LKC_DIRECT_LINK
yann@1
    17
#include "lkc.h"
yann@1
    18
yann@1
    19
static void conf_warning(const char *fmt, ...)
yann@1
    20
	__attribute__ ((format (printf, 1, 2)));
yann@1
    21
yann@2448
    22
static void conf_message(const char *fmt, ...)
yann@2448
    23
	__attribute__ ((format (printf, 1, 2)));
yann@2448
    24
yann@1
    25
static const char *conf_filename;
yann@1
    26
static int conf_lineno, conf_warnings, conf_unsaved;
yann@1
    27
yann@1
    28
const char conf_defname[] = "arch/$ARCH/defconfig";
yann@1
    29
yann@1
    30
static void conf_warning(const char *fmt, ...)
yann@1
    31
{
yann@1
    32
	va_list ap;
yann@1
    33
	va_start(ap, fmt);
yann@1
    34
	fprintf(stderr, "%s:%d:warning: ", conf_filename, conf_lineno);
yann@1
    35
	vfprintf(stderr, fmt, ap);
yann@1
    36
	fprintf(stderr, "\n");
yann@1
    37
	va_end(ap);
yann@1
    38
	conf_warnings++;
yann@1
    39
}
yann@1
    40
yann@2448
    41
static void conf_default_message_callback(const char *fmt, va_list ap)
yann@2448
    42
{
yann@2448
    43
	printf("#\n# ");
yann@2448
    44
	vprintf(fmt, ap);
yann@2448
    45
	printf("\n#\n");
yann@2448
    46
}
yann@2448
    47
yann@2448
    48
static void (*conf_message_callback) (const char *fmt, va_list ap) =
yann@2448
    49
	conf_default_message_callback;
yann@2448
    50
void conf_set_message_callback(void (*fn) (const char *fmt, va_list ap))
yann@2448
    51
{
yann@2448
    52
	conf_message_callback = fn;
yann@2448
    53
}
yann@2448
    54
yann@2448
    55
static void conf_message(const char *fmt, ...)
yann@2448
    56
{
yann@2448
    57
	va_list ap;
yann@2448
    58
yann@2448
    59
	va_start(ap, fmt);
yann@2448
    60
	if (conf_message_callback)
yann@2448
    61
		conf_message_callback(fmt, ap);
yann@2448
    62
}
yann@2448
    63
yann@1
    64
const char *conf_get_configname(void)
yann@1
    65
{
yann@1
    66
	char *name = getenv("KCONFIG_CONFIG");
yann@1
    67
yann@1
    68
	return name ? name : ".config";
yann@1
    69
}
yann@1
    70
yann@2448
    71
const char *conf_get_autoconfig_name(void)
yann@2448
    72
{
yann@2448
    73
	char *name = getenv("KCONFIG_AUTOCONFIG");
yann@2448
    74
yann@2448
    75
	return name ? name : "include/config/auto.conf";
yann@2448
    76
}
yann@2448
    77
yann@1
    78
static char *conf_expand_value(const char *in)
yann@1
    79
{
yann@1
    80
	struct symbol *sym;
yann@1
    81
	const char *src;
yann@1
    82
	static char res_value[SYMBOL_MAXLENGTH];
yann@1
    83
	char *dst, name[SYMBOL_MAXLENGTH];
yann@1
    84
yann@1
    85
	res_value[0] = 0;
yann@1
    86
	dst = name;
yann@1
    87
	while ((src = strchr(in, '$'))) {
yann@1
    88
		strncat(res_value, in, src - in);
yann@1
    89
		src++;
yann@1
    90
		dst = name;
yann@1
    91
		while (isalnum(*src) || *src == '_')
yann@1
    92
			*dst++ = *src++;
yann@1
    93
		*dst = 0;
yann@1
    94
		sym = sym_lookup(name, 0);
yann@1
    95
		sym_calc_value(sym);
yann@1
    96
		strcat(res_value, sym_get_string_value(sym));
yann@1
    97
		in = src;
yann@1
    98
	}
yann@1
    99
	strcat(res_value, in);
yann@1
   100
yann@1
   101
	return res_value;
yann@1
   102
}
yann@1
   103
yann@1
   104
char *conf_get_default_confname(void)
yann@1
   105
{
yann@1
   106
	struct stat buf;
yann@1
   107
	static char fullname[PATH_MAX+1];
yann@1
   108
	char *env, *name;
yann@1
   109
yann@1
   110
	name = conf_expand_value(conf_defname);
yann@1
   111
	env = getenv(SRCTREE);
yann@1
   112
	if (env) {
yann@1
   113
		sprintf(fullname, "%s/%s", env, name);
yann@1
   114
		if (!stat(fullname, &buf))
yann@1
   115
			return fullname;
yann@1
   116
	}
yann@1
   117
	return name;
yann@1
   118
}
yann@1
   119
yann@943
   120
static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
yann@943
   121
{
yann@943
   122
	char *p2;
yann@943
   123
yann@943
   124
	switch (sym->type) {
yann@943
   125
	case S_TRISTATE:
yann@943
   126
		if (p[0] == 'm') {
yann@943
   127
			sym->def[def].tri = mod;
yann@943
   128
			sym->flags |= def_flags;
yann@943
   129
			break;
yann@943
   130
		}
yann@943
   131
	case S_BOOLEAN:
yann@943
   132
		if (p[0] == 'y') {
yann@943
   133
			sym->def[def].tri = yes;
yann@943
   134
			sym->flags |= def_flags;
yann@943
   135
			break;
yann@943
   136
		}
yann@943
   137
		if (p[0] == 'n') {
yann@943
   138
			sym->def[def].tri = no;
yann@943
   139
			sym->flags |= def_flags;
yann@943
   140
			break;
yann@943
   141
		}
yann@943
   142
		conf_warning("symbol value '%s' invalid for %s", p, sym->name);
yann@943
   143
		break;
yann@943
   144
	case S_OTHER:
yann@943
   145
		if (*p != '"') {
yann@943
   146
			for (p2 = p; *p2 && !isspace(*p2); p2++)
yann@943
   147
				;
yann@943
   148
			sym->type = S_STRING;
yann@943
   149
			goto done;
yann@943
   150
		}
yann@943
   151
	case S_STRING:
yann@943
   152
		if (*p++ != '"')
yann@943
   153
			break;
yann@943
   154
		for (p2 = p; (p2 = strpbrk(p2, "\"\\")); p2++) {
yann@943
   155
			if (*p2 == '"') {
yann@943
   156
				*p2 = 0;
yann@943
   157
				break;
yann@943
   158
			}
yann@943
   159
			memmove(p2, p2 + 1, strlen(p2));
yann@943
   160
		}
yann@943
   161
		if (!p2) {
yann@943
   162
			conf_warning("invalid string found");
yann@943
   163
			return 1;
yann@943
   164
		}
yann@943
   165
	case S_INT:
yann@943
   166
	case S_HEX:
yann@943
   167
	done:
yann@943
   168
		if (sym_string_valid(sym, p)) {
yann@943
   169
			sym->def[def].val = strdup(p);
yann@943
   170
			sym->flags |= def_flags;
yann@943
   171
		} else {
yann@943
   172
			conf_warning("symbol value '%s' invalid for %s", p, sym->name);
yann@943
   173
			return 1;
yann@943
   174
		}
yann@943
   175
		break;
yann@943
   176
	default:
yann@943
   177
		;
yann@943
   178
	}
yann@943
   179
	return 0;
yann@943
   180
}
yann@943
   181
yann@1
   182
int conf_read_simple(const char *name, int def)
yann@1
   183
{
yann@1
   184
	FILE *in = NULL;
yann@1
   185
	char line[1024];
yann@1
   186
	char *p, *p2;
yann@1
   187
	struct symbol *sym;
yann@1
   188
	int i, def_flags;
yann@1
   189
yann@1
   190
	if (name) {
yann@1
   191
		in = zconf_fopen(name);
yann@1
   192
	} else {
yann@1
   193
		struct property *prop;
yann@1
   194
yann@1
   195
		name = conf_get_configname();
yann@1
   196
		in = zconf_fopen(name);
yann@1
   197
		if (in)
yann@1
   198
			goto load;
yann@39
   199
		sym_add_change_count(1);
yann@2448
   200
		if (!sym_defconfig_list) {
yann@2448
   201
			if (modules_sym)
yann@2448
   202
				sym_calc_value(modules_sym);
yann@1
   203
			return 1;
yann@2448
   204
		}
yann@1
   205
yann@1
   206
		for_all_defaults(sym_defconfig_list, prop) {
yann@1
   207
			if (expr_calc_value(prop->visible.expr) == no ||
yann@1
   208
			    prop->expr->type != E_SYMBOL)
yann@1
   209
				continue;
yann@1
   210
			name = conf_expand_value(prop->expr->left.sym->name);
yann@1
   211
			in = zconf_fopen(name);
yann@1
   212
			if (in) {
yann@2448
   213
				conf_message(_("using defaults found in %s"),
yann@2448
   214
					 name);
yann@1
   215
				goto load;
yann@1
   216
			}
yann@1
   217
		}
yann@1
   218
	}
yann@1
   219
	if (!in)
yann@1
   220
		return 1;
yann@1
   221
yann@1
   222
load:
yann@1
   223
	conf_filename = name;
yann@1
   224
	conf_lineno = 0;
yann@1
   225
	conf_warnings = 0;
yann@1
   226
	conf_unsaved = 0;
yann@1
   227
yann@1
   228
	def_flags = SYMBOL_DEF << def;
yann@1
   229
	for_all_symbols(i, sym) {
yann@1
   230
		sym->flags |= SYMBOL_CHANGED;
yann@1
   231
		sym->flags &= ~(def_flags|SYMBOL_VALID);
yann@1
   232
		if (sym_is_choice(sym))
yann@1
   233
			sym->flags |= def_flags;
yann@1
   234
		switch (sym->type) {
yann@1
   235
		case S_INT:
yann@1
   236
		case S_HEX:
yann@1
   237
		case S_STRING:
yann@1
   238
			if (sym->def[def].val)
yann@1
   239
				free(sym->def[def].val);
yann@1
   240
		default:
yann@1
   241
			sym->def[def].val = NULL;
yann@1
   242
			sym->def[def].tri = no;
yann@1
   243
		}
yann@1
   244
	}
yann@1
   245
yann@1
   246
	while (fgets(line, sizeof(line), in)) {
yann@1
   247
		conf_lineno++;
yann@1
   248
		sym = NULL;
yann@2448
   249
		if (line[0] == '#') {
yann@2448
   250
			if (memcmp(line + 2, CONFIG_, strlen(CONFIG_)))
yann@1
   251
				continue;
yann@2448
   252
			p = strchr(line + 2 + strlen(CONFIG_), ' ');
yann@1
   253
			if (!p)
yann@1
   254
				continue;
yann@1
   255
			*p++ = 0;
yann@1
   256
			if (strncmp(p, "is not set", 10))
yann@1
   257
				continue;
yann@1
   258
			if (def == S_DEF_USER) {
yann@2448
   259
				sym = sym_find(line + 2 + strlen(CONFIG_));
yann@1
   260
				if (!sym) {
yann@943
   261
					sym_add_change_count(1);
yann@2448
   262
					goto setsym;
yann@1
   263
				}
yann@1
   264
			} else {
yann@2448
   265
				sym = sym_lookup(line + 2 + strlen(CONFIG_), 0);
yann@1
   266
				if (sym->type == S_UNKNOWN)
yann@1
   267
					sym->type = S_BOOLEAN;
yann@1
   268
			}
yann@1
   269
			if (sym->flags & def_flags) {
yann@943
   270
				conf_warning("override: reassigning to symbol %s", sym->name);
yann@1
   271
			}
yann@1
   272
			switch (sym->type) {
yann@1
   273
			case S_BOOLEAN:
yann@1
   274
			case S_TRISTATE:
yann@1
   275
				sym->def[def].tri = no;
yann@1
   276
				sym->flags |= def_flags;
yann@1
   277
				break;
yann@1
   278
			default:
yann@1
   279
				;
yann@1
   280
			}
yann@2448
   281
		} else if (memcmp(line, CONFIG_, strlen(CONFIG_)) == 0) {
yann@2448
   282
			p = strchr(line + strlen(CONFIG_), '=');
yann@1
   283
			if (!p)
yann@1
   284
				continue;
yann@1
   285
			*p++ = 0;
yann@1
   286
			p2 = strchr(p, '\n');
yann@1
   287
			if (p2) {
yann@1
   288
				*p2-- = 0;
yann@1
   289
				if (*p2 == '\r')
yann@1
   290
					*p2 = 0;
yann@1
   291
			}
yann@1
   292
			if (def == S_DEF_USER) {
yann@2448
   293
				sym = sym_find(line + strlen(CONFIG_));
yann@1
   294
				if (!sym) {
yann@943
   295
					sym_add_change_count(1);
yann@2448
   296
					goto setsym;
yann@1
   297
				}
yann@1
   298
			} else {
yann@2448
   299
				sym = sym_lookup(line + strlen(CONFIG_), 0);
yann@1
   300
				if (sym->type == S_UNKNOWN)
yann@1
   301
					sym->type = S_OTHER;
yann@1
   302
			}
yann@1
   303
			if (sym->flags & def_flags) {
yann@943
   304
				conf_warning("override: reassigning to symbol %s", sym->name);
yann@1
   305
			}
yann@943
   306
			if (conf_set_sym_val(sym, def, def_flags, p))
yann@943
   307
				continue;
yann@2448
   308
		} else {
yann@2448
   309
			if (line[0] != '\r' && line[0] != '\n')
yann@2448
   310
				conf_warning("unexpected data");
yann@1
   311
			continue;
yann@1
   312
		}
yann@2448
   313
setsym:
yann@1
   314
		if (sym && sym_is_choice_value(sym)) {
yann@1
   315
			struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
yann@1
   316
			switch (sym->def[def].tri) {
yann@1
   317
			case no:
yann@1
   318
				break;
yann@1
   319
			case mod:
yann@1
   320
				if (cs->def[def].tri == yes) {
yann@1
   321
					conf_warning("%s creates inconsistent choice state", sym->name);
yann@1
   322
					cs->flags &= ~def_flags;
yann@1
   323
				}
yann@1
   324
				break;
yann@1
   325
			case yes:
yann@943
   326
				if (cs->def[def].tri != no)
yann@943
   327
					conf_warning("override: %s changes choice state", sym->name);
yann@943
   328
				cs->def[def].val = sym;
yann@1
   329
				break;
yann@1
   330
			}
yann@943
   331
			cs->def[def].tri = EXPR_OR(cs->def[def].tri, sym->def[def].tri);
yann@1
   332
		}
yann@1
   333
	}
yann@1
   334
	fclose(in);
yann@1
   335
yann@1
   336
	if (modules_sym)
yann@1
   337
		sym_calc_value(modules_sym);
yann@1
   338
	return 0;
yann@1
   339
}
yann@1
   340
yann@1
   341
int conf_read(const char *name)
yann@1
   342
{
yann@943
   343
	struct symbol *sym, *choice_sym;
yann@1
   344
	struct property *prop;
yann@1
   345
	struct expr *e;
yann@1
   346
	int i, flags;
yann@1
   347
yann@39
   348
	sym_set_change_count(0);
yann@1
   349
yann@1
   350
	if (conf_read_simple(name, S_DEF_USER))
yann@1
   351
		return 1;
yann@1
   352
yann@1
   353
	for_all_symbols(i, sym) {
yann@1
   354
		sym_calc_value(sym);
yann@1
   355
		if (sym_is_choice(sym) || (sym->flags & SYMBOL_AUTO))
yann@1
   356
			goto sym_ok;
yann@1
   357
		if (sym_has_value(sym) && (sym->flags & SYMBOL_WRITE)) {
yann@1
   358
			/* check that calculated value agrees with saved value */
yann@1
   359
			switch (sym->type) {
yann@1
   360
			case S_BOOLEAN:
yann@1
   361
			case S_TRISTATE:
yann@1
   362
				if (sym->def[S_DEF_USER].tri != sym_get_tristate_value(sym))
yann@1
   363
					break;
yann@1
   364
				if (!sym_is_choice(sym))
yann@1
   365
					goto sym_ok;
yann@1
   366
			default:
yann@1
   367
				if (!strcmp(sym->curr.val, sym->def[S_DEF_USER].val))
yann@1
   368
					goto sym_ok;
yann@1
   369
				break;
yann@1
   370
			}
yann@1
   371
		} else if (!sym_has_value(sym) && !(sym->flags & SYMBOL_WRITE))
yann@1
   372
			/* no previous value and not saved */
yann@1
   373
			goto sym_ok;
yann@1
   374
		conf_unsaved++;
yann@1
   375
		/* maybe print value in verbose mode... */
yann@1
   376
	sym_ok:
yann@943
   377
		if (!sym_is_choice(sym))
yann@943
   378
			continue;
yann@943
   379
		/* The choice symbol only has a set value (and thus is not new)
yann@943
   380
		 * if all its visible childs have values.
yann@943
   381
		 */
yann@943
   382
		prop = sym_get_choice_prop(sym);
yann@943
   383
		flags = sym->flags;
yann@943
   384
		expr_list_for_each_sym(prop->expr, e, choice_sym)
yann@943
   385
			if (choice_sym->visible != no)
yann@943
   386
				flags &= choice_sym->flags;
yann@943
   387
		sym->flags &= flags | ~SYMBOL_DEF_USER;
yann@943
   388
	}
yann@943
   389
yann@943
   390
	for_all_symbols(i, sym) {
yann@1
   391
		if (sym_has_value(sym) && !sym_is_choice_value(sym)) {
yann@943
   392
			/* Reset values of generates values, so they'll appear
yann@943
   393
			 * as new, if they should become visible, but that
yann@943
   394
			 * doesn't quite work if the Kconfig and the saved
yann@943
   395
			 * configuration disagree.
yann@943
   396
			 */
yann@943
   397
			if (sym->visible == no && !conf_unsaved)
yann@1
   398
				sym->flags &= ~SYMBOL_DEF_USER;
yann@1
   399
			switch (sym->type) {
yann@1
   400
			case S_STRING:
yann@1
   401
			case S_INT:
yann@1
   402
			case S_HEX:
yann@943
   403
				/* Reset a string value if it's out of range */
yann@943
   404
				if (sym_string_within_range(sym, sym->def[S_DEF_USER].val))
yann@943
   405
					break;
yann@943
   406
				sym->flags &= ~(SYMBOL_VALID|SYMBOL_DEF_USER);
yann@943
   407
				conf_unsaved++;
yann@943
   408
				break;
yann@1
   409
			default:
yann@1
   410
				break;
yann@1
   411
			}
yann@1
   412
		}
yann@1
   413
	}
yann@1
   414
yann@39
   415
	sym_add_change_count(conf_warnings || conf_unsaved);
yann@1
   416
yann@1
   417
	return 0;
yann@1
   418
}
yann@1
   419
yann@2448
   420
/* Write a S_STRING */
yann@2448
   421
static void conf_write_string(bool headerfile, const char *name,
yann@2448
   422
                              const char *str, FILE *out)
yann@2448
   423
{
yann@2448
   424
	int l;
yann@2448
   425
	if (headerfile)
yann@2448
   426
		fprintf(out, "#define %s%s \"", CONFIG_, name);
yann@2448
   427
	else
yann@2448
   428
		fprintf(out, "%s%s=\"", CONFIG_, name);
yann@2448
   429
yann@2448
   430
	while (1) {
yann@2448
   431
		l = strcspn(str, "\"\\");
yann@2448
   432
		if (l) {
yann@2448
   433
			xfwrite(str, l, 1, out);
yann@2448
   434
			str += l;
yann@2448
   435
		}
yann@2448
   436
		if (!*str)
yann@2448
   437
			break;
yann@2448
   438
		fprintf(out, "\\%c", *str++);
yann@2448
   439
	}
yann@2448
   440
	fputs("\"\n", out);
yann@2448
   441
}
yann@2448
   442
yann@2448
   443
static void conf_write_symbol(struct symbol *sym, FILE *out, bool write_no)
yann@2448
   444
{
yann@2448
   445
	const char *str;
yann@2448
   446
yann@2448
   447
	switch (sym->type) {
yann@2448
   448
	case S_BOOLEAN:
yann@2448
   449
	case S_TRISTATE:
yann@2448
   450
		switch (sym_get_tristate_value(sym)) {
yann@2448
   451
		case no:
yann@2448
   452
			if (write_no)
yann@2448
   453
				fprintf(out, "# %s%s is not set\n",
yann@2448
   454
				    CONFIG_, sym->name);
yann@2448
   455
			break;
yann@2448
   456
		case mod:
yann@2448
   457
			fprintf(out, "%s%s=m\n", CONFIG_, sym->name);
yann@2448
   458
			break;
yann@2448
   459
		case yes:
yann@2448
   460
			fprintf(out, "%s%s=y\n", CONFIG_, sym->name);
yann@2448
   461
			break;
yann@2448
   462
		}
yann@2448
   463
		break;
yann@2448
   464
	case S_STRING:
yann@2448
   465
		conf_write_string(false, sym->name, sym_get_string_value(sym), out);
yann@2448
   466
		break;
yann@2448
   467
	case S_HEX:
yann@2448
   468
	case S_INT:
yann@2448
   469
		str = sym_get_string_value(sym);
yann@2448
   470
		fprintf(out, "%s%s=%s\n", CONFIG_, sym->name, str);
yann@2448
   471
		break;
yann@2448
   472
	case S_OTHER:
yann@2448
   473
	case S_UNKNOWN:
yann@2448
   474
		break;
yann@2448
   475
	}
yann@2448
   476
}
yann@2448
   477
yann@2448
   478
/*
yann@2448
   479
 * Write out a minimal config.
yann@2448
   480
 * All values that has default values are skipped as this is redundant.
yann@2448
   481
 */
yann@2448
   482
int conf_write_defconfig(const char *filename)
yann@2448
   483
{
yann@2448
   484
	struct symbol *sym;
yann@2448
   485
	struct menu *menu;
yann@2448
   486
	FILE *out;
yann@2448
   487
yann@2448
   488
	out = fopen(filename, "w");
yann@2448
   489
	if (!out)
yann@2448
   490
		return 1;
yann@2448
   491
yann@2448
   492
	sym_clear_all_valid();
yann@2448
   493
yann@2448
   494
	/* Traverse all menus to find all relevant symbols */
yann@2448
   495
	menu = rootmenu.list;
yann@2448
   496
yann@2448
   497
	while (menu != NULL)
yann@2448
   498
	{
yann@2448
   499
		sym = menu->sym;
yann@2448
   500
		if (sym == NULL) {
yann@2448
   501
			if (!menu_is_visible(menu))
yann@2448
   502
				goto next_menu;
yann@2448
   503
		} else if (!sym_is_choice(sym)) {
yann@2448
   504
			sym_calc_value(sym);
yann@2448
   505
			if (!(sym->flags & SYMBOL_WRITE))
yann@2448
   506
				goto next_menu;
yann@2448
   507
			sym->flags &= ~SYMBOL_WRITE;
yann@2448
   508
			/* If we cannot change the symbol - skip */
yann@2448
   509
			if (!sym_is_changable(sym))
yann@2448
   510
				goto next_menu;
yann@2448
   511
			/* If symbol equals to default value - skip */
yann@2448
   512
			if (strcmp(sym_get_string_value(sym), sym_get_string_default(sym)) == 0)
yann@2448
   513
				goto next_menu;
yann@2448
   514
yann@2448
   515
			/*
yann@2448
   516
			 * If symbol is a choice value and equals to the
yann@2448
   517
			 * default for a choice - skip.
yann@2448
   518
			 * But only if value is bool and equal to "y" and
yann@2448
   519
			 * choice is not "optional".
yann@2448
   520
			 * (If choice is "optional" then all values can be "n")
yann@2448
   521
			 */
yann@2448
   522
			if (sym_is_choice_value(sym)) {
yann@2448
   523
				struct symbol *cs;
yann@2448
   524
				struct symbol *ds;
yann@2448
   525
yann@2448
   526
				cs = prop_get_symbol(sym_get_choice_prop(sym));
yann@2448
   527
				ds = sym_choice_default(cs);
yann@2448
   528
				if (!sym_is_optional(cs) && sym == ds) {
yann@2448
   529
					if ((sym->type == S_BOOLEAN) &&
yann@2448
   530
					    sym_get_tristate_value(sym) == yes)
yann@2448
   531
						goto next_menu;
yann@2448
   532
				}
yann@2448
   533
			}
yann@2448
   534
			conf_write_symbol(sym, out, true);
yann@2448
   535
		}
yann@2448
   536
next_menu:
yann@2448
   537
		if (menu->list != NULL) {
yann@2448
   538
			menu = menu->list;
yann@2448
   539
		}
yann@2448
   540
		else if (menu->next != NULL) {
yann@2448
   541
			menu = menu->next;
yann@2448
   542
		} else {
yann@2448
   543
			while ((menu = menu->parent)) {
yann@2448
   544
				if (menu->next != NULL) {
yann@2448
   545
					menu = menu->next;
yann@2448
   546
					break;
yann@2448
   547
				}
yann@2448
   548
			}
yann@2448
   549
		}
yann@2448
   550
	}
yann@2448
   551
	fclose(out);
yann@2448
   552
	return 0;
yann@2448
   553
}
yann@2448
   554
yann@1
   555
int conf_write(const char *name)
yann@1
   556
{
yann@1
   557
	FILE *out;
yann@1
   558
	struct symbol *sym;
yann@1
   559
	struct menu *menu;
yann@1
   560
	const char *basename;
yann@1
   561
	const char *str;
yann@2448
   562
	char dirname[PATH_MAX+1], tmpname[PATH_MAX+1], newname[PATH_MAX+1];
yann@1
   563
	time_t now;
yann@1
   564
	int use_timestamp = 1;
yann@1
   565
	char *env;
yann@1
   566
yann@1
   567
	dirname[0] = 0;
yann@1
   568
	if (name && name[0]) {
yann@1
   569
		struct stat st;
yann@1
   570
		char *slash;
yann@1
   571
yann@1
   572
		if (!stat(name, &st) && S_ISDIR(st.st_mode)) {
yann@1
   573
			strcpy(dirname, name);
yann@1
   574
			strcat(dirname, "/");
yann@1
   575
			basename = conf_get_configname();
yann@1
   576
		} else if ((slash = strrchr(name, '/'))) {
yann@1
   577
			int size = slash - name + 1;
yann@1
   578
			memcpy(dirname, name, size);
yann@1
   579
			dirname[size] = 0;
yann@1
   580
			if (slash[1])
yann@1
   581
				basename = slash + 1;
yann@1
   582
			else
yann@1
   583
				basename = conf_get_configname();
yann@1
   584
		} else
yann@1
   585
			basename = name;
yann@1
   586
	} else
yann@1
   587
		basename = conf_get_configname();
yann@1
   588
yann@1
   589
	sprintf(newname, "%s%s", dirname, basename);
yann@1
   590
	env = getenv("KCONFIG_OVERWRITECONFIG");
yann@1
   591
	if (!env || !*env) {
yann@1
   592
		sprintf(tmpname, "%s.tmpconfig.%d", dirname, (int)getpid());
yann@1
   593
		out = fopen(tmpname, "w");
yann@1
   594
	} else {
yann@1
   595
		*tmpname = 0;
yann@1
   596
		out = fopen(newname, "w");
yann@1
   597
	}
yann@1
   598
	if (!out)
yann@1
   599
		return 1;
yann@1
   600
yann@1
   601
	time(&now);
yann@1
   602
	env = getenv("KCONFIG_NOTIMESTAMP");
yann@1
   603
	if (env && *env)
yann@1
   604
		use_timestamp = 0;
yann@1
   605
yann@1
   606
	fprintf(out, _("#\n"
yann@1
   607
		       "# Automatically generated make config: don't edit\n"
yann@2448
   608
		       "# %s\n"
yann@1
   609
		       "%s%s"
yann@1
   610
		       "#\n"),
yann@2448
   611
		     rootmenu.prompt->text,
yann@1
   612
		     use_timestamp ? "# " : "",
yann@1
   613
		     use_timestamp ? ctime(&now) : "");
yann@1
   614
yann@39
   615
	if (!conf_get_changed())
yann@1
   616
		sym_clear_all_valid();
yann@1
   617
yann@1
   618
	menu = rootmenu.list;
yann@1
   619
	while (menu) {
yann@1
   620
		sym = menu->sym;
yann@1
   621
		if (!sym) {
yann@1
   622
			if (!menu_is_visible(menu))
yann@1
   623
				goto next;
yann@1
   624
			str = menu_get_prompt(menu);
yann@1
   625
			fprintf(out, "\n"
yann@1
   626
				     "#\n"
yann@1
   627
				     "# %s\n"
yann@1
   628
				     "#\n", str);
yann@1
   629
		} else if (!(sym->flags & SYMBOL_CHOICE)) {
yann@1
   630
			sym_calc_value(sym);
yann@39
   631
			if (!(sym->flags & SYMBOL_WRITE))
yann@1
   632
				goto next;
yann@39
   633
			sym->flags &= ~SYMBOL_WRITE;
yann@2448
   634
			/* Write config symbol to file */
yann@2448
   635
			conf_write_symbol(sym, out, true);
yann@1
   636
		}
yann@1
   637
yann@2448
   638
next:
yann@39
   639
		if (menu->list) {
yann@39
   640
			menu = menu->list;
yann@39
   641
			continue;
yann@39
   642
		}
yann@39
   643
		if (menu->next)
yann@39
   644
			menu = menu->next;
yann@39
   645
		else while ((menu = menu->parent)) {
yann@39
   646
			if (menu->next) {
yann@39
   647
				menu = menu->next;
yann@39
   648
				break;
yann@1
   649
			}
yann@39
   650
		}
yann@1
   651
	}
yann@1
   652
	fclose(out);
yann@1
   653
yann@1
   654
	if (*tmpname) {
yann@1
   655
		strcat(dirname, basename);
yann@1
   656
		strcat(dirname, ".old");
yann@1
   657
		rename(newname, dirname);
yann@1
   658
		if (rename(tmpname, newname))
yann@1
   659
			return 1;
yann@1
   660
	}
yann@1
   661
yann@2452
   662
	conf_message(_("configuration saved"));
yann@2448
   663
yann@39
   664
	sym_set_change_count(0);
yann@1
   665
yann@1
   666
	return 0;
yann@1
   667
}
yann@1
   668
yann@2448
   669
static int conf_split_config(void)
yann@1
   670
{
yann@2448
   671
	const char *name;
yann@2448
   672
	char path[PATH_MAX+1];
yann@1
   673
	char *s, *d, c;
yann@1
   674
	struct symbol *sym;
yann@1
   675
	struct stat sb;
yann@1
   676
	int res, i, fd;
yann@1
   677
yann@2448
   678
	name = conf_get_autoconfig_name();
yann@1
   679
	conf_read_simple(name, S_DEF_AUTO);
yann@1
   680
yann@1
   681
	if (chdir("include/config"))
yann@1
   682
		return 1;
yann@1
   683
yann@1
   684
	res = 0;
yann@1
   685
	for_all_symbols(i, sym) {
yann@1
   686
		sym_calc_value(sym);
yann@1
   687
		if ((sym->flags & SYMBOL_AUTO) || !sym->name)
yann@1
   688
			continue;
yann@1
   689
		if (sym->flags & SYMBOL_WRITE) {
yann@1
   690
			if (sym->flags & SYMBOL_DEF_AUTO) {
yann@1
   691
				/*
yann@1
   692
				 * symbol has old and new value,
yann@1
   693
				 * so compare them...
yann@1
   694
				 */
yann@1
   695
				switch (sym->type) {
yann@1
   696
				case S_BOOLEAN:
yann@1
   697
				case S_TRISTATE:
yann@1
   698
					if (sym_get_tristate_value(sym) ==
yann@1
   699
					    sym->def[S_DEF_AUTO].tri)
yann@1
   700
						continue;
yann@1
   701
					break;
yann@1
   702
				case S_STRING:
yann@1
   703
				case S_HEX:
yann@1
   704
				case S_INT:
yann@1
   705
					if (!strcmp(sym_get_string_value(sym),
yann@1
   706
						    sym->def[S_DEF_AUTO].val))
yann@1
   707
						continue;
yann@1
   708
					break;
yann@1
   709
				default:
yann@1
   710
					break;
yann@1
   711
				}
yann@1
   712
			} else {
yann@1
   713
				/*
yann@1
   714
				 * If there is no old value, only 'no' (unset)
yann@1
   715
				 * is allowed as new value.
yann@1
   716
				 */
yann@1
   717
				switch (sym->type) {
yann@1
   718
				case S_BOOLEAN:
yann@1
   719
				case S_TRISTATE:
yann@1
   720
					if (sym_get_tristate_value(sym) == no)
yann@1
   721
						continue;
yann@1
   722
					break;
yann@1
   723
				default:
yann@1
   724
					break;
yann@1
   725
				}
yann@1
   726
			}
yann@1
   727
		} else if (!(sym->flags & SYMBOL_DEF_AUTO))
yann@1
   728
			/* There is neither an old nor a new value. */
yann@1
   729
			continue;
yann@1
   730
		/* else
yann@1
   731
		 *	There is an old value, but no new value ('no' (unset)
yann@1
   732
		 *	isn't saved in auto.conf, so the old value is always
yann@1
   733
		 *	different from 'no').
yann@1
   734
		 */
yann@1
   735
yann@1
   736
		/* Replace all '_' and append ".h" */
yann@1
   737
		s = sym->name;
yann@1
   738
		d = path;
yann@1
   739
		while ((c = *s++)) {
yann@1
   740
			c = tolower(c);
yann@1
   741
			*d++ = (c == '_') ? '/' : c;
yann@1
   742
		}
yann@1
   743
		strcpy(d, ".h");
yann@1
   744
yann@1
   745
		/* Assume directory path already exists. */
yann@1
   746
		fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
yann@1
   747
		if (fd == -1) {
yann@1
   748
			if (errno != ENOENT) {
yann@1
   749
				res = 1;
yann@1
   750
				break;
yann@1
   751
			}
yann@1
   752
			/*
yann@1
   753
			 * Create directory components,
yann@1
   754
			 * unless they exist already.
yann@1
   755
			 */
yann@1
   756
			d = path;
yann@1
   757
			while ((d = strchr(d, '/'))) {
yann@1
   758
				*d = 0;
yann@1
   759
				if (stat(path, &sb) && mkdir(path, 0755)) {
yann@1
   760
					res = 1;
yann@1
   761
					goto out;
yann@1
   762
				}
yann@1
   763
				*d++ = '/';
yann@1
   764
			}
yann@1
   765
			/* Try it again. */
yann@1
   766
			fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
yann@1
   767
			if (fd == -1) {
yann@1
   768
				res = 1;
yann@1
   769
				break;
yann@1
   770
			}
yann@1
   771
		}
yann@1
   772
		close(fd);
yann@1
   773
	}
yann@1
   774
out:
yann@1
   775
	if (chdir("../.."))
yann@1
   776
		return 1;
yann@1
   777
yann@1
   778
	return res;
yann@1
   779
}
yann@1
   780
yann@1
   781
int conf_write_autoconf(void)
yann@1
   782
{
yann@1
   783
	struct symbol *sym;
yann@1
   784
	const char *str;
yann@2448
   785
	const char *name;
yann@2448
   786
	FILE *out, *tristate, *out_h;
yann@2448
   787
	int i;
yann@1
   788
yann@1
   789
	sym_clear_all_valid();
yann@1
   790
yann@1
   791
	file_write_dep("include/config/auto.conf.cmd");
yann@1
   792
yann@1
   793
	if (conf_split_config())
yann@1
   794
		return 1;
yann@1
   795
yann@1
   796
	out = fopen(".tmpconfig", "w");
yann@1
   797
	if (!out)
yann@1
   798
		return 1;
yann@1
   799
yann@2448
   800
	tristate = fopen(".tmpconfig_tristate", "w");
yann@2448
   801
	if (!tristate) {
yann@1
   802
		fclose(out);
yann@1
   803
		return 1;
yann@1
   804
	}
yann@1
   805
yann@2448
   806
	out_h = fopen(".tmpconfig.h", "w");
yann@2448
   807
	if (!out_h) {
yann@2448
   808
		fclose(out);
yann@2448
   809
		fclose(tristate);
yann@2448
   810
		return 1;
yann@2448
   811
	}
yann@2448
   812
yann@1
   813
	fprintf(out, "#\n"
yann@1
   814
		     "# Automatically generated make config: don't edit\n"
yann@2448
   815
		     "# %s\n"
yann@1
   816
		     "#\n",
yann@2448
   817
		     rootmenu.prompt->text);
yann@2448
   818
	fprintf(tristate, "#\n"
yann@2448
   819
			  "# Automatically generated - do not edit\n"
yann@2448
   820
			  "\n");
yann@1
   821
	fprintf(out_h, "/*\n"
yann@1
   822
		       " * Automatically generated C config: don't edit\n"
yann@2448
   823
		       " * %s\n"
yann@2448
   824
		       " */\n",
yann@2448
   825
		       rootmenu.prompt->text);
yann@1
   826
yann@1
   827
	for_all_symbols(i, sym) {
yann@1
   828
		sym_calc_value(sym);
yann@1
   829
		if (!(sym->flags & SYMBOL_WRITE) || !sym->name)
yann@1
   830
			continue;
yann@2448
   831
yann@2448
   832
		/* write symbol to config file */
yann@2448
   833
		conf_write_symbol(sym, out, false);
yann@2448
   834
yann@2448
   835
		/* update autoconf and tristate files */
yann@1
   836
		switch (sym->type) {
yann@1
   837
		case S_BOOLEAN:
yann@1
   838
		case S_TRISTATE:
yann@1
   839
			switch (sym_get_tristate_value(sym)) {
yann@1
   840
			case no:
yann@1
   841
				break;
yann@1
   842
			case mod:
yann@2448
   843
				fprintf(tristate, "%s%s=M\n",
yann@2448
   844
				    CONFIG_, sym->name);
yann@2448
   845
				fprintf(out_h, "#define %s%s_MODULE 1\n",
yann@2448
   846
				    CONFIG_, sym->name);
yann@1
   847
				break;
yann@1
   848
			case yes:
yann@2448
   849
				if (sym->type == S_TRISTATE)
yann@2448
   850
					fprintf(tristate,"%s%s=Y\n",
yann@2448
   851
					    CONFIG_, sym->name);
yann@2448
   852
				fprintf(out_h, "#define %s%s 1\n",
yann@2448
   853
				    CONFIG_, sym->name);
yann@1
   854
				break;
yann@1
   855
			}
yann@1
   856
			break;
yann@1
   857
		case S_STRING:
yann@2448
   858
			conf_write_string(true, sym->name, sym_get_string_value(sym), out_h);
yann@1
   859
			break;
yann@1
   860
		case S_HEX:
yann@1
   861
			str = sym_get_string_value(sym);
yann@1
   862
			if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) {
yann@2448
   863
				fprintf(out_h, "#define %s%s 0x%s\n",
yann@2448
   864
				    CONFIG_, sym->name, str);
yann@1
   865
				break;
yann@1
   866
			}
yann@1
   867
		case S_INT:
yann@1
   868
			str = sym_get_string_value(sym);
yann@2448
   869
			fprintf(out_h, "#define %s%s %s\n",
yann@2448
   870
			    CONFIG_, sym->name, str);
yann@1
   871
			break;
yann@1
   872
		default:
yann@1
   873
			break;
yann@1
   874
		}
yann@1
   875
	}
yann@1
   876
	fclose(out);
yann@2448
   877
	fclose(tristate);
yann@1
   878
	fclose(out_h);
yann@1
   879
yann@1
   880
	name = getenv("KCONFIG_AUTOHEADER");
yann@1
   881
	if (!name)
yann@2448
   882
		name = "include/generated/autoconf.h";
yann@1
   883
	if (rename(".tmpconfig.h", name))
yann@1
   884
		return 1;
yann@2448
   885
	name = getenv("KCONFIG_TRISTATE");
yann@1
   886
	if (!name)
yann@2448
   887
		name = "include/config/tristate.conf";
yann@2448
   888
	if (rename(".tmpconfig_tristate", name))
yann@2448
   889
		return 1;
yann@2448
   890
	name = conf_get_autoconfig_name();
yann@1
   891
	/*
yann@1
   892
	 * This must be the last step, kbuild has a dependency on auto.conf
yann@1
   893
	 * and this marks the successful completion of the previous steps.
yann@1
   894
	 */
yann@1
   895
	if (rename(".tmpconfig", name))
yann@1
   896
		return 1;
yann@1
   897
yann@1
   898
	return 0;
yann@1
   899
}
yann@39
   900
yann@39
   901
static int sym_change_count;
yann@39
   902
static void (*conf_changed_callback)(void);
yann@39
   903
yann@39
   904
void sym_set_change_count(int count)
yann@39
   905
{
yann@39
   906
	int _sym_change_count = sym_change_count;
yann@39
   907
	sym_change_count = count;
yann@39
   908
	if (conf_changed_callback &&
yann@39
   909
	    (bool)_sym_change_count != (bool)count)
yann@39
   910
		conf_changed_callback();
yann@39
   911
}
yann@39
   912
yann@39
   913
void sym_add_change_count(int count)
yann@39
   914
{
yann@39
   915
	sym_set_change_count(count + sym_change_count);
yann@39
   916
}
yann@39
   917
yann@39
   918
bool conf_get_changed(void)
yann@39
   919
{
yann@39
   920
	return sym_change_count;
yann@39
   921
}
yann@39
   922
yann@39
   923
void conf_set_changed_callback(void (*fn)(void))
yann@39
   924
{
yann@39
   925
	conf_changed_callback = fn;
yann@39
   926
}
yann@943
   927
yann@2448
   928
static void randomize_choice_values(struct symbol *csym)
yann@2448
   929
{
yann@2448
   930
	struct property *prop;
yann@2448
   931
	struct symbol *sym;
yann@2448
   932
	struct expr *e;
yann@2448
   933
	int cnt, def;
yann@2448
   934
yann@2448
   935
	/*
yann@2448
   936
	 * If choice is mod then we may have more items selected
yann@2448
   937
	 * and if no then no-one.
yann@2448
   938
	 * In both cases stop.
yann@2448
   939
	 */
yann@2448
   940
	if (csym->curr.tri != yes)
yann@2448
   941
		return;
yann@2448
   942
yann@2448
   943
	prop = sym_get_choice_prop(csym);
yann@2448
   944
yann@2448
   945
	/* count entries in choice block */
yann@2448
   946
	cnt = 0;
yann@2448
   947
	expr_list_for_each_sym(prop->expr, e, sym)
yann@2448
   948
		cnt++;
yann@2448
   949
yann@2448
   950
	/*
yann@2448
   951
	 * find a random value and set it to yes,
yann@2448
   952
	 * set the rest to no so we have only one set
yann@2448
   953
	 */
yann@2448
   954
	def = (rand() % cnt);
yann@2448
   955
yann@2448
   956
	cnt = 0;
yann@2448
   957
	expr_list_for_each_sym(prop->expr, e, sym) {
yann@2448
   958
		if (def == cnt++) {
yann@2448
   959
			sym->def[S_DEF_USER].tri = yes;
yann@2448
   960
			csym->def[S_DEF_USER].val = sym;
yann@2448
   961
		}
yann@2448
   962
		else {
yann@2448
   963
			sym->def[S_DEF_USER].tri = no;
yann@2448
   964
		}
yann@2448
   965
	}
yann@2448
   966
	csym->flags |= SYMBOL_DEF_USER;
yann@2448
   967
	/* clear VALID to get value calculated */
yann@2448
   968
	csym->flags &= ~(SYMBOL_VALID);
yann@2448
   969
}
yann@2448
   970
yann@2448
   971
static void set_all_choice_values(struct symbol *csym)
yann@2448
   972
{
yann@2448
   973
	struct property *prop;
yann@2448
   974
	struct symbol *sym;
yann@2448
   975
	struct expr *e;
yann@2448
   976
yann@2448
   977
	prop = sym_get_choice_prop(csym);
yann@2448
   978
yann@2448
   979
	/*
yann@2448
   980
	 * Set all non-assinged choice values to no
yann@2448
   981
	 */
yann@2448
   982
	expr_list_for_each_sym(prop->expr, e, sym) {
yann@2448
   983
		if (!sym_has_value(sym))
yann@2448
   984
			sym->def[S_DEF_USER].tri = no;
yann@2448
   985
	}
yann@2448
   986
	csym->flags |= SYMBOL_DEF_USER;
yann@2448
   987
	/* clear VALID to get value calculated */
yann@2448
   988
	csym->flags &= ~(SYMBOL_VALID);
yann@2448
   989
}
yann@943
   990
yann@943
   991
void conf_set_all_new_symbols(enum conf_def_mode mode)
yann@943
   992
{
yann@943
   993
	struct symbol *sym, *csym;
yann@2448
   994
	int i, cnt;
yann@943
   995
yann@943
   996
	for_all_symbols(i, sym) {
yann@943
   997
		if (sym_has_value(sym))
yann@943
   998
			continue;
yann@943
   999
		switch (sym_get_type(sym)) {
yann@943
  1000
		case S_BOOLEAN:
yann@943
  1001
		case S_TRISTATE:
yann@943
  1002
			switch (mode) {
yann@943
  1003
			case def_yes:
yann@943
  1004
				sym->def[S_DEF_USER].tri = yes;
yann@943
  1005
				break;
yann@943
  1006
			case def_mod:
yann@943
  1007
				sym->def[S_DEF_USER].tri = mod;
yann@943
  1008
				break;
yann@943
  1009
			case def_no:
yann@943
  1010
				sym->def[S_DEF_USER].tri = no;
yann@943
  1011
				break;
yann@943
  1012
			case def_random:
yann@2448
  1013
				cnt = sym_get_type(sym) == S_TRISTATE ? 3 : 2;
yann@2448
  1014
				sym->def[S_DEF_USER].tri = (tristate)(rand() % cnt);
yann@943
  1015
				break;
yann@943
  1016
			default:
yann@943
  1017
				continue;
yann@943
  1018
			}
yann@2448
  1019
			if (!(sym_is_choice(sym) && mode == def_random))
yann@943
  1020
				sym->flags |= SYMBOL_DEF_USER;
yann@943
  1021
			break;
yann@943
  1022
		default:
yann@943
  1023
			break;
yann@943
  1024
		}
yann@943
  1025
yann@943
  1026
	}
yann@943
  1027
yann@1228
  1028
	sym_clear_all_valid();
yann@943
  1029
yann@2448
  1030
	/*
yann@2448
  1031
	 * We have different type of choice blocks.
yann@2448
  1032
	 * If curr.tri equals to mod then we can select several
yann@2448
  1033
	 * choice symbols in one block.
yann@2448
  1034
	 * In this case we do nothing.
yann@2448
  1035
	 * If curr.tri equals yes then only one symbol can be
yann@2448
  1036
	 * selected in a choice block and we set it to yes,
yann@2448
  1037
	 * and the rest to no.
yann@2448
  1038
	 */
yann@943
  1039
	for_all_symbols(i, csym) {
yann@943
  1040
		if (sym_has_value(csym) || !sym_is_choice(csym))
yann@943
  1041
			continue;
yann@943
  1042
yann@943
  1043
		sym_calc_value(csym);
yann@2448
  1044
		if (mode == def_random)
yann@2448
  1045
			randomize_choice_values(csym);
yann@2448
  1046
		else
yann@2448
  1047
			set_all_choice_values(csym);
yann@943
  1048
	}
yann@943
  1049
}