From 6737908f74ff566748864548cf35bb1da8e64af6 Mon Sep 17 00:00:00 2001 From: Eric Andersen Date: Thu, 31 Oct 2002 18:20:21 +0000 Subject: Ok, this commit is _huge_ and its gonna change the world. I've been working on a new config system on and off for about 6 months now, but I've never been fully satisfied. Well, I'm finally am happy with the new config system, so here it is. This completely removes the old uClibc configuration system, and replaces it with an entirely new system based on LinuxKernelConf, from http://www.xs4all.nl/~zippel/lc/ As it turns out, Linus has just merged LinuxKernelConf into Linux 2.5.45, so it looks like I made the right choice. I have thus far updated only x86. I'll be updating the other architectures shortly. -Erik --- extra/config/menu.c | 309 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 309 insertions(+) create mode 100644 extra/config/menu.c (limited to 'extra/config/menu.c') diff --git a/extra/config/menu.c b/extra/config/menu.c new file mode 100644 index 000000000..1beec1687 --- /dev/null +++ b/extra/config/menu.c @@ -0,0 +1,309 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include + +#define LKC_DIRECT_LINK +#include "lkc.h" + +struct menu rootmenu; +struct menu *current_menu, *current_entry; +static struct menu **last_entry_ptr; + +struct file *file_list; +struct file *current_file; + +void menu_init(void) +{ + current_entry = current_menu = &rootmenu; + last_entry_ptr = &rootmenu.list; +} + +void menu_add_entry(struct symbol *sym) +{ + struct menu *menu; + + menu = malloc(sizeof(*menu)); + memset(menu, 0, sizeof(*menu)); + menu->sym = sym; + menu->parent = current_menu; + menu->file = current_file; + menu->lineno = zconf_lineno(); + + *last_entry_ptr = menu; + last_entry_ptr = &menu->next; + current_entry = menu; +} + +void menu_end_entry(void) +{ +} + +void menu_add_menu(void) +{ + current_menu = current_entry; + last_entry_ptr = ¤t_entry->list; +} + +void menu_end_menu(void) +{ + last_entry_ptr = ¤t_menu->next; + current_menu = current_menu->parent; +} + +void menu_add_dep(struct expr *dep) +{ + current_entry->dep = expr_alloc_and(current_entry->dep, dep); +} + +void menu_set_type(int type) +{ + struct symbol *sym = current_entry->sym; + + if (sym->type == type) + return; + if (sym->type == S_UNKNOWN) { + sym->type = type; + return; + } + fprintf(stderr, "%s:%d: type of '%s' redefined from '%s' to '%s'\n", + current_entry->file->name, current_entry->lineno, + sym->name ? sym->name : "", sym_type_name(sym->type), sym_type_name(type)); +} + +struct property *create_prop(enum prop_type type) +{ + struct property *prop; + + prop = malloc(sizeof(*prop)); + memset(prop, 0, sizeof(*prop)); + prop->type = type; + prop->file = current_file; + prop->lineno = zconf_lineno(); + + return prop; +} + +struct property *menu_add_prop(int token, char *prompt, struct symbol *def, struct expr *dep) +{ + struct property *prop = create_prop(token); + struct property **propp; + + prop->sym = current_entry->sym; + prop->menu = current_entry; + prop->text = prompt; + prop->def = def; + E_EXPR(prop->visible) = dep; + + if (prompt) + current_entry->prompt = prop; + + /* append property to the prop list of symbol */ + if (prop->sym) { + for (propp = &prop->sym->prop; *propp; propp = &(*propp)->next) + ; + *propp = prop; + } + + return prop; +} + +void menu_add_prompt(int token, char *prompt, struct expr *dep) +{ + current_entry->prompt = menu_add_prop(token, prompt, NULL, dep); +} + +void menu_add_default(int token, struct symbol *def, struct expr *dep) +{ + current_entry->prompt = menu_add_prop(token, NULL, def, dep); +} + +void menu_finalize(struct menu *parent) +{ + struct menu *menu, *last_menu; + struct symbol *sym; + struct property *prop; + struct expr *parentdep, *basedep, *dep, *dep2; + + sym = parent->sym; + if (parent->list) { + if (sym && sym_is_choice(sym)) { + /* find the first choice value and find out choice type */ + for (menu = parent->list; menu; menu = menu->next) { + if (menu->sym) { + current_entry = parent; + menu_set_type(menu->sym->type); + current_entry = menu; + menu_set_type(sym->type); + break; + } + } + parentdep = expr_alloc_symbol(sym); + } else if (parent->prompt) + parentdep = E_EXPR(parent->prompt->visible); + else + parentdep = parent->dep; + + for (menu = parent->list; menu; menu = menu->next) { + basedep = expr_transform(menu->dep); + basedep = expr_alloc_and(expr_copy(parentdep), basedep); + basedep = expr_eliminate_dups(basedep); + menu->dep = basedep; + if (menu->sym) + prop = menu->sym->prop; + else + prop = menu->prompt; + for (; prop; prop = prop->next) { + if (prop->menu != menu) + continue; + dep = expr_transform(E_EXPR(prop->visible)); + dep = expr_alloc_and(expr_copy(basedep), dep); + dep = expr_eliminate_dups(dep); + if (menu->sym && menu->sym->type != S_TRISTATE) + dep = expr_trans_bool(dep); + E_EXPR(prop->visible) = dep; + } + } + for (menu = parent->list; menu; menu = menu->next) + menu_finalize(menu); + } else if (sym && parent->prompt) { + basedep = E_EXPR(parent->prompt->visible); + basedep = expr_trans_compare(basedep, E_UNEQUAL, &symbol_no); + basedep = expr_eliminate_dups(expr_transform(basedep)); + last_menu = NULL; + for (menu = parent->next; menu; menu = menu->next) { + dep = menu->prompt ? E_EXPR(menu->prompt->visible) : menu->dep; + if (!expr_contains_symbol(dep, sym)) + break; + if (expr_depends_symbol(dep, sym)) + goto next; + dep = expr_trans_compare(dep, E_UNEQUAL, &symbol_no); + dep = expr_eliminate_dups(expr_transform(dep)); + dep2 = expr_copy(basedep); + expr_eliminate_eq(&dep, &dep2); + expr_free(dep); + if (!expr_is_yes(dep2)) { + expr_free(dep2); + break; + } + expr_free(dep2); + next: + menu_finalize(menu); + menu->parent = parent; + last_menu = menu; + } + if (last_menu) { + parent->list = parent->next; + parent->next = last_menu->next; + last_menu->next = NULL; + } + } + for (menu = parent->list; menu; menu = menu->next) { + if (sym && sym_is_choice(sym) && menu->sym) { + menu->sym->flags |= SYMBOL_CHOICEVAL; + current_entry = menu; + menu_set_type(sym->type); + menu_add_prop(P_CHOICE, NULL, parent->sym, NULL); + prop = sym_get_choice_prop(parent->sym); + //dep = expr_alloc_one(E_CHOICE, dep); + //dep->right.sym = menu->sym; + prop->dep = expr_alloc_one(E_CHOICE, prop->dep); + prop->dep->right.sym = menu->sym; + } + if (menu->list && (!menu->prompt || !menu->prompt->text)) { + for (last_menu = menu->list; ; last_menu = last_menu->next) { + last_menu->parent = parent; + if (!last_menu->next) + break; + } + last_menu->next = menu->next; + menu->next = menu->list; + menu->list = NULL; + } + } +} + +bool menu_is_visible(struct menu *menu) +{ + tristate visible; + + if (!menu->prompt) + return false; + if (menu->sym) { + sym_calc_value(menu->sym); + visible = E_TRI(menu->prompt->visible); + } else + visible = E_CALC(menu->prompt->visible); + return visible != no; +} + +const char *menu_get_prompt(struct menu *menu) +{ + if (menu->prompt) + return menu->prompt->text; + else if (menu->sym) + return menu->sym->name; + return NULL; +} + +struct menu *menu_get_root_menu(struct menu *menu) +{ + return &rootmenu; +} + +struct menu *menu_get_parent_menu(struct menu *menu) +{ + enum prop_type type; + + while (menu != &rootmenu) { + menu = menu->parent; + type = menu->prompt ? menu->prompt->type : 0; + if (type == P_MENU || type == P_ROOTMENU) + break; + } + return menu; +} + +struct file *file_lookup(const char *name) +{ + struct file *file; + + for (file = file_list; file; file = file->next) { + if (!strcmp(name, file->name)) + return file; + } + + file = malloc(sizeof(*file)); + memset(file, 0, sizeof(*file)); + file->name = strdup(name); + file->next = file_list; + file_list = file; + return file; +} + +int file_write_dep(const char *name) +{ + struct file *file; + FILE *out; + + if (!name) + name = ".config.cmd"; + out = fopen(".config.tmp", "w"); + if (!out) + return 1; + fprintf(out, "deps_config := \\\n"); + for (file = file_list; file; file = file->next) { + if (file->next) + fprintf(out, "\t%s \\\n", file->name); + else + fprintf(out, "\t%s\n", file->name); + } + fprintf(out, "\n.config include/bits/uClibc_config.h: $(deps_config)\n\n$(deps_config):\n"); + fclose(out); + rename(".config.tmp", name); + return 0; +} + -- cgit v1.2.3