1/* Modified by Broadcom Corp. Portions Copyright (c) Broadcom Corp, 2003. */ 2/* 3 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> 4 * Released under the terms of the GNU GPL v2.0. 5 */ 6 7#include <stdlib.h> 8#include <string.h> 9 10#define LKC_DIRECT_LINK 11#include "lkc.h" 12 13struct menu rootmenu; 14struct menu *current_menu, *current_entry; 15static struct menu **last_entry_ptr; 16 17struct file *file_list; 18struct file *current_file; 19 20void menu_init(void) 21{ 22 current_entry = current_menu = &rootmenu; 23 last_entry_ptr = &rootmenu.list; 24} 25 26void menu_add_entry(struct symbol *sym) 27{ 28 struct menu *menu; 29 30 menu = malloc(sizeof(*menu)); 31 memset(menu, 0, sizeof(*menu)); 32 menu->sym = sym; 33 menu->parent = current_menu; 34 menu->file = current_file; 35 menu->lineno = zconf_lineno(); 36 37 *last_entry_ptr = menu; 38 last_entry_ptr = &menu->next; 39 current_entry = menu; 40} 41 42void menu_end_entry(void) 43{ 44} 45 46void menu_add_menu(void) 47{ 48 current_menu = current_entry; 49 last_entry_ptr = ¤t_entry->list; 50} 51 52void menu_end_menu(void) 53{ 54 last_entry_ptr = ¤t_menu->next; 55 current_menu = current_menu->parent; 56} 57 58void menu_add_dep(struct expr *dep) 59{ 60 current_entry->dep = expr_alloc_and(current_entry->dep, dep); 61} 62 63void menu_set_type(int type) 64{ 65 struct symbol *sym = current_entry->sym; 66 67 if (sym->type == type) 68 return; 69 if (sym->type == S_UNKNOWN) { 70 sym->type = type; 71 return; 72 } 73 fprintf(stderr, "%s:%d: type of '%s' redefined from '%s' to '%s'\n", 74 current_entry->file->name, current_entry->lineno, 75 sym->name ? sym->name : "<choice>", sym_type_name(sym->type), sym_type_name(type)); 76} 77 78struct property *create_prop(enum prop_type type) 79{ 80 struct property *prop; 81 82 prop = malloc(sizeof(*prop)); 83 memset(prop, 0, sizeof(*prop)); 84 prop->type = type; 85 prop->file = current_file; 86 prop->lineno = zconf_lineno(); 87 88 return prop; 89} 90 91struct property *menu_add_prop(int token, char *prompt, struct symbol *def, struct expr *dep) 92{ 93 struct property *prop = create_prop(token); 94 struct property **propp; 95 96 prop->sym = current_entry->sym; 97 prop->menu = current_entry; 98 prop->text = prompt; 99 prop->def = def; 100 E_EXPR(prop->visible) = dep; 101 102 if (prompt) 103 current_entry->prompt = prop; 104 105 /* append property to the prop list of symbol */ 106 if (prop->sym) { 107 for (propp = &prop->sym->prop; *propp; propp = &(*propp)->next) 108 ; 109 *propp = prop; 110 } 111 112 return prop; 113} 114 115void menu_add_prompt(int token, char *prompt, struct expr *dep) 116{ 117 current_entry->prompt = menu_add_prop(token, prompt, NULL, dep); 118} 119 120void menu_add_default(int token, struct symbol *def, struct expr *dep) 121{ 122 current_entry->prompt = menu_add_prop(token, NULL, def, dep); 123} 124 125void menu_finalize(struct menu *parent) 126{ 127 struct menu *menu, *last_menu; 128 struct symbol *sym; 129 struct property *prop; 130 struct expr *parentdep, *basedep, *dep, *dep2; 131 132 sym = parent->sym; 133 if (parent->list) { 134 if (sym && sym_is_choice(sym)) { 135 /* find the first choice value and find out choice type */ 136 for (menu = parent->list; menu; menu = menu->next) { 137 if (menu->sym) { 138 current_entry = parent; 139 menu_set_type(menu->sym->type); 140 current_entry = menu; 141 menu_set_type(sym->type); 142 break; 143 } 144 } 145 parentdep = expr_alloc_symbol(sym); 146 } else if (parent->prompt) 147 parentdep = E_EXPR(parent->prompt->visible); 148 else 149 parentdep = parent->dep; 150 151 for (menu = parent->list; menu; menu = menu->next) { 152 basedep = expr_transform(menu->dep); 153 basedep = expr_alloc_and(expr_copy(parentdep), basedep); 154 basedep = expr_eliminate_dups(basedep); 155 menu->dep = basedep; 156 if (menu->sym) 157 prop = menu->sym->prop; 158 else 159 prop = menu->prompt; 160 for (; prop; prop = prop->next) { 161 if (prop->menu != menu) 162 continue; 163 dep = expr_transform(E_EXPR(prop->visible)); 164 dep = expr_alloc_and(expr_copy(basedep), dep); 165 dep = expr_eliminate_dups(dep); 166 if (menu->sym && menu->sym->type != S_TRISTATE) 167 dep = expr_trans_bool(dep); 168 E_EXPR(prop->visible) = dep; 169 } 170 } 171 for (menu = parent->list; menu; menu = menu->next) 172 menu_finalize(menu); 173 } else if (sym && parent->prompt) { 174 basedep = E_EXPR(parent->prompt->visible); 175 basedep = expr_trans_compare(basedep, E_UNEQUAL, &symbol_no); 176 basedep = expr_eliminate_dups(expr_transform(basedep)); 177 last_menu = NULL; 178 for (menu = parent->next; menu; menu = menu->next) { 179 dep = menu->prompt ? E_EXPR(menu->prompt->visible) : menu->dep; 180 if (!expr_contains_symbol(dep, sym)) 181 break; 182 if (expr_depends_symbol(dep, sym)) 183 goto next; 184 dep = expr_trans_compare(dep, E_UNEQUAL, &symbol_no); 185 dep = expr_eliminate_dups(expr_transform(dep)); 186 dep2 = expr_copy(basedep); 187 expr_eliminate_eq(&dep, &dep2); 188 expr_free(dep); 189 if (!expr_is_yes(dep2)) { 190 expr_free(dep2); 191 break; 192 } 193 expr_free(dep2); 194 next: 195 menu_finalize(menu); 196 menu->parent = parent; 197 last_menu = menu; 198 } 199 if (last_menu) { 200 parent->list = parent->next; 201 parent->next = last_menu->next; 202 last_menu->next = NULL; 203 } 204 } 205 for (menu = parent->list; menu; menu = menu->next) { 206 if (sym && sym_is_choice(sym) && menu->sym) { 207 menu->sym->flags |= SYMBOL_CHOICEVAL; 208 current_entry = menu; 209 menu_set_type(sym->type); 210 menu_add_prop(P_CHOICE, NULL, parent->sym, NULL); 211 prop = sym_get_choice_prop(parent->sym); 212 //dep = expr_alloc_one(E_CHOICE, dep); 213 //dep->right.sym = menu->sym; 214 prop->dep = expr_alloc_one(E_CHOICE, prop->dep); 215 prop->dep->right.sym = menu->sym; 216 } 217 if (menu->list && (!menu->prompt || !menu->prompt->text)) { 218 for (last_menu = menu->list; ; last_menu = last_menu->next) { 219 last_menu->parent = parent; 220 if (!last_menu->next) 221 break; 222 } 223 last_menu->next = menu->next; 224 menu->next = menu->list; 225 menu->list = NULL; 226 } 227 } 228} 229 230bool menu_is_visible(struct menu *menu) 231{ 232 tristate visible; 233 234 if (!menu->prompt) 235 return false; 236 if (menu->sym) { 237 sym_calc_value(menu->sym); 238 visible = E_TRI(menu->prompt->visible); 239 } else 240 visible = E_CALC(menu->prompt->visible); 241 return visible != no; 242} 243 244const char *menu_get_prompt(struct menu *menu) 245{ 246 if (menu->prompt) 247 return menu->prompt->text; 248 else if (menu->sym) 249 return menu->sym->name; 250 return NULL; 251} 252 253struct menu *menu_get_root_menu(struct menu *menu) 254{ 255 return &rootmenu; 256} 257 258struct menu *menu_get_parent_menu(struct menu *menu) 259{ 260 enum prop_type type; 261 262 while (menu != &rootmenu) { 263 menu = menu->parent; 264 type = menu->prompt ? menu->prompt->type : 0; 265 if (type == P_MENU || type == P_ROOTMENU) 266 break; 267 } 268 return menu; 269} 270 271struct file *file_lookup(const char *name) 272{ 273 struct file *file; 274 275 for (file = file_list; file; file = file->next) { 276 if (!strcmp(name, file->name)) 277 return file; 278 } 279 280 file = malloc(sizeof(*file)); 281 memset(file, 0, sizeof(*file)); 282 file->name = strdup(name); 283 file->next = file_list; 284 file_list = file; 285 return file; 286} 287 288int file_write_dep(const char *name) 289{ 290 struct file *file; 291 FILE *out; 292 293 if (!name) 294 name = ".config.cmd"; 295 out = fopen(".config.tmp", "w"); 296 if (!out) 297 return 1; 298 fprintf(out, "deps_config := \\\n"); 299 for (file = file_list; file; file = file->next) { 300 if (file->next) 301 fprintf(out, "\t%s \\\n", file->name); 302 else 303 fprintf(out, "\t%s\n", file->name); 304 } 305 fclose(out); 306 rename(".config.tmp", name); 307 return 0; 308} 309