1.1 --- a/kconfig/confdata.c Wed Mar 04 18:54:37 2009 +0000
1.2 +++ b/kconfig/confdata.c Sun May 08 14:57:09 2011 +0200
1.3 @@ -5,6 +5,7 @@
1.4
1.5 #include <sys/stat.h>
1.6 #include <ctype.h>
1.7 +#include <errno.h>
1.8 #include <fcntl.h>
1.9 #include <stdio.h>
1.10 #include <stdlib.h>
1.11 @@ -18,6 +19,9 @@
1.12 static void conf_warning(const char *fmt, ...)
1.13 __attribute__ ((format (printf, 1, 2)));
1.14
1.15 +static void conf_message(const char *fmt, ...)
1.16 + __attribute__ ((format (printf, 1, 2)));
1.17 +
1.18 static const char *conf_filename;
1.19 static int conf_lineno, conf_warnings, conf_unsaved;
1.20
1.21 @@ -34,6 +38,29 @@
1.22 conf_warnings++;
1.23 }
1.24
1.25 +static void conf_default_message_callback(const char *fmt, va_list ap)
1.26 +{
1.27 + printf("#\n# ");
1.28 + vprintf(fmt, ap);
1.29 + printf("\n#\n");
1.30 +}
1.31 +
1.32 +static void (*conf_message_callback) (const char *fmt, va_list ap) =
1.33 + conf_default_message_callback;
1.34 +void conf_set_message_callback(void (*fn) (const char *fmt, va_list ap))
1.35 +{
1.36 + conf_message_callback = fn;
1.37 +}
1.38 +
1.39 +static void conf_message(const char *fmt, ...)
1.40 +{
1.41 + va_list ap;
1.42 +
1.43 + va_start(ap, fmt);
1.44 + if (conf_message_callback)
1.45 + conf_message_callback(fmt, ap);
1.46 +}
1.47 +
1.48 const char *conf_get_configname(void)
1.49 {
1.50 char *name = getenv("KCONFIG_CONFIG");
1.51 @@ -41,6 +68,13 @@
1.52 return name ? name : ".config";
1.53 }
1.54
1.55 +const char *conf_get_autoconfig_name(void)
1.56 +{
1.57 + char *name = getenv("KCONFIG_AUTOCONFIG");
1.58 +
1.59 + return name ? name : "include/config/auto.conf";
1.60 +}
1.61 +
1.62 static char *conf_expand_value(const char *in)
1.63 {
1.64 struct symbol *sym;
1.65 @@ -163,8 +197,11 @@
1.66 if (in)
1.67 goto load;
1.68 sym_add_change_count(1);
1.69 - if (!sym_defconfig_list)
1.70 + if (!sym_defconfig_list) {
1.71 + if (modules_sym)
1.72 + sym_calc_value(modules_sym);
1.73 return 1;
1.74 + }
1.75
1.76 for_all_defaults(sym_defconfig_list, prop) {
1.77 if (expr_calc_value(prop->visible.expr) == no ||
1.78 @@ -173,9 +210,8 @@
1.79 name = conf_expand_value(prop->expr->left.sym->name);
1.80 in = zconf_fopen(name);
1.81 if (in) {
1.82 - printf(_("#\n"
1.83 - "# using defaults found in %s\n"
1.84 - "#\n"), name);
1.85 + conf_message(_("using defaults found in %s"),
1.86 + name);
1.87 goto load;
1.88 }
1.89 }
1.90 @@ -210,24 +246,23 @@
1.91 while (fgets(line, sizeof(line), in)) {
1.92 conf_lineno++;
1.93 sym = NULL;
1.94 - switch (line[0]) {
1.95 - case '#':
1.96 - if (memcmp(line + 2, "CT_", 3))
1.97 + if (line[0] == '#') {
1.98 + if (memcmp(line + 2, CONFIG_, strlen(CONFIG_)))
1.99 continue;
1.100 - p = strchr(line + 5, ' ');
1.101 + p = strchr(line + 2 + strlen(CONFIG_), ' ');
1.102 if (!p)
1.103 continue;
1.104 *p++ = 0;
1.105 if (strncmp(p, "is not set", 10))
1.106 continue;
1.107 if (def == S_DEF_USER) {
1.108 - sym = sym_find(line + 5);
1.109 + sym = sym_find(line + 2 + strlen(CONFIG_));
1.110 if (!sym) {
1.111 sym_add_change_count(1);
1.112 - break;
1.113 + goto setsym;
1.114 }
1.115 } else {
1.116 - sym = sym_lookup(line + 5, 0);
1.117 + sym = sym_lookup(line + 2 + strlen(CONFIG_), 0);
1.118 if (sym->type == S_UNKNOWN)
1.119 sym->type = S_BOOLEAN;
1.120 }
1.121 @@ -243,13 +278,8 @@
1.122 default:
1.123 ;
1.124 }
1.125 - break;
1.126 - case 'C':
1.127 - if (memcmp(line, "CT_", 3)) {
1.128 - conf_warning("unexpected data");
1.129 - continue;
1.130 - }
1.131 - p = strchr(line + 3, '=');
1.132 + } else if (memcmp(line, CONFIG_, strlen(CONFIG_)) == 0) {
1.133 + p = strchr(line + strlen(CONFIG_), '=');
1.134 if (!p)
1.135 continue;
1.136 *p++ = 0;
1.137 @@ -260,13 +290,13 @@
1.138 *p2 = 0;
1.139 }
1.140 if (def == S_DEF_USER) {
1.141 - sym = sym_find(line + 3);
1.142 + sym = sym_find(line + strlen(CONFIG_));
1.143 if (!sym) {
1.144 sym_add_change_count(1);
1.145 - break;
1.146 + goto setsym;
1.147 }
1.148 } else {
1.149 - sym = sym_lookup(line + 3, 0);
1.150 + sym = sym_lookup(line + strlen(CONFIG_), 0);
1.151 if (sym->type == S_UNKNOWN)
1.152 sym->type = S_OTHER;
1.153 }
1.154 @@ -275,14 +305,12 @@
1.155 }
1.156 if (conf_set_sym_val(sym, def, def_flags, p))
1.157 continue;
1.158 - break;
1.159 - case '\r':
1.160 - case '\n':
1.161 - break;
1.162 - default:
1.163 - conf_warning("unexpected data");
1.164 + } else {
1.165 + if (line[0] != '\r' && line[0] != '\n')
1.166 + conf_warning("unexpected data");
1.167 continue;
1.168 }
1.169 +setsym:
1.170 if (sym && sym_is_choice_value(sym)) {
1.171 struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
1.172 switch (sym->def[def].tri) {
1.173 @@ -389,15 +417,149 @@
1.174 return 0;
1.175 }
1.176
1.177 +/* Write a S_STRING */
1.178 +static void conf_write_string(bool headerfile, const char *name,
1.179 + const char *str, FILE *out)
1.180 +{
1.181 + int l;
1.182 + if (headerfile)
1.183 + fprintf(out, "#define %s%s \"", CONFIG_, name);
1.184 + else
1.185 + fprintf(out, "%s%s=\"", CONFIG_, name);
1.186 +
1.187 + while (1) {
1.188 + l = strcspn(str, "\"\\");
1.189 + if (l) {
1.190 + xfwrite(str, l, 1, out);
1.191 + str += l;
1.192 + }
1.193 + if (!*str)
1.194 + break;
1.195 + fprintf(out, "\\%c", *str++);
1.196 + }
1.197 + fputs("\"\n", out);
1.198 +}
1.199 +
1.200 +static void conf_write_symbol(struct symbol *sym, FILE *out, bool write_no)
1.201 +{
1.202 + const char *str;
1.203 +
1.204 + switch (sym->type) {
1.205 + case S_BOOLEAN:
1.206 + case S_TRISTATE:
1.207 + switch (sym_get_tristate_value(sym)) {
1.208 + case no:
1.209 + if (write_no)
1.210 + fprintf(out, "# %s%s is not set\n",
1.211 + CONFIG_, sym->name);
1.212 + break;
1.213 + case mod:
1.214 + fprintf(out, "%s%s=m\n", CONFIG_, sym->name);
1.215 + break;
1.216 + case yes:
1.217 + fprintf(out, "%s%s=y\n", CONFIG_, sym->name);
1.218 + break;
1.219 + }
1.220 + break;
1.221 + case S_STRING:
1.222 + conf_write_string(false, sym->name, sym_get_string_value(sym), out);
1.223 + break;
1.224 + case S_HEX:
1.225 + case S_INT:
1.226 + str = sym_get_string_value(sym);
1.227 + fprintf(out, "%s%s=%s\n", CONFIG_, sym->name, str);
1.228 + break;
1.229 + case S_OTHER:
1.230 + case S_UNKNOWN:
1.231 + break;
1.232 + }
1.233 +}
1.234 +
1.235 +/*
1.236 + * Write out a minimal config.
1.237 + * All values that has default values are skipped as this is redundant.
1.238 + */
1.239 +int conf_write_defconfig(const char *filename)
1.240 +{
1.241 + struct symbol *sym;
1.242 + struct menu *menu;
1.243 + FILE *out;
1.244 +
1.245 + out = fopen(filename, "w");
1.246 + if (!out)
1.247 + return 1;
1.248 +
1.249 + sym_clear_all_valid();
1.250 +
1.251 + /* Traverse all menus to find all relevant symbols */
1.252 + menu = rootmenu.list;
1.253 +
1.254 + while (menu != NULL)
1.255 + {
1.256 + sym = menu->sym;
1.257 + if (sym == NULL) {
1.258 + if (!menu_is_visible(menu))
1.259 + goto next_menu;
1.260 + } else if (!sym_is_choice(sym)) {
1.261 + sym_calc_value(sym);
1.262 + if (!(sym->flags & SYMBOL_WRITE))
1.263 + goto next_menu;
1.264 + sym->flags &= ~SYMBOL_WRITE;
1.265 + /* If we cannot change the symbol - skip */
1.266 + if (!sym_is_changable(sym))
1.267 + goto next_menu;
1.268 + /* If symbol equals to default value - skip */
1.269 + if (strcmp(sym_get_string_value(sym), sym_get_string_default(sym)) == 0)
1.270 + goto next_menu;
1.271 +
1.272 + /*
1.273 + * If symbol is a choice value and equals to the
1.274 + * default for a choice - skip.
1.275 + * But only if value is bool and equal to "y" and
1.276 + * choice is not "optional".
1.277 + * (If choice is "optional" then all values can be "n")
1.278 + */
1.279 + if (sym_is_choice_value(sym)) {
1.280 + struct symbol *cs;
1.281 + struct symbol *ds;
1.282 +
1.283 + cs = prop_get_symbol(sym_get_choice_prop(sym));
1.284 + ds = sym_choice_default(cs);
1.285 + if (!sym_is_optional(cs) && sym == ds) {
1.286 + if ((sym->type == S_BOOLEAN) &&
1.287 + sym_get_tristate_value(sym) == yes)
1.288 + goto next_menu;
1.289 + }
1.290 + }
1.291 + conf_write_symbol(sym, out, true);
1.292 + }
1.293 +next_menu:
1.294 + if (menu->list != NULL) {
1.295 + menu = menu->list;
1.296 + }
1.297 + else if (menu->next != NULL) {
1.298 + menu = menu->next;
1.299 + } else {
1.300 + while ((menu = menu->parent)) {
1.301 + if (menu->next != NULL) {
1.302 + menu = menu->next;
1.303 + break;
1.304 + }
1.305 + }
1.306 + }
1.307 + }
1.308 + fclose(out);
1.309 + return 0;
1.310 +}
1.311 +
1.312 int conf_write(const char *name)
1.313 {
1.314 FILE *out;
1.315 struct symbol *sym;
1.316 struct menu *menu;
1.317 const char *basename;
1.318 - char dirname[128], tmpname[128], newname[128];
1.319 - int type, l;
1.320 const char *str;
1.321 + char dirname[PATH_MAX+1], tmpname[PATH_MAX+1], newname[PATH_MAX+1];
1.322 time_t now;
1.323 int use_timestamp = 1;
1.324 char *env;
1.325 @@ -436,8 +598,6 @@
1.326 if (!out)
1.327 return 1;
1.328
1.329 - sym = sym_lookup("PROJECTVERSION", 0);
1.330 - sym_calc_value(sym);
1.331 time(&now);
1.332 env = getenv("KCONFIG_NOTIMESTAMP");
1.333 if (env && *env)
1.334 @@ -445,10 +605,10 @@
1.335
1.336 fprintf(out, _("#\n"
1.337 "# Automatically generated make config: don't edit\n"
1.338 - "# " PACKAGE " version: %s\n"
1.339 + "# %s\n"
1.340 "%s%s"
1.341 "#\n"),
1.342 - sym_get_string_value(sym),
1.343 + rootmenu.prompt->text,
1.344 use_timestamp ? "# " : "",
1.345 use_timestamp ? ctime(&now) : "");
1.346
1.347 @@ -471,56 +631,11 @@
1.348 if (!(sym->flags & SYMBOL_WRITE))
1.349 goto next;
1.350 sym->flags &= ~SYMBOL_WRITE;
1.351 - type = sym->type;
1.352 - if (type == S_TRISTATE) {
1.353 - sym_calc_value(modules_sym);
1.354 - if (modules_sym->curr.tri == no)
1.355 - type = S_BOOLEAN;
1.356 - }
1.357 - switch (type) {
1.358 - case S_BOOLEAN:
1.359 - case S_TRISTATE:
1.360 - switch (sym_get_tristate_value(sym)) {
1.361 - case no:
1.362 - fprintf(out, "# CT_%s is not set\n", sym->name);
1.363 - break;
1.364 - case mod:
1.365 - fprintf(out, "CT_%s=m\n", sym->name);
1.366 - break;
1.367 - case yes:
1.368 - fprintf(out, "CT_%s=y\n", sym->name);
1.369 - break;
1.370 - }
1.371 - break;
1.372 - case S_STRING:
1.373 - str = sym_get_string_value(sym);
1.374 - fprintf(out, "CT_%s=\"", sym->name);
1.375 - while (1) {
1.376 - l = strcspn(str, "\"\\");
1.377 - if (l) {
1.378 - fwrite(str, l, 1, out);
1.379 - str += l;
1.380 - }
1.381 - if (!*str)
1.382 - break;
1.383 - fprintf(out, "\\%c", *str++);
1.384 - }
1.385 - fputs("\"\n", out);
1.386 - break;
1.387 - case S_HEX:
1.388 - str = sym_get_string_value(sym);
1.389 - if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) {
1.390 - fprintf(out, "CT_%s=%s\n", sym->name, str);
1.391 - break;
1.392 - }
1.393 - case S_INT:
1.394 - str = sym_get_string_value(sym);
1.395 - fprintf(out, "CT_%s=%s\n", sym->name, str);
1.396 - break;
1.397 - }
1.398 + /* Write config symbol to file */
1.399 + conf_write_symbol(sym, out, true);
1.400 }
1.401
1.402 - next:
1.403 +next:
1.404 if (menu->list) {
1.405 menu = menu->list;
1.406 continue;
1.407 @@ -544,22 +659,23 @@
1.408 return 1;
1.409 }
1.410
1.411 + conf_message(_("configuration written to %s"), newname);
1.412 +
1.413 sym_set_change_count(0);
1.414
1.415 return 0;
1.416 }
1.417
1.418 -int conf_split_config(void)
1.419 +static int conf_split_config(void)
1.420 {
1.421 - char *name, path[128];
1.422 + const char *name;
1.423 + char path[PATH_MAX+1];
1.424 char *s, *d, c;
1.425 struct symbol *sym;
1.426 struct stat sb;
1.427 int res, i, fd;
1.428
1.429 - name = getenv("KCONFIG_AUTOCONFIG");
1.430 - if (!name)
1.431 - name = "include/config/auto.conf";
1.432 + name = conf_get_autoconfig_name();
1.433 conf_read_simple(name, S_DEF_AUTO);
1.434
1.435 if (chdir("include/config"))
1.436 @@ -666,10 +782,9 @@
1.437 {
1.438 struct symbol *sym;
1.439 const char *str;
1.440 - char *name;
1.441 - FILE *out, *out_h;
1.442 - time_t now;
1.443 - int i, l;
1.444 + const char *name;
1.445 + FILE *out, *tristate, *out_h;
1.446 + int i;
1.447
1.448 sym_clear_all_valid();
1.449
1.450 @@ -682,33 +797,42 @@
1.451 if (!out)
1.452 return 1;
1.453
1.454 - out_h = fopen(".tmpconfig.h", "w");
1.455 - if (!out_h) {
1.456 + tristate = fopen(".tmpconfig_tristate", "w");
1.457 + if (!tristate) {
1.458 fclose(out);
1.459 return 1;
1.460 }
1.461
1.462 - sym = sym_lookup("PROJECTVERSION", 0);
1.463 - sym_calc_value(sym);
1.464 - time(&now);
1.465 + out_h = fopen(".tmpconfig.h", "w");
1.466 + if (!out_h) {
1.467 + fclose(out);
1.468 + fclose(tristate);
1.469 + return 1;
1.470 + }
1.471 +
1.472 fprintf(out, "#\n"
1.473 "# Automatically generated make config: don't edit\n"
1.474 - "# " PACKAGE " version: %s\n"
1.475 - "# %s"
1.476 + "# %s\n"
1.477 "#\n",
1.478 - sym_get_string_value(sym), ctime(&now));
1.479 + rootmenu.prompt->text);
1.480 + fprintf(tristate, "#\n"
1.481 + "# Automatically generated - do not edit\n"
1.482 + "\n");
1.483 fprintf(out_h, "/*\n"
1.484 " * Automatically generated C config: don't edit\n"
1.485 - " * " PACKAGE " version: %s\n"
1.486 - " * %s"
1.487 - " */\n"
1.488 - "#define AUTOCONF_INCLUDED\n",
1.489 - sym_get_string_value(sym), ctime(&now));
1.490 + " * %s\n"
1.491 + " */\n",
1.492 + rootmenu.prompt->text);
1.493
1.494 for_all_symbols(i, sym) {
1.495 sym_calc_value(sym);
1.496 if (!(sym->flags & SYMBOL_WRITE) || !sym->name)
1.497 continue;
1.498 +
1.499 + /* write symbol to config file */
1.500 + conf_write_symbol(sym, out, false);
1.501 +
1.502 + /* update autoconf and tristate files */
1.503 switch (sym->type) {
1.504 case S_BOOLEAN:
1.505 case S_TRISTATE:
1.506 @@ -716,62 +840,54 @@
1.507 case no:
1.508 break;
1.509 case mod:
1.510 - fprintf(out, "CT_%s=m\n", sym->name);
1.511 - fprintf(out_h, "#define CT_%s_MODULE 1\n", sym->name);
1.512 + fprintf(tristate, "%s%s=M\n",
1.513 + CONFIG_, sym->name);
1.514 + fprintf(out_h, "#define %s%s_MODULE 1\n",
1.515 + CONFIG_, sym->name);
1.516 break;
1.517 case yes:
1.518 - fprintf(out, "CT_%s=y\n", sym->name);
1.519 - fprintf(out_h, "#define CT_%s 1\n", sym->name);
1.520 + if (sym->type == S_TRISTATE)
1.521 + fprintf(tristate,"%s%s=Y\n",
1.522 + CONFIG_, sym->name);
1.523 + fprintf(out_h, "#define %s%s 1\n",
1.524 + CONFIG_, sym->name);
1.525 break;
1.526 }
1.527 break;
1.528 case S_STRING:
1.529 - str = sym_get_string_value(sym);
1.530 - fprintf(out, "CT_%s=\"", sym->name);
1.531 - fprintf(out_h, "#define CT_%s \"", sym->name);
1.532 - while (1) {
1.533 - l = strcspn(str, "\"\\");
1.534 - if (l) {
1.535 - fwrite(str, l, 1, out);
1.536 - fwrite(str, l, 1, out_h);
1.537 - str += l;
1.538 - }
1.539 - if (!*str)
1.540 - break;
1.541 - fprintf(out, "\\%c", *str);
1.542 - fprintf(out_h, "\\%c", *str);
1.543 - str++;
1.544 - }
1.545 - fputs("\"\n", out);
1.546 - fputs("\"\n", out_h);
1.547 + conf_write_string(true, sym->name, sym_get_string_value(sym), out_h);
1.548 break;
1.549 case S_HEX:
1.550 str = sym_get_string_value(sym);
1.551 if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) {
1.552 - fprintf(out, "CT_%s=%s\n", sym->name, str);
1.553 - fprintf(out_h, "#define CT_%s 0x%s\n", sym->name, str);
1.554 + fprintf(out_h, "#define %s%s 0x%s\n",
1.555 + CONFIG_, sym->name, str);
1.556 break;
1.557 }
1.558 case S_INT:
1.559 str = sym_get_string_value(sym);
1.560 - fprintf(out, "CT_%s=%s\n", sym->name, str);
1.561 - fprintf(out_h, "#define CT_%s %s\n", sym->name, str);
1.562 + fprintf(out_h, "#define %s%s %s\n",
1.563 + CONFIG_, sym->name, str);
1.564 break;
1.565 default:
1.566 break;
1.567 }
1.568 }
1.569 fclose(out);
1.570 + fclose(tristate);
1.571 fclose(out_h);
1.572
1.573 name = getenv("KCONFIG_AUTOHEADER");
1.574 if (!name)
1.575 - name = "include/linux/autoconf.h";
1.576 + name = "include/generated/autoconf.h";
1.577 if (rename(".tmpconfig.h", name))
1.578 return 1;
1.579 - name = getenv("KCONFIG_AUTOCONFIG");
1.580 + name = getenv("KCONFIG_TRISTATE");
1.581 if (!name)
1.582 - name = "include/config/auto.conf";
1.583 + name = "include/config/tristate.conf";
1.584 + if (rename(".tmpconfig_tristate", name))
1.585 + return 1;
1.586 + name = conf_get_autoconfig_name();
1.587 /*
1.588 * This must be the last step, kbuild has a dependency on auto.conf
1.589 * and this marks the successful completion of the previous steps.
1.590 @@ -809,13 +925,73 @@
1.591 conf_changed_callback = fn;
1.592 }
1.593
1.594 +static void randomize_choice_values(struct symbol *csym)
1.595 +{
1.596 + struct property *prop;
1.597 + struct symbol *sym;
1.598 + struct expr *e;
1.599 + int cnt, def;
1.600 +
1.601 + /*
1.602 + * If choice is mod then we may have more items selected
1.603 + * and if no then no-one.
1.604 + * In both cases stop.
1.605 + */
1.606 + if (csym->curr.tri != yes)
1.607 + return;
1.608 +
1.609 + prop = sym_get_choice_prop(csym);
1.610 +
1.611 + /* count entries in choice block */
1.612 + cnt = 0;
1.613 + expr_list_for_each_sym(prop->expr, e, sym)
1.614 + cnt++;
1.615 +
1.616 + /*
1.617 + * find a random value and set it to yes,
1.618 + * set the rest to no so we have only one set
1.619 + */
1.620 + def = (rand() % cnt);
1.621 +
1.622 + cnt = 0;
1.623 + expr_list_for_each_sym(prop->expr, e, sym) {
1.624 + if (def == cnt++) {
1.625 + sym->def[S_DEF_USER].tri = yes;
1.626 + csym->def[S_DEF_USER].val = sym;
1.627 + }
1.628 + else {
1.629 + sym->def[S_DEF_USER].tri = no;
1.630 + }
1.631 + }
1.632 + csym->flags |= SYMBOL_DEF_USER;
1.633 + /* clear VALID to get value calculated */
1.634 + csym->flags &= ~(SYMBOL_VALID);
1.635 +}
1.636 +
1.637 +static void set_all_choice_values(struct symbol *csym)
1.638 +{
1.639 + struct property *prop;
1.640 + struct symbol *sym;
1.641 + struct expr *e;
1.642 +
1.643 + prop = sym_get_choice_prop(csym);
1.644 +
1.645 + /*
1.646 + * Set all non-assinged choice values to no
1.647 + */
1.648 + expr_list_for_each_sym(prop->expr, e, sym) {
1.649 + if (!sym_has_value(sym))
1.650 + sym->def[S_DEF_USER].tri = no;
1.651 + }
1.652 + csym->flags |= SYMBOL_DEF_USER;
1.653 + /* clear VALID to get value calculated */
1.654 + csym->flags &= ~(SYMBOL_VALID);
1.655 +}
1.656
1.657 void conf_set_all_new_symbols(enum conf_def_mode mode)
1.658 {
1.659 struct symbol *sym, *csym;
1.660 - struct property *prop;
1.661 - struct expr *e;
1.662 - int i, cnt, def;
1.663 + int i, cnt;
1.664
1.665 for_all_symbols(i, sym) {
1.666 if (sym_has_value(sym))
1.667 @@ -834,12 +1010,13 @@
1.668 sym->def[S_DEF_USER].tri = no;
1.669 break;
1.670 case def_random:
1.671 - sym->def[S_DEF_USER].tri = (tristate)(rand() % 3);
1.672 + cnt = sym_get_type(sym) == S_TRISTATE ? 3 : 2;
1.673 + sym->def[S_DEF_USER].tri = (tristate)(rand() % cnt);
1.674 break;
1.675 default:
1.676 continue;
1.677 }
1.678 - if (!sym_is_choice(sym) || mode != def_random)
1.679 + if (!(sym_is_choice(sym) && mode == def_random))
1.680 sym->flags |= SYMBOL_DEF_USER;
1.681 break;
1.682 default:
1.683 @@ -850,30 +1027,23 @@
1.684
1.685 sym_clear_all_valid();
1.686
1.687 - if (mode != def_random)
1.688 - return;
1.689 -
1.690 + /*
1.691 + * We have different type of choice blocks.
1.692 + * If curr.tri equals to mod then we can select several
1.693 + * choice symbols in one block.
1.694 + * In this case we do nothing.
1.695 + * If curr.tri equals yes then only one symbol can be
1.696 + * selected in a choice block and we set it to yes,
1.697 + * and the rest to no.
1.698 + */
1.699 for_all_symbols(i, csym) {
1.700 if (sym_has_value(csym) || !sym_is_choice(csym))
1.701 continue;
1.702
1.703 sym_calc_value(csym);
1.704 - prop = sym_get_choice_prop(csym);
1.705 - def = -1;
1.706 - while (1) {
1.707 - cnt = 0;
1.708 - expr_list_for_each_sym(prop->expr, e, sym) {
1.709 - if (sym->visible == no)
1.710 - continue;
1.711 - if (def == cnt++) {
1.712 - csym->def[S_DEF_USER].val = sym;
1.713 - break;
1.714 - }
1.715 - }
1.716 - if (def >= 0 || cnt < 2)
1.717 - break;
1.718 - def = (rand() % cnt) + 1;
1.719 - }
1.720 - csym->flags |= SYMBOL_DEF_USER;
1.721 + if (mode == def_random)
1.722 + randomize_choice_values(csym);
1.723 + else
1.724 + set_all_choice_values(csym);
1.725 }
1.726 }