Merge branch 'kconfig' of git://git.kernel.org/pub/scm/linux/kernel/git/mmarek/kbuild
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 10 Jul 2013 23:06:46 +0000 (16:06 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 10 Jul 2013 23:06:46 +0000 (16:06 -0700)
Pull kconfig updates from Michal Marek:
 - dependency solver fix for make defconfig
 - randconfig fixes, one of which had to be reverted again
 - more user-friendly sorting of search results
 - hex and range keywords support longs
 - fix for [mn]conf not to rely on particular behavior of the LINES and
   COLS variables
 - cleanup of magic constants in kconfig/lxdialog
 - [mn]conf formatting fixes
 - fix for scripts/config's help text in out-of-tree usage (under a
   different name)

* 'kconfig' of git://git.kernel.org/pub/scm/linux/kernel/git/mmarek/kbuild:
  kconfig: allow "hex" and "range" to support longs
  Revert "kconfig: fix randomising choice entries in presence of KCONFIG_ALLCONFIG"
  kconfig: fix randomising choice entries in presence of KCONFIG_ALLCONFIG
  kconfig: loop as long as we changed some symbols in randconfig
  kconfig/[mn]conf: make it explicit in the search box that a regexp is possible
  kconfig: sort found symbols by relevance
  kconfig/conf: print the seed used to initialise the RNG for randconfig
  kconfig/conf: accept a base-16 seed for randconfig
  kconfig/conf: fix randconfig setting multiple symbols in a choice
  scripts/config: replace hard-coded script name by a dynamic value
  mconf/nconf: mark empty menus/menuconfigs different from non-empty ones
  nconf: use function calls instead of ncurses' variables LINES and COLS
  mconf: use function calls instead of ncurses' variables LINES and COLS
  kconfig/lxdialog: handle newline characters in print_autowrap()
  kconfig/lxdialog: Use new mininimum resize definitions in conf_choice()
  kconfig/lxdialog: Add definitions for mininimum (re)size values
  kconfig: Fix defconfig when one choice menu selects options that another choice menu depends on

19 files changed:
Documentation/kbuild/kconfig.txt
scripts/config
scripts/kconfig/conf.c
scripts/kconfig/confdata.c
scripts/kconfig/expr.h
scripts/kconfig/lkc.h
scripts/kconfig/lkc_proto.h
scripts/kconfig/lxdialog/checklist.c
scripts/kconfig/lxdialog/dialog.h
scripts/kconfig/lxdialog/inputbox.c
scripts/kconfig/lxdialog/menubox.c
scripts/kconfig/lxdialog/textbox.c
scripts/kconfig/lxdialog/util.c
scripts/kconfig/lxdialog/yesno.c
scripts/kconfig/mconf.c
scripts/kconfig/menu.c
scripts/kconfig/nconf.c
scripts/kconfig/nconf.gui.c
scripts/kconfig/symbol.c

index 213859e69e88096fc9c45e60d6ddebd92f512e31..e349f293cc9829dc5cad185a41f95cb8627e90ea 100644 (file)
@@ -174,6 +174,19 @@ Searching in menuconfig:
 
                /^hotplug
 
+       When searching, symbols are sorted thus:
+         - exact match first: an exact match is when the search matches
+           the complete symbol name;
+         - alphabetical order: when two symbols do not match exactly,
+           they are sorted in alphabetical order (in the user's current
+           locale).
+       For example: ^ATH.K matches:
+           ATH5K ATH9K ATH5K_AHB ATH5K_DEBUG [...] ATH6KL ATH6KL_DEBUG
+           [...] ATH9K_AHB ATH9K_BTCOEX_SUPPORT ATH9K_COMMON [...]
+       of which only ATH5K and ATH9K match exactly and so are sorted
+       first (and in alphabetical order), then come all other symbols,
+       sorted in alphabetical order.
+
 ______________________________________________________________________
 User interface options for 'menuconfig'
 
index a65ecbbdd32a90fbadf50aa9622ce555294cf350..567120a87c39c0152643fba45f5487979b305afc 100755 (executable)
@@ -1,6 +1,8 @@
 #!/bin/bash
 # Manipulate options in a .config file from the command line
 
+myname=${0##*/}
+
 # If no prefix forced, use the default CONFIG_
 CONFIG_="${CONFIG_-CONFIG_}"
 
@@ -8,7 +10,7 @@ usage() {
        cat >&2 <<EOL
 Manipulate options in a .config file from the command line.
 Usage:
-config options command ...
+$myname options command ...
 commands:
        --enable|-e option   Enable option
        --disable|-d option  Disable option
@@ -33,14 +35,14 @@ options:
        --file config-file   .config file to change (default .config)
        --keep-case|-k       Keep next symbols' case (dont' upper-case it)
 
-config doesn't check the validity of the .config file. This is done at next
+$myname doesn't check the validity of the .config file. This is done at next
 make time.
 
-By default, config will upper-case the given symbol. Use --keep-case to keep
+By default, $myname will upper-case the given symbol. Use --keep-case to keep
 the case of all following symbols unchanged.
 
-config uses 'CONFIG_' as the default symbol prefix. Set the environment
-variable CONFIG_ to the prefix to use. Eg.: CONFIG_="FOO_" config ...
+$myname uses 'CONFIG_' as the default symbol prefix. Set the environment
+variable CONFIG_ to the prefix to use. Eg.: CONFIG_="FOO_" $myname ...
 EOL
        exit 1
 }
index bde5b95c8c19dadea25bcb357ed6362daeb4f42a..d19944f9c3acb9e6004ca13a1f6e4444174a5359 100644 (file)
@@ -527,11 +527,12 @@ int main(int ac, char **av)
                        seed_env = getenv("KCONFIG_SEED");
                        if( seed_env && *seed_env ) {
                                char *endp;
-                               int tmp = (int)strtol(seed_env, &endp, 10);
+                               int tmp = (int)strtol(seed_env, &endp, 0);
                                if (*endp == '\0') {
                                        seed = tmp;
                                }
                        }
+                       fprintf( stderr, "KCONFIG_SEED=0x%X\n", seed );
                        srand(seed);
                        break;
                }
@@ -653,7 +654,8 @@ int main(int ac, char **av)
                conf_set_all_new_symbols(def_default);
                break;
        case randconfig:
-               conf_set_all_new_symbols(def_random);
+               /* Really nothing to do in this loop */
+               while (conf_set_all_new_symbols(def_random)) ;
                break;
        case defconfig:
                conf_set_all_new_symbols(def_default);
index 43eda40c38383e007a3ab66c755a86a085eef9cc..c55c227af463008396bc32548337769f71cc0d15 100644 (file)
@@ -1040,7 +1040,7 @@ void conf_set_changed_callback(void (*fn)(void))
        conf_changed_callback = fn;
 }
 
-static void randomize_choice_values(struct symbol *csym)
+static bool randomize_choice_values(struct symbol *csym)
 {
        struct property *prop;
        struct symbol *sym;
@@ -1053,7 +1053,7 @@ static void randomize_choice_values(struct symbol *csym)
         * In both cases stop.
         */
        if (csym->curr.tri != yes)
-               return;
+               return false;
 
        prop = sym_get_choice_prop(csym);
 
@@ -1077,13 +1077,18 @@ static void randomize_choice_values(struct symbol *csym)
                else {
                        sym->def[S_DEF_USER].tri = no;
                }
+               sym->flags |= SYMBOL_DEF_USER;
+               /* clear VALID to get value calculated */
+               sym->flags &= ~SYMBOL_VALID;
        }
        csym->flags |= SYMBOL_DEF_USER;
        /* clear VALID to get value calculated */
        csym->flags &= ~(SYMBOL_VALID);
+
+       return true;
 }
 
-static void set_all_choice_values(struct symbol *csym)
+void set_all_choice_values(struct symbol *csym)
 {
        struct property *prop;
        struct symbol *sym;
@@ -1100,10 +1105,10 @@ static void set_all_choice_values(struct symbol *csym)
        }
        csym->flags |= SYMBOL_DEF_USER;
        /* clear VALID to get value calculated */
-       csym->flags &= ~(SYMBOL_VALID);
+       csym->flags &= ~(SYMBOL_VALID | SYMBOL_NEED_SET_CHOICE_VALUES);
 }
 
-void conf_set_all_new_symbols(enum conf_def_mode mode)
+bool conf_set_all_new_symbols(enum conf_def_mode mode)
 {
        struct symbol *sym, *csym;
        int i, cnt, pby, pty, ptm;      /* pby: probability of boolean  = y
@@ -1151,6 +1156,7 @@ void conf_set_all_new_symbols(enum conf_def_mode mode)
                        exit( 1 );
                }
        }
+       bool has_changed = false;
 
        for_all_symbols(i, sym) {
                if (sym_has_value(sym) || (sym->flags & SYMBOL_VALID))
@@ -1158,6 +1164,7 @@ void conf_set_all_new_symbols(enum conf_def_mode mode)
                switch (sym_get_type(sym)) {
                case S_BOOLEAN:
                case S_TRISTATE:
+                       has_changed = true;
                        switch (mode) {
                        case def_yes:
                                sym->def[S_DEF_USER].tri = yes;
@@ -1202,14 +1209,26 @@ void conf_set_all_new_symbols(enum conf_def_mode mode)
         * selected in a choice block and we set it to yes,
         * and the rest to no.
         */
+       if (mode != def_random) {
+               for_all_symbols(i, csym) {
+                       if ((sym_is_choice(csym) && !sym_has_value(csym)) ||
+                           sym_is_choice_value(csym))
+                               csym->flags |= SYMBOL_NEED_SET_CHOICE_VALUES;
+               }
+       }
+
        for_all_symbols(i, csym) {
                if (sym_has_value(csym) || !sym_is_choice(csym))
                        continue;
 
                sym_calc_value(csym);
                if (mode == def_random)
-                       randomize_choice_values(csym);
-               else
+                       has_changed = randomize_choice_values(csym);
+               else {
                        set_all_choice_values(csym);
+                       has_changed = true;
+               }
        }
+
+       return has_changed;
 }
index cdd48600e02a9bd842f2e43ab6b7f263949451ec..df198a5f482217781e7d4a605962bf443881ce7b 100644 (file)
@@ -106,6 +106,9 @@ struct symbol {
 #define SYMBOL_DEF3       0x40000  /* symbol.def[S_DEF_3] is valid */
 #define SYMBOL_DEF4       0x80000  /* symbol.def[S_DEF_4] is valid */
 
+/* choice values need to be set before calculating this symbol value */
+#define SYMBOL_NEED_SET_CHOICE_VALUES  0x100000
+
 #define SYMBOL_MAXLENGTH       256
 #define SYMBOL_HASHSIZE                9973
 
index f8aee5fc6d5e607625fc9e7f93bcbcf7f2e9f13b..09f4edfdc91132887e1e54e09faf1a9b99865965 100644 (file)
@@ -86,7 +86,8 @@ const char *conf_get_autoconfig_name(void);
 char *conf_get_default_confname(void);
 void sym_set_change_count(int count);
 void sym_add_change_count(int count);
-void conf_set_all_new_symbols(enum conf_def_mode mode);
+bool conf_set_all_new_symbols(enum conf_def_mode mode);
+void set_all_choice_values(struct symbol *csym);
 
 struct conf_printer {
        void (*print_symbol)(FILE *, struct symbol *, const char *, void *);
index ef1a7381f956d5e7d0ebb8d3ba6af2361a0c3c74..ecdb9659b67d245da75eb60c82d3f4c070d1d68b 100644 (file)
@@ -14,6 +14,7 @@ P(conf_set_message_callback, void,(void (*fn)(const char *fmt, va_list ap)));
 /* menu.c */
 P(rootmenu,struct menu,);
 
+P(menu_is_empty, bool, (struct menu *menu));
 P(menu_is_visible, bool, (struct menu *menu));
 P(menu_has_prompt, bool, (struct menu *menu));
 P(menu_get_prompt,const char *,(struct menu *menu));
index a2eb80fbc896fe28b2b0f8efc614cf83fcbfc7b8..3b15c08ec1fac369f9b6e0b01c738e46fa3efb2d 100644 (file)
@@ -132,16 +132,16 @@ int dialog_checklist(const char *title, const char *prompt, int height,
        }
 
 do_resize:
-       if (getmaxy(stdscr) < (height + 6))
+       if (getmaxy(stdscr) < (height + CHECKLIST_HEIGTH_MIN))
                return -ERRDISPLAYTOOSMALL;
-       if (getmaxx(stdscr) < (width + 6))
+       if (getmaxx(stdscr) < (width + CHECKLIST_WIDTH_MIN))
                return -ERRDISPLAYTOOSMALL;
 
        max_choice = MIN(list_height, item_count());
 
        /* center dialog box on screen */
-       x = (COLS - width) / 2;
-       y = (LINES - height) / 2;
+       x = (getmaxx(stdscr) - width) / 2;
+       y = (getmaxy(stdscr) - height) / 2;
 
        draw_shadow(stdscr, y, x, height, width);
 
index 1099337079b6ab93463ddb9f707e518adcf01666..b4343d384926600329203b846855f940b597b5fd 100644 (file)
@@ -200,6 +200,20 @@ int item_is_tag(char tag);
 int on_key_esc(WINDOW *win);
 int on_key_resize(void);
 
+/* minimum (re)size values */
+#define CHECKLIST_HEIGTH_MIN 6 /* For dialog_checklist() */
+#define CHECKLIST_WIDTH_MIN 6
+#define INPUTBOX_HEIGTH_MIN 2  /* For dialog_inputbox() */
+#define INPUTBOX_WIDTH_MIN 2
+#define MENUBOX_HEIGTH_MIN 15  /* For dialog_menu() */
+#define MENUBOX_WIDTH_MIN 65
+#define TEXTBOX_HEIGTH_MIN 8   /* For dialog_textbox() */
+#define TEXTBOX_WIDTH_MIN 8
+#define YESNO_HEIGTH_MIN 4     /* For dialog_yesno() */
+#define YESNO_WIDTH_MIN 4
+#define WINDOW_HEIGTH_MIN 19   /* For init_dialog() */
+#define WINDOW_WIDTH_MIN 80
+
 int init_dialog(const char *backtitle);
 void set_dialog_backtitle(const char *backtitle);
 void set_dialog_subtitles(struct subtitle_list *subtitles);
index 21404a04d7c34dc37d9f29ffe804b6abeb3f2a62..447a582198c9bc70c37c4d2d034b128b5a62080d 100644 (file)
@@ -56,14 +56,14 @@ int dialog_inputbox(const char *title, const char *prompt, int height, int width
                strcpy(instr, init);
 
 do_resize:
-       if (getmaxy(stdscr) <= (height - 2))
+       if (getmaxy(stdscr) <= (height - INPUTBOX_HEIGTH_MIN))
                return -ERRDISPLAYTOOSMALL;
-       if (getmaxx(stdscr) <= (width - 2))
+       if (getmaxx(stdscr) <= (width - INPUTBOX_WIDTH_MIN))
                return -ERRDISPLAYTOOSMALL;
 
        /* center dialog box on screen */
-       x = (COLS - width) / 2;
-       y = (LINES - height) / 2;
+       x = (getmaxx(stdscr) - width) / 2;
+       y = (getmaxy(stdscr) - height) / 2;
 
        draw_shadow(stdscr, y, x, height, width);
 
index 38cd69c5660e5163bfc402617de0d702e3372bd6..c93de0b2faca28525588bceb023f99bdd8a14acf 100644 (file)
@@ -193,7 +193,7 @@ int dialog_menu(const char *title, const char *prompt,
 do_resize:
        height = getmaxy(stdscr);
        width = getmaxx(stdscr);
-       if (height < 15 || width < 65)
+       if (height < MENUBOX_HEIGTH_MIN || width < MENUBOX_WIDTH_MIN)
                return -ERRDISPLAYTOOSMALL;
 
        height -= 4;
@@ -203,8 +203,8 @@ do_resize:
        max_choice = MIN(menu_height, item_count());
 
        /* center dialog box on screen */
-       x = (COLS - width) / 2;
-       y = (LINES - height) / 2;
+       x = (getmaxx(stdscr) - width) / 2;
+       y = (getmaxy(stdscr) - height) / 2;
 
        draw_shadow(stdscr, y, x, height, width);
 
index a48bb93e09073f05ea14786fea9370202f5039f9..1773319b95e74f68ee2c618654e8ee00c96b1b37 100644 (file)
@@ -80,7 +80,7 @@ int dialog_textbox(const char *title, char *tbuf, int initial_height,
 
 do_resize:
        getmaxyx(stdscr, height, width);
-       if (height < 8 || width < 8)
+       if (height < TEXTBOX_HEIGTH_MIN || width < TEXTBOX_WIDTH_MIN)
                return -ERRDISPLAYTOOSMALL;
        if (initial_height != 0)
                height = initial_height;
@@ -98,8 +98,8 @@ do_resize:
                        width = 0;
 
        /* center dialog box on screen */
-       x = (COLS - width) / 2;
-       y = (LINES - height) / 2;
+       x = (getmaxx(stdscr) - width) / 2;
+       y = (getmaxy(stdscr) - height) / 2;
 
        draw_shadow(stdscr, y, x, height, width);
 
index a0e97c29941023a36ad05708610e62853818255a..58a8289dd650281c29f8e34827c153e9b4d4ac74 100644 (file)
@@ -254,7 +254,12 @@ void attr_clear(WINDOW * win, int height, int width, chtype attr)
 
 void dialog_clear(void)
 {
-       attr_clear(stdscr, LINES, COLS, dlg.screen.atr);
+       int lines, columns;
+
+       lines = getmaxy(stdscr);
+       columns = getmaxx(stdscr);
+
+       attr_clear(stdscr, lines, columns, dlg.screen.atr);
        /* Display background title if it exists ... - SLH */
        if (dlg.backtitle != NULL) {
                int i, len = 0, skip = 0;
@@ -269,10 +274,10 @@ void dialog_clear(void)
                }
 
                wmove(stdscr, 1, 1);
-               if (len > COLS - 2) {
+               if (len > columns - 2) {
                        const char *ellipsis = "[...] ";
                        waddstr(stdscr, ellipsis);
-                       skip = len - (COLS - 2 - strlen(ellipsis));
+                       skip = len - (columns - 2 - strlen(ellipsis));
                }
 
                for (pos = dlg.subtitles; pos != NULL; pos = pos->next) {
@@ -298,7 +303,7 @@ void dialog_clear(void)
                                skip--;
                }
 
-               for (i = len + 1; i < COLS - 1; i++)
+               for (i = len + 1; i < columns - 1; i++)
                        waddch(stdscr, ACS_HLINE);
        }
        wnoutrefresh(stdscr);
@@ -317,7 +322,7 @@ int init_dialog(const char *backtitle)
        getyx(stdscr, saved_y, saved_x);
 
        getmaxyx(stdscr, height, width);
-       if (height < 19 || width < 80) {
+       if (height < WINDOW_HEIGTH_MIN || width < WINDOW_WIDTH_MIN) {
                endwin();
                return -ERRDISPLAYTOOSMALL;
        }
@@ -371,27 +376,19 @@ void print_title(WINDOW *dialog, const char *title, int width)
 /*
  * Print a string of text in a window, automatically wrap around to the
  * next line if the string is too long to fit on one line. Newline
- * characters '\n' are replaced by spaces.  We start on a new line
+ * characters '\n' are propperly processed.  We start on a new line
  * if there is no room for at least 4 nonblanks following a double-space.
  */
 void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x)
 {
        int newl, cur_x, cur_y;
-       int i, prompt_len, room, wlen;
-       char tempstr[MAX_LEN + 1], *word, *sp, *sp2;
+       int prompt_len, room, wlen;
+       char tempstr[MAX_LEN + 1], *word, *sp, *sp2, *newline_separator = 0;
 
        strcpy(tempstr, prompt);
 
        prompt_len = strlen(tempstr);
 
-       /*
-        * Remove newlines
-        */
-       for (i = 0; i < prompt_len; i++) {
-               if (tempstr[i] == '\n')
-                       tempstr[i] = ' ';
-       }
-
        if (prompt_len <= width - x * 2) {      /* If prompt is short */
                wmove(win, y, (width - prompt_len) / 2);
                waddstr(win, tempstr);
@@ -401,7 +398,10 @@ void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x)
                newl = 1;
                word = tempstr;
                while (word && *word) {
-                       sp = strchr(word, ' ');
+                       sp = strpbrk(word, "\n ");
+                       if (sp && *sp == '\n')
+                               newline_separator = sp;
+
                        if (sp)
                                *sp++ = 0;
 
@@ -413,7 +413,7 @@ void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x)
                        if (wlen > room ||
                            (newl && wlen < 4 && sp
                             && wlen + 1 + strlen(sp) > room
-                            && (!(sp2 = strchr(sp, ' '))
+                            && (!(sp2 = strpbrk(sp, "\n "))
                                 || wlen + 1 + (sp2 - sp) > room))) {
                                cur_y++;
                                cur_x = x;
@@ -421,7 +421,15 @@ void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x)
                        wmove(win, cur_y, cur_x);
                        waddstr(win, word);
                        getyx(win, cur_y, cur_x);
-                       cur_x++;
+
+                       /* Move to the next line if the word separator was a newline */
+                       if (newline_separator) {
+                               cur_y++;
+                               cur_x = x;
+                               newline_separator = 0;
+                       } else
+                               cur_x++;
+
                        if (sp && *sp == ' ') {
                                cur_x++;        /* double space */
                                while (*++sp == ' ') ;
index 4e6e8090c20b573868e3cfe15015a6b6f54b2f69..676fb2f824a3d41c81ef5348a4efc3630155cb14 100644 (file)
@@ -45,14 +45,14 @@ int dialog_yesno(const char *title, const char *prompt, int height, int width)
        WINDOW *dialog;
 
 do_resize:
-       if (getmaxy(stdscr) < (height + 4))
+       if (getmaxy(stdscr) < (height + YESNO_HEIGTH_MIN))
                return -ERRDISPLAYTOOSMALL;
-       if (getmaxx(stdscr) < (width + 4))
+       if (getmaxx(stdscr) < (width + YESNO_WIDTH_MIN))
                return -ERRDISPLAYTOOSMALL;
 
        /* center dialog box on screen */
-       x = (COLS - width) / 2;
-       y = (LINES - height) / 2;
+       x = (getmaxx(stdscr) - width) / 2;
+       y = (getmaxy(stdscr) - height) / 2;
 
        draw_shadow(stdscr, y, x, height, width);
 
index a69cbd78fb38e62f3f6c3978ef6a3935551aaabc..6c9c45f9fbbac432a877112f4243f483ed01e9e3 100644 (file)
@@ -48,7 +48,7 @@ static const char mconf_readme[] = N_(
 "----------\n"
 "o  Use the Up/Down arrow keys (cursor keys) to highlight the item\n"
 "   you wish to change or submenu wish to select and press <Enter>.\n"
-"   Submenus are designated by \"--->\".\n"
+"   Submenus are designated by \"--->\", empty ones by \"----\".\n"
 "\n"
 "   Shortcut: Press the option's highlighted letter (hotkey).\n"
 "             Pressing a hotkey more than once will sequence\n"
@@ -176,7 +176,7 @@ static const char mconf_readme[] = N_(
 "\n"),
 menu_instructions[] = N_(
        "Arrow keys navigate the menu.  "
-       "<Enter> selects submenus --->.  "
+       "<Enter> selects submenus ---> (or empty submenus ----).  "
        "Highlighted letters are hotkeys.  "
        "Pressing <Y> includes, <N> excludes, <M> modularizes features.  "
        "Press <Esc><Esc> to exit, <?> for Help, </> for Search.  "
@@ -401,7 +401,7 @@ static void search_conf(void)
        struct subtitle_part stpart;
 
        title = str_new();
-       str_printf( &title, _("Enter %s (sub)string to search for "
+       str_printf( &title, _("Enter %s (sub)string or regexp to search for "
                              "(with or without \"%s\")"), CONFIG_, CONFIG_);
 
 again:
@@ -498,8 +498,9 @@ static void build_conf(struct menu *menu)
                                                  menu->data ? "-->" : "++>",
                                                  indent + 1, ' ', prompt);
                                } else
-                                       item_make("   %*c%s  --->", indent + 1, ' ', prompt);
-
+                                       item_make("   %*c%s  %s",
+                                                 indent + 1, ' ', prompt,
+                                                 menu_is_empty(menu) ? "----" : "--->");
                                item_set_tag('m');
                                item_set_data(menu);
                                if (single_menu_mode && menu->data)
@@ -630,7 +631,7 @@ static void build_conf(struct menu *menu)
                          (sym_has_value(sym) || !sym_is_changable(sym)) ?
                          "" : _(" (NEW)"));
                if (menu->prompt->type == P_MENU) {
-                       item_add_str("  --->");
+                       item_add_str("  %s", menu_is_empty(menu) ? "----" : "--->");
                        return;
                }
        }
@@ -826,7 +827,9 @@ static void conf_choice(struct menu *menu)
                dialog_clear();
                res = dialog_checklist(prompt ? _(prompt) : _("Main Menu"),
                                        _(radiolist_instructions),
-                                        15, 70, 6);
+                                       MENUBOX_HEIGTH_MIN,
+                                       MENUBOX_WIDTH_MIN,
+                                       CHECKLIST_HEIGTH_MIN);
                selected = item_activate_selected();
                switch (res) {
                case 0:
@@ -957,8 +960,8 @@ static int handle_exit(void)
        dialog_clear();
        if (conf_get_changed())
                res = dialog_yesno(NULL,
-                                  _("Do you wish to save your new configuration ?\n"
-                                    "<ESC><ESC> to continue."),
+                                  _("Do you wish to save your new configuration?\n"
+                                    "(Press <ESC><ESC> to continue kernel configuration.)"),
                                   6, 60);
        else
                res = -1;
index fd3f0180e08fbafb537e128c9e46641288c68774..7e233a6ca64ef7faf1bc9390ec89cb90ccef2d98 100644 (file)
@@ -443,6 +443,22 @@ bool menu_has_prompt(struct menu *menu)
        return true;
 }
 
+/*
+ * Determine if a menu is empty.
+ * A menu is considered empty if it contains no or only
+ * invisible entries.
+ */
+bool menu_is_empty(struct menu *menu)
+{
+       struct menu *child;
+
+       for (child = menu->list; child; child = child->next) {
+               if (menu_is_visible(child))
+                       return(false);
+       }
+       return(true);
+}
+
 bool menu_is_visible(struct menu *menu)
 {
        struct menu *child;
index dbf31edd22b261edafc003e6c3e0c3420e866c97..7975d8d258c3f6cb8848a137a3f263a4f16f1d20 100644 (file)
@@ -45,8 +45,8 @@ static const char nconf_global_help[] = N_(
 "<n> to remove it.  You may press the <Space> key to cycle through the\n"
 "available options.\n"
 "\n"
-"A trailing \"--->\" designates a submenu.\n"
-"\n"
+"A trailing \"--->\" designates a submenu, a trailing \"----\" an\n"
+"empty submenu.\n"
 "\n"
 "Menu navigation keys\n"
 "----------------------------------------------------------------------\n"
@@ -131,7 +131,7 @@ static const char nconf_global_help[] = N_(
 "\n"),
 menu_no_f_instructions[] = N_(
 "Legend:  [*] built-in  [ ] excluded  <M> module  < > module capable.\n"
-"Submenus are designated by a trailing \"--->\".\n"
+"Submenus are designated by a trailing \"--->\", empty ones by \"----\".\n"
 "\n"
 "Use the following keys to navigate the menus:\n"
 "Move up or down with <Up> and <Down>.\n"
@@ -148,7 +148,7 @@ menu_no_f_instructions[] = N_(
 "For help related to the current menu entry press <?> or <h>.\n"),
 menu_instructions[] = N_(
 "Legend:  [*] built-in  [ ] excluded  <M> module  < > module capable.\n"
-"Submenus are designated by a trailing \"--->\".\n"
+"Submenus are designated by a trailing \"--->\", empty ones by \"----\".\n"
 "\n"
 "Use the following keys to navigate the menus:\n"
 "Move up or down with <Up> or <Down>.\n"
@@ -365,15 +365,16 @@ static void print_function_line(void)
        int i;
        int offset = 1;
        const int skip = 1;
+       int lines = getmaxy(stdscr);
 
        for (i = 0; i < function_keys_num; i++) {
                (void) wattrset(main_window, attributes[FUNCTION_HIGHLIGHT]);
-               mvwprintw(main_window, LINES-3, offset,
+               mvwprintw(main_window, lines-3, offset,
                                "%s",
                                function_keys[i].key_str);
                (void) wattrset(main_window, attributes[FUNCTION_TEXT]);
                offset += strlen(function_keys[i].key_str);
-               mvwprintw(main_window, LINES-3,
+               mvwprintw(main_window, lines-3,
                                offset, "%s",
                                function_keys[i].func);
                offset += strlen(function_keys[i].func) + skip;
@@ -694,7 +695,7 @@ static void search_conf(void)
        int dres;
 
        title = str_new();
-       str_printf( &title, _("Enter %s (sub)string to search for "
+       str_printf( &title, _("Enter %s (sub)string or regexp to search for "
                              "(with or without \"%s\")"), CONFIG_, CONFIG_);
 
 again:
@@ -759,9 +760,9 @@ static void build_conf(struct menu *menu)
                                                indent + 1, ' ', prompt);
                                } else
                                        item_make(menu, 'm',
-                                               "   %*c%s  --->",
-                                               indent + 1,
-                                               ' ', prompt);
+                                                 "   %*c%s  %s",
+                                                 indent + 1, ' ', prompt,
+                                                 menu_is_empty(menu) ? "----" : "--->");
 
                                if (single_menu_mode && menu->data)
                                        goto conf_childs;
@@ -903,7 +904,7 @@ static void build_conf(struct menu *menu)
                                (sym_has_value(sym) || !sym_is_changable(sym)) ?
                                "" : _(" (NEW)"));
                if (menu->prompt && menu->prompt->type == P_MENU) {
-                       item_add_str("  --->");
+                       item_add_str("  %s", menu_is_empty(menu) ? "----" : "--->");
                        return;
                }
        }
@@ -954,7 +955,7 @@ static void show_menu(const char *prompt, const char *instructions,
 
        clear();
        (void) wattrset(main_window, attributes[NORMAL]);
-       print_in_middle(stdscr, 1, 0, COLS,
+       print_in_middle(stdscr, 1, 0, getmaxx(stdscr),
                        menu_backtitle,
                        attributes[MAIN_HEADING]);
 
@@ -1455,14 +1456,18 @@ static void conf_save(void)
 
 void setup_windows(void)
 {
+       int lines, columns;
+
+       getmaxyx(stdscr, lines, columns);
+
        if (main_window != NULL)
                delwin(main_window);
 
        /* set up the menu and menu window */
-       main_window = newwin(LINES-2, COLS-2, 2, 1);
+       main_window = newwin(lines-2, columns-2, 2, 1);
        keypad(main_window, TRUE);
-       mwin_max_lines = LINES-7;
-       mwin_max_cols = COLS-6;
+       mwin_max_lines = lines-7;
+       mwin_max_cols = columns-6;
 
        /* panels order is from bottom to top */
        new_panel(main_window);
@@ -1470,6 +1475,7 @@ void setup_windows(void)
 
 int main(int ac, char **av)
 {
+       int lines, columns;
        char *mode;
 
        setlocale(LC_ALL, "");
@@ -1495,7 +1501,8 @@ int main(int ac, char **av)
        keypad(stdscr, TRUE);
        curs_set(0);
 
-       if (COLS < 75 || LINES < 20) {
+       getmaxyx(stdscr, lines, columns);
+       if (columns < 75 || lines < 20) {
                endwin();
                printf("Your terminal should have at "
                        "least 20 lines and 75 columns\n");
index 9f8c44ecc703a1ea9cd27d3e656e5352f8e6ba86..8275f0e55106bc0055d0a1adfe2a169ad1b54193 100644 (file)
@@ -276,8 +276,8 @@ int btn_dialog(WINDOW *main_window, const char *msg, int btn_num, ...)
 
        total_width = max(msg_width, btns_width);
        /* place dialog in middle of screen */
-       y = (LINES-(msg_lines+4))/2;
-       x = (COLS-(total_width+4))/2;
+       y = (getmaxy(stdscr)-(msg_lines+4))/2;
+       x = (getmaxx(stdscr)-(total_width+4))/2;
 
 
        /* create the windows */
@@ -387,8 +387,8 @@ int dialog_inputbox(WINDOW *main_window,
                prompt_width = max(prompt_width, strlen(title));
 
        /* place dialog in middle of screen */
-       y = (LINES-(prompt_lines+4))/2;
-       x = (COLS-(prompt_width+4))/2;
+       y = (getmaxy(stdscr)-(prompt_lines+4))/2;
+       x = (getmaxx(stdscr)-(prompt_width+4))/2;
 
        strncpy(result, init, *result_len);
 
@@ -545,7 +545,7 @@ void show_scroll_win(WINDOW *main_window,
 {
        int res;
        int total_lines = get_line_no(text);
-       int x, y;
+       int x, y, lines, columns;
        int start_x = 0, start_y = 0;
        int text_lines = 0, text_cols = 0;
        int total_cols = 0;
@@ -556,6 +556,8 @@ void show_scroll_win(WINDOW *main_window,
        WINDOW *pad;
        PANEL *panel;
 
+       getmaxyx(stdscr, lines, columns);
+
        /* find the widest line of msg: */
        total_lines = get_line_no(text);
        for (i = 0; i < total_lines; i++) {
@@ -569,14 +571,14 @@ void show_scroll_win(WINDOW *main_window,
        (void) wattrset(pad, attributes[SCROLLWIN_TEXT]);
        fill_window(pad, text);
 
-       win_lines = min(total_lines+4, LINES-2);
-       win_cols = min(total_cols+2, COLS-2);
+       win_lines = min(total_lines+4, lines-2);
+       win_cols = min(total_cols+2, columns-2);
        text_lines = max(win_lines-4, 0);
        text_cols = max(win_cols-2, 0);
 
        /* place window in middle of screen */
-       y = (LINES-win_lines)/2;
-       x = (COLS-win_cols)/2;
+       y = (lines-win_lines)/2;
+       x = (columns-win_cols)/2;
 
        win = newwin(win_lines, win_cols, y, x);
        keypad(win, TRUE);
index ecc5aa5f865db7d253facefc10cc77fc2404e41d..d550300ec00c34e5b1748478c6381341e9412e0b 100644 (file)
@@ -136,7 +136,7 @@ static struct property *sym_get_range_prop(struct symbol *sym)
        return NULL;
 }
 
-static int sym_get_range_val(struct symbol *sym, int base)
+static long sym_get_range_val(struct symbol *sym, int base)
 {
        sym_calc_value(sym);
        switch (sym->type) {
@@ -155,7 +155,7 @@ static int sym_get_range_val(struct symbol *sym, int base)
 static void sym_validate_range(struct symbol *sym)
 {
        struct property *prop;
-       int base, val, val2;
+       long base, val, val2;
        char str[64];
 
        switch (sym->type) {
@@ -179,9 +179,9 @@ static void sym_validate_range(struct symbol *sym)
                        return;
        }
        if (sym->type == S_INT)
-               sprintf(str, "%d", val2);
+               sprintf(str, "%ld", val2);
        else
-               sprintf(str, "0x%x", val2);
+               sprintf(str, "0x%lx", val2);
        sym->curr.val = strdup(str);
 }
 
@@ -300,6 +300,14 @@ void sym_calc_value(struct symbol *sym)
 
        if (sym->flags & SYMBOL_VALID)
                return;
+
+       if (sym_is_choice_value(sym) &&
+           sym->flags & SYMBOL_NEED_SET_CHOICE_VALUES) {
+               sym->flags &= ~SYMBOL_NEED_SET_CHOICE_VALUES;
+               prop = sym_get_choice_prop(sym);
+               sym_calc_value(prop_get_symbol(prop));
+       }
+
        sym->flags |= SYMBOL_VALID;
 
        oldval = sym->curr;
@@ -425,6 +433,9 @@ void sym_calc_value(struct symbol *sym)
 
        if (sym->flags & SYMBOL_AUTO)
                sym->flags &= ~SYMBOL_WRITE;
+
+       if (sym->flags & SYMBOL_NEED_SET_CHOICE_VALUES)
+               set_all_choice_values(sym);
 }
 
 void sym_clear_all_valid(void)
@@ -583,7 +594,7 @@ bool sym_string_valid(struct symbol *sym, const char *str)
 bool sym_string_within_range(struct symbol *sym, const char *str)
 {
        struct property *prop;
-       int val;
+       long val;
 
        switch (sym->type) {
        case S_STRING:
@@ -943,38 +954,98 @@ const char *sym_escape_string_value(const char *in)
        return res;
 }
 
+struct sym_match {
+       struct symbol   *sym;
+       off_t           so, eo;
+};
+
+/* Compare matched symbols as thus:
+ * - first, symbols that match exactly
+ * - then, alphabetical sort
+ */
+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;
+       int l1, l2;
+
+       /* Exact match:
+        * - if matched length on symbol s1 is the length of that symbol,
+        *   then this symbol should come first;
+        * - if matched length on symbol s2 is the length of that symbol,
+        *   then this symbol should come first.
+        * Note: since the search can be a regexp, both symbols may match
+        * exactly; if this is the case, we can't decide which comes first,
+        * and we fallback to sorting alphabetically.
+        */
+       l1 = s1->eo - s1->so;
+       l2 = s2->eo - s2->so;
+       if (l1 == strlen(s1->sym->name) && l2 != strlen(s2->sym->name))
+               return -1;
+       if (l1 != strlen(s1->sym->name) && l2 == strlen(s2->sym->name))
+               return 1;
+
+       /* As a fallback, sort symbols alphabetically */
+       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->so = match[0].rm_so;
+               tmp_sym_match->eo = match[0].rm_eo;
+               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;