coreboot/payloads/libpayload/util/kconfig/confdata.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
   3 * Released under the terms of the GNU GPL v2.0.
   4 */
   5
   6#include <sys/stat.h>
   7#include <ctype.h>
   8#include <fcntl.h>
   9#include <stdio.h>
  10#include <stdlib.h>
  11#include <string.h>
  12#include <time.h>
  13#include <unistd.h>
  14
  15#define LKC_DIRECT_LINK
  16#include "lkc.h"
  17
  18#ifdef WIN32
  19#define mkdir(x,y) mkdir(x)
  20#define UNLINK_IF_NECESSARY(x) unlink(x)
  21#else
  22#define UNLINK_IF_NECESSARY(X)
  23#endif
  24
  25static void conf_warning(const char *fmt, ...)
  26        __attribute__ ((format (printf, 1, 2)));
  27
  28static const char *conf_filename;
  29static int conf_lineno, conf_warnings, conf_unsaved;
  30
  31const char conf_defname[] = "arch/$ARCH/defconfig";
  32
  33static void conf_warning(const char *fmt, ...)
  34{
  35        va_list ap;
  36        va_start(ap, fmt);
  37        fprintf(stderr, "%s:%d:warning: ", conf_filename, conf_lineno);
  38        vfprintf(stderr, fmt, ap);
  39        fprintf(stderr, "\n");
  40        va_end(ap);
  41        conf_warnings++;
  42}
  43
  44const char *conf_get_configname(void)
  45{
  46        char *name = getenv("KCONFIG_CONFIG");
  47
  48        return name ? name : ".config";
  49}
  50
  51static char *conf_expand_value(const char *in)
  52{
  53        struct symbol *sym;
  54        const char *src;
  55        static char res_value[SYMBOL_MAXLENGTH];
  56        char *dst, name[SYMBOL_MAXLENGTH];
  57
  58        res_value[0] = 0;
  59        dst = name;
  60        while ((src = strchr(in, '$'))) {
  61                strncat(res_value, in, src - in);
  62                src++;
  63                dst = name;
  64                while (isalnum(*src) || *src == '_')
  65                        *dst++ = *src++;
  66                *dst = 0;
  67                sym = sym_lookup(name, 0);
  68                sym_calc_value(sym);
  69                strcat(res_value, sym_get_string_value(sym));
  70                in = src;
  71        }
  72        strcat(res_value, in);
  73
  74        return res_value;
  75}
  76
  77char *conf_get_default_confname(void)
  78{
  79        struct stat buf;
  80        static char fullname[PATH_MAX+1];
  81        char *env, *name;
  82
  83        name = conf_expand_value(conf_defname);
  84        env = getenv(SRCTREE);
  85        if (env) {
  86                sprintf(fullname, "%s/%s", env, name);
  87                if (!stat(fullname, &buf))
  88                        return fullname;
  89        }
  90        return name;
  91}
  92
  93static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
  94{
  95        char *p2;
  96
  97        switch (sym->type) {
  98        case S_TRISTATE:
  99                if (p[0] == 'm') {
 100                        sym->def[def].tri = mod;
 101                        sym->flags |= def_flags;
 102                        break;
 103                }
 104        case S_BOOLEAN:
 105                if (p[0] == 'y') {
 106                        sym->def[def].tri = yes;
 107                        sym->flags |= def_flags;
 108                        break;
 109                }
 110                if (p[0] == 'n') {
 111                        sym->def[def].tri = no;
 112                        sym->flags |= def_flags;
 113                        break;
 114                }
 115                conf_warning("symbol value '%s' invalid for %s", p, sym->name);
 116                break;
 117        case S_OTHER:
 118                if (*p != '"') {
 119                        for (p2 = p; *p2 && !isspace(*p2); p2++)
 120                                ;
 121                        sym->type = S_STRING;
 122                        goto done;
 123                }
 124        case S_STRING:
 125                if (*p++ != '"')
 126                        break;
 127                for (p2 = p; (p2 = strpbrk(p2, "\"\\")); p2++) {
 128                        if (*p2 == '"') {
 129                                *p2 = 0;
 130                                break;
 131                        }
 132                        memmove(p2, p2 + 1, strlen(p2));
 133                }
 134                if (!p2) {
 135                        conf_warning("invalid string found");
 136                        return 1;
 137                }
 138        case S_INT:
 139        case S_HEX:
 140        done:
 141                if (sym_string_valid(sym, p)) {
 142                        sym->def[def].val = strdup(p);
 143                        sym->flags |= def_flags;
 144                } else {
 145                        conf_warning("symbol value '%s' invalid for %s", p, sym->name);
 146                        return 1;
 147                }
 148                break;
 149        default:
 150                ;
 151        }
 152        return 0;
 153}
 154
 155int conf_read_simple(const char *name, int def)
 156{
 157        FILE *in = NULL;
 158        char line[1024];
 159        char *p, *p2;
 160        struct symbol *sym;
 161        int i, def_flags;
 162
 163        if (name) {
 164                in = zconf_fopen(name);
 165        } else {
 166                struct property *prop;
 167
 168                name = conf_get_configname();
 169                in = zconf_fopen(name);
 170                if (in)
 171                        goto load;
 172                sym_add_change_count(1);
 173                if (!sym_defconfig_list)
 174                        return 1;
 175
 176                for_all_defaults(sym_defconfig_list, prop) {
 177                        if (expr_calc_value(prop->visible.expr) == no ||
 178                            prop->expr->type != E_SYMBOL)
 179                                continue;
 180                        name = conf_expand_value(prop->expr->left.sym->name);
 181                        in = zconf_fopen(name);
 182                        if (in) {
 183                                printf(_("#\n"
 184                                         "# using defaults found in %s\n"
 185                                         "#\n"), name);
 186                                goto load;
 187                        }
 188                }
 189        }
 190        if (!in)
 191                return 1;
 192
 193load:
 194        conf_filename = name;
 195        conf_lineno = 0;
 196        conf_warnings = 0;
 197        conf_unsaved = 0;
 198
 199        def_flags = SYMBOL_DEF << def;
 200        for_all_symbols(i, sym) {
 201                sym->flags |= SYMBOL_CHANGED;
 202                sym->flags &= ~(def_flags|SYMBOL_VALID);
 203                if (sym_is_choice(sym))
 204                        sym->flags |= def_flags;
 205                switch (sym->type) {
 206                case S_INT:
 207                case S_HEX:
 208                case S_STRING:
 209                        if (sym->def[def].val)
 210                                free(sym->def[def].val);
 211                default:
 212                        sym->def[def].val = NULL;
 213                        sym->def[def].tri = no;
 214                }
 215        }
 216
 217        while (fgets(line, sizeof(line), in)) {
 218                conf_lineno++;
 219                sym = NULL;
 220                switch (line[0]) {
 221                case '#':
 222                        if (memcmp(line + 2, "CONFIG_", 7))
 223                                continue;
 224                        p = strchr(line + 9, ' ');
 225                        if (!p)
 226                                continue;
 227                        *p++ = 0;
 228                        if (strncmp(p, "is not set", 10))
 229                                continue;
 230                        if (def == S_DEF_USER) {
 231                                sym = sym_find(line + 9);
 232                                if (!sym) {
 233                                        conf_warning("trying to assign nonexistent symbol %s", line + 9);
 234                                        break;
 235                                }
 236                        } else {
 237                                sym = sym_lookup(line + 9, 0);
 238                                if (sym->type == S_UNKNOWN)
 239                                        sym->type = S_BOOLEAN;
 240                        }
 241                        if (sym->flags & def_flags) {
 242                                conf_warning("override: reassigning to symbol %s", sym->name);
 243                        }
 244                        switch (sym->type) {
 245                        case S_BOOLEAN:
 246                        case S_TRISTATE:
 247                                sym->def[def].tri = no;
 248                                sym->flags |= def_flags;
 249                                break;
 250                        default:
 251                                ;
 252                        }
 253                        break;
 254                case 'C':
 255                        if (memcmp(line, "CONFIG_", 7)) {
 256                                conf_warning("unexpected data");
 257                                continue;
 258                        }
 259                        p = strchr(line + 7, '=');
 260                        if (!p)
 261                                continue;
 262                        *p++ = 0;
 263                        p2 = strchr(p, '\n');
 264                        if (p2) {
 265                                *p2-- = 0;
 266                                if (*p2 == '\r')
 267                                        *p2 = 0;
 268                        }
 269                        if (def == S_DEF_USER) {
 270                                sym = sym_find(line + 7);
 271                                if (!sym) {
 272                                        conf_warning("trying to assign nonexistent symbol %s", line + 7);
 273                                        break;
 274                                }
 275                        } else {
 276                                sym = sym_lookup(line + 7, 0);
 277                                if (sym->type == S_UNKNOWN)
 278                                        sym->type = S_OTHER;
 279                        }
 280                        if (sym->flags & def_flags) {
 281                                conf_warning("override: reassigning to symbol %s", sym->name);
 282                        }
 283                        if (conf_set_sym_val(sym, def, def_flags, p))
 284                                continue;
 285                        break;
 286                case '\r':
 287                case '\n':
 288                        break;
 289                default:
 290                        conf_warning("unexpected data");
 291                        continue;
 292                }
 293                if (sym && sym_is_choice_value(sym)) {
 294                        struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
 295                        switch (sym->def[def].tri) {
 296                        case no:
 297                                break;
 298                        case mod:
 299                                if (cs->def[def].tri == yes) {
 300                                        conf_warning("%s creates inconsistent choice state", sym->name);
 301                                        cs->flags &= ~def_flags;
 302                                }
 303                                break;
 304                        case yes:
 305                                if (cs->def[def].tri != no)
 306                                        conf_warning("override: %s changes choice state", sym->name);
 307                                cs->def[def].val = sym;
 308                                break;
 309                        }
 310                        cs->def[def].tri = EXPR_OR(cs->def[def].tri, sym->def[def].tri);
 311                }
 312        }
 313        fclose(in);
 314
 315        if (modules_sym)
 316                sym_calc_value(modules_sym);
 317        return 0;
 318}
 319
 320int conf_read(const char *name)
 321{
 322        struct symbol *sym, *choice_sym;
 323        struct property *prop;
 324        struct expr *e;
 325        int i, flags;
 326
 327        sym_set_change_count(0);
 328
 329        if (conf_read_simple(name, S_DEF_USER))
 330                return 1;
 331
 332        for_all_symbols(i, sym) {
 333                sym_calc_value(sym);
 334                if (sym_is_choice(sym) || (sym->flags & SYMBOL_AUTO))
 335                        goto sym_ok;
 336                if (sym_has_value(sym) && (sym->flags & SYMBOL_WRITE)) {
 337                        /* check that calculated value agrees with saved value */
 338                        switch (sym->type) {
 339                        case S_BOOLEAN:
 340                        case S_TRISTATE:
 341                                if (sym->def[S_DEF_USER].tri != sym_get_tristate_value(sym))
 342                                        break;
 343                                if (!sym_is_choice(sym))
 344                                        goto sym_ok;
 345                        default:
 346                                if (!strcmp(sym->curr.val, sym->def[S_DEF_USER].val))
 347                                        goto sym_ok;
 348                                break;
 349                        }
 350                } else if (!sym_has_value(sym) && !(sym->flags & SYMBOL_WRITE))
 351                        /* no previous value and not saved */
 352                        goto sym_ok;
 353                conf_unsaved++;
 354                /* maybe print value in verbose mode... */
 355        sym_ok:
 356                if (!sym_is_choice(sym))
 357                        continue;
 358                /* The choice symbol only has a set value (and thus is not new)
 359                 * if all its visible childs have values.
 360                 */
 361                prop = sym_get_choice_prop(sym);
 362                flags = sym->flags;
 363                expr_list_for_each_sym(prop->expr, e, choice_sym)
 364                        if (choice_sym->visible != no)
 365                                flags &= choice_sym->flags;
 366                sym->flags &= flags | ~SYMBOL_DEF_USER;
 367        }
 368
 369        for_all_symbols(i, sym) {
 370                if (sym_has_value(sym) && !sym_is_choice_value(sym)) {
 371                        /* Reset values of generates values, so they'll appear
 372                         * as new, if they should become visible, but that
 373                         * doesn't quite work if the Kconfig and the saved
 374                         * configuration disagree.
 375                         */
 376                        if (sym->visible == no && !conf_unsaved)
 377                                sym->flags &= ~SYMBOL_DEF_USER;
 378                        switch (sym->type) {
 379                        case S_STRING:
 380                        case S_INT:
 381                        case S_HEX:
 382                                /* Reset a string value if it's out of range */
 383                                if (sym_string_within_range(sym, sym->def[S_DEF_USER].val))
 384                                        break;
 385                                sym->flags &= ~(SYMBOL_VALID|SYMBOL_DEF_USER);
 386                                conf_unsaved++;
 387                                break;
 388                        default:
 389                                break;
 390                        }
 391                }
 392        }
 393
 394        sym_add_change_count(conf_warnings || conf_unsaved);
 395
 396        return 0;
 397}
 398
 399int conf_write(const char *name)
 400{
 401        FILE *out;
 402        struct symbol *sym;
 403        struct menu *menu;
 404        const char *basename;
 405        char dirname[128], tmpname[128], newname[128];
 406        int type, l;
 407        const char *str;
 408        time_t now;
 409        int use_timestamp = 1;
 410        char *env;
 411
 412        dirname[0] = 0;
 413        if (name && name[0]) {
 414                struct stat st;
 415                char *slash;
 416
 417                if (!stat(name, &st) && S_ISDIR(st.st_mode)) {
 418                        strcpy(dirname, name);
 419                        strcat(dirname, "/");
 420                        basename = conf_get_configname();
 421                } else if ((slash = strrchr(name, '/'))) {
 422                        int size = slash - name + 1;
 423                        memcpy(dirname, name, size);
 424                        dirname[size] = 0;
 425                        if (slash[1])
 426                                basename = slash + 1;
 427                        else
 428                                basename = conf_get_configname();
 429                } else
 430                        basename = name;
 431        } else
 432                basename = conf_get_configname();
 433
 434        sprintf(newname, "%s%s", dirname, basename);
 435        env = getenv("KCONFIG_OVERWRITECONFIG");
 436        if (!env || !*env) {
 437                sprintf(tmpname, "%s.tmpconfig.%d", dirname, (int)getpid());
 438                out = fopen(tmpname, "w");
 439        } else {
 440                *tmpname = 0;
 441                out = fopen(newname, "w");
 442        }
 443        if (!out)
 444                return 1;
 445
 446        sym = sym_lookup("KERNELVERSION", 0);
 447        sym_calc_value(sym);
 448        time(&now);
 449        env = getenv("KCONFIG_NOTIMESTAMP");
 450        if (env && *env)
 451                use_timestamp = 0;
 452
 453        fprintf(out, _("#\n"
 454                       "# Automatically generated make config: don't edit\n"
 455                       "# libpayload version: %s\n"
 456                       "%s%s"
 457                       "#\n"),
 458                     getenv("KERNELVERSION")?getenv("KERNELVERSION"):"",
 459                     use_timestamp ? "# " : "",
 460                     use_timestamp ? ctime(&now) : "");
 461
 462        if (!conf_get_changed())
 463                sym_clear_all_valid();
 464
 465        menu = rootmenu.list;
 466        while (menu) {
 467                sym = menu->sym;
 468                if (!sym) {
 469                        if (!menu_is_visible(menu))
 470                                goto next;
 471                        str = menu_get_prompt(menu);
 472                        fprintf(out, "\n"
 473                                     "#\n"
 474                                     "# %s\n"
 475                                     "#\n", str);
 476                } else if (!(sym->flags & SYMBOL_CHOICE)) {
 477                        sym_calc_value(sym);
 478                        if (!(sym->flags & SYMBOL_WRITE))
 479                                goto next;
 480                        sym->flags &= ~SYMBOL_WRITE;
 481                        type = sym->type;
 482                        if (type == S_TRISTATE) {
 483                                sym_calc_value(modules_sym);
 484                                if (modules_sym->curr.tri == no)
 485                                        type = S_BOOLEAN;
 486                        }
 487                        switch (type) {
 488                        case S_BOOLEAN:
 489                        case S_TRISTATE:
 490                                switch (sym_get_tristate_value(sym)) {
 491                                case no:
 492                                        fprintf(out, "# CONFIG_%s is not set\n", sym->name);
 493                                        break;
 494                                case mod:
 495                                        fprintf(out, "CONFIG_%s=m\n", sym->name);
 496                                        break;
 497                                case yes:
 498                                        fprintf(out, "CONFIG_%s=y\n", sym->name);
 499                                        break;
 500                                }
 501                                break;
 502                        case S_STRING:
 503                                str = sym_get_string_value(sym);
 504                                fprintf(out, "CONFIG_%s=\"", sym->name);
 505                                while (1) {
 506                                        l = strcspn(str, "\"\\");
 507                                        if (l) {
 508                                                fwrite(str, l, 1, out);
 509                                                str += l;
 510                                        }
 511                                        if (!*str)
 512                                                break;
 513                                        fprintf(out, "\\%c", *str++);
 514                                }
 515                                fputs("\"\n", out);
 516                                break;
 517                        case S_HEX:
 518                                str = sym_get_string_value(sym);
 519                                if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) {
 520                                        fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
 521                                        break;
 522                                }
 523                        case S_INT:
 524                                str = sym_get_string_value(sym);
 525                                fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
 526                                break;
 527                        }
 528                }
 529
 530        next:
 531                if (menu->list) {
 532                        menu = menu->list;
 533                        continue;
 534                }
 535                if (menu->next)
 536                        menu = menu->next;
 537                else while ((menu = menu->parent)) {
 538                        if (menu->next) {
 539                                menu = menu->next;
 540                                break;
 541                        }
 542                }
 543        }
 544        fclose(out);
 545
 546        if (*tmpname) {
 547                strcat(dirname, basename);
 548                strcat(dirname, ".old");
 549                UNLINK_IF_NECESSARY(dirname);
 550                rename(newname, dirname);
 551                if (rename(tmpname, newname))
 552                        return 1;
 553        }
 554
 555        printf(_("#\n"
 556                 "# configuration written to %s\n"
 557                 "#\n"), newname);
 558
 559        sym_set_change_count(0);
 560
 561        return 0;
 562}
 563
 564int conf_split_config(void)
 565{
 566        char *name, path[128];
 567        char *s, *d, c;
 568        struct symbol *sym;
 569        struct stat sb;
 570        int res, i, fd;
 571
 572        name = getenv("KCONFIG_AUTOCONFIG");
 573        if (!name)
 574                name = "include/config/auto.conf";
 575        conf_read_simple(name, S_DEF_AUTO);
 576
 577        if (chdir("build"))
 578                return 1;
 579
 580        res = 0;
 581        for_all_symbols(i, sym) {
 582                sym_calc_value(sym);
 583                if ((sym->flags & SYMBOL_AUTO) || !sym->name)
 584                        continue;
 585                if (sym->flags & SYMBOL_WRITE) {
 586                        if (sym->flags & SYMBOL_DEF_AUTO) {
 587                                /*
 588                                 * symbol has old and new value,
 589                                 * so compare them...
 590                                 */
 591                                switch (sym->type) {
 592                                case S_BOOLEAN:
 593                                case S_TRISTATE:
 594                                        if (sym_get_tristate_value(sym) ==
 595                                            sym->def[S_DEF_AUTO].tri)
 596                                                continue;
 597                                        break;
 598                                case S_STRING:
 599                                case S_HEX:
 600                                case S_INT:
 601                                        if (!strcmp(sym_get_string_value(sym),
 602                                                    sym->def[S_DEF_AUTO].val))
 603                                                continue;
 604                                        break;
 605                                default:
 606                                        break;
 607                                }
 608                        } else {
 609                                /*
 610                                 * If there is no old value, only 'no' (unset)
 611                                 * is allowed as new value.
 612                                 */
 613                                switch (sym->type) {
 614                                case S_BOOLEAN:
 615                                case S_TRISTATE:
 616                                        if (sym_get_tristate_value(sym) == no)
 617                                                continue;
 618                                        break;
 619                                default:
 620                                        break;
 621                                }
 622                        }
 623                } else if (!(sym->flags & SYMBOL_DEF_AUTO))
 624                        /* There is neither an old nor a new value. */
 625                        continue;
 626                /* else
 627                 *      There is an old value, but no new value ('no' (unset)
 628                 *      isn't saved in auto.conf, so the old value is always
 629                 *      different from 'no').
 630                 */
 631
 632                /* Replace all '_' and append ".h" */
 633                s = sym->name;
 634                d = path;
 635                while ((c = *s++)) {
 636                        c = tolower(c);
 637                        *d++ = (c == '_') ? '/' : c;
 638                }
 639                strcpy(d, ".h");
 640
 641                /* Assume directory path already exists. */
 642                fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
 643                if (fd == -1) {
 644                        if (errno != ENOENT) {
 645                                res = 1;
 646                                break;
 647                        }
 648                        /*
 649                         * Create directory components,
 650                         * unless they exist already.
 651                         */
 652                        d = path;
 653                        while ((d = strchr(d, '/'))) {
 654                                *d = 0;
 655                                if (stat(path, &sb) && mkdir(path, 0755)) {
 656                                        res = 1;
 657                                        goto out;
 658                                }
 659                                *d++ = '/';
 660                        }
 661                        /* Try it again. */
 662                        fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
 663                        if (fd == -1) {
 664                                res = 1;
 665                                break;
 666                        }
 667                }
 668                close(fd);
 669        }
 670out:
 671        if (chdir("../.."))
 672                return 1;
 673
 674        return res;
 675}
 676
 677int conf_write_autoconf(void)
 678{
 679        struct symbol *sym;
 680        const char *str;
 681        char *name;
 682        FILE *out, *out_h;
 683        time_t now;
 684        int i, l;
 685
 686        sym_clear_all_valid();
 687
 688        file_write_dep("build/auto.conf.cmd");
 689
 690#if 0
 691        if (conf_split_config())
 692                return 1;
 693#endif
 694
 695        out = fopen(".tmpconfig", "w");
 696        if (!out)
 697                return 1;
 698
 699        out_h = fopen(".tmpconfig.h", "w");
 700        if (!out_h) {
 701                fclose(out);
 702                return 1;
 703        }
 704
 705        sym = sym_lookup("KERNELVERSION", 0);
 706        sym_calc_value(sym);
 707        time(&now);
 708        fprintf(out, "#\n"
 709                     "# Automatically generated make config: don't edit\n"
 710                     "# libpayload version: %s\n"
 711                     "# %s"
 712                     "#\n",
 713                     getenv("KERNELVERSION")?getenv("KERNELVERSION"):"", ctime(&now));
 714        fprintf(out_h, "/*\n"
 715                       " * Automatically generated C config: don't edit\n"
 716                       " * libpayload version: %s\n"
 717                       " * %s"
 718                       " */\n"
 719                       "#define AUTOCONF_INCLUDED\n",
 720                       getenv("KERNELVERSION")?getenv("KERNELVERSION"):"", ctime(&now));
 721
 722        for_all_symbols(i, sym) {
 723                sym_calc_value(sym);
 724                if (!(sym->flags & SYMBOL_WRITE) || !sym->name)
 725                        continue;
 726                switch (sym->type) {
 727                case S_BOOLEAN:
 728                case S_TRISTATE:
 729                        switch (sym_get_tristate_value(sym)) {
 730                        case no:
 731                                break;
 732                        case mod:
 733                                fprintf(out, "CONFIG_%s=m\n", sym->name);
 734                                fprintf(out_h, "#define CONFIG_%s_MODULE 1\n", sym->name);
 735                                break;
 736                        case yes:
 737                                fprintf(out, "CONFIG_%s=y\n", sym->name);
 738                                fprintf(out_h, "#define CONFIG_%s 1\n", sym->name);
 739                                break;
 740                        }
 741                        break;
 742                case S_STRING:
 743                        str = sym_get_string_value(sym);
 744                        fprintf(out, "CONFIG_%s=\"", sym->name);
 745                        fprintf(out_h, "#define CONFIG_%s \"", sym->name);
 746                        while (1) {
 747                                l = strcspn(str, "\"\\");
 748                                if (l) {
 749                                        fwrite(str, l, 1, out);
 750                                        fwrite(str, l, 1, out_h);
 751                                        str += l;
 752                                }
 753                                if (!*str)
 754                                        break;
 755                                fprintf(out, "\\%c", *str);
 756                                fprintf(out_h, "\\%c", *str);
 757                                str++;
 758                        }
 759                        fputs("\"\n", out);
 760                        fputs("\"\n", out_h);
 761                        break;
 762                case S_HEX:
 763                        str = sym_get_string_value(sym);
 764                        if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) {
 765                                fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
 766                                fprintf(out_h, "#define CONFIG_%s 0x%s\n", sym->name, str);
 767                                break;
 768                        }
 769                case S_INT:
 770                        str = sym_get_string_value(sym);
 771                        fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
 772                        fprintf(out_h, "#define CONFIG_%s %s\n", sym->name, str);
 773                        break;
 774                default:
 775                        break;
 776                }
 777        }
 778        fclose(out);
 779        fclose(out_h);
 780
 781        name = getenv("KCONFIG_AUTOHEADER");
 782        if (!name)
 783                name = "include/linux/autoconf.h";
 784        UNLINK_IF_NECESSARY(name);
 785        if (rename(".tmpconfig.h", name))
 786                return 1;
 787        name = getenv("KCONFIG_AUTOCONFIG");
 788        if (!name)
 789                name = "include/config/auto.conf";
 790        /*
 791         * This must be the last step, kbuild has a dependency on auto.conf
 792         * and this marks the successful completion of the previous steps.
 793         */
 794        UNLINK_IF_NECESSARY(name);
 795        if (rename(".tmpconfig", name))
 796                return 1;
 797
 798        return 0;
 799}
 800
 801static int sym_change_count;
 802static void (*conf_changed_callback)(void);
 803
 804void sym_set_change_count(int count)
 805{
 806        int _sym_change_count = sym_change_count;
 807        sym_change_count = count;
 808        if (conf_changed_callback &&
 809            (bool)_sym_change_count != (bool)count)
 810                conf_changed_callback();
 811}
 812
 813void sym_add_change_count(int count)
 814{
 815        sym_set_change_count(count + sym_change_count);
 816}
 817
 818bool conf_get_changed(void)
 819{
 820        return sym_change_count;
 821}
 822
 823void conf_set_changed_callback(void (*fn)(void))
 824{
 825        conf_changed_callback = fn;
 826}
 827
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.