1 /* 2 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> 3 * Released under the terms of the GNU GPL v2.0. 4 */ 5 6 #include <ctype.h> 7 #include <stdlib.h> 8 #include <string.h> 9 #include <regex.h> 10 #include <sys/utsname.h> 11 12 #include "lkc.h" 13 14 struct symbol symbol_yes = { 15 .name = "y", 16 .curr = { "y", yes }, 17 .flags = SYMBOL_CONST|SYMBOL_VALID, 18 }, symbol_mod = { 19 .name = "m", 20 .curr = { "m", mod }, 21 .flags = SYMBOL_CONST|SYMBOL_VALID, 22 }, symbol_no = { 23 .name = "n", 24 .curr = { "n", no }, 25 .flags = SYMBOL_CONST|SYMBOL_VALID, 26 }, symbol_empty = { 27 .name = "", 28 .curr = { "", no }, 29 .flags = SYMBOL_VALID, 30 }; 31 32 struct symbol *sym_defconfig_list; 33 struct symbol *modules_sym; 34 tristate modules_val; 35 36 struct expr *sym_env_list; 37 38 static void sym_add_default(struct symbol *sym, const char *def) 39 { 40 struct property *prop = prop_alloc(P_DEFAULT, sym); 41 42 prop->expr = expr_alloc_symbol(sym_lookup(def, SYMBOL_CONST)); 43 } 44 45 void sym_init(void) 46 { 47 struct symbol *sym; 48 struct utsname uts; 49 static bool inited = false; 50 51 if (inited) 52 return; 53 inited = true; 54 55 uname(&uts); 56 57 sym = sym_lookup("UNAME_RELEASE", 0); 58 sym->type = S_STRING; 59 sym->flags |= SYMBOL_AUTO; 60 sym_add_default(sym, uts.release); 61 } 62 63 enum symbol_type sym_get_type(struct symbol *sym) 64 { 65 enum symbol_type type = sym->type; 66 67 if (type == S_TRISTATE) { 68 if (sym_is_choice_value(sym) && sym->visible == yes) 69 type = S_BOOLEAN; 70 else if (modules_val == no) 71 type = S_BOOLEAN; 72 } 73 return type; 74 } 75 76 const char *sym_type_name(enum symbol_type type) 77 { 78 switch (type) { 79 case S_BOOLEAN: 80 return "boolean"; 81 case S_TRISTATE: 82 return "tristate"; 83 case S_INT: 84 return "integer"; 85 case S_HEX: 86 return "hex"; 87 case S_STRING: 88 return "string"; 89 case S_UNKNOWN: 90 return "unknown"; 91 case S_OTHER: 92 break; 93 } 94 return "???"; 95 } 96 97 struct property *sym_get_choice_prop(struct symbol *sym) 98 { 99 struct property *prop; 100 101 for_all_choices(sym, prop) 102 return prop; 103 return NULL; 104 } 105 106 struct property *sym_get_env_prop(struct symbol *sym) 107 { 108 struct property *prop; 109 110 for_all_properties(sym, prop, P_ENV) 111 return prop; 112 return NULL; 113 } 114 115 struct property *sym_get_default_prop(struct symbol *sym) 116 { 117 struct property *prop; 118 119 for_all_defaults(sym, prop) { 120 prop->visible.tri = expr_calc_value(prop->visible.expr); 121 if (prop->visible.tri != no) 122 return prop; 123 } 124 return NULL; 125 } 126 127 static struct property *sym_get_range_prop(struct symbol *sym) 128 { 129 struct property *prop; 130 131 for_all_properties(sym, prop, P_RANGE) { 132 prop->visible.tri = expr_calc_value(prop->visible.expr); 133 if (prop->visible.tri != no) 134 return prop; 135 } 136 return NULL; 137 } 138 139 static int sym_get_range_val(struct symbol *sym, int base) 140 { 141 sym_calc_value(sym); 142 switch (sym->type) { 143 case S_INT: 144 base = 10; 145 break; 146 case S_HEX: 147 base = 16; 148 break; 149 default: 150 break; 151 } 152 return strtol(sym->curr.val, NULL, base); 153 } 154 155 static void sym_validate_range(struct symbol *sym) 156 { 157 struct property *prop; 158 int base, val, val2; 159 char str[64]; 160 161 switch (sym->type) { 162 case S_INT: 163 base = 10; 164 break; 165 case S_HEX: 166 base = 16; 167 break; 168 default: 169 return; 170 } 171 prop = sym_get_range_prop(sym); 172 if (!prop) 173 return; 174 val = strtol(sym->curr.val, NULL, base); 175 val2 = sym_get_range_val(prop->expr->left.sym, base); 176 if (val >= val2) { 177 val2 = sym_get_range_val(prop->expr->right.sym, base); 178 if (val <= val2) 179 return; 180 } 181 if (sym->type == S_INT) 182 sprintf(str, "%d", val2); 183 else 184 sprintf(str, "0x%x", val2); 185 sym->curr.val = strdup(str); 186 } 187 188 static void sym_calc_visibility(struct symbol *sym) 189 { 190 struct property *prop; 191 tristate tri; 192 193 /* any prompt visible? */ 194 tri = no; 195 for_all_prompts(sym, prop) { 196 prop->visible.tri = expr_calc_value(prop->visible.expr); 197 tri = EXPR_OR(tri, prop->visible.tri); 198 } 199 if (tri == mod && (sym->type != S_TRISTATE || modules_val == no)) 200 tri = yes; 201 if (sym->visible != tri) { 202 sym->visible = tri; 203 sym_set_changed(sym); 204 } 205 if (sym_is_choice_value(sym)) 206 return; 207 /* defaulting to "yes" if no explicit "depends on" are given */ 208 tri = yes; 209 if (sym->dir_dep.expr) 210 tri = expr_calc_value(sym->dir_dep.expr); 211 if (tri == mod) 212 tri = yes; 213 if (sym->dir_dep.tri != tri) { 214 sym->dir_dep.tri = tri; 215 sym_set_changed(sym); 216 } 217 tri = no; 218 if (sym->rev_dep.expr) 219 tri = expr_calc_value(sym->rev_dep.expr); 220 if (tri == mod && sym_get_type(sym) == S_BOOLEAN) 221 tri = yes; 222 if (sym->rev_dep.tri != tri) { 223 sym->rev_dep.tri = tri; 224 sym_set_changed(sym); 225 } 226 } 227 228 /* 229 * Find the default symbol for a choice. 230 * First try the default values for the choice symbol 231 * Next locate the first visible choice value 232 * Return NULL if none was found 233 */ 234 struct symbol *sym_choice_default(struct symbol *sym) 235 { 236 struct symbol *def_sym; 237 struct property *prop; 238 struct expr *e; 239 240 /* any of the defaults visible? */ 241 for_all_defaults(sym, prop) { 242 prop->visible.tri = expr_calc_value(prop->visible.expr); 243 if (prop->visible.tri == no) 244 continue; 245 def_sym = prop_get_symbol(prop); 246 if (def_sym->visible != no) 247 return def_sym; 248 } 249 250 /* just get the first visible value */ 251 prop = sym_get_choice_prop(sym); 252 expr_list_for_each_sym(prop->expr, e, def_sym) 253 if (def_sym->visible != no) 254 return def_sym; 255 256 /* failed to locate any defaults */ 257 return NULL; 258 } 259 260 static struct symbol *sym_calc_choice(struct symbol *sym) 261 { 262 struct symbol *def_sym; 263 struct property *prop; 264 struct expr *e; 265 int flags; 266 267 /* first calculate all choice values' visibilities */ 268 flags = sym->flags; 269 prop = sym_get_choice_prop(sym); 270 expr_list_for_each_sym(prop->expr, e, def_sym) { 271 sym_calc_visibility(def_sym); 272 if (def_sym->visible != no) 273 flags &= def_sym->flags; 274 } 275 276 sym->flags &= flags | ~SYMBOL_DEF_USER; 277 278 /* is the user choice visible? */ 279 def_sym = sym->def[S_DEF_USER].val; 280 if (def_sym && def_sym->visible != no) 281 return def_sym; 282 283 def_sym = sym_choice_default(sym); 284 285 if (def_sym == NULL) 286 /* no choice? reset tristate value */ 287 sym->curr.tri = no; 288 289 return def_sym; 290 } 291 292 void sym_calc_value(struct symbol *sym) 293 { 294 struct symbol_value newval, oldval; 295 struct property *prop; 296 struct expr *e; 297 298 if (!sym) 299 return; 300 301 if (sym->flags & SYMBOL_VALID) 302 return; 303 sym->flags |= SYMBOL_VALID; 304 305 oldval = sym->curr; 306 307 switch (sym->type) { 308 case S_INT: 309 case S_HEX: 310 case S_STRING: 311 newval = symbol_empty.curr; 312 break; 313 case S_BOOLEAN: 314 case S_TRISTATE: 315 newval = symbol_no.curr; 316 break; 317 default: 318 sym->curr.val = sym->name; 319 sym->curr.tri = no; 320 return; 321 } 322 if (!sym_is_choice_value(sym)) 323 sym->flags &= ~SYMBOL_WRITE; 324 325 sym_calc_visibility(sym); 326 327 /* set default if recursively called */ 328 sym->curr = newval; 329 330 switch (sym_get_type(sym)) { 331 case S_BOOLEAN: 332 case S_TRISTATE: 333 if (sym_is_choice_value(sym) && sym->visible == yes) { 334 prop = sym_get_choice_prop(sym); 335 newval.tri = (prop_get_symbol(prop)->curr.val == sym) ? yes : no; 336 } else { 337 if (sym->visible != no) { 338 /* if the symbol is visible use the user value 339 * if available, otherwise try the default value 340 */ 341 sym->flags |= SYMBOL_WRITE; 342 if (sym_has_value(sym)) { 343 newval.tri = EXPR_AND(sym->def[S_DEF_USER].tri, 344 sym->visible); 345 goto calc_newval; 346 } 347 } 348 if (sym->rev_dep.tri != no) 349 sym->flags |= SYMBOL_WRITE; 350 if (!sym_is_choice(sym)) { 351 prop = sym_get_default_prop(sym); 352 if (prop) { 353 sym->flags |= SYMBOL_WRITE; 354 newval.tri = EXPR_AND(expr_calc_value(prop->expr), 355 prop->visible.tri); 356 } 357 } 358 calc_newval: 359 if (sym->dir_dep.tri == no && sym->rev_dep.tri != no) { 360 struct expr *e; 361 e = expr_simplify_unmet_dep(sym->rev_dep.expr, 362 sym->dir_dep.expr); 363 fprintf(stderr, "warning: ("); 364 expr_fprint(e, stderr); 365 fprintf(stderr, ") selects %s which has unmet direct dependencies (", 366 sym->name); 367 expr_fprint(sym->dir_dep.expr, stderr); 368 fprintf(stderr, ")\n"); 369 expr_free(e); 370 } 371 newval.tri = EXPR_OR(newval.tri, sym->rev_dep.tri); 372 } 373 if (newval.tri == mod && sym_get_type(sym) == S_BOOLEAN) 374 newval.tri = yes; 375 break; 376 case S_STRING: 377 case S_HEX: 378 case S_INT: 379 if (sym->visible != no) { 380 sym->flags |= SYMBOL_WRITE; 381 if (sym_has_value(sym)) { 382 newval.val = sym->def[S_DEF_USER].val; 383 break; 384 } 385 } 386 prop = sym_get_default_prop(sym); 387 if (prop) { 388 struct symbol *ds = prop_get_symbol(prop); 389 if (ds) { 390 sym->flags |= SYMBOL_WRITE; 391 sym_calc_value(ds); 392 newval.val = ds->curr.val; 393 } 394 } 395 break; 396 default: 397 ; 398 } 399 400 sym->curr = newval; 401 if (sym_is_choice(sym) && newval.tri == yes) 402 sym->curr.val = sym_calc_choice(sym); 403 sym_validate_range(sym); 404 405 if (memcmp(&oldval, &sym->curr, sizeof(oldval))) { 406 sym_set_changed(sym); 407 if (modules_sym == sym) { 408 sym_set_all_changed(); 409 modules_val = modules_sym->curr.tri; 410 } 411 } 412 413 if (sym_is_choice(sym)) { 414 struct symbol *choice_sym; 415 416 prop = sym_get_choice_prop(sym); 417 expr_list_for_each_sym(prop->expr, e, choice_sym) { 418 if ((sym->flags & SYMBOL_WRITE) && 419 choice_sym->visible != no) 420 choice_sym->flags |= SYMBOL_WRITE; 421 if (sym->flags & SYMBOL_CHANGED) 422 sym_set_changed(choice_sym); 423 } 424 } 425 426 if (sym->flags & SYMBOL_AUTO) 427 sym->flags &= ~SYMBOL_WRITE; 428 } 429 430 void sym_clear_all_valid(void) 431 { 432 struct symbol *sym; 433 int i; 434 435 for_all_symbols(i, sym) 436 sym->flags &= ~SYMBOL_VALID; 437 sym_add_change_count(1); 438 if (modules_sym) 439 sym_calc_value(modules_sym); 440 } 441 442 void sym_set_changed(struct symbol *sym) 443 { 444 struct property *prop; 445 446 sym->flags |= SYMBOL_CHANGED; 447 for (prop = sym->prop; prop; prop = prop->next) { 448 if (prop->menu) 449 prop->menu->flags |= MENU_CHANGED; 450 } 451 } 452 453 void sym_set_all_changed(void) 454 { 455 struct symbol *sym; 456 int i; 457 458 for_all_symbols(i, sym) 459 sym_set_changed(sym); 460 } 461 462 bool sym_tristate_within_range(struct symbol *sym, tristate val) 463 { 464 int type = sym_get_type(sym); 465 466 if (sym->visible == no) 467 return false; 468 469 if (type != S_BOOLEAN && type != S_TRISTATE) 470 return false; 471 472 if (type == S_BOOLEAN && val == mod) 473 return false; 474 if (sym->visible <= sym->rev_dep.tri) 475 return false; 476 if (sym_is_choice_value(sym) && sym->visible == yes) 477 return val == yes; 478 return val >= sym->rev_dep.tri && val <= sym->visible; 479 } 480 481 bool sym_set_tristate_value(struct symbol *sym, tristate val) 482 { 483 tristate oldval = sym_get_tristate_value(sym); 484 485 if (oldval != val && !sym_tristate_within_range(sym, val)) 486 return false; 487 488 if (!(sym->flags & SYMBOL_DEF_USER)) { 489 sym->flags |= SYMBOL_DEF_USER; 490 sym_set_changed(sym); 491 } 492 /* 493 * setting a choice value also resets the new flag of the choice 494 * symbol and all other choice values. 495 */ 496 if (sym_is_choice_value(sym) && val == yes) { 497 struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym)); 498 struct property *prop; 499 struct expr *e; 500 501 cs->def[S_DEF_USER].val = sym; 502 cs->flags |= SYMBOL_DEF_USER; 503 prop = sym_get_choice_prop(cs); 504 for (e = prop->expr; e; e = e->left.expr) { 505 if (e->right.sym->visible != no) 506 e->right.sym->flags |= SYMBOL_DEF_USER; 507 } 508 } 509 510 sym->def[S_DEF_USER].tri = val; 511 if (oldval != val) 512 sym_clear_all_valid(); 513 514 return true; 515 } 516 517 tristate sym_toggle_tristate_value(struct symbol *sym) 518 { 519 tristate oldval, newval; 520 521 oldval = newval = sym_get_tristate_value(sym); 522 do { 523 switch (newval) { 524 case no: 525 newval = mod; 526 break; 527 case mod: 528 newval = yes; 529 break; 530 case yes: 531 newval = no; 532 break; 533 } 534 if (sym_set_tristate_value(sym, newval)) 535 break; 536 } while (oldval != newval); 537 return newval; 538 } 539 540 bool sym_string_valid(struct symbol *sym, const char *str) 541 { 542 signed char ch; 543 544 switch (sym->type) { 545 case S_STRING: 546 return true; 547 case S_INT: 548 ch = *str++; 549 if (ch == '-') 550 ch = *str++; 551 if (!isdigit(ch)) 552 return false; 553 if (ch == '0' && *str != 0) 554 return false; 555 while ((ch = *str++)) { 556 if (!isdigit(ch)) 557 return false; 558 } 559 return true; 560 case S_HEX: 561 if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) 562 str += 2; 563 ch = *str++; 564 do { 565 if (!isxdigit(ch)) 566 return false; 567 } while ((ch = *str++)); 568 return true; 569 case S_BOOLEAN: 570 case S_TRISTATE: 571 switch (str[0]) { 572 case 'y': case 'Y': 573 case 'm': case 'M': 574 case 'n': case 'N': 575 return true; 576 } 577 return false; 578 default: 579 return false; 580 } 581 } 582 583 bool sym_string_within_range(struct symbol *sym, const char *str) 584 { 585 struct property *prop; 586 int val; 587 588 switch (sym->type) { 589 case S_STRING: 590 return sym_string_valid(sym, str); 591 case S_INT: 592 if (!sym_string_valid(sym, str)) 593 return false; 594 prop = sym_get_range_prop(sym); 595 if (!prop) 596 return true; 597 val = strtol(str, NULL, 10); 598 return val >= sym_get_range_val(prop->expr->left.sym, 10) && 599 val <= sym_get_range_val(prop->expr->right.sym, 10); 600 case S_HEX: 601 if (!sym_string_valid(sym, str)) 602 return false; 603 prop = sym_get_range_prop(sym); 604 if (!prop) 605 return true; 606 val = strtol(str, NULL, 16); 607 return val >= sym_get_range_val(prop->expr->left.sym, 16) && 608 val <= sym_get_range_val(prop->expr->right.sym, 16); 609 case S_BOOLEAN: 610 case S_TRISTATE: 611 switch (str[0]) { 612 case 'y': case 'Y': 613 return sym_tristate_within_range(sym, yes); 614 case 'm': case 'M': 615 return sym_tristate_within_range(sym, mod); 616 case 'n': case 'N': 617 return sym_tristate_within_range(sym, no); 618 } 619 return false; 620 default: 621 return false; 622 } 623 } 624 625 bool sym_set_string_value(struct symbol *sym, const char *newval) 626 { 627 const char *oldval; 628 char *val; 629 int size; 630 631 switch (sym->type) { 632 case S_BOOLEAN: 633 case S_TRISTATE: 634 switch (newval[0]) { 635 case 'y': case 'Y': 636 return sym_set_tristate_value(sym, yes); 637 case 'm': case 'M': 638 return sym_set_tristate_value(sym, mod); 639 case 'n': case 'N': 640 return sym_set_tristate_value(sym, no); 641 } 642 return false; 643 default: 644 ; 645 } 646 647 if (!sym_string_within_range(sym, newval)) 648 return false; 649 650 if (!(sym->flags & SYMBOL_DEF_USER)) { 651 sym->flags |= SYMBOL_DEF_USER; 652 sym_set_changed(sym); 653 } 654 655 oldval = sym->def[S_DEF_USER].val; 656 size = strlen(newval) + 1; 657 if (sym->type == S_HEX && (newval[0] != '0' || (newval[1] != 'x' && newval[1] != 'X'))) { 658 size += 2; 659 sym->def[S_DEF_USER].val = val = xmalloc(size); 660 *val++ = '0'; 661 *val++ = 'x'; 662 } else if (!oldval || strcmp(oldval, newval)) 663 sym->def[S_DEF_USER].val = val = xmalloc(size); 664 else 665 return true; 666 667 strcpy(val, newval); 668 free((void *)oldval); 669 sym_clear_all_valid(); 670 671 return true; 672 } 673 674 /* 675 * Find the default value associated to a symbol. 676 * For tristate symbol handle the modules=n case 677 * in which case "m" becomes "y". 678 * If the symbol does not have any default then fallback 679 * to the fixed default values. 680 */ 681 const char *sym_get_string_default(struct symbol *sym) 682 { 683 struct property *prop; 684 struct symbol *ds; 685 const char *str; 686 tristate val; 687 688 sym_calc_visibility(sym); 689 sym_calc_value(modules_sym); 690 val = symbol_no.curr.tri; 691 str = symbol_empty.curr.val; 692 693 /* If symbol has a default value look it up */ 694 prop = sym_get_default_prop(sym); 695 if (prop != NULL) { 696 switch (sym->type) { 697 case S_BOOLEAN: 698 case S_TRISTATE: 699 /* The visibility may limit the value from yes => mod */ 700 val = EXPR_AND(expr_calc_value(prop->expr), prop->visible.tri); 701 break; 702 default: 703 /* 704 * The following fails to handle the situation 705 * where a default value is further limited by 706 * the valid range. 707 */ 708 ds = prop_get_symbol(prop); 709 if (ds != NULL) { 710 sym_calc_value(ds); 711 str = (const char *)ds->curr.val; 712 } 713 } 714 } 715 716 /* Handle select statements */ 717 val = EXPR_OR(val, sym->rev_dep.tri); 718 719 /* transpose mod to yes if modules are not enabled */ 720 if (val == mod) 721 if (!sym_is_choice_value(sym) && modules_sym->curr.tri == no) 722 val = yes; 723 724 /* transpose mod to yes if type is bool */ 725 if (sym->type == S_BOOLEAN && val == mod) 726 val = yes; 727 728 switch (sym->type) { 729 case S_BOOLEAN: 730 case S_TRISTATE: 731 switch (val) { 732 case no: return "n"; 733 case mod: return "m"; 734 case yes: return "y"; 735 } 736 case S_INT: 737 case S_HEX: 738 return str; 739 case S_STRING: 740 return str; 741 case S_OTHER: 742 case S_UNKNOWN: 743 break; 744 } 745 return ""; 746 } 747 748 const char *sym_get_string_value(struct symbol *sym) 749 { 750 tristate val; 751 752 switch (sym->type) { 753 case S_BOOLEAN: 754 case S_TRISTATE: 755 val = sym_get_tristate_value(sym); 756 switch (val) { 757 case no: 758 return "n"; 759 case mod: 760 sym_calc_value(modules_sym); 761 return (modules_sym->curr.tri == no) ? "n" : "m"; 762 case yes: 763 return "y"; 764 } 765 break; 766 default: 767 ; 768 } 769 return (const char *)sym->curr.val; 770 } 771 772 bool sym_is_changable(struct symbol *sym) 773 { 774 return sym->visible > sym->rev_dep.tri; 775 } 776 777 static unsigned strhash(const char *s) 778 { 779 /* fnv32 hash */ 780 unsigned hash = 2166136261U; 781 for (; *s; s++) 782 hash = (hash ^ *s) * 0x01000193; 783 return hash; 784 } 785 786 struct symbol *sym_lookup(const char *name, int flags) 787 { 788 struct symbol *symbol; 789 char *new_name; 790 int hash; 791 792 if (name) { 793 if (name[0] && !name[1]) { 794 switch (name[0]) { 795 case 'y': return &symbol_yes; 796 case 'm': return &symbol_mod; 797 case 'n': return &symbol_no; 798 } 799 } 800 hash = strhash(name) % SYMBOL_HASHSIZE; 801 802 for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) { 803 if (symbol->name && 804 !strcmp(symbol->name, name) && 805 (flags ? symbol->flags & flags 806 : !(symbol->flags & (SYMBOL_CONST|SYMBOL_CHOICE)))) 807 return symbol; 808 } 809 new_name = strdup(name); 810 } else { 811 new_name = NULL; 812 hash = 0; 813 } 814 815 symbol = xmalloc(sizeof(*symbol)); 816 memset(symbol, 0, sizeof(*symbol)); 817 symbol->name = new_name; 818 symbol->type = S_UNKNOWN; 819 symbol->flags |= flags; 820 821 symbol->next = symbol_hash[hash]; 822 symbol_hash[hash] = symbol; 823 824 return symbol; 825 } 826 827 struct symbol *sym_find(const char *name) 828 { 829 struct symbol *symbol = NULL; 830 int hash = 0; 831 832 if (!name) 833 return NULL; 834 835 if (name[0] && !name[1]) { 836 switch (name[0]) { 837 case 'y': return &symbol_yes; 838 case 'm': return &symbol_mod; 839 case 'n': return &symbol_no; 840 } 841 } 842 hash = strhash(name) % SYMBOL_HASHSIZE; 843 844 for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) { 845 if (symbol->name && 846 !strcmp(symbol->name, name) && 847 !(symbol->flags & SYMBOL_CONST)) 848 break; 849 } 850 851 return symbol; 852 } 853 854 /* 855 * Expand symbol's names embedded in the string given in argument. Symbols' 856 * name to be expanded shall be prefixed by a '$'. Unknown symbol expands to 857 * the empty string. 858 */ 859 const char *sym_expand_string_value(const char *in) 860 { 861 const char *src; 862 char *res; 863 size_t reslen; 864 865 reslen = strlen(in) + 1; 866 res = xmalloc(reslen); 867 res[0] = '\0'; 868 869 while ((src = strchr(in, '$'))) { 870 char *p, name[SYMBOL_MAXLENGTH]; 871 const char *symval = ""; 872 struct symbol *sym; 873 size_t newlen; 874 875 strncat(res, in, src - in); 876 src++; 877 878 p = name; 879 while (isalnum(*src) || *src == '_') 880 *p++ = *src++; 881 *p = '\0'; 882 883 sym = sym_find(name); 884 if (sym != NULL) { 885 sym_calc_value(sym); 886 symval = sym_get_string_value(sym); 887 } 888 889 newlen = strlen(res) + strlen(symval) + strlen(src) + 1; 890 if (newlen > reslen) { 891 reslen = newlen; 892 res = realloc(res, reslen); 893 } 894 895 strcat(res, symval); 896 in = src; 897 } 898 strcat(res, in); 899 900 return res; 901 } 902 903 const char *sym_escape_string_value(const char *in) 904 { 905 const char *p; 906 size_t reslen; 907 char *res; 908 size_t l; 909 910 reslen = strlen(in) + strlen("\"\"") + 1; 911 912 p = in; 913 for (;;) { 914 l = strcspn(p, "\"\\"); 915 p += l; 916 917 if (p[0] == '\0') 918 break; 919 920 reslen++; 921 p++; 922 } 923 924 res = xmalloc(reslen); 925 res[0] = '\0'; 926 927 strcat(res, "\""); 928 929 p = in; 930 for (;;) { 931 l = strcspn(p, "\"\\"); 932 strncat(res, p, l); 933 p += l; 934 935 if (p[0] == '\0') 936 break; 937 938 strcat(res, "\\"); 939 strncat(res, p++, 1); 940 } 941 942 strcat(res, "\""); 943 return res; 944 } 945 946 struct symbol **sym_re_search(const char *pattern) 947 { 948 struct symbol *sym, **sym_arr = NULL; 949 int i, cnt, size; 950 regex_t re; 951 952 cnt = size = 0; 953 /* Skip if empty */ 954 if (strlen(pattern) == 0) 955 return NULL; 956 if (regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB|REG_ICASE)) 957 return NULL; 958 959 for_all_symbols(i, sym) { 960 if (sym->flags & SYMBOL_CONST || !sym->name) 961 continue; 962 if (regexec(&re, sym->name, 0, NULL, 0)) 963 continue; 964 if (cnt + 1 >= size) { 965 void *tmp = sym_arr; 966 size += 16; 967 sym_arr = realloc(sym_arr, size * sizeof(struct symbol *)); 968 if (!sym_arr) { 969 free(tmp); 970 return NULL; 971 } 972 } 973 sym_calc_value(sym); 974 sym_arr[cnt++] = sym; 975 } 976 if (sym_arr) 977 sym_arr[cnt] = NULL; 978 regfree(&re); 979 980 return sym_arr; 981 } 982 983 /* 984 * When we check for recursive dependencies we use a stack to save 985 * current state so we can print out relevant info to user. 986 * The entries are located on the call stack so no need to free memory. 987 * Note inser() remove() must always match to properly clear the stack. 988 */ 989 static struct dep_stack { 990 struct dep_stack *prev, *next; 991 struct symbol *sym; 992 struct property *prop; 993 struct expr *expr; 994 } *check_top; 995 996 static void dep_stack_insert(struct dep_stack *stack, struct symbol *sym) 997 { 998 memset(stack, 0, sizeof(*stack)); 999 if (check_top) 1000 check_top->next = stack; 1001 stack->prev = check_top; 1002 stack->sym = sym; 1003 check_top = stack; 1004 } 1005 1006 static void dep_stack_remove(void) 1007 { 1008 check_top = check_top->prev; 1009 if (check_top) 1010 check_top->next = NULL; 1011 } 1012 1013 /* 1014 * Called when we have detected a recursive dependency. 1015 * check_top point to the top of the stact so we use 1016 * the ->prev pointer to locate the bottom of the stack. 1017 */ 1018 static void sym_check_print_recursive(struct symbol *last_sym) 1019 { 1020 struct dep_stack *stack; 1021 struct symbol *sym, *next_sym; 1022 struct menu *menu = NULL; 1023 struct property *prop; 1024 struct dep_stack cv_stack; 1025 1026 if (sym_is_choice_value(last_sym)) { 1027 dep_stack_insert(&cv_stack, last_sym); 1028 last_sym = prop_get_symbol(sym_get_choice_prop(last_sym)); 1029 } 1030 1031 for (stack = check_top; stack != NULL; stack = stack->prev) 1032 if (stack->sym == last_sym) 1033 break; 1034 if (!stack) { 1035 fprintf(stderr, "unexpected recursive dependency error\n"); 1036 return; 1037 } 1038 1039 for (; stack; stack = stack->next) { 1040 sym = stack->sym; 1041 next_sym = stack->next ? stack->next->sym : last_sym; 1042 prop = stack->prop; 1043 if (prop == NULL) 1044 prop = stack->sym->prop; 1045 1046 /* for choice values find the menu entry (used below) */ 1047 if (sym_is_choice(sym) || sym_is_choice_value(sym)) { 1048 for (prop = sym->prop; prop; prop = prop->next) { 1049 menu = prop->menu; 1050 if (prop->menu) 1051 break; 1052 } 1053 } 1054 if (stack->sym == last_sym) 1055 fprintf(stderr, "%s:%d:error: recursive dependency detected!\n", 1056 prop->file->name, prop->lineno); 1057 if (stack->expr) { 1058 fprintf(stderr, "%s:%d:\tsymbol %s %s value contains %s\n", 1059 prop->file->name, prop->lineno, 1060 sym->name ? sym->name : "<choice>", 1061 prop_get_type_name(prop->type), 1062 next_sym->name ? next_sym->name : "<choice>"); 1063 } else if (stack->prop) { 1064 fprintf(stderr, "%s:%d:\tsymbol %s depends on %s\n", 1065 prop->file->name, prop->lineno, 1066 sym->name ? sym->name : "<choice>", 1067 next_sym->name ? next_sym->name : "<choice>"); 1068 } else if (sym_is_choice(sym)) { 1069 fprintf(stderr, "%s:%d:\tchoice %s contains symbol %s\n", 1070 menu->file->name, menu->lineno, 1071 sym->name ? sym->name : "<choice>", 1072 next_sym->name ? next_sym->name : "<choice>"); 1073 } else if (sym_is_choice_value(sym)) { 1074 fprintf(stderr, "%s:%d:\tsymbol %s is part of choice %s\n", 1075 menu->file->name, menu->lineno, 1076 sym->name ? sym->name : "<choice>", 1077 next_sym->name ? next_sym->name : "<choice>"); 1078 } else { 1079 fprintf(stderr, "%s:%d:\tsymbol %s is selected by %s\n", 1080 prop->file->name, prop->lineno, 1081 sym->name ? sym->name : "<choice>", 1082 next_sym->name ? next_sym->name : "<choice>"); 1083 } 1084 } 1085 1086 if (check_top == &cv_stack) 1087 dep_stack_remove(); 1088 } 1089 1090 static struct symbol *sym_check_expr_deps(struct expr *e) 1091 { 1092 struct symbol *sym; 1093 1094 if (!e) 1095 return NULL; 1096 switch (e->type) { 1097 case E_OR: 1098 case E_AND: 1099 sym = sym_check_expr_deps(e->left.expr); 1100 if (sym) 1101 return sym; 1102 return sym_check_expr_deps(e->right.expr); 1103 case E_NOT: 1104 return sym_check_expr_deps(e->left.expr); 1105 case E_EQUAL: 1106 case E_UNEQUAL: 1107 sym = sym_check_deps(e->left.sym); 1108 if (sym) 1109 return sym; 1110 return sym_check_deps(e->right.sym); 1111 case E_SYMBOL: 1112 return sym_check_deps(e->left.sym); 1113 default: 1114 break; 1115 } 1116 printf("Oops! How to check %d?\n", e->type); 1117 return NULL; 1118 } 1119 1120 /* return NULL when dependencies are OK */ 1121 static struct symbol *sym_check_sym_deps(struct symbol *sym) 1122 { 1123 struct symbol *sym2; 1124 struct property *prop; 1125 struct dep_stack stack; 1126 1127 dep_stack_insert(&stack, sym); 1128 1129 sym2 = sym_check_expr_deps(sym->rev_dep.expr); 1130 if (sym2) 1131 goto out; 1132 1133 for (prop = sym->prop; prop; prop = prop->next) { 1134 if (prop->type == P_CHOICE || prop->type == P_SELECT) 1135 continue; 1136 stack.prop = prop; 1137 sym2 = sym_check_expr_deps(prop->visible.expr); 1138 if (sym2) 1139 break; 1140 if (prop->type != P_DEFAULT || sym_is_choice(sym)) 1141 continue; 1142 stack.expr = prop->expr; 1143 sym2 = sym_check_expr_deps(prop->expr); 1144 if (sym2) 1145 break; 1146 stack.expr = NULL; 1147 } 1148 1149 out: 1150 dep_stack_remove(); 1151 1152 return sym2; 1153 } 1154 1155 static struct symbol *sym_check_choice_deps(struct symbol *choice) 1156 { 1157 struct symbol *sym, *sym2; 1158 struct property *prop; 1159 struct expr *e; 1160 struct dep_stack stack; 1161 1162 dep_stack_insert(&stack, choice); 1163 1164 prop = sym_get_choice_prop(choice); 1165 expr_list_for_each_sym(prop->expr, e, sym) 1166 sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED); 1167 1168 choice->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED); 1169 sym2 = sym_check_sym_deps(choice); 1170 choice->flags &= ~SYMBOL_CHECK; 1171 if (sym2) 1172 goto out; 1173 1174 expr_list_for_each_sym(prop->expr, e, sym) { 1175 sym2 = sym_check_sym_deps(sym); 1176 if (sym2) 1177 break; 1178 } 1179 out: 1180 expr_list_for_each_sym(prop->expr, e, sym) 1181 sym->flags &= ~SYMBOL_CHECK; 1182 1183 if (sym2 && sym_is_choice_value(sym2) && 1184 prop_get_symbol(sym_get_choice_prop(sym2)) == choice) 1185 sym2 = choice; 1186 1187 dep_stack_remove(); 1188 1189 return sym2; 1190 } 1191 1192 struct symbol *sym_check_deps(struct symbol *sym) 1193 { 1194 struct symbol *sym2; 1195 struct property *prop; 1196 1197 if (sym->flags & SYMBOL_CHECK) { 1198 sym_check_print_recursive(sym); 1199 return sym; 1200 } 1201 if (sym->flags & SYMBOL_CHECKED) 1202 return NULL; 1203 1204 if (sym_is_choice_value(sym)) { 1205 struct dep_stack stack; 1206 1207 /* for choice groups start the check with main choice symbol */ 1208 dep_stack_insert(&stack, sym); 1209 prop = sym_get_choice_prop(sym); 1210 sym2 = sym_check_deps(prop_get_symbol(prop)); 1211 dep_stack_remove(); 1212 } else if (sym_is_choice(sym)) { 1213 sym2 = sym_check_choice_deps(sym); 1214 } else { 1215 sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED); 1216 sym2 = sym_check_sym_deps(sym); 1217 sym->flags &= ~SYMBOL_CHECK; 1218 } 1219 1220 if (sym2 && sym2 == sym) 1221 sym2 = NULL; 1222 1223 return sym2; 1224 } 1225 1226 struct property *prop_alloc(enum prop_type type, struct symbol *sym) 1227 { 1228 struct property *prop; 1229 struct property **propp; 1230 1231 prop = xmalloc(sizeof(*prop)); 1232 memset(prop, 0, sizeof(*prop)); 1233 prop->type = type; 1234 prop->sym = sym; 1235 prop->file = current_file; 1236 prop->lineno = zconf_lineno(); 1237 1238 /* append property to the prop list of symbol */ 1239 if (sym) { 1240 for (propp = &sym->prop; *propp; propp = &(*propp)->next) 1241 ; 1242 *propp = prop; 1243 } 1244 1245 return prop; 1246 } 1247 1248 struct symbol *prop_get_symbol(struct property *prop) 1249 { 1250 if (prop->expr && (prop->expr->type == E_SYMBOL || 1251 prop->expr->type == E_LIST)) 1252 return prop->expr->left.sym; 1253 return NULL; 1254 } 1255 1256 const char *prop_get_type_name(enum prop_type type) 1257 { 1258 switch (type) { 1259 case P_PROMPT: 1260 return "prompt"; 1261 case P_ENV: 1262 return "env"; 1263 case P_COMMENT: 1264 return "comment"; 1265 case P_MENU: 1266 return "menu"; 1267 case P_DEFAULT: 1268 return "default"; 1269 case P_CHOICE: 1270 return "choice"; 1271 case P_SELECT: 1272 return "select"; 1273 case P_RANGE: 1274 return "range"; 1275 case P_SYMBOL: 1276 return "symbol"; 1277 case P_UNKNOWN: 1278 break; 1279 } 1280 return "unknown"; 1281 } 1282 1283 static void prop_add_env(const char *env) 1284 { 1285 struct symbol *sym, *sym2; 1286 struct property *prop; 1287 char *p; 1288 1289 sym = current_entry->sym; 1290 sym->flags |= SYMBOL_AUTO; 1291 for_all_properties(sym, prop, P_ENV) { 1292 sym2 = prop_get_symbol(prop); 1293 if (strcmp(sym2->name, env)) 1294 menu_warn(current_entry, "redefining environment symbol from %s", 1295 sym2->name); 1296 return; 1297 } 1298 1299 prop = prop_alloc(P_ENV, sym); 1300 prop->expr = expr_alloc_symbol(sym_lookup(env, SYMBOL_CONST)); 1301 1302 sym_env_list = expr_alloc_one(E_LIST, sym_env_list); 1303 sym_env_list->right.sym = sym; 1304 1305 p = getenv(env); 1306 if (p) 1307 sym_add_default(sym, p); 1308 else 1309 menu_warn(current_entry, "environment variable %s undefined", env); 1310 } 1311