diff options
author | Eric Andersen <andersen@codepoet.org> | 2003-08-05 02:18:25 +0000 |
---|---|---|
committer | Eric Andersen <andersen@codepoet.org> | 2003-08-05 02:18:25 +0000 |
commit | 72d8e444f0e9e002b16328e73464ef9015979048 (patch) | |
tree | d1d99e668617e95836a1f767257e1263963feaa5 /scripts/config/symbol.c | |
parent | 461c279ac176a28dec40d1e40ebaffe4f0ac688d (diff) | |
download | busybox-w32-72d8e444f0e9e002b16328e73464ef9015979048.tar.gz busybox-w32-72d8e444f0e9e002b16328e73464ef9015979048.tar.bz2 busybox-w32-72d8e444f0e9e002b16328e73464ef9015979048.zip |
Merge/rework config system per the latest from linux-2.6.0-test2.
Fix the config bugs revealed by the updated config system.
-Erik
Diffstat (limited to 'scripts/config/symbol.c')
-rw-r--r-- | scripts/config/symbol.c | 518 |
1 files changed, 330 insertions, 188 deletions
diff --git a/scripts/config/symbol.c b/scripts/config/symbol.c index f2d0015de..29d8d3e0b 100644 --- a/scripts/config/symbol.c +++ b/scripts/config/symbol.c | |||
@@ -34,24 +34,14 @@ 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; | ||
55 | char *p; | 45 | char *p; |
56 | static bool inited = false; | 46 | static bool inited = false; |
57 | 47 | ||
@@ -59,17 +49,6 @@ void sym_init(void) | |||
59 | return; | 49 | return; |
60 | inited = true; | 50 | inited = true; |
61 | 51 | ||
62 | uname(&uts); | ||
63 | |||
64 | #if 0 | ||
65 | sym = sym_lookup("ARCH", 0); | ||
66 | sym->type = S_STRING; | ||
67 | sym->flags |= SYMBOL_AUTO; | ||
68 | p = getenv("ARCH"); | ||
69 | if (p) | ||
70 | sym_add_default(sym, p); | ||
71 | #endif | ||
72 | |||
73 | sym = sym_lookup("VERSION", 0); | 52 | sym = sym_lookup("VERSION", 0); |
74 | sym->type = S_STRING; | 53 | sym->type = S_STRING; |
75 | sym->flags |= SYMBOL_AUTO; | 54 | sym->flags |= SYMBOL_AUTO; |
@@ -77,37 +56,32 @@ void sym_init(void) | |||
77 | if (p) | 56 | if (p) |
78 | sym_add_default(sym, p); | 57 | sym_add_default(sym, p); |
79 | 58 | ||
80 | #if 0 | ||
81 | sym = sym_lookup("UNAME_RELEASE", 0); | ||
82 | sym->type = S_STRING; | ||
83 | sym->flags |= SYMBOL_AUTO; | ||
84 | sym_add_default(sym, uts.release); | ||
85 | #endif | ||
86 | |||
87 | sym = sym_lookup("TARGET_ARCH", 0); | 59 | sym = sym_lookup("TARGET_ARCH", 0); |
88 | sym->type = S_STRING; | 60 | sym->type = S_STRING; |
89 | sym->flags |= SYMBOL_AUTO; | 61 | sym->flags |= SYMBOL_AUTO; |
90 | p = getenv("TARGET_ARCH"); | 62 | p = getenv("TARGET_ARCH"); |
91 | if (p) | 63 | if (p) |
92 | sym_add_default(sym, p); | 64 | sym_add_default(sym, p); |
65 | |||
93 | } | 66 | } |
94 | 67 | ||
95 | int sym_get_type(struct symbol *sym) | 68 | enum symbol_type sym_get_type(struct symbol *sym) |
96 | { | 69 | { |
97 | int type = sym->type; | 70 | enum symbol_type type = sym->type; |
71 | |||
98 | if (type == S_TRISTATE) { | 72 | if (type == S_TRISTATE) { |
99 | if (sym_is_choice_value(sym) && sym->visible == yes) | 73 | if (sym_is_choice_value(sym) && sym->visible == yes) |
100 | type = S_BOOLEAN; | 74 | type = S_BOOLEAN; |
101 | else { | 75 | else { |
102 | sym_calc_value(modules_sym); | 76 | sym_calc_value(modules_sym); |
103 | if (S_TRI(modules_sym->curr) == no) | 77 | if (modules_sym->curr.tri == no) |
104 | type = S_BOOLEAN; | 78 | type = S_BOOLEAN; |
105 | } | 79 | } |
106 | } | 80 | } |
107 | return type; | 81 | return type; |
108 | } | 82 | } |
109 | 83 | ||
110 | const char *sym_type_name(int type) | 84 | const char *sym_type_name(enum symbol_type type) |
111 | { | 85 | { |
112 | switch (type) { | 86 | switch (type) { |
113 | case S_BOOLEAN: | 87 | case S_BOOLEAN: |
@@ -122,6 +96,8 @@ const char *sym_type_name(int type) | |||
122 | return "string"; | 96 | return "string"; |
123 | case S_UNKNOWN: | 97 | case S_UNKNOWN: |
124 | return "unknown"; | 98 | return "unknown"; |
99 | case S_OTHER: | ||
100 | break; | ||
125 | } | 101 | } |
126 | return "???"; | 102 | return "???"; |
127 | } | 103 | } |
@@ -138,41 +114,104 @@ struct property *sym_get_choice_prop(struct symbol *sym) | |||
138 | struct property *sym_get_default_prop(struct symbol *sym) | 114 | struct property *sym_get_default_prop(struct symbol *sym) |
139 | { | 115 | { |
140 | struct property *prop; | 116 | struct property *prop; |
141 | tristate visible; | ||
142 | 117 | ||
143 | for_all_defaults(sym, prop) { | 118 | for_all_defaults(sym, prop) { |
144 | visible = E_CALC(prop->visible); | 119 | prop->visible.tri = expr_calc_value(prop->visible.expr); |
145 | if (visible != no) | 120 | if (prop->visible.tri != no) |
121 | return prop; | ||
122 | } | ||
123 | return NULL; | ||
124 | } | ||
125 | |||
126 | struct property *sym_get_range_prop(struct symbol *sym) | ||
127 | { | ||
128 | struct property *prop; | ||
129 | |||
130 | for_all_properties(sym, prop, P_RANGE) { | ||
131 | prop->visible.tri = expr_calc_value(prop->visible.expr); | ||
132 | if (prop->visible.tri != no) | ||
146 | return prop; | 133 | return prop; |
147 | } | 134 | } |
148 | return NULL; | 135 | return NULL; |
149 | } | 136 | } |
150 | 137 | ||
151 | void sym_calc_visibility(struct symbol *sym) | 138 | static void sym_calc_visibility(struct symbol *sym) |
152 | { | 139 | { |
153 | struct property *prop; | 140 | struct property *prop; |
154 | tristate visible, oldvisible; | 141 | tristate tri; |
155 | 142 | ||
156 | /* any prompt visible? */ | 143 | /* any prompt visible? */ |
157 | oldvisible = sym->visible; | 144 | tri = no; |
158 | visible = no; | 145 | for_all_prompts(sym, prop) { |
159 | for_all_prompts(sym, prop) | 146 | prop->visible.tri = expr_calc_value(prop->visible.expr); |
160 | visible = E_OR(visible, E_CALC(prop->visible)); | 147 | tri = E_OR(tri, prop->visible.tri); |
161 | if (oldvisible != visible) { | 148 | } |
162 | sym->visible = visible; | 149 | if (sym->visible != tri) { |
163 | sym->flags |= SYMBOL_CHANGED; | 150 | sym->visible = tri; |
151 | sym_set_changed(sym); | ||
152 | } | ||
153 | if (sym_is_choice_value(sym)) | ||
154 | return; | ||
155 | tri = no; | ||
156 | if (sym->rev_dep.expr) | ||
157 | tri = expr_calc_value(sym->rev_dep.expr); | ||
158 | if (sym->rev_dep.tri != tri) { | ||
159 | sym->rev_dep.tri = tri; | ||
160 | sym_set_changed(sym); | ||
161 | } | ||
162 | } | ||
163 | |||
164 | static struct symbol *sym_calc_choice(struct symbol *sym) | ||
165 | { | ||
166 | struct symbol *def_sym; | ||
167 | struct property *prop; | ||
168 | struct expr *e; | ||
169 | |||
170 | /* is the user choice visible? */ | ||
171 | def_sym = sym->user.val; | ||
172 | if (def_sym) { | ||
173 | sym_calc_visibility(def_sym); | ||
174 | if (def_sym->visible != no) | ||
175 | return def_sym; | ||
164 | } | 176 | } |
177 | |||
178 | /* any of the defaults visible? */ | ||
179 | for_all_defaults(sym, prop) { | ||
180 | prop->visible.tri = expr_calc_value(prop->visible.expr); | ||
181 | if (prop->visible.tri == no) | ||
182 | continue; | ||
183 | def_sym = prop_get_symbol(prop); | ||
184 | sym_calc_visibility(def_sym); | ||
185 | if (def_sym->visible != no) | ||
186 | return def_sym; | ||
187 | } | ||
188 | |||
189 | /* just get the first visible value */ | ||
190 | prop = sym_get_choice_prop(sym); | ||
191 | for (e = prop->expr; e; e = e->left.expr) { | ||
192 | def_sym = e->right.sym; | ||
193 | sym_calc_visibility(def_sym); | ||
194 | if (def_sym->visible != no) | ||
195 | return def_sym; | ||
196 | } | ||
197 | |||
198 | /* no choice? reset tristate value */ | ||
199 | sym->curr.tri = no; | ||
200 | return NULL; | ||
165 | } | 201 | } |
166 | 202 | ||
167 | void sym_calc_value(struct symbol *sym) | 203 | void sym_calc_value(struct symbol *sym) |
168 | { | 204 | { |
169 | struct symbol_value newval, oldval; | 205 | struct symbol_value newval, oldval; |
170 | struct property *prop, *def_prop; | 206 | struct property *prop; |
171 | struct symbol *def_sym; | ||
172 | struct expr *e; | 207 | struct expr *e; |
173 | 208 | ||
209 | if (!sym) | ||
210 | return; | ||
211 | |||
174 | if (sym->flags & SYMBOL_VALID) | 212 | if (sym->flags & SYMBOL_VALID) |
175 | return; | 213 | return; |
214 | sym->flags |= SYMBOL_VALID; | ||
176 | 215 | ||
177 | oldval = sym->curr; | 216 | oldval = sym->curr; |
178 | 217 | ||
@@ -187,17 +226,10 @@ void sym_calc_value(struct symbol *sym) | |||
187 | newval = symbol_no.curr; | 226 | newval = symbol_no.curr; |
188 | break; | 227 | break; |
189 | default: | 228 | default: |
190 | S_VAL(newval) = sym->name; | 229 | sym->curr.val = sym->name; |
191 | S_TRI(newval) = no; | 230 | sym->curr.tri = no; |
192 | if (sym->flags & SYMBOL_CONST) { | 231 | return; |
193 | goto out; | ||
194 | } | ||
195 | //newval = symbol_empty.curr; | ||
196 | // generate warning somewhere here later | ||
197 | //S_TRI(newval) = yes; | ||
198 | goto out; | ||
199 | } | 232 | } |
200 | sym->flags |= SYMBOL_VALID; | ||
201 | if (!sym_is_choice_value(sym)) | 233 | if (!sym_is_choice_value(sym)) |
202 | sym->flags &= ~SYMBOL_WRITE; | 234 | sym->flags &= ~SYMBOL_WRITE; |
203 | 235 | ||
@@ -206,95 +238,77 @@ void sym_calc_value(struct symbol *sym) | |||
206 | /* set default if recursively called */ | 238 | /* set default if recursively called */ |
207 | sym->curr = newval; | 239 | sym->curr = newval; |
208 | 240 | ||
209 | if (sym->visible != no) { | 241 | switch (sym_get_type(sym)) { |
210 | sym->flags |= SYMBOL_WRITE; | 242 | case S_BOOLEAN: |
211 | if (!sym_has_value(sym)) { | 243 | case S_TRISTATE: |
212 | if (!sym_is_choice(sym)) { | ||
213 | prop = sym_get_default_prop(sym); | ||
214 | if (prop) { | ||
215 | sym_calc_value(prop->def); | ||
216 | newval = prop->def->curr; | ||
217 | } | ||
218 | } | ||
219 | } else | ||
220 | newval = sym->def; | ||
221 | |||
222 | S_TRI(newval) = E_AND(S_TRI(newval), sym->visible); | ||
223 | /* if the symbol is visible and not optionial, | ||
224 | * possibly ignore old user choice. */ | ||
225 | if (!sym_is_optional(sym) && S_TRI(newval) == no) | ||
226 | S_TRI(newval) = sym->visible; | ||
227 | if (sym_is_choice_value(sym) && sym->visible == yes) { | 244 | if (sym_is_choice_value(sym) && sym->visible == yes) { |
228 | prop = sym_get_choice_prop(sym); | 245 | prop = sym_get_choice_prop(sym); |
229 | S_TRI(newval) = (S_VAL(prop->def->curr) == sym) ? yes : no; | 246 | newval.tri = (prop_get_symbol(prop)->curr.val == sym) ? yes : no; |
230 | } | 247 | } else if (E_OR(sym->visible, sym->rev_dep.tri) != no) { |
231 | } else { | ||
232 | prop = sym_get_default_prop(sym); | ||
233 | if (prop) { | ||
234 | sym->flags |= SYMBOL_WRITE; | 248 | sym->flags |= SYMBOL_WRITE; |
235 | sym_calc_value(prop->def); | 249 | if (sym_has_value(sym)) |
236 | newval = prop->def->curr; | 250 | newval.tri = sym->user.tri; |
251 | else if (!sym_is_choice(sym)) { | ||
252 | prop = sym_get_default_prop(sym); | ||
253 | if (prop) | ||
254 | newval.tri = expr_calc_value(prop->expr); | ||
255 | } | ||
256 | newval.tri = E_OR(E_AND(newval.tri, sym->visible), sym->rev_dep.tri); | ||
257 | } else if (!sym_is_choice(sym)) { | ||
258 | prop = sym_get_default_prop(sym); | ||
259 | if (prop) { | ||
260 | sym->flags |= SYMBOL_WRITE; | ||
261 | newval.tri = expr_calc_value(prop->expr); | ||
262 | } | ||
237 | } | 263 | } |
238 | } | 264 | if (sym_get_type(sym) == S_BOOLEAN) { |
239 | 265 | if (newval.tri == mod) | |
240 | switch (sym_get_type(sym)) { | 266 | newval.tri = yes; |
241 | case S_TRISTATE: | 267 | if (sym->visible == mod) |
242 | if (S_TRI(newval) != mod) | 268 | sym->visible = yes; |
243 | break; | 269 | if (sym->rev_dep.tri == mod) |
244 | sym_calc_value(modules_sym); | 270 | sym->rev_dep.tri = yes; |
245 | if (S_TRI(modules_sym->curr) == no) | ||
246 | S_TRI(newval) = yes; | ||
247 | break; | ||
248 | case S_BOOLEAN: | ||
249 | if (S_TRI(newval) == mod) | ||
250 | S_TRI(newval) = yes; | ||
251 | } | ||
252 | |||
253 | out: | ||
254 | sym->curr = newval; | ||
255 | |||
256 | if (sym_is_choice(sym) && S_TRI(newval) == yes) { | ||
257 | def_sym = S_VAL(sym->def); | ||
258 | if (def_sym) { | ||
259 | sym_calc_visibility(def_sym); | ||
260 | if (def_sym->visible == no) | ||
261 | def_sym = NULL; | ||
262 | } | 271 | } |
263 | if (!def_sym) { | 272 | break; |
264 | for_all_defaults(sym, def_prop) { | 273 | case S_STRING: |
265 | if (E_CALC(def_prop->visible) == no) | 274 | case S_HEX: |
266 | continue; | 275 | case S_INT: |
267 | sym_calc_visibility(def_prop->def); | 276 | if (sym->visible != no) { |
268 | if (def_prop->def->visible != no) { | 277 | sym->flags |= SYMBOL_WRITE; |
269 | def_sym = def_prop->def; | 278 | if (sym_has_value(sym)) { |
270 | break; | 279 | newval.val = sym->user.val; |
271 | } | 280 | break; |
272 | } | 281 | } |
273 | } | 282 | } |
274 | 283 | prop = sym_get_default_prop(sym); | |
275 | if (!def_sym) { | 284 | if (prop) { |
276 | prop = sym_get_choice_prop(sym); | 285 | struct symbol *ds = prop_get_symbol(prop); |
277 | for (e = prop->dep; e; e = e->left.expr) { | 286 | if (ds) { |
278 | sym_calc_visibility(e->right.sym); | 287 | sym->flags |= SYMBOL_WRITE; |
279 | if (e->right.sym->visible != no) { | 288 | sym_calc_value(ds); |
280 | def_sym = e->right.sym; | 289 | newval.val = ds->curr.val; |
281 | break; | ||
282 | } | ||
283 | } | 290 | } |
284 | } | 291 | } |
285 | 292 | break; | |
286 | S_VAL(newval) = def_sym; | 293 | default: |
294 | ; | ||
287 | } | 295 | } |
288 | 296 | ||
289 | if (memcmp(&oldval, &newval, sizeof(newval))) | ||
290 | sym->flags |= SYMBOL_CHANGED; | ||
291 | sym->curr = newval; | 297 | sym->curr = newval; |
298 | if (sym_is_choice(sym) && newval.tri == yes) | ||
299 | sym->curr.val = sym_calc_choice(sym); | ||
300 | |||
301 | if (memcmp(&oldval, &sym->curr, sizeof(oldval))) | ||
302 | sym_set_changed(sym); | ||
292 | 303 | ||
293 | if (sym_is_choice(sym)) { | 304 | if (sym_is_choice(sym)) { |
294 | int flags = sym->flags & (SYMBOL_CHANGED | SYMBOL_WRITE); | 305 | int flags = sym->flags & (SYMBOL_CHANGED | SYMBOL_WRITE); |
295 | prop = sym_get_choice_prop(sym); | 306 | prop = sym_get_choice_prop(sym); |
296 | for (e = prop->dep; e; e = e->left.expr) | 307 | for (e = prop->expr; e; e = e->left.expr) { |
297 | e->right.sym->flags |= flags; | 308 | e->right.sym->flags |= flags; |
309 | if (flags & SYMBOL_CHANGED) | ||
310 | sym_set_changed(e->right.sym); | ||
311 | } | ||
298 | } | 312 | } |
299 | } | 313 | } |
300 | 314 | ||
@@ -308,13 +322,24 @@ void sym_clear_all_valid(void) | |||
308 | sym_change_count++; | 322 | sym_change_count++; |
309 | } | 323 | } |
310 | 324 | ||
325 | void sym_set_changed(struct symbol *sym) | ||
326 | { | ||
327 | struct property *prop; | ||
328 | |||
329 | sym->flags |= SYMBOL_CHANGED; | ||
330 | for (prop = sym->prop; prop; prop = prop->next) { | ||
331 | if (prop->menu) | ||
332 | prop->menu->flags |= MENU_CHANGED; | ||
333 | } | ||
334 | } | ||
335 | |||
311 | void sym_set_all_changed(void) | 336 | void sym_set_all_changed(void) |
312 | { | 337 | { |
313 | struct symbol *sym; | 338 | struct symbol *sym; |
314 | int i; | 339 | int i; |
315 | 340 | ||
316 | for_all_symbols(i, sym) | 341 | for_all_symbols(i, sym) |
317 | sym->flags |= SYMBOL_CHANGED; | 342 | sym_set_changed(sym); |
318 | } | 343 | } |
319 | 344 | ||
320 | bool sym_tristate_within_range(struct symbol *sym, tristate val) | 345 | bool sym_tristate_within_range(struct symbol *sym, tristate val) |
@@ -327,19 +352,13 @@ bool sym_tristate_within_range(struct symbol *sym, tristate val) | |||
327 | if (type != S_BOOLEAN && type != S_TRISTATE) | 352 | if (type != S_BOOLEAN && type != S_TRISTATE) |
328 | return false; | 353 | return false; |
329 | 354 | ||
330 | switch (val) { | 355 | if (type == S_BOOLEAN && val == mod) |
331 | case no: | 356 | return false; |
332 | if (sym_is_choice_value(sym) && sym->visible == yes) | 357 | if (sym->visible <= sym->rev_dep.tri) |
333 | return false; | 358 | return false; |
334 | return sym_is_optional(sym); | 359 | if (sym_is_choice_value(sym) && sym->visible == yes) |
335 | case mod: | 360 | return val == yes; |
336 | if (sym_is_choice_value(sym) && sym->visible == yes) | 361 | return val >= sym->rev_dep.tri && val <= sym->visible; |
337 | return false; | ||
338 | return type == S_TRISTATE; | ||
339 | case yes: | ||
340 | return type == S_BOOLEAN || sym->visible == yes; | ||
341 | } | ||
342 | return false; | ||
343 | } | 362 | } |
344 | 363 | ||
345 | bool sym_set_tristate_value(struct symbol *sym, tristate val) | 364 | bool sym_set_tristate_value(struct symbol *sym, tristate val) |
@@ -351,16 +370,16 @@ bool sym_set_tristate_value(struct symbol *sym, tristate val) | |||
351 | 370 | ||
352 | if (sym->flags & SYMBOL_NEW) { | 371 | if (sym->flags & SYMBOL_NEW) { |
353 | sym->flags &= ~SYMBOL_NEW; | 372 | sym->flags &= ~SYMBOL_NEW; |
354 | sym->flags |= SYMBOL_CHANGED; | 373 | sym_set_changed(sym); |
355 | } | 374 | } |
356 | if (sym_is_choice_value(sym) && val == yes) { | 375 | if (sym_is_choice_value(sym) && val == yes) { |
357 | struct property *prop = sym_get_choice_prop(sym); | 376 | struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym)); |
358 | 377 | ||
359 | S_VAL(prop->def->def) = sym; | 378 | cs->user.val = sym; |
360 | prop->def->flags &= ~SYMBOL_NEW; | 379 | cs->flags &= ~SYMBOL_NEW; |
361 | } | 380 | } |
362 | 381 | ||
363 | S_TRI(sym->def) = val; | 382 | sym->user.tri = val; |
364 | if (oldval != val) { | 383 | if (oldval != val) { |
365 | sym_clear_all_valid(); | 384 | sym_clear_all_valid(); |
366 | if (sym == modules_sym) | 385 | if (sym == modules_sym) |
@@ -404,12 +423,12 @@ bool sym_string_valid(struct symbol *sym, const char *str) | |||
404 | ch = *str++; | 423 | ch = *str++; |
405 | if (ch == '-') | 424 | if (ch == '-') |
406 | ch = *str++; | 425 | ch = *str++; |
407 | if (!isdigit((int)ch)) | 426 | if (!isdigit(ch)) |
408 | return false; | 427 | return false; |
409 | if (ch == '0' && *str != 0) | 428 | if (ch == '0' && *str != 0) |
410 | return false; | 429 | return false; |
411 | while ((ch = *str++)) { | 430 | while ((ch = *str++)) { |
412 | if (!isdigit((int)ch)) | 431 | if (!isdigit(ch)) |
413 | return false; | 432 | return false; |
414 | } | 433 | } |
415 | return true; | 434 | return true; |
@@ -418,21 +437,58 @@ bool sym_string_valid(struct symbol *sym, const char *str) | |||
418 | str += 2; | 437 | str += 2; |
419 | ch = *str++; | 438 | ch = *str++; |
420 | do { | 439 | do { |
421 | if (!isxdigit((int)ch)) | 440 | if (!isxdigit(ch)) |
422 | return false; | 441 | return false; |
423 | } while ((ch = *str++)); | 442 | } while ((ch = *str++)); |
424 | return true; | 443 | return true; |
425 | case S_BOOLEAN: | 444 | case S_BOOLEAN: |
426 | case S_TRISTATE: | 445 | case S_TRISTATE: |
427 | switch (str[0]) { | 446 | switch (str[0]) { |
428 | case 'y': | 447 | case 'y': case 'Y': |
429 | case 'Y': | 448 | case 'm': case 'M': |
449 | case 'n': case 'N': | ||
450 | return true; | ||
451 | } | ||
452 | return false; | ||
453 | default: | ||
454 | return false; | ||
455 | } | ||
456 | } | ||
457 | |||
458 | bool sym_string_within_range(struct symbol *sym, const char *str) | ||
459 | { | ||
460 | struct property *prop; | ||
461 | int val; | ||
462 | |||
463 | switch (sym->type) { | ||
464 | case S_STRING: | ||
465 | return sym_string_valid(sym, str); | ||
466 | case S_INT: | ||
467 | if (!sym_string_valid(sym, str)) | ||
468 | return false; | ||
469 | prop = sym_get_range_prop(sym); | ||
470 | if (!prop) | ||
471 | return true; | ||
472 | val = strtol(str, NULL, 10); | ||
473 | return val >= strtol(prop->expr->left.sym->name, NULL, 10) && | ||
474 | val <= strtol(prop->expr->right.sym->name, NULL, 10); | ||
475 | case S_HEX: | ||
476 | if (!sym_string_valid(sym, str)) | ||
477 | return false; | ||
478 | prop = sym_get_range_prop(sym); | ||
479 | if (!prop) | ||
480 | return true; | ||
481 | val = strtol(str, NULL, 16); | ||
482 | return val >= strtol(prop->expr->left.sym->name, NULL, 16) && | ||
483 | val <= strtol(prop->expr->right.sym->name, NULL, 16); | ||
484 | case S_BOOLEAN: | ||
485 | case S_TRISTATE: | ||
486 | switch (str[0]) { | ||
487 | case 'y': case 'Y': | ||
430 | return sym_tristate_within_range(sym, yes); | 488 | return sym_tristate_within_range(sym, yes); |
431 | case 'm': | 489 | case 'm': case 'M': |
432 | case 'M': | ||
433 | return sym_tristate_within_range(sym, mod); | 490 | return sym_tristate_within_range(sym, mod); |
434 | case 'n': | 491 | case 'n': case 'N': |
435 | case 'N': | ||
436 | return sym_tristate_within_range(sym, no); | 492 | return sym_tristate_within_range(sym, no); |
437 | } | 493 | } |
438 | return false; | 494 | return false; |
@@ -451,14 +507,11 @@ bool sym_set_string_value(struct symbol *sym, const char *newval) | |||
451 | case S_BOOLEAN: | 507 | case S_BOOLEAN: |
452 | case S_TRISTATE: | 508 | case S_TRISTATE: |
453 | switch (newval[0]) { | 509 | switch (newval[0]) { |
454 | case 'y': | 510 | case 'y': case 'Y': |
455 | case 'Y': | ||
456 | return sym_set_tristate_value(sym, yes); | 511 | return sym_set_tristate_value(sym, yes); |
457 | case 'm': | 512 | case 'm': case 'M': |
458 | case 'M': | ||
459 | return sym_set_tristate_value(sym, mod); | 513 | return sym_set_tristate_value(sym, mod); |
460 | case 'n': | 514 | case 'n': case 'N': |
461 | case 'N': | ||
462 | return sym_set_tristate_value(sym, no); | 515 | return sym_set_tristate_value(sym, no); |
463 | } | 516 | } |
464 | return false; | 517 | return false; |
@@ -466,23 +519,23 @@ bool sym_set_string_value(struct symbol *sym, const char *newval) | |||
466 | ; | 519 | ; |
467 | } | 520 | } |
468 | 521 | ||
469 | if (!sym_string_valid(sym, newval)) | 522 | if (!sym_string_within_range(sym, newval)) |
470 | return false; | 523 | return false; |
471 | 524 | ||
472 | if (sym->flags & SYMBOL_NEW) { | 525 | if (sym->flags & SYMBOL_NEW) { |
473 | sym->flags &= ~SYMBOL_NEW; | 526 | sym->flags &= ~SYMBOL_NEW; |
474 | sym->flags |= SYMBOL_CHANGED; | 527 | sym_set_changed(sym); |
475 | } | 528 | } |
476 | 529 | ||
477 | oldval = S_VAL(sym->def); | 530 | oldval = sym->user.val; |
478 | size = strlen(newval) + 1; | 531 | size = strlen(newval) + 1; |
479 | if (sym->type == S_HEX && (newval[0] != '0' || (newval[1] != 'x' && newval[1] != 'X'))) { | 532 | if (sym->type == S_HEX && (newval[0] != '0' || (newval[1] != 'x' && newval[1] != 'X'))) { |
480 | size += 2; | 533 | size += 2; |
481 | S_VAL(sym->def) = val = malloc(size); | 534 | sym->user.val = val = malloc(size); |
482 | *val++ = '0'; | 535 | *val++ = '0'; |
483 | *val++ = 'x'; | 536 | *val++ = 'x'; |
484 | } else if (!oldval || strcmp(oldval, newval)) | 537 | } else if (!oldval || strcmp(oldval, newval)) |
485 | S_VAL(sym->def) = val = malloc(size); | 538 | sym->user.val = val = malloc(size); |
486 | else | 539 | else |
487 | return true; | 540 | return true; |
488 | 541 | ||
@@ -513,20 +566,12 @@ const char *sym_get_string_value(struct symbol *sym) | |||
513 | default: | 566 | default: |
514 | ; | 567 | ; |
515 | } | 568 | } |
516 | return (const char *)S_VAL(sym->curr); | 569 | return (const char *)sym->curr.val; |
517 | } | 570 | } |
518 | 571 | ||
519 | bool sym_is_changable(struct symbol *sym) | 572 | bool sym_is_changable(struct symbol *sym) |
520 | { | 573 | { |
521 | if (sym->visible == no) | 574 | return sym->visible > sym->rev_dep.tri; |
522 | return false; | ||
523 | /* at least 'n' and 'y'/'m' is selectable */ | ||
524 | if (sym_is_optional(sym)) | ||
525 | return true; | ||
526 | /* no 'n', so 'y' and 'm' must be selectable */ | ||
527 | if (sym_get_type(sym) == S_TRISTATE && sym->visible == yes) | ||
528 | return true; | ||
529 | return false; | ||
530 | } | 575 | } |
531 | 576 | ||
532 | struct symbol *sym_lookup(const char *name, int isconst) | 577 | struct symbol *sym_lookup(const char *name, int isconst) |
@@ -536,7 +581,6 @@ struct symbol *sym_lookup(const char *name, int isconst) | |||
536 | char *new_name; | 581 | char *new_name; |
537 | int hash = 0; | 582 | int hash = 0; |
538 | 583 | ||
539 | //printf("lookup: %s -> ", name); | ||
540 | if (name) { | 584 | if (name) { |
541 | if (name[0] && !name[1]) { | 585 | if (name[0] && !name[1]) { |
542 | switch (name[0]) { | 586 | switch (name[0]) { |
@@ -552,10 +596,8 @@ struct symbol *sym_lookup(const char *name, int isconst) | |||
552 | for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) { | 596 | for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) { |
553 | if (!strcmp(symbol->name, name)) { | 597 | if (!strcmp(symbol->name, name)) { |
554 | if ((isconst && symbol->flags & SYMBOL_CONST) || | 598 | if ((isconst && symbol->flags & SYMBOL_CONST) || |
555 | (!isconst && !(symbol->flags & SYMBOL_CONST))) { | 599 | (!isconst && !(symbol->flags & SYMBOL_CONST))) |
556 | //printf("h:%p\n", symbol); | ||
557 | return symbol; | 600 | return symbol; |
558 | } | ||
559 | } | 601 | } |
560 | } | 602 | } |
561 | new_name = strdup(name); | 603 | new_name = strdup(name); |
@@ -575,7 +617,6 @@ struct symbol *sym_lookup(const char *name, int isconst) | |||
575 | symbol->next = symbol_hash[hash]; | 617 | symbol->next = symbol_hash[hash]; |
576 | symbol_hash[hash] = symbol; | 618 | symbol_hash[hash] = symbol; |
577 | 619 | ||
578 | //printf("n:%p\n", symbol); | ||
579 | return symbol; | 620 | return symbol; |
580 | } | 621 | } |
581 | 622 | ||
@@ -608,6 +649,104 @@ struct symbol *sym_find(const char *name) | |||
608 | return symbol; | 649 | return symbol; |
609 | } | 650 | } |
610 | 651 | ||
652 | struct symbol *sym_check_deps(struct symbol *sym); | ||
653 | |||
654 | static struct symbol *sym_check_expr_deps(struct expr *e) | ||
655 | { | ||
656 | struct symbol *sym; | ||
657 | |||
658 | if (!e) | ||
659 | return NULL; | ||
660 | switch (e->type) { | ||
661 | case E_OR: | ||
662 | case E_AND: | ||
663 | sym = sym_check_expr_deps(e->left.expr); | ||
664 | if (sym) | ||
665 | return sym; | ||
666 | return sym_check_expr_deps(e->right.expr); | ||
667 | case E_NOT: | ||
668 | return sym_check_expr_deps(e->left.expr); | ||
669 | case E_EQUAL: | ||
670 | case E_UNEQUAL: | ||
671 | sym = sym_check_deps(e->left.sym); | ||
672 | if (sym) | ||
673 | return sym; | ||
674 | return sym_check_deps(e->right.sym); | ||
675 | case E_SYMBOL: | ||
676 | return sym_check_deps(e->left.sym); | ||
677 | default: | ||
678 | break; | ||
679 | } | ||
680 | printf("Oops! How to check %d?\n", e->type); | ||
681 | return NULL; | ||
682 | } | ||
683 | |||
684 | struct symbol *sym_check_deps(struct symbol *sym) | ||
685 | { | ||
686 | struct symbol *sym2; | ||
687 | struct property *prop; | ||
688 | |||
689 | if (sym->flags & SYMBOL_CHECK_DONE) | ||
690 | return NULL; | ||
691 | if (sym->flags & SYMBOL_CHECK) { | ||
692 | printf("Warning! Found recursive dependency: %s", sym->name); | ||
693 | return sym; | ||
694 | } | ||
695 | |||
696 | sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED); | ||
697 | sym2 = sym_check_expr_deps(sym->rev_dep.expr); | ||
698 | if (sym2) | ||
699 | goto out; | ||
700 | |||
701 | for (prop = sym->prop; prop; prop = prop->next) { | ||
702 | if (prop->type == P_CHOICE) | ||
703 | continue; | ||
704 | sym2 = sym_check_expr_deps(prop->visible.expr); | ||
705 | if (sym2) | ||
706 | goto out; | ||
707 | if (prop->type != P_DEFAULT || sym_is_choice(sym)) | ||
708 | continue; | ||
709 | sym2 = sym_check_expr_deps(prop->expr); | ||
710 | if (sym2) | ||
711 | goto out; | ||
712 | } | ||
713 | out: | ||
714 | if (sym2) | ||
715 | printf(" %s", sym->name); | ||
716 | sym->flags &= ~SYMBOL_CHECK; | ||
717 | return sym2; | ||
718 | } | ||
719 | |||
720 | struct property *prop_alloc(enum prop_type type, struct symbol *sym) | ||
721 | { | ||
722 | struct property *prop; | ||
723 | struct property **propp; | ||
724 | |||
725 | prop = malloc(sizeof(*prop)); | ||
726 | memset(prop, 0, sizeof(*prop)); | ||
727 | prop->type = type; | ||
728 | prop->sym = sym; | ||
729 | prop->file = current_file; | ||
730 | prop->lineno = zconf_lineno(); | ||
731 | |||
732 | /* append property to the prop list of symbol */ | ||
733 | if (sym) { | ||
734 | for (propp = &sym->prop; *propp; propp = &(*propp)->next) | ||
735 | ; | ||
736 | *propp = prop; | ||
737 | } | ||
738 | |||
739 | return prop; | ||
740 | } | ||
741 | |||
742 | struct symbol *prop_get_symbol(struct property *prop) | ||
743 | { | ||
744 | if (prop->expr && (prop->expr->type == E_SYMBOL || | ||
745 | prop->expr->type == E_CHOICE)) | ||
746 | return prop->expr->left.sym; | ||
747 | return NULL; | ||
748 | } | ||
749 | |||
611 | const char *prop_get_type_name(enum prop_type type) | 750 | const char *prop_get_type_name(enum prop_type type) |
612 | { | 751 | { |
613 | switch (type) { | 752 | switch (type) { |
@@ -617,13 +756,16 @@ const char *prop_get_type_name(enum prop_type type) | |||
617 | return "comment"; | 756 | return "comment"; |
618 | case P_MENU: | 757 | case P_MENU: |
619 | return "menu"; | 758 | return "menu"; |
620 | case P_ROOTMENU: | ||
621 | return "rootmenu"; | ||
622 | case P_DEFAULT: | 759 | case P_DEFAULT: |
623 | return "default"; | 760 | return "default"; |
624 | case P_CHOICE: | 761 | case P_CHOICE: |
625 | return "choice"; | 762 | return "choice"; |
626 | default: | 763 | case P_SELECT: |
627 | return "unknown"; | 764 | return "select"; |
765 | case P_RANGE: | ||
766 | return "range"; | ||
767 | case P_UNKNOWN: | ||
768 | break; | ||
628 | } | 769 | } |
770 | return "unknown"; | ||
629 | } | 771 | } |