diff options
Diffstat (limited to 'scripts/kconfig/symbol.c')
| -rw-r--r-- | scripts/kconfig/symbol.c | 294 |
1 files changed, 261 insertions, 33 deletions
diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c index 2e7a048e0cfc..943712ca6c0a 100644 --- a/scripts/kconfig/symbol.c +++ b/scripts/kconfig/symbol.c | |||
| @@ -205,6 +205,16 @@ static void sym_calc_visibility(struct symbol *sym) | |||
| 205 | } | 205 | } |
| 206 | if (sym_is_choice_value(sym)) | 206 | if (sym_is_choice_value(sym)) |
| 207 | return; | 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 | } | ||
| 208 | tri = no; | 218 | tri = no; |
| 209 | if (sym->rev_dep.expr) | 219 | if (sym->rev_dep.expr) |
| 210 | tri = expr_calc_value(sym->rev_dep.expr); | 220 | tri = expr_calc_value(sym->rev_dep.expr); |
| @@ -216,44 +226,63 @@ static void sym_calc_visibility(struct symbol *sym) | |||
| 216 | } | 226 | } |
| 217 | } | 227 | } |
| 218 | 228 | ||
| 219 | static struct symbol *sym_calc_choice(struct symbol *sym) | 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) | ||
| 220 | { | 236 | { |
| 221 | struct symbol *def_sym; | 237 | struct symbol *def_sym; |
| 222 | struct property *prop; | 238 | struct property *prop; |
| 223 | struct expr *e; | 239 | struct expr *e; |
| 224 | 240 | ||
| 225 | /* is the user choice visible? */ | ||
| 226 | def_sym = sym->def[S_DEF_USER].val; | ||
| 227 | if (def_sym) { | ||
| 228 | sym_calc_visibility(def_sym); | ||
| 229 | if (def_sym->visible != no) | ||
| 230 | return def_sym; | ||
| 231 | } | ||
| 232 | |||
| 233 | /* any of the defaults visible? */ | 241 | /* any of the defaults visible? */ |
| 234 | for_all_defaults(sym, prop) { | 242 | for_all_defaults(sym, prop) { |
| 235 | prop->visible.tri = expr_calc_value(prop->visible.expr); | 243 | prop->visible.tri = expr_calc_value(prop->visible.expr); |
| 236 | if (prop->visible.tri == no) | 244 | if (prop->visible.tri == no) |
| 237 | continue; | 245 | continue; |
| 238 | def_sym = prop_get_symbol(prop); | 246 | def_sym = prop_get_symbol(prop); |
| 239 | sym_calc_visibility(def_sym); | ||
| 240 | if (def_sym->visible != no) | 247 | if (def_sym->visible != no) |
| 241 | return def_sym; | 248 | return def_sym; |
| 242 | } | 249 | } |
| 243 | 250 | ||
| 244 | /* just get the first visible value */ | 251 | /* just get the first visible value */ |
| 245 | prop = sym_get_choice_prop(sym); | 252 | prop = sym_get_choice_prop(sym); |
| 246 | expr_list_for_each_sym(prop->expr, e, def_sym) { | 253 | expr_list_for_each_sym(prop->expr, e, def_sym) |
| 247 | sym_calc_visibility(def_sym); | ||
| 248 | if (def_sym->visible != no) | 254 | if (def_sym->visible != no) |
| 249 | return def_sym; | 255 | return def_sym; |
| 250 | } | ||
| 251 | 256 | ||
| 252 | /* no choice? reset tristate value */ | 257 | /* failed to locate any defaults */ |
| 253 | sym->curr.tri = no; | ||
| 254 | return NULL; | 258 | return NULL; |
| 255 | } | 259 | } |
| 256 | 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 | |||
| 257 | void sym_calc_value(struct symbol *sym) | 286 | void sym_calc_value(struct symbol *sym) |
| 258 | { | 287 | { |
| 259 | struct symbol_value newval, oldval; | 288 | struct symbol_value newval, oldval; |
| @@ -321,6 +350,14 @@ void sym_calc_value(struct symbol *sym) | |||
| 321 | } | 350 | } |
| 322 | } | 351 | } |
| 323 | calc_newval: | 352 | calc_newval: |
| 353 | if (sym->dir_dep.tri == no && sym->rev_dep.tri != no) { | ||
| 354 | fprintf(stderr, "warning: ("); | ||
| 355 | expr_fprint(sym->rev_dep.expr, stderr); | ||
| 356 | fprintf(stderr, ") selects %s which has unmet direct dependencies (", | ||
| 357 | sym->name); | ||
| 358 | expr_fprint(sym->dir_dep.expr, stderr); | ||
| 359 | fprintf(stderr, ")\n"); | ||
| 360 | } | ||
| 324 | newval.tri = EXPR_OR(newval.tri, sym->rev_dep.tri); | 361 | newval.tri = EXPR_OR(newval.tri, sym->rev_dep.tri); |
| 325 | } | 362 | } |
| 326 | if (newval.tri == mod && sym_get_type(sym) == S_BOOLEAN) | 363 | if (newval.tri == mod && sym_get_type(sym) == S_BOOLEAN) |
| @@ -365,12 +402,13 @@ void sym_calc_value(struct symbol *sym) | |||
| 365 | 402 | ||
| 366 | if (sym_is_choice(sym)) { | 403 | if (sym_is_choice(sym)) { |
| 367 | struct symbol *choice_sym; | 404 | struct symbol *choice_sym; |
| 368 | int flags = sym->flags & (SYMBOL_CHANGED | SYMBOL_WRITE); | ||
| 369 | 405 | ||
| 370 | prop = sym_get_choice_prop(sym); | 406 | prop = sym_get_choice_prop(sym); |
| 371 | expr_list_for_each_sym(prop->expr, e, choice_sym) { | 407 | expr_list_for_each_sym(prop->expr, e, choice_sym) { |
| 372 | choice_sym->flags |= flags; | 408 | if ((sym->flags & SYMBOL_WRITE) && |
| 373 | if (flags & SYMBOL_CHANGED) | 409 | choice_sym->visible != no) |
| 410 | choice_sym->flags |= SYMBOL_WRITE; | ||
| 411 | if (sym->flags & SYMBOL_CHANGED) | ||
| 374 | sym_set_changed(choice_sym); | 412 | sym_set_changed(choice_sym); |
| 375 | } | 413 | } |
| 376 | } | 414 | } |
| @@ -623,6 +661,80 @@ bool sym_set_string_value(struct symbol *sym, const char *newval) | |||
| 623 | return true; | 661 | return true; |
| 624 | } | 662 | } |
| 625 | 663 | ||
| 664 | /* | ||
| 665 | * Find the default value associated to a symbol. | ||
| 666 | * For tristate symbol handle the modules=n case | ||
| 667 | * in which case "m" becomes "y". | ||
| 668 | * If the symbol does not have any default then fallback | ||
| 669 | * to the fixed default values. | ||
| 670 | */ | ||
| 671 | const char *sym_get_string_default(struct symbol *sym) | ||
| 672 | { | ||
| 673 | struct property *prop; | ||
| 674 | struct symbol *ds; | ||
| 675 | const char *str; | ||
| 676 | tristate val; | ||
| 677 | |||
| 678 | sym_calc_visibility(sym); | ||
| 679 | sym_calc_value(modules_sym); | ||
| 680 | val = symbol_no.curr.tri; | ||
| 681 | str = symbol_empty.curr.val; | ||
| 682 | |||
| 683 | /* If symbol has a default value look it up */ | ||
| 684 | prop = sym_get_default_prop(sym); | ||
| 685 | if (prop != NULL) { | ||
| 686 | switch (sym->type) { | ||
| 687 | case S_BOOLEAN: | ||
| 688 | case S_TRISTATE: | ||
| 689 | /* The visibility imay limit the value from yes => mod */ | ||
| 690 | val = EXPR_AND(expr_calc_value(prop->expr), prop->visible.tri); | ||
| 691 | break; | ||
| 692 | default: | ||
| 693 | /* | ||
| 694 | * The following fails to handle the situation | ||
| 695 | * where a default value is further limited by | ||
| 696 | * the valid range. | ||
| 697 | */ | ||
| 698 | ds = prop_get_symbol(prop); | ||
| 699 | if (ds != NULL) { | ||
| 700 | sym_calc_value(ds); | ||
| 701 | str = (const char *)ds->curr.val; | ||
| 702 | } | ||
| 703 | } | ||
| 704 | } | ||
| 705 | |||
| 706 | /* Handle select statements */ | ||
| 707 | val = EXPR_OR(val, sym->rev_dep.tri); | ||
| 708 | |||
| 709 | /* transpose mod to yes if modules are not enabled */ | ||
| 710 | if (val == mod) | ||
| 711 | if (!sym_is_choice_value(sym) && modules_sym->curr.tri == no) | ||
| 712 | val = yes; | ||
| 713 | |||
| 714 | /* transpose mod to yes if type is bool */ | ||
| 715 | if (sym->type == S_BOOLEAN && val == mod) | ||
| 716 | val = yes; | ||
| 717 | |||
| 718 | switch (sym->type) { | ||
| 719 | case S_BOOLEAN: | ||
| 720 | case S_TRISTATE: | ||
| 721 | switch (val) { | ||
| 722 | case no: return "n"; | ||
| 723 | case mod: return "m"; | ||
| 724 | case yes: return "y"; | ||
| 725 | } | ||
| 726 | case S_INT: | ||
| 727 | case S_HEX: | ||
| 728 | return str; | ||
| 729 | case S_STRING: | ||
| 730 | return str; | ||
| 731 | case S_OTHER: | ||
| 732 | case S_UNKNOWN: | ||
| 733 | break; | ||
| 734 | } | ||
| 735 | return ""; | ||
| 736 | } | ||
| 737 | |||
| 626 | const char *sym_get_string_value(struct symbol *sym) | 738 | const char *sym_get_string_value(struct symbol *sym) |
| 627 | { | 739 | { |
| 628 | tristate val; | 740 | tristate val; |
| @@ -765,6 +877,112 @@ struct symbol **sym_re_search(const char *pattern) | |||
| 765 | return sym_arr; | 877 | return sym_arr; |
| 766 | } | 878 | } |
| 767 | 879 | ||
| 880 | /* | ||
| 881 | * When we check for recursive dependencies we use a stack to save | ||
| 882 | * current state so we can print out relevant info to user. | ||
| 883 | * The entries are located on the call stack so no need to free memory. | ||
| 884 | * Note inser() remove() must always match to properly clear the stack. | ||
| 885 | */ | ||
| 886 | static struct dep_stack { | ||
| 887 | struct dep_stack *prev, *next; | ||
| 888 | struct symbol *sym; | ||
| 889 | struct property *prop; | ||
| 890 | struct expr *expr; | ||
| 891 | } *check_top; | ||
| 892 | |||
| 893 | static void dep_stack_insert(struct dep_stack *stack, struct symbol *sym) | ||
| 894 | { | ||
| 895 | memset(stack, 0, sizeof(*stack)); | ||
| 896 | if (check_top) | ||
| 897 | check_top->next = stack; | ||
| 898 | stack->prev = check_top; | ||
| 899 | stack->sym = sym; | ||
| 900 | check_top = stack; | ||
| 901 | } | ||
| 902 | |||
| 903 | static void dep_stack_remove(void) | ||
| 904 | { | ||
| 905 | check_top = check_top->prev; | ||
| 906 | if (check_top) | ||
| 907 | check_top->next = NULL; | ||
| 908 | } | ||
| 909 | |||
| 910 | /* | ||
| 911 | * Called when we have detected a recursive dependency. | ||
| 912 | * check_top point to the top of the stact so we use | ||
| 913 | * the ->prev pointer to locate the bottom of the stack. | ||
| 914 | */ | ||
| 915 | static void sym_check_print_recursive(struct symbol *last_sym) | ||
| 916 | { | ||
| 917 | struct dep_stack *stack; | ||
| 918 | struct symbol *sym, *next_sym; | ||
| 919 | struct menu *menu = NULL; | ||
| 920 | struct property *prop; | ||
| 921 | struct dep_stack cv_stack; | ||
| 922 | |||
| 923 | if (sym_is_choice_value(last_sym)) { | ||
| 924 | dep_stack_insert(&cv_stack, last_sym); | ||
| 925 | last_sym = prop_get_symbol(sym_get_choice_prop(last_sym)); | ||
| 926 | } | ||
| 927 | |||
| 928 | for (stack = check_top; stack != NULL; stack = stack->prev) | ||
| 929 | if (stack->sym == last_sym) | ||
| 930 | break; | ||
| 931 | if (!stack) { | ||
| 932 | fprintf(stderr, "unexpected recursive dependency error\n"); | ||
| 933 | return; | ||
| 934 | } | ||
| 935 | |||
| 936 | for (; stack; stack = stack->next) { | ||
| 937 | sym = stack->sym; | ||
| 938 | next_sym = stack->next ? stack->next->sym : last_sym; | ||
| 939 | prop = stack->prop; | ||
| 940 | if (prop == NULL) | ||
| 941 | prop = stack->sym->prop; | ||
| 942 | |||
| 943 | /* for choice values find the menu entry (used below) */ | ||
| 944 | if (sym_is_choice(sym) || sym_is_choice_value(sym)) { | ||
| 945 | for (prop = sym->prop; prop; prop = prop->next) { | ||
| 946 | menu = prop->menu; | ||
| 947 | if (prop->menu) | ||
| 948 | break; | ||
| 949 | } | ||
| 950 | } | ||
| 951 | if (stack->sym == last_sym) | ||
| 952 | fprintf(stderr, "%s:%d:error: recursive dependency detected!\n", | ||
| 953 | prop->file->name, prop->lineno); | ||
| 954 | if (stack->expr) { | ||
| 955 | fprintf(stderr, "%s:%d:\tsymbol %s %s value contains %s\n", | ||
| 956 | prop->file->name, prop->lineno, | ||
| 957 | sym->name ? sym->name : "<choice>", | ||
| 958 | prop_get_type_name(prop->type), | ||
| 959 | next_sym->name ? next_sym->name : "<choice>"); | ||
| 960 | } else if (stack->prop) { | ||
| 961 | fprintf(stderr, "%s:%d:\tsymbol %s depends on %s\n", | ||
| 962 | prop->file->name, prop->lineno, | ||
| 963 | sym->name ? sym->name : "<choice>", | ||
| 964 | next_sym->name ? next_sym->name : "<choice>"); | ||
| 965 | } else if (sym_is_choice(sym)) { | ||
| 966 | fprintf(stderr, "%s:%d:\tchoice %s contains symbol %s\n", | ||
| 967 | menu->file->name, menu->lineno, | ||
| 968 | sym->name ? sym->name : "<choice>", | ||
| 969 | next_sym->name ? next_sym->name : "<choice>"); | ||
| 970 | } else if (sym_is_choice_value(sym)) { | ||
| 971 | fprintf(stderr, "%s:%d:\tsymbol %s is part of choice %s\n", | ||
| 972 | menu->file->name, menu->lineno, | ||
| 973 | sym->name ? sym->name : "<choice>", | ||
| 974 | next_sym->name ? next_sym->name : "<choice>"); | ||
| 975 | } else { | ||
| 976 | fprintf(stderr, "%s:%d:\tsymbol %s is selected by %s\n", | ||
| 977 | prop->file->name, prop->lineno, | ||
| 978 | sym->name ? sym->name : "<choice>", | ||
| 979 | next_sym->name ? next_sym->name : "<choice>"); | ||
| 980 | } | ||
| 981 | } | ||
| 982 | |||
| 983 | if (check_top == &cv_stack) | ||
| 984 | dep_stack_remove(); | ||
| 985 | } | ||
| 768 | 986 | ||
| 769 | static struct symbol *sym_check_expr_deps(struct expr *e) | 987 | static struct symbol *sym_check_expr_deps(struct expr *e) |
| 770 | { | 988 | { |
| @@ -801,24 +1019,33 @@ static struct symbol *sym_check_sym_deps(struct symbol *sym) | |||
| 801 | { | 1019 | { |
| 802 | struct symbol *sym2; | 1020 | struct symbol *sym2; |
| 803 | struct property *prop; | 1021 | struct property *prop; |
| 1022 | struct dep_stack stack; | ||
| 1023 | |||
| 1024 | dep_stack_insert(&stack, sym); | ||
| 804 | 1025 | ||
| 805 | sym2 = sym_check_expr_deps(sym->rev_dep.expr); | 1026 | sym2 = sym_check_expr_deps(sym->rev_dep.expr); |
| 806 | if (sym2) | 1027 | if (sym2) |
| 807 | return sym2; | 1028 | goto out; |
| 808 | 1029 | ||
| 809 | for (prop = sym->prop; prop; prop = prop->next) { | 1030 | for (prop = sym->prop; prop; prop = prop->next) { |
| 810 | if (prop->type == P_CHOICE || prop->type == P_SELECT) | 1031 | if (prop->type == P_CHOICE || prop->type == P_SELECT) |
| 811 | continue; | 1032 | continue; |
| 1033 | stack.prop = prop; | ||
| 812 | sym2 = sym_check_expr_deps(prop->visible.expr); | 1034 | sym2 = sym_check_expr_deps(prop->visible.expr); |
| 813 | if (sym2) | 1035 | if (sym2) |
| 814 | break; | 1036 | break; |
| 815 | if (prop->type != P_DEFAULT || sym_is_choice(sym)) | 1037 | if (prop->type != P_DEFAULT || sym_is_choice(sym)) |
| 816 | continue; | 1038 | continue; |
| 1039 | stack.expr = prop->expr; | ||
| 817 | sym2 = sym_check_expr_deps(prop->expr); | 1040 | sym2 = sym_check_expr_deps(prop->expr); |
| 818 | if (sym2) | 1041 | if (sym2) |
| 819 | break; | 1042 | break; |
| 1043 | stack.expr = NULL; | ||
| 820 | } | 1044 | } |
| 821 | 1045 | ||
| 1046 | out: | ||
| 1047 | dep_stack_remove(); | ||
| 1048 | |||
| 822 | return sym2; | 1049 | return sym2; |
| 823 | } | 1050 | } |
| 824 | 1051 | ||
| @@ -827,6 +1054,9 @@ static struct symbol *sym_check_choice_deps(struct symbol *choice) | |||
| 827 | struct symbol *sym, *sym2; | 1054 | struct symbol *sym, *sym2; |
| 828 | struct property *prop; | 1055 | struct property *prop; |
| 829 | struct expr *e; | 1056 | struct expr *e; |
| 1057 | struct dep_stack stack; | ||
| 1058 | |||
| 1059 | dep_stack_insert(&stack, choice); | ||
| 830 | 1060 | ||
| 831 | prop = sym_get_choice_prop(choice); | 1061 | prop = sym_get_choice_prop(choice); |
| 832 | expr_list_for_each_sym(prop->expr, e, sym) | 1062 | expr_list_for_each_sym(prop->expr, e, sym) |
| @@ -840,10 +1070,8 @@ static struct symbol *sym_check_choice_deps(struct symbol *choice) | |||
| 840 | 1070 | ||
| 841 | expr_list_for_each_sym(prop->expr, e, sym) { | 1071 | expr_list_for_each_sym(prop->expr, e, sym) { |
| 842 | sym2 = sym_check_sym_deps(sym); | 1072 | sym2 = sym_check_sym_deps(sym); |
| 843 | if (sym2) { | 1073 | if (sym2) |
| 844 | fprintf(stderr, " -> %s", sym->name); | ||
| 845 | break; | 1074 | break; |
| 846 | } | ||
| 847 | } | 1075 | } |
| 848 | out: | 1076 | out: |
| 849 | expr_list_for_each_sym(prop->expr, e, sym) | 1077 | expr_list_for_each_sym(prop->expr, e, sym) |
| @@ -853,6 +1081,8 @@ out: | |||
| 853 | prop_get_symbol(sym_get_choice_prop(sym2)) == choice) | 1081 | prop_get_symbol(sym_get_choice_prop(sym2)) == choice) |
| 854 | sym2 = choice; | 1082 | sym2 = choice; |
| 855 | 1083 | ||
| 1084 | dep_stack_remove(); | ||
| 1085 | |||
| 856 | return sym2; | 1086 | return sym2; |
| 857 | } | 1087 | } |
| 858 | 1088 | ||
| @@ -862,18 +1092,20 @@ struct symbol *sym_check_deps(struct symbol *sym) | |||
| 862 | struct property *prop; | 1092 | struct property *prop; |
| 863 | 1093 | ||
| 864 | if (sym->flags & SYMBOL_CHECK) { | 1094 | if (sym->flags & SYMBOL_CHECK) { |
| 865 | fprintf(stderr, "%s:%d:error: found recursive dependency: %s", | 1095 | sym_check_print_recursive(sym); |
| 866 | sym->prop->file->name, sym->prop->lineno, | ||
| 867 | sym->name ? sym->name : "<choice>"); | ||
| 868 | return sym; | 1096 | return sym; |
| 869 | } | 1097 | } |
| 870 | if (sym->flags & SYMBOL_CHECKED) | 1098 | if (sym->flags & SYMBOL_CHECKED) |
| 871 | return NULL; | 1099 | return NULL; |
| 872 | 1100 | ||
| 873 | if (sym_is_choice_value(sym)) { | 1101 | if (sym_is_choice_value(sym)) { |
| 1102 | struct dep_stack stack; | ||
| 1103 | |||
| 874 | /* for choice groups start the check with main choice symbol */ | 1104 | /* for choice groups start the check with main choice symbol */ |
| 1105 | dep_stack_insert(&stack, sym); | ||
| 875 | prop = sym_get_choice_prop(sym); | 1106 | prop = sym_get_choice_prop(sym); |
| 876 | sym2 = sym_check_deps(prop_get_symbol(prop)); | 1107 | sym2 = sym_check_deps(prop_get_symbol(prop)); |
| 1108 | dep_stack_remove(); | ||
| 877 | } else if (sym_is_choice(sym)) { | 1109 | } else if (sym_is_choice(sym)) { |
| 878 | sym2 = sym_check_choice_deps(sym); | 1110 | sym2 = sym_check_choice_deps(sym); |
| 879 | } else { | 1111 | } else { |
| @@ -882,14 +1114,8 @@ struct symbol *sym_check_deps(struct symbol *sym) | |||
| 882 | sym->flags &= ~SYMBOL_CHECK; | 1114 | sym->flags &= ~SYMBOL_CHECK; |
| 883 | } | 1115 | } |
| 884 | 1116 | ||
| 885 | if (sym2) { | 1117 | if (sym2 && sym2 == sym) |
| 886 | fprintf(stderr, " -> %s", sym->name ? sym->name : "<choice>"); | 1118 | sym2 = NULL; |
| 887 | if (sym2 == sym) { | ||
| 888 | fprintf(stderr, "\n"); | ||
| 889 | zconfnerrs++; | ||
| 890 | sym2 = NULL; | ||
| 891 | } | ||
| 892 | } | ||
| 893 | 1119 | ||
| 894 | return sym2; | 1120 | return sym2; |
| 895 | } | 1121 | } |
| @@ -943,6 +1169,8 @@ const char *prop_get_type_name(enum prop_type type) | |||
| 943 | return "select"; | 1169 | return "select"; |
| 944 | case P_RANGE: | 1170 | case P_RANGE: |
| 945 | return "range"; | 1171 | return "range"; |
| 1172 | case P_SYMBOL: | ||
| 1173 | return "symbol"; | ||
| 946 | case P_UNKNOWN: | 1174 | case P_UNKNOWN: |
| 947 | break; | 1175 | break; |
| 948 | } | 1176 | } |
