|
|
1.1 ! root 1: /* ! 2: * Copyright (C) 2002 Roman Zippel <[email protected]> ! 3: * Released under the terms of the GNU GPL v2.0. ! 4: */ ! 5: ! 6: #include <sys/stat.h> ! 7: #include <ctype.h> ! 8: #include <errno.h> ! 9: #include <fcntl.h> ! 10: #include <stdio.h> ! 11: #include <stdlib.h> ! 12: #include <string.h> ! 13: #include <time.h> ! 14: #include <unistd.h> ! 15: ! 16: #define LKC_DIRECT_LINK ! 17: #include "lkc.h" ! 18: ! 19: static void conf_warning(const char *fmt, ...) ! 20: __attribute__ ((format (printf, 1, 2))); ! 21: ! 22: static void conf_message(const char *fmt, ...) ! 23: __attribute__ ((format (printf, 1, 2))); ! 24: ! 25: static const char *conf_filename; ! 26: static int conf_lineno, conf_warnings, conf_unsaved; ! 27: ! 28: const char conf_defname[] = "arch/$ARCH/defconfig"; ! 29: ! 30: static void conf_warning(const char *fmt, ...) ! 31: { ! 32: va_list ap; ! 33: va_start(ap, fmt); ! 34: fprintf(stderr, "%s:%d:warning: ", conf_filename, conf_lineno); ! 35: vfprintf(stderr, fmt, ap); ! 36: fprintf(stderr, "\n"); ! 37: va_end(ap); ! 38: conf_warnings++; ! 39: } ! 40: ! 41: static void conf_default_message_callback(const char *fmt, va_list ap) ! 42: { ! 43: printf("#\n# "); ! 44: vprintf(fmt, ap); ! 45: printf("\n#\n"); ! 46: } ! 47: ! 48: static void (*conf_message_callback) (const char *fmt, va_list ap) = ! 49: conf_default_message_callback; ! 50: void conf_set_message_callback(void (*fn) (const char *fmt, va_list ap)) ! 51: { ! 52: conf_message_callback = fn; ! 53: } ! 54: ! 55: static void conf_message(const char *fmt, ...) ! 56: { ! 57: va_list ap; ! 58: ! 59: va_start(ap, fmt); ! 60: if (conf_message_callback) ! 61: conf_message_callback(fmt, ap); ! 62: } ! 63: ! 64: const char *conf_get_configname(void) ! 65: { ! 66: char *name = getenv("KCONFIG_CONFIG"); ! 67: ! 68: return name ? name : ".config"; ! 69: } ! 70: ! 71: const char *conf_get_autoconfig_name(void) ! 72: { ! 73: char *name = getenv("KCONFIG_AUTOCONFIG"); ! 74: ! 75: return name ? name : "include/config/auto.conf"; ! 76: } ! 77: ! 78: static char *conf_expand_value(const char *in) ! 79: { ! 80: struct symbol *sym; ! 81: const char *src; ! 82: static char res_value[SYMBOL_MAXLENGTH]; ! 83: char *dst, name[SYMBOL_MAXLENGTH]; ! 84: ! 85: res_value[0] = 0; ! 86: dst = name; ! 87: while ((src = strchr(in, '$'))) { ! 88: strncat(res_value, in, src - in); ! 89: src++; ! 90: dst = name; ! 91: while (isalnum(*src) || *src == '_') ! 92: *dst++ = *src++; ! 93: *dst = 0; ! 94: sym = sym_lookup(name, 0); ! 95: sym_calc_value(sym); ! 96: strcat(res_value, sym_get_string_value(sym)); ! 97: in = src; ! 98: } ! 99: strcat(res_value, in); ! 100: ! 101: return res_value; ! 102: } ! 103: ! 104: char *conf_get_default_confname(void) ! 105: { ! 106: struct stat buf; ! 107: static char fullname[PATH_MAX+1]; ! 108: char *env, *name; ! 109: ! 110: name = conf_expand_value(conf_defname); ! 111: env = getenv(SRCTREE); ! 112: if (env) { ! 113: sprintf(fullname, "%s/%s", env, name); ! 114: if (!stat(fullname, &buf)) ! 115: return fullname; ! 116: } ! 117: return name; ! 118: } ! 119: ! 120: static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p) ! 121: { ! 122: char *p2; ! 123: ! 124: switch (sym->type) { ! 125: case S_TRISTATE: ! 126: if (p[0] == 'm') { ! 127: sym->def[def].tri = mod; ! 128: sym->flags |= def_flags; ! 129: break; ! 130: } ! 131: case S_BOOLEAN: ! 132: if (p[0] == 'y') { ! 133: sym->def[def].tri = yes; ! 134: sym->flags |= def_flags; ! 135: break; ! 136: } ! 137: if (p[0] == 'n') { ! 138: sym->def[def].tri = no; ! 139: sym->flags |= def_flags; ! 140: break; ! 141: } ! 142: conf_warning("symbol value '%s' invalid for %s", p, sym->name); ! 143: break; ! 144: case S_OTHER: ! 145: if (*p != '"') { ! 146: for (p2 = p; *p2 && !isspace(*p2); p2++) ! 147: ; ! 148: sym->type = S_STRING; ! 149: goto done; ! 150: } ! 151: case S_STRING: ! 152: if (*p++ != '"') ! 153: break; ! 154: for (p2 = p; (p2 = strpbrk(p2, "\"\\")); p2++) { ! 155: if (*p2 == '"') { ! 156: *p2 = 0; ! 157: break; ! 158: } ! 159: memmove(p2, p2 + 1, strlen(p2)); ! 160: } ! 161: if (!p2) { ! 162: conf_warning("invalid string found"); ! 163: return 1; ! 164: } ! 165: case S_INT: ! 166: case S_HEX: ! 167: done: ! 168: if (sym_string_valid(sym, p)) { ! 169: sym->def[def].val = strdup(p); ! 170: sym->flags |= def_flags; ! 171: } else { ! 172: conf_warning("symbol value '%s' invalid for %s", p, sym->name); ! 173: return 1; ! 174: } ! 175: break; ! 176: default: ! 177: ; ! 178: } ! 179: return 0; ! 180: } ! 181: ! 182: int conf_read_simple(const char *name, int def) ! 183: { ! 184: FILE *in = NULL; ! 185: char line[1024]; ! 186: char *p, *p2; ! 187: struct symbol *sym; ! 188: int i, def_flags; ! 189: ! 190: if (name) { ! 191: in = zconf_fopen(name); ! 192: } else { ! 193: struct property *prop; ! 194: ! 195: name = conf_get_configname(); ! 196: in = zconf_fopen(name); ! 197: if (in) ! 198: goto load; ! 199: sym_add_change_count(1); ! 200: if (!sym_defconfig_list) { ! 201: if (modules_sym) ! 202: sym_calc_value(modules_sym); ! 203: return 1; ! 204: } ! 205: ! 206: for_all_defaults(sym_defconfig_list, prop) { ! 207: if (expr_calc_value(prop->visible.expr) == no || ! 208: prop->expr->type != E_SYMBOL) ! 209: continue; ! 210: name = conf_expand_value(prop->expr->left.sym->name); ! 211: in = zconf_fopen(name); ! 212: if (in) { ! 213: conf_message(_("using defaults found in %s"), ! 214: name); ! 215: goto load; ! 216: } ! 217: } ! 218: } ! 219: if (!in) ! 220: return 1; ! 221: ! 222: load: ! 223: conf_filename = name; ! 224: conf_lineno = 0; ! 225: conf_warnings = 0; ! 226: conf_unsaved = 0; ! 227: ! 228: def_flags = SYMBOL_DEF << def; ! 229: for_all_symbols(i, sym) { ! 230: sym->flags |= SYMBOL_CHANGED; ! 231: sym->flags &= ~(def_flags|SYMBOL_VALID); ! 232: if (sym_is_choice(sym)) ! 233: sym->flags |= def_flags; ! 234: switch (sym->type) { ! 235: case S_INT: ! 236: case S_HEX: ! 237: case S_STRING: ! 238: if (sym->def[def].val) ! 239: free(sym->def[def].val); ! 240: default: ! 241: sym->def[def].val = NULL; ! 242: sym->def[def].tri = no; ! 243: } ! 244: } ! 245: ! 246: while (fgets(line, sizeof(line), in)) { ! 247: conf_lineno++; ! 248: sym = NULL; ! 249: if (line[0] == '#') { ! 250: if (memcmp(line + 2, CONFIG_, strlen(CONFIG_))) ! 251: continue; ! 252: p = strchr(line + 2 + strlen(CONFIG_), ' '); ! 253: if (!p) ! 254: continue; ! 255: *p++ = 0; ! 256: if (strncmp(p, "is not set", 10)) ! 257: continue; ! 258: if (def == S_DEF_USER) { ! 259: sym = sym_find(line + 2 + strlen(CONFIG_)); ! 260: if (!sym) { ! 261: sym_add_change_count(1); ! 262: goto setsym; ! 263: } ! 264: } else { ! 265: sym = sym_lookup(line + 2 + strlen(CONFIG_), 0); ! 266: if (sym->type == S_UNKNOWN) ! 267: sym->type = S_BOOLEAN; ! 268: } ! 269: if (sym->flags & def_flags) { ! 270: conf_warning("override: reassigning to symbol %s", sym->name); ! 271: } ! 272: switch (sym->type) { ! 273: case S_BOOLEAN: ! 274: case S_TRISTATE: ! 275: sym->def[def].tri = no; ! 276: sym->flags |= def_flags; ! 277: break; ! 278: default: ! 279: ; ! 280: } ! 281: } else if (memcmp(line, CONFIG_, strlen(CONFIG_)) == 0) { ! 282: p = strchr(line + strlen(CONFIG_), '='); ! 283: if (!p) ! 284: continue; ! 285: *p++ = 0; ! 286: p2 = strchr(p, '\n'); ! 287: if (p2) { ! 288: *p2-- = 0; ! 289: if (*p2 == '\r') ! 290: *p2 = 0; ! 291: } ! 292: if (def == S_DEF_USER) { ! 293: sym = sym_find(line + strlen(CONFIG_)); ! 294: if (!sym) { ! 295: sym_add_change_count(1); ! 296: goto setsym; ! 297: } ! 298: } else { ! 299: sym = sym_lookup(line + strlen(CONFIG_), 0); ! 300: if (sym->type == S_UNKNOWN) ! 301: sym->type = S_OTHER; ! 302: } ! 303: if (sym->flags & def_flags) { ! 304: conf_warning("override: reassigning to symbol %s", sym->name); ! 305: } ! 306: if (conf_set_sym_val(sym, def, def_flags, p)) ! 307: continue; ! 308: } else { ! 309: if (line[0] != '\r' && line[0] != '\n') ! 310: conf_warning("unexpected data"); ! 311: continue; ! 312: } ! 313: setsym: ! 314: if (sym && sym_is_choice_value(sym)) { ! 315: struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym)); ! 316: switch (sym->def[def].tri) { ! 317: case no: ! 318: break; ! 319: case mod: ! 320: if (cs->def[def].tri == yes) { ! 321: conf_warning("%s creates inconsistent choice state", sym->name); ! 322: cs->flags &= ~def_flags; ! 323: } ! 324: break; ! 325: case yes: ! 326: if (cs->def[def].tri != no) ! 327: conf_warning("override: %s changes choice state", sym->name); ! 328: cs->def[def].val = sym; ! 329: break; ! 330: } ! 331: cs->def[def].tri = EXPR_OR(cs->def[def].tri, sym->def[def].tri); ! 332: } ! 333: } ! 334: fclose(in); ! 335: ! 336: if (modules_sym) ! 337: sym_calc_value(modules_sym); ! 338: return 0; ! 339: } ! 340: ! 341: int conf_read(const char *name) ! 342: { ! 343: struct symbol *sym, *choice_sym; ! 344: struct property *prop; ! 345: struct expr *e; ! 346: int i, flags; ! 347: ! 348: sym_set_change_count(0); ! 349: ! 350: if (conf_read_simple(name, S_DEF_USER)) ! 351: return 1; ! 352: ! 353: for_all_symbols(i, sym) { ! 354: sym_calc_value(sym); ! 355: if (sym_is_choice(sym) || (sym->flags & SYMBOL_AUTO)) ! 356: goto sym_ok; ! 357: if (sym_has_value(sym) && (sym->flags & SYMBOL_WRITE)) { ! 358: /* check that calculated value agrees with saved value */ ! 359: switch (sym->type) { ! 360: case S_BOOLEAN: ! 361: case S_TRISTATE: ! 362: if (sym->def[S_DEF_USER].tri != sym_get_tristate_value(sym)) ! 363: break; ! 364: if (!sym_is_choice(sym)) ! 365: goto sym_ok; ! 366: default: ! 367: if (!strcmp(sym->curr.val, sym->def[S_DEF_USER].val)) ! 368: goto sym_ok; ! 369: break; ! 370: } ! 371: } else if (!sym_has_value(sym) && !(sym->flags & SYMBOL_WRITE)) ! 372: /* no previous value and not saved */ ! 373: goto sym_ok; ! 374: conf_unsaved++; ! 375: /* maybe print value in verbose mode... */ ! 376: sym_ok: ! 377: if (!sym_is_choice(sym)) ! 378: continue; ! 379: /* The choice symbol only has a set value (and thus is not new) ! 380: * if all its visible childs have values. ! 381: */ ! 382: prop = sym_get_choice_prop(sym); ! 383: flags = sym->flags; ! 384: expr_list_for_each_sym(prop->expr, e, choice_sym) ! 385: if (choice_sym->visible != no) ! 386: flags &= choice_sym->flags; ! 387: sym->flags &= flags | ~SYMBOL_DEF_USER; ! 388: } ! 389: ! 390: for_all_symbols(i, sym) { ! 391: if (sym_has_value(sym) && !sym_is_choice_value(sym)) { ! 392: /* Reset values of generates values, so they'll appear ! 393: * as new, if they should become visible, but that ! 394: * doesn't quite work if the Kconfig and the saved ! 395: * configuration disagree. ! 396: */ ! 397: if (sym->visible == no && !conf_unsaved) ! 398: sym->flags &= ~SYMBOL_DEF_USER; ! 399: switch (sym->type) { ! 400: case S_STRING: ! 401: case S_INT: ! 402: case S_HEX: ! 403: /* Reset a string value if it's out of range */ ! 404: if (sym_string_within_range(sym, sym->def[S_DEF_USER].val)) ! 405: break; ! 406: sym->flags &= ~(SYMBOL_VALID|SYMBOL_DEF_USER); ! 407: conf_unsaved++; ! 408: break; ! 409: default: ! 410: break; ! 411: } ! 412: } ! 413: } ! 414: ! 415: sym_add_change_count(conf_warnings || conf_unsaved); ! 416: ! 417: return 0; ! 418: } ! 419: ! 420: /* Write a S_STRING */ ! 421: static void conf_write_string(bool headerfile, const char *name, ! 422: const char *str, FILE *out) ! 423: { ! 424: int l; ! 425: if (headerfile) ! 426: fprintf(out, "#define %s%s \"", CONFIG_, name); ! 427: else ! 428: fprintf(out, "%s%s=\"", CONFIG_, name); ! 429: ! 430: while (1) { ! 431: l = strcspn(str, "\"\\"); ! 432: if (l) { ! 433: xfwrite(str, l, 1, out); ! 434: str += l; ! 435: } ! 436: if (!*str) ! 437: break; ! 438: fprintf(out, "\\%c", *str++); ! 439: } ! 440: fputs("\"\n", out); ! 441: } ! 442: ! 443: static void conf_write_symbol(struct symbol *sym, FILE *out, bool write_no) ! 444: { ! 445: const char *str; ! 446: ! 447: switch (sym->type) { ! 448: case S_BOOLEAN: ! 449: case S_TRISTATE: ! 450: switch (sym_get_tristate_value(sym)) { ! 451: case no: ! 452: if (write_no) ! 453: fprintf(out, "# %s%s is not set\n", ! 454: CONFIG_, sym->name); ! 455: break; ! 456: case mod: ! 457: fprintf(out, "%s%s=m\n", CONFIG_, sym->name); ! 458: break; ! 459: case yes: ! 460: fprintf(out, "%s%s=y\n", CONFIG_, sym->name); ! 461: break; ! 462: } ! 463: break; ! 464: case S_STRING: ! 465: conf_write_string(false, sym->name, sym_get_string_value(sym), out); ! 466: break; ! 467: case S_HEX: ! 468: case S_INT: ! 469: str = sym_get_string_value(sym); ! 470: fprintf(out, "%s%s=%s\n", CONFIG_, sym->name, str); ! 471: break; ! 472: case S_OTHER: ! 473: case S_UNKNOWN: ! 474: break; ! 475: } ! 476: } ! 477: ! 478: /* ! 479: * Write out a minimal config. ! 480: * All values that has default values are skipped as this is redundant. ! 481: */ ! 482: int conf_write_defconfig(const char *filename) ! 483: { ! 484: struct symbol *sym; ! 485: struct menu *menu; ! 486: FILE *out; ! 487: ! 488: out = fopen(filename, "w"); ! 489: if (!out) ! 490: return 1; ! 491: ! 492: sym_clear_all_valid(); ! 493: ! 494: /* Traverse all menus to find all relevant symbols */ ! 495: menu = rootmenu.list; ! 496: ! 497: while (menu != NULL) ! 498: { ! 499: sym = menu->sym; ! 500: if (sym == NULL) { ! 501: if (!menu_is_visible(menu)) ! 502: goto next_menu; ! 503: } else if (!sym_is_choice(sym)) { ! 504: sym_calc_value(sym); ! 505: if (!(sym->flags & SYMBOL_WRITE)) ! 506: goto next_menu; ! 507: sym->flags &= ~SYMBOL_WRITE; ! 508: /* If we cannot change the symbol - skip */ ! 509: if (!sym_is_changable(sym)) ! 510: goto next_menu; ! 511: /* If symbol equals to default value - skip */ ! 512: if (strcmp(sym_get_string_value(sym), sym_get_string_default(sym)) == 0) ! 513: goto next_menu; ! 514: ! 515: /* ! 516: * If symbol is a choice value and equals to the ! 517: * default for a choice - skip. ! 518: * But only if value is bool and equal to "y" and ! 519: * choice is not "optional". ! 520: * (If choice is "optional" then all values can be "n") ! 521: */ ! 522: if (sym_is_choice_value(sym)) { ! 523: struct symbol *cs; ! 524: struct symbol *ds; ! 525: ! 526: cs = prop_get_symbol(sym_get_choice_prop(sym)); ! 527: ds = sym_choice_default(cs); ! 528: if (!sym_is_optional(cs) && sym == ds) { ! 529: if ((sym->type == S_BOOLEAN) && ! 530: sym_get_tristate_value(sym) == yes) ! 531: goto next_menu; ! 532: } ! 533: } ! 534: conf_write_symbol(sym, out, true); ! 535: } ! 536: next_menu: ! 537: if (menu->list != NULL) { ! 538: menu = menu->list; ! 539: } ! 540: else if (menu->next != NULL) { ! 541: menu = menu->next; ! 542: } else { ! 543: while ((menu = menu->parent)) { ! 544: if (menu->next != NULL) { ! 545: menu = menu->next; ! 546: break; ! 547: } ! 548: } ! 549: } ! 550: } ! 551: fclose(out); ! 552: return 0; ! 553: } ! 554: ! 555: int conf_write(const char *name) ! 556: { ! 557: FILE *out; ! 558: struct symbol *sym; ! 559: struct menu *menu; ! 560: const char *basename; ! 561: const char *str; ! 562: char dirname[PATH_MAX+1], tmpname[PATH_MAX+1], newname[PATH_MAX+1]; ! 563: time_t now; ! 564: int use_timestamp = 1; ! 565: char *env; ! 566: ! 567: dirname[0] = 0; ! 568: if (name && name[0]) { ! 569: struct stat st; ! 570: char *slash; ! 571: ! 572: if (!stat(name, &st) && S_ISDIR(st.st_mode)) { ! 573: strcpy(dirname, name); ! 574: strcat(dirname, "/"); ! 575: basename = conf_get_configname(); ! 576: } else if ((slash = strrchr(name, '/'))) { ! 577: int size = slash - name + 1; ! 578: memcpy(dirname, name, size); ! 579: dirname[size] = 0; ! 580: if (slash[1]) ! 581: basename = slash + 1; ! 582: else ! 583: basename = conf_get_configname(); ! 584: } else ! 585: basename = name; ! 586: } else ! 587: basename = conf_get_configname(); ! 588: ! 589: sprintf(newname, "%s%s", dirname, basename); ! 590: env = getenv("KCONFIG_OVERWRITECONFIG"); ! 591: if (!env || !*env) { ! 592: sprintf(tmpname, "%s.tmpconfig.%d", dirname, (int)getpid()); ! 593: out = fopen(tmpname, "w"); ! 594: } else { ! 595: *tmpname = 0; ! 596: out = fopen(newname, "w"); ! 597: } ! 598: if (!out) ! 599: return 1; ! 600: ! 601: time(&now); ! 602: env = getenv("KCONFIG_NOTIMESTAMP"); ! 603: if (env && *env) ! 604: use_timestamp = 0; ! 605: ! 606: fprintf(out, _("#\n" ! 607: "# Automatically generated make config: don't edit\n" ! 608: "# %s\n" ! 609: "%s%s" ! 610: "#\n"), ! 611: rootmenu.prompt->text, ! 612: use_timestamp ? "# " : "", ! 613: use_timestamp ? ctime(&now) : ""); ! 614: ! 615: if (!conf_get_changed()) ! 616: sym_clear_all_valid(); ! 617: ! 618: menu = rootmenu.list; ! 619: while (menu) { ! 620: sym = menu->sym; ! 621: if (!sym) { ! 622: if (!menu_is_visible(menu)) ! 623: goto next; ! 624: str = menu_get_prompt(menu); ! 625: fprintf(out, "\n" ! 626: "#\n" ! 627: "# %s\n" ! 628: "#\n", str); ! 629: } else if (!(sym->flags & SYMBOL_CHOICE)) { ! 630: sym_calc_value(sym); ! 631: if (!(sym->flags & SYMBOL_WRITE)) ! 632: goto next; ! 633: sym->flags &= ~SYMBOL_WRITE; ! 634: /* Write config symbol to file */ ! 635: conf_write_symbol(sym, out, true); ! 636: } ! 637: ! 638: next: ! 639: if (menu->list) { ! 640: menu = menu->list; ! 641: continue; ! 642: } ! 643: if (menu->next) ! 644: menu = menu->next; ! 645: else while ((menu = menu->parent)) { ! 646: if (menu->next) { ! 647: menu = menu->next; ! 648: break; ! 649: } ! 650: } ! 651: } ! 652: fclose(out); ! 653: ! 654: if (*tmpname) { ! 655: strcat(dirname, basename); ! 656: strcat(dirname, ".old"); ! 657: rename(newname, dirname); ! 658: if (rename(tmpname, newname)) ! 659: return 1; ! 660: } ! 661: ! 662: conf_message(_("configuration written to %s"), newname); ! 663: ! 664: sym_set_change_count(0); ! 665: ! 666: return 0; ! 667: } ! 668: ! 669: static int conf_split_config(void) ! 670: { ! 671: const char *name; ! 672: char path[PATH_MAX+1]; ! 673: char *s, *d, c; ! 674: struct symbol *sym; ! 675: struct stat sb; ! 676: int res, i, fd; ! 677: ! 678: name = conf_get_autoconfig_name(); ! 679: conf_read_simple(name, S_DEF_AUTO); ! 680: ! 681: if (chdir("include/config")) ! 682: return 1; ! 683: ! 684: res = 0; ! 685: for_all_symbols(i, sym) { ! 686: sym_calc_value(sym); ! 687: if ((sym->flags & SYMBOL_AUTO) || !sym->name) ! 688: continue; ! 689: if (sym->flags & SYMBOL_WRITE) { ! 690: if (sym->flags & SYMBOL_DEF_AUTO) { ! 691: /* ! 692: * symbol has old and new value, ! 693: * so compare them... ! 694: */ ! 695: switch (sym->type) { ! 696: case S_BOOLEAN: ! 697: case S_TRISTATE: ! 698: if (sym_get_tristate_value(sym) == ! 699: sym->def[S_DEF_AUTO].tri) ! 700: continue; ! 701: break; ! 702: case S_STRING: ! 703: case S_HEX: ! 704: case S_INT: ! 705: if (!strcmp(sym_get_string_value(sym), ! 706: sym->def[S_DEF_AUTO].val)) ! 707: continue; ! 708: break; ! 709: default: ! 710: break; ! 711: } ! 712: } else { ! 713: /* ! 714: * If there is no old value, only 'no' (unset) ! 715: * is allowed as new value. ! 716: */ ! 717: switch (sym->type) { ! 718: case S_BOOLEAN: ! 719: case S_TRISTATE: ! 720: if (sym_get_tristate_value(sym) == no) ! 721: continue; ! 722: break; ! 723: default: ! 724: break; ! 725: } ! 726: } ! 727: } else if (!(sym->flags & SYMBOL_DEF_AUTO)) ! 728: /* There is neither an old nor a new value. */ ! 729: continue; ! 730: /* else ! 731: * There is an old value, but no new value ('no' (unset) ! 732: * isn't saved in auto.conf, so the old value is always ! 733: * different from 'no'). ! 734: */ ! 735: ! 736: /* Replace all '_' and append ".h" */ ! 737: s = sym->name; ! 738: d = path; ! 739: while ((c = *s++)) { ! 740: c = tolower(c); ! 741: *d++ = (c == '_') ? '/' : c; ! 742: } ! 743: strcpy(d, ".h"); ! 744: ! 745: /* Assume directory path already exists. */ ! 746: fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644); ! 747: if (fd == -1) { ! 748: if (errno != ENOENT) { ! 749: res = 1; ! 750: break; ! 751: } ! 752: /* ! 753: * Create directory components, ! 754: * unless they exist already. ! 755: */ ! 756: d = path; ! 757: while ((d = strchr(d, '/'))) { ! 758: *d = 0; ! 759: if (stat(path, &sb) && mkdir(path, 0755)) { ! 760: res = 1; ! 761: goto out; ! 762: } ! 763: *d++ = '/'; ! 764: } ! 765: /* Try it again. */ ! 766: fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644); ! 767: if (fd == -1) { ! 768: res = 1; ! 769: break; ! 770: } ! 771: } ! 772: close(fd); ! 773: } ! 774: out: ! 775: if (chdir("../..")) ! 776: return 1; ! 777: ! 778: return res; ! 779: } ! 780: ! 781: int conf_write_autoconf(void) ! 782: { ! 783: struct symbol *sym; ! 784: const char *str; ! 785: const char *name; ! 786: FILE *out, *tristate, *out_h; ! 787: time_t now; ! 788: int i; ! 789: ! 790: sym_clear_all_valid(); ! 791: ! 792: file_write_dep("include/config/auto.conf.cmd"); ! 793: ! 794: if (conf_split_config()) ! 795: return 1; ! 796: ! 797: out = fopen(".tmpconfig", "w"); ! 798: if (!out) ! 799: return 1; ! 800: ! 801: tristate = fopen(".tmpconfig_tristate", "w"); ! 802: if (!tristate) { ! 803: fclose(out); ! 804: return 1; ! 805: } ! 806: ! 807: out_h = fopen(".tmpconfig.h", "w"); ! 808: if (!out_h) { ! 809: fclose(out); ! 810: fclose(tristate); ! 811: return 1; ! 812: } ! 813: ! 814: time(&now); ! 815: fprintf(out, "#\n" ! 816: "# Automatically generated make config: don't edit\n" ! 817: "# %s\n" ! 818: "# %s" ! 819: "#\n", ! 820: rootmenu.prompt->text, ctime(&now)); ! 821: fprintf(tristate, "#\n" ! 822: "# Automatically generated - do not edit\n" ! 823: "\n"); ! 824: fprintf(out_h, "/*\n" ! 825: " * Automatically generated C config: don't edit\n" ! 826: " * %s\n" ! 827: " * %s" ! 828: " */\n", ! 829: rootmenu.prompt->text, ctime(&now)); ! 830: ! 831: for_all_symbols(i, sym) { ! 832: sym_calc_value(sym); ! 833: if (!sym->name) ! 834: continue; ! 835: if (!(sym->flags & SYMBOL_WRITE)) { ! 836: if (sym->type == S_BOOLEAN || sym->type == S_HEX ! 837: || sym->type == S_INT) ! 838: fprintf(out_h, "#define %s%s 0\n", ! 839: CONFIG_, sym->name); ! 840: continue; ! 841: } ! 842: ! 843: /* write symbol to config file */ ! 844: conf_write_symbol(sym, out, false); ! 845: ! 846: /* update autoconf and tristate files */ ! 847: switch (sym->type) { ! 848: case S_BOOLEAN: ! 849: case S_TRISTATE: ! 850: switch (sym_get_tristate_value(sym)) { ! 851: case no: ! 852: fprintf(out_h, "#define %s%s 0\n", ! 853: CONFIG_, sym->name); ! 854: break; ! 855: case mod: ! 856: fprintf(tristate, "%s%s=M\n", ! 857: CONFIG_, sym->name); ! 858: fprintf(out_h, "#define %s%s_MODULE 1\n", ! 859: CONFIG_, sym->name); ! 860: break; ! 861: case yes: ! 862: if (sym->type == S_TRISTATE) ! 863: fprintf(tristate,"%s%s=Y\n", ! 864: CONFIG_, sym->name); ! 865: fprintf(out_h, "#define %s%s 1\n", ! 866: CONFIG_, sym->name); ! 867: break; ! 868: } ! 869: break; ! 870: case S_STRING: ! 871: conf_write_string(true, sym->name, sym_get_string_value(sym), out_h); ! 872: break; ! 873: case S_HEX: ! 874: str = sym_get_string_value(sym); ! 875: if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) { ! 876: fprintf(out_h, "#define %s%s 0x%s\n", ! 877: CONFIG_, sym->name, str); ! 878: break; ! 879: } ! 880: case S_INT: ! 881: str = sym_get_string_value(sym); ! 882: fprintf(out_h, "#define %s%s %s\n", ! 883: CONFIG_, sym->name, str); ! 884: break; ! 885: default: ! 886: break; ! 887: } ! 888: } ! 889: fclose(out); ! 890: fclose(tristate); ! 891: fclose(out_h); ! 892: ! 893: name = getenv("KCONFIG_AUTOHEADER"); ! 894: if (!name) ! 895: name = "include/generated/autoconf.h"; ! 896: if (rename(".tmpconfig.h", name)) ! 897: return 1; ! 898: name = getenv("KCONFIG_TRISTATE"); ! 899: if (!name) ! 900: name = "include/config/tristate.conf"; ! 901: if (rename(".tmpconfig_tristate", name)) ! 902: return 1; ! 903: name = conf_get_autoconfig_name(); ! 904: /* ! 905: * This must be the last step, kbuild has a dependency on auto.conf ! 906: * and this marks the successful completion of the previous steps. ! 907: */ ! 908: if (rename(".tmpconfig", name)) ! 909: return 1; ! 910: ! 911: return 0; ! 912: } ! 913: ! 914: static int sym_change_count; ! 915: static void (*conf_changed_callback)(void); ! 916: ! 917: void sym_set_change_count(int count) ! 918: { ! 919: int _sym_change_count = sym_change_count; ! 920: sym_change_count = count; ! 921: if (conf_changed_callback && ! 922: (bool)_sym_change_count != (bool)count) ! 923: conf_changed_callback(); ! 924: } ! 925: ! 926: void sym_add_change_count(int count) ! 927: { ! 928: sym_set_change_count(count + sym_change_count); ! 929: } ! 930: ! 931: bool conf_get_changed(void) ! 932: { ! 933: return sym_change_count; ! 934: } ! 935: ! 936: void conf_set_changed_callback(void (*fn)(void)) ! 937: { ! 938: conf_changed_callback = fn; ! 939: } ! 940: ! 941: static void randomize_choice_values(struct symbol *csym) ! 942: { ! 943: struct property *prop; ! 944: struct symbol *sym; ! 945: struct expr *e; ! 946: int cnt, def; ! 947: ! 948: /* ! 949: * If choice is mod then we may have more items selected ! 950: * and if no then no-one. ! 951: * In both cases stop. ! 952: */ ! 953: if (csym->curr.tri != yes) ! 954: return; ! 955: ! 956: prop = sym_get_choice_prop(csym); ! 957: ! 958: /* count entries in choice block */ ! 959: cnt = 0; ! 960: expr_list_for_each_sym(prop->expr, e, sym) ! 961: cnt++; ! 962: ! 963: /* ! 964: * find a random value and set it to yes, ! 965: * set the rest to no so we have only one set ! 966: */ ! 967: def = (rand() % cnt); ! 968: ! 969: cnt = 0; ! 970: expr_list_for_each_sym(prop->expr, e, sym) { ! 971: if (def == cnt++) { ! 972: sym->def[S_DEF_USER].tri = yes; ! 973: csym->def[S_DEF_USER].val = sym; ! 974: } ! 975: else { ! 976: sym->def[S_DEF_USER].tri = no; ! 977: } ! 978: } ! 979: csym->flags |= SYMBOL_DEF_USER; ! 980: /* clear VALID to get value calculated */ ! 981: csym->flags &= ~(SYMBOL_VALID); ! 982: } ! 983: ! 984: static void set_all_choice_values(struct symbol *csym) ! 985: { ! 986: struct property *prop; ! 987: struct symbol *sym; ! 988: struct expr *e; ! 989: ! 990: prop = sym_get_choice_prop(csym); ! 991: ! 992: /* ! 993: * Set all non-assinged choice values to no ! 994: */ ! 995: expr_list_for_each_sym(prop->expr, e, sym) { ! 996: if (!sym_has_value(sym)) ! 997: sym->def[S_DEF_USER].tri = no; ! 998: } ! 999: csym->flags |= SYMBOL_DEF_USER; ! 1000: /* clear VALID to get value calculated */ ! 1001: csym->flags &= ~(SYMBOL_VALID); ! 1002: } ! 1003: ! 1004: void conf_set_all_new_symbols(enum conf_def_mode mode) ! 1005: { ! 1006: struct symbol *sym, *csym; ! 1007: int i, cnt; ! 1008: ! 1009: for_all_symbols(i, sym) { ! 1010: if (sym_has_value(sym)) ! 1011: continue; ! 1012: switch (sym_get_type(sym)) { ! 1013: case S_BOOLEAN: ! 1014: case S_TRISTATE: ! 1015: switch (mode) { ! 1016: case def_yes: ! 1017: sym->def[S_DEF_USER].tri = yes; ! 1018: break; ! 1019: case def_mod: ! 1020: sym->def[S_DEF_USER].tri = mod; ! 1021: break; ! 1022: case def_no: ! 1023: sym->def[S_DEF_USER].tri = no; ! 1024: break; ! 1025: case def_random: ! 1026: cnt = sym_get_type(sym) == S_TRISTATE ? 3 : 2; ! 1027: sym->def[S_DEF_USER].tri = (tristate)(rand() % cnt); ! 1028: break; ! 1029: default: ! 1030: continue; ! 1031: } ! 1032: if (!(sym_is_choice(sym) && mode == def_random)) ! 1033: sym->flags |= SYMBOL_DEF_USER; ! 1034: break; ! 1035: default: ! 1036: break; ! 1037: } ! 1038: ! 1039: } ! 1040: ! 1041: sym_clear_all_valid(); ! 1042: ! 1043: /* ! 1044: * We have different type of choice blocks. ! 1045: * If curr.tri equals to mod then we can select several ! 1046: * choice symbols in one block. ! 1047: * In this case we do nothing. ! 1048: * If curr.tri equals yes then only one symbol can be ! 1049: * selected in a choice block and we set it to yes, ! 1050: * and the rest to no. ! 1051: */ ! 1052: for_all_symbols(i, csym) { ! 1053: if (sym_has_value(csym) || !sym_is_choice(csym)) ! 1054: continue; ! 1055: ! 1056: sym_calc_value(csym); ! 1057: if (mode == def_random) ! 1058: randomize_choice_values(csym); ! 1059: else ! 1060: set_all_choice_values(csym); ! 1061: } ! 1062: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.