-rw-r--r-- | scripts/kconfig/symbol.c | 447 |
1 files changed, 298 insertions, 149 deletions
diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c index 845d8a3..11318d9 100644 --- a/scripts/kconfig/symbol.c +++ b/scripts/kconfig/symbol.c | |||
@@ -31,24 +31,15 @@ struct symbol symbol_yes = { | |||
31 | 31 | ||
32 | int sym_change_count; | 32 | int sym_change_count; |
33 | struct symbol *modules_sym; | 33 | struct symbol *modules_sym; |
34 | 34 | ||
35 | void sym_add_default(struct symbol *sym, const char *def) | 35 | void sym_add_default(struct symbol *sym, const char *def) |
36 | { | 36 | { |
37 | struct property *prop = create_prop(P_DEFAULT); | 37 | struct property *prop = prop_alloc(P_DEFAULT, sym); |
38 | struct property **propp; | ||
39 | |||
40 | prop->sym = sym; | ||
41 | prop->def = sym_lookup(def, 1); | ||
42 | 38 | ||
43 | /* append property to the prop list of symbol */ | 39 | prop->expr = expr_alloc_symbol(sym_lookup(def, 1)); |
44 | if (prop->sym) { | ||
45 | for (propp = &prop->sym->prop; *propp; propp = &(*propp)->next) | ||
46 | ; | ||
47 | *propp = prop; | ||
48 | } | ||
49 | } | 40 | } |
50 | 41 | ||
51 | void sym_init(void) | 42 | void sym_init(void) |
52 | { | 43 | { |
53 | struct symbol *sym; | 44 | struct symbol *sym; |
54 | struct utsname uts; | 45 | struct utsname uts; |
@@ -78,28 +69,29 @@ void sym_init(void) | |||
78 | sym = sym_lookup("UNAME_RELEASE", 0); | 69 | sym = sym_lookup("UNAME_RELEASE", 0); |
79 | sym->type = S_STRING; | 70 | sym->type = S_STRING; |
80 | sym->flags |= SYMBOL_AUTO; | 71 | sym->flags |= SYMBOL_AUTO; |
81 | sym_add_default(sym, uts.release); | 72 | sym_add_default(sym, uts.release); |
82 | } | 73 | } |
83 | 74 | ||
84 | int sym_get_type(struct symbol *sym) | 75 | enum symbol_type sym_get_type(struct symbol *sym) |
85 | { | 76 | { |
86 | int type = sym->type; | 77 | enum symbol_type type = sym->type; |
78 | |||
87 | if (type == S_TRISTATE) { | 79 | if (type == S_TRISTATE) { |
88 | if (sym_is_choice_value(sym) && sym->visible == yes) | 80 | if (sym_is_choice_value(sym) && sym->visible == yes) |
89 | type = S_BOOLEAN; | 81 | type = S_BOOLEAN; |
90 | else { | 82 | else { |
91 | sym_calc_value(modules_sym); | 83 | sym_calc_value(modules_sym); |
92 | if (S_TRI(modules_sym->curr) == no) | 84 | if (modules_sym->curr.tri == no) |
93 | type = S_BOOLEAN; | 85 | type = S_BOOLEAN; |
94 | } | 86 | } |
95 | } | 87 | } |
96 | return type; | 88 | return type; |
97 | } | 89 | } |
98 | 90 | ||
99 | const char *sym_type_name(int type) | 91 | const char *sym_type_name(enum symbol_type type) |
100 | { | 92 | { |
101 | switch (type) { | 93 | switch (type) { |
102 | case S_BOOLEAN: | 94 | case S_BOOLEAN: |
103 | return "boolean"; | 95 | return "boolean"; |
104 | case S_TRISTATE: | 96 | case S_TRISTATE: |
105 | return "tristate"; | 97 | return "tristate"; |
@@ -108,12 +100,14 @@ const char *sym_type_name(int type) | |||
108 | case S_HEX: | 100 | case S_HEX: |
109 | return "hex"; | 101 | return "hex"; |
110 | case S_STRING: | 102 | case S_STRING: |
111 | return "string"; | 103 | return "string"; |
112 | case S_UNKNOWN: | 104 | case S_UNKNOWN: |
113 | return "unknown"; | 105 | return "unknown"; |
106 | case S_OTHER: | ||
107 | break; | ||
114 | } | 108 | } |
115 | return "???"; | 109 | return "???"; |
116 | } | 110 | } |
117 | 111 | ||
118 | struct property *sym_get_choice_prop(struct symbol *sym) | 112 | struct property *sym_get_choice_prop(struct symbol *sym) |
119 | { | 113 | { |
@@ -124,47 +118,110 @@ struct property *sym_get_choice_prop(struct symbol *sym) | |||
124 | return NULL; | 118 | return NULL; |
125 | } | 119 | } |
126 | 120 | ||
127 | struct property *sym_get_default_prop(struct symbol *sym) | 121 | struct property *sym_get_default_prop(struct symbol *sym) |
128 | { | 122 | { |
129 | struct property *prop; | 123 | struct property *prop; |
130 | tristate visible; | ||
131 | 124 | ||
132 | for_all_defaults(sym, prop) { | 125 | for_all_defaults(sym, prop) { |
133 | visible = E_CALC(prop->visible); | 126 | prop->visible.tri = expr_calc_value(prop->visible.expr); |
134 | if (visible != no) | 127 | if (prop->visible.tri != no) |
135 | return prop; | 128 | return prop; |
136 | } | 129 | } |
137 | return NULL; | 130 | return NULL; |
138 | } | 131 | } |
139 | 132 | ||
140 | void sym_calc_visibility(struct symbol *sym) | 133 | struct property *sym_get_range_prop(struct symbol *sym) |
141 | { | 134 | { |
142 | struct property *prop; | 135 | struct property *prop; |
143 | tristate visible, oldvisible; | 136 | |
137 | for_all_properties(sym, prop, P_RANGE) { | ||
138 | prop->visible.tri = expr_calc_value(prop->visible.expr); | ||
139 | if (prop->visible.tri != no) | ||
140 | return prop; | ||
141 | } | ||
142 | return NULL; | ||
143 | } | ||
144 | |||
145 | static void sym_calc_visibility(struct symbol *sym) | ||
146 | { | ||
147 | struct property *prop; | ||
148 | tristate tri; | ||
144 | 149 | ||
145 | /* any prompt visible? */ | 150 | /* any prompt visible? */ |
146 | oldvisible = sym->visible; | 151 | tri = no; |
147 | visible = no; | 152 | for_all_prompts(sym, prop) { |
148 | for_all_prompts(sym, prop) | 153 | prop->visible.tri = expr_calc_value(prop->visible.expr); |
149 | visible = E_OR(visible, E_CALC(prop->visible)); | 154 | tri = E_OR(tri, prop->visible.tri); |
150 | if (oldvisible != visible) { | 155 | } |
151 | sym->visible = visible; | 156 | if (sym->visible != tri) { |
157 | sym->visible = tri; | ||
152 | sym_set_changed(sym); | 158 | sym_set_changed(sym); |
153 | } | 159 | } |
160 | if (sym_is_choice_value(sym)) | ||
161 | return; | ||
162 | tri = no; | ||
163 | if (sym->rev_dep.expr) | ||
164 | tri = expr_calc_value(sym->rev_dep.expr); | ||
165 | if (sym->rev_dep.tri != tri) { | ||
166 | sym->rev_dep.tri = tri; | ||
167 | sym_set_changed(sym); | ||
168 | } | ||
169 | } | ||
170 | |||
171 | static struct symbol *sym_calc_choice(struct symbol *sym) | ||
172 | { | ||
173 | struct symbol *def_sym; | ||
174 | struct property *prop; | ||
175 | struct expr *e; | ||
176 | |||
177 | /* is the user choice visible? */ | ||
178 | def_sym = sym->user.val; | ||
179 | if (def_sym) { | ||
180 | sym_calc_visibility(def_sym); | ||
181 | if (def_sym->visible != no) | ||
182 | return def_sym; | ||
183 | } | ||
184 | |||
185 | /* any of the defaults visible? */ | ||
186 | for_all_defaults(sym, prop) { | ||
187 | prop->visible.tri = expr_calc_value(prop->visible.expr); | ||
188 | if (prop->visible.tri == no) | ||
189 | continue; | ||
190 | def_sym = prop_get_symbol(prop); | ||
191 | sym_calc_visibility(def_sym); | ||
192 | if (def_sym->visible != no) | ||
193 | return def_sym; | ||
194 | } | ||
195 | |||
196 | /* just get the first visible value */ | ||
197 | prop = sym_get_choice_prop(sym); | ||
198 | for (e = prop->expr; e; e = e->left.expr) { | ||
199 | def_sym = e->right.sym; | ||
200 | sym_calc_visibility(def_sym); | ||
201 | if (def_sym->visible != no) | ||
202 | return def_sym; | ||
203 | } | ||
204 | |||
205 | /* no choice? reset tristate value */ | ||
206 | sym->curr.tri = no; | ||
207 | return NULL; | ||
154 | } | 208 | } |
155 | 209 | ||
156 | void sym_calc_value(struct symbol *sym) | 210 | void sym_calc_value(struct symbol *sym) |
157 | { | 211 | { |
158 | struct symbol_value newval, oldval; | 212 | struct symbol_value newval, oldval; |
159 | struct property *prop, *def_prop; | 213 | struct property *prop; |
160 | struct symbol *def_sym; | ||
161 | struct expr *e; | 214 | struct expr *e; |
162 | 215 | ||
216 | if (!sym) | ||
217 | return; | ||
218 | |||
163 | if (sym->flags & SYMBOL_VALID) | 219 | if (sym->flags & SYMBOL_VALID) |
164 | return; | 220 | return; |
221 | sym->flags |= SYMBOL_VALID; | ||
165 | 222 | ||
166 | oldval = sym->curr; | 223 | oldval = sym->curr; |
167 | 224 | ||
168 | switch (sym->type) { | 225 | switch (sym->type) { |
169 | case S_INT: | 226 | case S_INT: |
170 | case S_HEX: | 227 | case S_HEX: |
@@ -173,120 +230,91 @@ void sym_calc_value(struct symbol *sym) | |||
173 | break; | 230 | break; |
174 | case S_BOOLEAN: | 231 | case S_BOOLEAN: |
175 | case S_TRISTATE: | 232 | case S_TRISTATE: |
176 | newval = symbol_no.curr; | 233 | newval = symbol_no.curr; |
177 | break; | 234 | break; |
178 | default: | 235 | default: |
179 | S_VAL(newval) = sym->name; | 236 | sym->curr.val = sym->name; |
180 | S_TRI(newval) = no; | 237 | sym->curr.tri = no; |
181 | if (sym->flags & SYMBOL_CONST) { | 238 | return; |
182 | goto out; | ||
183 | } | ||
184 | //newval = symbol_empty.curr; | ||
185 | // generate warning somewhere here later | ||
186 | //S_TRI(newval) = yes; | ||
187 | goto out; | ||
188 | } | 239 | } |
189 | sym->flags |= SYMBOL_VALID; | ||
190 | if (!sym_is_choice_value(sym)) | 240 | if (!sym_is_choice_value(sym)) |
191 | sym->flags &= ~SYMBOL_WRITE; | 241 | sym->flags &= ~SYMBOL_WRITE; |
192 | 242 | ||
193 | sym_calc_visibility(sym); | 243 | sym_calc_visibility(sym); |
194 | 244 | ||
195 | /* set default if recursively called */ | 245 | /* set default if recursively called */ |
196 | sym->curr = newval; | 246 | sym->curr = newval; |
197 | 247 | ||
198 | if (sym->visible != no) { | 248 | switch (sym_get_type(sym)) { |
199 | sym->flags |= SYMBOL_WRITE; | 249 | case S_BOOLEAN: |
200 | if (!sym_has_value(sym)) { | 250 | case S_TRISTATE: |
201 | if (!sym_is_choice(sym)) { | ||
202 | prop = sym_get_default_prop(sym); | ||
203 | if (prop) { | ||
204 | sym_calc_value(prop->def); | ||
205 | newval = prop->def->curr; | ||
206 | } | ||
207 | } else | ||
208 | S_TRI(newval) = S_TRI(sym->def); | ||
209 | } else | ||
210 | newval = sym->def; | ||
211 | |||
212 | S_TRI(newval) = E_AND(S_TRI(newval), sym->visible); | ||
213 | /* if the symbol is visible and not optionial, | ||
214 | * possibly ignore old user choice. */ | ||
215 | if (!sym_is_optional(sym) && S_TRI(newval) == no) | ||
216 | S_TRI(newval) = sym->visible; | ||
217 | if (sym_is_choice_value(sym) && sym->visible == yes) { | 251 | if (sym_is_choice_value(sym) && sym->visible == yes) { |
218 | prop = sym_get_choice_prop(sym); | 252 | prop = sym_get_choice_prop(sym); |
219 | S_TRI(newval) = (S_VAL(prop->def->curr) == sym) ? yes : no; | 253 | newval.tri = (prop_get_symbol(prop)->curr.val == sym) ? yes : no; |
254 | } else if (E_OR(sym->visible, sym->rev_dep.tri) != no) { | ||
255 | sym->flags |= SYMBOL_WRITE; | ||
256 | if (sym_has_value(sym)) | ||
257 | newval.tri = sym->user.tri; | ||
258 | else if (!sym_is_choice(sym)) { | ||
259 | prop = sym_get_default_prop(sym); | ||
260 | if (prop) | ||
261 | newval.tri = expr_calc_value(prop->expr); | ||
220 | } | 262 | } |
221 | } else { | 263 | newval.tri = E_OR(E_AND(newval.tri, sym->visible), sym->rev_dep.tri); |
264 | } else if (!sym_is_choice(sym)) { | ||
222 | prop = sym_get_default_prop(sym); | 265 | prop = sym_get_default_prop(sym); |
223 | if (prop) { | 266 | if (prop) { |
224 | sym->flags |= SYMBOL_WRITE; | 267 | sym->flags |= SYMBOL_WRITE; |
225 | sym_calc_value(prop->def); | 268 | newval.tri = expr_calc_value(prop->expr); |
226 | newval = prop->def->curr; | ||
227 | } | 269 | } |
228 | } | 270 | } |
229 | 271 | if (sym_get_type(sym) == S_BOOLEAN) { | |
230 | switch (sym_get_type(sym)) { | 272 | if (newval.tri == mod) |
231 | case S_TRISTATE: | 273 | newval.tri = yes; |
232 | if (S_TRI(newval) != mod) | 274 | if (sym->visible == mod) |
275 | sym->visible = yes; | ||
276 | if (sym->rev_dep.tri == mod) | ||
277 | sym->rev_dep.tri = yes; | ||
278 | } | ||
233 | break; | 279 | break; |
234 | sym_calc_value(modules_sym); | 280 | case S_STRING: |
235 | if (S_TRI(modules_sym->curr) == no) | 281 | case S_HEX: |
236 | S_TRI(newval) = yes; | 282 | case S_INT: |
283 | if (sym->visible != no) { | ||
284 | sym->flags |= SYMBOL_WRITE; | ||
285 | if (sym_has_value(sym)) { | ||
286 | newval.val = sym->user.val; | ||
237 | break; | 287 | break; |
238 | case S_BOOLEAN: | ||
239 | if (S_TRI(newval) == mod) | ||
240 | S_TRI(newval) = yes; | ||
241 | } | ||
242 | |||
243 | out: | ||
244 | sym->curr = newval; | ||
245 | |||
246 | if (sym_is_choice(sym) && S_TRI(newval) == yes) { | ||
247 | def_sym = S_VAL(sym->def); | ||
248 | if (def_sym) { | ||
249 | sym_calc_visibility(def_sym); | ||
250 | if (def_sym->visible == no) | ||
251 | def_sym = NULL; | ||
252 | } | 288 | } |
253 | if (!def_sym) { | ||
254 | for_all_defaults(sym, def_prop) { | ||
255 | if (E_CALC(def_prop->visible) == no) | ||
256 | continue; | ||
257 | sym_calc_visibility(def_prop->def); | ||
258 | if (def_prop->def->visible != no) { | ||
259 | def_sym = def_prop->def; | ||
260 | break; | ||
261 | } | 289 | } |
290 | prop = sym_get_default_prop(sym); | ||
291 | if (prop) { | ||
292 | struct symbol *ds = prop_get_symbol(prop); | ||
293 | if (ds) { | ||
294 | sym->flags |= SYMBOL_WRITE; | ||
295 | sym_calc_value(ds); | ||
296 | newval.val = ds->curr.val; | ||
262 | } | 297 | } |
263 | } | 298 | } |
264 | |||
265 | if (!def_sym) { | ||
266 | prop = sym_get_choice_prop(sym); | ||
267 | for (e = prop->dep; e; e = e->left.expr) { | ||
268 | sym_calc_visibility(e->right.sym); | ||
269 | if (e->right.sym->visible != no) { | ||
270 | def_sym = e->right.sym; | ||
271 | break; | 299 | break; |
272 | } | 300 | default: |
273 | } | 301 | ; |
274 | } | 302 | } |
275 | 303 | ||
276 | S_VAL(newval) = def_sym; | 304 | sym->curr = newval; |
277 | } | 305 | if (sym_is_choice(sym) && newval.tri == yes) |
306 | sym->curr.val = sym_calc_choice(sym); | ||
278 | 307 | ||
279 | if (memcmp(&oldval, &newval, sizeof(newval))) | 308 | if (memcmp(&oldval, &sym->curr, sizeof(oldval))) |
280 | sym_set_changed(sym); | 309 | sym_set_changed(sym); |
281 | sym->curr = newval; | ||
282 | 310 | ||
283 | if (sym_is_choice(sym)) { | 311 | if (sym_is_choice(sym)) { |
284 | int flags = sym->flags & (SYMBOL_CHANGED | SYMBOL_WRITE); | 312 | int flags = sym->flags & (SYMBOL_CHANGED | SYMBOL_WRITE); |
285 | prop = sym_get_choice_prop(sym); | 313 | prop = sym_get_choice_prop(sym); |
286 | for (e = prop->dep; e; e = e->left.expr) { | 314 | for (e = prop->expr; e; e = e->left.expr) { |
287 | e->right.sym->flags |= flags; | 315 | e->right.sym->flags |= flags; |
288 | if (flags & SYMBOL_CHANGED) | 316 | if (flags & SYMBOL_CHANGED) |
289 | sym_set_changed(e->right.sym); | 317 | sym_set_changed(e->right.sym); |
290 | } | 318 | } |
291 | } | 319 | } |
292 | } | 320 | } |
@@ -328,25 +356,19 @@ bool sym_tristate_within_range(struct symbol *sym, tristate val) | |||
328 | if (sym->visible == no) | 356 | if (sym->visible == no) |
329 | return false; | 357 | return false; |
330 | 358 | ||
331 | if (type != S_BOOLEAN && type != S_TRISTATE) | 359 | if (type != S_BOOLEAN && type != S_TRISTATE) |
332 | return false; | 360 | return false; |
333 | 361 | ||
334 | switch (val) { | 362 | if (type == S_BOOLEAN && val == mod) |
335 | case no: | ||
336 | if (sym_is_choice_value(sym) && sym->visible == yes) | ||
337 | return false; | 363 | return false; |
338 | return sym_is_optional(sym); | 364 | if (sym->visible <= sym->rev_dep.tri) |
339 | case mod: | ||
340 | if (sym_is_choice_value(sym) && sym->visible == yes) | ||
341 | return false; | ||
342 | return type == S_TRISTATE; | ||
343 | case yes: | ||
344 | return type == S_BOOLEAN || sym->visible == yes; | ||
345 | } | ||
346 | return false; | 365 | return false; |
366 | if (sym_is_choice_value(sym) && sym->visible == yes) | ||
367 | return val == yes; | ||
368 | return val >= sym->rev_dep.tri && val <= sym->visible; | ||
347 | } | 369 | } |
348 | 370 | ||
349 | bool sym_set_tristate_value(struct symbol *sym, tristate val) | 371 | bool sym_set_tristate_value(struct symbol *sym, tristate val) |
350 | { | 372 | { |
351 | tristate oldval = sym_get_tristate_value(sym); | 373 | tristate oldval = sym_get_tristate_value(sym); |
352 | 374 | ||
@@ -355,19 +377,19 @@ bool sym_set_tristate_value(struct symbol *sym, tristate val) | |||
355 | 377 | ||
356 | if (sym->flags & SYMBOL_NEW) { | 378 | if (sym->flags & SYMBOL_NEW) { |
357 | sym->flags &= ~SYMBOL_NEW; | 379 | sym->flags &= ~SYMBOL_NEW; |
358 | sym_set_changed(sym); | 380 | sym_set_changed(sym); |
359 | } | 381 | } |
360 | if (sym_is_choice_value(sym) && val == yes) { | 382 | if (sym_is_choice_value(sym) && val == yes) { |
361 | struct property *prop = sym_get_choice_prop(sym); | 383 | struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym)); |
362 | 384 | ||
363 | S_VAL(prop->def->def) = sym; | 385 | cs->user.val = sym; |
364 | prop->def->flags &= ~SYMBOL_NEW; | 386 | cs->flags &= ~SYMBOL_NEW; |
365 | } | 387 | } |
366 | 388 | ||
367 | S_TRI(sym->def) = val; | 389 | sym->user.tri = val; |
368 | if (oldval != val) { | 390 | if (oldval != val) { |
369 | sym_clear_all_valid(); | 391 | sym_clear_all_valid(); |
370 | if (sym == modules_sym) | 392 | if (sym == modules_sym) |
371 | sym_set_all_changed(); | 393 | sym_set_all_changed(); |
372 | } | 394 | } |
373 | 395 | ||
@@ -426,20 +448,57 @@ bool sym_string_valid(struct symbol *sym, const char *str) | |||
426 | return false; | 448 | return false; |
427 | } while ((ch = *str++)); | 449 | } while ((ch = *str++)); |
428 | return true; | 450 | return true; |
429 | case S_BOOLEAN: | 451 | case S_BOOLEAN: |
430 | case S_TRISTATE: | 452 | case S_TRISTATE: |
431 | switch (str[0]) { | 453 | switch (str[0]) { |
432 | case 'y': | 454 | case 'y': case 'Y': |
433 | case 'Y': | 455 | case 'm': case 'M': |
456 | case 'n': case 'N': | ||
457 | return true; | ||
458 | } | ||
459 | return false; | ||
460 | default: | ||
461 | return false; | ||
462 | } | ||
463 | } | ||
464 | |||
465 | bool sym_string_within_range(struct symbol *sym, const char *str) | ||
466 | { | ||
467 | struct property *prop; | ||
468 | int val; | ||
469 | |||
470 | switch (sym->type) { | ||
471 | case S_STRING: | ||
472 | return sym_string_valid(sym, str); | ||
473 | case S_INT: | ||
474 | if (!sym_string_valid(sym, str)) | ||
475 | return false; | ||
476 | prop = sym_get_range_prop(sym); | ||
477 | if (!prop) | ||
478 | return true; | ||
479 | val = strtol(str, NULL, 10); | ||
480 | return val >= strtol(prop->expr->left.sym->name, NULL, 10) && | ||
481 | val <= strtol(prop->expr->right.sym->name, NULL, 10); | ||
482 | case S_HEX: | ||
483 | if (!sym_string_valid(sym, str)) | ||
484 | return false; | ||
485 | prop = sym_get_range_prop(sym); | ||
486 | if (!prop) | ||
487 | return true; | ||
488 | val = strtol(str, NULL, 16); | ||
489 | return val >= strtol(prop->expr->left.sym->name, NULL, 16) && | ||
490 | val <= strtol(prop->expr->right.sym->name, NULL, 16); | ||
491 | case S_BOOLEAN: | ||
492 | case S_TRISTATE: | ||
493 | switch (str[0]) { | ||
494 | case 'y': case 'Y': | ||
434 | return sym_tristate_within_range(sym, yes); | 495 | return sym_tristate_within_range(sym, yes); |
435 | case 'm': | 496 | case 'm': case 'M': |
436 | case 'M': | ||
437 | return sym_tristate_within_range(sym, mod); | 497 | return sym_tristate_within_range(sym, mod); |
438 | case 'n': | 498 | case 'n': case 'N': |
439 | case 'N': | ||
440 | return sym_tristate_within_range(sym, no); | 499 | return sym_tristate_within_range(sym, no); |
441 | } | 500 | } |
442 | return false; | 501 | return false; |
443 | default: | 502 | default: |
444 | return false; | 503 | return false; |
445 | } | 504 | } |
@@ -452,44 +511,41 @@ bool sym_set_string_value(struct symbol *sym, const char *newval) | |||
452 | int size; | 511 | int size; |
453 | 512 | ||
454 | switch (sym->type) { | 513 | switch (sym->type) { |
455 | case S_BOOLEAN: | 514 | case S_BOOLEAN: |
456 | case S_TRISTATE: | 515 | case S_TRISTATE: |
457 | switch (newval[0]) { | 516 | switch (newval[0]) { |
458 | case 'y': | 517 | case 'y': case 'Y': |
459 | case 'Y': | ||
460 | return sym_set_tristate_value(sym, yes); | 518 | return sym_set_tristate_value(sym, yes); |
461 | case 'm': | 519 | case 'm': case 'M': |
462 | case 'M': | ||
463 | return sym_set_tristate_value(sym, mod); | 520 | return sym_set_tristate_value(sym, mod); |
464 | case 'n': | 521 | case 'n': case 'N': |
465 | case 'N': | ||
466 | return sym_set_tristate_value(sym, no); | 522 | return sym_set_tristate_value(sym, no); |
467 | } | 523 | } |
468 | return false; | 524 | return false; |
469 | default: | 525 | default: |
470 | ; | 526 | ; |
471 | } | 527 | } |
472 | 528 | ||
473 | if (!sym_string_valid(sym, newval)) | 529 | if (!sym_string_within_range(sym, newval)) |
474 | return false; | 530 | return false; |
475 | 531 | ||
476 | if (sym->flags & SYMBOL_NEW) { | 532 | if (sym->flags & SYMBOL_NEW) { |
477 | sym->flags &= ~SYMBOL_NEW; | 533 | sym->flags &= ~SYMBOL_NEW; |
478 | sym_set_changed(sym); | 534 | sym_set_changed(sym); |
479 | } | 535 | } |
480 | 536 | ||
481 | oldval = S_VAL(sym->def); | 537 | oldval = sym->user.val; |
482 | size = strlen(newval) + 1; | 538 | size = strlen(newval) + 1; |
483 | if (sym->type == S_HEX && (newval[0] != '0' || (newval[1] != 'x' && newval[1] != 'X'))) { | 539 | if (sym->type == S_HEX && (newval[0] != '0' || (newval[1] != 'x' && newval[1] != 'X'))) { |
484 | size += 2; | 540 | size += 2; |
485 | S_VAL(sym->def) = val = malloc(size); | 541 | sym->user.val = val = malloc(size); |
486 | *val++ = '0'; | 542 | *val++ = '0'; |
487 | *val++ = 'x'; | 543 | *val++ = 'x'; |
488 | } else if (!oldval || strcmp(oldval, newval)) | 544 | } else if (!oldval || strcmp(oldval, newval)) |
489 | S_VAL(sym->def) = val = malloc(size); | 545 | sym->user.val = val = malloc(size); |
490 | else | 546 | else |
491 | return true; | 547 | return true; |
492 | 548 | ||
493 | strcpy(val, newval); | 549 | strcpy(val, newval); |
494 | free((void *)oldval); | 550 | free((void *)oldval); |
495 | sym_clear_all_valid(); | 551 | sym_clear_all_valid(); |
@@ -514,26 +570,18 @@ const char *sym_get_string_value(struct symbol *sym) | |||
514 | return "y"; | 570 | return "y"; |
515 | } | 571 | } |
516 | break; | 572 | break; |
517 | default: | 573 | default: |
518 | ; | 574 | ; |
519 | } | 575 | } |
520 | return (const char *)S_VAL(sym->curr); | 576 | return (const char *)sym->curr.val; |
521 | } | 577 | } |
522 | 578 | ||
523 | bool sym_is_changable(struct symbol *sym) | 579 | bool sym_is_changable(struct symbol *sym) |
524 | { | 580 | { |
525 | if (sym->visible == no) | 581 | return sym->visible > sym->rev_dep.tri; |
526 | return false; | ||
527 | /* at least 'n' and 'y'/'m' is selectable */ | ||
528 | if (sym_is_optional(sym)) | ||
529 | return true; | ||
530 | /* no 'n', so 'y' and 'm' must be selectable */ | ||
531 | if (sym_get_type(sym) == S_TRISTATE && sym->visible == yes) | ||
532 | return true; | ||
533 | return false; | ||
534 | } | 582 | } |
535 | 583 | ||
536 | struct symbol *sym_lookup(const char *name, int isconst) | 584 | struct symbol *sym_lookup(const char *name, int isconst) |
537 | { | 585 | { |
538 | struct symbol *symbol; | 586 | struct symbol *symbol; |
539 | const char *ptr; | 587 | const char *ptr; |
@@ -605,25 +653,126 @@ struct symbol *sym_find(const char *name) | |||
605 | break; | 653 | break; |
606 | } | 654 | } |
607 | 655 | ||
608 | return symbol; | 656 | return symbol; |
609 | } | 657 | } |
610 | 658 | ||
659 | struct symbol *sym_check_deps(struct symbol *sym); | ||
660 | |||
661 | static struct symbol *sym_check_expr_deps(struct expr *e) | ||
662 | { | ||
663 | struct symbol *sym; | ||
664 | |||
665 | if (!e) | ||
666 | return NULL; | ||
667 | switch (e->type) { | ||
668 | case E_OR: | ||
669 | case E_AND: | ||
670 | sym = sym_check_expr_deps(e->left.expr); | ||
671 | if (sym) | ||
672 | return sym; | ||
673 | return sym_check_expr_deps(e->right.expr); | ||
674 | case E_NOT: | ||
675 | return sym_check_expr_deps(e->left.expr); | ||
676 | case E_EQUAL: | ||
677 | case E_UNEQUAL: | ||
678 | sym = sym_check_deps(e->left.sym); | ||
679 | if (sym) | ||
680 | return sym; | ||
681 | return sym_check_deps(e->right.sym); | ||
682 | case E_SYMBOL: | ||
683 | return sym_check_deps(e->left.sym); | ||
684 | default: | ||
685 | break; | ||
686 | } | ||
687 | printf("Oops! How to check %d?\n", e->type); | ||
688 | return NULL; | ||
689 | } | ||
690 | |||
691 | struct symbol *sym_check_deps(struct symbol *sym) | ||
692 | { | ||
693 | struct symbol *sym2; | ||
694 | struct property *prop; | ||
695 | |||
696 | if (sym->flags & SYMBOL_CHECK_DONE) | ||
697 | return NULL; | ||
698 | if (sym->flags & SYMBOL_CHECK) { | ||
699 | printf("Warning! Found recursive dependency: %s", sym->name); | ||
700 | return sym; | ||
701 | } | ||
702 | |||
703 | sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED); | ||
704 | sym2 = sym_check_expr_deps(sym->rev_dep.expr); | ||
705 | if (sym2) | ||
706 | goto out; | ||
707 | |||
708 | for (prop = sym->prop; prop; prop = prop->next) { | ||
709 | if (prop->type == P_CHOICE) | ||
710 | continue; | ||
711 | sym2 = sym_check_expr_deps(prop->visible.expr); | ||
712 | if (sym2) | ||
713 | goto out; | ||
714 | if (prop->type != P_DEFAULT || sym_is_choice(sym)) | ||
715 | continue; | ||
716 | sym2 = sym_check_expr_deps(prop->expr); | ||
717 | if (sym2) | ||
718 | goto out; | ||
719 | } | ||
720 | out: | ||
721 | if (sym2) | ||
722 | printf(" %s", sym->name); | ||
723 | sym->flags &= ~SYMBOL_CHECK; | ||
724 | return sym2; | ||
725 | } | ||
726 | |||
727 | struct property *prop_alloc(enum prop_type type, struct symbol *sym) | ||
728 | { | ||
729 | struct property *prop; | ||
730 | struct property **propp; | ||
731 | |||
732 | prop = malloc(sizeof(*prop)); | ||
733 | memset(prop, 0, sizeof(*prop)); | ||
734 | prop->type = type; | ||
735 | prop->sym = sym; | ||
736 | prop->file = current_file; | ||
737 | prop->lineno = zconf_lineno(); | ||
738 | |||
739 | /* append property to the prop list of symbol */ | ||
740 | if (sym) { | ||
741 | for (propp = &sym->prop; *propp; propp = &(*propp)->next) | ||
742 | ; | ||
743 | *propp = prop; | ||
744 | } | ||
745 | |||
746 | return prop; | ||
747 | } | ||
748 | |||
749 | struct symbol *prop_get_symbol(struct property *prop) | ||
750 | { | ||
751 | if (prop->expr && (prop->expr->type == E_SYMBOL || | ||
752 | prop->expr->type == E_CHOICE)) | ||
753 | return prop->expr->left.sym; | ||
754 | return NULL; | ||
755 | } | ||
756 | |||
611 | const char *prop_get_type_name(enum prop_type type) | 757 | const char *prop_get_type_name(enum prop_type type) |
612 | { | 758 | { |
613 | switch (type) { | 759 | switch (type) { |
614 | case P_PROMPT: | 760 | case P_PROMPT: |
615 | return "prompt"; | 761 | return "prompt"; |
616 | case P_COMMENT: | 762 | case P_COMMENT: |
617 | return "comment"; | 763 | return "comment"; |
618 | case P_MENU: | 764 | case P_MENU: |
619 | return "menu"; | 765 | return "menu"; |
620 | case P_ROOTMENU: | ||
621 | return "rootmenu"; | ||
622 | case P_DEFAULT: | 766 | case P_DEFAULT: |
623 | return "default"; | 767 | return "default"; |
624 | case P_CHOICE: | 768 | case P_CHOICE: |
625 | return "choice"; | 769 | return "choice"; |
626 | default: | 770 | case P_SELECT: |
627 | return "unknown"; | 771 | return "select"; |
772 | case P_RANGE: | ||
773 | return "range"; | ||
774 | case P_UNKNOWN: | ||
775 | break; | ||
628 | } | 776 | } |
777 | return "unknown"; | ||
629 | } | 778 | } |