2 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
3 * Released under the terms of the GNU GPL v2.0.
9 #define LKC_DIRECT_LINK
13 struct menu
*current_menu
, *current_entry
;
14 static struct menu
**last_entry_ptr
;
16 struct file
*file_list
;
17 struct file
*current_file
;
21 current_entry
= current_menu
= &rootmenu
;
22 last_entry_ptr
= &rootmenu
.list
;
25 void menu_add_entry(struct symbol
*sym
)
29 menu
= malloc(sizeof(*menu
));
30 memset(menu
, 0, sizeof(*menu
));
32 menu
->parent
= current_menu
;
33 menu
->file
= current_file
;
34 menu
->lineno
= zconf_lineno();
36 *last_entry_ptr
= menu
;
37 last_entry_ptr
= &menu
->next
;
41 void menu_end_entry(void)
45 void menu_add_menu(void)
47 current_menu
= current_entry
;
48 last_entry_ptr
= ¤t_entry
->list
;
51 void menu_end_menu(void)
53 last_entry_ptr
= ¤t_menu
->next
;
54 current_menu
= current_menu
->parent
;
57 struct expr
*menu_check_dep(struct expr
*e
)
64 e
->left
.expr
= menu_check_dep(e
->left
.expr
);
68 e
->left
.expr
= menu_check_dep(e
->left
.expr
);
69 e
->right
.expr
= menu_check_dep(e
->right
.expr
);
72 /* change 'm' into 'm' && MODULES */
73 if (e
->left
.sym
== &symbol_mod
)
74 return expr_alloc_and(e
, expr_alloc_symbol(modules_sym
));
82 void menu_add_dep(struct expr
*dep
)
84 current_entry
->dep
= expr_alloc_and(current_entry
->dep
, menu_check_dep(dep
));
87 void menu_set_type(int type
)
89 struct symbol
*sym
= current_entry
->sym
;
91 if (sym
->type
== type
)
93 if (sym
->type
== S_UNKNOWN
) {
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
));
102 struct property
*menu_add_prop(enum prop_type type
, char *prompt
, struct expr
*expr
, struct expr
*dep
)
104 struct property
*prop
= prop_alloc(type
, current_entry
->sym
);
106 prop
->menu
= current_entry
;
109 prop
->visible
.expr
= menu_check_dep(dep
);
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
;
121 void menu_add_prompt(enum prop_type type
, char *prompt
, struct expr
*dep
)
123 menu_add_prop(type
, prompt
, NULL
, dep
);
126 void menu_add_expr(enum prop_type type
, struct expr
*expr
, struct expr
*dep
)
128 menu_add_prop(type
, NULL
, expr
, dep
);
131 void menu_add_symbol(enum prop_type type
, struct symbol
*sym
, struct expr
*dep
)
133 menu_add_prop(type
, NULL
, expr_alloc_symbol(sym
), dep
);
136 void menu_finalize(struct menu
*parent
)
138 struct menu
*menu
, *last_menu
;
140 struct property
*prop
;
141 struct expr
*parentdep
, *basedep
, *dep
, *dep2
, **ep
;
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
) {
149 current_entry
= parent
;
150 menu_set_type(menu
->sym
->type
);
151 current_entry
= menu
;
152 menu_set_type(sym
->type
);
156 parentdep
= expr_alloc_symbol(sym
);
157 } else if (parent
->prompt
)
158 parentdep
= parent
->prompt
->visible
.expr
;
160 parentdep
= parent
->dep
;
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
);
168 prop
= menu
->sym
->prop
;
171 for (; prop
; prop
= prop
->next
) {
172 if (prop
->menu
!= menu
)
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
)));
187 for (menu
= parent
->list
; menu
; menu
= menu
->next
)
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
));
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
))
198 if (expr_depends_symbol(dep
, sym
))
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
);
205 if (!expr_is_yes(dep2
)) {
212 menu
->parent
= parent
;
216 parent
->list
= parent
->next
;
217 parent
->next
= last_menu
->next
;
218 last_menu
->next
= NULL
;
221 for (menu
= parent
->list
; menu
; menu
= menu
->next
) {
222 if (sym
&& sym_is_choice(sym
) && menu
->sym
) {
223 menu
->sym
->flags
|= SYMBOL_CHOICEVAL
;
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
);
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
);
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
)
243 *ep
= expr_alloc_one(E_CHOICE
, NULL
);
244 (*ep
)->right
.sym
= menu
->sym
;
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
)
252 last_menu
->next
= menu
->next
;
253 menu
->next
= menu
->list
;
258 if (sym
&& !(sym
->flags
& SYMBOL_WARNED
)) {
260 if (sym
->type
== S_UNKNOWN
)
261 fprintf(stderr
, "%s:%d:warning: config symbol defined without type\n",
262 parent
->file
->name
, parent
->lineno
);
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
);
268 for (prop
= sym
->prop
; prop
; prop
= prop
->next
) {
269 switch (prop
->type
) {
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
);
277 sym2
= prop_get_symbol(prop
);
278 if ((sym
->type
!= S_BOOLEAN
&& sym
->type
!= S_TRISTATE
) ||
279 (sym2
->type
!= S_BOOLEAN
&& sym2
->type
!= S_TRISTATE
))
280 fprintf(stderr
, "%s:%d:warning: enable is only allowed with boolean and tristate symbols\n",
281 prop
->file
->name
, prop
->lineno
);
284 if (sym
->type
!= S_INT
&& sym
->type
!= S_HEX
)
285 fprintf(stderr
, "%s:%d:warning: range is only allowed for int or hex symbols\n",
286 prop
->file
->name
, prop
->lineno
);
287 if (!sym_string_valid(sym
, prop
->expr
->left
.sym
->name
) ||
288 !sym_string_valid(sym
, prop
->expr
->right
.sym
->name
))
289 fprintf(stderr
, "%s:%d:warning: range is invalid\n",
290 prop
->file
->name
, prop
->lineno
);
296 sym
->flags
|= SYMBOL_WARNED
;
299 if (sym
&& !sym_is_optional(sym
) && parent
->prompt
) {
300 sym
->rev_dep
.expr
= expr_alloc_or(sym
->rev_dep
.expr
,
301 expr_alloc_and(parent
->prompt
->visible
.expr
,
302 expr_alloc_symbol(&symbol_mod
)));
306 bool menu_is_visible(struct menu
*menu
)
317 visible
= menu
->prompt
->visible
.tri
;
319 visible
= menu
->prompt
->visible
.tri
= expr_calc_value(menu
->prompt
->visible
.expr
);
323 if (!sym
|| sym_get_tristate_value(menu
->sym
) == no
)
326 for (child
= menu
->list
; child
; child
= child
->next
)
327 if (menu_is_visible(child
))
332 const char *menu_get_prompt(struct menu
*menu
)
335 return menu
->prompt
->text
;
337 return menu
->sym
->name
;
341 struct menu
*menu_get_root_menu(struct menu
*menu
)
346 struct menu
*menu_get_parent_menu(struct menu
*menu
)
350 for (; menu
!= &rootmenu
; menu
= menu
->parent
) {
351 type
= menu
->prompt
? menu
->prompt
->type
: 0;
358 struct file
*file_lookup(const char *name
)
362 for (file
= file_list
; file
; file
= file
->next
) {
363 if (!strcmp(name
, file
->name
))
367 file
= malloc(sizeof(*file
));
368 memset(file
, 0, sizeof(*file
));
369 file
->name
= strdup(name
);
370 file
->next
= file_list
;
375 int file_write_dep(const char *name
)
381 name
= ".config.cmd";
382 out
= fopen("..config.tmp", "w");
385 fprintf(out
, "deps_config := \\\n");
386 for (file
= file_list
; file
; file
= file
->next
) {
388 fprintf(out
, "\t%s \\\n", file
->name
);
390 fprintf(out
, "\t%s\n", file
->name
);
392 fprintf(out
, "\n.config include/linux/autoconf.h: $(deps_config)\n\n$(deps_config):\n");
394 rename("..config.tmp", name
);