summaryrefslogtreecommitdiff
path: root/scripts/kconfig/symbol.c
Unidiff
Diffstat (limited to 'scripts/kconfig/symbol.c') (more/less context) (ignore whitespace changes)
-rw-r--r--scripts/kconfig/symbol.c465
1 files changed, 307 insertions, 158 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
@@ -13,379 +13,401 @@
13 13
14struct symbol symbol_yes = { 14struct symbol symbol_yes = {
15 name: "y", 15 name: "y",
16 curr: { "y", yes }, 16 curr: { "y", yes },
17 flags: SYMBOL_YES|SYMBOL_VALID, 17 flags: SYMBOL_YES|SYMBOL_VALID,
18}, symbol_mod = { 18}, symbol_mod = {
19 name: "m", 19 name: "m",
20 curr: { "m", mod }, 20 curr: { "m", mod },
21 flags: SYMBOL_MOD|SYMBOL_VALID, 21 flags: SYMBOL_MOD|SYMBOL_VALID,
22}, symbol_no = { 22}, symbol_no = {
23 name: "n", 23 name: "n",
24 curr: { "n", no }, 24 curr: { "n", no },
25 flags: SYMBOL_NO|SYMBOL_VALID, 25 flags: SYMBOL_NO|SYMBOL_VALID,
26}, symbol_empty = { 26}, symbol_empty = {
27 name: "", 27 name: "",
28 curr: { "", no }, 28 curr: { "", no },
29 flags: SYMBOL_VALID, 29 flags: SYMBOL_VALID,
30}; 30};
31 31
32int sym_change_count; 32int sym_change_count;
33struct symbol *modules_sym; 33struct symbol *modules_sym;
34 34
35void sym_add_default(struct symbol *sym, const char *def) 35void 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
51void sym_init(void) 42void sym_init(void)
52{ 43{
53 struct symbol *sym; 44 struct symbol *sym;
54 struct utsname uts; 45 struct utsname uts;
55 char *p; 46 char *p;
56 static bool inited = false; 47 static bool inited = false;
57 48
58 if (inited) 49 if (inited)
59 return; 50 return;
60 inited = true; 51 inited = true;
61 52
62 uname(&uts); 53 uname(&uts);
63 54
64 sym = sym_lookup("ARCH", 0); 55 sym = sym_lookup("ARCH", 0);
65 sym->type = S_STRING; 56 sym->type = S_STRING;
66 sym->flags |= SYMBOL_AUTO; 57 sym->flags |= SYMBOL_AUTO;
67 p = getenv("ARCH"); 58 p = getenv("ARCH");
68 if (p) 59 if (p)
69 sym_add_default(sym, p); 60 sym_add_default(sym, p);
70 61
71 sym = sym_lookup("KERNELRELEASE", 0); 62 sym = sym_lookup("KERNELRELEASE", 0);
72 sym->type = S_STRING; 63 sym->type = S_STRING;
73 sym->flags |= SYMBOL_AUTO; 64 sym->flags |= SYMBOL_AUTO;
74 p = getenv("KERNELRELEASE"); 65 p = getenv("KERNELRELEASE");
75 if (p) 66 if (p)
76 sym_add_default(sym, p); 67 sym_add_default(sym, p);
77 68
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
84int sym_get_type(struct symbol *sym) 75enum 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
99const char *sym_type_name(int type) 91const 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";
106 case S_INT: 98 case S_INT:
107 return "integer"; 99 return "integer";
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
118struct property *sym_get_choice_prop(struct symbol *sym) 112struct property *sym_get_choice_prop(struct symbol *sym)
119{ 113{
120 struct property *prop; 114 struct property *prop;
121 115
122 for_all_choices(sym, prop) 116 for_all_choices(sym, prop)
123 return prop; 117 return prop;
124 return NULL; 118 return NULL;
125} 119}
126 120
127struct property *sym_get_default_prop(struct symbol *sym) 121struct 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
140void sym_calc_visibility(struct symbol *sym) 133struct 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
145static 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;
158 sym_set_changed(sym);
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;
152 sym_set_changed(sym); 167 sym_set_changed(sym);
153 } 168 }
154} 169}
155 170
171static 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;
208}
209
156void sym_calc_value(struct symbol *sym) 210void 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:
171 case S_STRING: 228 case S_STRING:
172 newval = symbol_empty.curr; 229 newval = symbol_empty.curr;
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;
220 } 254 } else if (E_OR(sym->visible, sym->rev_dep.tri) != no) {
221 } else {
222 prop = sym_get_default_prop(sym);
223 if (prop) {
224 sym->flags |= SYMBOL_WRITE; 255 sym->flags |= SYMBOL_WRITE;
225 sym_calc_value(prop->def); 256 if (sym_has_value(sym))
226 newval = prop->def->curr; 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);
262 }
263 newval.tri = E_OR(E_AND(newval.tri, sym->visible), sym->rev_dep.tri);
264 } else if (!sym_is_choice(sym)) {
265 prop = sym_get_default_prop(sym);
266 if (prop) {
267 sym->flags |= SYMBOL_WRITE;
268 newval.tri = expr_calc_value(prop->expr);
269 }
227 } 270 }
228 } 271 if (sym_get_type(sym) == S_BOOLEAN) {
229 272 if (newval.tri == mod)
230 switch (sym_get_type(sym)) { 273 newval.tri = yes;
231 case S_TRISTATE: 274 if (sym->visible == mod)
232 if (S_TRI(newval) != mod) 275 sym->visible = yes;
233 break; 276 if (sym->rev_dep.tri == mod)
234 sym_calc_value(modules_sym); 277 sym->rev_dep.tri = yes;
235 if (S_TRI(modules_sym->curr) == no)
236 S_TRI(newval) = yes;
237 break;
238 case S_BOOLEAN:
239 if (S_TRI(newval) == mod)
240 S_TRI(newval) = yes;
241 }
242
243out:
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 } 278 }
253 if (!def_sym) { 279 break;
254 for_all_defaults(sym, def_prop) { 280 case S_STRING:
255 if (E_CALC(def_prop->visible) == no) 281 case S_HEX:
256 continue; 282 case S_INT:
257 sym_calc_visibility(def_prop->def); 283 if (sym->visible != no) {
258 if (def_prop->def->visible != no) { 284 sym->flags |= SYMBOL_WRITE;
259 def_sym = def_prop->def; 285 if (sym_has_value(sym)) {
260 break; 286 newval.val = sym->user.val;
261 } 287 break;
262 } 288 }
263 } 289 }
264 290 prop = sym_get_default_prop(sym);
265 if (!def_sym) { 291 if (prop) {
266 prop = sym_get_choice_prop(sym); 292 struct symbol *ds = prop_get_symbol(prop);
267 for (e = prop->dep; e; e = e->left.expr) { 293 if (ds) {
268 sym_calc_visibility(e->right.sym); 294 sym->flags |= SYMBOL_WRITE;
269 if (e->right.sym->visible != no) { 295 sym_calc_value(ds);
270 def_sym = e->right.sym; 296 newval.val = ds->curr.val;
271 break;
272 }
273 } 297 }
274 } 298 }
275 299 break;
276 S_VAL(newval) = def_sym; 300 default:
301 ;
277 } 302 }
278 303
279 if (memcmp(&oldval, &newval, sizeof(newval)))
280 sym_set_changed(sym);
281 sym->curr = newval; 304 sym->curr = newval;
305 if (sym_is_choice(sym) && newval.tri == yes)
306 sym->curr.val = sym_calc_choice(sym);
307
308 if (memcmp(&oldval, &sym->curr, sizeof(oldval)))
309 sym_set_changed(sym);
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}
293 321
294void sym_clear_all_valid(void) 322void sym_clear_all_valid(void)
295{ 323{
296 struct symbol *sym; 324 struct symbol *sym;
297 int i; 325 int i;
298 326
299 for_all_symbols(i, sym) 327 for_all_symbols(i, sym)
300 sym->flags &= ~SYMBOL_VALID; 328 sym->flags &= ~SYMBOL_VALID;
301 sym_change_count++; 329 sym_change_count++;
302} 330}
303 331
304void sym_set_changed(struct symbol *sym) 332void sym_set_changed(struct symbol *sym)
305{ 333{
306 struct property *prop; 334 struct property *prop;
307 335
308 sym->flags |= SYMBOL_CHANGED; 336 sym->flags |= SYMBOL_CHANGED;
309 for (prop = sym->prop; prop; prop = prop->next) { 337 for (prop = sym->prop; prop; prop = prop->next) {
310 if (prop->menu) 338 if (prop->menu)
311 prop->menu->flags |= MENU_CHANGED; 339 prop->menu->flags |= MENU_CHANGED;
312 } 340 }
313} 341}
314 342
315void sym_set_all_changed(void) 343void sym_set_all_changed(void)
316{ 344{
317 struct symbol *sym; 345 struct symbol *sym;
318 int i; 346 int i;
319 347
320 for_all_symbols(i, sym) 348 for_all_symbols(i, sym)
321 sym_set_changed(sym); 349 sym_set_changed(sym);
322} 350}
323 351
324bool sym_tristate_within_range(struct symbol *sym, tristate val) 352bool sym_tristate_within_range(struct symbol *sym, tristate val)
325{ 353{
326 int type = sym_get_type(sym); 354 int type = sym_get_type(sym);
327 355
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: 363 return false;
336 if (sym_is_choice_value(sym) && sym->visible == yes) 364 if (sym->visible <= sym->rev_dep.tri)
337 return false; 365 return false;
338 return sym_is_optional(sym); 366 if (sym_is_choice_value(sym) && sym->visible == yes)
339 case mod: 367 return val == yes;
340 if (sym_is_choice_value(sym) && sym->visible == yes) 368 return val >= sym->rev_dep.tri && val <= sym->visible;
341 return false;
342 return type == S_TRISTATE;
343 case yes:
344 return type == S_BOOLEAN || sym->visible == yes;
345 }
346 return false;
347} 369}
348 370
349bool sym_set_tristate_value(struct symbol *sym, tristate val) 371bool 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
353 if (oldval != val && !sym_tristate_within_range(sym, val)) 375 if (oldval != val && !sym_tristate_within_range(sym, val))
354 return false; 376 return false;
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
374 return true; 396 return true;
375} 397}
376 398
377tristate sym_toggle_tristate_value(struct symbol *sym) 399tristate sym_toggle_tristate_value(struct symbol *sym)
378{ 400{
379 tristate oldval, newval; 401 tristate oldval, newval;
380 402
381 oldval = newval = sym_get_tristate_value(sym); 403 oldval = newval = sym_get_tristate_value(sym);
382 do { 404 do {
383 switch (newval) { 405 switch (newval) {
384 case no: 406 case no:
385 newval = mod; 407 newval = mod;
386 break; 408 break;
387 case mod: 409 case mod:
388 newval = yes; 410 newval = yes;
389 break; 411 break;
390 case yes: 412 case yes:
391 newval = no; 413 newval = no;
@@ -408,150 +430,176 @@ bool sym_string_valid(struct symbol *sym, const char *str)
408 ch = *str++; 430 ch = *str++;
409 if (ch == '-') 431 if (ch == '-')
410 ch = *str++; 432 ch = *str++;
411 if (!isdigit(ch)) 433 if (!isdigit(ch))
412 return false; 434 return false;
413 if (ch == '0' && *str != 0) 435 if (ch == '0' && *str != 0)
414 return false; 436 return false;
415 while ((ch = *str++)) { 437 while ((ch = *str++)) {
416 if (!isdigit(ch)) 438 if (!isdigit(ch))
417 return false; 439 return false;
418 } 440 }
419 return true; 441 return true;
420 case S_HEX: 442 case S_HEX:
421 if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) 443 if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
422 str += 2; 444 str += 2;
423 ch = *str++; 445 ch = *str++;
424 do { 446 do {
425 if (!isxdigit(ch)) 447 if (!isxdigit(ch))
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
465bool 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 }
446} 505}
447 506
448bool sym_set_string_value(struct symbol *sym, const char *newval) 507bool sym_set_string_value(struct symbol *sym, const char *newval)
449{ 508{
450 const char *oldval; 509 const char *oldval;
451 char *val; 510 char *val;
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();
496 552
497 return true; 553 return true;
498} 554}
499 555
500const char *sym_get_string_value(struct symbol *sym) 556const char *sym_get_string_value(struct symbol *sym)
501{ 557{
502 tristate val; 558 tristate val;
503 559
504 switch (sym->type) { 560 switch (sym->type) {
505 case S_BOOLEAN: 561 case S_BOOLEAN:
506 case S_TRISTATE: 562 case S_TRISTATE:
507 val = sym_get_tristate_value(sym); 563 val = sym_get_tristate_value(sym);
508 switch (val) { 564 switch (val) {
509 case no: 565 case no:
510 return "n"; 566 return "n";
511 case mod: 567 case mod:
512 return "m"; 568 return "m";
513 case yes: 569 case yes:
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
523bool sym_is_changable(struct symbol *sym) 579bool 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
536struct symbol *sym_lookup(const char *name, int isconst) 584struct 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;
540 char *new_name; 588 char *new_name;
541 int hash = 0; 589 int hash = 0;
542 590
543 if (name) { 591 if (name) {
544 if (name[0] && !name[1]) { 592 if (name[0] && !name[1]) {
545 switch (name[0]) { 593 switch (name[0]) {
546 case 'y': return &symbol_yes; 594 case 'y': return &symbol_yes;
547 case 'm': return &symbol_mod; 595 case 'm': return &symbol_mod;
548 case 'n': return &symbol_no; 596 case 'n': return &symbol_no;
549 } 597 }
550 } 598 }
551 for (ptr = name; *ptr; ptr++) 599 for (ptr = name; *ptr; ptr++)
552 hash += *ptr; 600 hash += *ptr;
553 hash &= 0xff; 601 hash &= 0xff;
554 602
555 for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) { 603 for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
556 if (!strcmp(symbol->name, name)) { 604 if (!strcmp(symbol->name, name)) {
557 if ((isconst && symbol->flags & SYMBOL_CONST) || 605 if ((isconst && symbol->flags & SYMBOL_CONST) ||
@@ -587,43 +635,144 @@ struct symbol *sym_find(const char *name)
587 635
588 if (!name) 636 if (!name)
589 return NULL; 637 return NULL;
590 638
591 if (name[0] && !name[1]) { 639 if (name[0] && !name[1]) {
592 switch (name[0]) { 640 switch (name[0]) {
593 case 'y': return &symbol_yes; 641 case 'y': return &symbol_yes;
594 case 'm': return &symbol_mod; 642 case 'm': return &symbol_mod;
595 case 'n': return &symbol_no; 643 case 'n': return &symbol_no;
596 } 644 }
597 } 645 }
598 for (ptr = name; *ptr; ptr++) 646 for (ptr = name; *ptr; ptr++)
599 hash += *ptr; 647 hash += *ptr;
600 hash &= 0xff; 648 hash &= 0xff;
601 649
602 for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) { 650 for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
603 if (!strcmp(symbol->name, name) && 651 if (!strcmp(symbol->name, name) &&
604 !(symbol->flags & SYMBOL_CONST)) 652 !(symbol->flags & SYMBOL_CONST))
605 break; 653 break;
606 } 654 }
607 655
608 return symbol; 656 return symbol;
609} 657}
610 658
659struct symbol *sym_check_deps(struct symbol *sym);
660
661static 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
691struct 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 }
720out:
721 if (sym2)
722 printf(" %s", sym->name);
723 sym->flags &= ~SYMBOL_CHECK;
724 return sym2;
725}
726
727struct 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
749struct 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
611const char *prop_get_type_name(enum prop_type type) 757const 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}