aboutsummaryrefslogtreecommitdiffstats
path: root/scripts/kconfig
diff options
context:
space:
mode:
authorYann E. MORIN <yann.morin.1998@free.fr>2013-05-06 08:57:47 -0400
committerYann E. MORIN <yann.morin.1998@free.fr>2013-06-24 13:57:45 -0400
commit193b40aeb537b59eaa36e3dfaabedc2025332ebf (patch)
treef72ea744e1e9aeb53c5a546c1599d496412bd5c6 /scripts/kconfig
parenta5f6d795f5941e97e757b643a6482968a66c6150 (diff)
kconfig: sort found symbols by relevance
When searching for symbols, return the symbols sorted by relevance. Sorting is done as thus: - first, symbols that match exactly - then, alphabetical sort Since the search can be a regexp, it is possible that more than one symbol matches exactly. In this case, we can't decide which to sort first, so we fallback to alphabeticall sort. Explain this (new!) sorting heuristic in the documentation. Reported-by: Jean Delvare <jdelvare@suse.de> Signed-off-by: "Yann E. MORIN" <yann.morin.1998@free.fr> Cc: Jean Delvare <jdelvare@suse.de> Cc: Michal Marek <mmarek@suse.cz> Cc: Roland Eggner <edvx1@systemanalysen.net> Cc: Wang YanQing <udknight@gmail.com> -- Changes v1->v2: - drop the previous, complex heuristic in favour of a simpler heuristic that is both easier to understand, *and* to maintain (Jean) - explain sorting heuristic in the doc (Jean)
Diffstat (limited to 'scripts/kconfig')
-rw-r--r--scripts/kconfig/symbol.c78
1 files changed, 69 insertions, 9 deletions
diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c
index ab8f4c835933..387d55483882 100644
--- a/scripts/kconfig/symbol.c
+++ b/scripts/kconfig/symbol.c
@@ -954,38 +954,98 @@ const char *sym_escape_string_value(const char *in)
954 return res; 954 return res;
955} 955}
956 956
957struct sym_match {
958 struct symbol *sym;
959 off_t so, eo;
960};
961
962/* Compare matched symbols as thus:
963 * - first, symbols that match exactly
964 * - then, alphabetical sort
965 */
966static int sym_rel_comp( const void *sym1, const void *sym2 )
967{
968 struct sym_match *s1 = *(struct sym_match **)sym1;
969 struct sym_match *s2 = *(struct sym_match **)sym2;
970 int l1, l2;
971
972 /* Exact match:
973 * - if matched length on symbol s1 is the length of that symbol,
974 * then this symbol should come first;
975 * - if matched length on symbol s2 is the length of that symbol,
976 * then this symbol should come first.
977 * Note: since the search can be a regexp, both symbols may match
978 * exactly; if this is the case, we can't decide which comes first,
979 * and we fallback to sorting alphabetically.
980 */
981 l1 = s1->eo - s1->so;
982 l2 = s2->eo - s2->so;
983 if (l1 == strlen(s1->sym->name) && l2 != strlen(s2->sym->name))
984 return -1;
985 if (l1 != strlen(s1->sym->name) && l2 == strlen(s2->sym->name))
986 return 1;
987
988 /* As a fallback, sort symbols alphabetically */
989 return strcmp(s1->sym->name, s2->sym->name);
990}
991
957struct symbol **sym_re_search(const char *pattern) 992struct symbol **sym_re_search(const char *pattern)
958{ 993{
959 struct symbol *sym, **sym_arr = NULL; 994 struct symbol *sym, **sym_arr = NULL;
995 struct sym_match **sym_match_arr = NULL;
960 int i, cnt, size; 996 int i, cnt, size;
961 regex_t re; 997 regex_t re;
998 regmatch_t match[1];
962 999
963 cnt = size = 0; 1000 cnt = size = 0;
964 /* Skip if empty */ 1001 /* Skip if empty */
965 if (strlen(pattern) == 0) 1002 if (strlen(pattern) == 0)
966 return NULL; 1003 return NULL;
967 if (regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB|REG_ICASE)) 1004 if (regcomp(&re, pattern, REG_EXTENDED|REG_ICASE))
968 return NULL; 1005 return NULL;
969 1006
970 for_all_symbols(i, sym) { 1007 for_all_symbols(i, sym) {
1008 struct sym_match *tmp_sym_match;
971 if (sym->flags & SYMBOL_CONST || !sym->name) 1009 if (sym->flags & SYMBOL_CONST || !sym->name)
972 continue; 1010 continue;
973 if (regexec(&re, sym->name, 0, NULL, 0)) 1011 if (regexec(&re, sym->name, 1, match, 0))
974 continue; 1012 continue;
975 if (cnt + 1 >= size) { 1013 if (cnt + 1 >= size) {
976 void *tmp = sym_arr; 1014 void *tmp;
977 size += 16; 1015 size += 16;
978 sym_arr = realloc(sym_arr, size * sizeof(struct symbol *)); 1016 tmp = realloc(sym_match_arr, size * sizeof(struct sym_match *));
979 if (!sym_arr) { 1017 if (!tmp) {
980 free(tmp); 1018 goto sym_re_search_free;
981 return NULL;
982 } 1019 }
1020 sym_match_arr = tmp;
983 } 1021 }
984 sym_calc_value(sym); 1022 sym_calc_value(sym);
985 sym_arr[cnt++] = sym; 1023 tmp_sym_match = (struct sym_match*)malloc(sizeof(struct sym_match));
1024 if (!tmp_sym_match)
1025 goto sym_re_search_free;
1026 tmp_sym_match->sym = sym;
1027 /* As regexec return 0, we know we have a match, so
1028 * we can use match[0].rm_[se]o without further checks
1029 */
1030 tmp_sym_match->so = match[0].rm_so;
1031 tmp_sym_match->eo = match[0].rm_eo;
1032 sym_match_arr[cnt++] = tmp_sym_match;
986 } 1033 }
987 if (sym_arr) 1034 if (sym_match_arr) {
1035 qsort(sym_match_arr, cnt, sizeof(struct sym_match*), sym_rel_comp);
1036 sym_arr = malloc((cnt+1) * sizeof(struct symbol));
1037 if (!sym_arr)
1038 goto sym_re_search_free;
1039 for (i = 0; i < cnt; i++)
1040 sym_arr[i] = sym_match_arr[i]->sym;
988 sym_arr[cnt] = NULL; 1041 sym_arr[cnt] = NULL;
1042 }
1043sym_re_search_free:
1044 if (sym_match_arr) {
1045 for (i = 0; i < cnt; i++)
1046 free(sym_match_arr[i]);
1047 free(sym_match_arr);
1048 }
989 regfree(&re); 1049 regfree(&re);
990 1050
991 return sym_arr; 1051 return sym_arr;