kconfig: allow multiple default values per symbol
[pandora-kernel.git] / scripts / kconfig / confdata.c
index ccd4513..54ca1a7 100644 (file)
@@ -98,20 +98,28 @@ int conf_read_simple(const char *name)
                in = zconf_fopen(name);
        } else {
                const char **names = conf_confnames;
+               name = *names++;
+               if (!name)
+                       return 1;
+               in = zconf_fopen(name);
+               if (in)
+                       goto load;
+               sym_change_count++;
                while ((name = *names++)) {
                        name = conf_expand_value(name);
                        in = zconf_fopen(name);
                        if (in) {
                                printf(_("#\n"
-                                        "# using defaults found in %s\n"
-                                        "#\n"), name);
-                               break;
+                                        "# using defaults found in %s\n"
+                                        "#\n"), name);
+                               goto load;
                        }
                }
        }
        if (!in)
                return 1;
 
+load:
        conf_filename = name;
        conf_lineno = 0;
        conf_warnings = 0;
@@ -126,11 +134,11 @@ int conf_read_simple(const char *name)
                case S_INT:
                case S_HEX:
                case S_STRING:
-                       if (sym->user.val)
-                               free(sym->user.val);
+                       if (sym->def[S_DEF_USER].val)
+                               free(sym->def[S_DEF_USER].val);
                default:
-                       sym->user.val = NULL;
-                       sym->user.tri = no;
+                       sym->def[S_DEF_USER].val = NULL;
+                       sym->def[S_DEF_USER].tri = no;
                }
        }
 
@@ -158,7 +166,7 @@ int conf_read_simple(const char *name)
                        switch (sym->type) {
                        case S_BOOLEAN:
                        case S_TRISTATE:
-                               sym->user.tri = no;
+                               sym->def[S_DEF_USER].tri = no;
                                sym->flags &= ~SYMBOL_NEW;
                                break;
                        default:
@@ -188,18 +196,18 @@ int conf_read_simple(const char *name)
                        switch (sym->type) {
                        case S_TRISTATE:
                                if (p[0] == 'm') {
-                                       sym->user.tri = mod;
+                                       sym->def[S_DEF_USER].tri = mod;
                                        sym->flags &= ~SYMBOL_NEW;
                                        break;
                                }
                        case S_BOOLEAN:
                                if (p[0] == 'y') {
-                                       sym->user.tri = yes;
+                                       sym->def[S_DEF_USER].tri = yes;
                                        sym->flags &= ~SYMBOL_NEW;
                                        break;
                                }
                                if (p[0] == 'n') {
-                                       sym->user.tri = no;
+                                       sym->def[S_DEF_USER].tri = no;
                                        sym->flags &= ~SYMBOL_NEW;
                                        break;
                                }
@@ -222,7 +230,7 @@ int conf_read_simple(const char *name)
                        case S_INT:
                        case S_HEX:
                                if (sym_string_valid(sym, p)) {
-                                       sym->user.val = strdup(p);
+                                       sym->def[S_DEF_USER].val = strdup(p);
                                        sym->flags &= ~SYMBOL_NEW;
                                } else {
                                        conf_warning("symbol value '%s' invalid for %s", p, sym->name);
@@ -241,24 +249,24 @@ int conf_read_simple(const char *name)
                }
                if (sym && sym_is_choice_value(sym)) {
                        struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
-                       switch (sym->user.tri) {
+                       switch (sym->def[S_DEF_USER].tri) {
                        case no:
                                break;
                        case mod:
-                               if (cs->user.tri == yes) {
+                               if (cs->def[S_DEF_USER].tri == yes) {
                                        conf_warning("%s creates inconsistent choice state", sym->name);
                                        cs->flags |= SYMBOL_NEW;
                                }
                                break;
                        case yes:
-                               if (cs->user.tri != no) {
+                               if (cs->def[S_DEF_USER].tri != no) {
                                        conf_warning("%s creates inconsistent choice state", sym->name);
                                        cs->flags |= SYMBOL_NEW;
                                } else
-                                       cs->user.val = sym;
+                                       cs->def[S_DEF_USER].val = sym;
                                break;
                        }
-                       cs->user.tri = E_OR(cs->user.tri, sym->user.tri);
+                       cs->def[S_DEF_USER].tri = E_OR(cs->def[S_DEF_USER].tri, sym->def[S_DEF_USER].tri);
                }
        }
        fclose(in);
@@ -275,6 +283,8 @@ int conf_read(const char *name)
        struct expr *e;
        int i;
 
+       sym_change_count = 0;
+
        if (conf_read_simple(name))
                return 1;
 
@@ -287,12 +297,12 @@ int conf_read(const char *name)
                        switch (sym->type) {
                        case S_BOOLEAN:
                        case S_TRISTATE:
-                               if (sym->user.tri != sym_get_tristate_value(sym))
+                               if (sym->def[S_DEF_USER].tri != sym_get_tristate_value(sym))
                                        break;
                                if (!sym_is_choice(sym))
                                        goto sym_ok;
                        default:
-                               if (!strcmp(sym->curr.val, sym->user.val))
+                               if (!strcmp(sym->curr.val, sym->def[S_DEF_USER].val))
                                        goto sym_ok;
                                break;
                        }
@@ -309,7 +319,7 @@ int conf_read(const char *name)
                        case S_STRING:
                        case S_INT:
                        case S_HEX:
-                               if (!sym_string_within_range(sym, sym->user.val)) {
+                               if (!sym_string_within_range(sym, sym->def[S_DEF_USER].val)) {
                                        sym->flags |= SYMBOL_NEW;
                                        sym->flags &= ~SYMBOL_VALID;
                                }
@@ -325,14 +335,14 @@ int conf_read(const char *name)
                                sym->flags |= e->right.sym->flags & SYMBOL_NEW;
        }
 
-       sym_change_count = conf_warnings && conf_unsaved;
+       sym_change_count += conf_warnings || conf_unsaved;
 
        return 0;
 }
 
 int conf_write(const char *name)
 {
-       FILE *out, *out_h;
+       FILE *out;
        struct symbol *sym;
        struct menu *menu;
        const char *basename;
@@ -369,13 +379,7 @@ int conf_write(const char *name)
        out = fopen(newname, "w");
        if (!out)
                return 1;
-       out_h = NULL;
-       if (!name) {
-               out_h = fopen(".tmpconfig.h", "w");
-               if (!out_h)
-                       return 1;
-       }
-       sym = sym_lookup("KERNELRELEASE", 0);
+       sym = sym_lookup("KERNELVERSION", 0);
        sym_calc_value(sym);
        time(&now);
        env = getenv("KCONFIG_NOTIMESTAMP");
@@ -390,16 +394,6 @@ int conf_write(const char *name)
                     sym_get_string_value(sym),
                     use_timestamp ? "# " : "",
                     use_timestamp ? ctime(&now) : "");
-       if (out_h)
-               fprintf(out_h, "/*\n"
-                              " * Automatically generated C config: don't edit\n"
-                              " * Linux kernel version: %s\n"
-                              "%s%s"
-                              " */\n"
-                              "#define AUTOCONF_INCLUDED\n",
-                              sym_get_string_value(sym),
-                              use_timestamp ? " * " : "",
-                              use_timestamp ? ctime(&now) : "");
 
        if (!sym_change_count)
                sym_clear_all_valid();
@@ -415,11 +409,6 @@ int conf_write(const char *name)
                                     "#\n"
                                     "# %s\n"
                                     "#\n", str);
-                       if (out_h)
-                               fprintf(out_h, "\n"
-                                              "/*\n"
-                                              " * %s\n"
-                                              " */\n", str);
                } else if (!(sym->flags & SYMBOL_CHOICE)) {
                        sym_calc_value(sym);
                        if (!(sym->flags & SYMBOL_WRITE))
@@ -437,59 +426,39 @@ int conf_write(const char *name)
                                switch (sym_get_tristate_value(sym)) {
                                case no:
                                        fprintf(out, "# CONFIG_%s is not set\n", sym->name);
-                                       if (out_h)
-                                               fprintf(out_h, "#undef CONFIG_%s\n", sym->name);
                                        break;
                                case mod:
                                        fprintf(out, "CONFIG_%s=m\n", sym->name);
-                                       if (out_h)
-                                               fprintf(out_h, "#define CONFIG_%s_MODULE 1\n", sym->name);
                                        break;
                                case yes:
                                        fprintf(out, "CONFIG_%s=y\n", sym->name);
-                                       if (out_h)
-                                               fprintf(out_h, "#define CONFIG_%s 1\n", sym->name);
                                        break;
                                }
                                break;
                        case S_STRING:
-                               // fix me
                                str = sym_get_string_value(sym);
                                fprintf(out, "CONFIG_%s=\"", sym->name);
-                               if (out_h)
-                                       fprintf(out_h, "#define CONFIG_%s \"", sym->name);
-                               do {
+                               while (1) {
                                        l = strcspn(str, "\"\\");
                                        if (l) {
                                                fwrite(str, l, 1, out);
-                                               if (out_h)
-                                                       fwrite(str, l, 1, out_h);
+                                               str += l;
                                        }
-                                       str += l;
-                                       while (*str == '\\' || *str == '"') {
-                                               fprintf(out, "\\%c", *str);
-                                               if (out_h)
-                                                       fprintf(out_h, "\\%c", *str);
-                                               str++;
-                                       }
-                               } while (*str);
+                                       if (!*str)
+                                               break;
+                                       fprintf(out, "\\%c", *str++);
+                               }
                                fputs("\"\n", out);
-                               if (out_h)
-                                       fputs("\"\n", out_h);
                                break;
                        case S_HEX:
                                str = sym_get_string_value(sym);
                                if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) {
                                        fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
-                                       if (out_h)
-                                               fprintf(out_h, "#define CONFIG_%s 0x%s\n", sym->name, str);
                                        break;
                                }
                        case S_INT:
                                str = sym_get_string_value(sym);
                                fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
-                               if (out_h)
-                                       fprintf(out_h, "#define CONFIG_%s %s\n", sym->name, str);
                                break;
                        }
                }
@@ -509,11 +478,6 @@ int conf_write(const char *name)
                }
        }
        fclose(out);
-       if (out_h) {
-               fclose(out_h);
-               rename(".tmpconfig.h", "include/linux/autoconf.h");
-               file_write_dep(NULL);
-       }
        if (!name || basename != conf_def_filename) {
                if (!name)
                        name = conf_def_filename;
@@ -524,7 +488,128 @@ int conf_write(const char *name)
        if (rename(newname, tmpname))
                return 1;
 
+       printf(_("#\n"
+                "# configuration written to %s\n"
+                "#\n"), tmpname);
+
        sym_change_count = 0;
 
        return 0;
 }
+
+int conf_write_autoconf(void)
+{
+       struct symbol *sym;
+       const char *str;
+       char *name;
+       FILE *out, *out_h;
+       time_t now;
+       int i, l;
+
+       file_write_dep("include/config/auto.conf.cmd");
+
+       out = fopen(".tmpconfig", "w");
+       if (!out)
+               return 1;
+
+       out_h = fopen(".tmpconfig.h", "w");
+       if (!out_h) {
+               fclose(out);
+               return 1;
+       }
+
+       sym = sym_lookup("KERNELVERSION", 0);
+       sym_calc_value(sym);
+       time(&now);
+       fprintf(out, "#\n"
+                    "# Automatically generated make config: don't edit\n"
+                    "# Linux kernel version: %s\n"
+                    "# %s"
+                    "#\n",
+                    sym_get_string_value(sym), ctime(&now));
+       fprintf(out_h, "/*\n"
+                      " * Automatically generated C config: don't edit\n"
+                      " * Linux kernel version: %s\n"
+                      " * %s"
+                      " */\n"
+                      "#define AUTOCONF_INCLUDED\n",
+                      sym_get_string_value(sym), ctime(&now));
+
+       sym_clear_all_valid();
+
+       for_all_symbols(i, sym) {
+               sym_calc_value(sym);
+               if (!(sym->flags & SYMBOL_WRITE) || !sym->name)
+                       continue;
+               switch (sym->type) {
+               case S_BOOLEAN:
+               case S_TRISTATE:
+                       switch (sym_get_tristate_value(sym)) {
+                       case no:
+                               break;
+                       case mod:
+                               fprintf(out, "CONFIG_%s=m\n", sym->name);
+                               fprintf(out_h, "#define CONFIG_%s_MODULE 1\n", sym->name);
+                               break;
+                       case yes:
+                               fprintf(out, "CONFIG_%s=y\n", sym->name);
+                               fprintf(out_h, "#define CONFIG_%s 1\n", sym->name);
+                               break;
+                       }
+                       break;
+               case S_STRING:
+                       str = sym_get_string_value(sym);
+                       fprintf(out, "CONFIG_%s=\"", sym->name);
+                       fprintf(out_h, "#define CONFIG_%s \"", sym->name);
+                       while (1) {
+                               l = strcspn(str, "\"\\");
+                               if (l) {
+                                       fwrite(str, l, 1, out);
+                                       fwrite(str, l, 1, out_h);
+                                       str += l;
+                               }
+                               if (!*str)
+                                       break;
+                               fprintf(out, "\\%c", *str);
+                               fprintf(out_h, "\\%c", *str);
+                               str++;
+                       }
+                       fputs("\"\n", out);
+                       fputs("\"\n", out_h);
+                       break;
+               case S_HEX:
+                       str = sym_get_string_value(sym);
+                       if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) {
+                               fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
+                               fprintf(out_h, "#define CONFIG_%s 0x%s\n", sym->name, str);
+                               break;
+                       }
+               case S_INT:
+                       str = sym_get_string_value(sym);
+                       fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
+                       fprintf(out_h, "#define CONFIG_%s %s\n", sym->name, str);
+                       break;
+               default:
+                       break;
+               }
+       }
+       fclose(out);
+       fclose(out_h);
+
+       name = getenv("KCONFIG_AUTOHEADER");
+       if (!name)
+               name = "include/linux/autoconf.h";
+       if (rename(".tmpconfig.h", name))
+               return 1;
+       name = getenv("KCONFIG_AUTOCONFIG");
+       if (!name)
+               name = "include/config/auto.conf";
+       /*
+        * This must be the last step, kbuild has a dependency on auto.conf
+        * and this marks the successful completion of the previous steps.
+        */
+       if (rename(".tmpconfig", name))
+               return 1;
+
+       return 0;
+}