~ubuntu-branches/ubuntu/trusty/apex/trusty

« back to all changes in this revision

Viewing changes to scripts/menu.c

  • Committer: Bazaar Package Importer
  • Author(s): Oliver Grawert
  • Date: 2009-11-10 11:55:15 UTC
  • mfrom: (2.2.2 squeeze)
  • Revision ID: james.westby@ubuntu.com-20091110115515-6jjsf6rc8py35awe
Tags: 1.6.10ubuntu1
* Merge from debian testing, remaining changes:
  - Move apex VMA address to 4MiB to leave enough space for the ubuntu
  kernel and not overwrite apex in ram when loading.
  - nslu2 configuration: set CONFIG_RAMDISK_SIZE=0x0055FFF0 instead of
  0x005FFFF0 to make enough room for ubuntu initramfs.

Show diffs side-by-side

added added

removed removed

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