Commit b202c0d5 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'kconfig' of git://git.kernel.org/pub/scm/linux/kernel/git/mmarek/kbuild

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
parents cb63fc26 b57caaae
...@@ -174,6 +174,19 @@ Searching in menuconfig: ...@@ -174,6 +174,19 @@ Searching in menuconfig:
/^hotplug /^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' User interface options for 'menuconfig'
......
#!/bin/bash #!/bin/bash
# Manipulate options in a .config file from the command line # Manipulate options in a .config file from the command line
myname=${0##*/}
# If no prefix forced, use the default CONFIG_ # If no prefix forced, use the default CONFIG_
CONFIG_="${CONFIG_-CONFIG_}" CONFIG_="${CONFIG_-CONFIG_}"
...@@ -8,7 +10,7 @@ usage() { ...@@ -8,7 +10,7 @@ usage() {
cat >&2 <<EOL cat >&2 <<EOL
Manipulate options in a .config file from the command line. Manipulate options in a .config file from the command line.
Usage: Usage:
config options command ... $myname options command ...
commands: commands:
--enable|-e option Enable option --enable|-e option Enable option
--disable|-d option Disable option --disable|-d option Disable option
...@@ -33,14 +35,14 @@ options: ...@@ -33,14 +35,14 @@ options:
--file config-file .config file to change (default .config) --file config-file .config file to change (default .config)
--keep-case|-k Keep next symbols' case (dont' upper-case it) --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. 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. the case of all following symbols unchanged.
config uses 'CONFIG_' as the default symbol prefix. Set the environment $myname uses 'CONFIG_' as the default symbol prefix. Set the environment
variable CONFIG_ to the prefix to use. Eg.: CONFIG_="FOO_" config ... variable CONFIG_ to the prefix to use. Eg.: CONFIG_="FOO_" $myname ...
EOL EOL
exit 1 exit 1
} }
......
...@@ -527,11 +527,12 @@ int main(int ac, char **av) ...@@ -527,11 +527,12 @@ int main(int ac, char **av)
seed_env = getenv("KCONFIG_SEED"); seed_env = getenv("KCONFIG_SEED");
if( seed_env && *seed_env ) { if( seed_env && *seed_env ) {
char *endp; char *endp;
int tmp = (int)strtol(seed_env, &endp, 10); int tmp = (int)strtol(seed_env, &endp, 0);
if (*endp == '\0') { if (*endp == '\0') {
seed = tmp; seed = tmp;
} }
} }
fprintf( stderr, "KCONFIG_SEED=0x%X\n", seed );
srand(seed); srand(seed);
break; break;
} }
...@@ -653,7 +654,8 @@ int main(int ac, char **av) ...@@ -653,7 +654,8 @@ int main(int ac, char **av)
conf_set_all_new_symbols(def_default); conf_set_all_new_symbols(def_default);
break; break;
case randconfig: 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; break;
case defconfig: case defconfig:
conf_set_all_new_symbols(def_default); conf_set_all_new_symbols(def_default);
......
...@@ -1040,7 +1040,7 @@ void conf_set_changed_callback(void (*fn)(void)) ...@@ -1040,7 +1040,7 @@ void conf_set_changed_callback(void (*fn)(void))
conf_changed_callback = fn; conf_changed_callback = fn;
} }
static void randomize_choice_values(struct symbol *csym) static bool randomize_choice_values(struct symbol *csym)
{ {
struct property *prop; struct property *prop;
struct symbol *sym; struct symbol *sym;
...@@ -1053,7 +1053,7 @@ static void randomize_choice_values(struct symbol *csym) ...@@ -1053,7 +1053,7 @@ static void randomize_choice_values(struct symbol *csym)
* In both cases stop. * In both cases stop.
*/ */
if (csym->curr.tri != yes) if (csym->curr.tri != yes)
return; return false;
prop = sym_get_choice_prop(csym); prop = sym_get_choice_prop(csym);
...@@ -1077,13 +1077,18 @@ static void randomize_choice_values(struct symbol *csym) ...@@ -1077,13 +1077,18 @@ static void randomize_choice_values(struct symbol *csym)
else { else {
sym->def[S_DEF_USER].tri = no; 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; csym->flags |= SYMBOL_DEF_USER;
/* clear VALID to get value calculated */ /* clear VALID to get value calculated */
csym->flags &= ~(SYMBOL_VALID); 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 property *prop;
struct symbol *sym; struct symbol *sym;
...@@ -1100,10 +1105,10 @@ static void set_all_choice_values(struct symbol *csym) ...@@ -1100,10 +1105,10 @@ static void set_all_choice_values(struct symbol *csym)
} }
csym->flags |= SYMBOL_DEF_USER; csym->flags |= SYMBOL_DEF_USER;
/* clear VALID to get value calculated */ /* 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; struct symbol *sym, *csym;
int i, cnt, pby, pty, ptm; /* pby: probability of boolean = y 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) ...@@ -1151,6 +1156,7 @@ void conf_set_all_new_symbols(enum conf_def_mode mode)
exit( 1 ); exit( 1 );
} }
} }
bool has_changed = false;
for_all_symbols(i, sym) { for_all_symbols(i, sym) {
if (sym_has_value(sym) || (sym->flags & SYMBOL_VALID)) if (sym_has_value(sym) || (sym->flags & SYMBOL_VALID))
...@@ -1158,6 +1164,7 @@ void conf_set_all_new_symbols(enum conf_def_mode mode) ...@@ -1158,6 +1164,7 @@ void conf_set_all_new_symbols(enum conf_def_mode mode)
switch (sym_get_type(sym)) { switch (sym_get_type(sym)) {
case S_BOOLEAN: case S_BOOLEAN:
case S_TRISTATE: case S_TRISTATE:
has_changed = true;
switch (mode) { switch (mode) {
case def_yes: case def_yes:
sym->def[S_DEF_USER].tri = yes; sym->def[S_DEF_USER].tri = yes;
...@@ -1202,14 +1209,26 @@ void conf_set_all_new_symbols(enum conf_def_mode mode) ...@@ -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, * selected in a choice block and we set it to yes,
* and the rest to no. * 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) { for_all_symbols(i, csym) {
if (sym_has_value(csym) || !sym_is_choice(csym)) if (sym_has_value(csym) || !sym_is_choice(csym))
continue; continue;
sym_calc_value(csym); sym_calc_value(csym);
if (mode == def_random) if (mode == def_random)
randomize_choice_values(csym); has_changed = randomize_choice_values(csym);
else else {
set_all_choice_values(csym); set_all_choice_values(csym);
has_changed = true;
}
} }
return has_changed;
} }
...@@ -106,6 +106,9 @@ struct symbol { ...@@ -106,6 +106,9 @@ struct symbol {
#define SYMBOL_DEF3 0x40000 /* symbol.def[S_DEF_3] is valid */ #define SYMBOL_DEF3 0x40000 /* symbol.def[S_DEF_3] is valid */
#define SYMBOL_DEF4 0x80000 /* symbol.def[S_DEF_4] 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_MAXLENGTH 256
#define SYMBOL_HASHSIZE 9973 #define SYMBOL_HASHSIZE 9973
......
...@@ -86,7 +86,8 @@ const char *conf_get_autoconfig_name(void); ...@@ -86,7 +86,8 @@ const char *conf_get_autoconfig_name(void);
char *conf_get_default_confname(void); char *conf_get_default_confname(void);
void sym_set_change_count(int count); void sym_set_change_count(int count);
void sym_add_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 { struct conf_printer {
void (*print_symbol)(FILE *, struct symbol *, const char *, void *); void (*print_symbol)(FILE *, struct symbol *, const char *, void *);
......
...@@ -14,6 +14,7 @@ P(conf_set_message_callback, void,(void (*fn)(const char *fmt, va_list ap))); ...@@ -14,6 +14,7 @@ P(conf_set_message_callback, void,(void (*fn)(const char *fmt, va_list ap)));
/* menu.c */ /* menu.c */
P(rootmenu,struct menu,); P(rootmenu,struct menu,);
P(menu_is_empty, bool, (struct menu *menu));
P(menu_is_visible, bool, (struct menu *menu)); P(menu_is_visible, bool, (struct menu *menu));
P(menu_has_prompt, bool, (struct menu *menu)); P(menu_has_prompt, bool, (struct menu *menu));
P(menu_get_prompt,const char *,(struct menu *menu)); P(menu_get_prompt,const char *,(struct menu *menu));
......
...@@ -132,16 +132,16 @@ int dialog_checklist(const char *title, const char *prompt, int height, ...@@ -132,16 +132,16 @@ int dialog_checklist(const char *title, const char *prompt, int height,
} }
do_resize: do_resize:
if (getmaxy(stdscr) < (height + 6)) if (getmaxy(stdscr) < (height + CHECKLIST_HEIGTH_MIN))
return -ERRDISPLAYTOOSMALL; return -ERRDISPLAYTOOSMALL;
if (getmaxx(stdscr) < (width + 6)) if (getmaxx(stdscr) < (width + CHECKLIST_WIDTH_MIN))
return -ERRDISPLAYTOOSMALL; return -ERRDISPLAYTOOSMALL;
max_choice = MIN(list_height, item_count()); max_choice = MIN(list_height, item_count());
/* center dialog box on screen */ /* center dialog box on screen */
x = (COLS - width) / 2; x = (getmaxx(stdscr) - width) / 2;
y = (LINES - height) / 2; y = (getmaxy(stdscr) - height) / 2;
draw_shadow(stdscr, y, x, height, width); draw_shadow(stdscr, y, x, height, width);
......
...@@ -200,6 +200,20 @@ int item_is_tag(char tag); ...@@ -200,6 +200,20 @@ int item_is_tag(char tag);
int on_key_esc(WINDOW *win); int on_key_esc(WINDOW *win);
int on_key_resize(void); 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); int init_dialog(const char *backtitle);
void set_dialog_backtitle(const char *backtitle); void set_dialog_backtitle(const char *backtitle);
void set_dialog_subtitles(struct subtitle_list *subtitles); void set_dialog_subtitles(struct subtitle_list *subtitles);
......
...@@ -56,14 +56,14 @@ int dialog_inputbox(const char *title, const char *prompt, int height, int width ...@@ -56,14 +56,14 @@ int dialog_inputbox(const char *title, const char *prompt, int height, int width
strcpy(instr, init); strcpy(instr, init);
do_resize: do_resize:
if (getmaxy(stdscr) <= (height - 2)) if (getmaxy(stdscr) <= (height - INPUTBOX_HEIGTH_MIN))
return -ERRDISPLAYTOOSMALL; return -ERRDISPLAYTOOSMALL;
if (getmaxx(stdscr) <= (width - 2)) if (getmaxx(stdscr) <= (width - INPUTBOX_WIDTH_MIN))
return -ERRDISPLAYTOOSMALL; return -ERRDISPLAYTOOSMALL;
/* center dialog box on screen */ /* center dialog box on screen */
x = (COLS - width) / 2; x = (getmaxx(stdscr) - width) / 2;
y = (LINES - height) / 2; y = (getmaxy(stdscr) - height) / 2;
draw_shadow(stdscr, y, x, height, width); draw_shadow(stdscr, y, x, height, width);
......
...@@ -193,7 +193,7 @@ int dialog_menu(const char *title, const char *prompt, ...@@ -193,7 +193,7 @@ int dialog_menu(const char *title, const char *prompt,
do_resize: do_resize:
height = getmaxy(stdscr); height = getmaxy(stdscr);
width = getmaxx(stdscr); width = getmaxx(stdscr);
if (height < 15 || width < 65) if (height < MENUBOX_HEIGTH_MIN || width < MENUBOX_WIDTH_MIN)
return -ERRDISPLAYTOOSMALL; return -ERRDISPLAYTOOSMALL;
height -= 4; height -= 4;
...@@ -203,8 +203,8 @@ int dialog_menu(const char *title, const char *prompt, ...@@ -203,8 +203,8 @@ int dialog_menu(const char *title, const char *prompt,
max_choice = MIN(menu_height, item_count()); max_choice = MIN(menu_height, item_count());
/* center dialog box on screen */ /* center dialog box on screen */
x = (COLS - width) / 2; x = (getmaxx(stdscr) - width) / 2;
y = (LINES - height) / 2; y = (getmaxy(stdscr) - height) / 2;
draw_shadow(stdscr, y, x, height, width); draw_shadow(stdscr, y, x, height, width);
......
...@@ -80,7 +80,7 @@ int dialog_textbox(const char *title, char *tbuf, int initial_height, ...@@ -80,7 +80,7 @@ int dialog_textbox(const char *title, char *tbuf, int initial_height,
do_resize: do_resize:
getmaxyx(stdscr, height, width); getmaxyx(stdscr, height, width);
if (height < 8 || width < 8) if (height < TEXTBOX_HEIGTH_MIN || width < TEXTBOX_WIDTH_MIN)
return -ERRDISPLAYTOOSMALL; return -ERRDISPLAYTOOSMALL;
if (initial_height != 0) if (initial_height != 0)
height = initial_height; height = initial_height;
...@@ -98,8 +98,8 @@ int dialog_textbox(const char *title, char *tbuf, int initial_height, ...@@ -98,8 +98,8 @@ int dialog_textbox(const char *title, char *tbuf, int initial_height,
width = 0; width = 0;
/* center dialog box on screen */ /* center dialog box on screen */
x = (COLS - width) / 2; x = (getmaxx(stdscr) - width) / 2;
y = (LINES - height) / 2; y = (getmaxy(stdscr) - height) / 2;
draw_shadow(stdscr, y, x, height, width); draw_shadow(stdscr, y, x, height, width);
......
...@@ -254,7 +254,12 @@ void attr_clear(WINDOW * win, int height, int width, chtype attr) ...@@ -254,7 +254,12 @@ void attr_clear(WINDOW * win, int height, int width, chtype attr)
void dialog_clear(void) 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 */ /* Display background title if it exists ... - SLH */
if (dlg.backtitle != NULL) { if (dlg.backtitle != NULL) {
int i, len = 0, skip = 0; int i, len = 0, skip = 0;
...@@ -269,10 +274,10 @@ void dialog_clear(void) ...@@ -269,10 +274,10 @@ void dialog_clear(void)
} }
wmove(stdscr, 1, 1); wmove(stdscr, 1, 1);
if (len > COLS - 2) { if (len > columns - 2) {
const char *ellipsis = "[...] "; const char *ellipsis = "[...] ";
waddstr(stdscr, 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) { for (pos = dlg.subtitles; pos != NULL; pos = pos->next) {
...@@ -298,7 +303,7 @@ void dialog_clear(void) ...@@ -298,7 +303,7 @@ void dialog_clear(void)
skip--; skip--;
} }
for (i = len + 1; i < COLS - 1; i++) for (i = len + 1; i < columns - 1; i++)
waddch(stdscr, ACS_HLINE); waddch(stdscr, ACS_HLINE);
} }
wnoutrefresh(stdscr); wnoutrefresh(stdscr);
...@@ -317,7 +322,7 @@ int init_dialog(const char *backtitle) ...@@ -317,7 +322,7 @@ int init_dialog(const char *backtitle)
getyx(stdscr, saved_y, saved_x); getyx(stdscr, saved_y, saved_x);
getmaxyx(stdscr, height, width); getmaxyx(stdscr, height, width);
if (height < 19 || width < 80) { if (height < WINDOW_HEIGTH_MIN || width < WINDOW_WIDTH_MIN) {
endwin(); endwin();
return -ERRDISPLAYTOOSMALL; return -ERRDISPLAYTOOSMALL;
} }
...@@ -371,27 +376,19 @@ void print_title(WINDOW *dialog, const char *title, int width) ...@@ -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 * 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 * 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. * 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) void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x)
{ {
int newl, cur_x, cur_y; int newl, cur_x, cur_y;
int i, prompt_len, room, wlen; int prompt_len, room, wlen;
char tempstr[MAX_LEN + 1], *word, *sp, *sp2; char tempstr[MAX_LEN + 1], *word, *sp, *sp2, *newline_separator = 0;
strcpy(tempstr, prompt); strcpy(tempstr, prompt);
prompt_len = strlen(tempstr); 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 */ if (prompt_len <= width - x * 2) { /* If prompt is short */
wmove(win, y, (width - prompt_len) / 2); wmove(win, y, (width - prompt_len) / 2);
waddstr(win, tempstr); waddstr(win, tempstr);
...@@ -401,7 +398,10 @@ void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x) ...@@ -401,7 +398,10 @@ void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x)
newl = 1; newl = 1;
word = tempstr; word = tempstr;
while (word && *word) { while (word && *word) {
sp = strchr(word, ' '); sp = strpbrk(word, "\n ");
if (sp && *sp == '\n')
newline_separator = sp;
if (sp) if (sp)
*sp++ = 0; *sp++ = 0;
...@@ -413,7 +413,7 @@ void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x) ...@@ -413,7 +413,7 @@ void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x)
if (wlen > room || if (wlen > room ||
(newl && wlen < 4 && sp (newl && wlen < 4 && sp
&& wlen + 1 + strlen(sp) > room && wlen + 1 + strlen(sp) > room
&& (!(sp2 = strchr(sp, ' ')) && (!(sp2 = strpbrk(sp, "\n "))
|| wlen + 1 + (sp2 - sp) > room))) { || wlen + 1 + (sp2 - sp) > room))) {
cur_y++; cur_y++;
cur_x = x; cur_x = x;
...@@ -421,7 +421,15 @@ void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int 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); wmove(win, cur_y, cur_x);
waddstr(win, word); waddstr(win, word);
getyx(win, cur_y, cur_x); getyx(win, cur_y, 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++; cur_x++;
if (sp && *sp == ' ') { if (sp && *sp == ' ') {
cur_x++; /* double space */ cur_x++; /* double space */
while (*++sp == ' ') ; while (*++sp == ' ') ;
......
...@@ -45,14 +45,14 @@ int dialog_yesno(const char *title, const char *prompt, int height, int width) ...@@ -45,14 +45,14 @@ int dialog_yesno(const char *title, const char *prompt, int height, int width)
WINDOW *dialog; WINDOW *dialog;
do_resize: do_resize:
if (getmaxy(stdscr) < (height + 4)) if (getmaxy(stdscr) < (height + YESNO_HEIGTH_MIN))
return -ERRDISPLAYTOOSMALL; return -ERRDISPLAYTOOSMALL;
if (getmaxx(stdscr) < (width + 4)) if (getmaxx(stdscr) < (width + YESNO_WIDTH_MIN))
return -ERRDISPLAYTOOSMALL; return -ERRDISPLAYTOOSMALL;
/* center dialog box on screen */ /* center dialog box on screen */
x = (COLS - width) / 2; x = (getmaxx(stdscr) - width) / 2;
y = (LINES - height) / 2; y = (getmaxy(stdscr) - height) / 2;
draw_shadow(stdscr, y, x, height, width); draw_shadow(stdscr, y, x, height, width);
......
...@@ -48,7 +48,7 @@ static const char mconf_readme[] = N_( ...@@ -48,7 +48,7 @@ static const char mconf_readme[] = N_(
"----------\n" "----------\n"
"o Use the Up/Down arrow keys (cursor keys) to highlight the item\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" " 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" "\n"
" Shortcut: Press the option's highlighted letter (hotkey).\n" " Shortcut: Press the option's highlighted letter (hotkey).\n"
" Pressing a hotkey more than once will sequence\n" " Pressing a hotkey more than once will sequence\n"
...@@ -176,7 +176,7 @@ static const char mconf_readme[] = N_( ...@@ -176,7 +176,7 @@ static const char mconf_readme[] = N_(
"\n"), "\n"),
menu_instructions[] = N_( menu_instructions[] = N_(
"Arrow keys navigate the menu. " "Arrow keys navigate the menu. "
"<Enter> selects submenus --->. " "<Enter> selects submenus ---> (or empty submenus ----). "
"Highlighted letters are hotkeys. " "Highlighted letters are hotkeys. "
"Pressing <Y> includes, <N> excludes, <M> modularizes features. " "Pressing <Y> includes, <N> excludes, <M> modularizes features. "
"Press <Esc><Esc> to exit, <?> for Help, </> for Search. " "Press <Esc><Esc> to exit, <?> for Help, </> for Search. "
...@@ -401,7 +401,7 @@ static void search_conf(void) ...@@ -401,7 +401,7 @@ static void search_conf(void)
struct subtitle_part stpart; struct subtitle_part stpart;
title = str_new(); 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_); "(with or without \"%s\")"), CONFIG_, CONFIG_);
again: again:
...@@ -498,8 +498,9 @@ static void build_conf(struct menu *menu) ...@@ -498,8 +498,9 @@ static void build_conf(struct menu *menu)
menu->data ? "-->" : "++>", menu->data ? "-->" : "++>",
indent + 1, ' ', prompt); indent + 1, ' ', prompt);
} else } 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_tag('m');
item_set_data(menu); item_set_data(menu);
if (single_menu_mode && menu->data) if (single_menu_mode && menu->data)
...@@ -630,7 +631,7 @@ static void build_conf(struct menu *menu) ...@@ -630,7 +631,7 @@ static void build_conf(struct menu *menu)
(sym_has_value(sym) || !sym_is_changable(sym)) ? (sym_has_value(sym) || !sym_is_changable(sym)) ?
"" : _(" (NEW)")); "" : _(" (NEW)"));
if (menu->prompt->type == P_MENU) { if (menu->prompt->type == P_MENU) {
item_add_str(" --->"); item_add_str(" %s", menu_is_empty(menu) ? "----" : "--->");
return; return;
} }
} }
...@@ -826,7 +827,9 @@ static void conf_choice(struct menu *menu) ...@@ -826,7 +827,9 @@ static void conf_choice(struct menu *menu)
dialog_clear(); dialog_clear();
res = dialog_checklist(prompt ? _(prompt) : _("Main Menu"), res = dialog_checklist(prompt ? _(prompt) : _("Main Menu"),
_(radiolist_instructions), _(radiolist_instructions),
15, 70, 6); MENUBOX_HEIGTH_MIN,
MENUBOX_WIDTH_MIN,
CHECKLIST_HEIGTH_MIN);
selected = item_activate_selected(); selected = item_activate_selected();
switch (res) { switch (res) {
case 0: case 0:
...@@ -957,8 +960,8 @@ static int handle_exit(void) ...@@ -957,8 +960,8 @@ static int handle_exit(void)
dialog_clear(); dialog_clear();
if (conf_get_changed()) if (conf_get_changed())
res = dialog_yesno(NULL, res = dialog_yesno(NULL,
_("Do you wish to save your new configuration ?\n" _("Do you wish to save your new configuration?\n"
"<ESC><ESC> to continue."), "(Press <ESC><ESC> to continue kernel configuration.)"),
6, 60); 6, 60);
else else
res = -1; res = -1;
......
...@@ -443,6 +443,22 @@ bool menu_has_prompt(struct menu *menu) ...@@ -443,6 +443,22 @@ bool menu_has_prompt(struct menu *menu)
return true; 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) bool menu_is_visible(struct menu *menu)
{ {
struct menu *child; struct menu *child;
......
...@@ -45,8 +45,8 @@ static const char nconf_global_help[] = N_( ...@@ -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" "<n> to remove it. You may press the <Space> key to cycle through the\n"
"available options.\n" "available options.\n"
"\n" "\n"
"A trailing \"--->\" designates a submenu.\n" "A trailing \"--->\" designates a submenu, a trailing \"----\" an\n"
"\n" "empty submenu.\n"
"\n" "\n"
"Menu navigation keys\n" "Menu navigation keys\n"
"----------------------------------------------------------------------\n" "----------------------------------------------------------------------\n"
...@@ -131,7 +131,7 @@ static const char nconf_global_help[] = N_( ...@@ -131,7 +131,7 @@ static const char nconf_global_help[] = N_(
"\n"), "\n"),
menu_no_f_instructions[] = N_( menu_no_f_instructions[] = N_(
"Legend: [*] built-in [ ] excluded <M> module < > module capable.\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" "\n"
"Use the following keys to navigate the menus:\n" "Use the following keys to navigate the menus:\n"
"Move up or down with <Up> and <Down>.\n" "Move up or down with <Up> and <Down>.\n"
...@@ -148,7 +148,7 @@ menu_no_f_instructions[] = N_( ...@@ -148,7 +148,7 @@ menu_no_f_instructions[] = N_(
"For help related to the current menu entry press <?> or <h>.\n"), "For help related to the current menu entry press <?> or <h>.\n"),
menu_instructions[] = N_( menu_instructions[] = N_(
"Legend: [*] built-in [ ] excluded <M> module < > module capable.\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" "\n"
"Use the following keys to navigate the menus:\n" "Use the following keys to navigate the menus:\n"
"Move up or down with <Up> or <Down>.\n" "Move up or down with <Up> or <Down>.\n"
...@@ -365,15 +365,16 @@ static void print_function_line(void) ...@@ -365,15 +365,16 @@ static void print_function_line(void)
int i; int i;
int offset = 1; int offset = 1;
const int skip = 1; const int skip = 1;
int lines = getmaxy(stdscr);
for (i = 0; i < function_keys_num; i++) { for (i = 0; i < function_keys_num; i++) {
(void) wattrset(main_window, attributes[FUNCTION_HIGHLIGHT]); (void) wattrset(main_window, attributes[FUNCTION_HIGHLIGHT]);
mvwprintw(main_window, LINES-3, offset, mvwprintw(main_window, lines-3, offset,
"%s", "%s",
function_keys[i].key_str); function_keys[i].key_str);
(void) wattrset(main_window, attributes[FUNCTION_TEXT]); (void) wattrset(main_window, attributes[FUNCTION_TEXT]);
offset += strlen(function_keys[i].key_str); offset += strlen(function_keys[i].key_str);
mvwprintw(main_window, LINES-3, mvwprintw(main_window, lines-3,
offset, "%s", offset, "%s",
function_keys[i].func); function_keys[i].func);
offset += strlen(function_keys[i].func) + skip; offset += strlen(function_keys[i].func) + skip;
...@@ -694,7 +695,7 @@ static void search_conf(void) ...@@ -694,7 +695,7 @@ static void search_conf(void)
int dres; int dres;
title = str_new(); 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_); "(with or without \"%s\")"), CONFIG_, CONFIG_);
again: again:
...@@ -759,9 +760,9 @@ static void build_conf(struct menu *menu) ...@@ -759,9 +760,9 @@ static void build_conf(struct menu *menu)
indent + 1, ' ', prompt); indent + 1, ' ', prompt);
} else } else
item_make(menu, 'm', item_make(menu, 'm',
" %*c%s --->", " %*c%s %s",
indent + 1, indent + 1, ' ', prompt,
' ', prompt); menu_is_empty(menu) ? "----" : "--->");
if (single_menu_mode && menu->data) if (single_menu_mode && menu->data)
goto conf_childs; goto conf_childs;
...@@ -903,7 +904,7 @@ static void build_conf(struct menu *menu) ...@@ -903,7 +904,7 @@ static void build_conf(struct menu *menu)
(sym_has_value(sym) || !sym_is_changable(sym)) ? (sym_has_value(sym) || !sym_is_changable(sym)) ?
"" : _(" (NEW)")); "" : _(" (NEW)"));
if (menu->prompt && menu->prompt->type == P_MENU) { if (menu->prompt && menu->prompt->type == P_MENU) {
item_add_str(" --->"); item_add_str(" %s", menu_is_empty(menu) ? "----" : "--->");
return; return;
} }
} }
...@@ -954,7 +955,7 @@ static void show_menu(const char *prompt, const char *instructions, ...@@ -954,7 +955,7 @@ static void show_menu(const char *prompt, const char *instructions,
clear(); clear();
(void) wattrset(main_window, attributes[NORMAL]); (void) wattrset(main_window, attributes[NORMAL]);
print_in_middle(stdscr, 1, 0, COLS, print_in_middle(stdscr, 1, 0, getmaxx(stdscr),
menu_backtitle, menu_backtitle,
attributes[MAIN_HEADING]); attributes[MAIN_HEADING]);
...@@ -1455,14 +1456,18 @@ static void conf_save(void) ...@@ -1455,14 +1456,18 @@ static void conf_save(void)
void setup_windows(void) void setup_windows(void)
{ {
int lines, columns;
getmaxyx(stdscr, lines, columns);
if (main_window != NULL) if (main_window != NULL)
delwin(main_window); delwin(main_window);
/* set up the menu and menu 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); keypad(main_window, TRUE);
mwin_max_lines = LINES-7; mwin_max_lines = lines-7;
mwin_max_cols = COLS-6; mwin_max_cols = columns-6;
/* panels order is from bottom to top */ /* panels order is from bottom to top */
new_panel(main_window); new_panel(main_window);
...@@ -1470,6 +1475,7 @@ void setup_windows(void) ...@@ -1470,6 +1475,7 @@ void setup_windows(void)
int main(int ac, char **av) int main(int ac, char **av)
{ {
int lines, columns;
char *mode; char *mode;
setlocale(LC_ALL, ""); setlocale(LC_ALL, "");
...@@ -1495,7 +1501,8 @@ int main(int ac, char **av) ...@@ -1495,7 +1501,8 @@ int main(int ac, char **av)
keypad(stdscr, TRUE); keypad(stdscr, TRUE);
curs_set(0); curs_set(0);
if (COLS < 75 || LINES < 20) { getmaxyx(stdscr, lines, columns);
if (columns < 75 || lines < 20) {
endwin(); endwin();
printf("Your terminal should have at " printf("Your terminal should have at "
"least 20 lines and 75 columns\n"); "least 20 lines and 75 columns\n");
......
...@@ -276,8 +276,8 @@ int btn_dialog(WINDOW *main_window, const char *msg, int btn_num, ...) ...@@ -276,8 +276,8 @@ int btn_dialog(WINDOW *main_window, const char *msg, int btn_num, ...)
total_width = max(msg_width, btns_width); total_width = max(msg_width, btns_width);
/* place dialog in middle of screen */ /* place dialog in middle of screen */
y = (LINES-(msg_lines+4))/2; y = (getmaxy(stdscr)-(msg_lines+4))/2;
x = (COLS-(total_width+4))/2; x = (getmaxx(stdscr)-(total_width+4))/2;
/* create the windows */ /* create the windows */
...@@ -387,8 +387,8 @@ int dialog_inputbox(WINDOW *main_window, ...@@ -387,8 +387,8 @@ int dialog_inputbox(WINDOW *main_window,
prompt_width = max(prompt_width, strlen(title)); prompt_width = max(prompt_width, strlen(title));
/* place dialog in middle of screen */ /* place dialog in middle of screen */
y = (LINES-(prompt_lines+4))/2; y = (getmaxy(stdscr)-(prompt_lines+4))/2;
x = (COLS-(prompt_width+4))/2; x = (getmaxx(stdscr)-(prompt_width+4))/2;
strncpy(result, init, *result_len); strncpy(result, init, *result_len);
...@@ -545,7 +545,7 @@ void show_scroll_win(WINDOW *main_window, ...@@ -545,7 +545,7 @@ void show_scroll_win(WINDOW *main_window,
{ {
int res; int res;
int total_lines = get_line_no(text); int total_lines = get_line_no(text);
int x, y; int x, y, lines, columns;
int start_x = 0, start_y = 0; int start_x = 0, start_y = 0;
int text_lines = 0, text_cols = 0; int text_lines = 0, text_cols = 0;
int total_cols = 0; int total_cols = 0;
...@@ -556,6 +556,8 @@ void show_scroll_win(WINDOW *main_window, ...@@ -556,6 +556,8 @@ void show_scroll_win(WINDOW *main_window,
WINDOW *pad; WINDOW *pad;
PANEL *panel; PANEL *panel;
getmaxyx(stdscr, lines, columns);
/* find the widest line of msg: */ /* find the widest line of msg: */
total_lines = get_line_no(text); total_lines = get_line_no(text);
for (i = 0; i < total_lines; i++) { for (i = 0; i < total_lines; i++) {
...@@ -569,14 +571,14 @@ void show_scroll_win(WINDOW *main_window, ...@@ -569,14 +571,14 @@ void show_scroll_win(WINDOW *main_window,
(void) wattrset(pad, attributes[SCROLLWIN_TEXT]); (void) wattrset(pad, attributes[SCROLLWIN_TEXT]);
fill_window(pad, text); fill_window(pad, text);
win_lines = min(total_lines+4, LINES-2); win_lines = min(total_lines+4, lines-2);
win_cols = min(total_cols+2, COLS-2); win_cols = min(total_cols+2, columns-2);
text_lines = max(win_lines-4, 0); text_lines = max(win_lines-4, 0);
text_cols = max(win_cols-2, 0); text_cols = max(win_cols-2, 0);
/* place window in middle of screen */ /* place window in middle of screen */
y = (LINES-win_lines)/2; y = (lines-win_lines)/2;
x = (COLS-win_cols)/2; x = (columns-win_cols)/2;
win = newwin(win_lines, win_cols, y, x); win = newwin(win_lines, win_cols, y, x);
keypad(win, TRUE); keypad(win, TRUE);
......
...@@ -136,7 +136,7 @@ static struct property *sym_get_range_prop(struct symbol *sym) ...@@ -136,7 +136,7 @@ static struct property *sym_get_range_prop(struct symbol *sym)
return NULL; 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); sym_calc_value(sym);
switch (sym->type) { switch (sym->type) {
...@@ -155,7 +155,7 @@ static int sym_get_range_val(struct symbol *sym, int base) ...@@ -155,7 +155,7 @@ static int sym_get_range_val(struct symbol *sym, int base)
static void sym_validate_range(struct symbol *sym) static void sym_validate_range(struct symbol *sym)
{ {
struct property *prop; struct property *prop;
int base, val, val2; long base, val, val2;
char str[64]; char str[64];
switch (sym->type) { switch (sym->type) {
...@@ -179,9 +179,9 @@ static void sym_validate_range(struct symbol *sym) ...@@ -179,9 +179,9 @@ static void sym_validate_range(struct symbol *sym)
return; return;
} }
if (sym->type == S_INT) if (sym->type == S_INT)
sprintf(str, "%d", val2); sprintf(str, "%ld", val2);
else else
sprintf(str, "0x%x", val2); sprintf(str, "0x%lx", val2);
sym->curr.val = strdup(str); sym->curr.val = strdup(str);
} }
...@@ -300,6 +300,14 @@ void sym_calc_value(struct symbol *sym) ...@@ -300,6 +300,14 @@ void sym_calc_value(struct symbol *sym)
if (sym->flags & SYMBOL_VALID) if (sym->flags & SYMBOL_VALID)
return; 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; sym->flags |= SYMBOL_VALID;
oldval = sym->curr; oldval = sym->curr;
...@@ -425,6 +433,9 @@ void sym_calc_value(struct symbol *sym) ...@@ -425,6 +433,9 @@ void sym_calc_value(struct symbol *sym)
if (sym->flags & SYMBOL_AUTO) if (sym->flags & SYMBOL_AUTO)
sym->flags &= ~SYMBOL_WRITE; sym->flags &= ~SYMBOL_WRITE;
if (sym->flags & SYMBOL_NEED_SET_CHOICE_VALUES)
set_all_choice_values(sym);
} }
void sym_clear_all_valid(void) void sym_clear_all_valid(void)
...@@ -583,7 +594,7 @@ bool sym_string_valid(struct symbol *sym, const char *str) ...@@ -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) bool sym_string_within_range(struct symbol *sym, const char *str)
{ {
struct property *prop; struct property *prop;
int val; long val;
switch (sym->type) { switch (sym->type) {
case S_STRING: case S_STRING:
...@@ -943,38 +954,98 @@ const char *sym_escape_string_value(const char *in) ...@@ -943,38 +954,98 @@ const char *sym_escape_string_value(const char *in)
return res; 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_re_search(const char *pattern)
{ {
struct symbol *sym, **sym_arr = NULL; struct symbol *sym, **sym_arr = NULL;
struct sym_match **sym_match_arr = NULL;
int i, cnt, size; int i, cnt, size;
regex_t re; regex_t re;
regmatch_t match[1];
cnt = size = 0; cnt = size = 0;
/* Skip if empty */ /* Skip if empty */
if (strlen(pattern) == 0) if (strlen(pattern) == 0)
return NULL; return NULL;
if (regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB|REG_ICASE)) if (regcomp(&re, pattern, REG_EXTENDED|REG_ICASE))
return NULL; return NULL;
for_all_symbols(i, sym) { for_all_symbols(i, sym) {
struct sym_match *tmp_sym_match;
if (sym->flags & SYMBOL_CONST || !sym->name) if (sym->flags & SYMBOL_CONST || !sym->name)
continue; continue;
if (regexec(&re, sym->name, 0, NULL, 0)) if (regexec(&re, sym->name, 1, match, 0))
continue; continue;
if (cnt + 1 >= size) { if (cnt + 1 >= size) {
void *tmp = sym_arr; void *tmp;
size += 16; size += 16;
sym_arr = realloc(sym_arr, size * sizeof(struct symbol *)); tmp = realloc(sym_match_arr, size * sizeof(struct sym_match *));
if (!sym_arr) { if (!tmp) {
free(tmp); goto sym_re_search_free;
return NULL;
} }
sym_match_arr = tmp;
} }
sym_calc_value(sym); sym_calc_value(sym);
sym_arr[cnt++] = sym; tmp_sym_match = (struct sym_match*)malloc(sizeof(struct sym_match));
} if (!tmp_sym_match)
if (sym_arr) 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_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_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); regfree(&re);
return sym_arr; return sym_arr;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment