Commit 246cf9c26bf11f2bffbecea6e5bd222eee7b1df8

Authored by Catalin Marinas
Committed by Michal Marek
1 parent 60c8eca69f

kbuild: Warn on selecting symbols with unmet direct dependencies

The "select" statement in Kconfig files allows the enabling of options
even if they have unmet direct dependencies (i.e. "depends on" expands
to "no"). Currently, the "depends on" clauses are used in calculating
the visibility but they do not affect the reverse dependencies in any
way.

The patch introduces additional tracking of the "depends on" statements
and prints a warning on selecting an option if its direct dependencies
are not met.

Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Cc: Sam Ravnborg <sam@ravnborg.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Michal Marek <mmarek@suse.cz>

Showing 3 changed files with 25 additions and 0 deletions Inline Diff

scripts/kconfig/expr.h
1 /* 1 /*
2 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> 2 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
3 * Released under the terms of the GNU GPL v2.0. 3 * Released under the terms of the GNU GPL v2.0.
4 */ 4 */
5 5
6 #ifndef EXPR_H 6 #ifndef EXPR_H
7 #define EXPR_H 7 #define EXPR_H
8 8
9 #ifdef __cplusplus 9 #ifdef __cplusplus
10 extern "C" { 10 extern "C" {
11 #endif 11 #endif
12 12
13 #include <stdio.h> 13 #include <stdio.h>
14 #ifndef __cplusplus 14 #ifndef __cplusplus
15 #include <stdbool.h> 15 #include <stdbool.h>
16 #endif 16 #endif
17 17
18 struct file { 18 struct file {
19 struct file *next; 19 struct file *next;
20 struct file *parent; 20 struct file *parent;
21 char *name; 21 char *name;
22 int lineno; 22 int lineno;
23 int flags; 23 int flags;
24 }; 24 };
25 25
26 #define FILE_BUSY 0x0001 26 #define FILE_BUSY 0x0001
27 #define FILE_SCANNED 0x0002 27 #define FILE_SCANNED 0x0002
28 28
29 typedef enum tristate { 29 typedef enum tristate {
30 no, mod, yes 30 no, mod, yes
31 } tristate; 31 } tristate;
32 32
33 enum expr_type { 33 enum expr_type {
34 E_NONE, E_OR, E_AND, E_NOT, E_EQUAL, E_UNEQUAL, E_LIST, E_SYMBOL, E_RANGE 34 E_NONE, E_OR, E_AND, E_NOT, E_EQUAL, E_UNEQUAL, E_LIST, E_SYMBOL, E_RANGE
35 }; 35 };
36 36
37 union expr_data { 37 union expr_data {
38 struct expr *expr; 38 struct expr *expr;
39 struct symbol *sym; 39 struct symbol *sym;
40 }; 40 };
41 41
42 struct expr { 42 struct expr {
43 enum expr_type type; 43 enum expr_type type;
44 union expr_data left, right; 44 union expr_data left, right;
45 }; 45 };
46 46
47 #define EXPR_OR(dep1, dep2) (((dep1)>(dep2))?(dep1):(dep2)) 47 #define EXPR_OR(dep1, dep2) (((dep1)>(dep2))?(dep1):(dep2))
48 #define EXPR_AND(dep1, dep2) (((dep1)<(dep2))?(dep1):(dep2)) 48 #define EXPR_AND(dep1, dep2) (((dep1)<(dep2))?(dep1):(dep2))
49 #define EXPR_NOT(dep) (2-(dep)) 49 #define EXPR_NOT(dep) (2-(dep))
50 50
51 #define expr_list_for_each_sym(l, e, s) \ 51 #define expr_list_for_each_sym(l, e, s) \
52 for (e = (l); e && (s = e->right.sym); e = e->left.expr) 52 for (e = (l); e && (s = e->right.sym); e = e->left.expr)
53 53
54 struct expr_value { 54 struct expr_value {
55 struct expr *expr; 55 struct expr *expr;
56 tristate tri; 56 tristate tri;
57 }; 57 };
58 58
59 struct symbol_value { 59 struct symbol_value {
60 void *val; 60 void *val;
61 tristate tri; 61 tristate tri;
62 }; 62 };
63 63
64 enum symbol_type { 64 enum symbol_type {
65 S_UNKNOWN, S_BOOLEAN, S_TRISTATE, S_INT, S_HEX, S_STRING, S_OTHER 65 S_UNKNOWN, S_BOOLEAN, S_TRISTATE, S_INT, S_HEX, S_STRING, S_OTHER
66 }; 66 };
67 67
68 /* enum values are used as index to symbol.def[] */ 68 /* enum values are used as index to symbol.def[] */
69 enum { 69 enum {
70 S_DEF_USER, /* main user value */ 70 S_DEF_USER, /* main user value */
71 S_DEF_AUTO, /* values read from auto.conf */ 71 S_DEF_AUTO, /* values read from auto.conf */
72 S_DEF_DEF3, /* Reserved for UI usage */ 72 S_DEF_DEF3, /* Reserved for UI usage */
73 S_DEF_DEF4, /* Reserved for UI usage */ 73 S_DEF_DEF4, /* Reserved for UI usage */
74 S_DEF_COUNT 74 S_DEF_COUNT
75 }; 75 };
76 76
77 struct symbol { 77 struct symbol {
78 struct symbol *next; 78 struct symbol *next;
79 char *name; 79 char *name;
80 enum symbol_type type; 80 enum symbol_type type;
81 struct symbol_value curr; 81 struct symbol_value curr;
82 struct symbol_value def[S_DEF_COUNT]; 82 struct symbol_value def[S_DEF_COUNT];
83 tristate visible; 83 tristate visible;
84 int flags; 84 int flags;
85 struct property *prop; 85 struct property *prop;
86 struct expr_value dir_dep;
86 struct expr_value rev_dep; 87 struct expr_value rev_dep;
87 }; 88 };
88 89
89 #define for_all_symbols(i, sym) for (i = 0; i < SYMBOL_HASHSIZE; i++) for (sym = symbol_hash[i]; sym; sym = sym->next) if (sym->type != S_OTHER) 90 #define for_all_symbols(i, sym) for (i = 0; i < SYMBOL_HASHSIZE; i++) for (sym = symbol_hash[i]; sym; sym = sym->next) if (sym->type != S_OTHER)
90 91
91 #define SYMBOL_CONST 0x0001 /* symbol is const */ 92 #define SYMBOL_CONST 0x0001 /* symbol is const */
92 #define SYMBOL_CHECK 0x0008 /* used during dependency checking */ 93 #define SYMBOL_CHECK 0x0008 /* used during dependency checking */
93 #define SYMBOL_CHOICE 0x0010 /* start of a choice block (null name) */ 94 #define SYMBOL_CHOICE 0x0010 /* start of a choice block (null name) */
94 #define SYMBOL_CHOICEVAL 0x0020 /* used as a value in a choice block */ 95 #define SYMBOL_CHOICEVAL 0x0020 /* used as a value in a choice block */
95 #define SYMBOL_VALID 0x0080 /* set when symbol.curr is calculated */ 96 #define SYMBOL_VALID 0x0080 /* set when symbol.curr is calculated */
96 #define SYMBOL_OPTIONAL 0x0100 /* choice is optional - values can be 'n' */ 97 #define SYMBOL_OPTIONAL 0x0100 /* choice is optional - values can be 'n' */
97 #define SYMBOL_WRITE 0x0200 /* ? */ 98 #define SYMBOL_WRITE 0x0200 /* ? */
98 #define SYMBOL_CHANGED 0x0400 /* ? */ 99 #define SYMBOL_CHANGED 0x0400 /* ? */
99 #define SYMBOL_AUTO 0x1000 /* value from environment variable */ 100 #define SYMBOL_AUTO 0x1000 /* value from environment variable */
100 #define SYMBOL_CHECKED 0x2000 /* used during dependency checking */ 101 #define SYMBOL_CHECKED 0x2000 /* used during dependency checking */
101 #define SYMBOL_WARNED 0x8000 /* warning has been issued */ 102 #define SYMBOL_WARNED 0x8000 /* warning has been issued */
102 103
103 /* Set when symbol.def[] is used */ 104 /* Set when symbol.def[] is used */
104 #define SYMBOL_DEF 0x10000 /* First bit of SYMBOL_DEF */ 105 #define SYMBOL_DEF 0x10000 /* First bit of SYMBOL_DEF */
105 #define SYMBOL_DEF_USER 0x10000 /* symbol.def[S_DEF_USER] is valid */ 106 #define SYMBOL_DEF_USER 0x10000 /* symbol.def[S_DEF_USER] is valid */
106 #define SYMBOL_DEF_AUTO 0x20000 /* symbol.def[S_DEF_AUTO] is valid */ 107 #define SYMBOL_DEF_AUTO 0x20000 /* symbol.def[S_DEF_AUTO] is valid */
107 #define SYMBOL_DEF3 0x40000 /* symbol.def[S_DEF_3] is valid */ 108 #define SYMBOL_DEF3 0x40000 /* symbol.def[S_DEF_3] is valid */
108 #define SYMBOL_DEF4 0x80000 /* symbol.def[S_DEF_4] is valid */ 109 #define SYMBOL_DEF4 0x80000 /* symbol.def[S_DEF_4] is valid */
109 110
110 #define SYMBOL_MAXLENGTH 256 111 #define SYMBOL_MAXLENGTH 256
111 #define SYMBOL_HASHSIZE 9973 112 #define SYMBOL_HASHSIZE 9973
112 113
113 /* A property represent the config options that can be associated 114 /* A property represent the config options that can be associated
114 * with a config "symbol". 115 * with a config "symbol".
115 * Sample: 116 * Sample:
116 * config FOO 117 * config FOO
117 * default y 118 * default y
118 * prompt "foo prompt" 119 * prompt "foo prompt"
119 * select BAR 120 * select BAR
120 * config BAZ 121 * config BAZ
121 * int "BAZ Value" 122 * int "BAZ Value"
122 * range 1..255 123 * range 1..255
123 */ 124 */
124 enum prop_type { 125 enum prop_type {
125 P_UNKNOWN, 126 P_UNKNOWN,
126 P_PROMPT, /* prompt "foo prompt" or "BAZ Value" */ 127 P_PROMPT, /* prompt "foo prompt" or "BAZ Value" */
127 P_COMMENT, /* text associated with a comment */ 128 P_COMMENT, /* text associated with a comment */
128 P_MENU, /* prompt associated with a menuconfig option */ 129 P_MENU, /* prompt associated with a menuconfig option */
129 P_DEFAULT, /* default y */ 130 P_DEFAULT, /* default y */
130 P_CHOICE, /* choice value */ 131 P_CHOICE, /* choice value */
131 P_SELECT, /* select BAR */ 132 P_SELECT, /* select BAR */
132 P_RANGE, /* range 7..100 (for a symbol) */ 133 P_RANGE, /* range 7..100 (for a symbol) */
133 P_ENV, /* value from environment variable */ 134 P_ENV, /* value from environment variable */
134 }; 135 };
135 136
136 struct property { 137 struct property {
137 struct property *next; /* next property - null if last */ 138 struct property *next; /* next property - null if last */
138 struct symbol *sym; /* the symbol for which the property is associated */ 139 struct symbol *sym; /* the symbol for which the property is associated */
139 enum prop_type type; /* type of property */ 140 enum prop_type type; /* type of property */
140 const char *text; /* the prompt value - P_PROMPT, P_MENU, P_COMMENT */ 141 const char *text; /* the prompt value - P_PROMPT, P_MENU, P_COMMENT */
141 struct expr_value visible; 142 struct expr_value visible;
142 struct expr *expr; /* the optional conditional part of the property */ 143 struct expr *expr; /* the optional conditional part of the property */
143 struct menu *menu; /* the menu the property are associated with 144 struct menu *menu; /* the menu the property are associated with
144 * valid for: P_SELECT, P_RANGE, P_CHOICE, 145 * valid for: P_SELECT, P_RANGE, P_CHOICE,
145 * P_PROMPT, P_DEFAULT, P_MENU, P_COMMENT */ 146 * P_PROMPT, P_DEFAULT, P_MENU, P_COMMENT */
146 struct file *file; /* what file was this property defined */ 147 struct file *file; /* what file was this property defined */
147 int lineno; /* what lineno was this property defined */ 148 int lineno; /* what lineno was this property defined */
148 }; 149 };
149 150
150 #define for_all_properties(sym, st, tok) \ 151 #define for_all_properties(sym, st, tok) \
151 for (st = sym->prop; st; st = st->next) \ 152 for (st = sym->prop; st; st = st->next) \
152 if (st->type == (tok)) 153 if (st->type == (tok))
153 #define for_all_defaults(sym, st) for_all_properties(sym, st, P_DEFAULT) 154 #define for_all_defaults(sym, st) for_all_properties(sym, st, P_DEFAULT)
154 #define for_all_choices(sym, st) for_all_properties(sym, st, P_CHOICE) 155 #define for_all_choices(sym, st) for_all_properties(sym, st, P_CHOICE)
155 #define for_all_prompts(sym, st) \ 156 #define for_all_prompts(sym, st) \
156 for (st = sym->prop; st; st = st->next) \ 157 for (st = sym->prop; st; st = st->next) \
157 if (st->text) 158 if (st->text)
158 159
159 struct menu { 160 struct menu {
160 struct menu *next; 161 struct menu *next;
161 struct menu *parent; 162 struct menu *parent;
162 struct menu *list; 163 struct menu *list;
163 struct symbol *sym; 164 struct symbol *sym;
164 struct property *prompt; 165 struct property *prompt;
165 struct expr *dep; 166 struct expr *dep;
167 struct expr *dir_dep;
166 unsigned int flags; 168 unsigned int flags;
167 char *help; 169 char *help;
168 struct file *file; 170 struct file *file;
169 int lineno; 171 int lineno;
170 void *data; 172 void *data;
171 }; 173 };
172 174
173 #define MENU_CHANGED 0x0001 175 #define MENU_CHANGED 0x0001
174 #define MENU_ROOT 0x0002 176 #define MENU_ROOT 0x0002
175 177
176 #ifndef SWIG 178 #ifndef SWIG
177 179
178 extern struct file *file_list; 180 extern struct file *file_list;
179 extern struct file *current_file; 181 extern struct file *current_file;
180 struct file *lookup_file(const char *name); 182 struct file *lookup_file(const char *name);
181 183
182 extern struct symbol symbol_yes, symbol_no, symbol_mod; 184 extern struct symbol symbol_yes, symbol_no, symbol_mod;
183 extern struct symbol *modules_sym; 185 extern struct symbol *modules_sym;
184 extern struct symbol *sym_defconfig_list; 186 extern struct symbol *sym_defconfig_list;
185 extern int cdebug; 187 extern int cdebug;
186 struct expr *expr_alloc_symbol(struct symbol *sym); 188 struct expr *expr_alloc_symbol(struct symbol *sym);
187 struct expr *expr_alloc_one(enum expr_type type, struct expr *ce); 189 struct expr *expr_alloc_one(enum expr_type type, struct expr *ce);
188 struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e2); 190 struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e2);
189 struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2); 191 struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2);
190 struct expr *expr_alloc_and(struct expr *e1, struct expr *e2); 192 struct expr *expr_alloc_and(struct expr *e1, struct expr *e2);
191 struct expr *expr_alloc_or(struct expr *e1, struct expr *e2); 193 struct expr *expr_alloc_or(struct expr *e1, struct expr *e2);
192 struct expr *expr_copy(struct expr *org); 194 struct expr *expr_copy(struct expr *org);
193 void expr_free(struct expr *e); 195 void expr_free(struct expr *e);
194 int expr_eq(struct expr *e1, struct expr *e2); 196 int expr_eq(struct expr *e1, struct expr *e2);
195 void expr_eliminate_eq(struct expr **ep1, struct expr **ep2); 197 void expr_eliminate_eq(struct expr **ep1, struct expr **ep2);
196 tristate expr_calc_value(struct expr *e); 198 tristate expr_calc_value(struct expr *e);
197 struct expr *expr_eliminate_yn(struct expr *e); 199 struct expr *expr_eliminate_yn(struct expr *e);
198 struct expr *expr_trans_bool(struct expr *e); 200 struct expr *expr_trans_bool(struct expr *e);
199 struct expr *expr_eliminate_dups(struct expr *e); 201 struct expr *expr_eliminate_dups(struct expr *e);
200 struct expr *expr_transform(struct expr *e); 202 struct expr *expr_transform(struct expr *e);
201 int expr_contains_symbol(struct expr *dep, struct symbol *sym); 203 int expr_contains_symbol(struct expr *dep, struct symbol *sym);
202 bool expr_depends_symbol(struct expr *dep, struct symbol *sym); 204 bool expr_depends_symbol(struct expr *dep, struct symbol *sym);
203 struct expr *expr_extract_eq_and(struct expr **ep1, struct expr **ep2); 205 struct expr *expr_extract_eq_and(struct expr **ep1, struct expr **ep2);
204 struct expr *expr_extract_eq_or(struct expr **ep1, struct expr **ep2); 206 struct expr *expr_extract_eq_or(struct expr **ep1, struct expr **ep2);
205 void expr_extract_eq(enum expr_type type, struct expr **ep, struct expr **ep1, struct expr **ep2); 207 void expr_extract_eq(enum expr_type type, struct expr **ep, struct expr **ep1, struct expr **ep2);
206 struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym); 208 struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym);
207 209
208 void expr_fprint(struct expr *e, FILE *out); 210 void expr_fprint(struct expr *e, FILE *out);
209 struct gstr; /* forward */ 211 struct gstr; /* forward */
210 void expr_gstr_print(struct expr *e, struct gstr *gs); 212 void expr_gstr_print(struct expr *e, struct gstr *gs);
211 213
212 static inline int expr_is_yes(struct expr *e) 214 static inline int expr_is_yes(struct expr *e)
213 { 215 {
214 return !e || (e->type == E_SYMBOL && e->left.sym == &symbol_yes); 216 return !e || (e->type == E_SYMBOL && e->left.sym == &symbol_yes);
215 } 217 }
216 218
217 static inline int expr_is_no(struct expr *e) 219 static inline int expr_is_no(struct expr *e)
218 { 220 {
219 return e && (e->type == E_SYMBOL && e->left.sym == &symbol_no); 221 return e && (e->type == E_SYMBOL && e->left.sym == &symbol_no);
220 } 222 }
221 #endif 223 #endif
222 224
223 #ifdef __cplusplus 225 #ifdef __cplusplus
224 } 226 }
225 #endif 227 #endif
226 228
227 #endif /* EXPR_H */ 229 #endif /* EXPR_H */
228 230
scripts/kconfig/menu.c
1 /* 1 /*
2 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> 2 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
3 * Released under the terms of the GNU GPL v2.0. 3 * Released under the terms of the GNU GPL v2.0.
4 */ 4 */
5 5
6 #include <stdlib.h> 6 #include <stdlib.h>
7 #include <string.h> 7 #include <string.h>
8 8
9 #define LKC_DIRECT_LINK 9 #define LKC_DIRECT_LINK
10 #include "lkc.h" 10 #include "lkc.h"
11 11
12 static const char nohelp_text[] = N_( 12 static const char nohelp_text[] = N_(
13 "There is no help available for this kernel option.\n"); 13 "There is no help available for this kernel option.\n");
14 14
15 struct menu rootmenu; 15 struct menu rootmenu;
16 static struct menu **last_entry_ptr; 16 static struct menu **last_entry_ptr;
17 17
18 struct file *file_list; 18 struct file *file_list;
19 struct file *current_file; 19 struct file *current_file;
20 20
21 void menu_warn(struct menu *menu, const char *fmt, ...) 21 void menu_warn(struct menu *menu, const char *fmt, ...)
22 { 22 {
23 va_list ap; 23 va_list ap;
24 va_start(ap, fmt); 24 va_start(ap, fmt);
25 fprintf(stderr, "%s:%d:warning: ", menu->file->name, menu->lineno); 25 fprintf(stderr, "%s:%d:warning: ", menu->file->name, menu->lineno);
26 vfprintf(stderr, fmt, ap); 26 vfprintf(stderr, fmt, ap);
27 fprintf(stderr, "\n"); 27 fprintf(stderr, "\n");
28 va_end(ap); 28 va_end(ap);
29 } 29 }
30 30
31 static void prop_warn(struct property *prop, const char *fmt, ...) 31 static void prop_warn(struct property *prop, const char *fmt, ...)
32 { 32 {
33 va_list ap; 33 va_list ap;
34 va_start(ap, fmt); 34 va_start(ap, fmt);
35 fprintf(stderr, "%s:%d:warning: ", prop->file->name, prop->lineno); 35 fprintf(stderr, "%s:%d:warning: ", prop->file->name, prop->lineno);
36 vfprintf(stderr, fmt, ap); 36 vfprintf(stderr, fmt, ap);
37 fprintf(stderr, "\n"); 37 fprintf(stderr, "\n");
38 va_end(ap); 38 va_end(ap);
39 } 39 }
40 40
41 void _menu_init(void) 41 void _menu_init(void)
42 { 42 {
43 current_entry = current_menu = &rootmenu; 43 current_entry = current_menu = &rootmenu;
44 last_entry_ptr = &rootmenu.list; 44 last_entry_ptr = &rootmenu.list;
45 } 45 }
46 46
47 void menu_add_entry(struct symbol *sym) 47 void menu_add_entry(struct symbol *sym)
48 { 48 {
49 struct menu *menu; 49 struct menu *menu;
50 50
51 menu = malloc(sizeof(*menu)); 51 menu = malloc(sizeof(*menu));
52 memset(menu, 0, sizeof(*menu)); 52 memset(menu, 0, sizeof(*menu));
53 menu->sym = sym; 53 menu->sym = sym;
54 menu->parent = current_menu; 54 menu->parent = current_menu;
55 menu->file = current_file; 55 menu->file = current_file;
56 menu->lineno = zconf_lineno(); 56 menu->lineno = zconf_lineno();
57 57
58 *last_entry_ptr = menu; 58 *last_entry_ptr = menu;
59 last_entry_ptr = &menu->next; 59 last_entry_ptr = &menu->next;
60 current_entry = menu; 60 current_entry = menu;
61 } 61 }
62 62
63 void menu_end_entry(void) 63 void menu_end_entry(void)
64 { 64 {
65 } 65 }
66 66
67 struct menu *menu_add_menu(void) 67 struct menu *menu_add_menu(void)
68 { 68 {
69 menu_end_entry(); 69 menu_end_entry();
70 last_entry_ptr = &current_entry->list; 70 last_entry_ptr = &current_entry->list;
71 return current_menu = current_entry; 71 return current_menu = current_entry;
72 } 72 }
73 73
74 void menu_end_menu(void) 74 void menu_end_menu(void)
75 { 75 {
76 last_entry_ptr = &current_menu->next; 76 last_entry_ptr = &current_menu->next;
77 current_menu = current_menu->parent; 77 current_menu = current_menu->parent;
78 } 78 }
79 79
80 static struct expr *menu_check_dep(struct expr *e) 80 static struct expr *menu_check_dep(struct expr *e)
81 { 81 {
82 if (!e) 82 if (!e)
83 return e; 83 return e;
84 84
85 switch (e->type) { 85 switch (e->type) {
86 case E_NOT: 86 case E_NOT:
87 e->left.expr = menu_check_dep(e->left.expr); 87 e->left.expr = menu_check_dep(e->left.expr);
88 break; 88 break;
89 case E_OR: 89 case E_OR:
90 case E_AND: 90 case E_AND:
91 e->left.expr = menu_check_dep(e->left.expr); 91 e->left.expr = menu_check_dep(e->left.expr);
92 e->right.expr = menu_check_dep(e->right.expr); 92 e->right.expr = menu_check_dep(e->right.expr);
93 break; 93 break;
94 case E_SYMBOL: 94 case E_SYMBOL:
95 /* change 'm' into 'm' && MODULES */ 95 /* change 'm' into 'm' && MODULES */
96 if (e->left.sym == &symbol_mod) 96 if (e->left.sym == &symbol_mod)
97 return expr_alloc_and(e, expr_alloc_symbol(modules_sym)); 97 return expr_alloc_and(e, expr_alloc_symbol(modules_sym));
98 break; 98 break;
99 default: 99 default:
100 break; 100 break;
101 } 101 }
102 return e; 102 return e;
103 } 103 }
104 104
105 void menu_add_dep(struct expr *dep) 105 void menu_add_dep(struct expr *dep)
106 { 106 {
107 current_entry->dep = expr_alloc_and(current_entry->dep, menu_check_dep(dep)); 107 current_entry->dep = expr_alloc_and(current_entry->dep, menu_check_dep(dep));
108 current_entry->dir_dep = current_entry->dep;
108 } 109 }
109 110
110 void menu_set_type(int type) 111 void menu_set_type(int type)
111 { 112 {
112 struct symbol *sym = current_entry->sym; 113 struct symbol *sym = current_entry->sym;
113 114
114 if (sym->type == type) 115 if (sym->type == type)
115 return; 116 return;
116 if (sym->type == S_UNKNOWN) { 117 if (sym->type == S_UNKNOWN) {
117 sym->type = type; 118 sym->type = type;
118 return; 119 return;
119 } 120 }
120 menu_warn(current_entry, "type of '%s' redefined from '%s' to '%s'", 121 menu_warn(current_entry, "type of '%s' redefined from '%s' to '%s'",
121 sym->name ? sym->name : "<choice>", 122 sym->name ? sym->name : "<choice>",
122 sym_type_name(sym->type), sym_type_name(type)); 123 sym_type_name(sym->type), sym_type_name(type));
123 } 124 }
124 125
125 struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep) 126 struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep)
126 { 127 {
127 struct property *prop = prop_alloc(type, current_entry->sym); 128 struct property *prop = prop_alloc(type, current_entry->sym);
128 129
129 prop->menu = current_entry; 130 prop->menu = current_entry;
130 prop->expr = expr; 131 prop->expr = expr;
131 prop->visible.expr = menu_check_dep(dep); 132 prop->visible.expr = menu_check_dep(dep);
132 133
133 if (prompt) { 134 if (prompt) {
134 if (isspace(*prompt)) { 135 if (isspace(*prompt)) {
135 prop_warn(prop, "leading whitespace ignored"); 136 prop_warn(prop, "leading whitespace ignored");
136 while (isspace(*prompt)) 137 while (isspace(*prompt))
137 prompt++; 138 prompt++;
138 } 139 }
139 if (current_entry->prompt) 140 if (current_entry->prompt)
140 prop_warn(prop, "prompt redefined"); 141 prop_warn(prop, "prompt redefined");
141 current_entry->prompt = prop; 142 current_entry->prompt = prop;
142 } 143 }
143 prop->text = prompt; 144 prop->text = prompt;
144 145
145 return prop; 146 return prop;
146 } 147 }
147 148
148 struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep) 149 struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep)
149 { 150 {
150 return menu_add_prop(type, prompt, NULL, dep); 151 return menu_add_prop(type, prompt, NULL, dep);
151 } 152 }
152 153
153 void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep) 154 void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep)
154 { 155 {
155 menu_add_prop(type, NULL, expr, dep); 156 menu_add_prop(type, NULL, expr, dep);
156 } 157 }
157 158
158 void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep) 159 void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep)
159 { 160 {
160 menu_add_prop(type, NULL, expr_alloc_symbol(sym), dep); 161 menu_add_prop(type, NULL, expr_alloc_symbol(sym), dep);
161 } 162 }
162 163
163 void menu_add_option(int token, char *arg) 164 void menu_add_option(int token, char *arg)
164 { 165 {
165 struct property *prop; 166 struct property *prop;
166 167
167 switch (token) { 168 switch (token) {
168 case T_OPT_MODULES: 169 case T_OPT_MODULES:
169 prop = prop_alloc(P_DEFAULT, modules_sym); 170 prop = prop_alloc(P_DEFAULT, modules_sym);
170 prop->expr = expr_alloc_symbol(current_entry->sym); 171 prop->expr = expr_alloc_symbol(current_entry->sym);
171 break; 172 break;
172 case T_OPT_DEFCONFIG_LIST: 173 case T_OPT_DEFCONFIG_LIST:
173 if (!sym_defconfig_list) 174 if (!sym_defconfig_list)
174 sym_defconfig_list = current_entry->sym; 175 sym_defconfig_list = current_entry->sym;
175 else if (sym_defconfig_list != current_entry->sym) 176 else if (sym_defconfig_list != current_entry->sym)
176 zconf_error("trying to redefine defconfig symbol"); 177 zconf_error("trying to redefine defconfig symbol");
177 break; 178 break;
178 case T_OPT_ENV: 179 case T_OPT_ENV:
179 prop_add_env(arg); 180 prop_add_env(arg);
180 break; 181 break;
181 } 182 }
182 } 183 }
183 184
184 static int menu_range_valid_sym(struct symbol *sym, struct symbol *sym2) 185 static int menu_range_valid_sym(struct symbol *sym, struct symbol *sym2)
185 { 186 {
186 return sym2->type == S_INT || sym2->type == S_HEX || 187 return sym2->type == S_INT || sym2->type == S_HEX ||
187 (sym2->type == S_UNKNOWN && sym_string_valid(sym, sym2->name)); 188 (sym2->type == S_UNKNOWN && sym_string_valid(sym, sym2->name));
188 } 189 }
189 190
190 static void sym_check_prop(struct symbol *sym) 191 static void sym_check_prop(struct symbol *sym)
191 { 192 {
192 struct property *prop; 193 struct property *prop;
193 struct symbol *sym2; 194 struct symbol *sym2;
194 for (prop = sym->prop; prop; prop = prop->next) { 195 for (prop = sym->prop; prop; prop = prop->next) {
195 switch (prop->type) { 196 switch (prop->type) {
196 case P_DEFAULT: 197 case P_DEFAULT:
197 if ((sym->type == S_STRING || sym->type == S_INT || sym->type == S_HEX) && 198 if ((sym->type == S_STRING || sym->type == S_INT || sym->type == S_HEX) &&
198 prop->expr->type != E_SYMBOL) 199 prop->expr->type != E_SYMBOL)
199 prop_warn(prop, 200 prop_warn(prop,
200 "default for config symbol '%s'" 201 "default for config symbol '%s'"
201 " must be a single symbol", sym->name); 202 " must be a single symbol", sym->name);
202 break; 203 break;
203 case P_SELECT: 204 case P_SELECT:
204 sym2 = prop_get_symbol(prop); 205 sym2 = prop_get_symbol(prop);
205 if (sym->type != S_BOOLEAN && sym->type != S_TRISTATE) 206 if (sym->type != S_BOOLEAN && sym->type != S_TRISTATE)
206 prop_warn(prop, 207 prop_warn(prop,
207 "config symbol '%s' uses select, but is " 208 "config symbol '%s' uses select, but is "
208 "not boolean or tristate", sym->name); 209 "not boolean or tristate", sym->name);
209 else if (sym2->type != S_UNKNOWN && 210 else if (sym2->type != S_UNKNOWN &&
210 sym2->type != S_BOOLEAN && 211 sym2->type != S_BOOLEAN &&
211 sym2->type != S_TRISTATE) 212 sym2->type != S_TRISTATE)
212 prop_warn(prop, 213 prop_warn(prop,
213 "'%s' has wrong type. 'select' only " 214 "'%s' has wrong type. 'select' only "
214 "accept arguments of boolean and " 215 "accept arguments of boolean and "
215 "tristate type", sym2->name); 216 "tristate type", sym2->name);
216 break; 217 break;
217 case P_RANGE: 218 case P_RANGE:
218 if (sym->type != S_INT && sym->type != S_HEX) 219 if (sym->type != S_INT && sym->type != S_HEX)
219 prop_warn(prop, "range is only allowed " 220 prop_warn(prop, "range is only allowed "
220 "for int or hex symbols"); 221 "for int or hex symbols");
221 if (!menu_range_valid_sym(sym, prop->expr->left.sym) || 222 if (!menu_range_valid_sym(sym, prop->expr->left.sym) ||
222 !menu_range_valid_sym(sym, prop->expr->right.sym)) 223 !menu_range_valid_sym(sym, prop->expr->right.sym))
223 prop_warn(prop, "range is invalid"); 224 prop_warn(prop, "range is invalid");
224 break; 225 break;
225 default: 226 default:
226 ; 227 ;
227 } 228 }
228 } 229 }
229 } 230 }
230 231
231 void menu_finalize(struct menu *parent) 232 void menu_finalize(struct menu *parent)
232 { 233 {
233 struct menu *menu, *last_menu; 234 struct menu *menu, *last_menu;
234 struct symbol *sym; 235 struct symbol *sym;
235 struct property *prop; 236 struct property *prop;
236 struct expr *parentdep, *basedep, *dep, *dep2, **ep; 237 struct expr *parentdep, *basedep, *dep, *dep2, **ep;
237 238
238 sym = parent->sym; 239 sym = parent->sym;
239 if (parent->list) { 240 if (parent->list) {
240 if (sym && sym_is_choice(sym)) { 241 if (sym && sym_is_choice(sym)) {
241 if (sym->type == S_UNKNOWN) { 242 if (sym->type == S_UNKNOWN) {
242 /* find the first choice value to find out choice type */ 243 /* find the first choice value to find out choice type */
243 current_entry = parent; 244 current_entry = parent;
244 for (menu = parent->list; menu; menu = menu->next) { 245 for (menu = parent->list; menu; menu = menu->next) {
245 if (menu->sym && menu->sym->type != S_UNKNOWN) { 246 if (menu->sym && menu->sym->type != S_UNKNOWN) {
246 menu_set_type(menu->sym->type); 247 menu_set_type(menu->sym->type);
247 break; 248 break;
248 } 249 }
249 } 250 }
250 } 251 }
251 /* set the type of the remaining choice values */ 252 /* set the type of the remaining choice values */
252 for (menu = parent->list; menu; menu = menu->next) { 253 for (menu = parent->list; menu; menu = menu->next) {
253 current_entry = menu; 254 current_entry = menu;
254 if (menu->sym && menu->sym->type == S_UNKNOWN) 255 if (menu->sym && menu->sym->type == S_UNKNOWN)
255 menu_set_type(sym->type); 256 menu_set_type(sym->type);
256 } 257 }
257 parentdep = expr_alloc_symbol(sym); 258 parentdep = expr_alloc_symbol(sym);
258 } else if (parent->prompt) 259 } else if (parent->prompt)
259 parentdep = parent->prompt->visible.expr; 260 parentdep = parent->prompt->visible.expr;
260 else 261 else
261 parentdep = parent->dep; 262 parentdep = parent->dep;
262 263
263 for (menu = parent->list; menu; menu = menu->next) { 264 for (menu = parent->list; menu; menu = menu->next) {
264 basedep = expr_transform(menu->dep); 265 basedep = expr_transform(menu->dep);
265 basedep = expr_alloc_and(expr_copy(parentdep), basedep); 266 basedep = expr_alloc_and(expr_copy(parentdep), basedep);
266 basedep = expr_eliminate_dups(basedep); 267 basedep = expr_eliminate_dups(basedep);
267 menu->dep = basedep; 268 menu->dep = basedep;
268 if (menu->sym) 269 if (menu->sym)
269 prop = menu->sym->prop; 270 prop = menu->sym->prop;
270 else 271 else
271 prop = menu->prompt; 272 prop = menu->prompt;
272 for (; prop; prop = prop->next) { 273 for (; prop; prop = prop->next) {
273 if (prop->menu != menu) 274 if (prop->menu != menu)
274 continue; 275 continue;
275 dep = expr_transform(prop->visible.expr); 276 dep = expr_transform(prop->visible.expr);
276 dep = expr_alloc_and(expr_copy(basedep), dep); 277 dep = expr_alloc_and(expr_copy(basedep), dep);
277 dep = expr_eliminate_dups(dep); 278 dep = expr_eliminate_dups(dep);
278 if (menu->sym && menu->sym->type != S_TRISTATE) 279 if (menu->sym && menu->sym->type != S_TRISTATE)
279 dep = expr_trans_bool(dep); 280 dep = expr_trans_bool(dep);
280 prop->visible.expr = dep; 281 prop->visible.expr = dep;
281 if (prop->type == P_SELECT) { 282 if (prop->type == P_SELECT) {
282 struct symbol *es = prop_get_symbol(prop); 283 struct symbol *es = prop_get_symbol(prop);
283 es->rev_dep.expr = expr_alloc_or(es->rev_dep.expr, 284 es->rev_dep.expr = expr_alloc_or(es->rev_dep.expr,
284 expr_alloc_and(expr_alloc_symbol(menu->sym), expr_copy(dep))); 285 expr_alloc_and(expr_alloc_symbol(menu->sym), expr_copy(dep)));
285 } 286 }
286 } 287 }
287 } 288 }
288 for (menu = parent->list; menu; menu = menu->next) 289 for (menu = parent->list; menu; menu = menu->next)
289 menu_finalize(menu); 290 menu_finalize(menu);
290 } else if (sym) { 291 } else if (sym) {
292 /* ignore inherited dependencies for dir_dep */
293 sym->dir_dep.expr = expr_transform(expr_copy(parent->dir_dep));
294 sym->dir_dep.expr = expr_eliminate_dups(sym->dir_dep.expr);
295
291 basedep = parent->prompt ? parent->prompt->visible.expr : NULL; 296 basedep = parent->prompt ? parent->prompt->visible.expr : NULL;
292 basedep = expr_trans_compare(basedep, E_UNEQUAL, &symbol_no); 297 basedep = expr_trans_compare(basedep, E_UNEQUAL, &symbol_no);
293 basedep = expr_eliminate_dups(expr_transform(basedep)); 298 basedep = expr_eliminate_dups(expr_transform(basedep));
294 last_menu = NULL; 299 last_menu = NULL;
295 for (menu = parent->next; menu; menu = menu->next) { 300 for (menu = parent->next; menu; menu = menu->next) {
296 dep = menu->prompt ? menu->prompt->visible.expr : menu->dep; 301 dep = menu->prompt ? menu->prompt->visible.expr : menu->dep;
297 if (!expr_contains_symbol(dep, sym)) 302 if (!expr_contains_symbol(dep, sym))
298 break; 303 break;
299 if (expr_depends_symbol(dep, sym)) 304 if (expr_depends_symbol(dep, sym))
300 goto next; 305 goto next;
301 dep = expr_trans_compare(dep, E_UNEQUAL, &symbol_no); 306 dep = expr_trans_compare(dep, E_UNEQUAL, &symbol_no);
302 dep = expr_eliminate_dups(expr_transform(dep)); 307 dep = expr_eliminate_dups(expr_transform(dep));
303 dep2 = expr_copy(basedep); 308 dep2 = expr_copy(basedep);
304 expr_eliminate_eq(&dep, &dep2); 309 expr_eliminate_eq(&dep, &dep2);
305 expr_free(dep); 310 expr_free(dep);
306 if (!expr_is_yes(dep2)) { 311 if (!expr_is_yes(dep2)) {
307 expr_free(dep2); 312 expr_free(dep2);
308 break; 313 break;
309 } 314 }
310 expr_free(dep2); 315 expr_free(dep2);
311 next: 316 next:
312 menu_finalize(menu); 317 menu_finalize(menu);
313 menu->parent = parent; 318 menu->parent = parent;
314 last_menu = menu; 319 last_menu = menu;
315 } 320 }
316 if (last_menu) { 321 if (last_menu) {
317 parent->list = parent->next; 322 parent->list = parent->next;
318 parent->next = last_menu->next; 323 parent->next = last_menu->next;
319 last_menu->next = NULL; 324 last_menu->next = NULL;
320 } 325 }
321 } 326 }
322 for (menu = parent->list; menu; menu = menu->next) { 327 for (menu = parent->list; menu; menu = menu->next) {
323 if (sym && sym_is_choice(sym) && 328 if (sym && sym_is_choice(sym) &&
324 menu->sym && !sym_is_choice_value(menu->sym)) { 329 menu->sym && !sym_is_choice_value(menu->sym)) {
325 current_entry = menu; 330 current_entry = menu;
326 menu->sym->flags |= SYMBOL_CHOICEVAL; 331 menu->sym->flags |= SYMBOL_CHOICEVAL;
327 if (!menu->prompt) 332 if (!menu->prompt)
328 menu_warn(menu, "choice value must have a prompt"); 333 menu_warn(menu, "choice value must have a prompt");
329 for (prop = menu->sym->prop; prop; prop = prop->next) { 334 for (prop = menu->sym->prop; prop; prop = prop->next) {
330 if (prop->type == P_DEFAULT) 335 if (prop->type == P_DEFAULT)
331 prop_warn(prop, "defaults for choice " 336 prop_warn(prop, "defaults for choice "
332 "values not supported"); 337 "values not supported");
333 if (prop->menu == menu) 338 if (prop->menu == menu)
334 continue; 339 continue;
335 if (prop->type == P_PROMPT && 340 if (prop->type == P_PROMPT &&
336 prop->menu->parent->sym != sym) 341 prop->menu->parent->sym != sym)
337 prop_warn(prop, "choice value used outside its choice group"); 342 prop_warn(prop, "choice value used outside its choice group");
338 } 343 }
339 /* Non-tristate choice values of tristate choices must 344 /* Non-tristate choice values of tristate choices must
340 * depend on the choice being set to Y. The choice 345 * depend on the choice being set to Y. The choice
341 * values' dependencies were propagated to their 346 * values' dependencies were propagated to their
342 * properties above, so the change here must be re- 347 * properties above, so the change here must be re-
343 * propagated. 348 * propagated.
344 */ 349 */
345 if (sym->type == S_TRISTATE && menu->sym->type != S_TRISTATE) { 350 if (sym->type == S_TRISTATE && menu->sym->type != S_TRISTATE) {
346 basedep = expr_alloc_comp(E_EQUAL, sym, &symbol_yes); 351 basedep = expr_alloc_comp(E_EQUAL, sym, &symbol_yes);
347 menu->dep = expr_alloc_and(basedep, menu->dep); 352 menu->dep = expr_alloc_and(basedep, menu->dep);
348 for (prop = menu->sym->prop; prop; prop = prop->next) { 353 for (prop = menu->sym->prop; prop; prop = prop->next) {
349 if (prop->menu != menu) 354 if (prop->menu != menu)
350 continue; 355 continue;
351 prop->visible.expr = expr_alloc_and(expr_copy(basedep), 356 prop->visible.expr = expr_alloc_and(expr_copy(basedep),
352 prop->visible.expr); 357 prop->visible.expr);
353 } 358 }
354 } 359 }
355 menu_add_symbol(P_CHOICE, sym, NULL); 360 menu_add_symbol(P_CHOICE, sym, NULL);
356 prop = sym_get_choice_prop(sym); 361 prop = sym_get_choice_prop(sym);
357 for (ep = &prop->expr; *ep; ep = &(*ep)->left.expr) 362 for (ep = &prop->expr; *ep; ep = &(*ep)->left.expr)
358 ; 363 ;
359 *ep = expr_alloc_one(E_LIST, NULL); 364 *ep = expr_alloc_one(E_LIST, NULL);
360 (*ep)->right.sym = menu->sym; 365 (*ep)->right.sym = menu->sym;
361 } 366 }
362 if (menu->list && (!menu->prompt || !menu->prompt->text)) { 367 if (menu->list && (!menu->prompt || !menu->prompt->text)) {
363 for (last_menu = menu->list; ; last_menu = last_menu->next) { 368 for (last_menu = menu->list; ; last_menu = last_menu->next) {
364 last_menu->parent = parent; 369 last_menu->parent = parent;
365 if (!last_menu->next) 370 if (!last_menu->next)
366 break; 371 break;
367 } 372 }
368 last_menu->next = menu->next; 373 last_menu->next = menu->next;
369 menu->next = menu->list; 374 menu->next = menu->list;
370 menu->list = NULL; 375 menu->list = NULL;
371 } 376 }
372 } 377 }
373 378
374 if (sym && !(sym->flags & SYMBOL_WARNED)) { 379 if (sym && !(sym->flags & SYMBOL_WARNED)) {
375 if (sym->type == S_UNKNOWN) 380 if (sym->type == S_UNKNOWN)
376 menu_warn(parent, "config symbol defined without type"); 381 menu_warn(parent, "config symbol defined without type");
377 382
378 if (sym_is_choice(sym) && !parent->prompt) 383 if (sym_is_choice(sym) && !parent->prompt)
379 menu_warn(parent, "choice must have a prompt"); 384 menu_warn(parent, "choice must have a prompt");
380 385
381 /* Check properties connected to this symbol */ 386 /* Check properties connected to this symbol */
382 sym_check_prop(sym); 387 sym_check_prop(sym);
383 sym->flags |= SYMBOL_WARNED; 388 sym->flags |= SYMBOL_WARNED;
384 } 389 }
385 390
386 if (sym && !sym_is_optional(sym) && parent->prompt) { 391 if (sym && !sym_is_optional(sym) && parent->prompt) {
387 sym->rev_dep.expr = expr_alloc_or(sym->rev_dep.expr, 392 sym->rev_dep.expr = expr_alloc_or(sym->rev_dep.expr,
388 expr_alloc_and(parent->prompt->visible.expr, 393 expr_alloc_and(parent->prompt->visible.expr,
389 expr_alloc_symbol(&symbol_mod))); 394 expr_alloc_symbol(&symbol_mod)));
390 } 395 }
391 } 396 }
392 397
393 bool menu_has_prompt(struct menu *menu) 398 bool menu_has_prompt(struct menu *menu)
394 { 399 {
395 if (!menu->prompt) 400 if (!menu->prompt)
396 return false; 401 return false;
397 return true; 402 return true;
398 } 403 }
399 404
400 bool menu_is_visible(struct menu *menu) 405 bool menu_is_visible(struct menu *menu)
401 { 406 {
402 struct menu *child; 407 struct menu *child;
403 struct symbol *sym; 408 struct symbol *sym;
404 tristate visible; 409 tristate visible;
405 410
406 if (!menu->prompt) 411 if (!menu->prompt)
407 return false; 412 return false;
408 413
409 sym = menu->sym; 414 sym = menu->sym;
410 if (sym) { 415 if (sym) {
411 sym_calc_value(sym); 416 sym_calc_value(sym);
412 visible = menu->prompt->visible.tri; 417 visible = menu->prompt->visible.tri;
413 } else 418 } else
414 visible = menu->prompt->visible.tri = expr_calc_value(menu->prompt->visible.expr); 419 visible = menu->prompt->visible.tri = expr_calc_value(menu->prompt->visible.expr);
415 420
416 if (visible != no) 421 if (visible != no)
417 return true; 422 return true;
418 423
419 if (!sym || sym_get_tristate_value(menu->sym) == no) 424 if (!sym || sym_get_tristate_value(menu->sym) == no)
420 return false; 425 return false;
421 426
422 for (child = menu->list; child; child = child->next) { 427 for (child = menu->list; child; child = child->next) {
423 if (menu_is_visible(child)) { 428 if (menu_is_visible(child)) {
424 if (sym) 429 if (sym)
425 sym->flags |= SYMBOL_DEF_USER; 430 sym->flags |= SYMBOL_DEF_USER;
426 return true; 431 return true;
427 } 432 }
428 } 433 }
429 434
430 return false; 435 return false;
431 } 436 }
432 437
433 const char *menu_get_prompt(struct menu *menu) 438 const char *menu_get_prompt(struct menu *menu)
434 { 439 {
435 if (menu->prompt) 440 if (menu->prompt)
436 return menu->prompt->text; 441 return menu->prompt->text;
437 else if (menu->sym) 442 else if (menu->sym)
438 return menu->sym->name; 443 return menu->sym->name;
439 return NULL; 444 return NULL;
440 } 445 }
441 446
442 struct menu *menu_get_root_menu(struct menu *menu) 447 struct menu *menu_get_root_menu(struct menu *menu)
443 { 448 {
444 return &rootmenu; 449 return &rootmenu;
445 } 450 }
446 451
447 struct menu *menu_get_parent_menu(struct menu *menu) 452 struct menu *menu_get_parent_menu(struct menu *menu)
448 { 453 {
449 enum prop_type type; 454 enum prop_type type;
450 455
451 for (; menu != &rootmenu; menu = menu->parent) { 456 for (; menu != &rootmenu; menu = menu->parent) {
452 type = menu->prompt ? menu->prompt->type : 0; 457 type = menu->prompt ? menu->prompt->type : 0;
453 if (type == P_MENU) 458 if (type == P_MENU)
454 break; 459 break;
455 } 460 }
456 return menu; 461 return menu;
457 } 462 }
458 463
459 bool menu_has_help(struct menu *menu) 464 bool menu_has_help(struct menu *menu)
460 { 465 {
461 return menu->help != NULL; 466 return menu->help != NULL;
462 } 467 }
463 468
464 const char *menu_get_help(struct menu *menu) 469 const char *menu_get_help(struct menu *menu)
465 { 470 {
466 if (menu->help) 471 if (menu->help)
467 return menu->help; 472 return menu->help;
468 else 473 else
469 return ""; 474 return "";
470 } 475 }
471 476
472 static void get_prompt_str(struct gstr *r, struct property *prop) 477 static void get_prompt_str(struct gstr *r, struct property *prop)
473 { 478 {
474 int i, j; 479 int i, j;
475 struct menu *submenu[8], *menu; 480 struct menu *submenu[8], *menu;
476 481
477 str_printf(r, _("Prompt: %s\n"), _(prop->text)); 482 str_printf(r, _("Prompt: %s\n"), _(prop->text));
478 str_printf(r, _(" Defined at %s:%d\n"), prop->menu->file->name, 483 str_printf(r, _(" Defined at %s:%d\n"), prop->menu->file->name,
479 prop->menu->lineno); 484 prop->menu->lineno);
480 if (!expr_is_yes(prop->visible.expr)) { 485 if (!expr_is_yes(prop->visible.expr)) {
481 str_append(r, _(" Depends on: ")); 486 str_append(r, _(" Depends on: "));
482 expr_gstr_print(prop->visible.expr, r); 487 expr_gstr_print(prop->visible.expr, r);
483 str_append(r, "\n"); 488 str_append(r, "\n");
484 } 489 }
485 menu = prop->menu->parent; 490 menu = prop->menu->parent;
486 for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent) 491 for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent)
487 submenu[i++] = menu; 492 submenu[i++] = menu;
488 if (i > 0) { 493 if (i > 0) {
489 str_printf(r, _(" Location:\n")); 494 str_printf(r, _(" Location:\n"));
490 for (j = 4; --i >= 0; j += 2) { 495 for (j = 4; --i >= 0; j += 2) {
491 menu = submenu[i]; 496 menu = submenu[i];
492 str_printf(r, "%*c-> %s", j, ' ', _(menu_get_prompt(menu))); 497 str_printf(r, "%*c-> %s", j, ' ', _(menu_get_prompt(menu)));
493 if (menu->sym) { 498 if (menu->sym) {
494 str_printf(r, " (%s [=%s])", menu->sym->name ? 499 str_printf(r, " (%s [=%s])", menu->sym->name ?
495 menu->sym->name : _("<choice>"), 500 menu->sym->name : _("<choice>"),
496 sym_get_string_value(menu->sym)); 501 sym_get_string_value(menu->sym));
497 } 502 }
498 str_append(r, "\n"); 503 str_append(r, "\n");
499 } 504 }
500 } 505 }
501 } 506 }
502 507
503 void get_symbol_str(struct gstr *r, struct symbol *sym) 508 void get_symbol_str(struct gstr *r, struct symbol *sym)
504 { 509 {
505 bool hit; 510 bool hit;
506 struct property *prop; 511 struct property *prop;
507 512
508 if (sym && sym->name) { 513 if (sym && sym->name) {
509 str_printf(r, "Symbol: %s [=%s]\n", sym->name, 514 str_printf(r, "Symbol: %s [=%s]\n", sym->name,
510 sym_get_string_value(sym)); 515 sym_get_string_value(sym));
511 str_printf(r, "Type : %s\n", sym_type_name(sym->type)); 516 str_printf(r, "Type : %s\n", sym_type_name(sym->type));
512 if (sym->type == S_INT || sym->type == S_HEX) { 517 if (sym->type == S_INT || sym->type == S_HEX) {
513 prop = sym_get_range_prop(sym); 518 prop = sym_get_range_prop(sym);
514 if (prop) { 519 if (prop) {
515 str_printf(r, "Range : "); 520 str_printf(r, "Range : ");
516 expr_gstr_print(prop->expr, r); 521 expr_gstr_print(prop->expr, r);
517 str_append(r, "\n"); 522 str_append(r, "\n");
518 } 523 }
519 } 524 }
520 } 525 }
521 for_all_prompts(sym, prop) 526 for_all_prompts(sym, prop)
522 get_prompt_str(r, prop); 527 get_prompt_str(r, prop);
523 hit = false; 528 hit = false;
524 for_all_properties(sym, prop, P_SELECT) { 529 for_all_properties(sym, prop, P_SELECT) {
525 if (!hit) { 530 if (!hit) {
526 str_append(r, " Selects: "); 531 str_append(r, " Selects: ");
527 hit = true; 532 hit = true;
528 } else 533 } else
529 str_printf(r, " && "); 534 str_printf(r, " && ");
530 expr_gstr_print(prop->expr, r); 535 expr_gstr_print(prop->expr, r);
531 } 536 }
532 if (hit) 537 if (hit)
533 str_append(r, "\n"); 538 str_append(r, "\n");
534 if (sym->rev_dep.expr) { 539 if (sym->rev_dep.expr) {
535 str_append(r, _(" Selected by: ")); 540 str_append(r, _(" Selected by: "));
536 expr_gstr_print(sym->rev_dep.expr, r); 541 expr_gstr_print(sym->rev_dep.expr, r);
537 str_append(r, "\n"); 542 str_append(r, "\n");
538 } 543 }
539 str_append(r, "\n\n"); 544 str_append(r, "\n\n");
540 } 545 }
541 546
542 struct gstr get_relations_str(struct symbol **sym_arr) 547 struct gstr get_relations_str(struct symbol **sym_arr)
543 { 548 {
544 struct symbol *sym; 549 struct symbol *sym;
545 struct gstr res = str_new(); 550 struct gstr res = str_new();
546 int i; 551 int i;
547 552
548 for (i = 0; sym_arr && (sym = sym_arr[i]); i++) 553 for (i = 0; sym_arr && (sym = sym_arr[i]); i++)
549 get_symbol_str(&res, sym); 554 get_symbol_str(&res, sym);
550 if (!i) 555 if (!i)
551 str_append(&res, _("No matches found.\n")); 556 str_append(&res, _("No matches found.\n"));
552 return res; 557 return res;
553 } 558 }
554 559
555 560
556 void menu_get_ext_help(struct menu *menu, struct gstr *help) 561 void menu_get_ext_help(struct menu *menu, struct gstr *help)
557 { 562 {
558 struct symbol *sym = menu->sym; 563 struct symbol *sym = menu->sym;
559 564
560 if (menu_has_help(menu)) { 565 if (menu_has_help(menu)) {
561 if (sym->name) { 566 if (sym->name) {
562 str_printf(help, "CONFIG_%s:\n\n", sym->name); 567 str_printf(help, "CONFIG_%s:\n\n", sym->name);
563 str_append(help, _(menu_get_help(menu))); 568 str_append(help, _(menu_get_help(menu)));
564 str_append(help, "\n"); 569 str_append(help, "\n");
565 } 570 }
566 } else { 571 } else {
567 str_append(help, nohelp_text); 572 str_append(help, nohelp_text);
568 } 573 }
569 if (sym) 574 if (sym)
570 get_symbol_str(help, sym); 575 get_symbol_str(help, sym);
571 } 576 }
572 577
scripts/kconfig/symbol.c
1 /* 1 /*
2 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> 2 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
3 * Released under the terms of the GNU GPL v2.0. 3 * Released under the terms of the GNU GPL v2.0.
4 */ 4 */
5 5
6 #include <ctype.h> 6 #include <ctype.h>
7 #include <stdlib.h> 7 #include <stdlib.h>
8 #include <string.h> 8 #include <string.h>
9 #include <regex.h> 9 #include <regex.h>
10 #include <sys/utsname.h> 10 #include <sys/utsname.h>
11 11
12 #define LKC_DIRECT_LINK 12 #define LKC_DIRECT_LINK
13 #include "lkc.h" 13 #include "lkc.h"
14 14
15 struct symbol symbol_yes = { 15 struct symbol symbol_yes = {
16 .name = "y", 16 .name = "y",
17 .curr = { "y", yes }, 17 .curr = { "y", yes },
18 .flags = SYMBOL_CONST|SYMBOL_VALID, 18 .flags = SYMBOL_CONST|SYMBOL_VALID,
19 }, symbol_mod = { 19 }, symbol_mod = {
20 .name = "m", 20 .name = "m",
21 .curr = { "m", mod }, 21 .curr = { "m", mod },
22 .flags = SYMBOL_CONST|SYMBOL_VALID, 22 .flags = SYMBOL_CONST|SYMBOL_VALID,
23 }, symbol_no = { 23 }, symbol_no = {
24 .name = "n", 24 .name = "n",
25 .curr = { "n", no }, 25 .curr = { "n", no },
26 .flags = SYMBOL_CONST|SYMBOL_VALID, 26 .flags = SYMBOL_CONST|SYMBOL_VALID,
27 }, symbol_empty = { 27 }, symbol_empty = {
28 .name = "", 28 .name = "",
29 .curr = { "", no }, 29 .curr = { "", no },
30 .flags = SYMBOL_VALID, 30 .flags = SYMBOL_VALID,
31 }; 31 };
32 32
33 struct symbol *sym_defconfig_list; 33 struct symbol *sym_defconfig_list;
34 struct symbol *modules_sym; 34 struct symbol *modules_sym;
35 tristate modules_val; 35 tristate modules_val;
36 36
37 struct expr *sym_env_list; 37 struct expr *sym_env_list;
38 38
39 static void sym_add_default(struct symbol *sym, const char *def) 39 static void sym_add_default(struct symbol *sym, const char *def)
40 { 40 {
41 struct property *prop = prop_alloc(P_DEFAULT, sym); 41 struct property *prop = prop_alloc(P_DEFAULT, sym);
42 42
43 prop->expr = expr_alloc_symbol(sym_lookup(def, SYMBOL_CONST)); 43 prop->expr = expr_alloc_symbol(sym_lookup(def, SYMBOL_CONST));
44 } 44 }
45 45
46 void sym_init(void) 46 void sym_init(void)
47 { 47 {
48 struct symbol *sym; 48 struct symbol *sym;
49 struct utsname uts; 49 struct utsname uts;
50 static bool inited = false; 50 static bool inited = false;
51 51
52 if (inited) 52 if (inited)
53 return; 53 return;
54 inited = true; 54 inited = true;
55 55
56 uname(&uts); 56 uname(&uts);
57 57
58 sym = sym_lookup("UNAME_RELEASE", 0); 58 sym = sym_lookup("UNAME_RELEASE", 0);
59 sym->type = S_STRING; 59 sym->type = S_STRING;
60 sym->flags |= SYMBOL_AUTO; 60 sym->flags |= SYMBOL_AUTO;
61 sym_add_default(sym, uts.release); 61 sym_add_default(sym, uts.release);
62 } 62 }
63 63
64 enum symbol_type sym_get_type(struct symbol *sym) 64 enum symbol_type sym_get_type(struct symbol *sym)
65 { 65 {
66 enum symbol_type type = sym->type; 66 enum symbol_type type = sym->type;
67 67
68 if (type == S_TRISTATE) { 68 if (type == S_TRISTATE) {
69 if (sym_is_choice_value(sym) && sym->visible == yes) 69 if (sym_is_choice_value(sym) && sym->visible == yes)
70 type = S_BOOLEAN; 70 type = S_BOOLEAN;
71 else if (modules_val == no) 71 else if (modules_val == no)
72 type = S_BOOLEAN; 72 type = S_BOOLEAN;
73 } 73 }
74 return type; 74 return type;
75 } 75 }
76 76
77 const char *sym_type_name(enum symbol_type type) 77 const char *sym_type_name(enum symbol_type type)
78 { 78 {
79 switch (type) { 79 switch (type) {
80 case S_BOOLEAN: 80 case S_BOOLEAN:
81 return "boolean"; 81 return "boolean";
82 case S_TRISTATE: 82 case S_TRISTATE:
83 return "tristate"; 83 return "tristate";
84 case S_INT: 84 case S_INT:
85 return "integer"; 85 return "integer";
86 case S_HEX: 86 case S_HEX:
87 return "hex"; 87 return "hex";
88 case S_STRING: 88 case S_STRING:
89 return "string"; 89 return "string";
90 case S_UNKNOWN: 90 case S_UNKNOWN:
91 return "unknown"; 91 return "unknown";
92 case S_OTHER: 92 case S_OTHER:
93 break; 93 break;
94 } 94 }
95 return "???"; 95 return "???";
96 } 96 }
97 97
98 struct property *sym_get_choice_prop(struct symbol *sym) 98 struct property *sym_get_choice_prop(struct symbol *sym)
99 { 99 {
100 struct property *prop; 100 struct property *prop;
101 101
102 for_all_choices(sym, prop) 102 for_all_choices(sym, prop)
103 return prop; 103 return prop;
104 return NULL; 104 return NULL;
105 } 105 }
106 106
107 struct property *sym_get_env_prop(struct symbol *sym) 107 struct property *sym_get_env_prop(struct symbol *sym)
108 { 108 {
109 struct property *prop; 109 struct property *prop;
110 110
111 for_all_properties(sym, prop, P_ENV) 111 for_all_properties(sym, prop, P_ENV)
112 return prop; 112 return prop;
113 return NULL; 113 return NULL;
114 } 114 }
115 115
116 struct property *sym_get_default_prop(struct symbol *sym) 116 struct property *sym_get_default_prop(struct symbol *sym)
117 { 117 {
118 struct property *prop; 118 struct property *prop;
119 119
120 for_all_defaults(sym, prop) { 120 for_all_defaults(sym, prop) {
121 prop->visible.tri = expr_calc_value(prop->visible.expr); 121 prop->visible.tri = expr_calc_value(prop->visible.expr);
122 if (prop->visible.tri != no) 122 if (prop->visible.tri != no)
123 return prop; 123 return prop;
124 } 124 }
125 return NULL; 125 return NULL;
126 } 126 }
127 127
128 static struct property *sym_get_range_prop(struct symbol *sym) 128 static struct property *sym_get_range_prop(struct symbol *sym)
129 { 129 {
130 struct property *prop; 130 struct property *prop;
131 131
132 for_all_properties(sym, prop, P_RANGE) { 132 for_all_properties(sym, prop, P_RANGE) {
133 prop->visible.tri = expr_calc_value(prop->visible.expr); 133 prop->visible.tri = expr_calc_value(prop->visible.expr);
134 if (prop->visible.tri != no) 134 if (prop->visible.tri != no)
135 return prop; 135 return prop;
136 } 136 }
137 return NULL; 137 return NULL;
138 } 138 }
139 139
140 static int sym_get_range_val(struct symbol *sym, int base) 140 static int sym_get_range_val(struct symbol *sym, int base)
141 { 141 {
142 sym_calc_value(sym); 142 sym_calc_value(sym);
143 switch (sym->type) { 143 switch (sym->type) {
144 case S_INT: 144 case S_INT:
145 base = 10; 145 base = 10;
146 break; 146 break;
147 case S_HEX: 147 case S_HEX:
148 base = 16; 148 base = 16;
149 break; 149 break;
150 default: 150 default:
151 break; 151 break;
152 } 152 }
153 return strtol(sym->curr.val, NULL, base); 153 return strtol(sym->curr.val, NULL, base);
154 } 154 }
155 155
156 static void sym_validate_range(struct symbol *sym) 156 static void sym_validate_range(struct symbol *sym)
157 { 157 {
158 struct property *prop; 158 struct property *prop;
159 int base, val, val2; 159 int base, val, val2;
160 char str[64]; 160 char str[64];
161 161
162 switch (sym->type) { 162 switch (sym->type) {
163 case S_INT: 163 case S_INT:
164 base = 10; 164 base = 10;
165 break; 165 break;
166 case S_HEX: 166 case S_HEX:
167 base = 16; 167 base = 16;
168 break; 168 break;
169 default: 169 default:
170 return; 170 return;
171 } 171 }
172 prop = sym_get_range_prop(sym); 172 prop = sym_get_range_prop(sym);
173 if (!prop) 173 if (!prop)
174 return; 174 return;
175 val = strtol(sym->curr.val, NULL, base); 175 val = strtol(sym->curr.val, NULL, base);
176 val2 = sym_get_range_val(prop->expr->left.sym, base); 176 val2 = sym_get_range_val(prop->expr->left.sym, base);
177 if (val >= val2) { 177 if (val >= val2) {
178 val2 = sym_get_range_val(prop->expr->right.sym, base); 178 val2 = sym_get_range_val(prop->expr->right.sym, base);
179 if (val <= val2) 179 if (val <= val2)
180 return; 180 return;
181 } 181 }
182 if (sym->type == S_INT) 182 if (sym->type == S_INT)
183 sprintf(str, "%d", val2); 183 sprintf(str, "%d", val2);
184 else 184 else
185 sprintf(str, "0x%x", val2); 185 sprintf(str, "0x%x", val2);
186 sym->curr.val = strdup(str); 186 sym->curr.val = strdup(str);
187 } 187 }
188 188
189 static void sym_calc_visibility(struct symbol *sym) 189 static void sym_calc_visibility(struct symbol *sym)
190 { 190 {
191 struct property *prop; 191 struct property *prop;
192 tristate tri; 192 tristate tri;
193 193
194 /* any prompt visible? */ 194 /* any prompt visible? */
195 tri = no; 195 tri = no;
196 for_all_prompts(sym, prop) { 196 for_all_prompts(sym, prop) {
197 prop->visible.tri = expr_calc_value(prop->visible.expr); 197 prop->visible.tri = expr_calc_value(prop->visible.expr);
198 tri = EXPR_OR(tri, prop->visible.tri); 198 tri = EXPR_OR(tri, prop->visible.tri);
199 } 199 }
200 if (tri == mod && (sym->type != S_TRISTATE || modules_val == no)) 200 if (tri == mod && (sym->type != S_TRISTATE || modules_val == no))
201 tri = yes; 201 tri = yes;
202 if (sym->visible != tri) { 202 if (sym->visible != tri) {
203 sym->visible = tri; 203 sym->visible = tri;
204 sym_set_changed(sym); 204 sym_set_changed(sym);
205 } 205 }
206 if (sym_is_choice_value(sym)) 206 if (sym_is_choice_value(sym))
207 return; 207 return;
208 /* defaulting to "yes" if no explicit "depends on" are given */
209 tri = yes;
210 if (sym->dir_dep.expr)
211 tri = expr_calc_value(sym->dir_dep.expr);
212 if (tri == mod)
213 tri = yes;
214 if (sym->dir_dep.tri != tri) {
215 sym->dir_dep.tri = tri;
216 sym_set_changed(sym);
217 }
208 tri = no; 218 tri = no;
209 if (sym->rev_dep.expr) 219 if (sym->rev_dep.expr)
210 tri = expr_calc_value(sym->rev_dep.expr); 220 tri = expr_calc_value(sym->rev_dep.expr);
211 if (tri == mod && sym_get_type(sym) == S_BOOLEAN) 221 if (tri == mod && sym_get_type(sym) == S_BOOLEAN)
212 tri = yes; 222 tri = yes;
213 if (sym->rev_dep.tri != tri) { 223 if (sym->rev_dep.tri != tri) {
214 sym->rev_dep.tri = tri; 224 sym->rev_dep.tri = tri;
215 sym_set_changed(sym); 225 sym_set_changed(sym);
216 } 226 }
217 } 227 }
218 228
219 static struct symbol *sym_calc_choice(struct symbol *sym) 229 static struct symbol *sym_calc_choice(struct symbol *sym)
220 { 230 {
221 struct symbol *def_sym; 231 struct symbol *def_sym;
222 struct property *prop; 232 struct property *prop;
223 struct expr *e; 233 struct expr *e;
224 234
225 /* is the user choice visible? */ 235 /* is the user choice visible? */
226 def_sym = sym->def[S_DEF_USER].val; 236 def_sym = sym->def[S_DEF_USER].val;
227 if (def_sym) { 237 if (def_sym) {
228 sym_calc_visibility(def_sym); 238 sym_calc_visibility(def_sym);
229 if (def_sym->visible != no) 239 if (def_sym->visible != no)
230 return def_sym; 240 return def_sym;
231 } 241 }
232 242
233 /* any of the defaults visible? */ 243 /* any of the defaults visible? */
234 for_all_defaults(sym, prop) { 244 for_all_defaults(sym, prop) {
235 prop->visible.tri = expr_calc_value(prop->visible.expr); 245 prop->visible.tri = expr_calc_value(prop->visible.expr);
236 if (prop->visible.tri == no) 246 if (prop->visible.tri == no)
237 continue; 247 continue;
238 def_sym = prop_get_symbol(prop); 248 def_sym = prop_get_symbol(prop);
239 sym_calc_visibility(def_sym); 249 sym_calc_visibility(def_sym);
240 if (def_sym->visible != no) 250 if (def_sym->visible != no)
241 return def_sym; 251 return def_sym;
242 } 252 }
243 253
244 /* just get the first visible value */ 254 /* just get the first visible value */
245 prop = sym_get_choice_prop(sym); 255 prop = sym_get_choice_prop(sym);
246 expr_list_for_each_sym(prop->expr, e, def_sym) { 256 expr_list_for_each_sym(prop->expr, e, def_sym) {
247 sym_calc_visibility(def_sym); 257 sym_calc_visibility(def_sym);
248 if (def_sym->visible != no) 258 if (def_sym->visible != no)
249 return def_sym; 259 return def_sym;
250 } 260 }
251 261
252 /* no choice? reset tristate value */ 262 /* no choice? reset tristate value */
253 sym->curr.tri = no; 263 sym->curr.tri = no;
254 return NULL; 264 return NULL;
255 } 265 }
256 266
257 void sym_calc_value(struct symbol *sym) 267 void sym_calc_value(struct symbol *sym)
258 { 268 {
259 struct symbol_value newval, oldval; 269 struct symbol_value newval, oldval;
260 struct property *prop; 270 struct property *prop;
261 struct expr *e; 271 struct expr *e;
262 272
263 if (!sym) 273 if (!sym)
264 return; 274 return;
265 275
266 if (sym->flags & SYMBOL_VALID) 276 if (sym->flags & SYMBOL_VALID)
267 return; 277 return;
268 sym->flags |= SYMBOL_VALID; 278 sym->flags |= SYMBOL_VALID;
269 279
270 oldval = sym->curr; 280 oldval = sym->curr;
271 281
272 switch (sym->type) { 282 switch (sym->type) {
273 case S_INT: 283 case S_INT:
274 case S_HEX: 284 case S_HEX:
275 case S_STRING: 285 case S_STRING:
276 newval = symbol_empty.curr; 286 newval = symbol_empty.curr;
277 break; 287 break;
278 case S_BOOLEAN: 288 case S_BOOLEAN:
279 case S_TRISTATE: 289 case S_TRISTATE:
280 newval = symbol_no.curr; 290 newval = symbol_no.curr;
281 break; 291 break;
282 default: 292 default:
283 sym->curr.val = sym->name; 293 sym->curr.val = sym->name;
284 sym->curr.tri = no; 294 sym->curr.tri = no;
285 return; 295 return;
286 } 296 }
287 if (!sym_is_choice_value(sym)) 297 if (!sym_is_choice_value(sym))
288 sym->flags &= ~SYMBOL_WRITE; 298 sym->flags &= ~SYMBOL_WRITE;
289 299
290 sym_calc_visibility(sym); 300 sym_calc_visibility(sym);
291 301
292 /* set default if recursively called */ 302 /* set default if recursively called */
293 sym->curr = newval; 303 sym->curr = newval;
294 304
295 switch (sym_get_type(sym)) { 305 switch (sym_get_type(sym)) {
296 case S_BOOLEAN: 306 case S_BOOLEAN:
297 case S_TRISTATE: 307 case S_TRISTATE:
298 if (sym_is_choice_value(sym) && sym->visible == yes) { 308 if (sym_is_choice_value(sym) && sym->visible == yes) {
299 prop = sym_get_choice_prop(sym); 309 prop = sym_get_choice_prop(sym);
300 newval.tri = (prop_get_symbol(prop)->curr.val == sym) ? yes : no; 310 newval.tri = (prop_get_symbol(prop)->curr.val == sym) ? yes : no;
301 } else { 311 } else {
302 if (sym->visible != no) { 312 if (sym->visible != no) {
303 /* if the symbol is visible use the user value 313 /* if the symbol is visible use the user value
304 * if available, otherwise try the default value 314 * if available, otherwise try the default value
305 */ 315 */
306 sym->flags |= SYMBOL_WRITE; 316 sym->flags |= SYMBOL_WRITE;
307 if (sym_has_value(sym)) { 317 if (sym_has_value(sym)) {
308 newval.tri = EXPR_AND(sym->def[S_DEF_USER].tri, 318 newval.tri = EXPR_AND(sym->def[S_DEF_USER].tri,
309 sym->visible); 319 sym->visible);
310 goto calc_newval; 320 goto calc_newval;
311 } 321 }
312 } 322 }
313 if (sym->rev_dep.tri != no) 323 if (sym->rev_dep.tri != no)
314 sym->flags |= SYMBOL_WRITE; 324 sym->flags |= SYMBOL_WRITE;
315 if (!sym_is_choice(sym)) { 325 if (!sym_is_choice(sym)) {
316 prop = sym_get_default_prop(sym); 326 prop = sym_get_default_prop(sym);
317 if (prop) { 327 if (prop) {
318 sym->flags |= SYMBOL_WRITE; 328 sym->flags |= SYMBOL_WRITE;
319 newval.tri = EXPR_AND(expr_calc_value(prop->expr), 329 newval.tri = EXPR_AND(expr_calc_value(prop->expr),
320 prop->visible.tri); 330 prop->visible.tri);
321 } 331 }
322 } 332 }
323 calc_newval: 333 calc_newval:
334 if (sym->dir_dep.tri == no && sym->rev_dep.tri != no) {
335 fprintf(stderr, "warning: (");
336 expr_fprint(sym->rev_dep.expr, stderr);
337 fprintf(stderr, ") selects %s which has unmet direct dependencies (",
338 sym->name);
339 expr_fprint(sym->dir_dep.expr, stderr);
340 fprintf(stderr, ")\n");
341 }
324 newval.tri = EXPR_OR(newval.tri, sym->rev_dep.tri); 342 newval.tri = EXPR_OR(newval.tri, sym->rev_dep.tri);
325 } 343 }
326 if (newval.tri == mod && sym_get_type(sym) == S_BOOLEAN) 344 if (newval.tri == mod && sym_get_type(sym) == S_BOOLEAN)
327 newval.tri = yes; 345 newval.tri = yes;
328 break; 346 break;
329 case S_STRING: 347 case S_STRING:
330 case S_HEX: 348 case S_HEX:
331 case S_INT: 349 case S_INT:
332 if (sym->visible != no) { 350 if (sym->visible != no) {
333 sym->flags |= SYMBOL_WRITE; 351 sym->flags |= SYMBOL_WRITE;
334 if (sym_has_value(sym)) { 352 if (sym_has_value(sym)) {
335 newval.val = sym->def[S_DEF_USER].val; 353 newval.val = sym->def[S_DEF_USER].val;
336 break; 354 break;
337 } 355 }
338 } 356 }
339 prop = sym_get_default_prop(sym); 357 prop = sym_get_default_prop(sym);
340 if (prop) { 358 if (prop) {
341 struct symbol *ds = prop_get_symbol(prop); 359 struct symbol *ds = prop_get_symbol(prop);
342 if (ds) { 360 if (ds) {
343 sym->flags |= SYMBOL_WRITE; 361 sym->flags |= SYMBOL_WRITE;
344 sym_calc_value(ds); 362 sym_calc_value(ds);
345 newval.val = ds->curr.val; 363 newval.val = ds->curr.val;
346 } 364 }
347 } 365 }
348 break; 366 break;
349 default: 367 default:
350 ; 368 ;
351 } 369 }
352 370
353 sym->curr = newval; 371 sym->curr = newval;
354 if (sym_is_choice(sym) && newval.tri == yes) 372 if (sym_is_choice(sym) && newval.tri == yes)
355 sym->curr.val = sym_calc_choice(sym); 373 sym->curr.val = sym_calc_choice(sym);
356 sym_validate_range(sym); 374 sym_validate_range(sym);
357 375
358 if (memcmp(&oldval, &sym->curr, sizeof(oldval))) { 376 if (memcmp(&oldval, &sym->curr, sizeof(oldval))) {
359 sym_set_changed(sym); 377 sym_set_changed(sym);
360 if (modules_sym == sym) { 378 if (modules_sym == sym) {
361 sym_set_all_changed(); 379 sym_set_all_changed();
362 modules_val = modules_sym->curr.tri; 380 modules_val = modules_sym->curr.tri;
363 } 381 }
364 } 382 }
365 383
366 if (sym_is_choice(sym)) { 384 if (sym_is_choice(sym)) {
367 struct symbol *choice_sym; 385 struct symbol *choice_sym;
368 int flags = sym->flags & (SYMBOL_CHANGED | SYMBOL_WRITE); 386 int flags = sym->flags & (SYMBOL_CHANGED | SYMBOL_WRITE);
369 387
370 prop = sym_get_choice_prop(sym); 388 prop = sym_get_choice_prop(sym);
371 expr_list_for_each_sym(prop->expr, e, choice_sym) { 389 expr_list_for_each_sym(prop->expr, e, choice_sym) {
372 choice_sym->flags |= flags; 390 choice_sym->flags |= flags;
373 if (flags & SYMBOL_CHANGED) 391 if (flags & SYMBOL_CHANGED)
374 sym_set_changed(choice_sym); 392 sym_set_changed(choice_sym);
375 } 393 }
376 } 394 }
377 395
378 if (sym->flags & SYMBOL_AUTO) 396 if (sym->flags & SYMBOL_AUTO)
379 sym->flags &= ~SYMBOL_WRITE; 397 sym->flags &= ~SYMBOL_WRITE;
380 } 398 }
381 399
382 void sym_clear_all_valid(void) 400 void sym_clear_all_valid(void)
383 { 401 {
384 struct symbol *sym; 402 struct symbol *sym;
385 int i; 403 int i;
386 404
387 for_all_symbols(i, sym) 405 for_all_symbols(i, sym)
388 sym->flags &= ~SYMBOL_VALID; 406 sym->flags &= ~SYMBOL_VALID;
389 sym_add_change_count(1); 407 sym_add_change_count(1);
390 if (modules_sym) 408 if (modules_sym)
391 sym_calc_value(modules_sym); 409 sym_calc_value(modules_sym);
392 } 410 }
393 411
394 void sym_set_changed(struct symbol *sym) 412 void sym_set_changed(struct symbol *sym)
395 { 413 {
396 struct property *prop; 414 struct property *prop;
397 415
398 sym->flags |= SYMBOL_CHANGED; 416 sym->flags |= SYMBOL_CHANGED;
399 for (prop = sym->prop; prop; prop = prop->next) { 417 for (prop = sym->prop; prop; prop = prop->next) {
400 if (prop->menu) 418 if (prop->menu)
401 prop->menu->flags |= MENU_CHANGED; 419 prop->menu->flags |= MENU_CHANGED;
402 } 420 }
403 } 421 }
404 422
405 void sym_set_all_changed(void) 423 void sym_set_all_changed(void)
406 { 424 {
407 struct symbol *sym; 425 struct symbol *sym;
408 int i; 426 int i;
409 427
410 for_all_symbols(i, sym) 428 for_all_symbols(i, sym)
411 sym_set_changed(sym); 429 sym_set_changed(sym);
412 } 430 }
413 431
414 bool sym_tristate_within_range(struct symbol *sym, tristate val) 432 bool sym_tristate_within_range(struct symbol *sym, tristate val)
415 { 433 {
416 int type = sym_get_type(sym); 434 int type = sym_get_type(sym);
417 435
418 if (sym->visible == no) 436 if (sym->visible == no)
419 return false; 437 return false;
420 438
421 if (type != S_BOOLEAN && type != S_TRISTATE) 439 if (type != S_BOOLEAN && type != S_TRISTATE)
422 return false; 440 return false;
423 441
424 if (type == S_BOOLEAN && val == mod) 442 if (type == S_BOOLEAN && val == mod)
425 return false; 443 return false;
426 if (sym->visible <= sym->rev_dep.tri) 444 if (sym->visible <= sym->rev_dep.tri)
427 return false; 445 return false;
428 if (sym_is_choice_value(sym) && sym->visible == yes) 446 if (sym_is_choice_value(sym) && sym->visible == yes)
429 return val == yes; 447 return val == yes;
430 return val >= sym->rev_dep.tri && val <= sym->visible; 448 return val >= sym->rev_dep.tri && val <= sym->visible;
431 } 449 }
432 450
433 bool sym_set_tristate_value(struct symbol *sym, tristate val) 451 bool sym_set_tristate_value(struct symbol *sym, tristate val)
434 { 452 {
435 tristate oldval = sym_get_tristate_value(sym); 453 tristate oldval = sym_get_tristate_value(sym);
436 454
437 if (oldval != val && !sym_tristate_within_range(sym, val)) 455 if (oldval != val && !sym_tristate_within_range(sym, val))
438 return false; 456 return false;
439 457
440 if (!(sym->flags & SYMBOL_DEF_USER)) { 458 if (!(sym->flags & SYMBOL_DEF_USER)) {
441 sym->flags |= SYMBOL_DEF_USER; 459 sym->flags |= SYMBOL_DEF_USER;
442 sym_set_changed(sym); 460 sym_set_changed(sym);
443 } 461 }
444 /* 462 /*
445 * setting a choice value also resets the new flag of the choice 463 * setting a choice value also resets the new flag of the choice
446 * symbol and all other choice values. 464 * symbol and all other choice values.
447 */ 465 */
448 if (sym_is_choice_value(sym) && val == yes) { 466 if (sym_is_choice_value(sym) && val == yes) {
449 struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym)); 467 struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
450 struct property *prop; 468 struct property *prop;
451 struct expr *e; 469 struct expr *e;
452 470
453 cs->def[S_DEF_USER].val = sym; 471 cs->def[S_DEF_USER].val = sym;
454 cs->flags |= SYMBOL_DEF_USER; 472 cs->flags |= SYMBOL_DEF_USER;
455 prop = sym_get_choice_prop(cs); 473 prop = sym_get_choice_prop(cs);
456 for (e = prop->expr; e; e = e->left.expr) { 474 for (e = prop->expr; e; e = e->left.expr) {
457 if (e->right.sym->visible != no) 475 if (e->right.sym->visible != no)
458 e->right.sym->flags |= SYMBOL_DEF_USER; 476 e->right.sym->flags |= SYMBOL_DEF_USER;
459 } 477 }
460 } 478 }
461 479
462 sym->def[S_DEF_USER].tri = val; 480 sym->def[S_DEF_USER].tri = val;
463 if (oldval != val) 481 if (oldval != val)
464 sym_clear_all_valid(); 482 sym_clear_all_valid();
465 483
466 return true; 484 return true;
467 } 485 }
468 486
469 tristate sym_toggle_tristate_value(struct symbol *sym) 487 tristate sym_toggle_tristate_value(struct symbol *sym)
470 { 488 {
471 tristate oldval, newval; 489 tristate oldval, newval;
472 490
473 oldval = newval = sym_get_tristate_value(sym); 491 oldval = newval = sym_get_tristate_value(sym);
474 do { 492 do {
475 switch (newval) { 493 switch (newval) {
476 case no: 494 case no:
477 newval = mod; 495 newval = mod;
478 break; 496 break;
479 case mod: 497 case mod:
480 newval = yes; 498 newval = yes;
481 break; 499 break;
482 case yes: 500 case yes:
483 newval = no; 501 newval = no;
484 break; 502 break;
485 } 503 }
486 if (sym_set_tristate_value(sym, newval)) 504 if (sym_set_tristate_value(sym, newval))
487 break; 505 break;
488 } while (oldval != newval); 506 } while (oldval != newval);
489 return newval; 507 return newval;
490 } 508 }
491 509
492 bool sym_string_valid(struct symbol *sym, const char *str) 510 bool sym_string_valid(struct symbol *sym, const char *str)
493 { 511 {
494 signed char ch; 512 signed char ch;
495 513
496 switch (sym->type) { 514 switch (sym->type) {
497 case S_STRING: 515 case S_STRING:
498 return true; 516 return true;
499 case S_INT: 517 case S_INT:
500 ch = *str++; 518 ch = *str++;
501 if (ch == '-') 519 if (ch == '-')
502 ch = *str++; 520 ch = *str++;
503 if (!isdigit(ch)) 521 if (!isdigit(ch))
504 return false; 522 return false;
505 if (ch == '0' && *str != 0) 523 if (ch == '0' && *str != 0)
506 return false; 524 return false;
507 while ((ch = *str++)) { 525 while ((ch = *str++)) {
508 if (!isdigit(ch)) 526 if (!isdigit(ch))
509 return false; 527 return false;
510 } 528 }
511 return true; 529 return true;
512 case S_HEX: 530 case S_HEX:
513 if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) 531 if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
514 str += 2; 532 str += 2;
515 ch = *str++; 533 ch = *str++;
516 do { 534 do {
517 if (!isxdigit(ch)) 535 if (!isxdigit(ch))
518 return false; 536 return false;
519 } while ((ch = *str++)); 537 } while ((ch = *str++));
520 return true; 538 return true;
521 case S_BOOLEAN: 539 case S_BOOLEAN:
522 case S_TRISTATE: 540 case S_TRISTATE:
523 switch (str[0]) { 541 switch (str[0]) {
524 case 'y': case 'Y': 542 case 'y': case 'Y':
525 case 'm': case 'M': 543 case 'm': case 'M':
526 case 'n': case 'N': 544 case 'n': case 'N':
527 return true; 545 return true;
528 } 546 }
529 return false; 547 return false;
530 default: 548 default:
531 return false; 549 return false;
532 } 550 }
533 } 551 }
534 552
535 bool sym_string_within_range(struct symbol *sym, const char *str) 553 bool sym_string_within_range(struct symbol *sym, const char *str)
536 { 554 {
537 struct property *prop; 555 struct property *prop;
538 int val; 556 int val;
539 557
540 switch (sym->type) { 558 switch (sym->type) {
541 case S_STRING: 559 case S_STRING:
542 return sym_string_valid(sym, str); 560 return sym_string_valid(sym, str);
543 case S_INT: 561 case S_INT:
544 if (!sym_string_valid(sym, str)) 562 if (!sym_string_valid(sym, str))
545 return false; 563 return false;
546 prop = sym_get_range_prop(sym); 564 prop = sym_get_range_prop(sym);
547 if (!prop) 565 if (!prop)
548 return true; 566 return true;
549 val = strtol(str, NULL, 10); 567 val = strtol(str, NULL, 10);
550 return val >= sym_get_range_val(prop->expr->left.sym, 10) && 568 return val >= sym_get_range_val(prop->expr->left.sym, 10) &&
551 val <= sym_get_range_val(prop->expr->right.sym, 10); 569 val <= sym_get_range_val(prop->expr->right.sym, 10);
552 case S_HEX: 570 case S_HEX:
553 if (!sym_string_valid(sym, str)) 571 if (!sym_string_valid(sym, str))
554 return false; 572 return false;
555 prop = sym_get_range_prop(sym); 573 prop = sym_get_range_prop(sym);
556 if (!prop) 574 if (!prop)
557 return true; 575 return true;
558 val = strtol(str, NULL, 16); 576 val = strtol(str, NULL, 16);
559 return val >= sym_get_range_val(prop->expr->left.sym, 16) && 577 return val >= sym_get_range_val(prop->expr->left.sym, 16) &&
560 val <= sym_get_range_val(prop->expr->right.sym, 16); 578 val <= sym_get_range_val(prop->expr->right.sym, 16);
561 case S_BOOLEAN: 579 case S_BOOLEAN:
562 case S_TRISTATE: 580 case S_TRISTATE:
563 switch (str[0]) { 581 switch (str[0]) {
564 case 'y': case 'Y': 582 case 'y': case 'Y':
565 return sym_tristate_within_range(sym, yes); 583 return sym_tristate_within_range(sym, yes);
566 case 'm': case 'M': 584 case 'm': case 'M':
567 return sym_tristate_within_range(sym, mod); 585 return sym_tristate_within_range(sym, mod);
568 case 'n': case 'N': 586 case 'n': case 'N':
569 return sym_tristate_within_range(sym, no); 587 return sym_tristate_within_range(sym, no);
570 } 588 }
571 return false; 589 return false;
572 default: 590 default:
573 return false; 591 return false;
574 } 592 }
575 } 593 }
576 594
577 bool sym_set_string_value(struct symbol *sym, const char *newval) 595 bool sym_set_string_value(struct symbol *sym, const char *newval)
578 { 596 {
579 const char *oldval; 597 const char *oldval;
580 char *val; 598 char *val;
581 int size; 599 int size;
582 600
583 switch (sym->type) { 601 switch (sym->type) {
584 case S_BOOLEAN: 602 case S_BOOLEAN:
585 case S_TRISTATE: 603 case S_TRISTATE:
586 switch (newval[0]) { 604 switch (newval[0]) {
587 case 'y': case 'Y': 605 case 'y': case 'Y':
588 return sym_set_tristate_value(sym, yes); 606 return sym_set_tristate_value(sym, yes);
589 case 'm': case 'M': 607 case 'm': case 'M':
590 return sym_set_tristate_value(sym, mod); 608 return sym_set_tristate_value(sym, mod);
591 case 'n': case 'N': 609 case 'n': case 'N':
592 return sym_set_tristate_value(sym, no); 610 return sym_set_tristate_value(sym, no);
593 } 611 }
594 return false; 612 return false;
595 default: 613 default:
596 ; 614 ;
597 } 615 }
598 616
599 if (!sym_string_within_range(sym, newval)) 617 if (!sym_string_within_range(sym, newval))
600 return false; 618 return false;
601 619
602 if (!(sym->flags & SYMBOL_DEF_USER)) { 620 if (!(sym->flags & SYMBOL_DEF_USER)) {
603 sym->flags |= SYMBOL_DEF_USER; 621 sym->flags |= SYMBOL_DEF_USER;
604 sym_set_changed(sym); 622 sym_set_changed(sym);
605 } 623 }
606 624
607 oldval = sym->def[S_DEF_USER].val; 625 oldval = sym->def[S_DEF_USER].val;
608 size = strlen(newval) + 1; 626 size = strlen(newval) + 1;
609 if (sym->type == S_HEX && (newval[0] != '0' || (newval[1] != 'x' && newval[1] != 'X'))) { 627 if (sym->type == S_HEX && (newval[0] != '0' || (newval[1] != 'x' && newval[1] != 'X'))) {
610 size += 2; 628 size += 2;
611 sym->def[S_DEF_USER].val = val = malloc(size); 629 sym->def[S_DEF_USER].val = val = malloc(size);
612 *val++ = '0'; 630 *val++ = '0';
613 *val++ = 'x'; 631 *val++ = 'x';
614 } else if (!oldval || strcmp(oldval, newval)) 632 } else if (!oldval || strcmp(oldval, newval))
615 sym->def[S_DEF_USER].val = val = malloc(size); 633 sym->def[S_DEF_USER].val = val = malloc(size);
616 else 634 else
617 return true; 635 return true;
618 636
619 strcpy(val, newval); 637 strcpy(val, newval);
620 free((void *)oldval); 638 free((void *)oldval);
621 sym_clear_all_valid(); 639 sym_clear_all_valid();
622 640
623 return true; 641 return true;
624 } 642 }
625 643
626 const char *sym_get_string_value(struct symbol *sym) 644 const char *sym_get_string_value(struct symbol *sym)
627 { 645 {
628 tristate val; 646 tristate val;
629 647
630 switch (sym->type) { 648 switch (sym->type) {
631 case S_BOOLEAN: 649 case S_BOOLEAN:
632 case S_TRISTATE: 650 case S_TRISTATE:
633 val = sym_get_tristate_value(sym); 651 val = sym_get_tristate_value(sym);
634 switch (val) { 652 switch (val) {
635 case no: 653 case no:
636 return "n"; 654 return "n";
637 case mod: 655 case mod:
638 return "m"; 656 return "m";
639 case yes: 657 case yes:
640 return "y"; 658 return "y";
641 } 659 }
642 break; 660 break;
643 default: 661 default:
644 ; 662 ;
645 } 663 }
646 return (const char *)sym->curr.val; 664 return (const char *)sym->curr.val;
647 } 665 }
648 666
649 bool sym_is_changable(struct symbol *sym) 667 bool sym_is_changable(struct symbol *sym)
650 { 668 {
651 return sym->visible > sym->rev_dep.tri; 669 return sym->visible > sym->rev_dep.tri;
652 } 670 }
653 671
654 static unsigned strhash(const char *s) 672 static unsigned strhash(const char *s)
655 { 673 {
656 /* fnv32 hash */ 674 /* fnv32 hash */
657 unsigned hash = 2166136261U; 675 unsigned hash = 2166136261U;
658 for (; *s; s++) 676 for (; *s; s++)
659 hash = (hash ^ *s) * 0x01000193; 677 hash = (hash ^ *s) * 0x01000193;
660 return hash; 678 return hash;
661 } 679 }
662 680
663 struct symbol *sym_lookup(const char *name, int flags) 681 struct symbol *sym_lookup(const char *name, int flags)
664 { 682 {
665 struct symbol *symbol; 683 struct symbol *symbol;
666 char *new_name; 684 char *new_name;
667 int hash; 685 int hash;
668 686
669 if (name) { 687 if (name) {
670 if (name[0] && !name[1]) { 688 if (name[0] && !name[1]) {
671 switch (name[0]) { 689 switch (name[0]) {
672 case 'y': return &symbol_yes; 690 case 'y': return &symbol_yes;
673 case 'm': return &symbol_mod; 691 case 'm': return &symbol_mod;
674 case 'n': return &symbol_no; 692 case 'n': return &symbol_no;
675 } 693 }
676 } 694 }
677 hash = strhash(name) % SYMBOL_HASHSIZE; 695 hash = strhash(name) % SYMBOL_HASHSIZE;
678 696
679 for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) { 697 for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
680 if (symbol->name && 698 if (symbol->name &&
681 !strcmp(symbol->name, name) && 699 !strcmp(symbol->name, name) &&
682 (flags ? symbol->flags & flags 700 (flags ? symbol->flags & flags
683 : !(symbol->flags & (SYMBOL_CONST|SYMBOL_CHOICE)))) 701 : !(symbol->flags & (SYMBOL_CONST|SYMBOL_CHOICE))))
684 return symbol; 702 return symbol;
685 } 703 }
686 new_name = strdup(name); 704 new_name = strdup(name);
687 } else { 705 } else {
688 new_name = NULL; 706 new_name = NULL;
689 hash = 0; 707 hash = 0;
690 } 708 }
691 709
692 symbol = malloc(sizeof(*symbol)); 710 symbol = malloc(sizeof(*symbol));
693 memset(symbol, 0, sizeof(*symbol)); 711 memset(symbol, 0, sizeof(*symbol));
694 symbol->name = new_name; 712 symbol->name = new_name;
695 symbol->type = S_UNKNOWN; 713 symbol->type = S_UNKNOWN;
696 symbol->flags |= flags; 714 symbol->flags |= flags;
697 715
698 symbol->next = symbol_hash[hash]; 716 symbol->next = symbol_hash[hash];
699 symbol_hash[hash] = symbol; 717 symbol_hash[hash] = symbol;
700 718
701 return symbol; 719 return symbol;
702 } 720 }
703 721
704 struct symbol *sym_find(const char *name) 722 struct symbol *sym_find(const char *name)
705 { 723 {
706 struct symbol *symbol = NULL; 724 struct symbol *symbol = NULL;
707 int hash = 0; 725 int hash = 0;
708 726
709 if (!name) 727 if (!name)
710 return NULL; 728 return NULL;
711 729
712 if (name[0] && !name[1]) { 730 if (name[0] && !name[1]) {
713 switch (name[0]) { 731 switch (name[0]) {
714 case 'y': return &symbol_yes; 732 case 'y': return &symbol_yes;
715 case 'm': return &symbol_mod; 733 case 'm': return &symbol_mod;
716 case 'n': return &symbol_no; 734 case 'n': return &symbol_no;
717 } 735 }
718 } 736 }
719 hash = strhash(name) % SYMBOL_HASHSIZE; 737 hash = strhash(name) % SYMBOL_HASHSIZE;
720 738
721 for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) { 739 for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
722 if (symbol->name && 740 if (symbol->name &&
723 !strcmp(symbol->name, name) && 741 !strcmp(symbol->name, name) &&
724 !(symbol->flags & SYMBOL_CONST)) 742 !(symbol->flags & SYMBOL_CONST))
725 break; 743 break;
726 } 744 }
727 745
728 return symbol; 746 return symbol;
729 } 747 }
730 748
731 struct symbol **sym_re_search(const char *pattern) 749 struct symbol **sym_re_search(const char *pattern)
732 { 750 {
733 struct symbol *sym, **sym_arr = NULL; 751 struct symbol *sym, **sym_arr = NULL;
734 int i, cnt, size; 752 int i, cnt, size;
735 regex_t re; 753 regex_t re;
736 754
737 cnt = size = 0; 755 cnt = size = 0;
738 /* Skip if empty */ 756 /* Skip if empty */
739 if (strlen(pattern) == 0) 757 if (strlen(pattern) == 0)
740 return NULL; 758 return NULL;
741 if (regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB|REG_ICASE)) 759 if (regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB|REG_ICASE))
742 return NULL; 760 return NULL;
743 761
744 for_all_symbols(i, sym) { 762 for_all_symbols(i, sym) {
745 if (sym->flags & SYMBOL_CONST || !sym->name) 763 if (sym->flags & SYMBOL_CONST || !sym->name)
746 continue; 764 continue;
747 if (regexec(&re, sym->name, 0, NULL, 0)) 765 if (regexec(&re, sym->name, 0, NULL, 0))
748 continue; 766 continue;
749 if (cnt + 1 >= size) { 767 if (cnt + 1 >= size) {
750 void *tmp = sym_arr; 768 void *tmp = sym_arr;
751 size += 16; 769 size += 16;
752 sym_arr = realloc(sym_arr, size * sizeof(struct symbol *)); 770 sym_arr = realloc(sym_arr, size * sizeof(struct symbol *));
753 if (!sym_arr) { 771 if (!sym_arr) {
754 free(tmp); 772 free(tmp);
755 return NULL; 773 return NULL;
756 } 774 }
757 } 775 }
758 sym_calc_value(sym); 776 sym_calc_value(sym);
759 sym_arr[cnt++] = sym; 777 sym_arr[cnt++] = sym;
760 } 778 }
761 if (sym_arr) 779 if (sym_arr)
762 sym_arr[cnt] = NULL; 780 sym_arr[cnt] = NULL;
763 regfree(&re); 781 regfree(&re);
764 782
765 return sym_arr; 783 return sym_arr;
766 } 784 }
767 785
768 786
769 static struct symbol *sym_check_expr_deps(struct expr *e) 787 static struct symbol *sym_check_expr_deps(struct expr *e)
770 { 788 {
771 struct symbol *sym; 789 struct symbol *sym;
772 790
773 if (!e) 791 if (!e)
774 return NULL; 792 return NULL;
775 switch (e->type) { 793 switch (e->type) {
776 case E_OR: 794 case E_OR:
777 case E_AND: 795 case E_AND:
778 sym = sym_check_expr_deps(e->left.expr); 796 sym = sym_check_expr_deps(e->left.expr);
779 if (sym) 797 if (sym)
780 return sym; 798 return sym;
781 return sym_check_expr_deps(e->right.expr); 799 return sym_check_expr_deps(e->right.expr);
782 case E_NOT: 800 case E_NOT:
783 return sym_check_expr_deps(e->left.expr); 801 return sym_check_expr_deps(e->left.expr);
784 case E_EQUAL: 802 case E_EQUAL:
785 case E_UNEQUAL: 803 case E_UNEQUAL:
786 sym = sym_check_deps(e->left.sym); 804 sym = sym_check_deps(e->left.sym);
787 if (sym) 805 if (sym)
788 return sym; 806 return sym;
789 return sym_check_deps(e->right.sym); 807 return sym_check_deps(e->right.sym);
790 case E_SYMBOL: 808 case E_SYMBOL:
791 return sym_check_deps(e->left.sym); 809 return sym_check_deps(e->left.sym);
792 default: 810 default:
793 break; 811 break;
794 } 812 }
795 printf("Oops! How to check %d?\n", e->type); 813 printf("Oops! How to check %d?\n", e->type);
796 return NULL; 814 return NULL;
797 } 815 }
798 816
799 /* return NULL when dependencies are OK */ 817 /* return NULL when dependencies are OK */
800 static struct symbol *sym_check_sym_deps(struct symbol *sym) 818 static struct symbol *sym_check_sym_deps(struct symbol *sym)
801 { 819 {
802 struct symbol *sym2; 820 struct symbol *sym2;
803 struct property *prop; 821 struct property *prop;
804 822
805 sym2 = sym_check_expr_deps(sym->rev_dep.expr); 823 sym2 = sym_check_expr_deps(sym->rev_dep.expr);
806 if (sym2) 824 if (sym2)
807 return sym2; 825 return sym2;
808 826
809 for (prop = sym->prop; prop; prop = prop->next) { 827 for (prop = sym->prop; prop; prop = prop->next) {
810 if (prop->type == P_CHOICE || prop->type == P_SELECT) 828 if (prop->type == P_CHOICE || prop->type == P_SELECT)
811 continue; 829 continue;
812 sym2 = sym_check_expr_deps(prop->visible.expr); 830 sym2 = sym_check_expr_deps(prop->visible.expr);
813 if (sym2) 831 if (sym2)
814 break; 832 break;
815 if (prop->type != P_DEFAULT || sym_is_choice(sym)) 833 if (prop->type != P_DEFAULT || sym_is_choice(sym))
816 continue; 834 continue;
817 sym2 = sym_check_expr_deps(prop->expr); 835 sym2 = sym_check_expr_deps(prop->expr);
818 if (sym2) 836 if (sym2)
819 break; 837 break;
820 } 838 }
821 839
822 return sym2; 840 return sym2;
823 } 841 }
824 842
825 static struct symbol *sym_check_choice_deps(struct symbol *choice) 843 static struct symbol *sym_check_choice_deps(struct symbol *choice)
826 { 844 {
827 struct symbol *sym, *sym2; 845 struct symbol *sym, *sym2;
828 struct property *prop; 846 struct property *prop;
829 struct expr *e; 847 struct expr *e;
830 848
831 prop = sym_get_choice_prop(choice); 849 prop = sym_get_choice_prop(choice);
832 expr_list_for_each_sym(prop->expr, e, sym) 850 expr_list_for_each_sym(prop->expr, e, sym)
833 sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED); 851 sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);
834 852
835 choice->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED); 853 choice->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);
836 sym2 = sym_check_sym_deps(choice); 854 sym2 = sym_check_sym_deps(choice);
837 choice->flags &= ~SYMBOL_CHECK; 855 choice->flags &= ~SYMBOL_CHECK;
838 if (sym2) 856 if (sym2)
839 goto out; 857 goto out;
840 858
841 expr_list_for_each_sym(prop->expr, e, sym) { 859 expr_list_for_each_sym(prop->expr, e, sym) {
842 sym2 = sym_check_sym_deps(sym); 860 sym2 = sym_check_sym_deps(sym);
843 if (sym2) { 861 if (sym2) {
844 fprintf(stderr, " -> %s", sym->name); 862 fprintf(stderr, " -> %s", sym->name);
845 break; 863 break;
846 } 864 }
847 } 865 }
848 out: 866 out:
849 expr_list_for_each_sym(prop->expr, e, sym) 867 expr_list_for_each_sym(prop->expr, e, sym)
850 sym->flags &= ~SYMBOL_CHECK; 868 sym->flags &= ~SYMBOL_CHECK;
851 869
852 if (sym2 && sym_is_choice_value(sym2) && 870 if (sym2 && sym_is_choice_value(sym2) &&
853 prop_get_symbol(sym_get_choice_prop(sym2)) == choice) 871 prop_get_symbol(sym_get_choice_prop(sym2)) == choice)
854 sym2 = choice; 872 sym2 = choice;
855 873
856 return sym2; 874 return sym2;
857 } 875 }
858 876
859 struct symbol *sym_check_deps(struct symbol *sym) 877 struct symbol *sym_check_deps(struct symbol *sym)
860 { 878 {
861 struct symbol *sym2; 879 struct symbol *sym2;
862 struct property *prop; 880 struct property *prop;
863 881
864 if (sym->flags & SYMBOL_CHECK) { 882 if (sym->flags & SYMBOL_CHECK) {
865 fprintf(stderr, "%s:%d:error: found recursive dependency: %s", 883 fprintf(stderr, "%s:%d:error: found recursive dependency: %s",
866 sym->prop->file->name, sym->prop->lineno, 884 sym->prop->file->name, sym->prop->lineno,
867 sym->name ? sym->name : "<choice>"); 885 sym->name ? sym->name : "<choice>");
868 return sym; 886 return sym;
869 } 887 }
870 if (sym->flags & SYMBOL_CHECKED) 888 if (sym->flags & SYMBOL_CHECKED)
871 return NULL; 889 return NULL;
872 890
873 if (sym_is_choice_value(sym)) { 891 if (sym_is_choice_value(sym)) {
874 /* for choice groups start the check with main choice symbol */ 892 /* for choice groups start the check with main choice symbol */
875 prop = sym_get_choice_prop(sym); 893 prop = sym_get_choice_prop(sym);
876 sym2 = sym_check_deps(prop_get_symbol(prop)); 894 sym2 = sym_check_deps(prop_get_symbol(prop));
877 } else if (sym_is_choice(sym)) { 895 } else if (sym_is_choice(sym)) {
878 sym2 = sym_check_choice_deps(sym); 896 sym2 = sym_check_choice_deps(sym);
879 } else { 897 } else {
880 sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED); 898 sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);
881 sym2 = sym_check_sym_deps(sym); 899 sym2 = sym_check_sym_deps(sym);
882 sym->flags &= ~SYMBOL_CHECK; 900 sym->flags &= ~SYMBOL_CHECK;
883 } 901 }
884 902
885 if (sym2) { 903 if (sym2) {
886 fprintf(stderr, " -> %s", sym->name ? sym->name : "<choice>"); 904 fprintf(stderr, " -> %s", sym->name ? sym->name : "<choice>");
887 if (sym2 == sym) { 905 if (sym2 == sym) {
888 fprintf(stderr, "\n"); 906 fprintf(stderr, "\n");
889 zconfnerrs++; 907 zconfnerrs++;
890 sym2 = NULL; 908 sym2 = NULL;
891 } 909 }
892 } 910 }
893 911
894 return sym2; 912 return sym2;
895 } 913 }
896 914
897 struct property *prop_alloc(enum prop_type type, struct symbol *sym) 915 struct property *prop_alloc(enum prop_type type, struct symbol *sym)
898 { 916 {
899 struct property *prop; 917 struct property *prop;
900 struct property **propp; 918 struct property **propp;
901 919
902 prop = malloc(sizeof(*prop)); 920 prop = malloc(sizeof(*prop));
903 memset(prop, 0, sizeof(*prop)); 921 memset(prop, 0, sizeof(*prop));
904 prop->type = type; 922 prop->type = type;
905 prop->sym = sym; 923 prop->sym = sym;
906 prop->file = current_file; 924 prop->file = current_file;
907 prop->lineno = zconf_lineno(); 925 prop->lineno = zconf_lineno();
908 926
909 /* append property to the prop list of symbol */ 927 /* append property to the prop list of symbol */
910 if (sym) { 928 if (sym) {
911 for (propp = &sym->prop; *propp; propp = &(*propp)->next) 929 for (propp = &sym->prop; *propp; propp = &(*propp)->next)
912 ; 930 ;
913 *propp = prop; 931 *propp = prop;
914 } 932 }
915 933
916 return prop; 934 return prop;
917 } 935 }
918 936
919 struct symbol *prop_get_symbol(struct property *prop) 937 struct symbol *prop_get_symbol(struct property *prop)
920 { 938 {
921 if (prop->expr && (prop->expr->type == E_SYMBOL || 939 if (prop->expr && (prop->expr->type == E_SYMBOL ||
922 prop->expr->type == E_LIST)) 940 prop->expr->type == E_LIST))
923 return prop->expr->left.sym; 941 return prop->expr->left.sym;
924 return NULL; 942 return NULL;
925 } 943 }
926 944
927 const char *prop_get_type_name(enum prop_type type) 945 const char *prop_get_type_name(enum prop_type type)
928 { 946 {
929 switch (type) { 947 switch (type) {
930 case P_PROMPT: 948 case P_PROMPT:
931 return "prompt"; 949 return "prompt";
932 case P_ENV: 950 case P_ENV:
933 return "env"; 951 return "env";
934 case P_COMMENT: 952 case P_COMMENT:
935 return "comment"; 953 return "comment";
936 case P_MENU: 954 case P_MENU:
937 return "menu"; 955 return "menu";
938 case P_DEFAULT: 956 case P_DEFAULT:
939 return "default"; 957 return "default";
940 case P_CHOICE: 958 case P_CHOICE:
941 return "choice"; 959 return "choice";
942 case P_SELECT: 960 case P_SELECT:
943 return "select"; 961 return "select";
944 case P_RANGE: 962 case P_RANGE:
945 return "range"; 963 return "range";
946 case P_UNKNOWN: 964 case P_UNKNOWN:
947 break; 965 break;
948 } 966 }
949 return "unknown"; 967 return "unknown";
950 } 968 }
951 969
952 static void prop_add_env(const char *env) 970 static void prop_add_env(const char *env)
953 { 971 {
954 struct symbol *sym, *sym2; 972 struct symbol *sym, *sym2;
955 struct property *prop; 973 struct property *prop;
956 char *p; 974 char *p;
957 975
958 sym = current_entry->sym; 976 sym = current_entry->sym;
959 sym->flags |= SYMBOL_AUTO; 977 sym->flags |= SYMBOL_AUTO;
960 for_all_properties(sym, prop, P_ENV) { 978 for_all_properties(sym, prop, P_ENV) {
961 sym2 = prop_get_symbol(prop); 979 sym2 = prop_get_symbol(prop);
962 if (strcmp(sym2->name, env)) 980 if (strcmp(sym2->name, env))
963 menu_warn(current_entry, "redefining environment symbol from %s", 981 menu_warn(current_entry, "redefining environment symbol from %s",
964 sym2->name); 982 sym2->name);
965 return; 983 return;
966 } 984 }
967 985
968 prop = prop_alloc(P_ENV, sym); 986 prop = prop_alloc(P_ENV, sym);
969 prop->expr = expr_alloc_symbol(sym_lookup(env, SYMBOL_CONST)); 987 prop->expr = expr_alloc_symbol(sym_lookup(env, SYMBOL_CONST));
970 988
971 sym_env_list = expr_alloc_one(E_LIST, sym_env_list); 989 sym_env_list = expr_alloc_one(E_LIST, sym_env_list);
972 sym_env_list->right.sym = sym; 990 sym_env_list->right.sym = sym;
973 991
974 p = getenv(env); 992 p = getenv(env);
975 if (p) 993 if (p)
976 sym_add_default(sym, p); 994 sym_add_default(sym, p);
977 else 995 else
978 menu_warn(current_entry, "environment variable %s undefined", env); 996 menu_warn(current_entry, "environment variable %s undefined", env);
979 } 997 }
980 998