build: add new menuconfig code based on linux 3.9

SVN-Revision: 36361
This commit is contained in:
Felix Fietkau 2013-04-18 12:05:16 +00:00
parent 97e7fdf6fd
commit 9d5510a500
35 changed files with 5827 additions and 3897 deletions

View file

@ -89,10 +89,15 @@ config-clean: FORCE
defconfig: scripts/config/conf prepare-tmpinfo FORCE defconfig: scripts/config/conf prepare-tmpinfo FORCE
touch .config touch .config
$< -D .config Config.in $< --defconfig .config Config.in
confdefault-y=allyes
confdefault-m=allmod
confdefault-n=allno
confdefault:=$(confdefault-$(CONFDEFAULT))
oldconfig: scripts/config/conf prepare-tmpinfo FORCE oldconfig: scripts/config/conf prepare-tmpinfo FORCE
$< -$(if $(CONFDEFAULT),$(CONFDEFAULT),o) Config.in $< --$(if $(confdefault),$(confdefault),old)config Config.in
menuconfig: scripts/config/mconf prepare-tmpinfo FORCE menuconfig: scripts/config/mconf prepare-tmpinfo FORCE
if [ \! -e .config -a -e $(HOME)/.openwrt/defconfig ]; then \ if [ \! -e .config -a -e $(HOME)/.openwrt/defconfig ]; then \
@ -147,7 +152,7 @@ prereq:: prepare-tmpinfo .config
@+$(PREP_MK) $(NO_TRACE_MAKE) -r -s prereq @+$(PREP_MK) $(NO_TRACE_MAKE) -r -s prereq
@( \ @( \
cp .config tmp/.config; \ cp .config tmp/.config; \
./scripts/config/conf -D tmp/.config -w tmp/.config Config.in > /dev/null 2>&1; \ ./scripts/config/conf --defconfig tmp/.config -w tmp/.config Config.in > /dev/null 2>&1; \
if ./scripts/kconfig.pl '>' .config tmp/.config | grep -q CONFIG; then \ if ./scripts/kconfig.pl '>' .config tmp/.config | grep -q CONFIG; then \
printf "$(_R)WARNING: your configuration is out of sync. Please run make menuconfig, oldconfig or defconfig!$(_N)\n" >&2; \ printf "$(_R)WARNING: your configuration is out of sync. Please run make menuconfig, oldconfig or defconfig!$(_N)\n" >&2; \
fi \ fi \

View file

@ -13,41 +13,39 @@
# Platform specific fixes # Platform specific fixes
# #
# FreeBSD # FreeBSD
export CFLAGS+=-DKBUILD_NO_NLS
check_lxdialog = $(shell $(SHELL) $(CURDIR)/lxdialog/check-lxdialog.sh -$(1))
export CFLAGS += -DKBUILD_NO_NLS -I. $(call check_lxdialog,ccflags)
conf-objs := conf.o zconf.tab.o conf-objs := conf.o zconf.tab.o
mconf-objs := mconf.o zconf.tab.o mconf-objs := mconf.o zconf.tab.o
lxdialog-objs := \
lxdialog/checklist.o lxdialog/util.o lxdialog/inputbox.o \
lxdialog/textbox.o lxdialog/yesno.o lxdialog/menubox.o
clean-files := lkc_defs.h qconf.moc .tmp_qtcheck \ clean-files := zconf.tab.c lex.zconf.c zconf.hash.c
.tmp_gtkcheck zconf.tab.c lex.zconf.c zconf.hash.c
all: conf mconf lxdialog/lxdialog all: conf mconf
lxdialog/lxdialog:
$(MAKE) -C lxdialog
conf: $(conf-objs) conf: $(conf-objs)
mconf: $(mconf-objs) mconf: $(mconf-objs) $(lxdialog-objs)
$(CC) -o $@ $^ $(call check_lxdialog,ldflags $(CC))
clean: clean:
rm -f *.o $(clean-files) conf mconf rm -f *.o lxdialog/*.o $(clean-files) conf mconf
$(MAKE) -C lxdialog clean
zconf.tab.o: lex.zconf.c zconf.hash.c confdata.c zconf.tab.o: zconf.lex.c zconf.hash.c confdata.c
kconfig_load.o: lkc_defs.h kconfig_load.o: lkc_defs.h
lkc_defs.h: $(src)/lkc_proto.h
sed < $< > $@ 's/P(\([^,]*\),.*/#define \1 (\*\1_p)/'
zconf.tab.c: zconf.y zconf.tab.c: zconf.y
lex.zconf.c: zconf.l zconf.lex.c: zconf.l
zconf.hash.c: zconf.gperf zconf.hash.c: zconf.gperf
%.tab.c: %.y %.tab.c: %.y
cp $@_shipped $@ || bison -l -b $* -p $(notdir $*) $< cp $@_shipped $@ || bison -l -b $* -p $(notdir $*) $<
lex.%.c: %.l %.lex.c: %.l
cp $@_shipped $@ || flex -L -P$(notdir $*) -o$@ $< cp $@_shipped $@ || flex -L -P$(notdir $*) -o$@ $<
%.hash.c: %.gperf %.hash.c: %.gperf

View file

@ -1,2 +1,2 @@
These files were taken from the Linux 2.6.16.7 Kernel These files were taken from the Linux 3.9 Kernel
Configuration System and modified for the OpenWrt Buildroot. Configuration System and modified for the OpenWrt Buildroot.

View file

@ -3,38 +3,55 @@
* Released under the terms of the GNU GPL v2.0. * Released under the terms of the GNU GPL v2.0.
*/ */
#include <locale.h>
#include <ctype.h> #include <ctype.h>
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h>
#include <time.h> #include <time.h>
#include <unistd.h>
#include <getopt.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/time.h>
#define LKC_DIRECT_LINK
#include "lkc.h" #include "lkc.h"
static void conf(struct menu *menu); static void conf(struct menu *menu);
static void check_conf(struct menu *menu); static void check_conf(struct menu *menu);
static void xfgets(char *str, int size, FILE *in);
enum { enum input_mode {
ask_all, oldaskconfig,
ask_new, silentoldconfig,
ask_silent, oldconfig,
set_default, allnoconfig,
set_yes, allyesconfig,
set_mod, allmodconfig,
set_no, alldefconfig,
set_random randconfig,
} input_mode = ask_all; defconfig,
char *defconfig_file; savedefconfig,
listnewconfig,
olddefconfig,
} input_mode = oldaskconfig;
static int indent = 1; static int indent = 1;
static int tty_stdio;
static int valid_stdin = 1; static int valid_stdin = 1;
static int sync_kconfig;
static int conf_cnt; static int conf_cnt;
static char line[128]; static char line[128];
static struct menu *rootEntry; static struct menu *rootEntry;
static char nohelp_text[] = N_("Sorry, no help available for this option yet.\n"); static void print_help(struct menu *menu)
{
struct gstr help = str_new();
menu_get_ext_help(menu, &help);
printf("\n%s\n", str_get(&help));
str_free(&help);
}
static void strip(char *str) static void strip(char *str)
{ {
@ -55,7 +72,7 @@ static void strip(char *str)
static void check_stdin(void) static void check_stdin(void)
{ {
if (!valid_stdin && input_mode == ask_silent) { if (!valid_stdin) {
printf(_("aborted!\n\n")); printf(_("aborted!\n\n"));
printf(_("Console input/output is redirected. ")); printf(_("Console input/output is redirected. "));
printf(_("Run 'make oldconfig' to update configuration.\n\n")); printf(_("Run 'make oldconfig' to update configuration.\n\n"));
@ -63,27 +80,12 @@ static void check_stdin(void)
} }
} }
static char *fgets_check_stream(char *s, int size, FILE *stream) static int conf_askvalue(struct symbol *sym, const char *def)
{
char *ret = fgets(s, size, stream);
if (ret == NULL && feof(stream)) {
printf(_("aborted!\n\n"));
printf(_("Console input is closed. "));
printf(_("Run 'make oldconfig' to update configuration.\n\n"));
exit(1);
}
return ret;
}
static void conf_askvalue(struct symbol *sym, const char *def)
{ {
enum symbol_type type = sym_get_type(sym); enum symbol_type type = sym_get_type(sym);
tristate val;
if (!sym_has_value(sym)) if (!sym_has_value(sym))
printf("(NEW) "); printf(_("(NEW) "));
line[0] = '\n'; line[0] = '\n';
line[1] = 0; line[1] = 0;
@ -92,33 +94,24 @@ static void conf_askvalue(struct symbol *sym, const char *def)
printf("%s\n", def); printf("%s\n", def);
line[0] = '\n'; line[0] = '\n';
line[1] = 0; line[1] = 0;
return; return 0;
} }
switch (input_mode) { switch (input_mode) {
case set_no: case oldconfig:
case set_mod: case silentoldconfig:
case set_yes:
case set_random:
if (sym_has_value(sym)) { if (sym_has_value(sym)) {
printf("%s\n", def); printf("%s\n", def);
return; return 0;
}
break;
case ask_new:
case ask_silent:
if (sym_has_value(sym)) {
printf("%s\n", def);
return;
} }
check_stdin(); check_stdin();
case ask_all: /* fall through */
case oldaskconfig:
fflush(stdout); fflush(stdout);
fgets_check_stream(line, 128, stdin); xfgets(line, 128, stdin);
return; if (!tty_stdio)
case set_default: printf("\n");
printf("%s\n", def); return 1;
return;
default: default:
break; break;
} }
@ -128,84 +121,38 @@ static void conf_askvalue(struct symbol *sym, const char *def)
case S_HEX: case S_HEX:
case S_STRING: case S_STRING:
printf("%s\n", def); printf("%s\n", def);
return; return 1;
default: default:
; ;
} }
switch (input_mode) {
case set_yes:
if (sym_tristate_within_range(sym, yes)) {
line[0] = 'y';
line[1] = '\n';
line[2] = 0;
break;
}
case set_mod:
if (type == S_TRISTATE) {
if (sym_tristate_within_range(sym, mod)) {
line[0] = 'm';
line[1] = '\n';
line[2] = 0;
break;
}
} else {
if (sym_tristate_within_range(sym, yes)) {
line[0] = 'y';
line[1] = '\n';
line[2] = 0;
break;
}
}
case set_no:
if (sym_tristate_within_range(sym, no)) {
line[0] = 'n';
line[1] = '\n';
line[2] = 0;
break;
}
case set_random:
do {
val = (tristate)(random() % 3);
} while (!sym_tristate_within_range(sym, val));
switch (val) {
case no: line[0] = 'n'; break;
case mod: line[0] = 'm'; break;
case yes: line[0] = 'y'; break;
}
line[1] = '\n';
line[2] = 0;
break;
default:
break;
}
printf("%s", line); printf("%s", line);
return 1;
} }
int conf_string(struct menu *menu) static int conf_string(struct menu *menu)
{ {
struct symbol *sym = menu->sym; struct symbol *sym = menu->sym;
const char *def, *help; const char *def;
while (1) { while (1) {
printf("%*s%s ", indent - 1, "", menu->prompt->text); printf("%*s%s ", indent - 1, "", _(menu->prompt->text));
printf("(%s) ", sym->name); printf("(%s) ", sym->name);
def = sym_get_string_value(sym); def = sym_get_string_value(sym);
if (sym_get_string_value(sym)) if (sym_get_string_value(sym))
printf("[%s] ", def); printf("[%s] ", def);
conf_askvalue(sym, def); if (!conf_askvalue(sym, def))
return 0;
switch (line[0]) { switch (line[0]) {
case '\n': case '\n':
break; break;
case '?': case '?':
/* print help */ /* print help */
if (line[1] == '\n') { if (line[1] == '\n') {
help = nohelp_text; print_help(menu);
if (menu->sym->help)
help = menu->sym->help;
printf("\n%s\n", menu->sym->help);
def = NULL; def = NULL;
break; break;
} }
/* fall through */
default: default:
line[strlen(line)-1] = 0; line[strlen(line)-1] = 0;
def = line; def = line;
@ -218,15 +165,12 @@ int conf_string(struct menu *menu)
static int conf_sym(struct menu *menu) static int conf_sym(struct menu *menu)
{ {
struct symbol *sym = menu->sym; struct symbol *sym = menu->sym;
int type;
tristate oldval, newval; tristate oldval, newval;
const char *help;
while (1) { while (1) {
printf("%*s%s ", indent - 1, "", menu->prompt->text); printf("%*s%s ", indent - 1, "", _(menu->prompt->text));
if (sym->name) if (sym->name)
printf("(%s) ", sym->name); printf("(%s) ", sym->name);
type = sym_get_type(sym);
putchar('['); putchar('[');
oldval = sym_get_tristate_value(sym); oldval = sym_get_tristate_value(sym);
switch (oldval) { switch (oldval) {
@ -246,10 +190,11 @@ static int conf_sym(struct menu *menu)
printf("/m"); printf("/m");
if (oldval != yes && sym_tristate_within_range(sym, yes)) if (oldval != yes && sym_tristate_within_range(sym, yes))
printf("/y"); printf("/y");
if (sym->help) if (menu_has_help(menu))
printf("/?"); printf("/?");
printf("] "); printf("] ");
conf_askvalue(sym, sym_get_string_value(sym)); if (!conf_askvalue(sym, sym_get_string_value(sym)))
return 0;
strip(line); strip(line);
switch (line[0]) { switch (line[0]) {
@ -282,10 +227,7 @@ static int conf_sym(struct menu *menu)
if (sym_set_tristate_value(sym, newval)) if (sym_set_tristate_value(sym, newval))
return 0; return 0;
help: help:
help = nohelp_text; print_help(menu);
if (sym->help)
help = sym->help;
printf("\n%s\n", help);
} }
} }
@ -293,11 +235,9 @@ static int conf_choice(struct menu *menu)
{ {
struct symbol *sym, *def_sym; struct symbol *sym, *def_sym;
struct menu *child; struct menu *child;
int type;
bool is_new; bool is_new;
sym = menu->sym; sym = menu->sym;
type = sym_get_type(sym);
is_new = !sym_has_value(sym); is_new = !sym_has_value(sym);
if (sym_is_changable(sym)) { if (sym_is_changable(sym)) {
conf_sym(menu); conf_sym(menu);
@ -315,7 +255,7 @@ static int conf_choice(struct menu *menu)
case no: case no:
return 1; return 1;
case mod: case mod:
printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu)); printf("%*s%s\n", indent - 1, "", _(menu_get_prompt(menu)));
return 0; return 0;
case yes: case yes:
break; break;
@ -325,16 +265,15 @@ static int conf_choice(struct menu *menu)
while (1) { while (1) {
int cnt, def; int cnt, def;
printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu)); printf("%*s%s\n", indent - 1, "", _(menu_get_prompt(menu)));
def_sym = sym_get_choice_value(sym); def_sym = sym_get_choice_value(sym);
cnt = def = 0; cnt = def = 0;
line[0] = '0'; line[0] = 0;
line[1] = 0;
for (child = menu->list; child; child = child->next) { for (child = menu->list; child; child = child->next) {
if (!menu_is_visible(child)) if (!menu_is_visible(child))
continue; continue;
if (!child->sym) { if (!child->sym) {
printf("%*c %s\n", indent, '*', menu_get_prompt(child)); printf("%*c %s\n", indent, '*', _(menu_get_prompt(child)));
continue; continue;
} }
cnt++; cnt++;
@ -343,38 +282,38 @@ static int conf_choice(struct menu *menu)
printf("%*c", indent, '>'); printf("%*c", indent, '>');
} else } else
printf("%*c", indent, ' '); printf("%*c", indent, ' ');
printf(" %d. %s", cnt, menu_get_prompt(child)); printf(" %d. %s", cnt, _(menu_get_prompt(child)));
if (child->sym->name) if (child->sym->name)
printf(" (%s)", child->sym->name); printf(" (%s)", child->sym->name);
if (!sym_has_value(child->sym)) if (!sym_has_value(child->sym))
printf(" (NEW)"); printf(_(" (NEW)"));
printf("\n"); printf("\n");
} }
printf("%*schoice", indent - 1, ""); printf(_("%*schoice"), indent - 1, "");
if (cnt == 1) { if (cnt == 1) {
printf("[1]: 1\n"); printf("[1]: 1\n");
goto conf_childs; goto conf_childs;
} }
printf("[1-%d", cnt); printf("[1-%d", cnt);
if (sym->help) if (menu_has_help(menu))
printf("?"); printf("?");
printf("]: "); printf("]: ");
switch (input_mode) { switch (input_mode) {
case ask_new: case oldconfig:
case ask_silent: case silentoldconfig:
if (!is_new) { if (!is_new) {
cnt = def; cnt = def;
printf("%d\n", cnt); printf("%d\n", cnt);
break; break;
} }
check_stdin(); check_stdin();
case ask_all: /* fall through */
case oldaskconfig:
fflush(stdout); fflush(stdout);
fgets_check_stream(line, 128, stdin); xfgets(line, 128, stdin);
strip(line); strip(line);
if (line[0] == '?') { if (line[0] == '?') {
printf("\n%s\n", menu->sym->help ? print_help(menu);
menu->sym->help : nohelp_text);
continue; continue;
} }
if (!line[0]) if (!line[0])
@ -384,14 +323,7 @@ static int conf_choice(struct menu *menu)
else else
continue; continue;
break; break;
case set_random: default:
def = (random() % cnt) + 1;
case set_default:
case set_yes:
case set_mod:
case set_no:
cnt = def;
printf("%d\n", cnt);
break; break;
} }
@ -404,15 +336,14 @@ static int conf_choice(struct menu *menu)
} }
if (!child) if (!child)
continue; continue;
if (line[strlen(line) - 1] == '?') { if (line[0] && line[strlen(line) - 1] == '?') {
printf("\n%s\n", child->sym->help ? print_help(child);
child->sym->help : nohelp_text);
continue; continue;
} }
sym_set_choice_value(sym, child->sym); sym_set_choice_value(sym, child->sym);
if (child->list) { for (child = child->list; child; child = child->next) {
indent += 2; indent += 2;
conf(child->list); conf(child);
indent -= 2; indent -= 2;
} }
return 1; return 1;
@ -435,16 +366,20 @@ static void conf(struct menu *menu)
switch (prop->type) { switch (prop->type) {
case P_MENU: case P_MENU:
if (input_mode == ask_silent && rootEntry != menu) { if ((input_mode == silentoldconfig ||
input_mode == listnewconfig ||
input_mode == olddefconfig) &&
rootEntry != menu) {
check_conf(menu); check_conf(menu);
return; return;
} }
/* fall through */
case P_COMMENT: case P_COMMENT:
prompt = menu_get_prompt(menu); prompt = menu_get_prompt(menu);
if (prompt) if (prompt)
printf("%*c\n%*c %s\n%*c\n", printf("%*c\n%*c %s\n%*c\n",
indent, '*', indent, '*',
indent, '*', prompt, indent, '*', _(prompt),
indent, '*'); indent, '*');
default: default:
; ;
@ -493,10 +428,16 @@ static void check_conf(struct menu *menu)
if (sym && !sym_has_value(sym)) { if (sym && !sym_has_value(sym)) {
if (sym_is_changable(sym) || if (sym_is_changable(sym) ||
(sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)) { (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)) {
if (!conf_cnt++) if (input_mode == listnewconfig) {
printf(_("*\n* Restart config...\n*\n")); if (sym->name && !sym_is_choice_value(sym)) {
rootEntry = menu_get_parent_menu(menu); printf("%s%s\n", CONFIG_, sym->name);
conf(rootEntry); }
} else if (input_mode != olddefconfig) {
if (!conf_cnt++)
printf(_("*\n* Restart config...\n*\n"));
rootEntry = menu_get_parent_menu(menu);
conf(rootEntry);
}
} }
} }
@ -504,110 +445,242 @@ static void check_conf(struct menu *menu)
check_conf(child); check_conf(child);
} }
static struct option long_opts[] = {
{"oldaskconfig", no_argument, NULL, oldaskconfig},
{"oldconfig", no_argument, NULL, oldconfig},
{"silentoldconfig", no_argument, NULL, silentoldconfig},
{"defconfig", optional_argument, NULL, defconfig},
{"savedefconfig", required_argument, NULL, savedefconfig},
{"allnoconfig", no_argument, NULL, allnoconfig},
{"allyesconfig", no_argument, NULL, allyesconfig},
{"allmodconfig", no_argument, NULL, allmodconfig},
{"alldefconfig", no_argument, NULL, alldefconfig},
{"randconfig", no_argument, NULL, randconfig},
{"listnewconfig", no_argument, NULL, listnewconfig},
{"olddefconfig", no_argument, NULL, olddefconfig},
/*
* oldnoconfig is an alias of olddefconfig, because people already
* are dependent on its behavior(sets new symbols to their default
* value but not 'n') with the counter-intuitive name.
*/
{"oldnoconfig", no_argument, NULL, olddefconfig},
{NULL, 0, NULL, 0}
};
static void conf_usage(const char *progname)
{
printf("Usage: %s [option] <kconfig-file>\n", progname);
printf("[option] is _one_ of the following:\n");
printf(" --listnewconfig List new options\n");
printf(" --oldaskconfig Start a new configuration using a line-oriented program\n");
printf(" --oldconfig Update a configuration using a provided .config as base\n");
printf(" --silentoldconfig Same as oldconfig, but quietly, additionally update deps\n");
printf(" --olddefconfig Same as silentoldconfig but sets new symbols to their default value\n");
printf(" --oldnoconfig An alias of olddefconfig\n");
printf(" --defconfig <file> New config with default defined in <file>\n");
printf(" --savedefconfig <file> Save the minimal current configuration to <file>\n");
printf(" --allnoconfig New config where all options are answered with no\n");
printf(" --allyesconfig New config where all options are answered with yes\n");
printf(" --allmodconfig New config where all options are answered with mod\n");
printf(" --alldefconfig New config with all symbols set to default\n");
printf(" --randconfig New config with random answer to all options\n");
}
int main(int ac, char **av) int main(int ac, char **av)
{ {
int i = 1; const char *progname = av[0];
const char *name; int opt;
char *output = NULL; const char *name, *defconfig_file = NULL /* gcc uninit */;
struct stat tmpstat; struct stat tmpstat;
const char *input_file = NULL, *output_file = NULL;
while (ac > i && av[i][0] == '-') { setlocale(LC_ALL, "");
switch (av[i++][1]) { bindtextdomain(PACKAGE, LOCALEDIR);
case 'o': textdomain(PACKAGE);
input_mode = ask_new;
tty_stdio = isatty(0) && isatty(1) && isatty(2);
while ((opt = getopt_long(ac, av, "r:w:", long_opts, NULL)) != -1) {
input_mode = (enum input_mode)opt;
switch (opt) {
case silentoldconfig:
sync_kconfig = 1;
break; break;
case 's': case defconfig:
input_mode = ask_silent; case savedefconfig:
valid_stdin = isatty(0) && isatty(1) && isatty(2); defconfig_file = optarg;
break; break;
case 'd': case randconfig:
input_mode = set_default; {
struct timeval now;
unsigned int seed;
/*
* Use microseconds derived seed,
* compensate for systems where it may be zero
*/
gettimeofday(&now, NULL);
seed = (unsigned int)((now.tv_sec + 1) * (now.tv_usec + 1));
srand(seed);
break; break;
case 'D': }
input_mode = set_default; case oldaskconfig:
defconfig_file = av[i++]; case oldconfig:
if (!defconfig_file) { case allnoconfig:
printf(_("%s: No default config file specified\n"), case allyesconfig:
av[0]); case allmodconfig:
exit(1); case alldefconfig:
} case listnewconfig:
break; case olddefconfig:
case 'w':
output = av[i++];
break;
case 'n':
input_mode = set_no;
break;
case 'm':
input_mode = set_mod;
break;
case 'y':
input_mode = set_yes;
break; break;
case 'r': case 'r':
input_mode = set_random; input_file = optarg;
srandom(time(NULL)); break;
case 'w':
output_file = optarg;
break; break;
case 'h':
case '?': case '?':
printf("%s [-o|-s] config\n", av[0]); conf_usage(progname);
exit(0); exit(1);
break;
} }
} }
name = av[i]; if (ac == optind) {
if (!name) {
printf(_("%s: Kconfig file missing\n"), av[0]); printf(_("%s: Kconfig file missing\n"), av[0]);
conf_usage(progname);
exit(1);
} }
name = av[optind];
conf_parse(name); conf_parse(name);
//zconfdump(stdout); //zconfdump(stdout);
switch (input_mode) { if (sync_kconfig) {
case set_default: name = conf_get_configname();
if (!defconfig_file) if (stat(name, &tmpstat)) {
defconfig_file = conf_get_default_confname(); fprintf(stderr, _("***\n"
if (conf_read(defconfig_file)) { "*** Configuration file \"%s\" not found!\n"
printf("***\n"
"*** Can't find default configuration \"%s\"!\n"
"***\n", defconfig_file);
exit(1);
}
break;
case ask_silent:
if (stat(".config", &tmpstat)) {
printf(_("***\n"
"*** You have not yet configured your build!\n"
"***\n" "***\n"
"*** Please run some configurator (e.g. \"make oldconfig\" or\n" "*** Please run some configurator (e.g. \"make oldconfig\" or\n"
"*** \"make menuconfig\" or \"make xconfig\").\n" "*** \"make menuconfig\" or \"make xconfig\").\n"
"***\n")); "***\n"), name);
exit(1); exit(1);
} }
case ask_all: }
case ask_new:
case set_no: switch (input_mode) {
case set_mod: case defconfig:
case set_yes: if (!defconfig_file)
case set_random: defconfig_file = conf_get_default_confname();
conf_read(NULL); if (conf_read(defconfig_file)) {
printf(_("***\n"
"*** Can't find default configuration \"%s\"!\n"
"***\n"), defconfig_file);
exit(1);
}
break;
case savedefconfig:
case silentoldconfig:
case oldaskconfig:
case oldconfig:
case listnewconfig:
case olddefconfig:
case allnoconfig:
case allyesconfig:
case allmodconfig:
case alldefconfig:
case randconfig:
conf_read(input_file);
break; break;
default: default:
break; break;
} }
if (input_mode != ask_silent) { if (sync_kconfig) {
if (conf_get_changed()) {
name = getenv("KCONFIG_NOSILENTUPDATE");
if (name && *name) {
fprintf(stderr,
_("\n*** The configuration requires explicit update.\n\n"));
return 1;
}
}
valid_stdin = tty_stdio;
}
switch (input_mode) {
case allnoconfig:
conf_set_all_new_symbols(def_no);
break;
case allyesconfig:
conf_set_all_new_symbols(def_yes);
break;
case allmodconfig:
conf_set_all_new_symbols(def_mod);
break;
case alldefconfig:
conf_set_all_new_symbols(def_default);
break;
case randconfig:
conf_set_all_new_symbols(def_random);
break;
case defconfig:
conf_set_all_new_symbols(def_default);
break;
case savedefconfig:
break;
case oldaskconfig:
rootEntry = &rootmenu; rootEntry = &rootmenu;
conf(&rootmenu); conf(&rootmenu);
if (input_mode == ask_all) { input_mode = silentoldconfig;
input_mode = ask_silent; /* fall through */
valid_stdin = 1; case oldconfig:
} case listnewconfig:
case olddefconfig:
case silentoldconfig:
/* Update until a loop caused no more changes */
do {
conf_cnt = 0;
check_conf(&rootmenu);
} while (conf_cnt &&
(input_mode != listnewconfig &&
input_mode != olddefconfig));
break;
} }
do {
conf_cnt = 0; if (sync_kconfig) {
check_conf(&rootmenu); /* silentoldconfig is used during the build so we shall update autoconf.
} while (conf_cnt); * All other commands are only used to generate a config.
if (conf_write(output)) { */
fprintf(stderr, _("\n*** Error during writing of the build configuration.\n\n")); if ((output_file || conf_get_changed()) &&
return 1; conf_write(output_file)) {
fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n"));
exit(1);
}
if (conf_write_autoconf()) {
fprintf(stderr, _("\n*** Error during update of the configuration.\n\n"));
return 1;
}
} else if (input_mode == savedefconfig) {
if (conf_write_defconfig(defconfig_file)) {
fprintf(stderr, _("n*** Error while saving defconfig to: %s\n\n"),
defconfig_file);
return 1;
}
} else if (input_mode != listnewconfig) {
if (conf_write(output_file)) {
fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n"));
exit(1);
}
} }
return 0; return 0;
} }
/*
* Helper function to facilitate fgets() by Jean Sacren.
*/
void xfgets(char *str, int size, FILE *in)
{
if (fgets(str, size, in) == NULL)
fprintf(stderr, "\nError in reading or end of file.\n");
}

File diff suppressed because it is too large Load diff

View file

@ -7,15 +7,13 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#define LKC_DIRECT_LINK
#include "lkc.h" #include "lkc.h"
#define DEBUG_EXPR 0 #define DEBUG_EXPR 0
struct expr *expr_alloc_symbol(struct symbol *sym) struct expr *expr_alloc_symbol(struct symbol *sym)
{ {
struct expr *e = malloc(sizeof(*e)); struct expr *e = xcalloc(1, sizeof(*e));
memset(e, 0, sizeof(*e));
e->type = E_SYMBOL; e->type = E_SYMBOL;
e->left.sym = sym; e->left.sym = sym;
return e; return e;
@ -23,8 +21,7 @@ struct expr *expr_alloc_symbol(struct symbol *sym)
struct expr *expr_alloc_one(enum expr_type type, struct expr *ce) struct expr *expr_alloc_one(enum expr_type type, struct expr *ce)
{ {
struct expr *e = malloc(sizeof(*e)); struct expr *e = xcalloc(1, sizeof(*e));
memset(e, 0, sizeof(*e));
e->type = type; e->type = type;
e->left.expr = ce; e->left.expr = ce;
return e; return e;
@ -32,8 +29,7 @@ struct expr *expr_alloc_one(enum expr_type type, struct expr *ce)
struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e2) struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e2)
{ {
struct expr *e = malloc(sizeof(*e)); struct expr *e = xcalloc(1, sizeof(*e));
memset(e, 0, sizeof(*e));
e->type = type; e->type = type;
e->left.expr = e1; e->left.expr = e1;
e->right.expr = e2; e->right.expr = e2;
@ -42,8 +38,7 @@ struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e
struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2) struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2)
{ {
struct expr *e = malloc(sizeof(*e)); struct expr *e = xcalloc(1, sizeof(*e));
memset(e, 0, sizeof(*e));
e->type = type; e->type = type;
e->left.sym = s1; e->left.sym = s1;
e->right.sym = s2; e->right.sym = s2;
@ -64,14 +59,14 @@ struct expr *expr_alloc_or(struct expr *e1, struct expr *e2)
return e2 ? expr_alloc_two(E_OR, e1, e2) : e1; return e2 ? expr_alloc_two(E_OR, e1, e2) : e1;
} }
struct expr *expr_copy(struct expr *org) struct expr *expr_copy(const struct expr *org)
{ {
struct expr *e; struct expr *e;
if (!org) if (!org)
return NULL; return NULL;
e = malloc(sizeof(*org)); e = xmalloc(sizeof(*org));
memcpy(e, org, sizeof(*org)); memcpy(e, org, sizeof(*org));
switch (org->type) { switch (org->type) {
case E_SYMBOL: case E_SYMBOL:
@ -87,7 +82,7 @@ struct expr *expr_copy(struct expr *org)
break; break;
case E_AND: case E_AND:
case E_OR: case E_OR:
case E_CHOICE: case E_LIST:
e->left.expr = expr_copy(org->left.expr); e->left.expr = expr_copy(org->left.expr);
e->right.expr = expr_copy(org->right.expr); e->right.expr = expr_copy(org->right.expr);
break; break;
@ -217,7 +212,7 @@ int expr_eq(struct expr *e1, struct expr *e2)
expr_free(e2); expr_free(e2);
trans_count = old_count; trans_count = old_count;
return res; return res;
case E_CHOICE: case E_LIST:
case E_RANGE: case E_RANGE:
case E_NONE: case E_NONE:
/* panic */; /* panic */;
@ -648,7 +643,7 @@ struct expr *expr_transform(struct expr *e)
case E_EQUAL: case E_EQUAL:
case E_UNEQUAL: case E_UNEQUAL:
case E_SYMBOL: case E_SYMBOL:
case E_CHOICE: case E_LIST:
break; break;
default: default:
e->left.expr = expr_transform(e->left.expr); e->left.expr = expr_transform(e->left.expr);
@ -932,7 +927,7 @@ struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symb
break; break;
case E_SYMBOL: case E_SYMBOL:
return expr_alloc_comp(type, e->left.sym, sym); return expr_alloc_comp(type, e->left.sym, sym);
case E_CHOICE: case E_LIST:
case E_RANGE: case E_RANGE:
case E_NONE: case E_NONE:
/* panic */; /* panic */;
@ -955,14 +950,14 @@ tristate expr_calc_value(struct expr *e)
case E_AND: case E_AND:
val1 = expr_calc_value(e->left.expr); val1 = expr_calc_value(e->left.expr);
val2 = expr_calc_value(e->right.expr); val2 = expr_calc_value(e->right.expr);
return E_AND(val1, val2); return EXPR_AND(val1, val2);
case E_OR: case E_OR:
val1 = expr_calc_value(e->left.expr); val1 = expr_calc_value(e->left.expr);
val2 = expr_calc_value(e->right.expr); val2 = expr_calc_value(e->right.expr);
return E_OR(val1, val2); return EXPR_OR(val1, val2);
case E_NOT: case E_NOT:
val1 = expr_calc_value(e->left.expr); val1 = expr_calc_value(e->left.expr);
return E_NOT(val1); return EXPR_NOT(val1);
case E_EQUAL: case E_EQUAL:
sym_calc_value(e->left.sym); sym_calc_value(e->left.sym);
sym_calc_value(e->right.sym); sym_calc_value(e->right.sym);
@ -1000,9 +995,9 @@ int expr_compare_type(enum expr_type t1, enum expr_type t2)
if (t2 == E_OR) if (t2 == E_OR)
return 1; return 1;
case E_OR: case E_OR:
if (t2 == E_CHOICE) if (t2 == E_LIST)
return 1; return 1;
case E_CHOICE: case E_LIST:
if (t2 == 0) if (t2 == 0)
return 1; return 1;
default: default:
@ -1013,6 +1008,48 @@ int expr_compare_type(enum expr_type t1, enum expr_type t2)
#endif #endif
} }
static inline struct expr *
expr_get_leftmost_symbol(const struct expr *e)
{
if (e == NULL)
return NULL;
while (e->type != E_SYMBOL)
e = e->left.expr;
return expr_copy(e);
}
/*
* Given expression `e1' and `e2', returns the leaf of the longest
* sub-expression of `e1' not containing 'e2.
*/
struct expr *expr_simplify_unmet_dep(struct expr *e1, struct expr *e2)
{
struct expr *ret;
switch (e1->type) {
case E_OR:
return expr_alloc_and(
expr_simplify_unmet_dep(e1->left.expr, e2),
expr_simplify_unmet_dep(e1->right.expr, e2));
case E_AND: {
struct expr *e;
e = expr_alloc_and(expr_copy(e1), expr_copy(e2));
e = expr_eliminate_dups(e);
ret = (!expr_eq(e, e1)) ? e1 : NULL;
expr_free(e);
break;
}
default:
ret = e1;
break;
}
return expr_get_leftmost_symbol(ret);
}
void expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken) void expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken)
{ {
if (!e) { if (!e) {
@ -1059,11 +1096,11 @@ void expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char *
fn(data, NULL, " && "); fn(data, NULL, " && ");
expr_print(e->right.expr, fn, data, E_AND); expr_print(e->right.expr, fn, data, E_AND);
break; break;
case E_CHOICE: case E_LIST:
fn(data, e->right.sym, e->right.sym->name); fn(data, e->right.sym, e->right.sym->name);
if (e->left.expr) { if (e->left.expr) {
fn(data, NULL, " ^ "); fn(data, NULL, " ^ ");
expr_print(e->left.expr, fn, data, E_CHOICE); expr_print(e->left.expr, fn, data, E_LIST);
} }
break; break;
case E_RANGE: case E_RANGE:
@ -1087,7 +1124,7 @@ void expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char *
static void expr_print_file_helper(void *data, struct symbol *sym, const char *str) static void expr_print_file_helper(void *data, struct symbol *sym, const char *str)
{ {
fwrite(str, strlen(str), 1, data); xfwrite(str, strlen(str), 1, data);
} }
void expr_fprint(struct expr *e, FILE *out) void expr_fprint(struct expr *e, FILE *out)

View file

@ -10,7 +10,9 @@
extern "C" { extern "C" {
#endif #endif
#include <assert.h>
#include <stdio.h> #include <stdio.h>
#include "list.h"
#ifndef __cplusplus #ifndef __cplusplus
#include <stdbool.h> #include <stdbool.h>
#endif #endif
@ -18,21 +20,16 @@ extern "C" {
struct file { struct file {
struct file *next; struct file *next;
struct file *parent; struct file *parent;
char *name; const char *name;
int lineno; int lineno;
int flags;
}; };
#define FILE_BUSY 0x0001
#define FILE_SCANNED 0x0002
#define FILE_PRINTED 0x0004
typedef enum tristate { typedef enum tristate {
no, mod, yes no, mod, yes
} tristate; } tristate;
enum expr_type { enum expr_type {
E_NONE, E_OR, E_AND, E_NOT, E_EQUAL, E_UNEQUAL, E_CHOICE, E_SYMBOL, E_RANGE E_NONE, E_OR, E_AND, E_NOT, E_EQUAL, E_UNEQUAL, E_LIST, E_SYMBOL, E_RANGE
}; };
union expr_data { union expr_data {
@ -45,9 +42,12 @@ struct expr {
union expr_data left, right; union expr_data left, right;
}; };
#define E_OR(dep1, dep2) (((dep1)>(dep2))?(dep1):(dep2)) #define EXPR_OR(dep1, dep2) (((dep1)>(dep2))?(dep1):(dep2))
#define E_AND(dep1, dep2) (((dep1)<(dep2))?(dep1):(dep2)) #define EXPR_AND(dep1, dep2) (((dep1)<(dep2))?(dep1):(dep2))
#define E_NOT(dep) (2-(dep)) #define EXPR_NOT(dep) (2-(dep))
#define expr_list_for_each_sym(l, e, s) \
for (e = (l); e && (s = e->right.sym); e = e->left.expr)
struct expr_value { struct expr_value {
struct expr *expr; struct expr *expr;
@ -63,56 +63,89 @@ enum symbol_type {
S_UNKNOWN, S_BOOLEAN, S_TRISTATE, S_INT, S_HEX, S_STRING, S_OTHER S_UNKNOWN, S_BOOLEAN, S_TRISTATE, S_INT, S_HEX, S_STRING, S_OTHER
}; };
/* enum values are used as index to symbol.def[] */
enum {
S_DEF_USER, /* main user value */
S_DEF_AUTO, /* values read from auto.conf */
S_DEF_DEF3, /* Reserved for UI usage */
S_DEF_DEF4, /* Reserved for UI usage */
S_DEF_COUNT
};
struct symbol { struct symbol {
struct symbol *next; struct symbol *next;
char *name; char *name;
char *help;
enum symbol_type type; enum symbol_type type;
struct symbol_value curr, user; struct symbol_value curr;
struct symbol_value def[S_DEF_COUNT];
tristate visible; tristate visible;
int flags; int flags;
struct property *prop; struct property *prop;
struct expr *dep, *dep2; struct expr_value dir_dep;
struct expr_value rev_dep; struct expr_value rev_dep;
struct expr_value rev_dep_inv;
}; };
#define for_all_symbols(i, sym) for (i = 0; i < SYMBOL_HASHSIZE; i++) for (sym = symbol_hash[i]; sym; sym = sym->next) if (sym->type != S_OTHER) #define for_all_symbols(i, sym) for (i = 0; i < SYMBOL_HASHSIZE; i++) for (sym = symbol_hash[i]; sym; sym = sym->next) if (sym->type != S_OTHER)
#define SYMBOL_YES 0x0001 #define SYMBOL_CONST 0x0001 /* symbol is const */
#define SYMBOL_MOD 0x0002 #define SYMBOL_CHECK 0x0008 /* used during dependency checking */
#define SYMBOL_NO 0x0004 #define SYMBOL_CHOICE 0x0010 /* start of a choice block (null name) */
#define SYMBOL_CONST 0x0007 #define SYMBOL_CHOICEVAL 0x0020 /* used as a value in a choice block */
#define SYMBOL_CHECK 0x0008 #define SYMBOL_VALID 0x0080 /* set when symbol.curr is calculated */
#define SYMBOL_CHOICE 0x0010 #define SYMBOL_OPTIONAL 0x0100 /* choice is optional - values can be 'n' */
#define SYMBOL_CHOICEVAL 0x0020 #define SYMBOL_WRITE 0x0200 /* ? */
#define SYMBOL_PRINTED 0x0040 #define SYMBOL_CHANGED 0x0400 /* ? */
#define SYMBOL_VALID 0x0080 #define SYMBOL_AUTO 0x1000 /* value from environment variable */
#define SYMBOL_OPTIONAL 0x0100 #define SYMBOL_CHECKED 0x2000 /* used during dependency checking */
#define SYMBOL_WRITE 0x0200 #define SYMBOL_WARNED 0x8000 /* warning has been issued */
#define SYMBOL_CHANGED 0x0400
#define SYMBOL_NEW 0x0800 /* Set when symbol.def[] is used */
#define SYMBOL_AUTO 0x1000 #define SYMBOL_DEF 0x10000 /* First bit of SYMBOL_DEF */
#define SYMBOL_CHECKED 0x2000 #define SYMBOL_DEF_USER 0x10000 /* symbol.def[S_DEF_USER] is valid */
#define SYMBOL_WARNED 0x8000 #define SYMBOL_DEF_AUTO 0x20000 /* symbol.def[S_DEF_AUTO] 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_MAXLENGTH 256 #define SYMBOL_MAXLENGTH 256
#define SYMBOL_HASHSIZE 257 #define SYMBOL_HASHSIZE 9973
/* A property represent the config options that can be associated
* with a config "symbol".
* Sample:
* config FOO
* default y
* prompt "foo prompt"
* select BAR
* config BAZ
* int "BAZ Value"
* range 1..255
*/
enum prop_type { enum prop_type {
P_UNKNOWN, P_PROMPT, P_COMMENT, P_MENU, P_DEFAULT, P_CHOICE, P_DESELECT, P_SELECT, P_RANGE, P_RESET P_UNKNOWN,
P_PROMPT, /* prompt "foo prompt" or "BAZ Value" */
P_COMMENT, /* text associated with a comment */
P_MENU, /* prompt associated with a menuconfig option */
P_DEFAULT, /* default y */
P_CHOICE, /* choice value */
P_SELECT, /* select BAR */
P_RANGE, /* range 7..100 (for a symbol) */
P_ENV, /* value from environment variable */
P_SYMBOL, /* where a symbol is defined */
P_RESET, /* reset to defaults condition */
}; };
struct property { struct property {
struct property *next; struct property *next; /* next property - null if last */
struct symbol *sym; struct symbol *sym; /* the symbol for which the property is associated */
enum prop_type type; enum prop_type type; /* type of property */
const char *text; const char *text; /* the prompt value - P_PROMPT, P_MENU, P_COMMENT */
struct expr_value visible; struct expr_value visible;
struct expr *expr; struct expr *expr; /* the optional conditional part of the property */
struct menu *menu; struct menu *menu; /* the menu the property are associated with
struct file *file; * valid for: P_SELECT, P_RANGE, P_CHOICE,
int lineno; * P_PROMPT, P_DEFAULT, P_MENU, P_COMMENT */
struct file *file; /* what file was this property defined */
int lineno; /* what lineno was this property defined */
}; };
#define for_all_properties(sym, st, tok) \ #define for_all_properties(sym, st, tok) \
@ -130,9 +163,10 @@ struct menu {
struct menu *list; struct menu *list;
struct symbol *sym; struct symbol *sym;
struct property *prompt; struct property *prompt;
struct expr *visibility;
struct expr *dep; struct expr *dep;
unsigned int flags; unsigned int flags;
//char *help; char *help;
struct file *file; struct file *file;
int lineno; int lineno;
void *data; void *data;
@ -141,7 +175,14 @@ struct menu {
#define MENU_CHANGED 0x0001 #define MENU_CHANGED 0x0001
#define MENU_ROOT 0x0002 #define MENU_ROOT 0x0002
#ifndef SWIG struct jump_key {
struct list_head entries;
size_t offset;
struct menu *target;
int index;
};
#define JUMP_NB 9
extern struct file *file_list; extern struct file *file_list;
extern struct file *current_file; extern struct file *current_file;
@ -149,6 +190,7 @@ struct file *lookup_file(const char *name);
extern struct symbol symbol_yes, symbol_no, symbol_mod; extern struct symbol symbol_yes, symbol_no, symbol_mod;
extern struct symbol *modules_sym; extern struct symbol *modules_sym;
extern struct symbol *sym_defconfig_list;
extern int cdebug; extern int cdebug;
struct expr *expr_alloc_symbol(struct symbol *sym); struct expr *expr_alloc_symbol(struct symbol *sym);
struct expr *expr_alloc_one(enum expr_type type, struct expr *ce); struct expr *expr_alloc_one(enum expr_type type, struct expr *ce);
@ -156,7 +198,7 @@ struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e
struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2); struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2);
struct expr *expr_alloc_and(struct expr *e1, struct expr *e2); struct expr *expr_alloc_and(struct expr *e1, struct expr *e2);
struct expr *expr_alloc_or(struct expr *e1, struct expr *e2); struct expr *expr_alloc_or(struct expr *e1, struct expr *e2);
struct expr *expr_copy(struct expr *org); struct expr *expr_copy(const struct expr *org);
void expr_free(struct expr *e); void expr_free(struct expr *e);
int expr_eq(struct expr *e1, struct expr *e2); int expr_eq(struct expr *e1, struct expr *e2);
void expr_eliminate_eq(struct expr **ep1, struct expr **ep2); void expr_eliminate_eq(struct expr **ep1, struct expr **ep2);
@ -171,6 +213,7 @@ struct expr *expr_extract_eq_and(struct expr **ep1, struct expr **ep2);
struct expr *expr_extract_eq_or(struct expr **ep1, struct expr **ep2); struct expr *expr_extract_eq_or(struct expr **ep1, struct expr **ep2);
void expr_extract_eq(enum expr_type type, struct expr **ep, struct expr **ep1, struct expr **ep2); void expr_extract_eq(enum expr_type type, struct expr **ep, struct expr **ep1, struct expr **ep2);
struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym); struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym);
struct expr *expr_simplify_unmet_dep(struct expr *e1, struct expr *e2);
void expr_fprint(struct expr *e, FILE *out); void expr_fprint(struct expr *e, FILE *out);
struct gstr; /* forward */ struct gstr; /* forward */
@ -185,7 +228,6 @@ static inline int expr_is_no(struct expr *e)
{ {
return e && (e->type == E_SYMBOL && e->left.sym == &symbol_no); return e && (e->type == E_SYMBOL && e->left.sym == &symbol_no);
} }
#endif
#ifdef __cplusplus #ifdef __cplusplus
} }

View file

@ -1,35 +0,0 @@
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include "lkc.h"
#define P(name,type,arg) type (*name ## _p) arg
#include "lkc_proto.h"
#undef P
void kconfig_load(void)
{
void *handle;
char *error;
handle = dlopen("./libkconfig.so", RTLD_LAZY);
if (!handle) {
handle = dlopen("./scripts/kconfig/libkconfig.so", RTLD_LAZY);
if (!handle) {
fprintf(stderr, "%s\n", dlerror());
exit(1);
}
}
#define P(name,type,arg) \
{ \
name ## _p = dlsym(handle, #name); \
if ((error = dlerror())) { \
fprintf(stderr, "%s\n", error); \
exit(1); \
} \
}
#include "lkc_proto.h"
#undef P
}

View file

@ -1 +0,0 @@
No backing up.

91
scripts/config/list.h Normal file
View file

@ -0,0 +1,91 @@
#ifndef LIST_H
#define LIST_H
/*
* Copied from include/linux/...
*/
#undef offsetof
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
/**
* container_of - cast a member of a structure out to the containing structure
* @ptr: the pointer to the member.
* @type: the type of the container struct this is embedded in.
* @member: the name of the member within the struct.
*
*/
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
struct list_head {
struct list_head *next, *prev;
};
#define LIST_HEAD_INIT(name) { &(name), &(name) }
#define LIST_HEAD(name) \
struct list_head name = LIST_HEAD_INIT(name)
/**
* list_entry - get the struct for this entry
* @ptr: the &struct list_head pointer.
* @type: the type of the struct this is embedded in.
* @member: the name of the list_struct within the struct.
*/
#define list_entry(ptr, type, member) \
container_of(ptr, type, member)
/**
* list_for_each_entry - iterate over list of given type
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*/
#define list_for_each_entry(pos, head, member) \
for (pos = list_entry((head)->next, typeof(*pos), member); \
&pos->member != (head); \
pos = list_entry(pos->member.next, typeof(*pos), member))
/**
* list_empty - tests whether a list is empty
* @head: the list to test.
*/
static inline int list_empty(const struct list_head *head)
{
return head->next == head;
}
/*
* Insert a new entry between two known consecutive entries.
*
* This is only for internal list manipulation where we know
* the prev/next entries already!
*/
static inline void __list_add(struct list_head *_new,
struct list_head *prev,
struct list_head *next)
{
next->prev = _new;
_new->next = next;
_new->prev = prev;
prev->next = _new;
}
/**
* list_add_tail - add a new entry
* @new: new entry to be added
* @head: list head to add it before
*
* Insert a new entry before the specified head.
* This is useful for implementing queues.
*/
static inline void list_add_tail(struct list_head *_new, struct list_head *head)
{
__list_add(_new, head->prev, head);
}
#endif

View file

@ -11,35 +11,56 @@
#ifndef KBUILD_NO_NLS #ifndef KBUILD_NO_NLS
# include <libintl.h> # include <libintl.h>
#else #else
# define gettext(Msgid) ((const char *) (Msgid)) static inline const char *gettext(const char *txt) { return txt; }
# define textdomain(Domainname) ((const char *) (Domainname)) static inline void textdomain(const char *domainname) {}
# define bindtextdomain(Domainname, Dirname) ((const char *) (Dirname)) static inline void bindtextdomain(const char *name, const char *dir) {}
static inline char *bind_textdomain_codeset(const char *dn, char *c) { return c; }
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
#ifdef LKC_DIRECT_LINK
#define P(name,type,arg) extern type name arg #define P(name,type,arg) extern type name arg
#else
#include "lkc_defs.h"
#define P(name,type,arg) extern type (*name ## _p) arg
#endif
#include "lkc_proto.h" #include "lkc_proto.h"
#undef P #undef P
#define SRCTREE "srctree" #define SRCTREE "srctree"
#ifndef PACKAGE
#define PACKAGE "linux" #define PACKAGE "linux"
#endif
#define LOCALEDIR "/usr/share/locale" #define LOCALEDIR "/usr/share/locale"
#define _(text) gettext(text) #define _(text) gettext(text)
#define N_(text) (text) #define N_(text) (text)
#ifndef CONFIG_
#define CONFIG_ "CONFIG_"
#endif
static inline const char *CONFIG_prefix(void)
{
return getenv( "CONFIG_" ) ?: CONFIG_;
}
#undef CONFIG_
#define CONFIG_ CONFIG_prefix()
#define TF_COMMAND 0x0001 #define TF_COMMAND 0x0001
#define TF_PARAM 0x0002 #define TF_PARAM 0x0002
#define TF_OPTION 0x0004
enum conf_def_mode {
def_default,
def_yes,
def_mod,
def_no,
def_random
};
#define T_OPT_MODULES 1
#define T_OPT_DEFCONFIG_LIST 2
#define T_OPT_ENV 3
struct kconf_id { struct kconf_id {
int name; int name;
@ -48,50 +69,69 @@ struct kconf_id {
enum symbol_type stype; enum symbol_type stype;
}; };
extern int zconfdebug;
int zconfparse(void); int zconfparse(void);
void zconfdump(FILE *out); void zconfdump(FILE *out);
extern int zconfdebug;
void zconf_starthelp(void); void zconf_starthelp(void);
FILE *zconf_fopen(const char *name); FILE *zconf_fopen(const char *name);
void zconf_initscan(const char *name); void zconf_initscan(const char *name);
void zconf_nextfile(const char *name); void zconf_nextfile(const char *name);
int zconf_lineno(void); int zconf_lineno(void);
char *zconf_curname(void); const char *zconf_curname(void);
/* confdata.c */ /* confdata.c */
extern const char conf_def_filename[]; const char *conf_get_configname(void);
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_add_change_count(int count);
void conf_set_all_new_symbols(enum conf_def_mode mode);
/* kconfig_load.c */ struct conf_printer {
void kconfig_load(void); void (*print_symbol)(FILE *, struct symbol *, const char *, void *);
void (*print_comment)(FILE *, const char *, void *);
};
/* confdata.c and expr.c */
static inline void xfwrite(const void *str, size_t len, size_t count, FILE *out)
{
assert(len != 0);
if (fwrite(str, len, count, out) != count)
fprintf(stderr, "Error in writing or end of file.\n");
}
/* menu.c */ /* menu.c */
void menu_init(void); void _menu_init(void);
void menu_warn(struct menu *menu, const char *fmt, ...);
struct menu *menu_add_menu(void); struct menu *menu_add_menu(void);
void menu_end_menu(void); void menu_end_menu(void);
void menu_add_entry(struct symbol *sym); void menu_add_entry(struct symbol *sym);
void menu_end_entry(void); void menu_end_entry(void);
void menu_add_dep(struct expr *dep); void menu_add_dep(struct expr *dep);
void menu_add_visibility(struct expr *dep);
struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep); struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep);
struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep); struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep);
void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep); void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep);
void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep); void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep);
void menu_add_option(int token, char *arg);
void menu_finalize(struct menu *parent); void menu_finalize(struct menu *parent);
void menu_set_type(int type); void menu_set_type(int type);
/* util.c */ /* util.c */
struct file *file_lookup(const char *name); struct file *file_lookup(const char *name);
int file_write_dep(const char *name); int file_write_dep(const char *name);
void *xmalloc(size_t size);
void *xcalloc(size_t nmemb, size_t size);
struct gstr { struct gstr {
size_t len; size_t len;
char *s; char *s;
/* /*
* when max_width is not zero long lines in string s (if any) get * when max_width is not zero long lines in string s (if any) get
* wrapped not to exceed the max_width value * wrapped not to exceed the max_width value
*/ */
int max_width; int max_width;
}; };
struct gstr str_new(void); struct gstr str_new(void);
@ -102,12 +142,18 @@ void str_printf(struct gstr *gs, const char *fmt, ...);
const char *str_get(struct gstr *gs); const char *str_get(struct gstr *gs);
/* symbol.c */ /* symbol.c */
extern struct expr *sym_env_list;
void sym_init(void); void sym_init(void);
void sym_clear_all_valid(void); void sym_clear_all_valid(void);
void sym_set_all_changed(void);
void sym_set_changed(struct symbol *sym); void sym_set_changed(struct symbol *sym);
struct symbol *sym_choice_default(struct symbol *sym);
const char *sym_get_string_default(struct symbol *sym);
struct symbol *sym_check_deps(struct symbol *sym); struct symbol *sym_check_deps(struct symbol *sym);
struct property *prop_alloc(enum prop_type type, struct symbol *sym); struct property *prop_alloc(enum prop_type type, struct symbol *sym);
struct symbol *prop_get_symbol(struct property *prop); struct symbol *prop_get_symbol(struct property *prop);
struct property *sym_get_env_prop(struct symbol *sym);
static inline tristate sym_get_tristate_value(struct symbol *sym) static inline tristate sym_get_tristate_value(struct symbol *sym)
{ {
@ -142,7 +188,7 @@ static inline bool sym_is_optional(struct symbol *sym)
static inline bool sym_has_value(struct symbol *sym) static inline bool sym_has_value(struct symbol *sym)
{ {
return sym->flags & SYMBOL_NEW ? false : true; return sym->flags & SYMBOL_DEF_USER ? true : false;
} }
#ifdef __cplusplus #ifdef __cplusplus

View file

@ -1,25 +1,40 @@
#include <stdarg.h>
/* confdata.c */ /* confdata.c */
P(conf_parse,void,(const char *name)); P(conf_parse,void,(const char *name));
P(conf_read,int,(const char *name)); P(conf_read,int,(const char *name));
P(conf_reset,void,(void)); P(conf_read_simple,int,(const char *name, int));
P(conf_read_simple,int,(const char *name, int load_config)); P(conf_reset,void,(int));
P(conf_write_defconfig,int,(const char *name));
P(conf_write,int,(const char *name)); P(conf_write,int,(const char *name));
P(conf_write_autoconf,int,(void));
P(conf_get_changed,bool,(void));
P(conf_set_changed_callback, void,(void (*fn)(void)));
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_visible,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)); P(menu_get_prompt,const char *,(struct menu *menu));
P(menu_get_root_menu,struct menu *,(struct menu *menu)); P(menu_get_root_menu,struct menu *,(struct menu *menu));
P(menu_get_parent_menu,struct menu *,(struct menu *menu)); P(menu_get_parent_menu,struct menu *,(struct menu *menu));
P(menu_has_help,bool,(struct menu *menu));
P(menu_get_help,const char *,(struct menu *menu));
P(get_symbol_str, void, (struct gstr *r, struct symbol *sym, struct list_head
*head));
P(get_relations_str, struct gstr, (struct symbol **sym_arr, struct list_head
*head));
P(menu_get_ext_help,void,(struct menu *menu, struct gstr *help));
/* symbol.c */ /* symbol.c */
P(symbol_hash,struct symbol *,[SYMBOL_HASHSIZE]); P(symbol_hash,struct symbol *,[SYMBOL_HASHSIZE]);
P(sym_change_count,int,);
P(sym_lookup,struct symbol *,(const char *name, int isconst)); P(sym_lookup,struct symbol *,(const char *name, int flags));
P(sym_find,struct symbol *,(const char *name)); P(sym_find,struct symbol *,(const char *name));
P(sym_expand_string_value,const char *,(const char *in));
P(sym_escape_string_value, const char *,(const char *in));
P(sym_re_search,struct symbol **,(const char *pattern)); P(sym_re_search,struct symbol **,(const char *pattern));
P(sym_type_name,const char *,(enum symbol_type type)); P(sym_type_name,const char *,(enum symbol_type type));
P(sym_calc_value,void,(struct symbol *sym)); P(sym_calc_value,void,(struct symbol *sym));

View file

@ -1,28 +0,0 @@
# Makefile to build lxdialog package
#
all: lxdialog
# Use reursively expanded variables so we do not call gcc unless
# we really need to do so. (Do not call gcc as part of make mrproper)
CFLAGS := $(shell sh check-lxdialog.sh -ccflags)
LIBS := $(shell sh check-lxdialog.sh -ldflags gcc)
# workaround for OpenBSD, which does not use symlinks to libncurses.so
OS := $(shell uname -s)
ifeq ($(strip $(OS)),OpenBSD)
LIBS := -lncurses
endif
ifeq ($(shell uname -o),Cygwin)
LIBS := -lncurses
endif
always := $(hostprogs-y) dochecklxdialog
%.o: %.c
$(CC) -c $(CFLAGS) -o $@ $<
lxdialog: checklist.o menubox.o textbox.o yesno.o inputbox.o util.o lxdialog.o msgbox.o
$(CC) -o $@ $^ $(LIBS)
clean:
rm -f *.o lxdialog

View file

@ -1,24 +1,14 @@
#!/usr/bin/env bash #!/bin/sh
# Check ncurses compatibility # Check ncurses compatibility
# What library to link # What library to link
ldflags() ldflags()
{ {
for ext in so dylib; do for ext in so a dll.a dylib ; do
for dir in "" /usr/local/lib /opt/local/lib; do for lib in ncursesw ncurses curses ; do
$cc ${dir:+-L$dir} -print-file-name=libncursesw.$ext | grep -q / $cc -print-file-name=lib${lib}.${ext} | grep -q /
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
echo $dir '-lncursesw' echo "-l${lib}"
exit
fi
$cc ${dir:+-L$dir} -print-file-name=libncurses.$ext | grep -q /
if [ $? -eq 0 ]; then
echo $dir '-lncurses'
exit
fi
$cc ${dir:+-L$dir} -print-file-name=libcurses.$ext | grep -q /
if [ $? -eq 0 ]; then
echo $dir '-lcurses'
exit exit
fi fi
done done
@ -29,12 +19,13 @@ ldflags()
# Where is ncurses.h? # Where is ncurses.h?
ccflags() ccflags()
{ {
if [ -f /usr/include/ncurses/ncurses.h ]; then if [ -f /usr/include/ncursesw/curses.h ]; then
echo '-I/usr/include/ncursesw -DCURSES_LOC="<ncursesw/curses.h>"'
echo ' -DNCURSES_WIDECHAR=1'
elif [ -f /usr/include/ncurses/ncurses.h ]; then
echo '-I/usr/include/ncurses -DCURSES_LOC="<ncurses.h>"' echo '-I/usr/include/ncurses -DCURSES_LOC="<ncurses.h>"'
elif [ -f /usr/include/ncurses/curses.h ]; then elif [ -f /usr/include/ncurses/curses.h ]; then
echo '-I/usr/include/ncurses -DCURSES_LOC="<ncurses/curses.h>"' echo '-I/usr/include/ncurses -DCURSES_LOC="<ncurses/curses.h>"'
elif [ -f /opt/local/include/ncurses/ncurses.h ]; then
echo '-I/opt/local/include -I/opt/local/include/ncurses -DCURSES_LOC="<ncurses/ncurses.h>"'
elif [ -f /usr/include/ncurses.h ]; then elif [ -f /usr/include/ncurses.h ]; then
echo '-DCURSES_LOC="<ncurses.h>"' echo '-DCURSES_LOC="<ncurses.h>"'
else else
@ -48,19 +39,23 @@ trap "rm -f $tmp" 0 1 2 3 15
# Check if we can link to ncurses # Check if we can link to ncurses
check() { check() {
echo "main() {}" | $cc -xc - -o $tmp 2> /dev/null $cc -x c - -o $tmp 2>/dev/null <<'EOF'
#include CURSES_LOC
main() {}
EOF
if [ $? != 0 ]; then if [ $? != 0 ]; then
echo " *** Unable to find the ncurses libraries." 1>&2 echo " *** Unable to find the ncurses libraries or the" 1>&2
echo " *** make menuconfig require the ncurses libraries" 1>&2 echo " *** required header files." 1>&2
echo " *** " 1>&2 echo " *** 'make menuconfig' requires the ncurses libraries." 1>&2
echo " *** Install ncurses (ncurses-devel) and try again" 1>&2 echo " *** " 1>&2
echo " *** " 1>&2 echo " *** Install ncurses (ncurses-devel) and try again." 1>&2
exit 1 echo " *** " 1>&2
exit 1
fi fi
} }
usage() { usage() {
printf "Usage: $0 [-check compiler options|-header|-library]\n" printf "Usage: $0 [-check compiler options|-ccflags|-ldflags compiler options]\n"
} }
if [ $# -eq 0 ]; then if [ $# -eq 0 ]; then

View file

@ -28,29 +28,35 @@ static int list_width, check_x, item_x;
/* /*
* Print list item * Print list item
*/ */
static void print_item(WINDOW * win, const char *item, int status, int choice, static void print_item(WINDOW * win, int choice, int selected)
int selected)
{ {
int i; int i;
char *list_item = malloc(list_width + 1);
strncpy(list_item, item_str(), list_width - item_x);
list_item[list_width - item_x] = '\0';
/* Clear 'residue' of last item */ /* Clear 'residue' of last item */
wattrset(win, menubox_attr); wattrset(win, dlg.menubox.atr);
wmove(win, choice, 0); wmove(win, choice, 0);
for (i = 0; i < list_width; i++) for (i = 0; i < list_width; i++)
waddch(win, ' '); waddch(win, ' ');
wmove(win, choice, check_x); wmove(win, choice, check_x);
wattrset(win, selected ? check_selected_attr : check_attr); wattrset(win, selected ? dlg.check_selected.atr
wprintw(win, "(%c)", status ? 'X' : ' '); : dlg.check.atr);
if (!item_is_tag(':'))
wprintw(win, "(%c)", item_is_tag('X') ? 'X' : ' ');
wattrset(win, selected ? tag_selected_attr : tag_attr); wattrset(win, selected ? dlg.tag_selected.atr : dlg.tag.atr);
mvwaddch(win, choice, item_x, item[0]); mvwaddch(win, choice, item_x, list_item[0]);
wattrset(win, selected ? item_selected_attr : item_attr); wattrset(win, selected ? dlg.item_selected.atr : dlg.item.atr);
waddstr(win, (char *)item + 1); waddstr(win, list_item + 1);
if (selected) { if (selected) {
wmove(win, choice, check_x + 1); wmove(win, choice, check_x + 1);
wrefresh(win); wrefresh(win);
} }
free(list_item);
} }
/* /*
@ -62,11 +68,11 @@ static void print_arrows(WINDOW * win, int choice, int item_no, int scroll,
wmove(win, y, x); wmove(win, y, x);
if (scroll > 0) { if (scroll > 0) {
wattrset(win, uarrow_attr); wattrset(win, dlg.uarrow.atr);
waddch(win, ACS_UARROW); waddch(win, ACS_UARROW);
waddstr(win, "(-)"); waddstr(win, "(-)");
} else { } else {
wattrset(win, menubox_attr); wattrset(win, dlg.menubox.atr);
waddch(win, ACS_HLINE); waddch(win, ACS_HLINE);
waddch(win, ACS_HLINE); waddch(win, ACS_HLINE);
waddch(win, ACS_HLINE); waddch(win, ACS_HLINE);
@ -77,11 +83,11 @@ static void print_arrows(WINDOW * win, int choice, int item_no, int scroll,
wmove(win, y, x); wmove(win, y, x);
if ((height < item_no) && (scroll + choice < item_no - 1)) { if ((height < item_no) && (scroll + choice < item_no - 1)) {
wattrset(win, darrow_attr); wattrset(win, dlg.darrow.atr);
waddch(win, ACS_DARROW); waddch(win, ACS_DARROW);
waddstr(win, "(+)"); waddstr(win, "(+)");
} else { } else {
wattrset(win, menubox_border_attr); wattrset(win, dlg.menubox_border.atr);
waddch(win, ACS_HLINE); waddch(win, ACS_HLINE);
waddch(win, ACS_HLINE); waddch(win, ACS_HLINE);
waddch(win, ACS_HLINE); waddch(win, ACS_HLINE);
@ -97,8 +103,8 @@ static void print_buttons(WINDOW * dialog, int height, int width, int selected)
int x = width / 2 - 11; int x = width / 2 - 11;
int y = height - 2; int y = height - 2;
print_button(dialog, "Select", y, x, selected == 0); print_button(dialog, gettext("Select"), y, x, selected == 0);
print_button(dialog, " Help ", y, x + 14, selected == 1); print_button(dialog, gettext(" Help "), y, x + 14, selected == 1);
wmove(dialog, y, x + 1 + 14 * selected); wmove(dialog, y, x + 1 + 14 * selected);
wrefresh(dialog); wrefresh(dialog);
@ -109,32 +115,29 @@ static void print_buttons(WINDOW * dialog, int height, int width, int selected)
* in the style of radiolist (only one option turned on at a time). * in the style of radiolist (only one option turned on at a time).
*/ */
int dialog_checklist(const char *title, const char *prompt, int height, int dialog_checklist(const char *title, const char *prompt, int height,
int width, int list_height, int item_no, int width, int list_height)
const char *const *items)
{ {
int i, x, y, box_x, box_y; int i, x, y, box_x, box_y;
int key = 0, button = 0, choice = 0, scroll = 0, max_choice, *status; int key = 0, button = 0, choice = 0, scroll = 0, max_choice;
WINDOW *dialog, *list; WINDOW *dialog, *list;
/* Allocate space for storing item on/off status */ /* which item to highlight */
if ((status = malloc(sizeof(int) * item_no)) == NULL) { item_foreach() {
endwin(); if (item_is_tag('X'))
fprintf(stderr, choice = item_n();
"\nCan't allocate memory in dialog_checklist().\n"); if (item_is_selected()) {
exit(-1); choice = item_n();
break;
}
} }
/* Initializes status */ do_resize:
for (i = 0; i < item_no; i++) { if (getmaxy(stdscr) < (height + 6))
status[i] = !strcasecmp(items[i * 3 + 2], "on"); return -ERRDISPLAYTOOSMALL;
if ((!choice && status[i]) if (getmaxx(stdscr) < (width + 6))
|| !strcasecmp(items[i * 3 + 2], "selected")) return -ERRDISPLAYTOOSMALL;
choice = i + 1;
}
if (choice)
choice--;
max_choice = MIN(list_height, item_no); max_choice = MIN(list_height, item_count());
/* center dialog box on screen */ /* center dialog box on screen */
x = (COLS - width) / 2; x = (COLS - width) / 2;
@ -145,17 +148,18 @@ int dialog_checklist(const char *title, const char *prompt, int height,
dialog = newwin(height, width, y, x); dialog = newwin(height, width, y, x);
keypad(dialog, TRUE); keypad(dialog, TRUE);
draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr); draw_box(dialog, 0, 0, height, width,
wattrset(dialog, border_attr); dlg.dialog.atr, dlg.border.atr);
wattrset(dialog, dlg.border.atr);
mvwaddch(dialog, height - 3, 0, ACS_LTEE); mvwaddch(dialog, height - 3, 0, ACS_LTEE);
for (i = 0; i < width - 2; i++) for (i = 0; i < width - 2; i++)
waddch(dialog, ACS_HLINE); waddch(dialog, ACS_HLINE);
wattrset(dialog, dialog_attr); wattrset(dialog, dlg.dialog.atr);
waddch(dialog, ACS_RTEE); waddch(dialog, ACS_RTEE);
print_title(dialog, title, width); print_title(dialog, title, width);
wattrset(dialog, dialog_attr); wattrset(dialog, dlg.dialog.atr);
print_autowrap(dialog, prompt, width - 2, 1, 3); print_autowrap(dialog, prompt, width - 2, 1, 3);
list_width = width - 6; list_width = width - 6;
@ -170,12 +174,13 @@ int dialog_checklist(const char *title, const char *prompt, int height,
/* draw a box around the list items */ /* draw a box around the list items */
draw_box(dialog, box_y, box_x, list_height + 2, list_width + 2, draw_box(dialog, box_y, box_x, list_height + 2, list_width + 2,
menubox_border_attr, menubox_attr); dlg.menubox_border.atr, dlg.menubox.atr);
/* Find length of longest item in order to center checklist */ /* Find length of longest item in order to center checklist */
check_x = 0; check_x = 0;
for (i = 0; i < item_no; i++) item_foreach()
check_x = MAX(check_x, +strlen(items[i * 3 + 1]) + 4); check_x = MAX(check_x, strlen(item_str()) + 4);
check_x = MIN(check_x, list_width);
check_x = (list_width - check_x) / 2; check_x = (list_width - check_x) / 2;
item_x = check_x + 4; item_x = check_x + 4;
@ -187,26 +192,27 @@ int dialog_checklist(const char *title, const char *prompt, int height,
/* Print the list */ /* Print the list */
for (i = 0; i < max_choice; i++) { for (i = 0; i < max_choice; i++) {
print_item(list, items[(scroll + i) * 3 + 1], item_set(scroll + i);
status[i + scroll], i, i == choice); print_item(list, i, i == choice);
} }
print_arrows(dialog, choice, item_no, scroll, print_arrows(dialog, choice, item_count(), scroll,
box_y, box_x + check_x + 5, list_height); box_y, box_x + check_x + 5, list_height);
print_buttons(dialog, height, width, 0); print_buttons(dialog, height, width, 0);
wnoutrefresh(list);
wnoutrefresh(dialog); wnoutrefresh(dialog);
wnoutrefresh(list);
doupdate(); doupdate();
while (key != ESC) { while (key != KEY_ESC) {
key = wgetch(dialog); key = wgetch(dialog);
for (i = 0; i < max_choice; i++) for (i = 0; i < max_choice; i++) {
if (toupper(key) == item_set(i + scroll);
toupper(items[(scroll + i) * 3 + 1][0])) if (toupper(key) == toupper(item_str()[0]))
break; break;
}
if (i < max_choice || key == KEY_UP || key == KEY_DOWN || if (i < max_choice || key == KEY_UP || key == KEY_DOWN ||
key == '+' || key == '-') { key == '+' || key == '-') {
@ -217,47 +223,48 @@ int dialog_checklist(const char *title, const char *prompt, int height,
/* Scroll list down */ /* Scroll list down */
if (list_height > 1) { if (list_height > 1) {
/* De-highlight current first item */ /* De-highlight current first item */
print_item(list, items[scroll * 3 + 1], item_set(scroll);
status[scroll], 0, FALSE); print_item(list, 0, FALSE);
scrollok(list, TRUE); scrollok(list, TRUE);
wscrl(list, -1); wscrl(list, -1);
scrollok(list, FALSE); scrollok(list, FALSE);
} }
scroll--; scroll--;
print_item(list, items[scroll * 3 + 1], status[scroll], 0, TRUE); item_set(scroll);
wnoutrefresh(list); print_item(list, 0, TRUE);
print_arrows(dialog, choice, item_count(),
print_arrows(dialog, choice, item_no,
scroll, box_y, box_x + check_x + 5, list_height); scroll, box_y, box_x + check_x + 5, list_height);
wrefresh(dialog); wnoutrefresh(dialog);
wrefresh(list);
continue; /* wait for another key press */ continue; /* wait for another key press */
} else } else
i = choice - 1; i = choice - 1;
} else if (key == KEY_DOWN || key == '+') { } else if (key == KEY_DOWN || key == '+') {
if (choice == max_choice - 1) { if (choice == max_choice - 1) {
if (scroll + choice >= item_no - 1) if (scroll + choice >= item_count() - 1)
continue; continue;
/* Scroll list up */ /* Scroll list up */
if (list_height > 1) { if (list_height > 1) {
/* De-highlight current last item before scrolling up */ /* De-highlight current last item before scrolling up */
print_item(list, items[(scroll + max_choice - 1) * 3 + 1], item_set(scroll + max_choice - 1);
status[scroll + max_choice - 1], print_item(list,
max_choice - 1, FALSE); max_choice - 1,
FALSE);
scrollok(list, TRUE); scrollok(list, TRUE);
wscrl(list, 1); wscrl(list, 1);
scrollok(list, FALSE); scrollok(list, FALSE);
} }
scroll++; scroll++;
print_item(list, items[(scroll + max_choice - 1) * 3 + 1], item_set(scroll + max_choice - 1);
status[scroll + max_choice - 1], max_choice - 1, TRUE); print_item(list, max_choice - 1, TRUE);
wnoutrefresh(list);
print_arrows(dialog, choice, item_no, print_arrows(dialog, choice, item_count(),
scroll, box_y, box_x + check_x + 5, list_height); scroll, box_y, box_x + check_x + 5, list_height);
wrefresh(dialog); wnoutrefresh(dialog);
wrefresh(list);
continue; /* wait for another key press */ continue; /* wait for another key press */
} else } else
@ -265,14 +272,14 @@ int dialog_checklist(const char *title, const char *prompt, int height,
} }
if (i != choice) { if (i != choice) {
/* De-highlight current item */ /* De-highlight current item */
print_item(list, items[(scroll + choice) * 3 + 1], item_set(scroll + choice);
status[scroll + choice], choice, FALSE); print_item(list, choice, FALSE);
/* Highlight new item */ /* Highlight new item */
choice = i; choice = i;
print_item(list, items[(scroll + choice) * 3 + 1], item_set(scroll + choice);
status[scroll + choice], choice, TRUE); print_item(list, choice, TRUE);
wnoutrefresh(list); wnoutrefresh(dialog);
wrefresh(dialog); wrefresh(list);
} }
continue; /* wait for another key press */ continue; /* wait for another key press */
} }
@ -280,10 +287,19 @@ int dialog_checklist(const char *title, const char *prompt, int height,
case 'H': case 'H':
case 'h': case 'h':
case '?': case '?':
fprintf(stderr, "%s", items[(scroll + choice) * 3]); button = 1;
/* fall-through */
case 'S':
case 's':
case ' ':
case '\n':
item_foreach()
item_set_selected(0);
item_set(scroll + choice);
item_set_selected(1);
delwin(list);
delwin(dialog); delwin(dialog);
free(status); return button;
return 1;
case TAB: case TAB:
case KEY_LEFT: case KEY_LEFT:
case KEY_RIGHT: case KEY_RIGHT:
@ -293,42 +309,24 @@ int dialog_checklist(const char *title, const char *prompt, int height,
print_buttons(dialog, height, width, button); print_buttons(dialog, height, width, button);
wrefresh(dialog); wrefresh(dialog);
break; break;
case 'S':
case 's':
case ' ':
case '\n':
if (!button) {
if (!status[scroll + choice]) {
for (i = 0; i < item_no; i++)
status[i] = 0;
status[scroll + choice] = 1;
for (i = 0; i < max_choice; i++)
print_item(list, items[(scroll + i) * 3 + 1],
status[scroll + i], i, i == choice);
}
wnoutrefresh(list);
wrefresh(dialog);
for (i = 0; i < item_no; i++)
if (status[i])
fprintf(stderr, "%s", items[i * 3]);
} else
fprintf(stderr, "%s", items[(scroll + choice) * 3]);
delwin(dialog);
free(status);
return button;
case 'X': case 'X':
case 'x': case 'x':
key = ESC; key = KEY_ESC;
case ESC:
break; break;
case KEY_ESC:
key = on_key_esc(dialog);
break;
case KEY_RESIZE:
delwin(list);
delwin(dialog);
on_key_resize();
goto do_resize;
} }
/* Now, update everything... */ /* Now, update everything... */
doupdate(); doupdate();
} }
delwin(list);
delwin(dialog); delwin(dialog);
free(status); return key; /* ESC pressed */
return -1; /* ESC pressed */
} }

View file

@ -1,154 +0,0 @@
/*
* colors.h -- color attribute definitions
*
* AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* Default color definitions
*
* *_FG = foreground
* *_BG = background
* *_HL = highlight?
*/
#define SCREEN_FG COLOR_CYAN
#define SCREEN_BG COLOR_BLUE
#define SCREEN_HL TRUE
#define SHADOW_FG COLOR_BLACK
#define SHADOW_BG COLOR_BLACK
#define SHADOW_HL TRUE
#define DIALOG_FG COLOR_BLACK
#define DIALOG_BG COLOR_WHITE
#define DIALOG_HL FALSE
#define TITLE_FG COLOR_BLUE
#define TITLE_BG COLOR_WHITE
#define TITLE_HL TRUE
#define BORDER_FG COLOR_WHITE
#define BORDER_BG COLOR_WHITE
#define BORDER_HL TRUE
#define BUTTON_ACTIVE_FG COLOR_WHITE
#define BUTTON_ACTIVE_BG COLOR_BLUE
#define BUTTON_ACTIVE_HL TRUE
#define BUTTON_INACTIVE_FG COLOR_BLACK
#define BUTTON_INACTIVE_BG COLOR_WHITE
#define BUTTON_INACTIVE_HL FALSE
#define BUTTON_KEY_ACTIVE_FG COLOR_WHITE
#define BUTTON_KEY_ACTIVE_BG COLOR_BLUE
#define BUTTON_KEY_ACTIVE_HL TRUE
#define BUTTON_KEY_INACTIVE_FG COLOR_RED
#define BUTTON_KEY_INACTIVE_BG COLOR_WHITE
#define BUTTON_KEY_INACTIVE_HL FALSE
#define BUTTON_LABEL_ACTIVE_FG COLOR_YELLOW
#define BUTTON_LABEL_ACTIVE_BG COLOR_BLUE
#define BUTTON_LABEL_ACTIVE_HL TRUE
#define BUTTON_LABEL_INACTIVE_FG COLOR_BLACK
#define BUTTON_LABEL_INACTIVE_BG COLOR_WHITE
#define BUTTON_LABEL_INACTIVE_HL TRUE
#define INPUTBOX_FG COLOR_BLACK
#define INPUTBOX_BG COLOR_WHITE
#define INPUTBOX_HL FALSE
#define INPUTBOX_BORDER_FG COLOR_BLACK
#define INPUTBOX_BORDER_BG COLOR_WHITE
#define INPUTBOX_BORDER_HL FALSE
#define SEARCHBOX_FG COLOR_BLACK
#define SEARCHBOX_BG COLOR_WHITE
#define SEARCHBOX_HL FALSE
#define SEARCHBOX_TITLE_FG COLOR_BLUE
#define SEARCHBOX_TITLE_BG COLOR_WHITE
#define SEARCHBOX_TITLE_HL TRUE
#define SEARCHBOX_BORDER_FG COLOR_WHITE
#define SEARCHBOX_BORDER_BG COLOR_WHITE
#define SEARCHBOX_BORDER_HL TRUE
#define POSITION_INDICATOR_FG COLOR_BLUE
#define POSITION_INDICATOR_BG COLOR_WHITE
#define POSITION_INDICATOR_HL TRUE
#define MENUBOX_FG COLOR_BLACK
#define MENUBOX_BG COLOR_WHITE
#define MENUBOX_HL FALSE
#define MENUBOX_BORDER_FG COLOR_WHITE
#define MENUBOX_BORDER_BG COLOR_WHITE
#define MENUBOX_BORDER_HL TRUE
#define ITEM_FG COLOR_BLACK
#define ITEM_BG COLOR_WHITE
#define ITEM_HL FALSE
#define ITEM_SELECTED_FG COLOR_WHITE
#define ITEM_SELECTED_BG COLOR_BLUE
#define ITEM_SELECTED_HL TRUE
#define TAG_FG COLOR_BLUE
#define TAG_BG COLOR_WHITE
#define TAG_HL TRUE
#define TAG_SELECTED_FG COLOR_YELLOW
#define TAG_SELECTED_BG COLOR_BLUE
#define TAG_SELECTED_HL TRUE
#define TAG_KEY_FG COLOR_BLUE
#define TAG_KEY_BG COLOR_WHITE
#define TAG_KEY_HL TRUE
#define TAG_KEY_SELECTED_FG COLOR_YELLOW
#define TAG_KEY_SELECTED_BG COLOR_BLUE
#define TAG_KEY_SELECTED_HL TRUE
#define CHECK_FG COLOR_BLACK
#define CHECK_BG COLOR_WHITE
#define CHECK_HL FALSE
#define CHECK_SELECTED_FG COLOR_WHITE
#define CHECK_SELECTED_BG COLOR_BLUE
#define CHECK_SELECTED_HL TRUE
#define UARROW_FG COLOR_GREEN
#define UARROW_BG COLOR_WHITE
#define UARROW_HL TRUE
#define DARROW_FG COLOR_GREEN
#define DARROW_BG COLOR_WHITE
#define DARROW_HL TRUE
/* End of default color definitions */
#define C_ATTR(x,y) ((x ? A_BOLD : 0) | COLOR_PAIR((y)))
#define COLOR_NAME_LEN 10
#define COLOR_COUNT 8
/*
* Global variables
*/
extern int color_table[][3];

View file

@ -24,6 +24,13 @@
#include <ctype.h> #include <ctype.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <stdbool.h>
#ifndef KBUILD_NO_NLS
# include <libintl.h>
#else
# define gettext(Msgid) ((const char *) (Msgid))
#endif
#ifdef __sun__ #ifdef __sun__
#define CURS_MACROS #define CURS_MACROS
@ -48,7 +55,7 @@
#define TR(params) _tracef params #define TR(params) _tracef params
#define ESC 27 #define KEY_ESC 27
#define TAB 9 #define TAB 9
#define MAX_LEN 2048 #define MAX_LEN 2048
#define BUF_SIZE (10*1024) #define BUF_SIZE (10*1024)
@ -86,63 +93,112 @@
#define ACS_DARROW 'v' #define ACS_DARROW 'v'
#endif #endif
/* /* error return codes */
* Attribute names #define ERRDISPLAYTOOSMALL (KEY_MAX + 1)
*/
#define screen_attr attributes[0]
#define shadow_attr attributes[1]
#define dialog_attr attributes[2]
#define title_attr attributes[3]
#define border_attr attributes[4]
#define button_active_attr attributes[5]
#define button_inactive_attr attributes[6]
#define button_key_active_attr attributes[7]
#define button_key_inactive_attr attributes[8]
#define button_label_active_attr attributes[9]
#define button_label_inactive_attr attributes[10]
#define inputbox_attr attributes[11]
#define inputbox_border_attr attributes[12]
#define searchbox_attr attributes[13]
#define searchbox_title_attr attributes[14]
#define searchbox_border_attr attributes[15]
#define position_indicator_attr attributes[16]
#define menubox_attr attributes[17]
#define menubox_border_attr attributes[18]
#define item_attr attributes[19]
#define item_selected_attr attributes[20]
#define tag_attr attributes[21]
#define tag_selected_attr attributes[22]
#define tag_key_attr attributes[23]
#define tag_key_selected_attr attributes[24]
#define check_attr attributes[25]
#define check_selected_attr attributes[26]
#define uarrow_attr attributes[27]
#define darrow_attr attributes[28]
/* number of attributes */ /*
#define ATTRIBUTE_COUNT 29 * Color definitions
*/
struct dialog_color {
chtype atr; /* Color attribute */
int fg; /* foreground */
int bg; /* background */
int hl; /* highlight this item */
};
struct dialog_info {
const char *backtitle;
struct dialog_color screen;
struct dialog_color shadow;
struct dialog_color dialog;
struct dialog_color title;
struct dialog_color border;
struct dialog_color button_active;
struct dialog_color button_inactive;
struct dialog_color button_key_active;
struct dialog_color button_key_inactive;
struct dialog_color button_label_active;
struct dialog_color button_label_inactive;
struct dialog_color inputbox;
struct dialog_color inputbox_border;
struct dialog_color searchbox;
struct dialog_color searchbox_title;
struct dialog_color searchbox_border;
struct dialog_color position_indicator;
struct dialog_color menubox;
struct dialog_color menubox_border;
struct dialog_color item;
struct dialog_color item_selected;
struct dialog_color tag;
struct dialog_color tag_selected;
struct dialog_color tag_key;
struct dialog_color tag_key_selected;
struct dialog_color check;
struct dialog_color check_selected;
struct dialog_color uarrow;
struct dialog_color darrow;
};
/* /*
* Global variables * Global variables
*/ */
extern bool use_colors; extern struct dialog_info dlg;
extern bool use_shadow; extern char dialog_input_result[];
extern int saved_x, saved_y; /* Needed in signal handler in mconf.c */
extern chtype attributes[];
extern const char *backtitle;
/* /*
* Function prototypes * Function prototypes
*/ */
extern void create_rc(const char *filename);
extern int parse_rc(void);
void init_dialog(void); /* item list as used by checklist and menubox */
void end_dialog(void); void item_reset(void);
void item_make(const char *fmt, ...);
void item_add_str(const char *fmt, ...);
void item_set_tag(char tag);
void item_set_data(void *p);
void item_set_selected(int val);
int item_activate_selected(void);
void *item_data(void);
char item_tag(void);
/* item list manipulation for lxdialog use */
#define MAXITEMSTR 200
struct dialog_item {
char str[MAXITEMSTR]; /* promtp displayed */
char tag;
void *data; /* pointer to menu item - used by menubox+checklist */
int selected; /* Set to 1 by dialog_*() function if selected. */
};
/* list of lialog_items */
struct dialog_list {
struct dialog_item node;
struct dialog_list *next;
};
extern struct dialog_list *item_cur;
extern struct dialog_list item_nil;
extern struct dialog_list *item_head;
int item_count(void);
void item_set(int n);
int item_n(void);
const char *item_str(void);
int item_is_selected(void);
int item_is_tag(char tag);
#define item_foreach() \
for (item_cur = item_head ? item_head: item_cur; \
item_cur && (item_cur != &item_nil); item_cur = item_cur->next)
/* generic key handlers */
int on_key_esc(WINDOW *win);
int on_key_resize(void);
int init_dialog(const char *backtitle);
void set_dialog_backtitle(const char *backtitle);
void end_dialog(int x, int y);
void attr_clear(WINDOW * win, int height, int width, chtype attr); void attr_clear(WINDOW * win, int height, int width, chtype attr);
void dialog_clear(void); void dialog_clear(void);
void color_setup(void);
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);
void print_button(WINDOW * win, const char *label, int y, int x, int selected); void print_button(WINDOW * win, const char *label, int y, int x, int selected);
void print_title(WINDOW *dialog, const char *title, int width); void print_title(WINDOW *dialog, const char *title, int width);
@ -154,14 +210,17 @@ int first_alpha(const char *string, const char *exempt);
int dialog_yesno(const char *title, const char *prompt, int height, int width); int dialog_yesno(const char *title, const char *prompt, int height, int width);
int dialog_msgbox(const char *title, const char *prompt, int height, int dialog_msgbox(const char *title, const char *prompt, int height,
int width, int pause); int width, int pause);
int dialog_textbox(const char *title, const char *file, int height, int width);
int dialog_menu(const char *title, const char *prompt, int height, int width,
int menu_height, const char *choice, int item_no, typedef void (*update_text_fn)(char *buf, size_t start, size_t end, void
const char *const *items); *_data);
int dialog_textbox(const char *title, char *tbuf, int initial_height,
int initial_width, int *keys, int *_vscroll, int *_hscroll,
update_text_fn update_text, void *data);
int dialog_menu(const char *title, const char *prompt,
const void *selected, int *s_scroll);
int dialog_checklist(const char *title, const char *prompt, int height, int dialog_checklist(const char *title, const char *prompt, int height,
int width, int list_height, int item_no, int width, int list_height);
const char *const *items);
extern char dialog_input_result[];
int dialog_inputbox(const char *title, const char *prompt, int height, int dialog_inputbox(const char *title, const char *prompt, int height,
int width, const char *init); int width, const char *init);

View file

@ -31,8 +31,8 @@ static void print_buttons(WINDOW * dialog, int height, int width, int selected)
int x = width / 2 - 11; int x = width / 2 - 11;
int y = height - 2; int y = height - 2;
print_button(dialog, " Ok ", y, x, selected == 0); print_button(dialog, gettext(" Ok "), y, x, selected == 0);
print_button(dialog, " Help ", y, x + 14, selected == 1); print_button(dialog, gettext(" Help "), y, x + 14, selected == 1);
wmove(dialog, y, x + 1 + 14 * selected); wmove(dialog, y, x + 1 + 14 * selected);
wrefresh(dialog); wrefresh(dialog);
@ -45,10 +45,22 @@ int dialog_inputbox(const char *title, const char *prompt, int height, int width
const char *init) const char *init)
{ {
int i, x, y, box_y, box_x, box_width; int i, x, y, box_y, box_x, box_width;
int input_x = 0, scroll = 0, key = 0, button = -1; int input_x = 0, key = 0, button = -1;
int show_x, len, pos;
char *instr = dialog_input_result; char *instr = dialog_input_result;
WINDOW *dialog; WINDOW *dialog;
if (!init)
instr[0] = '\0';
else
strcpy(instr, init);
do_resize:
if (getmaxy(stdscr) <= (height - 2))
return -ERRDISPLAYTOOSMALL;
if (getmaxx(stdscr) <= (width - 2))
return -ERRDISPLAYTOOSMALL;
/* center dialog box on screen */ /* center dialog box on screen */
x = (COLS - width) / 2; x = (COLS - width) / 2;
y = (LINES - height) / 2; y = (LINES - height) / 2;
@ -58,17 +70,18 @@ int dialog_inputbox(const char *title, const char *prompt, int height, int width
dialog = newwin(height, width, y, x); dialog = newwin(height, width, y, x);
keypad(dialog, TRUE); keypad(dialog, TRUE);
draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr); draw_box(dialog, 0, 0, height, width,
wattrset(dialog, border_attr); dlg.dialog.atr, dlg.border.atr);
wattrset(dialog, dlg.border.atr);
mvwaddch(dialog, height - 3, 0, ACS_LTEE); mvwaddch(dialog, height - 3, 0, ACS_LTEE);
for (i = 0; i < width - 2; i++) for (i = 0; i < width - 2; i++)
waddch(dialog, ACS_HLINE); waddch(dialog, ACS_HLINE);
wattrset(dialog, dialog_attr); wattrset(dialog, dlg.dialog.atr);
waddch(dialog, ACS_RTEE); waddch(dialog, ACS_RTEE);
print_title(dialog, title, width); print_title(dialog, title, width);
wattrset(dialog, dialog_attr); wattrset(dialog, dlg.dialog.atr);
print_autowrap(dialog, prompt, width - 2, 1, 3); print_autowrap(dialog, prompt, width - 2, 1, 3);
/* Draw the input field box */ /* Draw the input field box */
@ -76,27 +89,26 @@ int dialog_inputbox(const char *title, const char *prompt, int height, int width
getyx(dialog, y, x); getyx(dialog, y, x);
box_y = y + 2; box_y = y + 2;
box_x = (width - box_width) / 2; box_x = (width - box_width) / 2;
draw_box(dialog, y + 1, box_x - 1, 3, box_width + 2, border_attr, dialog_attr); draw_box(dialog, y + 1, box_x - 1, 3, box_width + 2,
dlg.dialog.atr, dlg.border.atr);
print_buttons(dialog, height, width, 0); print_buttons(dialog, height, width, 0);
/* Set up the initial value */ /* Set up the initial value */
wmove(dialog, box_y, box_x); wmove(dialog, box_y, box_x);
wattrset(dialog, inputbox_attr); wattrset(dialog, dlg.inputbox.atr);
if (!init) len = strlen(instr);
instr[0] = '\0'; pos = len;
else
strcpy(instr, init);
input_x = strlen(instr); if (len >= box_width) {
show_x = len - box_width + 1;
if (input_x >= box_width) {
scroll = input_x - box_width + 1;
input_x = box_width - 1; input_x = box_width - 1;
for (i = 0; i < box_width - 1; i++) for (i = 0; i < box_width - 1; i++)
waddch(dialog, instr[scroll + i]); waddch(dialog, instr[show_x + i]);
} else { } else {
show_x = 0;
input_x = len;
waddstr(dialog, instr); waddstr(dialog, instr);
} }
@ -104,7 +116,7 @@ int dialog_inputbox(const char *title, const char *prompt, int height, int width
wrefresh(dialog); wrefresh(dialog);
while (key != ESC) { while (key != KEY_ESC) {
key = wgetch(dialog); key = wgetch(dialog);
if (button == -1) { /* Input box selected */ if (button == -1) { /* Input box selected */
@ -113,45 +125,104 @@ int dialog_inputbox(const char *title, const char *prompt, int height, int width
case KEY_UP: case KEY_UP:
case KEY_DOWN: case KEY_DOWN:
break; break;
case KEY_LEFT:
continue;
case KEY_RIGHT:
continue;
case KEY_BACKSPACE: case KEY_BACKSPACE:
case 127: case 127:
if (input_x || scroll) { if (pos) {
wattrset(dialog, inputbox_attr); wattrset(dialog, dlg.inputbox.atr);
if (!input_x) { if (input_x == 0) {
scroll = scroll < box_width - 1 ? 0 : scroll - (box_width - 1); show_x--;
wmove(dialog, box_y, box_x);
for (i = 0; i < box_width; i++)
waddch(dialog,
instr[scroll + input_x + i] ?
instr[scroll + input_x + i] : ' ');
input_x = strlen(instr) - scroll;
} else } else
input_x--; input_x--;
instr[scroll + input_x] = '\0';
mvwaddch(dialog, box_y, input_x + box_x, ' '); if (pos < len) {
for (i = pos - 1; i < len; i++) {
instr[i] = instr[i+1];
}
}
pos--;
len--;
instr[len] = '\0';
wmove(dialog, box_y, box_x);
for (i = 0; i < box_width; i++) {
if (!instr[show_x + i]) {
waddch(dialog, ' ');
break;
}
waddch(dialog, instr[show_x + i]);
}
wmove(dialog, box_y, input_x + box_x); wmove(dialog, box_y, input_x + box_x);
wrefresh(dialog); wrefresh(dialog);
} }
continue; continue;
case KEY_LEFT:
if (pos > 0) {
if (input_x > 0) {
wmove(dialog, box_y, --input_x + box_x);
} else if (input_x == 0) {
show_x--;
wmove(dialog, box_y, box_x);
for (i = 0; i < box_width; i++) {
if (!instr[show_x + i]) {
waddch(dialog, ' ');
break;
}
waddch(dialog, instr[show_x + i]);
}
wmove(dialog, box_y, box_x);
}
pos--;
}
continue;
case KEY_RIGHT:
if (pos < len) {
if (input_x < box_width - 1) {
wmove(dialog, box_y, ++input_x + box_x);
} else if (input_x == box_width - 1) {
show_x++;
wmove(dialog, box_y, box_x);
for (i = 0; i < box_width; i++) {
if (!instr[show_x + i]) {
waddch(dialog, ' ');
break;
}
waddch(dialog, instr[show_x + i]);
}
wmove(dialog, box_y, input_x + box_x);
}
pos++;
}
continue;
default: default:
if (key < 0x100 && isprint(key)) { if (key < 0x100 && isprint(key)) {
if (scroll + input_x < MAX_LEN) { if (len < MAX_LEN) {
wattrset(dialog, inputbox_attr); wattrset(dialog, dlg.inputbox.atr);
instr[scroll + input_x] = key; if (pos < len) {
instr[scroll + input_x + 1] = '\0'; for (i = len; i > pos; i--)
if (input_x == box_width - 1) { instr[i] = instr[i-1];
scroll++; instr[pos] = key;
wmove(dialog, box_y, box_x);
for (i = 0; i < box_width - 1; i++)
waddch(dialog, instr [scroll + i]);
} else { } else {
wmove(dialog, box_y, input_x++ + box_x); instr[len] = key;
waddch(dialog, key);
} }
pos++;
len++;
instr[len] = '\0';
if (input_x == box_width - 1) {
show_x++;
} else {
input_x++;
}
wmove(dialog, box_y, box_x);
for (i = 0; i < box_width; i++) {
if (!instr[show_x + i]) {
waddch(dialog, ' ');
break;
}
waddch(dialog, instr[show_x + i]);
}
wmove(dialog, box_y, input_x + box_x);
wrefresh(dialog); wrefresh(dialog);
} else } else
flash(); /* Alarm user about overflow */ flash(); /* Alarm user about overflow */
@ -172,7 +243,7 @@ int dialog_inputbox(const char *title, const char *prompt, int height, int width
case KEY_LEFT: case KEY_LEFT:
switch (button) { switch (button) {
case -1: case -1:
button = 1; /* Indicates "Cancel" button is selected */ button = 1; /* Indicates "Help" button is selected */
print_buttons(dialog, height, width, 1); print_buttons(dialog, height, width, 1);
break; break;
case 0: case 0:
@ -196,7 +267,7 @@ int dialog_inputbox(const char *title, const char *prompt, int height, int width
print_buttons(dialog, height, width, 0); print_buttons(dialog, height, width, 0);
break; break;
case 0: case 0:
button = 1; /* Indicates "Cancel" button is selected */ button = 1; /* Indicates "Help" button is selected */
print_buttons(dialog, height, width, 1); print_buttons(dialog, height, width, 1);
break; break;
case 1: case 1:
@ -213,12 +284,18 @@ int dialog_inputbox(const char *title, const char *prompt, int height, int width
return (button == -1 ? 0 : button); return (button == -1 ? 0 : button);
case 'X': case 'X':
case 'x': case 'x':
key = ESC; key = KEY_ESC;
case ESC:
break; break;
case KEY_ESC:
key = on_key_esc(dialog);
break;
case KEY_RESIZE:
delwin(dialog);
on_key_resize();
goto do_resize;
} }
} }
delwin(dialog); delwin(dialog);
return -1; /* ESC pressed */ return KEY_ESC; /* ESC pressed */
} }

View file

@ -1,204 +0,0 @@
/*
* dialog - Display simple dialog boxes from shell scripts
*
* ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
* MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "dialog.h"
static void Usage(const char *name);
typedef int (jumperFn) (const char *title, int argc, const char *const *argv);
struct Mode {
char *name;
int argmin, argmax, argmod;
jumperFn *jumper;
};
jumperFn j_menu, j_radiolist, j_yesno, j_textbox, j_inputbox;
jumperFn j_msgbox, j_infobox;
static struct Mode modes[] = {
{"--menu", 9, 0, 3, j_menu},
{"--radiolist", 9, 0, 3, j_radiolist},
{"--yesno", 5, 5, 1, j_yesno},
{"--textbox", 5, 5, 1, j_textbox},
{"--inputbox", 5, 6, 1, j_inputbox},
{"--msgbox", 5, 5, 1, j_msgbox},
{"--infobox", 5, 5, 1, j_infobox},
{NULL, 0, 0, 0, NULL}
};
static struct Mode *modePtr;
#ifdef LOCALE
#include <locale.h>
#endif
int main(int argc, const char *const *argv)
{
int offset = 0, opt_clear = 0, end_common_opts = 0, retval;
const char *title = NULL;
#ifdef LOCALE
(void)setlocale(LC_ALL, "");
#endif
#ifdef TRACE
trace(TRACE_CALLS | TRACE_UPDATE);
#endif
if (argc < 2) {
Usage(argv[0]);
exit(-1);
}
while (offset < argc - 1 && !end_common_opts) { /* Common options */
if (!strcmp(argv[offset + 1], "--title")) {
if (argc - offset < 3 || title != NULL) {
Usage(argv[0]);
exit(-1);
} else {
title = argv[offset + 2];
offset += 2;
}
} else if (!strcmp(argv[offset + 1], "--backtitle")) {
if (backtitle != NULL) {
Usage(argv[0]);
exit(-1);
} else {
backtitle = argv[offset + 2];
offset += 2;
}
} else if (!strcmp(argv[offset + 1], "--clear")) {
if (opt_clear) { /* Hey, "--clear" can't appear twice! */
Usage(argv[0]);
exit(-1);
} else if (argc == 2) { /* we only want to clear the screen */
init_dialog();
refresh(); /* init_dialog() will clear the screen for us */
end_dialog();
return 0;
} else {
opt_clear = 1;
offset++;
}
} else /* no more common options */
end_common_opts = 1;
}
if (argc - 1 == offset) { /* no more options */
Usage(argv[0]);
exit(-1);
}
/* use a table to look for the requested mode, to avoid code duplication */
for (modePtr = modes; modePtr->name; modePtr++) /* look for the mode */
if (!strcmp(argv[offset + 1], modePtr->name))
break;
if (!modePtr->name)
Usage(argv[0]);
if (argc - offset < modePtr->argmin)
Usage(argv[0]);
if (modePtr->argmax && argc - offset > modePtr->argmax)
Usage(argv[0]);
init_dialog();
retval = (*(modePtr->jumper)) (title, argc - offset, argv + offset);
if (opt_clear) { /* clear screen before exit */
attr_clear(stdscr, LINES, COLS, screen_attr);
refresh();
}
end_dialog();
exit(retval);
}
/*
* Print program usage
*/
static void Usage(const char *name)
{
fprintf(stderr, "\
\ndialog, by Savio Lam (lam836@cs.cuhk.hk).\
\n patched by Stuart Herbert (S.Herbert@shef.ac.uk)\
\n modified/gutted for use as a Linux kernel config tool by \
\n William Roadcap (roadcapw@cfw.com)\
\n\
\n* Display dialog boxes from shell scripts *\
\n\
\nUsage: %s --clear\
\n %s [--title <title>] [--backtitle <backtitle>] --clear <Box options>\
\n\
\nBox options:\
\n\
\n --menu <text> <height> <width> <menu height> <tag1> <item1>...\
\n --radiolist <text> <height> <width> <list height> <tag1> <item1> <status1>...\
\n --textbox <file> <height> <width>\
\n --inputbox <text> <height> <width> [<init>]\
\n --yesno <text> <height> <width>\
\n", name, name);
exit(-1);
}
/*
* These are the program jumpers
*/
int j_menu(const char *t, int ac, const char *const *av)
{
return dialog_menu(t, av[2], atoi(av[3]), atoi(av[4]),
atoi(av[5]), av[6], (ac - 6) / 2, av + 7);
}
int j_radiolist(const char *t, int ac, const char *const *av)
{
return dialog_checklist(t, av[2], atoi(av[3]), atoi(av[4]),
atoi(av[5]), (ac - 6) / 3, av + 6);
}
int j_textbox(const char *t, int ac, const char *const *av)
{
return dialog_textbox(t, av[2], atoi(av[3]), atoi(av[4]));
}
int j_yesno(const char *t, int ac, const char *const *av)
{
return dialog_yesno(t, av[2], atoi(av[3]), atoi(av[4]));
}
int j_inputbox(const char *t, int ac, const char *const *av)
{
int ret = dialog_inputbox(t, av[2], atoi(av[3]), atoi(av[4]),
ac == 6 ? av[5] : (char *)NULL);
if (ret == 0)
fprintf(stderr, "%s", dialog_input_result);
return ret;
}
int j_msgbox(const char *t, int ac, const char *const *av)
{
return dialog_msgbox(t, av[2], atoi(av[3]), atoi(av[4]), 1);
}
int j_infobox(const char *t, int ac, const char *const *av)
{
return dialog_msgbox(t, av[2], atoi(av[3]), atoi(av[4]), 0);
}

View file

@ -26,7 +26,7 @@
* *
* *) A bugfix for the Page-Down problem * *) A bugfix for the Page-Down problem
* *
* *) Formerly when I used Page Down and Page Up, the cursor would be set * *) Formerly when I used Page Down and Page Up, the cursor would be set
* to the first position in the menu box. Now lxdialog is a bit * to the first position in the menu box. Now lxdialog is a bit
* smarter and works more like other menu systems (just have a look at * smarter and works more like other menu systems (just have a look at
* it). * it).
@ -58,25 +58,24 @@
#include "dialog.h" #include "dialog.h"
#define ITEM_IDENT 1 /* Indent of menu entries. Fixed for all menus */ static int menu_width, item_x;
static int menu_width;
/* /*
* Print menu item * Print menu item
*/ */
static void do_print_item(WINDOW * win, const char *item, int choice, static void do_print_item(WINDOW * win, const char *item, int line_y,
int selected, int hotkey) int selected, int hotkey)
{ {
int j; int j;
char *menu_item = malloc(menu_width + 1); char *menu_item = malloc(menu_width + 1);
strncpy(menu_item, item, menu_width - ITEM_IDENT); strncpy(menu_item, item, menu_width - item_x);
menu_item[menu_width] = 0; menu_item[menu_width - item_x] = '\0';
j = first_alpha(menu_item, "YyNnMmHh"); j = first_alpha(menu_item, "YyNnMmHh");
/* Clear 'residue' of last item */ /* Clear 'residue' of last item */
wattrset(win, menubox_attr); wattrset(win, dlg.menubox.atr);
wmove(win, choice, 0); wmove(win, line_y, 0);
#if OLD_NCURSES #if OLD_NCURSES
{ {
int i; int i;
@ -86,23 +85,24 @@ static void do_print_item(WINDOW * win, const char *item, int choice,
#else #else
wclrtoeol(win); wclrtoeol(win);
#endif #endif
wattrset(win, selected ? item_selected_attr : item_attr); wattrset(win, selected ? dlg.item_selected.atr : dlg.item.atr);
mvwaddstr(win, choice, ITEM_IDENT, menu_item); mvwaddstr(win, line_y, item_x, menu_item);
if (hotkey) { if (hotkey) {
wattrset(win, selected ? tag_key_selected_attr : tag_key_attr); wattrset(win, selected ? dlg.tag_key_selected.atr
mvwaddch(win, choice, ITEM_IDENT + j, menu_item[j]); : dlg.tag_key.atr);
mvwaddch(win, line_y, item_x + j, menu_item[j]);
} }
if (selected) { if (selected) {
wmove(win, choice, ITEM_IDENT + 1); wmove(win, line_y, item_x + 1);
} }
free(menu_item); free(menu_item);
wrefresh(win); wrefresh(win);
} }
#define print_item(index, choice, selected) \ #define print_item(index, choice, selected) \
do {\ do { \
int hotkey = (items[(index) * 2][0] != ':'); \ item_set(index); \
do_print_item(menu, items[(index) * 2 + 1], choice, selected, hotkey); \ do_print_item(menu, item_str(), choice, selected, !item_is_tag(':')); \
} while (0) } while (0)
/* /*
@ -118,11 +118,11 @@ static void print_arrows(WINDOW * win, int item_no, int scroll, int y, int x,
wmove(win, y, x); wmove(win, y, x);
if (scroll > 0) { if (scroll > 0) {
wattrset(win, uarrow_attr); wattrset(win, dlg.uarrow.atr);
waddch(win, ACS_UARROW); waddch(win, ACS_UARROW);
waddstr(win, "(-)"); waddstr(win, "(-)");
} else { } else {
wattrset(win, menubox_attr); wattrset(win, dlg.menubox.atr);
waddch(win, ACS_HLINE); waddch(win, ACS_HLINE);
waddch(win, ACS_HLINE); waddch(win, ACS_HLINE);
waddch(win, ACS_HLINE); waddch(win, ACS_HLINE);
@ -134,11 +134,11 @@ static void print_arrows(WINDOW * win, int item_no, int scroll, int y, int x,
wrefresh(win); wrefresh(win);
if ((height < item_no) && (scroll + height < item_no)) { if ((height < item_no) && (scroll + height < item_no)) {
wattrset(win, darrow_attr); wattrset(win, dlg.darrow.atr);
waddch(win, ACS_DARROW); waddch(win, ACS_DARROW);
waddstr(win, "(+)"); waddstr(win, "(+)");
} else { } else {
wattrset(win, menubox_border_attr); wattrset(win, dlg.menubox_border.atr);
waddch(win, ACS_HLINE); waddch(win, ACS_HLINE);
waddch(win, ACS_HLINE); waddch(win, ACS_HLINE);
waddch(win, ACS_HLINE); waddch(win, ACS_HLINE);
@ -154,12 +154,14 @@ static void print_arrows(WINDOW * win, int item_no, int scroll, int y, int x,
*/ */
static void print_buttons(WINDOW * win, int height, int width, int selected) static void print_buttons(WINDOW * win, int height, int width, int selected)
{ {
int x = width / 2 - 16; int x = width / 2 - 28;
int y = height - 2; int y = height - 2;
print_button(win, "Select", y, x, selected == 0); print_button(win, gettext("Select"), y, x, selected == 0);
print_button(win, " Exit ", y, x + 12, selected == 1); print_button(win, gettext(" Exit "), y, x + 12, selected == 1);
print_button(win, " Help ", y, x + 24, selected == 2); print_button(win, gettext(" Help "), y, x + 24, selected == 2);
print_button(win, gettext(" Save "), y, x + 36, selected == 3);
print_button(win, gettext(" Load "), y, x + 48, selected == 4);
wmove(win, y, x + 1 + 12 * selected); wmove(win, y, x + 1 + 12 * selected);
wrefresh(win); wrefresh(win);
@ -179,17 +181,26 @@ static void do_scroll(WINDOW *win, int *scroll, int n)
/* /*
* Display a menu for choosing among a number of options * Display a menu for choosing among a number of options
*/ */
int dialog_menu(const char *title, const char *prompt, int height, int width, int dialog_menu(const char *title, const char *prompt,
int menu_height, const char *current, int item_no, const void *selected, int *s_scroll)
const char *const *items)
{ {
int i, j, x, y, box_x, box_y; int i, j, x, y, box_x, box_y;
int height, width, menu_height;
int key = 0, button = 0, scroll = 0, choice = 0; int key = 0, button = 0, scroll = 0, choice = 0;
int first_item = 0, max_choice; int first_item = 0, max_choice;
WINDOW *dialog, *menu; WINDOW *dialog, *menu;
FILE *f;
max_choice = MIN(menu_height, item_no); do_resize:
height = getmaxy(stdscr);
width = getmaxx(stdscr);
if (height < 15 || width < 65)
return -ERRDISPLAYTOOSMALL;
height -= 4;
width -= 5;
menu_height = height - 10;
max_choice = MIN(menu_height, item_count());
/* center dialog box on screen */ /* center dialog box on screen */
x = (COLS - width) / 2; x = (COLS - width) / 2;
@ -200,18 +211,19 @@ int dialog_menu(const char *title, const char *prompt, int height, int width,
dialog = newwin(height, width, y, x); dialog = newwin(height, width, y, x);
keypad(dialog, TRUE); keypad(dialog, TRUE);
draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr); draw_box(dialog, 0, 0, height, width,
wattrset(dialog, border_attr); dlg.dialog.atr, dlg.border.atr);
wattrset(dialog, dlg.border.atr);
mvwaddch(dialog, height - 3, 0, ACS_LTEE); mvwaddch(dialog, height - 3, 0, ACS_LTEE);
for (i = 0; i < width - 2; i++) for (i = 0; i < width - 2; i++)
waddch(dialog, ACS_HLINE); waddch(dialog, ACS_HLINE);
wattrset(dialog, dialog_attr); wattrset(dialog, dlg.dialog.atr);
wbkgdset(dialog, dialog_attr & A_COLOR); wbkgdset(dialog, dlg.dialog.atr & A_COLOR);
waddch(dialog, ACS_RTEE); waddch(dialog, ACS_RTEE);
print_title(dialog, title, width); print_title(dialog, title, width);
wattrset(dialog, dialog_attr); wattrset(dialog, dlg.dialog.atr);
print_autowrap(dialog, prompt, width - 2, 1, 3); print_autowrap(dialog, prompt, width - 2, 1, 3);
menu_width = width - 6; menu_width = width - 6;
@ -225,31 +237,29 @@ int dialog_menu(const char *title, const char *prompt, int height, int width,
/* draw a box around the menu items */ /* draw a box around the menu items */
draw_box(dialog, box_y, box_x, menu_height + 2, menu_width + 2, draw_box(dialog, box_y, box_x, menu_height + 2, menu_width + 2,
menubox_border_attr, menubox_attr); dlg.menubox_border.atr, dlg.menubox.atr);
if (menu_width >= 80)
item_x = (menu_width - 70) / 2;
else
item_x = 4;
/* Set choice to default item */ /* Set choice to default item */
for (i = 0; i < item_no; i++) item_foreach()
if (strcmp(current, items[i * 2]) == 0) if (selected && (selected == item_data()))
choice = i; choice = item_n();
/* get the saved scroll info */
/* get the scroll info from the temp file */ scroll = *s_scroll;
if ((f = fopen("lxdialog.scrltmp", "r")) != NULL) { if ((scroll <= choice) && (scroll + max_choice > choice) &&
if ((fscanf(f, "%d\n", &scroll) == 1) && (scroll <= choice) && (scroll >= 0) && (scroll + max_choice <= item_count())) {
(scroll + max_choice > choice) && (scroll >= 0) && first_item = scroll;
(scroll + max_choice <= item_no)) { choice = choice - scroll;
first_item = scroll; } else {
choice = choice - scroll; scroll = 0;
fclose(f);
} else {
scroll = 0;
remove("lxdialog.scrltmp");
fclose(f);
f = NULL;
}
} }
if ((choice >= max_choice) || (f == NULL && choice >= max_choice / 2)) { if ((choice >= max_choice)) {
if (choice >= item_no - max_choice / 2) if (choice >= item_count() - max_choice / 2)
scroll = first_item = item_no - max_choice; scroll = first_item = item_count() - max_choice;
else else
scroll = first_item = choice - max_choice / 2; scroll = first_item = choice - max_choice / 2;
choice = choice - scroll; choice = choice - scroll;
@ -262,14 +272,14 @@ int dialog_menu(const char *title, const char *prompt, int height, int width,
wnoutrefresh(menu); wnoutrefresh(menu);
print_arrows(dialog, item_no, scroll, print_arrows(dialog, item_count(), scroll,
box_y, box_x + ITEM_IDENT + 1, menu_height); box_y, box_x + item_x + 1, menu_height);
print_buttons(dialog, height, width, 0); print_buttons(dialog, height, width, 0);
wmove(menu, choice, ITEM_IDENT + 1); wmove(menu, choice, item_x + 1);
wrefresh(menu); wrefresh(menu);
while (key != ESC) { while (key != KEY_ESC) {
key = wgetch(menu); key = wgetch(menu);
if (key < 256 && isalpha(key)) if (key < 256 && isalpha(key))
@ -279,14 +289,16 @@ int dialog_menu(const char *title, const char *prompt, int height, int width,
i = max_choice; i = max_choice;
else { else {
for (i = choice + 1; i < max_choice; i++) { for (i = choice + 1; i < max_choice; i++) {
j = first_alpha(items[(scroll + i) * 2 + 1], "YyNnMmHh"); item_set(scroll + i);
if (key == tolower(items[(scroll + i) * 2 + 1][j])) j = first_alpha(item_str(), "YyNnMmHh");
if (key == tolower(item_str()[j]))
break; break;
} }
if (i == max_choice) if (i == max_choice)
for (i = 0; i < max_choice; i++) { for (i = 0; i < max_choice; i++) {
j = first_alpha(items [(scroll + i) * 2 + 1], "YyNnMmHh"); item_set(scroll + i);
if (key == tolower(items[(scroll + i) * 2 + 1][j])) j = first_alpha(item_str(), "YyNnMmHh");
if (key == tolower(item_str()[j]))
break; break;
} }
} }
@ -311,7 +323,7 @@ int dialog_menu(const char *title, const char *prompt, int height, int width,
print_item(scroll+choice, choice, FALSE); print_item(scroll+choice, choice, FALSE);
if ((choice > max_choice - 3) && if ((choice > max_choice - 3) &&
(scroll + max_choice < item_no)) { (scroll + max_choice < item_count())) {
/* Scroll menu up */ /* Scroll menu up */
do_scroll(menu, &scroll, 1); do_scroll(menu, &scroll, 1);
@ -334,7 +346,7 @@ int dialog_menu(const char *title, const char *prompt, int height, int width,
} else if (key == KEY_NPAGE) { } else if (key == KEY_NPAGE) {
for (i = 0; (i < max_choice); i++) { for (i = 0; (i < max_choice); i++) {
if (scroll + max_choice < item_no) { if (scroll + max_choice < item_count()) {
do_scroll(menu, &scroll, 1); do_scroll(menu, &scroll, 1);
print_item(scroll+max_choice-1, print_item(scroll+max_choice-1,
max_choice - 1, FALSE); max_choice - 1, FALSE);
@ -348,8 +360,8 @@ int dialog_menu(const char *title, const char *prompt, int height, int width,
print_item(scroll + choice, choice, TRUE); print_item(scroll + choice, choice, TRUE);
print_arrows(dialog, item_no, scroll, print_arrows(dialog, item_count(), scroll,
box_y, box_x + ITEM_IDENT + 1, menu_height); box_y, box_x + item_x + 1, menu_height);
wnoutrefresh(dialog); wnoutrefresh(dialog);
wrefresh(menu); wrefresh(menu);
@ -362,7 +374,7 @@ int dialog_menu(const char *title, const char *prompt, int height, int width,
case TAB: case TAB:
case KEY_RIGHT: case KEY_RIGHT:
button = ((key == KEY_LEFT ? --button : ++button) < 0) button = ((key == KEY_LEFT ? --button : ++button) < 0)
? 2 : (button > 2 ? 0 : button); ? 4 : (button > 4 ? 0 : button);
print_buttons(dialog, height, width, button); print_buttons(dialog, height, width, button);
wrefresh(menu); wrefresh(menu);
@ -373,53 +385,52 @@ int dialog_menu(const char *title, const char *prompt, int height, int width,
case 'n': case 'n':
case 'm': case 'm':
case '/': case '/':
/* save scroll info */
if ((f = fopen("lxdialog.scrltmp", "w")) != NULL) {
fprintf(f, "%d\n", scroll);
fclose(f);
}
delwin(dialog);
fprintf(stderr, "%s\n", items[(scroll + choice) * 2]);
switch (key) {
case 's':
return 3;
case 'y':
return 3;
case 'n':
return 4;
case 'm':
return 5;
case ' ':
return 6;
case '/':
return 7;
}
return 0;
case 'h': case 'h':
case '?': case '?':
button = 2; case 'z':
case '\n': case '\n':
/* save scroll info */
*s_scroll = scroll;
delwin(menu);
delwin(dialog); delwin(dialog);
if (button == 2) item_set(scroll + choice);
fprintf(stderr, "%s \"%s\"\n", item_set_selected(1);
items[(scroll + choice) * 2], switch (key) {
items[(scroll + choice) * 2 + 1] + case 'h':
first_alpha(items [(scroll + choice) * 2 + 1], "")); case '?':
else return 2;
fprintf(stderr, "%s\n", case 's':
items[(scroll + choice) * 2]); case 'y':
return 5;
remove("lxdialog.scrltmp"); case 'n':
return button; return 6;
case 'm':
return 7;
case ' ':
return 8;
case '/':
return 9;
case 'z':
return 10;
case '\n':
return button;
}
return 0;
case 'e': case 'e':
case 'x': case 'x':
key = ESC; key = KEY_ESC;
case ESC:
break; break;
case KEY_ESC:
key = on_key_esc(menu);
break;
case KEY_RESIZE:
on_key_resize();
delwin(menu);
delwin(dialog);
goto do_resize;
} }
} }
delwin(menu);
delwin(dialog); delwin(dialog);
remove("lxdialog.scrltmp"); return key; /* ESC pressed */
return -1; /* ESC pressed */
} }

View file

@ -1,71 +0,0 @@
/*
* msgbox.c -- implements the message box and info box
*
* ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
* MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcapw@cfw.com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "dialog.h"
/*
* Display a message box. Program will pause and display an "OK" button
* if the parameter 'pause' is non-zero.
*/
int dialog_msgbox(const char *title, const char *prompt, int height, int width,
int pause)
{
int i, x, y, key = 0;
WINDOW *dialog;
/* center dialog box on screen */
x = (COLS - width) / 2;
y = (LINES - height) / 2;
draw_shadow(stdscr, y, x, height, width);
dialog = newwin(height, width, y, x);
keypad(dialog, TRUE);
draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr);
print_title(dialog, title, width);
wattrset(dialog, dialog_attr);
print_autowrap(dialog, prompt, width - 2, 1, 2);
if (pause) {
wattrset(dialog, border_attr);
mvwaddch(dialog, height - 3, 0, ACS_LTEE);
for (i = 0; i < width - 2; i++)
waddch(dialog, ACS_HLINE);
wattrset(dialog, dialog_attr);
waddch(dialog, ACS_RTEE);
print_button(dialog, " Ok ", height - 2, width / 2 - 4, TRUE);
wrefresh(dialog);
while (key != ESC && key != '\n' && key != ' ' &&
key != 'O' && key != 'o' && key != 'X' && key != 'x')
key = wgetch(dialog);
} else {
key = '\n';
wrefresh(dialog);
}
delwin(dialog);
return key == ESC ? -1 : 0;
}

View file

@ -22,59 +22,80 @@
#include "dialog.h" #include "dialog.h"
static void back_lines(int n); static void back_lines(int n);
static void print_page(WINDOW * win, int height, int width); static void print_page(WINDOW *win, int height, int width, update_text_fn
static void print_line(WINDOW * win, int row, int width); update_text, void *data);
static void print_line(WINDOW *win, int row, int width);
static char *get_line(void); static char *get_line(void);
static void print_position(WINDOW * win, int height, int width); static void print_position(WINDOW * win);
static int hscroll;
static int begin_reached, end_reached, page_length;
static char *buf;
static char *page;
/*
* refresh window content
*/
static void refresh_text_box(WINDOW *dialog, WINDOW *box, int boxh, int boxw,
int cur_y, int cur_x, update_text_fn update_text,
void *data)
{
print_page(box, boxh, boxw, update_text, data);
print_position(dialog);
wmove(dialog, cur_y, cur_x); /* Restore cursor position */
wrefresh(dialog);
}
static int hscroll, fd, file_size, bytes_read;
static int begin_reached = 1, end_reached, page_length;
static char *buf, *page;
/* /*
* Display text from a file in a dialog box. * Display text from a file in a dialog box.
*
* keys is a null-terminated array
* update_text() may not add or remove any '\n' or '\0' in tbuf
*/ */
int dialog_textbox(const char *title, const char *file, int height, int width) int dialog_textbox(const char *title, char *tbuf, int initial_height,
int initial_width, int *keys, int *_vscroll, int *_hscroll,
update_text_fn update_text, void *data)
{ {
int i, x, y, cur_x, cur_y, fpos, key = 0; int i, x, y, cur_x, cur_y, key = 0;
int passed_end; int height, width, boxh, boxw;
char search_term[MAX_LEN + 1]; WINDOW *dialog, *box;
WINDOW *dialog, *text; bool done = false;
search_term[0] = '\0'; /* no search term entered yet */ begin_reached = 1;
end_reached = 0;
page_length = 0;
hscroll = 0;
buf = tbuf;
page = buf; /* page is pointer to start of page to be displayed */
/* Open input file for reading */ if (_vscroll && *_vscroll) {
if ((fd = open(file, O_RDONLY)) == -1) { begin_reached = 0;
endwin();
fprintf(stderr, "\nCan't open input file in dialog_textbox().\n"); for (i = 0; i < *_vscroll; i++)
exit(-1); get_line();
} }
/* Get file size. Actually, 'file_size' is the real file size - 1, if (_hscroll)
since it's only the last byte offset from the beginning */ hscroll = *_hscroll;
if ((file_size = lseek(fd, 0, SEEK_END)) == -1) {
endwin(); do_resize:
fprintf(stderr, "\nError getting file size in dialog_textbox().\n"); getmaxyx(stdscr, height, width);
exit(-1); if (height < 8 || width < 8)
} return -ERRDISPLAYTOOSMALL;
/* Restore file pointer to beginning of file after getting file size */ if (initial_height != 0)
if (lseek(fd, 0, SEEK_SET) == -1) { height = initial_height;
endwin(); else
fprintf(stderr, "\nError moving file pointer in dialog_textbox().\n"); if (height > 4)
exit(-1); height -= 4;
} else
/* Allocate space for read buffer */ height = 0;
if ((buf = malloc(BUF_SIZE + 1)) == NULL) { if (initial_width != 0)
endwin(); width = initial_width;
fprintf(stderr, "\nCan't allocate memory in dialog_textbox().\n"); else
exit(-1); if (width > 5)
} width -= 5;
if ((bytes_read = read(fd, buf, BUF_SIZE)) == -1) { else
endwin(); width = 0;
fprintf(stderr, "\nError reading file in dialog_textbox().\n");
exit(-1);
}
buf[bytes_read] = '\0'; /* mark end of valid data */
page = buf; /* page is pointer to start of page to be displayed */
/* center dialog box on screen */ /* center dialog box on screen */
x = (COLS - width) / 2; x = (COLS - width) / 2;
@ -85,182 +106,108 @@ int dialog_textbox(const char *title, const char *file, int height, int width)
dialog = newwin(height, width, y, x); dialog = newwin(height, width, y, x);
keypad(dialog, TRUE); keypad(dialog, TRUE);
/* Create window for text region, used for scrolling text */ /* Create window for box region, used for scrolling text */
text = subwin(dialog, height - 4, width - 2, y + 1, x + 1); boxh = height - 4;
wattrset(text, dialog_attr); boxw = width - 2;
wbkgdset(text, dialog_attr & A_COLOR); box = subwin(dialog, boxh, boxw, y + 1, x + 1);
wattrset(box, dlg.dialog.atr);
wbkgdset(box, dlg.dialog.atr & A_COLOR);
keypad(text, TRUE); keypad(box, TRUE);
/* register the new window, along with its borders */ /* register the new window, along with its borders */
draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr); draw_box(dialog, 0, 0, height, width,
dlg.dialog.atr, dlg.border.atr);
wattrset(dialog, border_attr); wattrset(dialog, dlg.border.atr);
mvwaddch(dialog, height - 3, 0, ACS_LTEE); mvwaddch(dialog, height - 3, 0, ACS_LTEE);
for (i = 0; i < width - 2; i++) for (i = 0; i < width - 2; i++)
waddch(dialog, ACS_HLINE); waddch(dialog, ACS_HLINE);
wattrset(dialog, dialog_attr); wattrset(dialog, dlg.dialog.atr);
wbkgdset(dialog, dialog_attr & A_COLOR); wbkgdset(dialog, dlg.dialog.atr & A_COLOR);
waddch(dialog, ACS_RTEE); waddch(dialog, ACS_RTEE);
print_title(dialog, title, width); print_title(dialog, title, width);
print_button(dialog, " Exit ", height - 2, width / 2 - 4, TRUE); print_button(dialog, gettext(" Exit "), height - 2, width / 2 - 4, TRUE);
wnoutrefresh(dialog); wnoutrefresh(dialog);
getyx(dialog, cur_y, cur_x); /* Save cursor position */ getyx(dialog, cur_y, cur_x); /* Save cursor position */
/* Print first page of text */ /* Print first page of text */
attr_clear(text, height - 4, width - 2, dialog_attr); attr_clear(box, boxh, boxw, dlg.dialog.atr);
print_page(text, height - 4, width - 2); refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x, update_text,
print_position(dialog, height, width); data);
wmove(dialog, cur_y, cur_x); /* Restore cursor position */
wrefresh(dialog);
while ((key != ESC) && (key != '\n')) { while (!done) {
key = wgetch(dialog); key = wgetch(dialog);
switch (key) { switch (key) {
case 'E': /* Exit */ case 'E': /* Exit */
case 'e': case 'e':
case 'X': case 'X':
case 'x': case 'x':
delwin(dialog); case 'q':
free(buf); case '\n':
close(fd); done = true;
return 0; break;
case 'g': /* First page */ case 'g': /* First page */
case KEY_HOME: case KEY_HOME:
if (!begin_reached) { if (!begin_reached) {
begin_reached = 1; begin_reached = 1;
/* First page not in buffer? */
if ((fpos = lseek(fd, 0, SEEK_CUR)) == -1) {
endwin();
fprintf(stderr, "\nError moving file pointer in dialog_textbox().\n");
exit(-1);
}
if (fpos > bytes_read) { /* Yes, we have to read it in */
if (lseek(fd, 0, SEEK_SET) == -1) {
endwin();
fprintf(stderr, "\nError moving file pointer in "
"dialog_textbox().\n");
exit(-1);
}
if ((bytes_read =
read(fd, buf, BUF_SIZE)) == -1) {
endwin();
fprintf(stderr, "\nError reading file in dialog_textbox().\n");
exit(-1);
}
buf[bytes_read] = '\0';
}
page = buf; page = buf;
print_page(text, height - 4, width - 2); refresh_text_box(dialog, box, boxh, boxw,
print_position(dialog, height, width); cur_y, cur_x, update_text,
wmove(dialog, cur_y, cur_x); /* Restore cursor position */ data);
wrefresh(dialog);
} }
break; break;
case 'G': /* Last page */ case 'G': /* Last page */
case KEY_END: case KEY_END:
end_reached = 1; end_reached = 1;
/* Last page not in buffer? */ /* point to last char in buf */
if ((fpos = lseek(fd, 0, SEEK_CUR)) == -1) { page = buf + strlen(buf);
endwin(); back_lines(boxh);
fprintf(stderr, "\nError moving file pointer in dialog_textbox().\n"); refresh_text_box(dialog, box, boxh, boxw, cur_y,
exit(-1); cur_x, update_text, data);
}
if (fpos < file_size) { /* Yes, we have to read it in */
if (lseek(fd, -BUF_SIZE, SEEK_END) == -1) {
endwin();
fprintf(stderr, "\nError moving file pointer in dialog_textbox().\n");
exit(-1);
}
if ((bytes_read =
read(fd, buf, BUF_SIZE)) == -1) {
endwin();
fprintf(stderr, "\nError reading file in dialog_textbox().\n");
exit(-1);
}
buf[bytes_read] = '\0';
}
page = buf + bytes_read;
back_lines(height - 4);
print_page(text, height - 4, width - 2);
print_position(dialog, height, width);
wmove(dialog, cur_y, cur_x); /* Restore cursor position */
wrefresh(dialog);
break; break;
case 'K': /* Previous line */ case 'K': /* Previous line */
case 'k': case 'k':
case KEY_UP: case KEY_UP:
if (!begin_reached) { if (begin_reached)
back_lines(page_length + 1); break;
/* We don't call print_page() here but use scrolling to ensure back_lines(page_length + 1);
faster screen update. However, 'end_reached' and refresh_text_box(dialog, box, boxh, boxw, cur_y,
'page_length' should still be updated, and 'page' should cur_x, update_text, data);
point to start of next page. This is done by calling
get_line() in the following 'for' loop. */
scrollok(text, TRUE);
wscrl(text, -1); /* Scroll text region down one line */
scrollok(text, FALSE);
page_length = 0;
passed_end = 0;
for (i = 0; i < height - 4; i++) {
if (!i) {
/* print first line of page */
print_line(text, 0, width - 2);
wnoutrefresh(text);
} else
/* Called to update 'end_reached' and 'page' */
get_line();
if (!passed_end)
page_length++;
if (end_reached && !passed_end)
passed_end = 1;
}
print_position(dialog, height, width);
wmove(dialog, cur_y, cur_x); /* Restore cursor position */
wrefresh(dialog);
}
break; break;
case 'B': /* Previous page */ case 'B': /* Previous page */
case 'b': case 'b':
case 'u':
case KEY_PPAGE: case KEY_PPAGE:
if (begin_reached) if (begin_reached)
break; break;
back_lines(page_length + height - 4); back_lines(page_length + boxh);
print_page(text, height - 4, width - 2); refresh_text_box(dialog, box, boxh, boxw, cur_y,
print_position(dialog, height, width); cur_x, update_text, data);
wmove(dialog, cur_y, cur_x);
wrefresh(dialog);
break; break;
case 'J': /* Next line */ case 'J': /* Next line */
case 'j': case 'j':
case KEY_DOWN: case KEY_DOWN:
if (!end_reached) { if (end_reached)
begin_reached = 0; break;
scrollok(text, TRUE);
scroll(text); /* Scroll text region up one line */ back_lines(page_length - 1);
scrollok(text, FALSE); refresh_text_box(dialog, box, boxh, boxw, cur_y,
print_line(text, height - 5, width - 2); cur_x, update_text, data);
wnoutrefresh(text);
print_position(dialog, height, width);
wmove(dialog, cur_y, cur_x); /* Restore cursor position */
wrefresh(dialog);
}
break; break;
case KEY_NPAGE: /* Next page */ case KEY_NPAGE: /* Next page */
case ' ': case ' ':
case 'd':
if (end_reached) if (end_reached)
break; break;
begin_reached = 0; begin_reached = 0;
print_page(text, height - 4, width - 2); refresh_text_box(dialog, box, boxh, boxw, cur_y,
print_position(dialog, height, width); cur_x, update_text, data);
wmove(dialog, cur_y, cur_x);
wrefresh(dialog);
break; break;
case '0': /* Beginning of line */ case '0': /* Beginning of line */
case 'H': /* Scroll left */ case 'H': /* Scroll left */
@ -275,9 +222,8 @@ int dialog_textbox(const char *title, const char *file, int height, int width)
hscroll--; hscroll--;
/* Reprint current page to scroll horizontally */ /* Reprint current page to scroll horizontally */
back_lines(page_length); back_lines(page_length);
print_page(text, height - 4, width - 2); refresh_text_box(dialog, box, boxh, boxw, cur_y,
wmove(dialog, cur_y, cur_x); cur_x, update_text, data);
wrefresh(dialog);
break; break;
case 'L': /* Scroll right */ case 'L': /* Scroll right */
case 'l': case 'l':
@ -287,140 +233,97 @@ int dialog_textbox(const char *title, const char *file, int height, int width)
hscroll++; hscroll++;
/* Reprint current page to scroll horizontally */ /* Reprint current page to scroll horizontally */
back_lines(page_length); back_lines(page_length);
print_page(text, height - 4, width - 2); refresh_text_box(dialog, box, boxh, boxw, cur_y,
wmove(dialog, cur_y, cur_x); cur_x, update_text, data);
wrefresh(dialog);
break; break;
case ESC: case KEY_ESC:
if (on_key_esc(dialog) == KEY_ESC)
done = true;
break; break;
case KEY_RESIZE:
back_lines(height);
delwin(box);
delwin(dialog);
on_key_resize();
goto do_resize;
default:
for (i = 0; keys[i]; i++) {
if (key == keys[i]) {
done = true;
break;
}
}
} }
} }
delwin(box);
delwin(dialog); delwin(dialog);
free(buf); if (_vscroll) {
close(fd); const char *s;
return -1; /* ESC pressed */
s = buf;
*_vscroll = 0;
back_lines(page_length);
while (s < page && (s = strchr(s, '\n'))) {
(*_vscroll)++;
s++;
}
}
if (_hscroll)
*_hscroll = hscroll;
return key;
} }
/* /*
* Go back 'n' lines in text file. Called by dialog_textbox(). * Go back 'n' lines in text. Called by dialog_textbox().
* 'page' will be updated to point to the desired line in 'buf'. * 'page' will be updated to point to the desired line in 'buf'.
*/ */
static void back_lines(int n) static void back_lines(int n)
{ {
int i, fpos; int i;
begin_reached = 0; begin_reached = 0;
/* We have to distinguish between end_reached and !end_reached /* Go back 'n' lines */
since at end of file, the line is not ended by a '\n'. for (i = 0; i < n; i++) {
The code inside 'if' basically does a '--page' to move one if (*page == '\0') {
character backward so as to skip '\n' of the previous line */ if (end_reached) {
if (!end_reached) { end_reached = 0;
/* Either beginning of buffer or beginning of file reached? */ continue;
if (page == buf) {
if ((fpos = lseek(fd, 0, SEEK_CUR)) == -1) {
endwin();
fprintf(stderr, "\nError moving file pointer in "
"back_lines().\n");
exit(-1);
} }
if (fpos > bytes_read) { /* Not beginning of file yet */ }
/* We've reached beginning of buffer, but not beginning of if (page == buf) {
file yet, so read previous part of file into buffer. begin_reached = 1;
Note that we only move backward for BUF_SIZE/2 bytes, return;
but not BUF_SIZE bytes to avoid re-reading again in }
print_page() later */ page--;
/* Really possible to move backward BUF_SIZE/2 bytes? */ do {
if (fpos < BUF_SIZE / 2 + bytes_read) { if (page == buf) {
/* No, move less then */
if (lseek(fd, 0, SEEK_SET) == -1) {
endwin();
fprintf(stderr, "\nError moving file pointer in "
"back_lines().\n");
exit(-1);
}
page = buf + fpos - bytes_read;
} else { /* Move backward BUF_SIZE/2 bytes */
if (lseek (fd, -(BUF_SIZE / 2 + bytes_read), SEEK_CUR) == -1) {
endwin();
fprintf(stderr, "\nError moving file pointer "
"in back_lines().\n");
exit(-1);
}
page = buf + BUF_SIZE / 2;
}
if ((bytes_read =
read(fd, buf, BUF_SIZE)) == -1) {
endwin();
fprintf(stderr, "\nError reading file in back_lines().\n");
exit(-1);
}
buf[bytes_read] = '\0';
} else { /* Beginning of file reached */
begin_reached = 1; begin_reached = 1;
return; return;
} }
} page--;
if (*(--page) != '\n') { /* '--page' here */ } while (*page != '\n');
/* Something's wrong... */ page++;
endwin();
fprintf(stderr, "\nInternal error in back_lines().\n");
exit(-1);
}
} }
/* Go back 'n' lines */
for (i = 0; i < n; i++)
do {
if (page == buf) {
if ((fpos = lseek(fd, 0, SEEK_CUR)) == -1) {
endwin();
fprintf(stderr, "\nError moving file pointer in back_lines().\n");
exit(-1);
}
if (fpos > bytes_read) {
/* Really possible to move backward BUF_SIZE/2 bytes? */
if (fpos < BUF_SIZE / 2 + bytes_read) {
/* No, move less then */
if (lseek(fd, 0, SEEK_SET) == -1) {
endwin();
fprintf(stderr, "\nError moving file pointer "
"in back_lines().\n");
exit(-1);
}
page = buf + fpos - bytes_read;
} else { /* Move backward BUF_SIZE/2 bytes */
if (lseek (fd, -(BUF_SIZE / 2 + bytes_read), SEEK_CUR) == -1) {
endwin();
fprintf(stderr, "\nError moving file pointer"
" in back_lines().\n");
exit(-1);
}
page = buf + BUF_SIZE / 2;
}
if ((bytes_read =
read(fd, buf, BUF_SIZE)) == -1) {
endwin();
fprintf(stderr, "\nError reading file in "
"back_lines().\n");
exit(-1);
}
buf[bytes_read] = '\0';
} else { /* Beginning of file reached */
begin_reached = 1;
return;
}
}
} while (*(--page) != '\n');
page++;
} }
/* /*
* Print a new page of text. Called by dialog_textbox(). * Print a new page of text.
*/ */
static void print_page(WINDOW * win, int height, int width) static void print_page(WINDOW *win, int height, int width, update_text_fn
update_text, void *data)
{ {
int i, passed_end = 0; int i, passed_end = 0;
if (update_text) {
char *end;
for (i = 0; i < height; i++)
get_line();
end = page;
back_lines(height);
update_text(buf, page - buf, end - buf, data);
}
page_length = 0; page_length = 0;
for (i = 0; i < height; i++) { for (i = 0; i < height; i++) {
print_line(win, i, width); print_line(win, i, width);
@ -433,11 +336,10 @@ static void print_page(WINDOW * win, int height, int width)
} }
/* /*
* Print a new line of text. Called by dialog_textbox() and print_page(). * Print a new line of text.
*/ */
static void print_line(WINDOW * win, int row, int width) static void print_line(WINDOW * win, int row, int width)
{ {
int y, x;
char *line; char *line;
line = get_line(); line = get_line();
@ -446,10 +348,10 @@ static void print_line(WINDOW * win, int row, int width)
waddch(win, ' '); waddch(win, ' ');
waddnstr(win, line, MIN(strlen(line), width - 2)); waddnstr(win, line, MIN(strlen(line), width - 2));
getyx(win, y, x);
/* Clear 'residue' of previous line */ /* Clear 'residue' of previous line */
#if OLD_NCURSES #if OLD_NCURSES
{ {
int x = getcurx(win);
int i; int i;
for (i = 0; i < width - x; i++) for (i = 0; i < width - x; i++)
waddch(win, ' '); waddch(win, ' ');
@ -466,35 +368,14 @@ static void print_line(WINDOW * win, int row, int width)
*/ */
static char *get_line(void) static char *get_line(void)
{ {
int i = 0, fpos; int i = 0;
static char line[MAX_LEN + 1]; static char line[MAX_LEN + 1];
end_reached = 0; end_reached = 0;
while (*page != '\n') { while (*page != '\n') {
if (*page == '\0') { if (*page == '\0') {
/* Either end of file or end of buffer reached */ end_reached = 1;
if ((fpos = lseek(fd, 0, SEEK_CUR)) == -1) { break;
endwin();
fprintf(stderr, "\nError moving file pointer in "
"get_line().\n");
exit(-1);
}
if (fpos < file_size) { /* Not end of file yet */
/* We've reached end of buffer, but not end of file yet,
so read next part of file into buffer */
if ((bytes_read =
read(fd, buf, BUF_SIZE)) == -1) {
endwin();
fprintf(stderr, "\nError reading file in get_line().\n");
exit(-1);
}
buf[bytes_read] = '\0';
page = buf;
} else {
if (!end_reached)
end_reached = 1;
break;
}
} else if (i < MAX_LEN) } else if (i < MAX_LEN)
line[i++] = *(page++); line[i++] = *(page++);
else { else {
@ -507,7 +388,7 @@ static char *get_line(void)
if (i <= MAX_LEN) if (i <= MAX_LEN)
line[i] = '\0'; line[i] = '\0';
if (!end_reached) if (!end_reached)
page++; /* move pass '\n' */ page++; /* move past '\n' */
return line; return line;
} }
@ -515,19 +396,13 @@ static char *get_line(void)
/* /*
* Print current position * Print current position
*/ */
static void print_position(WINDOW * win, int height, int width) static void print_position(WINDOW * win)
{ {
int fpos, percent; int percent;
if ((fpos = lseek(fd, 0, SEEK_CUR)) == -1) { wattrset(win, dlg.position_indicator.atr);
endwin(); wbkgdset(win, dlg.position_indicator.atr & A_COLOR);
fprintf(stderr, "\nError moving file pointer in print_position().\n"); percent = (page - buf) * 100 / strlen(buf);
exit(-1); wmove(win, getmaxy(win) - 3, getmaxx(win) - 9);
}
wattrset(win, position_indicator_attr);
wbkgdset(win, position_indicator_attr & A_COLOR);
percent = !file_size ?
100 : ((fpos - bytes_read + page - buf) * 100) / file_size;
wmove(win, height - 3, width - 9);
wprintw(win, "(%3d%%)", percent); wprintw(win, "(%3d%%)", percent);
} }

View file

@ -19,87 +19,222 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
#include <stdarg.h>
#include "dialog.h" #include "dialog.h"
/* use colors by default? */ /* Needed in signal handler in mconf.c */
bool use_colors = 1; int saved_x, saved_y;
const char *backtitle = NULL; struct dialog_info dlg;
static void set_mono_theme(void)
{
dlg.screen.atr = A_NORMAL;
dlg.shadow.atr = A_NORMAL;
dlg.dialog.atr = A_NORMAL;
dlg.title.atr = A_BOLD;
dlg.border.atr = A_NORMAL;
dlg.button_active.atr = A_REVERSE;
dlg.button_inactive.atr = A_DIM;
dlg.button_key_active.atr = A_REVERSE;
dlg.button_key_inactive.atr = A_BOLD;
dlg.button_label_active.atr = A_REVERSE;
dlg.button_label_inactive.atr = A_NORMAL;
dlg.inputbox.atr = A_NORMAL;
dlg.inputbox_border.atr = A_NORMAL;
dlg.searchbox.atr = A_NORMAL;
dlg.searchbox_title.atr = A_BOLD;
dlg.searchbox_border.atr = A_NORMAL;
dlg.position_indicator.atr = A_BOLD;
dlg.menubox.atr = A_NORMAL;
dlg.menubox_border.atr = A_NORMAL;
dlg.item.atr = A_NORMAL;
dlg.item_selected.atr = A_REVERSE;
dlg.tag.atr = A_BOLD;
dlg.tag_selected.atr = A_REVERSE;
dlg.tag_key.atr = A_BOLD;
dlg.tag_key_selected.atr = A_REVERSE;
dlg.check.atr = A_BOLD;
dlg.check_selected.atr = A_REVERSE;
dlg.uarrow.atr = A_BOLD;
dlg.darrow.atr = A_BOLD;
}
#define DLG_COLOR(dialog, f, b, h) \
do { \
dlg.dialog.fg = (f); \
dlg.dialog.bg = (b); \
dlg.dialog.hl = (h); \
} while (0)
static void set_classic_theme(void)
{
DLG_COLOR(screen, COLOR_CYAN, COLOR_BLUE, true);
DLG_COLOR(shadow, COLOR_BLACK, COLOR_BLACK, true);
DLG_COLOR(dialog, COLOR_BLACK, COLOR_WHITE, false);
DLG_COLOR(title, COLOR_YELLOW, COLOR_WHITE, true);
DLG_COLOR(border, COLOR_WHITE, COLOR_WHITE, true);
DLG_COLOR(button_active, COLOR_WHITE, COLOR_BLUE, true);
DLG_COLOR(button_inactive, COLOR_BLACK, COLOR_WHITE, false);
DLG_COLOR(button_key_active, COLOR_WHITE, COLOR_BLUE, true);
DLG_COLOR(button_key_inactive, COLOR_RED, COLOR_WHITE, false);
DLG_COLOR(button_label_active, COLOR_YELLOW, COLOR_BLUE, true);
DLG_COLOR(button_label_inactive, COLOR_BLACK, COLOR_WHITE, true);
DLG_COLOR(inputbox, COLOR_BLACK, COLOR_WHITE, false);
DLG_COLOR(inputbox_border, COLOR_BLACK, COLOR_WHITE, false);
DLG_COLOR(searchbox, COLOR_BLACK, COLOR_WHITE, false);
DLG_COLOR(searchbox_title, COLOR_YELLOW, COLOR_WHITE, true);
DLG_COLOR(searchbox_border, COLOR_WHITE, COLOR_WHITE, true);
DLG_COLOR(position_indicator, COLOR_YELLOW, COLOR_WHITE, true);
DLG_COLOR(menubox, COLOR_BLACK, COLOR_WHITE, false);
DLG_COLOR(menubox_border, COLOR_WHITE, COLOR_WHITE, true);
DLG_COLOR(item, COLOR_BLACK, COLOR_WHITE, false);
DLG_COLOR(item_selected, COLOR_WHITE, COLOR_BLUE, true);
DLG_COLOR(tag, COLOR_YELLOW, COLOR_WHITE, true);
DLG_COLOR(tag_selected, COLOR_YELLOW, COLOR_BLUE, true);
DLG_COLOR(tag_key, COLOR_YELLOW, COLOR_WHITE, true);
DLG_COLOR(tag_key_selected, COLOR_YELLOW, COLOR_BLUE, true);
DLG_COLOR(check, COLOR_BLACK, COLOR_WHITE, false);
DLG_COLOR(check_selected, COLOR_WHITE, COLOR_BLUE, true);
DLG_COLOR(uarrow, COLOR_GREEN, COLOR_WHITE, true);
DLG_COLOR(darrow, COLOR_GREEN, COLOR_WHITE, true);
}
static void set_blackbg_theme(void)
{
DLG_COLOR(screen, COLOR_RED, COLOR_BLACK, true);
DLG_COLOR(shadow, COLOR_BLACK, COLOR_BLACK, false);
DLG_COLOR(dialog, COLOR_WHITE, COLOR_BLACK, false);
DLG_COLOR(title, COLOR_RED, COLOR_BLACK, false);
DLG_COLOR(border, COLOR_BLACK, COLOR_BLACK, true);
DLG_COLOR(button_active, COLOR_YELLOW, COLOR_RED, false);
DLG_COLOR(button_inactive, COLOR_YELLOW, COLOR_BLACK, false);
DLG_COLOR(button_key_active, COLOR_YELLOW, COLOR_RED, true);
DLG_COLOR(button_key_inactive, COLOR_RED, COLOR_BLACK, false);
DLG_COLOR(button_label_active, COLOR_WHITE, COLOR_RED, false);
DLG_COLOR(button_label_inactive, COLOR_BLACK, COLOR_BLACK, true);
DLG_COLOR(inputbox, COLOR_YELLOW, COLOR_BLACK, false);
DLG_COLOR(inputbox_border, COLOR_YELLOW, COLOR_BLACK, false);
DLG_COLOR(searchbox, COLOR_YELLOW, COLOR_BLACK, false);
DLG_COLOR(searchbox_title, COLOR_YELLOW, COLOR_BLACK, true);
DLG_COLOR(searchbox_border, COLOR_BLACK, COLOR_BLACK, true);
DLG_COLOR(position_indicator, COLOR_RED, COLOR_BLACK, false);
DLG_COLOR(menubox, COLOR_YELLOW, COLOR_BLACK, false);
DLG_COLOR(menubox_border, COLOR_BLACK, COLOR_BLACK, true);
DLG_COLOR(item, COLOR_WHITE, COLOR_BLACK, false);
DLG_COLOR(item_selected, COLOR_WHITE, COLOR_RED, false);
DLG_COLOR(tag, COLOR_RED, COLOR_BLACK, false);
DLG_COLOR(tag_selected, COLOR_YELLOW, COLOR_RED, true);
DLG_COLOR(tag_key, COLOR_RED, COLOR_BLACK, false);
DLG_COLOR(tag_key_selected, COLOR_YELLOW, COLOR_RED, true);
DLG_COLOR(check, COLOR_YELLOW, COLOR_BLACK, false);
DLG_COLOR(check_selected, COLOR_YELLOW, COLOR_RED, true);
DLG_COLOR(uarrow, COLOR_RED, COLOR_BLACK, false);
DLG_COLOR(darrow, COLOR_RED, COLOR_BLACK, false);
}
static void set_bluetitle_theme(void)
{
set_classic_theme();
DLG_COLOR(title, COLOR_BLUE, COLOR_WHITE, true);
DLG_COLOR(button_key_active, COLOR_YELLOW, COLOR_BLUE, true);
DLG_COLOR(button_label_active, COLOR_WHITE, COLOR_BLUE, true);
DLG_COLOR(searchbox_title, COLOR_BLUE, COLOR_WHITE, true);
DLG_COLOR(position_indicator, COLOR_BLUE, COLOR_WHITE, true);
DLG_COLOR(tag, COLOR_BLUE, COLOR_WHITE, true);
DLG_COLOR(tag_key, COLOR_BLUE, COLOR_WHITE, true);
}
/* /*
* Attribute values, default is for mono display * Select color theme
*/ */
chtype attributes[] = { static int set_theme(const char *theme)
A_NORMAL, /* screen_attr */ {
A_NORMAL, /* shadow_attr */ int use_color = 1;
A_NORMAL, /* dialog_attr */ if (!theme)
A_BOLD, /* title_attr */ set_bluetitle_theme();
A_NORMAL, /* border_attr */ else if (strcmp(theme, "classic") == 0)
A_REVERSE, /* button_active_attr */ set_classic_theme();
A_DIM, /* button_inactive_attr */ else if (strcmp(theme, "bluetitle") == 0)
A_REVERSE, /* button_key_active_attr */ set_bluetitle_theme();
A_BOLD, /* button_key_inactive_attr */ else if (strcmp(theme, "blackbg") == 0)
A_REVERSE, /* button_label_active_attr */ set_blackbg_theme();
A_NORMAL, /* button_label_inactive_attr */ else if (strcmp(theme, "mono") == 0)
A_NORMAL, /* inputbox_attr */ use_color = 0;
A_NORMAL, /* inputbox_border_attr */
A_NORMAL, /* searchbox_attr */
A_BOLD, /* searchbox_title_attr */
A_NORMAL, /* searchbox_border_attr */
A_BOLD, /* position_indicator_attr */
A_NORMAL, /* menubox_attr */
A_NORMAL, /* menubox_border_attr */
A_NORMAL, /* item_attr */
A_REVERSE, /* item_selected_attr */
A_BOLD, /* tag_attr */
A_REVERSE, /* tag_selected_attr */
A_BOLD, /* tag_key_attr */
A_REVERSE, /* tag_key_selected_attr */
A_BOLD, /* check_attr */
A_REVERSE, /* check_selected_attr */
A_BOLD, /* uarrow_attr */
A_BOLD /* darrow_attr */
};
#include "colors.h" return use_color;
}
static void init_one_color(struct dialog_color *color)
{
static int pair = 0;
pair++;
init_pair(pair, color->fg, color->bg);
if (color->hl)
color->atr = A_BOLD | COLOR_PAIR(pair);
else
color->atr = COLOR_PAIR(pair);
}
static void init_dialog_colors(void)
{
init_one_color(&dlg.screen);
init_one_color(&dlg.shadow);
init_one_color(&dlg.dialog);
init_one_color(&dlg.title);
init_one_color(&dlg.border);
init_one_color(&dlg.button_active);
init_one_color(&dlg.button_inactive);
init_one_color(&dlg.button_key_active);
init_one_color(&dlg.button_key_inactive);
init_one_color(&dlg.button_label_active);
init_one_color(&dlg.button_label_inactive);
init_one_color(&dlg.inputbox);
init_one_color(&dlg.inputbox_border);
init_one_color(&dlg.searchbox);
init_one_color(&dlg.searchbox_title);
init_one_color(&dlg.searchbox_border);
init_one_color(&dlg.position_indicator);
init_one_color(&dlg.menubox);
init_one_color(&dlg.menubox_border);
init_one_color(&dlg.item);
init_one_color(&dlg.item_selected);
init_one_color(&dlg.tag);
init_one_color(&dlg.tag_selected);
init_one_color(&dlg.tag_key);
init_one_color(&dlg.tag_key_selected);
init_one_color(&dlg.check);
init_one_color(&dlg.check_selected);
init_one_color(&dlg.uarrow);
init_one_color(&dlg.darrow);
}
/* /*
* Table of color values * Setup for color display
*/ */
int color_table[][3] = { static void color_setup(const char *theme)
{SCREEN_FG, SCREEN_BG, SCREEN_HL}, {
{SHADOW_FG, SHADOW_BG, SHADOW_HL}, int use_color;
{DIALOG_FG, DIALOG_BG, DIALOG_HL},
{TITLE_FG, TITLE_BG, TITLE_HL}, use_color = set_theme(theme);
{BORDER_FG, BORDER_BG, BORDER_HL}, if (use_color && has_colors()) {
{BUTTON_ACTIVE_FG, BUTTON_ACTIVE_BG, BUTTON_ACTIVE_HL}, start_color();
{BUTTON_INACTIVE_FG, BUTTON_INACTIVE_BG, BUTTON_INACTIVE_HL}, init_dialog_colors();
{BUTTON_KEY_ACTIVE_FG, BUTTON_KEY_ACTIVE_BG, BUTTON_KEY_ACTIVE_HL}, } else
{BUTTON_KEY_INACTIVE_FG, BUTTON_KEY_INACTIVE_BG, set_mono_theme();
BUTTON_KEY_INACTIVE_HL}, }
{BUTTON_LABEL_ACTIVE_FG, BUTTON_LABEL_ACTIVE_BG,
BUTTON_LABEL_ACTIVE_HL},
{BUTTON_LABEL_INACTIVE_FG, BUTTON_LABEL_INACTIVE_BG,
BUTTON_LABEL_INACTIVE_HL},
{INPUTBOX_FG, INPUTBOX_BG, INPUTBOX_HL},
{INPUTBOX_BORDER_FG, INPUTBOX_BORDER_BG, INPUTBOX_BORDER_HL},
{SEARCHBOX_FG, SEARCHBOX_BG, SEARCHBOX_HL},
{SEARCHBOX_TITLE_FG, SEARCHBOX_TITLE_BG, SEARCHBOX_TITLE_HL},
{SEARCHBOX_BORDER_FG, SEARCHBOX_BORDER_BG, SEARCHBOX_BORDER_HL},
{POSITION_INDICATOR_FG, POSITION_INDICATOR_BG, POSITION_INDICATOR_HL},
{MENUBOX_FG, MENUBOX_BG, MENUBOX_HL},
{MENUBOX_BORDER_FG, MENUBOX_BORDER_BG, MENUBOX_BORDER_HL},
{ITEM_FG, ITEM_BG, ITEM_HL},
{ITEM_SELECTED_FG, ITEM_SELECTED_BG, ITEM_SELECTED_HL},
{TAG_FG, TAG_BG, TAG_HL},
{TAG_SELECTED_FG, TAG_SELECTED_BG, TAG_SELECTED_HL},
{TAG_KEY_FG, TAG_KEY_BG, TAG_KEY_HL},
{TAG_KEY_SELECTED_FG, TAG_KEY_SELECTED_BG, TAG_KEY_SELECTED_HL},
{CHECK_FG, CHECK_BG, CHECK_HL},
{CHECK_SELECTED_FG, CHECK_SELECTED_BG, CHECK_SELECTED_HL},
{UARROW_FG, UARROW_BG, UARROW_HL},
{DARROW_FG, DARROW_BG, DARROW_HL},
}; /* color_table */
/* /*
* Set window to attribute 'attr' * Set window to attribute 'attr'
@ -119,13 +254,13 @@ void attr_clear(WINDOW * win, int height, int width, chtype attr)
void dialog_clear(void) void dialog_clear(void)
{ {
attr_clear(stdscr, LINES, COLS, screen_attr); attr_clear(stdscr, LINES, COLS, dlg.screen.atr);
/* Display background title if it exists ... - SLH */ /* Display background title if it exists ... - SLH */
if (backtitle != NULL) { if (dlg.backtitle != NULL) {
int i; int i;
wattrset(stdscr, screen_attr); wattrset(stdscr, dlg.screen.atr);
mvwaddstr(stdscr, 0, 1, (char *)backtitle); mvwaddstr(stdscr, 0, 1, (char *)dlg.backtitle);
wmove(stdscr, 1, 1); wmove(stdscr, 1, 1);
for (i = 1; i < COLS - 1; i++) for (i = 1; i < COLS - 1; i++)
waddch(stdscr, ACS_HLINE); waddch(stdscr, ACS_HLINE);
@ -136,44 +271,45 @@ void dialog_clear(void)
/* /*
* Do some initialization for dialog * Do some initialization for dialog
*/ */
void init_dialog(void) int init_dialog(const char *backtitle)
{ {
int height, width;
initscr(); /* Init curses */ initscr(); /* Init curses */
/* Get current cursor position for signal handler in mconf.c */
getyx(stdscr, saved_y, saved_x);
getmaxyx(stdscr, height, width);
if (height < 19 || width < 80) {
endwin();
return -ERRDISPLAYTOOSMALL;
}
dlg.backtitle = backtitle;
color_setup(getenv("MENUCONFIG_COLOR"));
keypad(stdscr, TRUE); keypad(stdscr, TRUE);
cbreak(); cbreak();
noecho(); noecho();
if (use_colors) /* Set up colors */
color_setup();
dialog_clear(); dialog_clear();
return 0;
} }
/* void set_dialog_backtitle(const char *backtitle)
* Setup for color display
*/
void color_setup(void)
{ {
int i; dlg.backtitle = backtitle;
if (has_colors()) { /* Terminal supports color? */
start_color();
/* Initialize color pairs */
for (i = 0; i < ATTRIBUTE_COUNT; i++)
init_pair(i + 1, color_table[i][0], color_table[i][1]);
/* Setup color attributes */
for (i = 0; i < ATTRIBUTE_COUNT; i++)
attributes[i] = C_ATTR(color_table[i][2], i + 1);
}
} }
/* /*
* End using dialog functions. * End using dialog functions.
*/ */
void end_dialog(void) void end_dialog(int x, int y)
{ {
/* move cursor back to original position */
move(y, x);
refresh();
endwin(); endwin();
} }
@ -184,7 +320,7 @@ void print_title(WINDOW *dialog, const char *title, int width)
{ {
if (title) { if (title) {
int tlen = MIN(width - 2, strlen(title)); int tlen = MIN(width - 2, strlen(title));
wattrset(dialog, title_attr); wattrset(dialog, dlg.title.atr);
mvwaddch(dialog, 0, (width - tlen) / 2 - 1, ' '); mvwaddch(dialog, 0, (width - tlen) / 2 - 1, ' ');
mvwaddnstr(dialog, 0, (width - tlen)/2, title, tlen); mvwaddnstr(dialog, 0, (width - tlen)/2, title, tlen);
waddch(dialog, ' '); waddch(dialog, ' ');
@ -224,7 +360,7 @@ 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 = index(word, ' '); sp = strchr(word, ' ');
if (sp) if (sp)
*sp++ = 0; *sp++ = 0;
@ -236,7 +372,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 = index(sp, ' ')) && (!(sp2 = strchr(sp, ' '))
|| wlen + 1 + (sp2 - sp) > room))) { || wlen + 1 + (sp2 - sp) > room))) {
cur_y++; cur_y++;
cur_x = x; cur_x = x;
@ -264,21 +400,23 @@ void print_button(WINDOW * win, const char *label, int y, int x, int selected)
int i, temp; int i, temp;
wmove(win, y, x); wmove(win, y, x);
wattrset(win, selected ? button_active_attr : button_inactive_attr); wattrset(win, selected ? dlg.button_active.atr
: dlg.button_inactive.atr);
waddstr(win, "<"); waddstr(win, "<");
temp = strspn(label, " "); temp = strspn(label, " ");
label += temp; label += temp;
wattrset(win, selected ? button_label_active_attr wattrset(win, selected ? dlg.button_label_active.atr
: button_label_inactive_attr); : dlg.button_label_inactive.atr);
for (i = 0; i < temp; i++) for (i = 0; i < temp; i++)
waddch(win, ' '); waddch(win, ' ');
wattrset(win, selected ? button_key_active_attr wattrset(win, selected ? dlg.button_key_active.atr
: button_key_inactive_attr); : dlg.button_key_inactive.atr);
waddch(win, label[0]); waddch(win, label[0]);
wattrset(win, selected ? button_label_active_attr wattrset(win, selected ? dlg.button_label_active.atr
: button_label_inactive_attr); : dlg.button_label_inactive.atr);
waddstr(win, (char *)label + 1); waddstr(win, (char *)label + 1);
wattrset(win, selected ? button_active_attr : button_inactive_attr); wattrset(win, selected ? dlg.button_active.atr
: dlg.button_inactive.atr);
waddstr(win, ">"); waddstr(win, ">");
wmove(win, y, x + temp + 1); wmove(win, y, x + temp + 1);
} }
@ -326,7 +464,7 @@ void draw_shadow(WINDOW * win, int y, int x, int height, int width)
int i; int i;
if (has_colors()) { /* Whether terminal supports color? */ if (has_colors()) { /* Whether terminal supports color? */
wattrset(win, shadow_attr); wattrset(win, dlg.shadow.atr);
wmove(win, y + height, x + 2); wmove(win, y + height, x + 2);
for (i = 0; i < width; i++) for (i = 0; i < width; i++)
waddch(win, winch(win) & A_CHARTEXT); waddch(win, winch(win) & A_CHARTEXT);
@ -360,3 +498,167 @@ int first_alpha(const char *string, const char *exempt)
return 0; return 0;
} }
/*
* ncurses uses ESC to detect escaped char sequences. This resutl in
* a small timeout before ESC is actually delivered to the application.
* lxdialog suggest <ESC> <ESC> which is correctly translated to two
* times esc. But then we need to ignore the second esc to avoid stepping
* out one menu too much. Filter away all escaped key sequences since
* keypad(FALSE) turn off ncurses support for escape sequences - and thats
* needed to make notimeout() do as expected.
*/
int on_key_esc(WINDOW *win)
{
int key;
int key2;
int key3;
nodelay(win, TRUE);
keypad(win, FALSE);
key = wgetch(win);
key2 = wgetch(win);
do {
key3 = wgetch(win);
} while (key3 != ERR);
nodelay(win, FALSE);
keypad(win, TRUE);
if (key == KEY_ESC && key2 == ERR)
return KEY_ESC;
else if (key != ERR && key != KEY_ESC && key2 == ERR)
ungetch(key);
return -1;
}
/* redraw screen in new size */
int on_key_resize(void)
{
dialog_clear();
return KEY_RESIZE;
}
struct dialog_list *item_cur;
struct dialog_list item_nil;
struct dialog_list *item_head;
void item_reset(void)
{
struct dialog_list *p, *next;
for (p = item_head; p; p = next) {
next = p->next;
free(p);
}
item_head = NULL;
item_cur = &item_nil;
}
void item_make(const char *fmt, ...)
{
va_list ap;
struct dialog_list *p = malloc(sizeof(*p));
if (item_head)
item_cur->next = p;
else
item_head = p;
item_cur = p;
memset(p, 0, sizeof(*p));
va_start(ap, fmt);
vsnprintf(item_cur->node.str, sizeof(item_cur->node.str), fmt, ap);
va_end(ap);
}
void item_add_str(const char *fmt, ...)
{
va_list ap;
size_t avail;
avail = sizeof(item_cur->node.str) - strlen(item_cur->node.str);
va_start(ap, fmt);
vsnprintf(item_cur->node.str + strlen(item_cur->node.str),
avail, fmt, ap);
item_cur->node.str[sizeof(item_cur->node.str) - 1] = '\0';
va_end(ap);
}
void item_set_tag(char tag)
{
item_cur->node.tag = tag;
}
void item_set_data(void *ptr)
{
item_cur->node.data = ptr;
}
void item_set_selected(int val)
{
item_cur->node.selected = val;
}
int item_activate_selected(void)
{
item_foreach()
if (item_is_selected())
return 1;
return 0;
}
void *item_data(void)
{
return item_cur->node.data;
}
char item_tag(void)
{
return item_cur->node.tag;
}
int item_count(void)
{
int n = 0;
struct dialog_list *p;
for (p = item_head; p; p = p->next)
n++;
return n;
}
void item_set(int n)
{
int i = 0;
item_foreach()
if (i++ == n)
return;
}
int item_n(void)
{
int n = 0;
struct dialog_list *p;
for (p = item_head; p; p = p->next) {
if (p == item_cur)
return n;
n++;
}
return 0;
}
const char *item_str(void)
{
return item_cur->node.str;
}
int item_is_selected(void)
{
return (item_cur->node.selected != 0);
}
int item_is_tag(char tag)
{
return (item_cur->node.tag == tag);
}

View file

@ -29,8 +29,8 @@ static void print_buttons(WINDOW * dialog, int height, int width, int selected)
int x = width / 2 - 10; int x = width / 2 - 10;
int y = height - 2; int y = height - 2;
print_button(dialog, " Yes ", y, x, selected == 0); print_button(dialog, gettext(" Yes "), y, x, selected == 0);
print_button(dialog, " No ", y, x + 13, selected == 1); print_button(dialog, gettext(" No "), y, x + 13, selected == 1);
wmove(dialog, y, x + 1 + 13 * selected); wmove(dialog, y, x + 1 + 13 * selected);
wrefresh(dialog); wrefresh(dialog);
@ -44,6 +44,12 @@ int dialog_yesno(const char *title, const char *prompt, int height, int width)
int i, x, y, key = 0, button = 0; int i, x, y, key = 0, button = 0;
WINDOW *dialog; WINDOW *dialog;
do_resize:
if (getmaxy(stdscr) < (height + 4))
return -ERRDISPLAYTOOSMALL;
if (getmaxx(stdscr) < (width + 4))
return -ERRDISPLAYTOOSMALL;
/* center dialog box on screen */ /* center dialog box on screen */
x = (COLS - width) / 2; x = (COLS - width) / 2;
y = (LINES - height) / 2; y = (LINES - height) / 2;
@ -53,22 +59,23 @@ int dialog_yesno(const char *title, const char *prompt, int height, int width)
dialog = newwin(height, width, y, x); dialog = newwin(height, width, y, x);
keypad(dialog, TRUE); keypad(dialog, TRUE);
draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr); draw_box(dialog, 0, 0, height, width,
wattrset(dialog, border_attr); dlg.dialog.atr, dlg.border.atr);
wattrset(dialog, dlg.border.atr);
mvwaddch(dialog, height - 3, 0, ACS_LTEE); mvwaddch(dialog, height - 3, 0, ACS_LTEE);
for (i = 0; i < width - 2; i++) for (i = 0; i < width - 2; i++)
waddch(dialog, ACS_HLINE); waddch(dialog, ACS_HLINE);
wattrset(dialog, dialog_attr); wattrset(dialog, dlg.dialog.atr);
waddch(dialog, ACS_RTEE); waddch(dialog, ACS_RTEE);
print_title(dialog, title, width); print_title(dialog, title, width);
wattrset(dialog, dialog_attr); wattrset(dialog, dlg.dialog.atr);
print_autowrap(dialog, prompt, width - 2, 1, 3); print_autowrap(dialog, prompt, width - 2, 1, 3);
print_buttons(dialog, height, width, 0); print_buttons(dialog, height, width, 0);
while (key != ESC) { while (key != KEY_ESC) {
key = wgetch(dialog); key = wgetch(dialog);
switch (key) { switch (key) {
case 'Y': case 'Y':
@ -92,11 +99,16 @@ int dialog_yesno(const char *title, const char *prompt, int height, int width)
case '\n': case '\n':
delwin(dialog); delwin(dialog);
return button; return button;
case ESC: case KEY_ESC:
key = on_key_esc(dialog);
break; break;
case KEY_RESIZE:
delwin(dialog);
on_key_resize();
goto do_resize;
} }
} }
delwin(dialog); delwin(dialog);
return -1; /* ESC pressed */ return key; /* ESC pressed */
} }

File diff suppressed because it is too large Load diff

View file

@ -3,19 +3,22 @@
* Released under the terms of the GNU GPL v2.0. * Released under the terms of the GNU GPL v2.0.
*/ */
#include <ctype.h>
#include <stdarg.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#define LKC_DIRECT_LINK
#include "lkc.h" #include "lkc.h"
static const char nohelp_text[] = "There is no help available for this option.";
struct menu rootmenu; struct menu rootmenu;
static struct menu **last_entry_ptr; static struct menu **last_entry_ptr;
struct file *file_list; struct file *file_list;
struct file *current_file; struct file *current_file;
static void menu_warn(struct menu *menu, const char *fmt, ...) void menu_warn(struct menu *menu, const char *fmt, ...)
{ {
va_list ap; va_list ap;
va_start(ap, fmt); va_start(ap, fmt);
@ -35,7 +38,7 @@ static void prop_warn(struct property *prop, const char *fmt, ...)
va_end(ap); va_end(ap);
} }
void menu_init(void) void _menu_init(void)
{ {
current_entry = current_menu = &rootmenu; current_entry = current_menu = &rootmenu;
last_entry_ptr = &rootmenu.list; last_entry_ptr = &rootmenu.list;
@ -45,7 +48,7 @@ void menu_add_entry(struct symbol *sym)
{ {
struct menu *menu; struct menu *menu;
menu = malloc(sizeof(*menu)); menu = xmalloc(sizeof(*menu));
memset(menu, 0, sizeof(*menu)); memset(menu, 0, sizeof(*menu));
menu->sym = sym; menu->sym = sym;
menu->parent = current_menu; menu->parent = current_menu;
@ -55,6 +58,8 @@ void menu_add_entry(struct symbol *sym)
*last_entry_ptr = menu; *last_entry_ptr = menu;
last_entry_ptr = &menu->next; last_entry_ptr = &menu->next;
current_entry = menu; current_entry = menu;
if (sym)
menu_add_symbol(P_SYMBOL, sym, NULL);
} }
void menu_end_entry(void) void menu_end_entry(void)
@ -74,9 +79,34 @@ void menu_end_menu(void)
current_menu = current_menu->parent; current_menu = current_menu->parent;
} }
static struct expr *menu_check_dep(struct expr *e)
{
if (!e)
return e;
switch (e->type) {
case E_NOT:
e->left.expr = menu_check_dep(e->left.expr);
break;
case E_OR:
case E_AND:
e->left.expr = menu_check_dep(e->left.expr);
e->right.expr = menu_check_dep(e->right.expr);
break;
case E_SYMBOL:
/* change 'm' into 'm' && MODULES */
if (e->left.sym == &symbol_mod)
return expr_alloc_and(e, expr_alloc_symbol(modules_sym));
break;
default:
break;
}
return e;
}
void menu_add_dep(struct expr *dep) void menu_add_dep(struct expr *dep)
{ {
current_entry->dep = expr_alloc_and(current_entry->dep, dep); current_entry->dep = expr_alloc_and(current_entry->dep, menu_check_dep(dep));
} }
void menu_set_type(int type) void menu_set_type(int type)
@ -89,7 +119,7 @@ void menu_set_type(int type)
sym->type = type; sym->type = type;
return; return;
} }
menu_warn(current_entry, "type of '%s' redefined from '%s' to '%s'\n", menu_warn(current_entry, "type of '%s' redefined from '%s' to '%s'",
sym->name ? sym->name : "<choice>", sym->name ? sym->name : "<choice>",
sym_type_name(sym->type), sym_type_name(type)); sym_type_name(sym->type), sym_type_name(type));
} }
@ -99,15 +129,34 @@ struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *e
struct property *prop = prop_alloc(type, current_entry->sym); struct property *prop = prop_alloc(type, current_entry->sym);
prop->menu = current_entry; prop->menu = current_entry;
prop->text = prompt;
prop->expr = expr; prop->expr = expr;
prop->visible.expr = dep; prop->visible.expr = menu_check_dep(dep);
if (prompt) { if (prompt) {
if (current_entry->prompt) if (isspace(*prompt)) {
menu_warn(current_entry, "prompt redefined\n"); prop_warn(prop, "leading whitespace ignored");
while (isspace(*prompt))
prompt++;
}
if (current_entry->prompt && current_entry != &rootmenu)
prop_warn(prop, "prompt redefined");
/* Apply all upper menus' visibilities to actual prompts. */
if(type == P_PROMPT) {
struct menu *menu = current_entry;
while ((menu = menu->parent) != NULL) {
if (!menu->visibility)
continue;
prop->visible.expr
= expr_alloc_and(prop->visible.expr,
menu->visibility);
}
}
current_entry->prompt = prop; current_entry->prompt = prop;
} }
prop->text = prompt;
return prop; return prop;
} }
@ -117,6 +166,12 @@ struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr
return menu_add_prop(type, prompt, NULL, dep); return menu_add_prop(type, prompt, NULL, dep);
} }
void menu_add_visibility(struct expr *expr)
{
current_entry->visibility = expr_alloc_and(current_entry->visibility,
expr);
}
void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep) void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep)
{ {
menu_add_prop(type, NULL, expr, dep); menu_add_prop(type, NULL, expr, dep);
@ -127,13 +182,34 @@ void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep)
menu_add_prop(type, NULL, expr_alloc_symbol(sym), dep); menu_add_prop(type, NULL, expr_alloc_symbol(sym), dep);
} }
static int menu_range_valid_sym(struct symbol *sym, struct symbol *sym2) void menu_add_option(int token, char *arg)
{
struct property *prop;
switch (token) {
case T_OPT_MODULES:
prop = prop_alloc(P_DEFAULT, modules_sym);
prop->expr = expr_alloc_symbol(current_entry->sym);
break;
case T_OPT_DEFCONFIG_LIST:
if (!sym_defconfig_list)
sym_defconfig_list = current_entry->sym;
else if (sym_defconfig_list != current_entry->sym)
zconf_error("trying to redefine defconfig symbol");
break;
case T_OPT_ENV:
prop_add_env(arg);
break;
}
}
static int menu_validate_number(struct symbol *sym, struct symbol *sym2)
{ {
return sym2->type == S_INT || sym2->type == S_HEX || return sym2->type == S_INT || sym2->type == S_HEX ||
(sym2->type == S_UNKNOWN && sym_string_valid(sym, sym2->name)); (sym2->type == S_UNKNOWN && sym_string_valid(sym, sym2->name));
} }
void sym_check_prop(struct symbol *sym) static void sym_check_prop(struct symbol *sym)
{ {
struct property *prop; struct property *prop;
struct symbol *sym2; struct symbol *sym2;
@ -143,8 +219,17 @@ void sym_check_prop(struct symbol *sym)
if ((sym->type == S_STRING || sym->type == S_INT || sym->type == S_HEX) && if ((sym->type == S_STRING || sym->type == S_INT || sym->type == S_HEX) &&
prop->expr->type != E_SYMBOL) prop->expr->type != E_SYMBOL)
prop_warn(prop, prop_warn(prop,
"default for config symbol '%'" "default for config symbol '%s'"
" must be a single symbol", sym->name); " must be a single symbol", sym->name);
if (prop->expr->type != E_SYMBOL)
break;
sym2 = prop_get_symbol(prop);
if (sym->type == S_HEX || sym->type == S_INT) {
if (!menu_validate_number(sym, sym2))
prop_warn(prop,
"'%s': number is invalid",
sym->name);
}
break; break;
case P_SELECT: case P_SELECT:
sym2 = prop_get_symbol(prop); sym2 = prop_get_symbol(prop);
@ -152,40 +237,20 @@ void sym_check_prop(struct symbol *sym)
prop_warn(prop, prop_warn(prop,
"config symbol '%s' uses select, but is " "config symbol '%s' uses select, but is "
"not boolean or tristate", sym->name); "not boolean or tristate", sym->name);
else if (sym2->type == S_UNKNOWN) else if (sym2->type != S_UNKNOWN &&
prop_warn(prop, sym2->type != S_BOOLEAN &&
"'select' used by config symbol '%s' " sym2->type != S_TRISTATE)
"refer to undefined symbol '%s'",
sym->name, sym2->name);
else if (sym2->type != S_BOOLEAN && sym2->type != S_TRISTATE)
prop_warn(prop, prop_warn(prop,
"'%s' has wrong type. 'select' only " "'%s' has wrong type. 'select' only "
"accept arguments of boolean and " "accept arguments of boolean and "
"tristate type", sym2->name); "tristate type", sym2->name);
break; break;
case P_DESELECT:
sym2 = prop_get_symbol(prop);
if (sym->type != S_BOOLEAN && sym->type != S_TRISTATE)
prop_warn(prop,
"config symbol '%s' uses deselect, but is "
"not boolean or tristate", sym->name);
else if (sym2->type == S_UNKNOWN)
prop_warn(prop,
"'deselect' used by config symbol '%s' "
"refer to undefined symbol '%s'",
sym->name, sym2->name);
else if (sym2->type != S_BOOLEAN && sym2->type != S_TRISTATE)
prop_warn(prop,
"'%s' has wrong type. 'deselect' only "
"accept arguments of boolean and "
"tristate type", sym2->name);
break;
case P_RANGE: case P_RANGE:
if (sym->type != S_INT && sym->type != S_HEX) if (sym->type != S_INT && sym->type != S_HEX)
prop_warn(prop, "range is only allowed " prop_warn(prop, "range is only allowed "
"for int or hex symbols"); "for int or hex symbols");
if (!menu_range_valid_sym(sym, prop->expr->left.sym) || if (!menu_validate_number(sym, prop->expr->left.sym) ||
!menu_range_valid_sym(sym, prop->expr->right.sym)) !menu_validate_number(sym, prop->expr->right.sym))
prop_warn(prop, "range is invalid"); prop_warn(prop, "range is invalid");
break; break;
default: default:
@ -204,16 +269,22 @@ void menu_finalize(struct menu *parent)
sym = parent->sym; sym = parent->sym;
if (parent->list) { if (parent->list) {
if (sym && sym_is_choice(sym)) { if (sym && sym_is_choice(sym)) {
/* find the first choice value and find out choice type */ if (sym->type == S_UNKNOWN) {
for (menu = parent->list; menu; menu = menu->next) { /* find the first choice value to find out choice type */
if (menu->sym) { current_entry = parent;
current_entry = parent; for (menu = parent->list; menu; menu = menu->next) {
menu_set_type(menu->sym->type); if (menu->sym && menu->sym->type != S_UNKNOWN) {
current_entry = menu; menu_set_type(menu->sym->type);
menu_set_type(sym->type); break;
break; }
} }
} }
/* set the type of the remaining choice values */
for (menu = parent->list; menu; menu = menu->next) {
current_entry = menu;
if (menu->sym && menu->sym->type == S_UNKNOWN)
menu_set_type(sym->type);
}
parentdep = expr_alloc_symbol(sym); parentdep = expr_alloc_symbol(sym);
} else if (parent->prompt) } else if (parent->prompt)
parentdep = parent->prompt->visible.expr; parentdep = parent->prompt->visible.expr;
@ -229,12 +300,11 @@ void menu_finalize(struct menu *parent)
prop = menu->sym->prop; prop = menu->sym->prop;
else else
prop = menu->prompt; prop = menu->prompt;
for (; prop; prop = prop->next) { for (; prop; prop = prop->next) {
if (prop->menu != menu) if (prop->menu != menu)
continue; continue;
dep = expr_transform(prop->visible.expr); dep = expr_transform(prop->visible.expr);
dep = expr_alloc_and(expr_copy(menu->dep), dep); dep = expr_alloc_and(expr_copy(basedep), dep);
dep = expr_eliminate_dups(dep); dep = expr_eliminate_dups(dep);
if (menu->sym && menu->sym->type != S_TRISTATE) if (menu->sym && menu->sym->type != S_TRISTATE)
dep = expr_trans_bool(dep); dep = expr_trans_bool(dep);
@ -244,11 +314,6 @@ void menu_finalize(struct menu *parent)
es->rev_dep.expr = expr_alloc_or(es->rev_dep.expr, es->rev_dep.expr = expr_alloc_or(es->rev_dep.expr,
expr_alloc_and(expr_alloc_symbol(menu->sym), expr_copy(dep))); expr_alloc_and(expr_alloc_symbol(menu->sym), expr_copy(dep)));
} }
if (prop->type == P_DESELECT) {
struct symbol *es = prop_get_symbol(prop);
es->rev_dep_inv.expr = expr_alloc_or(es->rev_dep_inv.expr,
expr_alloc_and(expr_alloc_symbol(menu->sym), expr_copy(dep)));
}
} }
} }
for (menu = parent->list; menu; menu = menu->next) for (menu = parent->list; menu; menu = menu->next)
@ -284,26 +349,47 @@ void menu_finalize(struct menu *parent)
parent->next = last_menu->next; parent->next = last_menu->next;
last_menu->next = NULL; last_menu->next = NULL;
} }
sym->dir_dep.expr = expr_alloc_or(sym->dir_dep.expr, parent->dep);
} }
for (menu = parent->list; menu; menu = menu->next) { for (menu = parent->list; menu; menu = menu->next) {
if (sym && sym_is_choice(sym) && menu->sym) { if (sym && sym_is_choice(sym) &&
menu->sym && !sym_is_choice_value(menu->sym)) {
current_entry = menu;
menu->sym->flags |= SYMBOL_CHOICEVAL; menu->sym->flags |= SYMBOL_CHOICEVAL;
if (!menu->prompt) if (!menu->prompt)
menu_warn(menu, "choice value must have a prompt"); menu_warn(menu, "choice value must have a prompt");
for (prop = menu->sym->prop; prop; prop = prop->next) { for (prop = menu->sym->prop; prop; prop = prop->next) {
if (prop->type == P_PROMPT && prop->menu != menu) { if (prop->type == P_DEFAULT)
prop_warn(prop, "choice values " prop_warn(prop, "defaults for choice "
"currently only support a " "values not supported");
"single prompt"); if (prop->menu == menu)
continue;
if (prop->type == P_PROMPT &&
prop->menu->parent->sym != sym)
prop_warn(prop, "choice value used outside its choice group");
}
/* Non-tristate choice values of tristate choices must
* depend on the choice being set to Y. The choice
* values' dependencies were propagated to their
* properties above, so the change here must be re-
* propagated.
*/
if (sym->type == S_TRISTATE && menu->sym->type != S_TRISTATE) {
basedep = expr_alloc_comp(E_EQUAL, sym, &symbol_yes);
menu->dep = expr_alloc_and(basedep, menu->dep);
for (prop = menu->sym->prop; prop; prop = prop->next) {
if (prop->menu != menu)
continue;
prop->visible.expr = expr_alloc_and(expr_copy(basedep),
prop->visible.expr);
} }
} }
current_entry = menu;
menu_set_type(sym->type);
menu_add_symbol(P_CHOICE, sym, NULL); menu_add_symbol(P_CHOICE, sym, NULL);
prop = sym_get_choice_prop(sym); prop = sym_get_choice_prop(sym);
for (ep = &prop->expr; *ep; ep = &(*ep)->left.expr) for (ep = &prop->expr; *ep; ep = &(*ep)->left.expr)
; ;
*ep = expr_alloc_one(E_CHOICE, NULL); *ep = expr_alloc_one(E_LIST, NULL);
(*ep)->right.sym = menu->sym; (*ep)->right.sym = menu->sym;
} }
if (menu->list && (!menu->prompt || !menu->prompt->text)) { if (menu->list && (!menu->prompt || !menu->prompt->text)) {
@ -320,11 +406,10 @@ void menu_finalize(struct menu *parent)
if (sym && !(sym->flags & SYMBOL_WARNED)) { if (sym && !(sym->flags & SYMBOL_WARNED)) {
if (sym->type == S_UNKNOWN) if (sym->type == S_UNKNOWN)
menu_warn(parent, "config symbol defined " menu_warn(parent, "config symbol defined without type");
"without type\n");
if (sym_is_choice(sym) && !parent->prompt) if (sym_is_choice(sym) && !parent->prompt)
menu_warn(parent, "choice must have a prompt\n"); menu_warn(parent, "choice must have a prompt");
/* Check properties connected to this symbol */ /* Check properties connected to this symbol */
sym_check_prop(sym); sym_check_prop(sym);
@ -338,6 +423,13 @@ void menu_finalize(struct menu *parent)
} }
} }
bool menu_has_prompt(struct menu *menu)
{
if (!menu->prompt)
return false;
return true;
}
bool menu_is_visible(struct menu *menu) bool menu_is_visible(struct menu *menu)
{ {
struct menu *child; struct menu *child;
@ -346,6 +438,12 @@ bool menu_is_visible(struct menu *menu)
if (!menu->prompt) if (!menu->prompt)
return false; return false;
if (menu->visibility) {
if (expr_calc_value(menu->visibility) == no)
return no;
}
sym = menu->sym; sym = menu->sym;
if (sym) { if (sym) {
sym_calc_value(sym); sym_calc_value(sym);
@ -355,21 +453,27 @@ bool menu_is_visible(struct menu *menu)
if (visible != no) if (visible != no)
return true; return true;
if (!sym || sym_get_tristate_value(menu->sym) == no) if (!sym || sym_get_tristate_value(menu->sym) == no)
return false; return false;
for (child = menu->list; child; child = child->next) for (child = menu->list; child; child = child->next) {
if (menu_is_visible(child)) if (menu_is_visible(child)) {
if (sym)
sym->flags |= SYMBOL_DEF_USER;
return true; return true;
}
}
return false; return false;
} }
const char *menu_get_prompt(struct menu *menu) const char *menu_get_prompt(struct menu *menu)
{ {
if (menu->prompt) if (menu->prompt)
return _(menu->prompt->text); return menu->prompt->text;
else if (menu->sym) else if (menu->sym)
return _(menu->sym->name); return menu->sym->name;
return NULL; return NULL;
} }
@ -390,3 +494,151 @@ struct menu *menu_get_parent_menu(struct menu *menu)
return menu; return menu;
} }
bool menu_has_help(struct menu *menu)
{
return menu->help != NULL;
}
const char *menu_get_help(struct menu *menu)
{
if (menu->help)
return menu->help;
else
return "";
}
static void get_prompt_str(struct gstr *r, struct property *prop,
struct list_head *head)
{
int i, j;
struct menu *submenu[8], *menu, *location = NULL;
struct jump_key *jump;
str_printf(r, _("Prompt: %s\n"), _(prop->text));
str_printf(r, _(" Defined at %s:%d\n"), prop->menu->file->name,
prop->menu->lineno);
if (!expr_is_yes(prop->visible.expr)) {
str_append(r, _(" Depends on: "));
expr_gstr_print(prop->visible.expr, r);
str_append(r, "\n");
}
menu = prop->menu->parent;
for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent) {
bool accessible = menu_is_visible(menu);
submenu[i++] = menu;
if (location == NULL && accessible)
location = menu;
}
if (head && location) {
jump = xmalloc(sizeof(struct jump_key));
if (menu_is_visible(prop->menu)) {
/*
* There is not enough room to put the hint at the
* beginning of the "Prompt" line. Put the hint on the
* last "Location" line even when it would belong on
* the former.
*/
jump->target = prop->menu;
} else
jump->target = location;
if (list_empty(head))
jump->index = 0;
else
jump->index = list_entry(head->prev, struct jump_key,
entries)->index + 1;
list_add_tail(&jump->entries, head);
}
if (i > 0) {
str_printf(r, _(" Location:\n"));
for (j = 4; --i >= 0; j += 2) {
menu = submenu[i];
if (head && location && menu == location)
jump->offset = r->len - 1;
str_printf(r, "%*c-> %s", j, ' ',
_(menu_get_prompt(menu)));
if (menu->sym) {
str_printf(r, " (%s [=%s])", menu->sym->name ?
menu->sym->name : _("<choice>"),
sym_get_string_value(menu->sym));
}
str_append(r, "\n");
}
}
}
/*
* head is optional and may be NULL
*/
void get_symbol_str(struct gstr *r, struct symbol *sym,
struct list_head *head)
{
bool hit;
struct property *prop;
if (sym && sym->name) {
str_printf(r, "Symbol: %s [=%s]\n", sym->name,
sym_get_string_value(sym));
str_printf(r, "Type : %s\n", sym_type_name(sym->type));
if (sym->type == S_INT || sym->type == S_HEX) {
prop = sym_get_range_prop(sym);
if (prop) {
str_printf(r, "Range : ");
expr_gstr_print(prop->expr, r);
str_append(r, "\n");
}
}
}
for_all_prompts(sym, prop)
get_prompt_str(r, prop, head);
hit = false;
for_all_properties(sym, prop, P_SELECT) {
if (!hit) {
str_append(r, " Selects: ");
hit = true;
} else
str_printf(r, " && ");
expr_gstr_print(prop->expr, r);
}
if (hit)
str_append(r, "\n");
if (sym->rev_dep.expr) {
str_append(r, _(" Selected by: "));
expr_gstr_print(sym->rev_dep.expr, r);
str_append(r, "\n");
}
str_append(r, "\n\n");
}
struct gstr get_relations_str(struct symbol **sym_arr, struct list_head *head)
{
struct symbol *sym;
struct gstr res = str_new();
int i;
for (i = 0; sym_arr && (sym = sym_arr[i]); i++)
get_symbol_str(&res, sym, head);
if (!i)
str_append(&res, _("No matches found.\n"));
return res;
}
void menu_get_ext_help(struct menu *menu, struct gstr *help)
{
struct symbol *sym = menu->sym;
const char *help_text = nohelp_text;
if (menu_has_help(menu)) {
if (sym->name)
str_printf(help, "%s%s:\n\n", CONFIG_, sym->name);
help_text = menu_get_help(menu);
}
str_printf(help, "%s\n", _(help_text));
if (sym)
get_symbol_str(help, sym, NULL);
}

File diff suppressed because it is too large Load diff

View file

@ -5,6 +5,8 @@
* Released under the terms of the GNU GPL v2.0. * Released under the terms of the GNU GPL v2.0.
*/ */
#include <stdarg.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include "lkc.h" #include "lkc.h"
@ -12,26 +14,76 @@
struct file *file_lookup(const char *name) struct file *file_lookup(const char *name)
{ {
struct file *file; struct file *file;
const char *file_name = sym_expand_string_value(name);
for (file = file_list; file; file = file->next) { for (file = file_list; file; file = file->next) {
if (!strcmp(name, file->name)) if (!strcmp(name, file->name)) {
free((void *)file_name);
return file; return file;
}
} }
file = malloc(sizeof(*file)); file = xmalloc(sizeof(*file));
memset(file, 0, sizeof(*file)); memset(file, 0, sizeof(*file));
file->name = strdup(name); file->name = file_name;
file->next = file_list; file->next = file_list;
file_list = file; file_list = file;
return file; return file;
} }
/* Allocate initial growable sting */ /* write a dependency file as used by kbuild to track dependencies */
int file_write_dep(const char *name)
{
struct symbol *sym, *env_sym;
struct expr *e;
struct file *file;
FILE *out;
if (!name)
name = ".kconfig.d";
out = fopen("..config.tmp", "w");
if (!out)
return 1;
fprintf(out, "deps_config := \\\n");
for (file = file_list; file; file = file->next) {
if (file->next)
fprintf(out, "\t%s \\\n", file->name);
else
fprintf(out, "\t%s\n", file->name);
}
fprintf(out, "\n%s: \\\n"
"\t$(deps_config)\n\n", conf_get_autoconfig_name());
expr_list_for_each_sym(sym_env_list, e, sym) {
struct property *prop;
const char *value;
prop = sym_get_env_prop(sym);
env_sym = prop_get_symbol(prop);
if (!env_sym)
continue;
value = getenv(env_sym->name);
if (!value)
value = "";
fprintf(out, "ifneq \"$(%s)\" \"%s\"\n", env_sym->name, value);
fprintf(out, "%s: FORCE\n", conf_get_autoconfig_name());
fprintf(out, "endif\n");
}
fprintf(out, "\n$(deps_config): ;\n");
fclose(out);
rename("..config.tmp", name);
return 0;
}
/* Allocate initial growable string */
struct gstr str_new(void) struct gstr str_new(void)
{ {
struct gstr gs; struct gstr gs;
gs.s = malloc(sizeof(char) * 64); gs.s = xmalloc(sizeof(char) * 64);
gs.len = 16; gs.len = 64;
gs.max_width = 0;
strcpy(gs.s, "\0"); strcpy(gs.s, "\0");
return gs; return gs;
} }
@ -42,6 +94,7 @@ struct gstr str_assign(const char *s)
struct gstr gs; struct gstr gs;
gs.s = strdup(s); gs.s = strdup(s);
gs.len = strlen(s) + 1; gs.len = strlen(s) + 1;
gs.max_width = 0;
return gs; return gs;
} }
@ -57,12 +110,15 @@ void str_free(struct gstr *gs)
/* Append to growable string */ /* Append to growable string */
void str_append(struct gstr *gs, const char *s) void str_append(struct gstr *gs, const char *s)
{ {
size_t l = strlen(gs->s) + strlen(s) + 1; size_t l;
if (l > gs->len) { if (s) {
gs->s = realloc(gs->s, l); l = strlen(gs->s) + strlen(s) + 1;
gs->len = l; if (l > gs->len) {
gs->s = realloc(gs->s, l);
gs->len = l;
}
strcat(gs->s, s);
} }
strcat(gs->s, s);
} }
/* Append printf formatted string to growable string */ /* Append printf formatted string to growable string */
@ -82,3 +138,22 @@ const char *str_get(struct gstr *gs)
return gs->s; return gs->s;
} }
void *xmalloc(size_t size)
{
void *p = malloc(size);
if (p)
return p;
fprintf(stderr, "Out of memory.\n");
exit(1);
}
void *xcalloc(size_t nmemb, size_t size)
{
void *p = calloc(nmemb, size);
if (p)
return p;
fprintf(stderr, "Out of memory.\n");
exit(1);
}

View file

@ -9,6 +9,7 @@
struct kconf_id; struct kconf_id;
%% %%
mainmenu, T_MAINMENU, TF_COMMAND mainmenu, T_MAINMENU, TF_COMMAND
menu, T_MENU, TF_COMMAND menu, T_MENU, TF_COMMAND
@ -23,9 +24,7 @@ help, T_HELP, TF_COMMAND
if, T_IF, TF_COMMAND|TF_PARAM if, T_IF, TF_COMMAND|TF_PARAM
endif, T_ENDIF, TF_COMMAND endif, T_ENDIF, TF_COMMAND
depends, T_DEPENDS, TF_COMMAND depends, T_DEPENDS, TF_COMMAND
requires, T_REQUIRES, TF_COMMAND
optional, T_OPTIONAL, TF_COMMAND optional, T_OPTIONAL, TF_COMMAND
reset, T_RESET, TF_COMMAND
default, T_DEFAULT, TF_COMMAND, S_UNKNOWN default, T_DEFAULT, TF_COMMAND, S_UNKNOWN
prompt, T_PROMPT, TF_COMMAND prompt, T_PROMPT, TF_COMMAND
tristate, T_TYPE, TF_COMMAND, S_TRISTATE tristate, T_TYPE, TF_COMMAND, S_TRISTATE
@ -33,13 +32,16 @@ def_tristate, T_DEFAULT, TF_COMMAND, S_TRISTATE
bool, T_TYPE, TF_COMMAND, S_BOOLEAN bool, T_TYPE, TF_COMMAND, S_BOOLEAN
boolean, T_TYPE, TF_COMMAND, S_BOOLEAN boolean, T_TYPE, TF_COMMAND, S_BOOLEAN
def_bool, T_DEFAULT, TF_COMMAND, S_BOOLEAN def_bool, T_DEFAULT, TF_COMMAND, S_BOOLEAN
def_boolean, T_DEFAULT, TF_COMMAND, S_BOOLEAN
int, T_TYPE, TF_COMMAND, S_INT int, T_TYPE, TF_COMMAND, S_INT
hex, T_TYPE, TF_COMMAND, S_HEX hex, T_TYPE, TF_COMMAND, S_HEX
string, T_TYPE, TF_COMMAND, S_STRING string, T_TYPE, TF_COMMAND, S_STRING
deselect, T_DESELECT, TF_COMMAND
select, T_SELECT, TF_COMMAND select, T_SELECT, TF_COMMAND
enable, T_SELECT, TF_COMMAND
range, T_RANGE, TF_COMMAND range, T_RANGE, TF_COMMAND
visible, T_VISIBLE, TF_COMMAND
option, T_OPTION, TF_COMMAND
on, T_ON, TF_PARAM on, T_ON, TF_PARAM
modules, T_OPT_MODULES, TF_OPTION
defconfig_list, T_OPT_DEFCONFIG_LIST,TF_OPTION
env, T_OPT_ENV, TF_OPTION
reset, T_RESET, TF_COMMAND
%% %%

View file

@ -1,4 +1,4 @@
/* ANSI-C code produced by gperf version 3.0.1 */ /* ANSI-C code produced by gperf version 3.0.4 */
/* Command-line: gperf */ /* Command-line: gperf */
/* Computed positions: -k'1,3' */ /* Computed positions: -k'1,3' */
@ -30,46 +30,44 @@
#endif #endif
struct kconf_id; struct kconf_id;
/* maximum key range = 40, duplicates = 0 */ /* maximum key range = 47, duplicates = 0 */
#ifdef __GNUC__ #if (defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__cplusplus) || defined(__GNUC_STDC_INLINE__)
__inline
#else
#ifdef __cplusplus
inline inline
#endif #elif defined(__GNUC__)
__inline
#endif #endif
static unsigned int static unsigned int
kconf_id_hash (register const char *str, register unsigned int len) kconf_id_hash (register const char *str, register unsigned int len)
{ {
static unsigned char asso_values[] = static unsigned char asso_values[] =
{ {
42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
42, 42, 42, 42, 42, 42, 42, 35, 0, 20, 49, 49, 49, 49, 49, 49, 49, 49, 40, 5,
5, 0, 5, 42, 0, 25, 42, 42, 5, 5, 0, 0, 5, 49, 5, 20, 49, 49, 5, 20,
10, 0, 25, 15, 0, 0, 0, 10, 42, 42, 5, 0, 35, 49, 0, 15, 0, 10, 15, 49,
0, 42, 42, 42, 42, 42, 42, 42, 42, 42, 25, 49, 49, 49, 49, 49, 49, 49, 49, 49,
42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
42, 42, 42, 42, 42, 42 49, 49, 49, 49, 49, 49
}; };
register int hval = len; register int hval = len;
@ -89,129 +87,139 @@ kconf_id_hash (register const char *str, register unsigned int len)
struct kconf_id_strings_t struct kconf_id_strings_t
{ {
char kconf_id_strings_str2[sizeof("on")]; char kconf_id_strings_str2[sizeof("on")];
char kconf_id_strings_str3[sizeof("hex")]; char kconf_id_strings_str5[sizeof("endif")];
char kconf_id_strings_str4[sizeof("bool")]; char kconf_id_strings_str6[sizeof("option")];
char kconf_id_strings_str5[sizeof("reset")]; char kconf_id_strings_str7[sizeof("endmenu")];
char kconf_id_strings_str6[sizeof("string")];
char kconf_id_strings_str7[sizeof("boolean")];
char kconf_id_strings_str8[sizeof("optional")]; char kconf_id_strings_str8[sizeof("optional")];
char kconf_id_strings_str9[sizeof("help")]; char kconf_id_strings_str9[sizeof("endchoice")];
char kconf_id_strings_str10[sizeof("endif")]; char kconf_id_strings_str10[sizeof("range")];
char kconf_id_strings_str11[sizeof("select")]; char kconf_id_strings_str11[sizeof("choice")];
char kconf_id_strings_str12[sizeof("endmenu")]; char kconf_id_strings_str12[sizeof("default")];
char kconf_id_strings_str13[sizeof("deselect")]; char kconf_id_strings_str13[sizeof("def_bool")];
char kconf_id_strings_str14[sizeof("endchoice")]; char kconf_id_strings_str14[sizeof("help")];
char kconf_id_strings_str15[sizeof("range")]; char kconf_id_strings_str16[sizeof("config")];
char kconf_id_strings_str16[sizeof("source")]; char kconf_id_strings_str17[sizeof("def_tristate")];
char kconf_id_strings_str17[sizeof("default")]; char kconf_id_strings_str18[sizeof("env")];
char kconf_id_strings_str18[sizeof("def_bool")]; char kconf_id_strings_str19[sizeof("defconfig_list")];
char kconf_id_strings_str19[sizeof("menu")]; char kconf_id_strings_str20[sizeof("reset")];
char kconf_id_strings_str21[sizeof("def_boolean")]; char kconf_id_strings_str21[sizeof("string")];
char kconf_id_strings_str22[sizeof("def_tristate")]; char kconf_id_strings_str22[sizeof("if")];
char kconf_id_strings_str23[sizeof("requires")]; char kconf_id_strings_str23[sizeof("int")];
char kconf_id_strings_str25[sizeof("menuconfig")]; char kconf_id_strings_str26[sizeof("select")];
char kconf_id_strings_str26[sizeof("choice")]; char kconf_id_strings_str27[sizeof("modules")];
char kconf_id_strings_str27[sizeof("if")]; char kconf_id_strings_str28[sizeof("tristate")];
char kconf_id_strings_str28[sizeof("int")]; char kconf_id_strings_str29[sizeof("menu")];
char kconf_id_strings_str31[sizeof("prompt")]; char kconf_id_strings_str31[sizeof("source")];
char kconf_id_strings_str32[sizeof("comment")]; char kconf_id_strings_str32[sizeof("comment")];
char kconf_id_strings_str33[sizeof("tristate")]; char kconf_id_strings_str33[sizeof("hex")];
char kconf_id_strings_str36[sizeof("config")]; char kconf_id_strings_str35[sizeof("menuconfig")];
char kconf_id_strings_str37[sizeof("depends")]; char kconf_id_strings_str37[sizeof("visible")];
char kconf_id_strings_str38[sizeof("mainmenu")]; char kconf_id_strings_str41[sizeof("prompt")];
char kconf_id_strings_str41[sizeof("enable")]; char kconf_id_strings_str42[sizeof("depends")];
char kconf_id_strings_str44[sizeof("bool")];
char kconf_id_strings_str47[sizeof("boolean")];
char kconf_id_strings_str48[sizeof("mainmenu")];
}; };
static struct kconf_id_strings_t kconf_id_strings_contents = static struct kconf_id_strings_t kconf_id_strings_contents =
{ {
"on", "on",
"hex",
"bool",
"reset",
"string",
"boolean",
"optional",
"help",
"endif", "endif",
"select", "option",
"endmenu", "endmenu",
"deselect", "optional",
"endchoice", "endchoice",
"range", "range",
"source", "choice",
"default", "default",
"def_bool", "def_bool",
"menu", "help",
"def_boolean", "config",
"def_tristate", "def_tristate",
"requires", "env",
"menuconfig", "defconfig_list",
"choice", "reset",
"string",
"if", "if",
"int", "int",
"prompt", "select",
"comment", "modules",
"tristate", "tristate",
"config", "menu",
"source",
"comment",
"hex",
"menuconfig",
"visible",
"prompt",
"depends", "depends",
"mainmenu", "bool",
"enable" "boolean",
"mainmenu"
}; };
#define kconf_id_strings ((const char *) &kconf_id_strings_contents) #define kconf_id_strings ((const char *) &kconf_id_strings_contents)
#ifdef __GNUC__ #ifdef __GNUC__
__inline __inline
#if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__
__attribute__ ((__gnu_inline__))
#endif
#endif #endif
struct kconf_id * struct kconf_id *
kconf_id_lookup (register const char *str, register unsigned int len) kconf_id_lookup (register const char *str, register unsigned int len)
{ {
enum enum
{ {
TOTAL_KEYWORDS = 32, TOTAL_KEYWORDS = 33,
MIN_WORD_LENGTH = 2, MIN_WORD_LENGTH = 2,
MAX_WORD_LENGTH = 12, MAX_WORD_LENGTH = 14,
MIN_HASH_VALUE = 2, MIN_HASH_VALUE = 2,
MAX_HASH_VALUE = 41 MAX_HASH_VALUE = 48
}; };
static struct kconf_id wordlist[] = static struct kconf_id wordlist[] =
{ {
{-1}, {-1}, {-1}, {-1},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str2, T_ON, TF_PARAM}, {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str2, T_ON, TF_PARAM},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str3, T_TYPE, TF_COMMAND, S_HEX}, {-1}, {-1},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str4, T_TYPE, TF_COMMAND, S_BOOLEAN}, {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str5, T_ENDIF, TF_COMMAND},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str5, T_RESET, TF_COMMAND}, {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str6, T_OPTION, TF_COMMAND},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str6, T_TYPE, TF_COMMAND, S_STRING}, {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str7, T_ENDMENU, TF_COMMAND},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str7, T_TYPE, TF_COMMAND, S_BOOLEAN},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str8, T_OPTIONAL, TF_COMMAND}, {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str8, T_OPTIONAL, TF_COMMAND},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str9, T_HELP, TF_COMMAND}, {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str9, T_ENDCHOICE, TF_COMMAND},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str10, T_ENDIF, TF_COMMAND}, {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str10, T_RANGE, TF_COMMAND},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str11, T_SELECT, TF_COMMAND}, {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str11, T_CHOICE, TF_COMMAND},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str12, T_ENDMENU, TF_COMMAND}, {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str12, T_DEFAULT, TF_COMMAND, S_UNKNOWN},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str13, T_DESELECT, TF_COMMAND}, {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str13, T_DEFAULT, TF_COMMAND, S_BOOLEAN},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str14, T_ENDCHOICE, TF_COMMAND}, {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str14, T_HELP, TF_COMMAND},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str15, T_RANGE, TF_COMMAND},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str16, T_SOURCE, TF_COMMAND},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str17, T_DEFAULT, TF_COMMAND, S_UNKNOWN},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str18, T_DEFAULT, TF_COMMAND, S_BOOLEAN},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str19, T_MENU, TF_COMMAND},
{-1}, {-1},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str21, T_DEFAULT, TF_COMMAND, S_BOOLEAN}, {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str16, T_CONFIG, TF_COMMAND},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str22, T_DEFAULT, TF_COMMAND, S_TRISTATE}, {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str17, T_DEFAULT, TF_COMMAND, S_TRISTATE},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str23, T_REQUIRES, TF_COMMAND}, {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str18, T_OPT_ENV, TF_OPTION},
{-1}, {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str19, T_OPT_DEFCONFIG_LIST,TF_OPTION},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str25, T_MENUCONFIG, TF_COMMAND}, {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str20, T_RESET, TF_COMMAND},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str26, T_CHOICE, TF_COMMAND}, {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str21, T_TYPE, TF_COMMAND, S_STRING},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str27, T_IF, TF_COMMAND|TF_PARAM}, {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str22, T_IF, TF_COMMAND|TF_PARAM},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str28, T_TYPE, TF_COMMAND, S_INT}, {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str23, T_TYPE, TF_COMMAND, S_INT},
{-1}, {-1}, {-1}, {-1},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str31, T_PROMPT, TF_COMMAND}, {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str26, T_SELECT, TF_COMMAND},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str27, T_OPT_MODULES, TF_OPTION},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str28, T_TYPE, TF_COMMAND, S_TRISTATE},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str29, T_MENU, TF_COMMAND},
{-1},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str31, T_SOURCE, TF_COMMAND},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str32, T_COMMENT, TF_COMMAND}, {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str32, T_COMMENT, TF_COMMAND},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str33, T_TYPE, TF_COMMAND, S_TRISTATE}, {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str33, T_TYPE, TF_COMMAND, S_HEX},
{-1},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str35, T_MENUCONFIG, TF_COMMAND},
{-1},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str37, T_VISIBLE, TF_COMMAND},
{-1}, {-1}, {-1},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str41, T_PROMPT, TF_COMMAND},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str42, T_DEPENDS, TF_COMMAND},
{-1},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str44, T_TYPE, TF_COMMAND, S_BOOLEAN},
{-1}, {-1}, {-1}, {-1},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str36, T_CONFIG, TF_COMMAND}, {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str47, T_TYPE, TF_COMMAND, S_BOOLEAN},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str37, T_DEPENDS, TF_COMMAND}, {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str48, T_MAINMENU, TF_COMMAND}
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str38, T_MAINMENU, TF_COMMAND},
{-1}, {-1},
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str41, T_SELECT, TF_COMMAND}
}; };
if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)

View file

@ -1,5 +1,6 @@
%option backup nostdinit noyywrap never-interactive full ecs %option nostdinit noyywrap never-interactive full ecs
%option 8bit backup nodefault perf-report perf-report %option 8bit nodefault perf-report perf-report
%option noinput
%x COMMAND HELP STRING PARAM %x COMMAND HELP STRING PARAM
%{ %{
/* /*
@ -14,7 +15,6 @@
#include <unistd.h> #include <unistd.h>
#include <glob.h> #include <glob.h>
#define LKC_DIRECT_LINK
#include "lkc.h" #include "lkc.h"
#define START_STRSIZE 16 #define START_STRSIZE 16
@ -39,15 +39,15 @@ static int last_ts, first_ts;
static void zconf_endhelp(void); static void zconf_endhelp(void);
static void zconf_endfile(void); static void zconf_endfile(void);
void new_string(void) static void new_string(void)
{ {
text = malloc(START_STRSIZE); text = xmalloc(START_STRSIZE);
text_asize = START_STRSIZE; text_asize = START_STRSIZE;
text_size = 0; text_size = 0;
*text = 0; *text = 0;
} }
void append_string(const char *str, int size) static void append_string(const char *str, int size)
{ {
int new_size = text_size + size + 1; int new_size = text_size + size + 1;
if (new_size > text_asize) { if (new_size > text_asize) {
@ -61,9 +61,9 @@ void append_string(const char *str, int size)
text[text_size] = 0; text[text_size] = 0;
} }
void alloc_string(const char *str, int size) static void alloc_string(const char *str, int size)
{ {
text = malloc(size + 1); text = xmalloc(size + 1);
memcpy(text, str, size); memcpy(text, str, size);
text[size] = 0; text[size] = 0;
} }
@ -96,7 +96,7 @@ n [A-Za-z0-9_]
<COMMAND>{ <COMMAND>{
{n}+ { {n}+ {
struct kconf_id *id = kconf_id_lookup(yytext, yyleng); const struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
BEGIN(PARAM); BEGIN(PARAM);
current_pos.file = current_file; current_pos.file = current_file;
current_pos.lineno = current_file->lineno; current_pos.lineno = current_file->lineno;
@ -132,7 +132,7 @@ n [A-Za-z0-9_]
\n BEGIN(INITIAL); current_file->lineno++; return T_EOL; \n BEGIN(INITIAL); current_file->lineno++; return T_EOL;
--- /* ignore */ --- /* ignore */
({n}|[-/.])+ { ({n}|[-/.])+ {
struct kconf_id *id = kconf_id_lookup(yytext, yyleng); const struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
if (id && id->flags & TF_PARAM) { if (id && id->flags & TF_PARAM) {
zconflval.id = id; zconflval.id = id;
return id->token; return id->token;
@ -218,6 +218,11 @@ n [A-Za-z0-9_]
append_string("\n", 1); append_string("\n", 1);
} }
[^ \t\n].* { [^ \t\n].* {
while (yyleng) {
if ((yytext[yyleng-1] != ' ') && (yytext[yyleng-1] != '\t'))
break;
yyleng--;
}
append_string(yytext, yyleng); append_string(yytext, yyleng);
if (!first_ts) if (!first_ts)
first_ts = last_ts; first_ts = last_ts;
@ -266,7 +271,7 @@ FILE *zconf_fopen(const char *name)
FILE *f; FILE *f;
f = fopen(name, "r"); f = fopen(name, "r");
if (!f && name[0] != '/') { if (!f && name != NULL && name[0] != '/') {
env = getenv(SRCTREE); env = getenv(SRCTREE);
if (env) { if (env) {
sprintf(fullname, "%s/%s", env, name); sprintf(fullname, "%s/%s", env, name);
@ -284,73 +289,93 @@ void zconf_initscan(const char *name)
exit(1); exit(1);
} }
current_buf = malloc(sizeof(*current_buf)); current_buf = xmalloc(sizeof(*current_buf));
memset(current_buf, 0, sizeof(*current_buf)); memset(current_buf, 0, sizeof(*current_buf));
current_file = file_lookup(name); current_file = file_lookup(name);
current_file->lineno = 1; current_file->lineno = 1;
current_file->flags = FILE_BUSY; }
static void __zconf_nextfile(const char *name)
{
struct file *iter;
struct file *file = file_lookup(name);
struct buffer *buf = xmalloc(sizeof(*buf));
memset(buf, 0, sizeof(*buf));
current_buf->state = YY_CURRENT_BUFFER;
yyin = zconf_fopen(file->name);
if (!yyin) {
printf("%s:%d: can't open file \"%s\"\n",
zconf_curname(), zconf_lineno(), file->name);
exit(1);
}
yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
buf->parent = current_buf;
current_buf = buf;
for (iter = current_file->parent; iter; iter = iter->parent ) {
if (!strcmp(current_file->name,iter->name) ) {
printf("%s:%d: recursive inclusion detected. "
"Inclusion path:\n current file : '%s'\n",
zconf_curname(), zconf_lineno(),
zconf_curname());
iter = current_file->parent;
while (iter && \
strcmp(iter->name,current_file->name)) {
printf(" included from: '%s:%d'\n",
iter->name, iter->lineno-1);
iter = iter->parent;
}
if (iter)
printf(" included from: '%s:%d'\n",
iter->name, iter->lineno+1);
exit(1);
}
}
file->lineno = 1;
file->parent = current_file;
current_file = file;
} }
void zconf_nextfile(const char *name) void zconf_nextfile(const char *name)
{ {
size_t i; glob_t gl;
int retval; int err;
glob_t files; int i;
char *filename;
struct file *file;
struct buffer *buf;
retval = glob(name, GLOB_ERR | GLOB_MARK, NULL, &files); err = glob(name, GLOB_ERR | GLOB_MARK, NULL, &gl);
if (retval == GLOB_NOMATCH) if (err) {
return; const char *reason = "unknown error";
switch (err) {
case GLOB_NOSPACE:
reason = "out of memory";
break;
case GLOB_ABORTED:
reason = "read error";
break;
case GLOB_NOMATCH:
reason = "No files found";
break;
default:
break;
}
if (retval == GLOB_NOSPACE || retval == GLOB_ABORTED) {
printf("%s:%d: glob failed: %s \"%s\"\n", zconf_curname(), zconf_lineno(), printf("%s:%d: glob failed: %s \"%s\"\n", zconf_curname(), zconf_lineno(),
retval == GLOB_NOSPACE ? "failed to allocate memory" : reason, name);
retval == GLOB_ABORTED ? "read error" : "no match",
name);
exit(1); exit(1);
} }
for (i = files.gl_pathc-1; i != (size_t)-1; --i) { for (i = 0; i < gl.gl_pathc; i++)
filename = files.gl_pathv[i]; __zconf_nextfile(gl.gl_pathv[i]);
file = file_lookup(filename);
buf = malloc(sizeof(*buf));
memset(buf, 0, sizeof(*buf));
current_buf->state = YY_CURRENT_BUFFER;
zconfin = zconf_fopen(filename);
if (!zconfin) {
printf("%s:%d: can't open file \"%s\"\n",
zconf_curname(), zconf_lineno(), filename);
exit(1);
}
zconf_switch_to_buffer(zconf_create_buffer(zconfin,YY_BUF_SIZE));
buf->parent = current_buf;
current_buf = buf;
if (file->flags & FILE_BUSY) {
printf("recursive scan (%s)?\n", filename);
exit(1);
}
if (file->flags & FILE_SCANNED) {
printf("file %s already scanned?\n", filename);
exit(1);
}
file->flags |= FILE_BUSY;
file->lineno = 1;
file->parent = current_file;
current_file = file;
}
} }
static void zconf_endfile(void) static void zconf_endfile(void)
{ {
struct buffer *parent; struct buffer *parent;
current_file->flags |= FILE_SCANNED;
current_file->flags &= ~FILE_BUSY;
current_file = current_file->parent; current_file = current_file->parent;
parent = current_buf->parent; parent = current_buf->parent;
@ -368,7 +393,7 @@ int zconf_lineno(void)
return current_pos.lineno; return current_pos.lineno;
} }
char *zconf_curname(void) const char *zconf_curname(void)
{ {
return current_pos.file ? current_pos.file->name : "<none>"; return current_pos.file ? current_pos.file->name : "<none>";
} }

View file

@ -1,14 +1,33 @@
#line 3 "lex.zconf.c" #line 3 "zconf.lex.c"
#define YY_INT_ALIGNED short int #define YY_INT_ALIGNED short int
/* A lexical scanner generated by flex */ /* A lexical scanner generated by flex */
#define yy_create_buffer zconf_create_buffer
#define yy_delete_buffer zconf_delete_buffer
#define yy_flex_debug zconf_flex_debug
#define yy_init_buffer zconf_init_buffer
#define yy_flush_buffer zconf_flush_buffer
#define yy_load_buffer_state zconf_load_buffer_state
#define yy_switch_to_buffer zconf_switch_to_buffer
#define yyin zconfin
#define yyleng zconfleng
#define yylex zconflex
#define yylineno zconflineno
#define yyout zconfout
#define yyrestart zconfrestart
#define yytext zconftext
#define yywrap zconfwrap
#define yyalloc zconfalloc
#define yyrealloc zconfrealloc
#define yyfree zconffree
#define FLEX_SCANNER #define FLEX_SCANNER
#define YY_FLEX_MAJOR_VERSION 2 #define YY_FLEX_MAJOR_VERSION 2
#define YY_FLEX_MINOR_VERSION 5 #define YY_FLEX_MINOR_VERSION 5
#define YY_FLEX_SUBMINOR_VERSION 31 #define YY_FLEX_SUBMINOR_VERSION 37
#if YY_FLEX_SUBMINOR_VERSION > 0 #if YY_FLEX_SUBMINOR_VERSION > 0
#define FLEX_BETA #define FLEX_BETA
#endif #endif
@ -30,7 +49,15 @@
/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */ /* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
#if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L #if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
* if you want the limit (max/min) macros for int types.
*/
#ifndef __STDC_LIMIT_MACROS
#define __STDC_LIMIT_MACROS 1
#endif
#include <inttypes.h> #include <inttypes.h>
typedef int8_t flex_int8_t; typedef int8_t flex_int8_t;
typedef uint8_t flex_uint8_t; typedef uint8_t flex_uint8_t;
@ -45,7 +72,6 @@ typedef int flex_int32_t;
typedef unsigned char flex_uint8_t; typedef unsigned char flex_uint8_t;
typedef unsigned short int flex_uint16_t; typedef unsigned short int flex_uint16_t;
typedef unsigned int flex_uint32_t; typedef unsigned int flex_uint32_t;
#endif /* ! C99 */
/* Limits of integral types. */ /* Limits of integral types. */
#ifndef INT8_MIN #ifndef INT8_MIN
@ -76,6 +102,8 @@ typedef unsigned int flex_uint32_t;
#define UINT32_MAX (4294967295U) #define UINT32_MAX (4294967295U)
#endif #endif
#endif /* ! C99 */
#endif /* ! FLEXINT_H */ #endif /* ! FLEXINT_H */
#ifdef __cplusplus #ifdef __cplusplus
@ -85,11 +113,12 @@ typedef unsigned int flex_uint32_t;
#else /* ! __cplusplus */ #else /* ! __cplusplus */
#if __STDC__ /* C99 requires __STDC__ to be defined as 1. */
#if defined (__STDC__)
#define YY_USE_CONST #define YY_USE_CONST
#endif /* __STDC__ */ #endif /* defined (__STDC__) */
#endif /* ! __cplusplus */ #endif /* ! __cplusplus */
#ifdef YY_USE_CONST #ifdef YY_USE_CONST
@ -134,12 +163,21 @@ typedef unsigned int flex_uint32_t;
#define YY_BUF_SIZE 16384 #define YY_BUF_SIZE 16384
#endif #endif
/* The state buf must be large enough to hold one state per character in the main buffer.
*/
#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
#ifndef YY_TYPEDEF_YY_BUFFER_STATE #ifndef YY_TYPEDEF_YY_BUFFER_STATE
#define YY_TYPEDEF_YY_BUFFER_STATE #define YY_TYPEDEF_YY_BUFFER_STATE
typedef struct yy_buffer_state *YY_BUFFER_STATE; typedef struct yy_buffer_state *YY_BUFFER_STATE;
#endif #endif
extern int zconfleng; #ifndef YY_TYPEDEF_YY_SIZE_T
#define YY_TYPEDEF_YY_SIZE_T
typedef size_t yy_size_t;
#endif
extern yy_size_t zconfleng;
extern FILE *zconfin, *zconfout; extern FILE *zconfin, *zconfout;
@ -165,16 +203,6 @@ extern FILE *zconfin, *zconfout;
#define unput(c) yyunput( c, (yytext_ptr) ) #define unput(c) yyunput( c, (yytext_ptr) )
/* The following is because we cannot portably get our hands on size_t
* (without autoconf's help, which isn't available because we want
* flex-generated scanners to compile on their own).
*/
#ifndef YY_TYPEDEF_YY_SIZE_T
#define YY_TYPEDEF_YY_SIZE_T
typedef unsigned int yy_size_t;
#endif
#ifndef YY_STRUCT_YY_BUFFER_STATE #ifndef YY_STRUCT_YY_BUFFER_STATE
#define YY_STRUCT_YY_BUFFER_STATE #define YY_STRUCT_YY_BUFFER_STATE
struct yy_buffer_state struct yy_buffer_state
@ -192,7 +220,7 @@ struct yy_buffer_state
/* Number of characters read into yy_ch_buf, not including EOB /* Number of characters read into yy_ch_buf, not including EOB
* characters. * characters.
*/ */
int yy_n_chars; yy_size_t yy_n_chars;
/* Whether we "own" the buffer - i.e., we know we created it, /* Whether we "own" the buffer - i.e., we know we created it,
* and can realloc() it to grow it, and should free() it to * and can realloc() it to grow it, and should free() it to
@ -262,12 +290,12 @@ static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */
/* yy_hold_char holds the character lost when zconftext is formed. */ /* yy_hold_char holds the character lost when zconftext is formed. */
static char yy_hold_char; static char yy_hold_char;
static int yy_n_chars; /* number of characters read into yy_ch_buf */ static yy_size_t yy_n_chars; /* number of characters read into yy_ch_buf */
int zconfleng; yy_size_t zconfleng;
/* Points to current character in buffer. */ /* Points to current character in buffer. */
static char *yy_c_buf_p = (char *) 0; static char *yy_c_buf_p = (char *) 0;
static int yy_init = 1; /* whether we need to initialize */ static int yy_init = 0; /* whether we need to initialize */
static int yy_start = 0; /* start state number */ static int yy_start = 0; /* start state number */
/* Flag which is used to allow zconfwrap()'s to do buffer switches /* Flag which is used to allow zconfwrap()'s to do buffer switches
@ -291,7 +319,7 @@ static void zconf_init_buffer (YY_BUFFER_STATE b,FILE *file );
YY_BUFFER_STATE zconf_scan_buffer (char *base,yy_size_t size ); YY_BUFFER_STATE zconf_scan_buffer (char *base,yy_size_t size );
YY_BUFFER_STATE zconf_scan_string (yyconst char *yy_str ); YY_BUFFER_STATE zconf_scan_string (yyconst char *yy_str );
YY_BUFFER_STATE zconf_scan_bytes (yyconst char *bytes,int len ); YY_BUFFER_STATE zconf_scan_bytes (yyconst char *bytes,yy_size_t len );
void *zconfalloc (yy_size_t ); void *zconfalloc (yy_size_t );
void *zconfrealloc (void *,yy_size_t ); void *zconfrealloc (void *,yy_size_t );
@ -323,7 +351,7 @@ void zconffree (void * );
/* Begin user sect3 */ /* Begin user sect3 */
#define zconfwrap(n) 1 #define zconfwrap() 1
#define YY_SKIP_YYWRAP #define YY_SKIP_YYWRAP
typedef unsigned char YY_CHAR; typedef unsigned char YY_CHAR;
@ -736,6 +764,7 @@ int zconf_flex_debug = 0;
#define YY_MORE_ADJ 0 #define YY_MORE_ADJ 0
#define YY_RESTORE_YY_MORE_OFFSET #define YY_RESTORE_YY_MORE_OFFSET
char *zconftext; char *zconftext;
#define YY_NO_INPUT 1
/* /*
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
@ -749,7 +778,6 @@ char *zconftext;
#include <unistd.h> #include <unistd.h>
#include <glob.h> #include <glob.h>
#define LKC_DIRECT_LINK
#include "lkc.h" #include "lkc.h"
#define START_STRSIZE 16 #define START_STRSIZE 16
@ -774,15 +802,15 @@ static int last_ts, first_ts;
static void zconf_endhelp(void); static void zconf_endhelp(void);
static void zconf_endfile(void); static void zconf_endfile(void);
void new_string(void) static void new_string(void)
{ {
text = malloc(START_STRSIZE); text = xmalloc(START_STRSIZE);
text_asize = START_STRSIZE; text_asize = START_STRSIZE;
text_size = 0; text_size = 0;
*text = 0; *text = 0;
} }
void append_string(const char *str, int size) static void append_string(const char *str, int size)
{ {
int new_size = text_size + size + 1; int new_size = text_size + size + 1;
if (new_size > text_asize) { if (new_size > text_asize) {
@ -796,9 +824,9 @@ void append_string(const char *str, int size)
text[text_size] = 0; text[text_size] = 0;
} }
void alloc_string(const char *str, int size) static void alloc_string(const char *str, int size)
{ {
text = malloc(size + 1); text = xmalloc(size + 1);
memcpy(text, str, size); memcpy(text, str, size);
text[size] = 0; text[size] = 0;
} }
@ -821,6 +849,37 @@ void alloc_string(const char *str, int size)
#define YY_EXTRA_TYPE void * #define YY_EXTRA_TYPE void *
#endif #endif
static int yy_init_globals (void );
/* Accessor methods to globals.
These are made visible to non-reentrant scanners for convenience. */
int zconflex_destroy (void );
int zconfget_debug (void );
void zconfset_debug (int debug_flag );
YY_EXTRA_TYPE zconfget_extra (void );
void zconfset_extra (YY_EXTRA_TYPE user_defined );
FILE *zconfget_in (void );
void zconfset_in (FILE * in_str );
FILE *zconfget_out (void );
void zconfset_out (FILE * out_str );
yy_size_t zconfget_leng (void );
char *zconfget_text (void );
int zconfget_lineno (void );
void zconfset_lineno (int line_number );
/* Macros after this point can all be overridden by user definitions in /* Macros after this point can all be overridden by user definitions in
* section 1. * section 1.
*/ */
@ -863,7 +922,7 @@ static int input (void );
/* This used to be an fputs(), but since the string might contain NUL's, /* This used to be an fputs(), but since the string might contain NUL's,
* we now use fwrite(). * we now use fwrite().
*/ */
#define ECHO (void) fwrite( zconftext, zconfleng, 1, zconfout ) #define ECHO do { if (fwrite( zconftext, zconfleng, 1, zconfout )) {} } while (0)
#endif #endif
/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, /* Gets input and stuffs it into "buf". number of characters read, or YY_NULL,
@ -943,9 +1002,9 @@ YY_DECL
int str = 0; int str = 0;
int ts, i; int ts, i;
if ( (yy_init) ) if ( !(yy_init) )
{ {
(yy_init) = 0; (yy_init) = 1;
#ifdef YY_USER_INIT #ifdef YY_USER_INIT
YY_USER_INIT; YY_USER_INIT;
@ -1028,7 +1087,7 @@ YY_RULE_SETUP
case 6: case 6:
YY_RULE_SETUP YY_RULE_SETUP
{ {
struct kconf_id *id = kconf_id_lookup(zconftext, zconfleng); const struct kconf_id *id = kconf_id_lookup(zconftext, zconfleng);
BEGIN(PARAM); BEGIN(PARAM);
current_pos.file = current_file; current_pos.file = current_file;
current_pos.lineno = current_file->lineno; current_pos.lineno = current_file->lineno;
@ -1103,7 +1162,7 @@ YY_RULE_SETUP
case 19: case 19:
YY_RULE_SETUP YY_RULE_SETUP
{ {
struct kconf_id *id = kconf_id_lookup(zconftext, zconfleng); const struct kconf_id *id = kconf_id_lookup(zconftext, zconfleng);
if (id && id->flags & TF_PARAM) { if (id && id->flags & TF_PARAM) {
zconflval.id = id; zconflval.id = id;
return id->token; return id->token;
@ -1243,6 +1302,11 @@ YY_RULE_SETUP
case 32: case 32:
YY_RULE_SETUP YY_RULE_SETUP
{ {
while (zconfleng) {
if ((zconftext[zconfleng-1] != ' ') && (zconftext[zconfleng-1] != '\t'))
break;
zconfleng--;
}
append_string(zconftext, zconfleng); append_string(zconftext, zconfleng);
if (!first_ts) if (!first_ts)
first_ts = last_ts; first_ts = last_ts;
@ -1453,21 +1517,21 @@ static int yy_get_next_buffer (void)
else else
{ {
size_t num_to_read = yy_size_t num_to_read =
YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
while ( num_to_read <= 0 ) while ( num_to_read <= 0 )
{ /* Not enough room in the buffer - grow it. */ { /* Not enough room in the buffer - grow it. */
/* just a shorter name for the current buffer */ /* just a shorter name for the current buffer */
YY_BUFFER_STATE b = YY_CURRENT_BUFFER; YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE;
int yy_c_buf_p_offset = int yy_c_buf_p_offset =
(int) ((yy_c_buf_p) - b->yy_ch_buf); (int) ((yy_c_buf_p) - b->yy_ch_buf);
if ( b->yy_is_our_buffer ) if ( b->yy_is_our_buffer )
{ {
int new_size = b->yy_buf_size * 2; yy_size_t new_size = b->yy_buf_size * 2;
if ( new_size <= 0 ) if ( new_size <= 0 )
b->yy_buf_size += b->yy_buf_size / 8; b->yy_buf_size += b->yy_buf_size / 8;
@ -1522,6 +1586,14 @@ static int yy_get_next_buffer (void)
else else
ret_val = EOB_ACT_CONTINUE_SCAN; ret_val = EOB_ACT_CONTINUE_SCAN;
if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
/* Extend the array by 50%, plus the number we really need. */
yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1);
YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) zconfrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size );
if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
}
(yy_n_chars) += number_to_move; (yy_n_chars) += number_to_move;
YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;
@ -1560,7 +1632,7 @@ static int yy_get_next_buffer (void)
yy_current_state = yy_nxt[yy_current_state][1]; yy_current_state = yy_nxt[yy_current_state][1];
yy_is_jam = (yy_current_state <= 0); yy_is_jam = (yy_current_state <= 0);
return yy_is_jam ? 0 : yy_current_state; return yy_is_jam ? 0 : yy_current_state;
} }
static void yyunput (int c, register char * yy_bp ) static void yyunput (int c, register char * yy_bp )
@ -1575,7 +1647,7 @@ static int yy_get_next_buffer (void)
if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
{ /* need to shift things up to make room */ { /* need to shift things up to make room */
/* +2 for EOB chars. */ /* +2 for EOB chars. */
register int number_to_move = (yy_n_chars) + 2; register yy_size_t number_to_move = (yy_n_chars) + 2;
register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[ register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2]; YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];
register char *source = register char *source =
@ -1624,7 +1696,7 @@ static int yy_get_next_buffer (void)
else else
{ /* need more input */ { /* need more input */
int offset = (yy_c_buf_p) - (yytext_ptr); yy_size_t offset = (yy_c_buf_p) - (yytext_ptr);
++(yy_c_buf_p); ++(yy_c_buf_p);
switch ( yy_get_next_buffer( ) ) switch ( yy_get_next_buffer( ) )
@ -1896,7 +1968,7 @@ void zconfpop_buffer_state (void)
*/ */
static void zconfensure_buffer_stack (void) static void zconfensure_buffer_stack (void)
{ {
int num_to_alloc; yy_size_t num_to_alloc;
if (!(yy_buffer_stack)) { if (!(yy_buffer_stack)) {
@ -1908,7 +1980,9 @@ static void zconfensure_buffer_stack (void)
(yy_buffer_stack) = (struct yy_buffer_state**)zconfalloc (yy_buffer_stack) = (struct yy_buffer_state**)zconfalloc
(num_to_alloc * sizeof(struct yy_buffer_state*) (num_to_alloc * sizeof(struct yy_buffer_state*)
); );
if ( ! (yy_buffer_stack) )
YY_FATAL_ERROR( "out of dynamic memory in zconfensure_buffer_stack()" );
memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
(yy_buffer_stack_max) = num_to_alloc; (yy_buffer_stack_max) = num_to_alloc;
@ -1926,6 +2000,8 @@ static void zconfensure_buffer_stack (void)
((yy_buffer_stack), ((yy_buffer_stack),
num_to_alloc * sizeof(struct yy_buffer_state*) num_to_alloc * sizeof(struct yy_buffer_state*)
); );
if ( ! (yy_buffer_stack) )
YY_FATAL_ERROR( "out of dynamic memory in zconfensure_buffer_stack()" );
/* zero only the new slots.*/ /* zero only the new slots.*/
memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));
@ -1970,26 +2046,26 @@ YY_BUFFER_STATE zconf_scan_buffer (char * base, yy_size_t size )
/** Setup the input buffer state to scan a string. The next call to zconflex() will /** Setup the input buffer state to scan a string. The next call to zconflex() will
* scan from a @e copy of @a str. * scan from a @e copy of @a str.
* @param str a NUL-terminated string to scan * @param yystr a NUL-terminated string to scan
* *
* @return the newly allocated buffer state object. * @return the newly allocated buffer state object.
* @note If you want to scan bytes that may contain NUL values, then use * @note If you want to scan bytes that may contain NUL values, then use
* zconf_scan_bytes() instead. * zconf_scan_bytes() instead.
*/ */
YY_BUFFER_STATE zconf_scan_string (yyconst char * yy_str ) YY_BUFFER_STATE zconf_scan_string (yyconst char * yystr )
{ {
return zconf_scan_bytes(yy_str,strlen(yy_str) ); return zconf_scan_bytes(yystr,strlen(yystr) );
} }
/** Setup the input buffer state to scan the given bytes. The next call to zconflex() will /** Setup the input buffer state to scan the given bytes. The next call to zconflex() will
* scan from a @e copy of @a bytes. * scan from a @e copy of @a bytes.
* @param bytes the byte buffer to scan * @param yybytes the byte buffer to scan
* @param len the number of bytes in the buffer pointed to by @a bytes. * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
* *
* @return the newly allocated buffer state object. * @return the newly allocated buffer state object.
*/ */
YY_BUFFER_STATE zconf_scan_bytes (yyconst char * bytes, int len ) YY_BUFFER_STATE zconf_scan_bytes (yyconst char * yybytes, yy_size_t _yybytes_len )
{ {
YY_BUFFER_STATE b; YY_BUFFER_STATE b;
char *buf; char *buf;
@ -1997,15 +2073,15 @@ YY_BUFFER_STATE zconf_scan_bytes (yyconst char * bytes, int len )
int i; int i;
/* Get memory for full buffer, including space for trailing EOB's. */ /* Get memory for full buffer, including space for trailing EOB's. */
n = len + 2; n = _yybytes_len + 2;
buf = (char *) zconfalloc(n ); buf = (char *) zconfalloc(n );
if ( ! buf ) if ( ! buf )
YY_FATAL_ERROR( "out of dynamic memory in zconf_scan_bytes()" ); YY_FATAL_ERROR( "out of dynamic memory in zconf_scan_bytes()" );
for ( i = 0; i < len; ++i ) for ( i = 0; i < _yybytes_len; ++i )
buf[i] = bytes[i]; buf[i] = yybytes[i];
buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR; buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
b = zconf_scan_buffer(buf,n ); b = zconf_scan_buffer(buf,n );
if ( ! b ) if ( ! b )
@ -2076,7 +2152,7 @@ FILE *zconfget_out (void)
/** Get the length of the current token. /** Get the length of the current token.
* *
*/ */
int zconfget_leng (void) yy_size_t zconfget_leng (void)
{ {
return zconfleng; return zconfleng;
} }
@ -2126,6 +2202,34 @@ void zconfset_debug (int bdebug )
zconf_flex_debug = bdebug ; zconf_flex_debug = bdebug ;
} }
static int yy_init_globals (void)
{
/* Initialization is the same as for the non-reentrant scanner.
* This function is called from zconflex_destroy(), so don't allocate here.
*/
(yy_buffer_stack) = 0;
(yy_buffer_stack_top) = 0;
(yy_buffer_stack_max) = 0;
(yy_c_buf_p) = (char *) 0;
(yy_init) = 0;
(yy_start) = 0;
/* Defined in main.c */
#ifdef YY_STDINIT
zconfin = stdin;
zconfout = stdout;
#else
zconfin = (FILE *) 0;
zconfout = (FILE *) 0;
#endif
/* For future reference: Set errno on error, since we are called by
* zconflex_init()
*/
return 0;
}
/* zconflex_destroy is for both reentrant and non-reentrant scanners. */ /* zconflex_destroy is for both reentrant and non-reentrant scanners. */
int zconflex_destroy (void) int zconflex_destroy (void)
{ {
@ -2141,6 +2245,10 @@ int zconflex_destroy (void)
zconffree((yy_buffer_stack) ); zconffree((yy_buffer_stack) );
(yy_buffer_stack) = NULL; (yy_buffer_stack) = NULL;
/* Reset the globals. This is important in a non-reentrant scanner so the next time
* zconflex() is called, initialization will occur. */
yy_init_globals( );
return 0; return 0;
} }
@ -2152,7 +2260,7 @@ int zconflex_destroy (void)
static void yy_flex_strncpy (char* s1, yyconst char * s2, int n ) static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
{ {
register int i; register int i;
for ( i = 0; i < n; ++i ) for ( i = 0; i < n; ++i )
s1[i] = s2[i]; s1[i] = s2[i];
} }
#endif #endif
@ -2161,7 +2269,7 @@ static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
static int yy_flex_strlen (yyconst char * s ) static int yy_flex_strlen (yyconst char * s )
{ {
register int n; register int n;
for ( n = 0; s[n]; ++n ) for ( n = 0; s[n]; ++n )
; ;
return n; return n;
@ -2192,19 +2300,6 @@ void zconffree (void * ptr )
#define YYTABLES_NAME "yytables" #define YYTABLES_NAME "yytables"
#undef YY_NEW_FILE
#undef YY_FLUSH_BUFFER
#undef yy_set_bol
#undef yy_new_buffer
#undef yy_set_interactive
#undef yytext_ptr
#undef YY_DO_BEFORE_ACTION
#ifdef YY_DECL_IS_OURS
#undef YY_DECL_IS_OURS
#undef YY_DECL
#endif
void zconf_starthelp(void) void zconf_starthelp(void)
{ {
new_string(); new_string();
@ -2232,7 +2327,7 @@ FILE *zconf_fopen(const char *name)
FILE *f; FILE *f;
f = fopen(name, "r"); f = fopen(name, "r");
if (!f && name[0] != '/') { if (!f && name != NULL && name[0] != '/') {
env = getenv(SRCTREE); env = getenv(SRCTREE);
if (env) { if (env) {
sprintf(fullname, "%s/%s", env, name); sprintf(fullname, "%s/%s", env, name);
@ -2250,73 +2345,93 @@ void zconf_initscan(const char *name)
exit(1); exit(1);
} }
current_buf = malloc(sizeof(*current_buf)); current_buf = xmalloc(sizeof(*current_buf));
memset(current_buf, 0, sizeof(*current_buf)); memset(current_buf, 0, sizeof(*current_buf));
current_file = file_lookup(name); current_file = file_lookup(name);
current_file->lineno = 1; current_file->lineno = 1;
current_file->flags = FILE_BUSY; }
static void __zconf_nextfile(const char *name)
{
struct file *iter;
struct file *file = file_lookup(name);
struct buffer *buf = xmalloc(sizeof(*buf));
memset(buf, 0, sizeof(*buf));
current_buf->state = YY_CURRENT_BUFFER;
zconfin = zconf_fopen(file->name);
if (!zconfin) {
printf("%s:%d: can't open file \"%s\"\n",
zconf_curname(), zconf_lineno(), file->name);
exit(1);
}
zconf_switch_to_buffer(zconf_create_buffer(zconfin,YY_BUF_SIZE));
buf->parent = current_buf;
current_buf = buf;
for (iter = current_file->parent; iter; iter = iter->parent ) {
if (!strcmp(current_file->name,iter->name) ) {
printf("%s:%d: recursive inclusion detected. "
"Inclusion path:\n current file : '%s'\n",
zconf_curname(), zconf_lineno(),
zconf_curname());
iter = current_file->parent;
while (iter && \
strcmp(iter->name,current_file->name)) {
printf(" included from: '%s:%d'\n",
iter->name, iter->lineno-1);
iter = iter->parent;
}
if (iter)
printf(" included from: '%s:%d'\n",
iter->name, iter->lineno+1);
exit(1);
}
}
file->lineno = 1;
file->parent = current_file;
current_file = file;
} }
void zconf_nextfile(const char *name) void zconf_nextfile(const char *name)
{ {
size_t i; glob_t gl;
int retval; int err;
glob_t files; int i;
char *filename;
struct file *file;
struct buffer *buf;
retval = glob(name, GLOB_ERR | GLOB_MARK, NULL, &files); err = glob(name, GLOB_ERR | GLOB_MARK, NULL, &gl);
if (retval == GLOB_NOMATCH) if (err) {
return; const char *reason = "unknown error";
switch (err) {
case GLOB_NOSPACE:
reason = "out of memory";
break;
case GLOB_ABORTED:
reason = "read error";
break;
case GLOB_NOMATCH:
reason = "No files found";
break;
default:
break;
}
if (retval == GLOB_NOSPACE || retval == GLOB_ABORTED) {
printf("%s:%d: glob failed: %s \"%s\"\n", zconf_curname(), zconf_lineno(), printf("%s:%d: glob failed: %s \"%s\"\n", zconf_curname(), zconf_lineno(),
retval == GLOB_NOSPACE ? "failed to allocate memory" : reason, name);
retval == GLOB_ABORTED ? "read error" : "no match",
name);
exit(1); exit(1);
} }
for (i = files.gl_pathc-1; i != (size_t)-1; --i) { for (i = 0; i < gl.gl_pathc; i++)
filename = files.gl_pathv[i]; __zconf_nextfile(gl.gl_pathv[i]);
file = file_lookup(filename);
buf = malloc(sizeof(*buf));
memset(buf, 0, sizeof(*buf));
current_buf->state = YY_CURRENT_BUFFER;
zconfin = zconf_fopen(filename);
if (!zconfin) {
printf("%s:%d: can't open file \"%s\"\n",
zconf_curname(), zconf_lineno(), filename);
exit(1);
}
zconf_switch_to_buffer(zconf_create_buffer(zconfin,YY_BUF_SIZE));
buf->parent = current_buf;
current_buf = buf;
if (file->flags & FILE_BUSY) {
printf("recursive scan (%s)?\n", filename);
exit(1);
}
if (file->flags & FILE_SCANNED) {
printf("file %s already scanned?\n", filename);
exit(1);
}
file->flags |= FILE_BUSY;
file->lineno = 1;
file->parent = current_file;
current_file = file;
}
} }
static void zconf_endfile(void) static void zconf_endfile(void)
{ {
struct buffer *parent; struct buffer *parent;
current_file->flags |= FILE_SCANNED;
current_file->flags &= ~FILE_BUSY;
current_file = current_file->parent; current_file = current_file->parent;
parent = current_buf->parent; parent = current_buf->parent;
@ -2334,7 +2449,7 @@ int zconf_lineno(void)
return current_pos.lineno; return current_pos.lineno;
} }
char *zconf_curname(void) const char *zconf_curname(void)
{ {
return current_pos.file ? current_pos.file->name : "<none>"; return current_pos.file ? current_pos.file->name : "<none>";
} }

File diff suppressed because it is too large Load diff

View file

@ -11,11 +11,8 @@
#include <string.h> #include <string.h>
#include <stdbool.h> #include <stdbool.h>
#define LKC_DIRECT_LINK
#include "lkc.h" #include "lkc.h"
#include "zconf.hash.c"
#define printd(mask, fmt...) if (cdebug & (mask)) printf(fmt) #define printd(mask, fmt...) if (cdebug & (mask)) printf(fmt)
#define PRINTD 0x0001 #define PRINTD 0x0001
@ -27,18 +24,14 @@ extern int zconflex(void);
static void zconfprint(const char *err, ...); static void zconfprint(const char *err, ...);
static void zconf_error(const char *err, ...); static void zconf_error(const char *err, ...);
static void zconferror(const char *err); static void zconferror(const char *err);
static bool zconf_endtoken(struct kconf_id *id, int starttoken, int endtoken); static bool zconf_endtoken(const struct kconf_id *id, int starttoken, int endtoken);
struct symbol *symbol_hash[257]; struct symbol *symbol_hash[SYMBOL_HASHSIZE];
static struct menu *current_menu, *current_entry; static struct menu *current_menu, *current_entry;
#define YYDEBUG 0
#if YYDEBUG
#define YYERROR_VERBOSE
#endif
%} %}
%expect 26 %expect 30
%union %union
{ {
@ -47,7 +40,7 @@ static struct menu *current_menu, *current_entry;
struct symbol *symbol; struct symbol *symbol;
struct expr *expr; struct expr *expr;
struct menu *menu; struct menu *menu;
struct kconf_id *id; const struct kconf_id *id;
} }
%token <id>T_MAINMENU %token <id>T_MAINMENU
@ -64,14 +57,14 @@ static struct menu *current_menu, *current_entry;
%token <id>T_IF %token <id>T_IF
%token <id>T_ENDIF %token <id>T_ENDIF
%token <id>T_DEPENDS %token <id>T_DEPENDS
%token <id>T_REQUIRES
%token <id>T_OPTIONAL %token <id>T_OPTIONAL
%token <id>T_PROMPT %token <id>T_PROMPT
%token <id>T_TYPE %token <id>T_TYPE
%token <id>T_DEFAULT %token <id>T_DEFAULT
%token <id>T_DESELECT
%token <id>T_SELECT %token <id>T_SELECT
%token <id>T_RANGE %token <id>T_RANGE
%token <id>T_VISIBLE
%token <id>T_OPTION
%token <id>T_ON %token <id>T_ON
%token <id>T_RESET %token <id>T_RESET
%token <string> T_WORD %token <string> T_WORD
@ -93,6 +86,7 @@ static struct menu *current_menu, *current_entry;
%type <id> end %type <id> end
%type <id> option_name %type <id> option_name
%type <menu> if_entry menu_entry choice_entry %type <menu> if_entry menu_entry choice_entry
%type <string> symbol_option_arg word_opt
%destructor { %destructor {
fprintf(stderr, "%s:%d: missing end statement for this entry\n", fprintf(stderr, "%s:%d: missing end statement for this entry\n",
@ -101,15 +95,21 @@ static struct menu *current_menu, *current_entry;
menu_end_menu(); menu_end_menu();
} if_entry menu_entry choice_entry } if_entry menu_entry choice_entry
%{
/* Include zconf.hash.c here so it can see the token constants. */
#include "zconf.hash.c"
%}
%% %%
input: stmt_list; input: nl start | start;
start: mainmenu_stmt stmt_list | stmt_list;
stmt_list: stmt_list:
/* empty */ /* empty */
| stmt_list common_stmt | stmt_list common_stmt
| stmt_list choice_stmt | stmt_list choice_stmt
| stmt_list menu_stmt | stmt_list menu_stmt
| stmt_list T_MAINMENU prompt nl
| stmt_list end { zconf_error("unexpected end statement"); } | stmt_list end { zconf_error("unexpected end statement"); }
| stmt_list T_WORD error T_EOL { zconf_error("unknown statement \"%s\"", $2); } | stmt_list T_WORD error T_EOL { zconf_error("unknown statement \"%s\"", $2); }
| stmt_list option_name error T_EOL | stmt_list option_name error T_EOL
@ -120,7 +120,7 @@ stmt_list:
; ;
option_name: option_name:
T_DEPENDS | T_PROMPT | T_TYPE | T_DESELECT | T_SELECT | T_OPTIONAL | T_RANGE | T_DEFAULT | T_RESET T_DEPENDS | T_PROMPT | T_TYPE | T_SELECT | T_OPTIONAL | T_RANGE | T_DEFAULT | T_VISIBLE | T_RESET
; ;
common_stmt: common_stmt:
@ -175,6 +175,7 @@ menuconfig_stmt: menuconfig_entry_start config_option_list
config_option_list: config_option_list:
/* empty */ /* empty */
| config_option_list config_option | config_option_list config_option
| config_option_list symbol_option
| config_option_list depends | config_option_list depends
| config_option_list help | config_option_list help
| config_option_list option_error | config_option_list option_error
@ -205,12 +206,6 @@ config_option: T_DEFAULT expr if_expr T_EOL
$1->stype); $1->stype);
}; };
config_option: T_DESELECT T_WORD if_expr T_EOL
{
menu_add_symbol(P_DESELECT, sym_lookup($2, 0), $3);
printd(DEBUG_PARSE, "%s:%d:deselect\n", zconf_curname(), zconf_lineno());
};
config_option: T_SELECT T_WORD if_expr T_EOL config_option: T_SELECT T_WORD if_expr T_EOL
{ {
menu_add_symbol(P_SELECT, sym_lookup($2, 0), $3); menu_add_symbol(P_SELECT, sym_lookup($2, 0), $3);
@ -223,12 +218,32 @@ config_option: T_RANGE symbol symbol if_expr T_EOL
printd(DEBUG_PARSE, "%s:%d:range\n", zconf_curname(), zconf_lineno()); printd(DEBUG_PARSE, "%s:%d:range\n", zconf_curname(), zconf_lineno());
}; };
symbol_option: T_OPTION symbol_option_list T_EOL
;
symbol_option_list:
/* empty */
| symbol_option_list T_WORD symbol_option_arg
{
const struct kconf_id *id = kconf_id_lookup($2, strlen($2));
if (id && id->flags & TF_OPTION)
menu_add_option(id->token, $3);
else
zconfprint("warning: ignoring unknown option %s", $2);
free($2);
};
symbol_option_arg:
/* empty */ { $$ = NULL; }
| T_EQUAL prompt { $$ = $2; }
;
/* choice entry */ /* choice entry */
choice: T_CHOICE T_EOL choice: T_CHOICE word_opt T_EOL
{ {
struct symbol *sym = sym_lookup(NULL, 0); struct symbol *sym = sym_lookup($2, SYMBOL_CHOICE);
sym->flags |= SYMBOL_CHOICE; sym->flags |= SYMBOL_AUTO;
menu_add_entry(sym); menu_add_entry(sym);
menu_add_expr(P_CHOICE, NULL, NULL); menu_add_expr(P_CHOICE, NULL, NULL);
printd(DEBUG_PARSE, "%s:%d:choice\n", zconf_curname(), zconf_lineno()); printd(DEBUG_PARSE, "%s:%d:choice\n", zconf_curname(), zconf_lineno());
@ -330,6 +345,13 @@ if_block:
| if_block choice_stmt | if_block choice_stmt
; ;
/* mainmenu entry */
mainmenu_stmt: T_MAINMENU prompt nl
{
menu_add_prompt(P_MENU, $2, NULL);
};
/* menu entry */ /* menu entry */
menu: T_MENU prompt T_EOL menu: T_MENU prompt T_EOL
@ -339,7 +361,7 @@ menu: T_MENU prompt T_EOL
printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno()); printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno());
}; };
menu_entry: menu depends_list menu_entry: menu visibility_list depends_list
{ {
$$ = menu_add_menu(); $$ = menu_add_menu();
}; };
@ -392,7 +414,7 @@ help_start: T_HELP T_EOL
help: help_start T_HELPTEXT help: help_start T_HELPTEXT
{ {
current_entry->sym->help = $2; current_entry->help = $2;
}; };
/* depends option */ /* depends option */
@ -408,16 +430,19 @@ depends: T_DEPENDS T_ON expr T_EOL
{ {
menu_add_dep($3); menu_add_dep($3);
printd(DEBUG_PARSE, "%s:%d:depends on\n", zconf_curname(), zconf_lineno()); printd(DEBUG_PARSE, "%s:%d:depends on\n", zconf_curname(), zconf_lineno());
} };
| T_DEPENDS expr T_EOL
/* visibility option */
visibility_list:
/* empty */
| visibility_list visible
| visibility_list T_EOL
;
visible: T_VISIBLE if_expr
{ {
menu_add_dep($2); menu_add_visibility($2);
printd(DEBUG_PARSE, "%s:%d:depends\n", zconf_curname(), zconf_lineno());
}
| T_REQUIRES expr T_EOL
{
menu_add_dep($2);
printd(DEBUG_PARSE, "%s:%d:requires\n", zconf_curname(), zconf_lineno());
}; };
/* prompt statement */ /* prompt statement */
@ -457,9 +482,12 @@ expr: symbol { $$ = expr_alloc_symbol($1); }
; ;
symbol: T_WORD { $$ = sym_lookup($1, 0); free($1); } symbol: T_WORD { $$ = sym_lookup($1, 0); free($1); }
| T_WORD_QUOTE { $$ = sym_lookup($1, 1); free($1); } | T_WORD_QUOTE { $$ = sym_lookup($1, SYMBOL_CONST); free($1); }
; ;
word_opt: /* empty */ { $$ = NULL; }
| T_WORD
%% %%
void conf_parse(const char *name) void conf_parse(const char *name)
@ -470,9 +498,11 @@ void conf_parse(const char *name)
zconf_initscan(name); zconf_initscan(name);
sym_init(); sym_init();
menu_init(); _menu_init();
modules_sym = sym_lookup("MODULES", 0); modules_sym = sym_lookup(NULL, 0);
rootmenu.prompt = menu_add_prompt(P_MENU, "OpenWrt Configuration", NULL); modules_sym->type = S_BOOLEAN;
modules_sym->flags |= SYMBOL_AUTO;
rootmenu.prompt = menu_add_prompt(P_MENU, "Linux Kernel Configuration", NULL);
#if YYDEBUG #if YYDEBUG
if (getenv("ZCONF_DEBUG")) if (getenv("ZCONF_DEBUG"))
@ -481,15 +511,27 @@ void conf_parse(const char *name)
zconfparse(); zconfparse();
if (zconfnerrs) if (zconfnerrs)
exit(1); exit(1);
if (!modules_sym->prop) {
struct property *prop;
prop = prop_alloc(P_DEFAULT, modules_sym);
prop->expr = expr_alloc_symbol(sym_lookup("MODULES", 0));
}
rootmenu.prompt->text = _(rootmenu.prompt->text);
rootmenu.prompt->text = sym_expand_string_value(rootmenu.prompt->text);
menu_finalize(&rootmenu); menu_finalize(&rootmenu);
for_all_symbols(i, sym) { for_all_symbols(i, sym) {
sym_check_deps(sym); if (sym_check_deps(sym))
zconfnerrs++;
} }
if (zconfnerrs)
sym_change_count = 1; exit(1);
sym_set_change_count(1);
} }
const char *zconf_tokenname(int token) static const char *zconf_tokenname(int token)
{ {
switch (token) { switch (token) {
case T_MENU: return "menu"; case T_MENU: return "menu";
@ -499,11 +541,12 @@ const char *zconf_tokenname(int token)
case T_IF: return "if"; case T_IF: return "if";
case T_ENDIF: return "endif"; case T_ENDIF: return "endif";
case T_DEPENDS: return "depends"; case T_DEPENDS: return "depends";
case T_VISIBLE: return "visible";
} }
return "<token>"; return "<token>";
} }
static bool zconf_endtoken(struct kconf_id *id, int starttoken, int endtoken) static bool zconf_endtoken(const struct kconf_id *id, int starttoken, int endtoken)
{ {
if (id->token != endtoken) { if (id->token != endtoken) {
zconf_error("unexpected '%s' within %s block", zconf_error("unexpected '%s' within %s block",
@ -548,12 +591,10 @@ static void zconf_error(const char *err, ...)
static void zconferror(const char *err) static void zconferror(const char *err)
{ {
#if YYDEBUG
fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno() + 1, err); fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno() + 1, err);
#endif
} }
void print_quoted_string(FILE *out, const char *str) static void print_quoted_string(FILE *out, const char *str)
{ {
const char *p; const char *p;
int len; int len;
@ -570,15 +611,15 @@ void print_quoted_string(FILE *out, const char *str)
putc('"', out); putc('"', out);
} }
void print_symbol(FILE *out, struct menu *menu) static void print_symbol(FILE *out, struct menu *menu)
{ {
struct symbol *sym = menu->sym; struct symbol *sym = menu->sym;
struct property *prop; struct property *prop;
if (sym_is_choice(sym)) if (sym_is_choice(sym))
fprintf(out, "choice\n"); fprintf(out, "\nchoice\n");
else else
fprintf(out, "config %s\n", sym->name); fprintf(out, "\nconfig %s\n", sym->name);
switch (sym->type) { switch (sym->type) {
case S_BOOLEAN: case S_BOOLEAN:
fputs(" boolean\n", out); fputs(" boolean\n", out);
@ -624,18 +665,32 @@ void print_symbol(FILE *out, struct menu *menu)
case P_CHOICE: case P_CHOICE:
fputs(" #choice value\n", out); fputs(" #choice value\n", out);
break; break;
case P_SELECT:
fputs( " select ", out);
expr_fprint(prop->expr, out);
fputc('\n', out);
break;
case P_RANGE:
fputs( " range ", out);
expr_fprint(prop->expr, out);
fputc('\n', out);
break;
case P_MENU:
fputs( " menu ", out);
print_quoted_string(out, prop->text);
fputc('\n', out);
break;
default: default:
fprintf(out, " unknown prop %d!\n", prop->type); fprintf(out, " unknown prop %d!\n", prop->type);
break; break;
} }
} }
if (sym->help) { if (menu->help) {
int len = strlen(sym->help); int len = strlen(menu->help);
while (sym->help[--len] == '\n') while (menu->help[--len] == '\n')
sym->help[len] = 0; menu->help[len] = 0;
fprintf(out, " help\n%s\n", sym->help); fprintf(out, " help\n%s\n", menu->help);
} }
fputc('\n', out);
} }
void zconfdump(FILE *out) void zconfdump(FILE *out)
@ -668,7 +723,6 @@ void zconfdump(FILE *out)
expr_fprint(prop->visible.expr, out); expr_fprint(prop->visible.expr, out);
fputc('\n', out); fputc('\n', out);
} }
fputs("\n", out);
} }
if (menu->list) if (menu->list)
@ -686,7 +740,7 @@ void zconfdump(FILE *out)
} }
} }
#include "lex.zconf.c" #include "zconf.lex.c"
#include "util.c" #include "util.c"
#include "confdata.c" #include "confdata.c"
#include "expr.c" #include "expr.c"

View file

@ -3,9 +3,9 @@ grep \^CONFIG_TARGET_ .config | head -n3 > tmp/.diffconfig.head
grep '^CONFIG_ALL=y' .config >> tmp/.diffconfig.head grep '^CONFIG_ALL=y' .config >> tmp/.diffconfig.head
grep '^CONFIG_DEVEL=y' .config >> tmp/.diffconfig.head grep '^CONFIG_DEVEL=y' .config >> tmp/.diffconfig.head
grep '^CONFIG_TOOLCHAINOPTS=y' .config >> tmp/.diffconfig.head grep '^CONFIG_TOOLCHAINOPTS=y' .config >> tmp/.diffconfig.head
./scripts/config/conf -D tmp/.diffconfig.head -w tmp/.diffconfig.stage1 Config.in >/dev/null ./scripts/config/conf --defconfig=tmp/.diffconfig.head -w tmp/.diffconfig.stage1 Config.in >/dev/null
./scripts/kconfig.pl '>+' tmp/.diffconfig.stage1 .config >> tmp/.diffconfig.head ./scripts/kconfig.pl '>+' tmp/.diffconfig.stage1 .config >> tmp/.diffconfig.head
./scripts/config/conf -D tmp/.diffconfig.head -w tmp/.diffconfig.stage2 Config.in >/dev/null ./scripts/config/conf --defconfig=tmp/.diffconfig.head -w tmp/.diffconfig.stage2 Config.in >/dev/null
./scripts/kconfig.pl '>' tmp/.diffconfig.stage2 .config >> tmp/.diffconfig.head ./scripts/kconfig.pl '>' tmp/.diffconfig.stage2 .config >> tmp/.diffconfig.head
cat tmp/.diffconfig.head cat tmp/.diffconfig.head
rm -f tmp/.diffconfig tmp/.diffconfig.head rm -f tmp/.diffconfig tmp/.diffconfig.head