]> nv-tegra.nvidia Code Review - linux-3.10.git/blobdiff - scripts/kconfig/confdata.c
kconfig: use xfwrite wrapper function to silence warnings
[linux-3.10.git] / scripts / kconfig / confdata.c
index c07060ab7820c572876a7d0005247d0a8dc87a8f..7c7a5a6cc3f504bd759dc01019536b2bf804fbbd 100644 (file)
@@ -7,13 +7,13 @@
 #include <ctype.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <stdarg.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <time.h>
 #include <unistd.h>
 
-#define LKC_DIRECT_LINK
 #include "lkc.h"
 
 static void conf_warning(const char *fmt, ...)
@@ -128,6 +128,7 @@ static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
                        sym->flags |= def_flags;
                        break;
                }
+               /* fall through */
        case S_BOOLEAN:
                if (p[0] == 'y') {
                        sym->def[def].tri = yes;
@@ -140,7 +141,7 @@ static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
                        break;
                }
                conf_warning("symbol value '%s' invalid for %s", p, sym->name);
-               break;
+               return 1;
        case S_OTHER:
                if (*p != '"') {
                        for (p2 = p; *p2 && !isspace(*p2); p2++)
@@ -148,6 +149,7 @@ static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
                        sym->type = S_STRING;
                        goto done;
                }
+               /* fall through */
        case S_STRING:
                if (*p++ != '"')
                        break;
@@ -162,6 +164,7 @@ static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
                        conf_warning("invalid string found");
                        return 1;
                }
+               /* fall through */
        case S_INT:
        case S_HEX:
        done:
@@ -237,6 +240,7 @@ load:
                case S_STRING:
                        if (sym->def[def].val)
                                free(sym->def[def].val);
+                       /* fall through */
                default:
                        sym->def[def].val = NULL;
                        sym->def[def].tri = no;
@@ -246,24 +250,23 @@ load:
        while (fgets(line, sizeof(line), in)) {
                conf_lineno++;
                sym = NULL;
-               switch (line[0]) {
-               case '#':
-                       if (memcmp(line + 2, "CONFIG_", 7))
+               if (line[0] == '#') {
+                       if (memcmp(line + 2, CONFIG_, strlen(CONFIG_)))
                                continue;
-                       p = strchr(line + 9, ' ');
+                       p = strchr(line + 2 + strlen(CONFIG_), ' ');
                        if (!p)
                                continue;
                        *p++ = 0;
                        if (strncmp(p, "is not set", 10))
                                continue;
                        if (def == S_DEF_USER) {
-                               sym = sym_find(line + 9);
+                               sym = sym_find(line + 2 + strlen(CONFIG_));
                                if (!sym) {
                                        sym_add_change_count(1);
-                                       break;
+                                       goto setsym;
                                }
                        } else {
-                               sym = sym_lookup(line + 9, 0);
+                               sym = sym_lookup(line + 2 + strlen(CONFIG_), 0);
                                if (sym->type == S_UNKNOWN)
                                        sym->type = S_BOOLEAN;
                        }
@@ -279,13 +282,8 @@ load:
                        default:
                                ;
                        }
-                       break;
-               case 'C':
-                       if (memcmp(line, "CONFIG_", 7)) {
-                               conf_warning("unexpected data");
-                               continue;
-                       }
-                       p = strchr(line + 7, '=');
+               } else if (memcmp(line, CONFIG_, strlen(CONFIG_)) == 0) {
+                       p = strchr(line + strlen(CONFIG_), '=');
                        if (!p)
                                continue;
                        *p++ = 0;
@@ -296,13 +294,13 @@ load:
                                        *p2 = 0;
                        }
                        if (def == S_DEF_USER) {
-                               sym = sym_find(line + 7);
+                               sym = sym_find(line + strlen(CONFIG_));
                                if (!sym) {
                                        sym_add_change_count(1);
-                                       break;
+                                       goto setsym;
                                }
                        } else {
-                               sym = sym_lookup(line + 7, 0);
+                               sym = sym_lookup(line + strlen(CONFIG_), 0);
                                if (sym->type == S_UNKNOWN)
                                        sym->type = S_OTHER;
                        }
@@ -311,14 +309,12 @@ load:
                        }
                        if (conf_set_sym_val(sym, def, def_flags, p))
                                continue;
-                       break;
-               case '\r':
-               case '\n':
-                       break;
-               default:
-                       conf_warning("unexpected data");
+               } else {
+                       if (line[0] != '\r' && line[0] != '\n')
+                               conf_warning("unexpected data");
                        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) {
@@ -371,6 +367,7 @@ int conf_read(const char *name)
                                        break;
                                if (!sym_is_choice(sym))
                                        goto sym_ok;
+                               /* fall through */
                        default:
                                if (!strcmp(sym->curr.val, sym->def[S_DEF_USER].val))
                                        goto sym_ok;
@@ -425,64 +422,220 @@ int conf_read(const char *name)
        return 0;
 }
 
-/* Write a S_STRING */
-static void conf_write_string(bool headerfile, const char *name,
-                              const char *str, FILE *out)
+/*
+ * Kconfig configuration printer
+ *
+ * This printer is used when generating the resulting configuration after
+ * kconfig invocation and `defconfig' files. Unset symbol might be omitted by
+ * passing a non-NULL argument to the printer.
+ *
+ */
+static void
+kconfig_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg)
+{
+
+       switch (sym->type) {
+       case S_BOOLEAN:
+       case S_TRISTATE:
+               if (*value == 'n') {
+                       bool skip_unset = (arg != NULL);
+
+                       if (!skip_unset)
+                               fprintf(fp, "# %s%s is not set\n",
+                                   CONFIG_, sym->name);
+                       return;
+               }
+               break;
+       default:
+               break;
+       }
+
+       fprintf(fp, "%s%s=%s\n", CONFIG_, sym->name, value);
+}
+
+static void
+kconfig_print_comment(FILE *fp, const char *value, void *arg)
 {
-       int l;
-       if (headerfile)
-               fprintf(out, "#define CONFIG_%s \"", name);
-       else
-               fprintf(out, "CONFIG_%s=\"", name);
-
-       while (1) {
-               l = strcspn(str, "\"\\");
+       const char *p = value;
+       size_t l;
+
+       for (;;) {
+               l = strcspn(p, "\n");
+               fprintf(fp, "#");
                if (l) {
-                       xfwrite(str, l, 1, out);
-                       str += l;
+                       fprintf(fp, " ");
+                       xfwrite(p, l, 1, fp);
+                       p += l;
                }
-               if (!*str)
+               fprintf(fp, "\n");
+               if (*p++ == '\0')
                        break;
-               fprintf(out, "\\%c", *str++);
        }
-       fputs("\"\n", out);
 }
 
-static void conf_write_symbol(struct symbol *sym, enum symbol_type type,
-                              FILE *out, bool write_no)
+static struct conf_printer kconfig_printer_cb =
 {
-       const char *str;
+       .print_symbol = kconfig_print_symbol,
+       .print_comment = kconfig_print_comment,
+};
 
-       switch (type) {
+/*
+ * Header printer
+ *
+ * This printer is used when generating the `include/generated/autoconf.h' file.
+ */
+static void
+header_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg)
+{
+
+       switch (sym->type) {
        case S_BOOLEAN:
-       case S_TRISTATE:
-               switch (sym_get_tristate_value(sym)) {
-               case no:
-                       if (write_no)
-                               fprintf(out, "# CONFIG_%s is not set\n", sym->name);
-                       break;
-               case mod:
-                       fprintf(out, "CONFIG_%s=m\n", sym->name);
-                       break;
-               case yes:
-                       fprintf(out, "CONFIG_%s=y\n", sym->name);
+       case S_TRISTATE: {
+               const char *suffix = "";
+
+               switch (*value) {
+               case 'n':
                        break;
+               case 'm':
+                       suffix = "_MODULE";
+                       /* fall through */
+               default:
+                       fprintf(fp, "#define %s%s%s 1\n",
+                           CONFIG_, sym->name, suffix);
                }
                break;
-       case S_STRING:
-               conf_write_string(false, sym->name, sym_get_string_value(sym), out);
+       }
+       case S_HEX: {
+               const char *prefix = "";
+
+               if (value[0] != '0' || (value[1] != 'x' && value[1] != 'X'))
+                       prefix = "0x";
+               fprintf(fp, "#define %s%s %s%s\n",
+                   CONFIG_, sym->name, prefix, value);
                break;
-       case S_HEX:
+       }
+       case S_STRING:
        case S_INT:
-               str = sym_get_string_value(sym);
-               fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
+               fprintf(fp, "#define %s%s %s\n",
+                   CONFIG_, sym->name, value);
+               break;
+       default:
                break;
+       }
+
+}
+
+static void
+header_print_comment(FILE *fp, const char *value, void *arg)
+{
+       const char *p = value;
+       size_t l;
+
+       fprintf(fp, "/*\n");
+       for (;;) {
+               l = strcspn(p, "\n");
+               fprintf(fp, " *");
+               if (l) {
+                       fprintf(fp, " ");
+                       xfwrite(p, l, 1, fp);
+                       p += l;
+               }
+               fprintf(fp, "\n");
+               if (*p++ == '\0')
+                       break;
+       }
+       fprintf(fp, " */\n");
+}
+
+static struct conf_printer header_printer_cb =
+{
+       .print_symbol = header_print_symbol,
+       .print_comment = header_print_comment,
+};
+
+/*
+ * Generate the __enabled_CONFIG_* and __enabled_CONFIG_*_MODULE macros for
+ * use by the IS_{ENABLED,BUILTIN,MODULE} macros. The _MODULE variant is
+ * generated even for booleans so that the IS_ENABLED() macro works.
+ */
+static void
+header_print__enabled_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg)
+{
+
+       switch (sym->type) {
+       case S_BOOLEAN:
+       case S_TRISTATE: {
+               fprintf(fp, "#define __enabled_" CONFIG_ "%s %d\n",
+                   sym->name, (*value == 'y'));
+               fprintf(fp, "#define __enabled_" CONFIG_ "%s_MODULE %d\n",
+                   sym->name, (*value == 'm'));
+               break;
+       }
+       default:
+               break;
+       }
+}
+
+static struct conf_printer header__enabled_printer_cb =
+{
+       .print_symbol = header_print__enabled_symbol,
+       .print_comment = header_print_comment,
+};
+
+/*
+ * Tristate printer
+ *
+ * This printer is used when generating the `include/config/tristate.conf' file.
+ */
+static void
+tristate_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg)
+{
+
+       if (sym->type == S_TRISTATE && *value != 'n')
+               fprintf(fp, "%s%s=%c\n", CONFIG_, sym->name, (char)toupper(*value));
+}
+
+static struct conf_printer tristate_printer_cb =
+{
+       .print_symbol = tristate_print_symbol,
+       .print_comment = kconfig_print_comment,
+};
+
+static void conf_write_symbol(FILE *fp, struct symbol *sym,
+                             struct conf_printer *printer, void *printer_arg)
+{
+       const char *str;
+
+       switch (sym->type) {
        case S_OTHER:
        case S_UNKNOWN:
                break;
+       case S_STRING:
+               str = sym_get_string_value(sym);
+               str = sym_escape_string_value(str);
+               printer->print_symbol(fp, sym, str, printer_arg);
+               free((void *)str);
+               break;
+       default:
+               str = sym_get_string_value(sym);
+               printer->print_symbol(fp, sym, str, printer_arg);
        }
 }
 
+static void
+conf_write_heading(FILE *fp, struct conf_printer *printer, void *printer_arg)
+{
+       char buf[256];
+
+       snprintf(buf, sizeof(buf),
+           "\n"
+           "Automatically generated file; DO NOT EDIT.\n"
+           "%s\n",
+           rootmenu.prompt->text);
+
+       printer->print_comment(fp, buf, printer_arg);
+}
+
 /*
  * Write out a minimal config.
  * All values that has default values are skipped as this is redundant.
@@ -539,7 +692,7 @@ int conf_write_defconfig(const char *filename)
                                                goto next_menu;
                                }
                        }
-                       conf_write_symbol(sym, sym->type, out, true);
+                       conf_write_symbol(out, sym, &kconfig_printer_cb, NULL);
                }
 next_menu:
                if (menu->list != NULL) {
@@ -567,10 +720,7 @@ int conf_write(const char *name)
        struct menu *menu;
        const char *basename;
        const char *str;
-       char dirname[128], tmpname[128], newname[128];
-       enum symbol_type type;
-       time_t now;
-       int use_timestamp = 1;
+       char dirname[PATH_MAX+1], tmpname[PATH_MAX+1], newname[PATH_MAX+1];
        char *env;
 
        dirname[0] = 0;
@@ -607,21 +757,7 @@ int conf_write(const char *name)
        if (!out)
                return 1;
 
-       sym = sym_lookup("KERNELVERSION", 0);
-       sym_calc_value(sym);
-       time(&now);
-       env = getenv("KCONFIG_NOTIMESTAMP");
-       if (env && *env)
-               use_timestamp = 0;
-
-       fprintf(out, _("#\n"
-                      "# Automatically generated make config: don't edit\n"
-                      "# Linux kernel version: %s\n"
-                      "%s%s"
-                      "#\n"),
-                    sym_get_string_value(sym),
-                    use_timestamp ? "# " : "",
-                    use_timestamp ? ctime(&now) : "");
+       conf_write_heading(out, &kconfig_printer_cb, NULL);
 
        if (!conf_get_changed())
                sym_clear_all_valid();
@@ -642,14 +778,8 @@ int conf_write(const char *name)
                        if (!(sym->flags & SYMBOL_WRITE))
                                goto next;
                        sym->flags &= ~SYMBOL_WRITE;
-                       type = sym->type;
-                       if (type == S_TRISTATE) {
-                               sym_calc_value(modules_sym);
-                               if (modules_sym->curr.tri == no)
-                                       type = S_BOOLEAN;
-                       }
-                       /* Write config symbol to file */
-                       conf_write_symbol(sym, type, out, true);
+
+                       conf_write_symbol(out, sym, &kconfig_printer_cb, NULL);
                }
 
 next:
@@ -686,7 +816,7 @@ next:
 static int conf_split_config(void)
 {
        const char *name;
-       char path[128];
+       char path[PATH_MAX+1];
        char *s, *d, c;
        struct symbol *sym;
        struct stat sb;
@@ -798,10 +928,8 @@ out:
 int conf_write_autoconf(void)
 {
        struct symbol *sym;
-       const char *str;
        const char *name;
        FILE *out, *tristate, *out_h;
-       time_t now;
        int i;
 
        sym_clear_all_valid();
@@ -828,69 +956,28 @@ int conf_write_autoconf(void)
                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(tristate, "#\n"
-                         "# Automatically generated - do not edit\n"
-                         "\n");
-       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));
+       conf_write_heading(out, &kconfig_printer_cb, NULL);
+
+       conf_write_heading(tristate, &tristate_printer_cb, NULL);
+
+       conf_write_heading(out_h, &header_printer_cb, NULL);
 
        for_all_symbols(i, sym) {
+               if (!sym->name)
+                       continue;
+
                sym_calc_value(sym);
-               if (!(sym->flags & SYMBOL_WRITE) || !sym->name)
+
+               conf_write_symbol(out_h, sym, &header__enabled_printer_cb, NULL);
+
+               if (!(sym->flags & SYMBOL_WRITE))
                        continue;
 
-               /* write symbol to config file */
-               conf_write_symbol(sym, sym->type, out, false);
+               conf_write_symbol(out, sym, &kconfig_printer_cb, (void *)1);
 
-               /* update autoconf and tristate files */
-               switch (sym->type) {
-               case S_BOOLEAN:
-               case S_TRISTATE:
-                       switch (sym_get_tristate_value(sym)) {
-                       case no:
-                               break;
-                       case mod:
-                               fprintf(tristate, "CONFIG_%s=M\n", sym->name);
-                               fprintf(out_h, "#define CONFIG_%s_MODULE 1\n", sym->name);
-                               break;
-                       case yes:
-                               if (sym->type == S_TRISTATE)
-                                       fprintf(tristate, "CONFIG_%s=Y\n",
-                                                       sym->name);
-                               fprintf(out_h, "#define CONFIG_%s 1\n", sym->name);
-                               break;
-                       }
-                       break;
-               case S_STRING:
-                       conf_write_string(true, sym->name, sym_get_string_value(sym), out_h);
-                       break;
-               case S_HEX:
-                       str = sym_get_string_value(sym);
-                       if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) {
-                               fprintf(out_h, "#define CONFIG_%s 0x%s\n", sym->name, str);
-                               break;
-                       }
-               case S_INT:
-                       str = sym_get_string_value(sym);
-                       fprintf(out_h, "#define CONFIG_%s %s\n", sym->name, str);
-                       break;
-               default:
-                       break;
-               }
+               conf_write_symbol(tristate, sym, &tristate_printer_cb, (void *)1);
+
+               conf_write_symbol(out_h, sym, &header_printer_cb, NULL);
        }
        fclose(out);
        fclose(tristate);
@@ -952,7 +1039,7 @@ static void randomize_choice_values(struct symbol *csym)
        int cnt, def;
 
        /*
-        * If choice is mod then we may have more items slected
+        * If choice is mod then we may have more items selected
         * and if no then no-one.
         * In both cases stop.
         */
@@ -1048,10 +1135,10 @@ void conf_set_all_new_symbols(enum conf_def_mode mode)
 
        /*
         * We have different type of choice blocks.
-        * If curr.tri equal to mod then we can select several
+        * If curr.tri equals to mod then we can select several
         * choice symbols in one block.
         * In this case we do nothing.
-        * If curr.tri equal yes then only one symbol can be
+        * If curr.tri equals yes then only one symbol can be
         * selected in a choice block and we set it to yes,
         * and the rest to no.
         */