base/config/kconfig/symbol.c

Go to the documentation of this file.
00001 /* 00002 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> 00003 * Released under the terms of the GNU GPL v2.0. 00004 */ 00005 00006 #include <ctype.h> 00007 #include <stdlib.h> 00008 #include <string.h> 00009 #include <sys/utsname.h> 00010 00011 #define LKC_DIRECT_LINK 00012 #include "lkc.h" 00013 00014 struct symbol symbol_yes = { 00015 .name = "y", 00016 .curr = { "y", yes }, 00017 .flags = SYMBOL_YES|SYMBOL_VALID, 00018 }, symbol_mod = { 00019 .name = "m", 00020 .curr = { "m", mod }, 00021 .flags = SYMBOL_MOD|SYMBOL_VALID, 00022 }, symbol_no = { 00023 .name = "n", 00024 .curr = { "n", no }, 00025 .flags = SYMBOL_NO|SYMBOL_VALID, 00026 }, symbol_empty = { 00027 .name = "", 00028 .curr = { "", no }, 00029 .flags = SYMBOL_VALID, 00030 }; 00031 00032 int sym_change_count; 00033 struct symbol *modules_sym; 00034 00035 void sym_add_default(struct symbol *sym, const char *def) 00036 { 00037 struct property *prop = prop_alloc(P_DEFAULT, sym); 00038 00039 prop->expr = expr_alloc_symbol(sym_lookup(def, 1)); 00040 } 00041 00042 void sym_init(void) 00043 { 00044 struct symbol *sym; 00045 struct utsname uts; 00046 char *p; 00047 static bool inited = false; 00048 00049 if (inited) 00050 return; 00051 inited = true; 00052 00053 uname(&uts); 00054 00055 sym = sym_lookup("ARCH", 0); 00056 sym->type = S_STRING; 00057 sym->flags |= SYMBOL_AUTO; 00058 p = getenv("ARCH"); 00059 if (p) 00060 sym_add_default(sym, p); 00061 00062 sym = sym_lookup("KERNELRELEASE", 0); 00063 sym->type = S_STRING; 00064 sym->flags |= SYMBOL_AUTO; 00065 p = getenv("KERNELRELEASE"); 00066 if (p) 00067 sym_add_default(sym, p); 00068 00069 sym = sym_lookup("UNAME_RELEASE", 0); 00070 sym->type = S_STRING; 00071 sym->flags |= SYMBOL_AUTO; 00072 sym_add_default(sym, uts.release); 00073 } 00074 00075 enum symbol_type sym_get_type(struct symbol *sym) 00076 { 00077 enum symbol_type type = sym->type; 00078 00079 if (type == S_TRISTATE) { 00080 if (sym_is_choice_value(sym) && sym->visible == yes) 00081 type = S_BOOLEAN; 00082 else { 00083 sym_calc_value(modules_sym); 00084 if (modules_sym->curr.tri == no) 00085 type = S_BOOLEAN; 00086 } 00087 } 00088 return type; 00089 } 00090 00091 const char *sym_type_name(enum symbol_type type) 00092 { 00093 switch (type) { 00094 case S_BOOLEAN: 00095 return "boolean"; 00096 case S_TRISTATE: 00097 return "tristate"; 00098 case S_INT: 00099 return "integer"; 00100 case S_HEX: 00101 return "hex"; 00102 case S_STRING: 00103 return "string"; 00104 case S_UNKNOWN: 00105 return "unknown"; 00106 case S_OTHER: 00107 break; 00108 } 00109 return "???"; 00110 } 00111 00112 struct property *sym_get_choice_prop(struct symbol *sym) 00113 { 00114 struct property *prop; 00115 00116 for_all_choices(sym, prop) 00117 return prop; 00118 return NULL; 00119 } 00120 00121 struct property *sym_get_default_prop(struct symbol *sym) 00122 { 00123 struct property *prop; 00124 00125 for_all_defaults(sym, prop) { 00126 prop->visible.tri = expr_calc_value(prop->visible.expr); 00127 if (prop->visible.tri != no) 00128 return prop; 00129 } 00130 return NULL; 00131 } 00132 00133 struct property *sym_get_range_prop(struct symbol *sym) 00134 { 00135 struct property *prop; 00136 00137 for_all_properties(sym, prop, P_RANGE) { 00138 prop->visible.tri = expr_calc_value(prop->visible.expr); 00139 if (prop->visible.tri != no) 00140 return prop; 00141 } 00142 return NULL; 00143 } 00144 00145 static void sym_calc_visibility(struct symbol *sym) 00146 { 00147 struct property *prop; 00148 tristate tri; 00149 00150 /* any prompt visible? */ 00151 tri = no; 00152 for_all_prompts(sym, prop) { 00153 prop->visible.tri = expr_calc_value(prop->visible.expr); 00154 tri = E_OR(tri, prop->visible.tri); 00155 } 00156 if (sym->visible != tri) { 00157 sym->visible = tri; 00158 sym_set_changed(sym); 00159 } 00160 if (sym_is_choice_value(sym)) 00161 return; 00162 tri = no; 00163 if (sym->rev_dep.expr) 00164 tri = expr_calc_value(sym->rev_dep.expr); 00165 if (sym->rev_dep.tri != tri) { 00166 sym->rev_dep.tri = tri; 00167 sym_set_changed(sym); 00168 } 00169 } 00170 00171 static struct symbol *sym_calc_choice(struct symbol *sym) 00172 { 00173 struct symbol *def_sym; 00174 struct property *prop; 00175 struct expr *e; 00176 00177 /* is the user choice visible? */ 00178 def_sym = sym->user.val; 00179 if (def_sym) { 00180 sym_calc_visibility(def_sym); 00181 if (def_sym->visible != no) 00182 return def_sym; 00183 } 00184 00185 /* any of the defaults visible? */ 00186 for_all_defaults(sym, prop) { 00187 prop->visible.tri = expr_calc_value(prop->visible.expr); 00188 if (prop->visible.tri == no) 00189 continue; 00190 def_sym = prop_get_symbol(prop); 00191 sym_calc_visibility(def_sym); 00192 if (def_sym->visible != no) 00193 return def_sym; 00194 } 00195 00196 /* just get the first visible value */ 00197 prop = sym_get_choice_prop(sym); 00198 for (e = prop->expr; e; e = e->left.expr) { 00199 def_sym = e->right.sym; 00200 sym_calc_visibility(def_sym); 00201 if (def_sym->visible != no) 00202 return def_sym; 00203 } 00204 00205 /* no choice? reset tristate value */ 00206 sym->curr.tri = no; 00207 return NULL; 00208 } 00209 00210 void sym_calc_value(struct symbol *sym) 00211 { 00212 struct symbol_value newval, oldval; 00213 struct property *prop; 00214 struct expr *e; 00215 00216 if (!sym) 00217 return; 00218 00219 if (sym->flags & SYMBOL_VALID) 00220 return; 00221 sym->flags |= SYMBOL_VALID; 00222 00223 oldval = sym->curr; 00224 00225 switch (sym->type) { 00226 case S_INT: 00227 case S_HEX: 00228 case S_STRING: 00229 newval = symbol_empty.curr; 00230 break; 00231 case S_BOOLEAN: 00232 case S_TRISTATE: 00233 newval = symbol_no.curr; 00234 break; 00235 default: 00236 sym->curr.val = sym->name; 00237 sym->curr.tri = no; 00238 return; 00239 } 00240 if (!sym_is_choice_value(sym)) 00241 sym->flags &= ~SYMBOL_WRITE; 00242 00243 sym_calc_visibility(sym); 00244 00245 /* set default if recursively called */ 00246 sym->curr = newval; 00247 00248 switch (sym_get_type(sym)) { 00249 case S_BOOLEAN: 00250 case S_TRISTATE: 00251 if (sym_is_choice_value(sym) && sym->visible == yes) { 00252 prop = sym_get_choice_prop(sym); 00253 newval.tri = (prop_get_symbol(prop)->curr.val == sym) ? yes : no; 00254 } else if (E_OR(sym->visible, sym->rev_dep.tri) != no) { 00255 sym->flags |= SYMBOL_WRITE; 00256 if (sym_has_value(sym)) 00257 newval.tri = sym->user.tri; 00258 else if (!sym_is_choice(sym)) { 00259 prop = sym_get_default_prop(sym); 00260 if (prop) 00261 newval.tri = expr_calc_value(prop->expr); 00262 } 00263 newval.tri = E_OR(E_AND(newval.tri, sym->visible), sym->rev_dep.tri); 00264 } else if (!sym_is_choice(sym)) { 00265 prop = sym_get_default_prop(sym); 00266 if (prop) { 00267 sym->flags |= SYMBOL_WRITE; 00268 newval.tri = expr_calc_value(prop->expr); 00269 } 00270 } 00271 if (sym_get_type(sym) == S_BOOLEAN) { 00272 if (newval.tri == mod) 00273 newval.tri = yes; 00274 if (sym->visible == mod) 00275 sym->visible = yes; 00276 if (sym->rev_dep.tri == mod) 00277 sym->rev_dep.tri = yes; 00278 } 00279 break; 00280 case S_STRING: 00281 case S_HEX: 00282 case S_INT: 00283 if (sym->visible != no) { 00284 sym->flags |= SYMBOL_WRITE; 00285 if (sym_has_value(sym)) { 00286 newval.val = sym->user.val; 00287 break; 00288 } 00289 } 00290 prop = sym_get_default_prop(sym); 00291 if (prop) { 00292 struct symbol *ds = prop_get_symbol(prop); 00293 if (ds) { 00294 sym->flags |= SYMBOL_WRITE; 00295 sym_calc_value(ds); 00296 newval.val = ds->curr.val; 00297 } 00298 } 00299 break; 00300 default: 00301 ; 00302 } 00303 00304 sym->curr = newval; 00305 if (sym_is_choice(sym) && newval.tri == yes) 00306 sym->curr.val = sym_calc_choice(sym); 00307 00308 if (memcmp(&oldval, &sym->curr, sizeof(oldval))) 00309 sym_set_changed(sym); 00310 00311 if (sym_is_choice(sym)) { 00312 int flags = sym->flags & (SYMBOL_CHANGED | SYMBOL_WRITE); 00313 prop = sym_get_choice_prop(sym); 00314 for (e = prop->expr; e; e = e->left.expr) { 00315 e->right.sym->flags |= flags; 00316 if (flags & SYMBOL_CHANGED) 00317 sym_set_changed(e->right.sym); 00318 } 00319 } 00320 } 00321 00322 void sym_clear_all_valid(void) 00323 { 00324 struct symbol *sym; 00325 int i; 00326 00327 for_all_symbols(i, sym) 00328 sym->flags &= ~SYMBOL_VALID; 00329 sym_change_count++; 00330 } 00331 00332 void sym_set_changed(struct symbol *sym) 00333 { 00334 struct property *prop; 00335 00336 sym->flags |= SYMBOL_CHANGED; 00337 for (prop = sym->prop; prop; prop = prop->next) { 00338 if (prop->menu) 00339 prop->menu->flags |= MENU_CHANGED; 00340 } 00341 } 00342 00343 void sym_set_all_changed(void) 00344 { 00345 struct symbol *sym; 00346 int i; 00347 00348 for_all_symbols(i, sym) 00349 sym_set_changed(sym); 00350 } 00351 00352 bool sym_tristate_within_range(struct symbol *sym, tristate val) 00353 { 00354 int type = sym_get_type(sym); 00355 00356 if (sym->visible == no) 00357 return false; 00358 00359 if (type != S_BOOLEAN && type != S_TRISTATE) 00360 return false; 00361 00362 if (type == S_BOOLEAN && val == mod) 00363 return false; 00364 if (sym->visible <= sym->rev_dep.tri) 00365 return false; 00366 if (sym_is_choice_value(sym) && sym->visible == yes) 00367 return val == yes; 00368 return val >= sym->rev_dep.tri && val <= sym->visible; 00369 } 00370 00371 bool sym_set_tristate_value(struct symbol *sym, tristate val) 00372 { 00373 tristate oldval = sym_get_tristate_value(sym); 00374 00375 if (oldval != val && !sym_tristate_within_range(sym, val)) 00376 return false; 00377 00378 if (sym->flags & SYMBOL_NEW) { 00379 sym->flags &= ~SYMBOL_NEW; 00380 sym_set_changed(sym); 00381 } 00382 if (sym_is_choice_value(sym) && val == yes) { 00383 struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym)); 00384 00385 cs->user.val = sym; 00386 cs->flags &= ~SYMBOL_NEW; 00387 } 00388 00389 sym->user.tri = val; 00390 if (oldval != val) { 00391 sym_clear_all_valid(); 00392 if (sym == modules_sym) 00393 sym_set_all_changed(); 00394 } 00395 00396 return true; 00397 } 00398 00399 tristate sym_toggle_tristate_value(struct symbol *sym) 00400 { 00401 tristate oldval, newval; 00402 00403 oldval = newval = sym_get_tristate_value(sym); 00404 do { 00405 switch (newval) { 00406 case no: 00407 newval = mod; 00408 break; 00409 case mod: 00410 newval = yes; 00411 break; 00412 case yes: 00413 newval = no; 00414 break; 00415 } 00416 if (sym_set_tristate_value(sym, newval)) 00417 break; 00418 } while (oldval != newval); 00419 return newval; 00420 } 00421 00422 bool sym_string_valid(struct symbol *sym, const char *str) 00423 { 00424 char ch; 00425 00426 switch (sym->type) { 00427 case S_STRING: 00428 return true; 00429 case S_INT: 00430 ch = *str++; 00431 if (ch == '-') 00432 ch = *str++; 00433 if (!isdigit(ch)) 00434 return false; 00435 if (ch == '0' && *str != 0) 00436 return false; 00437 while ((ch = *str++)) { 00438 if (!isdigit(ch)) 00439 return false; 00440 } 00441 return true; 00442 case S_HEX: 00443 if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) 00444 str += 2; 00445 ch = *str++; 00446 do { 00447 if (!isxdigit(ch)) 00448 return false; 00449 } while ((ch = *str++)); 00450 return true; 00451 case S_BOOLEAN: 00452 case S_TRISTATE: 00453 switch (str[0]) { 00454 case 'y': case 'Y': 00455 case 'm': case 'M': 00456 case 'n': case 'N': 00457 return true; 00458 } 00459 return false; 00460 default: 00461 return false; 00462 } 00463 } 00464 00465 bool sym_string_within_range(struct symbol *sym, const char *str) 00466 { 00467 struct property *prop; 00468 int val; 00469 00470 switch (sym->type) { 00471 case S_STRING: 00472 return sym_string_valid(sym, str); 00473 case S_INT: 00474 if (!sym_string_valid(sym, str)) 00475 return false; 00476 prop = sym_get_range_prop(sym); 00477 if (!prop) 00478 return true; 00479 val = strtol(str, NULL, 10); 00480 return val >= strtol(prop->expr->left.sym->name, NULL, 10) && 00481 val <= strtol(prop->expr->right.sym->name, NULL, 10); 00482 case S_HEX: 00483 if (!sym_string_valid(sym, str)) 00484 return false; 00485 prop = sym_get_range_prop(sym); 00486 if (!prop) 00487 return true; 00488 val = strtol(str, NULL, 16); 00489 return val >= strtol(prop->expr->left.sym->name, NULL, 16) && 00490 val <= strtol(prop->expr->right.sym->name, NULL, 16); 00491 case S_BOOLEAN: 00492 case S_TRISTATE: 00493 switch (str[0]) { 00494 case 'y': case 'Y': 00495 return sym_tristate_within_range(sym, yes); 00496 case 'm': case 'M': 00497 return sym_tristate_within_range(sym, mod); 00498 case 'n': case 'N': 00499 return sym_tristate_within_range(sym, no); 00500 } 00501 return false; 00502 default: 00503 return false; 00504 } 00505 } 00506 00507 bool sym_set_string_value(struct symbol *sym, const char *newval) 00508 { 00509 const char *oldval; 00510 char *val; 00511 int size; 00512 00513 switch (sym->type) { 00514 case S_BOOLEAN: 00515 case S_TRISTATE: 00516 switch (newval[0]) { 00517 case 'y': case 'Y': 00518 return sym_set_tristate_value(sym, yes); 00519 case 'm': case 'M': 00520 return sym_set_tristate_value(sym, mod); 00521 case 'n': case 'N': 00522 return sym_set_tristate_value(sym, no); 00523 } 00524 return false; 00525 default: 00526 ; 00527 } 00528 00529 if (!sym_string_within_range(sym, newval)) 00530 return false; 00531 00532 if (sym->flags & SYMBOL_NEW) { 00533 sym->flags &= ~SYMBOL_NEW; 00534 sym_set_changed(sym); 00535 } 00536 00537 oldval = sym->user.val; 00538 size = strlen(newval) + 1; 00539 if (sym->type == S_HEX && (newval[0] != '0' || (newval[1] != 'x' && newval[1] != 'X'))) { 00540 size += 2; 00541 sym->user.val = val = malloc(size); 00542 *val++ = '0'; 00543 *val++ = 'x'; 00544 } else if (!oldval || strcmp(oldval, newval)) 00545 sym->user.val = val = malloc(size); 00546 else 00547 return true; 00548 00549 strcpy(val, newval); 00550 free((void *)oldval); 00551 sym_clear_all_valid(); 00552 00553 return true; 00554 } 00555 00556 const char *sym_get_string_value(struct symbol *sym) 00557 { 00558 tristate val; 00559 00560 switch (sym->type) { 00561 case S_BOOLEAN: 00562 case S_TRISTATE: 00563 val = sym_get_tristate_value(sym); 00564 switch (val) { 00565 case no: 00566 return "n"; 00567 case mod: 00568 return "m"; 00569 case yes: 00570 return "y"; 00571 } 00572 break; 00573 default: 00574 ; 00575 } 00576 return (const char *)sym->curr.val; 00577 } 00578 00579 bool sym_is_changable(struct symbol *sym) 00580 { 00581 return sym->visible > sym->rev_dep.tri; 00582 } 00583 00584 struct symbol *sym_lookup(const char *name, int isconst) 00585 { 00586 struct symbol *symbol; 00587 const char *ptr; 00588 char *new_name; 00589 int hash = 0; 00590 00591 if (name) { 00592 if (name[0] && !name[1]) { 00593 switch (name[0]) { 00594 case 'y': return &symbol_yes; 00595 case 'm': return &symbol_mod; 00596 case 'n': return &symbol_no; 00597 } 00598 } 00599 for (ptr = name; *ptr; ptr++) 00600 hash += *ptr; 00601 hash &= 0xff; 00602 00603 for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) { 00604 if (!strcmp(symbol->name, name)) { 00605 if ((isconst && symbol->flags & SYMBOL_CONST) || 00606 (!isconst && !(symbol->flags & SYMBOL_CONST))) 00607 return symbol; 00608 } 00609 } 00610 new_name = strdup(name); 00611 } else { 00612 new_name = NULL; 00613 hash = 256; 00614 } 00615 00616 symbol = malloc(sizeof(*symbol)); 00617 memset(symbol, 0, sizeof(*symbol)); 00618 symbol->name = new_name; 00619 symbol->type = S_UNKNOWN; 00620 symbol->flags = SYMBOL_NEW; 00621 if (isconst) 00622 symbol->flags |= SYMBOL_CONST; 00623 00624 symbol->next = symbol_hash[hash]; 00625 symbol_hash[hash] = symbol; 00626 00627 return symbol; 00628 } 00629 00630 struct symbol *sym_find(const char *name) 00631 { 00632 struct symbol *symbol = NULL; 00633 const char *ptr; 00634 int hash = 0; 00635 00636 if (!name) 00637 return NULL; 00638 00639 if (name[0] && !name[1]) { 00640 switch (name[0]) { 00641 case 'y': return &symbol_yes; 00642 case 'm': return &symbol_mod; 00643 case 'n': return &symbol_no; 00644 } 00645 } 00646 for (ptr = name; *ptr; ptr++) 00647 hash += *ptr; 00648 hash &= 0xff; 00649 00650 for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) { 00651 if (!strcmp(symbol->name, name) && 00652 !(symbol->flags & SYMBOL_CONST)) 00653 break; 00654 } 00655 00656 return symbol; 00657 } 00658 00659 struct symbol *sym_check_deps(struct symbol *sym); 00660 00661 static struct symbol *sym_check_expr_deps(struct expr *e) 00662 { 00663 struct symbol *sym; 00664 00665 if (!e) 00666 return NULL; 00667 switch (e->type) { 00668 case E_OR: 00669 case E_AND: 00670 sym = sym_check_expr_deps(e->left.expr); 00671 if (sym) 00672 return sym; 00673 return sym_check_expr_deps(e->right.expr); 00674 case E_NOT: 00675 return sym_check_expr_deps(e->left.expr); 00676 case E_EQUAL: 00677 case E_UNEQUAL: 00678 sym = sym_check_deps(e->left.sym); 00679 if (sym) 00680 return sym; 00681 return sym_check_deps(e->right.sym); 00682 case E_SYMBOL: 00683 return sym_check_deps(e->left.sym); 00684 default: 00685 break; 00686 } 00687 printf("Oops! How to check %d?\n", e->type); 00688 return NULL; 00689 } 00690 00691 struct symbol *sym_check_deps(struct symbol *sym) 00692 { 00693 struct symbol *sym2; 00694 struct property *prop; 00695 00696 if (sym->flags & SYMBOL_CHECK_DONE) 00697 return NULL; 00698 if (sym->flags & SYMBOL_CHECK) { 00699 printf("Warning! Found recursive dependency: %s", sym->name); 00700 return sym; 00701 } 00702 00703 sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED); 00704 sym2 = sym_check_expr_deps(sym->rev_dep.expr); 00705 if (sym2) 00706 goto out; 00707 00708 for (prop = sym->prop; prop; prop = prop->next) { 00709 if (prop->type == P_CHOICE) 00710 continue; 00711 sym2 = sym_check_expr_deps(prop->visible.expr); 00712 if (sym2) 00713 goto out; 00714 if (prop->type != P_DEFAULT || sym_is_choice(sym)) 00715 continue; 00716 sym2 = sym_check_expr_deps(prop->expr); 00717 if (sym2) 00718 goto out; 00719 } 00720 out: 00721 if (sym2) 00722 printf(" %s", sym->name); 00723 sym->flags &= ~SYMBOL_CHECK; 00724 return sym2; 00725 } 00726 00727 struct property *prop_alloc(enum prop_type type, struct symbol *sym) 00728 { 00729 struct property *prop; 00730 struct property **propp; 00731 00732 prop = malloc(sizeof(*prop)); 00733 memset(prop, 0, sizeof(*prop)); 00734 prop->type = type; 00735 prop->sym = sym; 00736 prop->file = current_file; 00737 prop->lineno = zconf_lineno(); 00738 00739 /* append property to the prop list of symbol */ 00740 if (sym) { 00741 for (propp = &sym->prop; *propp; propp = &(*propp)->next) 00742 ; 00743 *propp = prop; 00744 } 00745 00746 return prop; 00747 } 00748 00749 struct symbol *prop_get_symbol(struct property *prop) 00750 { 00751 if (prop->expr && (prop->expr->type == E_SYMBOL || 00752 prop->expr->type == E_CHOICE)) 00753 return prop->expr->left.sym; 00754 return NULL; 00755 } 00756 00757 const char *prop_get_type_name(enum prop_type type) 00758 { 00759 switch (type) { 00760 case P_PROMPT: 00761 return "prompt"; 00762 case P_COMMENT: 00763 return "comment"; 00764 case P_MENU: 00765 return "menu"; 00766 case P_DEFAULT: 00767 return "default"; 00768 case P_CHOICE: 00769 return "choice"; 00770 case P_SELECT: 00771 return "select"; 00772 case P_RANGE: 00773 return "range"; 00774 case P_UNKNOWN: 00775 break; 00776 } 00777 return "unknown"; 00778 }

Generated on Thu Nov 20 11:49:48 2008 for RTAI API by doxygen 1.3.8