Contents of /trunk/mkinitrd-magellan/busybox/scripts/kconfig/confdata.c
Parent Directory | Revision Log
Revision 984 -
(show annotations)
(download)
Sun May 30 11:32:42 2010 UTC (13 years, 11 months ago) by niro
File MIME type: text/plain
File size: 13317 byte(s)
Sun May 30 11:32:42 2010 UTC (13 years, 11 months ago) by niro
File MIME type: text/plain
File size: 13317 byte(s)
-updated to busybox-1.16.1 and enabled blkid/uuid support in default config
1 | /* |
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> |
8 | #include <stdio.h> |
9 | #include <stdlib.h> |
10 | #include <string.h> |
11 | #include <time.h> |
12 | #include <unistd.h> |
13 | |
14 | #define LKC_DIRECT_LINK |
15 | #include "lkc.h" |
16 | |
17 | static void conf_warning(const char *fmt, ...) |
18 | __attribute__ ((format (printf, 1, 2))); |
19 | |
20 | static const char *conf_filename; |
21 | static int conf_lineno, conf_warnings, conf_unsaved; |
22 | |
23 | const char conf_def_filename[] = ".config"; |
24 | |
25 | const char conf_defname[] = "scripts/defconfig"; |
26 | |
27 | const char *conf_confnames[] = { |
28 | conf_def_filename, |
29 | conf_defname, |
30 | NULL, |
31 | }; |
32 | |
33 | static void conf_warning(const char *fmt, ...) |
34 | { |
35 | va_list ap; |
36 | va_start(ap, fmt); |
37 | fprintf(stderr, "%s:%d:warning: ", conf_filename, conf_lineno); |
38 | vfprintf(stderr, fmt, ap); |
39 | fprintf(stderr, "\n"); |
40 | va_end(ap); |
41 | conf_warnings++; |
42 | } |
43 | |
44 | static char *conf_expand_value(const char *in) |
45 | { |
46 | struct symbol *sym; |
47 | const char *src; |
48 | static char res_value[SYMBOL_MAXLENGTH]; |
49 | char *dst, name[SYMBOL_MAXLENGTH]; |
50 | |
51 | res_value[0] = 0; |
52 | dst = name; |
53 | while ((src = strchr(in, '$'))) { |
54 | strncat(res_value, in, src - in); |
55 | src++; |
56 | dst = name; |
57 | while (isalnum(*src) || *src == '_') |
58 | *dst++ = *src++; |
59 | *dst = 0; |
60 | sym = sym_lookup(name, 0); |
61 | sym_calc_value(sym); |
62 | strcat(res_value, sym_get_string_value(sym)); |
63 | in = src; |
64 | } |
65 | strcat(res_value, in); |
66 | |
67 | return res_value; |
68 | } |
69 | |
70 | char *conf_get_default_confname(void) |
71 | { |
72 | struct stat buf; |
73 | static char fullname[PATH_MAX+1]; |
74 | char *env, *name; |
75 | |
76 | name = conf_expand_value(conf_defname); |
77 | env = getenv(SRCTREE); |
78 | if (env) { |
79 | sprintf(fullname, "%s/%s", env, name); |
80 | if (!stat(fullname, &buf)) |
81 | return fullname; |
82 | } |
83 | return name; |
84 | } |
85 | |
86 | int conf_read_simple(const char *name) |
87 | { |
88 | FILE *in = NULL; |
89 | char line[1024]; |
90 | char *p, *p2; |
91 | struct symbol *sym; |
92 | int i; |
93 | |
94 | if (name) { |
95 | in = zconf_fopen(name); |
96 | } else { |
97 | const char **names = conf_confnames; |
98 | while ((name = *names++)) { |
99 | name = conf_expand_value(name); |
100 | in = zconf_fopen(name); |
101 | if (in) { |
102 | printf(_("#\n" |
103 | "# using defaults found in %s\n" |
104 | "#\n"), name); |
105 | break; |
106 | } |
107 | } |
108 | } |
109 | if (!in) |
110 | return 1; |
111 | |
112 | conf_filename = name; |
113 | conf_lineno = 0; |
114 | conf_warnings = 0; |
115 | conf_unsaved = 0; |
116 | |
117 | for_all_symbols(i, sym) { |
118 | sym->flags |= SYMBOL_NEW | SYMBOL_CHANGED; |
119 | if (sym_is_choice(sym)) |
120 | sym->flags &= ~SYMBOL_NEW; |
121 | sym->flags &= ~SYMBOL_VALID; |
122 | switch (sym->type) { |
123 | case S_INT: |
124 | case S_HEX: |
125 | case S_STRING: |
126 | if (sym->user.val) |
127 | free(sym->user.val); |
128 | default: |
129 | sym->user.val = NULL; |
130 | sym->user.tri = no; |
131 | } |
132 | } |
133 | |
134 | while (fgets(line, sizeof(line), in)) { |
135 | conf_lineno++; |
136 | sym = NULL; |
137 | switch (line[0]) { |
138 | case '#': |
139 | if (memcmp(line + 2, "CONFIG_", 7)) |
140 | continue; |
141 | p = strchr(line + 9, ' '); |
142 | if (!p) |
143 | continue; |
144 | *p++ = 0; |
145 | if (strncmp(p, "is not set", 10)) |
146 | continue; |
147 | sym = sym_find(line + 9); |
148 | if (!sym) { |
149 | conf_warning("trying to assign nonexistent symbol %s", line + 9); |
150 | break; |
151 | } else if (!(sym->flags & SYMBOL_NEW)) { |
152 | conf_warning("trying to reassign symbol %s", sym->name); |
153 | break; |
154 | } |
155 | switch (sym->type) { |
156 | case S_BOOLEAN: |
157 | case S_TRISTATE: |
158 | sym->user.tri = no; |
159 | sym->flags &= ~SYMBOL_NEW; |
160 | break; |
161 | default: |
162 | ; |
163 | } |
164 | break; |
165 | case 'C': |
166 | if (memcmp(line, "CONFIG_", 7)) { |
167 | conf_warning("unexpected data"); |
168 | continue; |
169 | } |
170 | p = strchr(line + 7, '='); |
171 | if (!p) |
172 | continue; |
173 | *p++ = 0; |
174 | p2 = strchr(p, '\n'); |
175 | if (p2) |
176 | *p2 = 0; |
177 | sym = sym_find(line + 7); |
178 | if (!sym) { |
179 | conf_warning("trying to assign nonexistent symbol %s", line + 7); |
180 | break; |
181 | } else if (!(sym->flags & SYMBOL_NEW)) { |
182 | conf_warning("trying to reassign symbol %s", sym->name); |
183 | break; |
184 | } |
185 | switch (sym->type) { |
186 | case S_TRISTATE: |
187 | if (p[0] == 'm') { |
188 | sym->user.tri = mod; |
189 | sym->flags &= ~SYMBOL_NEW; |
190 | break; |
191 | } |
192 | case S_BOOLEAN: |
193 | if (p[0] == 'y') { |
194 | sym->user.tri = yes; |
195 | sym->flags &= ~SYMBOL_NEW; |
196 | break; |
197 | } |
198 | if (p[0] == 'n') { |
199 | sym->user.tri = no; |
200 | sym->flags &= ~SYMBOL_NEW; |
201 | break; |
202 | } |
203 | conf_warning("symbol value '%s' invalid for %s", p, sym->name); |
204 | break; |
205 | case S_STRING: |
206 | if (*p++ != '"') |
207 | break; |
208 | for (p2 = p; (p2 = strpbrk(p2, "\"\\")); p2++) { |
209 | if (*p2 == '"') { |
210 | *p2 = 0; |
211 | break; |
212 | } |
213 | memmove(p2, p2 + 1, strlen(p2)); |
214 | } |
215 | if (!p2) { |
216 | conf_warning("invalid string found"); |
217 | continue; |
218 | } |
219 | case S_INT: |
220 | case S_HEX: |
221 | if (sym_string_valid(sym, p)) { |
222 | sym->user.val = strdup(p); |
223 | sym->flags &= ~SYMBOL_NEW; |
224 | } else { |
225 | if (p[0]) /* bbox */ |
226 | conf_warning("symbol value '%s' invalid for %s", p, sym->name); |
227 | continue; |
228 | } |
229 | break; |
230 | default: |
231 | ; |
232 | } |
233 | break; |
234 | case '\n': |
235 | break; |
236 | default: |
237 | conf_warning("unexpected data"); |
238 | continue; |
239 | } |
240 | if (sym && sym_is_choice_value(sym)) { |
241 | struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym)); |
242 | switch (sym->user.tri) { |
243 | case no: |
244 | break; |
245 | case mod: |
246 | if (cs->user.tri == yes) { |
247 | conf_warning("%s creates inconsistent choice state", sym->name); |
248 | cs->flags |= SYMBOL_NEW; |
249 | } |
250 | break; |
251 | case yes: |
252 | if (cs->user.tri != no) { |
253 | conf_warning("%s creates inconsistent choice state", sym->name); |
254 | cs->flags |= SYMBOL_NEW; |
255 | } else |
256 | cs->user.val = sym; |
257 | break; |
258 | } |
259 | cs->user.tri = E_OR(cs->user.tri, sym->user.tri); |
260 | } |
261 | } |
262 | fclose(in); |
263 | |
264 | if (modules_sym) |
265 | sym_calc_value(modules_sym); |
266 | return 0; |
267 | } |
268 | |
269 | int conf_read(const char *name) |
270 | { |
271 | struct symbol *sym; |
272 | struct property *prop; |
273 | struct expr *e; |
274 | int i; |
275 | |
276 | if (conf_read_simple(name)) |
277 | return 1; |
278 | |
279 | for_all_symbols(i, sym) { |
280 | sym_calc_value(sym); |
281 | if (sym_is_choice(sym) || (sym->flags & SYMBOL_AUTO)) |
282 | goto sym_ok; |
283 | if (sym_has_value(sym) && (sym->flags & SYMBOL_WRITE)) { |
284 | /* check that calculated value agrees with saved value */ |
285 | switch (sym->type) { |
286 | case S_BOOLEAN: |
287 | case S_TRISTATE: |
288 | if (sym->user.tri != sym_get_tristate_value(sym)) |
289 | break; |
290 | if (!sym_is_choice(sym)) |
291 | goto sym_ok; |
292 | default: |
293 | if (!strcmp(sym->curr.val, sym->user.val)) |
294 | goto sym_ok; |
295 | break; |
296 | } |
297 | } else if (!sym_has_value(sym) && !(sym->flags & SYMBOL_WRITE)) |
298 | /* no previous value and not saved */ |
299 | goto sym_ok; |
300 | conf_unsaved++; |
301 | /* maybe print value in verbose mode... */ |
302 | sym_ok: |
303 | if (sym_has_value(sym) && !sym_is_choice_value(sym)) { |
304 | if (sym->visible == no) |
305 | sym->flags |= SYMBOL_NEW; |
306 | switch (sym->type) { |
307 | case S_STRING: |
308 | case S_INT: |
309 | case S_HEX: |
310 | if (!sym_string_within_range(sym, sym->user.val)) { |
311 | sym->flags |= SYMBOL_NEW; |
312 | sym->flags &= ~SYMBOL_VALID; |
313 | } |
314 | default: |
315 | break; |
316 | } |
317 | } |
318 | if (!sym_is_choice(sym)) |
319 | continue; |
320 | prop = sym_get_choice_prop(sym); |
321 | for (e = prop->expr; e; e = e->left.expr) |
322 | if (e->right.sym->visible != no) |
323 | sym->flags |= e->right.sym->flags & SYMBOL_NEW; |
324 | } |
325 | |
326 | sym_change_count = conf_warnings || conf_unsaved; |
327 | |
328 | return 0; |
329 | } |
330 | |
331 | int conf_write(const char *name) |
332 | { |
333 | FILE *out, *out_h; |
334 | struct symbol *sym; |
335 | struct menu *menu; |
336 | const char *basename; |
337 | char dirname[128], tmpname[128], newname[128]; |
338 | int type, l; |
339 | const char *str; |
340 | time_t now; |
341 | int use_timestamp = 1; |
342 | char *env; |
343 | |
344 | dirname[0] = 0; |
345 | if (name && name[0]) { |
346 | struct stat st; |
347 | char *slash; |
348 | |
349 | if (!stat(name, &st) && S_ISDIR(st.st_mode)) { |
350 | strcpy(dirname, name); |
351 | strcat(dirname, "/"); |
352 | basename = conf_def_filename; |
353 | } else if ((slash = strrchr(name, '/'))) { |
354 | int size = slash - name + 1; |
355 | memcpy(dirname, name, size); |
356 | dirname[size] = 0; |
357 | if (slash[1]) |
358 | basename = slash + 1; |
359 | else |
360 | basename = conf_def_filename; |
361 | } else |
362 | basename = name; |
363 | } else |
364 | basename = conf_def_filename; |
365 | |
366 | sprintf(newname, "%s.tmpconfig.%d", dirname, (int)getpid()); |
367 | out = fopen(newname, "w"); |
368 | if (!out) |
369 | return 1; |
370 | out_h = NULL; |
371 | if (!name) { |
372 | out_h = fopen(".tmpconfig.h", "w"); |
373 | if (!out_h) |
374 | return 1; |
375 | file_write_dep(NULL); |
376 | } |
377 | sym = sym_lookup("KERNELVERSION", 0); |
378 | sym_calc_value(sym); |
379 | time(&now); |
380 | env = getenv("KCONFIG_NOTIMESTAMP"); |
381 | if (env && *env) |
382 | use_timestamp = 0; |
383 | |
384 | fprintf(out, _("#\n" |
385 | "# Automatically generated make config: don't edit\n" |
386 | "# Busybox version: %s\n" |
387 | "%s%s" |
388 | "#\n"), |
389 | sym_get_string_value(sym), |
390 | use_timestamp ? "# " : "", |
391 | use_timestamp ? ctime(&now) : ""); |
392 | if (out_h) { |
393 | char buf[sizeof("#define AUTOCONF_TIMESTAMP " |
394 | "\"YYYY-MM-DD HH:MM:SS some_timezone\"\n")]; |
395 | buf[0] = '\0'; |
396 | if (use_timestamp) { |
397 | size_t ret = \ |
398 | strftime(buf, sizeof(buf), "#define AUTOCONF_TIMESTAMP " |
399 | "\"%Y-%m-%d %H:%M:%S %Z\"\n", localtime(&now)); |
400 | /* if user has Factory timezone or some other odd install, the |
401 | * %Z above will overflow the string leaving us with undefined |
402 | * results ... so let's try again without the timezone. |
403 | */ |
404 | if (ret == 0) |
405 | strftime(buf, sizeof(buf), "#define AUTOCONF_TIMESTAMP " |
406 | "\"%Y-%m-%d %H:%M:%S\"\n", localtime(&now)); |
407 | } else { /* bbox */ |
408 | strcpy(buf, "#define AUTOCONF_TIMESTAMP \"\"\n"); |
409 | } |
410 | fprintf(out_h, "/*\n" |
411 | " * Automatically generated C config: don't edit\n" |
412 | " * Busybox version: %s\n" |
413 | " */\n" |
414 | "%s" |
415 | "\n", |
416 | sym_get_string_value(sym), |
417 | buf); |
418 | } |
419 | if (!sym_change_count) |
420 | sym_clear_all_valid(); |
421 | |
422 | menu = rootmenu.list; |
423 | while (menu) { |
424 | sym = menu->sym; |
425 | if (!sym) { |
426 | if (!menu_is_visible(menu)) |
427 | goto next; |
428 | str = menu_get_prompt(menu); |
429 | fprintf(out, "\n" |
430 | "#\n" |
431 | "# %s\n" |
432 | "#\n", str); |
433 | if (out_h) |
434 | fprintf(out_h, "\n" |
435 | "/*\n" |
436 | " * %s\n" |
437 | " */\n", str); |
438 | } else if (!(sym->flags & SYMBOL_CHOICE)) { |
439 | sym_calc_value(sym); |
440 | /* bbox: we want to see all syms |
441 | if (!(sym->flags & SYMBOL_WRITE)) |
442 | goto next; |
443 | */ |
444 | sym->flags &= ~SYMBOL_WRITE; |
445 | type = sym->type; |
446 | if (type == S_TRISTATE) { |
447 | sym_calc_value(modules_sym); |
448 | if (modules_sym->curr.tri == no) |
449 | type = S_BOOLEAN; |
450 | } |
451 | switch (type) { |
452 | case S_BOOLEAN: |
453 | case S_TRISTATE: |
454 | switch (sym_get_tristate_value(sym)) { |
455 | case no: |
456 | fprintf(out, "# CONFIG_%s is not set\n", sym->name); |
457 | if (out_h) { |
458 | fprintf(out_h, "#undef CONFIG_%s\n", sym->name); |
459 | /* bbox */ |
460 | fprintf(out_h, "#define ENABLE_%s 0\n", sym->name); |
461 | fprintf(out_h, "#define IF_%s(...)\n", sym->name); |
462 | fprintf(out_h, "#define IF_NOT_%s(...) __VA_ARGS__\n", sym->name); |
463 | } |
464 | break; |
465 | case mod: |
466 | fprintf(out, "CONFIG_%s=m\n", sym->name); |
467 | if (out_h) |
468 | fprintf(out_h, "#define CONFIG_%s_MODULE 1\n", sym->name); |
469 | break; |
470 | case yes: |
471 | fprintf(out, "CONFIG_%s=y\n", sym->name); |
472 | if (out_h) { |
473 | fprintf(out_h, "#define CONFIG_%s 1\n", sym->name); |
474 | /* bbox */ |
475 | fprintf(out_h, "#define ENABLE_%s 1\n", sym->name); |
476 | fprintf(out_h, "#define IF_%s(...) __VA_ARGS__\n", sym->name); |
477 | fprintf(out_h, "#define IF_NOT_%s(...)\n", sym->name); |
478 | } |
479 | break; |
480 | } |
481 | break; |
482 | case S_STRING: |
483 | // fix me |
484 | str = sym_get_string_value(sym); |
485 | fprintf(out, "CONFIG_%s=\"", sym->name); |
486 | if (out_h) |
487 | fprintf(out_h, "#define CONFIG_%s \"", sym->name); |
488 | do { |
489 | l = strcspn(str, "\"\\"); |
490 | if (l) { |
491 | fwrite(str, l, 1, out); |
492 | if (out_h) |
493 | fwrite(str, l, 1, out_h); |
494 | } |
495 | str += l; |
496 | while (*str == '\\' || *str == '"') { |
497 | fprintf(out, "\\%c", *str); |
498 | if (out_h) |
499 | fprintf(out_h, "\\%c", *str); |
500 | str++; |
501 | } |
502 | } while (*str); |
503 | fputs("\"\n", out); |
504 | if (out_h) { |
505 | fputs("\"\n", out_h); |
506 | /* bbox */ |
507 | fprintf(out_h, "#define ENABLE_%s 1\n", sym->name); |
508 | fprintf(out_h, "#define IF_%s(...) __VA_ARGS__\n", sym->name); |
509 | fprintf(out_h, "#define IF_NOT_%s(...)\n", sym->name); |
510 | } |
511 | break; |
512 | case S_HEX: |
513 | str = sym_get_string_value(sym); |
514 | if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) { |
515 | fprintf(out, "CONFIG_%s=%s\n", sym->name, str); |
516 | if (out_h) { |
517 | fprintf(out_h, "#define CONFIG_%s 0x%s\n", sym->name, str); |
518 | /* bbox */ |
519 | fprintf(out_h, "#define ENABLE_%s 1\n", sym->name); |
520 | fprintf(out_h, "#define IF_%s(...) __VA_ARGS__\n", sym->name); |
521 | fprintf(out_h, "#define IF_NOT_%s(...)\n", sym->name); |
522 | } |
523 | break; |
524 | } |
525 | case S_INT: |
526 | str = sym_get_string_value(sym); |
527 | if (!str[0]) |
528 | str = "0"; |
529 | fprintf(out, "CONFIG_%s=%s\n", sym->name, str); |
530 | if (out_h) { |
531 | fprintf(out_h, "#define CONFIG_%s %s\n", sym->name, str); |
532 | /* bbox */ |
533 | fprintf(out_h, "#define ENABLE_%s 1\n", sym->name); |
534 | fprintf(out_h, "#define IF_%s(...) __VA_ARGS__\n", sym->name); |
535 | fprintf(out_h, "#define IF_NOT_%s(...)\n", sym->name); |
536 | } |
537 | break; |
538 | } |
539 | } |
540 | |
541 | next: |
542 | if (menu->list) { |
543 | menu = menu->list; |
544 | continue; |
545 | } |
546 | if (menu->next) |
547 | menu = menu->next; |
548 | else while ((menu = menu->parent)) { |
549 | if (menu->next) { |
550 | menu = menu->next; |
551 | break; |
552 | } |
553 | } |
554 | } |
555 | fclose(out); |
556 | if (out_h) { |
557 | fclose(out_h); |
558 | rename(".tmpconfig.h", "include/autoconf.h"); |
559 | } |
560 | if (!name || basename != conf_def_filename) { |
561 | if (!name) |
562 | name = conf_def_filename; |
563 | sprintf(tmpname, "%s.old", name); |
564 | rename(name, tmpname); |
565 | } |
566 | sprintf(tmpname, "%s%s", dirname, basename); |
567 | if (rename(newname, tmpname)) |
568 | return 1; |
569 | |
570 | sym_change_count = 0; |
571 | |
572 | return 0; |
573 | } |