busybox/scripts/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 <stdio.h>
   9#include <stdlib.h>
  10#include <string.h>
  11#include <time.h>
  12#include <unistd.h>
  13
  14#define LKC_DIRECT_LINK
  15#include "lkc.h"
  16
  17static void conf_warning(const char *fmt, ...)
  18        __attribute__ ((format (printf, 1, 2)));
  19
  20static const char *conf_filename;
  21static int conf_lineno, conf_warnings, conf_unsaved;
  22
  23const char conf_def_filename[] = ".config";
  24
  25const char conf_defname[] = "/dev/null"; //bbox
  26
  27const char *conf_confnames[] = {
  28        conf_def_filename,
  29        conf_defname,
  30        NULL,
  31};
  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
  44static char *conf_expand_value(const char *in)
  45{
  46        struct symbol *sym;
  47        const char *src;
  48        static char res_value[SYMBOL_MAXLENGTH];
  49        char *dst, name[SYMBOL_MAXLENGTH];
  50
  51        res_value[0] = 0;
  52        dst = name;
  53        while ((src = strchr(in, '$'))) {
  54                strncat(res_value, in, src - in);
  55                src++;
  56                dst = name;
  57                while (isalnum(*src) || *src == '_')
  58                        *dst++ = *src++;
  59                *dst = 0;
  60                sym = sym_lookup(name, 0);
  61                sym_calc_value(sym);
  62                strcat(res_value, sym_get_string_value(sym));
  63                in = src;
  64        }
  65        strcat(res_value, in);
  66
  67        return res_value;
  68}
  69
  70char *conf_get_default_confname(void)
  71{
  72        struct stat buf;
  73        static char *fullname = NULL;
  74        char *env, *name;
  75
  76        name = conf_expand_value(conf_defname);
  77        env = getenv(SRCTREE);
  78        if (env) {
  79                fullname = realloc(fullname, strlen(env) + strlen(name) + 2);
  80                sprintf(fullname, "%s/%s", env, name);
  81                if (!stat(fullname, &buf))
  82                        return fullname;
  83        }
  84        return name;
  85}
  86
  87int conf_read_simple(const char *name)
  88{
  89        FILE *in = NULL;
  90        char line[1024];
  91        char *p, *p2;
  92        struct symbol *sym;
  93        int i;
  94
  95        if (name) {
  96                in = zconf_fopen(name);
  97        } else {
  98                const char **names = conf_confnames;
  99                while ((name = *names++)) {
 100                        name = conf_expand_value(name);
 101                        in = zconf_fopen(name);
 102                        if (in) {
 103                                printf(_("#\n"
 104                                         "# using defaults found in %s\n"
 105                                         "#\n"), name);
 106                                break;
 107                        }
 108                }
 109        }
 110        if (!in)
 111                return 1;
 112
 113        conf_filename = name;
 114        conf_lineno = 0;
 115        conf_warnings = 0;
 116        conf_unsaved = 0;
 117
 118        for_all_symbols(i, sym) {
 119                sym->flags |= SYMBOL_NEW | SYMBOL_CHANGED;
 120                if (sym_is_choice(sym))
 121                        sym->flags &= ~SYMBOL_NEW;
 122                sym->flags &= ~SYMBOL_VALID;
 123                switch (sym->type) {
 124                case S_INT:
 125                case S_HEX:
 126                case S_STRING:
 127                        if (sym->user.val)
 128                                free(sym->user.val);
 129                default:
 130                        sym->user.val = NULL;
 131                        sym->user.tri = no;
 132                }
 133        }
 134
 135        while (fgets(line, sizeof(line), in)) {
 136                conf_lineno++;
 137                sym = NULL;
 138                switch (line[0]) {
 139                case '#':
 140                        if (memcmp(line + 2, "CONFIG_", 7))
 141                                continue;
 142                        p = strchr(line + 9, ' ');
 143                        if (!p)
 144                                continue;
 145                        *p++ = 0;
 146                        if (strncmp(p, "is not set", 10))
 147                                continue;
 148                        sym = sym_find(line + 9);
 149                        if (!sym) {
 150                                conf_warning("trying to assign nonexistent symbol %s", line + 9);
 151                                break;
 152                        } else if (!(sym->flags & SYMBOL_NEW)) {
 153                                conf_warning("trying to reassign symbol %s", sym->name);
 154                                break;
 155                        }
 156                        switch (sym->type) {
 157                        case S_BOOLEAN:
 158                        case S_TRISTATE:
 159                                sym->user.tri = no;
 160                                sym->flags &= ~SYMBOL_NEW;
 161                                break;
 162                        default:
 163                                ;
 164                        }
 165                        break;
 166                case 'C':
 167                        if (memcmp(line, "CONFIG_", 7)) {
 168                                conf_warning("unexpected data");
 169                                continue;
 170                        }
 171                        p = strchr(line + 7, '=');
 172                        if (!p)
 173                                continue;
 174                        *p++ = 0;
 175                        p2 = strchr(p, '\n');
 176                        if (p2)
 177                                *p2 = 0;
 178                        sym = sym_find(line + 7);
 179                        if (!sym) {
 180                                conf_warning("trying to assign nonexistent symbol %s", line + 7);
 181                                break;
 182                        } else if (!(sym->flags & SYMBOL_NEW)) {
 183                                conf_warning("trying to reassign symbol %s", sym->name);
 184                                break;
 185                        }
 186                        switch (sym->type) {
 187                        case S_TRISTATE:
 188                                if (p[0] == 'm') {
 189                                        sym->user.tri = mod;
 190                                        sym->flags &= ~SYMBOL_NEW;
 191                                        break;
 192                                }
 193                        case S_BOOLEAN:
 194                                if (p[0] == 'y') {
 195                                        sym->user.tri = yes;
 196                                        sym->flags &= ~SYMBOL_NEW;
 197                                        break;
 198                                }
 199                                if (p[0] == 'n') {
 200                                        sym->user.tri = no;
 201                                        sym->flags &= ~SYMBOL_NEW;
 202                                        break;
 203                                }
 204                                conf_warning("symbol value '%s' invalid for %s", p, sym->name);
 205                                break;
 206                        case S_STRING:
 207                                if (*p++ != '"')
 208                                        break;
 209                                for (p2 = p; (p2 = strpbrk(p2, "\"\\")); p2++) {
 210                                        if (*p2 == '"') {
 211                                                *p2 = 0;
 212                                                break;
 213                                        }
 214                                        memmove(p2, p2 + 1, strlen(p2));
 215                                }
 216                                if (!p2) {
 217                                        conf_warning("invalid string found");
 218                                        continue;
 219                                }
 220                        case S_INT:
 221                        case S_HEX:
 222                                if (sym_string_valid(sym, p)) {
 223                                        sym->user.val = strdup(p);
 224                                        sym->flags &= ~SYMBOL_NEW;
 225                                } else {
 226                                        if (p[0]) /* bbox */
 227                                                conf_warning("symbol value '%s' invalid for %s", p, sym->name);
 228                                        continue;
 229                                }
 230                                break;
 231                        default:
 232                                ;
 233                        }
 234                        break;
 235                case '\n':
 236                        break;
 237                default:
 238                        conf_warning("unexpected data");
 239                        continue;
 240                }
 241                if (sym && sym_is_choice_value(sym)) {
 242                        struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
 243                        switch (sym->user.tri) {
 244                        case no:
 245                                break;
 246                        case mod:
 247                                if (cs->user.tri == yes) {
 248                                        conf_warning("%s creates inconsistent choice state", sym->name);
 249                                        cs->flags |= SYMBOL_NEW;
 250                                }
 251                                break;
 252                        case yes:
 253                                if (cs->user.tri != no) {
 254                                        conf_warning("%s creates inconsistent choice state", sym->name);
 255                                        cs->flags |= SYMBOL_NEW;
 256                                } else
 257                                        cs->user.val = sym;
 258                                break;
 259                        }
 260                        cs->user.tri = E_OR(cs->user.tri, sym->user.tri);
 261                }
 262        }
 263        fclose(in);
 264
 265        if (modules_sym)
 266                sym_calc_value(modules_sym);
 267        return 0;
 268}
 269
 270int conf_read(const char *name)
 271{
 272        struct symbol *sym;
 273        struct property *prop;
 274        struct expr *e;
 275        int i;
 276
 277        if (conf_read_simple(name))
 278                return 1;
 279
 280        for_all_symbols(i, sym) {
 281                sym_calc_value(sym);
 282                if (sym_is_choice(sym) || (sym->flags & SYMBOL_AUTO))
 283                        goto sym_ok;
 284                if (sym_has_value(sym) && (sym->flags & SYMBOL_WRITE)) {
 285                        /* check that calculated value agrees with saved value */
 286                        switch (sym->type) {
 287                        case S_BOOLEAN:
 288                        case S_TRISTATE:
 289                                if (sym->user.tri != sym_get_tristate_value(sym))
 290                                        break;
 291                                if (!sym_is_choice(sym))
 292                                        goto sym_ok;
 293                        default:
 294                                if (!strcmp(sym->curr.val, sym->user.val))
 295                                        goto sym_ok;
 296                                break;
 297                        }
 298                } else if (!sym_has_value(sym) && !(sym->flags & SYMBOL_WRITE))
 299                        /* no previous value and not saved */
 300                        goto sym_ok;
 301                conf_unsaved++;
 302                /* maybe print value in verbose mode... */
 303        sym_ok:
 304                if (sym_has_value(sym) && !sym_is_choice_value(sym)) {
 305                        if (sym->visible == no)
 306                                sym->flags |= SYMBOL_NEW;
 307                        switch (sym->type) {
 308                        case S_STRING:
 309                        case S_INT:
 310                        case S_HEX:
 311                                if (!sym_string_within_range(sym, sym->user.val)) {
 312                                        sym->flags |= SYMBOL_NEW;
 313                                        sym->flags &= ~SYMBOL_VALID;
 314                                }
 315                        default:
 316                                break;
 317                        }
 318                }
 319                if (!sym_is_choice(sym))
 320                        continue;
 321                prop = sym_get_choice_prop(sym);
 322                for (e = prop->expr; e; e = e->left.expr)
 323                        if (e->right.sym->visible != no)
 324                                sym->flags |= e->right.sym->flags & SYMBOL_NEW;
 325        }
 326
 327        sym_change_count = conf_warnings || conf_unsaved;
 328
 329        return 0;
 330}
 331
 332int conf_write(const char *name)
 333{
 334        FILE *out, *out_h;
 335        struct symbol *sym;
 336        struct menu *menu;
 337        const char *basename;
 338        char dirname[128], tmpname[128], newname[128];
 339        int type, l;
 340        const char *str;
 341        time_t now;
 342        int use_timestamp = 1;
 343        char *env;
 344
 345        dirname[0] = 0;
 346        if (name && name[0]) {
 347                struct stat st;
 348                char *slash;
 349
 350                if (!stat(name, &st) && S_ISDIR(st.st_mode)) {
 351                        strcpy(dirname, name);
 352                        strcat(dirname, "/");
 353                        basename = conf_def_filename;
 354                } else if ((slash = strrchr(name, '/'))) {
 355                        int size = slash - name + 1;
 356                        memcpy(dirname, name, size);
 357                        dirname[size] = 0;
 358                        if (slash[1])
 359                                basename = slash + 1;
 360                        else
 361                                basename = conf_def_filename;
 362                } else
 363                        basename = name;
 364        } else
 365                basename = conf_def_filename;
 366
 367        sprintf(newname, "%s.tmpconfig.%d", dirname, (int)getpid());
 368        out = fopen(newname, "w");
 369        if (!out)
 370                return 1;
 371        out_h = NULL;
 372        if (!name) {
 373                out_h = fopen(".tmpconfig.h", "w");
 374                if (!out_h)
 375                        return 1;
 376                file_write_dep(NULL);
 377        }
 378        sym = sym_lookup("KERNELVERSION", 0);
 379        sym_calc_value(sym);
 380        time(&now);
 381        env = getenv("KCONFIG_NOTIMESTAMP");
 382        if (env && *env)
 383                use_timestamp = 0;
 384
 385        fprintf(out, _("#\n"
 386                       "# Automatically generated make config: don't edit\n"
 387                       "# Busybox version: %s\n"
 388                       "%s%s"
 389                       "#\n"),
 390                     sym_get_string_value(sym),
 391                     use_timestamp ? "# " : "",
 392                     use_timestamp ? ctime(&now) : "");
 393        if (out_h) {
 394                char buf[sizeof("#define AUTOCONF_TIMESTAMP "
 395                                "\"YYYY-MM-DD HH:MM:SS some_timezone\"\n")];
 396                buf[0] = '\0';
 397                if (use_timestamp) {
 398                        size_t ret = \
 399                                strftime(buf, sizeof(buf), "#define AUTOCONF_TIMESTAMP "
 400                                        "\"%Y-%m-%d %H:%M:%S %Z\"\n", localtime(&now));
 401                        /* if user has Factory timezone or some other odd install, the
 402                         * %Z above will overflow the string leaving us with undefined
 403                         * results ... so let's try again without the timezone.
 404                         */
 405                        if (ret == 0)
 406                                strftime(buf, sizeof(buf), "#define AUTOCONF_TIMESTAMP "
 407                                        "\"%Y-%m-%d %H:%M:%S\"\n", localtime(&now));
 408                } else { /* bbox */
 409                        strcpy(buf, "#define AUTOCONF_TIMESTAMP \"\"\n");
 410                }
 411                fprintf(out_h, "/*\n"
 412                               " * Automatically generated C config: don't edit\n"
 413                               " * Busybox version: %s\n"
 414                               " */\n"
 415                               "%s"
 416                               "\n",
 417                               sym_get_string_value(sym),
 418                               buf);
 419        }
 420        if (!sym_change_count)
 421                sym_clear_all_valid();
 422
 423        menu = rootmenu.list;
 424        while (menu) {
 425                sym = menu->sym;
 426                if (!sym) {
 427                        if (!menu_is_visible(menu))
 428                                goto next;
 429                        str = menu_get_prompt(menu);
 430                        fprintf(out, "\n"
 431                                     "#\n"
 432                                     "# %s\n"
 433                                     "#\n", str);
 434                        if (out_h)
 435                                fprintf(out_h, "\n"
 436                                               "/*\n"
 437                                               " * %s\n"
 438                                               " */\n", str);
 439                } else if (!(sym->flags & SYMBOL_CHOICE)) {
 440                        sym_calc_value(sym);
 441/* bbox: we want to see all syms
 442                        if (!(sym->flags & SYMBOL_WRITE))
 443                                goto next;
 444*/
 445                        sym->flags &= ~SYMBOL_WRITE;
 446                        type = sym->type;
 447                        if (type == S_TRISTATE) {
 448                                sym_calc_value(modules_sym);
 449                                if (modules_sym->curr.tri == no)
 450                                        type = S_BOOLEAN;
 451                        }
 452                        switch (type) {
 453                        case S_BOOLEAN:
 454                        case S_TRISTATE:
 455                                switch (sym_get_tristate_value(sym)) {
 456                                case no:
 457                                        fprintf(out, "# CONFIG_%s is not set\n", sym->name);
 458                                        if (out_h) {
 459                                                fprintf(out_h, "#undef CONFIG_%s\n", sym->name);
 460                                                /* bbox */
 461                                                fprintf(out_h, "#define ENABLE_%s 0\n", sym->name);
 462                                                fprintf(out_h, "#define IF_%s(...)\n", sym->name);
 463                                                fprintf(out_h, "#define IF_NOT_%s(...) __VA_ARGS__\n", sym->name);
 464                                        }
 465                                        break;
 466                                case mod:
 467                                        fprintf(out, "CONFIG_%s=m\n", sym->name);
 468                                        if (out_h)
 469                                                fprintf(out_h, "#define CONFIG_%s_MODULE 1\n", sym->name);
 470                                        break;
 471                                case yes:
 472                                        fprintf(out, "CONFIG_%s=y\n", sym->name);
 473                                        if (out_h) {
 474                                                fprintf(out_h, "#define CONFIG_%s 1\n", sym->name);
 475                                                /* bbox */
 476                                                fprintf(out_h, "#define ENABLE_%s 1\n", sym->name);
 477                                                fprintf(out_h, "#define IF_%s(...) __VA_ARGS__\n", sym->name);
 478                                                fprintf(out_h, "#define IF_NOT_%s(...)\n", sym->name);
 479                                        }
 480                                        break;
 481                                }
 482                                break;
 483                        case S_STRING:
 484                                // fix me
 485                                str = sym_get_string_value(sym);
 486                                fprintf(out, "CONFIG_%s=\"", sym->name);
 487                                if (out_h)
 488                                        fprintf(out_h, "#define CONFIG_%s \"", sym->name);
 489                                do {
 490                                        l = strcspn(str, "\"\\");
 491                                        if (l) {
 492                                                fwrite(str, l, 1, out);
 493                                                if (out_h)
 494                                                        fwrite(str, l, 1, out_h);
 495                                        }
 496                                        str += l;
 497                                        while (*str == '\\' || *str == '"') {
 498                                                fprintf(out, "\\%c", *str);
 499                                                if (out_h)
 500                                                        fprintf(out_h, "\\%c", *str);
 501                                                str++;
 502                                        }
 503                                } while (*str);
 504                                fputs("\"\n", out);
 505                                if (out_h) {
 506                                        fputs("\"\n", out_h);
 507                                        /* bbox */
 508                                        fprintf(out_h, "#define ENABLE_%s 1\n", sym->name);
 509                                        fprintf(out_h, "#define IF_%s(...) __VA_ARGS__\n", sym->name);
 510                                        fprintf(out_h, "#define IF_NOT_%s(...)\n", sym->name);
 511                                }
 512                                break;
 513                        case S_HEX:
 514                                str = sym_get_string_value(sym);
 515                                if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) {
 516                                        fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
 517                                        if (out_h) {
 518                                                fprintf(out_h, "#define CONFIG_%s 0x%s\n", sym->name, str);
 519                                                /* bbox */
 520                                                fprintf(out_h, "#define ENABLE_%s 1\n", sym->name);
 521                                                fprintf(out_h, "#define IF_%s(...) __VA_ARGS__\n", sym->name);
 522                                                fprintf(out_h, "#define IF_NOT_%s(...)\n", sym->name);
 523                                        }
 524                                        break;
 525                                }
 526                        case S_INT:
 527                                str = sym_get_string_value(sym);
 528                                if (!str[0])
 529                                        str = "0";
 530                                fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
 531                                if (out_h) {
 532                                        fprintf(out_h, "#define CONFIG_%s %s\n", sym->name, str);
 533                                        /* bbox */
 534                                        fprintf(out_h, "#define ENABLE_%s 1\n", sym->name);
 535                                        fprintf(out_h, "#define IF_%s(...) __VA_ARGS__\n", sym->name);
 536                                        fprintf(out_h, "#define IF_NOT_%s(...)\n", sym->name);
 537                                }
 538                                break;
 539                        }
 540                }
 541
 542        next:
 543                if (menu->list) {
 544                        menu = menu->list;
 545                        continue;
 546                }
 547                if (menu->next)
 548                        menu = menu->next;
 549                else while ((menu = menu->parent)) {
 550                        if (menu->next) {
 551                                menu = menu->next;
 552                                break;
 553                        }
 554                }
 555        }
 556        fclose(out);
 557        if (out_h) {
 558                fclose(out_h);
 559                rename(".tmpconfig.h", "include/autoconf.h");
 560        }
 561        if (!name || basename != conf_def_filename) {
 562                if (!name)
 563                        name = conf_def_filename;
 564                sprintf(tmpname, "%s.old", name);
 565                rename(name, tmpname);
 566        }
 567        sprintf(tmpname, "%s%s", dirname, basename);
 568        if (rename(newname, tmpname))
 569                return 1;
 570
 571        sym_change_count = 0;
 572
 573        return 0;
 574}
 575