Chameleon

Chameleon Svn Source Tree

Root/branches/ErmaC/Enoch/i386/config/confdata.c

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 <errno.h>
9#include <fcntl.h>
10#include <stdio.h>
11#include <stdlib.h>
12#include <string.h>
13#include <time.h>
14#include <unistd.h>
15
16#define LKC_DIRECT_LINK
17#include "lkc.h"
18
19#define max(a, b) ({\
20typeof(a) _a = a;\
21typeof(b) _b = b;\
22_a > _b ? _a : _b; })
23
24#define min(a, b) ({\
25typeof(a) _a = a;\
26typeof(b) _b = b;\
27_a < _b ? _a : _b; })
28
29static void conf_warning(const char *fmt, ...)
30__attribute__ ((format (printf, 1, 2)));
31
32static void conf_message(const char *fmt, ...)
33__attribute__ ((format (printf, 1, 2)));
34
35static const char *conf_filename;
36static int conf_lineno, conf_warnings, conf_unsaved;
37
38const char conf_defname[] = "config/defconfig";
39
40static void conf_warning(const char *fmt, ...)
41{
42va_list ap;
43va_start(ap, fmt);
44fprintf(stderr, "%s:%d:warning: ", conf_filename, conf_lineno);
45vfprintf(stderr, fmt, ap);
46fprintf(stderr, "\n");
47va_end(ap);
48conf_warnings++;
49}
50
51static void conf_default_message_callback(const char *fmt, va_list ap)
52{
53printf("#\n# ");
54vprintf(fmt, ap);
55printf("\n#\n");
56}
57
58static void (*conf_message_callback) (const char *fmt, va_list ap) =
59conf_default_message_callback;
60void conf_set_message_callback(void (*fn) (const char *fmt, va_list ap))
61{
62conf_message_callback = fn;
63}
64
65static void conf_message(const char *fmt, ...)
66{
67va_list ap;
68
69va_start(ap, fmt);
70if (conf_message_callback)
71conf_message_callback(fmt, ap);
72}
73
74const char *conf_get_configname(void)
75{
76char *name = getenv("KCONFIG_CONFIG");
77
78return name ? name : ".config";
79}
80
81const char *conf_get_autoconfig_name(void)
82{
83char *name = getenv("KCONFIG_AUTOCONFIG");
84
85return name ? name : "auto.conf";
86}
87
88/* TODO: figure out if symbols are always null-terminated */
89static char *conf_expand_value(const char *in)
90{
91static char res_value[SYMBOL_MAXLENGTH + 1];
92char name[SYMBOL_MAXLENGTH];
93size_t res_rem = SYMBOL_MAXLENGTH;
94char *res_ptr = res_value;
95const char *src;
96*res_ptr = 0;
97res_ptr[SYMBOL_MAXLENGTH] = 0;
98while ((src = strchr(in, '$'))) {
99struct symbol *sym;
100const char *symval;
101char *name_ptr = name;
102size_t n = min(res_rem, src - in);
103
104res_ptr = stpncpy(res_ptr, in, n);
105if (!(res_rem -= n)) {
106return res_value; /* buffer full, quit now */
107}
108src++;
109
110*name_ptr = 0;
111while (isalnum(*src) || *src == '_') {
112*name_ptr++ = *src++;
113}
114*name_ptr = 0;
115
116sym = sym_lookup(name, 0);
117sym_calc_value(sym);
118symval = sym_get_string_value(sym);
119n = min(res_rem, strlen(symval));
120
121res_ptr = stpncpy(res_ptr, symval, n);
122if (!(res_rem -= n)) {
123return res_value; /* buffer full, quit now */
124}
125in = src;
126}
127
128strncpy(res_ptr, in, res_rem + 1);
129return res_value;
130}
131
132char *conf_get_default_confname(void)
133{
134struct stat buf;
135static char fullname[PATH_MAX+1];
136char *env, *name;
137
138name = conf_expand_value(conf_defname);
139env = getenv(SRCTREE);
140if (env) {
141snprintf(fullname, PATH_MAX+1, "%s/%s", env, name);
142if (!stat(fullname, &buf))
143return fullname;
144}
145return name;
146}
147
148static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
149{
150char *p2;
151
152switch (sym->type) {
153case S_TRISTATE:
154if (p[0] == 'm') {
155sym->def[def].tri = mod;
156sym->flags |= def_flags;
157break;
158}
159case S_BOOLEAN:
160if (p[0] == 'y') {
161sym->def[def].tri = yes;
162sym->flags |= def_flags;
163break;
164}
165if (p[0] == 'n') {
166sym->def[def].tri = no;
167sym->flags |= def_flags;
168break;
169}
170conf_warning("symbol value '%s' invalid for %s", p, sym->name);
171break;
172case S_OTHER:
173if (*p != '"') {
174for (p2 = p; *p2 && !isspace(*p2); p2++)
175;
176sym->type = S_STRING;
177goto done;
178}
179case S_STRING:
180if (*p++ != '"')
181break;
182for (p2 = p; (p2 = strpbrk(p2, "\"\\")); p2++) {
183if (*p2 == '"') {
184*p2 = 0;
185break;
186}
187memmove(p2, p2 + 1, strlen(p2));
188}
189if (!p2) {
190conf_warning("invalid string found");
191return 1;
192}
193case S_INT:
194case S_HEX:
195done:
196if (sym_string_valid(sym, p)) {
197sym->def[def].val = strdup(p);
198sym->flags |= def_flags;
199} else {
200conf_warning("symbol value '%s' invalid for %s", p, sym->name);
201return 1;
202}
203break;
204default:
205;
206}
207return 0;
208}
209
210int conf_read_simple(const char *name, int def)
211{
212FILE *in = NULL;
213char line[1024];
214char *p, *p2;
215struct symbol *sym;
216int i, def_flags;
217
218if (name) {
219in = zconf_fopen(name);
220} else {
221struct property *prop;
222
223name = conf_get_configname();
224in = zconf_fopen(name);
225if (in)
226goto load;
227sym_add_change_count(1);
228if (!sym_defconfig_list) {
229if (modules_sym)
230sym_calc_value(modules_sym);
231return 1;
232}
233
234for_all_defaults(sym_defconfig_list, prop) {
235if (expr_calc_value(prop->visible.expr) == no ||
236 prop->expr->type != E_SYMBOL)
237continue;
238name = conf_expand_value(prop->expr->left.sym->name);
239in = zconf_fopen(name);
240if (in) {
241conf_message(_("using defaults found in %s"),
242 name);
243goto load;
244}
245}
246}
247if (!in)
248return 1;
249
250load:
251conf_filename = name;
252conf_lineno = 0;
253conf_warnings = 0;
254conf_unsaved = 0;
255
256def_flags = SYMBOL_DEF << def;
257for_all_symbols(i, sym) {
258sym->flags |= SYMBOL_CHANGED;
259sym->flags &= ~(def_flags|SYMBOL_VALID);
260if (sym_is_choice(sym))
261sym->flags |= def_flags;
262switch (sym->type) {
263case S_INT:
264case S_HEX:
265case S_STRING:
266if (sym->def[def].val)
267free(sym->def[def].val);
268default:
269sym->def[def].val = NULL;
270sym->def[def].tri = no;
271}
272}
273
274while (fgets(line, sizeof(line), in)) {
275conf_lineno++;
276sym = NULL;
277if (line[0] == '#') {
278if (memcmp(line + 2, CONFIG_, strlen(CONFIG_)))
279continue;
280p = strchr(line + 2 + strlen(CONFIG_), ' ');
281if (!p)
282continue;
283*p++ = 0;
284if (strncmp(p, "is not set", 10))
285continue;
286if (def == S_DEF_USER) {
287sym = sym_find(line + 2 + strlen(CONFIG_));
288if (!sym) {
289sym_add_change_count(1);
290goto setsym;
291}
292} else {
293sym = sym_lookup(line + 2 + strlen(CONFIG_), 0);
294if (sym->type == S_UNKNOWN)
295sym->type = S_BOOLEAN;
296}
297if (sym->flags & def_flags) {
298conf_warning("override: reassigning to symbol %s", sym->name);
299}
300switch (sym->type) {
301case S_BOOLEAN:
302case S_TRISTATE:
303sym->def[def].tri = no;
304sym->flags |= def_flags;
305break;
306default:
307;
308}
309} else if (memcmp(line, CONFIG_, strlen(CONFIG_)) == 0) {
310p = strchr(line + strlen(CONFIG_), '=');
311if (!p)
312continue;
313*p++ = 0;
314p2 = strchr(p, '\n');
315if (p2) {
316*p2-- = 0;
317if (*p2 == '\r')
318*p2 = 0;
319}
320if (def == S_DEF_USER) {
321sym = sym_find(line + strlen(CONFIG_));
322if (!sym) {
323sym_add_change_count(1);
324goto setsym;
325}
326} else {
327sym = sym_lookup(line + strlen(CONFIG_), 0);
328if (sym->type == S_UNKNOWN)
329sym->type = S_OTHER;
330}
331if (sym->flags & def_flags) {
332conf_warning("override: reassigning to symbol %s", sym->name);
333}
334if (conf_set_sym_val(sym, def, def_flags, p))
335continue;
336} else {
337if (line[0] != '\r' && line[0] != '\n')
338conf_warning("unexpected data");
339continue;
340}
341setsym:
342if (sym && sym_is_choice_value(sym)) {
343struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
344switch (sym->def[def].tri) {
345case no:
346break;
347case mod:
348if (cs->def[def].tri == yes) {
349conf_warning("%s creates inconsistent choice state", sym->name);
350cs->flags &= ~def_flags;
351}
352break;
353case yes:
354if (cs->def[def].tri != no)
355conf_warning("override: %s changes choice state", sym->name);
356cs->def[def].val = sym;
357break;
358}
359cs->def[def].tri = EXPR_OR(cs->def[def].tri, sym->def[def].tri);
360}
361}
362fclose(in);
363
364if (modules_sym)
365sym_calc_value(modules_sym);
366return 0;
367}
368
369int conf_read(const char *name)
370{
371struct symbol *sym, *choice_sym;
372struct property *prop;
373struct expr *e;
374int i, flags;
375
376sym_set_change_count(0);
377
378if (conf_read_simple(name, S_DEF_USER))
379return 1;
380
381for_all_symbols(i, sym) {
382sym_calc_value(sym);
383if (sym_is_choice(sym) || (sym->flags & SYMBOL_AUTO))
384goto sym_ok;
385if (sym_has_value(sym) && (sym->flags & SYMBOL_WRITE)) {
386/* check that calculated value agrees with saved value */
387switch (sym->type) {
388case S_BOOLEAN:
389case S_TRISTATE:
390if (sym->def[S_DEF_USER].tri != sym_get_tristate_value(sym))
391break;
392if (!sym_is_choice(sym))
393goto sym_ok;
394default:
395if (!strcmp(sym->curr.val, sym->def[S_DEF_USER].val))
396goto sym_ok;
397break;
398}
399} else if (!sym_has_value(sym) && !(sym->flags & SYMBOL_WRITE))
400/* no previous value and not saved */
401goto sym_ok;
402conf_unsaved++;
403/* maybe print value in verbose mode... */
404sym_ok:
405if (!sym_is_choice(sym))
406continue;
407/* The choice symbol only has a set value (and thus is not new)
408 * if all its visible childs have values.
409 */
410prop = sym_get_choice_prop(sym);
411flags = sym->flags;
412expr_list_for_each_sym(prop->expr, e, choice_sym)
413if (choice_sym->visible != no)
414flags &= choice_sym->flags;
415sym->flags &= flags | ~SYMBOL_DEF_USER;
416}
417
418for_all_symbols(i, sym) {
419if (sym_has_value(sym) && !sym_is_choice_value(sym)) {
420/* Reset values of generates values, so they'll appear
421 * as new, if they should become visible, but that
422 * doesn't quite work if the Kconfig and the saved
423 * configuration disagree.
424 */
425if (sym->visible == no && !conf_unsaved)
426sym->flags &= ~SYMBOL_DEF_USER;
427switch (sym->type) {
428case S_STRING:
429case S_INT:
430case S_HEX:
431/* Reset a string value if it's out of range */
432if (sym_string_within_range(sym, sym->def[S_DEF_USER].val))
433break;
434sym->flags &= ~(SYMBOL_VALID|SYMBOL_DEF_USER);
435conf_unsaved++;
436break;
437default:
438break;
439}
440}
441}
442
443sym_add_change_count(conf_warnings || conf_unsaved);
444
445return 0;
446}
447
448/* Write a S_STRING */
449static void conf_write_string(bool headerfile, const char *name,
450 const char *str, FILE *out)
451{
452int l;
453if (headerfile)
454fprintf(out, "#define %s%s \"", CONFIG_, name);
455else
456fprintf(out, "%s%s=\"", CONFIG_, name);
457
458while (1) {
459l = strcspn(str, "\"\\");
460if (l) {
461xfwrite(str, l, 1, out);
462str += l;
463}
464if (!*str)
465break;
466fprintf(out, "\\%c", *str++);
467}
468fputs("\"\n", out);
469}
470
471static void conf_write_symbol(struct symbol *sym, FILE *out, bool write_no)
472{
473const char *str;
474
475switch (sym->type) {
476case S_BOOLEAN:
477case S_TRISTATE:
478switch (sym_get_tristate_value(sym)) {
479case no:
480if (write_no)
481fprintf(out, "# %s%s is not set\n",
482 CONFIG_, sym->name);
483break;
484case mod:
485fprintf(out, "%s%s=m\n", CONFIG_, sym->name);
486break;
487case yes:
488fprintf(out, "%s%s=y\n", CONFIG_, sym->name);
489break;
490}
491break;
492case S_STRING:
493conf_write_string(false, sym->name, sym_get_string_value(sym), out);
494break;
495case S_HEX:
496case S_INT:
497str = sym_get_string_value(sym);
498fprintf(out, "%s%s=%s\n", CONFIG_, sym->name, str);
499break;
500case S_OTHER:
501case S_UNKNOWN:
502break;
503}
504}
505
506/*
507 * Write out a minimal config.
508 * All values that has default values are skipped as this is redundant.
509 */
510int conf_write_defconfig(const char *filename)
511{
512struct symbol *sym;
513struct menu *menu;
514FILE *out;
515
516out = fopen(filename, "w");
517if (!out)
518return 1;
519
520sym_clear_all_valid();
521
522/* Traverse all menus to find all relevant symbols */
523menu = rootmenu.list;
524
525while (menu != NULL)
526{
527sym = menu->sym;
528if (sym == NULL) {
529if (!menu_is_visible(menu))
530goto next_menu;
531} else if (!sym_is_choice(sym)) {
532sym_calc_value(sym);
533if (!(sym->flags & SYMBOL_WRITE))
534goto next_menu;
535sym->flags &= ~SYMBOL_WRITE;
536/* If we cannot change the symbol - skip */
537if (!sym_is_changable(sym))
538goto next_menu;
539/* If symbol equals to default value - skip */
540if (strcmp(sym_get_string_value(sym), sym_get_string_default(sym)) == 0)
541goto next_menu;
542
543/*
544 * If symbol is a choice value and equals to the
545 * default for a choice - skip.
546 * But only if value is bool and equal to "y" and
547 * choice is not "optional".
548 * (If choice is "optional" then all values can be "n")
549 */
550if (sym_is_choice_value(sym)) {
551struct symbol *cs;
552struct symbol *ds;
553
554cs = prop_get_symbol(sym_get_choice_prop(sym));
555ds = sym_choice_default(cs);
556if (!sym_is_optional(cs) && sym == ds) {
557if ((sym->type == S_BOOLEAN) &&
558 sym_get_tristate_value(sym) == yes)
559goto next_menu;
560}
561}
562conf_write_symbol(sym, out, true);
563}
564next_menu:
565if (menu->list != NULL) {
566menu = menu->list;
567}
568else if (menu->next != NULL) {
569menu = menu->next;
570} else {
571while ((menu = menu->parent)) {
572if (menu->next != NULL) {
573menu = menu->next;
574break;
575}
576}
577}
578}
579fclose(out);
580return 0;
581}
582
583int conf_write(const char *name)
584{
585FILE *out;
586struct symbol *sym;
587struct menu *menu;
588const char *basename;
589const char *str;
590char dirname[PATH_MAX+1], tmpname[PATH_MAX+1], newname[PATH_MAX+1];
591time_t now;
592int use_timestamp = 1;
593char *env;
594
595dirname[0] = 0;
596if (name && name[0]) {
597struct stat st;
598char *slash;
599
600if (!stat(name, &st) && S_ISDIR(st.st_mode)) {
601/* FIXME: add length check */
602strcpy(stpcpy(dirname, name), "/");
603basename = conf_get_configname();
604} else if ((slash = strrchr(name, '/'))) {
605size_t size = slash - name + 1;
606memcpy(dirname, name, size);
607dirname[size] = 0;
608if (slash[1]) {
609basename = slash + 1;
610} else {
611basename = conf_get_configname();
612}
613} else {
614basename = name;
615}
616} else {
617basename = conf_get_configname();
618}
619snprintf(newname, PATH_MAX+1, "%s%s", dirname, basename);
620env = getenv("KCONFIG_OVERWRITECONFIG");
621if (!env || !*env) {
622snprintf(tmpname, PATH_MAX+1, "%s.tmpconfig.%d", dirname, (int)getpid());
623out = fopen(tmpname, "w");
624} else {
625*tmpname = 0;
626out = fopen(newname, "w");
627}
628if (!out) {
629return 1;
630}
631time(&now);
632env = getenv("KCONFIG_NOTIMESTAMP");
633if (env && *env) {
634use_timestamp = 0;
635}
636
637fprintf(out, _("#\n"
638 "# Automatically generated make config: don't edit\n"
639 "# %s\n"
640 "%s%s"
641 "#\n"),
642 rootmenu.prompt->text,
643 use_timestamp ? "# " : "",
644 use_timestamp ? ctime(&now) : "");
645
646if (!conf_get_changed())
647sym_clear_all_valid();
648
649menu = rootmenu.list;
650while (menu) {
651sym = menu->sym;
652if (!sym) {
653if (!menu_is_visible(menu))
654goto next;
655str = menu_get_prompt(menu);
656fprintf(out, "\n"
657 "#\n"
658 "# %s\n"
659 "#\n", str);
660} else if (!(sym->flags & SYMBOL_CHOICE)) {
661sym_calc_value(sym);
662if (!(sym->flags & SYMBOL_WRITE))
663goto next;
664sym->flags &= ~SYMBOL_WRITE;
665/* Write config symbol to file */
666conf_write_symbol(sym, out, true);
667}
668
669next:
670if (menu->list) {
671menu = menu->list;
672continue;
673}
674if (menu->next) {
675menu = menu->next;
676} else while ((menu = menu->parent)) {
677if (menu->next) {
678menu = menu->next;
679break;
680}
681}
682}
683fclose(out);
684
685if (*tmpname) {
686strcat(dirname, basename);
687strcat(dirname, ".old");
688rename(newname, dirname);
689if (rename(tmpname, newname)) {
690return 1;
691}
692}
693
694//conf_message(_("configuration written to %s"), newname);
695
696sym_set_change_count(0);
697
698return 0;
699}
700#if 0
701
702static int conf_split_config(void)
703{
704const char *name;
705char path[PATH_MAX+1];
706char *s, *d, c;
707struct symbol *sym;
708struct stat sb;
709int res, i, fd;
710
711name = conf_get_autoconfig_name();
712conf_read_simple(name, S_DEF_AUTO);
713
714//if (chdir("include/config"))
715//return 1;
716
717res = 0;
718for_all_symbols(i, sym) {
719sym_calc_value(sym);
720if ((sym->flags & SYMBOL_AUTO) || !sym->name)
721continue;
722if (sym->flags & SYMBOL_WRITE) {
723if (sym->flags & SYMBOL_DEF_AUTO) {
724/*
725 * symbol has old and new value,
726 * so compare them...
727 */
728switch (sym->type) {
729case S_BOOLEAN:
730case S_TRISTATE:
731if (sym_get_tristate_value(sym) ==
732 sym->def[S_DEF_AUTO].tri)
733continue;
734break;
735case S_STRING:
736case S_HEX:
737case S_INT:
738if (!strcmp(sym_get_string_value(sym),
739 sym->def[S_DEF_AUTO].val))
740continue;
741break;
742default:
743break;
744}
745} else {
746/*
747 * If there is no old value, only 'no' (unset)
748 * is allowed as new value.
749 */
750switch (sym->type) {
751case S_BOOLEAN:
752case S_TRISTATE:
753if (sym_get_tristate_value(sym) == no)
754continue;
755break;
756default:
757break;
758}
759}
760} else if (!(sym->flags & SYMBOL_DEF_AUTO))
761/* There is neither an old nor a new value. */
762continue;
763/* else
764 *There is an old value, but no new value ('no' (unset)
765 *isn't saved in auto.conf, so the old value is always
766 *different from 'no').
767 */
768
769/* Replace all '_' and append ".h" */
770s = sym->name;
771d = path;
772while ((c = *s++)) {
773c = tolower(c);
774*d++ = (c == '_') ? '/' : c;
775}
776strcpy(d, ".h");
777
778/* Assume directory path already exists. */
779fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
780if (fd == -1) {
781if (errno != ENOENT) {
782res = 1;
783break;
784}
785/*
786 * Create directory components,
787 * unless they exist already.
788 */
789d = path;
790while ((d = strchr(d, '/'))) {
791*d = 0;
792if (stat(path, &sb) && mkdir(path, 0755)) {
793res = 1;
794goto out;
795}
796*d++ = '/';
797}
798/* Try it again. */
799fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
800if (fd == -1) {
801res = 1;
802break;
803}
804}
805close(fd);
806}
807out:
808if (chdir("../.."))
809return 1;
810
811return res;
812}
813#endif
814int conf_write_autoconf(void)
815{
816struct symbol *sym;
817const char *str;
818const char *name;
819FILE *out, *out_h, *out_inc;
820time_t now;
821int i;
822
823sym_clear_all_valid();
824
825/*if (conf_split_config())
826{
827 printf("ERR: conf_split_config");
828 return 1;
829 }*/
830
831out = fopen(".tmpconfig", "w");
832if (!out)
833 {
834 printf("ERR: .tmpconfig");
835return 1;
836 }
837
838out_h = fopen(".tmpconfig.h", "w");
839if (!out_h) {
840fclose(out);
841return 1;
842}
843
844 out_inc = fopen(".tmpconfig.inc", "w");
845if (!out_inc) {
846fclose(out);
847 fclose(out_h);
848return 1;
849}
850
851
852time(&now);
853fprintf(out, "#\n"
854 "# Automatically generated make config: don't edit\n"
855 "# %s\n"
856 "# %s"
857 "#\n",
858 rootmenu.prompt->text, ctime(&now));
859
860fprintf(out_h, "//\n"
861 "// Automatically generated make config: don't edit\n"
862 "// %s\n"
863 "// %s"
864 "// \n",
865 rootmenu.prompt->text, ctime(&now));
866
867 fprintf(out_inc, ";\n"
868 "; Automatically generated make config: don't edit\n"
869 "; %s\n"
870 "; %s"
871 ";\n",
872 rootmenu.prompt->text, ctime(&now));
873
874
875 fprintf(out_h, "#define CONFIG_IS_BUILTIN 1\n");
876 fprintf(out_h, "#define CONFIG_IS_MODULE 2\n");
877
878
879for_all_symbols(i, sym) {
880sym_calc_value(sym);
881if (!(sym->flags & SYMBOL_WRITE) || !sym->name)
882continue;
883
884/* write symbol to config file */
885conf_write_symbol(sym, out, false);
886
887/* update autoconf and tristate files */
888switch (sym->type) {
889case S_BOOLEAN:
890case S_TRISTATE:
891switch (sym_get_tristate_value(sym)) {
892case no:
893 fprintf(out_inc, "%s%s EQU 0\n",
894 CONFIG_, sym->name);
895
896break;
897case mod:
898fprintf(out_inc, "%s%s EQU 1\n",
899 CONFIG_, sym->name);
900 fprintf(out_h, "#define %s%s CONFIG_IS_MODULE\n",
901 CONFIG_, sym->name);
902
903break;
904case yes:
905 fprintf(out_inc, "%s%s EQU 1\n",
906 CONFIG_, sym->name);
907fprintf(out_h, "#define %s%s CONFIG_IS_BUILTIN\n",
908 CONFIG_, sym->name);
909break;
910}
911break;
912case S_STRING:
913conf_write_string(true, sym->name, sym_get_string_value(sym), out_h);
914break;
915case S_HEX:
916str = sym_get_string_value(sym);
917if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) {
918 fprintf(out_inc, "%s%s EQU 0x%s\n",
919 CONFIG_, sym->name, str);
920fprintf(out_h, "#define %s%s 0x%s\n",
921 CONFIG_, sym->name, str);
922break;
923}
924case S_INT:
925str = sym_get_string_value(sym);
926 fprintf(out_inc, "%s%s EQU %s\n",
927 CONFIG_, sym->name, str);
928fprintf(out_h, "#define %s%s %s\n",
929 CONFIG_, sym->name, str);
930break;
931default:
932break;
933}
934}
935fclose(out);
936fclose(out_h);
937fclose(out_inc);
938
939name = getenv("CCONFIG_AUTOHEADER");
940if (!name) name = "autoconf.h";
941if (rename(".tmpconfig.h", name))
942return 1;
943
944 name = getenv("CCONFIG_AUTOINC");
945if (!name) name = "autoconf.inc";
946if (rename(".tmpconfig.inc", name))
947return 1;
948
949
950name = conf_get_autoconfig_name();
951/*
952 * This must be the last step, kbuild has a dependency on auto.conf
953 * and this marks the successful completion of the previous steps.
954 */
955if (rename(".tmpconfig", name))
956 {
957 printf("rename");
958return 1;
959 }
960return 0;
961}
962
963static int sym_change_count;
964static void (*conf_changed_callback)(void);
965
966void sym_set_change_count(int count)
967{
968int _sym_change_count = sym_change_count;
969sym_change_count = count;
970if (conf_changed_callback &&
971 (bool)_sym_change_count != (bool)count)
972conf_changed_callback();
973}
974
975void sym_add_change_count(int count)
976{
977sym_set_change_count(count + sym_change_count);
978}
979
980bool conf_get_changed(void)
981{
982return sym_change_count;
983}
984
985void conf_set_changed_callback(void (*fn)(void))
986{
987conf_changed_callback = fn;
988}
989
990static void randomize_choice_values(struct symbol *csym)
991{
992struct property *prop;
993struct symbol *sym;
994struct expr *e;
995int cnt, def;
996
997/*
998 * If choice is mod then we may have more items selected
999 * and if no then no-one.
1000 * In both cases stop.
1001 */
1002if (csym->curr.tri != yes)
1003return;
1004
1005prop = sym_get_choice_prop(csym);
1006
1007/* count entries in choice block */
1008cnt = 0;
1009expr_list_for_each_sym(prop->expr, e, sym)
1010cnt++;
1011
1012/*
1013 * find a random value and set it to yes,
1014 * set the rest to no so we have only one set
1015 */
1016def = (rand() % cnt);
1017
1018cnt = 0;
1019expr_list_for_each_sym(prop->expr, e, sym) {
1020if (def == cnt++) {
1021sym->def[S_DEF_USER].tri = yes;
1022csym->def[S_DEF_USER].val = sym;
1023}
1024else {
1025sym->def[S_DEF_USER].tri = no;
1026}
1027}
1028csym->flags |= SYMBOL_DEF_USER;
1029/* clear VALID to get value calculated */
1030csym->flags &= ~(SYMBOL_VALID);
1031}
1032
1033static void set_all_choice_values(struct symbol *csym)
1034{
1035struct property *prop;
1036struct symbol *sym;
1037struct expr *e;
1038
1039prop = sym_get_choice_prop(csym);
1040
1041/*
1042 * Set all non-assinged choice values to no
1043 */
1044expr_list_for_each_sym(prop->expr, e, sym) {
1045if (!sym_has_value(sym))
1046sym->def[S_DEF_USER].tri = no;
1047}
1048csym->flags |= SYMBOL_DEF_USER;
1049/* clear VALID to get value calculated */
1050csym->flags &= ~(SYMBOL_VALID);
1051}
1052
1053void conf_set_all_new_symbols(enum conf_def_mode mode)
1054{
1055struct symbol *sym, *csym;
1056int i, cnt;
1057
1058for_all_symbols(i, sym) {
1059if (sym_has_value(sym))
1060continue;
1061switch (sym_get_type(sym)) {
1062case S_BOOLEAN:
1063case S_TRISTATE:
1064switch (mode) {
1065case def_yes:
1066sym->def[S_DEF_USER].tri = yes;
1067break;
1068case def_mod:
1069sym->def[S_DEF_USER].tri = mod;
1070break;
1071case def_no:
1072sym->def[S_DEF_USER].tri = no;
1073break;
1074case def_random:
1075cnt = sym_get_type(sym) == S_TRISTATE ? 3 : 2;
1076sym->def[S_DEF_USER].tri = (tristate)(rand() % cnt);
1077break;
1078default:
1079continue;
1080}
1081if (!(sym_is_choice(sym) && mode == def_random))
1082sym->flags |= SYMBOL_DEF_USER;
1083break;
1084default:
1085break;
1086}
1087
1088}
1089
1090sym_clear_all_valid();
1091
1092/*
1093 * We have different type of choice blocks.
1094 * If curr.tri equals to mod then we can select several
1095 * choice symbols in one block.
1096 * In this case we do nothing.
1097 * If curr.tri equals yes then only one symbol can be
1098 * selected in a choice block and we set it to yes,
1099 * and the rest to no.
1100 */
1101for_all_symbols(i, csym) {
1102if (sym_has_value(csym) || !sym_is_choice(csym))
1103continue;
1104
1105sym_calc_value(csym);
1106if (mode == def_random)
1107randomize_choice_values(csym);
1108else
1109set_all_choice_values(csym);
1110}
1111}
1112

Archive Download this file

Revision: 2341