blob: 5bd66f45118918f123c378b83a57fa448c93a6f8 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
3 * Released under the terms of the GNU GPL v2.0.
4 */
5
6#include <sys/stat.h>
7#include <ctype.h>
Roman Zippel2e3646e2006-06-08 22:12:42 -07008#include <fcntl.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -07009#include <stdio.h>
10#include <stdlib.h>
11#include <string.h>
12#include <time.h>
13#include <unistd.h>
14
15#define LKC_DIRECT_LINK
16#include "lkc.h"
17
Roman Zippelc1a0f5e2005-11-08 21:34:54 -080018static void conf_warning(const char *fmt, ...)
19 __attribute__ ((format (printf, 1, 2)));
20
21static const char *conf_filename;
22static int conf_lineno, conf_warnings, conf_unsaved;
23
Linus Torvalds1da177e2005-04-16 15:20:36 -070024const char conf_def_filename[] = ".config";
25
26const char conf_defname[] = "arch/$ARCH/defconfig";
27
Roman Zippelc1a0f5e2005-11-08 21:34:54 -080028static void conf_warning(const char *fmt, ...)
29{
30 va_list ap;
31 va_start(ap, fmt);
32 fprintf(stderr, "%s:%d:warning: ", conf_filename, conf_lineno);
33 vfprintf(stderr, fmt, ap);
34 fprintf(stderr, "\n");
35 va_end(ap);
36 conf_warnings++;
37}
38
J.A. Magallon48b9d032005-06-25 14:59:22 -070039static char *conf_expand_value(const char *in)
Linus Torvalds1da177e2005-04-16 15:20:36 -070040{
41 struct symbol *sym;
J.A. Magallon48b9d032005-06-25 14:59:22 -070042 const char *src;
Linus Torvalds1da177e2005-04-16 15:20:36 -070043 static char res_value[SYMBOL_MAXLENGTH];
44 char *dst, name[SYMBOL_MAXLENGTH];
45
46 res_value[0] = 0;
47 dst = name;
48 while ((src = strchr(in, '$'))) {
49 strncat(res_value, in, src - in);
50 src++;
51 dst = name;
52 while (isalnum(*src) || *src == '_')
53 *dst++ = *src++;
54 *dst = 0;
55 sym = sym_lookup(name, 0);
56 sym_calc_value(sym);
57 strcat(res_value, sym_get_string_value(sym));
58 in = src;
59 }
60 strcat(res_value, in);
61
62 return res_value;
63}
64
65char *conf_get_default_confname(void)
66{
67 struct stat buf;
68 static char fullname[PATH_MAX+1];
69 char *env, *name;
70
71 name = conf_expand_value(conf_defname);
72 env = getenv(SRCTREE);
73 if (env) {
74 sprintf(fullname, "%s/%s", env, name);
75 if (!stat(fullname, &buf))
76 return fullname;
77 }
78 return name;
79}
80
Roman Zippel669bfad2006-06-08 22:12:42 -070081int conf_read_simple(const char *name, int def)
Linus Torvalds1da177e2005-04-16 15:20:36 -070082{
83 FILE *in = NULL;
84 char line[1024];
85 char *p, *p2;
Linus Torvalds1da177e2005-04-16 15:20:36 -070086 struct symbol *sym;
Roman Zippel669bfad2006-06-08 22:12:42 -070087 int i, def_flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -070088
89 if (name) {
90 in = zconf_fopen(name);
91 } else {
Roman Zippelface4372006-06-08 22:12:45 -070092 struct property *prop;
93
94 name = conf_def_filename;
Roman Zippelddc97ca2006-06-08 22:12:38 -070095 in = zconf_fopen(name);
96 if (in)
97 goto load;
98 sym_change_count++;
Roman Zippelface4372006-06-08 22:12:45 -070099 if (!sym_defconfig_list)
100 return 1;
101
102 for_all_defaults(sym_defconfig_list, prop) {
103 if (expr_calc_value(prop->visible.expr) == no ||
104 prop->expr->type != E_SYMBOL)
105 continue;
106 name = conf_expand_value(prop->expr->left.sym->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700107 in = zconf_fopen(name);
108 if (in) {
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700109 printf(_("#\n"
Roman Zippelddc97ca2006-06-08 22:12:38 -0700110 "# using defaults found in %s\n"
111 "#\n"), name);
112 goto load;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700113 }
114 }
115 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700116 if (!in)
117 return 1;
118
Roman Zippelddc97ca2006-06-08 22:12:38 -0700119load:
Roman Zippelc1a0f5e2005-11-08 21:34:54 -0800120 conf_filename = name;
121 conf_lineno = 0;
122 conf_warnings = 0;
123 conf_unsaved = 0;
124
Roman Zippel669bfad2006-06-08 22:12:42 -0700125 def_flags = SYMBOL_DEF << def;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126 for_all_symbols(i, sym) {
Roman Zippel669bfad2006-06-08 22:12:42 -0700127 sym->flags |= SYMBOL_CHANGED;
128 sym->flags &= ~(def_flags|SYMBOL_VALID);
Roman Zippelc1a0f5e2005-11-08 21:34:54 -0800129 if (sym_is_choice(sym))
Roman Zippel669bfad2006-06-08 22:12:42 -0700130 sym->flags |= def_flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700131 switch (sym->type) {
132 case S_INT:
133 case S_HEX:
134 case S_STRING:
Roman Zippel669bfad2006-06-08 22:12:42 -0700135 if (sym->def[def].val)
136 free(sym->def[def].val);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137 default:
Roman Zippel669bfad2006-06-08 22:12:42 -0700138 sym->def[def].val = NULL;
139 sym->def[def].tri = no;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140 }
141 }
142
143 while (fgets(line, sizeof(line), in)) {
Roman Zippelc1a0f5e2005-11-08 21:34:54 -0800144 conf_lineno++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700145 sym = NULL;
146 switch (line[0]) {
147 case '#':
148 if (memcmp(line + 2, "CONFIG_", 7))
149 continue;
150 p = strchr(line + 9, ' ');
151 if (!p)
152 continue;
153 *p++ = 0;
154 if (strncmp(p, "is not set", 10))
155 continue;
Roman Zippel669bfad2006-06-08 22:12:42 -0700156 if (def == S_DEF_USER) {
157 sym = sym_find(line + 9);
158 if (!sym) {
159 conf_warning("trying to assign nonexistent symbol %s", line + 9);
160 break;
161 }
162 } else {
163 sym = sym_lookup(line + 9, 0);
164 if (sym->type == S_UNKNOWN)
165 sym->type = S_BOOLEAN;
166 }
167 if (sym->flags & def_flags) {
Roman Zippelc1a0f5e2005-11-08 21:34:54 -0800168 conf_warning("trying to reassign symbol %s", sym->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700169 break;
170 }
171 switch (sym->type) {
172 case S_BOOLEAN:
173 case S_TRISTATE:
Roman Zippel669bfad2006-06-08 22:12:42 -0700174 sym->def[def].tri = no;
175 sym->flags |= def_flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700176 break;
177 default:
178 ;
179 }
180 break;
181 case 'C':
Roman Zippelc1a0f5e2005-11-08 21:34:54 -0800182 if (memcmp(line, "CONFIG_", 7)) {
183 conf_warning("unexpected data");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700184 continue;
Roman Zippelc1a0f5e2005-11-08 21:34:54 -0800185 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700186 p = strchr(line + 7, '=');
187 if (!p)
188 continue;
189 *p++ = 0;
190 p2 = strchr(p, '\n');
191 if (p2)
192 *p2 = 0;
Roman Zippel669bfad2006-06-08 22:12:42 -0700193 if (def == S_DEF_USER) {
194 sym = sym_find(line + 7);
195 if (!sym) {
196 conf_warning("trying to assign nonexistent symbol %s", line + 7);
197 break;
198 }
199 } else {
200 sym = sym_lookup(line + 7, 0);
201 if (sym->type == S_UNKNOWN)
202 sym->type = S_OTHER;
203 }
204 if (sym->flags & def_flags) {
Roman Zippelc1a0f5e2005-11-08 21:34:54 -0800205 conf_warning("trying to reassign symbol %s", sym->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700206 break;
207 }
208 switch (sym->type) {
209 case S_TRISTATE:
210 if (p[0] == 'm') {
Roman Zippel669bfad2006-06-08 22:12:42 -0700211 sym->def[def].tri = mod;
212 sym->flags |= def_flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700213 break;
214 }
215 case S_BOOLEAN:
216 if (p[0] == 'y') {
Roman Zippel669bfad2006-06-08 22:12:42 -0700217 sym->def[def].tri = yes;
218 sym->flags |= def_flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700219 break;
220 }
221 if (p[0] == 'n') {
Roman Zippel669bfad2006-06-08 22:12:42 -0700222 sym->def[def].tri = no;
223 sym->flags |= def_flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700224 break;
225 }
Roman Zippelc1a0f5e2005-11-08 21:34:54 -0800226 conf_warning("symbol value '%s' invalid for %s", p, sym->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700227 break;
Roman Zippel669bfad2006-06-08 22:12:42 -0700228 case S_OTHER:
229 if (*p != '"') {
230 for (p2 = p; *p2 && !isspace(*p2); p2++)
231 ;
232 sym->type = S_STRING;
233 goto done;
234 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700235 case S_STRING:
236 if (*p++ != '"')
237 break;
238 for (p2 = p; (p2 = strpbrk(p2, "\"\\")); p2++) {
239 if (*p2 == '"') {
240 *p2 = 0;
241 break;
242 }
243 memmove(p2, p2 + 1, strlen(p2));
244 }
245 if (!p2) {
Roman Zippelc1a0f5e2005-11-08 21:34:54 -0800246 conf_warning("invalid string found");
247 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700248 }
249 case S_INT:
250 case S_HEX:
Roman Zippel669bfad2006-06-08 22:12:42 -0700251 done:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252 if (sym_string_valid(sym, p)) {
Roman Zippel669bfad2006-06-08 22:12:42 -0700253 sym->def[def].val = strdup(p);
254 sym->flags |= def_flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255 } else {
Roman Zippelc1a0f5e2005-11-08 21:34:54 -0800256 conf_warning("symbol value '%s' invalid for %s", p, sym->name);
257 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258 }
259 break;
260 default:
261 ;
262 }
263 break;
264 case '\n':
265 break;
266 default:
Roman Zippelc1a0f5e2005-11-08 21:34:54 -0800267 conf_warning("unexpected data");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268 continue;
269 }
270 if (sym && sym_is_choice_value(sym)) {
271 struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
Roman Zippel669bfad2006-06-08 22:12:42 -0700272 switch (sym->def[def].tri) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273 case no:
274 break;
275 case mod:
Roman Zippel669bfad2006-06-08 22:12:42 -0700276 if (cs->def[def].tri == yes) {
Roman Zippelc1a0f5e2005-11-08 21:34:54 -0800277 conf_warning("%s creates inconsistent choice state", sym->name);
Roman Zippel669bfad2006-06-08 22:12:42 -0700278 cs->flags &= ~def_flags;
Roman Zippelc1a0f5e2005-11-08 21:34:54 -0800279 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700280 break;
281 case yes:
Roman Zippel669bfad2006-06-08 22:12:42 -0700282 if (cs->def[def].tri != no) {
Roman Zippelc1a0f5e2005-11-08 21:34:54 -0800283 conf_warning("%s creates inconsistent choice state", sym->name);
Roman Zippel669bfad2006-06-08 22:12:42 -0700284 cs->flags &= ~def_flags;
Roman Zippelc1a0f5e2005-11-08 21:34:54 -0800285 } else
Roman Zippel669bfad2006-06-08 22:12:42 -0700286 cs->def[def].val = sym;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287 break;
288 }
Roman Zippel669bfad2006-06-08 22:12:42 -0700289 cs->def[def].tri = E_OR(cs->def[def].tri, sym->def[def].tri);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700290 }
291 }
292 fclose(in);
293
294 if (modules_sym)
295 sym_calc_value(modules_sym);
Roman Zippel90389162005-11-08 21:34:49 -0800296 return 0;
297}
298
299int conf_read(const char *name)
300{
301 struct symbol *sym;
302 struct property *prop;
303 struct expr *e;
Roman Zippel669bfad2006-06-08 22:12:42 -0700304 int i, flags;
Roman Zippel90389162005-11-08 21:34:49 -0800305
Roman Zippelddc97ca2006-06-08 22:12:38 -0700306 sym_change_count = 0;
307
Roman Zippel669bfad2006-06-08 22:12:42 -0700308 if (conf_read_simple(name, S_DEF_USER))
Roman Zippel90389162005-11-08 21:34:49 -0800309 return 1;
310
Linus Torvalds1da177e2005-04-16 15:20:36 -0700311 for_all_symbols(i, sym) {
312 sym_calc_value(sym);
Roman Zippelc1a0f5e2005-11-08 21:34:54 -0800313 if (sym_is_choice(sym) || (sym->flags & SYMBOL_AUTO))
314 goto sym_ok;
315 if (sym_has_value(sym) && (sym->flags & SYMBOL_WRITE)) {
316 /* check that calculated value agrees with saved value */
317 switch (sym->type) {
318 case S_BOOLEAN:
319 case S_TRISTATE:
Roman Zippel0c1822e2006-06-08 22:12:41 -0700320 if (sym->def[S_DEF_USER].tri != sym_get_tristate_value(sym))
Roman Zippelc1a0f5e2005-11-08 21:34:54 -0800321 break;
322 if (!sym_is_choice(sym))
323 goto sym_ok;
324 default:
Roman Zippel0c1822e2006-06-08 22:12:41 -0700325 if (!strcmp(sym->curr.val, sym->def[S_DEF_USER].val))
Roman Zippelc1a0f5e2005-11-08 21:34:54 -0800326 goto sym_ok;
327 break;
328 }
329 } else if (!sym_has_value(sym) && !(sym->flags & SYMBOL_WRITE))
330 /* no previous value and not saved */
331 goto sym_ok;
332 conf_unsaved++;
333 /* maybe print value in verbose mode... */
334 sym_ok:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700335 if (sym_has_value(sym) && !sym_is_choice_value(sym)) {
336 if (sym->visible == no)
Roman Zippel669bfad2006-06-08 22:12:42 -0700337 sym->flags &= ~SYMBOL_DEF_USER;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700338 switch (sym->type) {
339 case S_STRING:
340 case S_INT:
341 case S_HEX:
Roman Zippel669bfad2006-06-08 22:12:42 -0700342 if (!sym_string_within_range(sym, sym->def[S_DEF_USER].val))
343 sym->flags &= ~(SYMBOL_VALID|SYMBOL_DEF_USER);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700344 default:
345 break;
346 }
347 }
348 if (!sym_is_choice(sym))
349 continue;
350 prop = sym_get_choice_prop(sym);
Roman Zippel669bfad2006-06-08 22:12:42 -0700351 flags = sym->flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352 for (e = prop->expr; e; e = e->left.expr)
353 if (e->right.sym->visible != no)
Roman Zippel669bfad2006-06-08 22:12:42 -0700354 flags &= e->right.sym->flags;
355 sym->flags |= flags & SYMBOL_DEF_USER;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356 }
357
Roman Zippelddc97ca2006-06-08 22:12:38 -0700358 sym_change_count += conf_warnings || conf_unsaved;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359
360 return 0;
361}
362
363int conf_write(const char *name)
364{
Roman Zippelc955cca2006-06-08 22:12:39 -0700365 FILE *out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366 struct symbol *sym;
367 struct menu *menu;
368 const char *basename;
369 char dirname[128], tmpname[128], newname[128];
370 int type, l;
371 const char *str;
372 time_t now;
373 int use_timestamp = 1;
374 char *env;
375
376 dirname[0] = 0;
377 if (name && name[0]) {
378 struct stat st;
379 char *slash;
380
381 if (!stat(name, &st) && S_ISDIR(st.st_mode)) {
382 strcpy(dirname, name);
383 strcat(dirname, "/");
384 basename = conf_def_filename;
385 } else if ((slash = strrchr(name, '/'))) {
386 int size = slash - name + 1;
387 memcpy(dirname, name, size);
388 dirname[size] = 0;
389 if (slash[1])
390 basename = slash + 1;
391 else
392 basename = conf_def_filename;
393 } else
394 basename = name;
395 } else
396 basename = conf_def_filename;
397
398 sprintf(newname, "%s.tmpconfig.%d", dirname, (int)getpid());
399 out = fopen(newname, "w");
400 if (!out)
401 return 1;
Sam Ravnborg2244cbd2006-01-16 12:12:12 +0100402 sym = sym_lookup("KERNELVERSION", 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403 sym_calc_value(sym);
404 time(&now);
405 env = getenv("KCONFIG_NOTIMESTAMP");
406 if (env && *env)
407 use_timestamp = 0;
408
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700409 fprintf(out, _("#\n"
410 "# Automatically generated make config: don't edit\n"
411 "# Linux kernel version: %s\n"
412 "%s%s"
413 "#\n"),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414 sym_get_string_value(sym),
415 use_timestamp ? "# " : "",
416 use_timestamp ? ctime(&now) : "");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417
418 if (!sym_change_count)
419 sym_clear_all_valid();
420
421 menu = rootmenu.list;
422 while (menu) {
423 sym = menu->sym;
424 if (!sym) {
425 if (!menu_is_visible(menu))
426 goto next;
427 str = menu_get_prompt(menu);
428 fprintf(out, "\n"
429 "#\n"
430 "# %s\n"
431 "#\n", str);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432 } else if (!(sym->flags & SYMBOL_CHOICE)) {
433 sym_calc_value(sym);
434 if (!(sym->flags & SYMBOL_WRITE))
435 goto next;
436 sym->flags &= ~SYMBOL_WRITE;
437 type = sym->type;
438 if (type == S_TRISTATE) {
439 sym_calc_value(modules_sym);
440 if (modules_sym->curr.tri == no)
441 type = S_BOOLEAN;
442 }
443 switch (type) {
444 case S_BOOLEAN:
445 case S_TRISTATE:
446 switch (sym_get_tristate_value(sym)) {
447 case no:
448 fprintf(out, "# CONFIG_%s is not set\n", sym->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449 break;
450 case mod:
451 fprintf(out, "CONFIG_%s=m\n", sym->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452 break;
453 case yes:
454 fprintf(out, "CONFIG_%s=y\n", sym->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700455 break;
456 }
457 break;
458 case S_STRING:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700459 str = sym_get_string_value(sym);
460 fprintf(out, "CONFIG_%s=\"", sym->name);
Roman Zippelc955cca2006-06-08 22:12:39 -0700461 while (1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462 l = strcspn(str, "\"\\");
463 if (l) {
464 fwrite(str, l, 1, out);
Roman Zippelc955cca2006-06-08 22:12:39 -0700465 str += l;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466 }
Roman Zippelc955cca2006-06-08 22:12:39 -0700467 if (!*str)
468 break;
469 fprintf(out, "\\%c", *str++);
470 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700471 fputs("\"\n", out);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700472 break;
473 case S_HEX:
474 str = sym_get_string_value(sym);
475 if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) {
476 fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477 break;
478 }
479 case S_INT:
480 str = sym_get_string_value(sym);
481 fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482 break;
483 }
484 }
485
486 next:
487 if (menu->list) {
488 menu = menu->list;
489 continue;
490 }
491 if (menu->next)
492 menu = menu->next;
493 else while ((menu = menu->parent)) {
494 if (menu->next) {
495 menu = menu->next;
496 break;
497 }
498 }
499 }
500 fclose(out);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501 if (!name || basename != conf_def_filename) {
502 if (!name)
503 name = conf_def_filename;
504 sprintf(tmpname, "%s.old", name);
505 rename(name, tmpname);
506 }
507 sprintf(tmpname, "%s%s", dirname, basename);
508 if (rename(newname, tmpname))
509 return 1;
510
Roman Zippelddc97ca2006-06-08 22:12:38 -0700511 printf(_("#\n"
512 "# configuration written to %s\n"
513 "#\n"), tmpname);
514
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515 sym_change_count = 0;
516
517 return 0;
518}
Roman Zippelc955cca2006-06-08 22:12:39 -0700519
Roman Zippel2e3646e2006-06-08 22:12:42 -0700520int conf_split_config(void)
521{
522 char *name, path[128];
523 char *s, *d, c;
524 struct symbol *sym;
525 struct stat sb;
526 int res, i, fd;
527
528 name = getenv("KCONFIG_AUTOCONFIG");
529 if (!name)
530 name = "include/config/auto.conf";
531 conf_read_simple(name, S_DEF_AUTO);
532
533 if (chdir("include/config"))
534 return 1;
535
536 res = 0;
537 for_all_symbols(i, sym) {
538 sym_calc_value(sym);
539 if ((sym->flags & SYMBOL_AUTO) || !sym->name)
540 continue;
541 if (sym->flags & SYMBOL_WRITE) {
542 if (sym->flags & SYMBOL_DEF_AUTO) {
543 /*
544 * symbol has old and new value,
545 * so compare them...
546 */
547 switch (sym->type) {
548 case S_BOOLEAN:
549 case S_TRISTATE:
550 if (sym_get_tristate_value(sym) ==
551 sym->def[S_DEF_AUTO].tri)
552 continue;
553 break;
554 case S_STRING:
555 case S_HEX:
556 case S_INT:
557 if (!strcmp(sym_get_string_value(sym),
558 sym->def[S_DEF_AUTO].val))
559 continue;
560 break;
561 default:
562 break;
563 }
564 } else {
565 /*
566 * If there is no old value, only 'no' (unset)
567 * is allowed as new value.
568 */
569 switch (sym->type) {
570 case S_BOOLEAN:
571 case S_TRISTATE:
572 if (sym_get_tristate_value(sym) == no)
573 continue;
574 break;
575 default:
576 break;
577 }
578 }
579 } else if (!(sym->flags & SYMBOL_DEF_AUTO))
580 /* There is neither an old nor a new value. */
581 continue;
582 /* else
583 * There is an old value, but no new value ('no' (unset)
584 * isn't saved in auto.conf, so the old value is always
585 * different from 'no').
586 */
587
588 /* Replace all '_' and append ".h" */
589 s = sym->name;
590 d = path;
591 while ((c = *s++)) {
592 c = tolower(c);
593 *d++ = (c == '_') ? '/' : c;
594 }
595 strcpy(d, ".h");
596
597 /* Assume directory path already exists. */
598 fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
599 if (fd == -1) {
600 if (errno != ENOENT) {
601 res = 1;
602 break;
603 }
604 /*
605 * Create directory components,
606 * unless they exist already.
607 */
608 d = path;
609 while ((d = strchr(d, '/'))) {
610 *d = 0;
611 if (stat(path, &sb) && mkdir(path, 0755)) {
612 res = 1;
613 goto out;
614 }
615 *d++ = '/';
616 }
617 /* Try it again. */
618 fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
619 if (fd == -1) {
620 res = 1;
621 break;
622 }
623 }
624 close(fd);
625 }
626out:
627 if (chdir("../.."))
628 return 1;
629
630 return res;
631}
632
Roman Zippelc955cca2006-06-08 22:12:39 -0700633int conf_write_autoconf(void)
634{
635 struct symbol *sym;
636 const char *str;
637 char *name;
638 FILE *out, *out_h;
639 time_t now;
640 int i, l;
641
Roman Zippel2e3646e2006-06-08 22:12:42 -0700642 sym_clear_all_valid();
643
Roman Zippelc955cca2006-06-08 22:12:39 -0700644 file_write_dep("include/config/auto.conf.cmd");
645
Roman Zippel2e3646e2006-06-08 22:12:42 -0700646 if (conf_split_config())
647 return 1;
648
Roman Zippelc955cca2006-06-08 22:12:39 -0700649 out = fopen(".tmpconfig", "w");
650 if (!out)
651 return 1;
652
653 out_h = fopen(".tmpconfig.h", "w");
654 if (!out_h) {
655 fclose(out);
656 return 1;
657 }
658
659 sym = sym_lookup("KERNELVERSION", 0);
660 sym_calc_value(sym);
661 time(&now);
662 fprintf(out, "#\n"
663 "# Automatically generated make config: don't edit\n"
664 "# Linux kernel version: %s\n"
665 "# %s"
666 "#\n",
667 sym_get_string_value(sym), ctime(&now));
668 fprintf(out_h, "/*\n"
669 " * Automatically generated C config: don't edit\n"
670 " * Linux kernel version: %s\n"
671 " * %s"
672 " */\n"
673 "#define AUTOCONF_INCLUDED\n",
674 sym_get_string_value(sym), ctime(&now));
675
Roman Zippelc955cca2006-06-08 22:12:39 -0700676 for_all_symbols(i, sym) {
677 sym_calc_value(sym);
678 if (!(sym->flags & SYMBOL_WRITE) || !sym->name)
679 continue;
680 switch (sym->type) {
681 case S_BOOLEAN:
682 case S_TRISTATE:
683 switch (sym_get_tristate_value(sym)) {
684 case no:
685 break;
686 case mod:
687 fprintf(out, "CONFIG_%s=m\n", sym->name);
688 fprintf(out_h, "#define CONFIG_%s_MODULE 1\n", sym->name);
689 break;
690 case yes:
691 fprintf(out, "CONFIG_%s=y\n", sym->name);
692 fprintf(out_h, "#define CONFIG_%s 1\n", sym->name);
693 break;
694 }
695 break;
696 case S_STRING:
697 str = sym_get_string_value(sym);
698 fprintf(out, "CONFIG_%s=\"", sym->name);
699 fprintf(out_h, "#define CONFIG_%s \"", sym->name);
700 while (1) {
701 l = strcspn(str, "\"\\");
702 if (l) {
703 fwrite(str, l, 1, out);
704 fwrite(str, l, 1, out_h);
705 str += l;
706 }
707 if (!*str)
708 break;
709 fprintf(out, "\\%c", *str);
710 fprintf(out_h, "\\%c", *str);
711 str++;
712 }
713 fputs("\"\n", out);
714 fputs("\"\n", out_h);
715 break;
716 case S_HEX:
717 str = sym_get_string_value(sym);
718 if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) {
719 fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
720 fprintf(out_h, "#define CONFIG_%s 0x%s\n", sym->name, str);
721 break;
722 }
723 case S_INT:
724 str = sym_get_string_value(sym);
725 fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
726 fprintf(out_h, "#define CONFIG_%s %s\n", sym->name, str);
727 break;
728 default:
729 break;
730 }
731 }
732 fclose(out);
733 fclose(out_h);
734
735 name = getenv("KCONFIG_AUTOHEADER");
736 if (!name)
737 name = "include/linux/autoconf.h";
738 if (rename(".tmpconfig.h", name))
739 return 1;
740 name = getenv("KCONFIG_AUTOCONFIG");
741 if (!name)
742 name = "include/config/auto.conf";
743 /*
744 * This must be the last step, kbuild has a dependency on auto.conf
745 * and this marks the successful completion of the previous steps.
746 */
747 if (rename(".tmpconfig", name))
748 return 1;
749
750 return 0;
751}