Root/scripts/config/confdata.c

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

Archive Download this file



interactive