linux 2.6.16.38 w/ vs2.0.3-rc1
[linux-2.6.git] / scripts / kconfig / confdata.c
index f777c91..b0cbbe2 100644 (file)
@@ -5,7 +5,6 @@
 
 #include <sys/stat.h>
 #include <ctype.h>
-#include <fcntl.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -21,8 +20,19 @@ static void conf_warning(const char *fmt, ...)
 static const char *conf_filename;
 static int conf_lineno, conf_warnings, conf_unsaved;
 
+const char conf_def_filename[] = ".config";
+
 const char conf_defname[] = "arch/$ARCH/defconfig";
 
+const char *conf_confnames[] = {
+       ".config",
+       "/lib/modules/$UNAME_RELEASE/.config",
+       "/etc/kernel-config",
+       "/boot/config-$UNAME_RELEASE",
+       conf_defname,
+       NULL,
+};
+
 static void conf_warning(const char *fmt, ...)
 {
        va_list ap;
@@ -34,13 +44,6 @@ static void conf_warning(const char *fmt, ...)
        conf_warnings++;
 }
 
-const char *conf_get_configname(void)
-{
-       char *name = getenv("KCONFIG_CONFIG");
-
-       return name ? name : ".config";
-}
-
 static char *conf_expand_value(const char *in)
 {
        struct symbol *sym;
@@ -83,65 +86,51 @@ char *conf_get_default_confname(void)
        return name;
 }
 
-int conf_read_simple(const char *name, int def)
+int conf_read_simple(const char *name)
 {
        FILE *in = NULL;
        char line[1024];
        char *p, *p2;
        struct symbol *sym;
-       int i, def_flags;
+       int i;
 
        if (name) {
                in = zconf_fopen(name);
        } else {
-               struct property *prop;
-
-               name = conf_get_configname();
-               in = zconf_fopen(name);
-               if (in)
-                       goto load;
-               sym_change_count++;
-               if (!sym_defconfig_list)
-                       return 1;
-
-               for_all_defaults(sym_defconfig_list, prop) {
-                       if (expr_calc_value(prop->visible.expr) == no ||
-                           prop->expr->type != E_SYMBOL)
-                               continue;
-                       name = conf_expand_value(prop->expr->left.sym->name);
+               const char **names = conf_confnames;
+               while ((name = *names++)) {
+                       name = conf_expand_value(name);
                        in = zconf_fopen(name);
                        if (in) {
                                printf(_("#\n"
-                                        "# using defaults found in %s\n"
-                                        "#\n"), name);
-                               goto load;
+                                        "# using defaults found in %s\n"
+                                        "#\n"), name);
+                               break;
                        }
                }
        }
        if (!in)
                return 1;
 
-load:
        conf_filename = name;
        conf_lineno = 0;
        conf_warnings = 0;
        conf_unsaved = 0;
 
-       def_flags = SYMBOL_DEF << def;
        for_all_symbols(i, sym) {
-               sym->flags |= SYMBOL_CHANGED;
-               sym->flags &= ~(def_flags|SYMBOL_VALID);
+               sym->flags |= SYMBOL_NEW | SYMBOL_CHANGED;
                if (sym_is_choice(sym))
-                       sym->flags |= def_flags;
+                       sym->flags &= ~SYMBOL_NEW;
+               sym->flags &= ~SYMBOL_VALID;
                switch (sym->type) {
                case S_INT:
                case S_HEX:
                case S_STRING:
-                       if (sym->def[def].val)
-                               free(sym->def[def].val);
+                       if (sym->user.val)
+                               free(sym->user.val);
                default:
-                       sym->def[def].val = NULL;
-                       sym->def[def].tri = no;
+                       sym->user.val = NULL;
+                       sym->user.tri = no;
                }
        }
 
@@ -158,25 +147,19 @@ load:
                        *p++ = 0;
                        if (strncmp(p, "is not set", 10))
                                continue;
-                       if (def == S_DEF_USER) {
-                               sym = sym_find(line + 9);
-                               if (!sym) {
-                                       conf_warning("trying to assign nonexistent symbol %s", line + 9);
-                                       break;
-                               }
-                       } else {
-                               sym = sym_lookup(line + 9, 0);
-                               if (sym->type == S_UNKNOWN)
-                                       sym->type = S_BOOLEAN;
-                       }
-                       if (sym->flags & def_flags) {
+                       sym = sym_find(line + 9);
+                       if (!sym) {
+                               conf_warning("trying to assign nonexistent symbol %s", line + 9);
+                               break;
+                       } else if (!(sym->flags & SYMBOL_NEW)) {
                                conf_warning("trying to reassign symbol %s", sym->name);
+                               break;
                        }
                        switch (sym->type) {
                        case S_BOOLEAN:
                        case S_TRISTATE:
-                               sym->def[def].tri = no;
-                               sym->flags |= def_flags;
+                               sym->user.tri = no;
+                               sym->flags &= ~SYMBOL_NEW;
                                break;
                        default:
                                ;
@@ -194,47 +177,34 @@ load:
                        p2 = strchr(p, '\n');
                        if (p2)
                                *p2 = 0;
-                       if (def == S_DEF_USER) {
-                               sym = sym_find(line + 7);
-                               if (!sym) {
-                                       conf_warning("trying to assign nonexistent symbol %s", line + 7);
-                                       break;
-                               }
-                       } else {
-                               sym = sym_lookup(line + 7, 0);
-                               if (sym->type == S_UNKNOWN)
-                                       sym->type = S_OTHER;
-                       }
-                       if (sym->flags & def_flags) {
+                       sym = sym_find(line + 7);
+                       if (!sym) {
+                               conf_warning("trying to assign nonexistent symbol %s", line + 7);
+                               break;
+                       } else if (!(sym->flags & SYMBOL_NEW)) {
                                conf_warning("trying to reassign symbol %s", sym->name);
+                               break;
                        }
                        switch (sym->type) {
                        case S_TRISTATE:
                                if (p[0] == 'm') {
-                                       sym->def[def].tri = mod;
-                                       sym->flags |= def_flags;
+                                       sym->user.tri = mod;
+                                       sym->flags &= ~SYMBOL_NEW;
                                        break;
                                }
                        case S_BOOLEAN:
                                if (p[0] == 'y') {
-                                       sym->def[def].tri = yes;
-                                       sym->flags |= def_flags;
+                                       sym->user.tri = yes;
+                                       sym->flags &= ~SYMBOL_NEW;
                                        break;
                                }
                                if (p[0] == 'n') {
-                                       sym->def[def].tri = no;
-                                       sym->flags |= def_flags;
+                                       sym->user.tri = no;
+                                       sym->flags &= ~SYMBOL_NEW;
                                        break;
                                }
                                conf_warning("symbol value '%s' invalid for %s", p, sym->name);
                                break;
-                       case S_OTHER:
-                               if (*p != '"') {
-                                       for (p2 = p; *p2 && !isspace(*p2); p2++)
-                                               ;
-                                       sym->type = S_STRING;
-                                       goto done;
-                               }
                        case S_STRING:
                                if (*p++ != '"')
                                        break;
@@ -251,10 +221,9 @@ load:
                                }
                        case S_INT:
                        case S_HEX:
-                       done:
                                if (sym_string_valid(sym, p)) {
-                                       sym->def[def].val = strdup(p);
-                                       sym->flags |= def_flags;
+                                       sym->user.val = strdup(p);
+                                       sym->flags &= ~SYMBOL_NEW;
                                } else {
                                        conf_warning("symbol value '%s' invalid for %s", p, sym->name);
                                        continue;
@@ -272,24 +241,24 @@ load:
                }
                if (sym && sym_is_choice_value(sym)) {
                        struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
-                       switch (sym->def[def].tri) {
+                       switch (sym->user.tri) {
                        case no:
                                break;
                        case mod:
-                               if (cs->def[def].tri == yes) {
+                               if (cs->user.tri == yes) {
                                        conf_warning("%s creates inconsistent choice state", sym->name);
-                                       cs->flags &= ~def_flags;
+                                       cs->flags |= SYMBOL_NEW;
                                }
                                break;
                        case yes:
-                               if (cs->def[def].tri != no) {
+                               if (cs->user.tri != no) {
                                        conf_warning("%s creates inconsistent choice state", sym->name);
-                                       cs->flags &= ~def_flags;
+                                       cs->flags |= SYMBOL_NEW;
                                } else
-                                       cs->def[def].val = sym;
+                                       cs->user.val = sym;
                                break;
                        }
-                       cs->def[def].tri = E_OR(cs->def[def].tri, sym->def[def].tri);
+                       cs->user.tri = E_OR(cs->user.tri, sym->user.tri);
                }
        }
        fclose(in);
@@ -304,11 +273,9 @@ int conf_read(const char *name)
        struct symbol *sym;
        struct property *prop;
        struct expr *e;
-       int i, flags;
-
-       sym_change_count = 0;
+       int i;
 
-       if (conf_read_simple(name, S_DEF_USER))
+       if (conf_read_simple(name))
                return 1;
 
        for_all_symbols(i, sym) {
@@ -320,12 +287,12 @@ int conf_read(const char *name)
                        switch (sym->type) {
                        case S_BOOLEAN:
                        case S_TRISTATE:
-                               if (sym->def[S_DEF_USER].tri != sym_get_tristate_value(sym))
+                               if (sym->user.tri != sym_get_tristate_value(sym))
                                        break;
                                if (!sym_is_choice(sym))
                                        goto sym_ok;
                        default:
-                               if (!strcmp(sym->curr.val, sym->def[S_DEF_USER].val))
+                               if (!strcmp(sym->curr.val, sym->user.val))
                                        goto sym_ok;
                                break;
                        }
@@ -337,13 +304,15 @@ int conf_read(const char *name)
        sym_ok:
                if (sym_has_value(sym) && !sym_is_choice_value(sym)) {
                        if (sym->visible == no)
-                               sym->flags &= ~SYMBOL_DEF_USER;
+                               sym->flags |= SYMBOL_NEW;
                        switch (sym->type) {
                        case S_STRING:
                        case S_INT:
                        case S_HEX:
-                               if (!sym_string_within_range(sym, sym->def[S_DEF_USER].val))
-                                       sym->flags &= ~(SYMBOL_VALID|SYMBOL_DEF_USER);
+                               if (!sym_string_within_range(sym, sym->user.val)) {
+                                       sym->flags |= SYMBOL_NEW;
+                                       sym->flags &= ~SYMBOL_VALID;
+                               }
                        default:
                                break;
                        }
@@ -351,21 +320,19 @@ int conf_read(const char *name)
                if (!sym_is_choice(sym))
                        continue;
                prop = sym_get_choice_prop(sym);
-               flags = sym->flags;
                for (e = prop->expr; e; e = e->left.expr)
                        if (e->right.sym->visible != no)
-                               flags &= e->right.sym->flags;
-               sym->flags &= flags | ~SYMBOL_DEF_USER;
+                               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;
+       FILE *out, *out_h;
        struct symbol *sym;
        struct menu *menu;
        const char *basename;
@@ -384,7 +351,7 @@ int conf_write(const char *name)
                if (!stat(name, &st) && S_ISDIR(st.st_mode)) {
                        strcpy(dirname, name);
                        strcat(dirname, "/");
-                       basename = conf_get_configname();
+                       basename = conf_def_filename;
                } else if ((slash = strrchr(name, '/'))) {
                        int size = slash - name + 1;
                        memcpy(dirname, name, size);
@@ -392,24 +359,22 @@ int conf_write(const char *name)
                        if (slash[1])
                                basename = slash + 1;
                        else
-                               basename = conf_get_configname();
+                               basename = conf_def_filename;
                } else
                        basename = name;
        } else
-               basename = conf_get_configname();
+               basename = conf_def_filename;
 
-       sprintf(newname, "%s%s", dirname, basename);
-       env = getenv("KCONFIG_OVERWRITECONFIG");
-       if (!env || !*env) {
-               sprintf(tmpname, "%s.tmpconfig.%d", dirname, (int)getpid());
-               out = fopen(tmpname, "w");
-       } else {
-               *tmpname = 0;
-               out = fopen(newname, "w");
-       }
+       sprintf(newname, "%s.tmpconfig.%d", dirname, (int)getpid());
+       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("KERNELVERSION", 0);
        sym_calc_value(sym);
        time(&now);
@@ -425,6 +390,16 @@ 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();
@@ -440,6 +415,11 @@ 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))
@@ -457,39 +437,59 @@ 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);
-                               while (1) {
+                               if (out_h)
+                                       fprintf(out_h, "#define CONFIG_%s \"", sym->name);
+                               do {
                                        l = strcspn(str, "\"\\");
                                        if (l) {
                                                fwrite(str, l, 1, out);
-                                               str += l;
+                                               if (out_h)
+                                                       fwrite(str, l, 1, out_h);
                                        }
-                                       if (!*str)
-                                               break;
-                                       fprintf(out, "\\%c", *str++);
-                               }
+                                       str += l;
+                                       while (*str == '\\' || *str == '"') {
+                                               fprintf(out, "\\%c", *str);
+                                               if (out_h)
+                                                       fprintf(out_h, "\\%c", *str);
+                                               str++;
+                                       }
+                               } while (*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,253 +509,22 @@ int conf_write(const char *name)
                }
        }
        fclose(out);
-
-       if (*tmpname) {
-               strcat(dirname, name ? name : conf_get_configname());
-               strcat(dirname, ".old");
-               rename(newname, dirname);
-               if (rename(tmpname, newname))
-                       return 1;
+       if (out_h) {
+               fclose(out_h);
+               rename(".tmpconfig.h", "include/linux/autoconf.h");
+               file_write_dep(NULL);
        }
-
-       printf(_("#\n"
-                "# configuration written to %s\n"
-                "#\n"), newname);
-
-       sym_change_count = 0;
-
-       return 0;
-}
-
-int conf_split_config(void)
-{
-       char *name, path[128];
-       char *s, *d, c;
-       struct symbol *sym;
-       struct stat sb;
-       int res, i, fd;
-
-       name = getenv("KCONFIG_AUTOCONFIG");
-       if (!name)
-               name = "include/config/auto.conf";
-       conf_read_simple(name, S_DEF_AUTO);
-
-       if (chdir("include/config"))
-               return 1;
-
-       res = 0;
-       for_all_symbols(i, sym) {
-               sym_calc_value(sym);
-               if ((sym->flags & SYMBOL_AUTO) || !sym->name)
-                       continue;
-               if (sym->flags & SYMBOL_WRITE) {
-                       if (sym->flags & SYMBOL_DEF_AUTO) {
-                               /*
-                                * symbol has old and new value,
-                                * so compare them...
-                                */
-                               switch (sym->type) {
-                               case S_BOOLEAN:
-                               case S_TRISTATE:
-                                       if (sym_get_tristate_value(sym) ==
-                                           sym->def[S_DEF_AUTO].tri)
-                                               continue;
-                                       break;
-                               case S_STRING:
-                               case S_HEX:
-                               case S_INT:
-                                       if (!strcmp(sym_get_string_value(sym),
-                                                   sym->def[S_DEF_AUTO].val))
-                                               continue;
-                                       break;
-                               default:
-                                       break;
-                               }
-                       } else {
-                               /*
-                                * If there is no old value, only 'no' (unset)
-                                * is allowed as new value.
-                                */
-                               switch (sym->type) {
-                               case S_BOOLEAN:
-                               case S_TRISTATE:
-                                       if (sym_get_tristate_value(sym) == no)
-                                               continue;
-                                       break;
-                               default:
-                                       break;
-                               }
-                       }
-               } else if (!(sym->flags & SYMBOL_DEF_AUTO))
-                       /* There is neither an old nor a new value. */
-                       continue;
-               /* else
-                *      There is an old value, but no new value ('no' (unset)
-                *      isn't saved in auto.conf, so the old value is always
-                *      different from 'no').
-                */
-
-               /* Replace all '_' and append ".h" */
-               s = sym->name;
-               d = path;
-               while ((c = *s++)) {
-                       c = tolower(c);
-                       *d++ = (c == '_') ? '/' : c;
-               }
-               strcpy(d, ".h");
-
-               /* Assume directory path already exists. */
-               fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
-               if (fd == -1) {
-                       if (errno != ENOENT) {
-                               res = 1;
-                               break;
-                       }
-                       /*
-                        * Create directory components,
-                        * unless they exist already.
-                        */
-                       d = path;
-                       while ((d = strchr(d, '/'))) {
-                               *d = 0;
-                               if (stat(path, &sb) && mkdir(path, 0755)) {
-                                       res = 1;
-                                       goto out;
-                               }
-                               *d++ = '/';
-                       }
-                       /* Try it again. */
-                       fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
-                       if (fd == -1) {
-                               res = 1;
-                               break;
-                       }
-               }
-               close(fd);
+       if (!name || basename != conf_def_filename) {
+               if (!name)
+                       name = conf_def_filename;
+               sprintf(tmpname, "%s.old", name);
+               rename(name, tmpname);
        }
-out:
-       if (chdir("../.."))
-               return 1;
-
-       return res;
-}
-
-int conf_write_autoconf(void)
-{
-       struct symbol *sym;
-       const char *str;
-       char *name;
-       FILE *out, *out_h;
-       time_t now;
-       int i, l;
-
-       sym_clear_all_valid();
-
-       file_write_dep("include/config/auto.conf.cmd");
-
-       if (conf_split_config())
-               return 1;
-
-       out = fopen(".tmpconfig", "w");
-       if (!out)
-               return 1;
-
-       out_h = fopen(".tmpconfig.h", "w");
-       if (!out_h) {
-               fclose(out);
+       sprintf(tmpname, "%s%s", dirname, basename);
+       if (rename(newname, tmpname))
                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));
 
-       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;
+       sym_change_count = 0;
 
        return 0;
 }