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