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