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

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [scripts/] [kconfig/] [menu.c] - Blame information for rev 82

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
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 <stdlib.h>
7
#include <string.h>
8
 
9
#define LKC_DIRECT_LINK
10
#include "lkc.h"
11
 
12
struct menu rootmenu;
13
static struct menu **last_entry_ptr;
14
 
15
struct file *file_list;
16
struct file *current_file;
17
 
18
static void menu_warn(struct menu *menu, const char *fmt, ...)
19
{
20
        va_list ap;
21
        va_start(ap, fmt);
22
        fprintf(stderr, "%s:%d:warning: ", menu->file->name, menu->lineno);
23
        vfprintf(stderr, fmt, ap);
24
        fprintf(stderr, "\n");
25
        va_end(ap);
26
}
27
 
28
static void prop_warn(struct property *prop, const char *fmt, ...)
29
{
30
        va_list ap;
31
        va_start(ap, fmt);
32
        fprintf(stderr, "%s:%d:warning: ", prop->file->name, prop->lineno);
33
        vfprintf(stderr, fmt, ap);
34
        fprintf(stderr, "\n");
35
        va_end(ap);
36
}
37
 
38
void menu_init(void)
39
{
40
        current_entry = current_menu = &rootmenu;
41
        last_entry_ptr = &rootmenu.list;
42
}
43
 
44
void menu_add_entry(struct symbol *sym)
45
{
46
        struct menu *menu;
47
 
48
        menu = malloc(sizeof(*menu));
49
        memset(menu, 0, sizeof(*menu));
50
        menu->sym = sym;
51
        menu->parent = current_menu;
52
        menu->file = current_file;
53
        menu->lineno = zconf_lineno();
54
 
55
        *last_entry_ptr = menu;
56
        last_entry_ptr = &menu->next;
57
        current_entry = menu;
58
}
59
 
60
void menu_end_entry(void)
61
{
62
}
63
 
64
struct menu *menu_add_menu(void)
65
{
66
        menu_end_entry();
67
        last_entry_ptr = &current_entry->list;
68
        return current_menu = current_entry;
69
}
70
 
71
void menu_end_menu(void)
72
{
73
        last_entry_ptr = &current_menu->next;
74
        current_menu = current_menu->parent;
75
}
76
 
77
struct expr *menu_check_dep(struct expr *e)
78
{
79
        if (!e)
80
                return e;
81
 
82
        switch (e->type) {
83
        case E_NOT:
84
                e->left.expr = menu_check_dep(e->left.expr);
85
                break;
86
        case E_OR:
87
        case E_AND:
88
                e->left.expr = menu_check_dep(e->left.expr);
89
                e->right.expr = menu_check_dep(e->right.expr);
90
                break;
91
        case E_SYMBOL:
92
                /* change 'm' into 'm' && MODULES */
93
                if (e->left.sym == &symbol_mod)
94
                        return expr_alloc_and(e, expr_alloc_symbol(modules_sym));
95
                break;
96
        default:
97
                break;
98
        }
99
        return e;
100
}
101
 
102
void menu_add_dep(struct expr *dep)
103
{
104
        current_entry->dep = expr_alloc_and(current_entry->dep, menu_check_dep(dep));
105
}
106
 
107
void menu_set_type(int type)
108
{
109
        struct symbol *sym = current_entry->sym;
110
 
111
        if (sym->type == type)
112
                return;
113
        if (sym->type == S_UNKNOWN) {
114
                sym->type = type;
115
                return;
116
        }
117
        menu_warn(current_entry, "type of '%s' redefined from '%s' to '%s'",
118
            sym->name ? sym->name : "<choice>",
119
            sym_type_name(sym->type), sym_type_name(type));
120
}
121
 
122
struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep)
123
{
124
        struct property *prop = prop_alloc(type, current_entry->sym);
125
 
126
        prop->menu = current_entry;
127
        prop->expr = expr;
128
        prop->visible.expr = menu_check_dep(dep);
129
 
130
        if (prompt) {
131
                if (isspace(*prompt)) {
132
                        prop_warn(prop, "leading whitespace ignored");
133
                        while (isspace(*prompt))
134
                                prompt++;
135
                }
136
                if (current_entry->prompt)
137
                        prop_warn(prop, "prompt redefined");
138
                current_entry->prompt = prop;
139
        }
140
        prop->text = prompt;
141
 
142
        return prop;
143
}
144
 
145
struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep)
146
{
147
        return menu_add_prop(type, prompt, NULL, dep);
148
}
149
 
150
void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep)
151
{
152
        menu_add_prop(type, NULL, expr, dep);
153
}
154
 
155
void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep)
156
{
157
        menu_add_prop(type, NULL, expr_alloc_symbol(sym), dep);
158
}
159
 
160
void menu_add_option(int token, char *arg)
161
{
162
        struct property *prop;
163
 
164
        switch (token) {
165
        case T_OPT_MODULES:
166
                prop = prop_alloc(P_DEFAULT, modules_sym);
167
                prop->expr = expr_alloc_symbol(current_entry->sym);
168
                break;
169
        case T_OPT_DEFCONFIG_LIST:
170
                if (!sym_defconfig_list)
171
                        sym_defconfig_list = current_entry->sym;
172
                else if (sym_defconfig_list != current_entry->sym)
173
                        zconf_error("trying to redefine defconfig symbol");
174
                break;
175
        }
176
}
177
 
178
static int menu_range_valid_sym(struct symbol *sym, struct symbol *sym2)
179
{
180
        return sym2->type == S_INT || sym2->type == S_HEX ||
181
               (sym2->type == S_UNKNOWN && sym_string_valid(sym, sym2->name));
182
}
183
 
184
void sym_check_prop(struct symbol *sym)
185
{
186
        struct property *prop;
187
        struct symbol *sym2;
188
        for (prop = sym->prop; prop; prop = prop->next) {
189
                switch (prop->type) {
190
                case P_DEFAULT:
191
                        if ((sym->type == S_STRING || sym->type == S_INT || sym->type == S_HEX) &&
192
                            prop->expr->type != E_SYMBOL)
193
                                prop_warn(prop,
194
                                    "default for config symbol '%'"
195
                                    " must be a single symbol", sym->name);
196
                        break;
197
                case P_SELECT:
198
                        sym2 = prop_get_symbol(prop);
199
                        if (sym->type != S_BOOLEAN && sym->type != S_TRISTATE)
200
                                prop_warn(prop,
201
                                    "config symbol '%s' uses select, but is "
202
                                    "not boolean or tristate", sym->name);
203
                        else if (sym2->type == S_UNKNOWN)
204
                                prop_warn(prop,
205
                                    "'select' used by config symbol '%s' "
206
                                    "refers to undefined symbol '%s'",
207
                                    sym->name, sym2->name);
208
                        else if (sym2->type != S_BOOLEAN && sym2->type != S_TRISTATE)
209
                                prop_warn(prop,
210
                                    "'%s' has wrong type. 'select' only "
211
                                    "accept arguments of boolean and "
212
                                    "tristate type", sym2->name);
213
                        break;
214
                case P_RANGE:
215
                        if (sym->type != S_INT && sym->type != S_HEX)
216
                                prop_warn(prop, "range is only allowed "
217
                                                "for int or hex symbols");
218
                        if (!menu_range_valid_sym(sym, prop->expr->left.sym) ||
219
                            !menu_range_valid_sym(sym, prop->expr->right.sym))
220
                                prop_warn(prop, "range is invalid");
221
                        break;
222
                default:
223
                        ;
224
                }
225
        }
226
}
227
 
228
void menu_finalize(struct menu *parent)
229
{
230
        struct menu *menu, *last_menu;
231
        struct symbol *sym;
232
        struct property *prop;
233
        struct expr *parentdep, *basedep, *dep, *dep2, **ep;
234
 
235
        sym = parent->sym;
236
        if (parent->list) {
237
                if (sym && sym_is_choice(sym)) {
238
                        /* find the first choice value and find out choice type */
239
                        for (menu = parent->list; menu; menu = menu->next) {
240
                                if (menu->sym) {
241
                                        current_entry = parent;
242
                                        menu_set_type(menu->sym->type);
243
                                        current_entry = menu;
244
                                        menu_set_type(sym->type);
245
                                        break;
246
                                }
247
                        }
248
                        parentdep = expr_alloc_symbol(sym);
249
                } else if (parent->prompt)
250
                        parentdep = parent->prompt->visible.expr;
251
                else
252
                        parentdep = parent->dep;
253
 
254
                for (menu = parent->list; menu; menu = menu->next) {
255
                        basedep = expr_transform(menu->dep);
256
                        basedep = expr_alloc_and(expr_copy(parentdep), basedep);
257
                        basedep = expr_eliminate_dups(basedep);
258
                        menu->dep = basedep;
259
                        if (menu->sym)
260
                                prop = menu->sym->prop;
261
                        else
262
                                prop = menu->prompt;
263
                        for (; prop; prop = prop->next) {
264
                                if (prop->menu != menu)
265
                                        continue;
266
                                dep = expr_transform(prop->visible.expr);
267
                                dep = expr_alloc_and(expr_copy(basedep), dep);
268
                                dep = expr_eliminate_dups(dep);
269
                                if (menu->sym && menu->sym->type != S_TRISTATE)
270
                                        dep = expr_trans_bool(dep);
271
                                prop->visible.expr = dep;
272
                                if (prop->type == P_SELECT) {
273
                                        struct symbol *es = prop_get_symbol(prop);
274
                                        es->rev_dep.expr = expr_alloc_or(es->rev_dep.expr,
275
                                                        expr_alloc_and(expr_alloc_symbol(menu->sym), expr_copy(dep)));
276
                                }
277
                        }
278
                }
279
                for (menu = parent->list; menu; menu = menu->next)
280
                        menu_finalize(menu);
281
        } else if (sym) {
282
                basedep = parent->prompt ? parent->prompt->visible.expr : NULL;
283
                basedep = expr_trans_compare(basedep, E_UNEQUAL, &symbol_no);
284
                basedep = expr_eliminate_dups(expr_transform(basedep));
285
                last_menu = NULL;
286
                for (menu = parent->next; menu; menu = menu->next) {
287
                        dep = menu->prompt ? menu->prompt->visible.expr : menu->dep;
288
                        if (!expr_contains_symbol(dep, sym))
289
                                break;
290
                        if (expr_depends_symbol(dep, sym))
291
                                goto next;
292
                        dep = expr_trans_compare(dep, E_UNEQUAL, &symbol_no);
293
                        dep = expr_eliminate_dups(expr_transform(dep));
294
                        dep2 = expr_copy(basedep);
295
                        expr_eliminate_eq(&dep, &dep2);
296
                        expr_free(dep);
297
                        if (!expr_is_yes(dep2)) {
298
                                expr_free(dep2);
299
                                break;
300
                        }
301
                        expr_free(dep2);
302
                next:
303
                        menu_finalize(menu);
304
                        menu->parent = parent;
305
                        last_menu = menu;
306
                }
307
                if (last_menu) {
308
                        parent->list = parent->next;
309
                        parent->next = last_menu->next;
310
                        last_menu->next = NULL;
311
                }
312
        }
313
        for (menu = parent->list; menu; menu = menu->next) {
314
                if (sym && sym_is_choice(sym) && menu->sym) {
315
                        menu->sym->flags |= SYMBOL_CHOICEVAL;
316
                        if (!menu->prompt)
317
                                menu_warn(menu, "choice value must have a prompt");
318
                        for (prop = menu->sym->prop; prop; prop = prop->next) {
319
                                if (prop->type == P_PROMPT && prop->menu != menu) {
320
                                        prop_warn(prop, "choice values "
321
                                            "currently only support a "
322
                                            "single prompt");
323
                                }
324
                                if (prop->type == P_DEFAULT)
325
                                        prop_warn(prop, "defaults for choice "
326
                                            "values not supported");
327
                        }
328
                        current_entry = menu;
329
                        menu_set_type(sym->type);
330
                        menu_add_symbol(P_CHOICE, sym, NULL);
331
                        prop = sym_get_choice_prop(sym);
332
                        for (ep = &prop->expr; *ep; ep = &(*ep)->left.expr)
333
                                ;
334
                        *ep = expr_alloc_one(E_CHOICE, NULL);
335
                        (*ep)->right.sym = menu->sym;
336
                }
337
                if (menu->list && (!menu->prompt || !menu->prompt->text)) {
338
                        for (last_menu = menu->list; ; last_menu = last_menu->next) {
339
                                last_menu->parent = parent;
340
                                if (!last_menu->next)
341
                                        break;
342
                        }
343
                        last_menu->next = menu->next;
344
                        menu->next = menu->list;
345
                        menu->list = NULL;
346
                }
347
        }
348
 
349
        if (sym && !(sym->flags & SYMBOL_WARNED)) {
350
                if (sym->type == S_UNKNOWN)
351
                        menu_warn(parent, "config symbol defined without type");
352
 
353
                if (sym_is_choice(sym) && !parent->prompt)
354
                        menu_warn(parent, "choice must have a prompt");
355
 
356
                /* Check properties connected to this symbol */
357
                sym_check_prop(sym);
358
                sym->flags |= SYMBOL_WARNED;
359
        }
360
 
361
        if (sym && !sym_is_optional(sym) && parent->prompt) {
362
                sym->rev_dep.expr = expr_alloc_or(sym->rev_dep.expr,
363
                                expr_alloc_and(parent->prompt->visible.expr,
364
                                        expr_alloc_symbol(&symbol_mod)));
365
        }
366
}
367
 
368
bool menu_is_visible(struct menu *menu)
369
{
370
        struct menu *child;
371
        struct symbol *sym;
372
        tristate visible;
373
 
374
        if (!menu->prompt)
375
                return false;
376
        sym = menu->sym;
377
        if (sym) {
378
                sym_calc_value(sym);
379
                visible = menu->prompt->visible.tri;
380
        } else
381
                visible = menu->prompt->visible.tri = expr_calc_value(menu->prompt->visible.expr);
382
 
383
        if (visible != no)
384
                return true;
385
        if (!sym || sym_get_tristate_value(menu->sym) == no)
386
                return false;
387
 
388
        for (child = menu->list; child; child = child->next)
389
                if (menu_is_visible(child))
390
                        return true;
391
        return false;
392
}
393
 
394
const char *menu_get_prompt(struct menu *menu)
395
{
396
        if (menu->prompt)
397
                return _(menu->prompt->text);
398
        else if (menu->sym)
399
                return _(menu->sym->name);
400
        return NULL;
401
}
402
 
403
struct menu *menu_get_root_menu(struct menu *menu)
404
{
405
        return &rootmenu;
406
}
407
 
408
struct menu *menu_get_parent_menu(struct menu *menu)
409
{
410
        enum prop_type type;
411
 
412
        for (; menu != &rootmenu; menu = menu->parent) {
413
                type = menu->prompt ? menu->prompt->type : 0;
414
                if (type == P_MENU)
415
                        break;
416
        }
417
        return menu;
418
}
419
 
420
bool menu_has_help(struct menu *menu)
421
{
422
        return menu->help != NULL;
423
}
424
 
425
const char *menu_get_help(struct menu *menu)
426
{
427
        if (menu->help)
428
                return menu->help;
429
        else
430
                return "";
431
}

powered by: WebSVN 2.1.0

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