kconfig/confdata.c
author Arnaud Lacombe <lacombar@gmail.com>
Tue Aug 03 06:17:51 2010 +0200 (2010-08-03)
changeset 2064 f5ebe8c429dc
parent 943 1cca90ce0481
child 2448 a103abae1560
permissions -rw-r--r--
libc/uClibc: add uClibc 0.9.30.3

This version has been released a couple of month ago, but it never reached
crosstool-ng tree. This may be linked to the fact that the current 0.9.30.2,
once patched, has nothing much different from 0.9.30.3, released.

I'm not including any patch with this upgrade, on purpose.

Signed-off-by: Arnaud Lacombe <lacombar@gmail.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@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
}