kconfig: Fix defconfig when one choice menu selects options that another choice menu...
[carl9170fw.git] / config / confdata.c
index 089b7177ddb69c3500097eaa4e109a3978fbba94..bd7a229f15ab26f9008fa83b14bb51346eaa17f0 100644 (file)
@@ -1146,7 +1146,7 @@ static void randomize_choice_values(struct symbol *csym)
        csym->flags &= ~(SYMBOL_VALID);
 }
 
-static void set_all_choice_values(struct symbol *csym)
+void set_all_choice_values(struct symbol *csym)
 {
        struct property *prop;
        struct symbol *sym;
@@ -1163,13 +1163,57 @@ 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)
 {
        struct symbol *sym, *csym;
-       int i, cnt;
+       int i, cnt, pby, pty, ptm;      /* pby: probability of boolean  = 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 );
+               }
+       }
 
        for_all_symbols(i, sym) {
                if (sym_has_value(sym) || (sym->flags & SYMBOL_VALID))
@@ -1188,8 +1232,15 @@ void conf_set_all_new_symbols(enum conf_def_mode mode)
                                sym->def[S_DEF_USER].tri = no;
                                break;
                        case def_random:
-                               cnt = sym->type == 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;
@@ -1214,6 +1265,14 @@ 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;
@@ -1221,7 +1280,5 @@ void conf_set_all_new_symbols(enum conf_def_mode mode)
                sym_calc_value(csym);
                if (mode == def_random)
                        randomize_choice_values(csym);
-               else
-                       set_all_choice_values(csym);
        }
 }