OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [uClibc/] [extra/] [config/] [symbol.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1325 phoenix
/*
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 <sys/utsname.h>
10
 
11
#define LKC_DIRECT_LINK
12
#include "lkc.h"
13
 
14
struct symbol symbol_yes = {
15
        name: "y",
16
        curr: { "y", yes },
17
        flags: SYMBOL_YES|SYMBOL_VALID,
18
}, symbol_mod = {
19
        name: "m",
20
        curr: { "m", mod },
21
        flags: SYMBOL_MOD|SYMBOL_VALID,
22
}, symbol_no = {
23
        name: "n",
24
        curr: { "n", no },
25
        flags: SYMBOL_NO|SYMBOL_VALID,
26
}, symbol_empty = {
27
        name: "",
28
        curr: { "", no },
29
        flags: SYMBOL_VALID,
30
};
31
 
32
int sym_change_count;
33
struct symbol *modules_sym;
34
 
35
void sym_add_default(struct symbol *sym, const char *def)
36
{
37
        struct property *prop = prop_alloc(P_DEFAULT, sym);
38
 
39
        prop->expr = expr_alloc_symbol(sym_lookup(def, 1));
40
}
41
 
42
void sym_init(void)
43
{
44
        struct symbol *sym;
45
        char *p;
46
        static bool inited = false;
47
 
48
        if (inited)
49
                return;
50
        inited = true;
51
 
52
        sym = sym_lookup("VERSION", 0);
53
        sym->type = S_STRING;
54
        sym->flags |= SYMBOL_AUTO;
55
        p = getenv("VERSION");
56
        if (p)
57
                sym_add_default(sym, p);
58
 
59
        sym = sym_lookup("TARGET_ARCH", 0);
60
        sym->type = S_STRING;
61
        sym->flags |= SYMBOL_AUTO;
62
        p = getenv("TARGET_ARCH");
63
        if (p)
64
                sym_add_default(sym, p);
65
 
66
}
67
 
68
enum symbol_type sym_get_type(struct symbol *sym)
69
{
70
        enum symbol_type type = sym->type;
71
 
72
        if (type == S_TRISTATE) {
73
                if (sym_is_choice_value(sym) && sym->visible == yes)
74
                        type = S_BOOLEAN;
75
                else {
76
                        sym_calc_value(modules_sym);
77
                        if (modules_sym->curr.tri == no)
78
                                type = S_BOOLEAN;
79
                }
80
        }
81
        return type;
82
}
83
 
84
const char *sym_type_name(enum symbol_type type)
85
{
86
        switch (type) {
87
        case S_BOOLEAN:
88
                return "boolean";
89
        case S_TRISTATE:
90
                return "tristate";
91
        case S_INT:
92
                return "integer";
93
        case S_HEX:
94
                return "hex";
95
        case S_STRING:
96
                return "string";
97
        case S_UNKNOWN:
98
                return "unknown";
99
        case S_OTHER:
100
                break;
101
        }
102
        return "???";
103
}
104
 
105
struct property *sym_get_choice_prop(struct symbol *sym)
106
{
107
        struct property *prop;
108
 
109
        for_all_choices(sym, prop)
110
                return prop;
111
        return NULL;
112
}
113
 
114
struct property *sym_get_default_prop(struct symbol *sym)
115
{
116
        struct property *prop;
117
 
118
        for_all_defaults(sym, prop) {
119
                prop->visible.tri = expr_calc_value(prop->visible.expr);
120
                if (prop->visible.tri != no)
121
                        return prop;
122
        }
123
        return NULL;
124
}
125
 
126
struct property *sym_get_range_prop(struct symbol *sym)
127
{
128
        struct property *prop;
129
 
130
        for_all_properties(sym, prop, P_RANGE) {
131
                prop->visible.tri = expr_calc_value(prop->visible.expr);
132
                if (prop->visible.tri != no)
133
                        return prop;
134
        }
135
        return NULL;
136
}
137
 
138
static void sym_calc_visibility(struct symbol *sym)
139
{
140
        struct property *prop;
141
        tristate tri;
142
 
143
        /* any prompt visible? */
144
        tri = no;
145
        for_all_prompts(sym, prop) {
146
                prop->visible.tri = expr_calc_value(prop->visible.expr);
147
                tri = E_OR(tri, prop->visible.tri);
148
        }
149
        if (sym->visible != tri) {
150
                sym->visible = tri;
151
                sym_set_changed(sym);
152
        }
153
        if (sym_is_choice_value(sym))
154
                return;
155
        tri = no;
156
        if (sym->rev_dep.expr)
157
                tri = expr_calc_value(sym->rev_dep.expr);
158
        if (sym->rev_dep.tri != tri) {
159
                sym->rev_dep.tri = tri;
160
                sym_set_changed(sym);
161
        }
162
}
163
 
164
static struct symbol *sym_calc_choice(struct symbol *sym)
165
{
166
        struct symbol *def_sym;
167
        struct property *prop;
168
        struct expr *e;
169
 
170
        /* is the user choice visible? */
171
        def_sym = sym->user.val;
172
        if (def_sym) {
173
                sym_calc_visibility(def_sym);
174
                if (def_sym->visible != no)
175
                        return def_sym;
176
        }
177
 
178
        /* any of the defaults visible? */
179
        for_all_defaults(sym, prop) {
180
                prop->visible.tri = expr_calc_value(prop->visible.expr);
181
                if (prop->visible.tri == no)
182
                        continue;
183
                def_sym = prop_get_symbol(prop);
184
                sym_calc_visibility(def_sym);
185
                if (def_sym->visible != no)
186
                        return def_sym;
187
        }
188
 
189
        /* just get the first visible value */
190
        prop = sym_get_choice_prop(sym);
191
        for (e = prop->expr; e; e = e->left.expr) {
192
                def_sym = e->right.sym;
193
                sym_calc_visibility(def_sym);
194
                if (def_sym->visible != no)
195
                        return def_sym;
196
        }
197
 
198
        /* no choice? reset tristate value */
199
        sym->curr.tri = no;
200
        return NULL;
201
}
202
 
203
void sym_calc_value(struct symbol *sym)
204
{
205
        struct symbol_value newval, oldval;
206
        struct property *prop;
207
        struct expr *e;
208
 
209
        if (!sym)
210
                return;
211
 
212
        if (sym->flags & SYMBOL_VALID)
213
                return;
214
        sym->flags |= SYMBOL_VALID;
215
 
216
        oldval = sym->curr;
217
 
218
        switch (sym->type) {
219
        case S_INT:
220
        case S_HEX:
221
        case S_STRING:
222
                newval = symbol_empty.curr;
223
                break;
224
        case S_BOOLEAN:
225
        case S_TRISTATE:
226
                newval = symbol_no.curr;
227
                break;
228
        default:
229
                sym->curr.val = sym->name;
230
                sym->curr.tri = no;
231
                return;
232
        }
233
        if (!sym_is_choice_value(sym))
234
                sym->flags &= ~SYMBOL_WRITE;
235
 
236
        sym_calc_visibility(sym);
237
 
238
        /* set default if recursively called */
239
        sym->curr = newval;
240
 
241
        switch (sym_get_type(sym)) {
242
        case S_BOOLEAN:
243
        case S_TRISTATE:
244
                if (sym_is_choice_value(sym) && sym->visible == yes) {
245
                        prop = sym_get_choice_prop(sym);
246
                        newval.tri = (prop_get_symbol(prop)->curr.val == sym) ? yes : no;
247
                } else if (E_OR(sym->visible, sym->rev_dep.tri) != no) {
248
                        sym->flags |= SYMBOL_WRITE;
249
                        if (sym_has_value(sym))
250
                                newval.tri = sym->user.tri;
251
                        else if (!sym_is_choice(sym)) {
252
                                prop = sym_get_default_prop(sym);
253
                                if (prop)
254
                                        newval.tri = expr_calc_value(prop->expr);
255
                        }
256
                        newval.tri = E_OR(E_AND(newval.tri, sym->visible), sym->rev_dep.tri);
257
                } else if (!sym_is_choice(sym)) {
258
                        prop = sym_get_default_prop(sym);
259
                        if (prop) {
260
                                sym->flags |= SYMBOL_WRITE;
261
                                newval.tri = expr_calc_value(prop->expr);
262
                        }
263
                }
264
                if (sym_get_type(sym) == S_BOOLEAN) {
265
                        if (newval.tri == mod)
266
                                newval.tri = yes;
267
                        if (sym->visible == mod)
268
                                sym->visible = yes;
269
                        if (sym->rev_dep.tri == mod)
270
                                sym->rev_dep.tri = yes;
271
                }
272
                break;
273
        case S_STRING:
274
        case S_HEX:
275
        case S_INT:
276
                if (sym->visible != no) {
277
                        sym->flags |= SYMBOL_WRITE;
278
                        if (sym_has_value(sym)) {
279
                                newval.val = sym->user.val;
280
                                break;
281
                        }
282
                }
283
                prop = sym_get_default_prop(sym);
284
                if (prop) {
285
                        struct symbol *ds = prop_get_symbol(prop);
286
                        if (ds) {
287
                                sym->flags |= SYMBOL_WRITE;
288
                                sym_calc_value(ds);
289
                                newval.val = ds->curr.val;
290
                        }
291
                }
292
                break;
293
        default:
294
                ;
295
        }
296
 
297
        sym->curr = newval;
298
        if (sym_is_choice(sym) && newval.tri == yes)
299
                sym->curr.val = sym_calc_choice(sym);
300
 
301
        if (memcmp(&oldval, &sym->curr, sizeof(oldval)))
302
                sym_set_changed(sym);
303
 
304
        if (sym_is_choice(sym)) {
305
                int flags = sym->flags & (SYMBOL_CHANGED | SYMBOL_WRITE);
306
                prop = sym_get_choice_prop(sym);
307
                for (e = prop->expr; e; e = e->left.expr) {
308
                        e->right.sym->flags |= flags;
309
                        if (flags & SYMBOL_CHANGED)
310
                                sym_set_changed(e->right.sym);
311
                }
312
        }
313
}
314
 
315
void sym_clear_all_valid(void)
316
{
317
        struct symbol *sym;
318
        int i;
319
 
320
        for_all_symbols(i, sym)
321
                sym->flags &= ~SYMBOL_VALID;
322
        sym_change_count++;
323
}
324
 
325
void sym_set_changed(struct symbol *sym)
326
{
327
        struct property *prop;
328
 
329
        sym->flags |= SYMBOL_CHANGED;
330
        for (prop = sym->prop; prop; prop = prop->next) {
331
                if (prop->menu)
332
                        prop->menu->flags |= MENU_CHANGED;
333
        }
334
}
335
 
336
void sym_set_all_changed(void)
337
{
338
        struct symbol *sym;
339
        int i;
340
 
341
        for_all_symbols(i, sym)
342
                sym_set_changed(sym);
343
}
344
 
345
bool sym_tristate_within_range(struct symbol *sym, tristate val)
346
{
347
        int type = sym_get_type(sym);
348
 
349
        if (sym->visible == no)
350
                return false;
351
 
352
        if (type != S_BOOLEAN && type != S_TRISTATE)
353
                return false;
354
 
355
        if (type == S_BOOLEAN && val == mod)
356
                return false;
357
        if (sym->visible <= sym->rev_dep.tri)
358
                return false;
359
        if (sym_is_choice_value(sym) && sym->visible == yes)
360
                return val == yes;
361
        return val >= sym->rev_dep.tri && val <= sym->visible;
362
}
363
 
364
bool sym_set_tristate_value(struct symbol *sym, tristate val)
365
{
366
        tristate oldval = sym_get_tristate_value(sym);
367
 
368
        if (oldval != val && !sym_tristate_within_range(sym, val))
369
                return false;
370
 
371
        if (sym->flags & SYMBOL_NEW) {
372
                sym->flags &= ~SYMBOL_NEW;
373
                sym_set_changed(sym);
374
        }
375
        if (sym_is_choice_value(sym) && val == yes) {
376
                struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
377
 
378
                cs->user.val = sym;
379
                cs->flags &= ~SYMBOL_NEW;
380
        }
381
 
382
        sym->user.tri = val;
383
        if (oldval != val) {
384
                sym_clear_all_valid();
385
                if (sym == modules_sym)
386
                        sym_set_all_changed();
387
        }
388
 
389
        return true;
390
}
391
 
392
tristate sym_toggle_tristate_value(struct symbol *sym)
393
{
394
        tristate oldval, newval;
395
 
396
        oldval = newval = sym_get_tristate_value(sym);
397
        do {
398
                switch (newval) {
399
                case no:
400
                        newval = mod;
401
                        break;
402
                case mod:
403
                        newval = yes;
404
                        break;
405
                case yes:
406
                        newval = no;
407
                        break;
408
                }
409
                if (sym_set_tristate_value(sym, newval))
410
                        break;
411
        } while (oldval != newval);
412
        return newval;
413
}
414
 
415
bool sym_string_valid(struct symbol *sym, const char *str)
416
{
417
        char ch;
418
 
419
        switch (sym->type) {
420
        case S_STRING:
421
                return true;
422
        case S_INT:
423
                ch = *str++;
424
                if (ch == '-')
425
                        ch = *str++;
426
                if (!isdigit(ch))
427
                        return false;
428
                if (ch == '0' && *str != 0)
429
                        return false;
430
                while ((ch = *str++)) {
431
                        if (!isdigit(ch))
432
                                return false;
433
                }
434
                return true;
435
        case S_HEX:
436
                if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
437
                        str += 2;
438
                ch = *str++;
439
                do {
440
                        if (!isxdigit(ch))
441
                                return false;
442
                } while ((ch = *str++));
443
                return true;
444
        case S_BOOLEAN:
445
        case S_TRISTATE:
446
                switch (str[0]) {
447
                case 'y': case 'Y':
448
                case 'm': case 'M':
449
                case 'n': case 'N':
450
                        return true;
451
                }
452
                return false;
453
        default:
454
                return false;
455
        }
456
}
457
 
458
bool sym_string_within_range(struct symbol *sym, const char *str)
459
{
460
        struct property *prop;
461
        int val;
462
 
463
        switch (sym->type) {
464
        case S_STRING:
465
                return sym_string_valid(sym, str);
466
        case S_INT:
467
                if (!sym_string_valid(sym, str))
468
                        return false;
469
                prop = sym_get_range_prop(sym);
470
                if (!prop)
471
                        return true;
472
                val = strtol(str, NULL, 10);
473
                return val >= strtol(prop->expr->left.sym->name, NULL, 10) &&
474
                       val <= strtol(prop->expr->right.sym->name, NULL, 10);
475
        case S_HEX:
476
                if (!sym_string_valid(sym, str))
477
                        return false;
478
                prop = sym_get_range_prop(sym);
479
                if (!prop)
480
                        return true;
481
                val = strtol(str, NULL, 16);
482
                return val >= strtol(prop->expr->left.sym->name, NULL, 16) &&
483
                       val <= strtol(prop->expr->right.sym->name, NULL, 16);
484
        case S_BOOLEAN:
485
        case S_TRISTATE:
486
                switch (str[0]) {
487
                case 'y': case 'Y':
488
                        return sym_tristate_within_range(sym, yes);
489
                case 'm': case 'M':
490
                        return sym_tristate_within_range(sym, mod);
491
                case 'n': case 'N':
492
                        return sym_tristate_within_range(sym, no);
493
                }
494
                return false;
495
        default:
496
                return false;
497
        }
498
}
499
 
500
bool sym_set_string_value(struct symbol *sym, const char *newval)
501
{
502
        const char *oldval;
503
        char *val;
504
        int size;
505
 
506
        switch (sym->type) {
507
        case S_BOOLEAN:
508
        case S_TRISTATE:
509
                switch (newval[0]) {
510
                case 'y': case 'Y':
511
                        return sym_set_tristate_value(sym, yes);
512
                case 'm': case 'M':
513
                        return sym_set_tristate_value(sym, mod);
514
                case 'n': case 'N':
515
                        return sym_set_tristate_value(sym, no);
516
                }
517
                return false;
518
        default:
519
                ;
520
        }
521
 
522
        if (!sym_string_within_range(sym, newval))
523
                return false;
524
 
525
        if (sym->flags & SYMBOL_NEW) {
526
                sym->flags &= ~SYMBOL_NEW;
527
                sym_set_changed(sym);
528
        }
529
 
530
        oldval = sym->user.val;
531
        size = strlen(newval) + 1;
532
        if (sym->type == S_HEX && (newval[0] != '0' || (newval[1] != 'x' && newval[1] != 'X'))) {
533
                size += 2;
534
                sym->user.val = val = malloc(size);
535
                *val++ = '0';
536
                *val++ = 'x';
537
        } else if (!oldval || strcmp(oldval, newval))
538
                sym->user.val = val = malloc(size);
539
        else
540
                return true;
541
 
542
        strcpy(val, newval);
543
        free((void *)oldval);
544
        sym_clear_all_valid();
545
 
546
        return true;
547
}
548
 
549
const char *sym_get_string_value(struct symbol *sym)
550
{
551
        tristate val;
552
 
553
        switch (sym->type) {
554
        case S_BOOLEAN:
555
        case S_TRISTATE:
556
                val = sym_get_tristate_value(sym);
557
                switch (val) {
558
                case no:
559
                        return "n";
560
                case mod:
561
                        return "m";
562
                case yes:
563
                        return "y";
564
                }
565
                break;
566
        default:
567
                ;
568
        }
569
        return (const char *)sym->curr.val;
570
}
571
 
572
bool sym_is_changable(struct symbol *sym)
573
{
574
        return sym->visible > sym->rev_dep.tri;
575
}
576
 
577
struct symbol *sym_lookup(const char *name, int isconst)
578
{
579
        struct symbol *symbol;
580
        const char *ptr;
581
        char *new_name;
582
        int hash = 0;
583
 
584
        if (name) {
585
                if (name[0] && !name[1]) {
586
                        switch (name[0]) {
587
                        case 'y': return &symbol_yes;
588
                        case 'm': return &symbol_mod;
589
                        case 'n': return &symbol_no;
590
                        }
591
                }
592
                for (ptr = name; *ptr; ptr++)
593
                        hash += *ptr;
594
                hash &= 0xff;
595
 
596
                for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
597
                        if (!strcmp(symbol->name, name)) {
598
                                if ((isconst && symbol->flags & SYMBOL_CONST) ||
599
                                    (!isconst && !(symbol->flags & SYMBOL_CONST)))
600
                                        return symbol;
601
                        }
602
                }
603
                new_name = strdup(name);
604
        } else {
605
                new_name = NULL;
606
                hash = 256;
607
        }
608
 
609
        symbol = malloc(sizeof(*symbol));
610
        memset(symbol, 0, sizeof(*symbol));
611
        symbol->name = new_name;
612
        symbol->type = S_UNKNOWN;
613
        symbol->flags = SYMBOL_NEW;
614
        if (isconst)
615
                symbol->flags |= SYMBOL_CONST;
616
 
617
        symbol->next = symbol_hash[hash];
618
        symbol_hash[hash] = symbol;
619
 
620
        return symbol;
621
}
622
 
623
struct symbol *sym_find(const char *name)
624
{
625
        struct symbol *symbol = NULL;
626
        const char *ptr;
627
        int hash = 0;
628
 
629
        if (!name)
630
                return NULL;
631
 
632
        if (name[0] && !name[1]) {
633
                switch (name[0]) {
634
                case 'y': return &symbol_yes;
635
                case 'm': return &symbol_mod;
636
                case 'n': return &symbol_no;
637
                }
638
        }
639
        for (ptr = name; *ptr; ptr++)
640
                hash += *ptr;
641
        hash &= 0xff;
642
 
643
        for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
644
                if (!strcmp(symbol->name, name) &&
645
                    !(symbol->flags & SYMBOL_CONST))
646
                                break;
647
        }
648
 
649
        return symbol;
650
}
651
 
652
struct symbol *sym_check_deps(struct symbol *sym);
653
 
654
static struct symbol *sym_check_expr_deps(struct expr *e)
655
{
656
        struct symbol *sym;
657
 
658
        if (!e)
659
                return NULL;
660
        switch (e->type) {
661
        case E_OR:
662
        case E_AND:
663
                sym = sym_check_expr_deps(e->left.expr);
664
                if (sym)
665
                        return sym;
666
                return sym_check_expr_deps(e->right.expr);
667
        case E_NOT:
668
                return sym_check_expr_deps(e->left.expr);
669
        case E_EQUAL:
670
        case E_UNEQUAL:
671
                sym = sym_check_deps(e->left.sym);
672
                if (sym)
673
                        return sym;
674
                return sym_check_deps(e->right.sym);
675
        case E_SYMBOL:
676
                return sym_check_deps(e->left.sym);
677
        default:
678
                break;
679
        }
680
        printf("Oops! How to check %d?\n", e->type);
681
        return NULL;
682
}
683
 
684
struct symbol *sym_check_deps(struct symbol *sym)
685
{
686
        struct symbol *sym2;
687
        struct property *prop;
688
 
689
        if (sym->flags & SYMBOL_CHECK_DONE)
690
                return NULL;
691
        if (sym->flags & SYMBOL_CHECK) {
692
                printf("Warning! Found recursive dependency: %s", sym->name);
693
                return sym;
694
        }
695
 
696
        sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);
697
        sym2 = sym_check_expr_deps(sym->rev_dep.expr);
698
        if (sym2)
699
                goto out;
700
 
701
        for (prop = sym->prop; prop; prop = prop->next) {
702
                if (prop->type == P_CHOICE)
703
                        continue;
704
                sym2 = sym_check_expr_deps(prop->visible.expr);
705
                if (sym2)
706
                        goto out;
707
                if (prop->type != P_DEFAULT || sym_is_choice(sym))
708
                        continue;
709
                sym2 = sym_check_expr_deps(prop->expr);
710
                if (sym2)
711
                        goto out;
712
        }
713
out:
714
        if (sym2)
715
                printf(" %s", sym->name);
716
        sym->flags &= ~SYMBOL_CHECK;
717
        return sym2;
718
}
719
 
720
struct property *prop_alloc(enum prop_type type, struct symbol *sym)
721
{
722
        struct property *prop;
723
        struct property **propp;
724
 
725
        prop = malloc(sizeof(*prop));
726
        memset(prop, 0, sizeof(*prop));
727
        prop->type = type;
728
        prop->sym = sym;
729
        prop->file = current_file;
730
        prop->lineno = zconf_lineno();
731
 
732
        /* append property to the prop list of symbol */
733
        if (sym) {
734
                for (propp = &sym->prop; *propp; propp = &(*propp)->next)
735
                        ;
736
                *propp = prop;
737
        }
738
 
739
        return prop;
740
}
741
 
742
struct symbol *prop_get_symbol(struct property *prop)
743
{
744
        if (prop->expr && (prop->expr->type == E_SYMBOL ||
745
                           prop->expr->type == E_CHOICE))
746
                return prop->expr->left.sym;
747
        return NULL;
748
}
749
 
750
const char *prop_get_type_name(enum prop_type type)
751
{
752
        switch (type) {
753
        case P_PROMPT:
754
                return "prompt";
755
        case P_COMMENT:
756
                return "comment";
757
        case P_MENU:
758
                return "menu";
759
        case P_DEFAULT:
760
                return "default";
761
        case P_CHOICE:
762
                return "choice";
763
        case P_SELECT:
764
                return "select";
765
        case P_RANGE:
766
                return "range";
767
        case P_UNKNOWN:
768
                break;
769
        }
770
        return "unknown";
771
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.