kconfig: remove unneeded setsym label in conf_read_simple()
[carl9170fw.git] / config / confdata.c
index 75a63725bad4e77b229ada800414f746d5dd2408..b7171503936a208af6e103d07ad54c2a8d95ce38 100644 (file)
 
 #include "lkc.h"
 
+/* return true if 'path' exists, false otherwise */
+static bool is_present(const char *path)
+{
+       struct stat st;
+
+       return !stat(path, &st);
+}
+
+/* return true if 'path' exists and it is a directory, false otherwise */
+static bool is_dir(const char *path)
+{
+       struct stat st;
+
+       if (stat(path, &st))
+               return 0;
+
+       return S_ISDIR(st.st_mode);
+}
+
+/*
+ * Create the parent directory of the given path.
+ *
+ * For example, if 'include/config/auto.conf' is given, create 'include/config'.
+ */
+static int make_parent_dir(const char *path)
+{
+       char tmp[PATH_MAX + 1];
+       char *p;
+
+       strncpy(tmp, path, sizeof(tmp));
+       tmp[sizeof(tmp) - 1] = 0;
+
+       /* Remove the base name. Just return if nothing is left */
+       p = strrchr(tmp, '/');
+       if (!p)
+               return 0;
+       *(p + 1) = 0;
+
+       /* Just in case it is an absolute path */
+       p = tmp;
+       while (*p == '/')
+               p++;
+
+       while ((p = strchr(p, '/'))) {
+               *p = 0;
+
+               /* skip if the directory exists */
+               if (!is_dir(tmp) && mkdir(tmp, 0755))
+                       return -1;
+
+               *p = '/';
+               while (*p == '/')
+                       p++;
+       }
+
+       return 0;
+}
+
 struct conf_printer {
        void (*print_symbol)(FILE *, struct symbol *, const char *, void *);
        void (*print_comment)(FILE *, const char *, void *);
@@ -28,7 +86,7 @@ static void conf_message(const char *fmt, ...)
        __attribute__ ((format (printf, 1, 2)));
 
 static const char *conf_filename;
-static int conf_lineno, conf_warnings, conf_unsaved;
+static int conf_lineno, conf_warnings;
 
 const char conf_defname[] = "include/generated/defconfig";
 
@@ -43,16 +101,16 @@ static void conf_warning(const char *fmt, ...)
        conf_warnings++;
 }
 
-static void conf_default_message_callback(const char *fmt, va_list ap)
+static void conf_default_message_callback(const char *s)
 {
        printf("#\n# ");
-       vprintf(fmt, ap);
+       printf("%s", s);
        printf("\n#\n");
 }
 
-static void (*conf_message_callback) (const char *fmt, va_list ap) =
+static void (*conf_message_callback)(const char *s) =
        conf_default_message_callback;
-void conf_set_message_callback(void (*fn) (const char *fmt, va_list ap))
+void conf_set_message_callback(void (*fn)(const char *s))
 {
        conf_message_callback = fn;
 }
@@ -60,10 +118,15 @@ void conf_set_message_callback(void (*fn) (const char *fmt, va_list ap))
 static void conf_message(const char *fmt, ...)
 {
        va_list ap;
+       char buf[4096];
+
+       if (!conf_message_callback)
+               return;
 
        va_start(ap, fmt);
-       if (conf_message_callback)
-               conf_message_callback(fmt, ap);
+
+       vsnprintf(buf, sizeof(buf), fmt, ap);
+       conf_message_callback(buf);
        va_end(ap);
 }
 
@@ -81,43 +144,16 @@ const char *conf_get_autoconfig_name(void)
        return name ? name : "include/generated/auto.conf";
 }
 
-static char *conf_expand_value(const char *in)
-{
-       struct symbol *sym;
-       const char *src;
-       static char res_value[SYMBOL_MAXLENGTH];
-       char *dst, name[SYMBOL_MAXLENGTH];
-
-       res_value[0] = 0;
-       dst = name;
-       while ((src = strchr(in, '$'))) {
-               strncat(res_value, in, src - in);
-               src++;
-               dst = name;
-               while (isalnum(*src) || *src == '_')
-                       *dst++ = *src++;
-               *dst = 0;
-               sym = sym_lookup(name, 0);
-               sym_calc_value(sym);
-               strcat(res_value, sym_get_string_value(sym));
-               in = src;
-       }
-       strcat(res_value, in);
-
-       return res_value;
-}
-
 char *conf_get_default_confname(void)
 {
-       struct stat buf;
        static char fullname[PATH_MAX+1];
        char *env, *name;
 
-       name = conf_expand_value(conf_defname);
+       name = expand_string(conf_defname);
        env = getenv(SRCTREE);
        if (env) {
                sprintf(fullname, "%s/%s", env, name);
-               if (!stat(fullname, &buf))
+               if (is_present(fullname))
                        return fullname;
        }
        return name;
@@ -178,7 +214,7 @@ static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
        case S_HEX:
        done:
                if (sym_string_valid(sym, p)) {
-                       sym->def[def].val = strdup(p);
+                       sym->def[def].val = xstrdup(p);
                        sym->flags |= def_flags;
                } else {
                        if (def != S_DEF_AUTO)
@@ -201,7 +237,7 @@ static int add_byte(int c, char **lineptr, size_t slen, size_t *n)
        if (new_size > *n) {
                new_size += LINE_GROWTH - 1;
                new_size *= 2;
-               nline = realloc(*lineptr, new_size);
+               nline = xrealloc(*lineptr, new_size);
                if (!nline)
                        return -1;
 
@@ -267,20 +303,18 @@ int conf_read_simple(const char *name, int def)
                if (in)
                        goto load;
                sym_add_change_count(1);
-               if (!sym_defconfig_list) {
-                       if (modules_sym)
-                               sym_calc_value(modules_sym);
+               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);
+                       sym_calc_value(prop->expr->left.sym);
+                       name = sym_get_string_value(prop->expr->left.sym);
                        in = zconf_fopen(name);
                        if (in) {
-                               conf_message(_("using defaults found in %s"),
+                               conf_message("using defaults found in %s",
                                         name);
                                goto load;
                        }
@@ -293,7 +327,6 @@ load:
        conf_filename = name;
        conf_lineno = 0;
        conf_warnings = 0;
-       conf_unsaved = 0;
 
        def_flags = SYMBOL_DEF << def;
        for_all_symbols(i, sym) {
@@ -330,7 +363,7 @@ load:
                                sym = sym_find(line + 2 + strlen(CONFIG_));
                                if (!sym) {
                                        sym_add_change_count(1);
-                                       goto setsym;
+                                       continue;
                                }
                        } else {
                                sym = sym_lookup(line + 2 + strlen(CONFIG_), 0);
@@ -364,7 +397,7 @@ load:
                                sym = sym_find(line + strlen(CONFIG_));
                                if (!sym) {
                                        sym_add_change_count(1);
-                                       goto setsym;
+                                       continue;
                                }
                        } else {
                                sym = sym_lookup(line + strlen(CONFIG_), 0);
@@ -378,10 +411,12 @@ load:
                                continue;
                } else {
                        if (line[0] != '\r' && line[0] != '\n')
-                               conf_warning("unexpected data");
+                               conf_warning("unexpected data: %.*s",
+                                            (int)strcspn(line, "\r\n"), line);
+
                        continue;
                }
-setsym:
+
                if (sym && sym_is_choice_value(sym)) {
                        struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
                        switch (sym->def[def].tri) {
@@ -404,25 +439,27 @@ setsym:
        }
        free(line);
        fclose(in);
-
-       if (modules_sym)
-               sym_calc_value(modules_sym);
        return 0;
 }
 
 int conf_read(const char *name)
 {
        struct symbol *sym;
+       int conf_unsaved = 0;
        int i;
 
        sym_set_change_count(0);
 
-       if (conf_read_simple(name, S_DEF_USER))
+       if (conf_read_simple(name, S_DEF_USER)) {
+               sym_calc_value(modules_sym);
                return 1;
+       }
+
+       sym_calc_value(modules_sym);
 
        for_all_symbols(i, sym) {
                sym_calc_value(sym);
-               if (sym_is_choice(sym) || (sym->flags & SYMBOL_AUTO))
+               if (sym_is_choice(sym) || (sym->flags & SYMBOL_NO_WRITE))
                        continue;
                if (sym_has_value(sym) && (sym->flags & SYMBOL_WRITE)) {
                        /* check that calculated value agrees with saved value */
@@ -791,15 +828,14 @@ int conf_write(const char *name)
        struct menu *menu;
        const char *basename;
        const char *str;
-       char dirname[PATH_MAX+1], tmpname[PATH_MAX+1], newname[PATH_MAX+1];
+       char dirname[PATH_MAX+1], tmpname[PATH_MAX+22], newname[PATH_MAX+8];
        char *env;
 
        dirname[0] = 0;
        if (name && name[0]) {
-               struct stat st;
                char *slash;
 
-               if (!stat(name, &st) && S_ISDIR(st.st_mode)) {
+               if (is_dir(name)) {
                        strcpy(dirname, name);
                        strcat(dirname, "/");
                        basename = conf_get_configname();
@@ -877,32 +913,66 @@ next:
                        return 1;
        }
 
-       conf_message(_("configuration written to %s"), newname);
+       conf_message("configuration written to %s", newname);
 
        sym_set_change_count(0);
 
        return 0;
 }
 
+/* write a dependency file as used by kbuild to track dependencies */
+static int conf_write_dep(const char *name)
+{
+       struct file *file;
+       FILE *out;
+
+       if (!name)
+               name = ".kconfig.d";
+       out = fopen("..config.tmp", "w");
+       if (!out)
+               return 1;
+       fprintf(out, "deps_config := \\\n");
+       for (file = file_list; file; file = file->next) {
+               if (file->next)
+                       fprintf(out, "\t%s \\\n", file->name);
+               else
+                       fprintf(out, "\t%s\n", file->name);
+       }
+       fprintf(out, "\n%s: \\\n"
+                    "\t$(deps_config)\n\n", conf_get_autoconfig_name());
+
+       env_write_dep(out, conf_get_autoconfig_name());
+
+       fprintf(out, "\n$(deps_config): ;\n");
+       fclose(out);
+
+       if (make_parent_dir(name))
+               return 1;
+       rename("..config.tmp", name);
+       return 0;
+}
+
 static int conf_split_config(void)
 {
        const char *name;
        char path[PATH_MAX+1];
        char *s, *d, c;
        struct symbol *sym;
-       struct stat sb;
        int res, i, fd;
 
        name = conf_get_autoconfig_name();
        conf_read_simple(name, S_DEF_AUTO);
+       sym_calc_value(modules_sym);
 
+       if (make_parent_dir("include/generated/foo.h"))
+               return 1;
        if (chdir("include/generated"))
                return 1;
 
        res = 0;
        for_all_symbols(i, sym) {
                sym_calc_value(sym);
-               if ((sym->flags & SYMBOL_AUTO) || !sym->name)
+               if ((sym->flags & SYMBOL_NO_WRITE) || !sym->name)
                        continue;
                if (sym->flags & SYMBOL_WRITE) {
                        if (sym->flags & SYMBOL_DEF_AUTO) {
@@ -967,19 +1037,12 @@ static int conf_split_config(void)
                                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++ = '/';
+
+                       if (make_parent_dir(path)) {
+                               res = 1;
+                               goto out;
                        }
+
                        /* Try it again. */
                        fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
                        if (fd == -1) {
@@ -1005,7 +1068,7 @@ int conf_write_autoconf(void)
 
        sym_clear_all_valid();
 
-       file_write_dep("include/generated/auto.conf.cmd");
+       conf_write_dep("include/generated/auto.conf.cmd");
 
        if (conf_split_config())
                return 1;
@@ -1064,19 +1127,31 @@ int conf_write_autoconf(void)
        name = getenv("KCONFIG_AUTOHEADER");
        if (!name)
                name = "include/generated/autoconf.h";
+       if (make_parent_dir(name))
+               return 1;
        if (rename(".tmpconfig.h", name))
                return 1;
+
        name = getenv("KCONFIG_TRISTATE");
        if (!name)
                name = "include/generated/tristate.conf";
+       if (make_parent_dir(name))
+               return 1;
        if (rename(".tmpconfig_tristate", name))
                return 1;
+
        name = getenv("KCONFIG_CMAKE");
        if (!name)
                name = "config.cmake";
+       if (make_parent_dir(name))
+               return 1;
        if (rename(".tmpconfig.cmake", name))
                return 1;
+
        name = conf_get_autoconfig_name();
+       if (make_parent_dir(name))
+               return 1;
+
        /*
         * This must be the last step, kbuild has a dependency on auto.conf
         * and this marks the successful completion of the previous steps.
@@ -1185,7 +1260,7 @@ void set_all_choice_values(struct symbol *csym)
 bool conf_set_all_new_symbols(enum conf_def_mode mode)
 {
        struct symbol *sym, *csym;
-       int i, cnt, pby, pty, ptm;      /* pby: probability of boolean  = y
+       int i, cnt, pby, pty, ptm;      /* pby: probability of bool     = y
                                         * pty: probability of tristate = y
                                         * ptm: probability of tristate = m
                                         */