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