kconfig/confdata.c
author "Yann E. MORIN" <yann.morin.1998@anciens.enib.fr>
Tue Aug 23 21:11:26 2011 +0200 (2011-08-23)
changeset 2891 f176fee535a0
parent 2448 a103abae1560
permissions -rw-r--r--
cc/gcc: add 'cflags' paramater to the core backend

As the core backend is used to generate the bare-metal compiler,
we need to pass it the host CFLAGS.

Signed-off-by: "Yann E. MORIN" <yann.morin.1998@anciens.enib.fr>
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
}