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