source: MondoRescue/branches/stable/mindi-busybox/scripts/kconfig/confdata.c @ 1770

Last change on this file since 1770 was 1765, checked in by Bruno Cornec, 12 years ago

Update to busybox 1.7.2

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