kconfig: drop localization support
[carl9170fw.git] / config / confdata.c
index c9939fa622e5c0dd15fa6bde786bfcd385034169..94c5efa68912772b3b4ccade24c4c4073382978c 100644 (file)
 
 #include "lkc.h"
 
+struct conf_printer {
+       void (*print_symbol)(FILE *, struct symbol *, const char *, void *);
+       void (*print_comment)(FILE *, const char *, void *);
+};
+
 static void conf_warning(const char *fmt, ...)
        __attribute__ ((format (printf, 1, 2)));
 
@@ -23,7 +28,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";
 
@@ -59,6 +64,7 @@ static void conf_message(const char *fmt, ...)
        va_start(ap, fmt);
        if (conf_message_callback)
                conf_message_callback(fmt, ap);
+       va_end(ap);
 }
 
 const char *conf_get_configname(void)
@@ -140,7 +146,9 @@ static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
                        sym->flags |= def_flags;
                        break;
                }
-               conf_warning("symbol value '%s' invalid for %s", p, sym->name);
+               if (def != S_DEF_AUTO)
+                       conf_warning("symbol value '%s' invalid for %s",
+                                    p, sym->name);
                return 1;
        case S_OTHER:
                if (*p != '"') {
@@ -161,7 +169,8 @@ static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
                        memmove(p2, p2 + 1, strlen(p2));
                }
                if (!p2) {
-                       conf_warning("invalid string found");
+                       if (def != S_DEF_AUTO)
+                               conf_warning("invalid string found");
                        return 1;
                }
                /* fall through */
@@ -169,10 +178,12 @@ 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 {
-                       conf_warning("symbol value '%s' invalid for %s", p, sym->name);
+                       if (def != S_DEF_AUTO)
+                               conf_warning("symbol value '%s' invalid for %s",
+                                            p, sym->name);
                        return 1;
                }
                break;
@@ -182,10 +193,66 @@ static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
        return 0;
 }
 
+#define LINE_GROWTH 16
+static int add_byte(int c, char **lineptr, size_t slen, size_t *n)
+{
+       char *nline;
+       size_t new_size = slen + 1;
+       if (new_size > *n) {
+               new_size += LINE_GROWTH - 1;
+               new_size *= 2;
+               nline = xrealloc(*lineptr, new_size);
+               if (!nline)
+                       return -1;
+
+               *lineptr = nline;
+               *n = new_size;
+       }
+
+       (*lineptr)[slen] = c;
+
+       return 0;
+}
+
+static ssize_t compat_getline(char **lineptr, size_t *n, FILE *stream)
+{
+       char *line = *lineptr;
+       size_t slen = 0;
+
+       for (;;) {
+               int c = getc(stream);
+
+               switch (c) {
+               case '\n':
+                       if (add_byte(c, &line, slen, n) < 0)
+                               goto e_out;
+                       slen++;
+                       /* fall through */
+               case EOF:
+                       if (add_byte('\0', &line, slen, n) < 0)
+                               goto e_out;
+                       *lineptr = line;
+                       if (slen == 0)
+                               return -1;
+                       return slen;
+               default:
+                       if (add_byte(c, &line, slen, n) < 0)
+                               goto e_out;
+                       slen++;
+               }
+       }
+
+e_out:
+       line[slen-1] = '\0';
+       *lineptr = line;
+       return -1;
+}
+
 int conf_read_simple(const char *name, int def)
 {
        FILE *in = NULL;
-       char line[1024];
+       char   *line = NULL;
+       size_t  line_asize = 0;
        char *p, *p2;
        struct symbol *sym;
        int i, def_flags;
@@ -200,11 +267,8 @@ 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 ||
@@ -213,7 +277,7 @@ int conf_read_simple(const char *name, int def)
                        name = conf_expand_value(prop->expr->left.sym->name);
                        in = zconf_fopen(name);
                        if (in) {
-                               conf_message(_("using defaults found in %s"),
+                               conf_message("using defaults found in %s",
                                         name);
                                goto load;
                        }
@@ -226,7 +290,6 @@ load:
        conf_filename = name;
        conf_lineno = 0;
        conf_warnings = 0;
-       conf_unsaved = 0;
 
        def_flags = SYMBOL_DEF << def;
        for_all_symbols(i, sym) {
@@ -247,7 +310,7 @@ load:
                }
        }
 
-       while (fgets(line, sizeof(line), in)) {
+       while (compat_getline(&line, &line_asize, in) != -1) {
                conf_lineno++;
                sym = NULL;
                if (line[0] == '#') {
@@ -311,7 +374,9 @@ 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:
@@ -335,29 +400,30 @@ setsym:
                        cs->def[def].tri = EXPR_OR(cs->def[def].tri, sym->def[def].tri);
                }
        }
+       free(line);
        fclose(in);
-
-       if (modules_sym)
-               sym_calc_value(modules_sym);
        return 0;
 }
 
 int conf_read(const char *name)
 {
-       struct symbol *sym, *choice_sym;
-       struct property *prop;
-       struct expr *e;
-       int i, flags;
+       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))
-                       goto sym_ok;
+                       continue;
                if (sym_has_value(sym) && (sym->flags & SYMBOL_WRITE)) {
                        /* check that calculated value agrees with saved value */
                        switch (sym->type) {
@@ -366,30 +432,18 @@ int conf_read(const char *name)
                                if (sym->def[S_DEF_USER].tri != sym_get_tristate_value(sym))
                                        break;
                                if (!sym_is_choice(sym))
-                                       goto sym_ok;
+                                       continue;
                                /* fall through */
                        default:
                                if (!strcmp(sym->curr.val, sym->def[S_DEF_USER].val))
-                                       goto sym_ok;
+                                       continue;
                                break;
                        }
                } else if (!sym_has_value(sym) && !(sym->flags & SYMBOL_WRITE))
                        /* no previous value and not saved */
-                       goto sym_ok;
+                       continue;
                conf_unsaved++;
                /* maybe print value in verbose mode... */
-       sym_ok:
-               if (!sym_is_choice(sym))
-                       continue;
-               /* The choice symbol only has a set value (and thus is not new)
-                * if all its visible childs have values.
-                */
-               prop = sym_get_choice_prop(sym);
-               flags = sym->flags;
-               expr_list_for_each_sym(prop->expr, e, choice_sym)
-                       if (choice_sym->visible != no)
-                               flags &= choice_sym->flags;
-               sym->flags &= flags | ~SYMBOL_DEF_USER;
        }
 
        for_all_symbols(i, sym) {
@@ -504,7 +558,7 @@ kconfig_print_comment(FILE *fp, const char *value, void *arg)
                fprintf(fp, "#");
                if (l) {
                        fprintf(fp, " ");
-                       fwrite(p, l, 1, fp);
+                       xfwrite(p, l, 1, fp);
                        p += l;
                }
                fprintf(fp, "\n");
@@ -549,17 +603,6 @@ header_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg)
                        fprintf(fp, "#define %s%s%s 1\n",
                            CONFIG_, sym->name, suffix);
                }
-               /*
-                * 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.
-                */
-               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;
        }
        case S_HEX: {
@@ -594,7 +637,7 @@ header_print_comment(FILE *fp, const char *value, void *arg)
                fprintf(fp, " *");
                if (l) {
                        fprintf(fp, " ");
-                       fwrite(p, l, 1, fp);
+                       xfwrite(p, l, 1, fp);
                        p += l;
                }
                fprintf(fp, "\n");
@@ -834,7 +877,7 @@ next:
                        return 1;
        }
 
-       conf_message(_("configuration written to %s"), newname);
+       conf_message("configuration written to %s", newname);
 
        sym_set_change_count(0);
 
@@ -852,6 +895,7 @@ static int conf_split_config(void)
 
        name = conf_get_autoconfig_name();
        conf_read_simple(name, S_DEF_AUTO);
+       sym_calc_value(modules_sym);
 
        if (chdir("include/generated"))
                return 1;
@@ -1071,7 +1115,7 @@ void conf_set_changed_callback(void (*fn)(void))
        conf_changed_callback = fn;
 }
 
-static void randomize_choice_values(struct symbol *csym)
+static bool randomize_choice_values(struct symbol *csym)
 {
        struct property *prop;
        struct symbol *sym;
@@ -1084,7 +1128,7 @@ static void randomize_choice_values(struct symbol *csym)
         * In both cases stop.
         */
        if (csym->curr.tri != yes)
-               return;
+               return false;
 
        prop = sym_get_choice_prop(csym);
 
@@ -1108,13 +1152,18 @@ static void randomize_choice_values(struct symbol *csym)
                else {
                        sym->def[S_DEF_USER].tri = no;
                }
+               sym->flags |= SYMBOL_DEF_USER;
+               /* clear VALID to get value calculated */
+               sym->flags &= ~SYMBOL_VALID;
        }
        csym->flags |= SYMBOL_DEF_USER;
        /* clear VALID to get value calculated */
        csym->flags &= ~(SYMBOL_VALID);
+
+       return true;
 }
 
-static void set_all_choice_values(struct symbol *csym)
+void set_all_choice_values(struct symbol *csym)
 {
        struct property *prop;
        struct symbol *sym;
@@ -1131,20 +1180,66 @@ static void set_all_choice_values(struct symbol *csym)
        }
        csym->flags |= SYMBOL_DEF_USER;
        /* clear VALID to get value calculated */
-       csym->flags &= ~(SYMBOL_VALID);
+       csym->flags &= ~(SYMBOL_VALID | SYMBOL_NEED_SET_CHOICE_VALUES);
 }
 
-void conf_set_all_new_symbols(enum conf_def_mode mode)
+bool conf_set_all_new_symbols(enum conf_def_mode mode)
 {
        struct symbol *sym, *csym;
-       int i, cnt;
+       int i, cnt, pby, pty, ptm;      /* pby: probability of bool     = y
+                                        * pty: probability of tristate = y
+                                        * ptm: probability of tristate = m
+                                        */
+
+       pby = 50; pty = ptm = 33; /* can't go as the default in switch-case
+                                  * below, otherwise gcc whines about
+                                  * -Wmaybe-uninitialized */
+       if (mode == def_random) {
+               int n, p[3];
+               char *env = getenv("KCONFIG_PROBABILITY");
+               n = 0;
+               while( env && *env ) {
+                       char *endp;
+                       int tmp = strtol( env, &endp, 10 );
+                       if( tmp >= 0 && tmp <= 100 ) {
+                               p[n++] = tmp;
+                       } else {
+                               errno = ERANGE;
+                               perror( "KCONFIG_PROBABILITY" );
+                               exit( 1 );
+                       }
+                       env = (*endp == ':') ? endp+1 : endp;
+                       if( n >=3 ) {
+                               break;
+                       }
+               }
+               switch( n ) {
+               case 1:
+                       pby = p[0]; ptm = pby/2; pty = pby-ptm;
+                       break;
+               case 2:
+                       pty = p[0]; ptm = p[1]; pby = pty + ptm;
+                       break;
+               case 3:
+                       pby = p[0]; pty = p[1]; ptm = p[2];
+                       break;
+               }
+
+               if( pty+ptm > 100 ) {
+                       errno = ERANGE;
+                       perror( "KCONFIG_PROBABILITY" );
+                       exit( 1 );
+               }
+       }
+       bool has_changed = false;
 
        for_all_symbols(i, sym) {
-               if (sym_has_value(sym))
+               if (sym_has_value(sym) || (sym->flags & SYMBOL_VALID))
                        continue;
                switch (sym_get_type(sym)) {
                case S_BOOLEAN:
                case S_TRISTATE:
+                       has_changed = true;
                        switch (mode) {
                        case def_yes:
                                sym->def[S_DEF_USER].tri = yes;
@@ -1153,11 +1248,21 @@ void conf_set_all_new_symbols(enum conf_def_mode mode)
                                sym->def[S_DEF_USER].tri = mod;
                                break;
                        case def_no:
-                               sym->def[S_DEF_USER].tri = no;
+                               if (sym->flags & SYMBOL_ALLNOCONFIG_Y)
+                                       sym->def[S_DEF_USER].tri = yes;
+                               else
+                                       sym->def[S_DEF_USER].tri = no;
                                break;
                        case def_random:
-                               cnt = sym_get_type(sym) == S_TRISTATE ? 3 : 2;
-                               sym->def[S_DEF_USER].tri = (tristate)(rand() % cnt);
+                               sym->def[S_DEF_USER].tri = no;
+                               cnt = rand() % 100;
+                               if (sym->type == S_TRISTATE) {
+                                       if (cnt < pty)
+                                               sym->def[S_DEF_USER].tri = yes;
+                                       else if (cnt < (pty+ptm))
+                                               sym->def[S_DEF_USER].tri = mod;
+                               } else if (cnt < pby)
+                                       sym->def[S_DEF_USER].tri = yes;
                                break;
                        default:
                                continue;
@@ -1182,14 +1287,26 @@ void conf_set_all_new_symbols(enum conf_def_mode mode)
         * selected in a choice block and we set it to yes,
         * and the rest to no.
         */
+       if (mode != def_random) {
+               for_all_symbols(i, csym) {
+                       if ((sym_is_choice(csym) && !sym_has_value(csym)) ||
+                           sym_is_choice_value(csym))
+                               csym->flags |= SYMBOL_NEED_SET_CHOICE_VALUES;
+               }
+       }
+
        for_all_symbols(i, csym) {
                if (sym_has_value(csym) || !sym_is_choice(csym))
                        continue;
 
                sym_calc_value(csym);
                if (mode == def_random)
-                       randomize_choice_values(csym);
-               else
+                       has_changed = randomize_choice_values(csym);
+               else {
                        set_all_choice_values(csym);
+                       has_changed = true;
+               }
        }
+
+       return has_changed;
 }