Root/scripts/kconfig/symbol.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 <ctype.h>
7#include <stdlib.h>
8#include <string.h>
9#include <regex.h>
10#include <sys/utsname.h>
11
12#define LKC_DIRECT_LINK
13#include "lkc.h"
14
15struct symbol symbol_yes = {
16    .name = "y",
17    .curr = { "y", yes },
18    .flags = SYMBOL_CONST|SYMBOL_VALID,
19}, symbol_mod = {
20    .name = "m",
21    .curr = { "m", mod },
22    .flags = SYMBOL_CONST|SYMBOL_VALID,
23}, symbol_no = {
24    .name = "n",
25    .curr = { "n", no },
26    .flags = SYMBOL_CONST|SYMBOL_VALID,
27}, symbol_empty = {
28    .name = "",
29    .curr = { "", no },
30    .flags = SYMBOL_VALID,
31};
32
33struct symbol *sym_defconfig_list;
34struct symbol *modules_sym;
35tristate modules_val;
36
37struct expr *sym_env_list;
38
39static void sym_add_default(struct symbol *sym, const char *def)
40{
41    struct property *prop = prop_alloc(P_DEFAULT, sym);
42
43    prop->expr = expr_alloc_symbol(sym_lookup(def, SYMBOL_CONST));
44}
45
46void sym_init(void)
47{
48    struct symbol *sym;
49    struct utsname uts;
50    static bool inited = false;
51
52    if (inited)
53        return;
54    inited = true;
55
56    uname(&uts);
57
58    sym = sym_lookup("UNAME_RELEASE", 0);
59    sym->type = S_STRING;
60    sym->flags |= SYMBOL_AUTO;
61    sym_add_default(sym, uts.release);
62}
63
64enum symbol_type sym_get_type(struct symbol *sym)
65{
66    enum symbol_type type = sym->type;
67
68    if (type == S_TRISTATE) {
69        if (sym_is_choice_value(sym) && sym->visible == yes)
70            type = S_BOOLEAN;
71        else if (modules_val == no)
72            type = S_BOOLEAN;
73    }
74    return type;
75}
76
77const char *sym_type_name(enum symbol_type type)
78{
79    switch (type) {
80    case S_BOOLEAN:
81        return "boolean";
82    case S_TRISTATE:
83        return "tristate";
84    case S_INT:
85        return "integer";
86    case S_HEX:
87        return "hex";
88    case S_STRING:
89        return "string";
90    case S_UNKNOWN:
91        return "unknown";
92    case S_OTHER:
93        break;
94    }
95    return "???";
96}
97
98struct property *sym_get_choice_prop(struct symbol *sym)
99{
100    struct property *prop;
101
102    for_all_choices(sym, prop)
103        return prop;
104    return NULL;
105}
106
107struct property *sym_get_env_prop(struct symbol *sym)
108{
109    struct property *prop;
110
111    for_all_properties(sym, prop, P_ENV)
112        return prop;
113    return NULL;
114}
115
116struct property *sym_get_default_prop(struct symbol *sym)
117{
118    struct property *prop;
119
120    for_all_defaults(sym, prop) {
121        prop->visible.tri = expr_calc_value(prop->visible.expr);
122        if (prop->visible.tri != no)
123            return prop;
124    }
125    return NULL;
126}
127
128static struct property *sym_get_range_prop(struct symbol *sym)
129{
130    struct property *prop;
131
132    for_all_properties(sym, prop, P_RANGE) {
133        prop->visible.tri = expr_calc_value(prop->visible.expr);
134        if (prop->visible.tri != no)
135            return prop;
136    }
137    return NULL;
138}
139
140static int sym_get_range_val(struct symbol *sym, int base)
141{
142    sym_calc_value(sym);
143    switch (sym->type) {
144    case S_INT:
145        base = 10;
146        break;
147    case S_HEX:
148        base = 16;
149        break;
150    default:
151        break;
152    }
153    return strtol(sym->curr.val, NULL, base);
154}
155
156static void sym_validate_range(struct symbol *sym)
157{
158    struct property *prop;
159    int base, val, val2;
160    char str[64];
161
162    switch (sym->type) {
163    case S_INT:
164        base = 10;
165        break;
166    case S_HEX:
167        base = 16;
168        break;
169    default:
170        return;
171    }
172    prop = sym_get_range_prop(sym);
173    if (!prop)
174        return;
175    val = strtol(sym->curr.val, NULL, base);
176    val2 = sym_get_range_val(prop->expr->left.sym, base);
177    if (val >= val2) {
178        val2 = sym_get_range_val(prop->expr->right.sym, base);
179        if (val <= val2)
180            return;
181    }
182    if (sym->type == S_INT)
183        sprintf(str, "%d", val2);
184    else
185        sprintf(str, "0x%x", val2);
186    sym->curr.val = strdup(str);
187}
188
189static void sym_calc_visibility(struct symbol *sym)
190{
191    struct property *prop;
192    tristate tri;
193
194    /* any prompt visible? */
195    tri = no;
196    for_all_prompts(sym, prop) {
197        prop->visible.tri = expr_calc_value(prop->visible.expr);
198        tri = EXPR_OR(tri, prop->visible.tri);
199    }
200    if (tri == mod && (sym->type != S_TRISTATE || modules_val == no))
201        tri = yes;
202    if (sym->visible != tri) {
203        sym->visible = tri;
204        sym_set_changed(sym);
205    }
206    if (sym_is_choice_value(sym))
207        return;
208    /* defaulting to "yes" if no explicit "depends on" are given */
209    tri = yes;
210    if (sym->dir_dep.expr)
211        tri = expr_calc_value(sym->dir_dep.expr);
212    if (tri == mod)
213        tri = yes;
214    if (sym->dir_dep.tri != tri) {
215        sym->dir_dep.tri = tri;
216        sym_set_changed(sym);
217    }
218    tri = no;
219    if (sym->rev_dep.expr)
220        tri = expr_calc_value(sym->rev_dep.expr);
221    if (tri == mod && sym_get_type(sym) == S_BOOLEAN)
222        tri = yes;
223    if (sym->rev_dep.tri != tri) {
224        sym->rev_dep.tri = tri;
225        sym_set_changed(sym);
226    }
227}
228
229/*
230 * Find the default symbol for a choice.
231 * First try the default values for the choice symbol
232 * Next locate the first visible choice value
233 * Return NULL if none was found
234 */
235struct symbol *sym_choice_default(struct symbol *sym)
236{
237    struct symbol *def_sym;
238    struct property *prop;
239    struct expr *e;
240
241    /* any of the defaults visible? */
242    for_all_defaults(sym, prop) {
243        prop->visible.tri = expr_calc_value(prop->visible.expr);
244        if (prop->visible.tri == no)
245            continue;
246        def_sym = prop_get_symbol(prop);
247        if (def_sym->visible != no)
248            return def_sym;
249    }
250
251    /* just get the first visible value */
252    prop = sym_get_choice_prop(sym);
253    expr_list_for_each_sym(prop->expr, e, def_sym)
254        if (def_sym->visible != no)
255            return def_sym;
256
257    /* failed to locate any defaults */
258    return NULL;
259}
260
261static struct symbol *sym_calc_choice(struct symbol *sym)
262{
263    struct symbol *def_sym;
264    struct property *prop;
265    struct expr *e;
266
267    /* first calculate all choice values' visibilities */
268    prop = sym_get_choice_prop(sym);
269    expr_list_for_each_sym(prop->expr, e, def_sym)
270        sym_calc_visibility(def_sym);
271
272    /* is the user choice visible? */
273    def_sym = sym->def[S_DEF_USER].val;
274    if (def_sym && def_sym->visible != no)
275        return def_sym;
276
277    def_sym = sym_choice_default(sym);
278
279    if (def_sym == NULL)
280        /* no choice? reset tristate value */
281        sym->curr.tri = no;
282
283    return def_sym;
284}
285
286void sym_calc_value(struct symbol *sym)
287{
288    struct symbol_value newval, oldval;
289    struct property *prop;
290    struct expr *e;
291
292    if (!sym)
293        return;
294
295    if (sym->flags & SYMBOL_VALID)
296        return;
297    sym->flags |= SYMBOL_VALID;
298
299    oldval = sym->curr;
300
301    switch (sym->type) {
302    case S_INT:
303    case S_HEX:
304    case S_STRING:
305        newval = symbol_empty.curr;
306        break;
307    case S_BOOLEAN:
308    case S_TRISTATE:
309        newval = symbol_no.curr;
310        break;
311    default:
312        sym->curr.val = sym->name;
313        sym->curr.tri = no;
314        return;
315    }
316    if (!sym_is_choice_value(sym))
317        sym->flags &= ~SYMBOL_WRITE;
318
319    sym_calc_visibility(sym);
320
321    /* set default if recursively called */
322    sym->curr = newval;
323
324    switch (sym_get_type(sym)) {
325    case S_BOOLEAN:
326    case S_TRISTATE:
327        if (sym_is_choice_value(sym) && sym->visible == yes) {
328            prop = sym_get_choice_prop(sym);
329            newval.tri = (prop_get_symbol(prop)->curr.val == sym) ? yes : no;
330        } else {
331            if (sym->visible != no) {
332                /* if the symbol is visible use the user value
333                 * if available, otherwise try the default value
334                 */
335                sym->flags |= SYMBOL_WRITE;
336                if (sym_has_value(sym)) {
337                    newval.tri = EXPR_AND(sym->def[S_DEF_USER].tri,
338                                  sym->visible);
339                    goto calc_newval;
340                }
341            }
342            if (sym->rev_dep.tri != no)
343                sym->flags |= SYMBOL_WRITE;
344            if (!sym_is_choice(sym)) {
345                prop = sym_get_default_prop(sym);
346                if (prop) {
347                    sym->flags |= SYMBOL_WRITE;
348                    newval.tri = EXPR_AND(expr_calc_value(prop->expr),
349                                  prop->visible.tri);
350                }
351            }
352        calc_newval:
353            if (sym->dir_dep.tri == no && sym->rev_dep.tri != no) {
354                struct expr *e;
355                e = expr_simplify_unmet_dep(sym->rev_dep.expr,
356                    sym->dir_dep.expr);
357                fprintf(stderr, "warning: (");
358                expr_fprint(e, stderr);
359                fprintf(stderr, ") selects %s which has unmet direct dependencies (",
360                    sym->name);
361                expr_fprint(sym->dir_dep.expr, stderr);
362                fprintf(stderr, ")\n");
363                expr_free(e);
364            }
365            newval.tri = EXPR_OR(newval.tri, sym->rev_dep.tri);
366        }
367        if (newval.tri == mod && sym_get_type(sym) == S_BOOLEAN)
368            newval.tri = yes;
369        break;
370    case S_STRING:
371    case S_HEX:
372    case S_INT:
373        if (sym->visible != no) {
374            sym->flags |= SYMBOL_WRITE;
375            if (sym_has_value(sym)) {
376                newval.val = sym->def[S_DEF_USER].val;
377                break;
378            }
379        }
380        prop = sym_get_default_prop(sym);
381        if (prop) {
382            struct symbol *ds = prop_get_symbol(prop);
383            if (ds) {
384                sym->flags |= SYMBOL_WRITE;
385                sym_calc_value(ds);
386                newval.val = ds->curr.val;
387            }
388        }
389        break;
390    default:
391        ;
392    }
393
394    sym->curr = newval;
395    if (sym_is_choice(sym) && newval.tri == yes)
396        sym->curr.val = sym_calc_choice(sym);
397    sym_validate_range(sym);
398
399    if (memcmp(&oldval, &sym->curr, sizeof(oldval))) {
400        sym_set_changed(sym);
401        if (modules_sym == sym) {
402            sym_set_all_changed();
403            modules_val = modules_sym->curr.tri;
404        }
405    }
406
407    if (sym_is_choice(sym)) {
408        struct symbol *choice_sym;
409
410        prop = sym_get_choice_prop(sym);
411        expr_list_for_each_sym(prop->expr, e, choice_sym) {
412            if ((sym->flags & SYMBOL_WRITE) &&
413                choice_sym->visible != no)
414                choice_sym->flags |= SYMBOL_WRITE;
415            if (sym->flags & SYMBOL_CHANGED)
416                sym_set_changed(choice_sym);
417        }
418    }
419
420    if (sym->flags & SYMBOL_AUTO)
421        sym->flags &= ~SYMBOL_WRITE;
422}
423
424void sym_clear_all_valid(void)
425{
426    struct symbol *sym;
427    int i;
428
429    for_all_symbols(i, sym)
430        sym->flags &= ~SYMBOL_VALID;
431    sym_add_change_count(1);
432    if (modules_sym)
433        sym_calc_value(modules_sym);
434}
435
436void sym_set_changed(struct symbol *sym)
437{
438    struct property *prop;
439
440    sym->flags |= SYMBOL_CHANGED;
441    for (prop = sym->prop; prop; prop = prop->next) {
442        if (prop->menu)
443            prop->menu->flags |= MENU_CHANGED;
444    }
445}
446
447void sym_set_all_changed(void)
448{
449    struct symbol *sym;
450    int i;
451
452    for_all_symbols(i, sym)
453        sym_set_changed(sym);
454}
455
456bool sym_tristate_within_range(struct symbol *sym, tristate val)
457{
458    int type = sym_get_type(sym);
459
460    if (sym->visible == no)
461        return false;
462
463    if (type != S_BOOLEAN && type != S_TRISTATE)
464        return false;
465
466    if (type == S_BOOLEAN && val == mod)
467        return false;
468    if (sym->visible <= sym->rev_dep.tri)
469        return false;
470    if (sym_is_choice_value(sym) && sym->visible == yes)
471        return val == yes;
472    return val >= sym->rev_dep.tri && val <= sym->visible;
473}
474
475bool sym_set_tristate_value(struct symbol *sym, tristate val)
476{
477    tristate oldval = sym_get_tristate_value(sym);
478
479    if (oldval != val && !sym_tristate_within_range(sym, val))
480        return false;
481
482    if (!(sym->flags & SYMBOL_DEF_USER)) {
483        sym->flags |= SYMBOL_DEF_USER;
484        sym_set_changed(sym);
485    }
486    /*
487     * setting a choice value also resets the new flag of the choice
488     * symbol and all other choice values.
489     */
490    if (sym_is_choice_value(sym) && val == yes) {
491        struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
492        struct property *prop;
493        struct expr *e;
494
495        cs->def[S_DEF_USER].val = sym;
496        cs->flags |= SYMBOL_DEF_USER;
497        prop = sym_get_choice_prop(cs);
498        for (e = prop->expr; e; e = e->left.expr) {
499            if (e->right.sym->visible != no)
500                e->right.sym->flags |= SYMBOL_DEF_USER;
501        }
502    }
503
504    sym->def[S_DEF_USER].tri = val;
505    if (oldval != val)
506        sym_clear_all_valid();
507
508    return true;
509}
510
511tristate sym_toggle_tristate_value(struct symbol *sym)
512{
513    tristate oldval, newval;
514
515    oldval = newval = sym_get_tristate_value(sym);
516    do {
517        switch (newval) {
518        case no:
519            newval = mod;
520            break;
521        case mod:
522            newval = yes;
523            break;
524        case yes:
525            newval = no;
526            break;
527        }
528        if (sym_set_tristate_value(sym, newval))
529            break;
530    } while (oldval != newval);
531    return newval;
532}
533
534bool sym_string_valid(struct symbol *sym, const char *str)
535{
536    signed char ch;
537
538    switch (sym->type) {
539    case S_STRING:
540        return true;
541    case S_INT:
542        ch = *str++;
543        if (ch == '-')
544            ch = *str++;
545        if (!isdigit(ch))
546            return false;
547        if (ch == '0' && *str != 0)
548            return false;
549        while ((ch = *str++)) {
550            if (!isdigit(ch))
551                return false;
552        }
553        return true;
554    case S_HEX:
555        if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
556            str += 2;
557        ch = *str++;
558        do {
559            if (!isxdigit(ch))
560                return false;
561        } while ((ch = *str++));
562        return true;
563    case S_BOOLEAN:
564    case S_TRISTATE:
565        switch (str[0]) {
566        case 'y': case 'Y':
567        case 'm': case 'M':
568        case 'n': case 'N':
569            return true;
570        }
571        return false;
572    default:
573        return false;
574    }
575}
576
577bool sym_string_within_range(struct symbol *sym, const char *str)
578{
579    struct property *prop;
580    int val;
581
582    switch (sym->type) {
583    case S_STRING:
584        return sym_string_valid(sym, str);
585    case S_INT:
586        if (!sym_string_valid(sym, str))
587            return false;
588        prop = sym_get_range_prop(sym);
589        if (!prop)
590            return true;
591        val = strtol(str, NULL, 10);
592        return val >= sym_get_range_val(prop->expr->left.sym, 10) &&
593               val <= sym_get_range_val(prop->expr->right.sym, 10);
594    case S_HEX:
595        if (!sym_string_valid(sym, str))
596            return false;
597        prop = sym_get_range_prop(sym);
598        if (!prop)
599            return true;
600        val = strtol(str, NULL, 16);
601        return val >= sym_get_range_val(prop->expr->left.sym, 16) &&
602               val <= sym_get_range_val(prop->expr->right.sym, 16);
603    case S_BOOLEAN:
604    case S_TRISTATE:
605        switch (str[0]) {
606        case 'y': case 'Y':
607            return sym_tristate_within_range(sym, yes);
608        case 'm': case 'M':
609            return sym_tristate_within_range(sym, mod);
610        case 'n': case 'N':
611            return sym_tristate_within_range(sym, no);
612        }
613        return false;
614    default:
615        return false;
616    }
617}
618
619bool sym_set_string_value(struct symbol *sym, const char *newval)
620{
621    const char *oldval;
622    char *val;
623    int size;
624
625    switch (sym->type) {
626    case S_BOOLEAN:
627    case S_TRISTATE:
628        switch (newval[0]) {
629        case 'y': case 'Y':
630            return sym_set_tristate_value(sym, yes);
631        case 'm': case 'M':
632            return sym_set_tristate_value(sym, mod);
633        case 'n': case 'N':
634            return sym_set_tristate_value(sym, no);
635        }
636        return false;
637    default:
638        ;
639    }
640
641    if (!sym_string_within_range(sym, newval))
642        return false;
643
644    if (!(sym->flags & SYMBOL_DEF_USER)) {
645        sym->flags |= SYMBOL_DEF_USER;
646        sym_set_changed(sym);
647    }
648
649    oldval = sym->def[S_DEF_USER].val;
650    size = strlen(newval) + 1;
651    if (sym->type == S_HEX && (newval[0] != '0' || (newval[1] != 'x' && newval[1] != 'X'))) {
652        size += 2;
653        sym->def[S_DEF_USER].val = val = malloc(size);
654        *val++ = '0';
655        *val++ = 'x';
656    } else if (!oldval || strcmp(oldval, newval))
657        sym->def[S_DEF_USER].val = val = malloc(size);
658    else
659        return true;
660
661    strcpy(val, newval);
662    free((void *)oldval);
663    sym_clear_all_valid();
664
665    return true;
666}
667
668/*
669 * Find the default value associated to a symbol.
670 * For tristate symbol handle the modules=n case
671 * in which case "m" becomes "y".
672 * If the symbol does not have any default then fallback
673 * to the fixed default values.
674 */
675const char *sym_get_string_default(struct symbol *sym)
676{
677    struct property *prop;
678    struct symbol *ds;
679    const char *str;
680    tristate val;
681
682    sym_calc_visibility(sym);
683    sym_calc_value(modules_sym);
684    val = symbol_no.curr.tri;
685    str = symbol_empty.curr.val;
686
687    /* If symbol has a default value look it up */
688    prop = sym_get_default_prop(sym);
689    if (prop != NULL) {
690        switch (sym->type) {
691        case S_BOOLEAN:
692        case S_TRISTATE:
693            /* The visibility may limit the value from yes => mod */
694            val = EXPR_AND(expr_calc_value(prop->expr), prop->visible.tri);
695            break;
696        default:
697            /*
698             * The following fails to handle the situation
699             * where a default value is further limited by
700             * the valid range.
701             */
702            ds = prop_get_symbol(prop);
703            if (ds != NULL) {
704                sym_calc_value(ds);
705                str = (const char *)ds->curr.val;
706            }
707        }
708    }
709
710    /* Handle select statements */
711    val = EXPR_OR(val, sym->rev_dep.tri);
712
713    /* transpose mod to yes if modules are not enabled */
714    if (val == mod)
715        if (!sym_is_choice_value(sym) && modules_sym->curr.tri == no)
716            val = yes;
717
718    /* transpose mod to yes if type is bool */
719    if (sym->type == S_BOOLEAN && val == mod)
720        val = yes;
721
722    switch (sym->type) {
723    case S_BOOLEAN:
724    case S_TRISTATE:
725        switch (val) {
726        case no: return "n";
727        case mod: return "m";
728        case yes: return "y";
729        }
730    case S_INT:
731    case S_HEX:
732        return str;
733    case S_STRING:
734        return str;
735    case S_OTHER:
736    case S_UNKNOWN:
737        break;
738    }
739    return "";
740}
741
742const char *sym_get_string_value(struct symbol *sym)
743{
744    tristate val;
745
746    switch (sym->type) {
747    case S_BOOLEAN:
748    case S_TRISTATE:
749        val = sym_get_tristate_value(sym);
750        switch (val) {
751        case no:
752            return "n";
753        case mod:
754            return "m";
755        case yes:
756            return "y";
757        }
758        break;
759    default:
760        ;
761    }
762    return (const char *)sym->curr.val;
763}
764
765bool sym_is_changable(struct symbol *sym)
766{
767    return sym->visible > sym->rev_dep.tri;
768}
769
770static unsigned strhash(const char *s)
771{
772    /* fnv32 hash */
773    unsigned hash = 2166136261U;
774    for (; *s; s++)
775        hash = (hash ^ *s) * 0x01000193;
776    return hash;
777}
778
779struct symbol *sym_lookup(const char *name, int flags)
780{
781    struct symbol *symbol;
782    char *new_name;
783    int hash;
784
785    if (name) {
786        if (name[0] && !name[1]) {
787            switch (name[0]) {
788            case 'y': return &symbol_yes;
789            case 'm': return &symbol_mod;
790            case 'n': return &symbol_no;
791            }
792        }
793        hash = strhash(name) % SYMBOL_HASHSIZE;
794
795        for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
796            if (symbol->name &&
797                !strcmp(symbol->name, name) &&
798                (flags ? symbol->flags & flags
799                   : !(symbol->flags & (SYMBOL_CONST|SYMBOL_CHOICE))))
800                return symbol;
801        }
802        new_name = strdup(name);
803    } else {
804        new_name = NULL;
805        hash = 0;
806    }
807
808    symbol = malloc(sizeof(*symbol));
809    memset(symbol, 0, sizeof(*symbol));
810    symbol->name = new_name;
811    symbol->type = S_UNKNOWN;
812    symbol->flags |= flags;
813
814    symbol->next = symbol_hash[hash];
815    symbol_hash[hash] = symbol;
816
817    return symbol;
818}
819
820struct symbol *sym_find(const char *name)
821{
822    struct symbol *symbol = NULL;
823    int hash = 0;
824
825    if (!name)
826        return NULL;
827
828    if (name[0] && !name[1]) {
829        switch (name[0]) {
830        case 'y': return &symbol_yes;
831        case 'm': return &symbol_mod;
832        case 'n': return &symbol_no;
833        }
834    }
835    hash = strhash(name) % SYMBOL_HASHSIZE;
836
837    for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
838        if (symbol->name &&
839            !strcmp(symbol->name, name) &&
840            !(symbol->flags & SYMBOL_CONST))
841                break;
842    }
843
844    return symbol;
845}
846
847/*
848 * Expand symbol's names embedded in the string given in argument. Symbols'
849 * name to be expanded shall be prefixed by a '$'. Unknown symbol expands to
850 * the empty string.
851 */
852const char *sym_expand_string_value(const char *in)
853{
854    const char *src;
855    char *res;
856    size_t reslen;
857
858    reslen = strlen(in) + 1;
859    res = malloc(reslen);
860    res[0] = '\0';
861
862    while ((src = strchr(in, '$'))) {
863        char *p, name[SYMBOL_MAXLENGTH];
864        const char *symval = "";
865        struct symbol *sym;
866        size_t newlen;
867
868        strncat(res, in, src - in);
869        src++;
870
871        p = name;
872        while (isalnum(*src) || *src == '_')
873            *p++ = *src++;
874        *p = '\0';
875
876        sym = sym_find(name);
877        if (sym != NULL) {
878            sym_calc_value(sym);
879            symval = sym_get_string_value(sym);
880        }
881
882        newlen = strlen(res) + strlen(symval) + strlen(src) + 1;
883        if (newlen > reslen) {
884            reslen = newlen;
885            res = realloc(res, reslen);
886        }
887
888        strcat(res, symval);
889        in = src;
890    }
891    strcat(res, in);
892
893    return res;
894}
895
896struct symbol **sym_re_search(const char *pattern)
897{
898    struct symbol *sym, **sym_arr = NULL;
899    int i, cnt, size;
900    regex_t re;
901
902    cnt = size = 0;
903    /* Skip if empty */
904    if (strlen(pattern) == 0)
905        return NULL;
906    if (regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB|REG_ICASE))
907        return NULL;
908
909    for_all_symbols(i, sym) {
910        if (sym->flags & SYMBOL_CONST || !sym->name)
911            continue;
912        if (regexec(&re, sym->name, 0, NULL, 0))
913            continue;
914        if (cnt + 1 >= size) {
915            void *tmp = sym_arr;
916            size += 16;
917            sym_arr = realloc(sym_arr, size * sizeof(struct symbol *));
918            if (!sym_arr) {
919                free(tmp);
920                return NULL;
921            }
922        }
923        sym_calc_value(sym);
924        sym_arr[cnt++] = sym;
925    }
926    if (sym_arr)
927        sym_arr[cnt] = NULL;
928    regfree(&re);
929
930    return sym_arr;
931}
932
933/*
934 * When we check for recursive dependencies we use a stack to save
935 * current state so we can print out relevant info to user.
936 * The entries are located on the call stack so no need to free memory.
937 * Note inser() remove() must always match to properly clear the stack.
938 */
939static struct dep_stack {
940    struct dep_stack *prev, *next;
941    struct symbol *sym;
942    struct property *prop;
943    struct expr *expr;
944} *check_top;
945
946static void dep_stack_insert(struct dep_stack *stack, struct symbol *sym)
947{
948    memset(stack, 0, sizeof(*stack));
949    if (check_top)
950        check_top->next = stack;
951    stack->prev = check_top;
952    stack->sym = sym;
953    check_top = stack;
954}
955
956static void dep_stack_remove(void)
957{
958    check_top = check_top->prev;
959    if (check_top)
960        check_top->next = NULL;
961}
962
963/*
964 * Called when we have detected a recursive dependency.
965 * check_top point to the top of the stact so we use
966 * the ->prev pointer to locate the bottom of the stack.
967 */
968static void sym_check_print_recursive(struct symbol *last_sym)
969{
970    struct dep_stack *stack;
971    struct symbol *sym, *next_sym;
972    struct menu *menu = NULL;
973    struct property *prop;
974    struct dep_stack cv_stack;
975
976    if (sym_is_choice_value(last_sym)) {
977        dep_stack_insert(&cv_stack, last_sym);
978        last_sym = prop_get_symbol(sym_get_choice_prop(last_sym));
979    }
980
981    for (stack = check_top; stack != NULL; stack = stack->prev)
982        if (stack->sym == last_sym)
983            break;
984    if (!stack) {
985        fprintf(stderr, "unexpected recursive dependency error\n");
986        return;
987    }
988
989    for (; stack; stack = stack->next) {
990        sym = stack->sym;
991        next_sym = stack->next ? stack->next->sym : last_sym;
992        prop = stack->prop;
993        if (prop == NULL)
994            prop = stack->sym->prop;
995
996        /* for choice values find the menu entry (used below) */
997        if (sym_is_choice(sym) || sym_is_choice_value(sym)) {
998            for (prop = sym->prop; prop; prop = prop->next) {
999                menu = prop->menu;
1000                if (prop->menu)
1001                    break;
1002            }
1003        }
1004        if (stack->sym == last_sym)
1005            fprintf(stderr, "%s:%d:error: recursive dependency detected!\n",
1006                prop->file->name, prop->lineno);
1007        if (stack->expr) {
1008            fprintf(stderr, "%s:%d:\tsymbol %s %s value contains %s\n",
1009                prop->file->name, prop->lineno,
1010                sym->name ? sym->name : "<choice>",
1011                prop_get_type_name(prop->type),
1012                next_sym->name ? next_sym->name : "<choice>");
1013        } else if (stack->prop) {
1014            fprintf(stderr, "%s:%d:\tsymbol %s depends on %s\n",
1015                prop->file->name, prop->lineno,
1016                sym->name ? sym->name : "<choice>",
1017                next_sym->name ? next_sym->name : "<choice>");
1018        } else if (sym_is_choice(sym)) {
1019            fprintf(stderr, "%s:%d:\tchoice %s contains symbol %s\n",
1020                menu->file->name, menu->lineno,
1021                sym->name ? sym->name : "<choice>",
1022                next_sym->name ? next_sym->name : "<choice>");
1023        } else if (sym_is_choice_value(sym)) {
1024            fprintf(stderr, "%s:%d:\tsymbol %s is part of choice %s\n",
1025                menu->file->name, menu->lineno,
1026                sym->name ? sym->name : "<choice>",
1027                next_sym->name ? next_sym->name : "<choice>");
1028        } else {
1029            fprintf(stderr, "%s:%d:\tsymbol %s is selected by %s\n",
1030                prop->file->name, prop->lineno,
1031                sym->name ? sym->name : "<choice>",
1032                next_sym->name ? next_sym->name : "<choice>");
1033        }
1034    }
1035
1036    if (check_top == &cv_stack)
1037        dep_stack_remove();
1038}
1039
1040static struct symbol *sym_check_expr_deps(struct expr *e)
1041{
1042    struct symbol *sym;
1043
1044    if (!e)
1045        return NULL;
1046    switch (e->type) {
1047    case E_OR:
1048    case E_AND:
1049        sym = sym_check_expr_deps(e->left.expr);
1050        if (sym)
1051            return sym;
1052        return sym_check_expr_deps(e->right.expr);
1053    case E_NOT:
1054        return sym_check_expr_deps(e->left.expr);
1055    case E_EQUAL:
1056    case E_UNEQUAL:
1057        sym = sym_check_deps(e->left.sym);
1058        if (sym)
1059            return sym;
1060        return sym_check_deps(e->right.sym);
1061    case E_SYMBOL:
1062        return sym_check_deps(e->left.sym);
1063    default:
1064        break;
1065    }
1066    printf("Oops! How to check %d?\n", e->type);
1067    return NULL;
1068}
1069
1070/* return NULL when dependencies are OK */
1071static struct symbol *sym_check_sym_deps(struct symbol *sym)
1072{
1073    struct symbol *sym2;
1074    struct property *prop;
1075    struct dep_stack stack;
1076
1077    dep_stack_insert(&stack, sym);
1078
1079    sym2 = sym_check_expr_deps(sym->rev_dep.expr);
1080    if (sym2)
1081        goto out;
1082
1083    for (prop = sym->prop; prop; prop = prop->next) {
1084        if (prop->type == P_CHOICE || prop->type == P_SELECT)
1085            continue;
1086        stack.prop = prop;
1087        sym2 = sym_check_expr_deps(prop->visible.expr);
1088        if (sym2)
1089            break;
1090        if (prop->type != P_DEFAULT || sym_is_choice(sym))
1091            continue;
1092        stack.expr = prop->expr;
1093        sym2 = sym_check_expr_deps(prop->expr);
1094        if (sym2)
1095            break;
1096        stack.expr = NULL;
1097    }
1098
1099out:
1100    dep_stack_remove();
1101
1102    return sym2;
1103}
1104
1105static struct symbol *sym_check_choice_deps(struct symbol *choice)
1106{
1107    struct symbol *sym, *sym2;
1108    struct property *prop;
1109    struct expr *e;
1110    struct dep_stack stack;
1111
1112    dep_stack_insert(&stack, choice);
1113
1114    prop = sym_get_choice_prop(choice);
1115    expr_list_for_each_sym(prop->expr, e, sym)
1116        sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);
1117
1118    choice->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);
1119    sym2 = sym_check_sym_deps(choice);
1120    choice->flags &= ~SYMBOL_CHECK;
1121    if (sym2)
1122        goto out;
1123
1124    expr_list_for_each_sym(prop->expr, e, sym) {
1125        sym2 = sym_check_sym_deps(sym);
1126        if (sym2)
1127            break;
1128    }
1129out:
1130    expr_list_for_each_sym(prop->expr, e, sym)
1131        sym->flags &= ~SYMBOL_CHECK;
1132
1133    if (sym2 && sym_is_choice_value(sym2) &&
1134        prop_get_symbol(sym_get_choice_prop(sym2)) == choice)
1135        sym2 = choice;
1136
1137    dep_stack_remove();
1138
1139    return sym2;
1140}
1141
1142struct symbol *sym_check_deps(struct symbol *sym)
1143{
1144    struct symbol *sym2;
1145    struct property *prop;
1146
1147    if (sym->flags & SYMBOL_CHECK) {
1148        sym_check_print_recursive(sym);
1149        return sym;
1150    }
1151    if (sym->flags & SYMBOL_CHECKED)
1152        return NULL;
1153
1154    if (sym_is_choice_value(sym)) {
1155        struct dep_stack stack;
1156
1157        /* for choice groups start the check with main choice symbol */
1158        dep_stack_insert(&stack, sym);
1159        prop = sym_get_choice_prop(sym);
1160        sym2 = sym_check_deps(prop_get_symbol(prop));
1161        dep_stack_remove();
1162    } else if (sym_is_choice(sym)) {
1163        sym2 = sym_check_choice_deps(sym);
1164    } else {
1165        sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);
1166        sym2 = sym_check_sym_deps(sym);
1167        sym->flags &= ~SYMBOL_CHECK;
1168    }
1169
1170    if (sym2 && sym2 == sym)
1171        sym2 = NULL;
1172
1173    return sym2;
1174}
1175
1176struct property *prop_alloc(enum prop_type type, struct symbol *sym)
1177{
1178    struct property *prop;
1179    struct property **propp;
1180
1181    prop = malloc(sizeof(*prop));
1182    memset(prop, 0, sizeof(*prop));
1183    prop->type = type;
1184    prop->sym = sym;
1185    prop->file = current_file;
1186    prop->lineno = zconf_lineno();
1187
1188    /* append property to the prop list of symbol */
1189    if (sym) {
1190        for (propp = &sym->prop; *propp; propp = &(*propp)->next)
1191            ;
1192        *propp = prop;
1193    }
1194
1195    return prop;
1196}
1197
1198struct symbol *prop_get_symbol(struct property *prop)
1199{
1200    if (prop->expr && (prop->expr->type == E_SYMBOL ||
1201               prop->expr->type == E_LIST))
1202        return prop->expr->left.sym;
1203    return NULL;
1204}
1205
1206const char *prop_get_type_name(enum prop_type type)
1207{
1208    switch (type) {
1209    case P_PROMPT:
1210        return "prompt";
1211    case P_ENV:
1212        return "env";
1213    case P_COMMENT:
1214        return "comment";
1215    case P_MENU:
1216        return "menu";
1217    case P_DEFAULT:
1218        return "default";
1219    case P_CHOICE:
1220        return "choice";
1221    case P_SELECT:
1222        return "select";
1223    case P_RANGE:
1224        return "range";
1225    case P_SYMBOL:
1226        return "symbol";
1227    case P_UNKNOWN:
1228        break;
1229    }
1230    return "unknown";
1231}
1232
1233static void prop_add_env(const char *env)
1234{
1235    struct symbol *sym, *sym2;
1236    struct property *prop;
1237    char *p;
1238
1239    sym = current_entry->sym;
1240    sym->flags |= SYMBOL_AUTO;
1241    for_all_properties(sym, prop, P_ENV) {
1242        sym2 = prop_get_symbol(prop);
1243        if (strcmp(sym2->name, env))
1244            menu_warn(current_entry, "redefining environment symbol from %s",
1245                  sym2->name);
1246        return;
1247    }
1248
1249    prop = prop_alloc(P_ENV, sym);
1250    prop->expr = expr_alloc_symbol(sym_lookup(env, SYMBOL_CONST));
1251
1252    sym_env_list = expr_alloc_one(E_LIST, sym_env_list);
1253    sym_env_list->right.sym = sym;
1254
1255    p = getenv(env);
1256    if (p)
1257        sym_add_default(sym, p);
1258    else
1259        menu_warn(current_entry, "environment variable %s undefined", env);
1260}
1261

Archive Download this file



interactive