--- linux-3.2/scripts/kconfig/qconf.h.orig 2012-01-05 01:55:44.000000000 +0200 +++ linux-3.2/scripts/kconfig/qconf.h 2012-01-09 11:06:34.541652833 +0200 @@ -5,9 +5,12 @@ #if QT_VERSION < 0x040000 #include +#include #else #include +#include #endif +#include #include #if QT_VERSION < 0x040000 @@ -22,6 +25,7 @@ #define Q3ToolBar QToolBar #define Q3ListViewItemIterator QListViewItemIterator #define Q3FileDialog QFileDialog +#define Q3VButtonGroup QVButtonGroup #endif class ConfigView; @@ -278,6 +282,7 @@ bool _showDebug; }; +enum SEARCH_TYPE { SUBSTRING, KEYWORDS, REGEX }; class ConfigSearchWindow : public QDialog { Q_OBJECT typedef class QDialog Parent; @@ -291,11 +296,15 @@ protected: QLineEdit* editField; QPushButton* searchButton; + Q3VButtonGroup *searchType, *options; + QCheckBox *caseSensitivity; QSplitter* split; ConfigView* list; ConfigInfoView* info; struct symbol **result; + + unsigned int getSearchFlags(); }; class ConfigMainWindow : public Q3MainWindow { @@ -335,3 +344,4 @@ QSplitter* split1; QSplitter* split2; }; + --- linux-3.2/scripts/kconfig/keywords_search.c.orig 2012-01-09 11:06:34.531652839 +0200 +++ linux-3.2/scripts/kconfig/keywords_search.c 2012-01-09 11:06:34.531652839 +0200 @@ -0,0 +1,216 @@ +/* + * Keywords' Search Micro-Library. + * + * Copyrighted by Shlomi Fish, 2007. + * + * Licensed under the MIT/X11 License: + * + * http://www.opensource.org/licenses/mit-license.php + * + * */ +#include "keywords_search.h" +#include +#include +#include + +#define is_word_char(c) (isalpha(c) || isdigit(c)) + +static int add_word(keywords_search_handle_t *h, const char **p) +{ + const char *start; + keywords_search_keyword_t *word; + + start = *p; + while (is_word_char(**p)) + { + (*p)++; + } + if (h->num_words == h->max_num_words) + { + void *new_ptr; + h->max_num_words += 16; + new_ptr = realloc(h->words, + sizeof(h->words[0]) * h->max_num_words + ); + if (new_ptr == NULL) + { + return 0; + } + h->words = new_ptr; + } + word = &(h->words[h->num_words++]); + word->found = 0; + word->word = + malloc(sizeof(word->word[0]) * + (word->word_len = (*p)-start)+1 + ); + if (! word->word) + { + return 0; + } + memcpy(word->word, start, word->word_len); + word->word[word->word_len] = '\0'; + + return 1; +} + +keywords_search_handle_t *keywords_search_compile(const char *pattern) +{ + int i; + keywords_search_handle_t *ret = NULL; + const char *char_ptr; + + ret = malloc(sizeof(*ret)); + if (!ret) + { + return NULL; + } + + ret->num_words = 0; + ret->max_num_words = 0; + ret->num_found_words = 0; + ret->words = NULL; + + char_ptr = pattern; + + while (*char_ptr) + { + if (is_word_char(*char_ptr)) + { + if (!add_word(ret, &char_ptr)) + { + goto cleanup_words; + } + } + else + { + char_ptr++; + } + } + + return ret; + +cleanup_words: + for(i=0;inum_words;i++) + { + free(ret->words[i].word); + ret->words[i].word = NULL; + } + free(ret->words); + ret->words = NULL; + + free(ret); + ret = NULL; + + return NULL; +} + +static int +cmp_word(keywords_search_handle_t* handle, keywords_search_keyword_t *word, const char *start, const int len) +{ + if (word->found || (word->word_len != len)) + { + return 0; + } + + if (handle->case_sensitivity) + { + return !strncmp(word->word, start, len); + } + else + { + return !strncasecmp(word->word, start, len); + } +} + +static int +find_word(keywords_search_handle_t* handle, const char *start, const int len) +{ + int i; + keywords_search_keyword_t *word; + + word = handle->words; + for(i = 0; i < handle->num_words; i++, word++) + { + if (cmp_word(handle, word, start, len)) + { + word->found = 1; + if (++handle->num_found_words == handle->num_words) + { + return 1; + } + } + } + return 0; +} + +int keywords_search_matches(keywords_search_handle_t *handle, const char *string, int case_sensitivity) +{ + const char *char_ptr, *start; + + char_ptr = string; + + handle->case_sensitivity = case_sensitivity; + + if (handle->num_found_words == handle->num_words) + { + return 1; + } + + /* Handle the NULL string gracefully. */ + if (! string) + { + return 0; + } + + while(*char_ptr) + { + if (is_word_char(*char_ptr)) + { + int len; + + start = char_ptr; + while (is_word_char(*char_ptr)) + { + char_ptr++; + } + + len = char_ptr - start; + + if (find_word(handle, start, len)) + { + return 1; + } + } + else + { + char_ptr++; + } + } + + return 0; +} + +void keywords_search_reset(keywords_search_handle_t *handle) +{ + int i; + + /* Reset the state of the handle to no words found. */ + handle->num_found_words = 0; + for(i=0 ; i < handle->num_words ; i++) + { + handle->words[i].found = 0; + } +} + +void keywords_search_free(keywords_search_handle_t *handle) +{ + int i; + + for(i=0 ; i < handle->num_words ; i++) + { + free(handle->words[i].word); + } + free(handle->words); + free(handle); +} --- linux-3.2/scripts/kconfig/keywords_search.h.orig 2012-01-09 11:06:34.531652839 +0200 +++ linux-3.2/scripts/kconfig/keywords_search.h 2012-01-09 11:06:34.531652839 +0200 @@ -0,0 +1,41 @@ +/* + * Keywords' Search Micro-Library. + * + * Copyrighted by Shlomi Fish, 2007. + * + * Licensed under the MIT/X11 License: + * + * http://www.opensource.org/licenses/mit-license.php + * + * */ +#ifndef KEYWORDS_SEARCH_H +#define KEYWORDS_SEARCH_H + +struct keywords_search_keyword_struct +{ + int found; + char *word; + int word_len; +}; + +typedef struct keywords_search_keyword_struct keywords_search_keyword_t; + +struct keywords_search_handle_struct +{ + int num_words; + int max_num_words; + int num_found_words; + keywords_search_keyword_t *words; + /* The case sensitivity flag - valid only for a search session. */ + int case_sensitivity; +}; + +typedef struct keywords_search_handle_struct keywords_search_handle_t; + +keywords_search_handle_t *keywords_search_compile(const char *pattern); +int keywords_search_matches(keywords_search_handle_t* handle, const char *string, int case_sensitivity); +void keywords_search_reset(keywords_search_handle_t *handle); +void keywords_search_free(keywords_search_handle_t *handle); + +#endif /* KEYWORDS_SEARCH_H */ + --- linux-3.2/scripts/kconfig/qconf.cc.orig 2012-01-05 01:55:44.000000000 +0200 +++ linux-3.2/scripts/kconfig/qconf.cc 2012-01-09 11:06:34.540652834 +0200 @@ -39,6 +39,7 @@ #include #include #include +#include #include @@ -1196,6 +1197,36 @@ layout2->addWidget(searchButton); layout1->addLayout(layout2); + // Initialize the "Search Type" button group. + searchType = new Q3VButtonGroup("Search Type", this, "searchType"); + + searchType->insert(new QRadioButton("Substring Match", searchType), + SYM_PATTERN_SEARCH_SUBSTRING + ); + + searchType->insert(new QRadioButton("Keywords", searchType), + SYM_PATTERN_SEARCH_KEYWORDS_AND + ); + + searchType->insert(new QRadioButton("Regular Expression", searchType), + SYM_PATTERN_SEARCH_REGEX + ); + + searchType->setButton(SYM_PATTERN_SEARCH_SUBSTRING); + layout1->addWidget(searchType); + + // Initialize the "Options" button group. + options = new Q3VButtonGroup("Options", this, "Options"); + + caseSensitivity = new QCheckBox( + "Case sensitive", options, "Case sensitive" + ); + + caseSensitivity->setChecked(FALSE); + + layout1->addWidget(options); + + // Initialize the ConfigView and ConfigInfoView split = new QSplitter(this); split->setOrientation(Qt::Vertical); list = new ConfigView(split, name); @@ -1242,6 +1273,17 @@ } } +unsigned int ConfigSearchWindow::getSearchFlags() +{ + return (searchType->selectedId() + | + (caseSensitivity->isChecked() + ? SYM_PATTERN_CASE_SENSITIVE + : SYM_PATTERN_CASE_INSENSITIVE + ) + ); +} + void ConfigSearchWindow::search(void) { struct symbol **p; @@ -1252,7 +1294,7 @@ list->list->clear(); info->clear(); - result = sym_re_search(editField->text().latin1()); + result = sym_pattern_search(editField->text(), getSearchFlags()); if (!result) return; for (p = result; *p; p++) { --- linux-3.2/scripts/kconfig/lkc.h.orig 2012-01-05 01:55:44.000000000 +0200 +++ linux-3.2/scripts/kconfig/lkc.h 2012-01-09 11:06:34.538652836 +0200 @@ -145,6 +145,21 @@ struct symbol *prop_get_symbol(struct property *prop); struct property *sym_get_env_prop(struct symbol *sym); +typedef int (*sym_search_filter_t)(struct symbol *sym, void *context); +struct symbol **sym_generic_search(sym_search_filter_t filter, void *context); +struct symbol **sym_pattern_search(const char *pattern, unsigned int flags); + +enum SYM_PATTERN_SEARCH_FLAGS +{ + SYM_PATTERN_SEARCH_REGEX = 0x0, + SYM_PATTERN_SEARCH_SUBSTRING = 0x1, + SYM_PATTERN_SEARCH_KEYWORDS_AND = 0x2, + SYM_PATTERN_SEARCH_TYPE_MASK = 0xF, + SYM_PATTERN_CASE_SENSITIVE = 0x10, + SYM_PATTERN_CASE_INSENSITIVE = 0x00, + SYM_PATTERN_CASE_MASK = 0x10, +}; + static inline tristate sym_get_tristate_value(struct symbol *sym) { return sym->curr.tri; --- linux-3.2/scripts/kconfig/Makefile.orig 2012-01-05 01:55:44.000000000 +0200 +++ linux-3.2/scripts/kconfig/Makefile 2012-01-09 11:09:27.171552078 +0200 @@ -140,13 +140,13 @@ lxdialog := lxdialog/checklist.o lxdialog/util.o lxdialog/inputbox.o lxdialog += lxdialog/textbox.o lxdialog/yesno.o lxdialog/menubox.o -conf-objs := conf.o zconf.tab.o -mconf-objs := mconf.o zconf.tab.o $(lxdialog) -nconf-objs := nconf.o zconf.tab.o nconf.gui.o -kxgettext-objs := kxgettext.o zconf.tab.o +conf-objs := conf.o zconf.tab.o keywords_search.o +mconf-objs := mconf.o zconf.tab.o keywords_search.o $(lxdialog) +nconf-objs := nconf.o zconf.tab.o keywords_search.o nconf.gui.o +kxgettext-objs := kxgettext.o zconf.tab.o keywords_search.o qconf-cxxobjs := qconf.o -qconf-objs := zconf.tab.o -gconf-objs := gconf.o zconf.tab.o +qconf-objs := zconf.tab.o keywords_search.o +gconf-objs := gconf.o zconf.tab.o keywords_search.o hostprogs-y := conf --- linux-3.2/scripts/kconfig/symbol.c.orig 2012-01-05 01:55:44.000000000 +0200 +++ linux-3.2/scripts/kconfig/symbol.c 2012-01-09 11:10:38.077509412 +0200 @@ -9,6 +9,7 @@ #include #include +#include "keywords_search.h" #include "lkc.h" struct symbol symbol_yes = { @@ -936,23 +937,209 @@ return res; } +static int re_search_filter(struct symbol *sym, void *re_void) +{ + return (regexec((regex_t*)re_void, sym->name, 0, NULL, 0) == 0); +} + + +/* The old function that only searches through sym->name. */ struct symbol **sym_re_search(const char *pattern) { - struct symbol *sym, **sym_arr = NULL; - int i, cnt, size; regex_t re; + struct symbol **results; - cnt = size = 0; - /* Skip if empty */ if (strlen(pattern) == 0) return NULL; if (regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB|REG_ICASE)) return NULL; + results = sym_generic_search(re_search_filter, (void *)&re); + + regfree(&re); + + return results; +} + +struct substring_search_context_struct +{ + const char * substring; + char *(*find_func)(const char *,const char *); +}; + +typedef struct substring_search_context_struct substring_search_context_t; + +#define MATCH_SYMBOL() \ + (MATCH(sym->name) || \ + (sym->prop && \ + ((sym->prop->text && MATCH(sym->prop->text)) || \ + (sym->prop->menu && sym->prop->menu->help && \ + MATCH(sym->prop->menu->help))) \ + )); + +static int substring_filter(struct symbol *sym, void *context_void) +{ + substring_search_context_t *context; + context = (substring_search_context_t *)context_void; + +#define MATCH(string) \ + (context->find_func((string), context->substring)) + + return MATCH_SYMBOL(); +#undef MATCH +} + +/* + * A not-so-efficient (but should be good enough) implementation of the + * GNU strcasestr extension. This is done because strcasestr is not portable + * and the compiler yells at us for using it. + * */ +static char * my_strcasestr(const char * haystack, const char * needle) +{ + size_t needle_len; + char * start_from; + + needle_len = strlen(needle); + start_from = (char *)haystack; + + while (*start_from) + { + if (!strncasecmp(start_from, needle, needle_len)) + { + return start_from; + } + + start_from++; + } + + return NULL; +} + +static struct symbol **substring_search(const char *substring, int case_sense) +{ + substring_search_context_t context; + + context.substring = substring; + context.find_func = case_sense ? strstr : my_strcasestr; + + return sym_generic_search(substring_filter, (void *)&context); +} + +struct keywords_search_context_struct +{ + keywords_search_handle_t * h; + int case_sense; +}; + +typedef struct keywords_search_context_struct keywords_search_context_t; + +static int keywords_filter(struct symbol *sym, void *context_void) +{ + keywords_search_context_t *context; + context = (keywords_search_context_t *)context_void; + + keywords_search_reset(context->h); + +#define MATCH(string) \ + (keywords_search_matches(context->h, string, context->case_sense)) + + return MATCH_SYMBOL(); +#undef MATCH +} + +static struct symbol **keywords_search(const char *query, int case_sense) +{ + struct symbol **results; + keywords_search_context_t context; + + context.h = keywords_search_compile(query); + if (! context.h) + { + return NULL; + } + context.case_sense = case_sense; + + results = sym_generic_search(keywords_filter, (void *)&context); + keywords_search_free (context.h); + + return results; +} + + +static int re_search2_filter(struct symbol *sym, void *re_void) +{ + regex_t *re = (regex_t*)re_void; + +#define MATCH(string) \ + (regexec(re, (string), 0, NULL, 0) == 0) + + return MATCH_SYMBOL(); +#undef MATCH +} + +static struct symbol **sym_re_search2(const char *pattern, int case_sense) +{ + regex_t re; + struct symbol **results; + int rc_flags; + + rc_flags = case_sense ? 0 : REG_ICASE; + + if (strlen(pattern) == 0) + return NULL; + if (regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB|rc_flags)) + return NULL; + + results = sym_generic_search(re_search2_filter, (void *)&re); + + regfree(&re); + + return results; +} + + +#undef MATCH_SYMBOL + +#define is_case_sensitive(flags) \ + (((flags) & SYM_PATTERN_CASE_MASK) == SYM_PATTERN_CASE_SENSITIVE) + +struct symbol **sym_pattern_search(const char *pattern, unsigned int flags) +{ + unsigned int type; + int case_sense; + + type = (flags & SYM_PATTERN_SEARCH_TYPE_MASK); + case_sense = is_case_sensitive(flags); + + if (type == SYM_PATTERN_SEARCH_REGEX) + { + return sym_re_search2(pattern, case_sense); + } + else if (type == SYM_PATTERN_SEARCH_SUBSTRING) + { + return substring_search(pattern, case_sense); + } + else if (type == SYM_PATTERN_SEARCH_KEYWORDS_AND) + { + return keywords_search(pattern, case_sense); + } + else + { + return NULL; + } +} + +struct symbol **sym_generic_search(sym_search_filter_t filter, void *context) +{ + struct symbol *sym, **sym_arr = NULL; + int i, cnt, size; + + cnt = size = 0; + for_all_symbols(i, sym) { if (sym->flags & SYMBOL_CONST || !sym->name) continue; - if (regexec(&re, sym->name, 0, NULL, 0)) + if (!filter(sym, context)) continue; if (cnt + 1 >= size) { void *tmp = sym_arr; @@ -968,7 +1155,6 @@ } if (sym_arr) sym_arr[cnt] = NULL; - regfree(&re); return sym_arr; }