@@ -943,38 +943,86 @@ const char *sym_escape_string_value(const char *in)
return res;
}
+struct sym_match {
+ struct symbol *sym;
+ int rel;
+};
+
+/* Compare matched symbols as thus:
+ * - highest relevance first
+ * - equal relevance sorted alphabetically
+ */
+static int sym_rel_comp( const void *sym1, const void *sym2 )
+{
+ struct sym_match **s1 = (struct sym_match **)sym1;
+ struct sym_match **s2 = (struct sym_match **)sym2;
+
+ if ( (*s1)->rel > (*s2)->rel )
+ return -1;
+ else if ( (*s1)->rel < (*s2)->rel )
+ return 1;
+ else
+ return strcmp( (*s1)->sym->name, (*s2)->sym->name );
+}
+
struct symbol **sym_re_search(const char *pattern)
{
struct symbol *sym, **sym_arr = NULL;
+ struct sym_match **sym_match_arr = NULL;
int i, cnt, size;
regex_t re;
+ regmatch_t match[1];
cnt = size = 0;
/* Skip if empty */
if (strlen(pattern) == 0)
return NULL;
- if (regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB|REG_ICASE))
+ if (regcomp(&re, pattern, REG_EXTENDED|REG_ICASE))
return NULL;
for_all_symbols(i, sym) {
+ struct sym_match *tmp_sym_match;
if (sym->flags & SYMBOL_CONST || !sym->name)
continue;
- if (regexec(&re, sym->name, 0, NULL, 0))
+ if (regexec(&re, sym->name, 1, match, 0))
continue;
if (cnt + 1 >= size) {
- void *tmp = sym_arr;
+ void *tmp;
size += 16;
- sym_arr = realloc(sym_arr, size * sizeof(struct symbol *));
- if (!sym_arr) {
- free(tmp);
- return NULL;
+ tmp = realloc(sym_match_arr, size * sizeof(struct sym_match *));
+ if (!tmp) {
+ goto sym_re_search_free;
}
+ sym_match_arr = tmp;
}
sym_calc_value(sym);
- sym_arr[cnt++] = sym;
+ tmp_sym_match = (struct sym_match*)malloc(sizeof(struct sym_match));
+ if (!tmp_sym_match)
+ goto sym_re_search_free;
+ tmp_sym_match->sym = sym;
+ /* As regexec return 0, we know we have a match, so
+ * we can use match[0].rm_[se]o without further checks
+ */
+ tmp_sym_match->rel = (100*(match[0].rm_eo-match[0].rm_so))
+ /strlen(sym->name);
+ sym_match_arr[cnt++] = tmp_sym_match;
}
- if (sym_arr)
+
+ if( sym_match_arr ) {
+ qsort( sym_match_arr, cnt, sizeof(struct sym_match*), sym_rel_comp );
+ sym_arr = malloc( (cnt+1) * sizeof(struct symbol) );
+ if (!sym_arr)
+ goto sym_re_search_free;
+ for ( i=0; i<cnt; i++ )
+ sym_arr[i] = sym_match_arr[i]->sym;
sym_arr[cnt] = NULL;
+ }
+sym_re_search_free:
+ if (sym_match_arr) {
+ for ( i=0; i<cnt; i++ )
+ free( sym_match_arr[i] );
+ free( sym_match_arr );
+ }
regfree(&re);
return sym_arr;