Chameleon

Chameleon Svn Source Tree

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

Archive Download this file

Revision: 1171