kconfig/confdata.c
author "Yann E. MORIN" <yann.morin.1998@anciens.enib.fr>
Mon May 25 19:48:42 2009 +0000 (2009-05-25)
branchgcc-4.4
changeset 1387 a52504ffac55
parent 943 1cca90ce0481
child 2448 a103abae1560
permissions -rw-r--r--
/devel/gcc-4.4:
- TODO: remove completed items

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