History

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)

Yann E. MORIN committed 13 years ago

Commit 193b40a1 parent a5f6d792 files · +82 −9Browse files

Showing the changes to scripts (1 of 2 files). Show all

Unified · Split

scripts/kconfig/symbol.c+69−9
@@ -954,38 +954,98 @@ const char *sym_escape_string_value(const char *in) · 953 unmodified lines
954954 return res;
955955 }
956956
957+struct 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+ */
966+static 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+
957992 struct symbol **sym_re_search(const char *pattern)
958993 {
959994 struct symbol *sym, **sym_arr = NULL;
995+ struct sym_match **sym_match_arr = NULL;
960996 int i, cnt, size;
961997 regex_t re;
998+ regmatch_t match[1];
962999
9631000 cnt = size = 0;
9641001 /* Skip if empty */
9651002 if (strlen(pattern) == 0)
9661003 return NULL;
967− if (regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB|REG_ICASE))
1004+ if (regcomp(&re, pattern, REG_EXTENDED|REG_ICASE))
9681005 return NULL;
9691006
9701007 for_all_symbols(i, sym) {
1008+ struct sym_match *tmp_sym_match;
9711009 if (sym->flags & SYMBOL_CONST || !sym->name)
9721010 continue;
973− if (regexec(&re, sym->name, 0, NULL, 0))
1011+ if (regexec(&re, sym->name, 1, match, 0))
9741012 continue;
9751013 if (cnt + 1 >= size) {
976− void *tmp = sym_arr;
1014+ void *tmp;
9771015 size += 16;
978− sym_arr = realloc(sym_arr, size * sizeof(struct symbol *));
979− if (!sym_arr) {
980− free(tmp);
981− return NULL;
1016+ tmp = realloc(sym_match_arr, size * sizeof(struct sym_match *));
1017+ if (!tmp) {
1018+ goto sym_re_search_free;
9821019 }
1020+ sym_match_arr = tmp;
9831021 }
9841022 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;
9861033 }
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;
9881041 sym_arr[cnt] = NULL;
1042+ }
1043+sym_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+ }
9891049 regfree(&re);
9901050
9911051 return sym_arr;

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t