source: debwrt/trunk/config/mconf/confdata.c @ 1

Last change on this file since 1 was 1, checked in by amain, 13 years ago

Initial import of the build environment for DebWrt

File size: 11.1 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
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                       "# DebWrt 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}
Note: See TracBrowser for help on using the repository browser.