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

Subversion Repositories or1k

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

powered by: WebSVN 2.1.0

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