Review and reorganise the package layout.
Signed-off-by: "Yann E. MORIN" <yann.morin.1998@anciens.enib.fr>
*.o
*.a
+frontends/conf/conf
+frontends/mconf/mconf
+frontends/nconf/nconf
+
+parser/?conf.c
+
aclocal.m4
configure
config.h
-SUFFIXES = .gperf
-
-bin_PROGRAMS = conf nconf mconf
-
-conf_SOURCES = \
- conf.c \
- yconf.y
-
-mconf_SOURCES = \
- mconf.c \
- yconf.y
-mconf_CFLAGS = -DCURSES_LOC='"${CURSES_LOC}"'
-mconf_LDADD = lxdialog/liblxdialog.a
-
-nconf_SOURCES = \
- nconf.c \
- nconf.gui.c \
- yconf.y
-nconf_LDADD = -lmenu -lpanel
-
-yconf.o: lconf.c hconf.c
-
-.gperf.c:
- $(GPERF) -t --output-file $@ -a -C -E -g -k 1,3,$$ -p -t $<
-
-.l.c:
- $(LEX) $(LFLAGS) $(AM_LFLAGS) -o$@ $<
-
-SUBDIRS = lxdialog .
+SUBDIRS = lxdialog parser frontends
+++ /dev/null
-scripts/kconfig/lxdialog/checklist.c
-scripts/kconfig/lxdialog/inputbox.c
-scripts/kconfig/lxdialog/menubox.c
-scripts/kconfig/lxdialog/textbox.c
-scripts/kconfig/lxdialog/util.c
-scripts/kconfig/lxdialog/yesno.c
-scripts/kconfig/mconf.c
-scripts/kconfig/conf.c
-scripts/kconfig/confdata.c
-scripts/kconfig/gconf.c
-scripts/kconfig/gconf.glade.h
-scripts/kconfig/qconf.cc
+++ /dev/null
-#!/bin/sh
-# Needed for systems without gettext
-$* -xc -o /dev/null - > /dev/null 2>&1 << EOF
-#include <libintl.h>
-int main()
-{
- gettext("");
- return 0;
-}
-EOF
-if [ ! "$?" -eq "0" ]; then
- echo -DKBUILD_NO_NLS;
-fi
-
+++ /dev/null
-/*
- * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
- * Released under the terms of the GNU GPL v2.0.
- */
-
-#include <locale.h>
-#include <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include <unistd.h>
-#include <getopt.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-
-#include "lkc.h"
-
-static void conf(struct menu *menu);
-static void check_conf(struct menu *menu);
-static void xfgets(char *str, int size, FILE *in);
-
-enum input_mode {
- oldaskconfig,
- silentoldconfig,
- oldconfig,
- allnoconfig,
- allyesconfig,
- allmodconfig,
- alldefconfig,
- randconfig,
- defconfig,
- savedefconfig,
- listnewconfig,
- oldnoconfig,
-} input_mode = oldaskconfig;
-
-static int indent = 1;
-static int valid_stdin = 1;
-static int sync_kconfig;
-static int conf_cnt;
-static char line[128];
-static struct menu *rootEntry;
-
-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)
-{
- char *p = str;
- int l;
-
- while ((isspace(*p)))
- p++;
- l = strlen(p);
- if (p != str)
- memmove(str, p, l + 1);
- if (!l)
- return;
- p = str + l - 1;
- while ((isspace(*p)))
- *p-- = 0;
-}
-
-static void check_stdin(void)
-{
- if (!valid_stdin) {
- printf(_("aborted!\n\n"));
- printf(_("Console input/output is redirected. "));
- printf(_("Run 'make oldconfig' to update configuration.\n\n"));
- exit(1);
- }
-}
-
-static int conf_askvalue(struct symbol *sym, const char *def)
-{
- enum symbol_type type = sym_get_type(sym);
-
- if (!sym_has_value(sym))
- printf(_("(NEW) "));
-
- line[0] = '\n';
- line[1] = 0;
-
- if (!sym_is_changable(sym)) {
- printf("%s\n", def);
- line[0] = '\n';
- line[1] = 0;
- return 0;
- }
-
- switch (input_mode) {
- case oldconfig:
- case silentoldconfig:
- if (sym_has_value(sym)) {
- printf("%s\n", def);
- return 0;
- }
- check_stdin();
- /* fall through */
- case oldaskconfig:
- fflush(stdout);
- xfgets(line, 128, stdin);
- return 1;
- default:
- break;
- }
-
- switch (type) {
- case S_INT:
- case S_HEX:
- case S_STRING:
- printf("%s\n", def);
- return 1;
- default:
- ;
- }
- printf("%s", line);
- return 1;
-}
-
-static int conf_string(struct menu *menu)
-{
- struct symbol *sym = menu->sym;
- const char *def;
-
- while (1) {
- printf("%*s%s ", indent - 1, "", _(menu->prompt->text));
- printf("(%s) ", sym->name);
- def = sym_get_string_value(sym);
- if (sym_get_string_value(sym))
- printf("[%s] ", def);
- if (!conf_askvalue(sym, def))
- return 0;
- switch (line[0]) {
- case '\n':
- break;
- case '?':
- /* print help */
- if (line[1] == '\n') {
- print_help(menu);
- def = NULL;
- break;
- }
- /* fall through */
- default:
- line[strlen(line)-1] = 0;
- def = line;
- }
- if (def && sym_set_string_value(sym, def))
- return 0;
- }
-}
-
-static int conf_sym(struct menu *menu)
-{
- struct symbol *sym = menu->sym;
- tristate oldval, newval;
-
- while (1) {
- printf("%*s%s ", indent - 1, "", _(menu->prompt->text));
- if (sym->name)
- printf("(%s) ", sym->name);
- putchar('[');
- oldval = sym_get_tristate_value(sym);
- switch (oldval) {
- case no:
- putchar('N');
- break;
- case mod:
- putchar('M');
- break;
- case yes:
- putchar('Y');
- break;
- }
- if (oldval != no && sym_tristate_within_range(sym, no))
- printf("/n");
- if (oldval != mod && sym_tristate_within_range(sym, mod))
- printf("/m");
- if (oldval != yes && sym_tristate_within_range(sym, yes))
- printf("/y");
- if (menu_has_help(menu))
- printf("/?");
- printf("] ");
- if (!conf_askvalue(sym, sym_get_string_value(sym)))
- return 0;
- strip(line);
-
- switch (line[0]) {
- case 'n':
- case 'N':
- newval = no;
- if (!line[1] || !strcmp(&line[1], "o"))
- break;
- continue;
- case 'm':
- case 'M':
- newval = mod;
- if (!line[1])
- break;
- continue;
- case 'y':
- case 'Y':
- newval = yes;
- if (!line[1] || !strcmp(&line[1], "es"))
- break;
- continue;
- case 0:
- newval = oldval;
- break;
- case '?':
- goto help;
- default:
- continue;
- }
- if (sym_set_tristate_value(sym, newval))
- return 0;
-help:
- print_help(menu);
- }
-}
-
-static int conf_choice(struct menu *menu)
-{
- struct symbol *sym, *def_sym;
- struct menu *child;
- bool is_new;
-
- sym = menu->sym;
- is_new = !sym_has_value(sym);
- if (sym_is_changable(sym)) {
- conf_sym(menu);
- sym_calc_value(sym);
- switch (sym_get_tristate_value(sym)) {
- case no:
- return 1;
- case mod:
- return 0;
- case yes:
- break;
- }
- } else {
- switch (sym_get_tristate_value(sym)) {
- case no:
- return 1;
- case mod:
- printf("%*s%s\n", indent - 1, "", _(menu_get_prompt(menu)));
- return 0;
- case yes:
- break;
- }
- }
-
- while (1) {
- int cnt, def;
-
- printf("%*s%s\n", indent - 1, "", _(menu_get_prompt(menu)));
- def_sym = sym_get_choice_value(sym);
- cnt = def = 0;
- line[0] = 0;
- for (child = menu->list; child; child = child->next) {
- if (!menu_is_visible(child))
- continue;
- if (!child->sym) {
- printf("%*c %s\n", indent, '*', _(menu_get_prompt(child)));
- continue;
- }
- cnt++;
- if (child->sym == def_sym) {
- def = cnt;
- printf("%*c", indent, '>');
- } else
- printf("%*c", indent, ' ');
- printf(" %d. %s", cnt, _(menu_get_prompt(child)));
- if (child->sym->name)
- printf(" (%s)", child->sym->name);
- if (!sym_has_value(child->sym))
- printf(_(" (NEW)"));
- printf("\n");
- }
- printf(_("%*schoice"), indent - 1, "");
- if (cnt == 1) {
- printf("[1]: 1\n");
- goto conf_childs;
- }
- printf("[1-%d", cnt);
- if (menu_has_help(menu))
- printf("?");
- printf("]: ");
- switch (input_mode) {
- case oldconfig:
- case silentoldconfig:
- if (!is_new) {
- cnt = def;
- printf("%d\n", cnt);
- break;
- }
- check_stdin();
- /* fall through */
- case oldaskconfig:
- fflush(stdout);
- xfgets(line, 128, stdin);
- strip(line);
- if (line[0] == '?') {
- print_help(menu);
- continue;
- }
- if (!line[0])
- cnt = def;
- else if (isdigit(line[0]))
- cnt = atoi(line);
- else
- continue;
- break;
- default:
- break;
- }
-
- conf_childs:
- for (child = menu->list; child; child = child->next) {
- if (!child->sym || !menu_is_visible(child))
- continue;
- if (!--cnt)
- break;
- }
- if (!child)
- continue;
- if (line[0] && line[strlen(line) - 1] == '?') {
- print_help(child);
- continue;
- }
- sym_set_choice_value(sym, child->sym);
- for (child = child->list; child; child = child->next) {
- indent += 2;
- conf(child);
- indent -= 2;
- }
- return 1;
- }
-}
-
-static void conf(struct menu *menu)
-{
- struct symbol *sym;
- struct property *prop;
- struct menu *child;
-
- if (!menu_is_visible(menu))
- return;
-
- sym = menu->sym;
- prop = menu->prompt;
- if (prop) {
- const char *prompt;
-
- switch (prop->type) {
- case P_MENU:
- if ((input_mode == silentoldconfig ||
- input_mode == listnewconfig ||
- input_mode == oldnoconfig) &&
- rootEntry != menu) {
- check_conf(menu);
- return;
- }
- /* fall through */
- case P_COMMENT:
- prompt = menu_get_prompt(menu);
- if (prompt)
- printf("%*c\n%*c %s\n%*c\n",
- indent, '*',
- indent, '*', _(prompt),
- indent, '*');
- default:
- ;
- }
- }
-
- if (!sym)
- goto conf_childs;
-
- if (sym_is_choice(sym)) {
- conf_choice(menu);
- if (sym->curr.tri != mod)
- return;
- goto conf_childs;
- }
-
- switch (sym->type) {
- case S_INT:
- case S_HEX:
- case S_STRING:
- conf_string(menu);
- break;
- default:
- conf_sym(menu);
- break;
- }
-
-conf_childs:
- if (sym)
- indent += 2;
- for (child = menu->list; child; child = child->next)
- conf(child);
- if (sym)
- indent -= 2;
-}
-
-static void check_conf(struct menu *menu)
-{
- struct symbol *sym;
- struct menu *child;
-
- if (!menu_is_visible(menu))
- return;
-
- sym = menu->sym;
- if (sym && !sym_has_value(sym)) {
- if (sym_is_changable(sym) ||
- (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)) {
- if (input_mode == listnewconfig) {
- if (sym->name && !sym_is_choice_value(sym)) {
- printf("%s%s\n", CONFIG_, sym->name);
- }
- } else if (input_mode != oldnoconfig) {
- if (!conf_cnt++)
- printf(_("*\n* Restart config...\n*\n"));
- rootEntry = menu_get_parent_menu(menu);
- conf(rootEntry);
- }
- }
- }
-
- for (child = menu->list; child; child = child->next)
- 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},
- {"oldnoconfig", no_argument, NULL, oldnoconfig},
- {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(" --oldnoconfig Same as silentoldconfig but set new symbols to no\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)
-{
- const char *progname = av[0];
- int opt;
- const char *name, *defconfig_file = NULL /* gcc uninit */;
- struct stat tmpstat;
-
- setlocale(LC_ALL, "");
- bindtextdomain(PACKAGE, LOCALEDIR);
- textdomain(PACKAGE);
-
- while ((opt = getopt_long(ac, av, "", long_opts, NULL)) != -1) {
- input_mode = (enum input_mode)opt;
- switch (opt) {
- case silentoldconfig:
- sync_kconfig = 1;
- break;
- case defconfig:
- case savedefconfig:
- defconfig_file = optarg;
- break;
- case randconfig:
- {
- 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;
- }
- case oldaskconfig:
- case oldconfig:
- case allnoconfig:
- case allyesconfig:
- case allmodconfig:
- case alldefconfig:
- case listnewconfig:
- case oldnoconfig:
- break;
- case '?':
- conf_usage(progname);
- exit(1);
- break;
- }
- }
- if (ac == optind) {
- printf(_("%s: Kconfig file missing\n"), av[0]);
- conf_usage(progname);
- exit(1);
- }
- name = av[optind];
- conf_parse(name);
- //zconfdump(stdout);
- if (sync_kconfig) {
- name = conf_get_configname();
- if (stat(name, &tmpstat)) {
- fprintf(stderr, _("***\n"
- "*** Configuration file \"%s\" not found!\n"
- "***\n"
- "*** Please run some configurator (e.g. \"make oldconfig\" or\n"
- "*** \"make menuconfig\" or \"make xconfig\").\n"
- "***\n"), name);
- exit(1);
- }
- }
-
- switch (input_mode) {
- case defconfig:
- if (!defconfig_file)
- defconfig_file = conf_get_default_confname();
- 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 oldnoconfig:
- conf_read(NULL);
- break;
- case allnoconfig:
- case allyesconfig:
- case allmodconfig:
- case alldefconfig:
- case randconfig:
- name = getenv("KCONFIG_ALLCONFIG");
- if (name && !stat(name, &tmpstat)) {
- conf_read_simple(name, S_DEF_USER);
- break;
- }
- switch (input_mode) {
- case allnoconfig: name = "allno.config"; break;
- case allyesconfig: name = "allyes.config"; break;
- case allmodconfig: name = "allmod.config"; break;
- case alldefconfig: name = "alldef.config"; break;
- case randconfig: name = "allrandom.config"; break;
- default: break;
- }
- if (!stat(name, &tmpstat))
- conf_read_simple(name, S_DEF_USER);
- else if (!stat("all.config", &tmpstat))
- conf_read_simple("all.config", S_DEF_USER);
- break;
- default:
- break;
- }
-
- 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 = isatty(0) && isatty(1) && isatty(2);
- }
-
- 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;
- conf(&rootmenu);
- input_mode = silentoldconfig;
- /* fall through */
- case oldconfig:
- case listnewconfig:
- case oldnoconfig:
- 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 != oldnoconfig));
- break;
- }
-
- if (sync_kconfig) {
- /* silentoldconfig is used during the build so we shall update autoconf.
- * All other commands are only used to generate a config.
- */
- if (conf_get_changed() && conf_write(NULL)) {
- 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(NULL)) {
- fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n"));
- exit(1);
- }
- }
- 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");
-}
+++ /dev/null
-/*
- * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
- * Released under the terms of the GNU GPL v2.0.
- */
-
-#include <sys/stat.h>
-#include <ctype.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include <unistd.h>
-
-#include "lkc.h"
-
-static void conf_warning(const char *fmt, ...)
- __attribute__ ((format (printf, 1, 2)));
-
-static void conf_message(const char *fmt, ...)
- __attribute__ ((format (printf, 1, 2)));
-
-static const char *conf_filename;
-static int conf_lineno, conf_warnings, conf_unsaved;
-
-const char conf_defname[] = "arch/$ARCH/defconfig";
-
-static void conf_warning(const char *fmt, ...)
-{
- va_list ap;
- va_start(ap, fmt);
- fprintf(stderr, "%s:%d:warning: ", conf_filename, conf_lineno);
- vfprintf(stderr, fmt, ap);
- fprintf(stderr, "\n");
- va_end(ap);
- conf_warnings++;
-}
-
-static void conf_default_message_callback(const char *fmt, va_list ap)
-{
- printf("#\n# ");
- vprintf(fmt, ap);
- printf("\n#\n");
-}
-
-static void (*conf_message_callback) (const char *fmt, va_list ap) =
- conf_default_message_callback;
-void conf_set_message_callback(void (*fn) (const char *fmt, va_list ap))
-{
- conf_message_callback = fn;
-}
-
-static void conf_message(const char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- if (conf_message_callback)
- conf_message_callback(fmt, ap);
-}
-
-const char *conf_get_configname(void)
-{
- char *name = getenv("KCONFIG_CONFIG");
-
- return name ? name : ".config";
-}
-
-const char *conf_get_autoconfig_name(void)
-{
- char *name = getenv("KCONFIG_AUTOCONFIG");
-
- return name ? name : "include/config/auto.conf";
-}
-
-static char *conf_expand_value(const char *in)
-{
- struct symbol *sym;
- const char *src;
- static char res_value[SYMBOL_MAXLENGTH];
- char *dst, name[SYMBOL_MAXLENGTH];
-
- res_value[0] = 0;
- dst = name;
- while ((src = strchr(in, '$'))) {
- strncat(res_value, in, src - in);
- src++;
- dst = name;
- while (isalnum(*src) || *src == '_')
- *dst++ = *src++;
- *dst = 0;
- sym = sym_lookup(name, 0);
- sym_calc_value(sym);
- strcat(res_value, sym_get_string_value(sym));
- in = src;
- }
- strcat(res_value, in);
-
- return res_value;
-}
-
-char *conf_get_default_confname(void)
-{
- struct stat buf;
- static char fullname[PATH_MAX+1];
- char *env, *name;
-
- name = conf_expand_value(conf_defname);
- env = getenv(SRCTREE);
- if (env) {
- sprintf(fullname, "%s/%s", env, name);
- if (!stat(fullname, &buf))
- return fullname;
- }
- return name;
-}
-
-static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
-{
- char *p2;
-
- switch (sym->type) {
- case S_TRISTATE:
- if (p[0] == 'm') {
- sym->def[def].tri = mod;
- sym->flags |= def_flags;
- break;
- }
- /* fall through */
- case S_BOOLEAN:
- if (p[0] == 'y') {
- sym->def[def].tri = yes;
- sym->flags |= def_flags;
- break;
- }
- if (p[0] == 'n') {
- sym->def[def].tri = no;
- sym->flags |= def_flags;
- break;
- }
- conf_warning("symbol value '%s' invalid for %s", p, sym->name);
- return 1;
- case S_OTHER:
- if (*p != '"') {
- for (p2 = p; *p2 && !isspace(*p2); p2++)
- ;
- sym->type = S_STRING;
- goto done;
- }
- /* fall through */
- case S_STRING:
- if (*p++ != '"')
- break;
- for (p2 = p; (p2 = strpbrk(p2, "\"\\")); p2++) {
- if (*p2 == '"') {
- *p2 = 0;
- break;
- }
- memmove(p2, p2 + 1, strlen(p2));
- }
- if (!p2) {
- conf_warning("invalid string found");
- return 1;
- }
- /* fall through */
- case S_INT:
- case S_HEX:
- done:
- if (sym_string_valid(sym, p)) {
- sym->def[def].val = strdup(p);
- sym->flags |= def_flags;
- } else {
- conf_warning("symbol value '%s' invalid for %s", p, sym->name);
- return 1;
- }
- break;
- default:
- ;
- }
- return 0;
-}
-
-int conf_read_simple(const char *name, int def)
-{
- FILE *in = NULL;
- char line[1024];
- char *p, *p2;
- struct symbol *sym;
- int i, def_flags;
-
- if (name) {
- in = zconf_fopen(name);
- } else {
- struct property *prop;
-
- name = conf_get_configname();
- in = zconf_fopen(name);
- if (in)
- goto load;
- sym_add_change_count(1);
- if (!sym_defconfig_list) {
- if (modules_sym)
- sym_calc_value(modules_sym);
- return 1;
- }
-
- for_all_defaults(sym_defconfig_list, prop) {
- if (expr_calc_value(prop->visible.expr) == no ||
- prop->expr->type != E_SYMBOL)
- continue;
- name = conf_expand_value(prop->expr->left.sym->name);
- in = zconf_fopen(name);
- if (in) {
- conf_message(_("using defaults found in %s"),
- name);
- goto load;
- }
- }
- }
- if (!in)
- return 1;
-
-load:
- conf_filename = name;
- conf_lineno = 0;
- conf_warnings = 0;
- conf_unsaved = 0;
-
- def_flags = SYMBOL_DEF << def;
- for_all_symbols(i, sym) {
- sym->flags |= SYMBOL_CHANGED;
- sym->flags &= ~(def_flags|SYMBOL_VALID);
- if (sym_is_choice(sym))
- sym->flags |= def_flags;
- switch (sym->type) {
- case S_INT:
- case S_HEX:
- case S_STRING:
- if (sym->def[def].val)
- free(sym->def[def].val);
- /* fall through */
- default:
- sym->def[def].val = NULL;
- sym->def[def].tri = no;
- }
- }
-
- while (fgets(line, sizeof(line), in)) {
- conf_lineno++;
- sym = NULL;
- if (line[0] == '#') {
- if (memcmp(line + 2, CONFIG_, strlen(CONFIG_)))
- continue;
- p = strchr(line + 2 + strlen(CONFIG_), ' ');
- if (!p)
- continue;
- *p++ = 0;
- if (strncmp(p, "is not set", 10))
- continue;
- if (def == S_DEF_USER) {
- sym = sym_find(line + 2 + strlen(CONFIG_));
- if (!sym) {
- sym_add_change_count(1);
- goto setsym;
- }
- } else {
- sym = sym_lookup(line + 2 + strlen(CONFIG_), 0);
- if (sym->type == S_UNKNOWN)
- sym->type = S_BOOLEAN;
- }
- if (sym->flags & def_flags) {
- conf_warning("override: reassigning to symbol %s", sym->name);
- }
- switch (sym->type) {
- case S_BOOLEAN:
- case S_TRISTATE:
- sym->def[def].tri = no;
- sym->flags |= def_flags;
- break;
- default:
- ;
- }
- } else if (memcmp(line, CONFIG_, strlen(CONFIG_)) == 0) {
- p = strchr(line + strlen(CONFIG_), '=');
- if (!p)
- continue;
- *p++ = 0;
- p2 = strchr(p, '\n');
- if (p2) {
- *p2-- = 0;
- if (*p2 == '\r')
- *p2 = 0;
- }
- if (def == S_DEF_USER) {
- sym = sym_find(line + strlen(CONFIG_));
- if (!sym) {
- sym_add_change_count(1);
- goto setsym;
- }
- } else {
- sym = sym_lookup(line + strlen(CONFIG_), 0);
- if (sym->type == S_UNKNOWN)
- sym->type = S_OTHER;
- }
- if (sym->flags & def_flags) {
- conf_warning("override: reassigning to symbol %s", sym->name);
- }
- if (conf_set_sym_val(sym, def, def_flags, p))
- continue;
- } else {
- if (line[0] != '\r' && line[0] != '\n')
- conf_warning("unexpected data");
- continue;
- }
-setsym:
- if (sym && sym_is_choice_value(sym)) {
- struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
- switch (sym->def[def].tri) {
- case no:
- break;
- case mod:
- if (cs->def[def].tri == yes) {
- conf_warning("%s creates inconsistent choice state", sym->name);
- cs->flags &= ~def_flags;
- }
- break;
- case yes:
- if (cs->def[def].tri != no)
- conf_warning("override: %s changes choice state", sym->name);
- cs->def[def].val = sym;
- break;
- }
- cs->def[def].tri = EXPR_OR(cs->def[def].tri, sym->def[def].tri);
- }
- }
- fclose(in);
-
- if (modules_sym)
- sym_calc_value(modules_sym);
- return 0;
-}
-
-int conf_read(const char *name)
-{
- struct symbol *sym, *choice_sym;
- struct property *prop;
- struct expr *e;
- int i, flags;
-
- sym_set_change_count(0);
-
- if (conf_read_simple(name, S_DEF_USER))
- return 1;
-
- for_all_symbols(i, sym) {
- sym_calc_value(sym);
- if (sym_is_choice(sym) || (sym->flags & SYMBOL_AUTO))
- goto sym_ok;
- if (sym_has_value(sym) && (sym->flags & SYMBOL_WRITE)) {
- /* check that calculated value agrees with saved value */
- switch (sym->type) {
- case S_BOOLEAN:
- case S_TRISTATE:
- if (sym->def[S_DEF_USER].tri != sym_get_tristate_value(sym))
- break;
- if (!sym_is_choice(sym))
- goto sym_ok;
- /* fall through */
- default:
- if (!strcmp(sym->curr.val, sym->def[S_DEF_USER].val))
- goto sym_ok;
- break;
- }
- } else if (!sym_has_value(sym) && !(sym->flags & SYMBOL_WRITE))
- /* no previous value and not saved */
- goto sym_ok;
- conf_unsaved++;
- /* maybe print value in verbose mode... */
- sym_ok:
- if (!sym_is_choice(sym))
- continue;
- /* The choice symbol only has a set value (and thus is not new)
- * if all its visible childs have values.
- */
- prop = sym_get_choice_prop(sym);
- flags = sym->flags;
- expr_list_for_each_sym(prop->expr, e, choice_sym)
- if (choice_sym->visible != no)
- flags &= choice_sym->flags;
- sym->flags &= flags | ~SYMBOL_DEF_USER;
- }
-
- for_all_symbols(i, sym) {
- if (sym_has_value(sym) && !sym_is_choice_value(sym)) {
- /* Reset values of generates values, so they'll appear
- * as new, if they should become visible, but that
- * doesn't quite work if the Kconfig and the saved
- * configuration disagree.
- */
- if (sym->visible == no && !conf_unsaved)
- sym->flags &= ~SYMBOL_DEF_USER;
- switch (sym->type) {
- case S_STRING:
- case S_INT:
- case S_HEX:
- /* Reset a string value if it's out of range */
- if (sym_string_within_range(sym, sym->def[S_DEF_USER].val))
- break;
- sym->flags &= ~(SYMBOL_VALID|SYMBOL_DEF_USER);
- conf_unsaved++;
- break;
- default:
- break;
- }
- }
- }
-
- sym_add_change_count(conf_warnings || conf_unsaved);
-
- return 0;
-}
-
-/*
- * Kconfig configuration printer
- *
- * This printer is used when generating the resulting configuration after
- * kconfig invocation and `defconfig' files. Unset symbol might be omitted by
- * passing a non-NULL argument to the printer.
- *
- */
-static void
-kconfig_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg)
-{
-
- switch (sym->type) {
- case S_BOOLEAN:
- case S_TRISTATE:
- if (*value == 'n') {
- bool skip_unset = (arg != NULL);
-
- if (!skip_unset)
- fprintf(fp, "# %s%s is not set\n",
- CONFIG_, sym->name);
- return;
- }
- break;
- default:
- break;
- }
-
- fprintf(fp, "%s%s=%s\n", CONFIG_, sym->name, value);
-}
-
-static void
-kconfig_print_comment(FILE *fp, const char *value, void *arg)
-{
- const char *p = value;
- size_t l;
-
- for (;;) {
- l = strcspn(p, "\n");
- fprintf(fp, "#");
- if (l) {
- fprintf(fp, " ");
- xfwrite(p, l, 1, fp);
- p += l;
- }
- fprintf(fp, "\n");
- if (*p++ == '\0')
- break;
- }
-}
-
-static struct conf_printer kconfig_printer_cb =
-{
- .print_symbol = kconfig_print_symbol,
- .print_comment = kconfig_print_comment,
-};
-
-/*
- * Header printer
- *
- * This printer is used when generating the `include/generated/autoconf.h' file.
- */
-static void
-header_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg)
-{
-
- switch (sym->type) {
- case S_BOOLEAN:
- case S_TRISTATE: {
- const char *suffix = "";
-
- switch (*value) {
- case 'n':
- break;
- case 'm':
- suffix = "_MODULE";
- /* fall through */
- default:
- fprintf(fp, "#define %s%s%s 1\n",
- CONFIG_, sym->name, suffix);
- }
- break;
- }
- case S_HEX: {
- const char *prefix = "";
-
- if (value[0] != '0' || (value[1] != 'x' && value[1] != 'X'))
- prefix = "0x";
- fprintf(fp, "#define %s%s %s%s\n",
- CONFIG_, sym->name, prefix, value);
- break;
- }
- case S_STRING:
- case S_INT:
- fprintf(fp, "#define %s%s %s\n",
- CONFIG_, sym->name, value);
- break;
- default:
- break;
- }
-
-}
-
-static void
-header_print_comment(FILE *fp, const char *value, void *arg)
-{
- const char *p = value;
- size_t l;
-
- fprintf(fp, "/*\n");
- for (;;) {
- l = strcspn(p, "\n");
- fprintf(fp, " *");
- if (l) {
- fprintf(fp, " ");
- xfwrite(p, l, 1, fp);
- p += l;
- }
- fprintf(fp, "\n");
- if (*p++ == '\0')
- break;
- }
- fprintf(fp, " */\n");
-}
-
-static struct conf_printer header_printer_cb =
-{
- .print_symbol = header_print_symbol,
- .print_comment = header_print_comment,
-};
-
-/*
- * Generate the __enabled_CONFIG_* and __enabled_CONFIG_*_MODULE macros for
- * use by the IS_{ENABLED,BUILTIN,MODULE} macros. The _MODULE variant is
- * generated even for booleans so that the IS_ENABLED() macro works.
- */
-static void
-header_print__enabled_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg)
-{
-
- switch (sym->type) {
- case S_BOOLEAN:
- case S_TRISTATE: {
- fprintf(fp, "#define __enabled_" CONFIG_ "%s %d\n",
- sym->name, (*value == 'y'));
- fprintf(fp, "#define __enabled_" CONFIG_ "%s_MODULE %d\n",
- sym->name, (*value == 'm'));
- break;
- }
- default:
- break;
- }
-}
-
-static struct conf_printer header__enabled_printer_cb =
-{
- .print_symbol = header_print__enabled_symbol,
- .print_comment = header_print_comment,
-};
-
-/*
- * Tristate printer
- *
- * This printer is used when generating the `include/config/tristate.conf' file.
- */
-static void
-tristate_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg)
-{
-
- if (sym->type == S_TRISTATE && *value != 'n')
- fprintf(fp, "%s%s=%c\n", CONFIG_, sym->name, (char)toupper(*value));
-}
-
-static struct conf_printer tristate_printer_cb =
-{
- .print_symbol = tristate_print_symbol,
- .print_comment = kconfig_print_comment,
-};
-
-static void conf_write_symbol(FILE *fp, struct symbol *sym,
- struct conf_printer *printer, void *printer_arg)
-{
- const char *str;
-
- switch (sym->type) {
- case S_OTHER:
- case S_UNKNOWN:
- break;
- case S_STRING:
- str = sym_get_string_value(sym);
- str = sym_escape_string_value(str);
- printer->print_symbol(fp, sym, str, printer_arg);
- free((void *)str);
- break;
- default:
- str = sym_get_string_value(sym);
- printer->print_symbol(fp, sym, str, printer_arg);
- }
-}
-
-static void
-conf_write_heading(FILE *fp, struct conf_printer *printer, void *printer_arg)
-{
- char buf[256];
-
- snprintf(buf, sizeof(buf),
- "\n"
- "Automatically generated file; DO NOT EDIT.\n"
- "%s\n",
- rootmenu.prompt->text);
-
- printer->print_comment(fp, buf, printer_arg);
-}
-
-/*
- * Write out a minimal config.
- * All values that has default values are skipped as this is redundant.
- */
-int conf_write_defconfig(const char *filename)
-{
- struct symbol *sym;
- struct menu *menu;
- FILE *out;
-
- out = fopen(filename, "w");
- if (!out)
- return 1;
-
- sym_clear_all_valid();
-
- /* Traverse all menus to find all relevant symbols */
- menu = rootmenu.list;
-
- while (menu != NULL)
- {
- sym = menu->sym;
- if (sym == NULL) {
- if (!menu_is_visible(menu))
- goto next_menu;
- } else if (!sym_is_choice(sym)) {
- sym_calc_value(sym);
- if (!(sym->flags & SYMBOL_WRITE))
- goto next_menu;
- sym->flags &= ~SYMBOL_WRITE;
- /* If we cannot change the symbol - skip */
- if (!sym_is_changable(sym))
- goto next_menu;
- /* If symbol equals to default value - skip */
- if (strcmp(sym_get_string_value(sym), sym_get_string_default(sym)) == 0)
- goto next_menu;
-
- /*
- * If symbol is a choice value and equals to the
- * default for a choice - skip.
- * But only if value is bool and equal to "y" and
- * choice is not "optional".
- * (If choice is "optional" then all values can be "n")
- */
- if (sym_is_choice_value(sym)) {
- struct symbol *cs;
- struct symbol *ds;
-
- cs = prop_get_symbol(sym_get_choice_prop(sym));
- ds = sym_choice_default(cs);
- if (!sym_is_optional(cs) && sym == ds) {
- if ((sym->type == S_BOOLEAN) &&
- sym_get_tristate_value(sym) == yes)
- goto next_menu;
- }
- }
- conf_write_symbol(out, sym, &kconfig_printer_cb, NULL);
- }
-next_menu:
- if (menu->list != NULL) {
- menu = menu->list;
- }
- else if (menu->next != NULL) {
- menu = menu->next;
- } else {
- while ((menu = menu->parent)) {
- if (menu->next != NULL) {
- menu = menu->next;
- break;
- }
- }
- }
- }
- fclose(out);
- return 0;
-}
-
-int conf_write(const char *name)
-{
- FILE *out;
- struct symbol *sym;
- struct menu *menu;
- const char *basename;
- const char *str;
- char dirname[PATH_MAX+1], tmpname[PATH_MAX+1], newname[PATH_MAX+1];
- char *env;
-
- dirname[0] = 0;
- if (name && name[0]) {
- struct stat st;
- char *slash;
-
- if (!stat(name, &st) && S_ISDIR(st.st_mode)) {
- strcpy(dirname, name);
- strcat(dirname, "/");
- basename = conf_get_configname();
- } else if ((slash = strrchr(name, '/'))) {
- int size = slash - name + 1;
- memcpy(dirname, name, size);
- dirname[size] = 0;
- if (slash[1])
- basename = slash + 1;
- else
- basename = conf_get_configname();
- } else
- basename = name;
- } else
- basename = conf_get_configname();
-
- sprintf(newname, "%s%s", dirname, basename);
- env = getenv("KCONFIG_OVERWRITECONFIG");
- if (!env || !*env) {
- sprintf(tmpname, "%s.tmpconfig.%d", dirname, (int)getpid());
- out = fopen(tmpname, "w");
- } else {
- *tmpname = 0;
- out = fopen(newname, "w");
- }
- if (!out)
- return 1;
-
- conf_write_heading(out, &kconfig_printer_cb, NULL);
-
- if (!conf_get_changed())
- sym_clear_all_valid();
-
- menu = rootmenu.list;
- while (menu) {
- sym = menu->sym;
- if (!sym) {
- if (!menu_is_visible(menu))
- goto next;
- str = menu_get_prompt(menu);
- fprintf(out, "\n"
- "#\n"
- "# %s\n"
- "#\n", str);
- } else if (!(sym->flags & SYMBOL_CHOICE)) {
- sym_calc_value(sym);
- if (!(sym->flags & SYMBOL_WRITE))
- goto next;
- sym->flags &= ~SYMBOL_WRITE;
-
- conf_write_symbol(out, sym, &kconfig_printer_cb, NULL);
- }
-
-next:
- if (menu->list) {
- menu = menu->list;
- continue;
- }
- if (menu->next)
- menu = menu->next;
- else while ((menu = menu->parent)) {
- if (menu->next) {
- menu = menu->next;
- break;
- }
- }
- }
- fclose(out);
-
- if (*tmpname) {
- strcat(dirname, basename);
- strcat(dirname, ".old");
- rename(newname, dirname);
- if (rename(tmpname, newname))
- return 1;
- }
-
- conf_message(_("configuration written to %s"), newname);
-
- sym_set_change_count(0);
-
- return 0;
-}
-
-static int conf_split_config(void)
-{
- const char *name;
- char path[PATH_MAX+1];
- char *s, *d, c;
- struct symbol *sym;
- struct stat sb;
- int res, i, fd;
-
- name = conf_get_autoconfig_name();
- conf_read_simple(name, S_DEF_AUTO);
-
- if (chdir("include/config"))
- return 1;
-
- res = 0;
- for_all_symbols(i, sym) {
- sym_calc_value(sym);
- if ((sym->flags & SYMBOL_AUTO) || !sym->name)
- continue;
- if (sym->flags & SYMBOL_WRITE) {
- if (sym->flags & SYMBOL_DEF_AUTO) {
- /*
- * symbol has old and new value,
- * so compare them...
- */
- switch (sym->type) {
- case S_BOOLEAN:
- case S_TRISTATE:
- if (sym_get_tristate_value(sym) ==
- sym->def[S_DEF_AUTO].tri)
- continue;
- break;
- case S_STRING:
- case S_HEX:
- case S_INT:
- if (!strcmp(sym_get_string_value(sym),
- sym->def[S_DEF_AUTO].val))
- continue;
- break;
- default:
- break;
- }
- } else {
- /*
- * If there is no old value, only 'no' (unset)
- * is allowed as new value.
- */
- switch (sym->type) {
- case S_BOOLEAN:
- case S_TRISTATE:
- if (sym_get_tristate_value(sym) == no)
- continue;
- break;
- default:
- break;
- }
- }
- } else if (!(sym->flags & SYMBOL_DEF_AUTO))
- /* There is neither an old nor a new value. */
- continue;
- /* else
- * There is an old value, but no new value ('no' (unset)
- * isn't saved in auto.conf, so the old value is always
- * different from 'no').
- */
-
- /* Replace all '_' and append ".h" */
- s = sym->name;
- d = path;
- while ((c = *s++)) {
- c = tolower(c);
- *d++ = (c == '_') ? '/' : c;
- }
- strcpy(d, ".h");
-
- /* Assume directory path already exists. */
- fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
- if (fd == -1) {
- if (errno != ENOENT) {
- res = 1;
- break;
- }
- /*
- * Create directory components,
- * unless they exist already.
- */
- d = path;
- while ((d = strchr(d, '/'))) {
- *d = 0;
- if (stat(path, &sb) && mkdir(path, 0755)) {
- res = 1;
- goto out;
- }
- *d++ = '/';
- }
- /* Try it again. */
- fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
- if (fd == -1) {
- res = 1;
- break;
- }
- }
- close(fd);
- }
-out:
- if (chdir("../.."))
- return 1;
-
- return res;
-}
-
-int conf_write_autoconf(void)
-{
- struct symbol *sym;
- const char *name;
- FILE *out, *tristate, *out_h;
- int i;
-
- sym_clear_all_valid();
-
- file_write_dep("include/config/auto.conf.cmd");
-
- if (conf_split_config())
- return 1;
-
- out = fopen(".tmpconfig", "w");
- if (!out)
- return 1;
-
- tristate = fopen(".tmpconfig_tristate", "w");
- if (!tristate) {
- fclose(out);
- return 1;
- }
-
- out_h = fopen(".tmpconfig.h", "w");
- if (!out_h) {
- fclose(out);
- fclose(tristate);
- return 1;
- }
-
- conf_write_heading(out, &kconfig_printer_cb, NULL);
-
- conf_write_heading(tristate, &tristate_printer_cb, NULL);
-
- conf_write_heading(out_h, &header_printer_cb, NULL);
-
- for_all_symbols(i, sym) {
- if (!sym->name)
- continue;
-
- sym_calc_value(sym);
-
- conf_write_symbol(out_h, sym, &header__enabled_printer_cb, NULL);
-
- if (!(sym->flags & SYMBOL_WRITE))
- continue;
-
- conf_write_symbol(out, sym, &kconfig_printer_cb, (void *)1);
-
- conf_write_symbol(tristate, sym, &tristate_printer_cb, (void *)1);
-
- conf_write_symbol(out_h, sym, &header_printer_cb, NULL);
- }
- fclose(out);
- fclose(tristate);
- fclose(out_h);
-
- name = getenv("KCONFIG_AUTOHEADER");
- if (!name)
- name = "include/generated/autoconf.h";
- if (rename(".tmpconfig.h", name))
- return 1;
- name = getenv("KCONFIG_TRISTATE");
- if (!name)
- name = "include/config/tristate.conf";
- if (rename(".tmpconfig_tristate", name))
- return 1;
- name = conf_get_autoconfig_name();
- /*
- * This must be the last step, kbuild has a dependency on auto.conf
- * and this marks the successful completion of the previous steps.
- */
- if (rename(".tmpconfig", name))
- return 1;
-
- return 0;
-}
-
-static int sym_change_count;
-static void (*conf_changed_callback)(void);
-
-void sym_set_change_count(int count)
-{
- int _sym_change_count = sym_change_count;
- sym_change_count = count;
- if (conf_changed_callback &&
- (bool)_sym_change_count != (bool)count)
- conf_changed_callback();
-}
-
-void sym_add_change_count(int count)
-{
- sym_set_change_count(count + sym_change_count);
-}
-
-bool conf_get_changed(void)
-{
- return sym_change_count;
-}
-
-void conf_set_changed_callback(void (*fn)(void))
-{
- conf_changed_callback = fn;
-}
-
-static void randomize_choice_values(struct symbol *csym)
-{
- struct property *prop;
- struct symbol *sym;
- struct expr *e;
- int cnt, def;
-
- /*
- * If choice is mod then we may have more items selected
- * and if no then no-one.
- * In both cases stop.
- */
- if (csym->curr.tri != yes)
- return;
-
- prop = sym_get_choice_prop(csym);
-
- /* count entries in choice block */
- cnt = 0;
- expr_list_for_each_sym(prop->expr, e, sym)
- cnt++;
-
- /*
- * find a random value and set it to yes,
- * set the rest to no so we have only one set
- */
- def = (rand() % cnt);
-
- cnt = 0;
- expr_list_for_each_sym(prop->expr, e, sym) {
- if (def == cnt++) {
- sym->def[S_DEF_USER].tri = yes;
- csym->def[S_DEF_USER].val = sym;
- }
- else {
- sym->def[S_DEF_USER].tri = no;
- }
- }
- csym->flags |= SYMBOL_DEF_USER;
- /* clear VALID to get value calculated */
- csym->flags &= ~(SYMBOL_VALID);
-}
-
-static void set_all_choice_values(struct symbol *csym)
-{
- struct property *prop;
- struct symbol *sym;
- struct expr *e;
-
- prop = sym_get_choice_prop(csym);
-
- /*
- * Set all non-assinged choice values to no
- */
- expr_list_for_each_sym(prop->expr, e, sym) {
- if (!sym_has_value(sym))
- sym->def[S_DEF_USER].tri = no;
- }
- csym->flags |= SYMBOL_DEF_USER;
- /* clear VALID to get value calculated */
- csym->flags &= ~(SYMBOL_VALID);
-}
-
-void conf_set_all_new_symbols(enum conf_def_mode mode)
-{
- struct symbol *sym, *csym;
- int i, cnt;
-
- for_all_symbols(i, sym) {
- if (sym_has_value(sym))
- continue;
- switch (sym_get_type(sym)) {
- case S_BOOLEAN:
- case S_TRISTATE:
- switch (mode) {
- case def_yes:
- sym->def[S_DEF_USER].tri = yes;
- break;
- case def_mod:
- sym->def[S_DEF_USER].tri = mod;
- break;
- case def_no:
- sym->def[S_DEF_USER].tri = no;
- break;
- case def_random:
- cnt = sym_get_type(sym) == S_TRISTATE ? 3 : 2;
- sym->def[S_DEF_USER].tri = (tristate)(rand() % cnt);
- break;
- default:
- continue;
- }
- if (!(sym_is_choice(sym) && mode == def_random))
- sym->flags |= SYMBOL_DEF_USER;
- break;
- default:
- break;
- }
-
- }
-
- sym_clear_all_valid();
-
- /*
- * We have different type of choice blocks.
- * If curr.tri equals to mod then we can select several
- * choice symbols in one block.
- * In this case we do nothing.
- * If curr.tri equals yes then only one symbol can be
- * selected in a choice block and we set it to yes,
- * and the rest to no.
- */
- for_all_symbols(i, csym) {
- if (sym_has_value(csym) || !sym_is_choice(csym))
- continue;
-
- sym_calc_value(csym);
- if (mode == def_random)
- randomize_choice_values(csym);
- else
- set_all_choice_values(csym);
- }
-}
AC_PREREQ([2.67])
AC_INIT([kconfig-frontends], [m4_esyscmd_s([cat .version])], [nobody@nowhere.org])
-AC_CONFIG_SRCDIR([menu.c])
+AC_CONFIG_SRCDIR([frontends/conf/conf.c])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_AUX_DIR([scripts])
AC_CONFIG_FILES([
Makefile
lxdialog/Makefile
+ parser/Makefile
+ frontends/Makefile
+ frontends/conf/Makefile
+ frontends/mconf/Makefile
+ frontends/nconf/Makefile
])
AC_OUTPUT
+++ /dev/null
-/*
- * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
- * Released under the terms of the GNU GPL v2.0.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "lkc.h"
-
-#define DEBUG_EXPR 0
-
-struct expr *expr_alloc_symbol(struct symbol *sym)
-{
- struct expr *e = calloc(1, sizeof(*e));
- e->type = E_SYMBOL;
- e->left.sym = sym;
- return e;
-}
-
-struct expr *expr_alloc_one(enum expr_type type, struct expr *ce)
-{
- struct expr *e = calloc(1, sizeof(*e));
- e->type = type;
- e->left.expr = ce;
- return e;
-}
-
-struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e2)
-{
- struct expr *e = calloc(1, sizeof(*e));
- e->type = type;
- e->left.expr = e1;
- e->right.expr = e2;
- return e;
-}
-
-struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2)
-{
- struct expr *e = calloc(1, sizeof(*e));
- e->type = type;
- e->left.sym = s1;
- e->right.sym = s2;
- return e;
-}
-
-struct expr *expr_alloc_and(struct expr *e1, struct expr *e2)
-{
- if (!e1)
- return e2;
- return e2 ? expr_alloc_two(E_AND, e1, e2) : e1;
-}
-
-struct expr *expr_alloc_or(struct expr *e1, struct expr *e2)
-{
- if (!e1)
- return e2;
- return e2 ? expr_alloc_two(E_OR, e1, e2) : e1;
-}
-
-struct expr *expr_copy(const struct expr *org)
-{
- struct expr *e;
-
- if (!org)
- return NULL;
-
- e = malloc(sizeof(*org));
- memcpy(e, org, sizeof(*org));
- switch (org->type) {
- case E_SYMBOL:
- e->left = org->left;
- break;
- case E_NOT:
- e->left.expr = expr_copy(org->left.expr);
- break;
- case E_EQUAL:
- case E_UNEQUAL:
- e->left.sym = org->left.sym;
- e->right.sym = org->right.sym;
- break;
- case E_AND:
- case E_OR:
- case E_LIST:
- e->left.expr = expr_copy(org->left.expr);
- e->right.expr = expr_copy(org->right.expr);
- break;
- default:
- printf("can't copy type %d\n", e->type);
- free(e);
- e = NULL;
- break;
- }
-
- return e;
-}
-
-void expr_free(struct expr *e)
-{
- if (!e)
- return;
-
- switch (e->type) {
- case E_SYMBOL:
- break;
- case E_NOT:
- expr_free(e->left.expr);
- return;
- case E_EQUAL:
- case E_UNEQUAL:
- break;
- case E_OR:
- case E_AND:
- expr_free(e->left.expr);
- expr_free(e->right.expr);
- break;
- default:
- printf("how to free type %d?\n", e->type);
- break;
- }
- free(e);
-}
-
-static int trans_count;
-
-#define e1 (*ep1)
-#define e2 (*ep2)
-
-static void __expr_eliminate_eq(enum expr_type type, struct expr **ep1, struct expr **ep2)
-{
- if (e1->type == type) {
- __expr_eliminate_eq(type, &e1->left.expr, &e2);
- __expr_eliminate_eq(type, &e1->right.expr, &e2);
- return;
- }
- if (e2->type == type) {
- __expr_eliminate_eq(type, &e1, &e2->left.expr);
- __expr_eliminate_eq(type, &e1, &e2->right.expr);
- return;
- }
- if (e1->type == E_SYMBOL && e2->type == E_SYMBOL &&
- e1->left.sym == e2->left.sym &&
- (e1->left.sym == &symbol_yes || e1->left.sym == &symbol_no))
- return;
- if (!expr_eq(e1, e2))
- return;
- trans_count++;
- expr_free(e1); expr_free(e2);
- switch (type) {
- case E_OR:
- e1 = expr_alloc_symbol(&symbol_no);
- e2 = expr_alloc_symbol(&symbol_no);
- break;
- case E_AND:
- e1 = expr_alloc_symbol(&symbol_yes);
- e2 = expr_alloc_symbol(&symbol_yes);
- break;
- default:
- ;
- }
-}
-
-void expr_eliminate_eq(struct expr **ep1, struct expr **ep2)
-{
- if (!e1 || !e2)
- return;
- switch (e1->type) {
- case E_OR:
- case E_AND:
- __expr_eliminate_eq(e1->type, ep1, ep2);
- default:
- ;
- }
- if (e1->type != e2->type) switch (e2->type) {
- case E_OR:
- case E_AND:
- __expr_eliminate_eq(e2->type, ep1, ep2);
- default:
- ;
- }
- e1 = expr_eliminate_yn(e1);
- e2 = expr_eliminate_yn(e2);
-}
-
-#undef e1
-#undef e2
-
-int expr_eq(struct expr *e1, struct expr *e2)
-{
- int res, old_count;
-
- if (e1->type != e2->type)
- return 0;
- switch (e1->type) {
- case E_EQUAL:
- case E_UNEQUAL:
- return e1->left.sym == e2->left.sym && e1->right.sym == e2->right.sym;
- case E_SYMBOL:
- return e1->left.sym == e2->left.sym;
- case E_NOT:
- return expr_eq(e1->left.expr, e2->left.expr);
- case E_AND:
- case E_OR:
- e1 = expr_copy(e1);
- e2 = expr_copy(e2);
- old_count = trans_count;
- expr_eliminate_eq(&e1, &e2);
- res = (e1->type == E_SYMBOL && e2->type == E_SYMBOL &&
- e1->left.sym == e2->left.sym);
- expr_free(e1);
- expr_free(e2);
- trans_count = old_count;
- return res;
- case E_LIST:
- case E_RANGE:
- case E_NONE:
- /* panic */;
- }
-
- if (DEBUG_EXPR) {
- expr_fprint(e1, stdout);
- printf(" = ");
- expr_fprint(e2, stdout);
- printf(" ?\n");
- }
-
- return 0;
-}
-
-struct expr *expr_eliminate_yn(struct expr *e)
-{
- struct expr *tmp;
-
- if (e) switch (e->type) {
- case E_AND:
- e->left.expr = expr_eliminate_yn(e->left.expr);
- e->right.expr = expr_eliminate_yn(e->right.expr);
- if (e->left.expr->type == E_SYMBOL) {
- if (e->left.expr->left.sym == &symbol_no) {
- expr_free(e->left.expr);
- expr_free(e->right.expr);
- e->type = E_SYMBOL;
- e->left.sym = &symbol_no;
- e->right.expr = NULL;
- return e;
- } else if (e->left.expr->left.sym == &symbol_yes) {
- free(e->left.expr);
- tmp = e->right.expr;
- *e = *(e->right.expr);
- free(tmp);
- return e;
- }
- }
- if (e->right.expr->type == E_SYMBOL) {
- if (e->right.expr->left.sym == &symbol_no) {
- expr_free(e->left.expr);
- expr_free(e->right.expr);
- e->type = E_SYMBOL;
- e->left.sym = &symbol_no;
- e->right.expr = NULL;
- return e;
- } else if (e->right.expr->left.sym == &symbol_yes) {
- free(e->right.expr);
- tmp = e->left.expr;
- *e = *(e->left.expr);
- free(tmp);
- return e;
- }
- }
- break;
- case E_OR:
- e->left.expr = expr_eliminate_yn(e->left.expr);
- e->right.expr = expr_eliminate_yn(e->right.expr);
- if (e->left.expr->type == E_SYMBOL) {
- if (e->left.expr->left.sym == &symbol_no) {
- free(e->left.expr);
- tmp = e->right.expr;
- *e = *(e->right.expr);
- free(tmp);
- return e;
- } else if (e->left.expr->left.sym == &symbol_yes) {
- expr_free(e->left.expr);
- expr_free(e->right.expr);
- e->type = E_SYMBOL;
- e->left.sym = &symbol_yes;
- e->right.expr = NULL;
- return e;
- }
- }
- if (e->right.expr->type == E_SYMBOL) {
- if (e->right.expr->left.sym == &symbol_no) {
- free(e->right.expr);
- tmp = e->left.expr;
- *e = *(e->left.expr);
- free(tmp);
- return e;
- } else if (e->right.expr->left.sym == &symbol_yes) {
- expr_free(e->left.expr);
- expr_free(e->right.expr);
- e->type = E_SYMBOL;
- e->left.sym = &symbol_yes;
- e->right.expr = NULL;
- return e;
- }
- }
- break;
- default:
- ;
- }
- return e;
-}
-
-/*
- * bool FOO!=n => FOO
- */
-struct expr *expr_trans_bool(struct expr *e)
-{
- if (!e)
- return NULL;
- switch (e->type) {
- case E_AND:
- case E_OR:
- case E_NOT:
- e->left.expr = expr_trans_bool(e->left.expr);
- e->right.expr = expr_trans_bool(e->right.expr);
- break;
- case E_UNEQUAL:
- // FOO!=n -> FOO
- if (e->left.sym->type == S_TRISTATE) {
- if (e->right.sym == &symbol_no) {
- e->type = E_SYMBOL;
- e->right.sym = NULL;
- }
- }
- break;
- default:
- ;
- }
- return e;
-}
-
-/*
- * e1 || e2 -> ?
- */
-static struct expr *expr_join_or(struct expr *e1, struct expr *e2)
-{
- struct expr *tmp;
- struct symbol *sym1, *sym2;
-
- if (expr_eq(e1, e2))
- return expr_copy(e1);
- if (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT)
- return NULL;
- if (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT)
- return NULL;
- if (e1->type == E_NOT) {
- tmp = e1->left.expr;
- if (tmp->type != E_EQUAL && tmp->type != E_UNEQUAL && tmp->type != E_SYMBOL)
- return NULL;
- sym1 = tmp->left.sym;
- } else
- sym1 = e1->left.sym;
- if (e2->type == E_NOT) {
- if (e2->left.expr->type != E_SYMBOL)
- return NULL;
- sym2 = e2->left.expr->left.sym;
- } else
- sym2 = e2->left.sym;
- if (sym1 != sym2)
- return NULL;
- if (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE)
- return NULL;
- if (sym1->type == S_TRISTATE) {
- if (e1->type == E_EQUAL && e2->type == E_EQUAL &&
- ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) ||
- (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes))) {
- // (a='y') || (a='m') -> (a!='n')
- return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_no);
- }
- if (e1->type == E_EQUAL && e2->type == E_EQUAL &&
- ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) ||
- (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes))) {
- // (a='y') || (a='n') -> (a!='m')
- return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_mod);
- }
- if (e1->type == E_EQUAL && e2->type == E_EQUAL &&
- ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) ||
- (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod))) {
- // (a='m') || (a='n') -> (a!='y')
- return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_yes);
- }
- }
- if (sym1->type == S_BOOLEAN && sym1 == sym2) {
- if ((e1->type == E_NOT && e1->left.expr->type == E_SYMBOL && e2->type == E_SYMBOL) ||
- (e2->type == E_NOT && e2->left.expr->type == E_SYMBOL && e1->type == E_SYMBOL))
- return expr_alloc_symbol(&symbol_yes);
- }
-
- if (DEBUG_EXPR) {
- printf("optimize (");
- expr_fprint(e1, stdout);
- printf(") || (");
- expr_fprint(e2, stdout);
- printf(")?\n");
- }
- return NULL;
-}
-
-static struct expr *expr_join_and(struct expr *e1, struct expr *e2)
-{
- struct expr *tmp;
- struct symbol *sym1, *sym2;
-
- if (expr_eq(e1, e2))
- return expr_copy(e1);
- if (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT)
- return NULL;
- if (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT)
- return NULL;
- if (e1->type == E_NOT) {
- tmp = e1->left.expr;
- if (tmp->type != E_EQUAL && tmp->type != E_UNEQUAL && tmp->type != E_SYMBOL)
- return NULL;
- sym1 = tmp->left.sym;
- } else
- sym1 = e1->left.sym;
- if (e2->type == E_NOT) {
- if (e2->left.expr->type != E_SYMBOL)
- return NULL;
- sym2 = e2->left.expr->left.sym;
- } else
- sym2 = e2->left.sym;
- if (sym1 != sym2)
- return NULL;
- if (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE)
- return NULL;
-
- if ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_yes) ||
- (e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_yes))
- // (a) && (a='y') -> (a='y')
- return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);
-
- if ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_no) ||
- (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_no))
- // (a) && (a!='n') -> (a)
- return expr_alloc_symbol(sym1);
-
- if ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_mod) ||
- (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_mod))
- // (a) && (a!='m') -> (a='y')
- return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);
-
- if (sym1->type == S_TRISTATE) {
- if (e1->type == E_EQUAL && e2->type == E_UNEQUAL) {
- // (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b'
- sym2 = e1->right.sym;
- if ((e2->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST))
- return sym2 != e2->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2)
- : expr_alloc_symbol(&symbol_no);
- }
- if (e1->type == E_UNEQUAL && e2->type == E_EQUAL) {
- // (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b'
- sym2 = e2->right.sym;
- if ((e1->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST))
- return sym2 != e1->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2)
- : expr_alloc_symbol(&symbol_no);
- }
- if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL &&
- ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) ||
- (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes)))
- // (a!='y') && (a!='n') -> (a='m')
- return expr_alloc_comp(E_EQUAL, sym1, &symbol_mod);
-
- if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL &&
- ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) ||
- (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes)))
- // (a!='y') && (a!='m') -> (a='n')
- return expr_alloc_comp(E_EQUAL, sym1, &symbol_no);
-
- if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL &&
- ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) ||
- (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod)))
- // (a!='m') && (a!='n') -> (a='m')
- return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);
-
- if ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_mod) ||
- (e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_mod) ||
- (e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_yes) ||
- (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_yes))
- return NULL;
- }
-
- if (DEBUG_EXPR) {
- printf("optimize (");
- expr_fprint(e1, stdout);
- printf(") && (");
- expr_fprint(e2, stdout);
- printf(")?\n");
- }
- return NULL;
-}
-
-static void expr_eliminate_dups1(enum expr_type type, struct expr **ep1, struct expr **ep2)
-{
-#define e1 (*ep1)
-#define e2 (*ep2)
- struct expr *tmp;
-
- if (e1->type == type) {
- expr_eliminate_dups1(type, &e1->left.expr, &e2);
- expr_eliminate_dups1(type, &e1->right.expr, &e2);
- return;
- }
- if (e2->type == type) {
- expr_eliminate_dups1(type, &e1, &e2->left.expr);
- expr_eliminate_dups1(type, &e1, &e2->right.expr);
- return;
- }
- if (e1 == e2)
- return;
-
- switch (e1->type) {
- case E_OR: case E_AND:
- expr_eliminate_dups1(e1->type, &e1, &e1);
- default:
- ;
- }
-
- switch (type) {
- case E_OR:
- tmp = expr_join_or(e1, e2);
- if (tmp) {
- expr_free(e1); expr_free(e2);
- e1 = expr_alloc_symbol(&symbol_no);
- e2 = tmp;
- trans_count++;
- }
- break;
- case E_AND:
- tmp = expr_join_and(e1, e2);
- if (tmp) {
- expr_free(e1); expr_free(e2);
- e1 = expr_alloc_symbol(&symbol_yes);
- e2 = tmp;
- trans_count++;
- }
- break;
- default:
- ;
- }
-#undef e1
-#undef e2
-}
-
-static void expr_eliminate_dups2(enum expr_type type, struct expr **ep1, struct expr **ep2)
-{
-#define e1 (*ep1)
-#define e2 (*ep2)
- struct expr *tmp, *tmp1, *tmp2;
-
- if (e1->type == type) {
- expr_eliminate_dups2(type, &e1->left.expr, &e2);
- expr_eliminate_dups2(type, &e1->right.expr, &e2);
- return;
- }
- if (e2->type == type) {
- expr_eliminate_dups2(type, &e1, &e2->left.expr);
- expr_eliminate_dups2(type, &e1, &e2->right.expr);
- }
- if (e1 == e2)
- return;
-
- switch (e1->type) {
- case E_OR:
- expr_eliminate_dups2(e1->type, &e1, &e1);
- // (FOO || BAR) && (!FOO && !BAR) -> n
- tmp1 = expr_transform(expr_alloc_one(E_NOT, expr_copy(e1)));
- tmp2 = expr_copy(e2);
- tmp = expr_extract_eq_and(&tmp1, &tmp2);
- if (expr_is_yes(tmp1)) {
- expr_free(e1);
- e1 = expr_alloc_symbol(&symbol_no);
- trans_count++;
- }
- expr_free(tmp2);
- expr_free(tmp1);
- expr_free(tmp);
- break;
- case E_AND:
- expr_eliminate_dups2(e1->type, &e1, &e1);
- // (FOO && BAR) || (!FOO || !BAR) -> y
- tmp1 = expr_transform(expr_alloc_one(E_NOT, expr_copy(e1)));
- tmp2 = expr_copy(e2);
- tmp = expr_extract_eq_or(&tmp1, &tmp2);
- if (expr_is_no(tmp1)) {
- expr_free(e1);
- e1 = expr_alloc_symbol(&symbol_yes);
- trans_count++;
- }
- expr_free(tmp2);
- expr_free(tmp1);
- expr_free(tmp);
- break;
- default:
- ;
- }
-#undef e1
-#undef e2
-}
-
-struct expr *expr_eliminate_dups(struct expr *e)
-{
- int oldcount;
- if (!e)
- return e;
-
- oldcount = trans_count;
- while (1) {
- trans_count = 0;
- switch (e->type) {
- case E_OR: case E_AND:
- expr_eliminate_dups1(e->type, &e, &e);
- expr_eliminate_dups2(e->type, &e, &e);
- default:
- ;
- }
- if (!trans_count)
- break;
- e = expr_eliminate_yn(e);
- }
- trans_count = oldcount;
- return e;
-}
-
-struct expr *expr_transform(struct expr *e)
-{
- struct expr *tmp;
-
- if (!e)
- return NULL;
- switch (e->type) {
- case E_EQUAL:
- case E_UNEQUAL:
- case E_SYMBOL:
- case E_LIST:
- break;
- default:
- e->left.expr = expr_transform(e->left.expr);
- e->right.expr = expr_transform(e->right.expr);
- }
-
- switch (e->type) {
- case E_EQUAL:
- if (e->left.sym->type != S_BOOLEAN)
- break;
- if (e->right.sym == &symbol_no) {
- e->type = E_NOT;
- e->left.expr = expr_alloc_symbol(e->left.sym);
- e->right.sym = NULL;
- break;
- }
- if (e->right.sym == &symbol_mod) {
- printf("boolean symbol %s tested for 'm'? test forced to 'n'\n", e->left.sym->name);
- e->type = E_SYMBOL;
- e->left.sym = &symbol_no;
- e->right.sym = NULL;
- break;
- }
- if (e->right.sym == &symbol_yes) {
- e->type = E_SYMBOL;
- e->right.sym = NULL;
- break;
- }
- break;
- case E_UNEQUAL:
- if (e->left.sym->type != S_BOOLEAN)
- break;
- if (e->right.sym == &symbol_no) {
- e->type = E_SYMBOL;
- e->right.sym = NULL;
- break;
- }
- if (e->right.sym == &symbol_mod) {
- printf("boolean symbol %s tested for 'm'? test forced to 'y'\n", e->left.sym->name);
- e->type = E_SYMBOL;
- e->left.sym = &symbol_yes;
- e->right.sym = NULL;
- break;
- }
- if (e->right.sym == &symbol_yes) {
- e->type = E_NOT;
- e->left.expr = expr_alloc_symbol(e->left.sym);
- e->right.sym = NULL;
- break;
- }
- break;
- case E_NOT:
- switch (e->left.expr->type) {
- case E_NOT:
- // !!a -> a
- tmp = e->left.expr->left.expr;
- free(e->left.expr);
- free(e);
- e = tmp;
- e = expr_transform(e);
- break;
- case E_EQUAL:
- case E_UNEQUAL:
- // !a='x' -> a!='x'
- tmp = e->left.expr;
- free(e);
- e = tmp;
- e->type = e->type == E_EQUAL ? E_UNEQUAL : E_EQUAL;
- break;
- case E_OR:
- // !(a || b) -> !a && !b
- tmp = e->left.expr;
- e->type = E_AND;
- e->right.expr = expr_alloc_one(E_NOT, tmp->right.expr);
- tmp->type = E_NOT;
- tmp->right.expr = NULL;
- e = expr_transform(e);
- break;
- case E_AND:
- // !(a && b) -> !a || !b
- tmp = e->left.expr;
- e->type = E_OR;
- e->right.expr = expr_alloc_one(E_NOT, tmp->right.expr);
- tmp->type = E_NOT;
- tmp->right.expr = NULL;
- e = expr_transform(e);
- break;
- case E_SYMBOL:
- if (e->left.expr->left.sym == &symbol_yes) {
- // !'y' -> 'n'
- tmp = e->left.expr;
- free(e);
- e = tmp;
- e->type = E_SYMBOL;
- e->left.sym = &symbol_no;
- break;
- }
- if (e->left.expr->left.sym == &symbol_mod) {
- // !'m' -> 'm'
- tmp = e->left.expr;
- free(e);
- e = tmp;
- e->type = E_SYMBOL;
- e->left.sym = &symbol_mod;
- break;
- }
- if (e->left.expr->left.sym == &symbol_no) {
- // !'n' -> 'y'
- tmp = e->left.expr;
- free(e);
- e = tmp;
- e->type = E_SYMBOL;
- e->left.sym = &symbol_yes;
- break;
- }
- break;
- default:
- ;
- }
- break;
- default:
- ;
- }
- return e;
-}
-
-int expr_contains_symbol(struct expr *dep, struct symbol *sym)
-{
- if (!dep)
- return 0;
-
- switch (dep->type) {
- case E_AND:
- case E_OR:
- return expr_contains_symbol(dep->left.expr, sym) ||
- expr_contains_symbol(dep->right.expr, sym);
- case E_SYMBOL:
- return dep->left.sym == sym;
- case E_EQUAL:
- case E_UNEQUAL:
- return dep->left.sym == sym ||
- dep->right.sym == sym;
- case E_NOT:
- return expr_contains_symbol(dep->left.expr, sym);
- default:
- ;
- }
- return 0;
-}
-
-bool expr_depends_symbol(struct expr *dep, struct symbol *sym)
-{
- if (!dep)
- return false;
-
- switch (dep->type) {
- case E_AND:
- return expr_depends_symbol(dep->left.expr, sym) ||
- expr_depends_symbol(dep->right.expr, sym);
- case E_SYMBOL:
- return dep->left.sym == sym;
- case E_EQUAL:
- if (dep->left.sym == sym) {
- if (dep->right.sym == &symbol_yes || dep->right.sym == &symbol_mod)
- return true;
- }
- break;
- case E_UNEQUAL:
- if (dep->left.sym == sym) {
- if (dep->right.sym == &symbol_no)
- return true;
- }
- break;
- default:
- ;
- }
- return false;
-}
-
-struct expr *expr_extract_eq_and(struct expr **ep1, struct expr **ep2)
-{
- struct expr *tmp = NULL;
- expr_extract_eq(E_AND, &tmp, ep1, ep2);
- if (tmp) {
- *ep1 = expr_eliminate_yn(*ep1);
- *ep2 = expr_eliminate_yn(*ep2);
- }
- return tmp;
-}
-
-struct expr *expr_extract_eq_or(struct expr **ep1, struct expr **ep2)
-{
- struct expr *tmp = NULL;
- expr_extract_eq(E_OR, &tmp, ep1, ep2);
- if (tmp) {
- *ep1 = expr_eliminate_yn(*ep1);
- *ep2 = expr_eliminate_yn(*ep2);
- }
- return tmp;
-}
-
-void expr_extract_eq(enum expr_type type, struct expr **ep, struct expr **ep1, struct expr **ep2)
-{
-#define e1 (*ep1)
-#define e2 (*ep2)
- if (e1->type == type) {
- expr_extract_eq(type, ep, &e1->left.expr, &e2);
- expr_extract_eq(type, ep, &e1->right.expr, &e2);
- return;
- }
- if (e2->type == type) {
- expr_extract_eq(type, ep, ep1, &e2->left.expr);
- expr_extract_eq(type, ep, ep1, &e2->right.expr);
- return;
- }
- if (expr_eq(e1, e2)) {
- *ep = *ep ? expr_alloc_two(type, *ep, e1) : e1;
- expr_free(e2);
- if (type == E_AND) {
- e1 = expr_alloc_symbol(&symbol_yes);
- e2 = expr_alloc_symbol(&symbol_yes);
- } else if (type == E_OR) {
- e1 = expr_alloc_symbol(&symbol_no);
- e2 = expr_alloc_symbol(&symbol_no);
- }
- }
-#undef e1
-#undef e2
-}
-
-struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym)
-{
- struct expr *e1, *e2;
-
- if (!e) {
- e = expr_alloc_symbol(sym);
- if (type == E_UNEQUAL)
- e = expr_alloc_one(E_NOT, e);
- return e;
- }
- switch (e->type) {
- case E_AND:
- e1 = expr_trans_compare(e->left.expr, E_EQUAL, sym);
- e2 = expr_trans_compare(e->right.expr, E_EQUAL, sym);
- if (sym == &symbol_yes)
- e = expr_alloc_two(E_AND, e1, e2);
- if (sym == &symbol_no)
- e = expr_alloc_two(E_OR, e1, e2);
- if (type == E_UNEQUAL)
- e = expr_alloc_one(E_NOT, e);
- return e;
- case E_OR:
- e1 = expr_trans_compare(e->left.expr, E_EQUAL, sym);
- e2 = expr_trans_compare(e->right.expr, E_EQUAL, sym);
- if (sym == &symbol_yes)
- e = expr_alloc_two(E_OR, e1, e2);
- if (sym == &symbol_no)
- e = expr_alloc_two(E_AND, e1, e2);
- if (type == E_UNEQUAL)
- e = expr_alloc_one(E_NOT, e);
- return e;
- case E_NOT:
- return expr_trans_compare(e->left.expr, type == E_EQUAL ? E_UNEQUAL : E_EQUAL, sym);
- case E_UNEQUAL:
- case E_EQUAL:
- if (type == E_EQUAL) {
- if (sym == &symbol_yes)
- return expr_copy(e);
- if (sym == &symbol_mod)
- return expr_alloc_symbol(&symbol_no);
- if (sym == &symbol_no)
- return expr_alloc_one(E_NOT, expr_copy(e));
- } else {
- if (sym == &symbol_yes)
- return expr_alloc_one(E_NOT, expr_copy(e));
- if (sym == &symbol_mod)
- return expr_alloc_symbol(&symbol_yes);
- if (sym == &symbol_no)
- return expr_copy(e);
- }
- break;
- case E_SYMBOL:
- return expr_alloc_comp(type, e->left.sym, sym);
- case E_LIST:
- case E_RANGE:
- case E_NONE:
- /* panic */;
- }
- return NULL;
-}
-
-tristate expr_calc_value(struct expr *e)
-{
- tristate val1, val2;
- const char *str1, *str2;
-
- if (!e)
- return yes;
-
- switch (e->type) {
- case E_SYMBOL:
- sym_calc_value(e->left.sym);
- return e->left.sym->curr.tri;
- case E_AND:
- val1 = expr_calc_value(e->left.expr);
- val2 = expr_calc_value(e->right.expr);
- return EXPR_AND(val1, val2);
- case E_OR:
- val1 = expr_calc_value(e->left.expr);
- val2 = expr_calc_value(e->right.expr);
- return EXPR_OR(val1, val2);
- case E_NOT:
- val1 = expr_calc_value(e->left.expr);
- return EXPR_NOT(val1);
- case E_EQUAL:
- sym_calc_value(e->left.sym);
- sym_calc_value(e->right.sym);
- str1 = sym_get_string_value(e->left.sym);
- str2 = sym_get_string_value(e->right.sym);
- return !strcmp(str1, str2) ? yes : no;
- case E_UNEQUAL:
- sym_calc_value(e->left.sym);
- sym_calc_value(e->right.sym);
- str1 = sym_get_string_value(e->left.sym);
- str2 = sym_get_string_value(e->right.sym);
- return !strcmp(str1, str2) ? no : yes;
- default:
- printf("expr_calc_value: %d?\n", e->type);
- return no;
- }
-}
-
-int expr_compare_type(enum expr_type t1, enum expr_type t2)
-{
-#if 0
- return 1;
-#else
- if (t1 == t2)
- return 0;
- switch (t1) {
- case E_EQUAL:
- case E_UNEQUAL:
- if (t2 == E_NOT)
- return 1;
- case E_NOT:
- if (t2 == E_AND)
- return 1;
- case E_AND:
- if (t2 == E_OR)
- return 1;
- case E_OR:
- if (t2 == E_LIST)
- return 1;
- case E_LIST:
- if (t2 == 0)
- return 1;
- default:
- return -1;
- }
- printf("[%dgt%d?]", t1, t2);
- return 0;
-#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)
-{
- if (!e) {
- fn(data, NULL, "y");
- return;
- }
-
- if (expr_compare_type(prevtoken, e->type) > 0)
- fn(data, NULL, "(");
- switch (e->type) {
- case E_SYMBOL:
- if (e->left.sym->name)
- fn(data, e->left.sym, e->left.sym->name);
- else
- fn(data, NULL, "<choice>");
- break;
- case E_NOT:
- fn(data, NULL, "!");
- expr_print(e->left.expr, fn, data, E_NOT);
- break;
- case E_EQUAL:
- if (e->left.sym->name)
- fn(data, e->left.sym, e->left.sym->name);
- else
- fn(data, NULL, "<choice>");
- fn(data, NULL, "=");
- fn(data, e->right.sym, e->right.sym->name);
- break;
- case E_UNEQUAL:
- if (e->left.sym->name)
- fn(data, e->left.sym, e->left.sym->name);
- else
- fn(data, NULL, "<choice>");
- fn(data, NULL, "!=");
- fn(data, e->right.sym, e->right.sym->name);
- break;
- case E_OR:
- expr_print(e->left.expr, fn, data, E_OR);
- fn(data, NULL, " || ");
- expr_print(e->right.expr, fn, data, E_OR);
- break;
- case E_AND:
- expr_print(e->left.expr, fn, data, E_AND);
- fn(data, NULL, " && ");
- expr_print(e->right.expr, fn, data, E_AND);
- break;
- case E_LIST:
- fn(data, e->right.sym, e->right.sym->name);
- if (e->left.expr) {
- fn(data, NULL, " ^ ");
- expr_print(e->left.expr, fn, data, E_LIST);
- }
- break;
- case E_RANGE:
- fn(data, NULL, "[");
- fn(data, e->left.sym, e->left.sym->name);
- fn(data, NULL, " ");
- fn(data, e->right.sym, e->right.sym->name);
- fn(data, NULL, "]");
- break;
- default:
- {
- char buf[32];
- sprintf(buf, "<unknown type %d>", e->type);
- fn(data, NULL, buf);
- break;
- }
- }
- if (expr_compare_type(prevtoken, e->type) > 0)
- fn(data, NULL, ")");
-}
-
-static void expr_print_file_helper(void *data, struct symbol *sym, const char *str)
-{
- xfwrite(str, strlen(str), 1, data);
-}
-
-void expr_fprint(struct expr *e, FILE *out)
-{
- expr_print(e, expr_print_file_helper, out, E_NONE);
-}
-
-static void expr_print_gstr_helper(void *data, struct symbol *sym, const char *str)
-{
- struct gstr *gs = (struct gstr*)data;
- const char *sym_str = NULL;
-
- if (sym)
- sym_str = sym_get_string_value(sym);
-
- if (gs->max_width) {
- unsigned extra_length = strlen(str);
- const char *last_cr = strrchr(gs->s, '\n');
- unsigned last_line_length;
-
- if (sym_str)
- extra_length += 4 + strlen(sym_str);
-
- if (!last_cr)
- last_cr = gs->s;
-
- last_line_length = strlen(gs->s) - (last_cr - gs->s);
-
- if ((last_line_length + extra_length) > gs->max_width)
- str_append(gs, "\\\n");
- }
-
- str_append(gs, str);
- if (sym && sym->type != S_UNKNOWN)
- str_printf(gs, " [=%s]", sym_str);
-}
-
-void expr_gstr_print(struct expr *e, struct gstr *gs)
-{
- expr_print(e, expr_print_gstr_helper, gs, E_NONE);
-}
+++ /dev/null
-/*
- * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
- * Released under the terms of the GNU GPL v2.0.
- */
-
-#ifndef EXPR_H
-#define EXPR_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <assert.h>
-#include <stdio.h>
-#ifndef __cplusplus
-#include <stdbool.h>
-#endif
-
-struct file {
- struct file *next;
- struct file *parent;
- const char *name;
- int lineno;
-};
-
-typedef enum tristate {
- no, mod, yes
-} tristate;
-
-enum expr_type {
- E_NONE, E_OR, E_AND, E_NOT, E_EQUAL, E_UNEQUAL, E_LIST, E_SYMBOL, E_RANGE
-};
-
-union expr_data {
- struct expr *expr;
- struct symbol *sym;
-};
-
-struct expr {
- enum expr_type type;
- union expr_data left, right;
-};
-
-#define EXPR_OR(dep1, dep2) (((dep1)>(dep2))?(dep1):(dep2))
-#define EXPR_AND(dep1, dep2) (((dep1)<(dep2))?(dep1):(dep2))
-#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 *expr;
- tristate tri;
-};
-
-struct symbol_value {
- void *val;
- tristate tri;
-};
-
-enum symbol_type {
- 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 *next;
- char *name;
- enum symbol_type type;
- struct symbol_value curr;
- struct symbol_value def[S_DEF_COUNT];
- tristate visible;
- int flags;
- struct property *prop;
- struct expr_value dir_dep;
- struct expr_value rev_dep;
-};
-
-#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_CONST 0x0001 /* symbol is const */
-#define SYMBOL_CHECK 0x0008 /* used during dependency checking */
-#define SYMBOL_CHOICE 0x0010 /* start of a choice block (null name) */
-#define SYMBOL_CHOICEVAL 0x0020 /* used as a value in a choice block */
-#define SYMBOL_VALID 0x0080 /* set when symbol.curr is calculated */
-#define SYMBOL_OPTIONAL 0x0100 /* choice is optional - values can be 'n' */
-#define SYMBOL_WRITE 0x0200 /* ? */
-#define SYMBOL_CHANGED 0x0400 /* ? */
-#define SYMBOL_AUTO 0x1000 /* value from environment variable */
-#define SYMBOL_CHECKED 0x2000 /* used during dependency checking */
-#define SYMBOL_WARNED 0x8000 /* warning has been issued */
-
-/* Set when symbol.def[] is used */
-#define SYMBOL_DEF 0x10000 /* First bit of SYMBOL_DEF */
-#define SYMBOL_DEF_USER 0x10000 /* symbol.def[S_DEF_USER] is valid */
-#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_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 {
- 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 */
-};
-
-struct property {
- struct property *next; /* next property - null if last */
- struct symbol *sym; /* the symbol for which the property is associated */
- enum prop_type type; /* type of property */
- const char *text; /* the prompt value - P_PROMPT, P_MENU, P_COMMENT */
- struct expr_value visible;
- struct expr *expr; /* the optional conditional part of the property */
- struct menu *menu; /* the menu the property are associated with
- * valid for: P_SELECT, P_RANGE, P_CHOICE,
- * 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) \
- for (st = sym->prop; st; st = st->next) \
- if (st->type == (tok))
-#define for_all_defaults(sym, st) for_all_properties(sym, st, P_DEFAULT)
-#define for_all_choices(sym, st) for_all_properties(sym, st, P_CHOICE)
-#define for_all_prompts(sym, st) \
- for (st = sym->prop; st; st = st->next) \
- if (st->text)
-
-struct menu {
- struct menu *next;
- struct menu *parent;
- struct menu *list;
- struct symbol *sym;
- struct property *prompt;
- struct expr *visibility;
- struct expr *dep;
- unsigned int flags;
- char *help;
- struct file *file;
- int lineno;
- void *data;
-};
-
-#define MENU_CHANGED 0x0001
-#define MENU_ROOT 0x0002
-
-extern struct file *file_list;
-extern struct file *current_file;
-struct file *lookup_file(const char *name);
-
-extern struct symbol symbol_yes, symbol_no, symbol_mod;
-extern struct symbol *modules_sym;
-extern struct symbol *sym_defconfig_list;
-extern int cdebug;
-struct expr *expr_alloc_symbol(struct symbol *sym);
-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_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_or(struct expr *e1, struct expr *e2);
-struct expr *expr_copy(const struct expr *org);
-void expr_free(struct expr *e);
-int expr_eq(struct expr *e1, struct expr *e2);
-void expr_eliminate_eq(struct expr **ep1, struct expr **ep2);
-tristate expr_calc_value(struct expr *e);
-struct expr *expr_eliminate_yn(struct expr *e);
-struct expr *expr_trans_bool(struct expr *e);
-struct expr *expr_eliminate_dups(struct expr *e);
-struct expr *expr_transform(struct expr *e);
-int expr_contains_symbol(struct expr *dep, struct symbol *sym);
-bool expr_depends_symbol(struct expr *dep, struct symbol *sym);
-struct expr *expr_extract_eq_and(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);
-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);
-struct gstr; /* forward */
-void expr_gstr_print(struct expr *e, struct gstr *gs);
-
-static inline int expr_is_yes(struct expr *e)
-{
- return !e || (e->type == E_SYMBOL && e->left.sym == &symbol_yes);
-}
-
-static inline int expr_is_no(struct expr *e)
-{
- return e && (e->type == E_SYMBOL && e->left.sym == &symbol_no);
-}
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* EXPR_H */
--- /dev/null
+SUBDIRS = conf mconf nconf
--- /dev/null
+bin_PROGRAMS = conf
+
+conf_SOURCES = conf.c
+conf_CPPFLAGS = $(AM_CPPFLAGS) -I../../parser
+conf_LDADD = ../../parser/libkconfigparser.a
--- /dev/null
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#include <locale.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+
+#include "lkc.h"
+
+static void conf(struct menu *menu);
+static void check_conf(struct menu *menu);
+static void xfgets(char *str, int size, FILE *in);
+
+enum input_mode {
+ oldaskconfig,
+ silentoldconfig,
+ oldconfig,
+ allnoconfig,
+ allyesconfig,
+ allmodconfig,
+ alldefconfig,
+ randconfig,
+ defconfig,
+ savedefconfig,
+ listnewconfig,
+ oldnoconfig,
+} input_mode = oldaskconfig;
+
+static int indent = 1;
+static int valid_stdin = 1;
+static int sync_kconfig;
+static int conf_cnt;
+static char line[128];
+static struct menu *rootEntry;
+
+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)
+{
+ char *p = str;
+ int l;
+
+ while ((isspace(*p)))
+ p++;
+ l = strlen(p);
+ if (p != str)
+ memmove(str, p, l + 1);
+ if (!l)
+ return;
+ p = str + l - 1;
+ while ((isspace(*p)))
+ *p-- = 0;
+}
+
+static void check_stdin(void)
+{
+ if (!valid_stdin) {
+ printf(_("aborted!\n\n"));
+ printf(_("Console input/output is redirected. "));
+ printf(_("Run 'make oldconfig' to update configuration.\n\n"));
+ exit(1);
+ }
+}
+
+static int conf_askvalue(struct symbol *sym, const char *def)
+{
+ enum symbol_type type = sym_get_type(sym);
+
+ if (!sym_has_value(sym))
+ printf(_("(NEW) "));
+
+ line[0] = '\n';
+ line[1] = 0;
+
+ if (!sym_is_changable(sym)) {
+ printf("%s\n", def);
+ line[0] = '\n';
+ line[1] = 0;
+ return 0;
+ }
+
+ switch (input_mode) {
+ case oldconfig:
+ case silentoldconfig:
+ if (sym_has_value(sym)) {
+ printf("%s\n", def);
+ return 0;
+ }
+ check_stdin();
+ /* fall through */
+ case oldaskconfig:
+ fflush(stdout);
+ xfgets(line, 128, stdin);
+ return 1;
+ default:
+ break;
+ }
+
+ switch (type) {
+ case S_INT:
+ case S_HEX:
+ case S_STRING:
+ printf("%s\n", def);
+ return 1;
+ default:
+ ;
+ }
+ printf("%s", line);
+ return 1;
+}
+
+static int conf_string(struct menu *menu)
+{
+ struct symbol *sym = menu->sym;
+ const char *def;
+
+ while (1) {
+ printf("%*s%s ", indent - 1, "", _(menu->prompt->text));
+ printf("(%s) ", sym->name);
+ def = sym_get_string_value(sym);
+ if (sym_get_string_value(sym))
+ printf("[%s] ", def);
+ if (!conf_askvalue(sym, def))
+ return 0;
+ switch (line[0]) {
+ case '\n':
+ break;
+ case '?':
+ /* print help */
+ if (line[1] == '\n') {
+ print_help(menu);
+ def = NULL;
+ break;
+ }
+ /* fall through */
+ default:
+ line[strlen(line)-1] = 0;
+ def = line;
+ }
+ if (def && sym_set_string_value(sym, def))
+ return 0;
+ }
+}
+
+static int conf_sym(struct menu *menu)
+{
+ struct symbol *sym = menu->sym;
+ tristate oldval, newval;
+
+ while (1) {
+ printf("%*s%s ", indent - 1, "", _(menu->prompt->text));
+ if (sym->name)
+ printf("(%s) ", sym->name);
+ putchar('[');
+ oldval = sym_get_tristate_value(sym);
+ switch (oldval) {
+ case no:
+ putchar('N');
+ break;
+ case mod:
+ putchar('M');
+ break;
+ case yes:
+ putchar('Y');
+ break;
+ }
+ if (oldval != no && sym_tristate_within_range(sym, no))
+ printf("/n");
+ if (oldval != mod && sym_tristate_within_range(sym, mod))
+ printf("/m");
+ if (oldval != yes && sym_tristate_within_range(sym, yes))
+ printf("/y");
+ if (menu_has_help(menu))
+ printf("/?");
+ printf("] ");
+ if (!conf_askvalue(sym, sym_get_string_value(sym)))
+ return 0;
+ strip(line);
+
+ switch (line[0]) {
+ case 'n':
+ case 'N':
+ newval = no;
+ if (!line[1] || !strcmp(&line[1], "o"))
+ break;
+ continue;
+ case 'm':
+ case 'M':
+ newval = mod;
+ if (!line[1])
+ break;
+ continue;
+ case 'y':
+ case 'Y':
+ newval = yes;
+ if (!line[1] || !strcmp(&line[1], "es"))
+ break;
+ continue;
+ case 0:
+ newval = oldval;
+ break;
+ case '?':
+ goto help;
+ default:
+ continue;
+ }
+ if (sym_set_tristate_value(sym, newval))
+ return 0;
+help:
+ print_help(menu);
+ }
+}
+
+static int conf_choice(struct menu *menu)
+{
+ struct symbol *sym, *def_sym;
+ struct menu *child;
+ bool is_new;
+
+ sym = menu->sym;
+ is_new = !sym_has_value(sym);
+ if (sym_is_changable(sym)) {
+ conf_sym(menu);
+ sym_calc_value(sym);
+ switch (sym_get_tristate_value(sym)) {
+ case no:
+ return 1;
+ case mod:
+ return 0;
+ case yes:
+ break;
+ }
+ } else {
+ switch (sym_get_tristate_value(sym)) {
+ case no:
+ return 1;
+ case mod:
+ printf("%*s%s\n", indent - 1, "", _(menu_get_prompt(menu)));
+ return 0;
+ case yes:
+ break;
+ }
+ }
+
+ while (1) {
+ int cnt, def;
+
+ printf("%*s%s\n", indent - 1, "", _(menu_get_prompt(menu)));
+ def_sym = sym_get_choice_value(sym);
+ cnt = def = 0;
+ line[0] = 0;
+ for (child = menu->list; child; child = child->next) {
+ if (!menu_is_visible(child))
+ continue;
+ if (!child->sym) {
+ printf("%*c %s\n", indent, '*', _(menu_get_prompt(child)));
+ continue;
+ }
+ cnt++;
+ if (child->sym == def_sym) {
+ def = cnt;
+ printf("%*c", indent, '>');
+ } else
+ printf("%*c", indent, ' ');
+ printf(" %d. %s", cnt, _(menu_get_prompt(child)));
+ if (child->sym->name)
+ printf(" (%s)", child->sym->name);
+ if (!sym_has_value(child->sym))
+ printf(_(" (NEW)"));
+ printf("\n");
+ }
+ printf(_("%*schoice"), indent - 1, "");
+ if (cnt == 1) {
+ printf("[1]: 1\n");
+ goto conf_childs;
+ }
+ printf("[1-%d", cnt);
+ if (menu_has_help(menu))
+ printf("?");
+ printf("]: ");
+ switch (input_mode) {
+ case oldconfig:
+ case silentoldconfig:
+ if (!is_new) {
+ cnt = def;
+ printf("%d\n", cnt);
+ break;
+ }
+ check_stdin();
+ /* fall through */
+ case oldaskconfig:
+ fflush(stdout);
+ xfgets(line, 128, stdin);
+ strip(line);
+ if (line[0] == '?') {
+ print_help(menu);
+ continue;
+ }
+ if (!line[0])
+ cnt = def;
+ else if (isdigit(line[0]))
+ cnt = atoi(line);
+ else
+ continue;
+ break;
+ default:
+ break;
+ }
+
+ conf_childs:
+ for (child = menu->list; child; child = child->next) {
+ if (!child->sym || !menu_is_visible(child))
+ continue;
+ if (!--cnt)
+ break;
+ }
+ if (!child)
+ continue;
+ if (line[0] && line[strlen(line) - 1] == '?') {
+ print_help(child);
+ continue;
+ }
+ sym_set_choice_value(sym, child->sym);
+ for (child = child->list; child; child = child->next) {
+ indent += 2;
+ conf(child);
+ indent -= 2;
+ }
+ return 1;
+ }
+}
+
+static void conf(struct menu *menu)
+{
+ struct symbol *sym;
+ struct property *prop;
+ struct menu *child;
+
+ if (!menu_is_visible(menu))
+ return;
+
+ sym = menu->sym;
+ prop = menu->prompt;
+ if (prop) {
+ const char *prompt;
+
+ switch (prop->type) {
+ case P_MENU:
+ if ((input_mode == silentoldconfig ||
+ input_mode == listnewconfig ||
+ input_mode == oldnoconfig) &&
+ rootEntry != menu) {
+ check_conf(menu);
+ return;
+ }
+ /* fall through */
+ case P_COMMENT:
+ prompt = menu_get_prompt(menu);
+ if (prompt)
+ printf("%*c\n%*c %s\n%*c\n",
+ indent, '*',
+ indent, '*', _(prompt),
+ indent, '*');
+ default:
+ ;
+ }
+ }
+
+ if (!sym)
+ goto conf_childs;
+
+ if (sym_is_choice(sym)) {
+ conf_choice(menu);
+ if (sym->curr.tri != mod)
+ return;
+ goto conf_childs;
+ }
+
+ switch (sym->type) {
+ case S_INT:
+ case S_HEX:
+ case S_STRING:
+ conf_string(menu);
+ break;
+ default:
+ conf_sym(menu);
+ break;
+ }
+
+conf_childs:
+ if (sym)
+ indent += 2;
+ for (child = menu->list; child; child = child->next)
+ conf(child);
+ if (sym)
+ indent -= 2;
+}
+
+static void check_conf(struct menu *menu)
+{
+ struct symbol *sym;
+ struct menu *child;
+
+ if (!menu_is_visible(menu))
+ return;
+
+ sym = menu->sym;
+ if (sym && !sym_has_value(sym)) {
+ if (sym_is_changable(sym) ||
+ (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)) {
+ if (input_mode == listnewconfig) {
+ if (sym->name && !sym_is_choice_value(sym)) {
+ printf("%s%s\n", CONFIG_, sym->name);
+ }
+ } else if (input_mode != oldnoconfig) {
+ if (!conf_cnt++)
+ printf(_("*\n* Restart config...\n*\n"));
+ rootEntry = menu_get_parent_menu(menu);
+ conf(rootEntry);
+ }
+ }
+ }
+
+ for (child = menu->list; child; child = child->next)
+ 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},
+ {"oldnoconfig", no_argument, NULL, oldnoconfig},
+ {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(" --oldnoconfig Same as silentoldconfig but set new symbols to no\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)
+{
+ const char *progname = av[0];
+ int opt;
+ const char *name, *defconfig_file = NULL /* gcc uninit */;
+ struct stat tmpstat;
+
+ setlocale(LC_ALL, "");
+ bindtextdomain(PACKAGE, LOCALEDIR);
+ textdomain(PACKAGE);
+
+ while ((opt = getopt_long(ac, av, "", long_opts, NULL)) != -1) {
+ input_mode = (enum input_mode)opt;
+ switch (opt) {
+ case silentoldconfig:
+ sync_kconfig = 1;
+ break;
+ case defconfig:
+ case savedefconfig:
+ defconfig_file = optarg;
+ break;
+ case randconfig:
+ {
+ 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;
+ }
+ case oldaskconfig:
+ case oldconfig:
+ case allnoconfig:
+ case allyesconfig:
+ case allmodconfig:
+ case alldefconfig:
+ case listnewconfig:
+ case oldnoconfig:
+ break;
+ case '?':
+ conf_usage(progname);
+ exit(1);
+ break;
+ }
+ }
+ if (ac == optind) {
+ printf(_("%s: Kconfig file missing\n"), av[0]);
+ conf_usage(progname);
+ exit(1);
+ }
+ name = av[optind];
+ conf_parse(name);
+ //zconfdump(stdout);
+ if (sync_kconfig) {
+ name = conf_get_configname();
+ if (stat(name, &tmpstat)) {
+ fprintf(stderr, _("***\n"
+ "*** Configuration file \"%s\" not found!\n"
+ "***\n"
+ "*** Please run some configurator (e.g. \"make oldconfig\" or\n"
+ "*** \"make menuconfig\" or \"make xconfig\").\n"
+ "***\n"), name);
+ exit(1);
+ }
+ }
+
+ switch (input_mode) {
+ case defconfig:
+ if (!defconfig_file)
+ defconfig_file = conf_get_default_confname();
+ 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 oldnoconfig:
+ conf_read(NULL);
+ break;
+ case allnoconfig:
+ case allyesconfig:
+ case allmodconfig:
+ case alldefconfig:
+ case randconfig:
+ name = getenv("KCONFIG_ALLCONFIG");
+ if (name && !stat(name, &tmpstat)) {
+ conf_read_simple(name, S_DEF_USER);
+ break;
+ }
+ switch (input_mode) {
+ case allnoconfig: name = "allno.config"; break;
+ case allyesconfig: name = "allyes.config"; break;
+ case allmodconfig: name = "allmod.config"; break;
+ case alldefconfig: name = "alldef.config"; break;
+ case randconfig: name = "allrandom.config"; break;
+ default: break;
+ }
+ if (!stat(name, &tmpstat))
+ conf_read_simple(name, S_DEF_USER);
+ else if (!stat("all.config", &tmpstat))
+ conf_read_simple("all.config", S_DEF_USER);
+ break;
+ default:
+ break;
+ }
+
+ 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 = isatty(0) && isatty(1) && isatty(2);
+ }
+
+ 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;
+ conf(&rootmenu);
+ input_mode = silentoldconfig;
+ /* fall through */
+ case oldconfig:
+ case listnewconfig:
+ case oldnoconfig:
+ 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 != oldnoconfig));
+ break;
+ }
+
+ if (sync_kconfig) {
+ /* silentoldconfig is used during the build so we shall update autoconf.
+ * All other commands are only used to generate a config.
+ */
+ if (conf_get_changed() && conf_write(NULL)) {
+ 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(NULL)) {
+ fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n"));
+ exit(1);
+ }
+ }
+ 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");
+}
--- /dev/null
+/* Hey EMACS -*- linux-c -*- */
+/*
+ *
+ * Copyright (C) 2002-2003 Romain Lievin <roms@tilp.info>
+ * Released under the terms of the GNU GPL v2.0.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "lkc.h"
+#include "images.c"
+
+#include <glade/glade.h>
+#include <gtk/gtk.h>
+#include <glib.h>
+#include <gdk/gdkkeysyms.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <time.h>
+#include <stdlib.h>
+
+//#define DEBUG
+
+enum {
+ SINGLE_VIEW, SPLIT_VIEW, FULL_VIEW
+};
+
+enum {
+ OPT_NORMAL, OPT_ALL, OPT_PROMPT
+};
+
+static gint view_mode = FULL_VIEW;
+static gboolean show_name = TRUE;
+static gboolean show_range = TRUE;
+static gboolean show_value = TRUE;
+static gboolean resizeable = FALSE;
+static int opt_mode = OPT_NORMAL;
+
+GtkWidget *main_wnd = NULL;
+GtkWidget *tree1_w = NULL; // left frame
+GtkWidget *tree2_w = NULL; // right frame
+GtkWidget *text_w = NULL;
+GtkWidget *hpaned = NULL;
+GtkWidget *vpaned = NULL;
+GtkWidget *back_btn = NULL;
+GtkWidget *save_btn = NULL;
+GtkWidget *save_menu_item = NULL;
+
+GtkTextTag *tag1, *tag2;
+GdkColor color;
+
+GtkTreeStore *tree1, *tree2, *tree;
+GtkTreeModel *model1, *model2;
+static GtkTreeIter *parents[256];
+static gint indent;
+
+static struct menu *current; // current node for SINGLE view
+static struct menu *browsed; // browsed node for SPLIT view
+
+enum {
+ COL_OPTION, COL_NAME, COL_NO, COL_MOD, COL_YES, COL_VALUE,
+ COL_MENU, COL_COLOR, COL_EDIT, COL_PIXBUF,
+ COL_PIXVIS, COL_BTNVIS, COL_BTNACT, COL_BTNINC, COL_BTNRAD,
+ COL_NUMBER
+};
+
+static void display_list(void);
+static void display_tree(struct menu *menu);
+static void display_tree_part(void);
+static void update_tree(struct menu *src, GtkTreeIter * dst);
+static void set_node(GtkTreeIter * node, struct menu *menu, gchar ** row);
+static gchar **fill_row(struct menu *menu);
+static void conf_changed(void);
+
+/* Helping/Debugging Functions */
+
+const char *dbg_sym_flags(int val)
+{
+ static char buf[256];
+
+ bzero(buf, 256);
+
+ if (val & SYMBOL_CONST)
+ strcat(buf, "const/");
+ if (val & SYMBOL_CHECK)
+ strcat(buf, "check/");
+ if (val & SYMBOL_CHOICE)
+ strcat(buf, "choice/");
+ if (val & SYMBOL_CHOICEVAL)
+ strcat(buf, "choiceval/");
+ if (val & SYMBOL_VALID)
+ strcat(buf, "valid/");
+ if (val & SYMBOL_OPTIONAL)
+ strcat(buf, "optional/");
+ if (val & SYMBOL_WRITE)
+ strcat(buf, "write/");
+ if (val & SYMBOL_CHANGED)
+ strcat(buf, "changed/");
+ if (val & SYMBOL_AUTO)
+ strcat(buf, "auto/");
+
+ buf[strlen(buf) - 1] = '\0';
+
+ return buf;
+}
+
+void replace_button_icon(GladeXML * xml, GdkDrawable * window,
+ GtkStyle * style, gchar * btn_name, gchar ** xpm)
+{
+ GdkPixmap *pixmap;
+ GdkBitmap *mask;
+ GtkToolButton *button;
+ GtkWidget *image;
+
+ pixmap = gdk_pixmap_create_from_xpm_d(window, &mask,
+ &style->bg[GTK_STATE_NORMAL],
+ xpm);
+
+ button = GTK_TOOL_BUTTON(glade_xml_get_widget(xml, btn_name));
+ image = gtk_image_new_from_pixmap(pixmap, mask);
+ gtk_widget_show(image);
+ gtk_tool_button_set_icon_widget(button, image);
+}
+
+/* Main Window Initialization */
+void init_main_window(const gchar * glade_file)
+{
+ GladeXML *xml;
+ GtkWidget *widget;
+ GtkTextBuffer *txtbuf;
+ GtkStyle *style;
+
+ xml = glade_xml_new(glade_file, "window1", NULL);
+ if (!xml)
+ g_error(_("GUI loading failed !\n"));
+ glade_xml_signal_autoconnect(xml);
+
+ main_wnd = glade_xml_get_widget(xml, "window1");
+ hpaned = glade_xml_get_widget(xml, "hpaned1");
+ vpaned = glade_xml_get_widget(xml, "vpaned1");
+ tree1_w = glade_xml_get_widget(xml, "treeview1");
+ tree2_w = glade_xml_get_widget(xml, "treeview2");
+ text_w = glade_xml_get_widget(xml, "textview3");
+
+ back_btn = glade_xml_get_widget(xml, "button1");
+ gtk_widget_set_sensitive(back_btn, FALSE);
+
+ widget = glade_xml_get_widget(xml, "show_name1");
+ gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,
+ show_name);
+
+ widget = glade_xml_get_widget(xml, "show_range1");
+ gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,
+ show_range);
+
+ widget = glade_xml_get_widget(xml, "show_data1");
+ gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,
+ show_value);
+
+ save_btn = glade_xml_get_widget(xml, "button3");
+ save_menu_item = glade_xml_get_widget(xml, "save1");
+ conf_set_changed_callback(conf_changed);
+
+ style = gtk_widget_get_style(main_wnd);
+ widget = glade_xml_get_widget(xml, "toolbar1");
+
+#if 0 /* Use stock Gtk icons instead */
+ replace_button_icon(xml, main_wnd->window, style,
+ "button1", (gchar **) xpm_back);
+ replace_button_icon(xml, main_wnd->window, style,
+ "button2", (gchar **) xpm_load);
+ replace_button_icon(xml, main_wnd->window, style,
+ "button3", (gchar **) xpm_save);
+#endif
+ replace_button_icon(xml, main_wnd->window, style,
+ "button4", (gchar **) xpm_single_view);
+ replace_button_icon(xml, main_wnd->window, style,
+ "button5", (gchar **) xpm_split_view);
+ replace_button_icon(xml, main_wnd->window, style,
+ "button6", (gchar **) xpm_tree_view);
+
+#if 0
+ switch (view_mode) {
+ case SINGLE_VIEW:
+ widget = glade_xml_get_widget(xml, "button4");
+ g_signal_emit_by_name(widget, "clicked");
+ break;
+ case SPLIT_VIEW:
+ widget = glade_xml_get_widget(xml, "button5");
+ g_signal_emit_by_name(widget, "clicked");
+ break;
+ case FULL_VIEW:
+ widget = glade_xml_get_widget(xml, "button6");
+ g_signal_emit_by_name(widget, "clicked");
+ break;
+ }
+#endif
+ txtbuf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w));
+ tag1 = gtk_text_buffer_create_tag(txtbuf, "mytag1",
+ "foreground", "red",
+ "weight", PANGO_WEIGHT_BOLD,
+ NULL);
+ tag2 = gtk_text_buffer_create_tag(txtbuf, "mytag2",
+ /*"style", PANGO_STYLE_OBLIQUE, */
+ NULL);
+
+ gtk_window_set_title(GTK_WINDOW(main_wnd), rootmenu.prompt->text);
+
+ gtk_widget_show(main_wnd);
+}
+
+void init_tree_model(void)
+{
+ gint i;
+
+ tree = tree2 = gtk_tree_store_new(COL_NUMBER,
+ G_TYPE_STRING, G_TYPE_STRING,
+ G_TYPE_STRING, G_TYPE_STRING,
+ G_TYPE_STRING, G_TYPE_STRING,
+ G_TYPE_POINTER, GDK_TYPE_COLOR,
+ G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF,
+ G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
+ G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
+ G_TYPE_BOOLEAN);
+ model2 = GTK_TREE_MODEL(tree2);
+
+ for (parents[0] = NULL, i = 1; i < 256; i++)
+ parents[i] = (GtkTreeIter *) g_malloc(sizeof(GtkTreeIter));
+
+ tree1 = gtk_tree_store_new(COL_NUMBER,
+ G_TYPE_STRING, G_TYPE_STRING,
+ G_TYPE_STRING, G_TYPE_STRING,
+ G_TYPE_STRING, G_TYPE_STRING,
+ G_TYPE_POINTER, GDK_TYPE_COLOR,
+ G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF,
+ G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
+ G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
+ G_TYPE_BOOLEAN);
+ model1 = GTK_TREE_MODEL(tree1);
+}
+
+void init_left_tree(void)
+{
+ GtkTreeView *view = GTK_TREE_VIEW(tree1_w);
+ GtkCellRenderer *renderer;
+ GtkTreeSelection *sel;
+ GtkTreeViewColumn *column;
+
+ gtk_tree_view_set_model(view, model1);
+ gtk_tree_view_set_headers_visible(view, TRUE);
+ gtk_tree_view_set_rules_hint(view, TRUE);
+
+ column = gtk_tree_view_column_new();
+ gtk_tree_view_append_column(view, column);
+ gtk_tree_view_column_set_title(column, _("Options"));
+
+ renderer = gtk_cell_renderer_toggle_new();
+ gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
+ renderer, FALSE);
+ gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
+ renderer,
+ "active", COL_BTNACT,
+ "inconsistent", COL_BTNINC,
+ "visible", COL_BTNVIS,
+ "radio", COL_BTNRAD, NULL);
+ renderer = gtk_cell_renderer_text_new();
+ gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
+ renderer, FALSE);
+ gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
+ renderer,
+ "text", COL_OPTION,
+ "foreground-gdk",
+ COL_COLOR, NULL);
+
+ sel = gtk_tree_view_get_selection(view);
+ gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE);
+ gtk_widget_realize(tree1_w);
+}
+
+static void renderer_edited(GtkCellRendererText * cell,
+ const gchar * path_string,
+ const gchar * new_text, gpointer user_data);
+
+void init_right_tree(void)
+{
+ GtkTreeView *view = GTK_TREE_VIEW(tree2_w);
+ GtkCellRenderer *renderer;
+ GtkTreeSelection *sel;
+ GtkTreeViewColumn *column;
+ gint i;
+
+ gtk_tree_view_set_model(view, model2);
+ gtk_tree_view_set_headers_visible(view, TRUE);
+ gtk_tree_view_set_rules_hint(view, TRUE);
+
+ column = gtk_tree_view_column_new();
+ gtk_tree_view_append_column(view, column);
+ gtk_tree_view_column_set_title(column, _("Options"));
+
+ renderer = gtk_cell_renderer_pixbuf_new();
+ gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
+ renderer, FALSE);
+ gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
+ renderer,
+ "pixbuf", COL_PIXBUF,
+ "visible", COL_PIXVIS, NULL);
+ renderer = gtk_cell_renderer_toggle_new();
+ gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
+ renderer, FALSE);
+ gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
+ renderer,
+ "active", COL_BTNACT,
+ "inconsistent", COL_BTNINC,
+ "visible", COL_BTNVIS,
+ "radio", COL_BTNRAD, NULL);
+ renderer = gtk_cell_renderer_text_new();
+ gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
+ renderer, FALSE);
+ gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
+ renderer,
+ "text", COL_OPTION,
+ "foreground-gdk",
+ COL_COLOR, NULL);
+
+ renderer = gtk_cell_renderer_text_new();
+ gtk_tree_view_insert_column_with_attributes(view, -1,
+ _("Name"), renderer,
+ "text", COL_NAME,
+ "foreground-gdk",
+ COL_COLOR, NULL);
+ renderer = gtk_cell_renderer_text_new();
+ gtk_tree_view_insert_column_with_attributes(view, -1,
+ "N", renderer,
+ "text", COL_NO,
+ "foreground-gdk",
+ COL_COLOR, NULL);
+ renderer = gtk_cell_renderer_text_new();
+ gtk_tree_view_insert_column_with_attributes(view, -1,
+ "M", renderer,
+ "text", COL_MOD,
+ "foreground-gdk",
+ COL_COLOR, NULL);
+ renderer = gtk_cell_renderer_text_new();
+ gtk_tree_view_insert_column_with_attributes(view, -1,
+ "Y", renderer,
+ "text", COL_YES,
+ "foreground-gdk",
+ COL_COLOR, NULL);
+ renderer = gtk_cell_renderer_text_new();
+ gtk_tree_view_insert_column_with_attributes(view, -1,
+ _("Value"), renderer,
+ "text", COL_VALUE,
+ "editable",
+ COL_EDIT,
+ "foreground-gdk",
+ COL_COLOR, NULL);
+ g_signal_connect(G_OBJECT(renderer), "edited",
+ G_CALLBACK(renderer_edited), NULL);
+
+ column = gtk_tree_view_get_column(view, COL_NAME);
+ gtk_tree_view_column_set_visible(column, show_name);
+ column = gtk_tree_view_get_column(view, COL_NO);
+ gtk_tree_view_column_set_visible(column, show_range);
+ column = gtk_tree_view_get_column(view, COL_MOD);
+ gtk_tree_view_column_set_visible(column, show_range);
+ column = gtk_tree_view_get_column(view, COL_YES);
+ gtk_tree_view_column_set_visible(column, show_range);
+ column = gtk_tree_view_get_column(view, COL_VALUE);
+ gtk_tree_view_column_set_visible(column, show_value);
+
+ if (resizeable) {
+ for (i = 0; i < COL_VALUE; i++) {
+ column = gtk_tree_view_get_column(view, i);
+ gtk_tree_view_column_set_resizable(column, TRUE);
+ }
+ }
+
+ sel = gtk_tree_view_get_selection(view);
+ gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE);
+}
+
+
+/* Utility Functions */
+
+
+static void text_insert_help(struct menu *menu)
+{
+ GtkTextBuffer *buffer;
+ GtkTextIter start, end;
+ const char *prompt = _(menu_get_prompt(menu));
+ struct gstr help = str_new();
+
+ menu_get_ext_help(menu, &help);
+
+ buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w));
+ gtk_text_buffer_get_bounds(buffer, &start, &end);
+ gtk_text_buffer_delete(buffer, &start, &end);
+ gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_w), 15);
+
+ gtk_text_buffer_get_end_iter(buffer, &end);
+ gtk_text_buffer_insert_with_tags(buffer, &end, prompt, -1, tag1,
+ NULL);
+ gtk_text_buffer_insert_at_cursor(buffer, "\n\n", 2);
+ gtk_text_buffer_get_end_iter(buffer, &end);
+ gtk_text_buffer_insert_with_tags(buffer, &end, str_get(&help), -1, tag2,
+ NULL);
+ str_free(&help);
+}
+
+
+static void text_insert_msg(const char *title, const char *message)
+{
+ GtkTextBuffer *buffer;
+ GtkTextIter start, end;
+ const char *msg = message;
+
+ buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w));
+ gtk_text_buffer_get_bounds(buffer, &start, &end);
+ gtk_text_buffer_delete(buffer, &start, &end);
+ gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_w), 15);
+
+ gtk_text_buffer_get_end_iter(buffer, &end);
+ gtk_text_buffer_insert_with_tags(buffer, &end, title, -1, tag1,
+ NULL);
+ gtk_text_buffer_insert_at_cursor(buffer, "\n\n", 2);
+ gtk_text_buffer_get_end_iter(buffer, &end);
+ gtk_text_buffer_insert_with_tags(buffer, &end, msg, -1, tag2,
+ NULL);
+}
+
+
+/* Main Windows Callbacks */
+
+void on_save_activate(GtkMenuItem * menuitem, gpointer user_data);
+gboolean on_window1_delete_event(GtkWidget * widget, GdkEvent * event,
+ gpointer user_data)
+{
+ GtkWidget *dialog, *label;
+ gint result;
+
+ if (!conf_get_changed())
+ return FALSE;
+
+ dialog = gtk_dialog_new_with_buttons(_("Warning !"),
+ GTK_WINDOW(main_wnd),
+ (GtkDialogFlags)
+ (GTK_DIALOG_MODAL |
+ GTK_DIALOG_DESTROY_WITH_PARENT),
+ GTK_STOCK_OK,
+ GTK_RESPONSE_YES,
+ GTK_STOCK_NO,
+ GTK_RESPONSE_NO,
+ GTK_STOCK_CANCEL,
+ GTK_RESPONSE_CANCEL, NULL);
+ gtk_dialog_set_default_response(GTK_DIALOG(dialog),
+ GTK_RESPONSE_CANCEL);
+
+ label = gtk_label_new(_("\nSave configuration ?\n"));
+ gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), label);
+ gtk_widget_show(label);
+
+ result = gtk_dialog_run(GTK_DIALOG(dialog));
+ switch (result) {
+ case GTK_RESPONSE_YES:
+ on_save_activate(NULL, NULL);
+ return FALSE;
+ case GTK_RESPONSE_NO:
+ return FALSE;
+ case GTK_RESPONSE_CANCEL:
+ case GTK_RESPONSE_DELETE_EVENT:
+ default:
+ gtk_widget_destroy(dialog);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+void on_window1_destroy(GtkObject * object, gpointer user_data)
+{
+ gtk_main_quit();
+}
+
+
+void
+on_window1_size_request(GtkWidget * widget,
+ GtkRequisition * requisition, gpointer user_data)
+{
+ static gint old_h;
+ gint w, h;
+
+ if (widget->window == NULL)
+ gtk_window_get_default_size(GTK_WINDOW(main_wnd), &w, &h);
+ else
+ gdk_window_get_size(widget->window, &w, &h);
+
+ if (h == old_h)
+ return;
+ old_h = h;
+
+ gtk_paned_set_position(GTK_PANED(vpaned), 2 * h / 3);
+}
+
+
+/* Menu & Toolbar Callbacks */
+
+
+static void
+load_filename(GtkFileSelection * file_selector, gpointer user_data)
+{
+ const gchar *fn;
+
+ fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION
+ (user_data));
+
+ if (conf_read(fn))
+ text_insert_msg(_("Error"), _("Unable to load configuration !"));
+ else
+ display_tree(&rootmenu);
+}
+
+void on_load1_activate(GtkMenuItem * menuitem, gpointer user_data)
+{
+ GtkWidget *fs;
+
+ fs = gtk_file_selection_new(_("Load file..."));
+ g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button),
+ "clicked",
+ G_CALLBACK(load_filename), (gpointer) fs);
+ g_signal_connect_swapped(GTK_OBJECT
+ (GTK_FILE_SELECTION(fs)->ok_button),
+ "clicked", G_CALLBACK(gtk_widget_destroy),
+ (gpointer) fs);
+ g_signal_connect_swapped(GTK_OBJECT
+ (GTK_FILE_SELECTION(fs)->cancel_button),
+ "clicked", G_CALLBACK(gtk_widget_destroy),
+ (gpointer) fs);
+ gtk_widget_show(fs);
+}
+
+
+void on_save_activate(GtkMenuItem * menuitem, gpointer user_data)
+{
+ if (conf_write(NULL))
+ text_insert_msg(_("Error"), _("Unable to save configuration !"));
+}
+
+
+static void
+store_filename(GtkFileSelection * file_selector, gpointer user_data)
+{
+ const gchar *fn;
+
+ fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION
+ (user_data));
+
+ if (conf_write(fn))
+ text_insert_msg(_("Error"), _("Unable to save configuration !"));
+
+ gtk_widget_destroy(GTK_WIDGET(user_data));
+}
+
+void on_save_as1_activate(GtkMenuItem * menuitem, gpointer user_data)
+{
+ GtkWidget *fs;
+
+ fs = gtk_file_selection_new(_("Save file as..."));
+ g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button),
+ "clicked",
+ G_CALLBACK(store_filename), (gpointer) fs);
+ g_signal_connect_swapped(GTK_OBJECT
+ (GTK_FILE_SELECTION(fs)->ok_button),
+ "clicked", G_CALLBACK(gtk_widget_destroy),
+ (gpointer) fs);
+ g_signal_connect_swapped(GTK_OBJECT
+ (GTK_FILE_SELECTION(fs)->cancel_button),
+ "clicked", G_CALLBACK(gtk_widget_destroy),
+ (gpointer) fs);
+ gtk_widget_show(fs);
+}
+
+
+void on_quit1_activate(GtkMenuItem * menuitem, gpointer user_data)
+{
+ if (!on_window1_delete_event(NULL, NULL, NULL))
+ gtk_widget_destroy(GTK_WIDGET(main_wnd));
+}
+
+
+void on_show_name1_activate(GtkMenuItem * menuitem, gpointer user_data)
+{
+ GtkTreeViewColumn *col;
+
+ show_name = GTK_CHECK_MENU_ITEM(menuitem)->active;
+ col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_NAME);
+ if (col)
+ gtk_tree_view_column_set_visible(col, show_name);
+}
+
+
+void on_show_range1_activate(GtkMenuItem * menuitem, gpointer user_data)
+{
+ GtkTreeViewColumn *col;
+
+ show_range = GTK_CHECK_MENU_ITEM(menuitem)->active;
+ col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_NO);
+ if (col)
+ gtk_tree_view_column_set_visible(col, show_range);
+ col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_MOD);
+ if (col)
+ gtk_tree_view_column_set_visible(col, show_range);
+ col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_YES);
+ if (col)
+ gtk_tree_view_column_set_visible(col, show_range);
+
+}
+
+
+void on_show_data1_activate(GtkMenuItem * menuitem, gpointer user_data)
+{
+ GtkTreeViewColumn *col;
+
+ show_value = GTK_CHECK_MENU_ITEM(menuitem)->active;
+ col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_VALUE);
+ if (col)
+ gtk_tree_view_column_set_visible(col, show_value);
+}
+
+
+void
+on_set_option_mode1_activate(GtkMenuItem *menuitem, gpointer user_data)
+{
+ opt_mode = OPT_NORMAL;
+ gtk_tree_store_clear(tree2);
+ display_tree(&rootmenu); /* instead of update_tree to speed-up */
+}
+
+
+void
+on_set_option_mode2_activate(GtkMenuItem *menuitem, gpointer user_data)
+{
+ opt_mode = OPT_ALL;
+ gtk_tree_store_clear(tree2);
+ display_tree(&rootmenu); /* instead of update_tree to speed-up */
+}
+
+
+void
+on_set_option_mode3_activate(GtkMenuItem *menuitem, gpointer user_data)
+{
+ opt_mode = OPT_PROMPT;
+ gtk_tree_store_clear(tree2);
+ display_tree(&rootmenu); /* instead of update_tree to speed-up */
+}
+
+
+void on_introduction1_activate(GtkMenuItem * menuitem, gpointer user_data)
+{
+ GtkWidget *dialog;
+ const gchar *intro_text = _(
+ "Welcome to gkc, the GTK+ graphical configuration tool\n"
+ "For each option, a blank box indicates the feature is disabled, a\n"
+ "check indicates it is enabled, and a dot indicates that it is to\n"
+ "be compiled as a module. Clicking on the box will cycle through the three states.\n"
+ "\n"
+ "If you do not see an option (e.g., a device driver) that you\n"
+ "believe should be present, try turning on Show All Options\n"
+ "under the Options menu.\n"
+ "Although there is no cross reference yet to help you figure out\n"
+ "what other options must be enabled to support the option you\n"
+ "are interested in, you can still view the help of a grayed-out\n"
+ "option.\n"
+ "\n"
+ "Toggling Show Debug Info under the Options menu will show \n"
+ "the dependencies, which you can then match by examining other options.");
+
+ dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_INFO,
+ GTK_BUTTONS_CLOSE, "%s", intro_text);
+ g_signal_connect_swapped(GTK_OBJECT(dialog), "response",
+ G_CALLBACK(gtk_widget_destroy),
+ GTK_OBJECT(dialog));
+ gtk_widget_show_all(dialog);
+}
+
+
+void on_about1_activate(GtkMenuItem * menuitem, gpointer user_data)
+{
+ GtkWidget *dialog;
+ const gchar *about_text =
+ _("gkc is copyright (c) 2002 Romain Lievin <roms@lpg.ticalc.org>.\n"
+ "Based on the source code from Roman Zippel.\n");
+
+ dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_INFO,
+ GTK_BUTTONS_CLOSE, "%s", about_text);
+ g_signal_connect_swapped(GTK_OBJECT(dialog), "response",
+ G_CALLBACK(gtk_widget_destroy),
+ GTK_OBJECT(dialog));
+ gtk_widget_show_all(dialog);
+}
+
+
+void on_license1_activate(GtkMenuItem * menuitem, gpointer user_data)
+{
+ GtkWidget *dialog;
+ const gchar *license_text =
+ _("gkc is released under the terms of the GNU GPL v2.\n"
+ "For more information, please see the source code or\n"
+ "visit http://www.fsf.org/licenses/licenses.html\n");
+
+ dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_INFO,
+ GTK_BUTTONS_CLOSE, "%s", license_text);
+ g_signal_connect_swapped(GTK_OBJECT(dialog), "response",
+ G_CALLBACK(gtk_widget_destroy),
+ GTK_OBJECT(dialog));
+ gtk_widget_show_all(dialog);
+}
+
+
+void on_back_clicked(GtkButton * button, gpointer user_data)
+{
+ enum prop_type ptype;
+
+ current = current->parent;
+ ptype = current->prompt ? current->prompt->type : P_UNKNOWN;
+ if (ptype != P_MENU)
+ current = current->parent;
+ display_tree_part();
+
+ if (current == &rootmenu)
+ gtk_widget_set_sensitive(back_btn, FALSE);
+}
+
+
+void on_load_clicked(GtkButton * button, gpointer user_data)
+{
+ on_load1_activate(NULL, user_data);
+}
+
+
+void on_single_clicked(GtkButton * button, gpointer user_data)
+{
+ view_mode = SINGLE_VIEW;
+ gtk_widget_hide(tree1_w);
+ current = &rootmenu;
+ display_tree_part();
+}
+
+
+void on_split_clicked(GtkButton * button, gpointer user_data)
+{
+ gint w, h;
+ view_mode = SPLIT_VIEW;
+ gtk_widget_show(tree1_w);
+ gtk_window_get_default_size(GTK_WINDOW(main_wnd), &w, &h);
+ gtk_paned_set_position(GTK_PANED(hpaned), w / 2);
+ if (tree2)
+ gtk_tree_store_clear(tree2);
+ display_list();
+
+ /* Disable back btn, like in full mode. */
+ gtk_widget_set_sensitive(back_btn, FALSE);
+}
+
+
+void on_full_clicked(GtkButton * button, gpointer user_data)
+{
+ view_mode = FULL_VIEW;
+ gtk_widget_hide(tree1_w);
+ if (tree2)
+ gtk_tree_store_clear(tree2);
+ display_tree(&rootmenu);
+ gtk_widget_set_sensitive(back_btn, FALSE);
+}
+
+
+void on_collapse_clicked(GtkButton * button, gpointer user_data)
+{
+ gtk_tree_view_collapse_all(GTK_TREE_VIEW(tree2_w));
+}
+
+
+void on_expand_clicked(GtkButton * button, gpointer user_data)
+{
+ gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w));
+}
+
+
+/* CTree Callbacks */
+
+/* Change hex/int/string value in the cell */
+static void renderer_edited(GtkCellRendererText * cell,
+ const gchar * path_string,
+ const gchar * new_text, gpointer user_data)
+{
+ GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
+ GtkTreeIter iter;
+ const char *old_def, *new_def;
+ struct menu *menu;
+ struct symbol *sym;
+
+ if (!gtk_tree_model_get_iter(model2, &iter, path))
+ return;
+
+ gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
+ sym = menu->sym;
+
+ gtk_tree_model_get(model2, &iter, COL_VALUE, &old_def, -1);
+ new_def = new_text;
+
+ sym_set_string_value(sym, new_def);
+
+ update_tree(&rootmenu, NULL);
+
+ gtk_tree_path_free(path);
+}
+
+/* Change the value of a symbol and update the tree */
+static void change_sym_value(struct menu *menu, gint col)
+{
+ struct symbol *sym = menu->sym;
+ tristate newval;
+
+ if (!sym)
+ return;
+
+ if (col == COL_NO)
+ newval = no;
+ else if (col == COL_MOD)
+ newval = mod;
+ else if (col == COL_YES)
+ newval = yes;
+ else
+ return;
+
+ switch (sym_get_type(sym)) {
+ case S_BOOLEAN:
+ case S_TRISTATE:
+ if (!sym_tristate_within_range(sym, newval))
+ newval = yes;
+ sym_set_tristate_value(sym, newval);
+ if (view_mode == FULL_VIEW)
+ update_tree(&rootmenu, NULL);
+ else if (view_mode == SPLIT_VIEW) {
+ update_tree(browsed, NULL);
+ display_list();
+ }
+ else if (view_mode == SINGLE_VIEW)
+ display_tree_part(); //fixme: keep exp/coll
+ break;
+ case S_INT:
+ case S_HEX:
+ case S_STRING:
+ default:
+ break;
+ }
+}
+
+static void toggle_sym_value(struct menu *menu)
+{
+ if (!menu->sym)
+ return;
+
+ sym_toggle_tristate_value(menu->sym);
+ if (view_mode == FULL_VIEW)
+ update_tree(&rootmenu, NULL);
+ else if (view_mode == SPLIT_VIEW) {
+ update_tree(browsed, NULL);
+ display_list();
+ }
+ else if (view_mode == SINGLE_VIEW)
+ display_tree_part(); //fixme: keep exp/coll
+}
+
+static gint column2index(GtkTreeViewColumn * column)
+{
+ gint i;
+
+ for (i = 0; i < COL_NUMBER; i++) {
+ GtkTreeViewColumn *col;
+
+ col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), i);
+ if (col == column)
+ return i;
+ }
+
+ return -1;
+}
+
+
+/* User click: update choice (full) or goes down (single) */
+gboolean
+on_treeview2_button_press_event(GtkWidget * widget,
+ GdkEventButton * event, gpointer user_data)
+{
+ GtkTreeView *view = GTK_TREE_VIEW(widget);
+ GtkTreePath *path;
+ GtkTreeViewColumn *column;
+ GtkTreeIter iter;
+ struct menu *menu;
+ gint col;
+
+#if GTK_CHECK_VERSION(2,1,4) // bug in ctree with earlier version of GTK
+ gint tx = (gint) event->x;
+ gint ty = (gint) event->y;
+ gint cx, cy;
+
+ gtk_tree_view_get_path_at_pos(view, tx, ty, &path, &column, &cx,
+ &cy);
+#else
+ gtk_tree_view_get_cursor(view, &path, &column);
+#endif
+ if (path == NULL)
+ return FALSE;
+
+ if (!gtk_tree_model_get_iter(model2, &iter, path))
+ return FALSE;
+ gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
+
+ col = column2index(column);
+ if (event->type == GDK_2BUTTON_PRESS) {
+ enum prop_type ptype;
+ ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
+
+ if (ptype == P_MENU && view_mode != FULL_VIEW && col == COL_OPTION) {
+ // goes down into menu
+ current = menu;
+ display_tree_part();
+ gtk_widget_set_sensitive(back_btn, TRUE);
+ } else if ((col == COL_OPTION)) {
+ toggle_sym_value(menu);
+ gtk_tree_view_expand_row(view, path, TRUE);
+ }
+ } else {
+ if (col == COL_VALUE) {
+ toggle_sym_value(menu);
+ gtk_tree_view_expand_row(view, path, TRUE);
+ } else if (col == COL_NO || col == COL_MOD
+ || col == COL_YES) {
+ change_sym_value(menu, col);
+ gtk_tree_view_expand_row(view, path, TRUE);
+ }
+ }
+
+ return FALSE;
+}
+
+/* Key pressed: update choice */
+gboolean
+on_treeview2_key_press_event(GtkWidget * widget,
+ GdkEventKey * event, gpointer user_data)
+{
+ GtkTreeView *view = GTK_TREE_VIEW(widget);
+ GtkTreePath *path;
+ GtkTreeViewColumn *column;
+ GtkTreeIter iter;
+ struct menu *menu;
+ gint col;
+
+ gtk_tree_view_get_cursor(view, &path, &column);
+ if (path == NULL)
+ return FALSE;
+
+ if (event->keyval == GDK_space) {
+ if (gtk_tree_view_row_expanded(view, path))
+ gtk_tree_view_collapse_row(view, path);
+ else
+ gtk_tree_view_expand_row(view, path, FALSE);
+ return TRUE;
+ }
+ if (event->keyval == GDK_KP_Enter) {
+ }
+ if (widget == tree1_w)
+ return FALSE;
+
+ gtk_tree_model_get_iter(model2, &iter, path);
+ gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
+
+ if (!strcasecmp(event->string, "n"))
+ col = COL_NO;
+ else if (!strcasecmp(event->string, "m"))
+ col = COL_MOD;
+ else if (!strcasecmp(event->string, "y"))
+ col = COL_YES;
+ else
+ col = -1;
+ change_sym_value(menu, col);
+
+ return FALSE;
+}
+
+
+/* Row selection changed: update help */
+void
+on_treeview2_cursor_changed(GtkTreeView * treeview, gpointer user_data)
+{
+ GtkTreeSelection *selection;
+ GtkTreeIter iter;
+ struct menu *menu;
+
+ selection = gtk_tree_view_get_selection(treeview);
+ if (gtk_tree_selection_get_selected(selection, &model2, &iter)) {
+ gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
+ text_insert_help(menu);
+ }
+}
+
+
+/* User click: display sub-tree in the right frame. */
+gboolean
+on_treeview1_button_press_event(GtkWidget * widget,
+ GdkEventButton * event, gpointer user_data)
+{
+ GtkTreeView *view = GTK_TREE_VIEW(widget);
+ GtkTreePath *path;
+ GtkTreeViewColumn *column;
+ GtkTreeIter iter;
+ struct menu *menu;
+
+ gint tx = (gint) event->x;
+ gint ty = (gint) event->y;
+ gint cx, cy;
+
+ gtk_tree_view_get_path_at_pos(view, tx, ty, &path, &column, &cx,
+ &cy);
+ if (path == NULL)
+ return FALSE;
+
+ gtk_tree_model_get_iter(model1, &iter, path);
+ gtk_tree_model_get(model1, &iter, COL_MENU, &menu, -1);
+
+ if (event->type == GDK_2BUTTON_PRESS) {
+ toggle_sym_value(menu);
+ current = menu;
+ display_tree_part();
+ } else {
+ browsed = menu;
+ display_tree_part();
+ }
+
+ gtk_widget_realize(tree2_w);
+ gtk_tree_view_set_cursor(view, path, NULL, FALSE);
+ gtk_widget_grab_focus(tree2_w);
+
+ return FALSE;
+}
+
+
+/* Fill a row of strings */
+static gchar **fill_row(struct menu *menu)
+{
+ static gchar *row[COL_NUMBER];
+ struct symbol *sym = menu->sym;
+ const char *def;
+ int stype;
+ tristate val;
+ enum prop_type ptype;
+ int i;
+
+ for (i = COL_OPTION; i <= COL_COLOR; i++)
+ g_free(row[i]);
+ bzero(row, sizeof(row));
+
+ row[COL_OPTION] =
+ g_strdup_printf("%s %s", _(menu_get_prompt(menu)),
+ sym && !sym_has_value(sym) ? "(NEW)" : "");
+
+ if (opt_mode == OPT_ALL && !menu_is_visible(menu))
+ row[COL_COLOR] = g_strdup("DarkGray");
+ else if (opt_mode == OPT_PROMPT &&
+ menu_has_prompt(menu) && !menu_is_visible(menu))
+ row[COL_COLOR] = g_strdup("DarkGray");
+ else
+ row[COL_COLOR] = g_strdup("Black");
+
+ ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
+ switch (ptype) {
+ case P_MENU:
+ row[COL_PIXBUF] = (gchar *) xpm_menu;
+ if (view_mode == SINGLE_VIEW)
+ row[COL_PIXVIS] = GINT_TO_POINTER(TRUE);
+ row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
+ break;
+ case P_COMMENT:
+ row[COL_PIXBUF] = (gchar *) xpm_void;
+ row[COL_PIXVIS] = GINT_TO_POINTER(FALSE);
+ row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
+ break;
+ default:
+ row[COL_PIXBUF] = (gchar *) xpm_void;
+ row[COL_PIXVIS] = GINT_TO_POINTER(FALSE);
+ row[COL_BTNVIS] = GINT_TO_POINTER(TRUE);
+ break;
+ }
+
+ if (!sym)
+ return row;
+ row[COL_NAME] = g_strdup(sym->name);
+
+ sym_calc_value(sym);
+ sym->flags &= ~SYMBOL_CHANGED;
+
+ if (sym_is_choice(sym)) { // parse childs for getting final value
+ struct menu *child;
+ struct symbol *def_sym = sym_get_choice_value(sym);
+ struct menu *def_menu = NULL;
+
+ row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
+
+ for (child = menu->list; child; child = child->next) {
+ if (menu_is_visible(child)
+ && child->sym == def_sym)
+ def_menu = child;
+ }
+
+ if (def_menu)
+ row[COL_VALUE] =
+ g_strdup(_(menu_get_prompt(def_menu)));
+ }
+ if (sym->flags & SYMBOL_CHOICEVAL)
+ row[COL_BTNRAD] = GINT_TO_POINTER(TRUE);
+
+ stype = sym_get_type(sym);
+ switch (stype) {
+ case S_BOOLEAN:
+ if (GPOINTER_TO_INT(row[COL_PIXVIS]) == FALSE)
+ row[COL_BTNVIS] = GINT_TO_POINTER(TRUE);
+ if (sym_is_choice(sym))
+ break;
+ /* fall through */
+ case S_TRISTATE:
+ val = sym_get_tristate_value(sym);
+ switch (val) {
+ case no:
+ row[COL_NO] = g_strdup("N");
+ row[COL_VALUE] = g_strdup("N");
+ row[COL_BTNACT] = GINT_TO_POINTER(FALSE);
+ row[COL_BTNINC] = GINT_TO_POINTER(FALSE);
+ break;
+ case mod:
+ row[COL_MOD] = g_strdup("M");
+ row[COL_VALUE] = g_strdup("M");
+ row[COL_BTNINC] = GINT_TO_POINTER(TRUE);
+ break;
+ case yes:
+ row[COL_YES] = g_strdup("Y");
+ row[COL_VALUE] = g_strdup("Y");
+ row[COL_BTNACT] = GINT_TO_POINTER(TRUE);
+ row[COL_BTNINC] = GINT_TO_POINTER(FALSE);
+ break;
+ }
+
+ if (val != no && sym_tristate_within_range(sym, no))
+ row[COL_NO] = g_strdup("_");
+ if (val != mod && sym_tristate_within_range(sym, mod))
+ row[COL_MOD] = g_strdup("_");
+ if (val != yes && sym_tristate_within_range(sym, yes))
+ row[COL_YES] = g_strdup("_");
+ break;
+ case S_INT:
+ case S_HEX:
+ case S_STRING:
+ def = sym_get_string_value(sym);
+ row[COL_VALUE] = g_strdup(def);
+ row[COL_EDIT] = GINT_TO_POINTER(TRUE);
+ row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
+ break;
+ }
+
+ return row;
+}
+
+
+/* Set the node content with a row of strings */
+static void set_node(GtkTreeIter * node, struct menu *menu, gchar ** row)
+{
+ GdkColor color;
+ gboolean success;
+ GdkPixbuf *pix;
+
+ pix = gdk_pixbuf_new_from_xpm_data((const char **)
+ row[COL_PIXBUF]);
+
+ gdk_color_parse(row[COL_COLOR], &color);
+ gdk_colormap_alloc_colors(gdk_colormap_get_system(), &color, 1,
+ FALSE, FALSE, &success);
+
+ gtk_tree_store_set(tree, node,
+ COL_OPTION, row[COL_OPTION],
+ COL_NAME, row[COL_NAME],
+ COL_NO, row[COL_NO],
+ COL_MOD, row[COL_MOD],
+ COL_YES, row[COL_YES],
+ COL_VALUE, row[COL_VALUE],
+ COL_MENU, (gpointer) menu,
+ COL_COLOR, &color,
+ COL_EDIT, GPOINTER_TO_INT(row[COL_EDIT]),
+ COL_PIXBUF, pix,
+ COL_PIXVIS, GPOINTER_TO_INT(row[COL_PIXVIS]),
+ COL_BTNVIS, GPOINTER_TO_INT(row[COL_BTNVIS]),
+ COL_BTNACT, GPOINTER_TO_INT(row[COL_BTNACT]),
+ COL_BTNINC, GPOINTER_TO_INT(row[COL_BTNINC]),
+ COL_BTNRAD, GPOINTER_TO_INT(row[COL_BTNRAD]),
+ -1);
+
+ g_object_unref(pix);
+}
+
+
+/* Add a node to the tree */
+static void place_node(struct menu *menu, char **row)
+{
+ GtkTreeIter *parent = parents[indent - 1];
+ GtkTreeIter *node = parents[indent];
+
+ gtk_tree_store_append(tree, node, parent);
+ set_node(node, menu, row);
+}
+
+
+/* Find a node in the GTK+ tree */
+static GtkTreeIter found;
+
+/*
+ * Find a menu in the GtkTree starting at parent.
+ */
+GtkTreeIter *gtktree_iter_find_node(GtkTreeIter * parent,
+ struct menu *tofind)
+{
+ GtkTreeIter iter;
+ GtkTreeIter *child = &iter;
+ gboolean valid;
+ GtkTreeIter *ret;
+
+ valid = gtk_tree_model_iter_children(model2, child, parent);
+ while (valid) {
+ struct menu *menu;
+
+ gtk_tree_model_get(model2, child, 6, &menu, -1);
+
+ if (menu == tofind) {
+ memcpy(&found, child, sizeof(GtkTreeIter));
+ return &found;
+ }
+
+ ret = gtktree_iter_find_node(child, tofind);
+ if (ret)
+ return ret;
+
+ valid = gtk_tree_model_iter_next(model2, child);
+ }
+
+ return NULL;
+}
+
+
+/*
+ * Update the tree by adding/removing entries
+ * Does not change other nodes
+ */
+static void update_tree(struct menu *src, GtkTreeIter * dst)
+{
+ struct menu *child1;
+ GtkTreeIter iter, tmp;
+ GtkTreeIter *child2 = &iter;
+ gboolean valid;
+ GtkTreeIter *sibling;
+ struct symbol *sym;
+ struct menu *menu1, *menu2;
+
+ if (src == &rootmenu)
+ indent = 1;
+
+ valid = gtk_tree_model_iter_children(model2, child2, dst);
+ for (child1 = src->list; child1; child1 = child1->next) {
+
+ sym = child1->sym;
+
+ reparse:
+ menu1 = child1;
+ if (valid)
+ gtk_tree_model_get(model2, child2, COL_MENU,
+ &menu2, -1);
+ else
+ menu2 = NULL; // force adding of a first child
+
+#ifdef DEBUG
+ printf("%*c%s | %s\n", indent, ' ',
+ menu1 ? menu_get_prompt(menu1) : "nil",
+ menu2 ? menu_get_prompt(menu2) : "nil");
+#endif
+
+ if ((opt_mode == OPT_NORMAL && !menu_is_visible(child1)) ||
+ (opt_mode == OPT_PROMPT && !menu_has_prompt(child1)) ||
+ (opt_mode == OPT_ALL && !menu_get_prompt(child1))) {
+
+ /* remove node */
+ if (gtktree_iter_find_node(dst, menu1) != NULL) {
+ memcpy(&tmp, child2, sizeof(GtkTreeIter));
+ valid = gtk_tree_model_iter_next(model2,
+ child2);
+ gtk_tree_store_remove(tree2, &tmp);
+ if (!valid)
+ return; /* next parent */
+ else
+ goto reparse; /* next child */
+ } else
+ continue;
+ }
+
+ if (menu1 != menu2) {
+ if (gtktree_iter_find_node(dst, menu1) == NULL) { // add node
+ if (!valid && !menu2)
+ sibling = NULL;
+ else
+ sibling = child2;
+ gtk_tree_store_insert_before(tree2,
+ child2,
+ dst, sibling);
+ set_node(child2, menu1, fill_row(menu1));
+ if (menu2 == NULL)
+ valid = TRUE;
+ } else { // remove node
+ memcpy(&tmp, child2, sizeof(GtkTreeIter));
+ valid = gtk_tree_model_iter_next(model2,
+ child2);
+ gtk_tree_store_remove(tree2, &tmp);
+ if (!valid)
+ return; // next parent
+ else
+ goto reparse; // next child
+ }
+ } else if (sym && (sym->flags & SYMBOL_CHANGED)) {
+ set_node(child2, menu1, fill_row(menu1));
+ }
+
+ indent++;
+ update_tree(child1, child2);
+ indent--;
+
+ valid = gtk_tree_model_iter_next(model2, child2);
+ }
+}
+
+
+/* Display the whole tree (single/split/full view) */
+static void display_tree(struct menu *menu)
+{
+ struct symbol *sym;
+ struct property *prop;
+ struct menu *child;
+ enum prop_type ptype;
+
+ if (menu == &rootmenu) {
+ indent = 1;
+ current = &rootmenu;
+ }
+
+ for (child = menu->list; child; child = child->next) {
+ prop = child->prompt;
+ sym = child->sym;
+ ptype = prop ? prop->type : P_UNKNOWN;
+
+ if (sym)
+ sym->flags &= ~SYMBOL_CHANGED;
+
+ if ((view_mode == SPLIT_VIEW)
+ && !(child->flags & MENU_ROOT) && (tree == tree1))
+ continue;
+
+ if ((view_mode == SPLIT_VIEW) && (child->flags & MENU_ROOT)
+ && (tree == tree2))
+ continue;
+
+ if ((opt_mode == OPT_NORMAL && menu_is_visible(child)) ||
+ (opt_mode == OPT_PROMPT && menu_has_prompt(child)) ||
+ (opt_mode == OPT_ALL && menu_get_prompt(child)))
+ place_node(child, fill_row(child));
+#ifdef DEBUG
+ printf("%*c%s: ", indent, ' ', menu_get_prompt(child));
+ printf("%s", child->flags & MENU_ROOT ? "rootmenu | " : "");
+ printf("%s", prop_get_type_name(ptype));
+ printf(" | ");
+ if (sym) {
+ printf("%s", sym_type_name(sym->type));
+ printf(" | ");
+ printf("%s", dbg_sym_flags(sym->flags));
+ printf("\n");
+ } else
+ printf("\n");
+#endif
+ if ((view_mode != FULL_VIEW) && (ptype == P_MENU)
+ && (tree == tree2))
+ continue;
+/*
+ if (((menu != &rootmenu) && !(menu->flags & MENU_ROOT))
+ || (view_mode == FULL_VIEW)
+ || (view_mode == SPLIT_VIEW))*/
+
+ /* Change paned position if the view is not in 'split mode' */
+ if (view_mode == SINGLE_VIEW || view_mode == FULL_VIEW) {
+ gtk_paned_set_position(GTK_PANED(hpaned), 0);
+ }
+
+ if (((view_mode == SINGLE_VIEW) && (menu->flags & MENU_ROOT))
+ || (view_mode == FULL_VIEW)
+ || (view_mode == SPLIT_VIEW)) {
+ indent++;
+ display_tree(child);
+ indent--;
+ }
+ }
+}
+
+/* Display a part of the tree starting at current node (single/split view) */
+static void display_tree_part(void)
+{
+ if (tree2)
+ gtk_tree_store_clear(tree2);
+ if (view_mode == SINGLE_VIEW)
+ display_tree(current);
+ else if (view_mode == SPLIT_VIEW)
+ display_tree(browsed);
+ gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w));
+}
+
+/* Display the list in the left frame (split view) */
+static void display_list(void)
+{
+ if (tree1)
+ gtk_tree_store_clear(tree1);
+
+ tree = tree1;
+ display_tree(&rootmenu);
+ gtk_tree_view_expand_all(GTK_TREE_VIEW(tree1_w));
+ tree = tree2;
+}
+
+void fixup_rootmenu(struct menu *menu)
+{
+ struct menu *child;
+ static int menu_cnt = 0;
+
+ menu->flags |= MENU_ROOT;
+ for (child = menu->list; child; child = child->next) {
+ if (child->prompt && child->prompt->type == P_MENU) {
+ menu_cnt++;
+ fixup_rootmenu(child);
+ menu_cnt--;
+ } else if (!menu_cnt)
+ fixup_rootmenu(child);
+ }
+}
+
+
+/* Main */
+int main(int ac, char *av[])
+{
+ const char *name;
+ char *env;
+ gchar *glade_file;
+
+ bindtextdomain(PACKAGE, LOCALEDIR);
+ bind_textdomain_codeset(PACKAGE, "UTF-8");
+ textdomain(PACKAGE);
+
+ /* GTK stuffs */
+ gtk_set_locale();
+ gtk_init(&ac, &av);
+ glade_init();
+
+ //add_pixmap_directory (PACKAGE_DATA_DIR "/" PACKAGE "/pixmaps");
+ //add_pixmap_directory (PACKAGE_SOURCE_DIR "/pixmaps");
+
+ /* Determine GUI path */
+ env = getenv(SRCTREE);
+ if (env)
+ glade_file = g_strconcat(env, "/scripts/kconfig/gconf.glade", NULL);
+ else if (av[0][0] == '/')
+ glade_file = g_strconcat(av[0], ".glade", NULL);
+ else
+ glade_file = g_strconcat(g_get_current_dir(), "/", av[0], ".glade", NULL);
+
+ /* Conf stuffs */
+ if (ac > 1 && av[1][0] == '-') {
+ switch (av[1][1]) {
+ case 'a':
+ //showAll = 1;
+ break;
+ case 'h':
+ case '?':
+ printf("%s <config>\n", av[0]);
+ exit(0);
+ }
+ name = av[2];
+ } else
+ name = av[1];
+
+ conf_parse(name);
+ fixup_rootmenu(&rootmenu);
+ conf_read(NULL);
+
+ /* Load the interface and connect signals */
+ init_main_window(glade_file);
+ init_tree_model();
+ init_left_tree();
+ init_right_tree();
+
+ switch (view_mode) {
+ case SINGLE_VIEW:
+ display_tree_part();
+ break;
+ case SPLIT_VIEW:
+ display_list();
+ break;
+ case FULL_VIEW:
+ display_tree(&rootmenu);
+ break;
+ }
+
+ gtk_main();
+
+ return 0;
+}
+
+static void conf_changed(void)
+{
+ bool changed = conf_get_changed();
+ gtk_widget_set_sensitive(save_btn, changed);
+ gtk_widget_set_sensitive(save_menu_item, changed);
+}
--- /dev/null
+<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
+
+<glade-interface>
+
+<widget class="GtkWindow" id="window1">
+ <property name="visible">True</property>
+ <property name="title" translatable="yes">Gtk Kernel Configurator</property>
+ <property name="type">GTK_WINDOW_TOPLEVEL</property>
+ <property name="window_position">GTK_WIN_POS_NONE</property>
+ <property name="modal">False</property>
+ <property name="default_width">640</property>
+ <property name="default_height">480</property>
+ <property name="resizable">True</property>
+ <property name="destroy_with_parent">False</property>
+ <property name="decorated">True</property>
+ <property name="skip_taskbar_hint">False</property>
+ <property name="skip_pager_hint">False</property>
+ <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property>
+ <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
+ <signal name="destroy" handler="on_window1_destroy" object="window1"/>
+ <signal name="size_request" handler="on_window1_size_request" object="vpaned1" last_modification_time="Fri, 11 Jan 2002 16:17:11 GMT"/>
+ <signal name="delete_event" handler="on_window1_delete_event" object="window1" last_modification_time="Sun, 09 Mar 2003 19:42:46 GMT"/>
+
+ <child>
+ <widget class="GtkVBox" id="vbox1">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkMenuBar" id="menubar1">
+ <property name="visible">True</property>
+
+ <child>
+ <widget class="GtkMenuItem" id="file1">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_File</property>
+ <property name="use_underline">True</property>
+
+ <child>
+ <widget class="GtkMenu" id="file1_menu">
+
+ <child>
+ <widget class="GtkImageMenuItem" id="load1">
+ <property name="visible">True</property>
+ <property name="tooltip" translatable="yes">Load a config file</property>
+ <property name="label" translatable="yes">_Load</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="on_load1_activate"/>
+ <accelerator key="L" modifiers="GDK_CONTROL_MASK" signal="activate"/>
+
+ <child internal-child="image">
+ <widget class="GtkImage" id="image39">
+ <property name="visible">True</property>
+ <property name="stock">gtk-open</property>
+ <property name="icon_size">1</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkImageMenuItem" id="save1">
+ <property name="visible">True</property>
+ <property name="tooltip" translatable="yes">Save the config in .config</property>
+ <property name="label" translatable="yes">_Save</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="on_save_activate"/>
+ <accelerator key="S" modifiers="GDK_CONTROL_MASK" signal="activate"/>
+
+ <child internal-child="image">
+ <widget class="GtkImage" id="image40">
+ <property name="visible">True</property>
+ <property name="stock">gtk-save</property>
+ <property name="icon_size">1</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkImageMenuItem" id="save_as1">
+ <property name="visible">True</property>
+ <property name="tooltip" translatable="yes">Save the config in a file</property>
+ <property name="label" translatable="yes">Save _as</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="on_save_as1_activate"/>
+
+ <child internal-child="image">
+ <widget class="GtkImage" id="image41">
+ <property name="visible">True</property>
+ <property name="stock">gtk-save-as</property>
+ <property name="icon_size">1</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkSeparatorMenuItem" id="separator1">
+ <property name="visible">True</property>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkImageMenuItem" id="quit1">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Quit</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="on_quit1_activate"/>
+ <accelerator key="Q" modifiers="GDK_CONTROL_MASK" signal="activate"/>
+
+ <child internal-child="image">
+ <widget class="GtkImage" id="image42">
+ <property name="visible">True</property>
+ <property name="stock">gtk-quit</property>
+ <property name="icon_size">1</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkMenuItem" id="options1">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Options</property>
+ <property name="use_underline">True</property>
+
+ <child>
+ <widget class="GtkMenu" id="options1_menu">
+
+ <child>
+ <widget class="GtkCheckMenuItem" id="show_name1">
+ <property name="visible">True</property>
+ <property name="tooltip" translatable="yes">Show name</property>
+ <property name="label" translatable="yes">Show _name</property>
+ <property name="use_underline">True</property>
+ <property name="active">False</property>
+ <signal name="activate" handler="on_show_name1_activate"/>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkCheckMenuItem" id="show_range1">
+ <property name="visible">True</property>
+ <property name="tooltip" translatable="yes">Show range (Y/M/N)</property>
+ <property name="label" translatable="yes">Show _range</property>
+ <property name="use_underline">True</property>
+ <property name="active">False</property>
+ <signal name="activate" handler="on_show_range1_activate"/>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkCheckMenuItem" id="show_data1">
+ <property name="visible">True</property>
+ <property name="tooltip" translatable="yes">Show value of the option</property>
+ <property name="label" translatable="yes">Show _data</property>
+ <property name="use_underline">True</property>
+ <property name="active">False</property>
+ <signal name="activate" handler="on_show_data1_activate"/>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkSeparatorMenuItem" id="separator2">
+ <property name="visible">True</property>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkRadioMenuItem" id="set_option_mode1">
+ <property name="visible">True</property>
+ <property name="tooltip" translatable="yes">Show normal options</property>
+ <property name="label" translatable="yes">Show normal options</property>
+ <property name="use_underline">True</property>
+ <property name="active">True</property>
+ <signal name="activate" handler="on_set_option_mode1_activate"/>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkRadioMenuItem" id="set_option_mode2">
+ <property name="visible">True</property>
+ <property name="tooltip" translatable="yes">Show all options</property>
+ <property name="label" translatable="yes">Show all _options</property>
+ <property name="use_underline">True</property>
+ <property name="active">False</property>
+ <property name="group">set_option_mode1</property>
+ <signal name="activate" handler="on_set_option_mode2_activate"/>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkRadioMenuItem" id="set_option_mode3">
+ <property name="visible">True</property>
+ <property name="tooltip" translatable="yes">Show all options with prompts</property>
+ <property name="label" translatable="yes">Show all prompt options</property>
+ <property name="use_underline">True</property>
+ <property name="active">False</property>
+ <property name="group">set_option_mode1</property>
+ <signal name="activate" handler="on_set_option_mode3_activate"/>
+ </widget>
+ </child>
+
+ </widget>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkMenuItem" id="help1">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Help</property>
+ <property name="use_underline">True</property>
+
+ <child>
+ <widget class="GtkMenu" id="help1_menu">
+
+ <child>
+ <widget class="GtkImageMenuItem" id="introduction1">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Introduction</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="on_introduction1_activate" last_modification_time="Fri, 15 Nov 2002 20:26:30 GMT"/>
+ <accelerator key="I" modifiers="GDK_CONTROL_MASK" signal="activate"/>
+
+ <child internal-child="image">
+ <widget class="GtkImage" id="image43">
+ <property name="visible">True</property>
+ <property name="stock">gtk-dialog-question</property>
+ <property name="icon_size">1</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkImageMenuItem" id="about1">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_About</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="on_about1_activate" last_modification_time="Fri, 15 Nov 2002 20:26:30 GMT"/>
+ <accelerator key="A" modifiers="GDK_CONTROL_MASK" signal="activate"/>
+
+ <child internal-child="image">
+ <widget class="GtkImage" id="image44">
+ <property name="visible">True</property>
+ <property name="stock">gtk-properties</property>
+ <property name="icon_size">1</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkImageMenuItem" id="license1">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_License</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="on_license1_activate" last_modification_time="Fri, 15 Nov 2002 20:26:30 GMT"/>
+
+ <child internal-child="image">
+ <widget class="GtkImage" id="image45">
+ <property name="visible">True</property>
+ <property name="stock">gtk-justify-fill</property>
+ <property name="icon_size">1</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkHandleBox" id="handlebox1">
+ <property name="visible">True</property>
+ <property name="shadow_type">GTK_SHADOW_OUT</property>
+ <property name="handle_position">GTK_POS_LEFT</property>
+ <property name="snap_edge">GTK_POS_TOP</property>
+
+ <child>
+ <widget class="GtkToolbar" id="toolbar1">
+ <property name="visible">True</property>
+ <property name="orientation">GTK_ORIENTATION_HORIZONTAL</property>
+ <property name="toolbar_style">GTK_TOOLBAR_BOTH</property>
+ <property name="tooltips">True</property>
+ <property name="show_arrow">True</property>
+
+ <child>
+ <widget class="GtkToolButton" id="button1">
+ <property name="visible">True</property>
+ <property name="tooltip" translatable="yes">Goes up of one level (single view)</property>
+ <property name="label" translatable="yes">Back</property>
+ <property name="use_underline">True</property>
+ <property name="stock_id">gtk-undo</property>
+ <property name="visible_horizontal">True</property>
+ <property name="visible_vertical">True</property>
+ <property name="is_important">False</property>
+ <signal name="clicked" handler="on_back_clicked"/>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkToolItem" id="toolitem1">
+ <property name="visible">True</property>
+ <property name="visible_horizontal">True</property>
+ <property name="visible_vertical">True</property>
+ <property name="is_important">False</property>
+
+ <child>
+ <widget class="GtkVSeparator" id="vseparator1">
+ <property name="visible">True</property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkToolButton" id="button2">
+ <property name="visible">True</property>
+ <property name="tooltip" translatable="yes">Load a config file</property>
+ <property name="label" translatable="yes">Load</property>
+ <property name="use_underline">True</property>
+ <property name="stock_id">gtk-open</property>
+ <property name="visible_horizontal">True</property>
+ <property name="visible_vertical">True</property>
+ <property name="is_important">False</property>
+ <signal name="clicked" handler="on_load_clicked"/>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkToolButton" id="button3">
+ <property name="visible">True</property>
+ <property name="tooltip" translatable="yes">Save a config file</property>
+ <property name="label" translatable="yes">Save</property>
+ <property name="use_underline">True</property>
+ <property name="stock_id">gtk-save</property>
+ <property name="visible_horizontal">True</property>
+ <property name="visible_vertical">True</property>
+ <property name="is_important">False</property>
+ <signal name="clicked" handler="on_save_activate"/>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkToolItem" id="toolitem2">
+ <property name="visible">True</property>
+ <property name="visible_horizontal">True</property>
+ <property name="visible_vertical">True</property>
+ <property name="is_important">False</property>
+
+ <child>
+ <widget class="GtkVSeparator" id="vseparator2">
+ <property name="visible">True</property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkToolButton" id="button4">
+ <property name="visible">True</property>
+ <property name="tooltip" translatable="yes">Single view</property>
+ <property name="label" translatable="yes">Single</property>
+ <property name="use_underline">True</property>
+ <property name="stock_id">gtk-missing-image</property>
+ <property name="visible_horizontal">True</property>
+ <property name="visible_vertical">True</property>
+ <property name="is_important">False</property>
+ <signal name="clicked" handler="on_single_clicked" last_modification_time="Sun, 12 Jan 2003 14:28:39 GMT"/>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkToolButton" id="button5">
+ <property name="visible">True</property>
+ <property name="tooltip" translatable="yes">Split view</property>
+ <property name="label" translatable="yes">Split</property>
+ <property name="use_underline">True</property>
+ <property name="stock_id">gtk-missing-image</property>
+ <property name="visible_horizontal">True</property>
+ <property name="visible_vertical">True</property>
+ <property name="is_important">False</property>
+ <signal name="clicked" handler="on_split_clicked" last_modification_time="Sun, 12 Jan 2003 14:28:45 GMT"/>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkToolButton" id="button6">
+ <property name="visible">True</property>
+ <property name="tooltip" translatable="yes">Full view</property>
+ <property name="label" translatable="yes">Full</property>
+ <property name="use_underline">True</property>
+ <property name="stock_id">gtk-missing-image</property>
+ <property name="visible_horizontal">True</property>
+ <property name="visible_vertical">True</property>
+ <property name="is_important">False</property>
+ <signal name="clicked" handler="on_full_clicked" last_modification_time="Sun, 12 Jan 2003 14:28:50 GMT"/>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkToolItem" id="toolitem3">
+ <property name="visible">True</property>
+ <property name="visible_horizontal">True</property>
+ <property name="visible_vertical">True</property>
+ <property name="is_important">False</property>
+
+ <child>
+ <widget class="GtkVSeparator" id="vseparator3">
+ <property name="visible">True</property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkToolButton" id="button7">
+ <property name="visible">True</property>
+ <property name="tooltip" translatable="yes">Collapse the whole tree in the right frame</property>
+ <property name="label" translatable="yes">Collapse</property>
+ <property name="use_underline">True</property>
+ <property name="stock_id">gtk-remove</property>
+ <property name="visible_horizontal">True</property>
+ <property name="visible_vertical">True</property>
+ <property name="is_important">False</property>
+ <signal name="clicked" handler="on_collapse_clicked"/>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkToolButton" id="button8">
+ <property name="visible">True</property>
+ <property name="tooltip" translatable="yes">Expand the whole tree in the right frame</property>
+ <property name="label" translatable="yes">Expand</property>
+ <property name="use_underline">True</property>
+ <property name="stock_id">gtk-add</property>
+ <property name="visible_horizontal">True</property>
+ <property name="visible_vertical">True</property>
+ <property name="is_important">False</property>
+ <signal name="clicked" handler="on_expand_clicked"/>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkHPaned" id="hpaned1">
+ <property name="width_request">1</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="position">0</property>
+
+ <child>
+ <widget class="GtkScrolledWindow" id="scrolledwindow1">
+ <property name="visible">True</property>
+ <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+ <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+ <property name="shadow_type">GTK_SHADOW_IN</property>
+ <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
+
+ <child>
+ <widget class="GtkTreeView" id="treeview1">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="headers_visible">True</property>
+ <property name="rules_hint">False</property>
+ <property name="reorderable">False</property>
+ <property name="enable_search">False</property>
+ <signal name="cursor_changed" handler="on_treeview2_cursor_changed" last_modification_time="Sun, 12 Jan 2003 15:58:22 GMT"/>
+ <signal name="button_press_event" handler="on_treeview1_button_press_event" last_modification_time="Sun, 12 Jan 2003 16:03:52 GMT"/>
+ <signal name="key_press_event" handler="on_treeview2_key_press_event" last_modification_time="Sun, 12 Jan 2003 16:11:44 GMT"/>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="shrink">True</property>
+ <property name="resize">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkVPaned" id="vpaned1">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="position">0</property>
+
+ <child>
+ <widget class="GtkScrolledWindow" id="scrolledwindow2">
+ <property name="visible">True</property>
+ <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+ <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+ <property name="shadow_type">GTK_SHADOW_IN</property>
+ <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
+
+ <child>
+ <widget class="GtkTreeView" id="treeview2">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="has_focus">True</property>
+ <property name="headers_visible">True</property>
+ <property name="rules_hint">False</property>
+ <property name="reorderable">False</property>
+ <property name="enable_search">False</property>
+ <signal name="cursor_changed" handler="on_treeview2_cursor_changed" last_modification_time="Sun, 12 Jan 2003 15:57:55 GMT"/>
+ <signal name="button_press_event" handler="on_treeview2_button_press_event" last_modification_time="Sun, 12 Jan 2003 15:57:58 GMT"/>
+ <signal name="key_press_event" handler="on_treeview2_key_press_event" last_modification_time="Sun, 12 Jan 2003 15:58:01 GMT"/>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="shrink">True</property>
+ <property name="resize">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkScrolledWindow" id="scrolledwindow3">
+ <property name="visible">True</property>
+ <property name="hscrollbar_policy">GTK_POLICY_NEVER</property>
+ <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+ <property name="shadow_type">GTK_SHADOW_IN</property>
+ <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
+
+ <child>
+ <widget class="GtkTextView" id="textview3">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="editable">False</property>
+ <property name="overwrite">False</property>
+ <property name="accepts_tab">True</property>
+ <property name="justification">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap_mode">GTK_WRAP_WORD</property>
+ <property name="cursor_visible">True</property>
+ <property name="pixels_above_lines">0</property>
+ <property name="pixels_below_lines">0</property>
+ <property name="pixels_inside_wrap">0</property>
+ <property name="left_margin">0</property>
+ <property name="right_margin">0</property>
+ <property name="indent">0</property>
+ <property name="text" translatable="yes">Sorry, no help available for this option yet.</property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="shrink">True</property>
+ <property name="resize">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="shrink">True</property>
+ <property name="resize">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+</widget>
+
+</glade-interface>
--- /dev/null
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+static const char *xpm_load[] = {
+"22 22 5 1",
+". c None",
+"# c #000000",
+"c c #838100",
+"a c #ffff00",
+"b c #ffffff",
+"......................",
+"......................",
+"......................",
+"............####....#.",
+"...........#....##.##.",
+"..................###.",
+".................####.",
+".####...........#####.",
+"#abab##########.......",
+"#babababababab#.......",
+"#ababababababa#.......",
+"#babababababab#.......",
+"#ababab###############",
+"#babab##cccccccccccc##",
+"#abab##cccccccccccc##.",
+"#bab##cccccccccccc##..",
+"#ab##cccccccccccc##...",
+"#b##cccccccccccc##....",
+"###cccccccccccc##.....",
+"##cccccccccccc##......",
+"###############.......",
+"......................"};
+
+static const char *xpm_save[] = {
+"22 22 5 1",
+". c None",
+"# c #000000",
+"a c #838100",
+"b c #c5c2c5",
+"c c #cdb6d5",
+"......................",
+".####################.",
+".#aa#bbbbbbbbbbbb#bb#.",
+".#aa#bbbbbbbbbbbb#bb#.",
+".#aa#bbbbbbbbbcbb####.",
+".#aa#bbbccbbbbbbb#aa#.",
+".#aa#bbbccbbbbbbb#aa#.",
+".#aa#bbbbbbbbbbbb#aa#.",
+".#aa#bbbbbbbbbbbb#aa#.",
+".#aa#bbbbbbbbbbbb#aa#.",
+".#aa#bbbbbbbbbbbb#aa#.",
+".#aaa############aaa#.",
+".#aaaaaaaaaaaaaaaaaa#.",
+".#aaaaaaaaaaaaaaaaaa#.",
+".#aaa#############aa#.",
+".#aaa#########bbb#aa#.",
+".#aaa#########bbb#aa#.",
+".#aaa#########bbb#aa#.",
+".#aaa#########bbb#aa#.",
+".#aaa#########bbb#aa#.",
+"..##################..",
+"......................"};
+
+static const char *xpm_back[] = {
+"22 22 3 1",
+". c None",
+"# c #000083",
+"a c #838183",
+"......................",
+"......................",
+"......................",
+"......................",
+"......................",
+"...........######a....",
+"..#......##########...",
+"..##...####......##a..",
+"..###.###.........##..",
+"..######..........##..",
+"..#####...........##..",
+"..######..........##..",
+"..#######.........##..",
+"..########.......##a..",
+"...............a###...",
+"...............###....",
+"......................",
+"......................",
+"......................",
+"......................",
+"......................",
+"......................"};
+
+static const char *xpm_tree_view[] = {
+"22 22 2 1",
+". c None",
+"# c #000000",
+"......................",
+"......................",
+"......#...............",
+"......#...............",
+"......#...............",
+"......#...............",
+"......#...............",
+"......########........",
+"......#...............",
+"......#...............",
+"......#...............",
+"......#...............",
+"......#...............",
+"......########........",
+"......#...............",
+"......#...............",
+"......#...............",
+"......#...............",
+"......#...............",
+"......########........",
+"......................",
+"......................"};
+
+static const char *xpm_single_view[] = {
+"22 22 2 1",
+". c None",
+"# c #000000",
+"......................",
+"......................",
+"..........#...........",
+"..........#...........",
+"..........#...........",
+"..........#...........",
+"..........#...........",
+"..........#...........",
+"..........#...........",
+"..........#...........",
+"..........#...........",
+"..........#...........",
+"..........#...........",
+"..........#...........",
+"..........#...........",
+"..........#...........",
+"..........#...........",
+"..........#...........",
+"..........#...........",
+"..........#...........",
+"......................",
+"......................"};
+
+static const char *xpm_split_view[] = {
+"22 22 2 1",
+". c None",
+"# c #000000",
+"......................",
+"......................",
+"......#......#........",
+"......#......#........",
+"......#......#........",
+"......#......#........",
+"......#......#........",
+"......#......#........",
+"......#......#........",
+"......#......#........",
+"......#......#........",
+"......#......#........",
+"......#......#........",
+"......#......#........",
+"......#......#........",
+"......#......#........",
+"......#......#........",
+"......#......#........",
+"......#......#........",
+"......#......#........",
+"......................",
+"......................"};
+
+static const char *xpm_symbol_no[] = {
+"12 12 2 1",
+" c white",
+". c black",
+" ",
+" .......... ",
+" . . ",
+" . . ",
+" . . ",
+" . . ",
+" . . ",
+" . . ",
+" . . ",
+" . . ",
+" .......... ",
+" "};
+
+static const char *xpm_symbol_mod[] = {
+"12 12 2 1",
+" c white",
+". c black",
+" ",
+" .......... ",
+" . . ",
+" . . ",
+" . .. . ",
+" . .... . ",
+" . .... . ",
+" . .. . ",
+" . . ",
+" . . ",
+" .......... ",
+" "};
+
+static const char *xpm_symbol_yes[] = {
+"12 12 2 1",
+" c white",
+". c black",
+" ",
+" .......... ",
+" . . ",
+" . . ",
+" . . . ",
+" . .. . ",
+" . . .. . ",
+" . .... . ",
+" . .. . ",
+" . . ",
+" .......... ",
+" "};
+
+static const char *xpm_choice_no[] = {
+"12 12 2 1",
+" c white",
+". c black",
+" ",
+" .... ",
+" .. .. ",
+" . . ",
+" . . ",
+" . . ",
+" . . ",
+" . . ",
+" . . ",
+" .. .. ",
+" .... ",
+" "};
+
+static const char *xpm_choice_yes[] = {
+"12 12 2 1",
+" c white",
+". c black",
+" ",
+" .... ",
+" .. .. ",
+" . . ",
+" . .. . ",
+" . .... . ",
+" . .... . ",
+" . .. . ",
+" . . ",
+" .. .. ",
+" .... ",
+" "};
+
+static const char *xpm_menu[] = {
+"12 12 2 1",
+" c white",
+". c black",
+" ",
+" .......... ",
+" . . ",
+" . .. . ",
+" . .... . ",
+" . ...... . ",
+" . ...... . ",
+" . .... . ",
+" . .. . ",
+" . . ",
+" .......... ",
+" "};
+
+static const char *xpm_menu_inv[] = {
+"12 12 2 1",
+" c white",
+". c black",
+" ",
+" .......... ",
+" .......... ",
+" .. ...... ",
+" .. .... ",
+" .. .. ",
+" .. .. ",
+" .. .... ",
+" .. ...... ",
+" .......... ",
+" .......... ",
+" "};
+
+static const char *xpm_menuback[] = {
+"12 12 2 1",
+" c white",
+". c black",
+" ",
+" .......... ",
+" . . ",
+" . .. . ",
+" . .... . ",
+" . ...... . ",
+" . ...... . ",
+" . .... . ",
+" . .. . ",
+" . . ",
+" .......... ",
+" "};
+
+static const char *xpm_void[] = {
+"12 12 2 1",
+" c white",
+". c black",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" "};
--- /dev/null
+bin_PROGRAMS = mconf
+
+mconf_SOURCES = mconf.c
+mconf_CPPFLAGS = $(AM_CPPFLAGS) -I../../parser -DCURSES_LOC='"${CURSES_LOC}"'
+mconf_LDADD = ../../parser/libkconfigparser.a ../../lxdialog/liblxdialog.a
--- /dev/null
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ *
+ * Introduced single menu mode (show all sub-menus in one large tree).
+ * 2002-11-06 Petr Baudis <pasky@ucw.cz>
+ *
+ * i18n, 2005, Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ */
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+#include <locale.h>
+
+#include "lkc.h"
+#include "lxdialog/dialog.h"
+
+static const char mconf_readme[] = N_(
+"Overview\n"
+"--------\n"
+"This interface let you select features and parameters for the build.\n"
+"Features can either be built-in, modularized, or ignored. Parameters\n"
+"must be entered in as decimal or hexadecimal numbers or text.\n"
+"\n"
+"Menu items beginning with following braces represent features that\n"
+" [ ] can be built in or removed\n"
+" < > can be built in, modularized or removed\n"
+" { } can be built in or modularized (selected by other feature)\n"
+" - - are selected by other feature,\n"
+"while *, M or whitespace inside braces means to build in, build as\n"
+"a module or to exclude the feature respectively.\n"
+"\n"
+"To change any of these features, highlight it with the cursor\n"
+"keys and press <Y> to build it in, <M> to make it a module or\n"
+"<N> to removed it. You may also press the <Space Bar> to cycle\n"
+"through the available options (ie. Y->N->M->Y).\n"
+"\n"
+"Some additional keyboard hints:\n"
+"\n"
+"Menus\n"
+"----------\n"
+"o Use the Up/Down arrow keys (cursor keys) to highlight the item\n"
+" you wish to change or submenu wish to select and press <Enter>.\n"
+" Submenus are designated by \"--->\".\n"
+"\n"
+" Shortcut: Press the option's highlighted letter (hotkey).\n"
+" Pressing a hotkey more than once will sequence\n"
+" through all visible items which use that hotkey.\n"
+"\n"
+" You may also use the <PAGE UP> and <PAGE DOWN> keys to scroll\n"
+" unseen options into view.\n"
+"\n"
+"o To exit a menu use the cursor keys to highlight the <Exit> button\n"
+" and press <ENTER>.\n"
+"\n"
+" Shortcut: Press <ESC><ESC> or <E> or <X> if there is no hotkey\n"
+" using those letters. You may press a single <ESC>, but\n"
+" there is a delayed response which you may find annoying.\n"
+"\n"
+" Also, the <TAB> and cursor keys will cycle between <Select>,\n"
+" <Exit> and <Help>.\n"
+"\n"
+"o To get help with an item, use the cursor keys to highlight <Help>\n"
+" and press <ENTER>.\n"
+"\n"
+" Shortcut: Press <H> or <?>.\n"
+"\n"
+"o To toggle the display of hidden options, press <Z>.\n"
+"\n"
+"\n"
+"Radiolists (Choice lists)\n"
+"-----------\n"
+"o Use the cursor keys to select the option you wish to set and press\n"
+" <S> or the <SPACE BAR>.\n"
+"\n"
+" Shortcut: Press the first letter of the option you wish to set then\n"
+" press <S> or <SPACE BAR>.\n"
+"\n"
+"o To see available help for the item, use the cursor keys to highlight\n"
+" <Help> and Press <ENTER>.\n"
+"\n"
+" Shortcut: Press <H> or <?>.\n"
+"\n"
+" Also, the <TAB> and cursor keys will cycle between <Select> and\n"
+" <Help>\n"
+"\n"
+"\n"
+"Data Entry\n"
+"-----------\n"
+"o Enter the requested information and press <ENTER>\n"
+" If you are entering hexadecimal values, it is not necessary to\n"
+" add the '0x' prefix to the entry.\n"
+"\n"
+"o For help, use the <TAB> or cursor keys to highlight the help option\n"
+" and press <ENTER>. You can try <TAB><H> as well.\n"
+"\n"
+"\n"
+"Text Box (Help Window)\n"
+"--------\n"
+"o Use the cursor keys to scroll up/down/left/right. The VI editor\n"
+" keys h,j,k,l function here as do <SPACE BAR> and <B> for those\n"
+" who are familiar with less and lynx.\n"
+"\n"
+"o Press <E>, <X>, <Enter> or <Esc><Esc> to exit.\n"
+"\n"
+"\n"
+"Alternate Configuration Files\n"
+"-----------------------------\n"
+"Menuconfig supports the use of alternate configuration files for\n"
+"those who, for various reasons, find it necessary to switch\n"
+"between different configurations.\n"
+"\n"
+"At the end of the main menu you will find two options. One is\n"
+"for saving the current configuration to a file of your choosing.\n"
+"The other option is for loading a previously saved alternate\n"
+"configuration.\n"
+"\n"
+"Even if you don't use alternate configuration files, but you\n"
+"find during a Menuconfig session that you have completely messed\n"
+"up your settings, you may use the \"Load Alternate...\" option to\n"
+"restore your previously saved settings from \".config\" without\n"
+"restarting Menuconfig.\n"
+"\n"
+"Other information\n"
+"-----------------\n"
+"If you use Menuconfig in an XTERM window make sure you have your\n"
+"$TERM variable set to point to a xterm definition which supports color.\n"
+"Otherwise, Menuconfig will look rather bad. Menuconfig will not\n"
+"display correctly in a RXVT window because rxvt displays only one\n"
+"intensity of color, bright.\n"
+"\n"
+"Menuconfig will display larger menus on screens or xterms which are\n"
+"set to display more than the standard 25 row by 80 column geometry.\n"
+"In order for this to work, the \"stty size\" command must be able to\n"
+"display the screen's current row and column geometry. I STRONGLY\n"
+"RECOMMEND that you make sure you do NOT have the shell variables\n"
+"LINES and COLUMNS exported into your environment. Some distributions\n"
+"export those variables via /etc/profile. Some ncurses programs can\n"
+"become confused when those variables (LINES & COLUMNS) don't reflect\n"
+"the true screen size.\n"
+"\n"
+"Optional personality available\n"
+"------------------------------\n"
+"If you prefer to have all of the options listed in a single menu, rather\n"
+"than the default multimenu hierarchy, run the menuconfig with\n"
+"MENUCONFIG_MODE environment variable set to single_menu. Example:\n"
+"\n"
+"make MENUCONFIG_MODE=single_menu menuconfig\n"
+"\n"
+"<Enter> will then unroll the appropriate category, or enfold it if it\n"
+"is already unrolled.\n"
+"\n"
+"Note that this mode can eventually be a little more CPU expensive\n"
+"(especially with a larger number of unrolled categories) than the\n"
+"default mode.\n"
+"\n"
+"Different color themes available\n"
+"--------------------------------\n"
+"It is possible to select different color themes using the variable\n"
+"MENUCONFIG_COLOR. To select a theme use:\n"
+"\n"
+"make MENUCONFIG_COLOR=<theme> menuconfig\n"
+"\n"
+"Available themes are\n"
+" mono => selects colors suitable for monochrome displays\n"
+" blackbg => selects a color scheme with black background\n"
+" classic => theme with blue background. The classic look\n"
+" bluetitle => a LCD friendly version of classic. (default)\n"
+"\n"),
+menu_instructions[] = N_(
+ "Arrow keys navigate the menu. "
+ "<Enter> selects submenus --->. "
+ "Highlighted letters are hotkeys. "
+ "Pressing <Y> includes, <N> excludes, <M> modularizes features. "
+ "Press <Esc><Esc> to exit, <?> for Help, </> for Search. "
+ "Legend: [*] built-in [ ] excluded <M> module < > module capable"),
+radiolist_instructions[] = N_(
+ "Use the arrow keys to navigate this window or "
+ "press the hotkey of the item you wish to select "
+ "followed by the <SPACE BAR>. "
+ "Press <?> for additional information about this option."),
+inputbox_instructions_int[] = N_(
+ "Please enter a decimal value. "
+ "Fractions will not be accepted. "
+ "Use the <TAB> key to move from the input field to the buttons below it."),
+inputbox_instructions_hex[] = N_(
+ "Please enter a hexadecimal value. "
+ "Use the <TAB> key to move from the input field to the buttons below it."),
+inputbox_instructions_string[] = N_(
+ "Please enter a string value. "
+ "Use the <TAB> key to move from the input field to the buttons below it."),
+setmod_text[] = N_(
+ "This feature depends on another which has been configured as a module.\n"
+ "As a result, this feature will be built as a module."),
+load_config_text[] = N_(
+ "Enter the name of the configuration file you wish to load. "
+ "Accept the name shown to restore the configuration you "
+ "last retrieved. Leave blank to abort."),
+load_config_help[] = N_(
+ "\n"
+ "For various reasons, one may wish to keep several different\n"
+ "configurations available on a single machine.\n"
+ "\n"
+ "If you have saved a previous configuration in a file other than the\n"
+ "default one, entering its name here will allow you to modify that\n"
+ "configuration.\n"
+ "\n"
+ "If you are uncertain, then you have probably never used alternate\n"
+ "configuration files. You should therefore leave this blank to abort.\n"),
+save_config_text[] = N_(
+ "Enter a filename to which this configuration should be saved "
+ "as an alternate. Leave blank to abort."),
+save_config_help[] = N_(
+ "\n"
+ "For various reasons, one may wish to keep different configurations\n"
+ "available on a single machine.\n"
+ "\n"
+ "Entering a file name here will allow you to later retrieve, modify\n"
+ "and use the current configuration as an alternate to whatever\n"
+ "configuration options you have selected at that time.\n"
+ "\n"
+ "If you are uncertain what all this means then you should probably\n"
+ "leave this blank.\n"),
+search_help[] = N_(
+ "\n"
+ "Search for symbols and display their relations.\n"
+ "Regular expressions are allowed.\n"
+ "Example: search for \"^FOO\"\n"
+ "Result:\n"
+ "-----------------------------------------------------------------\n"
+ "Symbol: FOO [=m]\n"
+ "Prompt: Foo bus is used to drive the bar HW\n"
+ "Defined at drivers/pci/Kconfig:47\n"
+ "Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n"
+ "Location:\n"
+ " -> Bus options (PCI, PCMCIA, EISA, MCA, ISA)\n"
+ " -> PCI support (PCI [=y])\n"
+ " -> PCI access mode (<choice> [=y])\n"
+ "Selects: LIBCRC32\n"
+ "Selected by: BAR\n"
+ "-----------------------------------------------------------------\n"
+ "o The line 'Prompt:' shows the text used in the menu structure for\n"
+ " this symbol\n"
+ "o The 'Defined at' line tell at what file / line number the symbol\n"
+ " is defined\n"
+ "o The 'Depends on:' line tell what symbols needs to be defined for\n"
+ " this symbol to be visible in the menu (selectable)\n"
+ "o The 'Location:' lines tell where in the menu structure this symbol\n"
+ " is located\n"
+ " A location followed by a [=y] indicate that this is a selectable\n"
+ " menu item - and current value is displayed inside brackets.\n"
+ "o The 'Selects:' line tell what symbol will be automatically\n"
+ " selected if this symbol is selected (y or m)\n"
+ "o The 'Selected by' line tell what symbol has selected this symbol\n"
+ "\n"
+ "Only relevant lines are shown.\n"
+ "\n\n"
+ "Search examples:\n"
+ "Examples: USB => find all symbols containing USB\n"
+ " ^USB => find all symbols starting with USB\n"
+ " USB$ => find all symbols ending with USB\n"
+ "\n");
+
+static int indent;
+static struct menu *current_menu;
+static int child_count;
+static int single_menu_mode;
+static int show_all_options;
+static int saved_x, saved_y;
+
+static void conf(struct menu *menu);
+static void conf_choice(struct menu *menu);
+static void conf_string(struct menu *menu);
+static void conf_load(void);
+static void conf_save(void);
+static void show_textbox(const char *title, const char *text, int r, int c);
+static void show_helptext(const char *title, const char *text);
+static void show_help(struct menu *menu);
+
+static char filename[PATH_MAX+1];
+static void set_config_filename(const char *config_filename)
+{
+ static char menu_backtitle[PATH_MAX+128];
+ int size;
+
+ size = snprintf(menu_backtitle, sizeof(menu_backtitle),
+ "%s - %s", config_filename, rootmenu.prompt->text);
+ if (size >= sizeof(menu_backtitle))
+ menu_backtitle[sizeof(menu_backtitle)-1] = '\0';
+ set_dialog_backtitle(menu_backtitle);
+
+ size = snprintf(filename, sizeof(filename), "%s", config_filename);
+ if (size >= sizeof(filename))
+ filename[sizeof(filename)-1] = '\0';
+}
+
+
+static void search_conf(void)
+{
+ struct symbol **sym_arr;
+ struct gstr res;
+ char *dialog_input;
+ int dres;
+again:
+ dialog_clear();
+ dres = dialog_inputbox(_("Search Configuration Parameter"),
+ _("Enter " CONFIG_ " (sub)string to search for "
+ "(with or without \"" CONFIG_ "\")"),
+ 10, 75, "");
+ switch (dres) {
+ case 0:
+ break;
+ case 1:
+ show_helptext(_("Search Configuration"), search_help);
+ goto again;
+ default:
+ return;
+ }
+
+ /* strip the prefix if necessary */
+ dialog_input = dialog_input_result;
+ if (strncasecmp(dialog_input_result, CONFIG_, strlen(CONFIG_)) == 0)
+ dialog_input += strlen(CONFIG_);
+
+ sym_arr = sym_re_search(dialog_input);
+ res = get_relations_str(sym_arr);
+ free(sym_arr);
+ show_textbox(_("Search Results"), str_get(&res), 0, 0);
+ str_free(&res);
+}
+
+static void build_conf(struct menu *menu)
+{
+ struct symbol *sym;
+ struct property *prop;
+ struct menu *child;
+ int type, tmp, doint = 2;
+ tristate val;
+ char ch;
+ bool visible;
+
+ /*
+ * note: menu_is_visible() has side effect that it will
+ * recalc the value of the symbol.
+ */
+ visible = menu_is_visible(menu);
+ if (show_all_options && !menu_has_prompt(menu))
+ return;
+ else if (!show_all_options && !visible)
+ return;
+
+ sym = menu->sym;
+ prop = menu->prompt;
+ if (!sym) {
+ if (prop && menu != current_menu) {
+ const char *prompt = menu_get_prompt(menu);
+ switch (prop->type) {
+ case P_MENU:
+ child_count++;
+ prompt = _(prompt);
+ if (single_menu_mode) {
+ item_make("%s%*c%s",
+ menu->data ? "-->" : "++>",
+ indent + 1, ' ', prompt);
+ } else
+ item_make(" %*c%s --->", indent + 1, ' ', prompt);
+
+ item_set_tag('m');
+ item_set_data(menu);
+ if (single_menu_mode && menu->data)
+ goto conf_childs;
+ return;
+ case P_COMMENT:
+ if (prompt) {
+ child_count++;
+ item_make(" %*c*** %s ***", indent + 1, ' ', _(prompt));
+ item_set_tag(':');
+ item_set_data(menu);
+ }
+ break;
+ default:
+ if (prompt) {
+ child_count++;
+ item_make("---%*c%s", indent + 1, ' ', _(prompt));
+ item_set_tag(':');
+ item_set_data(menu);
+ }
+ }
+ } else
+ doint = 0;
+ goto conf_childs;
+ }
+
+ type = sym_get_type(sym);
+ if (sym_is_choice(sym)) {
+ struct symbol *def_sym = sym_get_choice_value(sym);
+ struct menu *def_menu = NULL;
+
+ child_count++;
+ for (child = menu->list; child; child = child->next) {
+ if (menu_is_visible(child) && child->sym == def_sym)
+ def_menu = child;
+ }
+
+ val = sym_get_tristate_value(sym);
+ if (sym_is_changable(sym)) {
+ switch (type) {
+ case S_BOOLEAN:
+ item_make("[%c]", val == no ? ' ' : '*');
+ break;
+ case S_TRISTATE:
+ switch (val) {
+ case yes: ch = '*'; break;
+ case mod: ch = 'M'; break;
+ default: ch = ' '; break;
+ }
+ item_make("<%c>", ch);
+ break;
+ }
+ item_set_tag('t');
+ item_set_data(menu);
+ } else {
+ item_make(" ");
+ item_set_tag(def_menu ? 't' : ':');
+ item_set_data(menu);
+ }
+
+ item_add_str("%*c%s", indent + 1, ' ', _(menu_get_prompt(menu)));
+ if (val == yes) {
+ if (def_menu) {
+ item_add_str(" (%s)", _(menu_get_prompt(def_menu)));
+ item_add_str(" --->");
+ if (def_menu->list) {
+ indent += 2;
+ build_conf(def_menu);
+ indent -= 2;
+ }
+ }
+ return;
+ }
+ } else {
+ if (menu == current_menu) {
+ item_make("---%*c%s", indent + 1, ' ', _(menu_get_prompt(menu)));
+ item_set_tag(':');
+ item_set_data(menu);
+ goto conf_childs;
+ }
+ child_count++;
+ val = sym_get_tristate_value(sym);
+ if (sym_is_choice_value(sym) && val == yes) {
+ item_make(" ");
+ item_set_tag(':');
+ item_set_data(menu);
+ } else {
+ switch (type) {
+ case S_BOOLEAN:
+ if (sym_is_changable(sym))
+ item_make("[%c]", val == no ? ' ' : '*');
+ else
+ item_make("-%c-", val == no ? ' ' : '*');
+ item_set_tag('t');
+ item_set_data(menu);
+ break;
+ case S_TRISTATE:
+ switch (val) {
+ case yes: ch = '*'; break;
+ case mod: ch = 'M'; break;
+ default: ch = ' '; break;
+ }
+ if (sym_is_changable(sym)) {
+ if (sym->rev_dep.tri == mod)
+ item_make("{%c}", ch);
+ else
+ item_make("<%c>", ch);
+ } else
+ item_make("-%c-", ch);
+ item_set_tag('t');
+ item_set_data(menu);
+ break;
+ default:
+ tmp = 2 + strlen(sym_get_string_value(sym)); /* () = 2 */
+ item_make("(%s)", sym_get_string_value(sym));
+ tmp = indent - tmp + 4;
+ if (tmp < 0)
+ tmp = 0;
+ item_add_str("%*c%s%s", tmp, ' ', _(menu_get_prompt(menu)),
+ (sym_has_value(sym) || !sym_is_changable(sym)) ?
+ "" : _(" (NEW)"));
+ item_set_tag('s');
+ item_set_data(menu);
+ goto conf_childs;
+ }
+ }
+ item_add_str("%*c%s%s", indent + 1, ' ', _(menu_get_prompt(menu)),
+ (sym_has_value(sym) || !sym_is_changable(sym)) ?
+ "" : _(" (NEW)"));
+ if (menu->prompt->type == P_MENU) {
+ item_add_str(" --->");
+ return;
+ }
+ }
+
+conf_childs:
+ indent += doint;
+ for (child = menu->list; child; child = child->next)
+ build_conf(child);
+ indent -= doint;
+}
+
+static void conf(struct menu *menu)
+{
+ struct menu *submenu;
+ const char *prompt = menu_get_prompt(menu);
+ struct symbol *sym;
+ struct menu *active_menu = NULL;
+ int res;
+ int s_scroll = 0;
+
+ while (1) {
+ item_reset();
+ current_menu = menu;
+ build_conf(menu);
+ if (!child_count)
+ break;
+ if (menu == &rootmenu) {
+ item_make("--- ");
+ item_set_tag(':');
+ item_make(_(" Load an Alternate Configuration File"));
+ item_set_tag('L');
+ item_make(_(" Save an Alternate Configuration File"));
+ item_set_tag('S');
+ }
+ dialog_clear();
+ res = dialog_menu(prompt ? _(prompt) : _("Main Menu"),
+ _(menu_instructions),
+ active_menu, &s_scroll);
+ if (res == 1 || res == KEY_ESC || res == -ERRDISPLAYTOOSMALL)
+ break;
+ if (!item_activate_selected())
+ continue;
+ if (!item_tag())
+ continue;
+
+ submenu = item_data();
+ active_menu = item_data();
+ if (submenu)
+ sym = submenu->sym;
+ else
+ sym = NULL;
+
+ switch (res) {
+ case 0:
+ switch (item_tag()) {
+ case 'm':
+ if (single_menu_mode)
+ submenu->data = (void *) (long) !submenu->data;
+ else
+ conf(submenu);
+ break;
+ case 't':
+ if (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)
+ conf_choice(submenu);
+ else if (submenu->prompt->type == P_MENU)
+ conf(submenu);
+ break;
+ case 's':
+ conf_string(submenu);
+ break;
+ case 'L':
+ conf_load();
+ break;
+ case 'S':
+ conf_save();
+ break;
+ }
+ break;
+ case 2:
+ if (sym)
+ show_help(submenu);
+ else
+ show_helptext(_("README"), _(mconf_readme));
+ break;
+ case 3:
+ if (item_is_tag('t')) {
+ if (sym_set_tristate_value(sym, yes))
+ break;
+ if (sym_set_tristate_value(sym, mod))
+ show_textbox(NULL, setmod_text, 6, 74);
+ }
+ break;
+ case 4:
+ if (item_is_tag('t'))
+ sym_set_tristate_value(sym, no);
+ break;
+ case 5:
+ if (item_is_tag('t'))
+ sym_set_tristate_value(sym, mod);
+ break;
+ case 6:
+ if (item_is_tag('t'))
+ sym_toggle_tristate_value(sym);
+ else if (item_is_tag('m'))
+ conf(submenu);
+ break;
+ case 7:
+ search_conf();
+ break;
+ case 8:
+ show_all_options = !show_all_options;
+ break;
+ }
+ }
+}
+
+static void show_textbox(const char *title, const char *text, int r, int c)
+{
+ dialog_clear();
+ dialog_textbox(title, text, r, c);
+}
+
+static void show_helptext(const char *title, const char *text)
+{
+ show_textbox(title, text, 0, 0);
+}
+
+static void show_help(struct menu *menu)
+{
+ struct gstr help = str_new();
+
+ help.max_width = getmaxx(stdscr) - 10;
+ menu_get_ext_help(menu, &help);
+
+ show_helptext(_(menu_get_prompt(menu)), str_get(&help));
+ str_free(&help);
+}
+
+static void conf_choice(struct menu *menu)
+{
+ const char *prompt = _(menu_get_prompt(menu));
+ struct menu *child;
+ struct symbol *active;
+
+ active = sym_get_choice_value(menu->sym);
+ while (1) {
+ int res;
+ int selected;
+ item_reset();
+
+ current_menu = menu;
+ for (child = menu->list; child; child = child->next) {
+ if (!menu_is_visible(child))
+ continue;
+ if (child->sym)
+ item_make("%s", _(menu_get_prompt(child)));
+ else {
+ item_make("*** %s ***", _(menu_get_prompt(child)));
+ item_set_tag(':');
+ }
+ item_set_data(child);
+ if (child->sym == active)
+ item_set_selected(1);
+ if (child->sym == sym_get_choice_value(menu->sym))
+ item_set_tag('X');
+ }
+ dialog_clear();
+ res = dialog_checklist(prompt ? _(prompt) : _("Main Menu"),
+ _(radiolist_instructions),
+ 15, 70, 6);
+ selected = item_activate_selected();
+ switch (res) {
+ case 0:
+ if (selected) {
+ child = item_data();
+ if (!child->sym)
+ break;
+
+ sym_set_tristate_value(child->sym, yes);
+ }
+ return;
+ case 1:
+ if (selected) {
+ child = item_data();
+ show_help(child);
+ active = child->sym;
+ } else
+ show_help(menu);
+ break;
+ case KEY_ESC:
+ return;
+ case -ERRDISPLAYTOOSMALL:
+ return;
+ }
+ }
+}
+
+static void conf_string(struct menu *menu)
+{
+ const char *prompt = menu_get_prompt(menu);
+
+ while (1) {
+ int res;
+ const char *heading;
+
+ switch (sym_get_type(menu->sym)) {
+ case S_INT:
+ heading = _(inputbox_instructions_int);
+ break;
+ case S_HEX:
+ heading = _(inputbox_instructions_hex);
+ break;
+ case S_STRING:
+ heading = _(inputbox_instructions_string);
+ break;
+ default:
+ heading = _("Internal mconf error!");
+ }
+ dialog_clear();
+ res = dialog_inputbox(prompt ? _(prompt) : _("Main Menu"),
+ heading, 10, 75,
+ sym_get_string_value(menu->sym));
+ switch (res) {
+ case 0:
+ if (sym_set_string_value(menu->sym, dialog_input_result))
+ return;
+ show_textbox(NULL, _("You have made an invalid entry."), 5, 43);
+ break;
+ case 1:
+ show_help(menu);
+ break;
+ case KEY_ESC:
+ return;
+ }
+ }
+}
+
+static void conf_load(void)
+{
+
+ while (1) {
+ int res;
+ dialog_clear();
+ res = dialog_inputbox(NULL, load_config_text,
+ 11, 55, filename);
+ switch(res) {
+ case 0:
+ if (!dialog_input_result[0])
+ return;
+ if (!conf_read(dialog_input_result)) {
+ set_config_filename(dialog_input_result);
+ sym_set_change_count(1);
+ return;
+ }
+ show_textbox(NULL, _("File does not exist!"), 5, 38);
+ break;
+ case 1:
+ show_helptext(_("Load Alternate Configuration"), load_config_help);
+ break;
+ case KEY_ESC:
+ return;
+ }
+ }
+}
+
+static void conf_save(void)
+{
+ while (1) {
+ int res;
+ dialog_clear();
+ res = dialog_inputbox(NULL, save_config_text,
+ 11, 55, filename);
+ switch(res) {
+ case 0:
+ if (!dialog_input_result[0])
+ return;
+ if (!conf_write(dialog_input_result)) {
+ set_config_filename(dialog_input_result);
+ return;
+ }
+ show_textbox(NULL, _("Can't create file! Probably a nonexistent directory."), 5, 60);
+ break;
+ case 1:
+ show_helptext(_("Save Alternate Configuration"), save_config_help);
+ break;
+ case KEY_ESC:
+ return;
+ }
+ }
+}
+
+static int handle_exit(void)
+{
+ int res;
+
+ dialog_clear();
+ if (conf_get_changed())
+ res = dialog_yesno(NULL,
+ _("Do you wish to save your new configuration ?\n"
+ "<ESC><ESC> to continue."),
+ 6, 60);
+ else
+ res = -1;
+
+ end_dialog(saved_x, saved_y);
+
+ switch (res) {
+ case 0:
+ if (conf_write(filename)) {
+ fprintf(stderr, _("\n\n"
+ "Error while writing of the configuration.\n"
+ "Your configuration changes were NOT saved."
+ "\n\n"));
+ return 1;
+ }
+ /* fall through */
+ case -1:
+ printf(_("\n\n"
+ "*** End of the configuration.\n"
+ "*** Execute 'make' to start the build or try 'make help'."
+ "\n\n"));
+ res = 0;
+ break;
+ default:
+ fprintf(stderr, _("\n\n"
+ "Your configuration changes were NOT saved."
+ "\n\n"));
+ if (res != KEY_ESC)
+ res = 0;
+ }
+
+ return res;
+}
+
+static void sig_handler(int signo)
+{
+ exit(handle_exit());
+}
+
+int main(int ac, char **av)
+{
+ char *mode;
+ int res;
+
+ setlocale(LC_ALL, "");
+ bindtextdomain(PACKAGE, LOCALEDIR);
+ textdomain(PACKAGE);
+
+ signal(SIGINT, sig_handler);
+
+ conf_parse(av[1]);
+ conf_read(NULL);
+
+ mode = getenv("MENUCONFIG_MODE");
+ if (mode) {
+ if (!strcasecmp(mode, "single_menu"))
+ single_menu_mode = 1;
+ }
+
+ initscr();
+
+ getyx(stdscr, saved_y, saved_x);
+ if (init_dialog(NULL)) {
+ fprintf(stderr, N_("Your display is too small to run Menuconfig!\n"));
+ fprintf(stderr, N_("It must be at least 19 lines by 80 columns.\n"));
+ return 1;
+ }
+
+ set_config_filename(conf_get_configname());
+ do {
+ conf(&rootmenu);
+ res = handle_exit();
+ } while (res == KEY_ESC);
+
+ return res;
+}
+
--- /dev/null
+bin_PROGRAMS = nconf
+
+nconf_SOURCES = nconf.c nconf.gui.c nconf.h
+nconf_CPPFLAGS = $(AM_CPPFLAGS) -I../../parser
+nconf_LDADD = ../../parser/libkconfigparser.a -lmenu -lpanel
--- /dev/null
+/*
+ * Copyright (C) 2008 Nir Tzachar <nir.tzachar@gmail.com?
+ * Released under the terms of the GNU GPL v2.0.
+ *
+ * Derived from menuconfig.
+ *
+ */
+#define _GNU_SOURCE
+#include <string.h>
+
+#include "lkc.h"
+#include "nconf.h"
+#include <ctype.h>
+
+static const char nconf_readme[] = N_(
+"Overview\n"
+"--------\n"
+"This interface let you select features and parameters for the build.\n"
+"Features can either be built-in, modularized, or ignored. Parameters\n"
+"must be entered in as decimal or hexadecimal numbers or text.\n"
+"\n"
+"Menu items beginning with following braces represent features that\n"
+" [ ] can be built in or removed\n"
+" < > can be built in, modularized or removed\n"
+" { } can be built in or modularized (selected by other feature)\n"
+" - - are selected by other feature,\n"
+" XXX cannot be selected. Use Symbol Info to find out why,\n"
+"while *, M or whitespace inside braces means to build in, build as\n"
+"a module or to exclude the feature respectively.\n"
+"\n"
+"To change any of these features, highlight it with the cursor\n"
+"keys and press <Y> to build it in, <M> to make it a module or\n"
+"<N> to removed it. You may also press the <Space Bar> to cycle\n"
+"through the available options (ie. Y->N->M->Y).\n"
+"\n"
+"Some additional keyboard hints:\n"
+"\n"
+"Menus\n"
+"----------\n"
+"o Use the Up/Down arrow keys (cursor keys) to highlight the item\n"
+" you wish to change use <Enter> or <Space>. Goto submenu by \n"
+" pressing <Enter> of <right-arrow>. Use <Esc> or <left-arrow> to go back.\n"
+" Submenus are designated by \"--->\".\n"
+"\n"
+" Searching: pressing '/' triggers interactive search mode.\n"
+" nconfig performs a case insensitive search for the string\n"
+" in the menu prompts (no regex support).\n"
+" Pressing the up/down keys highlights the previous/next\n"
+" matching item. Backspace removes one character from the\n"
+" match string. Pressing either '/' again or ESC exits\n"
+" search mode. All other keys behave normally.\n"
+"\n"
+" You may also use the <PAGE UP> and <PAGE DOWN> keys to scroll\n"
+" unseen options into view.\n"
+"\n"
+"o To exit a menu use the just press <ESC> <F5> <F8> or <left-arrow>.\n"
+"\n"
+"o To get help with an item, press <F1>\n"
+" Shortcut: Press <h> or <?>.\n"
+"\n"
+"\n"
+"Radiolists (Choice lists)\n"
+"-----------\n"
+"o Use the cursor keys to select the option you wish to set and press\n"
+" <S> or the <SPACE BAR>.\n"
+"\n"
+" Shortcut: Press the first letter of the option you wish to set then\n"
+" press <S> or <SPACE BAR>.\n"
+"\n"
+"o To see available help for the item, press <F1>\n"
+" Shortcut: Press <H> or <?>.\n"
+"\n"
+"\n"
+"Data Entry\n"
+"-----------\n"
+"o Enter the requested information and press <ENTER>\n"
+" If you are entering hexadecimal values, it is not necessary to\n"
+" add the '0x' prefix to the entry.\n"
+"\n"
+"o For help, press <F1>.\n"
+"\n"
+"\n"
+"Text Box (Help Window)\n"
+"--------\n"
+"o Use the cursor keys to scroll up/down/left/right. The VI editor\n"
+" keys h,j,k,l function here as do <SPACE BAR> for those\n"
+" who are familiar with less and lynx.\n"
+"\n"
+"o Press <Enter>, <F1>, <F5>, <F7> or <Esc> to exit.\n"
+"\n"
+"\n"
+"Alternate Configuration Files\n"
+"-----------------------------\n"
+"nconfig supports the use of alternate configuration files for\n"
+"those who, for various reasons, find it necessary to switch\n"
+"between different configurations.\n"
+"\n"
+"At the end of the main menu you will find two options. One is\n"
+"for saving the current configuration to a file of your choosing.\n"
+"The other option is for loading a previously saved alternate\n"
+"configuration.\n"
+"\n"
+"Even if you don't use alternate configuration files, but you\n"
+"find during a nconfig session that you have completely messed\n"
+"up your settings, you may use the \"Load Alternate...\" option to\n"
+"restore your previously saved settings from \".config\" without\n"
+"restarting nconfig.\n"
+"\n"
+"Other information\n"
+"-----------------\n"
+"If you use nconfig in an XTERM window make sure you have your\n"
+"$TERM variable set to point to a xterm definition which supports color.\n"
+"Otherwise, nconfig will look rather bad. nconfig will not\n"
+"display correctly in a RXVT window because rxvt displays only one\n"
+"intensity of color, bright.\n"
+"\n"
+"nconfig will display larger menus on screens or xterms which are\n"
+"set to display more than the standard 25 row by 80 column geometry.\n"
+"In order for this to work, the \"stty size\" command must be able to\n"
+"display the screen's current row and column geometry. I STRONGLY\n"
+"RECOMMEND that you make sure you do NOT have the shell variables\n"
+"LINES and COLUMNS exported into your environment. Some distributions\n"
+"export those variables via /etc/profile. Some ncurses programs can\n"
+"become confused when those variables (LINES & COLUMNS) don't reflect\n"
+"the true screen size.\n"
+"\n"
+"Optional personality available\n"
+"------------------------------\n"
+"If you prefer to have all of the options listed in a single menu, rather\n"
+"than the default multimenu hierarchy, run the nconfig with NCONFIG_MODE\n"
+"environment variable set to single_menu. Example:\n"
+"\n"
+"make NCONFIG_MODE=single_menu nconfig\n"
+"\n"
+"<Enter> will then unroll the appropriate category, or enfold it if it\n"
+"is already unrolled.\n"
+"\n"
+"Note that this mode can eventually be a little more CPU expensive\n"
+"(especially with a larger number of unrolled categories) than the\n"
+"default mode.\n"
+"\n"),
+menu_no_f_instructions[] = N_(
+" You do not have function keys support. Please follow the\n"
+" following instructions:\n"
+" Arrow keys navigate the menu.\n"
+" <Enter> or <right-arrow> selects submenus --->.\n"
+" Capital Letters are hotkeys.\n"
+" Pressing <Y> includes, <N> excludes, <M> modularizes features.\n"
+" Pressing SpaceBar toggles between the above options.\n"
+" Press <Esc> or <left-arrow> to go back one menu,\n"
+" <?> or <h> for Help, </> for Search.\n"
+" <1> is interchangeable with <F1>, <2> with <F2>, etc.\n"
+" Legend: [*] built-in [ ] excluded <M> module < > module capable.\n"
+" <Esc> always leaves the current window.\n"),
+menu_instructions[] = N_(
+" Arrow keys navigate the menu.\n"
+" <Enter> or <right-arrow> selects submenus --->.\n"
+" Capital Letters are hotkeys.\n"
+" Pressing <Y> includes, <N> excludes, <M> modularizes features.\n"
+" Pressing SpaceBar toggles between the above options\n"
+" Press <Esc>, <F5> or <left-arrow> to go back one menu,\n"
+" <?>, <F1> or <h> for Help, </> for Search.\n"
+" <1> is interchangeable with <F1>, <2> with <F2>, etc.\n"
+" Legend: [*] built-in [ ] excluded <M> module < > module capable.\n"
+" <Esc> always leaves the current window\n"),
+radiolist_instructions[] = N_(
+" Use the arrow keys to navigate this window or\n"
+" press the hotkey of the item you wish to select\n"
+" followed by the <SPACE BAR>.\n"
+" Press <?>, <F1> or <h> for additional information about this option.\n"),
+inputbox_instructions_int[] = N_(
+"Please enter a decimal value.\n"
+"Fractions will not be accepted.\n"
+"Press <RETURN> to accept, <ESC> to cancel."),
+inputbox_instructions_hex[] = N_(
+"Please enter a hexadecimal value.\n"
+"Press <RETURN> to accept, <ESC> to cancel."),
+inputbox_instructions_string[] = N_(
+"Please enter a string value.\n"
+"Press <RETURN> to accept, <ESC> to cancel."),
+setmod_text[] = N_(
+"This feature depends on another which\n"
+"has been configured as a module.\n"
+"As a result, this feature will be built as a module."),
+load_config_text[] = N_(
+"Enter the name of the configuration file you wish to load.\n"
+"Accept the name shown to restore the configuration you\n"
+"last retrieved. Leave blank to abort."),
+load_config_help[] = N_(
+"\n"
+"For various reasons, one may wish to keep several different\n"
+"configurations available on a single machine.\n"
+"\n"
+"If you have saved a previous configuration in a file other than the\n"
+"default one, entering its name here will allow you to modify that\n"
+"configuration.\n"
+"\n"
+"If you are uncertain, then you have probably never used alternate\n"
+"configuration files. You should therefor leave this blank to abort.\n"),
+save_config_text[] = N_(
+"Enter a filename to which this configuration should be saved\n"
+"as an alternate. Leave blank to abort."),
+save_config_help[] = N_(
+"\n"
+"For various reasons, one may wish to keep different configurations\n"
+"available on a single machine.\n"
+"\n"
+"Entering a file name here will allow you to later retrieve, modify\n"
+"and use the current configuration as an alternate to whatever\n"
+"configuration options you have selected at that time.\n"
+"\n"
+"If you are uncertain what all this means then you should probably\n"
+"leave this blank.\n"),
+search_help[] = N_(
+"\n"
+"Search for symbols and display their relations. Regular expressions\n"
+"are allowed.\n"
+"Example: search for \"^FOO\"\n"
+"Result:\n"
+"-----------------------------------------------------------------\n"
+"Symbol: FOO [ = m]\n"
+"Prompt: Foo bus is used to drive the bar HW\n"
+"Defined at drivers/pci/Kconfig:47\n"
+"Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n"
+"Location:\n"
+" -> Bus options (PCI, PCMCIA, EISA, MCA, ISA)\n"
+" -> PCI support (PCI [ = y])\n"
+" -> PCI access mode (<choice> [ = y])\n"
+"Selects: LIBCRC32\n"
+"Selected by: BAR\n"
+"-----------------------------------------------------------------\n"
+"o The line 'Prompt:' shows the text used in the menu structure for\n"
+" this symbol\n"
+"o The 'Defined at' line tell at what file / line number the symbol\n"
+" is defined\n"
+"o The 'Depends on:' line tell what symbols needs to be defined for\n"
+" this symbol to be visible in the menu (selectable)\n"
+"o The 'Location:' lines tell where in the menu structure this symbol\n"
+" is located\n"
+" A location followed by a [ = y] indicate that this is a selectable\n"
+" menu item - and current value is displayed inside brackets.\n"
+"o The 'Selects:' line tell what symbol will be automatically\n"
+" selected if this symbol is selected (y or m)\n"
+"o The 'Selected by' line tell what symbol has selected this symbol\n"
+"\n"
+"Only relevant lines are shown.\n"
+"\n\n"
+"Search examples:\n"
+"Examples: USB => find all symbols containing USB\n"
+" ^USB => find all symbols starting with USB\n"
+" USB$ => find all symbols ending with USB\n"
+"\n");
+
+struct mitem {
+ char str[256];
+ char tag;
+ void *usrptr;
+ int is_visible;
+};
+
+#define MAX_MENU_ITEMS 4096
+static int show_all_items;
+static int indent;
+static struct menu *current_menu;
+static int child_count;
+static int single_menu_mode;
+/* the window in which all information appears */
+static WINDOW *main_window;
+/* the largest size of the menu window */
+static int mwin_max_lines;
+static int mwin_max_cols;
+/* the window in which we show option buttons */
+static MENU *curses_menu;
+static ITEM *curses_menu_items[MAX_MENU_ITEMS];
+static struct mitem k_menu_items[MAX_MENU_ITEMS];
+static int items_num;
+static int global_exit;
+/* the currently selected button */
+const char *current_instructions = menu_instructions;
+
+static char *dialog_input_result;
+static int dialog_input_result_len;
+
+static void conf(struct menu *menu);
+static void conf_choice(struct menu *menu);
+static void conf_string(struct menu *menu);
+static void conf_load(void);
+static void conf_save(void);
+static void show_help(struct menu *menu);
+static int do_exit(void);
+static void setup_windows(void);
+static void search_conf(void);
+
+typedef void (*function_key_handler_t)(int *key, struct menu *menu);
+static void handle_f1(int *key, struct menu *current_item);
+static void handle_f2(int *key, struct menu *current_item);
+static void handle_f3(int *key, struct menu *current_item);
+static void handle_f4(int *key, struct menu *current_item);
+static void handle_f5(int *key, struct menu *current_item);
+static void handle_f6(int *key, struct menu *current_item);
+static void handle_f7(int *key, struct menu *current_item);
+static void handle_f8(int *key, struct menu *current_item);
+static void handle_f9(int *key, struct menu *current_item);
+
+struct function_keys {
+ const char *key_str;
+ const char *func;
+ function_key key;
+ function_key_handler_t handler;
+};
+
+static const int function_keys_num = 9;
+struct function_keys function_keys[] = {
+ {
+ .key_str = "F1",
+ .func = "Help",
+ .key = F_HELP,
+ .handler = handle_f1,
+ },
+ {
+ .key_str = "F2",
+ .func = "Sym Info",
+ .key = F_SYMBOL,
+ .handler = handle_f2,
+ },
+ {
+ .key_str = "F3",
+ .func = "Insts",
+ .key = F_INSTS,
+ .handler = handle_f3,
+ },
+ {
+ .key_str = "F4",
+ .func = "Config",
+ .key = F_CONF,
+ .handler = handle_f4,
+ },
+ {
+ .key_str = "F5",
+ .func = "Back",
+ .key = F_BACK,
+ .handler = handle_f5,
+ },
+ {
+ .key_str = "F6",
+ .func = "Save",
+ .key = F_SAVE,
+ .handler = handle_f6,
+ },
+ {
+ .key_str = "F7",
+ .func = "Load",
+ .key = F_LOAD,
+ .handler = handle_f7,
+ },
+ {
+ .key_str = "F8",
+ .func = "Sym Search",
+ .key = F_SEARCH,
+ .handler = handle_f8,
+ },
+ {
+ .key_str = "F9",
+ .func = "Exit",
+ .key = F_EXIT,
+ .handler = handle_f9,
+ },
+};
+
+static void print_function_line(void)
+{
+ int i;
+ int offset = 1;
+ const int skip = 1;
+
+ for (i = 0; i < function_keys_num; i++) {
+ (void) wattrset(main_window, attributes[FUNCTION_HIGHLIGHT]);
+ mvwprintw(main_window, LINES-3, offset,
+ "%s",
+ function_keys[i].key_str);
+ (void) wattrset(main_window, attributes[FUNCTION_TEXT]);
+ offset += strlen(function_keys[i].key_str);
+ mvwprintw(main_window, LINES-3,
+ offset, "%s",
+ function_keys[i].func);
+ offset += strlen(function_keys[i].func) + skip;
+ }
+ (void) wattrset(main_window, attributes[NORMAL]);
+}
+
+/* help */
+static void handle_f1(int *key, struct menu *current_item)
+{
+ show_scroll_win(main_window,
+ _("README"), _(nconf_readme));
+ return;
+}
+
+/* symbole help */
+static void handle_f2(int *key, struct menu *current_item)
+{
+ show_help(current_item);
+ return;
+}
+
+/* instructions */
+static void handle_f3(int *key, struct menu *current_item)
+{
+ show_scroll_win(main_window,
+ _("Instructions"),
+ _(current_instructions));
+ return;
+}
+
+/* config */
+static void handle_f4(int *key, struct menu *current_item)
+{
+ int res = btn_dialog(main_window,
+ _("Show all symbols?"),
+ 2,
+ " <Show All> ",
+ "<Don't show all>");
+ if (res == 0)
+ show_all_items = 1;
+ else if (res == 1)
+ show_all_items = 0;
+
+ return;
+}
+
+/* back */
+static void handle_f5(int *key, struct menu *current_item)
+{
+ *key = KEY_LEFT;
+ return;
+}
+
+/* save */
+static void handle_f6(int *key, struct menu *current_item)
+{
+ conf_save();
+ return;
+}
+
+/* load */
+static void handle_f7(int *key, struct menu *current_item)
+{
+ conf_load();
+ return;
+}
+
+/* search */
+static void handle_f8(int *key, struct menu *current_item)
+{
+ search_conf();
+ return;
+}
+
+/* exit */
+static void handle_f9(int *key, struct menu *current_item)
+{
+ do_exit();
+ return;
+}
+
+/* return != 0 to indicate the key was handles */
+static int process_special_keys(int *key, struct menu *menu)
+{
+ int i;
+
+ if (*key == KEY_RESIZE) {
+ setup_windows();
+ return 1;
+ }
+
+ for (i = 0; i < function_keys_num; i++) {
+ if (*key == KEY_F(function_keys[i].key) ||
+ *key == '0' + function_keys[i].key){
+ function_keys[i].handler(key, menu);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static void clean_items(void)
+{
+ int i;
+ for (i = 0; curses_menu_items[i]; i++)
+ free_item(curses_menu_items[i]);
+ bzero(curses_menu_items, sizeof(curses_menu_items));
+ bzero(k_menu_items, sizeof(k_menu_items));
+ items_num = 0;
+}
+
+typedef enum {MATCH_TINKER_PATTERN_UP, MATCH_TINKER_PATTERN_DOWN,
+ FIND_NEXT_MATCH_DOWN, FIND_NEXT_MATCH_UP} match_f;
+
+/* return the index of the matched item, or -1 if no such item exists */
+static int get_mext_match(const char *match_str, match_f flag)
+{
+ int match_start = item_index(current_item(curses_menu));
+ int index;
+
+ if (flag == FIND_NEXT_MATCH_DOWN)
+ ++match_start;
+ else if (flag == FIND_NEXT_MATCH_UP)
+ --match_start;
+
+ index = match_start;
+ index = (index + items_num) % items_num;
+ while (true) {
+ char *str = k_menu_items[index].str;
+ if (strcasestr(str, match_str) != 0)
+ return index;
+ if (flag == FIND_NEXT_MATCH_UP ||
+ flag == MATCH_TINKER_PATTERN_UP)
+ --index;
+ else
+ ++index;
+ index = (index + items_num) % items_num;
+ if (index == match_start)
+ return -1;
+ }
+}
+
+/* Make a new item. */
+static void item_make(struct menu *menu, char tag, const char *fmt, ...)
+{
+ va_list ap;
+
+ if (items_num > MAX_MENU_ITEMS-1)
+ return;
+
+ bzero(&k_menu_items[items_num], sizeof(k_menu_items[0]));
+ k_menu_items[items_num].tag = tag;
+ k_menu_items[items_num].usrptr = menu;
+ if (menu != NULL)
+ k_menu_items[items_num].is_visible =
+ menu_is_visible(menu);
+ else
+ k_menu_items[items_num].is_visible = 1;
+
+ va_start(ap, fmt);
+ vsnprintf(k_menu_items[items_num].str,
+ sizeof(k_menu_items[items_num].str),
+ fmt, ap);
+ va_end(ap);
+
+ if (!k_menu_items[items_num].is_visible)
+ memcpy(k_menu_items[items_num].str, "XXX", 3);
+
+ curses_menu_items[items_num] = new_item(
+ k_menu_items[items_num].str,
+ k_menu_items[items_num].str);
+ set_item_userptr(curses_menu_items[items_num],
+ &k_menu_items[items_num]);
+ /*
+ if (!k_menu_items[items_num].is_visible)
+ item_opts_off(curses_menu_items[items_num], O_SELECTABLE);
+ */
+
+ items_num++;
+ curses_menu_items[items_num] = NULL;
+}
+
+/* very hackish. adds a string to the last item added */
+static void item_add_str(const char *fmt, ...)
+{
+ va_list ap;
+ int index = items_num-1;
+ char new_str[256];
+ char tmp_str[256];
+
+ if (index < 0)
+ return;
+
+ va_start(ap, fmt);
+ vsnprintf(new_str, sizeof(new_str), fmt, ap);
+ va_end(ap);
+ snprintf(tmp_str, sizeof(tmp_str), "%s%s",
+ k_menu_items[index].str, new_str);
+ strncpy(k_menu_items[index].str,
+ tmp_str,
+ sizeof(k_menu_items[index].str));
+
+ free_item(curses_menu_items[index]);
+ curses_menu_items[index] = new_item(
+ k_menu_items[index].str,
+ k_menu_items[index].str);
+ set_item_userptr(curses_menu_items[index],
+ &k_menu_items[index]);
+}
+
+/* get the tag of the currently selected item */
+static char item_tag(void)
+{
+ ITEM *cur;
+ struct mitem *mcur;
+
+ cur = current_item(curses_menu);
+ if (cur == NULL)
+ return 0;
+ mcur = (struct mitem *) item_userptr(cur);
+ return mcur->tag;
+}
+
+static int curses_item_index(void)
+{
+ return item_index(current_item(curses_menu));
+}
+
+static void *item_data(void)
+{
+ ITEM *cur;
+ struct mitem *mcur;
+
+ cur = current_item(curses_menu);
+ if (!cur)
+ return NULL;
+ mcur = (struct mitem *) item_userptr(cur);
+ return mcur->usrptr;
+
+}
+
+static int item_is_tag(char tag)
+{
+ return item_tag() == tag;
+}
+
+static char filename[PATH_MAX+1];
+static char menu_backtitle[PATH_MAX+128];
+static const char *set_config_filename(const char *config_filename)
+{
+ int size;
+
+ size = snprintf(menu_backtitle, sizeof(menu_backtitle),
+ "%s - %s", config_filename, rootmenu.prompt->text);
+ if (size >= sizeof(menu_backtitle))
+ menu_backtitle[sizeof(menu_backtitle)-1] = '\0';
+
+ size = snprintf(filename, sizeof(filename), "%s", config_filename);
+ if (size >= sizeof(filename))
+ filename[sizeof(filename)-1] = '\0';
+ return menu_backtitle;
+}
+
+/* return = 0 means we are successful.
+ * -1 means go on doing what you were doing
+ */
+static int do_exit(void)
+{
+ int res;
+ if (!conf_get_changed()) {
+ global_exit = 1;
+ return 0;
+ }
+ res = btn_dialog(main_window,
+ _("Do you wish to save your new configuration?\n"
+ "<ESC> to cancel and resume nconfig."),
+ 2,
+ " <save> ",
+ "<don't save>");
+ if (res == KEY_EXIT) {
+ global_exit = 0;
+ return -1;
+ }
+
+ /* if we got here, the user really wants to exit */
+ switch (res) {
+ case 0:
+ res = conf_write(filename);
+ if (res)
+ btn_dialog(
+ main_window,
+ _("Error during writing of configuration.\n"
+ "Your configuration changes were NOT saved."),
+ 1,
+ "<OK>");
+ break;
+ default:
+ btn_dialog(
+ main_window,
+ _("Your configuration changes were NOT saved."),
+ 1,
+ "<OK>");
+ break;
+ }
+ global_exit = 1;
+ return 0;
+}
+
+
+static void search_conf(void)
+{
+ struct symbol **sym_arr;
+ struct gstr res;
+ char *dialog_input;
+ int dres;
+again:
+ dres = dialog_inputbox(main_window,
+ _("Search Configuration Parameter"),
+ _("Enter " CONFIG_ " (sub)string to search for "
+ "(with or without \"" CONFIG_ "\")"),
+ "", &dialog_input_result, &dialog_input_result_len);
+ switch (dres) {
+ case 0:
+ break;
+ case 1:
+ show_scroll_win(main_window,
+ _("Search Configuration"), search_help);
+ goto again;
+ default:
+ return;
+ }
+
+ /* strip the prefix if necessary */
+ dialog_input = dialog_input_result;
+ if (strncasecmp(dialog_input_result, CONFIG_, strlen(CONFIG_)) == 0)
+ dialog_input += strlen(CONFIG_);
+
+ sym_arr = sym_re_search(dialog_input);
+ res = get_relations_str(sym_arr);
+ free(sym_arr);
+ show_scroll_win(main_window,
+ _("Search Results"), str_get(&res));
+ str_free(&res);
+}
+
+
+static void build_conf(struct menu *menu)
+{
+ struct symbol *sym;
+ struct property *prop;
+ struct menu *child;
+ int type, tmp, doint = 2;
+ tristate val;
+ char ch;
+
+ if (!menu || (!show_all_items && !menu_is_visible(menu)))
+ return;
+
+ sym = menu->sym;
+ prop = menu->prompt;
+ if (!sym) {
+ if (prop && menu != current_menu) {
+ const char *prompt = menu_get_prompt(menu);
+ enum prop_type ptype;
+ ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
+ switch (ptype) {
+ case P_MENU:
+ child_count++;
+ prompt = _(prompt);
+ if (single_menu_mode) {
+ item_make(menu, 'm',
+ "%s%*c%s",
+ menu->data ? "-->" : "++>",
+ indent + 1, ' ', prompt);
+ } else
+ item_make(menu, 'm',
+ " %*c%s --->",
+ indent + 1,
+ ' ', prompt);
+
+ if (single_menu_mode && menu->data)
+ goto conf_childs;
+ return;
+ case P_COMMENT:
+ if (prompt) {
+ child_count++;
+ item_make(menu, ':',
+ " %*c*** %s ***",
+ indent + 1, ' ',
+ _(prompt));
+ }
+ break;
+ default:
+ if (prompt) {
+ child_count++;
+ item_make(menu, ':', "---%*c%s",
+ indent + 1, ' ',
+ _(prompt));
+ }
+ }
+ } else
+ doint = 0;
+ goto conf_childs;
+ }
+
+ type = sym_get_type(sym);
+ if (sym_is_choice(sym)) {
+ struct symbol *def_sym = sym_get_choice_value(sym);
+ struct menu *def_menu = NULL;
+
+ child_count++;
+ for (child = menu->list; child; child = child->next) {
+ if (menu_is_visible(child) && child->sym == def_sym)
+ def_menu = child;
+ }
+
+ val = sym_get_tristate_value(sym);
+ if (sym_is_changable(sym)) {
+ switch (type) {
+ case S_BOOLEAN:
+ item_make(menu, 't', "[%c]",
+ val == no ? ' ' : '*');
+ break;
+ case S_TRISTATE:
+ switch (val) {
+ case yes:
+ ch = '*';
+ break;
+ case mod:
+ ch = 'M';
+ break;
+ default:
+ ch = ' ';
+ break;
+ }
+ item_make(menu, 't', "<%c>", ch);
+ break;
+ }
+ } else {
+ item_make(menu, def_menu ? 't' : ':', " ");
+ }
+
+ item_add_str("%*c%s", indent + 1,
+ ' ', _(menu_get_prompt(menu)));
+ if (val == yes) {
+ if (def_menu) {
+ item_add_str(" (%s)",
+ _(menu_get_prompt(def_menu)));
+ item_add_str(" --->");
+ if (def_menu->list) {
+ indent += 2;
+ build_conf(def_menu);
+ indent -= 2;
+ }
+ }
+ return;
+ }
+ } else {
+ if (menu == current_menu) {
+ item_make(menu, ':',
+ "---%*c%s", indent + 1,
+ ' ', _(menu_get_prompt(menu)));
+ goto conf_childs;
+ }
+ child_count++;
+ val = sym_get_tristate_value(sym);
+ if (sym_is_choice_value(sym) && val == yes) {
+ item_make(menu, ':', " ");
+ } else {
+ switch (type) {
+ case S_BOOLEAN:
+ if (sym_is_changable(sym))
+ item_make(menu, 't', "[%c]",
+ val == no ? ' ' : '*');
+ else
+ item_make(menu, 't', "-%c-",
+ val == no ? ' ' : '*');
+ break;
+ case S_TRISTATE:
+ switch (val) {
+ case yes:
+ ch = '*';
+ break;
+ case mod:
+ ch = 'M';
+ break;
+ default:
+ ch = ' ';
+ break;
+ }
+ if (sym_is_changable(sym)) {
+ if (sym->rev_dep.tri == mod)
+ item_make(menu,
+ 't', "{%c}", ch);
+ else
+ item_make(menu,
+ 't', "<%c>", ch);
+ } else
+ item_make(menu, 't', "-%c-", ch);
+ break;
+ default:
+ tmp = 2 + strlen(sym_get_string_value(sym));
+ item_make(menu, 's', " (%s)",
+ sym_get_string_value(sym));
+ tmp = indent - tmp + 4;
+ if (tmp < 0)
+ tmp = 0;
+ item_add_str("%*c%s%s", tmp, ' ',
+ _(menu_get_prompt(menu)),
+ (sym_has_value(sym) ||
+ !sym_is_changable(sym)) ? "" :
+ _(" (NEW)"));
+ goto conf_childs;
+ }
+ }
+ item_add_str("%*c%s%s", indent + 1, ' ',
+ _(menu_get_prompt(menu)),
+ (sym_has_value(sym) || !sym_is_changable(sym)) ?
+ "" : _(" (NEW)"));
+ if (menu->prompt && menu->prompt->type == P_MENU) {
+ item_add_str(" --->");
+ return;
+ }
+ }
+
+conf_childs:
+ indent += doint;
+ for (child = menu->list; child; child = child->next)
+ build_conf(child);
+ indent -= doint;
+}
+
+static void reset_menu(void)
+{
+ unpost_menu(curses_menu);
+ clean_items();
+}
+
+/* adjust the menu to show this item.
+ * prefer not to scroll the menu if possible*/
+static void center_item(int selected_index, int *last_top_row)
+{
+ int toprow;
+
+ set_top_row(curses_menu, *last_top_row);
+ toprow = top_row(curses_menu);
+ if (selected_index < toprow ||
+ selected_index >= toprow+mwin_max_lines) {
+ toprow = max(selected_index-mwin_max_lines/2, 0);
+ if (toprow >= item_count(curses_menu)-mwin_max_lines)
+ toprow = item_count(curses_menu)-mwin_max_lines;
+ set_top_row(curses_menu, toprow);
+ }
+ set_current_item(curses_menu,
+ curses_menu_items[selected_index]);
+ *last_top_row = toprow;
+ post_menu(curses_menu);
+ refresh_all_windows(main_window);
+}
+
+/* this function assumes reset_menu has been called before */
+static void show_menu(const char *prompt, const char *instructions,
+ int selected_index, int *last_top_row)
+{
+ int maxx, maxy;
+ WINDOW *menu_window;
+
+ current_instructions = instructions;
+
+ clear();
+ (void) wattrset(main_window, attributes[NORMAL]);
+ print_in_middle(stdscr, 1, 0, COLS,
+ menu_backtitle,
+ attributes[MAIN_HEADING]);
+
+ (void) wattrset(main_window, attributes[MAIN_MENU_BOX]);
+ box(main_window, 0, 0);
+ (void) wattrset(main_window, attributes[MAIN_MENU_HEADING]);
+ mvwprintw(main_window, 0, 3, " %s ", prompt);
+ (void) wattrset(main_window, attributes[NORMAL]);
+
+ set_menu_items(curses_menu, curses_menu_items);
+
+ /* position the menu at the middle of the screen */
+ scale_menu(curses_menu, &maxy, &maxx);
+ maxx = min(maxx, mwin_max_cols-2);
+ maxy = mwin_max_lines;
+ menu_window = derwin(main_window,
+ maxy,
+ maxx,
+ 2,
+ (mwin_max_cols-maxx)/2);
+ keypad(menu_window, TRUE);
+ set_menu_win(curses_menu, menu_window);
+ set_menu_sub(curses_menu, menu_window);
+
+ /* must reassert this after changing items, otherwise returns to a
+ * default of 16
+ */
+ set_menu_format(curses_menu, maxy, 1);
+ center_item(selected_index, last_top_row);
+ set_menu_format(curses_menu, maxy, 1);
+
+ print_function_line();
+
+ /* Post the menu */
+ post_menu(curses_menu);
+ refresh_all_windows(main_window);
+}
+
+static void adj_match_dir(match_f *match_direction)
+{
+ if (*match_direction == FIND_NEXT_MATCH_DOWN)
+ *match_direction =
+ MATCH_TINKER_PATTERN_DOWN;
+ else if (*match_direction == FIND_NEXT_MATCH_UP)
+ *match_direction =
+ MATCH_TINKER_PATTERN_UP;
+ /* else, do no change.. */
+}
+
+struct match_state
+{
+ int in_search;
+ match_f match_direction;
+ char pattern[256];
+};
+
+/* Return 0 means I have handled the key. In such a case, ans should hold the
+ * item to center, or -1 otherwise.
+ * Else return -1 .
+ */
+static int do_match(int key, struct match_state *state, int *ans)
+{
+ char c = (char) key;
+ int terminate_search = 0;
+ *ans = -1;
+ if (key == '/' || (state->in_search && key == 27)) {
+ move(0, 0);
+ refresh();
+ clrtoeol();
+ state->in_search = 1-state->in_search;
+ bzero(state->pattern, sizeof(state->pattern));
+ state->match_direction = MATCH_TINKER_PATTERN_DOWN;
+ return 0;
+ } else if (!state->in_search)
+ return 1;
+
+ if (isalnum(c) || isgraph(c) || c == ' ') {
+ state->pattern[strlen(state->pattern)] = c;
+ state->pattern[strlen(state->pattern)] = '\0';
+ adj_match_dir(&state->match_direction);
+ *ans = get_mext_match(state->pattern,
+ state->match_direction);
+ } else if (key == KEY_DOWN) {
+ state->match_direction = FIND_NEXT_MATCH_DOWN;
+ *ans = get_mext_match(state->pattern,
+ state->match_direction);
+ } else if (key == KEY_UP) {
+ state->match_direction = FIND_NEXT_MATCH_UP;
+ *ans = get_mext_match(state->pattern,
+ state->match_direction);
+ } else if (key == KEY_BACKSPACE || key == 127) {
+ state->pattern[strlen(state->pattern)-1] = '\0';
+ adj_match_dir(&state->match_direction);
+ } else
+ terminate_search = 1;
+
+ if (terminate_search) {
+ state->in_search = 0;
+ bzero(state->pattern, sizeof(state->pattern));
+ move(0, 0);
+ refresh();
+ clrtoeol();
+ return -1;
+ }
+ return 0;
+}
+
+static void conf(struct menu *menu)
+{
+ struct menu *submenu = 0;
+ const char *prompt = menu_get_prompt(menu);
+ struct symbol *sym;
+ int res;
+ int current_index = 0;
+ int last_top_row = 0;
+ struct match_state match_state = {
+ .in_search = 0,
+ .match_direction = MATCH_TINKER_PATTERN_DOWN,
+ .pattern = "",
+ };
+
+ while (!global_exit) {
+ reset_menu();
+ current_menu = menu;
+ build_conf(menu);
+ if (!child_count)
+ break;
+
+ show_menu(prompt ? _(prompt) : _("Main Menu"),
+ _(menu_instructions),
+ current_index, &last_top_row);
+ keypad((menu_win(curses_menu)), TRUE);
+ while (!global_exit) {
+ if (match_state.in_search) {
+ mvprintw(0, 0,
+ "searching: %s", match_state.pattern);
+ clrtoeol();
+ }
+ refresh_all_windows(main_window);
+ res = wgetch(menu_win(curses_menu));
+ if (!res)
+ break;
+ if (do_match(res, &match_state, ¤t_index) == 0) {
+ if (current_index != -1)
+ center_item(current_index,
+ &last_top_row);
+ continue;
+ }
+ if (process_special_keys(&res,
+ (struct menu *) item_data()))
+ break;
+ switch (res) {
+ case KEY_DOWN:
+ menu_driver(curses_menu, REQ_DOWN_ITEM);
+ break;
+ case KEY_UP:
+ menu_driver(curses_menu, REQ_UP_ITEM);
+ break;
+ case KEY_NPAGE:
+ menu_driver(curses_menu, REQ_SCR_DPAGE);
+ break;
+ case KEY_PPAGE:
+ menu_driver(curses_menu, REQ_SCR_UPAGE);
+ break;
+ case KEY_HOME:
+ menu_driver(curses_menu, REQ_FIRST_ITEM);
+ break;
+ case KEY_END:
+ menu_driver(curses_menu, REQ_LAST_ITEM);
+ break;
+ case 'h':
+ case '?':
+ show_help((struct menu *) item_data());
+ break;
+ }
+ if (res == 10 || res == 27 ||
+ res == 32 || res == 'n' || res == 'y' ||
+ res == KEY_LEFT || res == KEY_RIGHT ||
+ res == 'm')
+ break;
+ refresh_all_windows(main_window);
+ }
+
+ refresh_all_windows(main_window);
+ /* if ESC or left*/
+ if (res == 27 || (menu != &rootmenu && res == KEY_LEFT))
+ break;
+
+ /* remember location in the menu */
+ last_top_row = top_row(curses_menu);
+ current_index = curses_item_index();
+
+ if (!item_tag())
+ continue;
+
+ submenu = (struct menu *) item_data();
+ if (!submenu || !menu_is_visible(submenu))
+ continue;
+ sym = submenu->sym;
+
+ switch (res) {
+ case ' ':
+ if (item_is_tag('t'))
+ sym_toggle_tristate_value(sym);
+ else if (item_is_tag('m'))
+ conf(submenu);
+ break;
+ case KEY_RIGHT:
+ case 10: /* ENTER WAS PRESSED */
+ switch (item_tag()) {
+ case 'm':
+ if (single_menu_mode)
+ submenu->data =
+ (void *) (long) !submenu->data;
+ else
+ conf(submenu);
+ break;
+ case 't':
+ if (sym_is_choice(sym) &&
+ sym_get_tristate_value(sym) == yes)
+ conf_choice(submenu);
+ else if (submenu->prompt &&
+ submenu->prompt->type == P_MENU)
+ conf(submenu);
+ else if (res == 10)
+ sym_toggle_tristate_value(sym);
+ break;
+ case 's':
+ conf_string(submenu);
+ break;
+ }
+ break;
+ case 'y':
+ if (item_is_tag('t')) {
+ if (sym_set_tristate_value(sym, yes))
+ break;
+ if (sym_set_tristate_value(sym, mod))
+ btn_dialog(main_window, setmod_text, 0);
+ }
+ break;
+ case 'n':
+ if (item_is_tag('t'))
+ sym_set_tristate_value(sym, no);
+ break;
+ case 'm':
+ if (item_is_tag('t'))
+ sym_set_tristate_value(sym, mod);
+ break;
+ }
+ }
+}
+
+static void conf_message_callback(const char *fmt, va_list ap)
+{
+ char buf[1024];
+
+ vsnprintf(buf, sizeof(buf), fmt, ap);
+ btn_dialog(main_window, buf, 1, "<OK>");
+}
+
+static void show_help(struct menu *menu)
+{
+ struct gstr help;
+
+ if (!menu)
+ return;
+
+ help = str_new();
+ menu_get_ext_help(menu, &help);
+ show_scroll_win(main_window, _(menu_get_prompt(menu)), str_get(&help));
+ str_free(&help);
+}
+
+static void conf_choice(struct menu *menu)
+{
+ const char *prompt = _(menu_get_prompt(menu));
+ struct menu *child = 0;
+ struct symbol *active;
+ int selected_index = 0;
+ int last_top_row = 0;
+ int res, i = 0;
+ struct match_state match_state = {
+ .in_search = 0,
+ .match_direction = MATCH_TINKER_PATTERN_DOWN,
+ .pattern = "",
+ };
+
+ active = sym_get_choice_value(menu->sym);
+ /* this is mostly duplicated from the conf() function. */
+ while (!global_exit) {
+ reset_menu();
+
+ for (i = 0, child = menu->list; child; child = child->next) {
+ if (!show_all_items && !menu_is_visible(child))
+ continue;
+
+ if (child->sym == sym_get_choice_value(menu->sym))
+ item_make(child, ':', "<X> %s",
+ _(menu_get_prompt(child)));
+ else if (child->sym)
+ item_make(child, ':', " %s",
+ _(menu_get_prompt(child)));
+ else
+ item_make(child, ':', "*** %s ***",
+ _(menu_get_prompt(child)));
+
+ if (child->sym == active){
+ last_top_row = top_row(curses_menu);
+ selected_index = i;
+ }
+ i++;
+ }
+ show_menu(prompt ? _(prompt) : _("Choice Menu"),
+ _(radiolist_instructions),
+ selected_index,
+ &last_top_row);
+ while (!global_exit) {
+ if (match_state.in_search) {
+ mvprintw(0, 0, "searching: %s",
+ match_state.pattern);
+ clrtoeol();
+ }
+ refresh_all_windows(main_window);
+ res = wgetch(menu_win(curses_menu));
+ if (!res)
+ break;
+ if (do_match(res, &match_state, &selected_index) == 0) {
+ if (selected_index != -1)
+ center_item(selected_index,
+ &last_top_row);
+ continue;
+ }
+ if (process_special_keys(
+ &res,
+ (struct menu *) item_data()))
+ break;
+ switch (res) {
+ case KEY_DOWN:
+ menu_driver(curses_menu, REQ_DOWN_ITEM);
+ break;
+ case KEY_UP:
+ menu_driver(curses_menu, REQ_UP_ITEM);
+ break;
+ case KEY_NPAGE:
+ menu_driver(curses_menu, REQ_SCR_DPAGE);
+ break;
+ case KEY_PPAGE:
+ menu_driver(curses_menu, REQ_SCR_UPAGE);
+ break;
+ case KEY_HOME:
+ menu_driver(curses_menu, REQ_FIRST_ITEM);
+ break;
+ case KEY_END:
+ menu_driver(curses_menu, REQ_LAST_ITEM);
+ break;
+ case 'h':
+ case '?':
+ show_help((struct menu *) item_data());
+ break;
+ }
+ if (res == 10 || res == 27 || res == ' ' ||
+ res == KEY_LEFT){
+ break;
+ }
+ refresh_all_windows(main_window);
+ }
+ /* if ESC or left */
+ if (res == 27 || res == KEY_LEFT)
+ break;
+
+ child = item_data();
+ if (!child || !menu_is_visible(child) || !child->sym)
+ continue;
+ switch (res) {
+ case ' ':
+ case 10:
+ case KEY_RIGHT:
+ sym_set_tristate_value(child->sym, yes);
+ return;
+ case 'h':
+ case '?':
+ show_help(child);
+ active = child->sym;
+ break;
+ case KEY_EXIT:
+ return;
+ }
+ }
+}
+
+static void conf_string(struct menu *menu)
+{
+ const char *prompt = menu_get_prompt(menu);
+
+ while (1) {
+ int res;
+ const char *heading;
+
+ switch (sym_get_type(menu->sym)) {
+ case S_INT:
+ heading = _(inputbox_instructions_int);
+ break;
+ case S_HEX:
+ heading = _(inputbox_instructions_hex);
+ break;
+ case S_STRING:
+ heading = _(inputbox_instructions_string);
+ break;
+ default:
+ heading = _("Internal nconf error!");
+ }
+ res = dialog_inputbox(main_window,
+ prompt ? _(prompt) : _("Main Menu"),
+ heading,
+ sym_get_string_value(menu->sym),
+ &dialog_input_result,
+ &dialog_input_result_len);
+ switch (res) {
+ case 0:
+ if (sym_set_string_value(menu->sym,
+ dialog_input_result))
+ return;
+ btn_dialog(main_window,
+ _("You have made an invalid entry."), 0);
+ break;
+ case 1:
+ show_help(menu);
+ break;
+ case KEY_EXIT:
+ return;
+ }
+ }
+}
+
+static void conf_load(void)
+{
+ while (1) {
+ int res;
+ res = dialog_inputbox(main_window,
+ NULL, load_config_text,
+ filename,
+ &dialog_input_result,
+ &dialog_input_result_len);
+ switch (res) {
+ case 0:
+ if (!dialog_input_result[0])
+ return;
+ if (!conf_read(dialog_input_result)) {
+ set_config_filename(dialog_input_result);
+ sym_set_change_count(1);
+ return;
+ }
+ btn_dialog(main_window, _("File does not exist!"), 0);
+ break;
+ case 1:
+ show_scroll_win(main_window,
+ _("Load Alternate Configuration"),
+ load_config_help);
+ break;
+ case KEY_EXIT:
+ return;
+ }
+ }
+}
+
+static void conf_save(void)
+{
+ while (1) {
+ int res;
+ res = dialog_inputbox(main_window,
+ NULL, save_config_text,
+ filename,
+ &dialog_input_result,
+ &dialog_input_result_len);
+ switch (res) {
+ case 0:
+ if (!dialog_input_result[0])
+ return;
+ res = conf_write(dialog_input_result);
+ if (!res) {
+ set_config_filename(dialog_input_result);
+ return;
+ }
+ btn_dialog(main_window, _("Can't create file! "
+ "Probably a nonexistent directory."),
+ 1, "<OK>");
+ break;
+ case 1:
+ show_scroll_win(main_window,
+ _("Save Alternate Configuration"),
+ save_config_help);
+ break;
+ case KEY_EXIT:
+ return;
+ }
+ }
+}
+
+void setup_windows(void)
+{
+ if (main_window != NULL)
+ delwin(main_window);
+
+ /* set up the menu and menu window */
+ main_window = newwin(LINES-2, COLS-2, 2, 1);
+ keypad(main_window, TRUE);
+ mwin_max_lines = LINES-7;
+ mwin_max_cols = COLS-6;
+
+ /* panels order is from bottom to top */
+ new_panel(main_window);
+}
+
+int main(int ac, char **av)
+{
+ char *mode;
+
+ setlocale(LC_ALL, "");
+ bindtextdomain(PACKAGE, LOCALEDIR);
+ textdomain(PACKAGE);
+
+ conf_parse(av[1]);
+ conf_read(NULL);
+
+ mode = getenv("NCONFIG_MODE");
+ if (mode) {
+ if (!strcasecmp(mode, "single_menu"))
+ single_menu_mode = 1;
+ }
+
+ /* Initialize curses */
+ initscr();
+ /* set color theme */
+ set_colors();
+
+ cbreak();
+ noecho();
+ keypad(stdscr, TRUE);
+ curs_set(0);
+
+ if (COLS < 75 || LINES < 20) {
+ endwin();
+ printf("Your terminal should have at "
+ "least 20 lines and 75 columns\n");
+ return 1;
+ }
+
+ notimeout(stdscr, FALSE);
+ ESCDELAY = 1;
+
+ /* set btns menu */
+ curses_menu = new_menu(curses_menu_items);
+ menu_opts_off(curses_menu, O_SHOWDESC);
+ menu_opts_on(curses_menu, O_SHOWMATCH);
+ menu_opts_on(curses_menu, O_ONEVALUE);
+ menu_opts_on(curses_menu, O_NONCYCLIC);
+ menu_opts_on(curses_menu, O_IGNORECASE);
+ set_menu_mark(curses_menu, " ");
+ set_menu_fore(curses_menu, attributes[MAIN_MENU_FORE]);
+ set_menu_back(curses_menu, attributes[MAIN_MENU_BACK]);
+ set_menu_grey(curses_menu, attributes[MAIN_MENU_GREY]);
+
+ set_config_filename(conf_get_configname());
+ setup_windows();
+
+ /* check for KEY_FUNC(1) */
+ if (has_key(KEY_F(1)) == FALSE) {
+ show_scroll_win(main_window,
+ _("Instructions"),
+ _(menu_no_f_instructions));
+ }
+
+ conf_set_message_callback(conf_message_callback);
+ /* do the work */
+ while (!global_exit) {
+ conf(&rootmenu);
+ if (!global_exit && do_exit() == 0)
+ break;
+ }
+ /* ok, we are done */
+ unpost_menu(curses_menu);
+ free_menu(curses_menu);
+ delwin(main_window);
+ clear();
+ refresh();
+ endwin();
+ return 0;
+}
+
--- /dev/null
+/*
+ * Copyright (C) 2008 Nir Tzachar <nir.tzachar@gmail.com?
+ * Released under the terms of the GNU GPL v2.0.
+ *
+ * Derived from menuconfig.
+ *
+ */
+#include "nconf.h"
+
+/* a list of all the different widgets we use */
+attributes_t attributes[ATTR_MAX+1] = {0};
+
+/* available colors:
+ COLOR_BLACK 0
+ COLOR_RED 1
+ COLOR_GREEN 2
+ COLOR_YELLOW 3
+ COLOR_BLUE 4
+ COLOR_MAGENTA 5
+ COLOR_CYAN 6
+ COLOR_WHITE 7
+ */
+static void set_normal_colors(void)
+{
+ init_pair(NORMAL, -1, -1);
+ init_pair(MAIN_HEADING, COLOR_MAGENTA, -1);
+
+ /* FORE is for the selected item */
+ init_pair(MAIN_MENU_FORE, -1, -1);
+ /* BACK for all the rest */
+ init_pair(MAIN_MENU_BACK, -1, -1);
+ init_pair(MAIN_MENU_GREY, -1, -1);
+ init_pair(MAIN_MENU_HEADING, COLOR_GREEN, -1);
+ init_pair(MAIN_MENU_BOX, COLOR_YELLOW, -1);
+
+ init_pair(SCROLLWIN_TEXT, -1, -1);
+ init_pair(SCROLLWIN_HEADING, COLOR_GREEN, -1);
+ init_pair(SCROLLWIN_BOX, COLOR_YELLOW, -1);
+
+ init_pair(DIALOG_TEXT, -1, -1);
+ init_pair(DIALOG_BOX, COLOR_YELLOW, -1);
+ init_pair(DIALOG_MENU_BACK, COLOR_YELLOW, -1);
+ init_pair(DIALOG_MENU_FORE, COLOR_RED, -1);
+
+ init_pair(INPUT_BOX, COLOR_YELLOW, -1);
+ init_pair(INPUT_HEADING, COLOR_GREEN, -1);
+ init_pair(INPUT_TEXT, -1, -1);
+ init_pair(INPUT_FIELD, -1, -1);
+
+ init_pair(FUNCTION_HIGHLIGHT, -1, -1);
+ init_pair(FUNCTION_TEXT, COLOR_BLUE, -1);
+}
+
+/* available attributes:
+ A_NORMAL Normal display (no highlight)
+ A_STANDOUT Best highlighting mode of the terminal.
+ A_UNDERLINE Underlining
+ A_REVERSE Reverse video
+ A_BLINK Blinking
+ A_DIM Half bright
+ A_BOLD Extra bright or bold
+ A_PROTECT Protected mode
+ A_INVIS Invisible or blank mode
+ A_ALTCHARSET Alternate character set
+ A_CHARTEXT Bit-mask to extract a character
+ COLOR_PAIR(n) Color-pair number n
+ */
+static void normal_color_theme(void)
+{
+ /* automatically add color... */
+#define mkattr(name, attr) do { \
+attributes[name] = attr | COLOR_PAIR(name); } while (0)
+ mkattr(NORMAL, NORMAL);
+ mkattr(MAIN_HEADING, A_BOLD | A_UNDERLINE);
+
+ mkattr(MAIN_MENU_FORE, A_REVERSE);
+ mkattr(MAIN_MENU_BACK, A_NORMAL);
+ mkattr(MAIN_MENU_GREY, A_NORMAL);
+ mkattr(MAIN_MENU_HEADING, A_BOLD);
+ mkattr(MAIN_MENU_BOX, A_NORMAL);
+
+ mkattr(SCROLLWIN_TEXT, A_NORMAL);
+ mkattr(SCROLLWIN_HEADING, A_BOLD);
+ mkattr(SCROLLWIN_BOX, A_BOLD);
+
+ mkattr(DIALOG_TEXT, A_BOLD);
+ mkattr(DIALOG_BOX, A_BOLD);
+ mkattr(DIALOG_MENU_FORE, A_STANDOUT);
+ mkattr(DIALOG_MENU_BACK, A_NORMAL);
+
+ mkattr(INPUT_BOX, A_NORMAL);
+ mkattr(INPUT_HEADING, A_BOLD);
+ mkattr(INPUT_TEXT, A_NORMAL);
+ mkattr(INPUT_FIELD, A_UNDERLINE);
+
+ mkattr(FUNCTION_HIGHLIGHT, A_BOLD);
+ mkattr(FUNCTION_TEXT, A_REVERSE);
+}
+
+static void no_colors_theme(void)
+{
+ /* automatically add highlight, no color */
+#define mkattrn(name, attr) { attributes[name] = attr; }
+
+ mkattrn(NORMAL, NORMAL);
+ mkattrn(MAIN_HEADING, A_BOLD | A_UNDERLINE);
+
+ mkattrn(MAIN_MENU_FORE, A_STANDOUT);
+ mkattrn(MAIN_MENU_BACK, A_NORMAL);
+ mkattrn(MAIN_MENU_GREY, A_NORMAL);
+ mkattrn(MAIN_MENU_HEADING, A_BOLD);
+ mkattrn(MAIN_MENU_BOX, A_NORMAL);
+
+ mkattrn(SCROLLWIN_TEXT, A_NORMAL);
+ mkattrn(SCROLLWIN_HEADING, A_BOLD);
+ mkattrn(SCROLLWIN_BOX, A_BOLD);
+
+ mkattrn(DIALOG_TEXT, A_NORMAL);
+ mkattrn(DIALOG_BOX, A_BOLD);
+ mkattrn(DIALOG_MENU_FORE, A_STANDOUT);
+ mkattrn(DIALOG_MENU_BACK, A_NORMAL);
+
+ mkattrn(INPUT_BOX, A_BOLD);
+ mkattrn(INPUT_HEADING, A_BOLD);
+ mkattrn(INPUT_TEXT, A_NORMAL);
+ mkattrn(INPUT_FIELD, A_UNDERLINE);
+
+ mkattrn(FUNCTION_HIGHLIGHT, A_BOLD);
+ mkattrn(FUNCTION_TEXT, A_REVERSE);
+}
+
+void set_colors()
+{
+ start_color();
+ use_default_colors();
+ set_normal_colors();
+ if (has_colors()) {
+ normal_color_theme();
+ } else {
+ /* give defaults */
+ no_colors_theme();
+ }
+}
+
+
+/* this changes the windows attributes !!! */
+void print_in_middle(WINDOW *win,
+ int starty,
+ int startx,
+ int width,
+ const char *string,
+ chtype color)
+{ int length, x, y;
+ float temp;
+
+
+ if (win == NULL)
+ win = stdscr;
+ getyx(win, y, x);
+ if (startx != 0)
+ x = startx;
+ if (starty != 0)
+ y = starty;
+ if (width == 0)
+ width = 80;
+
+ length = strlen(string);
+ temp = (width - length) / 2;
+ x = startx + (int)temp;
+ (void) wattrset(win, color);
+ mvwprintw(win, y, x, "%s", string);
+ refresh();
+}
+
+int get_line_no(const char *text)
+{
+ int i;
+ int total = 1;
+
+ if (!text)
+ return 0;
+
+ for (i = 0; text[i] != '\0'; i++)
+ if (text[i] == '\n')
+ total++;
+ return total;
+}
+
+const char *get_line(const char *text, int line_no)
+{
+ int i;
+ int lines = 0;
+
+ if (!text)
+ return 0;
+
+ for (i = 0; text[i] != '\0' && lines < line_no; i++)
+ if (text[i] == '\n')
+ lines++;
+ return text+i;
+}
+
+int get_line_length(const char *line)
+{
+ int res = 0;
+ while (*line != '\0' && *line != '\n') {
+ line++;
+ res++;
+ }
+ return res;
+}
+
+/* print all lines to the window. */
+void fill_window(WINDOW *win, const char *text)
+{
+ int x, y;
+ int total_lines = get_line_no(text);
+ int i;
+
+ getmaxyx(win, y, x);
+ /* do not go over end of line */
+ total_lines = min(total_lines, y);
+ for (i = 0; i < total_lines; i++) {
+ char tmp[x+10];
+ const char *line = get_line(text, i);
+ int len = get_line_length(line);
+ strncpy(tmp, line, min(len, x));
+ tmp[len] = '\0';
+ mvwprintw(win, i, 0, "%s", tmp);
+ }
+}
+
+/* get the message, and buttons.
+ * each button must be a char*
+ * return the selected button
+ *
+ * this dialog is used for 2 different things:
+ * 1) show a text box, no buttons.
+ * 2) show a dialog, with horizontal buttons
+ */
+int btn_dialog(WINDOW *main_window, const char *msg, int btn_num, ...)
+{
+ va_list ap;
+ char *btn;
+ int btns_width = 0;
+ int msg_lines = 0;
+ int msg_width = 0;
+ int total_width;
+ int win_rows = 0;
+ WINDOW *win;
+ WINDOW *msg_win;
+ WINDOW *menu_win;
+ MENU *menu;
+ ITEM *btns[btn_num+1];
+ int i, x, y;
+ int res = -1;
+
+
+ va_start(ap, btn_num);
+ for (i = 0; i < btn_num; i++) {
+ btn = va_arg(ap, char *);
+ btns[i] = new_item(btn, "");
+ btns_width += strlen(btn)+1;
+ }
+ va_end(ap);
+ btns[btn_num] = NULL;
+
+ /* find the widest line of msg: */
+ msg_lines = get_line_no(msg);
+ for (i = 0; i < msg_lines; i++) {
+ const char *line = get_line(msg, i);
+ int len = get_line_length(line);
+ if (msg_width < len)
+ msg_width = len;
+ }
+
+ total_width = max(msg_width, btns_width);
+ /* place dialog in middle of screen */
+ y = (LINES-(msg_lines+4))/2;
+ x = (COLS-(total_width+4))/2;
+
+
+ /* create the windows */
+ if (btn_num > 0)
+ win_rows = msg_lines+4;
+ else
+ win_rows = msg_lines+2;
+
+ win = newwin(win_rows, total_width+4, y, x);
+ keypad(win, TRUE);
+ menu_win = derwin(win, 1, btns_width, win_rows-2,
+ 1+(total_width+2-btns_width)/2);
+ menu = new_menu(btns);
+ msg_win = derwin(win, win_rows-2, msg_width, 1,
+ 1+(total_width+2-msg_width)/2);
+
+ set_menu_fore(menu, attributes[DIALOG_MENU_FORE]);
+ set_menu_back(menu, attributes[DIALOG_MENU_BACK]);
+
+ (void) wattrset(win, attributes[DIALOG_BOX]);
+ box(win, 0, 0);
+
+ /* print message */
+ (void) wattrset(msg_win, attributes[DIALOG_TEXT]);
+ fill_window(msg_win, msg);
+
+ set_menu_win(menu, win);
+ set_menu_sub(menu, menu_win);
+ set_menu_format(menu, 1, btn_num);
+ menu_opts_off(menu, O_SHOWDESC);
+ menu_opts_off(menu, O_SHOWMATCH);
+ menu_opts_on(menu, O_ONEVALUE);
+ menu_opts_on(menu, O_NONCYCLIC);
+ set_menu_mark(menu, "");
+ post_menu(menu);
+
+
+ touchwin(win);
+ refresh_all_windows(main_window);
+ while ((res = wgetch(win))) {
+ switch (res) {
+ case KEY_LEFT:
+ menu_driver(menu, REQ_LEFT_ITEM);
+ break;
+ case KEY_RIGHT:
+ menu_driver(menu, REQ_RIGHT_ITEM);
+ break;
+ case 10: /* ENTER */
+ case 27: /* ESCAPE */
+ case ' ':
+ case KEY_F(F_BACK):
+ case KEY_F(F_EXIT):
+ break;
+ }
+ touchwin(win);
+ refresh_all_windows(main_window);
+
+ if (res == 10 || res == ' ') {
+ res = item_index(current_item(menu));
+ break;
+ } else if (res == 27 || res == KEY_F(F_BACK) ||
+ res == KEY_F(F_EXIT)) {
+ res = KEY_EXIT;
+ break;
+ }
+ }
+
+ unpost_menu(menu);
+ free_menu(menu);
+ for (i = 0; i < btn_num; i++)
+ free_item(btns[i]);
+
+ delwin(win);
+ return res;
+}
+
+int dialog_inputbox(WINDOW *main_window,
+ const char *title, const char *prompt,
+ const char *init, char **resultp, int *result_len)
+{
+ int prompt_lines = 0;
+ int prompt_width = 0;
+ WINDOW *win;
+ WINDOW *prompt_win;
+ WINDOW *form_win;
+ PANEL *panel;
+ int i, x, y;
+ int res = -1;
+ int cursor_position = strlen(init);
+ int cursor_form_win;
+ char *result = *resultp;
+
+ if (strlen(init)+1 > *result_len) {
+ *result_len = strlen(init)+1;
+ *resultp = result = realloc(result, *result_len);
+ }
+
+ /* find the widest line of msg: */
+ prompt_lines = get_line_no(prompt);
+ for (i = 0; i < prompt_lines; i++) {
+ const char *line = get_line(prompt, i);
+ int len = get_line_length(line);
+ prompt_width = max(prompt_width, len);
+ }
+
+ if (title)
+ prompt_width = max(prompt_width, strlen(title));
+
+ /* place dialog in middle of screen */
+ y = (LINES-(prompt_lines+4))/2;
+ x = (COLS-(prompt_width+4))/2;
+
+ strncpy(result, init, *result_len);
+
+ /* create the windows */
+ win = newwin(prompt_lines+6, prompt_width+7, y, x);
+ prompt_win = derwin(win, prompt_lines+1, prompt_width, 2, 2);
+ form_win = derwin(win, 1, prompt_width, prompt_lines+3, 2);
+ keypad(form_win, TRUE);
+
+ (void) wattrset(form_win, attributes[INPUT_FIELD]);
+
+ (void) wattrset(win, attributes[INPUT_BOX]);
+ box(win, 0, 0);
+ (void) wattrset(win, attributes[INPUT_HEADING]);
+ if (title)
+ mvwprintw(win, 0, 3, "%s", title);
+
+ /* print message */
+ (void) wattrset(prompt_win, attributes[INPUT_TEXT]);
+ fill_window(prompt_win, prompt);
+
+ mvwprintw(form_win, 0, 0, "%*s", prompt_width, " ");
+ cursor_form_win = min(cursor_position, prompt_width-1);
+ mvwprintw(form_win, 0, 0, "%s",
+ result + cursor_position-cursor_form_win);
+
+ /* create panels */
+ panel = new_panel(win);
+
+ /* show the cursor */
+ curs_set(1);
+
+ touchwin(win);
+ refresh_all_windows(main_window);
+ while ((res = wgetch(form_win))) {
+ int len = strlen(result);
+ switch (res) {
+ case 10: /* ENTER */
+ case 27: /* ESCAPE */
+ case KEY_F(F_HELP):
+ case KEY_F(F_EXIT):
+ case KEY_F(F_BACK):
+ break;
+ case 127:
+ case KEY_BACKSPACE:
+ if (cursor_position > 0) {
+ memmove(&result[cursor_position-1],
+ &result[cursor_position],
+ len-cursor_position+1);
+ cursor_position--;
+ cursor_form_win--;
+ len--;
+ }
+ break;
+ case KEY_DC:
+ if (cursor_position >= 0 && cursor_position < len) {
+ memmove(&result[cursor_position],
+ &result[cursor_position+1],
+ len-cursor_position+1);
+ len--;
+ }
+ break;
+ case KEY_UP:
+ case KEY_RIGHT:
+ if (cursor_position < len) {
+ cursor_position++;
+ cursor_form_win++;
+ }
+ break;
+ case KEY_DOWN:
+ case KEY_LEFT:
+ if (cursor_position > 0) {
+ cursor_position--;
+ cursor_form_win--;
+ }
+ break;
+ case KEY_HOME:
+ cursor_position = 0;
+ cursor_form_win = 0;
+ break;
+ case KEY_END:
+ cursor_position = len;
+ cursor_form_win = min(cursor_position, prompt_width-1);
+ break;
+ default:
+ if ((isgraph(res) || isspace(res))) {
+ /* one for new char, one for '\0' */
+ if (len+2 > *result_len) {
+ *result_len = len+2;
+ *resultp = result = realloc(result,
+ *result_len);
+ }
+ /* insert the char at the proper position */
+ memmove(&result[cursor_position+1],
+ &result[cursor_position],
+ len-cursor_position+1);
+ result[cursor_position] = res;
+ cursor_position++;
+ cursor_form_win++;
+ len++;
+ } else {
+ mvprintw(0, 0, "unknown key: %d\n", res);
+ }
+ break;
+ }
+ if (cursor_form_win < 0)
+ cursor_form_win = 0;
+ else if (cursor_form_win > prompt_width-1)
+ cursor_form_win = prompt_width-1;
+
+ wmove(form_win, 0, 0);
+ wclrtoeol(form_win);
+ mvwprintw(form_win, 0, 0, "%*s", prompt_width, " ");
+ mvwprintw(form_win, 0, 0, "%s",
+ result + cursor_position-cursor_form_win);
+ wmove(form_win, 0, cursor_form_win);
+ touchwin(win);
+ refresh_all_windows(main_window);
+
+ if (res == 10) {
+ res = 0;
+ break;
+ } else if (res == 27 || res == KEY_F(F_BACK) ||
+ res == KEY_F(F_EXIT)) {
+ res = KEY_EXIT;
+ break;
+ } else if (res == KEY_F(F_HELP)) {
+ res = 1;
+ break;
+ }
+ }
+
+ /* hide the cursor */
+ curs_set(0);
+ del_panel(panel);
+ delwin(prompt_win);
+ delwin(form_win);
+ delwin(win);
+ return res;
+}
+
+/* refresh all windows in the correct order */
+void refresh_all_windows(WINDOW *main_window)
+{
+ update_panels();
+ touchwin(main_window);
+ refresh();
+}
+
+/* layman's scrollable window... */
+void show_scroll_win(WINDOW *main_window,
+ const char *title,
+ const char *text)
+{
+ int res;
+ int total_lines = get_line_no(text);
+ int x, y;
+ int start_x = 0, start_y = 0;
+ int text_lines = 0, text_cols = 0;
+ int total_cols = 0;
+ int win_cols = 0;
+ int win_lines = 0;
+ int i = 0;
+ WINDOW *win;
+ WINDOW *pad;
+ PANEL *panel;
+
+ /* find the widest line of msg: */
+ total_lines = get_line_no(text);
+ for (i = 0; i < total_lines; i++) {
+ const char *line = get_line(text, i);
+ int len = get_line_length(line);
+ total_cols = max(total_cols, len+2);
+ }
+
+ /* create the pad */
+ pad = newpad(total_lines+10, total_cols+10);
+ (void) wattrset(pad, attributes[SCROLLWIN_TEXT]);
+ fill_window(pad, text);
+
+ win_lines = min(total_lines+4, LINES-2);
+ win_cols = min(total_cols+2, COLS-2);
+ text_lines = max(win_lines-4, 0);
+ text_cols = max(win_cols-2, 0);
+
+ /* place window in middle of screen */
+ y = (LINES-win_lines)/2;
+ x = (COLS-win_cols)/2;
+
+ win = newwin(win_lines, win_cols, y, x);
+ keypad(win, TRUE);
+ /* show the help in the help window, and show the help panel */
+ (void) wattrset(win, attributes[SCROLLWIN_BOX]);
+ box(win, 0, 0);
+ (void) wattrset(win, attributes[SCROLLWIN_HEADING]);
+ mvwprintw(win, 0, 3, " %s ", title);
+ panel = new_panel(win);
+
+ /* handle scrolling */
+ do {
+
+ copywin(pad, win, start_y, start_x, 2, 2, text_lines,
+ text_cols, 0);
+ print_in_middle(win,
+ text_lines+2,
+ 0,
+ text_cols,
+ "<OK>",
+ attributes[DIALOG_MENU_FORE]);
+ wrefresh(win);
+
+ res = wgetch(win);
+ switch (res) {
+ case KEY_NPAGE:
+ case ' ':
+ start_y += text_lines-2;
+ break;
+ case KEY_PPAGE:
+ start_y -= text_lines+2;
+ break;
+ case KEY_HOME:
+ start_y = 0;
+ break;
+ case KEY_END:
+ start_y = total_lines-text_lines;
+ break;
+ case KEY_DOWN:
+ case 'j':
+ start_y++;
+ break;
+ case KEY_UP:
+ case 'k':
+ start_y--;
+ break;
+ case KEY_LEFT:
+ case 'h':
+ start_x--;
+ break;
+ case KEY_RIGHT:
+ case 'l':
+ start_x++;
+ break;
+ }
+ if (res == 10 || res == 27 || res == 'q'
+ || res == KEY_F(F_BACK) || res == KEY_F(F_EXIT)) {
+ break;
+ }
+ if (start_y < 0)
+ start_y = 0;
+ if (start_y >= total_lines-text_lines)
+ start_y = total_lines-text_lines;
+ if (start_x < 0)
+ start_x = 0;
+ if (start_x >= total_cols-text_cols)
+ start_x = total_cols-text_cols;
+ } while (res);
+
+ del_panel(panel);
+ delwin(win);
+ refresh_all_windows(main_window);
+}
--- /dev/null
+/*
+ * Copyright (C) 2008 Nir Tzachar <nir.tzachar@gmail.com?
+ * Released under the terms of the GNU GPL v2.0.
+ *
+ * Derived from menuconfig.
+ *
+ */
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <locale.h>
+#include <curses.h>
+#include <menu.h>
+#include <panel.h>
+#include <form.h>
+
+#include <stdio.h>
+#include <time.h>
+#include <sys/time.h>
+
+#include "ncurses.h"
+
+#define max(a, b) ({\
+ typeof(a) _a = a;\
+ typeof(b) _b = b;\
+ _a > _b ? _a : _b; })
+
+#define min(a, b) ({\
+ typeof(a) _a = a;\
+ typeof(b) _b = b;\
+ _a < _b ? _a : _b; })
+
+typedef enum {
+ NORMAL = 1,
+ MAIN_HEADING,
+ MAIN_MENU_BOX,
+ MAIN_MENU_FORE,
+ MAIN_MENU_BACK,
+ MAIN_MENU_GREY,
+ MAIN_MENU_HEADING,
+ SCROLLWIN_TEXT,
+ SCROLLWIN_HEADING,
+ SCROLLWIN_BOX,
+ DIALOG_TEXT,
+ DIALOG_MENU_FORE,
+ DIALOG_MENU_BACK,
+ DIALOG_BOX,
+ INPUT_BOX,
+ INPUT_HEADING,
+ INPUT_TEXT,
+ INPUT_FIELD,
+ FUNCTION_TEXT,
+ FUNCTION_HIGHLIGHT,
+ ATTR_MAX
+} attributes_t;
+extern attributes_t attributes[];
+
+typedef enum {
+ F_HELP = 1,
+ F_SYMBOL = 2,
+ F_INSTS = 3,
+ F_CONF = 4,
+ F_BACK = 5,
+ F_SAVE = 6,
+ F_LOAD = 7,
+ F_SEARCH = 8,
+ F_EXIT = 9,
+} function_key;
+
+void set_colors(void);
+
+/* this changes the windows attributes !!! */
+void print_in_middle(WINDOW *win,
+ int starty,
+ int startx,
+ int width,
+ const char *string,
+ chtype color);
+int get_line_length(const char *line);
+int get_line_no(const char *text);
+const char *get_line(const char *text, int line_no);
+void fill_window(WINDOW *win, const char *text);
+int btn_dialog(WINDOW *main_window, const char *msg, int btn_num, ...);
+int dialog_inputbox(WINDOW *main_window,
+ const char *title, const char *prompt,
+ const char *init, char **resultp, int *result_len);
+void refresh_all_windows(WINDOW *main_window);
+void show_scroll_win(WINDOW *main_window,
+ const char *title,
+ const char *text);
--- /dev/null
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#include <qglobal.h>
+
+#if QT_VERSION < 0x040000
+#include <qmainwindow.h>
+#include <qvbox.h>
+#include <qvaluelist.h>
+#include <qtextbrowser.h>
+#include <qaction.h>
+#include <qheader.h>
+#include <qfiledialog.h>
+#include <qdragobject.h>
+#include <qpopupmenu.h>
+#else
+#include <q3mainwindow.h>
+#include <q3vbox.h>
+#include <q3valuelist.h>
+#include <q3textbrowser.h>
+#include <q3action.h>
+#include <q3header.h>
+#include <q3filedialog.h>
+#include <q3dragobject.h>
+#include <q3popupmenu.h>
+#endif
+
+#include <qapplication.h>
+#include <qdesktopwidget.h>
+#include <qtoolbar.h>
+#include <qlayout.h>
+#include <qsplitter.h>
+#include <qlineedit.h>
+#include <qlabel.h>
+#include <qpushbutton.h>
+#include <qmenubar.h>
+#include <qmessagebox.h>
+#include <qregexp.h>
+#include <qevent.h>
+
+#include <stdlib.h>
+
+#include "lkc.h"
+#include "qconf.h"
+
+#include "qconf.moc"
+#include "images.c"
+
+#ifdef _
+# undef _
+# define _ qgettext
+#endif
+
+static QApplication *configApp;
+static ConfigSettings *configSettings;
+
+Q3Action *ConfigMainWindow::saveAction;
+
+static inline QString qgettext(const char* str)
+{
+ return QString::fromLocal8Bit(gettext(str));
+}
+
+static inline QString qgettext(const QString& str)
+{
+ return QString::fromLocal8Bit(gettext(str.latin1()));
+}
+
+/**
+ * Reads a list of integer values from the application settings.
+ */
+Q3ValueList<int> ConfigSettings::readSizes(const QString& key, bool *ok)
+{
+ Q3ValueList<int> result;
+ QStringList entryList = readListEntry(key, ok);
+ QStringList::Iterator it;
+
+ for (it = entryList.begin(); it != entryList.end(); ++it)
+ result.push_back((*it).toInt());
+
+ return result;
+}
+
+/**
+ * Writes a list of integer values to the application settings.
+ */
+bool ConfigSettings::writeSizes(const QString& key, const Q3ValueList<int>& value)
+{
+ QStringList stringList;
+ Q3ValueList<int>::ConstIterator it;
+
+ for (it = value.begin(); it != value.end(); ++it)
+ stringList.push_back(QString::number(*it));
+ return writeEntry(key, stringList);
+}
+
+
+/*
+ * set the new data
+ * TODO check the value
+ */
+void ConfigItem::okRename(int col)
+{
+ Parent::okRename(col);
+ sym_set_string_value(menu->sym, text(dataColIdx).latin1());
+ listView()->updateList(this);
+}
+
+/*
+ * update the displayed of a menu entry
+ */
+void ConfigItem::updateMenu(void)
+{
+ ConfigList* list;
+ struct symbol* sym;
+ struct property *prop;
+ QString prompt;
+ int type;
+ tristate expr;
+
+ list = listView();
+ if (goParent) {
+ setPixmap(promptColIdx, list->menuBackPix);
+ prompt = "..";
+ goto set_prompt;
+ }
+
+ sym = menu->sym;
+ prop = menu->prompt;
+ prompt = _(menu_get_prompt(menu));
+
+ if (prop) switch (prop->type) {
+ case P_MENU:
+ if (list->mode == singleMode || list->mode == symbolMode) {
+ /* a menuconfig entry is displayed differently
+ * depending whether it's at the view root or a child.
+ */
+ if (sym && list->rootEntry == menu)
+ break;
+ setPixmap(promptColIdx, list->menuPix);
+ } else {
+ if (sym)
+ break;
+ setPixmap(promptColIdx, 0);
+ }
+ goto set_prompt;
+ case P_COMMENT:
+ setPixmap(promptColIdx, 0);
+ goto set_prompt;
+ default:
+ ;
+ }
+ if (!sym)
+ goto set_prompt;
+
+ setText(nameColIdx, QString::fromLocal8Bit(sym->name));
+
+ type = sym_get_type(sym);
+ switch (type) {
+ case S_BOOLEAN:
+ case S_TRISTATE:
+ char ch;
+
+ if (!sym_is_changable(sym) && list->optMode == normalOpt) {
+ setPixmap(promptColIdx, 0);
+ setText(noColIdx, QString::null);
+ setText(modColIdx, QString::null);
+ setText(yesColIdx, QString::null);
+ break;
+ }
+ expr = sym_get_tristate_value(sym);
+ switch (expr) {
+ case yes:
+ if (sym_is_choice_value(sym) && type == S_BOOLEAN)
+ setPixmap(promptColIdx, list->choiceYesPix);
+ else
+ setPixmap(promptColIdx, list->symbolYesPix);
+ setText(yesColIdx, "Y");
+ ch = 'Y';
+ break;
+ case mod:
+ setPixmap(promptColIdx, list->symbolModPix);
+ setText(modColIdx, "M");
+ ch = 'M';
+ break;
+ default:
+ if (sym_is_choice_value(sym) && type == S_BOOLEAN)
+ setPixmap(promptColIdx, list->choiceNoPix);
+ else
+ setPixmap(promptColIdx, list->symbolNoPix);
+ setText(noColIdx, "N");
+ ch = 'N';
+ break;
+ }
+ if (expr != no)
+ setText(noColIdx, sym_tristate_within_range(sym, no) ? "_" : 0);
+ if (expr != mod)
+ setText(modColIdx, sym_tristate_within_range(sym, mod) ? "_" : 0);
+ if (expr != yes)
+ setText(yesColIdx, sym_tristate_within_range(sym, yes) ? "_" : 0);
+
+ setText(dataColIdx, QChar(ch));
+ break;
+ case S_INT:
+ case S_HEX:
+ case S_STRING:
+ const char* data;
+
+ data = sym_get_string_value(sym);
+
+ int i = list->mapIdx(dataColIdx);
+ if (i >= 0)
+ setRenameEnabled(i, TRUE);
+ setText(dataColIdx, data);
+ if (type == S_STRING)
+ prompt = QString("%1: %2").arg(prompt).arg(data);
+ else
+ prompt = QString("(%2) %1").arg(prompt).arg(data);
+ break;
+ }
+ if (!sym_has_value(sym) && visible)
+ prompt += _(" (NEW)");
+set_prompt:
+ setText(promptColIdx, prompt);
+}
+
+void ConfigItem::testUpdateMenu(bool v)
+{
+ ConfigItem* i;
+
+ visible = v;
+ if (!menu)
+ return;
+
+ sym_calc_value(menu->sym);
+ if (menu->flags & MENU_CHANGED) {
+ /* the menu entry changed, so update all list items */
+ menu->flags &= ~MENU_CHANGED;
+ for (i = (ConfigItem*)menu->data; i; i = i->nextItem)
+ i->updateMenu();
+ } else if (listView()->updateAll)
+ updateMenu();
+}
+
+void ConfigItem::paintCell(QPainter* p, const QColorGroup& cg, int column, int width, int align)
+{
+ ConfigList* list = listView();
+
+ if (visible) {
+ if (isSelected() && !list->hasFocus() && list->mode == menuMode)
+ Parent::paintCell(p, list->inactivedColorGroup, column, width, align);
+ else
+ Parent::paintCell(p, cg, column, width, align);
+ } else
+ Parent::paintCell(p, list->disabledColorGroup, column, width, align);
+}
+
+/*
+ * construct a menu entry
+ */
+void ConfigItem::init(void)
+{
+ if (menu) {
+ ConfigList* list = listView();
+ nextItem = (ConfigItem*)menu->data;
+ menu->data = this;
+
+ if (list->mode != fullMode)
+ setOpen(TRUE);
+ sym_calc_value(menu->sym);
+ }
+ updateMenu();
+}
+
+/*
+ * destruct a menu entry
+ */
+ConfigItem::~ConfigItem(void)
+{
+ if (menu) {
+ ConfigItem** ip = (ConfigItem**)&menu->data;
+ for (; *ip; ip = &(*ip)->nextItem) {
+ if (*ip == this) {
+ *ip = nextItem;
+ break;
+ }
+ }
+ }
+}
+
+ConfigLineEdit::ConfigLineEdit(ConfigView* parent)
+ : Parent(parent)
+{
+ connect(this, SIGNAL(lostFocus()), SLOT(hide()));
+}
+
+void ConfigLineEdit::show(ConfigItem* i)
+{
+ item = i;
+ if (sym_get_string_value(item->menu->sym))
+ setText(QString::fromLocal8Bit(sym_get_string_value(item->menu->sym)));
+ else
+ setText(QString::null);
+ Parent::show();
+ setFocus();
+}
+
+void ConfigLineEdit::keyPressEvent(QKeyEvent* e)
+{
+ switch (e->key()) {
+ case Qt::Key_Escape:
+ break;
+ case Qt::Key_Return:
+ case Qt::Key_Enter:
+ sym_set_string_value(item->menu->sym, text().latin1());
+ parent()->updateList(item);
+ break;
+ default:
+ Parent::keyPressEvent(e);
+ return;
+ }
+ e->accept();
+ parent()->list->setFocus();
+ hide();
+}
+
+ConfigList::ConfigList(ConfigView* p, const char *name)
+ : Parent(p, name),
+ updateAll(false),
+ symbolYesPix(xpm_symbol_yes), symbolModPix(xpm_symbol_mod), symbolNoPix(xpm_symbol_no),
+ choiceYesPix(xpm_choice_yes), choiceNoPix(xpm_choice_no),
+ menuPix(xpm_menu), menuInvPix(xpm_menu_inv), menuBackPix(xpm_menuback), voidPix(xpm_void),
+ showName(false), showRange(false), showData(false), optMode(normalOpt),
+ rootEntry(0), headerPopup(0)
+{
+ int i;
+
+ setSorting(-1);
+ setRootIsDecorated(TRUE);
+ disabledColorGroup = palette().active();
+ disabledColorGroup.setColor(QColorGroup::Text, palette().disabled().text());
+ inactivedColorGroup = palette().active();
+ inactivedColorGroup.setColor(QColorGroup::Highlight, palette().disabled().highlight());
+
+ connect(this, SIGNAL(selectionChanged(void)),
+ SLOT(updateSelection(void)));
+
+ if (name) {
+ configSettings->beginGroup(name);
+ showName = configSettings->readBoolEntry("/showName", false);
+ showRange = configSettings->readBoolEntry("/showRange", false);
+ showData = configSettings->readBoolEntry("/showData", false);
+ optMode = (enum optionMode)configSettings->readNumEntry("/optionMode", false);
+ configSettings->endGroup();
+ connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings()));
+ }
+
+ for (i = 0; i < colNr; i++)
+ colMap[i] = colRevMap[i] = -1;
+ addColumn(promptColIdx, _("Option"));
+
+ reinit();
+}
+
+bool ConfigList::menuSkip(struct menu *menu)
+{
+ if (optMode == normalOpt && menu_is_visible(menu))
+ return false;
+ if (optMode == promptOpt && menu_has_prompt(menu))
+ return false;
+ if (optMode == allOpt)
+ return false;
+ return true;
+}
+
+void ConfigList::reinit(void)
+{
+ removeColumn(dataColIdx);
+ removeColumn(yesColIdx);
+ removeColumn(modColIdx);
+ removeColumn(noColIdx);
+ removeColumn(nameColIdx);
+
+ if (showName)
+ addColumn(nameColIdx, _("Name"));
+ if (showRange) {
+ addColumn(noColIdx, "N");
+ addColumn(modColIdx, "M");
+ addColumn(yesColIdx, "Y");
+ }
+ if (showData)
+ addColumn(dataColIdx, _("Value"));
+
+ updateListAll();
+}
+
+void ConfigList::saveSettings(void)
+{
+ if (name()) {
+ configSettings->beginGroup(name());
+ configSettings->writeEntry("/showName", showName);
+ configSettings->writeEntry("/showRange", showRange);
+ configSettings->writeEntry("/showData", showData);
+ configSettings->writeEntry("/optionMode", (int)optMode);
+ configSettings->endGroup();
+ }
+}
+
+ConfigItem* ConfigList::findConfigItem(struct menu *menu)
+{
+ ConfigItem* item = (ConfigItem*)menu->data;
+
+ for (; item; item = item->nextItem) {
+ if (this == item->listView())
+ break;
+ }
+
+ return item;
+}
+
+void ConfigList::updateSelection(void)
+{
+ struct menu *menu;
+ enum prop_type type;
+
+ ConfigItem* item = (ConfigItem*)selectedItem();
+ if (!item)
+ return;
+
+ menu = item->menu;
+ emit menuChanged(menu);
+ if (!menu)
+ return;
+ type = menu->prompt ? menu->prompt->type : P_UNKNOWN;
+ if (mode == menuMode && type == P_MENU)
+ emit menuSelected(menu);
+}
+
+void ConfigList::updateList(ConfigItem* item)
+{
+ ConfigItem* last = 0;
+
+ if (!rootEntry) {
+ if (mode != listMode)
+ goto update;
+ Q3ListViewItemIterator it(this);
+ ConfigItem* item;
+
+ for (; it.current(); ++it) {
+ item = (ConfigItem*)it.current();
+ if (!item->menu)
+ continue;
+ item->testUpdateMenu(menu_is_visible(item->menu));
+ }
+ return;
+ }
+
+ if (rootEntry != &rootmenu && (mode == singleMode ||
+ (mode == symbolMode && rootEntry->parent != &rootmenu))) {
+ item = firstChild();
+ if (!item)
+ item = new ConfigItem(this, 0, true);
+ last = item;
+ }
+ if ((mode == singleMode || (mode == symbolMode && !(rootEntry->flags & MENU_ROOT))) &&
+ rootEntry->sym && rootEntry->prompt) {
+ item = last ? last->nextSibling() : firstChild();
+ if (!item)
+ item = new ConfigItem(this, last, rootEntry, true);
+ else
+ item->testUpdateMenu(true);
+
+ updateMenuList(item, rootEntry);
+ triggerUpdate();
+ return;
+ }
+update:
+ updateMenuList(this, rootEntry);
+ triggerUpdate();
+}
+
+void ConfigList::setValue(ConfigItem* item, tristate val)
+{
+ struct symbol* sym;
+ int type;
+ tristate oldval;
+
+ sym = item->menu ? item->menu->sym : 0;
+ if (!sym)
+ return;
+
+ type = sym_get_type(sym);
+ switch (type) {
+ case S_BOOLEAN:
+ case S_TRISTATE:
+ oldval = sym_get_tristate_value(sym);
+
+ if (!sym_set_tristate_value(sym, val))
+ return;
+ if (oldval == no && item->menu->list)
+ item->setOpen(TRUE);
+ parent()->updateList(item);
+ break;
+ }
+}
+
+void ConfigList::changeValue(ConfigItem* item)
+{
+ struct symbol* sym;
+ struct menu* menu;
+ int type, oldexpr, newexpr;
+
+ menu = item->menu;
+ if (!menu)
+ return;
+ sym = menu->sym;
+ if (!sym) {
+ if (item->menu->list)
+ item->setOpen(!item->isOpen());
+ return;
+ }
+
+ type = sym_get_type(sym);
+ switch (type) {
+ case S_BOOLEAN:
+ case S_TRISTATE:
+ oldexpr = sym_get_tristate_value(sym);
+ newexpr = sym_toggle_tristate_value(sym);
+ if (item->menu->list) {
+ if (oldexpr == newexpr)
+ item->setOpen(!item->isOpen());
+ else if (oldexpr == no)
+ item->setOpen(TRUE);
+ }
+ if (oldexpr != newexpr)
+ parent()->updateList(item);
+ break;
+ case S_INT:
+ case S_HEX:
+ case S_STRING:
+ if (colMap[dataColIdx] >= 0)
+ item->startRename(colMap[dataColIdx]);
+ else
+ parent()->lineEdit->show(item);
+ break;
+ }
+}
+
+void ConfigList::setRootMenu(struct menu *menu)
+{
+ enum prop_type type;
+
+ if (rootEntry == menu)
+ return;
+ type = menu && menu->prompt ? menu->prompt->type : P_UNKNOWN;
+ if (type != P_MENU)
+ return;
+ updateMenuList(this, 0);
+ rootEntry = menu;
+ updateListAll();
+ setSelected(currentItem(), hasFocus());
+ ensureItemVisible(currentItem());
+}
+
+void ConfigList::setParentMenu(void)
+{
+ ConfigItem* item;
+ struct menu *oldroot;
+
+ oldroot = rootEntry;
+ if (rootEntry == &rootmenu)
+ return;
+ setRootMenu(menu_get_parent_menu(rootEntry->parent));
+
+ Q3ListViewItemIterator it(this);
+ for (; (item = (ConfigItem*)it.current()); it++) {
+ if (item->menu == oldroot) {
+ setCurrentItem(item);
+ ensureItemVisible(item);
+ break;
+ }
+ }
+}
+
+/*
+ * update all the children of a menu entry
+ * removes/adds the entries from the parent widget as necessary
+ *
+ * parent: either the menu list widget or a menu entry widget
+ * menu: entry to be updated
+ */
+template <class P>
+void ConfigList::updateMenuList(P* parent, struct menu* menu)
+{
+ struct menu* child;
+ ConfigItem* item;
+ ConfigItem* last;
+ bool visible;
+ enum prop_type type;
+
+ if (!menu) {
+ while ((item = parent->firstChild()))
+ delete item;
+ return;
+ }
+
+ last = parent->firstChild();
+ if (last && !last->goParent)
+ last = 0;
+ for (child = menu->list; child; child = child->next) {
+ item = last ? last->nextSibling() : parent->firstChild();
+ type = child->prompt ? child->prompt->type : P_UNKNOWN;
+
+ switch (mode) {
+ case menuMode:
+ if (!(child->flags & MENU_ROOT))
+ goto hide;
+ break;
+ case symbolMode:
+ if (child->flags & MENU_ROOT)
+ goto hide;
+ break;
+ default:
+ break;
+ }
+
+ visible = menu_is_visible(child);
+ if (!menuSkip(child)) {
+ if (!child->sym && !child->list && !child->prompt)
+ continue;
+ if (!item || item->menu != child)
+ item = new ConfigItem(parent, last, child, visible);
+ else
+ item->testUpdateMenu(visible);
+
+ if (mode == fullMode || mode == menuMode || type != P_MENU)
+ updateMenuList(item, child);
+ else
+ updateMenuList(item, 0);
+ last = item;
+ continue;
+ }
+ hide:
+ if (item && item->menu == child) {
+ last = parent->firstChild();
+ if (last == item)
+ last = 0;
+ else while (last->nextSibling() != item)
+ last = last->nextSibling();
+ delete item;
+ }
+ }
+}
+
+void ConfigList::keyPressEvent(QKeyEvent* ev)
+{
+ Q3ListViewItem* i = currentItem();
+ ConfigItem* item;
+ struct menu *menu;
+ enum prop_type type;
+
+ if (ev->key() == Qt::Key_Escape && mode != fullMode && mode != listMode) {
+ emit parentSelected();
+ ev->accept();
+ return;
+ }
+
+ if (!i) {
+ Parent::keyPressEvent(ev);
+ return;
+ }
+ item = (ConfigItem*)i;
+
+ switch (ev->key()) {
+ case Qt::Key_Return:
+ case Qt::Key_Enter:
+ if (item->goParent) {
+ emit parentSelected();
+ break;
+ }
+ menu = item->menu;
+ if (!menu)
+ break;
+ type = menu->prompt ? menu->prompt->type : P_UNKNOWN;
+ if (type == P_MENU && rootEntry != menu &&
+ mode != fullMode && mode != menuMode) {
+ emit menuSelected(menu);
+ break;
+ }
+ case Qt::Key_Space:
+ changeValue(item);
+ break;
+ case Qt::Key_N:
+ setValue(item, no);
+ break;
+ case Qt::Key_M:
+ setValue(item, mod);
+ break;
+ case Qt::Key_Y:
+ setValue(item, yes);
+ break;
+ default:
+ Parent::keyPressEvent(ev);
+ return;
+ }
+ ev->accept();
+}
+
+void ConfigList::contentsMousePressEvent(QMouseEvent* e)
+{
+ //QPoint p(contentsToViewport(e->pos()));
+ //printf("contentsMousePressEvent: %d,%d\n", p.x(), p.y());
+ Parent::contentsMousePressEvent(e);
+}
+
+void ConfigList::contentsMouseReleaseEvent(QMouseEvent* e)
+{
+ QPoint p(contentsToViewport(e->pos()));
+ ConfigItem* item = (ConfigItem*)itemAt(p);
+ struct menu *menu;
+ enum prop_type ptype;
+ const QPixmap* pm;
+ int idx, x;
+
+ if (!item)
+ goto skip;
+
+ menu = item->menu;
+ x = header()->offset() + p.x();
+ idx = colRevMap[header()->sectionAt(x)];
+ switch (idx) {
+ case promptColIdx:
+ pm = item->pixmap(promptColIdx);
+ if (pm) {
+ int off = header()->sectionPos(0) + itemMargin() +
+ treeStepSize() * (item->depth() + (rootIsDecorated() ? 1 : 0));
+ if (x >= off && x < off + pm->width()) {
+ if (item->goParent) {
+ emit parentSelected();
+ break;
+ } else if (!menu)
+ break;
+ ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
+ if (ptype == P_MENU && rootEntry != menu &&
+ mode != fullMode && mode != menuMode)
+ emit menuSelected(menu);
+ else
+ changeValue(item);
+ }
+ }
+ break;
+ case noColIdx:
+ setValue(item, no);
+ break;
+ case modColIdx:
+ setValue(item, mod);
+ break;
+ case yesColIdx:
+ setValue(item, yes);
+ break;
+ case dataColIdx:
+ changeValue(item);
+ break;
+ }
+
+skip:
+ //printf("contentsMouseReleaseEvent: %d,%d\n", p.x(), p.y());
+ Parent::contentsMouseReleaseEvent(e);
+}
+
+void ConfigList::contentsMouseMoveEvent(QMouseEvent* e)
+{
+ //QPoint p(contentsToViewport(e->pos()));
+ //printf("contentsMouseMoveEvent: %d,%d\n", p.x(), p.y());
+ Parent::contentsMouseMoveEvent(e);
+}
+
+void ConfigList::contentsMouseDoubleClickEvent(QMouseEvent* e)
+{
+ QPoint p(contentsToViewport(e->pos()));
+ ConfigItem* item = (ConfigItem*)itemAt(p);
+ struct menu *menu;
+ enum prop_type ptype;
+
+ if (!item)
+ goto skip;
+ if (item->goParent) {
+ emit parentSelected();
+ goto skip;
+ }
+ menu = item->menu;
+ if (!menu)
+ goto skip;
+ ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
+ if (ptype == P_MENU && (mode == singleMode || mode == symbolMode))
+ emit menuSelected(menu);
+ else if (menu->sym)
+ changeValue(item);
+
+skip:
+ //printf("contentsMouseDoubleClickEvent: %d,%d\n", p.x(), p.y());
+ Parent::contentsMouseDoubleClickEvent(e);
+}
+
+void ConfigList::focusInEvent(QFocusEvent *e)
+{
+ struct menu *menu = NULL;
+
+ Parent::focusInEvent(e);
+
+ ConfigItem* item = (ConfigItem *)currentItem();
+ if (item) {
+ setSelected(item, TRUE);
+ menu = item->menu;
+ }
+ emit gotFocus(menu);
+}
+
+void ConfigList::contextMenuEvent(QContextMenuEvent *e)
+{
+ if (e->y() <= header()->geometry().bottom()) {
+ if (!headerPopup) {
+ Q3Action *action;
+
+ headerPopup = new Q3PopupMenu(this);
+ action = new Q3Action(NULL, _("Show Name"), 0, this);
+ action->setToggleAction(TRUE);
+ connect(action, SIGNAL(toggled(bool)),
+ parent(), SLOT(setShowName(bool)));
+ connect(parent(), SIGNAL(showNameChanged(bool)),
+ action, SLOT(setOn(bool)));
+ action->setOn(showName);
+ action->addTo(headerPopup);
+ action = new Q3Action(NULL, _("Show Range"), 0, this);
+ action->setToggleAction(TRUE);
+ connect(action, SIGNAL(toggled(bool)),
+ parent(), SLOT(setShowRange(bool)));
+ connect(parent(), SIGNAL(showRangeChanged(bool)),
+ action, SLOT(setOn(bool)));
+ action->setOn(showRange);
+ action->addTo(headerPopup);
+ action = new Q3Action(NULL, _("Show Data"), 0, this);
+ action->setToggleAction(TRUE);
+ connect(action, SIGNAL(toggled(bool)),
+ parent(), SLOT(setShowData(bool)));
+ connect(parent(), SIGNAL(showDataChanged(bool)),
+ action, SLOT(setOn(bool)));
+ action->setOn(showData);
+ action->addTo(headerPopup);
+ }
+ headerPopup->exec(e->globalPos());
+ e->accept();
+ } else
+ e->ignore();
+}
+
+ConfigView*ConfigView::viewList;
+QAction *ConfigView::showNormalAction;
+QAction *ConfigView::showAllAction;
+QAction *ConfigView::showPromptAction;
+
+ConfigView::ConfigView(QWidget* parent, const char *name)
+ : Parent(parent, name)
+{
+ list = new ConfigList(this, name);
+ lineEdit = new ConfigLineEdit(this);
+ lineEdit->hide();
+
+ this->nextView = viewList;
+ viewList = this;
+}
+
+ConfigView::~ConfigView(void)
+{
+ ConfigView** vp;
+
+ for (vp = &viewList; *vp; vp = &(*vp)->nextView) {
+ if (*vp == this) {
+ *vp = nextView;
+ break;
+ }
+ }
+}
+
+void ConfigView::setOptionMode(QAction *act)
+{
+ if (act == showNormalAction)
+ list->optMode = normalOpt;
+ else if (act == showAllAction)
+ list->optMode = allOpt;
+ else
+ list->optMode = promptOpt;
+
+ list->updateListAll();
+}
+
+void ConfigView::setShowName(bool b)
+{
+ if (list->showName != b) {
+ list->showName = b;
+ list->reinit();
+ emit showNameChanged(b);
+ }
+}
+
+void ConfigView::setShowRange(bool b)
+{
+ if (list->showRange != b) {
+ list->showRange = b;
+ list->reinit();
+ emit showRangeChanged(b);
+ }
+}
+
+void ConfigView::setShowData(bool b)
+{
+ if (list->showData != b) {
+ list->showData = b;
+ list->reinit();
+ emit showDataChanged(b);
+ }
+}
+
+void ConfigList::setAllOpen(bool open)
+{
+ Q3ListViewItemIterator it(this);
+
+ for (; it.current(); it++)
+ it.current()->setOpen(open);
+}
+
+void ConfigView::updateList(ConfigItem* item)
+{
+ ConfigView* v;
+
+ for (v = viewList; v; v = v->nextView)
+ v->list->updateList(item);
+}
+
+void ConfigView::updateListAll(void)
+{
+ ConfigView* v;
+
+ for (v = viewList; v; v = v->nextView)
+ v->list->updateListAll();
+}
+
+ConfigInfoView::ConfigInfoView(QWidget* parent, const char *name)
+ : Parent(parent, name), sym(0), _menu(0)
+{
+ if (name) {
+ configSettings->beginGroup(name);
+ _showDebug = configSettings->readBoolEntry("/showDebug", false);
+ configSettings->endGroup();
+ connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings()));
+ }
+}
+
+void ConfigInfoView::saveSettings(void)
+{
+ if (name()) {
+ configSettings->beginGroup(name());
+ configSettings->writeEntry("/showDebug", showDebug());
+ configSettings->endGroup();
+ }
+}
+
+void ConfigInfoView::setShowDebug(bool b)
+{
+ if (_showDebug != b) {
+ _showDebug = b;
+ if (_menu)
+ menuInfo();
+ else if (sym)
+ symbolInfo();
+ emit showDebugChanged(b);
+ }
+}
+
+void ConfigInfoView::setInfo(struct menu *m)
+{
+ if (_menu == m)
+ return;
+ _menu = m;
+ sym = NULL;
+ if (!_menu)
+ clear();
+ else
+ menuInfo();
+}
+
+void ConfigInfoView::symbolInfo(void)
+{
+ QString str;
+
+ str += "<big>Symbol: <b>";
+ str += print_filter(sym->name);
+ str += "</b></big><br><br>value: ";
+ str += print_filter(sym_get_string_value(sym));
+ str += "<br>visibility: ";
+ str += sym->visible == yes ? "y" : sym->visible == mod ? "m" : "n";
+ str += "<br>";
+ str += debug_info(sym);
+
+ setText(str);
+}
+
+void ConfigInfoView::menuInfo(void)
+{
+ struct symbol* sym;
+ QString head, debug, help;
+
+ sym = _menu->sym;
+ if (sym) {
+ if (_menu->prompt) {
+ head += "<big><b>";
+ head += print_filter(_(_menu->prompt->text));
+ head += "</b></big>";
+ if (sym->name) {
+ head += " (";
+ if (showDebug())
+ head += QString().sprintf("<a href=\"s%p\">", sym);
+ head += print_filter(sym->name);
+ if (showDebug())
+ head += "</a>";
+ head += ")";
+ }
+ } else if (sym->name) {
+ head += "<big><b>";
+ if (showDebug())
+ head += QString().sprintf("<a href=\"s%p\">", sym);
+ head += print_filter(sym->name);
+ if (showDebug())
+ head += "</a>";
+ head += "</b></big>";
+ }
+ head += "<br><br>";
+
+ if (showDebug())
+ debug = debug_info(sym);
+
+ struct gstr help_gstr = str_new();
+ menu_get_ext_help(_menu, &help_gstr);
+ help = print_filter(str_get(&help_gstr));
+ str_free(&help_gstr);
+ } else if (_menu->prompt) {
+ head += "<big><b>";
+ head += print_filter(_(_menu->prompt->text));
+ head += "</b></big><br><br>";
+ if (showDebug()) {
+ if (_menu->prompt->visible.expr) {
+ debug += " dep: ";
+ expr_print(_menu->prompt->visible.expr, expr_print_help, &debug, E_NONE);
+ debug += "<br><br>";
+ }
+ }
+ }
+ if (showDebug())
+ debug += QString().sprintf("defined at %s:%d<br><br>", _menu->file->name, _menu->lineno);
+
+ setText(head + debug + help);
+}
+
+QString ConfigInfoView::debug_info(struct symbol *sym)
+{
+ QString debug;
+
+ debug += "type: ";
+ debug += print_filter(sym_type_name(sym->type));
+ if (sym_is_choice(sym))
+ debug += " (choice)";
+ debug += "<br>";
+ if (sym->rev_dep.expr) {
+ debug += "reverse dep: ";
+ expr_print(sym->rev_dep.expr, expr_print_help, &debug, E_NONE);
+ debug += "<br>";
+ }
+ for (struct property *prop = sym->prop; prop; prop = prop->next) {
+ switch (prop->type) {
+ case P_PROMPT:
+ case P_MENU:
+ debug += QString().sprintf("prompt: <a href=\"m%p\">", prop->menu);
+ debug += print_filter(_(prop->text));
+ debug += "</a><br>";
+ break;
+ case P_DEFAULT:
+ case P_SELECT:
+ case P_RANGE:
+ case P_ENV:
+ debug += prop_get_type_name(prop->type);
+ debug += ": ";
+ expr_print(prop->expr, expr_print_help, &debug, E_NONE);
+ debug += "<br>";
+ break;
+ case P_CHOICE:
+ if (sym_is_choice(sym)) {
+ debug += "choice: ";
+ expr_print(prop->expr, expr_print_help, &debug, E_NONE);
+ debug += "<br>";
+ }
+ break;
+ default:
+ debug += "unknown property: ";
+ debug += prop_get_type_name(prop->type);
+ debug += "<br>";
+ }
+ if (prop->visible.expr) {
+ debug += " dep: ";
+ expr_print(prop->visible.expr, expr_print_help, &debug, E_NONE);
+ debug += "<br>";
+ }
+ }
+ debug += "<br>";
+
+ return debug;
+}
+
+QString ConfigInfoView::print_filter(const QString &str)
+{
+ QRegExp re("[<>&\"\\n]");
+ QString res = str;
+ for (int i = 0; (i = res.find(re, i)) >= 0;) {
+ switch (res[i].latin1()) {
+ case '<':
+ res.replace(i, 1, "<");
+ i += 4;
+ break;
+ case '>':
+ res.replace(i, 1, ">");
+ i += 4;
+ break;
+ case '&':
+ res.replace(i, 1, "&");
+ i += 5;
+ break;
+ case '"':
+ res.replace(i, 1, """);
+ i += 6;
+ break;
+ case '\n':
+ res.replace(i, 1, "<br>");
+ i += 4;
+ break;
+ }
+ }
+ return res;
+}
+
+void ConfigInfoView::expr_print_help(void *data, struct symbol *sym, const char *str)
+{
+ QString* text = reinterpret_cast<QString*>(data);
+ QString str2 = print_filter(str);
+
+ if (sym && sym->name && !(sym->flags & SYMBOL_CONST)) {
+ *text += QString().sprintf("<a href=\"s%p\">", sym);
+ *text += str2;
+ *text += "</a>";
+ } else
+ *text += str2;
+}
+
+Q3PopupMenu* ConfigInfoView::createPopupMenu(const QPoint& pos)
+{
+ Q3PopupMenu* popup = Parent::createPopupMenu(pos);
+ Q3Action* action = new Q3Action(NULL, _("Show Debug Info"), 0, popup);
+ action->setToggleAction(TRUE);
+ connect(action, SIGNAL(toggled(bool)), SLOT(setShowDebug(bool)));
+ connect(this, SIGNAL(showDebugChanged(bool)), action, SLOT(setOn(bool)));
+ action->setOn(showDebug());
+ popup->insertSeparator();
+ action->addTo(popup);
+ return popup;
+}
+
+void ConfigInfoView::contentsContextMenuEvent(QContextMenuEvent *e)
+{
+ Parent::contentsContextMenuEvent(e);
+}
+
+ConfigSearchWindow::ConfigSearchWindow(ConfigMainWindow* parent, const char *name)
+ : Parent(parent, name), result(NULL)
+{
+ setCaption("Search Config");
+
+ QVBoxLayout* layout1 = new QVBoxLayout(this, 11, 6);
+ QHBoxLayout* layout2 = new QHBoxLayout(0, 0, 6);
+ layout2->addWidget(new QLabel(_("Find:"), this));
+ editField = new QLineEdit(this);
+ connect(editField, SIGNAL(returnPressed()), SLOT(search()));
+ layout2->addWidget(editField);
+ searchButton = new QPushButton(_("Search"), this);
+ searchButton->setAutoDefault(FALSE);
+ connect(searchButton, SIGNAL(clicked()), SLOT(search()));
+ layout2->addWidget(searchButton);
+ layout1->addLayout(layout2);
+
+ split = new QSplitter(this);
+ split->setOrientation(Qt::Vertical);
+ list = new ConfigView(split, name);
+ list->list->mode = listMode;
+ info = new ConfigInfoView(split, name);
+ connect(list->list, SIGNAL(menuChanged(struct menu *)),
+ info, SLOT(setInfo(struct menu *)));
+ connect(list->list, SIGNAL(menuChanged(struct menu *)),
+ parent, SLOT(setMenuLink(struct menu *)));
+
+ layout1->addWidget(split);
+
+ if (name) {
+ int x, y, width, height;
+ bool ok;
+
+ configSettings->beginGroup(name);
+ width = configSettings->readNumEntry("/window width", parent->width() / 2);
+ height = configSettings->readNumEntry("/window height", parent->height() / 2);
+ resize(width, height);
+ x = configSettings->readNumEntry("/window x", 0, &ok);
+ if (ok)
+ y = configSettings->readNumEntry("/window y", 0, &ok);
+ if (ok)
+ move(x, y);
+ Q3ValueList<int> sizes = configSettings->readSizes("/split", &ok);
+ if (ok)
+ split->setSizes(sizes);
+ configSettings->endGroup();
+ connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings()));
+ }
+}
+
+void ConfigSearchWindow::saveSettings(void)
+{
+ if (name()) {
+ configSettings->beginGroup(name());
+ configSettings->writeEntry("/window x", pos().x());
+ configSettings->writeEntry("/window y", pos().y());
+ configSettings->writeEntry("/window width", size().width());
+ configSettings->writeEntry("/window height", size().height());
+ configSettings->writeSizes("/split", split->sizes());
+ configSettings->endGroup();
+ }
+}
+
+void ConfigSearchWindow::search(void)
+{
+ struct symbol **p;
+ struct property *prop;
+ ConfigItem *lastItem = NULL;
+
+ free(result);
+ list->list->clear();
+ info->clear();
+
+ result = sym_re_search(editField->text().latin1());
+ if (!result)
+ return;
+ for (p = result; *p; p++) {
+ for_all_prompts((*p), prop)
+ lastItem = new ConfigItem(list->list, lastItem, prop->menu,
+ menu_is_visible(prop->menu));
+ }
+}
+
+/*
+ * Construct the complete config widget
+ */
+ConfigMainWindow::ConfigMainWindow(void)
+ : searchWindow(0)
+{
+ QMenuBar* menu;
+ bool ok;
+ int x, y, width, height;
+ char title[256];
+
+ QDesktopWidget *d = configApp->desktop();
+ snprintf(title, sizeof(title), "%s%s",
+ rootmenu.prompt->text,
+#if QT_VERSION < 0x040000
+ " (Qt3)"
+#else
+ ""
+#endif
+ );
+ setCaption(title);
+
+ width = configSettings->readNumEntry("/window width", d->width() - 64);
+ height = configSettings->readNumEntry("/window height", d->height() - 64);
+ resize(width, height);
+ x = configSettings->readNumEntry("/window x", 0, &ok);
+ if (ok)
+ y = configSettings->readNumEntry("/window y", 0, &ok);
+ if (ok)
+ move(x, y);
+
+ split1 = new QSplitter(this);
+ split1->setOrientation(Qt::Horizontal);
+ setCentralWidget(split1);
+
+ menuView = new ConfigView(split1, "menu");
+ menuList = menuView->list;
+
+ split2 = new QSplitter(split1);
+ split2->setOrientation(Qt::Vertical);
+
+ // create config tree
+ configView = new ConfigView(split2, "config");
+ configList = configView->list;
+
+ helpText = new ConfigInfoView(split2, "help");
+ helpText->setTextFormat(Qt::RichText);
+
+ setTabOrder(configList, helpText);
+ configList->setFocus();
+
+ menu = menuBar();
+ toolBar = new Q3ToolBar("Tools", this);
+
+ backAction = new Q3Action("Back", QPixmap(xpm_back), _("Back"), 0, this);
+ connect(backAction, SIGNAL(activated()), SLOT(goBack()));
+ backAction->setEnabled(FALSE);
+ Q3Action *quitAction = new Q3Action("Quit", _("&Quit"), Qt::CTRL + Qt::Key_Q, this);
+ connect(quitAction, SIGNAL(activated()), SLOT(close()));
+ Q3Action *loadAction = new Q3Action("Load", QPixmap(xpm_load), _("&Load"), Qt::CTRL + Qt::Key_L, this);
+ connect(loadAction, SIGNAL(activated()), SLOT(loadConfig()));
+ saveAction = new Q3Action("Save", QPixmap(xpm_save), _("&Save"), Qt::CTRL + Qt::Key_S, this);
+ connect(saveAction, SIGNAL(activated()), SLOT(saveConfig()));
+ conf_set_changed_callback(conf_changed);
+ // Set saveAction's initial state
+ conf_changed();
+ Q3Action *saveAsAction = new Q3Action("Save As...", _("Save &As..."), 0, this);
+ connect(saveAsAction, SIGNAL(activated()), SLOT(saveConfigAs()));
+ Q3Action *searchAction = new Q3Action("Find", _("&Find"), Qt::CTRL + Qt::Key_F, this);
+ connect(searchAction, SIGNAL(activated()), SLOT(searchConfig()));
+ Q3Action *singleViewAction = new Q3Action("Single View", QPixmap(xpm_single_view), _("Single View"), 0, this);
+ connect(singleViewAction, SIGNAL(activated()), SLOT(showSingleView()));
+ Q3Action *splitViewAction = new Q3Action("Split View", QPixmap(xpm_split_view), _("Split View"), 0, this);
+ connect(splitViewAction, SIGNAL(activated()), SLOT(showSplitView()));
+ Q3Action *fullViewAction = new Q3Action("Full View", QPixmap(xpm_tree_view), _("Full View"), 0, this);
+ connect(fullViewAction, SIGNAL(activated()), SLOT(showFullView()));
+
+ Q3Action *showNameAction = new Q3Action(NULL, _("Show Name"), 0, this);
+ showNameAction->setToggleAction(TRUE);
+ connect(showNameAction, SIGNAL(toggled(bool)), configView, SLOT(setShowName(bool)));
+ connect(configView, SIGNAL(showNameChanged(bool)), showNameAction, SLOT(setOn(bool)));
+ showNameAction->setOn(configView->showName());
+ Q3Action *showRangeAction = new Q3Action(NULL, _("Show Range"), 0, this);
+ showRangeAction->setToggleAction(TRUE);
+ connect(showRangeAction, SIGNAL(toggled(bool)), configView, SLOT(setShowRange(bool)));
+ connect(configView, SIGNAL(showRangeChanged(bool)), showRangeAction, SLOT(setOn(bool)));
+ showRangeAction->setOn(configList->showRange);
+ Q3Action *showDataAction = new Q3Action(NULL, _("Show Data"), 0, this);
+ showDataAction->setToggleAction(TRUE);
+ connect(showDataAction, SIGNAL(toggled(bool)), configView, SLOT(setShowData(bool)));
+ connect(configView, SIGNAL(showDataChanged(bool)), showDataAction, SLOT(setOn(bool)));
+ showDataAction->setOn(configList->showData);
+
+ QActionGroup *optGroup = new QActionGroup(this);
+ optGroup->setExclusive(TRUE);
+ connect(optGroup, SIGNAL(selected(QAction *)), configView,
+ SLOT(setOptionMode(QAction *)));
+ connect(optGroup, SIGNAL(selected(QAction *)), menuView,
+ SLOT(setOptionMode(QAction *)));
+
+#if QT_VERSION >= 0x040000
+ configView->showNormalAction = new QAction(_("Show Normal Options"), optGroup);
+ configView->showAllAction = new QAction(_("Show All Options"), optGroup);
+ configView->showPromptAction = new QAction(_("Show Prompt Options"), optGroup);
+#else
+ configView->showNormalAction = new QAction(_("Show Normal Options"), 0, optGroup);
+ configView->showAllAction = new QAction(_("Show All Options"), 0, optGroup);
+ configView->showPromptAction = new QAction(_("Show Prompt Options"), 0, optGroup);
+#endif
+ configView->showNormalAction->setToggleAction(TRUE);
+ configView->showNormalAction->setOn(configList->optMode == normalOpt);
+ configView->showAllAction->setToggleAction(TRUE);
+ configView->showAllAction->setOn(configList->optMode == allOpt);
+ configView->showPromptAction->setToggleAction(TRUE);
+ configView->showPromptAction->setOn(configList->optMode == promptOpt);
+
+ Q3Action *showDebugAction = new Q3Action(NULL, _("Show Debug Info"), 0, this);
+ showDebugAction->setToggleAction(TRUE);
+ connect(showDebugAction, SIGNAL(toggled(bool)), helpText, SLOT(setShowDebug(bool)));
+ connect(helpText, SIGNAL(showDebugChanged(bool)), showDebugAction, SLOT(setOn(bool)));
+ showDebugAction->setOn(helpText->showDebug());
+
+ Q3Action *showIntroAction = new Q3Action(NULL, _("Introduction"), 0, this);
+ connect(showIntroAction, SIGNAL(activated()), SLOT(showIntro()));
+ Q3Action *showAboutAction = new Q3Action(NULL, _("About"), 0, this);
+ connect(showAboutAction, SIGNAL(activated()), SLOT(showAbout()));
+
+ // init tool bar
+ backAction->addTo(toolBar);
+ toolBar->addSeparator();
+ loadAction->addTo(toolBar);
+ saveAction->addTo(toolBar);
+ toolBar->addSeparator();
+ singleViewAction->addTo(toolBar);
+ splitViewAction->addTo(toolBar);
+ fullViewAction->addTo(toolBar);
+
+ // create config menu
+ Q3PopupMenu* config = new Q3PopupMenu(this);
+ menu->insertItem(_("&File"), config);
+ loadAction->addTo(config);
+ saveAction->addTo(config);
+ saveAsAction->addTo(config);
+ config->insertSeparator();
+ quitAction->addTo(config);
+
+ // create edit menu
+ Q3PopupMenu* editMenu = new Q3PopupMenu(this);
+ menu->insertItem(_("&Edit"), editMenu);
+ searchAction->addTo(editMenu);
+
+ // create options menu
+ Q3PopupMenu* optionMenu = new Q3PopupMenu(this);
+ menu->insertItem(_("&Option"), optionMenu);
+ showNameAction->addTo(optionMenu);
+ showRangeAction->addTo(optionMenu);
+ showDataAction->addTo(optionMenu);
+ optionMenu->insertSeparator();
+ optGroup->addTo(optionMenu);
+ optionMenu->insertSeparator();
+
+ // create help menu
+ Q3PopupMenu* helpMenu = new Q3PopupMenu(this);
+ menu->insertSeparator();
+ menu->insertItem(_("&Help"), helpMenu);
+ showIntroAction->addTo(helpMenu);
+ showAboutAction->addTo(helpMenu);
+
+ connect(configList, SIGNAL(menuChanged(struct menu *)),
+ helpText, SLOT(setInfo(struct menu *)));
+ connect(configList, SIGNAL(menuSelected(struct menu *)),
+ SLOT(changeMenu(struct menu *)));
+ connect(configList, SIGNAL(parentSelected()),
+ SLOT(goBack()));
+ connect(menuList, SIGNAL(menuChanged(struct menu *)),
+ helpText, SLOT(setInfo(struct menu *)));
+ connect(menuList, SIGNAL(menuSelected(struct menu *)),
+ SLOT(changeMenu(struct menu *)));
+
+ connect(configList, SIGNAL(gotFocus(struct menu *)),
+ helpText, SLOT(setInfo(struct menu *)));
+ connect(menuList, SIGNAL(gotFocus(struct menu *)),
+ helpText, SLOT(setInfo(struct menu *)));
+ connect(menuList, SIGNAL(gotFocus(struct menu *)),
+ SLOT(listFocusChanged(void)));
+ connect(helpText, SIGNAL(menuSelected(struct menu *)),
+ SLOT(setMenuLink(struct menu *)));
+
+ QString listMode = configSettings->readEntry("/listMode", "symbol");
+ if (listMode == "single")
+ showSingleView();
+ else if (listMode == "full")
+ showFullView();
+ else /*if (listMode == "split")*/
+ showSplitView();
+
+ // UI setup done, restore splitter positions
+ Q3ValueList<int> sizes = configSettings->readSizes("/split1", &ok);
+ if (ok)
+ split1->setSizes(sizes);
+
+ sizes = configSettings->readSizes("/split2", &ok);
+ if (ok)
+ split2->setSizes(sizes);
+}
+
+void ConfigMainWindow::loadConfig(void)
+{
+ QString s = Q3FileDialog::getOpenFileName(conf_get_configname(), NULL, this);
+ if (s.isNull())
+ return;
+ if (conf_read(QFile::encodeName(s)))
+ QMessageBox::information(this, "qconf", _("Unable to load configuration!"));
+ ConfigView::updateListAll();
+}
+
+bool ConfigMainWindow::saveConfig(void)
+{
+ if (conf_write(NULL)) {
+ QMessageBox::information(this, "qconf", _("Unable to save configuration!"));
+ return false;
+ }
+ return true;
+}
+
+void ConfigMainWindow::saveConfigAs(void)
+{
+ QString s = Q3FileDialog::getSaveFileName(conf_get_configname(), NULL, this);
+ if (s.isNull())
+ return;
+ saveConfig();
+}
+
+void ConfigMainWindow::searchConfig(void)
+{
+ if (!searchWindow)
+ searchWindow = new ConfigSearchWindow(this, "search");
+ searchWindow->show();
+}
+
+void ConfigMainWindow::changeMenu(struct menu *menu)
+{
+ configList->setRootMenu(menu);
+ if (configList->rootEntry->parent == &rootmenu)
+ backAction->setEnabled(FALSE);
+ else
+ backAction->setEnabled(TRUE);
+}
+
+void ConfigMainWindow::setMenuLink(struct menu *menu)
+{
+ struct menu *parent;
+ ConfigList* list = NULL;
+ ConfigItem* item;
+
+ if (configList->menuSkip(menu))
+ return;
+
+ switch (configList->mode) {
+ case singleMode:
+ list = configList;
+ parent = menu_get_parent_menu(menu);
+ if (!parent)
+ return;
+ list->setRootMenu(parent);
+ break;
+ case symbolMode:
+ if (menu->flags & MENU_ROOT) {
+ configList->setRootMenu(menu);
+ configList->clearSelection();
+ list = menuList;
+ } else {
+ list = configList;
+ parent = menu_get_parent_menu(menu->parent);
+ if (!parent)
+ return;
+ item = menuList->findConfigItem(parent);
+ if (item) {
+ menuList->setSelected(item, TRUE);
+ menuList->ensureItemVisible(item);
+ }
+ list->setRootMenu(parent);
+ }
+ break;
+ case fullMode:
+ list = configList;
+ break;
+ default:
+ break;
+ }
+
+ if (list) {
+ item = list->findConfigItem(menu);
+ if (item) {
+ list->setSelected(item, TRUE);
+ list->ensureItemVisible(item);
+ list->setFocus();
+ }
+ }
+}
+
+void ConfigMainWindow::listFocusChanged(void)
+{
+ if (menuList->mode == menuMode)
+ configList->clearSelection();
+}
+
+void ConfigMainWindow::goBack(void)
+{
+ ConfigItem* item;
+
+ configList->setParentMenu();
+ if (configList->rootEntry == &rootmenu)
+ backAction->setEnabled(FALSE);
+ item = (ConfigItem*)menuList->selectedItem();
+ while (item) {
+ if (item->menu == configList->rootEntry) {
+ menuList->setSelected(item, TRUE);
+ break;
+ }
+ item = (ConfigItem*)item->parent();
+ }
+}
+
+void ConfigMainWindow::showSingleView(void)
+{
+ menuView->hide();
+ menuList->setRootMenu(0);
+ configList->mode = singleMode;
+ if (configList->rootEntry == &rootmenu)
+ configList->updateListAll();
+ else
+ configList->setRootMenu(&rootmenu);
+ configList->setAllOpen(TRUE);
+ configList->setFocus();
+}
+
+void ConfigMainWindow::showSplitView(void)
+{
+ configList->mode = symbolMode;
+ if (configList->rootEntry == &rootmenu)
+ configList->updateListAll();
+ else
+ configList->setRootMenu(&rootmenu);
+ configList->setAllOpen(TRUE);
+ configApp->processEvents();
+ menuList->mode = menuMode;
+ menuList->setRootMenu(&rootmenu);
+ menuList->setAllOpen(TRUE);
+ menuView->show();
+ menuList->setFocus();
+}
+
+void ConfigMainWindow::showFullView(void)
+{
+ menuView->hide();
+ menuList->setRootMenu(0);
+ configList->mode = fullMode;
+ if (configList->rootEntry == &rootmenu)
+ configList->updateListAll();
+ else
+ configList->setRootMenu(&rootmenu);
+ configList->setAllOpen(FALSE);
+ configList->setFocus();
+}
+
+/*
+ * ask for saving configuration before quitting
+ * TODO ask only when something changed
+ */
+void ConfigMainWindow::closeEvent(QCloseEvent* e)
+{
+ if (!conf_get_changed()) {
+ e->accept();
+ return;
+ }
+ QMessageBox mb("qconf", _("Save configuration?"), QMessageBox::Warning,
+ QMessageBox::Yes | QMessageBox::Default, QMessageBox::No, QMessageBox::Cancel | QMessageBox::Escape);
+ mb.setButtonText(QMessageBox::Yes, _("&Save Changes"));
+ mb.setButtonText(QMessageBox::No, _("&Discard Changes"));
+ mb.setButtonText(QMessageBox::Cancel, _("Cancel Exit"));
+ switch (mb.exec()) {
+ case QMessageBox::Yes:
+ if (saveConfig())
+ e->accept();
+ else
+ e->ignore();
+ break;
+ case QMessageBox::No:
+ e->accept();
+ break;
+ case QMessageBox::Cancel:
+ e->ignore();
+ break;
+ }
+}
+
+void ConfigMainWindow::showIntro(void)
+{
+ static const QString str = _("Welcome to the qconf graphical configuration tool.\n\n"
+ "For each option, a blank box indicates the feature is disabled, a check\n"
+ "indicates it is enabled, and a dot indicates that it is to be compiled\n"
+ "as a module. Clicking on the box will cycle through the three states.\n\n"
+ "If you do not see an option (e.g., a device driver) that you believe\n"
+ "should be present, try turning on Show All Options under the Options menu.\n"
+ "Although there is no cross reference yet to help you figure out what other\n"
+ "options must be enabled to support the option you are interested in, you can\n"
+ "still view the help of a grayed-out option.\n\n"
+ "Toggling Show Debug Info under the Options menu will show the dependencies,\n"
+ "which you can then match by examining other options.\n\n");
+
+ QMessageBox::information(this, "qconf", str);
+}
+
+void ConfigMainWindow::showAbout(void)
+{
+ static const QString str = _("qconf is Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>.\n\n"
+ "Bug reports and feature request can also be entered at http://bugzilla.kernel.org/\n");
+
+ QMessageBox::information(this, "qconf", str);
+}
+
+void ConfigMainWindow::saveSettings(void)
+{
+ configSettings->writeEntry("/window x", pos().x());
+ configSettings->writeEntry("/window y", pos().y());
+ configSettings->writeEntry("/window width", size().width());
+ configSettings->writeEntry("/window height", size().height());
+
+ QString entry;
+ switch(configList->mode) {
+ case singleMode :
+ entry = "single";
+ break;
+
+ case symbolMode :
+ entry = "split";
+ break;
+
+ case fullMode :
+ entry = "full";
+ break;
+
+ default:
+ break;
+ }
+ configSettings->writeEntry("/listMode", entry);
+
+ configSettings->writeSizes("/split1", split1->sizes());
+ configSettings->writeSizes("/split2", split2->sizes());
+}
+
+void ConfigMainWindow::conf_changed(void)
+{
+ if (saveAction)
+ saveAction->setEnabled(conf_get_changed());
+}
+
+void fixup_rootmenu(struct menu *menu)
+{
+ struct menu *child;
+ static int menu_cnt = 0;
+
+ menu->flags |= MENU_ROOT;
+ for (child = menu->list; child; child = child->next) {
+ if (child->prompt && child->prompt->type == P_MENU) {
+ menu_cnt++;
+ fixup_rootmenu(child);
+ menu_cnt--;
+ } else if (!menu_cnt)
+ fixup_rootmenu(child);
+ }
+}
+
+static const char *progname;
+
+static void usage(void)
+{
+ printf(_("%s <config>\n"), progname);
+ exit(0);
+}
+
+int main(int ac, char** av)
+{
+ ConfigMainWindow* v;
+ const char *name;
+
+ bindtextdomain(PACKAGE, LOCALEDIR);
+ textdomain(PACKAGE);
+
+ progname = av[0];
+ configApp = new QApplication(ac, av);
+ if (ac > 1 && av[1][0] == '-') {
+ switch (av[1][1]) {
+ case 'h':
+ case '?':
+ usage();
+ }
+ name = av[2];
+ } else
+ name = av[1];
+ if (!name)
+ usage();
+
+ conf_parse(name);
+ fixup_rootmenu(&rootmenu);
+ conf_read(NULL);
+ //zconfdump(stdout);
+
+ configSettings = new ConfigSettings();
+ configSettings->beginGroup("/kconfig/qconf");
+ v = new ConfigMainWindow();
+
+ //zconfdump(stdout);
+ configApp->setMainWidget(v);
+ configApp->connect(configApp, SIGNAL(lastWindowClosed()), SLOT(quit()));
+ configApp->connect(configApp, SIGNAL(aboutToQuit()), v, SLOT(saveSettings()));
+ v->show();
+ configApp->exec();
+
+ configSettings->endGroup();
+ delete configSettings;
+
+ return 0;
+}
--- /dev/null
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#if QT_VERSION < 0x040000
+#include <qlistview.h>
+#else
+#include <q3listview.h>
+#endif
+#include <qsettings.h>
+
+#if QT_VERSION < 0x040000
+#define Q3ValueList QValueList
+#define Q3PopupMenu QPopupMenu
+#define Q3ListView QListView
+#define Q3ListViewItem QListViewItem
+#define Q3VBox QVBox
+#define Q3TextBrowser QTextBrowser
+#define Q3MainWindow QMainWindow
+#define Q3Action QAction
+#define Q3ToolBar QToolBar
+#define Q3ListViewItemIterator QListViewItemIterator
+#define Q3FileDialog QFileDialog
+#endif
+
+class ConfigView;
+class ConfigList;
+class ConfigItem;
+class ConfigLineEdit;
+class ConfigMainWindow;
+
+class ConfigSettings : public QSettings {
+public:
+ Q3ValueList<int> readSizes(const QString& key, bool *ok);
+ bool writeSizes(const QString& key, const Q3ValueList<int>& value);
+};
+
+enum colIdx {
+ promptColIdx, nameColIdx, noColIdx, modColIdx, yesColIdx, dataColIdx, colNr
+};
+enum listMode {
+ singleMode, menuMode, symbolMode, fullMode, listMode
+};
+enum optionMode {
+ normalOpt = 0, allOpt, promptOpt
+};
+
+class ConfigList : public Q3ListView {
+ Q_OBJECT
+ typedef class Q3ListView Parent;
+public:
+ ConfigList(ConfigView* p, const char *name = 0);
+ void reinit(void);
+ ConfigView* parent(void) const
+ {
+ return (ConfigView*)Parent::parent();
+ }
+ ConfigItem* findConfigItem(struct menu *);
+
+protected:
+ void keyPressEvent(QKeyEvent *e);
+ void contentsMousePressEvent(QMouseEvent *e);
+ void contentsMouseReleaseEvent(QMouseEvent *e);
+ void contentsMouseMoveEvent(QMouseEvent *e);
+ void contentsMouseDoubleClickEvent(QMouseEvent *e);
+ void focusInEvent(QFocusEvent *e);
+ void contextMenuEvent(QContextMenuEvent *e);
+
+public slots:
+ void setRootMenu(struct menu *menu);
+
+ void updateList(ConfigItem *item);
+ void setValue(ConfigItem* item, tristate val);
+ void changeValue(ConfigItem* item);
+ void updateSelection(void);
+ void saveSettings(void);
+signals:
+ void menuChanged(struct menu *menu);
+ void menuSelected(struct menu *menu);
+ void parentSelected(void);
+ void gotFocus(struct menu *);
+
+public:
+ void updateListAll(void)
+ {
+ updateAll = true;
+ updateList(NULL);
+ updateAll = false;
+ }
+ ConfigList* listView()
+ {
+ return this;
+ }
+ ConfigItem* firstChild() const
+ {
+ return (ConfigItem *)Parent::firstChild();
+ }
+ int mapIdx(colIdx idx)
+ {
+ return colMap[idx];
+ }
+ void addColumn(colIdx idx, const QString& label)
+ {
+ colMap[idx] = Parent::addColumn(label);
+ colRevMap[colMap[idx]] = idx;
+ }
+ void removeColumn(colIdx idx)
+ {
+ int col = colMap[idx];
+ if (col >= 0) {
+ Parent::removeColumn(col);
+ colRevMap[col] = colMap[idx] = -1;
+ }
+ }
+ void setAllOpen(bool open);
+ void setParentMenu(void);
+
+ bool menuSkip(struct menu *);
+
+ template <class P>
+ void updateMenuList(P*, struct menu*);
+
+ bool updateAll;
+
+ QPixmap symbolYesPix, symbolModPix, symbolNoPix;
+ QPixmap choiceYesPix, choiceNoPix;
+ QPixmap menuPix, menuInvPix, menuBackPix, voidPix;
+
+ bool showName, showRange, showData;
+ enum listMode mode;
+ enum optionMode optMode;
+ struct menu *rootEntry;
+ QColorGroup disabledColorGroup;
+ QColorGroup inactivedColorGroup;
+ Q3PopupMenu* headerPopup;
+
+private:
+ int colMap[colNr];
+ int colRevMap[colNr];
+};
+
+class ConfigItem : public Q3ListViewItem {
+ typedef class Q3ListViewItem Parent;
+public:
+ ConfigItem(Q3ListView *parent, ConfigItem *after, struct menu *m, bool v)
+ : Parent(parent, after), menu(m), visible(v), goParent(false)
+ {
+ init();
+ }
+ ConfigItem(ConfigItem *parent, ConfigItem *after, struct menu *m, bool v)
+ : Parent(parent, after), menu(m), visible(v), goParent(false)
+ {
+ init();
+ }
+ ConfigItem(Q3ListView *parent, ConfigItem *after, bool v)
+ : Parent(parent, after), menu(0), visible(v), goParent(true)
+ {
+ init();
+ }
+ ~ConfigItem(void);
+ void init(void);
+ void okRename(int col);
+ void updateMenu(void);
+ void testUpdateMenu(bool v);
+ ConfigList* listView() const
+ {
+ return (ConfigList*)Parent::listView();
+ }
+ ConfigItem* firstChild() const
+ {
+ return (ConfigItem *)Parent::firstChild();
+ }
+ ConfigItem* nextSibling() const
+ {
+ return (ConfigItem *)Parent::nextSibling();
+ }
+ void setText(colIdx idx, const QString& text)
+ {
+ Parent::setText(listView()->mapIdx(idx), text);
+ }
+ QString text(colIdx idx) const
+ {
+ return Parent::text(listView()->mapIdx(idx));
+ }
+ void setPixmap(colIdx idx, const QPixmap& pm)
+ {
+ Parent::setPixmap(listView()->mapIdx(idx), pm);
+ }
+ const QPixmap* pixmap(colIdx idx) const
+ {
+ return Parent::pixmap(listView()->mapIdx(idx));
+ }
+ void paintCell(QPainter* p, const QColorGroup& cg, int column, int width, int align);
+
+ ConfigItem* nextItem;
+ struct menu *menu;
+ bool visible;
+ bool goParent;
+};
+
+class ConfigLineEdit : public QLineEdit {
+ Q_OBJECT
+ typedef class QLineEdit Parent;
+public:
+ ConfigLineEdit(ConfigView* parent);
+ ConfigView* parent(void) const
+ {
+ return (ConfigView*)Parent::parent();
+ }
+ void show(ConfigItem *i);
+ void keyPressEvent(QKeyEvent *e);
+
+public:
+ ConfigItem *item;
+};
+
+class ConfigView : public Q3VBox {
+ Q_OBJECT
+ typedef class Q3VBox Parent;
+public:
+ ConfigView(QWidget* parent, const char *name = 0);
+ ~ConfigView(void);
+ static void updateList(ConfigItem* item);
+ static void updateListAll(void);
+
+ bool showName(void) const { return list->showName; }
+ bool showRange(void) const { return list->showRange; }
+ bool showData(void) const { return list->showData; }
+public slots:
+ void setShowName(bool);
+ void setShowRange(bool);
+ void setShowData(bool);
+ void setOptionMode(QAction *);
+signals:
+ void showNameChanged(bool);
+ void showRangeChanged(bool);
+ void showDataChanged(bool);
+public:
+ ConfigList* list;
+ ConfigLineEdit* lineEdit;
+
+ static ConfigView* viewList;
+ ConfigView* nextView;
+
+ static QAction *showNormalAction;
+ static QAction *showAllAction;
+ static QAction *showPromptAction;
+};
+
+class ConfigInfoView : public Q3TextBrowser {
+ Q_OBJECT
+ typedef class Q3TextBrowser Parent;
+public:
+ ConfigInfoView(QWidget* parent, const char *name = 0);
+ bool showDebug(void) const { return _showDebug; }
+
+public slots:
+ void setInfo(struct menu *menu);
+ void saveSettings(void);
+ void setShowDebug(bool);
+
+signals:
+ void showDebugChanged(bool);
+ void menuSelected(struct menu *);
+
+protected:
+ void symbolInfo(void);
+ void menuInfo(void);
+ QString debug_info(struct symbol *sym);
+ static QString print_filter(const QString &str);
+ static void expr_print_help(void *data, struct symbol *sym, const char *str);
+ Q3PopupMenu* createPopupMenu(const QPoint& pos);
+ void contentsContextMenuEvent(QContextMenuEvent *e);
+
+ struct symbol *sym;
+ struct menu *_menu;
+ bool _showDebug;
+};
+
+class ConfigSearchWindow : public QDialog {
+ Q_OBJECT
+ typedef class QDialog Parent;
+public:
+ ConfigSearchWindow(ConfigMainWindow* parent, const char *name = 0);
+
+public slots:
+ void saveSettings(void);
+ void search(void);
+
+protected:
+ QLineEdit* editField;
+ QPushButton* searchButton;
+ QSplitter* split;
+ ConfigView* list;
+ ConfigInfoView* info;
+
+ struct symbol **result;
+};
+
+class ConfigMainWindow : public Q3MainWindow {
+ Q_OBJECT
+
+ static Q3Action *saveAction;
+ static void conf_changed(void);
+public:
+ ConfigMainWindow(void);
+public slots:
+ void changeMenu(struct menu *);
+ void setMenuLink(struct menu *);
+ void listFocusChanged(void);
+ void goBack(void);
+ void loadConfig(void);
+ bool saveConfig(void);
+ void saveConfigAs(void);
+ void searchConfig(void);
+ void showSingleView(void);
+ void showSplitView(void);
+ void showFullView(void);
+ void showIntro(void);
+ void showAbout(void);
+ void saveSettings(void);
+
+protected:
+ void closeEvent(QCloseEvent *e);
+
+ ConfigSearchWindow *searchWindow;
+ ConfigView *menuView;
+ ConfigList *menuList;
+ ConfigView *configView;
+ ConfigList *configList;
+ ConfigInfoView *helpText;
+ Q3ToolBar *toolBar;
+ Q3Action *backAction;
+ QSplitter* split1;
+ QSplitter* split2;
+};
+++ /dev/null
-/* Hey EMACS -*- linux-c -*- */
-/*
- *
- * Copyright (C) 2002-2003 Romain Lievin <roms@tilp.info>
- * Released under the terms of the GNU GPL v2.0.
- *
- */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include "lkc.h"
-#include "images.c"
-
-#include <glade/glade.h>
-#include <gtk/gtk.h>
-#include <glib.h>
-#include <gdk/gdkkeysyms.h>
-
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <time.h>
-#include <stdlib.h>
-
-//#define DEBUG
-
-enum {
- SINGLE_VIEW, SPLIT_VIEW, FULL_VIEW
-};
-
-enum {
- OPT_NORMAL, OPT_ALL, OPT_PROMPT
-};
-
-static gint view_mode = FULL_VIEW;
-static gboolean show_name = TRUE;
-static gboolean show_range = TRUE;
-static gboolean show_value = TRUE;
-static gboolean resizeable = FALSE;
-static int opt_mode = OPT_NORMAL;
-
-GtkWidget *main_wnd = NULL;
-GtkWidget *tree1_w = NULL; // left frame
-GtkWidget *tree2_w = NULL; // right frame
-GtkWidget *text_w = NULL;
-GtkWidget *hpaned = NULL;
-GtkWidget *vpaned = NULL;
-GtkWidget *back_btn = NULL;
-GtkWidget *save_btn = NULL;
-GtkWidget *save_menu_item = NULL;
-
-GtkTextTag *tag1, *tag2;
-GdkColor color;
-
-GtkTreeStore *tree1, *tree2, *tree;
-GtkTreeModel *model1, *model2;
-static GtkTreeIter *parents[256];
-static gint indent;
-
-static struct menu *current; // current node for SINGLE view
-static struct menu *browsed; // browsed node for SPLIT view
-
-enum {
- COL_OPTION, COL_NAME, COL_NO, COL_MOD, COL_YES, COL_VALUE,
- COL_MENU, COL_COLOR, COL_EDIT, COL_PIXBUF,
- COL_PIXVIS, COL_BTNVIS, COL_BTNACT, COL_BTNINC, COL_BTNRAD,
- COL_NUMBER
-};
-
-static void display_list(void);
-static void display_tree(struct menu *menu);
-static void display_tree_part(void);
-static void update_tree(struct menu *src, GtkTreeIter * dst);
-static void set_node(GtkTreeIter * node, struct menu *menu, gchar ** row);
-static gchar **fill_row(struct menu *menu);
-static void conf_changed(void);
-
-/* Helping/Debugging Functions */
-
-const char *dbg_sym_flags(int val)
-{
- static char buf[256];
-
- bzero(buf, 256);
-
- if (val & SYMBOL_CONST)
- strcat(buf, "const/");
- if (val & SYMBOL_CHECK)
- strcat(buf, "check/");
- if (val & SYMBOL_CHOICE)
- strcat(buf, "choice/");
- if (val & SYMBOL_CHOICEVAL)
- strcat(buf, "choiceval/");
- if (val & SYMBOL_VALID)
- strcat(buf, "valid/");
- if (val & SYMBOL_OPTIONAL)
- strcat(buf, "optional/");
- if (val & SYMBOL_WRITE)
- strcat(buf, "write/");
- if (val & SYMBOL_CHANGED)
- strcat(buf, "changed/");
- if (val & SYMBOL_AUTO)
- strcat(buf, "auto/");
-
- buf[strlen(buf) - 1] = '\0';
-
- return buf;
-}
-
-void replace_button_icon(GladeXML * xml, GdkDrawable * window,
- GtkStyle * style, gchar * btn_name, gchar ** xpm)
-{
- GdkPixmap *pixmap;
- GdkBitmap *mask;
- GtkToolButton *button;
- GtkWidget *image;
-
- pixmap = gdk_pixmap_create_from_xpm_d(window, &mask,
- &style->bg[GTK_STATE_NORMAL],
- xpm);
-
- button = GTK_TOOL_BUTTON(glade_xml_get_widget(xml, btn_name));
- image = gtk_image_new_from_pixmap(pixmap, mask);
- gtk_widget_show(image);
- gtk_tool_button_set_icon_widget(button, image);
-}
-
-/* Main Window Initialization */
-void init_main_window(const gchar * glade_file)
-{
- GladeXML *xml;
- GtkWidget *widget;
- GtkTextBuffer *txtbuf;
- GtkStyle *style;
-
- xml = glade_xml_new(glade_file, "window1", NULL);
- if (!xml)
- g_error(_("GUI loading failed !\n"));
- glade_xml_signal_autoconnect(xml);
-
- main_wnd = glade_xml_get_widget(xml, "window1");
- hpaned = glade_xml_get_widget(xml, "hpaned1");
- vpaned = glade_xml_get_widget(xml, "vpaned1");
- tree1_w = glade_xml_get_widget(xml, "treeview1");
- tree2_w = glade_xml_get_widget(xml, "treeview2");
- text_w = glade_xml_get_widget(xml, "textview3");
-
- back_btn = glade_xml_get_widget(xml, "button1");
- gtk_widget_set_sensitive(back_btn, FALSE);
-
- widget = glade_xml_get_widget(xml, "show_name1");
- gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,
- show_name);
-
- widget = glade_xml_get_widget(xml, "show_range1");
- gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,
- show_range);
-
- widget = glade_xml_get_widget(xml, "show_data1");
- gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,
- show_value);
-
- save_btn = glade_xml_get_widget(xml, "button3");
- save_menu_item = glade_xml_get_widget(xml, "save1");
- conf_set_changed_callback(conf_changed);
-
- style = gtk_widget_get_style(main_wnd);
- widget = glade_xml_get_widget(xml, "toolbar1");
-
-#if 0 /* Use stock Gtk icons instead */
- replace_button_icon(xml, main_wnd->window, style,
- "button1", (gchar **) xpm_back);
- replace_button_icon(xml, main_wnd->window, style,
- "button2", (gchar **) xpm_load);
- replace_button_icon(xml, main_wnd->window, style,
- "button3", (gchar **) xpm_save);
-#endif
- replace_button_icon(xml, main_wnd->window, style,
- "button4", (gchar **) xpm_single_view);
- replace_button_icon(xml, main_wnd->window, style,
- "button5", (gchar **) xpm_split_view);
- replace_button_icon(xml, main_wnd->window, style,
- "button6", (gchar **) xpm_tree_view);
-
-#if 0
- switch (view_mode) {
- case SINGLE_VIEW:
- widget = glade_xml_get_widget(xml, "button4");
- g_signal_emit_by_name(widget, "clicked");
- break;
- case SPLIT_VIEW:
- widget = glade_xml_get_widget(xml, "button5");
- g_signal_emit_by_name(widget, "clicked");
- break;
- case FULL_VIEW:
- widget = glade_xml_get_widget(xml, "button6");
- g_signal_emit_by_name(widget, "clicked");
- break;
- }
-#endif
- txtbuf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w));
- tag1 = gtk_text_buffer_create_tag(txtbuf, "mytag1",
- "foreground", "red",
- "weight", PANGO_WEIGHT_BOLD,
- NULL);
- tag2 = gtk_text_buffer_create_tag(txtbuf, "mytag2",
- /*"style", PANGO_STYLE_OBLIQUE, */
- NULL);
-
- gtk_window_set_title(GTK_WINDOW(main_wnd), rootmenu.prompt->text);
-
- gtk_widget_show(main_wnd);
-}
-
-void init_tree_model(void)
-{
- gint i;
-
- tree = tree2 = gtk_tree_store_new(COL_NUMBER,
- G_TYPE_STRING, G_TYPE_STRING,
- G_TYPE_STRING, G_TYPE_STRING,
- G_TYPE_STRING, G_TYPE_STRING,
- G_TYPE_POINTER, GDK_TYPE_COLOR,
- G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF,
- G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
- G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
- G_TYPE_BOOLEAN);
- model2 = GTK_TREE_MODEL(tree2);
-
- for (parents[0] = NULL, i = 1; i < 256; i++)
- parents[i] = (GtkTreeIter *) g_malloc(sizeof(GtkTreeIter));
-
- tree1 = gtk_tree_store_new(COL_NUMBER,
- G_TYPE_STRING, G_TYPE_STRING,
- G_TYPE_STRING, G_TYPE_STRING,
- G_TYPE_STRING, G_TYPE_STRING,
- G_TYPE_POINTER, GDK_TYPE_COLOR,
- G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF,
- G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
- G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
- G_TYPE_BOOLEAN);
- model1 = GTK_TREE_MODEL(tree1);
-}
-
-void init_left_tree(void)
-{
- GtkTreeView *view = GTK_TREE_VIEW(tree1_w);
- GtkCellRenderer *renderer;
- GtkTreeSelection *sel;
- GtkTreeViewColumn *column;
-
- gtk_tree_view_set_model(view, model1);
- gtk_tree_view_set_headers_visible(view, TRUE);
- gtk_tree_view_set_rules_hint(view, TRUE);
-
- column = gtk_tree_view_column_new();
- gtk_tree_view_append_column(view, column);
- gtk_tree_view_column_set_title(column, _("Options"));
-
- renderer = gtk_cell_renderer_toggle_new();
- gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
- renderer, FALSE);
- gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
- renderer,
- "active", COL_BTNACT,
- "inconsistent", COL_BTNINC,
- "visible", COL_BTNVIS,
- "radio", COL_BTNRAD, NULL);
- renderer = gtk_cell_renderer_text_new();
- gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
- renderer, FALSE);
- gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
- renderer,
- "text", COL_OPTION,
- "foreground-gdk",
- COL_COLOR, NULL);
-
- sel = gtk_tree_view_get_selection(view);
- gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE);
- gtk_widget_realize(tree1_w);
-}
-
-static void renderer_edited(GtkCellRendererText * cell,
- const gchar * path_string,
- const gchar * new_text, gpointer user_data);
-
-void init_right_tree(void)
-{
- GtkTreeView *view = GTK_TREE_VIEW(tree2_w);
- GtkCellRenderer *renderer;
- GtkTreeSelection *sel;
- GtkTreeViewColumn *column;
- gint i;
-
- gtk_tree_view_set_model(view, model2);
- gtk_tree_view_set_headers_visible(view, TRUE);
- gtk_tree_view_set_rules_hint(view, TRUE);
-
- column = gtk_tree_view_column_new();
- gtk_tree_view_append_column(view, column);
- gtk_tree_view_column_set_title(column, _("Options"));
-
- renderer = gtk_cell_renderer_pixbuf_new();
- gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
- renderer, FALSE);
- gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
- renderer,
- "pixbuf", COL_PIXBUF,
- "visible", COL_PIXVIS, NULL);
- renderer = gtk_cell_renderer_toggle_new();
- gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
- renderer, FALSE);
- gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
- renderer,
- "active", COL_BTNACT,
- "inconsistent", COL_BTNINC,
- "visible", COL_BTNVIS,
- "radio", COL_BTNRAD, NULL);
- renderer = gtk_cell_renderer_text_new();
- gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
- renderer, FALSE);
- gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
- renderer,
- "text", COL_OPTION,
- "foreground-gdk",
- COL_COLOR, NULL);
-
- renderer = gtk_cell_renderer_text_new();
- gtk_tree_view_insert_column_with_attributes(view, -1,
- _("Name"), renderer,
- "text", COL_NAME,
- "foreground-gdk",
- COL_COLOR, NULL);
- renderer = gtk_cell_renderer_text_new();
- gtk_tree_view_insert_column_with_attributes(view, -1,
- "N", renderer,
- "text", COL_NO,
- "foreground-gdk",
- COL_COLOR, NULL);
- renderer = gtk_cell_renderer_text_new();
- gtk_tree_view_insert_column_with_attributes(view, -1,
- "M", renderer,
- "text", COL_MOD,
- "foreground-gdk",
- COL_COLOR, NULL);
- renderer = gtk_cell_renderer_text_new();
- gtk_tree_view_insert_column_with_attributes(view, -1,
- "Y", renderer,
- "text", COL_YES,
- "foreground-gdk",
- COL_COLOR, NULL);
- renderer = gtk_cell_renderer_text_new();
- gtk_tree_view_insert_column_with_attributes(view, -1,
- _("Value"), renderer,
- "text", COL_VALUE,
- "editable",
- COL_EDIT,
- "foreground-gdk",
- COL_COLOR, NULL);
- g_signal_connect(G_OBJECT(renderer), "edited",
- G_CALLBACK(renderer_edited), NULL);
-
- column = gtk_tree_view_get_column(view, COL_NAME);
- gtk_tree_view_column_set_visible(column, show_name);
- column = gtk_tree_view_get_column(view, COL_NO);
- gtk_tree_view_column_set_visible(column, show_range);
- column = gtk_tree_view_get_column(view, COL_MOD);
- gtk_tree_view_column_set_visible(column, show_range);
- column = gtk_tree_view_get_column(view, COL_YES);
- gtk_tree_view_column_set_visible(column, show_range);
- column = gtk_tree_view_get_column(view, COL_VALUE);
- gtk_tree_view_column_set_visible(column, show_value);
-
- if (resizeable) {
- for (i = 0; i < COL_VALUE; i++) {
- column = gtk_tree_view_get_column(view, i);
- gtk_tree_view_column_set_resizable(column, TRUE);
- }
- }
-
- sel = gtk_tree_view_get_selection(view);
- gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE);
-}
-
-
-/* Utility Functions */
-
-
-static void text_insert_help(struct menu *menu)
-{
- GtkTextBuffer *buffer;
- GtkTextIter start, end;
- const char *prompt = _(menu_get_prompt(menu));
- struct gstr help = str_new();
-
- menu_get_ext_help(menu, &help);
-
- buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w));
- gtk_text_buffer_get_bounds(buffer, &start, &end);
- gtk_text_buffer_delete(buffer, &start, &end);
- gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_w), 15);
-
- gtk_text_buffer_get_end_iter(buffer, &end);
- gtk_text_buffer_insert_with_tags(buffer, &end, prompt, -1, tag1,
- NULL);
- gtk_text_buffer_insert_at_cursor(buffer, "\n\n", 2);
- gtk_text_buffer_get_end_iter(buffer, &end);
- gtk_text_buffer_insert_with_tags(buffer, &end, str_get(&help), -1, tag2,
- NULL);
- str_free(&help);
-}
-
-
-static void text_insert_msg(const char *title, const char *message)
-{
- GtkTextBuffer *buffer;
- GtkTextIter start, end;
- const char *msg = message;
-
- buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w));
- gtk_text_buffer_get_bounds(buffer, &start, &end);
- gtk_text_buffer_delete(buffer, &start, &end);
- gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_w), 15);
-
- gtk_text_buffer_get_end_iter(buffer, &end);
- gtk_text_buffer_insert_with_tags(buffer, &end, title, -1, tag1,
- NULL);
- gtk_text_buffer_insert_at_cursor(buffer, "\n\n", 2);
- gtk_text_buffer_get_end_iter(buffer, &end);
- gtk_text_buffer_insert_with_tags(buffer, &end, msg, -1, tag2,
- NULL);
-}
-
-
-/* Main Windows Callbacks */
-
-void on_save_activate(GtkMenuItem * menuitem, gpointer user_data);
-gboolean on_window1_delete_event(GtkWidget * widget, GdkEvent * event,
- gpointer user_data)
-{
- GtkWidget *dialog, *label;
- gint result;
-
- if (!conf_get_changed())
- return FALSE;
-
- dialog = gtk_dialog_new_with_buttons(_("Warning !"),
- GTK_WINDOW(main_wnd),
- (GtkDialogFlags)
- (GTK_DIALOG_MODAL |
- GTK_DIALOG_DESTROY_WITH_PARENT),
- GTK_STOCK_OK,
- GTK_RESPONSE_YES,
- GTK_STOCK_NO,
- GTK_RESPONSE_NO,
- GTK_STOCK_CANCEL,
- GTK_RESPONSE_CANCEL, NULL);
- gtk_dialog_set_default_response(GTK_DIALOG(dialog),
- GTK_RESPONSE_CANCEL);
-
- label = gtk_label_new(_("\nSave configuration ?\n"));
- gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), label);
- gtk_widget_show(label);
-
- result = gtk_dialog_run(GTK_DIALOG(dialog));
- switch (result) {
- case GTK_RESPONSE_YES:
- on_save_activate(NULL, NULL);
- return FALSE;
- case GTK_RESPONSE_NO:
- return FALSE;
- case GTK_RESPONSE_CANCEL:
- case GTK_RESPONSE_DELETE_EVENT:
- default:
- gtk_widget_destroy(dialog);
- return TRUE;
- }
-
- return FALSE;
-}
-
-
-void on_window1_destroy(GtkObject * object, gpointer user_data)
-{
- gtk_main_quit();
-}
-
-
-void
-on_window1_size_request(GtkWidget * widget,
- GtkRequisition * requisition, gpointer user_data)
-{
- static gint old_h;
- gint w, h;
-
- if (widget->window == NULL)
- gtk_window_get_default_size(GTK_WINDOW(main_wnd), &w, &h);
- else
- gdk_window_get_size(widget->window, &w, &h);
-
- if (h == old_h)
- return;
- old_h = h;
-
- gtk_paned_set_position(GTK_PANED(vpaned), 2 * h / 3);
-}
-
-
-/* Menu & Toolbar Callbacks */
-
-
-static void
-load_filename(GtkFileSelection * file_selector, gpointer user_data)
-{
- const gchar *fn;
-
- fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION
- (user_data));
-
- if (conf_read(fn))
- text_insert_msg(_("Error"), _("Unable to load configuration !"));
- else
- display_tree(&rootmenu);
-}
-
-void on_load1_activate(GtkMenuItem * menuitem, gpointer user_data)
-{
- GtkWidget *fs;
-
- fs = gtk_file_selection_new(_("Load file..."));
- g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button),
- "clicked",
- G_CALLBACK(load_filename), (gpointer) fs);
- g_signal_connect_swapped(GTK_OBJECT
- (GTK_FILE_SELECTION(fs)->ok_button),
- "clicked", G_CALLBACK(gtk_widget_destroy),
- (gpointer) fs);
- g_signal_connect_swapped(GTK_OBJECT
- (GTK_FILE_SELECTION(fs)->cancel_button),
- "clicked", G_CALLBACK(gtk_widget_destroy),
- (gpointer) fs);
- gtk_widget_show(fs);
-}
-
-
-void on_save_activate(GtkMenuItem * menuitem, gpointer user_data)
-{
- if (conf_write(NULL))
- text_insert_msg(_("Error"), _("Unable to save configuration !"));
-}
-
-
-static void
-store_filename(GtkFileSelection * file_selector, gpointer user_data)
-{
- const gchar *fn;
-
- fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION
- (user_data));
-
- if (conf_write(fn))
- text_insert_msg(_("Error"), _("Unable to save configuration !"));
-
- gtk_widget_destroy(GTK_WIDGET(user_data));
-}
-
-void on_save_as1_activate(GtkMenuItem * menuitem, gpointer user_data)
-{
- GtkWidget *fs;
-
- fs = gtk_file_selection_new(_("Save file as..."));
- g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button),
- "clicked",
- G_CALLBACK(store_filename), (gpointer) fs);
- g_signal_connect_swapped(GTK_OBJECT
- (GTK_FILE_SELECTION(fs)->ok_button),
- "clicked", G_CALLBACK(gtk_widget_destroy),
- (gpointer) fs);
- g_signal_connect_swapped(GTK_OBJECT
- (GTK_FILE_SELECTION(fs)->cancel_button),
- "clicked", G_CALLBACK(gtk_widget_destroy),
- (gpointer) fs);
- gtk_widget_show(fs);
-}
-
-
-void on_quit1_activate(GtkMenuItem * menuitem, gpointer user_data)
-{
- if (!on_window1_delete_event(NULL, NULL, NULL))
- gtk_widget_destroy(GTK_WIDGET(main_wnd));
-}
-
-
-void on_show_name1_activate(GtkMenuItem * menuitem, gpointer user_data)
-{
- GtkTreeViewColumn *col;
-
- show_name = GTK_CHECK_MENU_ITEM(menuitem)->active;
- col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_NAME);
- if (col)
- gtk_tree_view_column_set_visible(col, show_name);
-}
-
-
-void on_show_range1_activate(GtkMenuItem * menuitem, gpointer user_data)
-{
- GtkTreeViewColumn *col;
-
- show_range = GTK_CHECK_MENU_ITEM(menuitem)->active;
- col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_NO);
- if (col)
- gtk_tree_view_column_set_visible(col, show_range);
- col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_MOD);
- if (col)
- gtk_tree_view_column_set_visible(col, show_range);
- col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_YES);
- if (col)
- gtk_tree_view_column_set_visible(col, show_range);
-
-}
-
-
-void on_show_data1_activate(GtkMenuItem * menuitem, gpointer user_data)
-{
- GtkTreeViewColumn *col;
-
- show_value = GTK_CHECK_MENU_ITEM(menuitem)->active;
- col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_VALUE);
- if (col)
- gtk_tree_view_column_set_visible(col, show_value);
-}
-
-
-void
-on_set_option_mode1_activate(GtkMenuItem *menuitem, gpointer user_data)
-{
- opt_mode = OPT_NORMAL;
- gtk_tree_store_clear(tree2);
- display_tree(&rootmenu); /* instead of update_tree to speed-up */
-}
-
-
-void
-on_set_option_mode2_activate(GtkMenuItem *menuitem, gpointer user_data)
-{
- opt_mode = OPT_ALL;
- gtk_tree_store_clear(tree2);
- display_tree(&rootmenu); /* instead of update_tree to speed-up */
-}
-
-
-void
-on_set_option_mode3_activate(GtkMenuItem *menuitem, gpointer user_data)
-{
- opt_mode = OPT_PROMPT;
- gtk_tree_store_clear(tree2);
- display_tree(&rootmenu); /* instead of update_tree to speed-up */
-}
-
-
-void on_introduction1_activate(GtkMenuItem * menuitem, gpointer user_data)
-{
- GtkWidget *dialog;
- const gchar *intro_text = _(
- "Welcome to gkc, the GTK+ graphical configuration tool\n"
- "For each option, a blank box indicates the feature is disabled, a\n"
- "check indicates it is enabled, and a dot indicates that it is to\n"
- "be compiled as a module. Clicking on the box will cycle through the three states.\n"
- "\n"
- "If you do not see an option (e.g., a device driver) that you\n"
- "believe should be present, try turning on Show All Options\n"
- "under the Options menu.\n"
- "Although there is no cross reference yet to help you figure out\n"
- "what other options must be enabled to support the option you\n"
- "are interested in, you can still view the help of a grayed-out\n"
- "option.\n"
- "\n"
- "Toggling Show Debug Info under the Options menu will show \n"
- "the dependencies, which you can then match by examining other options.");
-
- dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
- GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_INFO,
- GTK_BUTTONS_CLOSE, "%s", intro_text);
- g_signal_connect_swapped(GTK_OBJECT(dialog), "response",
- G_CALLBACK(gtk_widget_destroy),
- GTK_OBJECT(dialog));
- gtk_widget_show_all(dialog);
-}
-
-
-void on_about1_activate(GtkMenuItem * menuitem, gpointer user_data)
-{
- GtkWidget *dialog;
- const gchar *about_text =
- _("gkc is copyright (c) 2002 Romain Lievin <roms@lpg.ticalc.org>.\n"
- "Based on the source code from Roman Zippel.\n");
-
- dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
- GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_INFO,
- GTK_BUTTONS_CLOSE, "%s", about_text);
- g_signal_connect_swapped(GTK_OBJECT(dialog), "response",
- G_CALLBACK(gtk_widget_destroy),
- GTK_OBJECT(dialog));
- gtk_widget_show_all(dialog);
-}
-
-
-void on_license1_activate(GtkMenuItem * menuitem, gpointer user_data)
-{
- GtkWidget *dialog;
- const gchar *license_text =
- _("gkc is released under the terms of the GNU GPL v2.\n"
- "For more information, please see the source code or\n"
- "visit http://www.fsf.org/licenses/licenses.html\n");
-
- dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
- GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_INFO,
- GTK_BUTTONS_CLOSE, "%s", license_text);
- g_signal_connect_swapped(GTK_OBJECT(dialog), "response",
- G_CALLBACK(gtk_widget_destroy),
- GTK_OBJECT(dialog));
- gtk_widget_show_all(dialog);
-}
-
-
-void on_back_clicked(GtkButton * button, gpointer user_data)
-{
- enum prop_type ptype;
-
- current = current->parent;
- ptype = current->prompt ? current->prompt->type : P_UNKNOWN;
- if (ptype != P_MENU)
- current = current->parent;
- display_tree_part();
-
- if (current == &rootmenu)
- gtk_widget_set_sensitive(back_btn, FALSE);
-}
-
-
-void on_load_clicked(GtkButton * button, gpointer user_data)
-{
- on_load1_activate(NULL, user_data);
-}
-
-
-void on_single_clicked(GtkButton * button, gpointer user_data)
-{
- view_mode = SINGLE_VIEW;
- gtk_widget_hide(tree1_w);
- current = &rootmenu;
- display_tree_part();
-}
-
-
-void on_split_clicked(GtkButton * button, gpointer user_data)
-{
- gint w, h;
- view_mode = SPLIT_VIEW;
- gtk_widget_show(tree1_w);
- gtk_window_get_default_size(GTK_WINDOW(main_wnd), &w, &h);
- gtk_paned_set_position(GTK_PANED(hpaned), w / 2);
- if (tree2)
- gtk_tree_store_clear(tree2);
- display_list();
-
- /* Disable back btn, like in full mode. */
- gtk_widget_set_sensitive(back_btn, FALSE);
-}
-
-
-void on_full_clicked(GtkButton * button, gpointer user_data)
-{
- view_mode = FULL_VIEW;
- gtk_widget_hide(tree1_w);
- if (tree2)
- gtk_tree_store_clear(tree2);
- display_tree(&rootmenu);
- gtk_widget_set_sensitive(back_btn, FALSE);
-}
-
-
-void on_collapse_clicked(GtkButton * button, gpointer user_data)
-{
- gtk_tree_view_collapse_all(GTK_TREE_VIEW(tree2_w));
-}
-
-
-void on_expand_clicked(GtkButton * button, gpointer user_data)
-{
- gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w));
-}
-
-
-/* CTree Callbacks */
-
-/* Change hex/int/string value in the cell */
-static void renderer_edited(GtkCellRendererText * cell,
- const gchar * path_string,
- const gchar * new_text, gpointer user_data)
-{
- GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
- GtkTreeIter iter;
- const char *old_def, *new_def;
- struct menu *menu;
- struct symbol *sym;
-
- if (!gtk_tree_model_get_iter(model2, &iter, path))
- return;
-
- gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
- sym = menu->sym;
-
- gtk_tree_model_get(model2, &iter, COL_VALUE, &old_def, -1);
- new_def = new_text;
-
- sym_set_string_value(sym, new_def);
-
- update_tree(&rootmenu, NULL);
-
- gtk_tree_path_free(path);
-}
-
-/* Change the value of a symbol and update the tree */
-static void change_sym_value(struct menu *menu, gint col)
-{
- struct symbol *sym = menu->sym;
- tristate newval;
-
- if (!sym)
- return;
-
- if (col == COL_NO)
- newval = no;
- else if (col == COL_MOD)
- newval = mod;
- else if (col == COL_YES)
- newval = yes;
- else
- return;
-
- switch (sym_get_type(sym)) {
- case S_BOOLEAN:
- case S_TRISTATE:
- if (!sym_tristate_within_range(sym, newval))
- newval = yes;
- sym_set_tristate_value(sym, newval);
- if (view_mode == FULL_VIEW)
- update_tree(&rootmenu, NULL);
- else if (view_mode == SPLIT_VIEW) {
- update_tree(browsed, NULL);
- display_list();
- }
- else if (view_mode == SINGLE_VIEW)
- display_tree_part(); //fixme: keep exp/coll
- break;
- case S_INT:
- case S_HEX:
- case S_STRING:
- default:
- break;
- }
-}
-
-static void toggle_sym_value(struct menu *menu)
-{
- if (!menu->sym)
- return;
-
- sym_toggle_tristate_value(menu->sym);
- if (view_mode == FULL_VIEW)
- update_tree(&rootmenu, NULL);
- else if (view_mode == SPLIT_VIEW) {
- update_tree(browsed, NULL);
- display_list();
- }
- else if (view_mode == SINGLE_VIEW)
- display_tree_part(); //fixme: keep exp/coll
-}
-
-static gint column2index(GtkTreeViewColumn * column)
-{
- gint i;
-
- for (i = 0; i < COL_NUMBER; i++) {
- GtkTreeViewColumn *col;
-
- col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), i);
- if (col == column)
- return i;
- }
-
- return -1;
-}
-
-
-/* User click: update choice (full) or goes down (single) */
-gboolean
-on_treeview2_button_press_event(GtkWidget * widget,
- GdkEventButton * event, gpointer user_data)
-{
- GtkTreeView *view = GTK_TREE_VIEW(widget);
- GtkTreePath *path;
- GtkTreeViewColumn *column;
- GtkTreeIter iter;
- struct menu *menu;
- gint col;
-
-#if GTK_CHECK_VERSION(2,1,4) // bug in ctree with earlier version of GTK
- gint tx = (gint) event->x;
- gint ty = (gint) event->y;
- gint cx, cy;
-
- gtk_tree_view_get_path_at_pos(view, tx, ty, &path, &column, &cx,
- &cy);
-#else
- gtk_tree_view_get_cursor(view, &path, &column);
-#endif
- if (path == NULL)
- return FALSE;
-
- if (!gtk_tree_model_get_iter(model2, &iter, path))
- return FALSE;
- gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
-
- col = column2index(column);
- if (event->type == GDK_2BUTTON_PRESS) {
- enum prop_type ptype;
- ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
-
- if (ptype == P_MENU && view_mode != FULL_VIEW && col == COL_OPTION) {
- // goes down into menu
- current = menu;
- display_tree_part();
- gtk_widget_set_sensitive(back_btn, TRUE);
- } else if ((col == COL_OPTION)) {
- toggle_sym_value(menu);
- gtk_tree_view_expand_row(view, path, TRUE);
- }
- } else {
- if (col == COL_VALUE) {
- toggle_sym_value(menu);
- gtk_tree_view_expand_row(view, path, TRUE);
- } else if (col == COL_NO || col == COL_MOD
- || col == COL_YES) {
- change_sym_value(menu, col);
- gtk_tree_view_expand_row(view, path, TRUE);
- }
- }
-
- return FALSE;
-}
-
-/* Key pressed: update choice */
-gboolean
-on_treeview2_key_press_event(GtkWidget * widget,
- GdkEventKey * event, gpointer user_data)
-{
- GtkTreeView *view = GTK_TREE_VIEW(widget);
- GtkTreePath *path;
- GtkTreeViewColumn *column;
- GtkTreeIter iter;
- struct menu *menu;
- gint col;
-
- gtk_tree_view_get_cursor(view, &path, &column);
- if (path == NULL)
- return FALSE;
-
- if (event->keyval == GDK_space) {
- if (gtk_tree_view_row_expanded(view, path))
- gtk_tree_view_collapse_row(view, path);
- else
- gtk_tree_view_expand_row(view, path, FALSE);
- return TRUE;
- }
- if (event->keyval == GDK_KP_Enter) {
- }
- if (widget == tree1_w)
- return FALSE;
-
- gtk_tree_model_get_iter(model2, &iter, path);
- gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
-
- if (!strcasecmp(event->string, "n"))
- col = COL_NO;
- else if (!strcasecmp(event->string, "m"))
- col = COL_MOD;
- else if (!strcasecmp(event->string, "y"))
- col = COL_YES;
- else
- col = -1;
- change_sym_value(menu, col);
-
- return FALSE;
-}
-
-
-/* Row selection changed: update help */
-void
-on_treeview2_cursor_changed(GtkTreeView * treeview, gpointer user_data)
-{
- GtkTreeSelection *selection;
- GtkTreeIter iter;
- struct menu *menu;
-
- selection = gtk_tree_view_get_selection(treeview);
- if (gtk_tree_selection_get_selected(selection, &model2, &iter)) {
- gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
- text_insert_help(menu);
- }
-}
-
-
-/* User click: display sub-tree in the right frame. */
-gboolean
-on_treeview1_button_press_event(GtkWidget * widget,
- GdkEventButton * event, gpointer user_data)
-{
- GtkTreeView *view = GTK_TREE_VIEW(widget);
- GtkTreePath *path;
- GtkTreeViewColumn *column;
- GtkTreeIter iter;
- struct menu *menu;
-
- gint tx = (gint) event->x;
- gint ty = (gint) event->y;
- gint cx, cy;
-
- gtk_tree_view_get_path_at_pos(view, tx, ty, &path, &column, &cx,
- &cy);
- if (path == NULL)
- return FALSE;
-
- gtk_tree_model_get_iter(model1, &iter, path);
- gtk_tree_model_get(model1, &iter, COL_MENU, &menu, -1);
-
- if (event->type == GDK_2BUTTON_PRESS) {
- toggle_sym_value(menu);
- current = menu;
- display_tree_part();
- } else {
- browsed = menu;
- display_tree_part();
- }
-
- gtk_widget_realize(tree2_w);
- gtk_tree_view_set_cursor(view, path, NULL, FALSE);
- gtk_widget_grab_focus(tree2_w);
-
- return FALSE;
-}
-
-
-/* Fill a row of strings */
-static gchar **fill_row(struct menu *menu)
-{
- static gchar *row[COL_NUMBER];
- struct symbol *sym = menu->sym;
- const char *def;
- int stype;
- tristate val;
- enum prop_type ptype;
- int i;
-
- for (i = COL_OPTION; i <= COL_COLOR; i++)
- g_free(row[i]);
- bzero(row, sizeof(row));
-
- row[COL_OPTION] =
- g_strdup_printf("%s %s", _(menu_get_prompt(menu)),
- sym && !sym_has_value(sym) ? "(NEW)" : "");
-
- if (opt_mode == OPT_ALL && !menu_is_visible(menu))
- row[COL_COLOR] = g_strdup("DarkGray");
- else if (opt_mode == OPT_PROMPT &&
- menu_has_prompt(menu) && !menu_is_visible(menu))
- row[COL_COLOR] = g_strdup("DarkGray");
- else
- row[COL_COLOR] = g_strdup("Black");
-
- ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
- switch (ptype) {
- case P_MENU:
- row[COL_PIXBUF] = (gchar *) xpm_menu;
- if (view_mode == SINGLE_VIEW)
- row[COL_PIXVIS] = GINT_TO_POINTER(TRUE);
- row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
- break;
- case P_COMMENT:
- row[COL_PIXBUF] = (gchar *) xpm_void;
- row[COL_PIXVIS] = GINT_TO_POINTER(FALSE);
- row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
- break;
- default:
- row[COL_PIXBUF] = (gchar *) xpm_void;
- row[COL_PIXVIS] = GINT_TO_POINTER(FALSE);
- row[COL_BTNVIS] = GINT_TO_POINTER(TRUE);
- break;
- }
-
- if (!sym)
- return row;
- row[COL_NAME] = g_strdup(sym->name);
-
- sym_calc_value(sym);
- sym->flags &= ~SYMBOL_CHANGED;
-
- if (sym_is_choice(sym)) { // parse childs for getting final value
- struct menu *child;
- struct symbol *def_sym = sym_get_choice_value(sym);
- struct menu *def_menu = NULL;
-
- row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
-
- for (child = menu->list; child; child = child->next) {
- if (menu_is_visible(child)
- && child->sym == def_sym)
- def_menu = child;
- }
-
- if (def_menu)
- row[COL_VALUE] =
- g_strdup(_(menu_get_prompt(def_menu)));
- }
- if (sym->flags & SYMBOL_CHOICEVAL)
- row[COL_BTNRAD] = GINT_TO_POINTER(TRUE);
-
- stype = sym_get_type(sym);
- switch (stype) {
- case S_BOOLEAN:
- if (GPOINTER_TO_INT(row[COL_PIXVIS]) == FALSE)
- row[COL_BTNVIS] = GINT_TO_POINTER(TRUE);
- if (sym_is_choice(sym))
- break;
- /* fall through */
- case S_TRISTATE:
- val = sym_get_tristate_value(sym);
- switch (val) {
- case no:
- row[COL_NO] = g_strdup("N");
- row[COL_VALUE] = g_strdup("N");
- row[COL_BTNACT] = GINT_TO_POINTER(FALSE);
- row[COL_BTNINC] = GINT_TO_POINTER(FALSE);
- break;
- case mod:
- row[COL_MOD] = g_strdup("M");
- row[COL_VALUE] = g_strdup("M");
- row[COL_BTNINC] = GINT_TO_POINTER(TRUE);
- break;
- case yes:
- row[COL_YES] = g_strdup("Y");
- row[COL_VALUE] = g_strdup("Y");
- row[COL_BTNACT] = GINT_TO_POINTER(TRUE);
- row[COL_BTNINC] = GINT_TO_POINTER(FALSE);
- break;
- }
-
- if (val != no && sym_tristate_within_range(sym, no))
- row[COL_NO] = g_strdup("_");
- if (val != mod && sym_tristate_within_range(sym, mod))
- row[COL_MOD] = g_strdup("_");
- if (val != yes && sym_tristate_within_range(sym, yes))
- row[COL_YES] = g_strdup("_");
- break;
- case S_INT:
- case S_HEX:
- case S_STRING:
- def = sym_get_string_value(sym);
- row[COL_VALUE] = g_strdup(def);
- row[COL_EDIT] = GINT_TO_POINTER(TRUE);
- row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
- break;
- }
-
- return row;
-}
-
-
-/* Set the node content with a row of strings */
-static void set_node(GtkTreeIter * node, struct menu *menu, gchar ** row)
-{
- GdkColor color;
- gboolean success;
- GdkPixbuf *pix;
-
- pix = gdk_pixbuf_new_from_xpm_data((const char **)
- row[COL_PIXBUF]);
-
- gdk_color_parse(row[COL_COLOR], &color);
- gdk_colormap_alloc_colors(gdk_colormap_get_system(), &color, 1,
- FALSE, FALSE, &success);
-
- gtk_tree_store_set(tree, node,
- COL_OPTION, row[COL_OPTION],
- COL_NAME, row[COL_NAME],
- COL_NO, row[COL_NO],
- COL_MOD, row[COL_MOD],
- COL_YES, row[COL_YES],
- COL_VALUE, row[COL_VALUE],
- COL_MENU, (gpointer) menu,
- COL_COLOR, &color,
- COL_EDIT, GPOINTER_TO_INT(row[COL_EDIT]),
- COL_PIXBUF, pix,
- COL_PIXVIS, GPOINTER_TO_INT(row[COL_PIXVIS]),
- COL_BTNVIS, GPOINTER_TO_INT(row[COL_BTNVIS]),
- COL_BTNACT, GPOINTER_TO_INT(row[COL_BTNACT]),
- COL_BTNINC, GPOINTER_TO_INT(row[COL_BTNINC]),
- COL_BTNRAD, GPOINTER_TO_INT(row[COL_BTNRAD]),
- -1);
-
- g_object_unref(pix);
-}
-
-
-/* Add a node to the tree */
-static void place_node(struct menu *menu, char **row)
-{
- GtkTreeIter *parent = parents[indent - 1];
- GtkTreeIter *node = parents[indent];
-
- gtk_tree_store_append(tree, node, parent);
- set_node(node, menu, row);
-}
-
-
-/* Find a node in the GTK+ tree */
-static GtkTreeIter found;
-
-/*
- * Find a menu in the GtkTree starting at parent.
- */
-GtkTreeIter *gtktree_iter_find_node(GtkTreeIter * parent,
- struct menu *tofind)
-{
- GtkTreeIter iter;
- GtkTreeIter *child = &iter;
- gboolean valid;
- GtkTreeIter *ret;
-
- valid = gtk_tree_model_iter_children(model2, child, parent);
- while (valid) {
- struct menu *menu;
-
- gtk_tree_model_get(model2, child, 6, &menu, -1);
-
- if (menu == tofind) {
- memcpy(&found, child, sizeof(GtkTreeIter));
- return &found;
- }
-
- ret = gtktree_iter_find_node(child, tofind);
- if (ret)
- return ret;
-
- valid = gtk_tree_model_iter_next(model2, child);
- }
-
- return NULL;
-}
-
-
-/*
- * Update the tree by adding/removing entries
- * Does not change other nodes
- */
-static void update_tree(struct menu *src, GtkTreeIter * dst)
-{
- struct menu *child1;
- GtkTreeIter iter, tmp;
- GtkTreeIter *child2 = &iter;
- gboolean valid;
- GtkTreeIter *sibling;
- struct symbol *sym;
- struct menu *menu1, *menu2;
-
- if (src == &rootmenu)
- indent = 1;
-
- valid = gtk_tree_model_iter_children(model2, child2, dst);
- for (child1 = src->list; child1; child1 = child1->next) {
-
- sym = child1->sym;
-
- reparse:
- menu1 = child1;
- if (valid)
- gtk_tree_model_get(model2, child2, COL_MENU,
- &menu2, -1);
- else
- menu2 = NULL; // force adding of a first child
-
-#ifdef DEBUG
- printf("%*c%s | %s\n", indent, ' ',
- menu1 ? menu_get_prompt(menu1) : "nil",
- menu2 ? menu_get_prompt(menu2) : "nil");
-#endif
-
- if ((opt_mode == OPT_NORMAL && !menu_is_visible(child1)) ||
- (opt_mode == OPT_PROMPT && !menu_has_prompt(child1)) ||
- (opt_mode == OPT_ALL && !menu_get_prompt(child1))) {
-
- /* remove node */
- if (gtktree_iter_find_node(dst, menu1) != NULL) {
- memcpy(&tmp, child2, sizeof(GtkTreeIter));
- valid = gtk_tree_model_iter_next(model2,
- child2);
- gtk_tree_store_remove(tree2, &tmp);
- if (!valid)
- return; /* next parent */
- else
- goto reparse; /* next child */
- } else
- continue;
- }
-
- if (menu1 != menu2) {
- if (gtktree_iter_find_node(dst, menu1) == NULL) { // add node
- if (!valid && !menu2)
- sibling = NULL;
- else
- sibling = child2;
- gtk_tree_store_insert_before(tree2,
- child2,
- dst, sibling);
- set_node(child2, menu1, fill_row(menu1));
- if (menu2 == NULL)
- valid = TRUE;
- } else { // remove node
- memcpy(&tmp, child2, sizeof(GtkTreeIter));
- valid = gtk_tree_model_iter_next(model2,
- child2);
- gtk_tree_store_remove(tree2, &tmp);
- if (!valid)
- return; // next parent
- else
- goto reparse; // next child
- }
- } else if (sym && (sym->flags & SYMBOL_CHANGED)) {
- set_node(child2, menu1, fill_row(menu1));
- }
-
- indent++;
- update_tree(child1, child2);
- indent--;
-
- valid = gtk_tree_model_iter_next(model2, child2);
- }
-}
-
-
-/* Display the whole tree (single/split/full view) */
-static void display_tree(struct menu *menu)
-{
- struct symbol *sym;
- struct property *prop;
- struct menu *child;
- enum prop_type ptype;
-
- if (menu == &rootmenu) {
- indent = 1;
- current = &rootmenu;
- }
-
- for (child = menu->list; child; child = child->next) {
- prop = child->prompt;
- sym = child->sym;
- ptype = prop ? prop->type : P_UNKNOWN;
-
- if (sym)
- sym->flags &= ~SYMBOL_CHANGED;
-
- if ((view_mode == SPLIT_VIEW)
- && !(child->flags & MENU_ROOT) && (tree == tree1))
- continue;
-
- if ((view_mode == SPLIT_VIEW) && (child->flags & MENU_ROOT)
- && (tree == tree2))
- continue;
-
- if ((opt_mode == OPT_NORMAL && menu_is_visible(child)) ||
- (opt_mode == OPT_PROMPT && menu_has_prompt(child)) ||
- (opt_mode == OPT_ALL && menu_get_prompt(child)))
- place_node(child, fill_row(child));
-#ifdef DEBUG
- printf("%*c%s: ", indent, ' ', menu_get_prompt(child));
- printf("%s", child->flags & MENU_ROOT ? "rootmenu | " : "");
- printf("%s", prop_get_type_name(ptype));
- printf(" | ");
- if (sym) {
- printf("%s", sym_type_name(sym->type));
- printf(" | ");
- printf("%s", dbg_sym_flags(sym->flags));
- printf("\n");
- } else
- printf("\n");
-#endif
- if ((view_mode != FULL_VIEW) && (ptype == P_MENU)
- && (tree == tree2))
- continue;
-/*
- if (((menu != &rootmenu) && !(menu->flags & MENU_ROOT))
- || (view_mode == FULL_VIEW)
- || (view_mode == SPLIT_VIEW))*/
-
- /* Change paned position if the view is not in 'split mode' */
- if (view_mode == SINGLE_VIEW || view_mode == FULL_VIEW) {
- gtk_paned_set_position(GTK_PANED(hpaned), 0);
- }
-
- if (((view_mode == SINGLE_VIEW) && (menu->flags & MENU_ROOT))
- || (view_mode == FULL_VIEW)
- || (view_mode == SPLIT_VIEW)) {
- indent++;
- display_tree(child);
- indent--;
- }
- }
-}
-
-/* Display a part of the tree starting at current node (single/split view) */
-static void display_tree_part(void)
-{
- if (tree2)
- gtk_tree_store_clear(tree2);
- if (view_mode == SINGLE_VIEW)
- display_tree(current);
- else if (view_mode == SPLIT_VIEW)
- display_tree(browsed);
- gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w));
-}
-
-/* Display the list in the left frame (split view) */
-static void display_list(void)
-{
- if (tree1)
- gtk_tree_store_clear(tree1);
-
- tree = tree1;
- display_tree(&rootmenu);
- gtk_tree_view_expand_all(GTK_TREE_VIEW(tree1_w));
- tree = tree2;
-}
-
-void fixup_rootmenu(struct menu *menu)
-{
- struct menu *child;
- static int menu_cnt = 0;
-
- menu->flags |= MENU_ROOT;
- for (child = menu->list; child; child = child->next) {
- if (child->prompt && child->prompt->type == P_MENU) {
- menu_cnt++;
- fixup_rootmenu(child);
- menu_cnt--;
- } else if (!menu_cnt)
- fixup_rootmenu(child);
- }
-}
-
-
-/* Main */
-int main(int ac, char *av[])
-{
- const char *name;
- char *env;
- gchar *glade_file;
-
- bindtextdomain(PACKAGE, LOCALEDIR);
- bind_textdomain_codeset(PACKAGE, "UTF-8");
- textdomain(PACKAGE);
-
- /* GTK stuffs */
- gtk_set_locale();
- gtk_init(&ac, &av);
- glade_init();
-
- //add_pixmap_directory (PACKAGE_DATA_DIR "/" PACKAGE "/pixmaps");
- //add_pixmap_directory (PACKAGE_SOURCE_DIR "/pixmaps");
-
- /* Determine GUI path */
- env = getenv(SRCTREE);
- if (env)
- glade_file = g_strconcat(env, "/scripts/kconfig/gconf.glade", NULL);
- else if (av[0][0] == '/')
- glade_file = g_strconcat(av[0], ".glade", NULL);
- else
- glade_file = g_strconcat(g_get_current_dir(), "/", av[0], ".glade", NULL);
-
- /* Conf stuffs */
- if (ac > 1 && av[1][0] == '-') {
- switch (av[1][1]) {
- case 'a':
- //showAll = 1;
- break;
- case 'h':
- case '?':
- printf("%s <config>\n", av[0]);
- exit(0);
- }
- name = av[2];
- } else
- name = av[1];
-
- conf_parse(name);
- fixup_rootmenu(&rootmenu);
- conf_read(NULL);
-
- /* Load the interface and connect signals */
- init_main_window(glade_file);
- init_tree_model();
- init_left_tree();
- init_right_tree();
-
- switch (view_mode) {
- case SINGLE_VIEW:
- display_tree_part();
- break;
- case SPLIT_VIEW:
- display_list();
- break;
- case FULL_VIEW:
- display_tree(&rootmenu);
- break;
- }
-
- gtk_main();
-
- return 0;
-}
-
-static void conf_changed(void)
-{
- bool changed = conf_get_changed();
- gtk_widget_set_sensitive(save_btn, changed);
- gtk_widget_set_sensitive(save_menu_item, changed);
-}
+++ /dev/null
-<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
-
-<glade-interface>
-
-<widget class="GtkWindow" id="window1">
- <property name="visible">True</property>
- <property name="title" translatable="yes">Gtk Kernel Configurator</property>
- <property name="type">GTK_WINDOW_TOPLEVEL</property>
- <property name="window_position">GTK_WIN_POS_NONE</property>
- <property name="modal">False</property>
- <property name="default_width">640</property>
- <property name="default_height">480</property>
- <property name="resizable">True</property>
- <property name="destroy_with_parent">False</property>
- <property name="decorated">True</property>
- <property name="skip_taskbar_hint">False</property>
- <property name="skip_pager_hint">False</property>
- <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property>
- <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
- <signal name="destroy" handler="on_window1_destroy" object="window1"/>
- <signal name="size_request" handler="on_window1_size_request" object="vpaned1" last_modification_time="Fri, 11 Jan 2002 16:17:11 GMT"/>
- <signal name="delete_event" handler="on_window1_delete_event" object="window1" last_modification_time="Sun, 09 Mar 2003 19:42:46 GMT"/>
-
- <child>
- <widget class="GtkVBox" id="vbox1">
- <property name="visible">True</property>
- <property name="homogeneous">False</property>
- <property name="spacing">0</property>
-
- <child>
- <widget class="GtkMenuBar" id="menubar1">
- <property name="visible">True</property>
-
- <child>
- <widget class="GtkMenuItem" id="file1">
- <property name="visible">True</property>
- <property name="label" translatable="yes">_File</property>
- <property name="use_underline">True</property>
-
- <child>
- <widget class="GtkMenu" id="file1_menu">
-
- <child>
- <widget class="GtkImageMenuItem" id="load1">
- <property name="visible">True</property>
- <property name="tooltip" translatable="yes">Load a config file</property>
- <property name="label" translatable="yes">_Load</property>
- <property name="use_underline">True</property>
- <signal name="activate" handler="on_load1_activate"/>
- <accelerator key="L" modifiers="GDK_CONTROL_MASK" signal="activate"/>
-
- <child internal-child="image">
- <widget class="GtkImage" id="image39">
- <property name="visible">True</property>
- <property name="stock">gtk-open</property>
- <property name="icon_size">1</property>
- <property name="xalign">0.5</property>
- <property name="yalign">0.5</property>
- <property name="xpad">0</property>
- <property name="ypad">0</property>
- </widget>
- </child>
- </widget>
- </child>
-
- <child>
- <widget class="GtkImageMenuItem" id="save1">
- <property name="visible">True</property>
- <property name="tooltip" translatable="yes">Save the config in .config</property>
- <property name="label" translatable="yes">_Save</property>
- <property name="use_underline">True</property>
- <signal name="activate" handler="on_save_activate"/>
- <accelerator key="S" modifiers="GDK_CONTROL_MASK" signal="activate"/>
-
- <child internal-child="image">
- <widget class="GtkImage" id="image40">
- <property name="visible">True</property>
- <property name="stock">gtk-save</property>
- <property name="icon_size">1</property>
- <property name="xalign">0.5</property>
- <property name="yalign">0.5</property>
- <property name="xpad">0</property>
- <property name="ypad">0</property>
- </widget>
- </child>
- </widget>
- </child>
-
- <child>
- <widget class="GtkImageMenuItem" id="save_as1">
- <property name="visible">True</property>
- <property name="tooltip" translatable="yes">Save the config in a file</property>
- <property name="label" translatable="yes">Save _as</property>
- <property name="use_underline">True</property>
- <signal name="activate" handler="on_save_as1_activate"/>
-
- <child internal-child="image">
- <widget class="GtkImage" id="image41">
- <property name="visible">True</property>
- <property name="stock">gtk-save-as</property>
- <property name="icon_size">1</property>
- <property name="xalign">0.5</property>
- <property name="yalign">0.5</property>
- <property name="xpad">0</property>
- <property name="ypad">0</property>
- </widget>
- </child>
- </widget>
- </child>
-
- <child>
- <widget class="GtkSeparatorMenuItem" id="separator1">
- <property name="visible">True</property>
- </widget>
- </child>
-
- <child>
- <widget class="GtkImageMenuItem" id="quit1">
- <property name="visible">True</property>
- <property name="label" translatable="yes">_Quit</property>
- <property name="use_underline">True</property>
- <signal name="activate" handler="on_quit1_activate"/>
- <accelerator key="Q" modifiers="GDK_CONTROL_MASK" signal="activate"/>
-
- <child internal-child="image">
- <widget class="GtkImage" id="image42">
- <property name="visible">True</property>
- <property name="stock">gtk-quit</property>
- <property name="icon_size">1</property>
- <property name="xalign">0.5</property>
- <property name="yalign">0.5</property>
- <property name="xpad">0</property>
- <property name="ypad">0</property>
- </widget>
- </child>
- </widget>
- </child>
- </widget>
- </child>
- </widget>
- </child>
-
- <child>
- <widget class="GtkMenuItem" id="options1">
- <property name="visible">True</property>
- <property name="label" translatable="yes">_Options</property>
- <property name="use_underline">True</property>
-
- <child>
- <widget class="GtkMenu" id="options1_menu">
-
- <child>
- <widget class="GtkCheckMenuItem" id="show_name1">
- <property name="visible">True</property>
- <property name="tooltip" translatable="yes">Show name</property>
- <property name="label" translatable="yes">Show _name</property>
- <property name="use_underline">True</property>
- <property name="active">False</property>
- <signal name="activate" handler="on_show_name1_activate"/>
- </widget>
- </child>
-
- <child>
- <widget class="GtkCheckMenuItem" id="show_range1">
- <property name="visible">True</property>
- <property name="tooltip" translatable="yes">Show range (Y/M/N)</property>
- <property name="label" translatable="yes">Show _range</property>
- <property name="use_underline">True</property>
- <property name="active">False</property>
- <signal name="activate" handler="on_show_range1_activate"/>
- </widget>
- </child>
-
- <child>
- <widget class="GtkCheckMenuItem" id="show_data1">
- <property name="visible">True</property>
- <property name="tooltip" translatable="yes">Show value of the option</property>
- <property name="label" translatable="yes">Show _data</property>
- <property name="use_underline">True</property>
- <property name="active">False</property>
- <signal name="activate" handler="on_show_data1_activate"/>
- </widget>
- </child>
-
- <child>
- <widget class="GtkSeparatorMenuItem" id="separator2">
- <property name="visible">True</property>
- </widget>
- </child>
-
- <child>
- <widget class="GtkRadioMenuItem" id="set_option_mode1">
- <property name="visible">True</property>
- <property name="tooltip" translatable="yes">Show normal options</property>
- <property name="label" translatable="yes">Show normal options</property>
- <property name="use_underline">True</property>
- <property name="active">True</property>
- <signal name="activate" handler="on_set_option_mode1_activate"/>
- </widget>
- </child>
-
- <child>
- <widget class="GtkRadioMenuItem" id="set_option_mode2">
- <property name="visible">True</property>
- <property name="tooltip" translatable="yes">Show all options</property>
- <property name="label" translatable="yes">Show all _options</property>
- <property name="use_underline">True</property>
- <property name="active">False</property>
- <property name="group">set_option_mode1</property>
- <signal name="activate" handler="on_set_option_mode2_activate"/>
- </widget>
- </child>
-
- <child>
- <widget class="GtkRadioMenuItem" id="set_option_mode3">
- <property name="visible">True</property>
- <property name="tooltip" translatable="yes">Show all options with prompts</property>
- <property name="label" translatable="yes">Show all prompt options</property>
- <property name="use_underline">True</property>
- <property name="active">False</property>
- <property name="group">set_option_mode1</property>
- <signal name="activate" handler="on_set_option_mode3_activate"/>
- </widget>
- </child>
-
- </widget>
- </child>
- </widget>
- </child>
-
- <child>
- <widget class="GtkMenuItem" id="help1">
- <property name="visible">True</property>
- <property name="label" translatable="yes">_Help</property>
- <property name="use_underline">True</property>
-
- <child>
- <widget class="GtkMenu" id="help1_menu">
-
- <child>
- <widget class="GtkImageMenuItem" id="introduction1">
- <property name="visible">True</property>
- <property name="label" translatable="yes">_Introduction</property>
- <property name="use_underline">True</property>
- <signal name="activate" handler="on_introduction1_activate" last_modification_time="Fri, 15 Nov 2002 20:26:30 GMT"/>
- <accelerator key="I" modifiers="GDK_CONTROL_MASK" signal="activate"/>
-
- <child internal-child="image">
- <widget class="GtkImage" id="image43">
- <property name="visible">True</property>
- <property name="stock">gtk-dialog-question</property>
- <property name="icon_size">1</property>
- <property name="xalign">0.5</property>
- <property name="yalign">0.5</property>
- <property name="xpad">0</property>
- <property name="ypad">0</property>
- </widget>
- </child>
- </widget>
- </child>
-
- <child>
- <widget class="GtkImageMenuItem" id="about1">
- <property name="visible">True</property>
- <property name="label" translatable="yes">_About</property>
- <property name="use_underline">True</property>
- <signal name="activate" handler="on_about1_activate" last_modification_time="Fri, 15 Nov 2002 20:26:30 GMT"/>
- <accelerator key="A" modifiers="GDK_CONTROL_MASK" signal="activate"/>
-
- <child internal-child="image">
- <widget class="GtkImage" id="image44">
- <property name="visible">True</property>
- <property name="stock">gtk-properties</property>
- <property name="icon_size">1</property>
- <property name="xalign">0.5</property>
- <property name="yalign">0.5</property>
- <property name="xpad">0</property>
- <property name="ypad">0</property>
- </widget>
- </child>
- </widget>
- </child>
-
- <child>
- <widget class="GtkImageMenuItem" id="license1">
- <property name="visible">True</property>
- <property name="label" translatable="yes">_License</property>
- <property name="use_underline">True</property>
- <signal name="activate" handler="on_license1_activate" last_modification_time="Fri, 15 Nov 2002 20:26:30 GMT"/>
-
- <child internal-child="image">
- <widget class="GtkImage" id="image45">
- <property name="visible">True</property>
- <property name="stock">gtk-justify-fill</property>
- <property name="icon_size">1</property>
- <property name="xalign">0.5</property>
- <property name="yalign">0.5</property>
- <property name="xpad">0</property>
- <property name="ypad">0</property>
- </widget>
- </child>
- </widget>
- </child>
- </widget>
- </child>
- </widget>
- </child>
- </widget>
- <packing>
- <property name="padding">0</property>
- <property name="expand">False</property>
- <property name="fill">False</property>
- </packing>
- </child>
-
- <child>
- <widget class="GtkHandleBox" id="handlebox1">
- <property name="visible">True</property>
- <property name="shadow_type">GTK_SHADOW_OUT</property>
- <property name="handle_position">GTK_POS_LEFT</property>
- <property name="snap_edge">GTK_POS_TOP</property>
-
- <child>
- <widget class="GtkToolbar" id="toolbar1">
- <property name="visible">True</property>
- <property name="orientation">GTK_ORIENTATION_HORIZONTAL</property>
- <property name="toolbar_style">GTK_TOOLBAR_BOTH</property>
- <property name="tooltips">True</property>
- <property name="show_arrow">True</property>
-
- <child>
- <widget class="GtkToolButton" id="button1">
- <property name="visible">True</property>
- <property name="tooltip" translatable="yes">Goes up of one level (single view)</property>
- <property name="label" translatable="yes">Back</property>
- <property name="use_underline">True</property>
- <property name="stock_id">gtk-undo</property>
- <property name="visible_horizontal">True</property>
- <property name="visible_vertical">True</property>
- <property name="is_important">False</property>
- <signal name="clicked" handler="on_back_clicked"/>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="homogeneous">True</property>
- </packing>
- </child>
-
- <child>
- <widget class="GtkToolItem" id="toolitem1">
- <property name="visible">True</property>
- <property name="visible_horizontal">True</property>
- <property name="visible_vertical">True</property>
- <property name="is_important">False</property>
-
- <child>
- <widget class="GtkVSeparator" id="vseparator1">
- <property name="visible">True</property>
- </widget>
- </child>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="homogeneous">False</property>
- </packing>
- </child>
-
- <child>
- <widget class="GtkToolButton" id="button2">
- <property name="visible">True</property>
- <property name="tooltip" translatable="yes">Load a config file</property>
- <property name="label" translatable="yes">Load</property>
- <property name="use_underline">True</property>
- <property name="stock_id">gtk-open</property>
- <property name="visible_horizontal">True</property>
- <property name="visible_vertical">True</property>
- <property name="is_important">False</property>
- <signal name="clicked" handler="on_load_clicked"/>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="homogeneous">True</property>
- </packing>
- </child>
-
- <child>
- <widget class="GtkToolButton" id="button3">
- <property name="visible">True</property>
- <property name="tooltip" translatable="yes">Save a config file</property>
- <property name="label" translatable="yes">Save</property>
- <property name="use_underline">True</property>
- <property name="stock_id">gtk-save</property>
- <property name="visible_horizontal">True</property>
- <property name="visible_vertical">True</property>
- <property name="is_important">False</property>
- <signal name="clicked" handler="on_save_activate"/>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="homogeneous">True</property>
- </packing>
- </child>
-
- <child>
- <widget class="GtkToolItem" id="toolitem2">
- <property name="visible">True</property>
- <property name="visible_horizontal">True</property>
- <property name="visible_vertical">True</property>
- <property name="is_important">False</property>
-
- <child>
- <widget class="GtkVSeparator" id="vseparator2">
- <property name="visible">True</property>
- </widget>
- </child>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="homogeneous">False</property>
- </packing>
- </child>
-
- <child>
- <widget class="GtkToolButton" id="button4">
- <property name="visible">True</property>
- <property name="tooltip" translatable="yes">Single view</property>
- <property name="label" translatable="yes">Single</property>
- <property name="use_underline">True</property>
- <property name="stock_id">gtk-missing-image</property>
- <property name="visible_horizontal">True</property>
- <property name="visible_vertical">True</property>
- <property name="is_important">False</property>
- <signal name="clicked" handler="on_single_clicked" last_modification_time="Sun, 12 Jan 2003 14:28:39 GMT"/>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="homogeneous">True</property>
- </packing>
- </child>
-
- <child>
- <widget class="GtkToolButton" id="button5">
- <property name="visible">True</property>
- <property name="tooltip" translatable="yes">Split view</property>
- <property name="label" translatable="yes">Split</property>
- <property name="use_underline">True</property>
- <property name="stock_id">gtk-missing-image</property>
- <property name="visible_horizontal">True</property>
- <property name="visible_vertical">True</property>
- <property name="is_important">False</property>
- <signal name="clicked" handler="on_split_clicked" last_modification_time="Sun, 12 Jan 2003 14:28:45 GMT"/>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="homogeneous">True</property>
- </packing>
- </child>
-
- <child>
- <widget class="GtkToolButton" id="button6">
- <property name="visible">True</property>
- <property name="tooltip" translatable="yes">Full view</property>
- <property name="label" translatable="yes">Full</property>
- <property name="use_underline">True</property>
- <property name="stock_id">gtk-missing-image</property>
- <property name="visible_horizontal">True</property>
- <property name="visible_vertical">True</property>
- <property name="is_important">False</property>
- <signal name="clicked" handler="on_full_clicked" last_modification_time="Sun, 12 Jan 2003 14:28:50 GMT"/>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="homogeneous">True</property>
- </packing>
- </child>
-
- <child>
- <widget class="GtkToolItem" id="toolitem3">
- <property name="visible">True</property>
- <property name="visible_horizontal">True</property>
- <property name="visible_vertical">True</property>
- <property name="is_important">False</property>
-
- <child>
- <widget class="GtkVSeparator" id="vseparator3">
- <property name="visible">True</property>
- </widget>
- </child>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="homogeneous">False</property>
- </packing>
- </child>
-
- <child>
- <widget class="GtkToolButton" id="button7">
- <property name="visible">True</property>
- <property name="tooltip" translatable="yes">Collapse the whole tree in the right frame</property>
- <property name="label" translatable="yes">Collapse</property>
- <property name="use_underline">True</property>
- <property name="stock_id">gtk-remove</property>
- <property name="visible_horizontal">True</property>
- <property name="visible_vertical">True</property>
- <property name="is_important">False</property>
- <signal name="clicked" handler="on_collapse_clicked"/>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="homogeneous">True</property>
- </packing>
- </child>
-
- <child>
- <widget class="GtkToolButton" id="button8">
- <property name="visible">True</property>
- <property name="tooltip" translatable="yes">Expand the whole tree in the right frame</property>
- <property name="label" translatable="yes">Expand</property>
- <property name="use_underline">True</property>
- <property name="stock_id">gtk-add</property>
- <property name="visible_horizontal">True</property>
- <property name="visible_vertical">True</property>
- <property name="is_important">False</property>
- <signal name="clicked" handler="on_expand_clicked"/>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="homogeneous">True</property>
- </packing>
- </child>
- </widget>
- </child>
- </widget>
- <packing>
- <property name="padding">0</property>
- <property name="expand">False</property>
- <property name="fill">False</property>
- </packing>
- </child>
-
- <child>
- <widget class="GtkHPaned" id="hpaned1">
- <property name="width_request">1</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="position">0</property>
-
- <child>
- <widget class="GtkScrolledWindow" id="scrolledwindow1">
- <property name="visible">True</property>
- <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
- <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
- <property name="shadow_type">GTK_SHADOW_IN</property>
- <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
-
- <child>
- <widget class="GtkTreeView" id="treeview1">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="headers_visible">True</property>
- <property name="rules_hint">False</property>
- <property name="reorderable">False</property>
- <property name="enable_search">False</property>
- <signal name="cursor_changed" handler="on_treeview2_cursor_changed" last_modification_time="Sun, 12 Jan 2003 15:58:22 GMT"/>
- <signal name="button_press_event" handler="on_treeview1_button_press_event" last_modification_time="Sun, 12 Jan 2003 16:03:52 GMT"/>
- <signal name="key_press_event" handler="on_treeview2_key_press_event" last_modification_time="Sun, 12 Jan 2003 16:11:44 GMT"/>
- </widget>
- </child>
- </widget>
- <packing>
- <property name="shrink">True</property>
- <property name="resize">False</property>
- </packing>
- </child>
-
- <child>
- <widget class="GtkVPaned" id="vpaned1">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="position">0</property>
-
- <child>
- <widget class="GtkScrolledWindow" id="scrolledwindow2">
- <property name="visible">True</property>
- <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
- <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
- <property name="shadow_type">GTK_SHADOW_IN</property>
- <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
-
- <child>
- <widget class="GtkTreeView" id="treeview2">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="has_focus">True</property>
- <property name="headers_visible">True</property>
- <property name="rules_hint">False</property>
- <property name="reorderable">False</property>
- <property name="enable_search">False</property>
- <signal name="cursor_changed" handler="on_treeview2_cursor_changed" last_modification_time="Sun, 12 Jan 2003 15:57:55 GMT"/>
- <signal name="button_press_event" handler="on_treeview2_button_press_event" last_modification_time="Sun, 12 Jan 2003 15:57:58 GMT"/>
- <signal name="key_press_event" handler="on_treeview2_key_press_event" last_modification_time="Sun, 12 Jan 2003 15:58:01 GMT"/>
- </widget>
- </child>
- </widget>
- <packing>
- <property name="shrink">True</property>
- <property name="resize">False</property>
- </packing>
- </child>
-
- <child>
- <widget class="GtkScrolledWindow" id="scrolledwindow3">
- <property name="visible">True</property>
- <property name="hscrollbar_policy">GTK_POLICY_NEVER</property>
- <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
- <property name="shadow_type">GTK_SHADOW_IN</property>
- <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
-
- <child>
- <widget class="GtkTextView" id="textview3">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="editable">False</property>
- <property name="overwrite">False</property>
- <property name="accepts_tab">True</property>
- <property name="justification">GTK_JUSTIFY_LEFT</property>
- <property name="wrap_mode">GTK_WRAP_WORD</property>
- <property name="cursor_visible">True</property>
- <property name="pixels_above_lines">0</property>
- <property name="pixels_below_lines">0</property>
- <property name="pixels_inside_wrap">0</property>
- <property name="left_margin">0</property>
- <property name="right_margin">0</property>
- <property name="indent">0</property>
- <property name="text" translatable="yes">Sorry, no help available for this option yet.</property>
- </widget>
- </child>
- </widget>
- <packing>
- <property name="shrink">True</property>
- <property name="resize">True</property>
- </packing>
- </child>
- </widget>
- <packing>
- <property name="shrink">True</property>
- <property name="resize">True</property>
- </packing>
- </child>
- </widget>
- <packing>
- <property name="padding">0</property>
- <property name="expand">True</property>
- <property name="fill">True</property>
- </packing>
- </child>
- </widget>
- </child>
-</widget>
-
-</glade-interface>
+++ /dev/null
-%language=ANSI-C
-%define hash-function-name kconf_id_hash
-%define lookup-function-name kconf_id_lookup
-%define string-pool-name kconf_id_strings
-%compare-strncmp
-%enum
-%pic
-%struct-type
-
-struct kconf_id;
-
-static const struct kconf_id *kconf_id_lookup(register const char *str, register unsigned int len);
-
-%%
-mainmenu, T_MAINMENU, TF_COMMAND
-menu, T_MENU, TF_COMMAND
-endmenu, T_ENDMENU, TF_COMMAND
-source, T_SOURCE, TF_COMMAND
-choice, T_CHOICE, TF_COMMAND
-endchoice, T_ENDCHOICE, TF_COMMAND
-comment, T_COMMENT, TF_COMMAND
-config, T_CONFIG, TF_COMMAND
-menuconfig, T_MENUCONFIG, TF_COMMAND
-help, T_HELP, TF_COMMAND
-if, T_IF, TF_COMMAND|TF_PARAM
-endif, T_ENDIF, TF_COMMAND
-depends, T_DEPENDS, TF_COMMAND
-optional, T_OPTIONAL, TF_COMMAND
-default, T_DEFAULT, TF_COMMAND, S_UNKNOWN
-prompt, T_PROMPT, TF_COMMAND
-tristate, T_TYPE, TF_COMMAND, S_TRISTATE
-def_tristate, T_DEFAULT, TF_COMMAND, S_TRISTATE
-bool, T_TYPE, TF_COMMAND, S_BOOLEAN
-boolean, T_TYPE, TF_COMMAND, S_BOOLEAN
-def_bool, T_DEFAULT, TF_COMMAND, S_BOOLEAN
-int, T_TYPE, TF_COMMAND, S_INT
-hex, T_TYPE, TF_COMMAND, S_HEX
-string, T_TYPE, TF_COMMAND, S_STRING
-select, T_SELECT, TF_COMMAND
-range, T_RANGE, TF_COMMAND
-visible, T_VISIBLE, TF_COMMAND
-option, T_OPTION, TF_COMMAND
-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
-%%
+++ /dev/null
-/*
- * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
- * Released under the terms of the GNU GPL v2.0.
- */
-
-static const char *xpm_load[] = {
-"22 22 5 1",
-". c None",
-"# c #000000",
-"c c #838100",
-"a c #ffff00",
-"b c #ffffff",
-"......................",
-"......................",
-"......................",
-"............####....#.",
-"...........#....##.##.",
-"..................###.",
-".................####.",
-".####...........#####.",
-"#abab##########.......",
-"#babababababab#.......",
-"#ababababababa#.......",
-"#babababababab#.......",
-"#ababab###############",
-"#babab##cccccccccccc##",
-"#abab##cccccccccccc##.",
-"#bab##cccccccccccc##..",
-"#ab##cccccccccccc##...",
-"#b##cccccccccccc##....",
-"###cccccccccccc##.....",
-"##cccccccccccc##......",
-"###############.......",
-"......................"};
-
-static const char *xpm_save[] = {
-"22 22 5 1",
-". c None",
-"# c #000000",
-"a c #838100",
-"b c #c5c2c5",
-"c c #cdb6d5",
-"......................",
-".####################.",
-".#aa#bbbbbbbbbbbb#bb#.",
-".#aa#bbbbbbbbbbbb#bb#.",
-".#aa#bbbbbbbbbcbb####.",
-".#aa#bbbccbbbbbbb#aa#.",
-".#aa#bbbccbbbbbbb#aa#.",
-".#aa#bbbbbbbbbbbb#aa#.",
-".#aa#bbbbbbbbbbbb#aa#.",
-".#aa#bbbbbbbbbbbb#aa#.",
-".#aa#bbbbbbbbbbbb#aa#.",
-".#aaa############aaa#.",
-".#aaaaaaaaaaaaaaaaaa#.",
-".#aaaaaaaaaaaaaaaaaa#.",
-".#aaa#############aa#.",
-".#aaa#########bbb#aa#.",
-".#aaa#########bbb#aa#.",
-".#aaa#########bbb#aa#.",
-".#aaa#########bbb#aa#.",
-".#aaa#########bbb#aa#.",
-"..##################..",
-"......................"};
-
-static const char *xpm_back[] = {
-"22 22 3 1",
-". c None",
-"# c #000083",
-"a c #838183",
-"......................",
-"......................",
-"......................",
-"......................",
-"......................",
-"...........######a....",
-"..#......##########...",
-"..##...####......##a..",
-"..###.###.........##..",
-"..######..........##..",
-"..#####...........##..",
-"..######..........##..",
-"..#######.........##..",
-"..########.......##a..",
-"...............a###...",
-"...............###....",
-"......................",
-"......................",
-"......................",
-"......................",
-"......................",
-"......................"};
-
-static const char *xpm_tree_view[] = {
-"22 22 2 1",
-". c None",
-"# c #000000",
-"......................",
-"......................",
-"......#...............",
-"......#...............",
-"......#...............",
-"......#...............",
-"......#...............",
-"......########........",
-"......#...............",
-"......#...............",
-"......#...............",
-"......#...............",
-"......#...............",
-"......########........",
-"......#...............",
-"......#...............",
-"......#...............",
-"......#...............",
-"......#...............",
-"......########........",
-"......................",
-"......................"};
-
-static const char *xpm_single_view[] = {
-"22 22 2 1",
-". c None",
-"# c #000000",
-"......................",
-"......................",
-"..........#...........",
-"..........#...........",
-"..........#...........",
-"..........#...........",
-"..........#...........",
-"..........#...........",
-"..........#...........",
-"..........#...........",
-"..........#...........",
-"..........#...........",
-"..........#...........",
-"..........#...........",
-"..........#...........",
-"..........#...........",
-"..........#...........",
-"..........#...........",
-"..........#...........",
-"..........#...........",
-"......................",
-"......................"};
-
-static const char *xpm_split_view[] = {
-"22 22 2 1",
-". c None",
-"# c #000000",
-"......................",
-"......................",
-"......#......#........",
-"......#......#........",
-"......#......#........",
-"......#......#........",
-"......#......#........",
-"......#......#........",
-"......#......#........",
-"......#......#........",
-"......#......#........",
-"......#......#........",
-"......#......#........",
-"......#......#........",
-"......#......#........",
-"......#......#........",
-"......#......#........",
-"......#......#........",
-"......#......#........",
-"......#......#........",
-"......................",
-"......................"};
-
-static const char *xpm_symbol_no[] = {
-"12 12 2 1",
-" c white",
-". c black",
-" ",
-" .......... ",
-" . . ",
-" . . ",
-" . . ",
-" . . ",
-" . . ",
-" . . ",
-" . . ",
-" . . ",
-" .......... ",
-" "};
-
-static const char *xpm_symbol_mod[] = {
-"12 12 2 1",
-" c white",
-". c black",
-" ",
-" .......... ",
-" . . ",
-" . . ",
-" . .. . ",
-" . .... . ",
-" . .... . ",
-" . .. . ",
-" . . ",
-" . . ",
-" .......... ",
-" "};
-
-static const char *xpm_symbol_yes[] = {
-"12 12 2 1",
-" c white",
-". c black",
-" ",
-" .......... ",
-" . . ",
-" . . ",
-" . . . ",
-" . .. . ",
-" . . .. . ",
-" . .... . ",
-" . .. . ",
-" . . ",
-" .......... ",
-" "};
-
-static const char *xpm_choice_no[] = {
-"12 12 2 1",
-" c white",
-". c black",
-" ",
-" .... ",
-" .. .. ",
-" . . ",
-" . . ",
-" . . ",
-" . . ",
-" . . ",
-" . . ",
-" .. .. ",
-" .... ",
-" "};
-
-static const char *xpm_choice_yes[] = {
-"12 12 2 1",
-" c white",
-". c black",
-" ",
-" .... ",
-" .. .. ",
-" . . ",
-" . .. . ",
-" . .... . ",
-" . .... . ",
-" . .. . ",
-" . . ",
-" .. .. ",
-" .... ",
-" "};
-
-static const char *xpm_menu[] = {
-"12 12 2 1",
-" c white",
-". c black",
-" ",
-" .......... ",
-" . . ",
-" . .. . ",
-" . .... . ",
-" . ...... . ",
-" . ...... . ",
-" . .... . ",
-" . .. . ",
-" . . ",
-" .......... ",
-" "};
-
-static const char *xpm_menu_inv[] = {
-"12 12 2 1",
-" c white",
-". c black",
-" ",
-" .......... ",
-" .......... ",
-" .. ...... ",
-" .. .... ",
-" .. .. ",
-" .. .. ",
-" .. .... ",
-" .. ...... ",
-" .......... ",
-" .......... ",
-" "};
-
-static const char *xpm_menuback[] = {
-"12 12 2 1",
-" c white",
-". c black",
-" ",
-" .......... ",
-" . . ",
-" . .. . ",
-" . .... . ",
-" . ...... . ",
-" . ...... . ",
-" . .... . ",
-" . .. . ",
-" . . ",
-" .......... ",
-" "};
-
-static const char *xpm_void[] = {
-"12 12 2 1",
-" c white",
-". c black",
-" ",
-" ",
-" ",
-" ",
-" ",
-" ",
-" ",
-" ",
-" ",
-" ",
-" ",
-" "};
+++ /dev/null
-/*
- * Arnaldo Carvalho de Melo <acme@conectiva.com.br>, 2005
- *
- * Released under the terms of the GNU GPL v2.0
- */
-
-#include <stdlib.h>
-#include <string.h>
-
-#include "lkc.h"
-
-static char *escape(const char* text, char *bf, int len)
-{
- char *bfp = bf;
- int multiline = strchr(text, '\n') != NULL;
- int eol = 0;
- int textlen = strlen(text);
-
- if ((textlen > 0) && (text[textlen-1] == '\n'))
- eol = 1;
-
- *bfp++ = '"';
- --len;
-
- if (multiline) {
- *bfp++ = '"';
- *bfp++ = '\n';
- *bfp++ = '"';
- len -= 3;
- }
-
- while (*text != '\0' && len > 1) {
- if (*text == '"')
- *bfp++ = '\\';
- else if (*text == '\n') {
- *bfp++ = '\\';
- *bfp++ = 'n';
- *bfp++ = '"';
- *bfp++ = '\n';
- *bfp++ = '"';
- len -= 5;
- ++text;
- goto next;
- }
- else if (*text == '\\') {
- *bfp++ = '\\';
- len--;
- }
- *bfp++ = *text++;
-next:
- --len;
- }
-
- if (multiline && eol)
- bfp -= 3;
-
- *bfp++ = '"';
- *bfp = '\0';
-
- return bf;
-}
-
-struct file_line {
- struct file_line *next;
- const char *file;
- int lineno;
-};
-
-static struct file_line *file_line__new(const char *file, int lineno)
-{
- struct file_line *self = malloc(sizeof(*self));
-
- if (self == NULL)
- goto out;
-
- self->file = file;
- self->lineno = lineno;
- self->next = NULL;
-out:
- return self;
-}
-
-struct message {
- const char *msg;
- const char *option;
- struct message *next;
- struct file_line *files;
-};
-
-static struct message *message__list;
-
-static struct message *message__new(const char *msg, char *option,
- const char *file, int lineno)
-{
- struct message *self = malloc(sizeof(*self));
-
- if (self == NULL)
- goto out;
-
- self->files = file_line__new(file, lineno);
- if (self->files == NULL)
- goto out_fail;
-
- self->msg = strdup(msg);
- if (self->msg == NULL)
- goto out_fail_msg;
-
- self->option = option;
- self->next = NULL;
-out:
- return self;
-out_fail_msg:
- free(self->files);
-out_fail:
- free(self);
- self = NULL;
- goto out;
-}
-
-static struct message *mesage__find(const char *msg)
-{
- struct message *m = message__list;
-
- while (m != NULL) {
- if (strcmp(m->msg, msg) == 0)
- break;
- m = m->next;
- }
-
- return m;
-}
-
-static int message__add_file_line(struct message *self, const char *file,
- int lineno)
-{
- int rc = -1;
- struct file_line *fl = file_line__new(file, lineno);
-
- if (fl == NULL)
- goto out;
-
- fl->next = self->files;
- self->files = fl;
- rc = 0;
-out:
- return rc;
-}
-
-static int message__add(const char *msg, char *option, const char *file,
- int lineno)
-{
- int rc = 0;
- char bf[16384];
- char *escaped = escape(msg, bf, sizeof(bf));
- struct message *m = mesage__find(escaped);
-
- if (m != NULL)
- rc = message__add_file_line(m, file, lineno);
- else {
- m = message__new(escaped, option, file, lineno);
-
- if (m != NULL) {
- m->next = message__list;
- message__list = m;
- } else
- rc = -1;
- }
- return rc;
-}
-
-static void menu_build_message_list(struct menu *menu)
-{
- struct menu *child;
-
- message__add(menu_get_prompt(menu), NULL,
- menu->file == NULL ? "Root Menu" : menu->file->name,
- menu->lineno);
-
- if (menu->sym != NULL && menu_has_help(menu))
- message__add(menu_get_help(menu), menu->sym->name,
- menu->file == NULL ? "Root Menu" : menu->file->name,
- menu->lineno);
-
- for (child = menu->list; child != NULL; child = child->next)
- if (child->prompt != NULL)
- menu_build_message_list(child);
-}
-
-static void message__print_file_lineno(struct message *self)
-{
- struct file_line *fl = self->files;
-
- putchar('\n');
- if (self->option != NULL)
- printf("# %s:00000\n", self->option);
-
- printf("#: %s:%d", fl->file, fl->lineno);
- fl = fl->next;
-
- while (fl != NULL) {
- printf(", %s:%d", fl->file, fl->lineno);
- fl = fl->next;
- }
-
- putchar('\n');
-}
-
-static void message__print_gettext_msgid_msgstr(struct message *self)
-{
- message__print_file_lineno(self);
-
- printf("msgid %s\n"
- "msgstr \"\"\n", self->msg);
-}
-
-static void menu__xgettext(void)
-{
- struct message *m = message__list;
-
- while (m != NULL) {
- /* skip empty lines ("") */
- if (strlen(m->msg) > sizeof("\"\""))
- message__print_gettext_msgid_msgstr(m);
- m = m->next;
- }
-}
-
-int main(int ac, char **av)
-{
- conf_parse(av[1]);
-
- menu_build_message_list(menu_get_root_menu(NULL));
- menu__xgettext();
- return 0;
-}
+++ /dev/null
-%option nostdinit noyywrap never-interactive full ecs
-%option 8bit nodefault perf-report perf-report
-%option noinput
-%x COMMAND HELP STRING PARAM
-%{
-/*
- * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
- * Released under the terms of the GNU GPL v2.0.
- */
-
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "lkc.h"
-
-#define START_STRSIZE 16
-
-static struct {
- struct file *file;
- int lineno;
-} current_pos;
-
-static char *text;
-static int text_size, text_asize;
-
-struct buffer {
- struct buffer *parent;
- YY_BUFFER_STATE state;
-};
-
-struct buffer *current_buf;
-
-static int last_ts, first_ts;
-
-static void zconf_endhelp(void);
-static void zconf_endfile(void);
-
-static void new_string(void)
-{
- text = malloc(START_STRSIZE);
- text_asize = START_STRSIZE;
- text_size = 0;
- *text = 0;
-}
-
-static void append_string(const char *str, int size)
-{
- int new_size = text_size + size + 1;
- if (new_size > text_asize) {
- new_size += START_STRSIZE - 1;
- new_size &= -START_STRSIZE;
- text = realloc(text, new_size);
- text_asize = new_size;
- }
- memcpy(text + text_size, str, size);
- text_size += size;
- text[text_size] = 0;
-}
-
-static void alloc_string(const char *str, int size)
-{
- text = malloc(size + 1);
- memcpy(text, str, size);
- text[size] = 0;
-}
-%}
-
-ws [ \n\t]
-n [A-Za-z0-9_]
-
-%%
- int str = 0;
- int ts, i;
-
-[ \t]*#.*\n |
-[ \t]*\n {
- current_file->lineno++;
- return T_EOL;
-}
-[ \t]*#.*
-
-
-[ \t]+ {
- BEGIN(COMMAND);
-}
-
-. {
- unput(yytext[0]);
- BEGIN(COMMAND);
-}
-
-
-<COMMAND>{
- {n}+ {
- const struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
- BEGIN(PARAM);
- current_pos.file = current_file;
- current_pos.lineno = current_file->lineno;
- if (id && id->flags & TF_COMMAND) {
- zconflval.id = id;
- return id->token;
- }
- alloc_string(yytext, yyleng);
- zconflval.string = text;
- return T_WORD;
- }
- .
- \n {
- BEGIN(INITIAL);
- current_file->lineno++;
- return T_EOL;
- }
-}
-
-<PARAM>{
- "&&" return T_AND;
- "||" return T_OR;
- "(" return T_OPEN_PAREN;
- ")" return T_CLOSE_PAREN;
- "!" return T_NOT;
- "=" return T_EQUAL;
- "!=" return T_UNEQUAL;
- \"|\' {
- str = yytext[0];
- new_string();
- BEGIN(STRING);
- }
- \n BEGIN(INITIAL); current_file->lineno++; return T_EOL;
- --- /* ignore */
- ({n}|[-/.])+ {
- const struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
- if (id && id->flags & TF_PARAM) {
- zconflval.id = id;
- return id->token;
- }
- alloc_string(yytext, yyleng);
- zconflval.string = text;
- return T_WORD;
- }
- #.* /* comment */
- \\\n current_file->lineno++;
- .
- <<EOF>> {
- BEGIN(INITIAL);
- }
-}
-
-<STRING>{
- [^'"\\\n]+/\n {
- append_string(yytext, yyleng);
- zconflval.string = text;
- return T_WORD_QUOTE;
- }
- [^'"\\\n]+ {
- append_string(yytext, yyleng);
- }
- \\.?/\n {
- append_string(yytext + 1, yyleng - 1);
- zconflval.string = text;
- return T_WORD_QUOTE;
- }
- \\.? {
- append_string(yytext + 1, yyleng - 1);
- }
- \'|\" {
- if (str == yytext[0]) {
- BEGIN(PARAM);
- zconflval.string = text;
- return T_WORD_QUOTE;
- } else
- append_string(yytext, 1);
- }
- \n {
- printf("%s:%d:warning: multi-line strings not supported\n", zconf_curname(), zconf_lineno());
- current_file->lineno++;
- BEGIN(INITIAL);
- return T_EOL;
- }
- <<EOF>> {
- BEGIN(INITIAL);
- }
-}
-
-<HELP>{
- [ \t]+ {
- ts = 0;
- for (i = 0; i < yyleng; i++) {
- if (yytext[i] == '\t')
- ts = (ts & ~7) + 8;
- else
- ts++;
- }
- last_ts = ts;
- if (first_ts) {
- if (ts < first_ts) {
- zconf_endhelp();
- return T_HELPTEXT;
- }
- ts -= first_ts;
- while (ts > 8) {
- append_string(" ", 8);
- ts -= 8;
- }
- append_string(" ", ts);
- }
- }
- [ \t]*\n/[^ \t\n] {
- current_file->lineno++;
- zconf_endhelp();
- return T_HELPTEXT;
- }
- [ \t]*\n {
- current_file->lineno++;
- append_string("\n", 1);
- }
- [^ \t\n].* {
- while (yyleng) {
- if ((yytext[yyleng-1] != ' ') && (yytext[yyleng-1] != '\t'))
- break;
- yyleng--;
- }
- append_string(yytext, yyleng);
- if (!first_ts)
- first_ts = last_ts;
- }
- <<EOF>> {
- zconf_endhelp();
- return T_HELPTEXT;
- }
-}
-
-<<EOF>> {
- if (current_file) {
- zconf_endfile();
- return T_EOL;
- }
- fclose(yyin);
- yyterminate();
-}
-
-%%
-void zconf_starthelp(void)
-{
- new_string();
- last_ts = first_ts = 0;
- BEGIN(HELP);
-}
-
-static void zconf_endhelp(void)
-{
- zconflval.string = text;
- BEGIN(INITIAL);
-}
-
-
-/*
- * Try to open specified file with following names:
- * ./name
- * $(srctree)/name
- * The latter is used when srctree is separate from objtree
- * when compiling the kernel.
- * Return NULL if file is not found.
- */
-FILE *zconf_fopen(const char *name)
-{
- char *env, fullname[PATH_MAX+1];
- FILE *f;
-
- f = fopen(name, "r");
- if (!f && name != NULL && name[0] != '/') {
- env = getenv(SRCTREE);
- if (env) {
- sprintf(fullname, "%s/%s", env, name);
- f = fopen(fullname, "r");
- }
- }
- return f;
-}
-
-void zconf_initscan(const char *name)
-{
- yyin = zconf_fopen(name);
- if (!yyin) {
- printf("can't find file %s\n", name);
- exit(1);
- }
-
- current_buf = malloc(sizeof(*current_buf));
- memset(current_buf, 0, sizeof(*current_buf));
-
- current_file = file_lookup(name);
- current_file->lineno = 1;
-}
-
-void zconf_nextfile(const char *name)
-{
- struct file *iter;
- struct file *file = file_lookup(name);
- struct buffer *buf = malloc(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;
-}
-
-static void zconf_endfile(void)
-{
- struct buffer *parent;
-
- current_file = current_file->parent;
-
- parent = current_buf->parent;
- if (parent) {
- fclose(yyin);
- yy_delete_buffer(YY_CURRENT_BUFFER);
- yy_switch_to_buffer(parent->state);
- }
- free(current_buf);
- current_buf = parent;
-}
-
-int zconf_lineno(void)
-{
- return current_pos.lineno;
-}
-
-const char *zconf_curname(void)
-{
- return current_pos.file ? current_pos.file->name : "<none>";
-}
+++ /dev/null
-/*
- * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
- * Released under the terms of the GNU GPL v2.0.
- */
-
-#ifndef LKC_H
-#define LKC_H
-
-#include "expr.h"
-
-#ifndef KBUILD_NO_NLS
-# include <libintl.h>
-#else
-static inline const char *gettext(const char *txt) { return txt; }
-static inline void textdomain(const char *domainname) {}
-static inline void bindtextdomain(const char *name, const char *dir) {}
-static inline char *bind_textdomain_codeset(const char *dn, char *c) { return c; }
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define P(name,type,arg) extern type name arg
-#include "lkc_proto.h"
-#undef P
-
-#define SRCTREE "srctree"
-
-#ifndef PACKAGE
-#define PACKAGE "linux"
-#endif
-
-#define LOCALEDIR "/usr/share/locale"
-
-#define _(text) gettext(text)
-#define N_(text) (text)
-
-#ifndef CONFIG_
-#define CONFIG_ "CONFIG_"
-#endif
-
-#define TF_COMMAND 0x0001
-#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 {
- int name;
- int token;
- unsigned int flags;
- enum symbol_type stype;
-};
-
-extern int zconfdebug;
-
-int zconfparse(void);
-void zconfdump(FILE *out);
-void zconf_starthelp(void);
-FILE *zconf_fopen(const char *name);
-void zconf_initscan(const char *name);
-void zconf_nextfile(const char *name);
-int zconf_lineno(void);
-const char *zconf_curname(void);
-
-/* confdata.c */
-const char *conf_get_configname(void);
-const char *conf_get_autoconfig_name(void);
-char *conf_get_default_confname(void);
-void sym_set_change_count(int count);
-void sym_add_change_count(int count);
-void conf_set_all_new_symbols(enum conf_def_mode mode);
-
-struct conf_printer {
- 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 */
-void _menu_init(void);
-void menu_warn(struct menu *menu, const char *fmt, ...);
-struct menu *menu_add_menu(void);
-void menu_end_menu(void);
-void menu_add_entry(struct symbol *sym);
-void menu_end_entry(void);
-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_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_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_set_type(int type);
-
-/* util.c */
-struct file *file_lookup(const char *name);
-int file_write_dep(const char *name);
-
-struct gstr {
- size_t len;
- char *s;
- /*
- * when max_width is not zero long lines in string s (if any) get
- * wrapped not to exceed the max_width value
- */
- int max_width;
-};
-struct gstr str_new(void);
-struct gstr str_assign(const char *s);
-void str_free(struct gstr *gs);
-void str_append(struct gstr *gs, const char *s);
-void str_printf(struct gstr *gs, const char *fmt, ...);
-const char *str_get(struct gstr *gs);
-
-/* symbol.c */
-extern struct expr *sym_env_list;
-
-void sym_init(void);
-void sym_clear_all_valid(void);
-void sym_set_all_changed(void);
-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 property *prop_alloc(enum prop_type type, struct symbol *sym);
-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)
-{
- return sym->curr.tri;
-}
-
-
-static inline struct symbol *sym_get_choice_value(struct symbol *sym)
-{
- return (struct symbol *)sym->curr.val;
-}
-
-static inline bool sym_set_choice_value(struct symbol *ch, struct symbol *chval)
-{
- return sym_set_tristate_value(chval, yes);
-}
-
-static inline bool sym_is_choice(struct symbol *sym)
-{
- return sym->flags & SYMBOL_CHOICE ? true : false;
-}
-
-static inline bool sym_is_choice_value(struct symbol *sym)
-{
- return sym->flags & SYMBOL_CHOICEVAL ? true : false;
-}
-
-static inline bool sym_is_optional(struct symbol *sym)
-{
- return sym->flags & SYMBOL_OPTIONAL ? true : false;
-}
-
-static inline bool sym_has_value(struct symbol *sym)
-{
- return sym->flags & SYMBOL_DEF_USER ? true : false;
-}
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* LKC_H */
+++ /dev/null
-#include <stdarg.h>
-
-/* confdata.c */
-P(conf_parse,void,(const char *name));
-P(conf_read,int,(const char *name));
-P(conf_read_simple,int,(const char *name, int));
-P(conf_write_defconfig,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 */
-P(rootmenu,struct 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_root_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));
-P(get_relations_str, struct gstr, (struct symbol **sym_arr));
-P(menu_get_ext_help,void,(struct menu *menu, struct gstr *help));
-
-/* symbol.c */
-P(symbol_hash,struct symbol *,[SYMBOL_HASHSIZE]);
-
-P(sym_lookup,struct symbol *,(const char *name, int flags));
-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_type_name,const char *,(enum symbol_type type));
-P(sym_calc_value,void,(struct symbol *sym));
-P(sym_get_type,enum symbol_type,(struct symbol *sym));
-P(sym_tristate_within_range,bool,(struct symbol *sym,tristate tri));
-P(sym_set_tristate_value,bool,(struct symbol *sym,tristate tri));
-P(sym_toggle_tristate_value,tristate,(struct symbol *sym));
-P(sym_string_valid,bool,(struct symbol *sym, const char *newval));
-P(sym_string_within_range,bool,(struct symbol *sym, const char *str));
-P(sym_set_string_value,bool,(struct symbol *sym, const char *newval));
-P(sym_is_changable,bool,(struct symbol *sym));
-P(sym_get_choice_prop,struct property *,(struct symbol *sym));
-P(sym_get_default_prop,struct property *,(struct symbol *sym));
-P(sym_get_string_value,const char *,(struct symbol *sym));
-
-P(prop_get_type_name,const char *,(enum prop_type type));
-
-/* expr.c */
-P(expr_compare_type,int,(enum expr_type t1, enum expr_type t2));
-P(expr_print,void,(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken));
util.c \
yesno.c
-liblxdialog_a_CFLAGS = -DCURSES_LOC='"${CURSES_LOC}"'
+liblxdialog_a_CPPFLAGS = $(AM_CPPFLAGS) -DCURSES_LOC='"${CURSES_LOC}"'
+++ /dev/null
-#!/bin/sh
-# Check ncurses compatibility
-
-# What library to link
-ldflags()
-{
- for ext in so a dylib ; do
- for lib in ncursesw ncurses curses ; do
- $cc -print-file-name=lib${lib}.${ext} | grep -q /
- if [ $? -eq 0 ]; then
- echo "-l${lib}"
- exit
- fi
- done
- done
- exit 1
-}
-
-# Where is ncurses.h?
-ccflags()
-{
- if [ -f /usr/include/ncurses/ncurses.h ]; then
- echo '-I/usr/include/ncurses -DCURSES_LOC="<ncurses.h>"'
- elif [ -f /usr/include/ncurses/curses.h ]; then
- echo '-I/usr/include/ncurses -DCURSES_LOC="<ncurses/curses.h>"'
- elif [ -f /usr/include/ncursesw/curses.h ]; then
- echo '-I/usr/include/ncursesw -DCURSES_LOC="<ncursesw/curses.h>"'
- elif [ -f /usr/include/ncurses.h ]; then
- echo '-DCURSES_LOC="<ncurses.h>"'
- else
- echo '-DCURSES_LOC="<curses.h>"'
- fi
-}
-
-# Temp file, try to clean up after us
-tmp=.lxdialog.tmp
-trap "rm -f $tmp" 0 1 2 3 15
-
-# Check if we can link to ncurses
-check() {
- $cc -xc - -o $tmp 2>/dev/null <<'EOF'
-#include CURSES_LOC
-main() {}
-EOF
- if [ $? != 0 ]; then
- echo " *** Unable to find the ncurses libraries or the" 1>&2
- echo " *** required header files." 1>&2
- echo " *** 'make menuconfig' requires the ncurses libraries." 1>&2
- echo " *** " 1>&2
- echo " *** Install ncurses (ncurses-devel) and try again." 1>&2
- echo " *** " 1>&2
- exit 1
- fi
-}
-
-usage() {
- printf "Usage: $0 [-check compiler options|-ccflags|-ldflags compiler options]\n"
-}
-
-if [ $# -eq 0 ]; then
- usage
- exit 1
-fi
-
-cc=""
-case "$1" in
- "-check")
- shift
- cc="$@"
- check
- ;;
- "-ccflags")
- ccflags
- ;;
- "-ldflags")
- shift
- cc="$@"
- ldflags
- ;;
- "*")
- usage
- exit 1
- ;;
-esac
+++ /dev/null
-/*
- * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
- * Released under the terms of the GNU GPL v2.0.
- *
- * Introduced single menu mode (show all sub-menus in one large tree).
- * 2002-11-06 Petr Baudis <pasky@ucw.cz>
- *
- * i18n, 2005, Arnaldo Carvalho de Melo <acme@conectiva.com.br>
- */
-
-#include <ctype.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
-#include <signal.h>
-#include <unistd.h>
-#include <locale.h>
-
-#include "lkc.h"
-#include "lxdialog/dialog.h"
-
-static const char mconf_readme[] = N_(
-"Overview\n"
-"--------\n"
-"This interface let you select features and parameters for the build.\n"
-"Features can either be built-in, modularized, or ignored. Parameters\n"
-"must be entered in as decimal or hexadecimal numbers or text.\n"
-"\n"
-"Menu items beginning with following braces represent features that\n"
-" [ ] can be built in or removed\n"
-" < > can be built in, modularized or removed\n"
-" { } can be built in or modularized (selected by other feature)\n"
-" - - are selected by other feature,\n"
-"while *, M or whitespace inside braces means to build in, build as\n"
-"a module or to exclude the feature respectively.\n"
-"\n"
-"To change any of these features, highlight it with the cursor\n"
-"keys and press <Y> to build it in, <M> to make it a module or\n"
-"<N> to removed it. You may also press the <Space Bar> to cycle\n"
-"through the available options (ie. Y->N->M->Y).\n"
-"\n"
-"Some additional keyboard hints:\n"
-"\n"
-"Menus\n"
-"----------\n"
-"o Use the Up/Down arrow keys (cursor keys) to highlight the item\n"
-" you wish to change or submenu wish to select and press <Enter>.\n"
-" Submenus are designated by \"--->\".\n"
-"\n"
-" Shortcut: Press the option's highlighted letter (hotkey).\n"
-" Pressing a hotkey more than once will sequence\n"
-" through all visible items which use that hotkey.\n"
-"\n"
-" You may also use the <PAGE UP> and <PAGE DOWN> keys to scroll\n"
-" unseen options into view.\n"
-"\n"
-"o To exit a menu use the cursor keys to highlight the <Exit> button\n"
-" and press <ENTER>.\n"
-"\n"
-" Shortcut: Press <ESC><ESC> or <E> or <X> if there is no hotkey\n"
-" using those letters. You may press a single <ESC>, but\n"
-" there is a delayed response which you may find annoying.\n"
-"\n"
-" Also, the <TAB> and cursor keys will cycle between <Select>,\n"
-" <Exit> and <Help>.\n"
-"\n"
-"o To get help with an item, use the cursor keys to highlight <Help>\n"
-" and press <ENTER>.\n"
-"\n"
-" Shortcut: Press <H> or <?>.\n"
-"\n"
-"o To toggle the display of hidden options, press <Z>.\n"
-"\n"
-"\n"
-"Radiolists (Choice lists)\n"
-"-----------\n"
-"o Use the cursor keys to select the option you wish to set and press\n"
-" <S> or the <SPACE BAR>.\n"
-"\n"
-" Shortcut: Press the first letter of the option you wish to set then\n"
-" press <S> or <SPACE BAR>.\n"
-"\n"
-"o To see available help for the item, use the cursor keys to highlight\n"
-" <Help> and Press <ENTER>.\n"
-"\n"
-" Shortcut: Press <H> or <?>.\n"
-"\n"
-" Also, the <TAB> and cursor keys will cycle between <Select> and\n"
-" <Help>\n"
-"\n"
-"\n"
-"Data Entry\n"
-"-----------\n"
-"o Enter the requested information and press <ENTER>\n"
-" If you are entering hexadecimal values, it is not necessary to\n"
-" add the '0x' prefix to the entry.\n"
-"\n"
-"o For help, use the <TAB> or cursor keys to highlight the help option\n"
-" and press <ENTER>. You can try <TAB><H> as well.\n"
-"\n"
-"\n"
-"Text Box (Help Window)\n"
-"--------\n"
-"o Use the cursor keys to scroll up/down/left/right. The VI editor\n"
-" keys h,j,k,l function here as do <SPACE BAR> and <B> for those\n"
-" who are familiar with less and lynx.\n"
-"\n"
-"o Press <E>, <X>, <Enter> or <Esc><Esc> to exit.\n"
-"\n"
-"\n"
-"Alternate Configuration Files\n"
-"-----------------------------\n"
-"Menuconfig supports the use of alternate configuration files for\n"
-"those who, for various reasons, find it necessary to switch\n"
-"between different configurations.\n"
-"\n"
-"At the end of the main menu you will find two options. One is\n"
-"for saving the current configuration to a file of your choosing.\n"
-"The other option is for loading a previously saved alternate\n"
-"configuration.\n"
-"\n"
-"Even if you don't use alternate configuration files, but you\n"
-"find during a Menuconfig session that you have completely messed\n"
-"up your settings, you may use the \"Load Alternate...\" option to\n"
-"restore your previously saved settings from \".config\" without\n"
-"restarting Menuconfig.\n"
-"\n"
-"Other information\n"
-"-----------------\n"
-"If you use Menuconfig in an XTERM window make sure you have your\n"
-"$TERM variable set to point to a xterm definition which supports color.\n"
-"Otherwise, Menuconfig will look rather bad. Menuconfig will not\n"
-"display correctly in a RXVT window because rxvt displays only one\n"
-"intensity of color, bright.\n"
-"\n"
-"Menuconfig will display larger menus on screens or xterms which are\n"
-"set to display more than the standard 25 row by 80 column geometry.\n"
-"In order for this to work, the \"stty size\" command must be able to\n"
-"display the screen's current row and column geometry. I STRONGLY\n"
-"RECOMMEND that you make sure you do NOT have the shell variables\n"
-"LINES and COLUMNS exported into your environment. Some distributions\n"
-"export those variables via /etc/profile. Some ncurses programs can\n"
-"become confused when those variables (LINES & COLUMNS) don't reflect\n"
-"the true screen size.\n"
-"\n"
-"Optional personality available\n"
-"------------------------------\n"
-"If you prefer to have all of the options listed in a single menu, rather\n"
-"than the default multimenu hierarchy, run the menuconfig with\n"
-"MENUCONFIG_MODE environment variable set to single_menu. Example:\n"
-"\n"
-"make MENUCONFIG_MODE=single_menu menuconfig\n"
-"\n"
-"<Enter> will then unroll the appropriate category, or enfold it if it\n"
-"is already unrolled.\n"
-"\n"
-"Note that this mode can eventually be a little more CPU expensive\n"
-"(especially with a larger number of unrolled categories) than the\n"
-"default mode.\n"
-"\n"
-"Different color themes available\n"
-"--------------------------------\n"
-"It is possible to select different color themes using the variable\n"
-"MENUCONFIG_COLOR. To select a theme use:\n"
-"\n"
-"make MENUCONFIG_COLOR=<theme> menuconfig\n"
-"\n"
-"Available themes are\n"
-" mono => selects colors suitable for monochrome displays\n"
-" blackbg => selects a color scheme with black background\n"
-" classic => theme with blue background. The classic look\n"
-" bluetitle => a LCD friendly version of classic. (default)\n"
-"\n"),
-menu_instructions[] = N_(
- "Arrow keys navigate the menu. "
- "<Enter> selects submenus --->. "
- "Highlighted letters are hotkeys. "
- "Pressing <Y> includes, <N> excludes, <M> modularizes features. "
- "Press <Esc><Esc> to exit, <?> for Help, </> for Search. "
- "Legend: [*] built-in [ ] excluded <M> module < > module capable"),
-radiolist_instructions[] = N_(
- "Use the arrow keys to navigate this window or "
- "press the hotkey of the item you wish to select "
- "followed by the <SPACE BAR>. "
- "Press <?> for additional information about this option."),
-inputbox_instructions_int[] = N_(
- "Please enter a decimal value. "
- "Fractions will not be accepted. "
- "Use the <TAB> key to move from the input field to the buttons below it."),
-inputbox_instructions_hex[] = N_(
- "Please enter a hexadecimal value. "
- "Use the <TAB> key to move from the input field to the buttons below it."),
-inputbox_instructions_string[] = N_(
- "Please enter a string value. "
- "Use the <TAB> key to move from the input field to the buttons below it."),
-setmod_text[] = N_(
- "This feature depends on another which has been configured as a module.\n"
- "As a result, this feature will be built as a module."),
-load_config_text[] = N_(
- "Enter the name of the configuration file you wish to load. "
- "Accept the name shown to restore the configuration you "
- "last retrieved. Leave blank to abort."),
-load_config_help[] = N_(
- "\n"
- "For various reasons, one may wish to keep several different\n"
- "configurations available on a single machine.\n"
- "\n"
- "If you have saved a previous configuration in a file other than the\n"
- "default one, entering its name here will allow you to modify that\n"
- "configuration.\n"
- "\n"
- "If you are uncertain, then you have probably never used alternate\n"
- "configuration files. You should therefore leave this blank to abort.\n"),
-save_config_text[] = N_(
- "Enter a filename to which this configuration should be saved "
- "as an alternate. Leave blank to abort."),
-save_config_help[] = N_(
- "\n"
- "For various reasons, one may wish to keep different configurations\n"
- "available on a single machine.\n"
- "\n"
- "Entering a file name here will allow you to later retrieve, modify\n"
- "and use the current configuration as an alternate to whatever\n"
- "configuration options you have selected at that time.\n"
- "\n"
- "If you are uncertain what all this means then you should probably\n"
- "leave this blank.\n"),
-search_help[] = N_(
- "\n"
- "Search for symbols and display their relations.\n"
- "Regular expressions are allowed.\n"
- "Example: search for \"^FOO\"\n"
- "Result:\n"
- "-----------------------------------------------------------------\n"
- "Symbol: FOO [=m]\n"
- "Prompt: Foo bus is used to drive the bar HW\n"
- "Defined at drivers/pci/Kconfig:47\n"
- "Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n"
- "Location:\n"
- " -> Bus options (PCI, PCMCIA, EISA, MCA, ISA)\n"
- " -> PCI support (PCI [=y])\n"
- " -> PCI access mode (<choice> [=y])\n"
- "Selects: LIBCRC32\n"
- "Selected by: BAR\n"
- "-----------------------------------------------------------------\n"
- "o The line 'Prompt:' shows the text used in the menu structure for\n"
- " this symbol\n"
- "o The 'Defined at' line tell at what file / line number the symbol\n"
- " is defined\n"
- "o The 'Depends on:' line tell what symbols needs to be defined for\n"
- " this symbol to be visible in the menu (selectable)\n"
- "o The 'Location:' lines tell where in the menu structure this symbol\n"
- " is located\n"
- " A location followed by a [=y] indicate that this is a selectable\n"
- " menu item - and current value is displayed inside brackets.\n"
- "o The 'Selects:' line tell what symbol will be automatically\n"
- " selected if this symbol is selected (y or m)\n"
- "o The 'Selected by' line tell what symbol has selected this symbol\n"
- "\n"
- "Only relevant lines are shown.\n"
- "\n\n"
- "Search examples:\n"
- "Examples: USB => find all symbols containing USB\n"
- " ^USB => find all symbols starting with USB\n"
- " USB$ => find all symbols ending with USB\n"
- "\n");
-
-static int indent;
-static struct menu *current_menu;
-static int child_count;
-static int single_menu_mode;
-static int show_all_options;
-static int saved_x, saved_y;
-
-static void conf(struct menu *menu);
-static void conf_choice(struct menu *menu);
-static void conf_string(struct menu *menu);
-static void conf_load(void);
-static void conf_save(void);
-static void show_textbox(const char *title, const char *text, int r, int c);
-static void show_helptext(const char *title, const char *text);
-static void show_help(struct menu *menu);
-
-static char filename[PATH_MAX+1];
-static void set_config_filename(const char *config_filename)
-{
- static char menu_backtitle[PATH_MAX+128];
- int size;
-
- size = snprintf(menu_backtitle, sizeof(menu_backtitle),
- "%s - %s", config_filename, rootmenu.prompt->text);
- if (size >= sizeof(menu_backtitle))
- menu_backtitle[sizeof(menu_backtitle)-1] = '\0';
- set_dialog_backtitle(menu_backtitle);
-
- size = snprintf(filename, sizeof(filename), "%s", config_filename);
- if (size >= sizeof(filename))
- filename[sizeof(filename)-1] = '\0';
-}
-
-
-static void search_conf(void)
-{
- struct symbol **sym_arr;
- struct gstr res;
- char *dialog_input;
- int dres;
-again:
- dialog_clear();
- dres = dialog_inputbox(_("Search Configuration Parameter"),
- _("Enter " CONFIG_ " (sub)string to search for "
- "(with or without \"" CONFIG_ "\")"),
- 10, 75, "");
- switch (dres) {
- case 0:
- break;
- case 1:
- show_helptext(_("Search Configuration"), search_help);
- goto again;
- default:
- return;
- }
-
- /* strip the prefix if necessary */
- dialog_input = dialog_input_result;
- if (strncasecmp(dialog_input_result, CONFIG_, strlen(CONFIG_)) == 0)
- dialog_input += strlen(CONFIG_);
-
- sym_arr = sym_re_search(dialog_input);
- res = get_relations_str(sym_arr);
- free(sym_arr);
- show_textbox(_("Search Results"), str_get(&res), 0, 0);
- str_free(&res);
-}
-
-static void build_conf(struct menu *menu)
-{
- struct symbol *sym;
- struct property *prop;
- struct menu *child;
- int type, tmp, doint = 2;
- tristate val;
- char ch;
- bool visible;
-
- /*
- * note: menu_is_visible() has side effect that it will
- * recalc the value of the symbol.
- */
- visible = menu_is_visible(menu);
- if (show_all_options && !menu_has_prompt(menu))
- return;
- else if (!show_all_options && !visible)
- return;
-
- sym = menu->sym;
- prop = menu->prompt;
- if (!sym) {
- if (prop && menu != current_menu) {
- const char *prompt = menu_get_prompt(menu);
- switch (prop->type) {
- case P_MENU:
- child_count++;
- prompt = _(prompt);
- if (single_menu_mode) {
- item_make("%s%*c%s",
- menu->data ? "-->" : "++>",
- indent + 1, ' ', prompt);
- } else
- item_make(" %*c%s --->", indent + 1, ' ', prompt);
-
- item_set_tag('m');
- item_set_data(menu);
- if (single_menu_mode && menu->data)
- goto conf_childs;
- return;
- case P_COMMENT:
- if (prompt) {
- child_count++;
- item_make(" %*c*** %s ***", indent + 1, ' ', _(prompt));
- item_set_tag(':');
- item_set_data(menu);
- }
- break;
- default:
- if (prompt) {
- child_count++;
- item_make("---%*c%s", indent + 1, ' ', _(prompt));
- item_set_tag(':');
- item_set_data(menu);
- }
- }
- } else
- doint = 0;
- goto conf_childs;
- }
-
- type = sym_get_type(sym);
- if (sym_is_choice(sym)) {
- struct symbol *def_sym = sym_get_choice_value(sym);
- struct menu *def_menu = NULL;
-
- child_count++;
- for (child = menu->list; child; child = child->next) {
- if (menu_is_visible(child) && child->sym == def_sym)
- def_menu = child;
- }
-
- val = sym_get_tristate_value(sym);
- if (sym_is_changable(sym)) {
- switch (type) {
- case S_BOOLEAN:
- item_make("[%c]", val == no ? ' ' : '*');
- break;
- case S_TRISTATE:
- switch (val) {
- case yes: ch = '*'; break;
- case mod: ch = 'M'; break;
- default: ch = ' '; break;
- }
- item_make("<%c>", ch);
- break;
- }
- item_set_tag('t');
- item_set_data(menu);
- } else {
- item_make(" ");
- item_set_tag(def_menu ? 't' : ':');
- item_set_data(menu);
- }
-
- item_add_str("%*c%s", indent + 1, ' ', _(menu_get_prompt(menu)));
- if (val == yes) {
- if (def_menu) {
- item_add_str(" (%s)", _(menu_get_prompt(def_menu)));
- item_add_str(" --->");
- if (def_menu->list) {
- indent += 2;
- build_conf(def_menu);
- indent -= 2;
- }
- }
- return;
- }
- } else {
- if (menu == current_menu) {
- item_make("---%*c%s", indent + 1, ' ', _(menu_get_prompt(menu)));
- item_set_tag(':');
- item_set_data(menu);
- goto conf_childs;
- }
- child_count++;
- val = sym_get_tristate_value(sym);
- if (sym_is_choice_value(sym) && val == yes) {
- item_make(" ");
- item_set_tag(':');
- item_set_data(menu);
- } else {
- switch (type) {
- case S_BOOLEAN:
- if (sym_is_changable(sym))
- item_make("[%c]", val == no ? ' ' : '*');
- else
- item_make("-%c-", val == no ? ' ' : '*');
- item_set_tag('t');
- item_set_data(menu);
- break;
- case S_TRISTATE:
- switch (val) {
- case yes: ch = '*'; break;
- case mod: ch = 'M'; break;
- default: ch = ' '; break;
- }
- if (sym_is_changable(sym)) {
- if (sym->rev_dep.tri == mod)
- item_make("{%c}", ch);
- else
- item_make("<%c>", ch);
- } else
- item_make("-%c-", ch);
- item_set_tag('t');
- item_set_data(menu);
- break;
- default:
- tmp = 2 + strlen(sym_get_string_value(sym)); /* () = 2 */
- item_make("(%s)", sym_get_string_value(sym));
- tmp = indent - tmp + 4;
- if (tmp < 0)
- tmp = 0;
- item_add_str("%*c%s%s", tmp, ' ', _(menu_get_prompt(menu)),
- (sym_has_value(sym) || !sym_is_changable(sym)) ?
- "" : _(" (NEW)"));
- item_set_tag('s');
- item_set_data(menu);
- goto conf_childs;
- }
- }
- item_add_str("%*c%s%s", indent + 1, ' ', _(menu_get_prompt(menu)),
- (sym_has_value(sym) || !sym_is_changable(sym)) ?
- "" : _(" (NEW)"));
- if (menu->prompt->type == P_MENU) {
- item_add_str(" --->");
- return;
- }
- }
-
-conf_childs:
- indent += doint;
- for (child = menu->list; child; child = child->next)
- build_conf(child);
- indent -= doint;
-}
-
-static void conf(struct menu *menu)
-{
- struct menu *submenu;
- const char *prompt = menu_get_prompt(menu);
- struct symbol *sym;
- struct menu *active_menu = NULL;
- int res;
- int s_scroll = 0;
-
- while (1) {
- item_reset();
- current_menu = menu;
- build_conf(menu);
- if (!child_count)
- break;
- if (menu == &rootmenu) {
- item_make("--- ");
- item_set_tag(':');
- item_make(_(" Load an Alternate Configuration File"));
- item_set_tag('L');
- item_make(_(" Save an Alternate Configuration File"));
- item_set_tag('S');
- }
- dialog_clear();
- res = dialog_menu(prompt ? _(prompt) : _("Main Menu"),
- _(menu_instructions),
- active_menu, &s_scroll);
- if (res == 1 || res == KEY_ESC || res == -ERRDISPLAYTOOSMALL)
- break;
- if (!item_activate_selected())
- continue;
- if (!item_tag())
- continue;
-
- submenu = item_data();
- active_menu = item_data();
- if (submenu)
- sym = submenu->sym;
- else
- sym = NULL;
-
- switch (res) {
- case 0:
- switch (item_tag()) {
- case 'm':
- if (single_menu_mode)
- submenu->data = (void *) (long) !submenu->data;
- else
- conf(submenu);
- break;
- case 't':
- if (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)
- conf_choice(submenu);
- else if (submenu->prompt->type == P_MENU)
- conf(submenu);
- break;
- case 's':
- conf_string(submenu);
- break;
- case 'L':
- conf_load();
- break;
- case 'S':
- conf_save();
- break;
- }
- break;
- case 2:
- if (sym)
- show_help(submenu);
- else
- show_helptext(_("README"), _(mconf_readme));
- break;
- case 3:
- if (item_is_tag('t')) {
- if (sym_set_tristate_value(sym, yes))
- break;
- if (sym_set_tristate_value(sym, mod))
- show_textbox(NULL, setmod_text, 6, 74);
- }
- break;
- case 4:
- if (item_is_tag('t'))
- sym_set_tristate_value(sym, no);
- break;
- case 5:
- if (item_is_tag('t'))
- sym_set_tristate_value(sym, mod);
- break;
- case 6:
- if (item_is_tag('t'))
- sym_toggle_tristate_value(sym);
- else if (item_is_tag('m'))
- conf(submenu);
- break;
- case 7:
- search_conf();
- break;
- case 8:
- show_all_options = !show_all_options;
- break;
- }
- }
-}
-
-static void show_textbox(const char *title, const char *text, int r, int c)
-{
- dialog_clear();
- dialog_textbox(title, text, r, c);
-}
-
-static void show_helptext(const char *title, const char *text)
-{
- show_textbox(title, text, 0, 0);
-}
-
-static void show_help(struct menu *menu)
-{
- struct gstr help = str_new();
-
- help.max_width = getmaxx(stdscr) - 10;
- menu_get_ext_help(menu, &help);
-
- show_helptext(_(menu_get_prompt(menu)), str_get(&help));
- str_free(&help);
-}
-
-static void conf_choice(struct menu *menu)
-{
- const char *prompt = _(menu_get_prompt(menu));
- struct menu *child;
- struct symbol *active;
-
- active = sym_get_choice_value(menu->sym);
- while (1) {
- int res;
- int selected;
- item_reset();
-
- current_menu = menu;
- for (child = menu->list; child; child = child->next) {
- if (!menu_is_visible(child))
- continue;
- if (child->sym)
- item_make("%s", _(menu_get_prompt(child)));
- else {
- item_make("*** %s ***", _(menu_get_prompt(child)));
- item_set_tag(':');
- }
- item_set_data(child);
- if (child->sym == active)
- item_set_selected(1);
- if (child->sym == sym_get_choice_value(menu->sym))
- item_set_tag('X');
- }
- dialog_clear();
- res = dialog_checklist(prompt ? _(prompt) : _("Main Menu"),
- _(radiolist_instructions),
- 15, 70, 6);
- selected = item_activate_selected();
- switch (res) {
- case 0:
- if (selected) {
- child = item_data();
- if (!child->sym)
- break;
-
- sym_set_tristate_value(child->sym, yes);
- }
- return;
- case 1:
- if (selected) {
- child = item_data();
- show_help(child);
- active = child->sym;
- } else
- show_help(menu);
- break;
- case KEY_ESC:
- return;
- case -ERRDISPLAYTOOSMALL:
- return;
- }
- }
-}
-
-static void conf_string(struct menu *menu)
-{
- const char *prompt = menu_get_prompt(menu);
-
- while (1) {
- int res;
- const char *heading;
-
- switch (sym_get_type(menu->sym)) {
- case S_INT:
- heading = _(inputbox_instructions_int);
- break;
- case S_HEX:
- heading = _(inputbox_instructions_hex);
- break;
- case S_STRING:
- heading = _(inputbox_instructions_string);
- break;
- default:
- heading = _("Internal mconf error!");
- }
- dialog_clear();
- res = dialog_inputbox(prompt ? _(prompt) : _("Main Menu"),
- heading, 10, 75,
- sym_get_string_value(menu->sym));
- switch (res) {
- case 0:
- if (sym_set_string_value(menu->sym, dialog_input_result))
- return;
- show_textbox(NULL, _("You have made an invalid entry."), 5, 43);
- break;
- case 1:
- show_help(menu);
- break;
- case KEY_ESC:
- return;
- }
- }
-}
-
-static void conf_load(void)
-{
-
- while (1) {
- int res;
- dialog_clear();
- res = dialog_inputbox(NULL, load_config_text,
- 11, 55, filename);
- switch(res) {
- case 0:
- if (!dialog_input_result[0])
- return;
- if (!conf_read(dialog_input_result)) {
- set_config_filename(dialog_input_result);
- sym_set_change_count(1);
- return;
- }
- show_textbox(NULL, _("File does not exist!"), 5, 38);
- break;
- case 1:
- show_helptext(_("Load Alternate Configuration"), load_config_help);
- break;
- case KEY_ESC:
- return;
- }
- }
-}
-
-static void conf_save(void)
-{
- while (1) {
- int res;
- dialog_clear();
- res = dialog_inputbox(NULL, save_config_text,
- 11, 55, filename);
- switch(res) {
- case 0:
- if (!dialog_input_result[0])
- return;
- if (!conf_write(dialog_input_result)) {
- set_config_filename(dialog_input_result);
- return;
- }
- show_textbox(NULL, _("Can't create file! Probably a nonexistent directory."), 5, 60);
- break;
- case 1:
- show_helptext(_("Save Alternate Configuration"), save_config_help);
- break;
- case KEY_ESC:
- return;
- }
- }
-}
-
-static int handle_exit(void)
-{
- int res;
-
- dialog_clear();
- if (conf_get_changed())
- res = dialog_yesno(NULL,
- _("Do you wish to save your new configuration ?\n"
- "<ESC><ESC> to continue."),
- 6, 60);
- else
- res = -1;
-
- end_dialog(saved_x, saved_y);
-
- switch (res) {
- case 0:
- if (conf_write(filename)) {
- fprintf(stderr, _("\n\n"
- "Error while writing of the configuration.\n"
- "Your configuration changes were NOT saved."
- "\n\n"));
- return 1;
- }
- /* fall through */
- case -1:
- printf(_("\n\n"
- "*** End of the configuration.\n"
- "*** Execute 'make' to start the build or try 'make help'."
- "\n\n"));
- res = 0;
- break;
- default:
- fprintf(stderr, _("\n\n"
- "Your configuration changes were NOT saved."
- "\n\n"));
- if (res != KEY_ESC)
- res = 0;
- }
-
- return res;
-}
-
-static void sig_handler(int signo)
-{
- exit(handle_exit());
-}
-
-int main(int ac, char **av)
-{
- char *mode;
- int res;
-
- setlocale(LC_ALL, "");
- bindtextdomain(PACKAGE, LOCALEDIR);
- textdomain(PACKAGE);
-
- signal(SIGINT, sig_handler);
-
- conf_parse(av[1]);
- conf_read(NULL);
-
- mode = getenv("MENUCONFIG_MODE");
- if (mode) {
- if (!strcasecmp(mode, "single_menu"))
- single_menu_mode = 1;
- }
-
- initscr();
-
- getyx(stdscr, saved_y, saved_x);
- if (init_dialog(NULL)) {
- fprintf(stderr, N_("Your display is too small to run Menuconfig!\n"));
- fprintf(stderr, N_("It must be at least 19 lines by 80 columns.\n"));
- return 1;
- }
-
- set_config_filename(conf_get_configname());
- do {
- conf(&rootmenu);
- res = handle_exit();
- } while (res == KEY_ESC);
-
- return res;
-}
-
+++ /dev/null
-/*
- * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
- * Released under the terms of the GNU GPL v2.0.
- */
-
-#include <ctype.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "lkc.h"
-
-static const char nohelp_text[] = "There is no help available for this option.";
-
-struct menu rootmenu;
-static struct menu **last_entry_ptr;
-
-struct file *file_list;
-struct file *current_file;
-
-void menu_warn(struct menu *menu, const char *fmt, ...)
-{
- va_list ap;
- va_start(ap, fmt);
- fprintf(stderr, "%s:%d:warning: ", menu->file->name, menu->lineno);
- vfprintf(stderr, fmt, ap);
- fprintf(stderr, "\n");
- va_end(ap);
-}
-
-static void prop_warn(struct property *prop, const char *fmt, ...)
-{
- va_list ap;
- va_start(ap, fmt);
- fprintf(stderr, "%s:%d:warning: ", prop->file->name, prop->lineno);
- vfprintf(stderr, fmt, ap);
- fprintf(stderr, "\n");
- va_end(ap);
-}
-
-void _menu_init(void)
-{
- current_entry = current_menu = &rootmenu;
- last_entry_ptr = &rootmenu.list;
-}
-
-void menu_add_entry(struct symbol *sym)
-{
- struct menu *menu;
-
- menu = malloc(sizeof(*menu));
- memset(menu, 0, sizeof(*menu));
- menu->sym = sym;
- menu->parent = current_menu;
- menu->file = current_file;
- menu->lineno = zconf_lineno();
-
- *last_entry_ptr = menu;
- last_entry_ptr = &menu->next;
- current_entry = menu;
- if (sym)
- menu_add_symbol(P_SYMBOL, sym, NULL);
-}
-
-void menu_end_entry(void)
-{
-}
-
-struct menu *menu_add_menu(void)
-{
- menu_end_entry();
- last_entry_ptr = ¤t_entry->list;
- return current_menu = current_entry;
-}
-
-void menu_end_menu(void)
-{
- last_entry_ptr = ¤t_menu->next;
- 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)
-{
- current_entry->dep = expr_alloc_and(current_entry->dep, menu_check_dep(dep));
-}
-
-void menu_set_type(int type)
-{
- struct symbol *sym = current_entry->sym;
-
- if (sym->type == type)
- return;
- if (sym->type == S_UNKNOWN) {
- sym->type = type;
- return;
- }
- menu_warn(current_entry, "type of '%s' redefined from '%s' to '%s'",
- sym->name ? sym->name : "<choice>",
- sym_type_name(sym->type), sym_type_name(type));
-}
-
-struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep)
-{
- struct property *prop = prop_alloc(type, current_entry->sym);
-
- prop->menu = current_entry;
- prop->expr = expr;
- prop->visible.expr = menu_check_dep(dep);
-
- if (prompt) {
- if (isspace(*prompt)) {
- 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;
- }
- prop->text = prompt;
-
- return prop;
-}
-
-struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *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)
-{
- menu_add_prop(type, NULL, expr, dep);
-}
-
-void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep)
-{
- menu_add_prop(type, NULL, expr_alloc_symbol(sym), dep);
-}
-
-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 ||
- (sym2->type == S_UNKNOWN && sym_string_valid(sym, sym2->name));
-}
-
-static void sym_check_prop(struct symbol *sym)
-{
- struct property *prop;
- struct symbol *sym2;
- for (prop = sym->prop; prop; prop = prop->next) {
- switch (prop->type) {
- case P_DEFAULT:
- if ((sym->type == S_STRING || sym->type == S_INT || sym->type == S_HEX) &&
- prop->expr->type != E_SYMBOL)
- prop_warn(prop,
- "default for config symbol '%s'"
- " 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;
- case P_SELECT:
- sym2 = prop_get_symbol(prop);
- if (sym->type != S_BOOLEAN && sym->type != S_TRISTATE)
- prop_warn(prop,
- "config symbol '%s' uses select, but is "
- "not boolean or tristate", sym->name);
- else if (sym2->type != S_UNKNOWN &&
- sym2->type != S_BOOLEAN &&
- sym2->type != S_TRISTATE)
- prop_warn(prop,
- "'%s' has wrong type. 'select' only "
- "accept arguments of boolean and "
- "tristate type", sym2->name);
- break;
- case P_RANGE:
- if (sym->type != S_INT && sym->type != S_HEX)
- prop_warn(prop, "range is only allowed "
- "for int or hex symbols");
- if (!menu_validate_number(sym, prop->expr->left.sym) ||
- !menu_validate_number(sym, prop->expr->right.sym))
- prop_warn(prop, "range is invalid");
- break;
- default:
- ;
- }
- }
-}
-
-void menu_finalize(struct menu *parent)
-{
- struct menu *menu, *last_menu;
- struct symbol *sym;
- struct property *prop;
- struct expr *parentdep, *basedep, *dep, *dep2, **ep;
-
- sym = parent->sym;
- if (parent->list) {
- if (sym && sym_is_choice(sym)) {
- if (sym->type == S_UNKNOWN) {
- /* find the first choice value to find out choice type */
- current_entry = parent;
- for (menu = parent->list; menu; menu = menu->next) {
- if (menu->sym && menu->sym->type != S_UNKNOWN) {
- menu_set_type(menu->sym->type);
- 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);
- } else if (parent->prompt)
- parentdep = parent->prompt->visible.expr;
- else
- parentdep = parent->dep;
-
- for (menu = parent->list; menu; menu = menu->next) {
- basedep = expr_transform(menu->dep);
- basedep = expr_alloc_and(expr_copy(parentdep), basedep);
- basedep = expr_eliminate_dups(basedep);
- menu->dep = basedep;
- if (menu->sym)
- prop = menu->sym->prop;
- else
- prop = menu->prompt;
- for (; prop; prop = prop->next) {
- if (prop->menu != menu)
- continue;
- dep = expr_transform(prop->visible.expr);
- dep = expr_alloc_and(expr_copy(basedep), dep);
- dep = expr_eliminate_dups(dep);
- if (menu->sym && menu->sym->type != S_TRISTATE)
- dep = expr_trans_bool(dep);
- prop->visible.expr = dep;
- if (prop->type == P_SELECT) {
- struct symbol *es = prop_get_symbol(prop);
- es->rev_dep.expr = expr_alloc_or(es->rev_dep.expr,
- expr_alloc_and(expr_alloc_symbol(menu->sym), expr_copy(dep)));
- }
- }
- }
- for (menu = parent->list; menu; menu = menu->next)
- menu_finalize(menu);
- } else if (sym) {
- basedep = parent->prompt ? parent->prompt->visible.expr : NULL;
- basedep = expr_trans_compare(basedep, E_UNEQUAL, &symbol_no);
- basedep = expr_eliminate_dups(expr_transform(basedep));
- last_menu = NULL;
- for (menu = parent->next; menu; menu = menu->next) {
- dep = menu->prompt ? menu->prompt->visible.expr : menu->dep;
- if (!expr_contains_symbol(dep, sym))
- break;
- if (expr_depends_symbol(dep, sym))
- goto next;
- dep = expr_trans_compare(dep, E_UNEQUAL, &symbol_no);
- dep = expr_eliminate_dups(expr_transform(dep));
- dep2 = expr_copy(basedep);
- expr_eliminate_eq(&dep, &dep2);
- expr_free(dep);
- if (!expr_is_yes(dep2)) {
- expr_free(dep2);
- break;
- }
- expr_free(dep2);
- next:
- menu_finalize(menu);
- menu->parent = parent;
- last_menu = menu;
- }
- if (last_menu) {
- parent->list = parent->next;
- parent->next = last_menu->next;
- 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) {
- if (sym && sym_is_choice(sym) &&
- menu->sym && !sym_is_choice_value(menu->sym)) {
- current_entry = menu;
- menu->sym->flags |= SYMBOL_CHOICEVAL;
- if (!menu->prompt)
- menu_warn(menu, "choice value must have a prompt");
- for (prop = menu->sym->prop; prop; prop = prop->next) {
- if (prop->type == P_DEFAULT)
- prop_warn(prop, "defaults for choice "
- "values not supported");
- 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);
- }
- }
- menu_add_symbol(P_CHOICE, sym, NULL);
- prop = sym_get_choice_prop(sym);
- for (ep = &prop->expr; *ep; ep = &(*ep)->left.expr)
- ;
- *ep = expr_alloc_one(E_LIST, NULL);
- (*ep)->right.sym = menu->sym;
- }
- if (menu->list && (!menu->prompt || !menu->prompt->text)) {
- for (last_menu = menu->list; ; last_menu = last_menu->next) {
- last_menu->parent = parent;
- if (!last_menu->next)
- break;
- }
- last_menu->next = menu->next;
- menu->next = menu->list;
- menu->list = NULL;
- }
- }
-
- if (sym && !(sym->flags & SYMBOL_WARNED)) {
- if (sym->type == S_UNKNOWN)
- menu_warn(parent, "config symbol defined without type");
-
- if (sym_is_choice(sym) && !parent->prompt)
- menu_warn(parent, "choice must have a prompt");
-
- /* Check properties connected to this symbol */
- sym_check_prop(sym);
- sym->flags |= SYMBOL_WARNED;
- }
-
- if (sym && !sym_is_optional(sym) && parent->prompt) {
- sym->rev_dep.expr = expr_alloc_or(sym->rev_dep.expr,
- expr_alloc_and(parent->prompt->visible.expr,
- expr_alloc_symbol(&symbol_mod)));
- }
-}
-
-bool menu_has_prompt(struct menu *menu)
-{
- if (!menu->prompt)
- return false;
- return true;
-}
-
-bool menu_is_visible(struct menu *menu)
-{
- struct menu *child;
- struct symbol *sym;
- tristate visible;
-
- if (!menu->prompt)
- return false;
-
- if (menu->visibility) {
- if (expr_calc_value(menu->visibility) == no)
- return no;
- }
-
- sym = menu->sym;
- if (sym) {
- sym_calc_value(sym);
- visible = menu->prompt->visible.tri;
- } else
- visible = menu->prompt->visible.tri = expr_calc_value(menu->prompt->visible.expr);
-
- if (visible != no)
- return true;
-
- if (!sym || sym_get_tristate_value(menu->sym) == no)
- return false;
-
- for (child = menu->list; child; child = child->next) {
- if (menu_is_visible(child)) {
- if (sym)
- sym->flags |= SYMBOL_DEF_USER;
- return true;
- }
- }
-
- return false;
-}
-
-const char *menu_get_prompt(struct menu *menu)
-{
- if (menu->prompt)
- return menu->prompt->text;
- else if (menu->sym)
- return menu->sym->name;
- return NULL;
-}
-
-struct menu *menu_get_root_menu(struct menu *menu)
-{
- return &rootmenu;
-}
-
-struct menu *menu_get_parent_menu(struct menu *menu)
-{
- enum prop_type type;
-
- for (; menu != &rootmenu; menu = menu->parent) {
- type = menu->prompt ? menu->prompt->type : 0;
- if (type == P_MENU)
- break;
- }
- 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)
-{
- int i, j;
- struct menu *submenu[8], *menu;
-
- 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)
- submenu[i++] = menu;
- if (i > 0) {
- str_printf(r, _(" Location:\n"));
- for (j = 4; --i >= 0; j += 2) {
- menu = submenu[i];
- 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");
- }
- }
-}
-
-void get_symbol_str(struct gstr *r, struct symbol *sym)
-{
- 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);
- 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 symbol *sym;
- struct gstr res = str_new();
- int i;
-
- for (i = 0; sym_arr && (sym = sym_arr[i]); i++)
- get_symbol_str(&res, sym);
- 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);
-}
+++ /dev/null
-#!/bin/sh
-# merge_config.sh - Takes a list of config fragment values, and merges
-# them one by one. Provides warnings on overridden values, and specified
-# values that did not make it to the resulting .config file (due to missed
-# dependencies or config symbol removal).
-#
-# Portions reused from kconf_check and generate_cfg:
-# http://git.yoctoproject.org/cgit/cgit.cgi/yocto-kernel-tools/tree/tools/kconf_check
-# http://git.yoctoproject.org/cgit/cgit.cgi/yocto-kernel-tools/tree/tools/generate_cfg
-#
-# Copyright (c) 2009-2010 Wind River Systems, Inc.
-# Copyright 2011 Linaro
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# 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.
-
-clean_up() {
- rm -f $TMP_FILE
- exit
-}
-trap clean_up HUP INT TERM
-
-usage() {
- echo "Usage: $0 [OPTIONS] [CONFIG [...]]"
- echo " -h display this help text"
- echo " -m only merge the fragments, do not execute the make command"
- echo " -n use allnoconfig instead of alldefconfig"
-}
-
-MAKE=true
-ALLTARGET=alldefconfig
-
-while true; do
- case $1 in
- "-n")
- ALLTARGET=allnoconfig
- shift
- continue
- ;;
- "-m")
- MAKE=false
- shift
- continue
- ;;
- "-h")
- usage
- exit
- ;;
- *)
- break
- ;;
- esac
-done
-
-
-
-MERGE_LIST=$*
-SED_CONFIG_EXP="s/^\(# \)\{0,1\}\(CONFIG_[a-zA-Z0-9_]*\)[= ].*/\2/p"
-TMP_FILE=$(mktemp ./.tmp.config.XXXXXXXXXX)
-
-# Merge files, printing warnings on overrided values
-for MERGE_FILE in $MERGE_LIST ; do
- echo "Merging $MERGE_FILE"
- CFG_LIST=$(sed -n "$SED_CONFIG_EXP" $MERGE_FILE)
-
- for CFG in $CFG_LIST ; do
- grep -q -w $CFG $TMP_FILE
- if [ $? -eq 0 ] ; then
- PREV_VAL=$(grep -w $CFG $TMP_FILE)
- NEW_VAL=$(grep -w $CFG $MERGE_FILE)
- if [ "x$PREV_VAL" != "x$NEW_VAL" ] ; then
- echo Value of $CFG is redefined by fragment $MERGE_FILE:
- echo Previous value: $PREV_VAL
- echo New value: $NEW_VAL
- echo
- fi
- sed -i "/$CFG[ =]/d" $TMP_FILE
- fi
- done
- cat $MERGE_FILE >> $TMP_FILE
-done
-
-if [ "$MAKE" = "false" ]; then
- cp $TMP_FILE .config
- echo "#"
- echo "# merged configuration written to .config (needs make)"
- echo "#"
- clean_up
- exit
-fi
-
-# Use the merged file as the starting point for:
-# alldefconfig: Fills in any missing symbols with Kconfig default
-# allnoconfig: Fills in any missing symbols with # CONFIG_* is not set
-make KCONFIG_ALLCONFIG=$TMP_FILE $ALLTARGET
-
-
-# Check all specified config values took (might have missed-dependency issues)
-for CFG in $(sed -n "$SED_CONFIG_EXP" $TMP_FILE); do
-
- REQUESTED_VAL=$(grep -w -e "$CFG" $TMP_FILE)
- ACTUAL_VAL=$(grep -w -e "$CFG" .config)
- if [ "x$REQUESTED_VAL" != "x$ACTUAL_VAL" ] ; then
- echo "Value requested for $CFG not in final .config"
- echo "Requested value: $REQUESTED_VAL"
- echo "Actual value: $ACTUAL_VAL"
- echo ""
- fi
-done
-
-clean_up
--- /dev/null
+/*
+ * Arnaldo Carvalho de Melo <acme@conectiva.com.br>, 2005
+ *
+ * Released under the terms of the GNU GPL v2.0
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "lkc.h"
+
+static char *escape(const char* text, char *bf, int len)
+{
+ char *bfp = bf;
+ int multiline = strchr(text, '\n') != NULL;
+ int eol = 0;
+ int textlen = strlen(text);
+
+ if ((textlen > 0) && (text[textlen-1] == '\n'))
+ eol = 1;
+
+ *bfp++ = '"';
+ --len;
+
+ if (multiline) {
+ *bfp++ = '"';
+ *bfp++ = '\n';
+ *bfp++ = '"';
+ len -= 3;
+ }
+
+ while (*text != '\0' && len > 1) {
+ if (*text == '"')
+ *bfp++ = '\\';
+ else if (*text == '\n') {
+ *bfp++ = '\\';
+ *bfp++ = 'n';
+ *bfp++ = '"';
+ *bfp++ = '\n';
+ *bfp++ = '"';
+ len -= 5;
+ ++text;
+ goto next;
+ }
+ else if (*text == '\\') {
+ *bfp++ = '\\';
+ len--;
+ }
+ *bfp++ = *text++;
+next:
+ --len;
+ }
+
+ if (multiline && eol)
+ bfp -= 3;
+
+ *bfp++ = '"';
+ *bfp = '\0';
+
+ return bf;
+}
+
+struct file_line {
+ struct file_line *next;
+ const char *file;
+ int lineno;
+};
+
+static struct file_line *file_line__new(const char *file, int lineno)
+{
+ struct file_line *self = malloc(sizeof(*self));
+
+ if (self == NULL)
+ goto out;
+
+ self->file = file;
+ self->lineno = lineno;
+ self->next = NULL;
+out:
+ return self;
+}
+
+struct message {
+ const char *msg;
+ const char *option;
+ struct message *next;
+ struct file_line *files;
+};
+
+static struct message *message__list;
+
+static struct message *message__new(const char *msg, char *option,
+ const char *file, int lineno)
+{
+ struct message *self = malloc(sizeof(*self));
+
+ if (self == NULL)
+ goto out;
+
+ self->files = file_line__new(file, lineno);
+ if (self->files == NULL)
+ goto out_fail;
+
+ self->msg = strdup(msg);
+ if (self->msg == NULL)
+ goto out_fail_msg;
+
+ self->option = option;
+ self->next = NULL;
+out:
+ return self;
+out_fail_msg:
+ free(self->files);
+out_fail:
+ free(self);
+ self = NULL;
+ goto out;
+}
+
+static struct message *mesage__find(const char *msg)
+{
+ struct message *m = message__list;
+
+ while (m != NULL) {
+ if (strcmp(m->msg, msg) == 0)
+ break;
+ m = m->next;
+ }
+
+ return m;
+}
+
+static int message__add_file_line(struct message *self, const char *file,
+ int lineno)
+{
+ int rc = -1;
+ struct file_line *fl = file_line__new(file, lineno);
+
+ if (fl == NULL)
+ goto out;
+
+ fl->next = self->files;
+ self->files = fl;
+ rc = 0;
+out:
+ return rc;
+}
+
+static int message__add(const char *msg, char *option, const char *file,
+ int lineno)
+{
+ int rc = 0;
+ char bf[16384];
+ char *escaped = escape(msg, bf, sizeof(bf));
+ struct message *m = mesage__find(escaped);
+
+ if (m != NULL)
+ rc = message__add_file_line(m, file, lineno);
+ else {
+ m = message__new(escaped, option, file, lineno);
+
+ if (m != NULL) {
+ m->next = message__list;
+ message__list = m;
+ } else
+ rc = -1;
+ }
+ return rc;
+}
+
+static void menu_build_message_list(struct menu *menu)
+{
+ struct menu *child;
+
+ message__add(menu_get_prompt(menu), NULL,
+ menu->file == NULL ? "Root Menu" : menu->file->name,
+ menu->lineno);
+
+ if (menu->sym != NULL && menu_has_help(menu))
+ message__add(menu_get_help(menu), menu->sym->name,
+ menu->file == NULL ? "Root Menu" : menu->file->name,
+ menu->lineno);
+
+ for (child = menu->list; child != NULL; child = child->next)
+ if (child->prompt != NULL)
+ menu_build_message_list(child);
+}
+
+static void message__print_file_lineno(struct message *self)
+{
+ struct file_line *fl = self->files;
+
+ putchar('\n');
+ if (self->option != NULL)
+ printf("# %s:00000\n", self->option);
+
+ printf("#: %s:%d", fl->file, fl->lineno);
+ fl = fl->next;
+
+ while (fl != NULL) {
+ printf(", %s:%d", fl->file, fl->lineno);
+ fl = fl->next;
+ }
+
+ putchar('\n');
+}
+
+static void message__print_gettext_msgid_msgstr(struct message *self)
+{
+ message__print_file_lineno(self);
+
+ printf("msgid %s\n"
+ "msgstr \"\"\n", self->msg);
+}
+
+static void menu__xgettext(void)
+{
+ struct message *m = message__list;
+
+ while (m != NULL) {
+ /* skip empty lines ("") */
+ if (strlen(m->msg) > sizeof("\"\""))
+ message__print_gettext_msgid_msgstr(m);
+ m = m->next;
+ }
+}
+
+int main(int ac, char **av)
+{
+ conf_parse(av[1]);
+
+ menu_build_message_list(menu_get_root_menu(NULL));
+ menu__xgettext();
+ return 0;
+}
--- /dev/null
+#!/bin/sh
+# merge_config.sh - Takes a list of config fragment values, and merges
+# them one by one. Provides warnings on overridden values, and specified
+# values that did not make it to the resulting .config file (due to missed
+# dependencies or config symbol removal).
+#
+# Portions reused from kconf_check and generate_cfg:
+# http://git.yoctoproject.org/cgit/cgit.cgi/yocto-kernel-tools/tree/tools/kconf_check
+# http://git.yoctoproject.org/cgit/cgit.cgi/yocto-kernel-tools/tree/tools/generate_cfg
+#
+# Copyright (c) 2009-2010 Wind River Systems, Inc.
+# Copyright 2011 Linaro
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# 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.
+
+clean_up() {
+ rm -f $TMP_FILE
+ exit
+}
+trap clean_up HUP INT TERM
+
+usage() {
+ echo "Usage: $0 [OPTIONS] [CONFIG [...]]"
+ echo " -h display this help text"
+ echo " -m only merge the fragments, do not execute the make command"
+ echo " -n use allnoconfig instead of alldefconfig"
+}
+
+MAKE=true
+ALLTARGET=alldefconfig
+
+while true; do
+ case $1 in
+ "-n")
+ ALLTARGET=allnoconfig
+ shift
+ continue
+ ;;
+ "-m")
+ MAKE=false
+ shift
+ continue
+ ;;
+ "-h")
+ usage
+ exit
+ ;;
+ *)
+ break
+ ;;
+ esac
+done
+
+
+
+MERGE_LIST=$*
+SED_CONFIG_EXP="s/^\(# \)\{0,1\}\(CONFIG_[a-zA-Z0-9_]*\)[= ].*/\2/p"
+TMP_FILE=$(mktemp ./.tmp.config.XXXXXXXXXX)
+
+# Merge files, printing warnings on overrided values
+for MERGE_FILE in $MERGE_LIST ; do
+ echo "Merging $MERGE_FILE"
+ CFG_LIST=$(sed -n "$SED_CONFIG_EXP" $MERGE_FILE)
+
+ for CFG in $CFG_LIST ; do
+ grep -q -w $CFG $TMP_FILE
+ if [ $? -eq 0 ] ; then
+ PREV_VAL=$(grep -w $CFG $TMP_FILE)
+ NEW_VAL=$(grep -w $CFG $MERGE_FILE)
+ if [ "x$PREV_VAL" != "x$NEW_VAL" ] ; then
+ echo Value of $CFG is redefined by fragment $MERGE_FILE:
+ echo Previous value: $PREV_VAL
+ echo New value: $NEW_VAL
+ echo
+ fi
+ sed -i "/$CFG[ =]/d" $TMP_FILE
+ fi
+ done
+ cat $MERGE_FILE >> $TMP_FILE
+done
+
+if [ "$MAKE" = "false" ]; then
+ cp $TMP_FILE .config
+ echo "#"
+ echo "# merged configuration written to .config (needs make)"
+ echo "#"
+ clean_up
+ exit
+fi
+
+# Use the merged file as the starting point for:
+# alldefconfig: Fills in any missing symbols with Kconfig default
+# allnoconfig: Fills in any missing symbols with # CONFIG_* is not set
+make KCONFIG_ALLCONFIG=$TMP_FILE $ALLTARGET
+
+
+# Check all specified config values took (might have missed-dependency issues)
+for CFG in $(sed -n "$SED_CONFIG_EXP" $TMP_FILE); do
+
+ REQUESTED_VAL=$(grep -w -e "$CFG" $TMP_FILE)
+ ACTUAL_VAL=$(grep -w -e "$CFG" .config)
+ if [ "x$REQUESTED_VAL" != "x$ACTUAL_VAL" ] ; then
+ echo "Value requested for $CFG not in final .config"
+ echo "Requested value: $REQUESTED_VAL"
+ echo "Actual value: $ACTUAL_VAL"
+ echo ""
+ fi
+done
+
+clean_up
--- /dev/null
+#!/usr/bin/perl -w
+#
+# Copyright 2005-2009 - Steven Rostedt
+# Licensed under the terms of the GNU GPL License version 2
+#
+# It's simple enough to figure out how this works.
+# If not, then you can ask me at stripconfig@goodmis.org
+#
+# What it does?
+#
+# If you have installed a Linux kernel from a distribution
+# that turns on way too many modules than you need, and
+# you only want the modules you use, then this program
+# is perfect for you.
+#
+# It gives you the ability to turn off all the modules that are
+# not loaded on your system.
+#
+# Howto:
+#
+# 1. Boot up the kernel that you want to stream line the config on.
+# 2. Change directory to the directory holding the source of the
+# kernel that you just booted.
+# 3. Copy the configuraton file to this directory as .config
+# 4. Have all your devices that you need modules for connected and
+# operational (make sure that their corresponding modules are loaded)
+# 5. Run this script redirecting the output to some other file
+# like config_strip.
+# 6. Back up your old config (if you want too).
+# 7. copy the config_strip file to .config
+# 8. Run "make oldconfig"
+#
+# Now your kernel is ready to be built with only the modules that
+# are loaded.
+#
+# Here's what I did with my Debian distribution.
+#
+# cd /usr/src/linux-2.6.10
+# cp /boot/config-2.6.10-1-686-smp .config
+# ~/bin/streamline_config > config_strip
+# mv .config config_sav
+# mv config_strip .config
+# make oldconfig
+#
+use strict;
+use Getopt::Long;
+
+my $config = ".config";
+
+my $uname = `uname -r`;
+chomp $uname;
+
+my @searchconfigs = (
+ {
+ "file" => ".config",
+ "exec" => "cat",
+ },
+ {
+ "file" => "/proc/config.gz",
+ "exec" => "zcat",
+ },
+ {
+ "file" => "/boot/config-$uname",
+ "exec" => "cat",
+ },
+ {
+ "file" => "/boot/vmlinuz-$uname",
+ "exec" => "scripts/extract-ikconfig",
+ "test" => "scripts/extract-ikconfig",
+ },
+ {
+ "file" => "vmlinux",
+ "exec" => "scripts/extract-ikconfig",
+ "test" => "scripts/extract-ikconfig",
+ },
+ {
+ "file" => "/lib/modules/$uname/kernel/kernel/configs.ko",
+ "exec" => "scripts/extract-ikconfig",
+ "test" => "scripts/extract-ikconfig",
+ },
+ {
+ "file" => "kernel/configs.ko",
+ "exec" => "scripts/extract-ikconfig",
+ "test" => "scripts/extract-ikconfig",
+ },
+ {
+ "file" => "kernel/configs.o",
+ "exec" => "scripts/extract-ikconfig",
+ "test" => "scripts/extract-ikconfig",
+ },
+);
+
+sub find_config {
+ foreach my $conf (@searchconfigs) {
+ my $file = $conf->{"file"};
+
+ next if ( ! -f "$file");
+
+ if (defined($conf->{"test"})) {
+ `$conf->{"test"} $conf->{"file"} 2>/dev/null`;
+ next if ($?);
+ }
+
+ my $exec = $conf->{"exec"};
+
+ print STDERR "using config: '$file'\n";
+
+ open(CIN, "$exec $file |") || die "Failed to run $exec $file";
+ return;
+ }
+ die "No config file found";
+}
+
+find_config;
+
+# Parse options
+my $localmodconfig = 0;
+my $localyesconfig = 0;
+
+GetOptions("localmodconfig" => \$localmodconfig,
+ "localyesconfig" => \$localyesconfig);
+
+# Get the build source and top level Kconfig file (passed in)
+my $ksource = $ARGV[0];
+my $kconfig = $ARGV[1];
+my $lsmod_file = $ENV{'LSMOD'};
+
+my @makefiles = `find $ksource -name Makefile 2>/dev/null`;
+chomp @makefiles;
+
+my %depends;
+my %selects;
+my %prompts;
+my %objects;
+my $var;
+my $iflevel = 0;
+my @ifdeps;
+
+# prevent recursion
+my %read_kconfigs;
+
+sub read_kconfig {
+ my ($kconfig) = @_;
+
+ my $state = "NONE";
+ my $config;
+ my @kconfigs;
+
+ my $cont = 0;
+ my $line;
+
+ my $source = "$ksource/$kconfig";
+ my $last_source = "";
+
+ # Check for any environment variables used
+ while ($source =~ /\$(\w+)/ && $last_source ne $source) {
+ my $env = $1;
+ $last_source = $source;
+ $source =~ s/\$$env/$ENV{$env}/;
+ }
+
+ open(KIN, "$source") || die "Can't open $kconfig";
+ while (<KIN>) {
+ chomp;
+
+ # Make sure that lines ending with \ continue
+ if ($cont) {
+ $_ = $line . " " . $_;
+ }
+
+ if (s/\\$//) {
+ $cont = 1;
+ $line = $_;
+ next;
+ }
+
+ $cont = 0;
+
+ # collect any Kconfig sources
+ if (/^source\s*"(.*)"/) {
+ $kconfigs[$#kconfigs+1] = $1;
+ }
+
+ # configs found
+ if (/^\s*(menu)?config\s+(\S+)\s*$/) {
+ $state = "NEW";
+ $config = $2;
+
+ for (my $i = 0; $i < $iflevel; $i++) {
+ if ($i) {
+ $depends{$config} .= " " . $ifdeps[$i];
+ } else {
+ $depends{$config} = $ifdeps[$i];
+ }
+ $state = "DEP";
+ }
+
+ # collect the depends for the config
+ } elsif ($state eq "NEW" && /^\s*depends\s+on\s+(.*)$/) {
+ $state = "DEP";
+ $depends{$config} = $1;
+ } elsif ($state eq "DEP" && /^\s*depends\s+on\s+(.*)$/) {
+ $depends{$config} .= " " . $1;
+
+ # Get the configs that select this config
+ } elsif ($state ne "NONE" && /^\s*select\s+(\S+)/) {
+ if (defined($selects{$1})) {
+ $selects{$1} .= " " . $config;
+ } else {
+ $selects{$1} = $config;
+ }
+
+ # configs without prompts must be selected
+ } elsif ($state ne "NONE" && /^\s*tristate\s\S/) {
+ # note if the config has a prompt
+ $prompts{$config} = 1;
+
+ # Check for if statements
+ } elsif (/^if\s+(.*\S)\s*$/) {
+ my $deps = $1;
+ # remove beginning and ending non text
+ $deps =~ s/^[^a-zA-Z0-9_]*//;
+ $deps =~ s/[^a-zA-Z0-9_]*$//;
+
+ my @deps = split /[^a-zA-Z0-9_]+/, $deps;
+
+ $ifdeps[$iflevel++] = join ':', @deps;
+
+ } elsif (/^endif/) {
+
+ $iflevel-- if ($iflevel);
+
+ # stop on "help"
+ } elsif (/^\s*help\s*$/) {
+ $state = "NONE";
+ }
+ }
+ close(KIN);
+
+ # read in any configs that were found.
+ foreach $kconfig (@kconfigs) {
+ if (!defined($read_kconfigs{$kconfig})) {
+ $read_kconfigs{$kconfig} = 1;
+ read_kconfig($kconfig);
+ }
+ }
+}
+
+if ($kconfig) {
+ read_kconfig($kconfig);
+}
+
+sub convert_vars {
+ my ($line, %vars) = @_;
+
+ my $process = "";
+
+ while ($line =~ s/^(.*?)(\$\((.*?)\))//) {
+ my $start = $1;
+ my $variable = $2;
+ my $var = $3;
+
+ if (defined($vars{$var})) {
+ $process .= $start . $vars{$var};
+ } else {
+ $process .= $start . $variable;
+ }
+ }
+
+ $process .= $line;
+
+ return $process;
+}
+
+# Read all Makefiles to map the configs to the objects
+foreach my $makefile (@makefiles) {
+
+ my $line = "";
+ my %make_vars;
+
+ open(MIN,$makefile) || die "Can't open $makefile";
+ while (<MIN>) {
+ # if this line ends with a backslash, continue
+ chomp;
+ if (/^(.*)\\$/) {
+ $line .= $1;
+ next;
+ }
+
+ $line .= $_;
+ $_ = $line;
+ $line = "";
+
+ my $objs;
+
+ $_ = convert_vars($_, %make_vars);
+
+ # collect objects after obj-$(CONFIG_FOO_BAR)
+ if (/obj-\$\((CONFIG_[^\)]*)\)\s*[+:]?=\s*(.*)/) {
+ $var = $1;
+ $objs = $2;
+
+ # check if variables are set
+ } elsif (/^\s*(\S+)\s*[:]?=\s*(.*\S)/) {
+ $make_vars{$1} = $2;
+ }
+ if (defined($objs)) {
+ foreach my $obj (split /\s+/,$objs) {
+ $obj =~ s/-/_/g;
+ if ($obj =~ /(.*)\.o$/) {
+ # Objects may be enabled by more than one config.
+ # Store configs in an array.
+ my @arr;
+
+ if (defined($objects{$1})) {
+ @arr = @{$objects{$1}};
+ }
+
+ $arr[$#arr+1] = $var;
+
+ # The objects have a hash mapping to a reference
+ # of an array of configs.
+ $objects{$1} = \@arr;
+ }
+ }
+ }
+ }
+ close(MIN);
+}
+
+my %modules;
+
+if (defined($lsmod_file)) {
+ if ( ! -f $lsmod_file) {
+ if ( -f $ENV{'objtree'}."/".$lsmod_file) {
+ $lsmod_file = $ENV{'objtree'}."/".$lsmod_file;
+ } else {
+ die "$lsmod_file not found";
+ }
+ }
+ if ( -x $lsmod_file) {
+ # the file is executable, run it
+ open(LIN, "$lsmod_file|");
+ } else {
+ # Just read the contents
+ open(LIN, "$lsmod_file");
+ }
+} else {
+
+ # see what modules are loaded on this system
+ my $lsmod;
+
+ foreach my $dir ( ("/sbin", "/bin", "/usr/sbin", "/usr/bin") ) {
+ if ( -x "$dir/lsmod" ) {
+ $lsmod = "$dir/lsmod";
+ last;
+ }
+}
+ if (!defined($lsmod)) {
+ # try just the path
+ $lsmod = "lsmod";
+ }
+
+ open(LIN,"$lsmod|") || die "Can not call lsmod with $lsmod";
+}
+
+while (<LIN>) {
+ next if (/^Module/); # Skip the first line.
+ if (/^(\S+)/) {
+ $modules{$1} = 1;
+ }
+}
+close (LIN);
+
+# add to the configs hash all configs that are needed to enable
+# a loaded module.
+my %configs;
+foreach my $module (keys(%modules)) {
+ if (defined($objects{$module})) {
+ my @arr = @{$objects{$module}};
+ foreach my $conf (@arr) {
+ $configs{$conf} = $module;
+ }
+ } else {
+ # Most likely, someone has a custom (binary?) module loaded.
+ print STDERR "$module config not found!!\n";
+ }
+}
+
+my $valid = "A-Za-z_0-9";
+my $repeat = 1;
+
+#
+# Note, we do not care about operands (like: &&, ||, !) we want to add any
+# config that is in the depend list of another config. This script does
+# not enable configs that are not already enabled. If we come across a
+# config A that depends on !B, we can still add B to the list of depends
+# to keep on. If A was on in the original config, B would not have been
+# and B would not be turned on by this script.
+#
+sub parse_config_dep_select
+{
+ my ($p) = @_;
+
+ while ($p =~ /[$valid]/) {
+
+ if ($p =~ /^[^$valid]*([$valid]+)/) {
+ my $conf = "CONFIG_" . $1;
+
+ $p =~ s/^[^$valid]*[$valid]+//;
+
+ if (!defined($configs{$conf})) {
+ # We must make sure that this config has its
+ # dependencies met.
+ $repeat = 1; # do again
+ $configs{$conf} = 1;
+ }
+ } else {
+ die "this should never happen";
+ }
+ }
+}
+
+while ($repeat) {
+ $repeat = 0;
+
+ foreach my $config (keys %configs) {
+ $config =~ s/^CONFIG_//;
+
+ if (defined($depends{$config})) {
+ # This config has dependencies. Make sure they are also included
+ parse_config_dep_select $depends{$config};
+ }
+
+ if (defined($prompts{$config}) || !defined($selects{$config})) {
+ next;
+ }
+
+ # config has no prompt and must be selected.
+ parse_config_dep_select $selects{$config};
+ }
+}
+
+my %setconfigs;
+
+# Finally, read the .config file and turn off any module enabled that
+# we could not find a reason to keep enabled.
+while(<CIN>) {
+
+ if (/CONFIG_IKCONFIG/) {
+ if (/# CONFIG_IKCONFIG is not set/) {
+ # enable IKCONFIG at least as a module
+ print "CONFIG_IKCONFIG=m\n";
+ # don't ask about PROC
+ print "# CONFIG_IKCONFIG_PROC is not set\n";
+ } else {
+ print;
+ }
+ next;
+ }
+
+ if (/^(CONFIG.*)=(m|y)/) {
+ if (defined($configs{$1})) {
+ if ($localyesconfig) {
+ $setconfigs{$1} = 'y';
+ } else {
+ $setconfigs{$1} = $2;
+ }
+ } elsif ($2 eq "m") {
+ print "# $1 is not set\n";
+ next;
+ }
+ }
+ print;
+}
+close(CIN);
+
+# Integrity check, make sure all modules that we want enabled do
+# indeed have their configs set.
+loop:
+foreach my $module (keys(%modules)) {
+ if (defined($objects{$module})) {
+ my @arr = @{$objects{$module}};
+ foreach my $conf (@arr) {
+ if (defined($setconfigs{$conf})) {
+ next loop;
+ }
+ }
+ print STDERR "module $module did not have configs";
+ foreach my $conf (@arr) {
+ print STDERR " " , $conf;
+ }
+ print STDERR "\n";
+ }
+}
+++ /dev/null
-/*
- * Copyright (C) 2008 Nir Tzachar <nir.tzachar@gmail.com?
- * Released under the terms of the GNU GPL v2.0.
- *
- * Derived from menuconfig.
- *
- */
-#define _GNU_SOURCE
-#include <string.h>
-
-#include "lkc.h"
-#include "nconf.h"
-#include <ctype.h>
-
-static const char nconf_readme[] = N_(
-"Overview\n"
-"--------\n"
-"This interface let you select features and parameters for the build.\n"
-"Features can either be built-in, modularized, or ignored. Parameters\n"
-"must be entered in as decimal or hexadecimal numbers or text.\n"
-"\n"
-"Menu items beginning with following braces represent features that\n"
-" [ ] can be built in or removed\n"
-" < > can be built in, modularized or removed\n"
-" { } can be built in or modularized (selected by other feature)\n"
-" - - are selected by other feature,\n"
-" XXX cannot be selected. Use Symbol Info to find out why,\n"
-"while *, M or whitespace inside braces means to build in, build as\n"
-"a module or to exclude the feature respectively.\n"
-"\n"
-"To change any of these features, highlight it with the cursor\n"
-"keys and press <Y> to build it in, <M> to make it a module or\n"
-"<N> to removed it. You may also press the <Space Bar> to cycle\n"
-"through the available options (ie. Y->N->M->Y).\n"
-"\n"
-"Some additional keyboard hints:\n"
-"\n"
-"Menus\n"
-"----------\n"
-"o Use the Up/Down arrow keys (cursor keys) to highlight the item\n"
-" you wish to change use <Enter> or <Space>. Goto submenu by \n"
-" pressing <Enter> of <right-arrow>. Use <Esc> or <left-arrow> to go back.\n"
-" Submenus are designated by \"--->\".\n"
-"\n"
-" Searching: pressing '/' triggers interactive search mode.\n"
-" nconfig performs a case insensitive search for the string\n"
-" in the menu prompts (no regex support).\n"
-" Pressing the up/down keys highlights the previous/next\n"
-" matching item. Backspace removes one character from the\n"
-" match string. Pressing either '/' again or ESC exits\n"
-" search mode. All other keys behave normally.\n"
-"\n"
-" You may also use the <PAGE UP> and <PAGE DOWN> keys to scroll\n"
-" unseen options into view.\n"
-"\n"
-"o To exit a menu use the just press <ESC> <F5> <F8> or <left-arrow>.\n"
-"\n"
-"o To get help with an item, press <F1>\n"
-" Shortcut: Press <h> or <?>.\n"
-"\n"
-"\n"
-"Radiolists (Choice lists)\n"
-"-----------\n"
-"o Use the cursor keys to select the option you wish to set and press\n"
-" <S> or the <SPACE BAR>.\n"
-"\n"
-" Shortcut: Press the first letter of the option you wish to set then\n"
-" press <S> or <SPACE BAR>.\n"
-"\n"
-"o To see available help for the item, press <F1>\n"
-" Shortcut: Press <H> or <?>.\n"
-"\n"
-"\n"
-"Data Entry\n"
-"-----------\n"
-"o Enter the requested information and press <ENTER>\n"
-" If you are entering hexadecimal values, it is not necessary to\n"
-" add the '0x' prefix to the entry.\n"
-"\n"
-"o For help, press <F1>.\n"
-"\n"
-"\n"
-"Text Box (Help Window)\n"
-"--------\n"
-"o Use the cursor keys to scroll up/down/left/right. The VI editor\n"
-" keys h,j,k,l function here as do <SPACE BAR> for those\n"
-" who are familiar with less and lynx.\n"
-"\n"
-"o Press <Enter>, <F1>, <F5>, <F7> or <Esc> to exit.\n"
-"\n"
-"\n"
-"Alternate Configuration Files\n"
-"-----------------------------\n"
-"nconfig supports the use of alternate configuration files for\n"
-"those who, for various reasons, find it necessary to switch\n"
-"between different configurations.\n"
-"\n"
-"At the end of the main menu you will find two options. One is\n"
-"for saving the current configuration to a file of your choosing.\n"
-"The other option is for loading a previously saved alternate\n"
-"configuration.\n"
-"\n"
-"Even if you don't use alternate configuration files, but you\n"
-"find during a nconfig session that you have completely messed\n"
-"up your settings, you may use the \"Load Alternate...\" option to\n"
-"restore your previously saved settings from \".config\" without\n"
-"restarting nconfig.\n"
-"\n"
-"Other information\n"
-"-----------------\n"
-"If you use nconfig in an XTERM window make sure you have your\n"
-"$TERM variable set to point to a xterm definition which supports color.\n"
-"Otherwise, nconfig will look rather bad. nconfig will not\n"
-"display correctly in a RXVT window because rxvt displays only one\n"
-"intensity of color, bright.\n"
-"\n"
-"nconfig will display larger menus on screens or xterms which are\n"
-"set to display more than the standard 25 row by 80 column geometry.\n"
-"In order for this to work, the \"stty size\" command must be able to\n"
-"display the screen's current row and column geometry. I STRONGLY\n"
-"RECOMMEND that you make sure you do NOT have the shell variables\n"
-"LINES and COLUMNS exported into your environment. Some distributions\n"
-"export those variables via /etc/profile. Some ncurses programs can\n"
-"become confused when those variables (LINES & COLUMNS) don't reflect\n"
-"the true screen size.\n"
-"\n"
-"Optional personality available\n"
-"------------------------------\n"
-"If you prefer to have all of the options listed in a single menu, rather\n"
-"than the default multimenu hierarchy, run the nconfig with NCONFIG_MODE\n"
-"environment variable set to single_menu. Example:\n"
-"\n"
-"make NCONFIG_MODE=single_menu nconfig\n"
-"\n"
-"<Enter> will then unroll the appropriate category, or enfold it if it\n"
-"is already unrolled.\n"
-"\n"
-"Note that this mode can eventually be a little more CPU expensive\n"
-"(especially with a larger number of unrolled categories) than the\n"
-"default mode.\n"
-"\n"),
-menu_no_f_instructions[] = N_(
-" You do not have function keys support. Please follow the\n"
-" following instructions:\n"
-" Arrow keys navigate the menu.\n"
-" <Enter> or <right-arrow> selects submenus --->.\n"
-" Capital Letters are hotkeys.\n"
-" Pressing <Y> includes, <N> excludes, <M> modularizes features.\n"
-" Pressing SpaceBar toggles between the above options.\n"
-" Press <Esc> or <left-arrow> to go back one menu,\n"
-" <?> or <h> for Help, </> for Search.\n"
-" <1> is interchangeable with <F1>, <2> with <F2>, etc.\n"
-" Legend: [*] built-in [ ] excluded <M> module < > module capable.\n"
-" <Esc> always leaves the current window.\n"),
-menu_instructions[] = N_(
-" Arrow keys navigate the menu.\n"
-" <Enter> or <right-arrow> selects submenus --->.\n"
-" Capital Letters are hotkeys.\n"
-" Pressing <Y> includes, <N> excludes, <M> modularizes features.\n"
-" Pressing SpaceBar toggles between the above options\n"
-" Press <Esc>, <F5> or <left-arrow> to go back one menu,\n"
-" <?>, <F1> or <h> for Help, </> for Search.\n"
-" <1> is interchangeable with <F1>, <2> with <F2>, etc.\n"
-" Legend: [*] built-in [ ] excluded <M> module < > module capable.\n"
-" <Esc> always leaves the current window\n"),
-radiolist_instructions[] = N_(
-" Use the arrow keys to navigate this window or\n"
-" press the hotkey of the item you wish to select\n"
-" followed by the <SPACE BAR>.\n"
-" Press <?>, <F1> or <h> for additional information about this option.\n"),
-inputbox_instructions_int[] = N_(
-"Please enter a decimal value.\n"
-"Fractions will not be accepted.\n"
-"Press <RETURN> to accept, <ESC> to cancel."),
-inputbox_instructions_hex[] = N_(
-"Please enter a hexadecimal value.\n"
-"Press <RETURN> to accept, <ESC> to cancel."),
-inputbox_instructions_string[] = N_(
-"Please enter a string value.\n"
-"Press <RETURN> to accept, <ESC> to cancel."),
-setmod_text[] = N_(
-"This feature depends on another which\n"
-"has been configured as a module.\n"
-"As a result, this feature will be built as a module."),
-load_config_text[] = N_(
-"Enter the name of the configuration file you wish to load.\n"
-"Accept the name shown to restore the configuration you\n"
-"last retrieved. Leave blank to abort."),
-load_config_help[] = N_(
-"\n"
-"For various reasons, one may wish to keep several different\n"
-"configurations available on a single machine.\n"
-"\n"
-"If you have saved a previous configuration in a file other than the\n"
-"default one, entering its name here will allow you to modify that\n"
-"configuration.\n"
-"\n"
-"If you are uncertain, then you have probably never used alternate\n"
-"configuration files. You should therefor leave this blank to abort.\n"),
-save_config_text[] = N_(
-"Enter a filename to which this configuration should be saved\n"
-"as an alternate. Leave blank to abort."),
-save_config_help[] = N_(
-"\n"
-"For various reasons, one may wish to keep different configurations\n"
-"available on a single machine.\n"
-"\n"
-"Entering a file name here will allow you to later retrieve, modify\n"
-"and use the current configuration as an alternate to whatever\n"
-"configuration options you have selected at that time.\n"
-"\n"
-"If you are uncertain what all this means then you should probably\n"
-"leave this blank.\n"),
-search_help[] = N_(
-"\n"
-"Search for symbols and display their relations. Regular expressions\n"
-"are allowed.\n"
-"Example: search for \"^FOO\"\n"
-"Result:\n"
-"-----------------------------------------------------------------\n"
-"Symbol: FOO [ = m]\n"
-"Prompt: Foo bus is used to drive the bar HW\n"
-"Defined at drivers/pci/Kconfig:47\n"
-"Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n"
-"Location:\n"
-" -> Bus options (PCI, PCMCIA, EISA, MCA, ISA)\n"
-" -> PCI support (PCI [ = y])\n"
-" -> PCI access mode (<choice> [ = y])\n"
-"Selects: LIBCRC32\n"
-"Selected by: BAR\n"
-"-----------------------------------------------------------------\n"
-"o The line 'Prompt:' shows the text used in the menu structure for\n"
-" this symbol\n"
-"o The 'Defined at' line tell at what file / line number the symbol\n"
-" is defined\n"
-"o The 'Depends on:' line tell what symbols needs to be defined for\n"
-" this symbol to be visible in the menu (selectable)\n"
-"o The 'Location:' lines tell where in the menu structure this symbol\n"
-" is located\n"
-" A location followed by a [ = y] indicate that this is a selectable\n"
-" menu item - and current value is displayed inside brackets.\n"
-"o The 'Selects:' line tell what symbol will be automatically\n"
-" selected if this symbol is selected (y or m)\n"
-"o The 'Selected by' line tell what symbol has selected this symbol\n"
-"\n"
-"Only relevant lines are shown.\n"
-"\n\n"
-"Search examples:\n"
-"Examples: USB => find all symbols containing USB\n"
-" ^USB => find all symbols starting with USB\n"
-" USB$ => find all symbols ending with USB\n"
-"\n");
-
-struct mitem {
- char str[256];
- char tag;
- void *usrptr;
- int is_visible;
-};
-
-#define MAX_MENU_ITEMS 4096
-static int show_all_items;
-static int indent;
-static struct menu *current_menu;
-static int child_count;
-static int single_menu_mode;
-/* the window in which all information appears */
-static WINDOW *main_window;
-/* the largest size of the menu window */
-static int mwin_max_lines;
-static int mwin_max_cols;
-/* the window in which we show option buttons */
-static MENU *curses_menu;
-static ITEM *curses_menu_items[MAX_MENU_ITEMS];
-static struct mitem k_menu_items[MAX_MENU_ITEMS];
-static int items_num;
-static int global_exit;
-/* the currently selected button */
-const char *current_instructions = menu_instructions;
-
-static char *dialog_input_result;
-static int dialog_input_result_len;
-
-static void conf(struct menu *menu);
-static void conf_choice(struct menu *menu);
-static void conf_string(struct menu *menu);
-static void conf_load(void);
-static void conf_save(void);
-static void show_help(struct menu *menu);
-static int do_exit(void);
-static void setup_windows(void);
-static void search_conf(void);
-
-typedef void (*function_key_handler_t)(int *key, struct menu *menu);
-static void handle_f1(int *key, struct menu *current_item);
-static void handle_f2(int *key, struct menu *current_item);
-static void handle_f3(int *key, struct menu *current_item);
-static void handle_f4(int *key, struct menu *current_item);
-static void handle_f5(int *key, struct menu *current_item);
-static void handle_f6(int *key, struct menu *current_item);
-static void handle_f7(int *key, struct menu *current_item);
-static void handle_f8(int *key, struct menu *current_item);
-static void handle_f9(int *key, struct menu *current_item);
-
-struct function_keys {
- const char *key_str;
- const char *func;
- function_key key;
- function_key_handler_t handler;
-};
-
-static const int function_keys_num = 9;
-struct function_keys function_keys[] = {
- {
- .key_str = "F1",
- .func = "Help",
- .key = F_HELP,
- .handler = handle_f1,
- },
- {
- .key_str = "F2",
- .func = "Sym Info",
- .key = F_SYMBOL,
- .handler = handle_f2,
- },
- {
- .key_str = "F3",
- .func = "Insts",
- .key = F_INSTS,
- .handler = handle_f3,
- },
- {
- .key_str = "F4",
- .func = "Config",
- .key = F_CONF,
- .handler = handle_f4,
- },
- {
- .key_str = "F5",
- .func = "Back",
- .key = F_BACK,
- .handler = handle_f5,
- },
- {
- .key_str = "F6",
- .func = "Save",
- .key = F_SAVE,
- .handler = handle_f6,
- },
- {
- .key_str = "F7",
- .func = "Load",
- .key = F_LOAD,
- .handler = handle_f7,
- },
- {
- .key_str = "F8",
- .func = "Sym Search",
- .key = F_SEARCH,
- .handler = handle_f8,
- },
- {
- .key_str = "F9",
- .func = "Exit",
- .key = F_EXIT,
- .handler = handle_f9,
- },
-};
-
-static void print_function_line(void)
-{
- int i;
- int offset = 1;
- const int skip = 1;
-
- for (i = 0; i < function_keys_num; i++) {
- (void) wattrset(main_window, attributes[FUNCTION_HIGHLIGHT]);
- mvwprintw(main_window, LINES-3, offset,
- "%s",
- function_keys[i].key_str);
- (void) wattrset(main_window, attributes[FUNCTION_TEXT]);
- offset += strlen(function_keys[i].key_str);
- mvwprintw(main_window, LINES-3,
- offset, "%s",
- function_keys[i].func);
- offset += strlen(function_keys[i].func) + skip;
- }
- (void) wattrset(main_window, attributes[NORMAL]);
-}
-
-/* help */
-static void handle_f1(int *key, struct menu *current_item)
-{
- show_scroll_win(main_window,
- _("README"), _(nconf_readme));
- return;
-}
-
-/* symbole help */
-static void handle_f2(int *key, struct menu *current_item)
-{
- show_help(current_item);
- return;
-}
-
-/* instructions */
-static void handle_f3(int *key, struct menu *current_item)
-{
- show_scroll_win(main_window,
- _("Instructions"),
- _(current_instructions));
- return;
-}
-
-/* config */
-static void handle_f4(int *key, struct menu *current_item)
-{
- int res = btn_dialog(main_window,
- _("Show all symbols?"),
- 2,
- " <Show All> ",
- "<Don't show all>");
- if (res == 0)
- show_all_items = 1;
- else if (res == 1)
- show_all_items = 0;
-
- return;
-}
-
-/* back */
-static void handle_f5(int *key, struct menu *current_item)
-{
- *key = KEY_LEFT;
- return;
-}
-
-/* save */
-static void handle_f6(int *key, struct menu *current_item)
-{
- conf_save();
- return;
-}
-
-/* load */
-static void handle_f7(int *key, struct menu *current_item)
-{
- conf_load();
- return;
-}
-
-/* search */
-static void handle_f8(int *key, struct menu *current_item)
-{
- search_conf();
- return;
-}
-
-/* exit */
-static void handle_f9(int *key, struct menu *current_item)
-{
- do_exit();
- return;
-}
-
-/* return != 0 to indicate the key was handles */
-static int process_special_keys(int *key, struct menu *menu)
-{
- int i;
-
- if (*key == KEY_RESIZE) {
- setup_windows();
- return 1;
- }
-
- for (i = 0; i < function_keys_num; i++) {
- if (*key == KEY_F(function_keys[i].key) ||
- *key == '0' + function_keys[i].key){
- function_keys[i].handler(key, menu);
- return 1;
- }
- }
-
- return 0;
-}
-
-static void clean_items(void)
-{
- int i;
- for (i = 0; curses_menu_items[i]; i++)
- free_item(curses_menu_items[i]);
- bzero(curses_menu_items, sizeof(curses_menu_items));
- bzero(k_menu_items, sizeof(k_menu_items));
- items_num = 0;
-}
-
-typedef enum {MATCH_TINKER_PATTERN_UP, MATCH_TINKER_PATTERN_DOWN,
- FIND_NEXT_MATCH_DOWN, FIND_NEXT_MATCH_UP} match_f;
-
-/* return the index of the matched item, or -1 if no such item exists */
-static int get_mext_match(const char *match_str, match_f flag)
-{
- int match_start = item_index(current_item(curses_menu));
- int index;
-
- if (flag == FIND_NEXT_MATCH_DOWN)
- ++match_start;
- else if (flag == FIND_NEXT_MATCH_UP)
- --match_start;
-
- index = match_start;
- index = (index + items_num) % items_num;
- while (true) {
- char *str = k_menu_items[index].str;
- if (strcasestr(str, match_str) != 0)
- return index;
- if (flag == FIND_NEXT_MATCH_UP ||
- flag == MATCH_TINKER_PATTERN_UP)
- --index;
- else
- ++index;
- index = (index + items_num) % items_num;
- if (index == match_start)
- return -1;
- }
-}
-
-/* Make a new item. */
-static void item_make(struct menu *menu, char tag, const char *fmt, ...)
-{
- va_list ap;
-
- if (items_num > MAX_MENU_ITEMS-1)
- return;
-
- bzero(&k_menu_items[items_num], sizeof(k_menu_items[0]));
- k_menu_items[items_num].tag = tag;
- k_menu_items[items_num].usrptr = menu;
- if (menu != NULL)
- k_menu_items[items_num].is_visible =
- menu_is_visible(menu);
- else
- k_menu_items[items_num].is_visible = 1;
-
- va_start(ap, fmt);
- vsnprintf(k_menu_items[items_num].str,
- sizeof(k_menu_items[items_num].str),
- fmt, ap);
- va_end(ap);
-
- if (!k_menu_items[items_num].is_visible)
- memcpy(k_menu_items[items_num].str, "XXX", 3);
-
- curses_menu_items[items_num] = new_item(
- k_menu_items[items_num].str,
- k_menu_items[items_num].str);
- set_item_userptr(curses_menu_items[items_num],
- &k_menu_items[items_num]);
- /*
- if (!k_menu_items[items_num].is_visible)
- item_opts_off(curses_menu_items[items_num], O_SELECTABLE);
- */
-
- items_num++;
- curses_menu_items[items_num] = NULL;
-}
-
-/* very hackish. adds a string to the last item added */
-static void item_add_str(const char *fmt, ...)
-{
- va_list ap;
- int index = items_num-1;
- char new_str[256];
- char tmp_str[256];
-
- if (index < 0)
- return;
-
- va_start(ap, fmt);
- vsnprintf(new_str, sizeof(new_str), fmt, ap);
- va_end(ap);
- snprintf(tmp_str, sizeof(tmp_str), "%s%s",
- k_menu_items[index].str, new_str);
- strncpy(k_menu_items[index].str,
- tmp_str,
- sizeof(k_menu_items[index].str));
-
- free_item(curses_menu_items[index]);
- curses_menu_items[index] = new_item(
- k_menu_items[index].str,
- k_menu_items[index].str);
- set_item_userptr(curses_menu_items[index],
- &k_menu_items[index]);
-}
-
-/* get the tag of the currently selected item */
-static char item_tag(void)
-{
- ITEM *cur;
- struct mitem *mcur;
-
- cur = current_item(curses_menu);
- if (cur == NULL)
- return 0;
- mcur = (struct mitem *) item_userptr(cur);
- return mcur->tag;
-}
-
-static int curses_item_index(void)
-{
- return item_index(current_item(curses_menu));
-}
-
-static void *item_data(void)
-{
- ITEM *cur;
- struct mitem *mcur;
-
- cur = current_item(curses_menu);
- if (!cur)
- return NULL;
- mcur = (struct mitem *) item_userptr(cur);
- return mcur->usrptr;
-
-}
-
-static int item_is_tag(char tag)
-{
- return item_tag() == tag;
-}
-
-static char filename[PATH_MAX+1];
-static char menu_backtitle[PATH_MAX+128];
-static const char *set_config_filename(const char *config_filename)
-{
- int size;
-
- size = snprintf(menu_backtitle, sizeof(menu_backtitle),
- "%s - %s", config_filename, rootmenu.prompt->text);
- if (size >= sizeof(menu_backtitle))
- menu_backtitle[sizeof(menu_backtitle)-1] = '\0';
-
- size = snprintf(filename, sizeof(filename), "%s", config_filename);
- if (size >= sizeof(filename))
- filename[sizeof(filename)-1] = '\0';
- return menu_backtitle;
-}
-
-/* return = 0 means we are successful.
- * -1 means go on doing what you were doing
- */
-static int do_exit(void)
-{
- int res;
- if (!conf_get_changed()) {
- global_exit = 1;
- return 0;
- }
- res = btn_dialog(main_window,
- _("Do you wish to save your new configuration?\n"
- "<ESC> to cancel and resume nconfig."),
- 2,
- " <save> ",
- "<don't save>");
- if (res == KEY_EXIT) {
- global_exit = 0;
- return -1;
- }
-
- /* if we got here, the user really wants to exit */
- switch (res) {
- case 0:
- res = conf_write(filename);
- if (res)
- btn_dialog(
- main_window,
- _("Error during writing of configuration.\n"
- "Your configuration changes were NOT saved."),
- 1,
- "<OK>");
- break;
- default:
- btn_dialog(
- main_window,
- _("Your configuration changes were NOT saved."),
- 1,
- "<OK>");
- break;
- }
- global_exit = 1;
- return 0;
-}
-
-
-static void search_conf(void)
-{
- struct symbol **sym_arr;
- struct gstr res;
- char *dialog_input;
- int dres;
-again:
- dres = dialog_inputbox(main_window,
- _("Search Configuration Parameter"),
- _("Enter " CONFIG_ " (sub)string to search for "
- "(with or without \"" CONFIG_ "\")"),
- "", &dialog_input_result, &dialog_input_result_len);
- switch (dres) {
- case 0:
- break;
- case 1:
- show_scroll_win(main_window,
- _("Search Configuration"), search_help);
- goto again;
- default:
- return;
- }
-
- /* strip the prefix if necessary */
- dialog_input = dialog_input_result;
- if (strncasecmp(dialog_input_result, CONFIG_, strlen(CONFIG_)) == 0)
- dialog_input += strlen(CONFIG_);
-
- sym_arr = sym_re_search(dialog_input);
- res = get_relations_str(sym_arr);
- free(sym_arr);
- show_scroll_win(main_window,
- _("Search Results"), str_get(&res));
- str_free(&res);
-}
-
-
-static void build_conf(struct menu *menu)
-{
- struct symbol *sym;
- struct property *prop;
- struct menu *child;
- int type, tmp, doint = 2;
- tristate val;
- char ch;
-
- if (!menu || (!show_all_items && !menu_is_visible(menu)))
- return;
-
- sym = menu->sym;
- prop = menu->prompt;
- if (!sym) {
- if (prop && menu != current_menu) {
- const char *prompt = menu_get_prompt(menu);
- enum prop_type ptype;
- ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
- switch (ptype) {
- case P_MENU:
- child_count++;
- prompt = _(prompt);
- if (single_menu_mode) {
- item_make(menu, 'm',
- "%s%*c%s",
- menu->data ? "-->" : "++>",
- indent + 1, ' ', prompt);
- } else
- item_make(menu, 'm',
- " %*c%s --->",
- indent + 1,
- ' ', prompt);
-
- if (single_menu_mode && menu->data)
- goto conf_childs;
- return;
- case P_COMMENT:
- if (prompt) {
- child_count++;
- item_make(menu, ':',
- " %*c*** %s ***",
- indent + 1, ' ',
- _(prompt));
- }
- break;
- default:
- if (prompt) {
- child_count++;
- item_make(menu, ':', "---%*c%s",
- indent + 1, ' ',
- _(prompt));
- }
- }
- } else
- doint = 0;
- goto conf_childs;
- }
-
- type = sym_get_type(sym);
- if (sym_is_choice(sym)) {
- struct symbol *def_sym = sym_get_choice_value(sym);
- struct menu *def_menu = NULL;
-
- child_count++;
- for (child = menu->list; child; child = child->next) {
- if (menu_is_visible(child) && child->sym == def_sym)
- def_menu = child;
- }
-
- val = sym_get_tristate_value(sym);
- if (sym_is_changable(sym)) {
- switch (type) {
- case S_BOOLEAN:
- item_make(menu, 't', "[%c]",
- val == no ? ' ' : '*');
- break;
- case S_TRISTATE:
- switch (val) {
- case yes:
- ch = '*';
- break;
- case mod:
- ch = 'M';
- break;
- default:
- ch = ' ';
- break;
- }
- item_make(menu, 't', "<%c>", ch);
- break;
- }
- } else {
- item_make(menu, def_menu ? 't' : ':', " ");
- }
-
- item_add_str("%*c%s", indent + 1,
- ' ', _(menu_get_prompt(menu)));
- if (val == yes) {
- if (def_menu) {
- item_add_str(" (%s)",
- _(menu_get_prompt(def_menu)));
- item_add_str(" --->");
- if (def_menu->list) {
- indent += 2;
- build_conf(def_menu);
- indent -= 2;
- }
- }
- return;
- }
- } else {
- if (menu == current_menu) {
- item_make(menu, ':',
- "---%*c%s", indent + 1,
- ' ', _(menu_get_prompt(menu)));
- goto conf_childs;
- }
- child_count++;
- val = sym_get_tristate_value(sym);
- if (sym_is_choice_value(sym) && val == yes) {
- item_make(menu, ':', " ");
- } else {
- switch (type) {
- case S_BOOLEAN:
- if (sym_is_changable(sym))
- item_make(menu, 't', "[%c]",
- val == no ? ' ' : '*');
- else
- item_make(menu, 't', "-%c-",
- val == no ? ' ' : '*');
- break;
- case S_TRISTATE:
- switch (val) {
- case yes:
- ch = '*';
- break;
- case mod:
- ch = 'M';
- break;
- default:
- ch = ' ';
- break;
- }
- if (sym_is_changable(sym)) {
- if (sym->rev_dep.tri == mod)
- item_make(menu,
- 't', "{%c}", ch);
- else
- item_make(menu,
- 't', "<%c>", ch);
- } else
- item_make(menu, 't', "-%c-", ch);
- break;
- default:
- tmp = 2 + strlen(sym_get_string_value(sym));
- item_make(menu, 's', " (%s)",
- sym_get_string_value(sym));
- tmp = indent - tmp + 4;
- if (tmp < 0)
- tmp = 0;
- item_add_str("%*c%s%s", tmp, ' ',
- _(menu_get_prompt(menu)),
- (sym_has_value(sym) ||
- !sym_is_changable(sym)) ? "" :
- _(" (NEW)"));
- goto conf_childs;
- }
- }
- item_add_str("%*c%s%s", indent + 1, ' ',
- _(menu_get_prompt(menu)),
- (sym_has_value(sym) || !sym_is_changable(sym)) ?
- "" : _(" (NEW)"));
- if (menu->prompt && menu->prompt->type == P_MENU) {
- item_add_str(" --->");
- return;
- }
- }
-
-conf_childs:
- indent += doint;
- for (child = menu->list; child; child = child->next)
- build_conf(child);
- indent -= doint;
-}
-
-static void reset_menu(void)
-{
- unpost_menu(curses_menu);
- clean_items();
-}
-
-/* adjust the menu to show this item.
- * prefer not to scroll the menu if possible*/
-static void center_item(int selected_index, int *last_top_row)
-{
- int toprow;
-
- set_top_row(curses_menu, *last_top_row);
- toprow = top_row(curses_menu);
- if (selected_index < toprow ||
- selected_index >= toprow+mwin_max_lines) {
- toprow = max(selected_index-mwin_max_lines/2, 0);
- if (toprow >= item_count(curses_menu)-mwin_max_lines)
- toprow = item_count(curses_menu)-mwin_max_lines;
- set_top_row(curses_menu, toprow);
- }
- set_current_item(curses_menu,
- curses_menu_items[selected_index]);
- *last_top_row = toprow;
- post_menu(curses_menu);
- refresh_all_windows(main_window);
-}
-
-/* this function assumes reset_menu has been called before */
-static void show_menu(const char *prompt, const char *instructions,
- int selected_index, int *last_top_row)
-{
- int maxx, maxy;
- WINDOW *menu_window;
-
- current_instructions = instructions;
-
- clear();
- (void) wattrset(main_window, attributes[NORMAL]);
- print_in_middle(stdscr, 1, 0, COLS,
- menu_backtitle,
- attributes[MAIN_HEADING]);
-
- (void) wattrset(main_window, attributes[MAIN_MENU_BOX]);
- box(main_window, 0, 0);
- (void) wattrset(main_window, attributes[MAIN_MENU_HEADING]);
- mvwprintw(main_window, 0, 3, " %s ", prompt);
- (void) wattrset(main_window, attributes[NORMAL]);
-
- set_menu_items(curses_menu, curses_menu_items);
-
- /* position the menu at the middle of the screen */
- scale_menu(curses_menu, &maxy, &maxx);
- maxx = min(maxx, mwin_max_cols-2);
- maxy = mwin_max_lines;
- menu_window = derwin(main_window,
- maxy,
- maxx,
- 2,
- (mwin_max_cols-maxx)/2);
- keypad(menu_window, TRUE);
- set_menu_win(curses_menu, menu_window);
- set_menu_sub(curses_menu, menu_window);
-
- /* must reassert this after changing items, otherwise returns to a
- * default of 16
- */
- set_menu_format(curses_menu, maxy, 1);
- center_item(selected_index, last_top_row);
- set_menu_format(curses_menu, maxy, 1);
-
- print_function_line();
-
- /* Post the menu */
- post_menu(curses_menu);
- refresh_all_windows(main_window);
-}
-
-static void adj_match_dir(match_f *match_direction)
-{
- if (*match_direction == FIND_NEXT_MATCH_DOWN)
- *match_direction =
- MATCH_TINKER_PATTERN_DOWN;
- else if (*match_direction == FIND_NEXT_MATCH_UP)
- *match_direction =
- MATCH_TINKER_PATTERN_UP;
- /* else, do no change.. */
-}
-
-struct match_state
-{
- int in_search;
- match_f match_direction;
- char pattern[256];
-};
-
-/* Return 0 means I have handled the key. In such a case, ans should hold the
- * item to center, or -1 otherwise.
- * Else return -1 .
- */
-static int do_match(int key, struct match_state *state, int *ans)
-{
- char c = (char) key;
- int terminate_search = 0;
- *ans = -1;
- if (key == '/' || (state->in_search && key == 27)) {
- move(0, 0);
- refresh();
- clrtoeol();
- state->in_search = 1-state->in_search;
- bzero(state->pattern, sizeof(state->pattern));
- state->match_direction = MATCH_TINKER_PATTERN_DOWN;
- return 0;
- } else if (!state->in_search)
- return 1;
-
- if (isalnum(c) || isgraph(c) || c == ' ') {
- state->pattern[strlen(state->pattern)] = c;
- state->pattern[strlen(state->pattern)] = '\0';
- adj_match_dir(&state->match_direction);
- *ans = get_mext_match(state->pattern,
- state->match_direction);
- } else if (key == KEY_DOWN) {
- state->match_direction = FIND_NEXT_MATCH_DOWN;
- *ans = get_mext_match(state->pattern,
- state->match_direction);
- } else if (key == KEY_UP) {
- state->match_direction = FIND_NEXT_MATCH_UP;
- *ans = get_mext_match(state->pattern,
- state->match_direction);
- } else if (key == KEY_BACKSPACE || key == 127) {
- state->pattern[strlen(state->pattern)-1] = '\0';
- adj_match_dir(&state->match_direction);
- } else
- terminate_search = 1;
-
- if (terminate_search) {
- state->in_search = 0;
- bzero(state->pattern, sizeof(state->pattern));
- move(0, 0);
- refresh();
- clrtoeol();
- return -1;
- }
- return 0;
-}
-
-static void conf(struct menu *menu)
-{
- struct menu *submenu = 0;
- const char *prompt = menu_get_prompt(menu);
- struct symbol *sym;
- int res;
- int current_index = 0;
- int last_top_row = 0;
- struct match_state match_state = {
- .in_search = 0,
- .match_direction = MATCH_TINKER_PATTERN_DOWN,
- .pattern = "",
- };
-
- while (!global_exit) {
- reset_menu();
- current_menu = menu;
- build_conf(menu);
- if (!child_count)
- break;
-
- show_menu(prompt ? _(prompt) : _("Main Menu"),
- _(menu_instructions),
- current_index, &last_top_row);
- keypad((menu_win(curses_menu)), TRUE);
- while (!global_exit) {
- if (match_state.in_search) {
- mvprintw(0, 0,
- "searching: %s", match_state.pattern);
- clrtoeol();
- }
- refresh_all_windows(main_window);
- res = wgetch(menu_win(curses_menu));
- if (!res)
- break;
- if (do_match(res, &match_state, ¤t_index) == 0) {
- if (current_index != -1)
- center_item(current_index,
- &last_top_row);
- continue;
- }
- if (process_special_keys(&res,
- (struct menu *) item_data()))
- break;
- switch (res) {
- case KEY_DOWN:
- menu_driver(curses_menu, REQ_DOWN_ITEM);
- break;
- case KEY_UP:
- menu_driver(curses_menu, REQ_UP_ITEM);
- break;
- case KEY_NPAGE:
- menu_driver(curses_menu, REQ_SCR_DPAGE);
- break;
- case KEY_PPAGE:
- menu_driver(curses_menu, REQ_SCR_UPAGE);
- break;
- case KEY_HOME:
- menu_driver(curses_menu, REQ_FIRST_ITEM);
- break;
- case KEY_END:
- menu_driver(curses_menu, REQ_LAST_ITEM);
- break;
- case 'h':
- case '?':
- show_help((struct menu *) item_data());
- break;
- }
- if (res == 10 || res == 27 ||
- res == 32 || res == 'n' || res == 'y' ||
- res == KEY_LEFT || res == KEY_RIGHT ||
- res == 'm')
- break;
- refresh_all_windows(main_window);
- }
-
- refresh_all_windows(main_window);
- /* if ESC or left*/
- if (res == 27 || (menu != &rootmenu && res == KEY_LEFT))
- break;
-
- /* remember location in the menu */
- last_top_row = top_row(curses_menu);
- current_index = curses_item_index();
-
- if (!item_tag())
- continue;
-
- submenu = (struct menu *) item_data();
- if (!submenu || !menu_is_visible(submenu))
- continue;
- sym = submenu->sym;
-
- switch (res) {
- case ' ':
- if (item_is_tag('t'))
- sym_toggle_tristate_value(sym);
- else if (item_is_tag('m'))
- conf(submenu);
- break;
- case KEY_RIGHT:
- case 10: /* ENTER WAS PRESSED */
- switch (item_tag()) {
- case 'm':
- if (single_menu_mode)
- submenu->data =
- (void *) (long) !submenu->data;
- else
- conf(submenu);
- break;
- case 't':
- if (sym_is_choice(sym) &&
- sym_get_tristate_value(sym) == yes)
- conf_choice(submenu);
- else if (submenu->prompt &&
- submenu->prompt->type == P_MENU)
- conf(submenu);
- else if (res == 10)
- sym_toggle_tristate_value(sym);
- break;
- case 's':
- conf_string(submenu);
- break;
- }
- break;
- case 'y':
- if (item_is_tag('t')) {
- if (sym_set_tristate_value(sym, yes))
- break;
- if (sym_set_tristate_value(sym, mod))
- btn_dialog(main_window, setmod_text, 0);
- }
- break;
- case 'n':
- if (item_is_tag('t'))
- sym_set_tristate_value(sym, no);
- break;
- case 'm':
- if (item_is_tag('t'))
- sym_set_tristate_value(sym, mod);
- break;
- }
- }
-}
-
-static void conf_message_callback(const char *fmt, va_list ap)
-{
- char buf[1024];
-
- vsnprintf(buf, sizeof(buf), fmt, ap);
- btn_dialog(main_window, buf, 1, "<OK>");
-}
-
-static void show_help(struct menu *menu)
-{
- struct gstr help;
-
- if (!menu)
- return;
-
- help = str_new();
- menu_get_ext_help(menu, &help);
- show_scroll_win(main_window, _(menu_get_prompt(menu)), str_get(&help));
- str_free(&help);
-}
-
-static void conf_choice(struct menu *menu)
-{
- const char *prompt = _(menu_get_prompt(menu));
- struct menu *child = 0;
- struct symbol *active;
- int selected_index = 0;
- int last_top_row = 0;
- int res, i = 0;
- struct match_state match_state = {
- .in_search = 0,
- .match_direction = MATCH_TINKER_PATTERN_DOWN,
- .pattern = "",
- };
-
- active = sym_get_choice_value(menu->sym);
- /* this is mostly duplicated from the conf() function. */
- while (!global_exit) {
- reset_menu();
-
- for (i = 0, child = menu->list; child; child = child->next) {
- if (!show_all_items && !menu_is_visible(child))
- continue;
-
- if (child->sym == sym_get_choice_value(menu->sym))
- item_make(child, ':', "<X> %s",
- _(menu_get_prompt(child)));
- else if (child->sym)
- item_make(child, ':', " %s",
- _(menu_get_prompt(child)));
- else
- item_make(child, ':', "*** %s ***",
- _(menu_get_prompt(child)));
-
- if (child->sym == active){
- last_top_row = top_row(curses_menu);
- selected_index = i;
- }
- i++;
- }
- show_menu(prompt ? _(prompt) : _("Choice Menu"),
- _(radiolist_instructions),
- selected_index,
- &last_top_row);
- while (!global_exit) {
- if (match_state.in_search) {
- mvprintw(0, 0, "searching: %s",
- match_state.pattern);
- clrtoeol();
- }
- refresh_all_windows(main_window);
- res = wgetch(menu_win(curses_menu));
- if (!res)
- break;
- if (do_match(res, &match_state, &selected_index) == 0) {
- if (selected_index != -1)
- center_item(selected_index,
- &last_top_row);
- continue;
- }
- if (process_special_keys(
- &res,
- (struct menu *) item_data()))
- break;
- switch (res) {
- case KEY_DOWN:
- menu_driver(curses_menu, REQ_DOWN_ITEM);
- break;
- case KEY_UP:
- menu_driver(curses_menu, REQ_UP_ITEM);
- break;
- case KEY_NPAGE:
- menu_driver(curses_menu, REQ_SCR_DPAGE);
- break;
- case KEY_PPAGE:
- menu_driver(curses_menu, REQ_SCR_UPAGE);
- break;
- case KEY_HOME:
- menu_driver(curses_menu, REQ_FIRST_ITEM);
- break;
- case KEY_END:
- menu_driver(curses_menu, REQ_LAST_ITEM);
- break;
- case 'h':
- case '?':
- show_help((struct menu *) item_data());
- break;
- }
- if (res == 10 || res == 27 || res == ' ' ||
- res == KEY_LEFT){
- break;
- }
- refresh_all_windows(main_window);
- }
- /* if ESC or left */
- if (res == 27 || res == KEY_LEFT)
- break;
-
- child = item_data();
- if (!child || !menu_is_visible(child) || !child->sym)
- continue;
- switch (res) {
- case ' ':
- case 10:
- case KEY_RIGHT:
- sym_set_tristate_value(child->sym, yes);
- return;
- case 'h':
- case '?':
- show_help(child);
- active = child->sym;
- break;
- case KEY_EXIT:
- return;
- }
- }
-}
-
-static void conf_string(struct menu *menu)
-{
- const char *prompt = menu_get_prompt(menu);
-
- while (1) {
- int res;
- const char *heading;
-
- switch (sym_get_type(menu->sym)) {
- case S_INT:
- heading = _(inputbox_instructions_int);
- break;
- case S_HEX:
- heading = _(inputbox_instructions_hex);
- break;
- case S_STRING:
- heading = _(inputbox_instructions_string);
- break;
- default:
- heading = _("Internal nconf error!");
- }
- res = dialog_inputbox(main_window,
- prompt ? _(prompt) : _("Main Menu"),
- heading,
- sym_get_string_value(menu->sym),
- &dialog_input_result,
- &dialog_input_result_len);
- switch (res) {
- case 0:
- if (sym_set_string_value(menu->sym,
- dialog_input_result))
- return;
- btn_dialog(main_window,
- _("You have made an invalid entry."), 0);
- break;
- case 1:
- show_help(menu);
- break;
- case KEY_EXIT:
- return;
- }
- }
-}
-
-static void conf_load(void)
-{
- while (1) {
- int res;
- res = dialog_inputbox(main_window,
- NULL, load_config_text,
- filename,
- &dialog_input_result,
- &dialog_input_result_len);
- switch (res) {
- case 0:
- if (!dialog_input_result[0])
- return;
- if (!conf_read(dialog_input_result)) {
- set_config_filename(dialog_input_result);
- sym_set_change_count(1);
- return;
- }
- btn_dialog(main_window, _("File does not exist!"), 0);
- break;
- case 1:
- show_scroll_win(main_window,
- _("Load Alternate Configuration"),
- load_config_help);
- break;
- case KEY_EXIT:
- return;
- }
- }
-}
-
-static void conf_save(void)
-{
- while (1) {
- int res;
- res = dialog_inputbox(main_window,
- NULL, save_config_text,
- filename,
- &dialog_input_result,
- &dialog_input_result_len);
- switch (res) {
- case 0:
- if (!dialog_input_result[0])
- return;
- res = conf_write(dialog_input_result);
- if (!res) {
- set_config_filename(dialog_input_result);
- return;
- }
- btn_dialog(main_window, _("Can't create file! "
- "Probably a nonexistent directory."),
- 1, "<OK>");
- break;
- case 1:
- show_scroll_win(main_window,
- _("Save Alternate Configuration"),
- save_config_help);
- break;
- case KEY_EXIT:
- return;
- }
- }
-}
-
-void setup_windows(void)
-{
- if (main_window != NULL)
- delwin(main_window);
-
- /* set up the menu and menu window */
- main_window = newwin(LINES-2, COLS-2, 2, 1);
- keypad(main_window, TRUE);
- mwin_max_lines = LINES-7;
- mwin_max_cols = COLS-6;
-
- /* panels order is from bottom to top */
- new_panel(main_window);
-}
-
-int main(int ac, char **av)
-{
- char *mode;
-
- setlocale(LC_ALL, "");
- bindtextdomain(PACKAGE, LOCALEDIR);
- textdomain(PACKAGE);
-
- conf_parse(av[1]);
- conf_read(NULL);
-
- mode = getenv("NCONFIG_MODE");
- if (mode) {
- if (!strcasecmp(mode, "single_menu"))
- single_menu_mode = 1;
- }
-
- /* Initialize curses */
- initscr();
- /* set color theme */
- set_colors();
-
- cbreak();
- noecho();
- keypad(stdscr, TRUE);
- curs_set(0);
-
- if (COLS < 75 || LINES < 20) {
- endwin();
- printf("Your terminal should have at "
- "least 20 lines and 75 columns\n");
- return 1;
- }
-
- notimeout(stdscr, FALSE);
- ESCDELAY = 1;
-
- /* set btns menu */
- curses_menu = new_menu(curses_menu_items);
- menu_opts_off(curses_menu, O_SHOWDESC);
- menu_opts_on(curses_menu, O_SHOWMATCH);
- menu_opts_on(curses_menu, O_ONEVALUE);
- menu_opts_on(curses_menu, O_NONCYCLIC);
- menu_opts_on(curses_menu, O_IGNORECASE);
- set_menu_mark(curses_menu, " ");
- set_menu_fore(curses_menu, attributes[MAIN_MENU_FORE]);
- set_menu_back(curses_menu, attributes[MAIN_MENU_BACK]);
- set_menu_grey(curses_menu, attributes[MAIN_MENU_GREY]);
-
- set_config_filename(conf_get_configname());
- setup_windows();
-
- /* check for KEY_FUNC(1) */
- if (has_key(KEY_F(1)) == FALSE) {
- show_scroll_win(main_window,
- _("Instructions"),
- _(menu_no_f_instructions));
- }
-
- conf_set_message_callback(conf_message_callback);
- /* do the work */
- while (!global_exit) {
- conf(&rootmenu);
- if (!global_exit && do_exit() == 0)
- break;
- }
- /* ok, we are done */
- unpost_menu(curses_menu);
- free_menu(curses_menu);
- delwin(main_window);
- clear();
- refresh();
- endwin();
- return 0;
-}
-
+++ /dev/null
-/*
- * Copyright (C) 2008 Nir Tzachar <nir.tzachar@gmail.com?
- * Released under the terms of the GNU GPL v2.0.
- *
- * Derived from menuconfig.
- *
- */
-#include "nconf.h"
-
-/* a list of all the different widgets we use */
-attributes_t attributes[ATTR_MAX+1] = {0};
-
-/* available colors:
- COLOR_BLACK 0
- COLOR_RED 1
- COLOR_GREEN 2
- COLOR_YELLOW 3
- COLOR_BLUE 4
- COLOR_MAGENTA 5
- COLOR_CYAN 6
- COLOR_WHITE 7
- */
-static void set_normal_colors(void)
-{
- init_pair(NORMAL, -1, -1);
- init_pair(MAIN_HEADING, COLOR_MAGENTA, -1);
-
- /* FORE is for the selected item */
- init_pair(MAIN_MENU_FORE, -1, -1);
- /* BACK for all the rest */
- init_pair(MAIN_MENU_BACK, -1, -1);
- init_pair(MAIN_MENU_GREY, -1, -1);
- init_pair(MAIN_MENU_HEADING, COLOR_GREEN, -1);
- init_pair(MAIN_MENU_BOX, COLOR_YELLOW, -1);
-
- init_pair(SCROLLWIN_TEXT, -1, -1);
- init_pair(SCROLLWIN_HEADING, COLOR_GREEN, -1);
- init_pair(SCROLLWIN_BOX, COLOR_YELLOW, -1);
-
- init_pair(DIALOG_TEXT, -1, -1);
- init_pair(DIALOG_BOX, COLOR_YELLOW, -1);
- init_pair(DIALOG_MENU_BACK, COLOR_YELLOW, -1);
- init_pair(DIALOG_MENU_FORE, COLOR_RED, -1);
-
- init_pair(INPUT_BOX, COLOR_YELLOW, -1);
- init_pair(INPUT_HEADING, COLOR_GREEN, -1);
- init_pair(INPUT_TEXT, -1, -1);
- init_pair(INPUT_FIELD, -1, -1);
-
- init_pair(FUNCTION_HIGHLIGHT, -1, -1);
- init_pair(FUNCTION_TEXT, COLOR_BLUE, -1);
-}
-
-/* available attributes:
- A_NORMAL Normal display (no highlight)
- A_STANDOUT Best highlighting mode of the terminal.
- A_UNDERLINE Underlining
- A_REVERSE Reverse video
- A_BLINK Blinking
- A_DIM Half bright
- A_BOLD Extra bright or bold
- A_PROTECT Protected mode
- A_INVIS Invisible or blank mode
- A_ALTCHARSET Alternate character set
- A_CHARTEXT Bit-mask to extract a character
- COLOR_PAIR(n) Color-pair number n
- */
-static void normal_color_theme(void)
-{
- /* automatically add color... */
-#define mkattr(name, attr) do { \
-attributes[name] = attr | COLOR_PAIR(name); } while (0)
- mkattr(NORMAL, NORMAL);
- mkattr(MAIN_HEADING, A_BOLD | A_UNDERLINE);
-
- mkattr(MAIN_MENU_FORE, A_REVERSE);
- mkattr(MAIN_MENU_BACK, A_NORMAL);
- mkattr(MAIN_MENU_GREY, A_NORMAL);
- mkattr(MAIN_MENU_HEADING, A_BOLD);
- mkattr(MAIN_MENU_BOX, A_NORMAL);
-
- mkattr(SCROLLWIN_TEXT, A_NORMAL);
- mkattr(SCROLLWIN_HEADING, A_BOLD);
- mkattr(SCROLLWIN_BOX, A_BOLD);
-
- mkattr(DIALOG_TEXT, A_BOLD);
- mkattr(DIALOG_BOX, A_BOLD);
- mkattr(DIALOG_MENU_FORE, A_STANDOUT);
- mkattr(DIALOG_MENU_BACK, A_NORMAL);
-
- mkattr(INPUT_BOX, A_NORMAL);
- mkattr(INPUT_HEADING, A_BOLD);
- mkattr(INPUT_TEXT, A_NORMAL);
- mkattr(INPUT_FIELD, A_UNDERLINE);
-
- mkattr(FUNCTION_HIGHLIGHT, A_BOLD);
- mkattr(FUNCTION_TEXT, A_REVERSE);
-}
-
-static void no_colors_theme(void)
-{
- /* automatically add highlight, no color */
-#define mkattrn(name, attr) { attributes[name] = attr; }
-
- mkattrn(NORMAL, NORMAL);
- mkattrn(MAIN_HEADING, A_BOLD | A_UNDERLINE);
-
- mkattrn(MAIN_MENU_FORE, A_STANDOUT);
- mkattrn(MAIN_MENU_BACK, A_NORMAL);
- mkattrn(MAIN_MENU_GREY, A_NORMAL);
- mkattrn(MAIN_MENU_HEADING, A_BOLD);
- mkattrn(MAIN_MENU_BOX, A_NORMAL);
-
- mkattrn(SCROLLWIN_TEXT, A_NORMAL);
- mkattrn(SCROLLWIN_HEADING, A_BOLD);
- mkattrn(SCROLLWIN_BOX, A_BOLD);
-
- mkattrn(DIALOG_TEXT, A_NORMAL);
- mkattrn(DIALOG_BOX, A_BOLD);
- mkattrn(DIALOG_MENU_FORE, A_STANDOUT);
- mkattrn(DIALOG_MENU_BACK, A_NORMAL);
-
- mkattrn(INPUT_BOX, A_BOLD);
- mkattrn(INPUT_HEADING, A_BOLD);
- mkattrn(INPUT_TEXT, A_NORMAL);
- mkattrn(INPUT_FIELD, A_UNDERLINE);
-
- mkattrn(FUNCTION_HIGHLIGHT, A_BOLD);
- mkattrn(FUNCTION_TEXT, A_REVERSE);
-}
-
-void set_colors()
-{
- start_color();
- use_default_colors();
- set_normal_colors();
- if (has_colors()) {
- normal_color_theme();
- } else {
- /* give defaults */
- no_colors_theme();
- }
-}
-
-
-/* this changes the windows attributes !!! */
-void print_in_middle(WINDOW *win,
- int starty,
- int startx,
- int width,
- const char *string,
- chtype color)
-{ int length, x, y;
- float temp;
-
-
- if (win == NULL)
- win = stdscr;
- getyx(win, y, x);
- if (startx != 0)
- x = startx;
- if (starty != 0)
- y = starty;
- if (width == 0)
- width = 80;
-
- length = strlen(string);
- temp = (width - length) / 2;
- x = startx + (int)temp;
- (void) wattrset(win, color);
- mvwprintw(win, y, x, "%s", string);
- refresh();
-}
-
-int get_line_no(const char *text)
-{
- int i;
- int total = 1;
-
- if (!text)
- return 0;
-
- for (i = 0; text[i] != '\0'; i++)
- if (text[i] == '\n')
- total++;
- return total;
-}
-
-const char *get_line(const char *text, int line_no)
-{
- int i;
- int lines = 0;
-
- if (!text)
- return 0;
-
- for (i = 0; text[i] != '\0' && lines < line_no; i++)
- if (text[i] == '\n')
- lines++;
- return text+i;
-}
-
-int get_line_length(const char *line)
-{
- int res = 0;
- while (*line != '\0' && *line != '\n') {
- line++;
- res++;
- }
- return res;
-}
-
-/* print all lines to the window. */
-void fill_window(WINDOW *win, const char *text)
-{
- int x, y;
- int total_lines = get_line_no(text);
- int i;
-
- getmaxyx(win, y, x);
- /* do not go over end of line */
- total_lines = min(total_lines, y);
- for (i = 0; i < total_lines; i++) {
- char tmp[x+10];
- const char *line = get_line(text, i);
- int len = get_line_length(line);
- strncpy(tmp, line, min(len, x));
- tmp[len] = '\0';
- mvwprintw(win, i, 0, "%s", tmp);
- }
-}
-
-/* get the message, and buttons.
- * each button must be a char*
- * return the selected button
- *
- * this dialog is used for 2 different things:
- * 1) show a text box, no buttons.
- * 2) show a dialog, with horizontal buttons
- */
-int btn_dialog(WINDOW *main_window, const char *msg, int btn_num, ...)
-{
- va_list ap;
- char *btn;
- int btns_width = 0;
- int msg_lines = 0;
- int msg_width = 0;
- int total_width;
- int win_rows = 0;
- WINDOW *win;
- WINDOW *msg_win;
- WINDOW *menu_win;
- MENU *menu;
- ITEM *btns[btn_num+1];
- int i, x, y;
- int res = -1;
-
-
- va_start(ap, btn_num);
- for (i = 0; i < btn_num; i++) {
- btn = va_arg(ap, char *);
- btns[i] = new_item(btn, "");
- btns_width += strlen(btn)+1;
- }
- va_end(ap);
- btns[btn_num] = NULL;
-
- /* find the widest line of msg: */
- msg_lines = get_line_no(msg);
- for (i = 0; i < msg_lines; i++) {
- const char *line = get_line(msg, i);
- int len = get_line_length(line);
- if (msg_width < len)
- msg_width = len;
- }
-
- total_width = max(msg_width, btns_width);
- /* place dialog in middle of screen */
- y = (LINES-(msg_lines+4))/2;
- x = (COLS-(total_width+4))/2;
-
-
- /* create the windows */
- if (btn_num > 0)
- win_rows = msg_lines+4;
- else
- win_rows = msg_lines+2;
-
- win = newwin(win_rows, total_width+4, y, x);
- keypad(win, TRUE);
- menu_win = derwin(win, 1, btns_width, win_rows-2,
- 1+(total_width+2-btns_width)/2);
- menu = new_menu(btns);
- msg_win = derwin(win, win_rows-2, msg_width, 1,
- 1+(total_width+2-msg_width)/2);
-
- set_menu_fore(menu, attributes[DIALOG_MENU_FORE]);
- set_menu_back(menu, attributes[DIALOG_MENU_BACK]);
-
- (void) wattrset(win, attributes[DIALOG_BOX]);
- box(win, 0, 0);
-
- /* print message */
- (void) wattrset(msg_win, attributes[DIALOG_TEXT]);
- fill_window(msg_win, msg);
-
- set_menu_win(menu, win);
- set_menu_sub(menu, menu_win);
- set_menu_format(menu, 1, btn_num);
- menu_opts_off(menu, O_SHOWDESC);
- menu_opts_off(menu, O_SHOWMATCH);
- menu_opts_on(menu, O_ONEVALUE);
- menu_opts_on(menu, O_NONCYCLIC);
- set_menu_mark(menu, "");
- post_menu(menu);
-
-
- touchwin(win);
- refresh_all_windows(main_window);
- while ((res = wgetch(win))) {
- switch (res) {
- case KEY_LEFT:
- menu_driver(menu, REQ_LEFT_ITEM);
- break;
- case KEY_RIGHT:
- menu_driver(menu, REQ_RIGHT_ITEM);
- break;
- case 10: /* ENTER */
- case 27: /* ESCAPE */
- case ' ':
- case KEY_F(F_BACK):
- case KEY_F(F_EXIT):
- break;
- }
- touchwin(win);
- refresh_all_windows(main_window);
-
- if (res == 10 || res == ' ') {
- res = item_index(current_item(menu));
- break;
- } else if (res == 27 || res == KEY_F(F_BACK) ||
- res == KEY_F(F_EXIT)) {
- res = KEY_EXIT;
- break;
- }
- }
-
- unpost_menu(menu);
- free_menu(menu);
- for (i = 0; i < btn_num; i++)
- free_item(btns[i]);
-
- delwin(win);
- return res;
-}
-
-int dialog_inputbox(WINDOW *main_window,
- const char *title, const char *prompt,
- const char *init, char **resultp, int *result_len)
-{
- int prompt_lines = 0;
- int prompt_width = 0;
- WINDOW *win;
- WINDOW *prompt_win;
- WINDOW *form_win;
- PANEL *panel;
- int i, x, y;
- int res = -1;
- int cursor_position = strlen(init);
- int cursor_form_win;
- char *result = *resultp;
-
- if (strlen(init)+1 > *result_len) {
- *result_len = strlen(init)+1;
- *resultp = result = realloc(result, *result_len);
- }
-
- /* find the widest line of msg: */
- prompt_lines = get_line_no(prompt);
- for (i = 0; i < prompt_lines; i++) {
- const char *line = get_line(prompt, i);
- int len = get_line_length(line);
- prompt_width = max(prompt_width, len);
- }
-
- if (title)
- prompt_width = max(prompt_width, strlen(title));
-
- /* place dialog in middle of screen */
- y = (LINES-(prompt_lines+4))/2;
- x = (COLS-(prompt_width+4))/2;
-
- strncpy(result, init, *result_len);
-
- /* create the windows */
- win = newwin(prompt_lines+6, prompt_width+7, y, x);
- prompt_win = derwin(win, prompt_lines+1, prompt_width, 2, 2);
- form_win = derwin(win, 1, prompt_width, prompt_lines+3, 2);
- keypad(form_win, TRUE);
-
- (void) wattrset(form_win, attributes[INPUT_FIELD]);
-
- (void) wattrset(win, attributes[INPUT_BOX]);
- box(win, 0, 0);
- (void) wattrset(win, attributes[INPUT_HEADING]);
- if (title)
- mvwprintw(win, 0, 3, "%s", title);
-
- /* print message */
- (void) wattrset(prompt_win, attributes[INPUT_TEXT]);
- fill_window(prompt_win, prompt);
-
- mvwprintw(form_win, 0, 0, "%*s", prompt_width, " ");
- cursor_form_win = min(cursor_position, prompt_width-1);
- mvwprintw(form_win, 0, 0, "%s",
- result + cursor_position-cursor_form_win);
-
- /* create panels */
- panel = new_panel(win);
-
- /* show the cursor */
- curs_set(1);
-
- touchwin(win);
- refresh_all_windows(main_window);
- while ((res = wgetch(form_win))) {
- int len = strlen(result);
- switch (res) {
- case 10: /* ENTER */
- case 27: /* ESCAPE */
- case KEY_F(F_HELP):
- case KEY_F(F_EXIT):
- case KEY_F(F_BACK):
- break;
- case 127:
- case KEY_BACKSPACE:
- if (cursor_position > 0) {
- memmove(&result[cursor_position-1],
- &result[cursor_position],
- len-cursor_position+1);
- cursor_position--;
- cursor_form_win--;
- len--;
- }
- break;
- case KEY_DC:
- if (cursor_position >= 0 && cursor_position < len) {
- memmove(&result[cursor_position],
- &result[cursor_position+1],
- len-cursor_position+1);
- len--;
- }
- break;
- case KEY_UP:
- case KEY_RIGHT:
- if (cursor_position < len) {
- cursor_position++;
- cursor_form_win++;
- }
- break;
- case KEY_DOWN:
- case KEY_LEFT:
- if (cursor_position > 0) {
- cursor_position--;
- cursor_form_win--;
- }
- break;
- case KEY_HOME:
- cursor_position = 0;
- cursor_form_win = 0;
- break;
- case KEY_END:
- cursor_position = len;
- cursor_form_win = min(cursor_position, prompt_width-1);
- break;
- default:
- if ((isgraph(res) || isspace(res))) {
- /* one for new char, one for '\0' */
- if (len+2 > *result_len) {
- *result_len = len+2;
- *resultp = result = realloc(result,
- *result_len);
- }
- /* insert the char at the proper position */
- memmove(&result[cursor_position+1],
- &result[cursor_position],
- len-cursor_position+1);
- result[cursor_position] = res;
- cursor_position++;
- cursor_form_win++;
- len++;
- } else {
- mvprintw(0, 0, "unknown key: %d\n", res);
- }
- break;
- }
- if (cursor_form_win < 0)
- cursor_form_win = 0;
- else if (cursor_form_win > prompt_width-1)
- cursor_form_win = prompt_width-1;
-
- wmove(form_win, 0, 0);
- wclrtoeol(form_win);
- mvwprintw(form_win, 0, 0, "%*s", prompt_width, " ");
- mvwprintw(form_win, 0, 0, "%s",
- result + cursor_position-cursor_form_win);
- wmove(form_win, 0, cursor_form_win);
- touchwin(win);
- refresh_all_windows(main_window);
-
- if (res == 10) {
- res = 0;
- break;
- } else if (res == 27 || res == KEY_F(F_BACK) ||
- res == KEY_F(F_EXIT)) {
- res = KEY_EXIT;
- break;
- } else if (res == KEY_F(F_HELP)) {
- res = 1;
- break;
- }
- }
-
- /* hide the cursor */
- curs_set(0);
- del_panel(panel);
- delwin(prompt_win);
- delwin(form_win);
- delwin(win);
- return res;
-}
-
-/* refresh all windows in the correct order */
-void refresh_all_windows(WINDOW *main_window)
-{
- update_panels();
- touchwin(main_window);
- refresh();
-}
-
-/* layman's scrollable window... */
-void show_scroll_win(WINDOW *main_window,
- const char *title,
- const char *text)
-{
- int res;
- int total_lines = get_line_no(text);
- int x, y;
- int start_x = 0, start_y = 0;
- int text_lines = 0, text_cols = 0;
- int total_cols = 0;
- int win_cols = 0;
- int win_lines = 0;
- int i = 0;
- WINDOW *win;
- WINDOW *pad;
- PANEL *panel;
-
- /* find the widest line of msg: */
- total_lines = get_line_no(text);
- for (i = 0; i < total_lines; i++) {
- const char *line = get_line(text, i);
- int len = get_line_length(line);
- total_cols = max(total_cols, len+2);
- }
-
- /* create the pad */
- pad = newpad(total_lines+10, total_cols+10);
- (void) wattrset(pad, attributes[SCROLLWIN_TEXT]);
- fill_window(pad, text);
-
- win_lines = min(total_lines+4, LINES-2);
- win_cols = min(total_cols+2, COLS-2);
- text_lines = max(win_lines-4, 0);
- text_cols = max(win_cols-2, 0);
-
- /* place window in middle of screen */
- y = (LINES-win_lines)/2;
- x = (COLS-win_cols)/2;
-
- win = newwin(win_lines, win_cols, y, x);
- keypad(win, TRUE);
- /* show the help in the help window, and show the help panel */
- (void) wattrset(win, attributes[SCROLLWIN_BOX]);
- box(win, 0, 0);
- (void) wattrset(win, attributes[SCROLLWIN_HEADING]);
- mvwprintw(win, 0, 3, " %s ", title);
- panel = new_panel(win);
-
- /* handle scrolling */
- do {
-
- copywin(pad, win, start_y, start_x, 2, 2, text_lines,
- text_cols, 0);
- print_in_middle(win,
- text_lines+2,
- 0,
- text_cols,
- "<OK>",
- attributes[DIALOG_MENU_FORE]);
- wrefresh(win);
-
- res = wgetch(win);
- switch (res) {
- case KEY_NPAGE:
- case ' ':
- start_y += text_lines-2;
- break;
- case KEY_PPAGE:
- start_y -= text_lines+2;
- break;
- case KEY_HOME:
- start_y = 0;
- break;
- case KEY_END:
- start_y = total_lines-text_lines;
- break;
- case KEY_DOWN:
- case 'j':
- start_y++;
- break;
- case KEY_UP:
- case 'k':
- start_y--;
- break;
- case KEY_LEFT:
- case 'h':
- start_x--;
- break;
- case KEY_RIGHT:
- case 'l':
- start_x++;
- break;
- }
- if (res == 10 || res == 27 || res == 'q'
- || res == KEY_F(F_BACK) || res == KEY_F(F_EXIT)) {
- break;
- }
- if (start_y < 0)
- start_y = 0;
- if (start_y >= total_lines-text_lines)
- start_y = total_lines-text_lines;
- if (start_x < 0)
- start_x = 0;
- if (start_x >= total_cols-text_cols)
- start_x = total_cols-text_cols;
- } while (res);
-
- del_panel(panel);
- delwin(win);
- refresh_all_windows(main_window);
-}
+++ /dev/null
-/*
- * Copyright (C) 2008 Nir Tzachar <nir.tzachar@gmail.com?
- * Released under the terms of the GNU GPL v2.0.
- *
- * Derived from menuconfig.
- *
- */
-
-#include <ctype.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <locale.h>
-#include <curses.h>
-#include <menu.h>
-#include <panel.h>
-#include <form.h>
-
-#include <stdio.h>
-#include <time.h>
-#include <sys/time.h>
-
-#include "ncurses.h"
-
-#define max(a, b) ({\
- typeof(a) _a = a;\
- typeof(b) _b = b;\
- _a > _b ? _a : _b; })
-
-#define min(a, b) ({\
- typeof(a) _a = a;\
- typeof(b) _b = b;\
- _a < _b ? _a : _b; })
-
-typedef enum {
- NORMAL = 1,
- MAIN_HEADING,
- MAIN_MENU_BOX,
- MAIN_MENU_FORE,
- MAIN_MENU_BACK,
- MAIN_MENU_GREY,
- MAIN_MENU_HEADING,
- SCROLLWIN_TEXT,
- SCROLLWIN_HEADING,
- SCROLLWIN_BOX,
- DIALOG_TEXT,
- DIALOG_MENU_FORE,
- DIALOG_MENU_BACK,
- DIALOG_BOX,
- INPUT_BOX,
- INPUT_HEADING,
- INPUT_TEXT,
- INPUT_FIELD,
- FUNCTION_TEXT,
- FUNCTION_HIGHLIGHT,
- ATTR_MAX
-} attributes_t;
-extern attributes_t attributes[];
-
-typedef enum {
- F_HELP = 1,
- F_SYMBOL = 2,
- F_INSTS = 3,
- F_CONF = 4,
- F_BACK = 5,
- F_SAVE = 6,
- F_LOAD = 7,
- F_SEARCH = 8,
- F_EXIT = 9,
-} function_key;
-
-void set_colors(void);
-
-/* this changes the windows attributes !!! */
-void print_in_middle(WINDOW *win,
- int starty,
- int startx,
- int width,
- const char *string,
- chtype color);
-int get_line_length(const char *line);
-int get_line_no(const char *text);
-const char *get_line(const char *text, int line_no);
-void fill_window(WINDOW *win, const char *text);
-int btn_dialog(WINDOW *main_window, const char *msg, int btn_num, ...);
-int dialog_inputbox(WINDOW *main_window,
- const char *title, const char *prompt,
- const char *init, char **resultp, int *result_len);
-void refresh_all_windows(WINDOW *main_window);
-void show_scroll_win(WINDOW *main_window,
- const char *title,
- const char *text);
--- /dev/null
+SUFFIXES = .gperf
+
+noinst_LIBRARIES = libkconfigparser.a
+
+libkconfigparser_a_SOURCES = yconf.y
+dist_EXTRA_libkconfigparser_a_SOURCES = \
+ hconf.gperf lconf.l \
+ confdata.c menu.c symbol.c util.c \
+ expr.c expr.h lkc.h lkc_proto.h
+
+BUILT_SOURCES = hconf.c lconf.c
+
+.gperf.c:
+ $(GPERF) -t --output-file $@ -a -C -E -g -k 1,3,$$ -p -t $<
+
+# The following rule produces a warning:
+# parser/Makefile.am:31: user target `.l.c' defined here...
+# /usr/share/automake-1.11/am/lex.am: ... overrides Automake target
+# `.l.c' defined here
+#
+# This is expected, and can't be avoided (for now).
+# That's because, when working with lex+yacc sources, the default is to
+# build each files searately, and then link them together into the final
+# output. But the Linux kernel's parser simply #include-s the lexer,
+# so we can't put lconf.l into the _SOURCES (it's in EXTRA_SOURCES),
+# and thus automake does not catch the need to call lex.
+# Secondly, when flex is told to change the symbols' prefix (kconfig
+# uses zconf in lieue of the original yy), then the output file is
+# also renamed, but automake does not now that, and make would fail
+# because it would think no file was generated.
+.l.c:
+ $(LEXCOMPILE) -o$@ $<
--- /dev/null
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#include <sys/stat.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "lkc.h"
+
+static void conf_warning(const char *fmt, ...)
+ __attribute__ ((format (printf, 1, 2)));
+
+static void conf_message(const char *fmt, ...)
+ __attribute__ ((format (printf, 1, 2)));
+
+static const char *conf_filename;
+static int conf_lineno, conf_warnings, conf_unsaved;
+
+const char conf_defname[] = "arch/$ARCH/defconfig";
+
+static void conf_warning(const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ fprintf(stderr, "%s:%d:warning: ", conf_filename, conf_lineno);
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, "\n");
+ va_end(ap);
+ conf_warnings++;
+}
+
+static void conf_default_message_callback(const char *fmt, va_list ap)
+{
+ printf("#\n# ");
+ vprintf(fmt, ap);
+ printf("\n#\n");
+}
+
+static void (*conf_message_callback) (const char *fmt, va_list ap) =
+ conf_default_message_callback;
+void conf_set_message_callback(void (*fn) (const char *fmt, va_list ap))
+{
+ conf_message_callback = fn;
+}
+
+static void conf_message(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ if (conf_message_callback)
+ conf_message_callback(fmt, ap);
+}
+
+const char *conf_get_configname(void)
+{
+ char *name = getenv("KCONFIG_CONFIG");
+
+ return name ? name : ".config";
+}
+
+const char *conf_get_autoconfig_name(void)
+{
+ char *name = getenv("KCONFIG_AUTOCONFIG");
+
+ return name ? name : "include/config/auto.conf";
+}
+
+static char *conf_expand_value(const char *in)
+{
+ struct symbol *sym;
+ const char *src;
+ static char res_value[SYMBOL_MAXLENGTH];
+ char *dst, name[SYMBOL_MAXLENGTH];
+
+ res_value[0] = 0;
+ dst = name;
+ while ((src = strchr(in, '$'))) {
+ strncat(res_value, in, src - in);
+ src++;
+ dst = name;
+ while (isalnum(*src) || *src == '_')
+ *dst++ = *src++;
+ *dst = 0;
+ sym = sym_lookup(name, 0);
+ sym_calc_value(sym);
+ strcat(res_value, sym_get_string_value(sym));
+ in = src;
+ }
+ strcat(res_value, in);
+
+ return res_value;
+}
+
+char *conf_get_default_confname(void)
+{
+ struct stat buf;
+ static char fullname[PATH_MAX+1];
+ char *env, *name;
+
+ name = conf_expand_value(conf_defname);
+ env = getenv(SRCTREE);
+ if (env) {
+ sprintf(fullname, "%s/%s", env, name);
+ if (!stat(fullname, &buf))
+ return fullname;
+ }
+ return name;
+}
+
+static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
+{
+ char *p2;
+
+ switch (sym->type) {
+ case S_TRISTATE:
+ if (p[0] == 'm') {
+ sym->def[def].tri = mod;
+ sym->flags |= def_flags;
+ break;
+ }
+ /* fall through */
+ case S_BOOLEAN:
+ if (p[0] == 'y') {
+ sym->def[def].tri = yes;
+ sym->flags |= def_flags;
+ break;
+ }
+ if (p[0] == 'n') {
+ sym->def[def].tri = no;
+ sym->flags |= def_flags;
+ break;
+ }
+ conf_warning("symbol value '%s' invalid for %s", p, sym->name);
+ return 1;
+ case S_OTHER:
+ if (*p != '"') {
+ for (p2 = p; *p2 && !isspace(*p2); p2++)
+ ;
+ sym->type = S_STRING;
+ goto done;
+ }
+ /* fall through */
+ case S_STRING:
+ if (*p++ != '"')
+ break;
+ for (p2 = p; (p2 = strpbrk(p2, "\"\\")); p2++) {
+ if (*p2 == '"') {
+ *p2 = 0;
+ break;
+ }
+ memmove(p2, p2 + 1, strlen(p2));
+ }
+ if (!p2) {
+ conf_warning("invalid string found");
+ return 1;
+ }
+ /* fall through */
+ case S_INT:
+ case S_HEX:
+ done:
+ if (sym_string_valid(sym, p)) {
+ sym->def[def].val = strdup(p);
+ sym->flags |= def_flags;
+ } else {
+ conf_warning("symbol value '%s' invalid for %s", p, sym->name);
+ return 1;
+ }
+ break;
+ default:
+ ;
+ }
+ return 0;
+}
+
+int conf_read_simple(const char *name, int def)
+{
+ FILE *in = NULL;
+ char line[1024];
+ char *p, *p2;
+ struct symbol *sym;
+ int i, def_flags;
+
+ if (name) {
+ in = zconf_fopen(name);
+ } else {
+ struct property *prop;
+
+ name = conf_get_configname();
+ in = zconf_fopen(name);
+ if (in)
+ goto load;
+ sym_add_change_count(1);
+ if (!sym_defconfig_list) {
+ if (modules_sym)
+ sym_calc_value(modules_sym);
+ return 1;
+ }
+
+ for_all_defaults(sym_defconfig_list, prop) {
+ if (expr_calc_value(prop->visible.expr) == no ||
+ prop->expr->type != E_SYMBOL)
+ continue;
+ name = conf_expand_value(prop->expr->left.sym->name);
+ in = zconf_fopen(name);
+ if (in) {
+ conf_message(_("using defaults found in %s"),
+ name);
+ goto load;
+ }
+ }
+ }
+ if (!in)
+ return 1;
+
+load:
+ conf_filename = name;
+ conf_lineno = 0;
+ conf_warnings = 0;
+ conf_unsaved = 0;
+
+ def_flags = SYMBOL_DEF << def;
+ for_all_symbols(i, sym) {
+ sym->flags |= SYMBOL_CHANGED;
+ sym->flags &= ~(def_flags|SYMBOL_VALID);
+ if (sym_is_choice(sym))
+ sym->flags |= def_flags;
+ switch (sym->type) {
+ case S_INT:
+ case S_HEX:
+ case S_STRING:
+ if (sym->def[def].val)
+ free(sym->def[def].val);
+ /* fall through */
+ default:
+ sym->def[def].val = NULL;
+ sym->def[def].tri = no;
+ }
+ }
+
+ while (fgets(line, sizeof(line), in)) {
+ conf_lineno++;
+ sym = NULL;
+ if (line[0] == '#') {
+ if (memcmp(line + 2, CONFIG_, strlen(CONFIG_)))
+ continue;
+ p = strchr(line + 2 + strlen(CONFIG_), ' ');
+ if (!p)
+ continue;
+ *p++ = 0;
+ if (strncmp(p, "is not set", 10))
+ continue;
+ if (def == S_DEF_USER) {
+ sym = sym_find(line + 2 + strlen(CONFIG_));
+ if (!sym) {
+ sym_add_change_count(1);
+ goto setsym;
+ }
+ } else {
+ sym = sym_lookup(line + 2 + strlen(CONFIG_), 0);
+ if (sym->type == S_UNKNOWN)
+ sym->type = S_BOOLEAN;
+ }
+ if (sym->flags & def_flags) {
+ conf_warning("override: reassigning to symbol %s", sym->name);
+ }
+ switch (sym->type) {
+ case S_BOOLEAN:
+ case S_TRISTATE:
+ sym->def[def].tri = no;
+ sym->flags |= def_flags;
+ break;
+ default:
+ ;
+ }
+ } else if (memcmp(line, CONFIG_, strlen(CONFIG_)) == 0) {
+ p = strchr(line + strlen(CONFIG_), '=');
+ if (!p)
+ continue;
+ *p++ = 0;
+ p2 = strchr(p, '\n');
+ if (p2) {
+ *p2-- = 0;
+ if (*p2 == '\r')
+ *p2 = 0;
+ }
+ if (def == S_DEF_USER) {
+ sym = sym_find(line + strlen(CONFIG_));
+ if (!sym) {
+ sym_add_change_count(1);
+ goto setsym;
+ }
+ } else {
+ sym = sym_lookup(line + strlen(CONFIG_), 0);
+ if (sym->type == S_UNKNOWN)
+ sym->type = S_OTHER;
+ }
+ if (sym->flags & def_flags) {
+ conf_warning("override: reassigning to symbol %s", sym->name);
+ }
+ if (conf_set_sym_val(sym, def, def_flags, p))
+ continue;
+ } else {
+ if (line[0] != '\r' && line[0] != '\n')
+ conf_warning("unexpected data");
+ continue;
+ }
+setsym:
+ if (sym && sym_is_choice_value(sym)) {
+ struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
+ switch (sym->def[def].tri) {
+ case no:
+ break;
+ case mod:
+ if (cs->def[def].tri == yes) {
+ conf_warning("%s creates inconsistent choice state", sym->name);
+ cs->flags &= ~def_flags;
+ }
+ break;
+ case yes:
+ if (cs->def[def].tri != no)
+ conf_warning("override: %s changes choice state", sym->name);
+ cs->def[def].val = sym;
+ break;
+ }
+ cs->def[def].tri = EXPR_OR(cs->def[def].tri, sym->def[def].tri);
+ }
+ }
+ fclose(in);
+
+ if (modules_sym)
+ sym_calc_value(modules_sym);
+ return 0;
+}
+
+int conf_read(const char *name)
+{
+ struct symbol *sym, *choice_sym;
+ struct property *prop;
+ struct expr *e;
+ int i, flags;
+
+ sym_set_change_count(0);
+
+ if (conf_read_simple(name, S_DEF_USER))
+ return 1;
+
+ for_all_symbols(i, sym) {
+ sym_calc_value(sym);
+ if (sym_is_choice(sym) || (sym->flags & SYMBOL_AUTO))
+ goto sym_ok;
+ if (sym_has_value(sym) && (sym->flags & SYMBOL_WRITE)) {
+ /* check that calculated value agrees with saved value */
+ switch (sym->type) {
+ case S_BOOLEAN:
+ case S_TRISTATE:
+ if (sym->def[S_DEF_USER].tri != sym_get_tristate_value(sym))
+ break;
+ if (!sym_is_choice(sym))
+ goto sym_ok;
+ /* fall through */
+ default:
+ if (!strcmp(sym->curr.val, sym->def[S_DEF_USER].val))
+ goto sym_ok;
+ break;
+ }
+ } else if (!sym_has_value(sym) && !(sym->flags & SYMBOL_WRITE))
+ /* no previous value and not saved */
+ goto sym_ok;
+ conf_unsaved++;
+ /* maybe print value in verbose mode... */
+ sym_ok:
+ if (!sym_is_choice(sym))
+ continue;
+ /* The choice symbol only has a set value (and thus is not new)
+ * if all its visible childs have values.
+ */
+ prop = sym_get_choice_prop(sym);
+ flags = sym->flags;
+ expr_list_for_each_sym(prop->expr, e, choice_sym)
+ if (choice_sym->visible != no)
+ flags &= choice_sym->flags;
+ sym->flags &= flags | ~SYMBOL_DEF_USER;
+ }
+
+ for_all_symbols(i, sym) {
+ if (sym_has_value(sym) && !sym_is_choice_value(sym)) {
+ /* Reset values of generates values, so they'll appear
+ * as new, if they should become visible, but that
+ * doesn't quite work if the Kconfig and the saved
+ * configuration disagree.
+ */
+ if (sym->visible == no && !conf_unsaved)
+ sym->flags &= ~SYMBOL_DEF_USER;
+ switch (sym->type) {
+ case S_STRING:
+ case S_INT:
+ case S_HEX:
+ /* Reset a string value if it's out of range */
+ if (sym_string_within_range(sym, sym->def[S_DEF_USER].val))
+ break;
+ sym->flags &= ~(SYMBOL_VALID|SYMBOL_DEF_USER);
+ conf_unsaved++;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ sym_add_change_count(conf_warnings || conf_unsaved);
+
+ return 0;
+}
+
+/*
+ * Kconfig configuration printer
+ *
+ * This printer is used when generating the resulting configuration after
+ * kconfig invocation and `defconfig' files. Unset symbol might be omitted by
+ * passing a non-NULL argument to the printer.
+ *
+ */
+static void
+kconfig_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg)
+{
+
+ switch (sym->type) {
+ case S_BOOLEAN:
+ case S_TRISTATE:
+ if (*value == 'n') {
+ bool skip_unset = (arg != NULL);
+
+ if (!skip_unset)
+ fprintf(fp, "# %s%s is not set\n",
+ CONFIG_, sym->name);
+ return;
+ }
+ break;
+ default:
+ break;
+ }
+
+ fprintf(fp, "%s%s=%s\n", CONFIG_, sym->name, value);
+}
+
+static void
+kconfig_print_comment(FILE *fp, const char *value, void *arg)
+{
+ const char *p = value;
+ size_t l;
+
+ for (;;) {
+ l = strcspn(p, "\n");
+ fprintf(fp, "#");
+ if (l) {
+ fprintf(fp, " ");
+ xfwrite(p, l, 1, fp);
+ p += l;
+ }
+ fprintf(fp, "\n");
+ if (*p++ == '\0')
+ break;
+ }
+}
+
+static struct conf_printer kconfig_printer_cb =
+{
+ .print_symbol = kconfig_print_symbol,
+ .print_comment = kconfig_print_comment,
+};
+
+/*
+ * Header printer
+ *
+ * This printer is used when generating the `include/generated/autoconf.h' file.
+ */
+static void
+header_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg)
+{
+
+ switch (sym->type) {
+ case S_BOOLEAN:
+ case S_TRISTATE: {
+ const char *suffix = "";
+
+ switch (*value) {
+ case 'n':
+ break;
+ case 'm':
+ suffix = "_MODULE";
+ /* fall through */
+ default:
+ fprintf(fp, "#define %s%s%s 1\n",
+ CONFIG_, sym->name, suffix);
+ }
+ break;
+ }
+ case S_HEX: {
+ const char *prefix = "";
+
+ if (value[0] != '0' || (value[1] != 'x' && value[1] != 'X'))
+ prefix = "0x";
+ fprintf(fp, "#define %s%s %s%s\n",
+ CONFIG_, sym->name, prefix, value);
+ break;
+ }
+ case S_STRING:
+ case S_INT:
+ fprintf(fp, "#define %s%s %s\n",
+ CONFIG_, sym->name, value);
+ break;
+ default:
+ break;
+ }
+
+}
+
+static void
+header_print_comment(FILE *fp, const char *value, void *arg)
+{
+ const char *p = value;
+ size_t l;
+
+ fprintf(fp, "/*\n");
+ for (;;) {
+ l = strcspn(p, "\n");
+ fprintf(fp, " *");
+ if (l) {
+ fprintf(fp, " ");
+ xfwrite(p, l, 1, fp);
+ p += l;
+ }
+ fprintf(fp, "\n");
+ if (*p++ == '\0')
+ break;
+ }
+ fprintf(fp, " */\n");
+}
+
+static struct conf_printer header_printer_cb =
+{
+ .print_symbol = header_print_symbol,
+ .print_comment = header_print_comment,
+};
+
+/*
+ * Generate the __enabled_CONFIG_* and __enabled_CONFIG_*_MODULE macros for
+ * use by the IS_{ENABLED,BUILTIN,MODULE} macros. The _MODULE variant is
+ * generated even for booleans so that the IS_ENABLED() macro works.
+ */
+static void
+header_print__enabled_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg)
+{
+
+ switch (sym->type) {
+ case S_BOOLEAN:
+ case S_TRISTATE: {
+ fprintf(fp, "#define __enabled_" CONFIG_ "%s %d\n",
+ sym->name, (*value == 'y'));
+ fprintf(fp, "#define __enabled_" CONFIG_ "%s_MODULE %d\n",
+ sym->name, (*value == 'm'));
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+static struct conf_printer header__enabled_printer_cb =
+{
+ .print_symbol = header_print__enabled_symbol,
+ .print_comment = header_print_comment,
+};
+
+/*
+ * Tristate printer
+ *
+ * This printer is used when generating the `include/config/tristate.conf' file.
+ */
+static void
+tristate_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg)
+{
+
+ if (sym->type == S_TRISTATE && *value != 'n')
+ fprintf(fp, "%s%s=%c\n", CONFIG_, sym->name, (char)toupper(*value));
+}
+
+static struct conf_printer tristate_printer_cb =
+{
+ .print_symbol = tristate_print_symbol,
+ .print_comment = kconfig_print_comment,
+};
+
+static void conf_write_symbol(FILE *fp, struct symbol *sym,
+ struct conf_printer *printer, void *printer_arg)
+{
+ const char *str;
+
+ switch (sym->type) {
+ case S_OTHER:
+ case S_UNKNOWN:
+ break;
+ case S_STRING:
+ str = sym_get_string_value(sym);
+ str = sym_escape_string_value(str);
+ printer->print_symbol(fp, sym, str, printer_arg);
+ free((void *)str);
+ break;
+ default:
+ str = sym_get_string_value(sym);
+ printer->print_symbol(fp, sym, str, printer_arg);
+ }
+}
+
+static void
+conf_write_heading(FILE *fp, struct conf_printer *printer, void *printer_arg)
+{
+ char buf[256];
+
+ snprintf(buf, sizeof(buf),
+ "\n"
+ "Automatically generated file; DO NOT EDIT.\n"
+ "%s\n",
+ rootmenu.prompt->text);
+
+ printer->print_comment(fp, buf, printer_arg);
+}
+
+/*
+ * Write out a minimal config.
+ * All values that has default values are skipped as this is redundant.
+ */
+int conf_write_defconfig(const char *filename)
+{
+ struct symbol *sym;
+ struct menu *menu;
+ FILE *out;
+
+ out = fopen(filename, "w");
+ if (!out)
+ return 1;
+
+ sym_clear_all_valid();
+
+ /* Traverse all menus to find all relevant symbols */
+ menu = rootmenu.list;
+
+ while (menu != NULL)
+ {
+ sym = menu->sym;
+ if (sym == NULL) {
+ if (!menu_is_visible(menu))
+ goto next_menu;
+ } else if (!sym_is_choice(sym)) {
+ sym_calc_value(sym);
+ if (!(sym->flags & SYMBOL_WRITE))
+ goto next_menu;
+ sym->flags &= ~SYMBOL_WRITE;
+ /* If we cannot change the symbol - skip */
+ if (!sym_is_changable(sym))
+ goto next_menu;
+ /* If symbol equals to default value - skip */
+ if (strcmp(sym_get_string_value(sym), sym_get_string_default(sym)) == 0)
+ goto next_menu;
+
+ /*
+ * If symbol is a choice value and equals to the
+ * default for a choice - skip.
+ * But only if value is bool and equal to "y" and
+ * choice is not "optional".
+ * (If choice is "optional" then all values can be "n")
+ */
+ if (sym_is_choice_value(sym)) {
+ struct symbol *cs;
+ struct symbol *ds;
+
+ cs = prop_get_symbol(sym_get_choice_prop(sym));
+ ds = sym_choice_default(cs);
+ if (!sym_is_optional(cs) && sym == ds) {
+ if ((sym->type == S_BOOLEAN) &&
+ sym_get_tristate_value(sym) == yes)
+ goto next_menu;
+ }
+ }
+ conf_write_symbol(out, sym, &kconfig_printer_cb, NULL);
+ }
+next_menu:
+ if (menu->list != NULL) {
+ menu = menu->list;
+ }
+ else if (menu->next != NULL) {
+ menu = menu->next;
+ } else {
+ while ((menu = menu->parent)) {
+ if (menu->next != NULL) {
+ menu = menu->next;
+ break;
+ }
+ }
+ }
+ }
+ fclose(out);
+ return 0;
+}
+
+int conf_write(const char *name)
+{
+ FILE *out;
+ struct symbol *sym;
+ struct menu *menu;
+ const char *basename;
+ const char *str;
+ char dirname[PATH_MAX+1], tmpname[PATH_MAX+1], newname[PATH_MAX+1];
+ char *env;
+
+ dirname[0] = 0;
+ if (name && name[0]) {
+ struct stat st;
+ char *slash;
+
+ if (!stat(name, &st) && S_ISDIR(st.st_mode)) {
+ strcpy(dirname, name);
+ strcat(dirname, "/");
+ basename = conf_get_configname();
+ } else if ((slash = strrchr(name, '/'))) {
+ int size = slash - name + 1;
+ memcpy(dirname, name, size);
+ dirname[size] = 0;
+ if (slash[1])
+ basename = slash + 1;
+ else
+ basename = conf_get_configname();
+ } else
+ basename = name;
+ } else
+ basename = conf_get_configname();
+
+ sprintf(newname, "%s%s", dirname, basename);
+ env = getenv("KCONFIG_OVERWRITECONFIG");
+ if (!env || !*env) {
+ sprintf(tmpname, "%s.tmpconfig.%d", dirname, (int)getpid());
+ out = fopen(tmpname, "w");
+ } else {
+ *tmpname = 0;
+ out = fopen(newname, "w");
+ }
+ if (!out)
+ return 1;
+
+ conf_write_heading(out, &kconfig_printer_cb, NULL);
+
+ if (!conf_get_changed())
+ sym_clear_all_valid();
+
+ menu = rootmenu.list;
+ while (menu) {
+ sym = menu->sym;
+ if (!sym) {
+ if (!menu_is_visible(menu))
+ goto next;
+ str = menu_get_prompt(menu);
+ fprintf(out, "\n"
+ "#\n"
+ "# %s\n"
+ "#\n", str);
+ } else if (!(sym->flags & SYMBOL_CHOICE)) {
+ sym_calc_value(sym);
+ if (!(sym->flags & SYMBOL_WRITE))
+ goto next;
+ sym->flags &= ~SYMBOL_WRITE;
+
+ conf_write_symbol(out, sym, &kconfig_printer_cb, NULL);
+ }
+
+next:
+ if (menu->list) {
+ menu = menu->list;
+ continue;
+ }
+ if (menu->next)
+ menu = menu->next;
+ else while ((menu = menu->parent)) {
+ if (menu->next) {
+ menu = menu->next;
+ break;
+ }
+ }
+ }
+ fclose(out);
+
+ if (*tmpname) {
+ strcat(dirname, basename);
+ strcat(dirname, ".old");
+ rename(newname, dirname);
+ if (rename(tmpname, newname))
+ return 1;
+ }
+
+ conf_message(_("configuration written to %s"), newname);
+
+ sym_set_change_count(0);
+
+ return 0;
+}
+
+static int conf_split_config(void)
+{
+ const char *name;
+ char path[PATH_MAX+1];
+ char *s, *d, c;
+ struct symbol *sym;
+ struct stat sb;
+ int res, i, fd;
+
+ name = conf_get_autoconfig_name();
+ conf_read_simple(name, S_DEF_AUTO);
+
+ if (chdir("include/config"))
+ return 1;
+
+ res = 0;
+ for_all_symbols(i, sym) {
+ sym_calc_value(sym);
+ if ((sym->flags & SYMBOL_AUTO) || !sym->name)
+ continue;
+ if (sym->flags & SYMBOL_WRITE) {
+ if (sym->flags & SYMBOL_DEF_AUTO) {
+ /*
+ * symbol has old and new value,
+ * so compare them...
+ */
+ switch (sym->type) {
+ case S_BOOLEAN:
+ case S_TRISTATE:
+ if (sym_get_tristate_value(sym) ==
+ sym->def[S_DEF_AUTO].tri)
+ continue;
+ break;
+ case S_STRING:
+ case S_HEX:
+ case S_INT:
+ if (!strcmp(sym_get_string_value(sym),
+ sym->def[S_DEF_AUTO].val))
+ continue;
+ break;
+ default:
+ break;
+ }
+ } else {
+ /*
+ * If there is no old value, only 'no' (unset)
+ * is allowed as new value.
+ */
+ switch (sym->type) {
+ case S_BOOLEAN:
+ case S_TRISTATE:
+ if (sym_get_tristate_value(sym) == no)
+ continue;
+ break;
+ default:
+ break;
+ }
+ }
+ } else if (!(sym->flags & SYMBOL_DEF_AUTO))
+ /* There is neither an old nor a new value. */
+ continue;
+ /* else
+ * There is an old value, but no new value ('no' (unset)
+ * isn't saved in auto.conf, so the old value is always
+ * different from 'no').
+ */
+
+ /* Replace all '_' and append ".h" */
+ s = sym->name;
+ d = path;
+ while ((c = *s++)) {
+ c = tolower(c);
+ *d++ = (c == '_') ? '/' : c;
+ }
+ strcpy(d, ".h");
+
+ /* Assume directory path already exists. */
+ fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
+ if (fd == -1) {
+ if (errno != ENOENT) {
+ res = 1;
+ break;
+ }
+ /*
+ * Create directory components,
+ * unless they exist already.
+ */
+ d = path;
+ while ((d = strchr(d, '/'))) {
+ *d = 0;
+ if (stat(path, &sb) && mkdir(path, 0755)) {
+ res = 1;
+ goto out;
+ }
+ *d++ = '/';
+ }
+ /* Try it again. */
+ fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
+ if (fd == -1) {
+ res = 1;
+ break;
+ }
+ }
+ close(fd);
+ }
+out:
+ if (chdir("../.."))
+ return 1;
+
+ return res;
+}
+
+int conf_write_autoconf(void)
+{
+ struct symbol *sym;
+ const char *name;
+ FILE *out, *tristate, *out_h;
+ int i;
+
+ sym_clear_all_valid();
+
+ file_write_dep("include/config/auto.conf.cmd");
+
+ if (conf_split_config())
+ return 1;
+
+ out = fopen(".tmpconfig", "w");
+ if (!out)
+ return 1;
+
+ tristate = fopen(".tmpconfig_tristate", "w");
+ if (!tristate) {
+ fclose(out);
+ return 1;
+ }
+
+ out_h = fopen(".tmpconfig.h", "w");
+ if (!out_h) {
+ fclose(out);
+ fclose(tristate);
+ return 1;
+ }
+
+ conf_write_heading(out, &kconfig_printer_cb, NULL);
+
+ conf_write_heading(tristate, &tristate_printer_cb, NULL);
+
+ conf_write_heading(out_h, &header_printer_cb, NULL);
+
+ for_all_symbols(i, sym) {
+ if (!sym->name)
+ continue;
+
+ sym_calc_value(sym);
+
+ conf_write_symbol(out_h, sym, &header__enabled_printer_cb, NULL);
+
+ if (!(sym->flags & SYMBOL_WRITE))
+ continue;
+
+ conf_write_symbol(out, sym, &kconfig_printer_cb, (void *)1);
+
+ conf_write_symbol(tristate, sym, &tristate_printer_cb, (void *)1);
+
+ conf_write_symbol(out_h, sym, &header_printer_cb, NULL);
+ }
+ fclose(out);
+ fclose(tristate);
+ fclose(out_h);
+
+ name = getenv("KCONFIG_AUTOHEADER");
+ if (!name)
+ name = "include/generated/autoconf.h";
+ if (rename(".tmpconfig.h", name))
+ return 1;
+ name = getenv("KCONFIG_TRISTATE");
+ if (!name)
+ name = "include/config/tristate.conf";
+ if (rename(".tmpconfig_tristate", name))
+ return 1;
+ name = conf_get_autoconfig_name();
+ /*
+ * This must be the last step, kbuild has a dependency on auto.conf
+ * and this marks the successful completion of the previous steps.
+ */
+ if (rename(".tmpconfig", name))
+ return 1;
+
+ return 0;
+}
+
+static int sym_change_count;
+static void (*conf_changed_callback)(void);
+
+void sym_set_change_count(int count)
+{
+ int _sym_change_count = sym_change_count;
+ sym_change_count = count;
+ if (conf_changed_callback &&
+ (bool)_sym_change_count != (bool)count)
+ conf_changed_callback();
+}
+
+void sym_add_change_count(int count)
+{
+ sym_set_change_count(count + sym_change_count);
+}
+
+bool conf_get_changed(void)
+{
+ return sym_change_count;
+}
+
+void conf_set_changed_callback(void (*fn)(void))
+{
+ conf_changed_callback = fn;
+}
+
+static void randomize_choice_values(struct symbol *csym)
+{
+ struct property *prop;
+ struct symbol *sym;
+ struct expr *e;
+ int cnt, def;
+
+ /*
+ * If choice is mod then we may have more items selected
+ * and if no then no-one.
+ * In both cases stop.
+ */
+ if (csym->curr.tri != yes)
+ return;
+
+ prop = sym_get_choice_prop(csym);
+
+ /* count entries in choice block */
+ cnt = 0;
+ expr_list_for_each_sym(prop->expr, e, sym)
+ cnt++;
+
+ /*
+ * find a random value and set it to yes,
+ * set the rest to no so we have only one set
+ */
+ def = (rand() % cnt);
+
+ cnt = 0;
+ expr_list_for_each_sym(prop->expr, e, sym) {
+ if (def == cnt++) {
+ sym->def[S_DEF_USER].tri = yes;
+ csym->def[S_DEF_USER].val = sym;
+ }
+ else {
+ sym->def[S_DEF_USER].tri = no;
+ }
+ }
+ csym->flags |= SYMBOL_DEF_USER;
+ /* clear VALID to get value calculated */
+ csym->flags &= ~(SYMBOL_VALID);
+}
+
+static void set_all_choice_values(struct symbol *csym)
+{
+ struct property *prop;
+ struct symbol *sym;
+ struct expr *e;
+
+ prop = sym_get_choice_prop(csym);
+
+ /*
+ * Set all non-assinged choice values to no
+ */
+ expr_list_for_each_sym(prop->expr, e, sym) {
+ if (!sym_has_value(sym))
+ sym->def[S_DEF_USER].tri = no;
+ }
+ csym->flags |= SYMBOL_DEF_USER;
+ /* clear VALID to get value calculated */
+ csym->flags &= ~(SYMBOL_VALID);
+}
+
+void conf_set_all_new_symbols(enum conf_def_mode mode)
+{
+ struct symbol *sym, *csym;
+ int i, cnt;
+
+ for_all_symbols(i, sym) {
+ if (sym_has_value(sym))
+ continue;
+ switch (sym_get_type(sym)) {
+ case S_BOOLEAN:
+ case S_TRISTATE:
+ switch (mode) {
+ case def_yes:
+ sym->def[S_DEF_USER].tri = yes;
+ break;
+ case def_mod:
+ sym->def[S_DEF_USER].tri = mod;
+ break;
+ case def_no:
+ sym->def[S_DEF_USER].tri = no;
+ break;
+ case def_random:
+ cnt = sym_get_type(sym) == S_TRISTATE ? 3 : 2;
+ sym->def[S_DEF_USER].tri = (tristate)(rand() % cnt);
+ break;
+ default:
+ continue;
+ }
+ if (!(sym_is_choice(sym) && mode == def_random))
+ sym->flags |= SYMBOL_DEF_USER;
+ break;
+ default:
+ break;
+ }
+
+ }
+
+ sym_clear_all_valid();
+
+ /*
+ * We have different type of choice blocks.
+ * If curr.tri equals to mod then we can select several
+ * choice symbols in one block.
+ * In this case we do nothing.
+ * If curr.tri equals yes then only one symbol can be
+ * selected in a choice block and we set it to yes,
+ * and the rest to no.
+ */
+ for_all_symbols(i, csym) {
+ if (sym_has_value(csym) || !sym_is_choice(csym))
+ continue;
+
+ sym_calc_value(csym);
+ if (mode == def_random)
+ randomize_choice_values(csym);
+ else
+ set_all_choice_values(csym);
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "lkc.h"
+
+#define DEBUG_EXPR 0
+
+struct expr *expr_alloc_symbol(struct symbol *sym)
+{
+ struct expr *e = calloc(1, sizeof(*e));
+ e->type = E_SYMBOL;
+ e->left.sym = sym;
+ return e;
+}
+
+struct expr *expr_alloc_one(enum expr_type type, struct expr *ce)
+{
+ struct expr *e = calloc(1, sizeof(*e));
+ e->type = type;
+ e->left.expr = ce;
+ return e;
+}
+
+struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e2)
+{
+ struct expr *e = calloc(1, sizeof(*e));
+ e->type = type;
+ e->left.expr = e1;
+ e->right.expr = e2;
+ return e;
+}
+
+struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2)
+{
+ struct expr *e = calloc(1, sizeof(*e));
+ e->type = type;
+ e->left.sym = s1;
+ e->right.sym = s2;
+ return e;
+}
+
+struct expr *expr_alloc_and(struct expr *e1, struct expr *e2)
+{
+ if (!e1)
+ return e2;
+ return e2 ? expr_alloc_two(E_AND, e1, e2) : e1;
+}
+
+struct expr *expr_alloc_or(struct expr *e1, struct expr *e2)
+{
+ if (!e1)
+ return e2;
+ return e2 ? expr_alloc_two(E_OR, e1, e2) : e1;
+}
+
+struct expr *expr_copy(const struct expr *org)
+{
+ struct expr *e;
+
+ if (!org)
+ return NULL;
+
+ e = malloc(sizeof(*org));
+ memcpy(e, org, sizeof(*org));
+ switch (org->type) {
+ case E_SYMBOL:
+ e->left = org->left;
+ break;
+ case E_NOT:
+ e->left.expr = expr_copy(org->left.expr);
+ break;
+ case E_EQUAL:
+ case E_UNEQUAL:
+ e->left.sym = org->left.sym;
+ e->right.sym = org->right.sym;
+ break;
+ case E_AND:
+ case E_OR:
+ case E_LIST:
+ e->left.expr = expr_copy(org->left.expr);
+ e->right.expr = expr_copy(org->right.expr);
+ break;
+ default:
+ printf("can't copy type %d\n", e->type);
+ free(e);
+ e = NULL;
+ break;
+ }
+
+ return e;
+}
+
+void expr_free(struct expr *e)
+{
+ if (!e)
+ return;
+
+ switch (e->type) {
+ case E_SYMBOL:
+ break;
+ case E_NOT:
+ expr_free(e->left.expr);
+ return;
+ case E_EQUAL:
+ case E_UNEQUAL:
+ break;
+ case E_OR:
+ case E_AND:
+ expr_free(e->left.expr);
+ expr_free(e->right.expr);
+ break;
+ default:
+ printf("how to free type %d?\n", e->type);
+ break;
+ }
+ free(e);
+}
+
+static int trans_count;
+
+#define e1 (*ep1)
+#define e2 (*ep2)
+
+static void __expr_eliminate_eq(enum expr_type type, struct expr **ep1, struct expr **ep2)
+{
+ if (e1->type == type) {
+ __expr_eliminate_eq(type, &e1->left.expr, &e2);
+ __expr_eliminate_eq(type, &e1->right.expr, &e2);
+ return;
+ }
+ if (e2->type == type) {
+ __expr_eliminate_eq(type, &e1, &e2->left.expr);
+ __expr_eliminate_eq(type, &e1, &e2->right.expr);
+ return;
+ }
+ if (e1->type == E_SYMBOL && e2->type == E_SYMBOL &&
+ e1->left.sym == e2->left.sym &&
+ (e1->left.sym == &symbol_yes || e1->left.sym == &symbol_no))
+ return;
+ if (!expr_eq(e1, e2))
+ return;
+ trans_count++;
+ expr_free(e1); expr_free(e2);
+ switch (type) {
+ case E_OR:
+ e1 = expr_alloc_symbol(&symbol_no);
+ e2 = expr_alloc_symbol(&symbol_no);
+ break;
+ case E_AND:
+ e1 = expr_alloc_symbol(&symbol_yes);
+ e2 = expr_alloc_symbol(&symbol_yes);
+ break;
+ default:
+ ;
+ }
+}
+
+void expr_eliminate_eq(struct expr **ep1, struct expr **ep2)
+{
+ if (!e1 || !e2)
+ return;
+ switch (e1->type) {
+ case E_OR:
+ case E_AND:
+ __expr_eliminate_eq(e1->type, ep1, ep2);
+ default:
+ ;
+ }
+ if (e1->type != e2->type) switch (e2->type) {
+ case E_OR:
+ case E_AND:
+ __expr_eliminate_eq(e2->type, ep1, ep2);
+ default:
+ ;
+ }
+ e1 = expr_eliminate_yn(e1);
+ e2 = expr_eliminate_yn(e2);
+}
+
+#undef e1
+#undef e2
+
+int expr_eq(struct expr *e1, struct expr *e2)
+{
+ int res, old_count;
+
+ if (e1->type != e2->type)
+ return 0;
+ switch (e1->type) {
+ case E_EQUAL:
+ case E_UNEQUAL:
+ return e1->left.sym == e2->left.sym && e1->right.sym == e2->right.sym;
+ case E_SYMBOL:
+ return e1->left.sym == e2->left.sym;
+ case E_NOT:
+ return expr_eq(e1->left.expr, e2->left.expr);
+ case E_AND:
+ case E_OR:
+ e1 = expr_copy(e1);
+ e2 = expr_copy(e2);
+ old_count = trans_count;
+ expr_eliminate_eq(&e1, &e2);
+ res = (e1->type == E_SYMBOL && e2->type == E_SYMBOL &&
+ e1->left.sym == e2->left.sym);
+ expr_free(e1);
+ expr_free(e2);
+ trans_count = old_count;
+ return res;
+ case E_LIST:
+ case E_RANGE:
+ case E_NONE:
+ /* panic */;
+ }
+
+ if (DEBUG_EXPR) {
+ expr_fprint(e1, stdout);
+ printf(" = ");
+ expr_fprint(e2, stdout);
+ printf(" ?\n");
+ }
+
+ return 0;
+}
+
+struct expr *expr_eliminate_yn(struct expr *e)
+{
+ struct expr *tmp;
+
+ if (e) switch (e->type) {
+ case E_AND:
+ e->left.expr = expr_eliminate_yn(e->left.expr);
+ e->right.expr = expr_eliminate_yn(e->right.expr);
+ if (e->left.expr->type == E_SYMBOL) {
+ if (e->left.expr->left.sym == &symbol_no) {
+ expr_free(e->left.expr);
+ expr_free(e->right.expr);
+ e->type = E_SYMBOL;
+ e->left.sym = &symbol_no;
+ e->right.expr = NULL;
+ return e;
+ } else if (e->left.expr->left.sym == &symbol_yes) {
+ free(e->left.expr);
+ tmp = e->right.expr;
+ *e = *(e->right.expr);
+ free(tmp);
+ return e;
+ }
+ }
+ if (e->right.expr->type == E_SYMBOL) {
+ if (e->right.expr->left.sym == &symbol_no) {
+ expr_free(e->left.expr);
+ expr_free(e->right.expr);
+ e->type = E_SYMBOL;
+ e->left.sym = &symbol_no;
+ e->right.expr = NULL;
+ return e;
+ } else if (e->right.expr->left.sym == &symbol_yes) {
+ free(e->right.expr);
+ tmp = e->left.expr;
+ *e = *(e->left.expr);
+ free(tmp);
+ return e;
+ }
+ }
+ break;
+ case E_OR:
+ e->left.expr = expr_eliminate_yn(e->left.expr);
+ e->right.expr = expr_eliminate_yn(e->right.expr);
+ if (e->left.expr->type == E_SYMBOL) {
+ if (e->left.expr->left.sym == &symbol_no) {
+ free(e->left.expr);
+ tmp = e->right.expr;
+ *e = *(e->right.expr);
+ free(tmp);
+ return e;
+ } else if (e->left.expr->left.sym == &symbol_yes) {
+ expr_free(e->left.expr);
+ expr_free(e->right.expr);
+ e->type = E_SYMBOL;
+ e->left.sym = &symbol_yes;
+ e->right.expr = NULL;
+ return e;
+ }
+ }
+ if (e->right.expr->type == E_SYMBOL) {
+ if (e->right.expr->left.sym == &symbol_no) {
+ free(e->right.expr);
+ tmp = e->left.expr;
+ *e = *(e->left.expr);
+ free(tmp);
+ return e;
+ } else if (e->right.expr->left.sym == &symbol_yes) {
+ expr_free(e->left.expr);
+ expr_free(e->right.expr);
+ e->type = E_SYMBOL;
+ e->left.sym = &symbol_yes;
+ e->right.expr = NULL;
+ return e;
+ }
+ }
+ break;
+ default:
+ ;
+ }
+ return e;
+}
+
+/*
+ * bool FOO!=n => FOO
+ */
+struct expr *expr_trans_bool(struct expr *e)
+{
+ if (!e)
+ return NULL;
+ switch (e->type) {
+ case E_AND:
+ case E_OR:
+ case E_NOT:
+ e->left.expr = expr_trans_bool(e->left.expr);
+ e->right.expr = expr_trans_bool(e->right.expr);
+ break;
+ case E_UNEQUAL:
+ // FOO!=n -> FOO
+ if (e->left.sym->type == S_TRISTATE) {
+ if (e->right.sym == &symbol_no) {
+ e->type = E_SYMBOL;
+ e->right.sym = NULL;
+ }
+ }
+ break;
+ default:
+ ;
+ }
+ return e;
+}
+
+/*
+ * e1 || e2 -> ?
+ */
+static struct expr *expr_join_or(struct expr *e1, struct expr *e2)
+{
+ struct expr *tmp;
+ struct symbol *sym1, *sym2;
+
+ if (expr_eq(e1, e2))
+ return expr_copy(e1);
+ if (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT)
+ return NULL;
+ if (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT)
+ return NULL;
+ if (e1->type == E_NOT) {
+ tmp = e1->left.expr;
+ if (tmp->type != E_EQUAL && tmp->type != E_UNEQUAL && tmp->type != E_SYMBOL)
+ return NULL;
+ sym1 = tmp->left.sym;
+ } else
+ sym1 = e1->left.sym;
+ if (e2->type == E_NOT) {
+ if (e2->left.expr->type != E_SYMBOL)
+ return NULL;
+ sym2 = e2->left.expr->left.sym;
+ } else
+ sym2 = e2->left.sym;
+ if (sym1 != sym2)
+ return NULL;
+ if (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE)
+ return NULL;
+ if (sym1->type == S_TRISTATE) {
+ if (e1->type == E_EQUAL && e2->type == E_EQUAL &&
+ ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) ||
+ (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes))) {
+ // (a='y') || (a='m') -> (a!='n')
+ return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_no);
+ }
+ if (e1->type == E_EQUAL && e2->type == E_EQUAL &&
+ ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) ||
+ (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes))) {
+ // (a='y') || (a='n') -> (a!='m')
+ return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_mod);
+ }
+ if (e1->type == E_EQUAL && e2->type == E_EQUAL &&
+ ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) ||
+ (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod))) {
+ // (a='m') || (a='n') -> (a!='y')
+ return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_yes);
+ }
+ }
+ if (sym1->type == S_BOOLEAN && sym1 == sym2) {
+ if ((e1->type == E_NOT && e1->left.expr->type == E_SYMBOL && e2->type == E_SYMBOL) ||
+ (e2->type == E_NOT && e2->left.expr->type == E_SYMBOL && e1->type == E_SYMBOL))
+ return expr_alloc_symbol(&symbol_yes);
+ }
+
+ if (DEBUG_EXPR) {
+ printf("optimize (");
+ expr_fprint(e1, stdout);
+ printf(") || (");
+ expr_fprint(e2, stdout);
+ printf(")?\n");
+ }
+ return NULL;
+}
+
+static struct expr *expr_join_and(struct expr *e1, struct expr *e2)
+{
+ struct expr *tmp;
+ struct symbol *sym1, *sym2;
+
+ if (expr_eq(e1, e2))
+ return expr_copy(e1);
+ if (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT)
+ return NULL;
+ if (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT)
+ return NULL;
+ if (e1->type == E_NOT) {
+ tmp = e1->left.expr;
+ if (tmp->type != E_EQUAL && tmp->type != E_UNEQUAL && tmp->type != E_SYMBOL)
+ return NULL;
+ sym1 = tmp->left.sym;
+ } else
+ sym1 = e1->left.sym;
+ if (e2->type == E_NOT) {
+ if (e2->left.expr->type != E_SYMBOL)
+ return NULL;
+ sym2 = e2->left.expr->left.sym;
+ } else
+ sym2 = e2->left.sym;
+ if (sym1 != sym2)
+ return NULL;
+ if (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE)
+ return NULL;
+
+ if ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_yes) ||
+ (e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_yes))
+ // (a) && (a='y') -> (a='y')
+ return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);
+
+ if ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_no) ||
+ (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_no))
+ // (a) && (a!='n') -> (a)
+ return expr_alloc_symbol(sym1);
+
+ if ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_mod) ||
+ (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_mod))
+ // (a) && (a!='m') -> (a='y')
+ return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);
+
+ if (sym1->type == S_TRISTATE) {
+ if (e1->type == E_EQUAL && e2->type == E_UNEQUAL) {
+ // (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b'
+ sym2 = e1->right.sym;
+ if ((e2->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST))
+ return sym2 != e2->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2)
+ : expr_alloc_symbol(&symbol_no);
+ }
+ if (e1->type == E_UNEQUAL && e2->type == E_EQUAL) {
+ // (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b'
+ sym2 = e2->right.sym;
+ if ((e1->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST))
+ return sym2 != e1->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2)
+ : expr_alloc_symbol(&symbol_no);
+ }
+ if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL &&
+ ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) ||
+ (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes)))
+ // (a!='y') && (a!='n') -> (a='m')
+ return expr_alloc_comp(E_EQUAL, sym1, &symbol_mod);
+
+ if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL &&
+ ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) ||
+ (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes)))
+ // (a!='y') && (a!='m') -> (a='n')
+ return expr_alloc_comp(E_EQUAL, sym1, &symbol_no);
+
+ if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL &&
+ ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) ||
+ (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod)))
+ // (a!='m') && (a!='n') -> (a='m')
+ return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);
+
+ if ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_mod) ||
+ (e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_mod) ||
+ (e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_yes) ||
+ (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_yes))
+ return NULL;
+ }
+
+ if (DEBUG_EXPR) {
+ printf("optimize (");
+ expr_fprint(e1, stdout);
+ printf(") && (");
+ expr_fprint(e2, stdout);
+ printf(")?\n");
+ }
+ return NULL;
+}
+
+static void expr_eliminate_dups1(enum expr_type type, struct expr **ep1, struct expr **ep2)
+{
+#define e1 (*ep1)
+#define e2 (*ep2)
+ struct expr *tmp;
+
+ if (e1->type == type) {
+ expr_eliminate_dups1(type, &e1->left.expr, &e2);
+ expr_eliminate_dups1(type, &e1->right.expr, &e2);
+ return;
+ }
+ if (e2->type == type) {
+ expr_eliminate_dups1(type, &e1, &e2->left.expr);
+ expr_eliminate_dups1(type, &e1, &e2->right.expr);
+ return;
+ }
+ if (e1 == e2)
+ return;
+
+ switch (e1->type) {
+ case E_OR: case E_AND:
+ expr_eliminate_dups1(e1->type, &e1, &e1);
+ default:
+ ;
+ }
+
+ switch (type) {
+ case E_OR:
+ tmp = expr_join_or(e1, e2);
+ if (tmp) {
+ expr_free(e1); expr_free(e2);
+ e1 = expr_alloc_symbol(&symbol_no);
+ e2 = tmp;
+ trans_count++;
+ }
+ break;
+ case E_AND:
+ tmp = expr_join_and(e1, e2);
+ if (tmp) {
+ expr_free(e1); expr_free(e2);
+ e1 = expr_alloc_symbol(&symbol_yes);
+ e2 = tmp;
+ trans_count++;
+ }
+ break;
+ default:
+ ;
+ }
+#undef e1
+#undef e2
+}
+
+static void expr_eliminate_dups2(enum expr_type type, struct expr **ep1, struct expr **ep2)
+{
+#define e1 (*ep1)
+#define e2 (*ep2)
+ struct expr *tmp, *tmp1, *tmp2;
+
+ if (e1->type == type) {
+ expr_eliminate_dups2(type, &e1->left.expr, &e2);
+ expr_eliminate_dups2(type, &e1->right.expr, &e2);
+ return;
+ }
+ if (e2->type == type) {
+ expr_eliminate_dups2(type, &e1, &e2->left.expr);
+ expr_eliminate_dups2(type, &e1, &e2->right.expr);
+ }
+ if (e1 == e2)
+ return;
+
+ switch (e1->type) {
+ case E_OR:
+ expr_eliminate_dups2(e1->type, &e1, &e1);
+ // (FOO || BAR) && (!FOO && !BAR) -> n
+ tmp1 = expr_transform(expr_alloc_one(E_NOT, expr_copy(e1)));
+ tmp2 = expr_copy(e2);
+ tmp = expr_extract_eq_and(&tmp1, &tmp2);
+ if (expr_is_yes(tmp1)) {
+ expr_free(e1);
+ e1 = expr_alloc_symbol(&symbol_no);
+ trans_count++;
+ }
+ expr_free(tmp2);
+ expr_free(tmp1);
+ expr_free(tmp);
+ break;
+ case E_AND:
+ expr_eliminate_dups2(e1->type, &e1, &e1);
+ // (FOO && BAR) || (!FOO || !BAR) -> y
+ tmp1 = expr_transform(expr_alloc_one(E_NOT, expr_copy(e1)));
+ tmp2 = expr_copy(e2);
+ tmp = expr_extract_eq_or(&tmp1, &tmp2);
+ if (expr_is_no(tmp1)) {
+ expr_free(e1);
+ e1 = expr_alloc_symbol(&symbol_yes);
+ trans_count++;
+ }
+ expr_free(tmp2);
+ expr_free(tmp1);
+ expr_free(tmp);
+ break;
+ default:
+ ;
+ }
+#undef e1
+#undef e2
+}
+
+struct expr *expr_eliminate_dups(struct expr *e)
+{
+ int oldcount;
+ if (!e)
+ return e;
+
+ oldcount = trans_count;
+ while (1) {
+ trans_count = 0;
+ switch (e->type) {
+ case E_OR: case E_AND:
+ expr_eliminate_dups1(e->type, &e, &e);
+ expr_eliminate_dups2(e->type, &e, &e);
+ default:
+ ;
+ }
+ if (!trans_count)
+ break;
+ e = expr_eliminate_yn(e);
+ }
+ trans_count = oldcount;
+ return e;
+}
+
+struct expr *expr_transform(struct expr *e)
+{
+ struct expr *tmp;
+
+ if (!e)
+ return NULL;
+ switch (e->type) {
+ case E_EQUAL:
+ case E_UNEQUAL:
+ case E_SYMBOL:
+ case E_LIST:
+ break;
+ default:
+ e->left.expr = expr_transform(e->left.expr);
+ e->right.expr = expr_transform(e->right.expr);
+ }
+
+ switch (e->type) {
+ case E_EQUAL:
+ if (e->left.sym->type != S_BOOLEAN)
+ break;
+ if (e->right.sym == &symbol_no) {
+ e->type = E_NOT;
+ e->left.expr = expr_alloc_symbol(e->left.sym);
+ e->right.sym = NULL;
+ break;
+ }
+ if (e->right.sym == &symbol_mod) {
+ printf("boolean symbol %s tested for 'm'? test forced to 'n'\n", e->left.sym->name);
+ e->type = E_SYMBOL;
+ e->left.sym = &symbol_no;
+ e->right.sym = NULL;
+ break;
+ }
+ if (e->right.sym == &symbol_yes) {
+ e->type = E_SYMBOL;
+ e->right.sym = NULL;
+ break;
+ }
+ break;
+ case E_UNEQUAL:
+ if (e->left.sym->type != S_BOOLEAN)
+ break;
+ if (e->right.sym == &symbol_no) {
+ e->type = E_SYMBOL;
+ e->right.sym = NULL;
+ break;
+ }
+ if (e->right.sym == &symbol_mod) {
+ printf("boolean symbol %s tested for 'm'? test forced to 'y'\n", e->left.sym->name);
+ e->type = E_SYMBOL;
+ e->left.sym = &symbol_yes;
+ e->right.sym = NULL;
+ break;
+ }
+ if (e->right.sym == &symbol_yes) {
+ e->type = E_NOT;
+ e->left.expr = expr_alloc_symbol(e->left.sym);
+ e->right.sym = NULL;
+ break;
+ }
+ break;
+ case E_NOT:
+ switch (e->left.expr->type) {
+ case E_NOT:
+ // !!a -> a
+ tmp = e->left.expr->left.expr;
+ free(e->left.expr);
+ free(e);
+ e = tmp;
+ e = expr_transform(e);
+ break;
+ case E_EQUAL:
+ case E_UNEQUAL:
+ // !a='x' -> a!='x'
+ tmp = e->left.expr;
+ free(e);
+ e = tmp;
+ e->type = e->type == E_EQUAL ? E_UNEQUAL : E_EQUAL;
+ break;
+ case E_OR:
+ // !(a || b) -> !a && !b
+ tmp = e->left.expr;
+ e->type = E_AND;
+ e->right.expr = expr_alloc_one(E_NOT, tmp->right.expr);
+ tmp->type = E_NOT;
+ tmp->right.expr = NULL;
+ e = expr_transform(e);
+ break;
+ case E_AND:
+ // !(a && b) -> !a || !b
+ tmp = e->left.expr;
+ e->type = E_OR;
+ e->right.expr = expr_alloc_one(E_NOT, tmp->right.expr);
+ tmp->type = E_NOT;
+ tmp->right.expr = NULL;
+ e = expr_transform(e);
+ break;
+ case E_SYMBOL:
+ if (e->left.expr->left.sym == &symbol_yes) {
+ // !'y' -> 'n'
+ tmp = e->left.expr;
+ free(e);
+ e = tmp;
+ e->type = E_SYMBOL;
+ e->left.sym = &symbol_no;
+ break;
+ }
+ if (e->left.expr->left.sym == &symbol_mod) {
+ // !'m' -> 'm'
+ tmp = e->left.expr;
+ free(e);
+ e = tmp;
+ e->type = E_SYMBOL;
+ e->left.sym = &symbol_mod;
+ break;
+ }
+ if (e->left.expr->left.sym == &symbol_no) {
+ // !'n' -> 'y'
+ tmp = e->left.expr;
+ free(e);
+ e = tmp;
+ e->type = E_SYMBOL;
+ e->left.sym = &symbol_yes;
+ break;
+ }
+ break;
+ default:
+ ;
+ }
+ break;
+ default:
+ ;
+ }
+ return e;
+}
+
+int expr_contains_symbol(struct expr *dep, struct symbol *sym)
+{
+ if (!dep)
+ return 0;
+
+ switch (dep->type) {
+ case E_AND:
+ case E_OR:
+ return expr_contains_symbol(dep->left.expr, sym) ||
+ expr_contains_symbol(dep->right.expr, sym);
+ case E_SYMBOL:
+ return dep->left.sym == sym;
+ case E_EQUAL:
+ case E_UNEQUAL:
+ return dep->left.sym == sym ||
+ dep->right.sym == sym;
+ case E_NOT:
+ return expr_contains_symbol(dep->left.expr, sym);
+ default:
+ ;
+ }
+ return 0;
+}
+
+bool expr_depends_symbol(struct expr *dep, struct symbol *sym)
+{
+ if (!dep)
+ return false;
+
+ switch (dep->type) {
+ case E_AND:
+ return expr_depends_symbol(dep->left.expr, sym) ||
+ expr_depends_symbol(dep->right.expr, sym);
+ case E_SYMBOL:
+ return dep->left.sym == sym;
+ case E_EQUAL:
+ if (dep->left.sym == sym) {
+ if (dep->right.sym == &symbol_yes || dep->right.sym == &symbol_mod)
+ return true;
+ }
+ break;
+ case E_UNEQUAL:
+ if (dep->left.sym == sym) {
+ if (dep->right.sym == &symbol_no)
+ return true;
+ }
+ break;
+ default:
+ ;
+ }
+ return false;
+}
+
+struct expr *expr_extract_eq_and(struct expr **ep1, struct expr **ep2)
+{
+ struct expr *tmp = NULL;
+ expr_extract_eq(E_AND, &tmp, ep1, ep2);
+ if (tmp) {
+ *ep1 = expr_eliminate_yn(*ep1);
+ *ep2 = expr_eliminate_yn(*ep2);
+ }
+ return tmp;
+}
+
+struct expr *expr_extract_eq_or(struct expr **ep1, struct expr **ep2)
+{
+ struct expr *tmp = NULL;
+ expr_extract_eq(E_OR, &tmp, ep1, ep2);
+ if (tmp) {
+ *ep1 = expr_eliminate_yn(*ep1);
+ *ep2 = expr_eliminate_yn(*ep2);
+ }
+ return tmp;
+}
+
+void expr_extract_eq(enum expr_type type, struct expr **ep, struct expr **ep1, struct expr **ep2)
+{
+#define e1 (*ep1)
+#define e2 (*ep2)
+ if (e1->type == type) {
+ expr_extract_eq(type, ep, &e1->left.expr, &e2);
+ expr_extract_eq(type, ep, &e1->right.expr, &e2);
+ return;
+ }
+ if (e2->type == type) {
+ expr_extract_eq(type, ep, ep1, &e2->left.expr);
+ expr_extract_eq(type, ep, ep1, &e2->right.expr);
+ return;
+ }
+ if (expr_eq(e1, e2)) {
+ *ep = *ep ? expr_alloc_two(type, *ep, e1) : e1;
+ expr_free(e2);
+ if (type == E_AND) {
+ e1 = expr_alloc_symbol(&symbol_yes);
+ e2 = expr_alloc_symbol(&symbol_yes);
+ } else if (type == E_OR) {
+ e1 = expr_alloc_symbol(&symbol_no);
+ e2 = expr_alloc_symbol(&symbol_no);
+ }
+ }
+#undef e1
+#undef e2
+}
+
+struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym)
+{
+ struct expr *e1, *e2;
+
+ if (!e) {
+ e = expr_alloc_symbol(sym);
+ if (type == E_UNEQUAL)
+ e = expr_alloc_one(E_NOT, e);
+ return e;
+ }
+ switch (e->type) {
+ case E_AND:
+ e1 = expr_trans_compare(e->left.expr, E_EQUAL, sym);
+ e2 = expr_trans_compare(e->right.expr, E_EQUAL, sym);
+ if (sym == &symbol_yes)
+ e = expr_alloc_two(E_AND, e1, e2);
+ if (sym == &symbol_no)
+ e = expr_alloc_two(E_OR, e1, e2);
+ if (type == E_UNEQUAL)
+ e = expr_alloc_one(E_NOT, e);
+ return e;
+ case E_OR:
+ e1 = expr_trans_compare(e->left.expr, E_EQUAL, sym);
+ e2 = expr_trans_compare(e->right.expr, E_EQUAL, sym);
+ if (sym == &symbol_yes)
+ e = expr_alloc_two(E_OR, e1, e2);
+ if (sym == &symbol_no)
+ e = expr_alloc_two(E_AND, e1, e2);
+ if (type == E_UNEQUAL)
+ e = expr_alloc_one(E_NOT, e);
+ return e;
+ case E_NOT:
+ return expr_trans_compare(e->left.expr, type == E_EQUAL ? E_UNEQUAL : E_EQUAL, sym);
+ case E_UNEQUAL:
+ case E_EQUAL:
+ if (type == E_EQUAL) {
+ if (sym == &symbol_yes)
+ return expr_copy(e);
+ if (sym == &symbol_mod)
+ return expr_alloc_symbol(&symbol_no);
+ if (sym == &symbol_no)
+ return expr_alloc_one(E_NOT, expr_copy(e));
+ } else {
+ if (sym == &symbol_yes)
+ return expr_alloc_one(E_NOT, expr_copy(e));
+ if (sym == &symbol_mod)
+ return expr_alloc_symbol(&symbol_yes);
+ if (sym == &symbol_no)
+ return expr_copy(e);
+ }
+ break;
+ case E_SYMBOL:
+ return expr_alloc_comp(type, e->left.sym, sym);
+ case E_LIST:
+ case E_RANGE:
+ case E_NONE:
+ /* panic */;
+ }
+ return NULL;
+}
+
+tristate expr_calc_value(struct expr *e)
+{
+ tristate val1, val2;
+ const char *str1, *str2;
+
+ if (!e)
+ return yes;
+
+ switch (e->type) {
+ case E_SYMBOL:
+ sym_calc_value(e->left.sym);
+ return e->left.sym->curr.tri;
+ case E_AND:
+ val1 = expr_calc_value(e->left.expr);
+ val2 = expr_calc_value(e->right.expr);
+ return EXPR_AND(val1, val2);
+ case E_OR:
+ val1 = expr_calc_value(e->left.expr);
+ val2 = expr_calc_value(e->right.expr);
+ return EXPR_OR(val1, val2);
+ case E_NOT:
+ val1 = expr_calc_value(e->left.expr);
+ return EXPR_NOT(val1);
+ case E_EQUAL:
+ sym_calc_value(e->left.sym);
+ sym_calc_value(e->right.sym);
+ str1 = sym_get_string_value(e->left.sym);
+ str2 = sym_get_string_value(e->right.sym);
+ return !strcmp(str1, str2) ? yes : no;
+ case E_UNEQUAL:
+ sym_calc_value(e->left.sym);
+ sym_calc_value(e->right.sym);
+ str1 = sym_get_string_value(e->left.sym);
+ str2 = sym_get_string_value(e->right.sym);
+ return !strcmp(str1, str2) ? no : yes;
+ default:
+ printf("expr_calc_value: %d?\n", e->type);
+ return no;
+ }
+}
+
+int expr_compare_type(enum expr_type t1, enum expr_type t2)
+{
+#if 0
+ return 1;
+#else
+ if (t1 == t2)
+ return 0;
+ switch (t1) {
+ case E_EQUAL:
+ case E_UNEQUAL:
+ if (t2 == E_NOT)
+ return 1;
+ case E_NOT:
+ if (t2 == E_AND)
+ return 1;
+ case E_AND:
+ if (t2 == E_OR)
+ return 1;
+ case E_OR:
+ if (t2 == E_LIST)
+ return 1;
+ case E_LIST:
+ if (t2 == 0)
+ return 1;
+ default:
+ return -1;
+ }
+ printf("[%dgt%d?]", t1, t2);
+ return 0;
+#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)
+{
+ if (!e) {
+ fn(data, NULL, "y");
+ return;
+ }
+
+ if (expr_compare_type(prevtoken, e->type) > 0)
+ fn(data, NULL, "(");
+ switch (e->type) {
+ case E_SYMBOL:
+ if (e->left.sym->name)
+ fn(data, e->left.sym, e->left.sym->name);
+ else
+ fn(data, NULL, "<choice>");
+ break;
+ case E_NOT:
+ fn(data, NULL, "!");
+ expr_print(e->left.expr, fn, data, E_NOT);
+ break;
+ case E_EQUAL:
+ if (e->left.sym->name)
+ fn(data, e->left.sym, e->left.sym->name);
+ else
+ fn(data, NULL, "<choice>");
+ fn(data, NULL, "=");
+ fn(data, e->right.sym, e->right.sym->name);
+ break;
+ case E_UNEQUAL:
+ if (e->left.sym->name)
+ fn(data, e->left.sym, e->left.sym->name);
+ else
+ fn(data, NULL, "<choice>");
+ fn(data, NULL, "!=");
+ fn(data, e->right.sym, e->right.sym->name);
+ break;
+ case E_OR:
+ expr_print(e->left.expr, fn, data, E_OR);
+ fn(data, NULL, " || ");
+ expr_print(e->right.expr, fn, data, E_OR);
+ break;
+ case E_AND:
+ expr_print(e->left.expr, fn, data, E_AND);
+ fn(data, NULL, " && ");
+ expr_print(e->right.expr, fn, data, E_AND);
+ break;
+ case E_LIST:
+ fn(data, e->right.sym, e->right.sym->name);
+ if (e->left.expr) {
+ fn(data, NULL, " ^ ");
+ expr_print(e->left.expr, fn, data, E_LIST);
+ }
+ break;
+ case E_RANGE:
+ fn(data, NULL, "[");
+ fn(data, e->left.sym, e->left.sym->name);
+ fn(data, NULL, " ");
+ fn(data, e->right.sym, e->right.sym->name);
+ fn(data, NULL, "]");
+ break;
+ default:
+ {
+ char buf[32];
+ sprintf(buf, "<unknown type %d>", e->type);
+ fn(data, NULL, buf);
+ break;
+ }
+ }
+ if (expr_compare_type(prevtoken, e->type) > 0)
+ fn(data, NULL, ")");
+}
+
+static void expr_print_file_helper(void *data, struct symbol *sym, const char *str)
+{
+ xfwrite(str, strlen(str), 1, data);
+}
+
+void expr_fprint(struct expr *e, FILE *out)
+{
+ expr_print(e, expr_print_file_helper, out, E_NONE);
+}
+
+static void expr_print_gstr_helper(void *data, struct symbol *sym, const char *str)
+{
+ struct gstr *gs = (struct gstr*)data;
+ const char *sym_str = NULL;
+
+ if (sym)
+ sym_str = sym_get_string_value(sym);
+
+ if (gs->max_width) {
+ unsigned extra_length = strlen(str);
+ const char *last_cr = strrchr(gs->s, '\n');
+ unsigned last_line_length;
+
+ if (sym_str)
+ extra_length += 4 + strlen(sym_str);
+
+ if (!last_cr)
+ last_cr = gs->s;
+
+ last_line_length = strlen(gs->s) - (last_cr - gs->s);
+
+ if ((last_line_length + extra_length) > gs->max_width)
+ str_append(gs, "\\\n");
+ }
+
+ str_append(gs, str);
+ if (sym && sym->type != S_UNKNOWN)
+ str_printf(gs, " [=%s]", sym_str);
+}
+
+void expr_gstr_print(struct expr *e, struct gstr *gs)
+{
+ expr_print(e, expr_print_gstr_helper, gs, E_NONE);
+}
--- /dev/null
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#ifndef EXPR_H
+#define EXPR_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <assert.h>
+#include <stdio.h>
+#ifndef __cplusplus
+#include <stdbool.h>
+#endif
+
+struct file {
+ struct file *next;
+ struct file *parent;
+ const char *name;
+ int lineno;
+};
+
+typedef enum tristate {
+ no, mod, yes
+} tristate;
+
+enum expr_type {
+ E_NONE, E_OR, E_AND, E_NOT, E_EQUAL, E_UNEQUAL, E_LIST, E_SYMBOL, E_RANGE
+};
+
+union expr_data {
+ struct expr *expr;
+ struct symbol *sym;
+};
+
+struct expr {
+ enum expr_type type;
+ union expr_data left, right;
+};
+
+#define EXPR_OR(dep1, dep2) (((dep1)>(dep2))?(dep1):(dep2))
+#define EXPR_AND(dep1, dep2) (((dep1)<(dep2))?(dep1):(dep2))
+#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 *expr;
+ tristate tri;
+};
+
+struct symbol_value {
+ void *val;
+ tristate tri;
+};
+
+enum symbol_type {
+ 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 *next;
+ char *name;
+ enum symbol_type type;
+ struct symbol_value curr;
+ struct symbol_value def[S_DEF_COUNT];
+ tristate visible;
+ int flags;
+ struct property *prop;
+ struct expr_value dir_dep;
+ struct expr_value rev_dep;
+};
+
+#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_CONST 0x0001 /* symbol is const */
+#define SYMBOL_CHECK 0x0008 /* used during dependency checking */
+#define SYMBOL_CHOICE 0x0010 /* start of a choice block (null name) */
+#define SYMBOL_CHOICEVAL 0x0020 /* used as a value in a choice block */
+#define SYMBOL_VALID 0x0080 /* set when symbol.curr is calculated */
+#define SYMBOL_OPTIONAL 0x0100 /* choice is optional - values can be 'n' */
+#define SYMBOL_WRITE 0x0200 /* ? */
+#define SYMBOL_CHANGED 0x0400 /* ? */
+#define SYMBOL_AUTO 0x1000 /* value from environment variable */
+#define SYMBOL_CHECKED 0x2000 /* used during dependency checking */
+#define SYMBOL_WARNED 0x8000 /* warning has been issued */
+
+/* Set when symbol.def[] is used */
+#define SYMBOL_DEF 0x10000 /* First bit of SYMBOL_DEF */
+#define SYMBOL_DEF_USER 0x10000 /* symbol.def[S_DEF_USER] is valid */
+#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_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 {
+ 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 */
+};
+
+struct property {
+ struct property *next; /* next property - null if last */
+ struct symbol *sym; /* the symbol for which the property is associated */
+ enum prop_type type; /* type of property */
+ const char *text; /* the prompt value - P_PROMPT, P_MENU, P_COMMENT */
+ struct expr_value visible;
+ struct expr *expr; /* the optional conditional part of the property */
+ struct menu *menu; /* the menu the property are associated with
+ * valid for: P_SELECT, P_RANGE, P_CHOICE,
+ * 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) \
+ for (st = sym->prop; st; st = st->next) \
+ if (st->type == (tok))
+#define for_all_defaults(sym, st) for_all_properties(sym, st, P_DEFAULT)
+#define for_all_choices(sym, st) for_all_properties(sym, st, P_CHOICE)
+#define for_all_prompts(sym, st) \
+ for (st = sym->prop; st; st = st->next) \
+ if (st->text)
+
+struct menu {
+ struct menu *next;
+ struct menu *parent;
+ struct menu *list;
+ struct symbol *sym;
+ struct property *prompt;
+ struct expr *visibility;
+ struct expr *dep;
+ unsigned int flags;
+ char *help;
+ struct file *file;
+ int lineno;
+ void *data;
+};
+
+#define MENU_CHANGED 0x0001
+#define MENU_ROOT 0x0002
+
+extern struct file *file_list;
+extern struct file *current_file;
+struct file *lookup_file(const char *name);
+
+extern struct symbol symbol_yes, symbol_no, symbol_mod;
+extern struct symbol *modules_sym;
+extern struct symbol *sym_defconfig_list;
+extern int cdebug;
+struct expr *expr_alloc_symbol(struct symbol *sym);
+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_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_or(struct expr *e1, struct expr *e2);
+struct expr *expr_copy(const struct expr *org);
+void expr_free(struct expr *e);
+int expr_eq(struct expr *e1, struct expr *e2);
+void expr_eliminate_eq(struct expr **ep1, struct expr **ep2);
+tristate expr_calc_value(struct expr *e);
+struct expr *expr_eliminate_yn(struct expr *e);
+struct expr *expr_trans_bool(struct expr *e);
+struct expr *expr_eliminate_dups(struct expr *e);
+struct expr *expr_transform(struct expr *e);
+int expr_contains_symbol(struct expr *dep, struct symbol *sym);
+bool expr_depends_symbol(struct expr *dep, struct symbol *sym);
+struct expr *expr_extract_eq_and(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);
+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);
+struct gstr; /* forward */
+void expr_gstr_print(struct expr *e, struct gstr *gs);
+
+static inline int expr_is_yes(struct expr *e)
+{
+ return !e || (e->type == E_SYMBOL && e->left.sym == &symbol_yes);
+}
+
+static inline int expr_is_no(struct expr *e)
+{
+ return e && (e->type == E_SYMBOL && e->left.sym == &symbol_no);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* EXPR_H */
--- /dev/null
+%language=ANSI-C
+%define hash-function-name kconf_id_hash
+%define lookup-function-name kconf_id_lookup
+%define string-pool-name kconf_id_strings
+%compare-strncmp
+%enum
+%pic
+%struct-type
+
+struct kconf_id;
+
+static const struct kconf_id *kconf_id_lookup(register const char *str, register unsigned int len);
+
+%%
+mainmenu, T_MAINMENU, TF_COMMAND
+menu, T_MENU, TF_COMMAND
+endmenu, T_ENDMENU, TF_COMMAND
+source, T_SOURCE, TF_COMMAND
+choice, T_CHOICE, TF_COMMAND
+endchoice, T_ENDCHOICE, TF_COMMAND
+comment, T_COMMENT, TF_COMMAND
+config, T_CONFIG, TF_COMMAND
+menuconfig, T_MENUCONFIG, TF_COMMAND
+help, T_HELP, TF_COMMAND
+if, T_IF, TF_COMMAND|TF_PARAM
+endif, T_ENDIF, TF_COMMAND
+depends, T_DEPENDS, TF_COMMAND
+optional, T_OPTIONAL, TF_COMMAND
+default, T_DEFAULT, TF_COMMAND, S_UNKNOWN
+prompt, T_PROMPT, TF_COMMAND
+tristate, T_TYPE, TF_COMMAND, S_TRISTATE
+def_tristate, T_DEFAULT, TF_COMMAND, S_TRISTATE
+bool, T_TYPE, TF_COMMAND, S_BOOLEAN
+boolean, T_TYPE, TF_COMMAND, S_BOOLEAN
+def_bool, T_DEFAULT, TF_COMMAND, S_BOOLEAN
+int, T_TYPE, TF_COMMAND, S_INT
+hex, T_TYPE, TF_COMMAND, S_HEX
+string, T_TYPE, TF_COMMAND, S_STRING
+select, T_SELECT, TF_COMMAND
+range, T_RANGE, TF_COMMAND
+visible, T_VISIBLE, TF_COMMAND
+option, T_OPTION, TF_COMMAND
+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
+%%
--- /dev/null
+%option nostdinit noyywrap never-interactive full ecs
+%option 8bit nodefault perf-report perf-report
+%option noinput
+%x COMMAND HELP STRING PARAM
+%{
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "lkc.h"
+
+#define START_STRSIZE 16
+
+static struct {
+ struct file *file;
+ int lineno;
+} current_pos;
+
+static char *text;
+static int text_size, text_asize;
+
+struct buffer {
+ struct buffer *parent;
+ YY_BUFFER_STATE state;
+};
+
+struct buffer *current_buf;
+
+static int last_ts, first_ts;
+
+static void zconf_endhelp(void);
+static void zconf_endfile(void);
+
+static void new_string(void)
+{
+ text = malloc(START_STRSIZE);
+ text_asize = START_STRSIZE;
+ text_size = 0;
+ *text = 0;
+}
+
+static void append_string(const char *str, int size)
+{
+ int new_size = text_size + size + 1;
+ if (new_size > text_asize) {
+ new_size += START_STRSIZE - 1;
+ new_size &= -START_STRSIZE;
+ text = realloc(text, new_size);
+ text_asize = new_size;
+ }
+ memcpy(text + text_size, str, size);
+ text_size += size;
+ text[text_size] = 0;
+}
+
+static void alloc_string(const char *str, int size)
+{
+ text = malloc(size + 1);
+ memcpy(text, str, size);
+ text[size] = 0;
+}
+%}
+
+ws [ \n\t]
+n [A-Za-z0-9_]
+
+%%
+ int str = 0;
+ int ts, i;
+
+[ \t]*#.*\n |
+[ \t]*\n {
+ current_file->lineno++;
+ return T_EOL;
+}
+[ \t]*#.*
+
+
+[ \t]+ {
+ BEGIN(COMMAND);
+}
+
+. {
+ unput(yytext[0]);
+ BEGIN(COMMAND);
+}
+
+
+<COMMAND>{
+ {n}+ {
+ const struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
+ BEGIN(PARAM);
+ current_pos.file = current_file;
+ current_pos.lineno = current_file->lineno;
+ if (id && id->flags & TF_COMMAND) {
+ zconflval.id = id;
+ return id->token;
+ }
+ alloc_string(yytext, yyleng);
+ zconflval.string = text;
+ return T_WORD;
+ }
+ .
+ \n {
+ BEGIN(INITIAL);
+ current_file->lineno++;
+ return T_EOL;
+ }
+}
+
+<PARAM>{
+ "&&" return T_AND;
+ "||" return T_OR;
+ "(" return T_OPEN_PAREN;
+ ")" return T_CLOSE_PAREN;
+ "!" return T_NOT;
+ "=" return T_EQUAL;
+ "!=" return T_UNEQUAL;
+ \"|\' {
+ str = yytext[0];
+ new_string();
+ BEGIN(STRING);
+ }
+ \n BEGIN(INITIAL); current_file->lineno++; return T_EOL;
+ --- /* ignore */
+ ({n}|[-/.])+ {
+ const struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
+ if (id && id->flags & TF_PARAM) {
+ zconflval.id = id;
+ return id->token;
+ }
+ alloc_string(yytext, yyleng);
+ zconflval.string = text;
+ return T_WORD;
+ }
+ #.* /* comment */
+ \\\n current_file->lineno++;
+ .
+ <<EOF>> {
+ BEGIN(INITIAL);
+ }
+}
+
+<STRING>{
+ [^'"\\\n]+/\n {
+ append_string(yytext, yyleng);
+ zconflval.string = text;
+ return T_WORD_QUOTE;
+ }
+ [^'"\\\n]+ {
+ append_string(yytext, yyleng);
+ }
+ \\.?/\n {
+ append_string(yytext + 1, yyleng - 1);
+ zconflval.string = text;
+ return T_WORD_QUOTE;
+ }
+ \\.? {
+ append_string(yytext + 1, yyleng - 1);
+ }
+ \'|\" {
+ if (str == yytext[0]) {
+ BEGIN(PARAM);
+ zconflval.string = text;
+ return T_WORD_QUOTE;
+ } else
+ append_string(yytext, 1);
+ }
+ \n {
+ printf("%s:%d:warning: multi-line strings not supported\n", zconf_curname(), zconf_lineno());
+ current_file->lineno++;
+ BEGIN(INITIAL);
+ return T_EOL;
+ }
+ <<EOF>> {
+ BEGIN(INITIAL);
+ }
+}
+
+<HELP>{
+ [ \t]+ {
+ ts = 0;
+ for (i = 0; i < yyleng; i++) {
+ if (yytext[i] == '\t')
+ ts = (ts & ~7) + 8;
+ else
+ ts++;
+ }
+ last_ts = ts;
+ if (first_ts) {
+ if (ts < first_ts) {
+ zconf_endhelp();
+ return T_HELPTEXT;
+ }
+ ts -= first_ts;
+ while (ts > 8) {
+ append_string(" ", 8);
+ ts -= 8;
+ }
+ append_string(" ", ts);
+ }
+ }
+ [ \t]*\n/[^ \t\n] {
+ current_file->lineno++;
+ zconf_endhelp();
+ return T_HELPTEXT;
+ }
+ [ \t]*\n {
+ current_file->lineno++;
+ append_string("\n", 1);
+ }
+ [^ \t\n].* {
+ while (yyleng) {
+ if ((yytext[yyleng-1] != ' ') && (yytext[yyleng-1] != '\t'))
+ break;
+ yyleng--;
+ }
+ append_string(yytext, yyleng);
+ if (!first_ts)
+ first_ts = last_ts;
+ }
+ <<EOF>> {
+ zconf_endhelp();
+ return T_HELPTEXT;
+ }
+}
+
+<<EOF>> {
+ if (current_file) {
+ zconf_endfile();
+ return T_EOL;
+ }
+ fclose(yyin);
+ yyterminate();
+}
+
+%%
+void zconf_starthelp(void)
+{
+ new_string();
+ last_ts = first_ts = 0;
+ BEGIN(HELP);
+}
+
+static void zconf_endhelp(void)
+{
+ zconflval.string = text;
+ BEGIN(INITIAL);
+}
+
+
+/*
+ * Try to open specified file with following names:
+ * ./name
+ * $(srctree)/name
+ * The latter is used when srctree is separate from objtree
+ * when compiling the kernel.
+ * Return NULL if file is not found.
+ */
+FILE *zconf_fopen(const char *name)
+{
+ char *env, fullname[PATH_MAX+1];
+ FILE *f;
+
+ f = fopen(name, "r");
+ if (!f && name != NULL && name[0] != '/') {
+ env = getenv(SRCTREE);
+ if (env) {
+ sprintf(fullname, "%s/%s", env, name);
+ f = fopen(fullname, "r");
+ }
+ }
+ return f;
+}
+
+void zconf_initscan(const char *name)
+{
+ yyin = zconf_fopen(name);
+ if (!yyin) {
+ printf("can't find file %s\n", name);
+ exit(1);
+ }
+
+ current_buf = malloc(sizeof(*current_buf));
+ memset(current_buf, 0, sizeof(*current_buf));
+
+ current_file = file_lookup(name);
+ current_file->lineno = 1;
+}
+
+void zconf_nextfile(const char *name)
+{
+ struct file *iter;
+ struct file *file = file_lookup(name);
+ struct buffer *buf = malloc(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;
+}
+
+static void zconf_endfile(void)
+{
+ struct buffer *parent;
+
+ current_file = current_file->parent;
+
+ parent = current_buf->parent;
+ if (parent) {
+ fclose(yyin);
+ yy_delete_buffer(YY_CURRENT_BUFFER);
+ yy_switch_to_buffer(parent->state);
+ }
+ free(current_buf);
+ current_buf = parent;
+}
+
+int zconf_lineno(void)
+{
+ return current_pos.lineno;
+}
+
+const char *zconf_curname(void)
+{
+ return current_pos.file ? current_pos.file->name : "<none>";
+}
--- /dev/null
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#ifndef LKC_H
+#define LKC_H
+
+#include "expr.h"
+
+#ifndef KBUILD_NO_NLS
+# include <libintl.h>
+#else
+static inline const char *gettext(const char *txt) { return txt; }
+static inline void textdomain(const char *domainname) {}
+static inline void bindtextdomain(const char *name, const char *dir) {}
+static inline char *bind_textdomain_codeset(const char *dn, char *c) { return c; }
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define P(name,type,arg) extern type name arg
+#include "lkc_proto.h"
+#undef P
+
+#define SRCTREE "srctree"
+
+#ifndef PACKAGE
+#define PACKAGE "linux"
+#endif
+
+#define LOCALEDIR "/usr/share/locale"
+
+#define _(text) gettext(text)
+#define N_(text) (text)
+
+#ifndef CONFIG_
+#define CONFIG_ "CONFIG_"
+#endif
+
+#define TF_COMMAND 0x0001
+#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 {
+ int name;
+ int token;
+ unsigned int flags;
+ enum symbol_type stype;
+};
+
+extern int zconfdebug;
+
+int zconfparse(void);
+void zconfdump(FILE *out);
+void zconf_starthelp(void);
+FILE *zconf_fopen(const char *name);
+void zconf_initscan(const char *name);
+void zconf_nextfile(const char *name);
+int zconf_lineno(void);
+const char *zconf_curname(void);
+
+/* confdata.c */
+const char *conf_get_configname(void);
+const char *conf_get_autoconfig_name(void);
+char *conf_get_default_confname(void);
+void sym_set_change_count(int count);
+void sym_add_change_count(int count);
+void conf_set_all_new_symbols(enum conf_def_mode mode);
+
+struct conf_printer {
+ 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 */
+void _menu_init(void);
+void menu_warn(struct menu *menu, const char *fmt, ...);
+struct menu *menu_add_menu(void);
+void menu_end_menu(void);
+void menu_add_entry(struct symbol *sym);
+void menu_end_entry(void);
+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_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_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_set_type(int type);
+
+/* util.c */
+struct file *file_lookup(const char *name);
+int file_write_dep(const char *name);
+
+struct gstr {
+ size_t len;
+ char *s;
+ /*
+ * when max_width is not zero long lines in string s (if any) get
+ * wrapped not to exceed the max_width value
+ */
+ int max_width;
+};
+struct gstr str_new(void);
+struct gstr str_assign(const char *s);
+void str_free(struct gstr *gs);
+void str_append(struct gstr *gs, const char *s);
+void str_printf(struct gstr *gs, const char *fmt, ...);
+const char *str_get(struct gstr *gs);
+
+/* symbol.c */
+extern struct expr *sym_env_list;
+
+void sym_init(void);
+void sym_clear_all_valid(void);
+void sym_set_all_changed(void);
+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 property *prop_alloc(enum prop_type type, struct symbol *sym);
+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)
+{
+ return sym->curr.tri;
+}
+
+
+static inline struct symbol *sym_get_choice_value(struct symbol *sym)
+{
+ return (struct symbol *)sym->curr.val;
+}
+
+static inline bool sym_set_choice_value(struct symbol *ch, struct symbol *chval)
+{
+ return sym_set_tristate_value(chval, yes);
+}
+
+static inline bool sym_is_choice(struct symbol *sym)
+{
+ return sym->flags & SYMBOL_CHOICE ? true : false;
+}
+
+static inline bool sym_is_choice_value(struct symbol *sym)
+{
+ return sym->flags & SYMBOL_CHOICEVAL ? true : false;
+}
+
+static inline bool sym_is_optional(struct symbol *sym)
+{
+ return sym->flags & SYMBOL_OPTIONAL ? true : false;
+}
+
+static inline bool sym_has_value(struct symbol *sym)
+{
+ return sym->flags & SYMBOL_DEF_USER ? true : false;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LKC_H */
--- /dev/null
+#include <stdarg.h>
+
+/* confdata.c */
+P(conf_parse,void,(const char *name));
+P(conf_read,int,(const char *name));
+P(conf_read_simple,int,(const char *name, int));
+P(conf_write_defconfig,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 */
+P(rootmenu,struct 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_root_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));
+P(get_relations_str, struct gstr, (struct symbol **sym_arr));
+P(menu_get_ext_help,void,(struct menu *menu, struct gstr *help));
+
+/* symbol.c */
+P(symbol_hash,struct symbol *,[SYMBOL_HASHSIZE]);
+
+P(sym_lookup,struct symbol *,(const char *name, int flags));
+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_type_name,const char *,(enum symbol_type type));
+P(sym_calc_value,void,(struct symbol *sym));
+P(sym_get_type,enum symbol_type,(struct symbol *sym));
+P(sym_tristate_within_range,bool,(struct symbol *sym,tristate tri));
+P(sym_set_tristate_value,bool,(struct symbol *sym,tristate tri));
+P(sym_toggle_tristate_value,tristate,(struct symbol *sym));
+P(sym_string_valid,bool,(struct symbol *sym, const char *newval));
+P(sym_string_within_range,bool,(struct symbol *sym, const char *str));
+P(sym_set_string_value,bool,(struct symbol *sym, const char *newval));
+P(sym_is_changable,bool,(struct symbol *sym));
+P(sym_get_choice_prop,struct property *,(struct symbol *sym));
+P(sym_get_default_prop,struct property *,(struct symbol *sym));
+P(sym_get_string_value,const char *,(struct symbol *sym));
+
+P(prop_get_type_name,const char *,(enum prop_type type));
+
+/* expr.c */
+P(expr_compare_type,int,(enum expr_type t1, enum expr_type t2));
+P(expr_print,void,(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken));
--- /dev/null
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#include <ctype.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "lkc.h"
+
+static const char nohelp_text[] = "There is no help available for this option.";
+
+struct menu rootmenu;
+static struct menu **last_entry_ptr;
+
+struct file *file_list;
+struct file *current_file;
+
+void menu_warn(struct menu *menu, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ fprintf(stderr, "%s:%d:warning: ", menu->file->name, menu->lineno);
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, "\n");
+ va_end(ap);
+}
+
+static void prop_warn(struct property *prop, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ fprintf(stderr, "%s:%d:warning: ", prop->file->name, prop->lineno);
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, "\n");
+ va_end(ap);
+}
+
+void _menu_init(void)
+{
+ current_entry = current_menu = &rootmenu;
+ last_entry_ptr = &rootmenu.list;
+}
+
+void menu_add_entry(struct symbol *sym)
+{
+ struct menu *menu;
+
+ menu = malloc(sizeof(*menu));
+ memset(menu, 0, sizeof(*menu));
+ menu->sym = sym;
+ menu->parent = current_menu;
+ menu->file = current_file;
+ menu->lineno = zconf_lineno();
+
+ *last_entry_ptr = menu;
+ last_entry_ptr = &menu->next;
+ current_entry = menu;
+ if (sym)
+ menu_add_symbol(P_SYMBOL, sym, NULL);
+}
+
+void menu_end_entry(void)
+{
+}
+
+struct menu *menu_add_menu(void)
+{
+ menu_end_entry();
+ last_entry_ptr = ¤t_entry->list;
+ return current_menu = current_entry;
+}
+
+void menu_end_menu(void)
+{
+ last_entry_ptr = ¤t_menu->next;
+ 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)
+{
+ current_entry->dep = expr_alloc_and(current_entry->dep, menu_check_dep(dep));
+}
+
+void menu_set_type(int type)
+{
+ struct symbol *sym = current_entry->sym;
+
+ if (sym->type == type)
+ return;
+ if (sym->type == S_UNKNOWN) {
+ sym->type = type;
+ return;
+ }
+ menu_warn(current_entry, "type of '%s' redefined from '%s' to '%s'",
+ sym->name ? sym->name : "<choice>",
+ sym_type_name(sym->type), sym_type_name(type));
+}
+
+struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep)
+{
+ struct property *prop = prop_alloc(type, current_entry->sym);
+
+ prop->menu = current_entry;
+ prop->expr = expr;
+ prop->visible.expr = menu_check_dep(dep);
+
+ if (prompt) {
+ if (isspace(*prompt)) {
+ 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;
+ }
+ prop->text = prompt;
+
+ return prop;
+}
+
+struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *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)
+{
+ menu_add_prop(type, NULL, expr, dep);
+}
+
+void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep)
+{
+ menu_add_prop(type, NULL, expr_alloc_symbol(sym), dep);
+}
+
+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 ||
+ (sym2->type == S_UNKNOWN && sym_string_valid(sym, sym2->name));
+}
+
+static void sym_check_prop(struct symbol *sym)
+{
+ struct property *prop;
+ struct symbol *sym2;
+ for (prop = sym->prop; prop; prop = prop->next) {
+ switch (prop->type) {
+ case P_DEFAULT:
+ if ((sym->type == S_STRING || sym->type == S_INT || sym->type == S_HEX) &&
+ prop->expr->type != E_SYMBOL)
+ prop_warn(prop,
+ "default for config symbol '%s'"
+ " 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;
+ case P_SELECT:
+ sym2 = prop_get_symbol(prop);
+ if (sym->type != S_BOOLEAN && sym->type != S_TRISTATE)
+ prop_warn(prop,
+ "config symbol '%s' uses select, but is "
+ "not boolean or tristate", sym->name);
+ else if (sym2->type != S_UNKNOWN &&
+ sym2->type != S_BOOLEAN &&
+ sym2->type != S_TRISTATE)
+ prop_warn(prop,
+ "'%s' has wrong type. 'select' only "
+ "accept arguments of boolean and "
+ "tristate type", sym2->name);
+ break;
+ case P_RANGE:
+ if (sym->type != S_INT && sym->type != S_HEX)
+ prop_warn(prop, "range is only allowed "
+ "for int or hex symbols");
+ if (!menu_validate_number(sym, prop->expr->left.sym) ||
+ !menu_validate_number(sym, prop->expr->right.sym))
+ prop_warn(prop, "range is invalid");
+ break;
+ default:
+ ;
+ }
+ }
+}
+
+void menu_finalize(struct menu *parent)
+{
+ struct menu *menu, *last_menu;
+ struct symbol *sym;
+ struct property *prop;
+ struct expr *parentdep, *basedep, *dep, *dep2, **ep;
+
+ sym = parent->sym;
+ if (parent->list) {
+ if (sym && sym_is_choice(sym)) {
+ if (sym->type == S_UNKNOWN) {
+ /* find the first choice value to find out choice type */
+ current_entry = parent;
+ for (menu = parent->list; menu; menu = menu->next) {
+ if (menu->sym && menu->sym->type != S_UNKNOWN) {
+ menu_set_type(menu->sym->type);
+ 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);
+ } else if (parent->prompt)
+ parentdep = parent->prompt->visible.expr;
+ else
+ parentdep = parent->dep;
+
+ for (menu = parent->list; menu; menu = menu->next) {
+ basedep = expr_transform(menu->dep);
+ basedep = expr_alloc_and(expr_copy(parentdep), basedep);
+ basedep = expr_eliminate_dups(basedep);
+ menu->dep = basedep;
+ if (menu->sym)
+ prop = menu->sym->prop;
+ else
+ prop = menu->prompt;
+ for (; prop; prop = prop->next) {
+ if (prop->menu != menu)
+ continue;
+ dep = expr_transform(prop->visible.expr);
+ dep = expr_alloc_and(expr_copy(basedep), dep);
+ dep = expr_eliminate_dups(dep);
+ if (menu->sym && menu->sym->type != S_TRISTATE)
+ dep = expr_trans_bool(dep);
+ prop->visible.expr = dep;
+ if (prop->type == P_SELECT) {
+ struct symbol *es = prop_get_symbol(prop);
+ es->rev_dep.expr = expr_alloc_or(es->rev_dep.expr,
+ expr_alloc_and(expr_alloc_symbol(menu->sym), expr_copy(dep)));
+ }
+ }
+ }
+ for (menu = parent->list; menu; menu = menu->next)
+ menu_finalize(menu);
+ } else if (sym) {
+ basedep = parent->prompt ? parent->prompt->visible.expr : NULL;
+ basedep = expr_trans_compare(basedep, E_UNEQUAL, &symbol_no);
+ basedep = expr_eliminate_dups(expr_transform(basedep));
+ last_menu = NULL;
+ for (menu = parent->next; menu; menu = menu->next) {
+ dep = menu->prompt ? menu->prompt->visible.expr : menu->dep;
+ if (!expr_contains_symbol(dep, sym))
+ break;
+ if (expr_depends_symbol(dep, sym))
+ goto next;
+ dep = expr_trans_compare(dep, E_UNEQUAL, &symbol_no);
+ dep = expr_eliminate_dups(expr_transform(dep));
+ dep2 = expr_copy(basedep);
+ expr_eliminate_eq(&dep, &dep2);
+ expr_free(dep);
+ if (!expr_is_yes(dep2)) {
+ expr_free(dep2);
+ break;
+ }
+ expr_free(dep2);
+ next:
+ menu_finalize(menu);
+ menu->parent = parent;
+ last_menu = menu;
+ }
+ if (last_menu) {
+ parent->list = parent->next;
+ parent->next = last_menu->next;
+ 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) {
+ if (sym && sym_is_choice(sym) &&
+ menu->sym && !sym_is_choice_value(menu->sym)) {
+ current_entry = menu;
+ menu->sym->flags |= SYMBOL_CHOICEVAL;
+ if (!menu->prompt)
+ menu_warn(menu, "choice value must have a prompt");
+ for (prop = menu->sym->prop; prop; prop = prop->next) {
+ if (prop->type == P_DEFAULT)
+ prop_warn(prop, "defaults for choice "
+ "values not supported");
+ 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);
+ }
+ }
+ menu_add_symbol(P_CHOICE, sym, NULL);
+ prop = sym_get_choice_prop(sym);
+ for (ep = &prop->expr; *ep; ep = &(*ep)->left.expr)
+ ;
+ *ep = expr_alloc_one(E_LIST, NULL);
+ (*ep)->right.sym = menu->sym;
+ }
+ if (menu->list && (!menu->prompt || !menu->prompt->text)) {
+ for (last_menu = menu->list; ; last_menu = last_menu->next) {
+ last_menu->parent = parent;
+ if (!last_menu->next)
+ break;
+ }
+ last_menu->next = menu->next;
+ menu->next = menu->list;
+ menu->list = NULL;
+ }
+ }
+
+ if (sym && !(sym->flags & SYMBOL_WARNED)) {
+ if (sym->type == S_UNKNOWN)
+ menu_warn(parent, "config symbol defined without type");
+
+ if (sym_is_choice(sym) && !parent->prompt)
+ menu_warn(parent, "choice must have a prompt");
+
+ /* Check properties connected to this symbol */
+ sym_check_prop(sym);
+ sym->flags |= SYMBOL_WARNED;
+ }
+
+ if (sym && !sym_is_optional(sym) && parent->prompt) {
+ sym->rev_dep.expr = expr_alloc_or(sym->rev_dep.expr,
+ expr_alloc_and(parent->prompt->visible.expr,
+ expr_alloc_symbol(&symbol_mod)));
+ }
+}
+
+bool menu_has_prompt(struct menu *menu)
+{
+ if (!menu->prompt)
+ return false;
+ return true;
+}
+
+bool menu_is_visible(struct menu *menu)
+{
+ struct menu *child;
+ struct symbol *sym;
+ tristate visible;
+
+ if (!menu->prompt)
+ return false;
+
+ if (menu->visibility) {
+ if (expr_calc_value(menu->visibility) == no)
+ return no;
+ }
+
+ sym = menu->sym;
+ if (sym) {
+ sym_calc_value(sym);
+ visible = menu->prompt->visible.tri;
+ } else
+ visible = menu->prompt->visible.tri = expr_calc_value(menu->prompt->visible.expr);
+
+ if (visible != no)
+ return true;
+
+ if (!sym || sym_get_tristate_value(menu->sym) == no)
+ return false;
+
+ for (child = menu->list; child; child = child->next) {
+ if (menu_is_visible(child)) {
+ if (sym)
+ sym->flags |= SYMBOL_DEF_USER;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+const char *menu_get_prompt(struct menu *menu)
+{
+ if (menu->prompt)
+ return menu->prompt->text;
+ else if (menu->sym)
+ return menu->sym->name;
+ return NULL;
+}
+
+struct menu *menu_get_root_menu(struct menu *menu)
+{
+ return &rootmenu;
+}
+
+struct menu *menu_get_parent_menu(struct menu *menu)
+{
+ enum prop_type type;
+
+ for (; menu != &rootmenu; menu = menu->parent) {
+ type = menu->prompt ? menu->prompt->type : 0;
+ if (type == P_MENU)
+ break;
+ }
+ 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)
+{
+ int i, j;
+ struct menu *submenu[8], *menu;
+
+ 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)
+ submenu[i++] = menu;
+ if (i > 0) {
+ str_printf(r, _(" Location:\n"));
+ for (j = 4; --i >= 0; j += 2) {
+ menu = submenu[i];
+ 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");
+ }
+ }
+}
+
+void get_symbol_str(struct gstr *r, struct symbol *sym)
+{
+ 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);
+ 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 symbol *sym;
+ struct gstr res = str_new();
+ int i;
+
+ for (i = 0; sym_arr && (sym = sym_arr[i]); i++)
+ get_symbol_str(&res, sym);
+ 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);
+}
--- /dev/null
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <regex.h>
+#include <sys/utsname.h>
+
+#include "lkc.h"
+
+struct symbol symbol_yes = {
+ .name = "y",
+ .curr = { "y", yes },
+ .flags = SYMBOL_CONST|SYMBOL_VALID,
+}, symbol_mod = {
+ .name = "m",
+ .curr = { "m", mod },
+ .flags = SYMBOL_CONST|SYMBOL_VALID,
+}, symbol_no = {
+ .name = "n",
+ .curr = { "n", no },
+ .flags = SYMBOL_CONST|SYMBOL_VALID,
+}, symbol_empty = {
+ .name = "",
+ .curr = { "", no },
+ .flags = SYMBOL_VALID,
+};
+
+struct symbol *sym_defconfig_list;
+struct symbol *modules_sym;
+tristate modules_val;
+
+struct expr *sym_env_list;
+
+static void sym_add_default(struct symbol *sym, const char *def)
+{
+ struct property *prop = prop_alloc(P_DEFAULT, sym);
+
+ prop->expr = expr_alloc_symbol(sym_lookup(def, SYMBOL_CONST));
+}
+
+void sym_init(void)
+{
+ struct symbol *sym;
+ struct utsname uts;
+ static bool inited = false;
+
+ if (inited)
+ return;
+ inited = true;
+
+ uname(&uts);
+
+ sym = sym_lookup("UNAME_RELEASE", 0);
+ sym->type = S_STRING;
+ sym->flags |= SYMBOL_AUTO;
+ sym_add_default(sym, uts.release);
+}
+
+enum symbol_type sym_get_type(struct symbol *sym)
+{
+ enum symbol_type type = sym->type;
+
+ if (type == S_TRISTATE) {
+ if (sym_is_choice_value(sym) && sym->visible == yes)
+ type = S_BOOLEAN;
+ else if (modules_val == no)
+ type = S_BOOLEAN;
+ }
+ return type;
+}
+
+const char *sym_type_name(enum symbol_type type)
+{
+ switch (type) {
+ case S_BOOLEAN:
+ return "boolean";
+ case S_TRISTATE:
+ return "tristate";
+ case S_INT:
+ return "integer";
+ case S_HEX:
+ return "hex";
+ case S_STRING:
+ return "string";
+ case S_UNKNOWN:
+ return "unknown";
+ case S_OTHER:
+ break;
+ }
+ return "???";
+}
+
+struct property *sym_get_choice_prop(struct symbol *sym)
+{
+ struct property *prop;
+
+ for_all_choices(sym, prop)
+ return prop;
+ return NULL;
+}
+
+struct property *sym_get_env_prop(struct symbol *sym)
+{
+ struct property *prop;
+
+ for_all_properties(sym, prop, P_ENV)
+ return prop;
+ return NULL;
+}
+
+struct property *sym_get_default_prop(struct symbol *sym)
+{
+ struct property *prop;
+
+ for_all_defaults(sym, prop) {
+ prop->visible.tri = expr_calc_value(prop->visible.expr);
+ if (prop->visible.tri != no)
+ return prop;
+ }
+ return NULL;
+}
+
+static struct property *sym_get_range_prop(struct symbol *sym)
+{
+ struct property *prop;
+
+ for_all_properties(sym, prop, P_RANGE) {
+ prop->visible.tri = expr_calc_value(prop->visible.expr);
+ if (prop->visible.tri != no)
+ return prop;
+ }
+ return NULL;
+}
+
+static int sym_get_range_val(struct symbol *sym, int base)
+{
+ sym_calc_value(sym);
+ switch (sym->type) {
+ case S_INT:
+ base = 10;
+ break;
+ case S_HEX:
+ base = 16;
+ break;
+ default:
+ break;
+ }
+ return strtol(sym->curr.val, NULL, base);
+}
+
+static void sym_validate_range(struct symbol *sym)
+{
+ struct property *prop;
+ int base, val, val2;
+ char str[64];
+
+ switch (sym->type) {
+ case S_INT:
+ base = 10;
+ break;
+ case S_HEX:
+ base = 16;
+ break;
+ default:
+ return;
+ }
+ prop = sym_get_range_prop(sym);
+ if (!prop)
+ return;
+ val = strtol(sym->curr.val, NULL, base);
+ val2 = sym_get_range_val(prop->expr->left.sym, base);
+ if (val >= val2) {
+ val2 = sym_get_range_val(prop->expr->right.sym, base);
+ if (val <= val2)
+ return;
+ }
+ if (sym->type == S_INT)
+ sprintf(str, "%d", val2);
+ else
+ sprintf(str, "0x%x", val2);
+ sym->curr.val = strdup(str);
+}
+
+static void sym_calc_visibility(struct symbol *sym)
+{
+ struct property *prop;
+ tristate tri;
+
+ /* any prompt visible? */
+ tri = no;
+ for_all_prompts(sym, prop) {
+ prop->visible.tri = expr_calc_value(prop->visible.expr);
+ tri = EXPR_OR(tri, prop->visible.tri);
+ }
+ if (tri == mod && (sym->type != S_TRISTATE || modules_val == no))
+ tri = yes;
+ if (sym->visible != tri) {
+ sym->visible = tri;
+ sym_set_changed(sym);
+ }
+ if (sym_is_choice_value(sym))
+ return;
+ /* defaulting to "yes" if no explicit "depends on" are given */
+ tri = yes;
+ if (sym->dir_dep.expr)
+ tri = expr_calc_value(sym->dir_dep.expr);
+ if (tri == mod)
+ tri = yes;
+ if (sym->dir_dep.tri != tri) {
+ sym->dir_dep.tri = tri;
+ sym_set_changed(sym);
+ }
+ tri = no;
+ if (sym->rev_dep.expr)
+ tri = expr_calc_value(sym->rev_dep.expr);
+ if (tri == mod && sym_get_type(sym) == S_BOOLEAN)
+ tri = yes;
+ if (sym->rev_dep.tri != tri) {
+ sym->rev_dep.tri = tri;
+ sym_set_changed(sym);
+ }
+}
+
+/*
+ * Find the default symbol for a choice.
+ * First try the default values for the choice symbol
+ * Next locate the first visible choice value
+ * Return NULL if none was found
+ */
+struct symbol *sym_choice_default(struct symbol *sym)
+{
+ struct symbol *def_sym;
+ struct property *prop;
+ struct expr *e;
+
+ /* any of the defaults visible? */
+ for_all_defaults(sym, prop) {
+ prop->visible.tri = expr_calc_value(prop->visible.expr);
+ if (prop->visible.tri == no)
+ continue;
+ def_sym = prop_get_symbol(prop);
+ if (def_sym->visible != no)
+ return def_sym;
+ }
+
+ /* just get the first visible value */
+ prop = sym_get_choice_prop(sym);
+ expr_list_for_each_sym(prop->expr, e, def_sym)
+ if (def_sym->visible != no)
+ return def_sym;
+
+ /* failed to locate any defaults */
+ return NULL;
+}
+
+static struct symbol *sym_calc_choice(struct symbol *sym)
+{
+ struct symbol *def_sym;
+ struct property *prop;
+ struct expr *e;
+
+ /* first calculate all choice values' visibilities */
+ prop = sym_get_choice_prop(sym);
+ expr_list_for_each_sym(prop->expr, e, def_sym)
+ sym_calc_visibility(def_sym);
+
+ /* is the user choice visible? */
+ def_sym = sym->def[S_DEF_USER].val;
+ if (def_sym && def_sym->visible != no)
+ return def_sym;
+
+ def_sym = sym_choice_default(sym);
+
+ if (def_sym == NULL)
+ /* no choice? reset tristate value */
+ sym->curr.tri = no;
+
+ return def_sym;
+}
+
+void sym_calc_value(struct symbol *sym)
+{
+ struct symbol_value newval, oldval;
+ struct property *prop;
+ struct expr *e;
+
+ if (!sym)
+ return;
+
+ if (sym->flags & SYMBOL_VALID)
+ return;
+ sym->flags |= SYMBOL_VALID;
+
+ oldval = sym->curr;
+
+ switch (sym->type) {
+ case S_INT:
+ case S_HEX:
+ case S_STRING:
+ newval = symbol_empty.curr;
+ break;
+ case S_BOOLEAN:
+ case S_TRISTATE:
+ newval = symbol_no.curr;
+ break;
+ default:
+ sym->curr.val = sym->name;
+ sym->curr.tri = no;
+ return;
+ }
+ if (!sym_is_choice_value(sym))
+ sym->flags &= ~SYMBOL_WRITE;
+
+ sym_calc_visibility(sym);
+
+ /* set default if recursively called */
+ sym->curr = newval;
+
+ switch (sym_get_type(sym)) {
+ case S_BOOLEAN:
+ case S_TRISTATE:
+ if (sym_is_choice_value(sym) && sym->visible == yes) {
+ prop = sym_get_choice_prop(sym);
+ newval.tri = (prop_get_symbol(prop)->curr.val == sym) ? yes : no;
+ } else {
+ if (sym->visible != no) {
+ /* if the symbol is visible use the user value
+ * if available, otherwise try the default value
+ */
+ sym->flags |= SYMBOL_WRITE;
+ if (sym_has_value(sym)) {
+ newval.tri = EXPR_AND(sym->def[S_DEF_USER].tri,
+ sym->visible);
+ goto calc_newval;
+ }
+ }
+ if (sym->rev_dep.tri != no)
+ sym->flags |= SYMBOL_WRITE;
+ if (!sym_is_choice(sym)) {
+ prop = sym_get_default_prop(sym);
+ if (prop) {
+ sym->flags |= SYMBOL_WRITE;
+ newval.tri = EXPR_AND(expr_calc_value(prop->expr),
+ prop->visible.tri);
+ }
+ }
+ calc_newval:
+ if (sym->dir_dep.tri == no && sym->rev_dep.tri != no) {
+ struct expr *e;
+ e = expr_simplify_unmet_dep(sym->rev_dep.expr,
+ sym->dir_dep.expr);
+ fprintf(stderr, "warning: (");
+ expr_fprint(e, stderr);
+ fprintf(stderr, ") selects %s which has unmet direct dependencies (",
+ sym->name);
+ expr_fprint(sym->dir_dep.expr, stderr);
+ fprintf(stderr, ")\n");
+ expr_free(e);
+ }
+ newval.tri = EXPR_OR(newval.tri, sym->rev_dep.tri);
+ }
+ if (newval.tri == mod && sym_get_type(sym) == S_BOOLEAN)
+ newval.tri = yes;
+ break;
+ case S_STRING:
+ case S_HEX:
+ case S_INT:
+ if (sym->visible != no) {
+ sym->flags |= SYMBOL_WRITE;
+ if (sym_has_value(sym)) {
+ newval.val = sym->def[S_DEF_USER].val;
+ break;
+ }
+ }
+ prop = sym_get_default_prop(sym);
+ if (prop) {
+ struct symbol *ds = prop_get_symbol(prop);
+ if (ds) {
+ sym->flags |= SYMBOL_WRITE;
+ sym_calc_value(ds);
+ newval.val = ds->curr.val;
+ }
+ }
+ break;
+ default:
+ ;
+ }
+
+ sym->curr = newval;
+ if (sym_is_choice(sym) && newval.tri == yes)
+ sym->curr.val = sym_calc_choice(sym);
+ sym_validate_range(sym);
+
+ if (memcmp(&oldval, &sym->curr, sizeof(oldval))) {
+ sym_set_changed(sym);
+ if (modules_sym == sym) {
+ sym_set_all_changed();
+ modules_val = modules_sym->curr.tri;
+ }
+ }
+
+ if (sym_is_choice(sym)) {
+ struct symbol *choice_sym;
+
+ prop = sym_get_choice_prop(sym);
+ expr_list_for_each_sym(prop->expr, e, choice_sym) {
+ if ((sym->flags & SYMBOL_WRITE) &&
+ choice_sym->visible != no)
+ choice_sym->flags |= SYMBOL_WRITE;
+ if (sym->flags & SYMBOL_CHANGED)
+ sym_set_changed(choice_sym);
+ }
+ }
+
+ if (sym->flags & SYMBOL_AUTO)
+ sym->flags &= ~SYMBOL_WRITE;
+}
+
+void sym_clear_all_valid(void)
+{
+ struct symbol *sym;
+ int i;
+
+ for_all_symbols(i, sym)
+ sym->flags &= ~SYMBOL_VALID;
+ sym_add_change_count(1);
+ if (modules_sym)
+ sym_calc_value(modules_sym);
+}
+
+void sym_set_changed(struct symbol *sym)
+{
+ struct property *prop;
+
+ sym->flags |= SYMBOL_CHANGED;
+ for (prop = sym->prop; prop; prop = prop->next) {
+ if (prop->menu)
+ prop->menu->flags |= MENU_CHANGED;
+ }
+}
+
+void sym_set_all_changed(void)
+{
+ struct symbol *sym;
+ int i;
+
+ for_all_symbols(i, sym)
+ sym_set_changed(sym);
+}
+
+bool sym_tristate_within_range(struct symbol *sym, tristate val)
+{
+ int type = sym_get_type(sym);
+
+ if (sym->visible == no)
+ return false;
+
+ if (type != S_BOOLEAN && type != S_TRISTATE)
+ return false;
+
+ if (type == S_BOOLEAN && val == mod)
+ return false;
+ if (sym->visible <= sym->rev_dep.tri)
+ return false;
+ if (sym_is_choice_value(sym) && sym->visible == yes)
+ return val == yes;
+ return val >= sym->rev_dep.tri && val <= sym->visible;
+}
+
+bool sym_set_tristate_value(struct symbol *sym, tristate val)
+{
+ tristate oldval = sym_get_tristate_value(sym);
+
+ if (oldval != val && !sym_tristate_within_range(sym, val))
+ return false;
+
+ if (!(sym->flags & SYMBOL_DEF_USER)) {
+ sym->flags |= SYMBOL_DEF_USER;
+ sym_set_changed(sym);
+ }
+ /*
+ * setting a choice value also resets the new flag of the choice
+ * symbol and all other choice values.
+ */
+ if (sym_is_choice_value(sym) && val == yes) {
+ struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
+ struct property *prop;
+ struct expr *e;
+
+ cs->def[S_DEF_USER].val = sym;
+ cs->flags |= SYMBOL_DEF_USER;
+ prop = sym_get_choice_prop(cs);
+ for (e = prop->expr; e; e = e->left.expr) {
+ if (e->right.sym->visible != no)
+ e->right.sym->flags |= SYMBOL_DEF_USER;
+ }
+ }
+
+ sym->def[S_DEF_USER].tri = val;
+ if (oldval != val)
+ sym_clear_all_valid();
+
+ return true;
+}
+
+tristate sym_toggle_tristate_value(struct symbol *sym)
+{
+ tristate oldval, newval;
+
+ oldval = newval = sym_get_tristate_value(sym);
+ do {
+ switch (newval) {
+ case no:
+ newval = mod;
+ break;
+ case mod:
+ newval = yes;
+ break;
+ case yes:
+ newval = no;
+ break;
+ }
+ if (sym_set_tristate_value(sym, newval))
+ break;
+ } while (oldval != newval);
+ return newval;
+}
+
+bool sym_string_valid(struct symbol *sym, const char *str)
+{
+ signed char ch;
+
+ switch (sym->type) {
+ case S_STRING:
+ return true;
+ case S_INT:
+ ch = *str++;
+ if (ch == '-')
+ ch = *str++;
+ if (!isdigit(ch))
+ return false;
+ if (ch == '0' && *str != 0)
+ return false;
+ while ((ch = *str++)) {
+ if (!isdigit(ch))
+ return false;
+ }
+ return true;
+ case S_HEX:
+ if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
+ str += 2;
+ ch = *str++;
+ do {
+ if (!isxdigit(ch))
+ return false;
+ } while ((ch = *str++));
+ return true;
+ case S_BOOLEAN:
+ case S_TRISTATE:
+ switch (str[0]) {
+ case 'y': case 'Y':
+ case 'm': case 'M':
+ case 'n': case 'N':
+ return true;
+ }
+ return false;
+ default:
+ return false;
+ }
+}
+
+bool sym_string_within_range(struct symbol *sym, const char *str)
+{
+ struct property *prop;
+ int val;
+
+ switch (sym->type) {
+ case S_STRING:
+ return sym_string_valid(sym, str);
+ case S_INT:
+ if (!sym_string_valid(sym, str))
+ return false;
+ prop = sym_get_range_prop(sym);
+ if (!prop)
+ return true;
+ val = strtol(str, NULL, 10);
+ return val >= sym_get_range_val(prop->expr->left.sym, 10) &&
+ val <= sym_get_range_val(prop->expr->right.sym, 10);
+ case S_HEX:
+ if (!sym_string_valid(sym, str))
+ return false;
+ prop = sym_get_range_prop(sym);
+ if (!prop)
+ return true;
+ val = strtol(str, NULL, 16);
+ return val >= sym_get_range_val(prop->expr->left.sym, 16) &&
+ val <= sym_get_range_val(prop->expr->right.sym, 16);
+ case S_BOOLEAN:
+ case S_TRISTATE:
+ switch (str[0]) {
+ case 'y': case 'Y':
+ return sym_tristate_within_range(sym, yes);
+ case 'm': case 'M':
+ return sym_tristate_within_range(sym, mod);
+ case 'n': case 'N':
+ return sym_tristate_within_range(sym, no);
+ }
+ return false;
+ default:
+ return false;
+ }
+}
+
+bool sym_set_string_value(struct symbol *sym, const char *newval)
+{
+ const char *oldval;
+ char *val;
+ int size;
+
+ switch (sym->type) {
+ case S_BOOLEAN:
+ case S_TRISTATE:
+ switch (newval[0]) {
+ case 'y': case 'Y':
+ return sym_set_tristate_value(sym, yes);
+ case 'm': case 'M':
+ return sym_set_tristate_value(sym, mod);
+ case 'n': case 'N':
+ return sym_set_tristate_value(sym, no);
+ }
+ return false;
+ default:
+ ;
+ }
+
+ if (!sym_string_within_range(sym, newval))
+ return false;
+
+ if (!(sym->flags & SYMBOL_DEF_USER)) {
+ sym->flags |= SYMBOL_DEF_USER;
+ sym_set_changed(sym);
+ }
+
+ oldval = sym->def[S_DEF_USER].val;
+ size = strlen(newval) + 1;
+ if (sym->type == S_HEX && (newval[0] != '0' || (newval[1] != 'x' && newval[1] != 'X'))) {
+ size += 2;
+ sym->def[S_DEF_USER].val = val = malloc(size);
+ *val++ = '0';
+ *val++ = 'x';
+ } else if (!oldval || strcmp(oldval, newval))
+ sym->def[S_DEF_USER].val = val = malloc(size);
+ else
+ return true;
+
+ strcpy(val, newval);
+ free((void *)oldval);
+ sym_clear_all_valid();
+
+ return true;
+}
+
+/*
+ * Find the default value associated to a symbol.
+ * For tristate symbol handle the modules=n case
+ * in which case "m" becomes "y".
+ * If the symbol does not have any default then fallback
+ * to the fixed default values.
+ */
+const char *sym_get_string_default(struct symbol *sym)
+{
+ struct property *prop;
+ struct symbol *ds;
+ const char *str;
+ tristate val;
+
+ sym_calc_visibility(sym);
+ sym_calc_value(modules_sym);
+ val = symbol_no.curr.tri;
+ str = symbol_empty.curr.val;
+
+ /* If symbol has a default value look it up */
+ prop = sym_get_default_prop(sym);
+ if (prop != NULL) {
+ switch (sym->type) {
+ case S_BOOLEAN:
+ case S_TRISTATE:
+ /* The visibility may limit the value from yes => mod */
+ val = EXPR_AND(expr_calc_value(prop->expr), prop->visible.tri);
+ break;
+ default:
+ /*
+ * The following fails to handle the situation
+ * where a default value is further limited by
+ * the valid range.
+ */
+ ds = prop_get_symbol(prop);
+ if (ds != NULL) {
+ sym_calc_value(ds);
+ str = (const char *)ds->curr.val;
+ }
+ }
+ }
+
+ /* Handle select statements */
+ val = EXPR_OR(val, sym->rev_dep.tri);
+
+ /* transpose mod to yes if modules are not enabled */
+ if (val == mod)
+ if (!sym_is_choice_value(sym) && modules_sym->curr.tri == no)
+ val = yes;
+
+ /* transpose mod to yes if type is bool */
+ if (sym->type == S_BOOLEAN && val == mod)
+ val = yes;
+
+ switch (sym->type) {
+ case S_BOOLEAN:
+ case S_TRISTATE:
+ switch (val) {
+ case no: return "n";
+ case mod: return "m";
+ case yes: return "y";
+ }
+ case S_INT:
+ case S_HEX:
+ return str;
+ case S_STRING:
+ return str;
+ case S_OTHER:
+ case S_UNKNOWN:
+ break;
+ }
+ return "";
+}
+
+const char *sym_get_string_value(struct symbol *sym)
+{
+ tristate val;
+
+ switch (sym->type) {
+ case S_BOOLEAN:
+ case S_TRISTATE:
+ val = sym_get_tristate_value(sym);
+ switch (val) {
+ case no:
+ return "n";
+ case mod:
+ sym_calc_value(modules_sym);
+ return (modules_sym->curr.tri == no) ? "n" : "m";
+ case yes:
+ return "y";
+ }
+ break;
+ default:
+ ;
+ }
+ return (const char *)sym->curr.val;
+}
+
+bool sym_is_changable(struct symbol *sym)
+{
+ return sym->visible > sym->rev_dep.tri;
+}
+
+static unsigned strhash(const char *s)
+{
+ /* fnv32 hash */
+ unsigned hash = 2166136261U;
+ for (; *s; s++)
+ hash = (hash ^ *s) * 0x01000193;
+ return hash;
+}
+
+struct symbol *sym_lookup(const char *name, int flags)
+{
+ struct symbol *symbol;
+ char *new_name;
+ int hash;
+
+ if (name) {
+ if (name[0] && !name[1]) {
+ switch (name[0]) {
+ case 'y': return &symbol_yes;
+ case 'm': return &symbol_mod;
+ case 'n': return &symbol_no;
+ }
+ }
+ hash = strhash(name) % SYMBOL_HASHSIZE;
+
+ for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
+ if (symbol->name &&
+ !strcmp(symbol->name, name) &&
+ (flags ? symbol->flags & flags
+ : !(symbol->flags & (SYMBOL_CONST|SYMBOL_CHOICE))))
+ return symbol;
+ }
+ new_name = strdup(name);
+ } else {
+ new_name = NULL;
+ hash = 0;
+ }
+
+ symbol = malloc(sizeof(*symbol));
+ memset(symbol, 0, sizeof(*symbol));
+ symbol->name = new_name;
+ symbol->type = S_UNKNOWN;
+ symbol->flags |= flags;
+
+ symbol->next = symbol_hash[hash];
+ symbol_hash[hash] = symbol;
+
+ return symbol;
+}
+
+struct symbol *sym_find(const char *name)
+{
+ struct symbol *symbol = NULL;
+ int hash = 0;
+
+ if (!name)
+ return NULL;
+
+ if (name[0] && !name[1]) {
+ switch (name[0]) {
+ case 'y': return &symbol_yes;
+ case 'm': return &symbol_mod;
+ case 'n': return &symbol_no;
+ }
+ }
+ hash = strhash(name) % SYMBOL_HASHSIZE;
+
+ for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
+ if (symbol->name &&
+ !strcmp(symbol->name, name) &&
+ !(symbol->flags & SYMBOL_CONST))
+ break;
+ }
+
+ return symbol;
+}
+
+/*
+ * Expand symbol's names embedded in the string given in argument. Symbols'
+ * name to be expanded shall be prefixed by a '$'. Unknown symbol expands to
+ * the empty string.
+ */
+const char *sym_expand_string_value(const char *in)
+{
+ const char *src;
+ char *res;
+ size_t reslen;
+
+ reslen = strlen(in) + 1;
+ res = malloc(reslen);
+ res[0] = '\0';
+
+ while ((src = strchr(in, '$'))) {
+ char *p, name[SYMBOL_MAXLENGTH];
+ const char *symval = "";
+ struct symbol *sym;
+ size_t newlen;
+
+ strncat(res, in, src - in);
+ src++;
+
+ p = name;
+ while (isalnum(*src) || *src == '_')
+ *p++ = *src++;
+ *p = '\0';
+
+ sym = sym_find(name);
+ if (sym != NULL) {
+ sym_calc_value(sym);
+ symval = sym_get_string_value(sym);
+ }
+
+ newlen = strlen(res) + strlen(symval) + strlen(src) + 1;
+ if (newlen > reslen) {
+ reslen = newlen;
+ res = realloc(res, reslen);
+ }
+
+ strcat(res, symval);
+ in = src;
+ }
+ strcat(res, in);
+
+ return res;
+}
+
+const char *sym_escape_string_value(const char *in)
+{
+ const char *p;
+ size_t reslen;
+ char *res;
+ size_t l;
+
+ reslen = strlen(in) + strlen("\"\"") + 1;
+
+ p = in;
+ for (;;) {
+ l = strcspn(p, "\"\\");
+ p += l;
+
+ if (p[0] == '\0')
+ break;
+
+ reslen++;
+ p++;
+ }
+
+ res = malloc(reslen);
+ res[0] = '\0';
+
+ strcat(res, "\"");
+
+ p = in;
+ for (;;) {
+ l = strcspn(p, "\"\\");
+ strncat(res, p, l);
+ p += l;
+
+ if (p[0] == '\0')
+ break;
+
+ strcat(res, "\\");
+ strncat(res, p++, 1);
+ }
+
+ strcat(res, "\"");
+ return res;
+}
+
+struct symbol **sym_re_search(const char *pattern)
+{
+ struct symbol *sym, **sym_arr = NULL;
+ int i, cnt, size;
+ regex_t re;
+
+ cnt = size = 0;
+ /* Skip if empty */
+ if (strlen(pattern) == 0)
+ return NULL;
+ if (regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB|REG_ICASE))
+ return NULL;
+
+ for_all_symbols(i, sym) {
+ if (sym->flags & SYMBOL_CONST || !sym->name)
+ continue;
+ if (regexec(&re, sym->name, 0, NULL, 0))
+ continue;
+ if (cnt + 1 >= size) {
+ void *tmp = sym_arr;
+ size += 16;
+ sym_arr = realloc(sym_arr, size * sizeof(struct symbol *));
+ if (!sym_arr) {
+ free(tmp);
+ return NULL;
+ }
+ }
+ sym_calc_value(sym);
+ sym_arr[cnt++] = sym;
+ }
+ if (sym_arr)
+ sym_arr[cnt] = NULL;
+ regfree(&re);
+
+ return sym_arr;
+}
+
+/*
+ * When we check for recursive dependencies we use a stack to save
+ * current state so we can print out relevant info to user.
+ * The entries are located on the call stack so no need to free memory.
+ * Note inser() remove() must always match to properly clear the stack.
+ */
+static struct dep_stack {
+ struct dep_stack *prev, *next;
+ struct symbol *sym;
+ struct property *prop;
+ struct expr *expr;
+} *check_top;
+
+static void dep_stack_insert(struct dep_stack *stack, struct symbol *sym)
+{
+ memset(stack, 0, sizeof(*stack));
+ if (check_top)
+ check_top->next = stack;
+ stack->prev = check_top;
+ stack->sym = sym;
+ check_top = stack;
+}
+
+static void dep_stack_remove(void)
+{
+ check_top = check_top->prev;
+ if (check_top)
+ check_top->next = NULL;
+}
+
+/*
+ * Called when we have detected a recursive dependency.
+ * check_top point to the top of the stact so we use
+ * the ->prev pointer to locate the bottom of the stack.
+ */
+static void sym_check_print_recursive(struct symbol *last_sym)
+{
+ struct dep_stack *stack;
+ struct symbol *sym, *next_sym;
+ struct menu *menu = NULL;
+ struct property *prop;
+ struct dep_stack cv_stack;
+
+ if (sym_is_choice_value(last_sym)) {
+ dep_stack_insert(&cv_stack, last_sym);
+ last_sym = prop_get_symbol(sym_get_choice_prop(last_sym));
+ }
+
+ for (stack = check_top; stack != NULL; stack = stack->prev)
+ if (stack->sym == last_sym)
+ break;
+ if (!stack) {
+ fprintf(stderr, "unexpected recursive dependency error\n");
+ return;
+ }
+
+ for (; stack; stack = stack->next) {
+ sym = stack->sym;
+ next_sym = stack->next ? stack->next->sym : last_sym;
+ prop = stack->prop;
+ if (prop == NULL)
+ prop = stack->sym->prop;
+
+ /* for choice values find the menu entry (used below) */
+ if (sym_is_choice(sym) || sym_is_choice_value(sym)) {
+ for (prop = sym->prop; prop; prop = prop->next) {
+ menu = prop->menu;
+ if (prop->menu)
+ break;
+ }
+ }
+ if (stack->sym == last_sym)
+ fprintf(stderr, "%s:%d:error: recursive dependency detected!\n",
+ prop->file->name, prop->lineno);
+ if (stack->expr) {
+ fprintf(stderr, "%s:%d:\tsymbol %s %s value contains %s\n",
+ prop->file->name, prop->lineno,
+ sym->name ? sym->name : "<choice>",
+ prop_get_type_name(prop->type),
+ next_sym->name ? next_sym->name : "<choice>");
+ } else if (stack->prop) {
+ fprintf(stderr, "%s:%d:\tsymbol %s depends on %s\n",
+ prop->file->name, prop->lineno,
+ sym->name ? sym->name : "<choice>",
+ next_sym->name ? next_sym->name : "<choice>");
+ } else if (sym_is_choice(sym)) {
+ fprintf(stderr, "%s:%d:\tchoice %s contains symbol %s\n",
+ menu->file->name, menu->lineno,
+ sym->name ? sym->name : "<choice>",
+ next_sym->name ? next_sym->name : "<choice>");
+ } else if (sym_is_choice_value(sym)) {
+ fprintf(stderr, "%s:%d:\tsymbol %s is part of choice %s\n",
+ menu->file->name, menu->lineno,
+ sym->name ? sym->name : "<choice>",
+ next_sym->name ? next_sym->name : "<choice>");
+ } else {
+ fprintf(stderr, "%s:%d:\tsymbol %s is selected by %s\n",
+ prop->file->name, prop->lineno,
+ sym->name ? sym->name : "<choice>",
+ next_sym->name ? next_sym->name : "<choice>");
+ }
+ }
+
+ if (check_top == &cv_stack)
+ dep_stack_remove();
+}
+
+static struct symbol *sym_check_expr_deps(struct expr *e)
+{
+ struct symbol *sym;
+
+ if (!e)
+ return NULL;
+ switch (e->type) {
+ case E_OR:
+ case E_AND:
+ sym = sym_check_expr_deps(e->left.expr);
+ if (sym)
+ return sym;
+ return sym_check_expr_deps(e->right.expr);
+ case E_NOT:
+ return sym_check_expr_deps(e->left.expr);
+ case E_EQUAL:
+ case E_UNEQUAL:
+ sym = sym_check_deps(e->left.sym);
+ if (sym)
+ return sym;
+ return sym_check_deps(e->right.sym);
+ case E_SYMBOL:
+ return sym_check_deps(e->left.sym);
+ default:
+ break;
+ }
+ printf("Oops! How to check %d?\n", e->type);
+ return NULL;
+}
+
+/* return NULL when dependencies are OK */
+static struct symbol *sym_check_sym_deps(struct symbol *sym)
+{
+ struct symbol *sym2;
+ struct property *prop;
+ struct dep_stack stack;
+
+ dep_stack_insert(&stack, sym);
+
+ sym2 = sym_check_expr_deps(sym->rev_dep.expr);
+ if (sym2)
+ goto out;
+
+ for (prop = sym->prop; prop; prop = prop->next) {
+ if (prop->type == P_CHOICE || prop->type == P_SELECT)
+ continue;
+ stack.prop = prop;
+ sym2 = sym_check_expr_deps(prop->visible.expr);
+ if (sym2)
+ break;
+ if (prop->type != P_DEFAULT || sym_is_choice(sym))
+ continue;
+ stack.expr = prop->expr;
+ sym2 = sym_check_expr_deps(prop->expr);
+ if (sym2)
+ break;
+ stack.expr = NULL;
+ }
+
+out:
+ dep_stack_remove();
+
+ return sym2;
+}
+
+static struct symbol *sym_check_choice_deps(struct symbol *choice)
+{
+ struct symbol *sym, *sym2;
+ struct property *prop;
+ struct expr *e;
+ struct dep_stack stack;
+
+ dep_stack_insert(&stack, choice);
+
+ prop = sym_get_choice_prop(choice);
+ expr_list_for_each_sym(prop->expr, e, sym)
+ sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);
+
+ choice->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);
+ sym2 = sym_check_sym_deps(choice);
+ choice->flags &= ~SYMBOL_CHECK;
+ if (sym2)
+ goto out;
+
+ expr_list_for_each_sym(prop->expr, e, sym) {
+ sym2 = sym_check_sym_deps(sym);
+ if (sym2)
+ break;
+ }
+out:
+ expr_list_for_each_sym(prop->expr, e, sym)
+ sym->flags &= ~SYMBOL_CHECK;
+
+ if (sym2 && sym_is_choice_value(sym2) &&
+ prop_get_symbol(sym_get_choice_prop(sym2)) == choice)
+ sym2 = choice;
+
+ dep_stack_remove();
+
+ return sym2;
+}
+
+struct symbol *sym_check_deps(struct symbol *sym)
+{
+ struct symbol *sym2;
+ struct property *prop;
+
+ if (sym->flags & SYMBOL_CHECK) {
+ sym_check_print_recursive(sym);
+ return sym;
+ }
+ if (sym->flags & SYMBOL_CHECKED)
+ return NULL;
+
+ if (sym_is_choice_value(sym)) {
+ struct dep_stack stack;
+
+ /* for choice groups start the check with main choice symbol */
+ dep_stack_insert(&stack, sym);
+ prop = sym_get_choice_prop(sym);
+ sym2 = sym_check_deps(prop_get_symbol(prop));
+ dep_stack_remove();
+ } else if (sym_is_choice(sym)) {
+ sym2 = sym_check_choice_deps(sym);
+ } else {
+ sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);
+ sym2 = sym_check_sym_deps(sym);
+ sym->flags &= ~SYMBOL_CHECK;
+ }
+
+ if (sym2 && sym2 == sym)
+ sym2 = NULL;
+
+ return sym2;
+}
+
+struct property *prop_alloc(enum prop_type type, struct symbol *sym)
+{
+ struct property *prop;
+ struct property **propp;
+
+ prop = malloc(sizeof(*prop));
+ memset(prop, 0, sizeof(*prop));
+ prop->type = type;
+ prop->sym = sym;
+ prop->file = current_file;
+ prop->lineno = zconf_lineno();
+
+ /* append property to the prop list of symbol */
+ if (sym) {
+ for (propp = &sym->prop; *propp; propp = &(*propp)->next)
+ ;
+ *propp = prop;
+ }
+
+ return prop;
+}
+
+struct symbol *prop_get_symbol(struct property *prop)
+{
+ if (prop->expr && (prop->expr->type == E_SYMBOL ||
+ prop->expr->type == E_LIST))
+ return prop->expr->left.sym;
+ return NULL;
+}
+
+const char *prop_get_type_name(enum prop_type type)
+{
+ switch (type) {
+ case P_PROMPT:
+ return "prompt";
+ case P_ENV:
+ return "env";
+ case P_COMMENT:
+ return "comment";
+ case P_MENU:
+ return "menu";
+ case P_DEFAULT:
+ return "default";
+ case P_CHOICE:
+ return "choice";
+ case P_SELECT:
+ return "select";
+ case P_RANGE:
+ return "range";
+ case P_SYMBOL:
+ return "symbol";
+ case P_UNKNOWN:
+ break;
+ }
+ return "unknown";
+}
+
+static void prop_add_env(const char *env)
+{
+ struct symbol *sym, *sym2;
+ struct property *prop;
+ char *p;
+
+ sym = current_entry->sym;
+ sym->flags |= SYMBOL_AUTO;
+ for_all_properties(sym, prop, P_ENV) {
+ sym2 = prop_get_symbol(prop);
+ if (strcmp(sym2->name, env))
+ menu_warn(current_entry, "redefining environment symbol from %s",
+ sym2->name);
+ return;
+ }
+
+ prop = prop_alloc(P_ENV, sym);
+ prop->expr = expr_alloc_symbol(sym_lookup(env, SYMBOL_CONST));
+
+ sym_env_list = expr_alloc_one(E_LIST, sym_env_list);
+ sym_env_list->right.sym = sym;
+
+ p = getenv(env);
+ if (p)
+ sym_add_default(sym, p);
+ else
+ menu_warn(current_entry, "environment variable %s undefined", env);
+}
--- /dev/null
+/*
+ * Copyright (C) 2002-2005 Roman Zippel <zippel@linux-m68k.org>
+ * Copyright (C) 2002-2005 Sam Ravnborg <sam@ravnborg.org>
+ *
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include "lkc.h"
+
+/* file already present in list? If not add it */
+struct file *file_lookup(const char *name)
+{
+ struct file *file;
+ const char *file_name = sym_expand_string_value(name);
+
+ for (file = file_list; file; file = file->next) {
+ if (!strcmp(name, file->name)) {
+ free((void *)file_name);
+ return file;
+ }
+ }
+
+ file = malloc(sizeof(*file));
+ memset(file, 0, sizeof(*file));
+ file->name = file_name;
+ file->next = file_list;
+ file_list = file;
+ return file;
+}
+
+/* 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 gs;
+ gs.s = malloc(sizeof(char) * 64);
+ gs.len = 64;
+ gs.max_width = 0;
+ strcpy(gs.s, "\0");
+ return gs;
+}
+
+/* Allocate and assign growable string */
+struct gstr str_assign(const char *s)
+{
+ struct gstr gs;
+ gs.s = strdup(s);
+ gs.len = strlen(s) + 1;
+ gs.max_width = 0;
+ return gs;
+}
+
+/* Free storage for growable string */
+void str_free(struct gstr *gs)
+{
+ if (gs->s)
+ free(gs->s);
+ gs->s = NULL;
+ gs->len = 0;
+}
+
+/* Append to growable string */
+void str_append(struct gstr *gs, const char *s)
+{
+ size_t l;
+ if (s) {
+ l = strlen(gs->s) + strlen(s) + 1;
+ if (l > gs->len) {
+ gs->s = realloc(gs->s, l);
+ gs->len = l;
+ }
+ strcat(gs->s, s);
+ }
+}
+
+/* Append printf formatted string to growable string */
+void str_printf(struct gstr *gs, const char *fmt, ...)
+{
+ va_list ap;
+ char s[10000]; /* big enough... */
+ va_start(ap, fmt);
+ vsnprintf(s, sizeof(s), fmt, ap);
+ str_append(gs, s);
+ va_end(ap);
+}
+
+/* Retrieve value of growable string */
+const char *str_get(struct gstr *gs)
+{
+ return gs->s;
+}
+
--- /dev/null
+%{
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#include <ctype.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+
+#include "lkc.h"
+
+#define printd(mask, fmt...) if (cdebug & (mask)) printf(fmt)
+
+#define PRINTD 0x0001
+#define DEBUG_PARSE 0x0002
+
+int cdebug = PRINTD;
+
+extern int zconflex(void);
+static void zconfprint(const char *err, ...);
+static void zconf_error(const char *err, ...);
+static void zconferror(const char *err);
+static bool zconf_endtoken(const struct kconf_id *id, int starttoken, int endtoken);
+
+struct symbol *symbol_hash[SYMBOL_HASHSIZE];
+
+static struct menu *current_menu, *current_entry;
+
+%}
+%expect 30
+
+%union
+{
+ char *string;
+ struct file *file;
+ struct symbol *symbol;
+ struct expr *expr;
+ struct menu *menu;
+ const struct kconf_id *id;
+}
+
+%token <id>T_MAINMENU
+%token <id>T_MENU
+%token <id>T_ENDMENU
+%token <id>T_SOURCE
+%token <id>T_CHOICE
+%token <id>T_ENDCHOICE
+%token <id>T_COMMENT
+%token <id>T_CONFIG
+%token <id>T_MENUCONFIG
+%token <id>T_HELP
+%token <string> T_HELPTEXT
+%token <id>T_IF
+%token <id>T_ENDIF
+%token <id>T_DEPENDS
+%token <id>T_OPTIONAL
+%token <id>T_PROMPT
+%token <id>T_TYPE
+%token <id>T_DEFAULT
+%token <id>T_SELECT
+%token <id>T_RANGE
+%token <id>T_VISIBLE
+%token <id>T_OPTION
+%token <id>T_ON
+%token <string> T_WORD
+%token <string> T_WORD_QUOTE
+%token T_UNEQUAL
+%token T_CLOSE_PAREN
+%token T_OPEN_PAREN
+%token T_EOL
+
+%left T_OR
+%left T_AND
+%left T_EQUAL T_UNEQUAL
+%nonassoc T_NOT
+
+%type <string> prompt
+%type <symbol> symbol
+%type <expr> expr
+%type <expr> if_expr
+%type <id> end
+%type <id> option_name
+%type <menu> if_entry menu_entry choice_entry
+%type <string> symbol_option_arg word_opt
+
+%destructor {
+ fprintf(stderr, "%s:%d: missing end statement for this entry\n",
+ $$->file->name, $$->lineno);
+ if (current_menu == $$)
+ menu_end_menu();
+} if_entry menu_entry choice_entry
+
+%{
+/* Include zconf.hash.c here so it can see the token constants. */
+#include "hconf.c"
+%}
+
+%%
+input: nl start | start;
+
+start: mainmenu_stmt stmt_list | stmt_list;
+
+stmt_list:
+ /* empty */
+ | stmt_list common_stmt
+ | stmt_list choice_stmt
+ | stmt_list menu_stmt
+ | stmt_list end { zconf_error("unexpected end statement"); }
+ | stmt_list T_WORD error T_EOL { zconf_error("unknown statement \"%s\"", $2); }
+ | stmt_list option_name error T_EOL
+{
+ zconf_error("unexpected option \"%s\"", kconf_id_strings + $2->name);
+}
+ | stmt_list error T_EOL { zconf_error("invalid statement"); }
+;
+
+option_name:
+ T_DEPENDS | T_PROMPT | T_TYPE | T_SELECT | T_OPTIONAL | T_RANGE | T_DEFAULT | T_VISIBLE
+;
+
+common_stmt:
+ T_EOL
+ | if_stmt
+ | comment_stmt
+ | config_stmt
+ | menuconfig_stmt
+ | source_stmt
+;
+
+option_error:
+ T_WORD error T_EOL { zconf_error("unknown option \"%s\"", $1); }
+ | error T_EOL { zconf_error("invalid option"); }
+;
+
+
+/* config/menuconfig entry */
+
+config_entry_start: T_CONFIG T_WORD T_EOL
+{
+ struct symbol *sym = sym_lookup($2, 0);
+ sym->flags |= SYMBOL_OPTIONAL;
+ menu_add_entry(sym);
+ printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), $2);
+};
+
+config_stmt: config_entry_start config_option_list
+{
+ menu_end_entry();
+ printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno());
+};
+
+menuconfig_entry_start: T_MENUCONFIG T_WORD T_EOL
+{
+ struct symbol *sym = sym_lookup($2, 0);
+ sym->flags |= SYMBOL_OPTIONAL;
+ menu_add_entry(sym);
+ printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), $2);
+};
+
+menuconfig_stmt: menuconfig_entry_start config_option_list
+{
+ if (current_entry->prompt)
+ current_entry->prompt->type = P_MENU;
+ else
+ zconfprint("warning: menuconfig statement without prompt");
+ menu_end_entry();
+ printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno());
+};
+
+config_option_list:
+ /* empty */
+ | config_option_list config_option
+ | config_option_list symbol_option
+ | config_option_list depends
+ | config_option_list help
+ | config_option_list option_error
+ | config_option_list T_EOL
+;
+
+config_option: T_TYPE prompt_stmt_opt T_EOL
+{
+ menu_set_type($1->stype);
+ printd(DEBUG_PARSE, "%s:%d:type(%u)\n",
+ zconf_curname(), zconf_lineno(),
+ $1->stype);
+};
+
+config_option: T_PROMPT prompt if_expr T_EOL
+{
+ menu_add_prompt(P_PROMPT, $2, $3);
+ printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
+};
+
+config_option: T_DEFAULT expr if_expr T_EOL
+{
+ menu_add_expr(P_DEFAULT, $2, $3);
+ if ($1->stype != S_UNKNOWN)
+ menu_set_type($1->stype);
+ printd(DEBUG_PARSE, "%s:%d:default(%u)\n",
+ zconf_curname(), zconf_lineno(),
+ $1->stype);
+};
+
+config_option: T_SELECT T_WORD if_expr T_EOL
+{
+ menu_add_symbol(P_SELECT, sym_lookup($2, 0), $3);
+ printd(DEBUG_PARSE, "%s:%d:select\n", zconf_curname(), zconf_lineno());
+};
+
+config_option: T_RANGE symbol symbol if_expr T_EOL
+{
+ menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,$2, $3), $4);
+ 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: T_CHOICE word_opt T_EOL
+{
+ struct symbol *sym = sym_lookup($2, SYMBOL_CHOICE);
+ sym->flags |= SYMBOL_AUTO;
+ menu_add_entry(sym);
+ menu_add_expr(P_CHOICE, NULL, NULL);
+ printd(DEBUG_PARSE, "%s:%d:choice\n", zconf_curname(), zconf_lineno());
+};
+
+choice_entry: choice choice_option_list
+{
+ $$ = menu_add_menu();
+};
+
+choice_end: end
+{
+ if (zconf_endtoken($1, T_CHOICE, T_ENDCHOICE)) {
+ menu_end_menu();
+ printd(DEBUG_PARSE, "%s:%d:endchoice\n", zconf_curname(), zconf_lineno());
+ }
+};
+
+choice_stmt: choice_entry choice_block choice_end
+;
+
+choice_option_list:
+ /* empty */
+ | choice_option_list choice_option
+ | choice_option_list depends
+ | choice_option_list help
+ | choice_option_list T_EOL
+ | choice_option_list option_error
+;
+
+choice_option: T_PROMPT prompt if_expr T_EOL
+{
+ menu_add_prompt(P_PROMPT, $2, $3);
+ printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
+};
+
+choice_option: T_TYPE prompt_stmt_opt T_EOL
+{
+ if ($1->stype == S_BOOLEAN || $1->stype == S_TRISTATE) {
+ menu_set_type($1->stype);
+ printd(DEBUG_PARSE, "%s:%d:type(%u)\n",
+ zconf_curname(), zconf_lineno(),
+ $1->stype);
+ } else
+ YYERROR;
+};
+
+choice_option: T_OPTIONAL T_EOL
+{
+ current_entry->sym->flags |= SYMBOL_OPTIONAL;
+ printd(DEBUG_PARSE, "%s:%d:optional\n", zconf_curname(), zconf_lineno());
+};
+
+choice_option: T_DEFAULT T_WORD if_expr T_EOL
+{
+ if ($1->stype == S_UNKNOWN) {
+ menu_add_symbol(P_DEFAULT, sym_lookup($2, 0), $3);
+ printd(DEBUG_PARSE, "%s:%d:default\n",
+ zconf_curname(), zconf_lineno());
+ } else
+ YYERROR;
+};
+
+choice_block:
+ /* empty */
+ | choice_block common_stmt
+;
+
+/* if entry */
+
+if_entry: T_IF expr nl
+{
+ printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno());
+ menu_add_entry(NULL);
+ menu_add_dep($2);
+ $$ = menu_add_menu();
+};
+
+if_end: end
+{
+ if (zconf_endtoken($1, T_IF, T_ENDIF)) {
+ menu_end_menu();
+ printd(DEBUG_PARSE, "%s:%d:endif\n", zconf_curname(), zconf_lineno());
+ }
+};
+
+if_stmt: if_entry if_block if_end
+;
+
+if_block:
+ /* empty */
+ | if_block common_stmt
+ | if_block menu_stmt
+ | if_block choice_stmt
+;
+
+/* mainmenu entry */
+
+mainmenu_stmt: T_MAINMENU prompt nl
+{
+ menu_add_prompt(P_MENU, $2, NULL);
+};
+
+/* menu entry */
+
+menu: T_MENU prompt T_EOL
+{
+ menu_add_entry(NULL);
+ menu_add_prompt(P_MENU, $2, NULL);
+ printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno());
+};
+
+menu_entry: menu visibility_list depends_list
+{
+ $$ = menu_add_menu();
+};
+
+menu_end: end
+{
+ if (zconf_endtoken($1, T_MENU, T_ENDMENU)) {
+ menu_end_menu();
+ printd(DEBUG_PARSE, "%s:%d:endmenu\n", zconf_curname(), zconf_lineno());
+ }
+};
+
+menu_stmt: menu_entry menu_block menu_end
+;
+
+menu_block:
+ /* empty */
+ | menu_block common_stmt
+ | menu_block menu_stmt
+ | menu_block choice_stmt
+;
+
+source_stmt: T_SOURCE prompt T_EOL
+{
+ printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), $2);
+ zconf_nextfile($2);
+};
+
+/* comment entry */
+
+comment: T_COMMENT prompt T_EOL
+{
+ menu_add_entry(NULL);
+ menu_add_prompt(P_COMMENT, $2, NULL);
+ printd(DEBUG_PARSE, "%s:%d:comment\n", zconf_curname(), zconf_lineno());
+};
+
+comment_stmt: comment depends_list
+{
+ menu_end_entry();
+};
+
+/* help option */
+
+help_start: T_HELP T_EOL
+{
+ printd(DEBUG_PARSE, "%s:%d:help\n", zconf_curname(), zconf_lineno());
+ zconf_starthelp();
+};
+
+help: help_start T_HELPTEXT
+{
+ current_entry->help = $2;
+};
+
+/* depends option */
+
+depends_list:
+ /* empty */
+ | depends_list depends
+ | depends_list T_EOL
+ | depends_list option_error
+;
+
+depends: T_DEPENDS T_ON expr T_EOL
+{
+ menu_add_dep($3);
+ printd(DEBUG_PARSE, "%s:%d:depends on\n", zconf_curname(), zconf_lineno());
+};
+
+/* visibility option */
+
+visibility_list:
+ /* empty */
+ | visibility_list visible
+ | visibility_list T_EOL
+;
+
+visible: T_VISIBLE if_expr
+{
+ menu_add_visibility($2);
+};
+
+/* prompt statement */
+
+prompt_stmt_opt:
+ /* empty */
+ | prompt if_expr
+{
+ menu_add_prompt(P_PROMPT, $1, $2);
+};
+
+prompt: T_WORD
+ | T_WORD_QUOTE
+;
+
+end: T_ENDMENU T_EOL { $$ = $1; }
+ | T_ENDCHOICE T_EOL { $$ = $1; }
+ | T_ENDIF T_EOL { $$ = $1; }
+;
+
+nl:
+ T_EOL
+ | nl T_EOL
+;
+
+if_expr: /* empty */ { $$ = NULL; }
+ | T_IF expr { $$ = $2; }
+;
+
+expr: symbol { $$ = expr_alloc_symbol($1); }
+ | symbol T_EQUAL symbol { $$ = expr_alloc_comp(E_EQUAL, $1, $3); }
+ | symbol T_UNEQUAL symbol { $$ = expr_alloc_comp(E_UNEQUAL, $1, $3); }
+ | T_OPEN_PAREN expr T_CLOSE_PAREN { $$ = $2; }
+ | T_NOT expr { $$ = expr_alloc_one(E_NOT, $2); }
+ | expr T_OR expr { $$ = expr_alloc_two(E_OR, $1, $3); }
+ | expr T_AND expr { $$ = expr_alloc_two(E_AND, $1, $3); }
+;
+
+symbol: T_WORD { $$ = sym_lookup($1, 0); free($1); }
+ | T_WORD_QUOTE { $$ = sym_lookup($1, SYMBOL_CONST); free($1); }
+;
+
+word_opt: /* empty */ { $$ = NULL; }
+ | T_WORD
+
+%%
+
+void conf_parse(const char *name)
+{
+ struct symbol *sym;
+ int i;
+
+ zconf_initscan(name);
+
+ sym_init();
+ _menu_init();
+ modules_sym = sym_lookup(NULL, 0);
+ modules_sym->type = S_BOOLEAN;
+ modules_sym->flags |= SYMBOL_AUTO;
+ rootmenu.prompt = menu_add_prompt(P_MENU, "Linux Kernel Configuration", NULL);
+
+ if (getenv("ZCONF_DEBUG"))
+ zconfdebug = 1;
+ zconfparse();
+ if (zconfnerrs)
+ 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);
+ for_all_symbols(i, sym) {
+ if (sym_check_deps(sym))
+ zconfnerrs++;
+ }
+ if (zconfnerrs)
+ exit(1);
+ sym_set_change_count(1);
+}
+
+static const char *zconf_tokenname(int token)
+{
+ switch (token) {
+ case T_MENU: return "menu";
+ case T_ENDMENU: return "endmenu";
+ case T_CHOICE: return "choice";
+ case T_ENDCHOICE: return "endchoice";
+ case T_IF: return "if";
+ case T_ENDIF: return "endif";
+ case T_DEPENDS: return "depends";
+ case T_VISIBLE: return "visible";
+ }
+ return "<token>";
+}
+
+static bool zconf_endtoken(const struct kconf_id *id, int starttoken, int endtoken)
+{
+ if (id->token != endtoken) {
+ zconf_error("unexpected '%s' within %s block",
+ kconf_id_strings + id->name, zconf_tokenname(starttoken));
+ zconfnerrs++;
+ return false;
+ }
+ if (current_menu->file != current_file) {
+ zconf_error("'%s' in different file than '%s'",
+ kconf_id_strings + id->name, zconf_tokenname(starttoken));
+ fprintf(stderr, "%s:%d: location of the '%s'\n",
+ current_menu->file->name, current_menu->lineno,
+ zconf_tokenname(starttoken));
+ zconfnerrs++;
+ return false;
+ }
+ return true;
+}
+
+static void zconfprint(const char *err, ...)
+{
+ va_list ap;
+
+ fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno());
+ va_start(ap, err);
+ vfprintf(stderr, err, ap);
+ va_end(ap);
+ fprintf(stderr, "\n");
+}
+
+static void zconf_error(const char *err, ...)
+{
+ va_list ap;
+
+ zconfnerrs++;
+ fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno());
+ va_start(ap, err);
+ vfprintf(stderr, err, ap);
+ va_end(ap);
+ fprintf(stderr, "\n");
+}
+
+static void zconferror(const char *err)
+{
+ fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno() + 1, err);
+}
+
+static void print_quoted_string(FILE *out, const char *str)
+{
+ const char *p;
+ int len;
+
+ putc('"', out);
+ while ((p = strchr(str, '"'))) {
+ len = p - str;
+ if (len)
+ fprintf(out, "%.*s", len, str);
+ fputs("\\\"", out);
+ str = p + 1;
+ }
+ fputs(str, out);
+ putc('"', out);
+}
+
+static void print_symbol(FILE *out, struct menu *menu)
+{
+ struct symbol *sym = menu->sym;
+ struct property *prop;
+
+ if (sym_is_choice(sym))
+ fprintf(out, "\nchoice\n");
+ else
+ fprintf(out, "\nconfig %s\n", sym->name);
+ switch (sym->type) {
+ case S_BOOLEAN:
+ fputs(" boolean\n", out);
+ break;
+ case S_TRISTATE:
+ fputs(" tristate\n", out);
+ break;
+ case S_STRING:
+ fputs(" string\n", out);
+ break;
+ case S_INT:
+ fputs(" integer\n", out);
+ break;
+ case S_HEX:
+ fputs(" hex\n", out);
+ break;
+ default:
+ fputs(" ???\n", out);
+ break;
+ }
+ for (prop = sym->prop; prop; prop = prop->next) {
+ if (prop->menu != menu)
+ continue;
+ switch (prop->type) {
+ case P_PROMPT:
+ fputs(" prompt ", out);
+ print_quoted_string(out, prop->text);
+ if (!expr_is_yes(prop->visible.expr)) {
+ fputs(" if ", out);
+ expr_fprint(prop->visible.expr, out);
+ }
+ fputc('\n', out);
+ break;
+ case P_DEFAULT:
+ fputs( " default ", out);
+ expr_fprint(prop->expr, out);
+ if (!expr_is_yes(prop->visible.expr)) {
+ fputs(" if ", out);
+ expr_fprint(prop->visible.expr, out);
+ }
+ fputc('\n', out);
+ break;
+ case P_CHOICE:
+ fputs(" #choice value\n", out);
+ 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:
+ fprintf(out, " unknown prop %d!\n", prop->type);
+ break;
+ }
+ }
+ if (menu->help) {
+ int len = strlen(menu->help);
+ while (menu->help[--len] == '\n')
+ menu->help[len] = 0;
+ fprintf(out, " help\n%s\n", menu->help);
+ }
+}
+
+void zconfdump(FILE *out)
+{
+ struct property *prop;
+ struct symbol *sym;
+ struct menu *menu;
+
+ menu = rootmenu.list;
+ while (menu) {
+ if ((sym = menu->sym))
+ print_symbol(out, menu);
+ else if ((prop = menu->prompt)) {
+ switch (prop->type) {
+ case P_COMMENT:
+ fputs("\ncomment ", out);
+ print_quoted_string(out, prop->text);
+ fputs("\n", out);
+ break;
+ case P_MENU:
+ fputs("\nmenu ", out);
+ print_quoted_string(out, prop->text);
+ fputs("\n", out);
+ break;
+ default:
+ ;
+ }
+ if (!expr_is_yes(prop->visible.expr)) {
+ fputs(" depends ", out);
+ expr_fprint(prop->visible.expr, out);
+ fputc('\n', out);
+ }
+ }
+
+ if (menu->list)
+ menu = menu->list;
+ else if (menu->next)
+ menu = menu->next;
+ else while ((menu = menu->parent)) {
+ if (menu->prompt && menu->prompt->type == P_MENU)
+ fputs("\nendmenu\n", out);
+ if (menu->next) {
+ menu = menu->next;
+ break;
+ }
+ }
+ }
+}
+
+#include "lconf.c"
+#include "util.c"
+#include "confdata.c"
+#include "expr.c"
+#include "symbol.c"
+#include "menu.c"
+++ /dev/null
-/*
- * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
- * Released under the terms of the GNU GPL v2.0.
- */
-
-#include <qglobal.h>
-
-#if QT_VERSION < 0x040000
-#include <qmainwindow.h>
-#include <qvbox.h>
-#include <qvaluelist.h>
-#include <qtextbrowser.h>
-#include <qaction.h>
-#include <qheader.h>
-#include <qfiledialog.h>
-#include <qdragobject.h>
-#include <qpopupmenu.h>
-#else
-#include <q3mainwindow.h>
-#include <q3vbox.h>
-#include <q3valuelist.h>
-#include <q3textbrowser.h>
-#include <q3action.h>
-#include <q3header.h>
-#include <q3filedialog.h>
-#include <q3dragobject.h>
-#include <q3popupmenu.h>
-#endif
-
-#include <qapplication.h>
-#include <qdesktopwidget.h>
-#include <qtoolbar.h>
-#include <qlayout.h>
-#include <qsplitter.h>
-#include <qlineedit.h>
-#include <qlabel.h>
-#include <qpushbutton.h>
-#include <qmenubar.h>
-#include <qmessagebox.h>
-#include <qregexp.h>
-#include <qevent.h>
-
-#include <stdlib.h>
-
-#include "lkc.h"
-#include "qconf.h"
-
-#include "qconf.moc"
-#include "images.c"
-
-#ifdef _
-# undef _
-# define _ qgettext
-#endif
-
-static QApplication *configApp;
-static ConfigSettings *configSettings;
-
-Q3Action *ConfigMainWindow::saveAction;
-
-static inline QString qgettext(const char* str)
-{
- return QString::fromLocal8Bit(gettext(str));
-}
-
-static inline QString qgettext(const QString& str)
-{
- return QString::fromLocal8Bit(gettext(str.latin1()));
-}
-
-/**
- * Reads a list of integer values from the application settings.
- */
-Q3ValueList<int> ConfigSettings::readSizes(const QString& key, bool *ok)
-{
- Q3ValueList<int> result;
- QStringList entryList = readListEntry(key, ok);
- QStringList::Iterator it;
-
- for (it = entryList.begin(); it != entryList.end(); ++it)
- result.push_back((*it).toInt());
-
- return result;
-}
-
-/**
- * Writes a list of integer values to the application settings.
- */
-bool ConfigSettings::writeSizes(const QString& key, const Q3ValueList<int>& value)
-{
- QStringList stringList;
- Q3ValueList<int>::ConstIterator it;
-
- for (it = value.begin(); it != value.end(); ++it)
- stringList.push_back(QString::number(*it));
- return writeEntry(key, stringList);
-}
-
-
-/*
- * set the new data
- * TODO check the value
- */
-void ConfigItem::okRename(int col)
-{
- Parent::okRename(col);
- sym_set_string_value(menu->sym, text(dataColIdx).latin1());
- listView()->updateList(this);
-}
-
-/*
- * update the displayed of a menu entry
- */
-void ConfigItem::updateMenu(void)
-{
- ConfigList* list;
- struct symbol* sym;
- struct property *prop;
- QString prompt;
- int type;
- tristate expr;
-
- list = listView();
- if (goParent) {
- setPixmap(promptColIdx, list->menuBackPix);
- prompt = "..";
- goto set_prompt;
- }
-
- sym = menu->sym;
- prop = menu->prompt;
- prompt = _(menu_get_prompt(menu));
-
- if (prop) switch (prop->type) {
- case P_MENU:
- if (list->mode == singleMode || list->mode == symbolMode) {
- /* a menuconfig entry is displayed differently
- * depending whether it's at the view root or a child.
- */
- if (sym && list->rootEntry == menu)
- break;
- setPixmap(promptColIdx, list->menuPix);
- } else {
- if (sym)
- break;
- setPixmap(promptColIdx, 0);
- }
- goto set_prompt;
- case P_COMMENT:
- setPixmap(promptColIdx, 0);
- goto set_prompt;
- default:
- ;
- }
- if (!sym)
- goto set_prompt;
-
- setText(nameColIdx, QString::fromLocal8Bit(sym->name));
-
- type = sym_get_type(sym);
- switch (type) {
- case S_BOOLEAN:
- case S_TRISTATE:
- char ch;
-
- if (!sym_is_changable(sym) && list->optMode == normalOpt) {
- setPixmap(promptColIdx, 0);
- setText(noColIdx, QString::null);
- setText(modColIdx, QString::null);
- setText(yesColIdx, QString::null);
- break;
- }
- expr = sym_get_tristate_value(sym);
- switch (expr) {
- case yes:
- if (sym_is_choice_value(sym) && type == S_BOOLEAN)
- setPixmap(promptColIdx, list->choiceYesPix);
- else
- setPixmap(promptColIdx, list->symbolYesPix);
- setText(yesColIdx, "Y");
- ch = 'Y';
- break;
- case mod:
- setPixmap(promptColIdx, list->symbolModPix);
- setText(modColIdx, "M");
- ch = 'M';
- break;
- default:
- if (sym_is_choice_value(sym) && type == S_BOOLEAN)
- setPixmap(promptColIdx, list->choiceNoPix);
- else
- setPixmap(promptColIdx, list->symbolNoPix);
- setText(noColIdx, "N");
- ch = 'N';
- break;
- }
- if (expr != no)
- setText(noColIdx, sym_tristate_within_range(sym, no) ? "_" : 0);
- if (expr != mod)
- setText(modColIdx, sym_tristate_within_range(sym, mod) ? "_" : 0);
- if (expr != yes)
- setText(yesColIdx, sym_tristate_within_range(sym, yes) ? "_" : 0);
-
- setText(dataColIdx, QChar(ch));
- break;
- case S_INT:
- case S_HEX:
- case S_STRING:
- const char* data;
-
- data = sym_get_string_value(sym);
-
- int i = list->mapIdx(dataColIdx);
- if (i >= 0)
- setRenameEnabled(i, TRUE);
- setText(dataColIdx, data);
- if (type == S_STRING)
- prompt = QString("%1: %2").arg(prompt).arg(data);
- else
- prompt = QString("(%2) %1").arg(prompt).arg(data);
- break;
- }
- if (!sym_has_value(sym) && visible)
- prompt += _(" (NEW)");
-set_prompt:
- setText(promptColIdx, prompt);
-}
-
-void ConfigItem::testUpdateMenu(bool v)
-{
- ConfigItem* i;
-
- visible = v;
- if (!menu)
- return;
-
- sym_calc_value(menu->sym);
- if (menu->flags & MENU_CHANGED) {
- /* the menu entry changed, so update all list items */
- menu->flags &= ~MENU_CHANGED;
- for (i = (ConfigItem*)menu->data; i; i = i->nextItem)
- i->updateMenu();
- } else if (listView()->updateAll)
- updateMenu();
-}
-
-void ConfigItem::paintCell(QPainter* p, const QColorGroup& cg, int column, int width, int align)
-{
- ConfigList* list = listView();
-
- if (visible) {
- if (isSelected() && !list->hasFocus() && list->mode == menuMode)
- Parent::paintCell(p, list->inactivedColorGroup, column, width, align);
- else
- Parent::paintCell(p, cg, column, width, align);
- } else
- Parent::paintCell(p, list->disabledColorGroup, column, width, align);
-}
-
-/*
- * construct a menu entry
- */
-void ConfigItem::init(void)
-{
- if (menu) {
- ConfigList* list = listView();
- nextItem = (ConfigItem*)menu->data;
- menu->data = this;
-
- if (list->mode != fullMode)
- setOpen(TRUE);
- sym_calc_value(menu->sym);
- }
- updateMenu();
-}
-
-/*
- * destruct a menu entry
- */
-ConfigItem::~ConfigItem(void)
-{
- if (menu) {
- ConfigItem** ip = (ConfigItem**)&menu->data;
- for (; *ip; ip = &(*ip)->nextItem) {
- if (*ip == this) {
- *ip = nextItem;
- break;
- }
- }
- }
-}
-
-ConfigLineEdit::ConfigLineEdit(ConfigView* parent)
- : Parent(parent)
-{
- connect(this, SIGNAL(lostFocus()), SLOT(hide()));
-}
-
-void ConfigLineEdit::show(ConfigItem* i)
-{
- item = i;
- if (sym_get_string_value(item->menu->sym))
- setText(QString::fromLocal8Bit(sym_get_string_value(item->menu->sym)));
- else
- setText(QString::null);
- Parent::show();
- setFocus();
-}
-
-void ConfigLineEdit::keyPressEvent(QKeyEvent* e)
-{
- switch (e->key()) {
- case Qt::Key_Escape:
- break;
- case Qt::Key_Return:
- case Qt::Key_Enter:
- sym_set_string_value(item->menu->sym, text().latin1());
- parent()->updateList(item);
- break;
- default:
- Parent::keyPressEvent(e);
- return;
- }
- e->accept();
- parent()->list->setFocus();
- hide();
-}
-
-ConfigList::ConfigList(ConfigView* p, const char *name)
- : Parent(p, name),
- updateAll(false),
- symbolYesPix(xpm_symbol_yes), symbolModPix(xpm_symbol_mod), symbolNoPix(xpm_symbol_no),
- choiceYesPix(xpm_choice_yes), choiceNoPix(xpm_choice_no),
- menuPix(xpm_menu), menuInvPix(xpm_menu_inv), menuBackPix(xpm_menuback), voidPix(xpm_void),
- showName(false), showRange(false), showData(false), optMode(normalOpt),
- rootEntry(0), headerPopup(0)
-{
- int i;
-
- setSorting(-1);
- setRootIsDecorated(TRUE);
- disabledColorGroup = palette().active();
- disabledColorGroup.setColor(QColorGroup::Text, palette().disabled().text());
- inactivedColorGroup = palette().active();
- inactivedColorGroup.setColor(QColorGroup::Highlight, palette().disabled().highlight());
-
- connect(this, SIGNAL(selectionChanged(void)),
- SLOT(updateSelection(void)));
-
- if (name) {
- configSettings->beginGroup(name);
- showName = configSettings->readBoolEntry("/showName", false);
- showRange = configSettings->readBoolEntry("/showRange", false);
- showData = configSettings->readBoolEntry("/showData", false);
- optMode = (enum optionMode)configSettings->readNumEntry("/optionMode", false);
- configSettings->endGroup();
- connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings()));
- }
-
- for (i = 0; i < colNr; i++)
- colMap[i] = colRevMap[i] = -1;
- addColumn(promptColIdx, _("Option"));
-
- reinit();
-}
-
-bool ConfigList::menuSkip(struct menu *menu)
-{
- if (optMode == normalOpt && menu_is_visible(menu))
- return false;
- if (optMode == promptOpt && menu_has_prompt(menu))
- return false;
- if (optMode == allOpt)
- return false;
- return true;
-}
-
-void ConfigList::reinit(void)
-{
- removeColumn(dataColIdx);
- removeColumn(yesColIdx);
- removeColumn(modColIdx);
- removeColumn(noColIdx);
- removeColumn(nameColIdx);
-
- if (showName)
- addColumn(nameColIdx, _("Name"));
- if (showRange) {
- addColumn(noColIdx, "N");
- addColumn(modColIdx, "M");
- addColumn(yesColIdx, "Y");
- }
- if (showData)
- addColumn(dataColIdx, _("Value"));
-
- updateListAll();
-}
-
-void ConfigList::saveSettings(void)
-{
- if (name()) {
- configSettings->beginGroup(name());
- configSettings->writeEntry("/showName", showName);
- configSettings->writeEntry("/showRange", showRange);
- configSettings->writeEntry("/showData", showData);
- configSettings->writeEntry("/optionMode", (int)optMode);
- configSettings->endGroup();
- }
-}
-
-ConfigItem* ConfigList::findConfigItem(struct menu *menu)
-{
- ConfigItem* item = (ConfigItem*)menu->data;
-
- for (; item; item = item->nextItem) {
- if (this == item->listView())
- break;
- }
-
- return item;
-}
-
-void ConfigList::updateSelection(void)
-{
- struct menu *menu;
- enum prop_type type;
-
- ConfigItem* item = (ConfigItem*)selectedItem();
- if (!item)
- return;
-
- menu = item->menu;
- emit menuChanged(menu);
- if (!menu)
- return;
- type = menu->prompt ? menu->prompt->type : P_UNKNOWN;
- if (mode == menuMode && type == P_MENU)
- emit menuSelected(menu);
-}
-
-void ConfigList::updateList(ConfigItem* item)
-{
- ConfigItem* last = 0;
-
- if (!rootEntry) {
- if (mode != listMode)
- goto update;
- Q3ListViewItemIterator it(this);
- ConfigItem* item;
-
- for (; it.current(); ++it) {
- item = (ConfigItem*)it.current();
- if (!item->menu)
- continue;
- item->testUpdateMenu(menu_is_visible(item->menu));
- }
- return;
- }
-
- if (rootEntry != &rootmenu && (mode == singleMode ||
- (mode == symbolMode && rootEntry->parent != &rootmenu))) {
- item = firstChild();
- if (!item)
- item = new ConfigItem(this, 0, true);
- last = item;
- }
- if ((mode == singleMode || (mode == symbolMode && !(rootEntry->flags & MENU_ROOT))) &&
- rootEntry->sym && rootEntry->prompt) {
- item = last ? last->nextSibling() : firstChild();
- if (!item)
- item = new ConfigItem(this, last, rootEntry, true);
- else
- item->testUpdateMenu(true);
-
- updateMenuList(item, rootEntry);
- triggerUpdate();
- return;
- }
-update:
- updateMenuList(this, rootEntry);
- triggerUpdate();
-}
-
-void ConfigList::setValue(ConfigItem* item, tristate val)
-{
- struct symbol* sym;
- int type;
- tristate oldval;
-
- sym = item->menu ? item->menu->sym : 0;
- if (!sym)
- return;
-
- type = sym_get_type(sym);
- switch (type) {
- case S_BOOLEAN:
- case S_TRISTATE:
- oldval = sym_get_tristate_value(sym);
-
- if (!sym_set_tristate_value(sym, val))
- return;
- if (oldval == no && item->menu->list)
- item->setOpen(TRUE);
- parent()->updateList(item);
- break;
- }
-}
-
-void ConfigList::changeValue(ConfigItem* item)
-{
- struct symbol* sym;
- struct menu* menu;
- int type, oldexpr, newexpr;
-
- menu = item->menu;
- if (!menu)
- return;
- sym = menu->sym;
- if (!sym) {
- if (item->menu->list)
- item->setOpen(!item->isOpen());
- return;
- }
-
- type = sym_get_type(sym);
- switch (type) {
- case S_BOOLEAN:
- case S_TRISTATE:
- oldexpr = sym_get_tristate_value(sym);
- newexpr = sym_toggle_tristate_value(sym);
- if (item->menu->list) {
- if (oldexpr == newexpr)
- item->setOpen(!item->isOpen());
- else if (oldexpr == no)
- item->setOpen(TRUE);
- }
- if (oldexpr != newexpr)
- parent()->updateList(item);
- break;
- case S_INT:
- case S_HEX:
- case S_STRING:
- if (colMap[dataColIdx] >= 0)
- item->startRename(colMap[dataColIdx]);
- else
- parent()->lineEdit->show(item);
- break;
- }
-}
-
-void ConfigList::setRootMenu(struct menu *menu)
-{
- enum prop_type type;
-
- if (rootEntry == menu)
- return;
- type = menu && menu->prompt ? menu->prompt->type : P_UNKNOWN;
- if (type != P_MENU)
- return;
- updateMenuList(this, 0);
- rootEntry = menu;
- updateListAll();
- setSelected(currentItem(), hasFocus());
- ensureItemVisible(currentItem());
-}
-
-void ConfigList::setParentMenu(void)
-{
- ConfigItem* item;
- struct menu *oldroot;
-
- oldroot = rootEntry;
- if (rootEntry == &rootmenu)
- return;
- setRootMenu(menu_get_parent_menu(rootEntry->parent));
-
- Q3ListViewItemIterator it(this);
- for (; (item = (ConfigItem*)it.current()); it++) {
- if (item->menu == oldroot) {
- setCurrentItem(item);
- ensureItemVisible(item);
- break;
- }
- }
-}
-
-/*
- * update all the children of a menu entry
- * removes/adds the entries from the parent widget as necessary
- *
- * parent: either the menu list widget or a menu entry widget
- * menu: entry to be updated
- */
-template <class P>
-void ConfigList::updateMenuList(P* parent, struct menu* menu)
-{
- struct menu* child;
- ConfigItem* item;
- ConfigItem* last;
- bool visible;
- enum prop_type type;
-
- if (!menu) {
- while ((item = parent->firstChild()))
- delete item;
- return;
- }
-
- last = parent->firstChild();
- if (last && !last->goParent)
- last = 0;
- for (child = menu->list; child; child = child->next) {
- item = last ? last->nextSibling() : parent->firstChild();
- type = child->prompt ? child->prompt->type : P_UNKNOWN;
-
- switch (mode) {
- case menuMode:
- if (!(child->flags & MENU_ROOT))
- goto hide;
- break;
- case symbolMode:
- if (child->flags & MENU_ROOT)
- goto hide;
- break;
- default:
- break;
- }
-
- visible = menu_is_visible(child);
- if (!menuSkip(child)) {
- if (!child->sym && !child->list && !child->prompt)
- continue;
- if (!item || item->menu != child)
- item = new ConfigItem(parent, last, child, visible);
- else
- item->testUpdateMenu(visible);
-
- if (mode == fullMode || mode == menuMode || type != P_MENU)
- updateMenuList(item, child);
- else
- updateMenuList(item, 0);
- last = item;
- continue;
- }
- hide:
- if (item && item->menu == child) {
- last = parent->firstChild();
- if (last == item)
- last = 0;
- else while (last->nextSibling() != item)
- last = last->nextSibling();
- delete item;
- }
- }
-}
-
-void ConfigList::keyPressEvent(QKeyEvent* ev)
-{
- Q3ListViewItem* i = currentItem();
- ConfigItem* item;
- struct menu *menu;
- enum prop_type type;
-
- if (ev->key() == Qt::Key_Escape && mode != fullMode && mode != listMode) {
- emit parentSelected();
- ev->accept();
- return;
- }
-
- if (!i) {
- Parent::keyPressEvent(ev);
- return;
- }
- item = (ConfigItem*)i;
-
- switch (ev->key()) {
- case Qt::Key_Return:
- case Qt::Key_Enter:
- if (item->goParent) {
- emit parentSelected();
- break;
- }
- menu = item->menu;
- if (!menu)
- break;
- type = menu->prompt ? menu->prompt->type : P_UNKNOWN;
- if (type == P_MENU && rootEntry != menu &&
- mode != fullMode && mode != menuMode) {
- emit menuSelected(menu);
- break;
- }
- case Qt::Key_Space:
- changeValue(item);
- break;
- case Qt::Key_N:
- setValue(item, no);
- break;
- case Qt::Key_M:
- setValue(item, mod);
- break;
- case Qt::Key_Y:
- setValue(item, yes);
- break;
- default:
- Parent::keyPressEvent(ev);
- return;
- }
- ev->accept();
-}
-
-void ConfigList::contentsMousePressEvent(QMouseEvent* e)
-{
- //QPoint p(contentsToViewport(e->pos()));
- //printf("contentsMousePressEvent: %d,%d\n", p.x(), p.y());
- Parent::contentsMousePressEvent(e);
-}
-
-void ConfigList::contentsMouseReleaseEvent(QMouseEvent* e)
-{
- QPoint p(contentsToViewport(e->pos()));
- ConfigItem* item = (ConfigItem*)itemAt(p);
- struct menu *menu;
- enum prop_type ptype;
- const QPixmap* pm;
- int idx, x;
-
- if (!item)
- goto skip;
-
- menu = item->menu;
- x = header()->offset() + p.x();
- idx = colRevMap[header()->sectionAt(x)];
- switch (idx) {
- case promptColIdx:
- pm = item->pixmap(promptColIdx);
- if (pm) {
- int off = header()->sectionPos(0) + itemMargin() +
- treeStepSize() * (item->depth() + (rootIsDecorated() ? 1 : 0));
- if (x >= off && x < off + pm->width()) {
- if (item->goParent) {
- emit parentSelected();
- break;
- } else if (!menu)
- break;
- ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
- if (ptype == P_MENU && rootEntry != menu &&
- mode != fullMode && mode != menuMode)
- emit menuSelected(menu);
- else
- changeValue(item);
- }
- }
- break;
- case noColIdx:
- setValue(item, no);
- break;
- case modColIdx:
- setValue(item, mod);
- break;
- case yesColIdx:
- setValue(item, yes);
- break;
- case dataColIdx:
- changeValue(item);
- break;
- }
-
-skip:
- //printf("contentsMouseReleaseEvent: %d,%d\n", p.x(), p.y());
- Parent::contentsMouseReleaseEvent(e);
-}
-
-void ConfigList::contentsMouseMoveEvent(QMouseEvent* e)
-{
- //QPoint p(contentsToViewport(e->pos()));
- //printf("contentsMouseMoveEvent: %d,%d\n", p.x(), p.y());
- Parent::contentsMouseMoveEvent(e);
-}
-
-void ConfigList::contentsMouseDoubleClickEvent(QMouseEvent* e)
-{
- QPoint p(contentsToViewport(e->pos()));
- ConfigItem* item = (ConfigItem*)itemAt(p);
- struct menu *menu;
- enum prop_type ptype;
-
- if (!item)
- goto skip;
- if (item->goParent) {
- emit parentSelected();
- goto skip;
- }
- menu = item->menu;
- if (!menu)
- goto skip;
- ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
- if (ptype == P_MENU && (mode == singleMode || mode == symbolMode))
- emit menuSelected(menu);
- else if (menu->sym)
- changeValue(item);
-
-skip:
- //printf("contentsMouseDoubleClickEvent: %d,%d\n", p.x(), p.y());
- Parent::contentsMouseDoubleClickEvent(e);
-}
-
-void ConfigList::focusInEvent(QFocusEvent *e)
-{
- struct menu *menu = NULL;
-
- Parent::focusInEvent(e);
-
- ConfigItem* item = (ConfigItem *)currentItem();
- if (item) {
- setSelected(item, TRUE);
- menu = item->menu;
- }
- emit gotFocus(menu);
-}
-
-void ConfigList::contextMenuEvent(QContextMenuEvent *e)
-{
- if (e->y() <= header()->geometry().bottom()) {
- if (!headerPopup) {
- Q3Action *action;
-
- headerPopup = new Q3PopupMenu(this);
- action = new Q3Action(NULL, _("Show Name"), 0, this);
- action->setToggleAction(TRUE);
- connect(action, SIGNAL(toggled(bool)),
- parent(), SLOT(setShowName(bool)));
- connect(parent(), SIGNAL(showNameChanged(bool)),
- action, SLOT(setOn(bool)));
- action->setOn(showName);
- action->addTo(headerPopup);
- action = new Q3Action(NULL, _("Show Range"), 0, this);
- action->setToggleAction(TRUE);
- connect(action, SIGNAL(toggled(bool)),
- parent(), SLOT(setShowRange(bool)));
- connect(parent(), SIGNAL(showRangeChanged(bool)),
- action, SLOT(setOn(bool)));
- action->setOn(showRange);
- action->addTo(headerPopup);
- action = new Q3Action(NULL, _("Show Data"), 0, this);
- action->setToggleAction(TRUE);
- connect(action, SIGNAL(toggled(bool)),
- parent(), SLOT(setShowData(bool)));
- connect(parent(), SIGNAL(showDataChanged(bool)),
- action, SLOT(setOn(bool)));
- action->setOn(showData);
- action->addTo(headerPopup);
- }
- headerPopup->exec(e->globalPos());
- e->accept();
- } else
- e->ignore();
-}
-
-ConfigView*ConfigView::viewList;
-QAction *ConfigView::showNormalAction;
-QAction *ConfigView::showAllAction;
-QAction *ConfigView::showPromptAction;
-
-ConfigView::ConfigView(QWidget* parent, const char *name)
- : Parent(parent, name)
-{
- list = new ConfigList(this, name);
- lineEdit = new ConfigLineEdit(this);
- lineEdit->hide();
-
- this->nextView = viewList;
- viewList = this;
-}
-
-ConfigView::~ConfigView(void)
-{
- ConfigView** vp;
-
- for (vp = &viewList; *vp; vp = &(*vp)->nextView) {
- if (*vp == this) {
- *vp = nextView;
- break;
- }
- }
-}
-
-void ConfigView::setOptionMode(QAction *act)
-{
- if (act == showNormalAction)
- list->optMode = normalOpt;
- else if (act == showAllAction)
- list->optMode = allOpt;
- else
- list->optMode = promptOpt;
-
- list->updateListAll();
-}
-
-void ConfigView::setShowName(bool b)
-{
- if (list->showName != b) {
- list->showName = b;
- list->reinit();
- emit showNameChanged(b);
- }
-}
-
-void ConfigView::setShowRange(bool b)
-{
- if (list->showRange != b) {
- list->showRange = b;
- list->reinit();
- emit showRangeChanged(b);
- }
-}
-
-void ConfigView::setShowData(bool b)
-{
- if (list->showData != b) {
- list->showData = b;
- list->reinit();
- emit showDataChanged(b);
- }
-}
-
-void ConfigList::setAllOpen(bool open)
-{
- Q3ListViewItemIterator it(this);
-
- for (; it.current(); it++)
- it.current()->setOpen(open);
-}
-
-void ConfigView::updateList(ConfigItem* item)
-{
- ConfigView* v;
-
- for (v = viewList; v; v = v->nextView)
- v->list->updateList(item);
-}
-
-void ConfigView::updateListAll(void)
-{
- ConfigView* v;
-
- for (v = viewList; v; v = v->nextView)
- v->list->updateListAll();
-}
-
-ConfigInfoView::ConfigInfoView(QWidget* parent, const char *name)
- : Parent(parent, name), sym(0), _menu(0)
-{
- if (name) {
- configSettings->beginGroup(name);
- _showDebug = configSettings->readBoolEntry("/showDebug", false);
- configSettings->endGroup();
- connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings()));
- }
-}
-
-void ConfigInfoView::saveSettings(void)
-{
- if (name()) {
- configSettings->beginGroup(name());
- configSettings->writeEntry("/showDebug", showDebug());
- configSettings->endGroup();
- }
-}
-
-void ConfigInfoView::setShowDebug(bool b)
-{
- if (_showDebug != b) {
- _showDebug = b;
- if (_menu)
- menuInfo();
- else if (sym)
- symbolInfo();
- emit showDebugChanged(b);
- }
-}
-
-void ConfigInfoView::setInfo(struct menu *m)
-{
- if (_menu == m)
- return;
- _menu = m;
- sym = NULL;
- if (!_menu)
- clear();
- else
- menuInfo();
-}
-
-void ConfigInfoView::symbolInfo(void)
-{
- QString str;
-
- str += "<big>Symbol: <b>";
- str += print_filter(sym->name);
- str += "</b></big><br><br>value: ";
- str += print_filter(sym_get_string_value(sym));
- str += "<br>visibility: ";
- str += sym->visible == yes ? "y" : sym->visible == mod ? "m" : "n";
- str += "<br>";
- str += debug_info(sym);
-
- setText(str);
-}
-
-void ConfigInfoView::menuInfo(void)
-{
- struct symbol* sym;
- QString head, debug, help;
-
- sym = _menu->sym;
- if (sym) {
- if (_menu->prompt) {
- head += "<big><b>";
- head += print_filter(_(_menu->prompt->text));
- head += "</b></big>";
- if (sym->name) {
- head += " (";
- if (showDebug())
- head += QString().sprintf("<a href=\"s%p\">", sym);
- head += print_filter(sym->name);
- if (showDebug())
- head += "</a>";
- head += ")";
- }
- } else if (sym->name) {
- head += "<big><b>";
- if (showDebug())
- head += QString().sprintf("<a href=\"s%p\">", sym);
- head += print_filter(sym->name);
- if (showDebug())
- head += "</a>";
- head += "</b></big>";
- }
- head += "<br><br>";
-
- if (showDebug())
- debug = debug_info(sym);
-
- struct gstr help_gstr = str_new();
- menu_get_ext_help(_menu, &help_gstr);
- help = print_filter(str_get(&help_gstr));
- str_free(&help_gstr);
- } else if (_menu->prompt) {
- head += "<big><b>";
- head += print_filter(_(_menu->prompt->text));
- head += "</b></big><br><br>";
- if (showDebug()) {
- if (_menu->prompt->visible.expr) {
- debug += " dep: ";
- expr_print(_menu->prompt->visible.expr, expr_print_help, &debug, E_NONE);
- debug += "<br><br>";
- }
- }
- }
- if (showDebug())
- debug += QString().sprintf("defined at %s:%d<br><br>", _menu->file->name, _menu->lineno);
-
- setText(head + debug + help);
-}
-
-QString ConfigInfoView::debug_info(struct symbol *sym)
-{
- QString debug;
-
- debug += "type: ";
- debug += print_filter(sym_type_name(sym->type));
- if (sym_is_choice(sym))
- debug += " (choice)";
- debug += "<br>";
- if (sym->rev_dep.expr) {
- debug += "reverse dep: ";
- expr_print(sym->rev_dep.expr, expr_print_help, &debug, E_NONE);
- debug += "<br>";
- }
- for (struct property *prop = sym->prop; prop; prop = prop->next) {
- switch (prop->type) {
- case P_PROMPT:
- case P_MENU:
- debug += QString().sprintf("prompt: <a href=\"m%p\">", prop->menu);
- debug += print_filter(_(prop->text));
- debug += "</a><br>";
- break;
- case P_DEFAULT:
- case P_SELECT:
- case P_RANGE:
- case P_ENV:
- debug += prop_get_type_name(prop->type);
- debug += ": ";
- expr_print(prop->expr, expr_print_help, &debug, E_NONE);
- debug += "<br>";
- break;
- case P_CHOICE:
- if (sym_is_choice(sym)) {
- debug += "choice: ";
- expr_print(prop->expr, expr_print_help, &debug, E_NONE);
- debug += "<br>";
- }
- break;
- default:
- debug += "unknown property: ";
- debug += prop_get_type_name(prop->type);
- debug += "<br>";
- }
- if (prop->visible.expr) {
- debug += " dep: ";
- expr_print(prop->visible.expr, expr_print_help, &debug, E_NONE);
- debug += "<br>";
- }
- }
- debug += "<br>";
-
- return debug;
-}
-
-QString ConfigInfoView::print_filter(const QString &str)
-{
- QRegExp re("[<>&\"\\n]");
- QString res = str;
- for (int i = 0; (i = res.find(re, i)) >= 0;) {
- switch (res[i].latin1()) {
- case '<':
- res.replace(i, 1, "<");
- i += 4;
- break;
- case '>':
- res.replace(i, 1, ">");
- i += 4;
- break;
- case '&':
- res.replace(i, 1, "&");
- i += 5;
- break;
- case '"':
- res.replace(i, 1, """);
- i += 6;
- break;
- case '\n':
- res.replace(i, 1, "<br>");
- i += 4;
- break;
- }
- }
- return res;
-}
-
-void ConfigInfoView::expr_print_help(void *data, struct symbol *sym, const char *str)
-{
- QString* text = reinterpret_cast<QString*>(data);
- QString str2 = print_filter(str);
-
- if (sym && sym->name && !(sym->flags & SYMBOL_CONST)) {
- *text += QString().sprintf("<a href=\"s%p\">", sym);
- *text += str2;
- *text += "</a>";
- } else
- *text += str2;
-}
-
-Q3PopupMenu* ConfigInfoView::createPopupMenu(const QPoint& pos)
-{
- Q3PopupMenu* popup = Parent::createPopupMenu(pos);
- Q3Action* action = new Q3Action(NULL, _("Show Debug Info"), 0, popup);
- action->setToggleAction(TRUE);
- connect(action, SIGNAL(toggled(bool)), SLOT(setShowDebug(bool)));
- connect(this, SIGNAL(showDebugChanged(bool)), action, SLOT(setOn(bool)));
- action->setOn(showDebug());
- popup->insertSeparator();
- action->addTo(popup);
- return popup;
-}
-
-void ConfigInfoView::contentsContextMenuEvent(QContextMenuEvent *e)
-{
- Parent::contentsContextMenuEvent(e);
-}
-
-ConfigSearchWindow::ConfigSearchWindow(ConfigMainWindow* parent, const char *name)
- : Parent(parent, name), result(NULL)
-{
- setCaption("Search Config");
-
- QVBoxLayout* layout1 = new QVBoxLayout(this, 11, 6);
- QHBoxLayout* layout2 = new QHBoxLayout(0, 0, 6);
- layout2->addWidget(new QLabel(_("Find:"), this));
- editField = new QLineEdit(this);
- connect(editField, SIGNAL(returnPressed()), SLOT(search()));
- layout2->addWidget(editField);
- searchButton = new QPushButton(_("Search"), this);
- searchButton->setAutoDefault(FALSE);
- connect(searchButton, SIGNAL(clicked()), SLOT(search()));
- layout2->addWidget(searchButton);
- layout1->addLayout(layout2);
-
- split = new QSplitter(this);
- split->setOrientation(Qt::Vertical);
- list = new ConfigView(split, name);
- list->list->mode = listMode;
- info = new ConfigInfoView(split, name);
- connect(list->list, SIGNAL(menuChanged(struct menu *)),
- info, SLOT(setInfo(struct menu *)));
- connect(list->list, SIGNAL(menuChanged(struct menu *)),
- parent, SLOT(setMenuLink(struct menu *)));
-
- layout1->addWidget(split);
-
- if (name) {
- int x, y, width, height;
- bool ok;
-
- configSettings->beginGroup(name);
- width = configSettings->readNumEntry("/window width", parent->width() / 2);
- height = configSettings->readNumEntry("/window height", parent->height() / 2);
- resize(width, height);
- x = configSettings->readNumEntry("/window x", 0, &ok);
- if (ok)
- y = configSettings->readNumEntry("/window y", 0, &ok);
- if (ok)
- move(x, y);
- Q3ValueList<int> sizes = configSettings->readSizes("/split", &ok);
- if (ok)
- split->setSizes(sizes);
- configSettings->endGroup();
- connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings()));
- }
-}
-
-void ConfigSearchWindow::saveSettings(void)
-{
- if (name()) {
- configSettings->beginGroup(name());
- configSettings->writeEntry("/window x", pos().x());
- configSettings->writeEntry("/window y", pos().y());
- configSettings->writeEntry("/window width", size().width());
- configSettings->writeEntry("/window height", size().height());
- configSettings->writeSizes("/split", split->sizes());
- configSettings->endGroup();
- }
-}
-
-void ConfigSearchWindow::search(void)
-{
- struct symbol **p;
- struct property *prop;
- ConfigItem *lastItem = NULL;
-
- free(result);
- list->list->clear();
- info->clear();
-
- result = sym_re_search(editField->text().latin1());
- if (!result)
- return;
- for (p = result; *p; p++) {
- for_all_prompts((*p), prop)
- lastItem = new ConfigItem(list->list, lastItem, prop->menu,
- menu_is_visible(prop->menu));
- }
-}
-
-/*
- * Construct the complete config widget
- */
-ConfigMainWindow::ConfigMainWindow(void)
- : searchWindow(0)
-{
- QMenuBar* menu;
- bool ok;
- int x, y, width, height;
- char title[256];
-
- QDesktopWidget *d = configApp->desktop();
- snprintf(title, sizeof(title), "%s%s",
- rootmenu.prompt->text,
-#if QT_VERSION < 0x040000
- " (Qt3)"
-#else
- ""
-#endif
- );
- setCaption(title);
-
- width = configSettings->readNumEntry("/window width", d->width() - 64);
- height = configSettings->readNumEntry("/window height", d->height() - 64);
- resize(width, height);
- x = configSettings->readNumEntry("/window x", 0, &ok);
- if (ok)
- y = configSettings->readNumEntry("/window y", 0, &ok);
- if (ok)
- move(x, y);
-
- split1 = new QSplitter(this);
- split1->setOrientation(Qt::Horizontal);
- setCentralWidget(split1);
-
- menuView = new ConfigView(split1, "menu");
- menuList = menuView->list;
-
- split2 = new QSplitter(split1);
- split2->setOrientation(Qt::Vertical);
-
- // create config tree
- configView = new ConfigView(split2, "config");
- configList = configView->list;
-
- helpText = new ConfigInfoView(split2, "help");
- helpText->setTextFormat(Qt::RichText);
-
- setTabOrder(configList, helpText);
- configList->setFocus();
-
- menu = menuBar();
- toolBar = new Q3ToolBar("Tools", this);
-
- backAction = new Q3Action("Back", QPixmap(xpm_back), _("Back"), 0, this);
- connect(backAction, SIGNAL(activated()), SLOT(goBack()));
- backAction->setEnabled(FALSE);
- Q3Action *quitAction = new Q3Action("Quit", _("&Quit"), Qt::CTRL + Qt::Key_Q, this);
- connect(quitAction, SIGNAL(activated()), SLOT(close()));
- Q3Action *loadAction = new Q3Action("Load", QPixmap(xpm_load), _("&Load"), Qt::CTRL + Qt::Key_L, this);
- connect(loadAction, SIGNAL(activated()), SLOT(loadConfig()));
- saveAction = new Q3Action("Save", QPixmap(xpm_save), _("&Save"), Qt::CTRL + Qt::Key_S, this);
- connect(saveAction, SIGNAL(activated()), SLOT(saveConfig()));
- conf_set_changed_callback(conf_changed);
- // Set saveAction's initial state
- conf_changed();
- Q3Action *saveAsAction = new Q3Action("Save As...", _("Save &As..."), 0, this);
- connect(saveAsAction, SIGNAL(activated()), SLOT(saveConfigAs()));
- Q3Action *searchAction = new Q3Action("Find", _("&Find"), Qt::CTRL + Qt::Key_F, this);
- connect(searchAction, SIGNAL(activated()), SLOT(searchConfig()));
- Q3Action *singleViewAction = new Q3Action("Single View", QPixmap(xpm_single_view), _("Single View"), 0, this);
- connect(singleViewAction, SIGNAL(activated()), SLOT(showSingleView()));
- Q3Action *splitViewAction = new Q3Action("Split View", QPixmap(xpm_split_view), _("Split View"), 0, this);
- connect(splitViewAction, SIGNAL(activated()), SLOT(showSplitView()));
- Q3Action *fullViewAction = new Q3Action("Full View", QPixmap(xpm_tree_view), _("Full View"), 0, this);
- connect(fullViewAction, SIGNAL(activated()), SLOT(showFullView()));
-
- Q3Action *showNameAction = new Q3Action(NULL, _("Show Name"), 0, this);
- showNameAction->setToggleAction(TRUE);
- connect(showNameAction, SIGNAL(toggled(bool)), configView, SLOT(setShowName(bool)));
- connect(configView, SIGNAL(showNameChanged(bool)), showNameAction, SLOT(setOn(bool)));
- showNameAction->setOn(configView->showName());
- Q3Action *showRangeAction = new Q3Action(NULL, _("Show Range"), 0, this);
- showRangeAction->setToggleAction(TRUE);
- connect(showRangeAction, SIGNAL(toggled(bool)), configView, SLOT(setShowRange(bool)));
- connect(configView, SIGNAL(showRangeChanged(bool)), showRangeAction, SLOT(setOn(bool)));
- showRangeAction->setOn(configList->showRange);
- Q3Action *showDataAction = new Q3Action(NULL, _("Show Data"), 0, this);
- showDataAction->setToggleAction(TRUE);
- connect(showDataAction, SIGNAL(toggled(bool)), configView, SLOT(setShowData(bool)));
- connect(configView, SIGNAL(showDataChanged(bool)), showDataAction, SLOT(setOn(bool)));
- showDataAction->setOn(configList->showData);
-
- QActionGroup *optGroup = new QActionGroup(this);
- optGroup->setExclusive(TRUE);
- connect(optGroup, SIGNAL(selected(QAction *)), configView,
- SLOT(setOptionMode(QAction *)));
- connect(optGroup, SIGNAL(selected(QAction *)), menuView,
- SLOT(setOptionMode(QAction *)));
-
-#if QT_VERSION >= 0x040000
- configView->showNormalAction = new QAction(_("Show Normal Options"), optGroup);
- configView->showAllAction = new QAction(_("Show All Options"), optGroup);
- configView->showPromptAction = new QAction(_("Show Prompt Options"), optGroup);
-#else
- configView->showNormalAction = new QAction(_("Show Normal Options"), 0, optGroup);
- configView->showAllAction = new QAction(_("Show All Options"), 0, optGroup);
- configView->showPromptAction = new QAction(_("Show Prompt Options"), 0, optGroup);
-#endif
- configView->showNormalAction->setToggleAction(TRUE);
- configView->showNormalAction->setOn(configList->optMode == normalOpt);
- configView->showAllAction->setToggleAction(TRUE);
- configView->showAllAction->setOn(configList->optMode == allOpt);
- configView->showPromptAction->setToggleAction(TRUE);
- configView->showPromptAction->setOn(configList->optMode == promptOpt);
-
- Q3Action *showDebugAction = new Q3Action(NULL, _("Show Debug Info"), 0, this);
- showDebugAction->setToggleAction(TRUE);
- connect(showDebugAction, SIGNAL(toggled(bool)), helpText, SLOT(setShowDebug(bool)));
- connect(helpText, SIGNAL(showDebugChanged(bool)), showDebugAction, SLOT(setOn(bool)));
- showDebugAction->setOn(helpText->showDebug());
-
- Q3Action *showIntroAction = new Q3Action(NULL, _("Introduction"), 0, this);
- connect(showIntroAction, SIGNAL(activated()), SLOT(showIntro()));
- Q3Action *showAboutAction = new Q3Action(NULL, _("About"), 0, this);
- connect(showAboutAction, SIGNAL(activated()), SLOT(showAbout()));
-
- // init tool bar
- backAction->addTo(toolBar);
- toolBar->addSeparator();
- loadAction->addTo(toolBar);
- saveAction->addTo(toolBar);
- toolBar->addSeparator();
- singleViewAction->addTo(toolBar);
- splitViewAction->addTo(toolBar);
- fullViewAction->addTo(toolBar);
-
- // create config menu
- Q3PopupMenu* config = new Q3PopupMenu(this);
- menu->insertItem(_("&File"), config);
- loadAction->addTo(config);
- saveAction->addTo(config);
- saveAsAction->addTo(config);
- config->insertSeparator();
- quitAction->addTo(config);
-
- // create edit menu
- Q3PopupMenu* editMenu = new Q3PopupMenu(this);
- menu->insertItem(_("&Edit"), editMenu);
- searchAction->addTo(editMenu);
-
- // create options menu
- Q3PopupMenu* optionMenu = new Q3PopupMenu(this);
- menu->insertItem(_("&Option"), optionMenu);
- showNameAction->addTo(optionMenu);
- showRangeAction->addTo(optionMenu);
- showDataAction->addTo(optionMenu);
- optionMenu->insertSeparator();
- optGroup->addTo(optionMenu);
- optionMenu->insertSeparator();
-
- // create help menu
- Q3PopupMenu* helpMenu = new Q3PopupMenu(this);
- menu->insertSeparator();
- menu->insertItem(_("&Help"), helpMenu);
- showIntroAction->addTo(helpMenu);
- showAboutAction->addTo(helpMenu);
-
- connect(configList, SIGNAL(menuChanged(struct menu *)),
- helpText, SLOT(setInfo(struct menu *)));
- connect(configList, SIGNAL(menuSelected(struct menu *)),
- SLOT(changeMenu(struct menu *)));
- connect(configList, SIGNAL(parentSelected()),
- SLOT(goBack()));
- connect(menuList, SIGNAL(menuChanged(struct menu *)),
- helpText, SLOT(setInfo(struct menu *)));
- connect(menuList, SIGNAL(menuSelected(struct menu *)),
- SLOT(changeMenu(struct menu *)));
-
- connect(configList, SIGNAL(gotFocus(struct menu *)),
- helpText, SLOT(setInfo(struct menu *)));
- connect(menuList, SIGNAL(gotFocus(struct menu *)),
- helpText, SLOT(setInfo(struct menu *)));
- connect(menuList, SIGNAL(gotFocus(struct menu *)),
- SLOT(listFocusChanged(void)));
- connect(helpText, SIGNAL(menuSelected(struct menu *)),
- SLOT(setMenuLink(struct menu *)));
-
- QString listMode = configSettings->readEntry("/listMode", "symbol");
- if (listMode == "single")
- showSingleView();
- else if (listMode == "full")
- showFullView();
- else /*if (listMode == "split")*/
- showSplitView();
-
- // UI setup done, restore splitter positions
- Q3ValueList<int> sizes = configSettings->readSizes("/split1", &ok);
- if (ok)
- split1->setSizes(sizes);
-
- sizes = configSettings->readSizes("/split2", &ok);
- if (ok)
- split2->setSizes(sizes);
-}
-
-void ConfigMainWindow::loadConfig(void)
-{
- QString s = Q3FileDialog::getOpenFileName(conf_get_configname(), NULL, this);
- if (s.isNull())
- return;
- if (conf_read(QFile::encodeName(s)))
- QMessageBox::information(this, "qconf", _("Unable to load configuration!"));
- ConfigView::updateListAll();
-}
-
-bool ConfigMainWindow::saveConfig(void)
-{
- if (conf_write(NULL)) {
- QMessageBox::information(this, "qconf", _("Unable to save configuration!"));
- return false;
- }
- return true;
-}
-
-void ConfigMainWindow::saveConfigAs(void)
-{
- QString s = Q3FileDialog::getSaveFileName(conf_get_configname(), NULL, this);
- if (s.isNull())
- return;
- saveConfig();
-}
-
-void ConfigMainWindow::searchConfig(void)
-{
- if (!searchWindow)
- searchWindow = new ConfigSearchWindow(this, "search");
- searchWindow->show();
-}
-
-void ConfigMainWindow::changeMenu(struct menu *menu)
-{
- configList->setRootMenu(menu);
- if (configList->rootEntry->parent == &rootmenu)
- backAction->setEnabled(FALSE);
- else
- backAction->setEnabled(TRUE);
-}
-
-void ConfigMainWindow::setMenuLink(struct menu *menu)
-{
- struct menu *parent;
- ConfigList* list = NULL;
- ConfigItem* item;
-
- if (configList->menuSkip(menu))
- return;
-
- switch (configList->mode) {
- case singleMode:
- list = configList;
- parent = menu_get_parent_menu(menu);
- if (!parent)
- return;
- list->setRootMenu(parent);
- break;
- case symbolMode:
- if (menu->flags & MENU_ROOT) {
- configList->setRootMenu(menu);
- configList->clearSelection();
- list = menuList;
- } else {
- list = configList;
- parent = menu_get_parent_menu(menu->parent);
- if (!parent)
- return;
- item = menuList->findConfigItem(parent);
- if (item) {
- menuList->setSelected(item, TRUE);
- menuList->ensureItemVisible(item);
- }
- list->setRootMenu(parent);
- }
- break;
- case fullMode:
- list = configList;
- break;
- default:
- break;
- }
-
- if (list) {
- item = list->findConfigItem(menu);
- if (item) {
- list->setSelected(item, TRUE);
- list->ensureItemVisible(item);
- list->setFocus();
- }
- }
-}
-
-void ConfigMainWindow::listFocusChanged(void)
-{
- if (menuList->mode == menuMode)
- configList->clearSelection();
-}
-
-void ConfigMainWindow::goBack(void)
-{
- ConfigItem* item;
-
- configList->setParentMenu();
- if (configList->rootEntry == &rootmenu)
- backAction->setEnabled(FALSE);
- item = (ConfigItem*)menuList->selectedItem();
- while (item) {
- if (item->menu == configList->rootEntry) {
- menuList->setSelected(item, TRUE);
- break;
- }
- item = (ConfigItem*)item->parent();
- }
-}
-
-void ConfigMainWindow::showSingleView(void)
-{
- menuView->hide();
- menuList->setRootMenu(0);
- configList->mode = singleMode;
- if (configList->rootEntry == &rootmenu)
- configList->updateListAll();
- else
- configList->setRootMenu(&rootmenu);
- configList->setAllOpen(TRUE);
- configList->setFocus();
-}
-
-void ConfigMainWindow::showSplitView(void)
-{
- configList->mode = symbolMode;
- if (configList->rootEntry == &rootmenu)
- configList->updateListAll();
- else
- configList->setRootMenu(&rootmenu);
- configList->setAllOpen(TRUE);
- configApp->processEvents();
- menuList->mode = menuMode;
- menuList->setRootMenu(&rootmenu);
- menuList->setAllOpen(TRUE);
- menuView->show();
- menuList->setFocus();
-}
-
-void ConfigMainWindow::showFullView(void)
-{
- menuView->hide();
- menuList->setRootMenu(0);
- configList->mode = fullMode;
- if (configList->rootEntry == &rootmenu)
- configList->updateListAll();
- else
- configList->setRootMenu(&rootmenu);
- configList->setAllOpen(FALSE);
- configList->setFocus();
-}
-
-/*
- * ask for saving configuration before quitting
- * TODO ask only when something changed
- */
-void ConfigMainWindow::closeEvent(QCloseEvent* e)
-{
- if (!conf_get_changed()) {
- e->accept();
- return;
- }
- QMessageBox mb("qconf", _("Save configuration?"), QMessageBox::Warning,
- QMessageBox::Yes | QMessageBox::Default, QMessageBox::No, QMessageBox::Cancel | QMessageBox::Escape);
- mb.setButtonText(QMessageBox::Yes, _("&Save Changes"));
- mb.setButtonText(QMessageBox::No, _("&Discard Changes"));
- mb.setButtonText(QMessageBox::Cancel, _("Cancel Exit"));
- switch (mb.exec()) {
- case QMessageBox::Yes:
- if (saveConfig())
- e->accept();
- else
- e->ignore();
- break;
- case QMessageBox::No:
- e->accept();
- break;
- case QMessageBox::Cancel:
- e->ignore();
- break;
- }
-}
-
-void ConfigMainWindow::showIntro(void)
-{
- static const QString str = _("Welcome to the qconf graphical configuration tool.\n\n"
- "For each option, a blank box indicates the feature is disabled, a check\n"
- "indicates it is enabled, and a dot indicates that it is to be compiled\n"
- "as a module. Clicking on the box will cycle through the three states.\n\n"
- "If you do not see an option (e.g., a device driver) that you believe\n"
- "should be present, try turning on Show All Options under the Options menu.\n"
- "Although there is no cross reference yet to help you figure out what other\n"
- "options must be enabled to support the option you are interested in, you can\n"
- "still view the help of a grayed-out option.\n\n"
- "Toggling Show Debug Info under the Options menu will show the dependencies,\n"
- "which you can then match by examining other options.\n\n");
-
- QMessageBox::information(this, "qconf", str);
-}
-
-void ConfigMainWindow::showAbout(void)
-{
- static const QString str = _("qconf is Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>.\n\n"
- "Bug reports and feature request can also be entered at http://bugzilla.kernel.org/\n");
-
- QMessageBox::information(this, "qconf", str);
-}
-
-void ConfigMainWindow::saveSettings(void)
-{
- configSettings->writeEntry("/window x", pos().x());
- configSettings->writeEntry("/window y", pos().y());
- configSettings->writeEntry("/window width", size().width());
- configSettings->writeEntry("/window height", size().height());
-
- QString entry;
- switch(configList->mode) {
- case singleMode :
- entry = "single";
- break;
-
- case symbolMode :
- entry = "split";
- break;
-
- case fullMode :
- entry = "full";
- break;
-
- default:
- break;
- }
- configSettings->writeEntry("/listMode", entry);
-
- configSettings->writeSizes("/split1", split1->sizes());
- configSettings->writeSizes("/split2", split2->sizes());
-}
-
-void ConfigMainWindow::conf_changed(void)
-{
- if (saveAction)
- saveAction->setEnabled(conf_get_changed());
-}
-
-void fixup_rootmenu(struct menu *menu)
-{
- struct menu *child;
- static int menu_cnt = 0;
-
- menu->flags |= MENU_ROOT;
- for (child = menu->list; child; child = child->next) {
- if (child->prompt && child->prompt->type == P_MENU) {
- menu_cnt++;
- fixup_rootmenu(child);
- menu_cnt--;
- } else if (!menu_cnt)
- fixup_rootmenu(child);
- }
-}
-
-static const char *progname;
-
-static void usage(void)
-{
- printf(_("%s <config>\n"), progname);
- exit(0);
-}
-
-int main(int ac, char** av)
-{
- ConfigMainWindow* v;
- const char *name;
-
- bindtextdomain(PACKAGE, LOCALEDIR);
- textdomain(PACKAGE);
-
- progname = av[0];
- configApp = new QApplication(ac, av);
- if (ac > 1 && av[1][0] == '-') {
- switch (av[1][1]) {
- case 'h':
- case '?':
- usage();
- }
- name = av[2];
- } else
- name = av[1];
- if (!name)
- usage();
-
- conf_parse(name);
- fixup_rootmenu(&rootmenu);
- conf_read(NULL);
- //zconfdump(stdout);
-
- configSettings = new ConfigSettings();
- configSettings->beginGroup("/kconfig/qconf");
- v = new ConfigMainWindow();
-
- //zconfdump(stdout);
- configApp->setMainWidget(v);
- configApp->connect(configApp, SIGNAL(lastWindowClosed()), SLOT(quit()));
- configApp->connect(configApp, SIGNAL(aboutToQuit()), v, SLOT(saveSettings()));
- v->show();
- configApp->exec();
-
- configSettings->endGroup();
- delete configSettings;
-
- return 0;
-}
+++ /dev/null
-/*
- * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
- * Released under the terms of the GNU GPL v2.0.
- */
-
-#if QT_VERSION < 0x040000
-#include <qlistview.h>
-#else
-#include <q3listview.h>
-#endif
-#include <qsettings.h>
-
-#if QT_VERSION < 0x040000
-#define Q3ValueList QValueList
-#define Q3PopupMenu QPopupMenu
-#define Q3ListView QListView
-#define Q3ListViewItem QListViewItem
-#define Q3VBox QVBox
-#define Q3TextBrowser QTextBrowser
-#define Q3MainWindow QMainWindow
-#define Q3Action QAction
-#define Q3ToolBar QToolBar
-#define Q3ListViewItemIterator QListViewItemIterator
-#define Q3FileDialog QFileDialog
-#endif
-
-class ConfigView;
-class ConfigList;
-class ConfigItem;
-class ConfigLineEdit;
-class ConfigMainWindow;
-
-class ConfigSettings : public QSettings {
-public:
- Q3ValueList<int> readSizes(const QString& key, bool *ok);
- bool writeSizes(const QString& key, const Q3ValueList<int>& value);
-};
-
-enum colIdx {
- promptColIdx, nameColIdx, noColIdx, modColIdx, yesColIdx, dataColIdx, colNr
-};
-enum listMode {
- singleMode, menuMode, symbolMode, fullMode, listMode
-};
-enum optionMode {
- normalOpt = 0, allOpt, promptOpt
-};
-
-class ConfigList : public Q3ListView {
- Q_OBJECT
- typedef class Q3ListView Parent;
-public:
- ConfigList(ConfigView* p, const char *name = 0);
- void reinit(void);
- ConfigView* parent(void) const
- {
- return (ConfigView*)Parent::parent();
- }
- ConfigItem* findConfigItem(struct menu *);
-
-protected:
- void keyPressEvent(QKeyEvent *e);
- void contentsMousePressEvent(QMouseEvent *e);
- void contentsMouseReleaseEvent(QMouseEvent *e);
- void contentsMouseMoveEvent(QMouseEvent *e);
- void contentsMouseDoubleClickEvent(QMouseEvent *e);
- void focusInEvent(QFocusEvent *e);
- void contextMenuEvent(QContextMenuEvent *e);
-
-public slots:
- void setRootMenu(struct menu *menu);
-
- void updateList(ConfigItem *item);
- void setValue(ConfigItem* item, tristate val);
- void changeValue(ConfigItem* item);
- void updateSelection(void);
- void saveSettings(void);
-signals:
- void menuChanged(struct menu *menu);
- void menuSelected(struct menu *menu);
- void parentSelected(void);
- void gotFocus(struct menu *);
-
-public:
- void updateListAll(void)
- {
- updateAll = true;
- updateList(NULL);
- updateAll = false;
- }
- ConfigList* listView()
- {
- return this;
- }
- ConfigItem* firstChild() const
- {
- return (ConfigItem *)Parent::firstChild();
- }
- int mapIdx(colIdx idx)
- {
- return colMap[idx];
- }
- void addColumn(colIdx idx, const QString& label)
- {
- colMap[idx] = Parent::addColumn(label);
- colRevMap[colMap[idx]] = idx;
- }
- void removeColumn(colIdx idx)
- {
- int col = colMap[idx];
- if (col >= 0) {
- Parent::removeColumn(col);
- colRevMap[col] = colMap[idx] = -1;
- }
- }
- void setAllOpen(bool open);
- void setParentMenu(void);
-
- bool menuSkip(struct menu *);
-
- template <class P>
- void updateMenuList(P*, struct menu*);
-
- bool updateAll;
-
- QPixmap symbolYesPix, symbolModPix, symbolNoPix;
- QPixmap choiceYesPix, choiceNoPix;
- QPixmap menuPix, menuInvPix, menuBackPix, voidPix;
-
- bool showName, showRange, showData;
- enum listMode mode;
- enum optionMode optMode;
- struct menu *rootEntry;
- QColorGroup disabledColorGroup;
- QColorGroup inactivedColorGroup;
- Q3PopupMenu* headerPopup;
-
-private:
- int colMap[colNr];
- int colRevMap[colNr];
-};
-
-class ConfigItem : public Q3ListViewItem {
- typedef class Q3ListViewItem Parent;
-public:
- ConfigItem(Q3ListView *parent, ConfigItem *after, struct menu *m, bool v)
- : Parent(parent, after), menu(m), visible(v), goParent(false)
- {
- init();
- }
- ConfigItem(ConfigItem *parent, ConfigItem *after, struct menu *m, bool v)
- : Parent(parent, after), menu(m), visible(v), goParent(false)
- {
- init();
- }
- ConfigItem(Q3ListView *parent, ConfigItem *after, bool v)
- : Parent(parent, after), menu(0), visible(v), goParent(true)
- {
- init();
- }
- ~ConfigItem(void);
- void init(void);
- void okRename(int col);
- void updateMenu(void);
- void testUpdateMenu(bool v);
- ConfigList* listView() const
- {
- return (ConfigList*)Parent::listView();
- }
- ConfigItem* firstChild() const
- {
- return (ConfigItem *)Parent::firstChild();
- }
- ConfigItem* nextSibling() const
- {
- return (ConfigItem *)Parent::nextSibling();
- }
- void setText(colIdx idx, const QString& text)
- {
- Parent::setText(listView()->mapIdx(idx), text);
- }
- QString text(colIdx idx) const
- {
- return Parent::text(listView()->mapIdx(idx));
- }
- void setPixmap(colIdx idx, const QPixmap& pm)
- {
- Parent::setPixmap(listView()->mapIdx(idx), pm);
- }
- const QPixmap* pixmap(colIdx idx) const
- {
- return Parent::pixmap(listView()->mapIdx(idx));
- }
- void paintCell(QPainter* p, const QColorGroup& cg, int column, int width, int align);
-
- ConfigItem* nextItem;
- struct menu *menu;
- bool visible;
- bool goParent;
-};
-
-class ConfigLineEdit : public QLineEdit {
- Q_OBJECT
- typedef class QLineEdit Parent;
-public:
- ConfigLineEdit(ConfigView* parent);
- ConfigView* parent(void) const
- {
- return (ConfigView*)Parent::parent();
- }
- void show(ConfigItem *i);
- void keyPressEvent(QKeyEvent *e);
-
-public:
- ConfigItem *item;
-};
-
-class ConfigView : public Q3VBox {
- Q_OBJECT
- typedef class Q3VBox Parent;
-public:
- ConfigView(QWidget* parent, const char *name = 0);
- ~ConfigView(void);
- static void updateList(ConfigItem* item);
- static void updateListAll(void);
-
- bool showName(void) const { return list->showName; }
- bool showRange(void) const { return list->showRange; }
- bool showData(void) const { return list->showData; }
-public slots:
- void setShowName(bool);
- void setShowRange(bool);
- void setShowData(bool);
- void setOptionMode(QAction *);
-signals:
- void showNameChanged(bool);
- void showRangeChanged(bool);
- void showDataChanged(bool);
-public:
- ConfigList* list;
- ConfigLineEdit* lineEdit;
-
- static ConfigView* viewList;
- ConfigView* nextView;
-
- static QAction *showNormalAction;
- static QAction *showAllAction;
- static QAction *showPromptAction;
-};
-
-class ConfigInfoView : public Q3TextBrowser {
- Q_OBJECT
- typedef class Q3TextBrowser Parent;
-public:
- ConfigInfoView(QWidget* parent, const char *name = 0);
- bool showDebug(void) const { return _showDebug; }
-
-public slots:
- void setInfo(struct menu *menu);
- void saveSettings(void);
- void setShowDebug(bool);
-
-signals:
- void showDebugChanged(bool);
- void menuSelected(struct menu *);
-
-protected:
- void symbolInfo(void);
- void menuInfo(void);
- QString debug_info(struct symbol *sym);
- static QString print_filter(const QString &str);
- static void expr_print_help(void *data, struct symbol *sym, const char *str);
- Q3PopupMenu* createPopupMenu(const QPoint& pos);
- void contentsContextMenuEvent(QContextMenuEvent *e);
-
- struct symbol *sym;
- struct menu *_menu;
- bool _showDebug;
-};
-
-class ConfigSearchWindow : public QDialog {
- Q_OBJECT
- typedef class QDialog Parent;
-public:
- ConfigSearchWindow(ConfigMainWindow* parent, const char *name = 0);
-
-public slots:
- void saveSettings(void);
- void search(void);
-
-protected:
- QLineEdit* editField;
- QPushButton* searchButton;
- QSplitter* split;
- ConfigView* list;
- ConfigInfoView* info;
-
- struct symbol **result;
-};
-
-class ConfigMainWindow : public Q3MainWindow {
- Q_OBJECT
-
- static Q3Action *saveAction;
- static void conf_changed(void);
-public:
- ConfigMainWindow(void);
-public slots:
- void changeMenu(struct menu *);
- void setMenuLink(struct menu *);
- void listFocusChanged(void);
- void goBack(void);
- void loadConfig(void);
- bool saveConfig(void);
- void saveConfigAs(void);
- void searchConfig(void);
- void showSingleView(void);
- void showSplitView(void);
- void showFullView(void);
- void showIntro(void);
- void showAbout(void);
- void saveSettings(void);
-
-protected:
- void closeEvent(QCloseEvent *e);
-
- ConfigSearchWindow *searchWindow;
- ConfigView *menuView;
- ConfigList *menuList;
- ConfigView *configView;
- ConfigList *configList;
- ConfigInfoView *helpText;
- Q3ToolBar *toolBar;
- Q3Action *backAction;
- QSplitter* split1;
- QSplitter* split2;
-};
+++ /dev/null
-#!/usr/bin/perl -w
-#
-# Copyright 2005-2009 - Steven Rostedt
-# Licensed under the terms of the GNU GPL License version 2
-#
-# It's simple enough to figure out how this works.
-# If not, then you can ask me at stripconfig@goodmis.org
-#
-# What it does?
-#
-# If you have installed a Linux kernel from a distribution
-# that turns on way too many modules than you need, and
-# you only want the modules you use, then this program
-# is perfect for you.
-#
-# It gives you the ability to turn off all the modules that are
-# not loaded on your system.
-#
-# Howto:
-#
-# 1. Boot up the kernel that you want to stream line the config on.
-# 2. Change directory to the directory holding the source of the
-# kernel that you just booted.
-# 3. Copy the configuraton file to this directory as .config
-# 4. Have all your devices that you need modules for connected and
-# operational (make sure that their corresponding modules are loaded)
-# 5. Run this script redirecting the output to some other file
-# like config_strip.
-# 6. Back up your old config (if you want too).
-# 7. copy the config_strip file to .config
-# 8. Run "make oldconfig"
-#
-# Now your kernel is ready to be built with only the modules that
-# are loaded.
-#
-# Here's what I did with my Debian distribution.
-#
-# cd /usr/src/linux-2.6.10
-# cp /boot/config-2.6.10-1-686-smp .config
-# ~/bin/streamline_config > config_strip
-# mv .config config_sav
-# mv config_strip .config
-# make oldconfig
-#
-use strict;
-use Getopt::Long;
-
-my $config = ".config";
-
-my $uname = `uname -r`;
-chomp $uname;
-
-my @searchconfigs = (
- {
- "file" => ".config",
- "exec" => "cat",
- },
- {
- "file" => "/proc/config.gz",
- "exec" => "zcat",
- },
- {
- "file" => "/boot/config-$uname",
- "exec" => "cat",
- },
- {
- "file" => "/boot/vmlinuz-$uname",
- "exec" => "scripts/extract-ikconfig",
- "test" => "scripts/extract-ikconfig",
- },
- {
- "file" => "vmlinux",
- "exec" => "scripts/extract-ikconfig",
- "test" => "scripts/extract-ikconfig",
- },
- {
- "file" => "/lib/modules/$uname/kernel/kernel/configs.ko",
- "exec" => "scripts/extract-ikconfig",
- "test" => "scripts/extract-ikconfig",
- },
- {
- "file" => "kernel/configs.ko",
- "exec" => "scripts/extract-ikconfig",
- "test" => "scripts/extract-ikconfig",
- },
- {
- "file" => "kernel/configs.o",
- "exec" => "scripts/extract-ikconfig",
- "test" => "scripts/extract-ikconfig",
- },
-);
-
-sub find_config {
- foreach my $conf (@searchconfigs) {
- my $file = $conf->{"file"};
-
- next if ( ! -f "$file");
-
- if (defined($conf->{"test"})) {
- `$conf->{"test"} $conf->{"file"} 2>/dev/null`;
- next if ($?);
- }
-
- my $exec = $conf->{"exec"};
-
- print STDERR "using config: '$file'\n";
-
- open(CIN, "$exec $file |") || die "Failed to run $exec $file";
- return;
- }
- die "No config file found";
-}
-
-find_config;
-
-# Parse options
-my $localmodconfig = 0;
-my $localyesconfig = 0;
-
-GetOptions("localmodconfig" => \$localmodconfig,
- "localyesconfig" => \$localyesconfig);
-
-# Get the build source and top level Kconfig file (passed in)
-my $ksource = $ARGV[0];
-my $kconfig = $ARGV[1];
-my $lsmod_file = $ENV{'LSMOD'};
-
-my @makefiles = `find $ksource -name Makefile 2>/dev/null`;
-chomp @makefiles;
-
-my %depends;
-my %selects;
-my %prompts;
-my %objects;
-my $var;
-my $iflevel = 0;
-my @ifdeps;
-
-# prevent recursion
-my %read_kconfigs;
-
-sub read_kconfig {
- my ($kconfig) = @_;
-
- my $state = "NONE";
- my $config;
- my @kconfigs;
-
- my $cont = 0;
- my $line;
-
- my $source = "$ksource/$kconfig";
- my $last_source = "";
-
- # Check for any environment variables used
- while ($source =~ /\$(\w+)/ && $last_source ne $source) {
- my $env = $1;
- $last_source = $source;
- $source =~ s/\$$env/$ENV{$env}/;
- }
-
- open(KIN, "$source") || die "Can't open $kconfig";
- while (<KIN>) {
- chomp;
-
- # Make sure that lines ending with \ continue
- if ($cont) {
- $_ = $line . " " . $_;
- }
-
- if (s/\\$//) {
- $cont = 1;
- $line = $_;
- next;
- }
-
- $cont = 0;
-
- # collect any Kconfig sources
- if (/^source\s*"(.*)"/) {
- $kconfigs[$#kconfigs+1] = $1;
- }
-
- # configs found
- if (/^\s*(menu)?config\s+(\S+)\s*$/) {
- $state = "NEW";
- $config = $2;
-
- for (my $i = 0; $i < $iflevel; $i++) {
- if ($i) {
- $depends{$config} .= " " . $ifdeps[$i];
- } else {
- $depends{$config} = $ifdeps[$i];
- }
- $state = "DEP";
- }
-
- # collect the depends for the config
- } elsif ($state eq "NEW" && /^\s*depends\s+on\s+(.*)$/) {
- $state = "DEP";
- $depends{$config} = $1;
- } elsif ($state eq "DEP" && /^\s*depends\s+on\s+(.*)$/) {
- $depends{$config} .= " " . $1;
-
- # Get the configs that select this config
- } elsif ($state ne "NONE" && /^\s*select\s+(\S+)/) {
- if (defined($selects{$1})) {
- $selects{$1} .= " " . $config;
- } else {
- $selects{$1} = $config;
- }
-
- # configs without prompts must be selected
- } elsif ($state ne "NONE" && /^\s*tristate\s\S/) {
- # note if the config has a prompt
- $prompts{$config} = 1;
-
- # Check for if statements
- } elsif (/^if\s+(.*\S)\s*$/) {
- my $deps = $1;
- # remove beginning and ending non text
- $deps =~ s/^[^a-zA-Z0-9_]*//;
- $deps =~ s/[^a-zA-Z0-9_]*$//;
-
- my @deps = split /[^a-zA-Z0-9_]+/, $deps;
-
- $ifdeps[$iflevel++] = join ':', @deps;
-
- } elsif (/^endif/) {
-
- $iflevel-- if ($iflevel);
-
- # stop on "help"
- } elsif (/^\s*help\s*$/) {
- $state = "NONE";
- }
- }
- close(KIN);
-
- # read in any configs that were found.
- foreach $kconfig (@kconfigs) {
- if (!defined($read_kconfigs{$kconfig})) {
- $read_kconfigs{$kconfig} = 1;
- read_kconfig($kconfig);
- }
- }
-}
-
-if ($kconfig) {
- read_kconfig($kconfig);
-}
-
-sub convert_vars {
- my ($line, %vars) = @_;
-
- my $process = "";
-
- while ($line =~ s/^(.*?)(\$\((.*?)\))//) {
- my $start = $1;
- my $variable = $2;
- my $var = $3;
-
- if (defined($vars{$var})) {
- $process .= $start . $vars{$var};
- } else {
- $process .= $start . $variable;
- }
- }
-
- $process .= $line;
-
- return $process;
-}
-
-# Read all Makefiles to map the configs to the objects
-foreach my $makefile (@makefiles) {
-
- my $line = "";
- my %make_vars;
-
- open(MIN,$makefile) || die "Can't open $makefile";
- while (<MIN>) {
- # if this line ends with a backslash, continue
- chomp;
- if (/^(.*)\\$/) {
- $line .= $1;
- next;
- }
-
- $line .= $_;
- $_ = $line;
- $line = "";
-
- my $objs;
-
- $_ = convert_vars($_, %make_vars);
-
- # collect objects after obj-$(CONFIG_FOO_BAR)
- if (/obj-\$\((CONFIG_[^\)]*)\)\s*[+:]?=\s*(.*)/) {
- $var = $1;
- $objs = $2;
-
- # check if variables are set
- } elsif (/^\s*(\S+)\s*[:]?=\s*(.*\S)/) {
- $make_vars{$1} = $2;
- }
- if (defined($objs)) {
- foreach my $obj (split /\s+/,$objs) {
- $obj =~ s/-/_/g;
- if ($obj =~ /(.*)\.o$/) {
- # Objects may be enabled by more than one config.
- # Store configs in an array.
- my @arr;
-
- if (defined($objects{$1})) {
- @arr = @{$objects{$1}};
- }
-
- $arr[$#arr+1] = $var;
-
- # The objects have a hash mapping to a reference
- # of an array of configs.
- $objects{$1} = \@arr;
- }
- }
- }
- }
- close(MIN);
-}
-
-my %modules;
-
-if (defined($lsmod_file)) {
- if ( ! -f $lsmod_file) {
- if ( -f $ENV{'objtree'}."/".$lsmod_file) {
- $lsmod_file = $ENV{'objtree'}."/".$lsmod_file;
- } else {
- die "$lsmod_file not found";
- }
- }
- if ( -x $lsmod_file) {
- # the file is executable, run it
- open(LIN, "$lsmod_file|");
- } else {
- # Just read the contents
- open(LIN, "$lsmod_file");
- }
-} else {
-
- # see what modules are loaded on this system
- my $lsmod;
-
- foreach my $dir ( ("/sbin", "/bin", "/usr/sbin", "/usr/bin") ) {
- if ( -x "$dir/lsmod" ) {
- $lsmod = "$dir/lsmod";
- last;
- }
-}
- if (!defined($lsmod)) {
- # try just the path
- $lsmod = "lsmod";
- }
-
- open(LIN,"$lsmod|") || die "Can not call lsmod with $lsmod";
-}
-
-while (<LIN>) {
- next if (/^Module/); # Skip the first line.
- if (/^(\S+)/) {
- $modules{$1} = 1;
- }
-}
-close (LIN);
-
-# add to the configs hash all configs that are needed to enable
-# a loaded module.
-my %configs;
-foreach my $module (keys(%modules)) {
- if (defined($objects{$module})) {
- my @arr = @{$objects{$module}};
- foreach my $conf (@arr) {
- $configs{$conf} = $module;
- }
- } else {
- # Most likely, someone has a custom (binary?) module loaded.
- print STDERR "$module config not found!!\n";
- }
-}
-
-my $valid = "A-Za-z_0-9";
-my $repeat = 1;
-
-#
-# Note, we do not care about operands (like: &&, ||, !) we want to add any
-# config that is in the depend list of another config. This script does
-# not enable configs that are not already enabled. If we come across a
-# config A that depends on !B, we can still add B to the list of depends
-# to keep on. If A was on in the original config, B would not have been
-# and B would not be turned on by this script.
-#
-sub parse_config_dep_select
-{
- my ($p) = @_;
-
- while ($p =~ /[$valid]/) {
-
- if ($p =~ /^[^$valid]*([$valid]+)/) {
- my $conf = "CONFIG_" . $1;
-
- $p =~ s/^[^$valid]*[$valid]+//;
-
- if (!defined($configs{$conf})) {
- # We must make sure that this config has its
- # dependencies met.
- $repeat = 1; # do again
- $configs{$conf} = 1;
- }
- } else {
- die "this should never happen";
- }
- }
-}
-
-while ($repeat) {
- $repeat = 0;
-
- foreach my $config (keys %configs) {
- $config =~ s/^CONFIG_//;
-
- if (defined($depends{$config})) {
- # This config has dependencies. Make sure they are also included
- parse_config_dep_select $depends{$config};
- }
-
- if (defined($prompts{$config}) || !defined($selects{$config})) {
- next;
- }
-
- # config has no prompt and must be selected.
- parse_config_dep_select $selects{$config};
- }
-}
-
-my %setconfigs;
-
-# Finally, read the .config file and turn off any module enabled that
-# we could not find a reason to keep enabled.
-while(<CIN>) {
-
- if (/CONFIG_IKCONFIG/) {
- if (/# CONFIG_IKCONFIG is not set/) {
- # enable IKCONFIG at least as a module
- print "CONFIG_IKCONFIG=m\n";
- # don't ask about PROC
- print "# CONFIG_IKCONFIG_PROC is not set\n";
- } else {
- print;
- }
- next;
- }
-
- if (/^(CONFIG.*)=(m|y)/) {
- if (defined($configs{$1})) {
- if ($localyesconfig) {
- $setconfigs{$1} = 'y';
- } else {
- $setconfigs{$1} = $2;
- }
- } elsif ($2 eq "m") {
- print "# $1 is not set\n";
- next;
- }
- }
- print;
-}
-close(CIN);
-
-# Integrity check, make sure all modules that we want enabled do
-# indeed have their configs set.
-loop:
-foreach my $module (keys(%modules)) {
- if (defined($objects{$module})) {
- my @arr = @{$objects{$module}};
- foreach my $conf (@arr) {
- if (defined($setconfigs{$conf})) {
- next loop;
- }
- }
- print STDERR "module $module did not have configs";
- foreach my $conf (@arr) {
- print STDERR " " , $conf;
- }
- print STDERR "\n";
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
- * Released under the terms of the GNU GPL v2.0.
- */
-
-#include <ctype.h>
-#include <stdlib.h>
-#include <string.h>
-#include <regex.h>
-#include <sys/utsname.h>
-
-#include "lkc.h"
-
-struct symbol symbol_yes = {
- .name = "y",
- .curr = { "y", yes },
- .flags = SYMBOL_CONST|SYMBOL_VALID,
-}, symbol_mod = {
- .name = "m",
- .curr = { "m", mod },
- .flags = SYMBOL_CONST|SYMBOL_VALID,
-}, symbol_no = {
- .name = "n",
- .curr = { "n", no },
- .flags = SYMBOL_CONST|SYMBOL_VALID,
-}, symbol_empty = {
- .name = "",
- .curr = { "", no },
- .flags = SYMBOL_VALID,
-};
-
-struct symbol *sym_defconfig_list;
-struct symbol *modules_sym;
-tristate modules_val;
-
-struct expr *sym_env_list;
-
-static void sym_add_default(struct symbol *sym, const char *def)
-{
- struct property *prop = prop_alloc(P_DEFAULT, sym);
-
- prop->expr = expr_alloc_symbol(sym_lookup(def, SYMBOL_CONST));
-}
-
-void sym_init(void)
-{
- struct symbol *sym;
- struct utsname uts;
- static bool inited = false;
-
- if (inited)
- return;
- inited = true;
-
- uname(&uts);
-
- sym = sym_lookup("UNAME_RELEASE", 0);
- sym->type = S_STRING;
- sym->flags |= SYMBOL_AUTO;
- sym_add_default(sym, uts.release);
-}
-
-enum symbol_type sym_get_type(struct symbol *sym)
-{
- enum symbol_type type = sym->type;
-
- if (type == S_TRISTATE) {
- if (sym_is_choice_value(sym) && sym->visible == yes)
- type = S_BOOLEAN;
- else if (modules_val == no)
- type = S_BOOLEAN;
- }
- return type;
-}
-
-const char *sym_type_name(enum symbol_type type)
-{
- switch (type) {
- case S_BOOLEAN:
- return "boolean";
- case S_TRISTATE:
- return "tristate";
- case S_INT:
- return "integer";
- case S_HEX:
- return "hex";
- case S_STRING:
- return "string";
- case S_UNKNOWN:
- return "unknown";
- case S_OTHER:
- break;
- }
- return "???";
-}
-
-struct property *sym_get_choice_prop(struct symbol *sym)
-{
- struct property *prop;
-
- for_all_choices(sym, prop)
- return prop;
- return NULL;
-}
-
-struct property *sym_get_env_prop(struct symbol *sym)
-{
- struct property *prop;
-
- for_all_properties(sym, prop, P_ENV)
- return prop;
- return NULL;
-}
-
-struct property *sym_get_default_prop(struct symbol *sym)
-{
- struct property *prop;
-
- for_all_defaults(sym, prop) {
- prop->visible.tri = expr_calc_value(prop->visible.expr);
- if (prop->visible.tri != no)
- return prop;
- }
- return NULL;
-}
-
-static struct property *sym_get_range_prop(struct symbol *sym)
-{
- struct property *prop;
-
- for_all_properties(sym, prop, P_RANGE) {
- prop->visible.tri = expr_calc_value(prop->visible.expr);
- if (prop->visible.tri != no)
- return prop;
- }
- return NULL;
-}
-
-static int sym_get_range_val(struct symbol *sym, int base)
-{
- sym_calc_value(sym);
- switch (sym->type) {
- case S_INT:
- base = 10;
- break;
- case S_HEX:
- base = 16;
- break;
- default:
- break;
- }
- return strtol(sym->curr.val, NULL, base);
-}
-
-static void sym_validate_range(struct symbol *sym)
-{
- struct property *prop;
- int base, val, val2;
- char str[64];
-
- switch (sym->type) {
- case S_INT:
- base = 10;
- break;
- case S_HEX:
- base = 16;
- break;
- default:
- return;
- }
- prop = sym_get_range_prop(sym);
- if (!prop)
- return;
- val = strtol(sym->curr.val, NULL, base);
- val2 = sym_get_range_val(prop->expr->left.sym, base);
- if (val >= val2) {
- val2 = sym_get_range_val(prop->expr->right.sym, base);
- if (val <= val2)
- return;
- }
- if (sym->type == S_INT)
- sprintf(str, "%d", val2);
- else
- sprintf(str, "0x%x", val2);
- sym->curr.val = strdup(str);
-}
-
-static void sym_calc_visibility(struct symbol *sym)
-{
- struct property *prop;
- tristate tri;
-
- /* any prompt visible? */
- tri = no;
- for_all_prompts(sym, prop) {
- prop->visible.tri = expr_calc_value(prop->visible.expr);
- tri = EXPR_OR(tri, prop->visible.tri);
- }
- if (tri == mod && (sym->type != S_TRISTATE || modules_val == no))
- tri = yes;
- if (sym->visible != tri) {
- sym->visible = tri;
- sym_set_changed(sym);
- }
- if (sym_is_choice_value(sym))
- return;
- /* defaulting to "yes" if no explicit "depends on" are given */
- tri = yes;
- if (sym->dir_dep.expr)
- tri = expr_calc_value(sym->dir_dep.expr);
- if (tri == mod)
- tri = yes;
- if (sym->dir_dep.tri != tri) {
- sym->dir_dep.tri = tri;
- sym_set_changed(sym);
- }
- tri = no;
- if (sym->rev_dep.expr)
- tri = expr_calc_value(sym->rev_dep.expr);
- if (tri == mod && sym_get_type(sym) == S_BOOLEAN)
- tri = yes;
- if (sym->rev_dep.tri != tri) {
- sym->rev_dep.tri = tri;
- sym_set_changed(sym);
- }
-}
-
-/*
- * Find the default symbol for a choice.
- * First try the default values for the choice symbol
- * Next locate the first visible choice value
- * Return NULL if none was found
- */
-struct symbol *sym_choice_default(struct symbol *sym)
-{
- struct symbol *def_sym;
- struct property *prop;
- struct expr *e;
-
- /* any of the defaults visible? */
- for_all_defaults(sym, prop) {
- prop->visible.tri = expr_calc_value(prop->visible.expr);
- if (prop->visible.tri == no)
- continue;
- def_sym = prop_get_symbol(prop);
- if (def_sym->visible != no)
- return def_sym;
- }
-
- /* just get the first visible value */
- prop = sym_get_choice_prop(sym);
- expr_list_for_each_sym(prop->expr, e, def_sym)
- if (def_sym->visible != no)
- return def_sym;
-
- /* failed to locate any defaults */
- return NULL;
-}
-
-static struct symbol *sym_calc_choice(struct symbol *sym)
-{
- struct symbol *def_sym;
- struct property *prop;
- struct expr *e;
-
- /* first calculate all choice values' visibilities */
- prop = sym_get_choice_prop(sym);
- expr_list_for_each_sym(prop->expr, e, def_sym)
- sym_calc_visibility(def_sym);
-
- /* is the user choice visible? */
- def_sym = sym->def[S_DEF_USER].val;
- if (def_sym && def_sym->visible != no)
- return def_sym;
-
- def_sym = sym_choice_default(sym);
-
- if (def_sym == NULL)
- /* no choice? reset tristate value */
- sym->curr.tri = no;
-
- return def_sym;
-}
-
-void sym_calc_value(struct symbol *sym)
-{
- struct symbol_value newval, oldval;
- struct property *prop;
- struct expr *e;
-
- if (!sym)
- return;
-
- if (sym->flags & SYMBOL_VALID)
- return;
- sym->flags |= SYMBOL_VALID;
-
- oldval = sym->curr;
-
- switch (sym->type) {
- case S_INT:
- case S_HEX:
- case S_STRING:
- newval = symbol_empty.curr;
- break;
- case S_BOOLEAN:
- case S_TRISTATE:
- newval = symbol_no.curr;
- break;
- default:
- sym->curr.val = sym->name;
- sym->curr.tri = no;
- return;
- }
- if (!sym_is_choice_value(sym))
- sym->flags &= ~SYMBOL_WRITE;
-
- sym_calc_visibility(sym);
-
- /* set default if recursively called */
- sym->curr = newval;
-
- switch (sym_get_type(sym)) {
- case S_BOOLEAN:
- case S_TRISTATE:
- if (sym_is_choice_value(sym) && sym->visible == yes) {
- prop = sym_get_choice_prop(sym);
- newval.tri = (prop_get_symbol(prop)->curr.val == sym) ? yes : no;
- } else {
- if (sym->visible != no) {
- /* if the symbol is visible use the user value
- * if available, otherwise try the default value
- */
- sym->flags |= SYMBOL_WRITE;
- if (sym_has_value(sym)) {
- newval.tri = EXPR_AND(sym->def[S_DEF_USER].tri,
- sym->visible);
- goto calc_newval;
- }
- }
- if (sym->rev_dep.tri != no)
- sym->flags |= SYMBOL_WRITE;
- if (!sym_is_choice(sym)) {
- prop = sym_get_default_prop(sym);
- if (prop) {
- sym->flags |= SYMBOL_WRITE;
- newval.tri = EXPR_AND(expr_calc_value(prop->expr),
- prop->visible.tri);
- }
- }
- calc_newval:
- if (sym->dir_dep.tri == no && sym->rev_dep.tri != no) {
- struct expr *e;
- e = expr_simplify_unmet_dep(sym->rev_dep.expr,
- sym->dir_dep.expr);
- fprintf(stderr, "warning: (");
- expr_fprint(e, stderr);
- fprintf(stderr, ") selects %s which has unmet direct dependencies (",
- sym->name);
- expr_fprint(sym->dir_dep.expr, stderr);
- fprintf(stderr, ")\n");
- expr_free(e);
- }
- newval.tri = EXPR_OR(newval.tri, sym->rev_dep.tri);
- }
- if (newval.tri == mod && sym_get_type(sym) == S_BOOLEAN)
- newval.tri = yes;
- break;
- case S_STRING:
- case S_HEX:
- case S_INT:
- if (sym->visible != no) {
- sym->flags |= SYMBOL_WRITE;
- if (sym_has_value(sym)) {
- newval.val = sym->def[S_DEF_USER].val;
- break;
- }
- }
- prop = sym_get_default_prop(sym);
- if (prop) {
- struct symbol *ds = prop_get_symbol(prop);
- if (ds) {
- sym->flags |= SYMBOL_WRITE;
- sym_calc_value(ds);
- newval.val = ds->curr.val;
- }
- }
- break;
- default:
- ;
- }
-
- sym->curr = newval;
- if (sym_is_choice(sym) && newval.tri == yes)
- sym->curr.val = sym_calc_choice(sym);
- sym_validate_range(sym);
-
- if (memcmp(&oldval, &sym->curr, sizeof(oldval))) {
- sym_set_changed(sym);
- if (modules_sym == sym) {
- sym_set_all_changed();
- modules_val = modules_sym->curr.tri;
- }
- }
-
- if (sym_is_choice(sym)) {
- struct symbol *choice_sym;
-
- prop = sym_get_choice_prop(sym);
- expr_list_for_each_sym(prop->expr, e, choice_sym) {
- if ((sym->flags & SYMBOL_WRITE) &&
- choice_sym->visible != no)
- choice_sym->flags |= SYMBOL_WRITE;
- if (sym->flags & SYMBOL_CHANGED)
- sym_set_changed(choice_sym);
- }
- }
-
- if (sym->flags & SYMBOL_AUTO)
- sym->flags &= ~SYMBOL_WRITE;
-}
-
-void sym_clear_all_valid(void)
-{
- struct symbol *sym;
- int i;
-
- for_all_symbols(i, sym)
- sym->flags &= ~SYMBOL_VALID;
- sym_add_change_count(1);
- if (modules_sym)
- sym_calc_value(modules_sym);
-}
-
-void sym_set_changed(struct symbol *sym)
-{
- struct property *prop;
-
- sym->flags |= SYMBOL_CHANGED;
- for (prop = sym->prop; prop; prop = prop->next) {
- if (prop->menu)
- prop->menu->flags |= MENU_CHANGED;
- }
-}
-
-void sym_set_all_changed(void)
-{
- struct symbol *sym;
- int i;
-
- for_all_symbols(i, sym)
- sym_set_changed(sym);
-}
-
-bool sym_tristate_within_range(struct symbol *sym, tristate val)
-{
- int type = sym_get_type(sym);
-
- if (sym->visible == no)
- return false;
-
- if (type != S_BOOLEAN && type != S_TRISTATE)
- return false;
-
- if (type == S_BOOLEAN && val == mod)
- return false;
- if (sym->visible <= sym->rev_dep.tri)
- return false;
- if (sym_is_choice_value(sym) && sym->visible == yes)
- return val == yes;
- return val >= sym->rev_dep.tri && val <= sym->visible;
-}
-
-bool sym_set_tristate_value(struct symbol *sym, tristate val)
-{
- tristate oldval = sym_get_tristate_value(sym);
-
- if (oldval != val && !sym_tristate_within_range(sym, val))
- return false;
-
- if (!(sym->flags & SYMBOL_DEF_USER)) {
- sym->flags |= SYMBOL_DEF_USER;
- sym_set_changed(sym);
- }
- /*
- * setting a choice value also resets the new flag of the choice
- * symbol and all other choice values.
- */
- if (sym_is_choice_value(sym) && val == yes) {
- struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
- struct property *prop;
- struct expr *e;
-
- cs->def[S_DEF_USER].val = sym;
- cs->flags |= SYMBOL_DEF_USER;
- prop = sym_get_choice_prop(cs);
- for (e = prop->expr; e; e = e->left.expr) {
- if (e->right.sym->visible != no)
- e->right.sym->flags |= SYMBOL_DEF_USER;
- }
- }
-
- sym->def[S_DEF_USER].tri = val;
- if (oldval != val)
- sym_clear_all_valid();
-
- return true;
-}
-
-tristate sym_toggle_tristate_value(struct symbol *sym)
-{
- tristate oldval, newval;
-
- oldval = newval = sym_get_tristate_value(sym);
- do {
- switch (newval) {
- case no:
- newval = mod;
- break;
- case mod:
- newval = yes;
- break;
- case yes:
- newval = no;
- break;
- }
- if (sym_set_tristate_value(sym, newval))
- break;
- } while (oldval != newval);
- return newval;
-}
-
-bool sym_string_valid(struct symbol *sym, const char *str)
-{
- signed char ch;
-
- switch (sym->type) {
- case S_STRING:
- return true;
- case S_INT:
- ch = *str++;
- if (ch == '-')
- ch = *str++;
- if (!isdigit(ch))
- return false;
- if (ch == '0' && *str != 0)
- return false;
- while ((ch = *str++)) {
- if (!isdigit(ch))
- return false;
- }
- return true;
- case S_HEX:
- if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
- str += 2;
- ch = *str++;
- do {
- if (!isxdigit(ch))
- return false;
- } while ((ch = *str++));
- return true;
- case S_BOOLEAN:
- case S_TRISTATE:
- switch (str[0]) {
- case 'y': case 'Y':
- case 'm': case 'M':
- case 'n': case 'N':
- return true;
- }
- return false;
- default:
- return false;
- }
-}
-
-bool sym_string_within_range(struct symbol *sym, const char *str)
-{
- struct property *prop;
- int val;
-
- switch (sym->type) {
- case S_STRING:
- return sym_string_valid(sym, str);
- case S_INT:
- if (!sym_string_valid(sym, str))
- return false;
- prop = sym_get_range_prop(sym);
- if (!prop)
- return true;
- val = strtol(str, NULL, 10);
- return val >= sym_get_range_val(prop->expr->left.sym, 10) &&
- val <= sym_get_range_val(prop->expr->right.sym, 10);
- case S_HEX:
- if (!sym_string_valid(sym, str))
- return false;
- prop = sym_get_range_prop(sym);
- if (!prop)
- return true;
- val = strtol(str, NULL, 16);
- return val >= sym_get_range_val(prop->expr->left.sym, 16) &&
- val <= sym_get_range_val(prop->expr->right.sym, 16);
- case S_BOOLEAN:
- case S_TRISTATE:
- switch (str[0]) {
- case 'y': case 'Y':
- return sym_tristate_within_range(sym, yes);
- case 'm': case 'M':
- return sym_tristate_within_range(sym, mod);
- case 'n': case 'N':
- return sym_tristate_within_range(sym, no);
- }
- return false;
- default:
- return false;
- }
-}
-
-bool sym_set_string_value(struct symbol *sym, const char *newval)
-{
- const char *oldval;
- char *val;
- int size;
-
- switch (sym->type) {
- case S_BOOLEAN:
- case S_TRISTATE:
- switch (newval[0]) {
- case 'y': case 'Y':
- return sym_set_tristate_value(sym, yes);
- case 'm': case 'M':
- return sym_set_tristate_value(sym, mod);
- case 'n': case 'N':
- return sym_set_tristate_value(sym, no);
- }
- return false;
- default:
- ;
- }
-
- if (!sym_string_within_range(sym, newval))
- return false;
-
- if (!(sym->flags & SYMBOL_DEF_USER)) {
- sym->flags |= SYMBOL_DEF_USER;
- sym_set_changed(sym);
- }
-
- oldval = sym->def[S_DEF_USER].val;
- size = strlen(newval) + 1;
- if (sym->type == S_HEX && (newval[0] != '0' || (newval[1] != 'x' && newval[1] != 'X'))) {
- size += 2;
- sym->def[S_DEF_USER].val = val = malloc(size);
- *val++ = '0';
- *val++ = 'x';
- } else if (!oldval || strcmp(oldval, newval))
- sym->def[S_DEF_USER].val = val = malloc(size);
- else
- return true;
-
- strcpy(val, newval);
- free((void *)oldval);
- sym_clear_all_valid();
-
- return true;
-}
-
-/*
- * Find the default value associated to a symbol.
- * For tristate symbol handle the modules=n case
- * in which case "m" becomes "y".
- * If the symbol does not have any default then fallback
- * to the fixed default values.
- */
-const char *sym_get_string_default(struct symbol *sym)
-{
- struct property *prop;
- struct symbol *ds;
- const char *str;
- tristate val;
-
- sym_calc_visibility(sym);
- sym_calc_value(modules_sym);
- val = symbol_no.curr.tri;
- str = symbol_empty.curr.val;
-
- /* If symbol has a default value look it up */
- prop = sym_get_default_prop(sym);
- if (prop != NULL) {
- switch (sym->type) {
- case S_BOOLEAN:
- case S_TRISTATE:
- /* The visibility may limit the value from yes => mod */
- val = EXPR_AND(expr_calc_value(prop->expr), prop->visible.tri);
- break;
- default:
- /*
- * The following fails to handle the situation
- * where a default value is further limited by
- * the valid range.
- */
- ds = prop_get_symbol(prop);
- if (ds != NULL) {
- sym_calc_value(ds);
- str = (const char *)ds->curr.val;
- }
- }
- }
-
- /* Handle select statements */
- val = EXPR_OR(val, sym->rev_dep.tri);
-
- /* transpose mod to yes if modules are not enabled */
- if (val == mod)
- if (!sym_is_choice_value(sym) && modules_sym->curr.tri == no)
- val = yes;
-
- /* transpose mod to yes if type is bool */
- if (sym->type == S_BOOLEAN && val == mod)
- val = yes;
-
- switch (sym->type) {
- case S_BOOLEAN:
- case S_TRISTATE:
- switch (val) {
- case no: return "n";
- case mod: return "m";
- case yes: return "y";
- }
- case S_INT:
- case S_HEX:
- return str;
- case S_STRING:
- return str;
- case S_OTHER:
- case S_UNKNOWN:
- break;
- }
- return "";
-}
-
-const char *sym_get_string_value(struct symbol *sym)
-{
- tristate val;
-
- switch (sym->type) {
- case S_BOOLEAN:
- case S_TRISTATE:
- val = sym_get_tristate_value(sym);
- switch (val) {
- case no:
- return "n";
- case mod:
- sym_calc_value(modules_sym);
- return (modules_sym->curr.tri == no) ? "n" : "m";
- case yes:
- return "y";
- }
- break;
- default:
- ;
- }
- return (const char *)sym->curr.val;
-}
-
-bool sym_is_changable(struct symbol *sym)
-{
- return sym->visible > sym->rev_dep.tri;
-}
-
-static unsigned strhash(const char *s)
-{
- /* fnv32 hash */
- unsigned hash = 2166136261U;
- for (; *s; s++)
- hash = (hash ^ *s) * 0x01000193;
- return hash;
-}
-
-struct symbol *sym_lookup(const char *name, int flags)
-{
- struct symbol *symbol;
- char *new_name;
- int hash;
-
- if (name) {
- if (name[0] && !name[1]) {
- switch (name[0]) {
- case 'y': return &symbol_yes;
- case 'm': return &symbol_mod;
- case 'n': return &symbol_no;
- }
- }
- hash = strhash(name) % SYMBOL_HASHSIZE;
-
- for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
- if (symbol->name &&
- !strcmp(symbol->name, name) &&
- (flags ? symbol->flags & flags
- : !(symbol->flags & (SYMBOL_CONST|SYMBOL_CHOICE))))
- return symbol;
- }
- new_name = strdup(name);
- } else {
- new_name = NULL;
- hash = 0;
- }
-
- symbol = malloc(sizeof(*symbol));
- memset(symbol, 0, sizeof(*symbol));
- symbol->name = new_name;
- symbol->type = S_UNKNOWN;
- symbol->flags |= flags;
-
- symbol->next = symbol_hash[hash];
- symbol_hash[hash] = symbol;
-
- return symbol;
-}
-
-struct symbol *sym_find(const char *name)
-{
- struct symbol *symbol = NULL;
- int hash = 0;
-
- if (!name)
- return NULL;
-
- if (name[0] && !name[1]) {
- switch (name[0]) {
- case 'y': return &symbol_yes;
- case 'm': return &symbol_mod;
- case 'n': return &symbol_no;
- }
- }
- hash = strhash(name) % SYMBOL_HASHSIZE;
-
- for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
- if (symbol->name &&
- !strcmp(symbol->name, name) &&
- !(symbol->flags & SYMBOL_CONST))
- break;
- }
-
- return symbol;
-}
-
-/*
- * Expand symbol's names embedded in the string given in argument. Symbols'
- * name to be expanded shall be prefixed by a '$'. Unknown symbol expands to
- * the empty string.
- */
-const char *sym_expand_string_value(const char *in)
-{
- const char *src;
- char *res;
- size_t reslen;
-
- reslen = strlen(in) + 1;
- res = malloc(reslen);
- res[0] = '\0';
-
- while ((src = strchr(in, '$'))) {
- char *p, name[SYMBOL_MAXLENGTH];
- const char *symval = "";
- struct symbol *sym;
- size_t newlen;
-
- strncat(res, in, src - in);
- src++;
-
- p = name;
- while (isalnum(*src) || *src == '_')
- *p++ = *src++;
- *p = '\0';
-
- sym = sym_find(name);
- if (sym != NULL) {
- sym_calc_value(sym);
- symval = sym_get_string_value(sym);
- }
-
- newlen = strlen(res) + strlen(symval) + strlen(src) + 1;
- if (newlen > reslen) {
- reslen = newlen;
- res = realloc(res, reslen);
- }
-
- strcat(res, symval);
- in = src;
- }
- strcat(res, in);
-
- return res;
-}
-
-const char *sym_escape_string_value(const char *in)
-{
- const char *p;
- size_t reslen;
- char *res;
- size_t l;
-
- reslen = strlen(in) + strlen("\"\"") + 1;
-
- p = in;
- for (;;) {
- l = strcspn(p, "\"\\");
- p += l;
-
- if (p[0] == '\0')
- break;
-
- reslen++;
- p++;
- }
-
- res = malloc(reslen);
- res[0] = '\0';
-
- strcat(res, "\"");
-
- p = in;
- for (;;) {
- l = strcspn(p, "\"\\");
- strncat(res, p, l);
- p += l;
-
- if (p[0] == '\0')
- break;
-
- strcat(res, "\\");
- strncat(res, p++, 1);
- }
-
- strcat(res, "\"");
- return res;
-}
-
-struct symbol **sym_re_search(const char *pattern)
-{
- struct symbol *sym, **sym_arr = NULL;
- int i, cnt, size;
- regex_t re;
-
- cnt = size = 0;
- /* Skip if empty */
- if (strlen(pattern) == 0)
- return NULL;
- if (regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB|REG_ICASE))
- return NULL;
-
- for_all_symbols(i, sym) {
- if (sym->flags & SYMBOL_CONST || !sym->name)
- continue;
- if (regexec(&re, sym->name, 0, NULL, 0))
- continue;
- if (cnt + 1 >= size) {
- void *tmp = sym_arr;
- size += 16;
- sym_arr = realloc(sym_arr, size * sizeof(struct symbol *));
- if (!sym_arr) {
- free(tmp);
- return NULL;
- }
- }
- sym_calc_value(sym);
- sym_arr[cnt++] = sym;
- }
- if (sym_arr)
- sym_arr[cnt] = NULL;
- regfree(&re);
-
- return sym_arr;
-}
-
-/*
- * When we check for recursive dependencies we use a stack to save
- * current state so we can print out relevant info to user.
- * The entries are located on the call stack so no need to free memory.
- * Note inser() remove() must always match to properly clear the stack.
- */
-static struct dep_stack {
- struct dep_stack *prev, *next;
- struct symbol *sym;
- struct property *prop;
- struct expr *expr;
-} *check_top;
-
-static void dep_stack_insert(struct dep_stack *stack, struct symbol *sym)
-{
- memset(stack, 0, sizeof(*stack));
- if (check_top)
- check_top->next = stack;
- stack->prev = check_top;
- stack->sym = sym;
- check_top = stack;
-}
-
-static void dep_stack_remove(void)
-{
- check_top = check_top->prev;
- if (check_top)
- check_top->next = NULL;
-}
-
-/*
- * Called when we have detected a recursive dependency.
- * check_top point to the top of the stact so we use
- * the ->prev pointer to locate the bottom of the stack.
- */
-static void sym_check_print_recursive(struct symbol *last_sym)
-{
- struct dep_stack *stack;
- struct symbol *sym, *next_sym;
- struct menu *menu = NULL;
- struct property *prop;
- struct dep_stack cv_stack;
-
- if (sym_is_choice_value(last_sym)) {
- dep_stack_insert(&cv_stack, last_sym);
- last_sym = prop_get_symbol(sym_get_choice_prop(last_sym));
- }
-
- for (stack = check_top; stack != NULL; stack = stack->prev)
- if (stack->sym == last_sym)
- break;
- if (!stack) {
- fprintf(stderr, "unexpected recursive dependency error\n");
- return;
- }
-
- for (; stack; stack = stack->next) {
- sym = stack->sym;
- next_sym = stack->next ? stack->next->sym : last_sym;
- prop = stack->prop;
- if (prop == NULL)
- prop = stack->sym->prop;
-
- /* for choice values find the menu entry (used below) */
- if (sym_is_choice(sym) || sym_is_choice_value(sym)) {
- for (prop = sym->prop; prop; prop = prop->next) {
- menu = prop->menu;
- if (prop->menu)
- break;
- }
- }
- if (stack->sym == last_sym)
- fprintf(stderr, "%s:%d:error: recursive dependency detected!\n",
- prop->file->name, prop->lineno);
- if (stack->expr) {
- fprintf(stderr, "%s:%d:\tsymbol %s %s value contains %s\n",
- prop->file->name, prop->lineno,
- sym->name ? sym->name : "<choice>",
- prop_get_type_name(prop->type),
- next_sym->name ? next_sym->name : "<choice>");
- } else if (stack->prop) {
- fprintf(stderr, "%s:%d:\tsymbol %s depends on %s\n",
- prop->file->name, prop->lineno,
- sym->name ? sym->name : "<choice>",
- next_sym->name ? next_sym->name : "<choice>");
- } else if (sym_is_choice(sym)) {
- fprintf(stderr, "%s:%d:\tchoice %s contains symbol %s\n",
- menu->file->name, menu->lineno,
- sym->name ? sym->name : "<choice>",
- next_sym->name ? next_sym->name : "<choice>");
- } else if (sym_is_choice_value(sym)) {
- fprintf(stderr, "%s:%d:\tsymbol %s is part of choice %s\n",
- menu->file->name, menu->lineno,
- sym->name ? sym->name : "<choice>",
- next_sym->name ? next_sym->name : "<choice>");
- } else {
- fprintf(stderr, "%s:%d:\tsymbol %s is selected by %s\n",
- prop->file->name, prop->lineno,
- sym->name ? sym->name : "<choice>",
- next_sym->name ? next_sym->name : "<choice>");
- }
- }
-
- if (check_top == &cv_stack)
- dep_stack_remove();
-}
-
-static struct symbol *sym_check_expr_deps(struct expr *e)
-{
- struct symbol *sym;
-
- if (!e)
- return NULL;
- switch (e->type) {
- case E_OR:
- case E_AND:
- sym = sym_check_expr_deps(e->left.expr);
- if (sym)
- return sym;
- return sym_check_expr_deps(e->right.expr);
- case E_NOT:
- return sym_check_expr_deps(e->left.expr);
- case E_EQUAL:
- case E_UNEQUAL:
- sym = sym_check_deps(e->left.sym);
- if (sym)
- return sym;
- return sym_check_deps(e->right.sym);
- case E_SYMBOL:
- return sym_check_deps(e->left.sym);
- default:
- break;
- }
- printf("Oops! How to check %d?\n", e->type);
- return NULL;
-}
-
-/* return NULL when dependencies are OK */
-static struct symbol *sym_check_sym_deps(struct symbol *sym)
-{
- struct symbol *sym2;
- struct property *prop;
- struct dep_stack stack;
-
- dep_stack_insert(&stack, sym);
-
- sym2 = sym_check_expr_deps(sym->rev_dep.expr);
- if (sym2)
- goto out;
-
- for (prop = sym->prop; prop; prop = prop->next) {
- if (prop->type == P_CHOICE || prop->type == P_SELECT)
- continue;
- stack.prop = prop;
- sym2 = sym_check_expr_deps(prop->visible.expr);
- if (sym2)
- break;
- if (prop->type != P_DEFAULT || sym_is_choice(sym))
- continue;
- stack.expr = prop->expr;
- sym2 = sym_check_expr_deps(prop->expr);
- if (sym2)
- break;
- stack.expr = NULL;
- }
-
-out:
- dep_stack_remove();
-
- return sym2;
-}
-
-static struct symbol *sym_check_choice_deps(struct symbol *choice)
-{
- struct symbol *sym, *sym2;
- struct property *prop;
- struct expr *e;
- struct dep_stack stack;
-
- dep_stack_insert(&stack, choice);
-
- prop = sym_get_choice_prop(choice);
- expr_list_for_each_sym(prop->expr, e, sym)
- sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);
-
- choice->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);
- sym2 = sym_check_sym_deps(choice);
- choice->flags &= ~SYMBOL_CHECK;
- if (sym2)
- goto out;
-
- expr_list_for_each_sym(prop->expr, e, sym) {
- sym2 = sym_check_sym_deps(sym);
- if (sym2)
- break;
- }
-out:
- expr_list_for_each_sym(prop->expr, e, sym)
- sym->flags &= ~SYMBOL_CHECK;
-
- if (sym2 && sym_is_choice_value(sym2) &&
- prop_get_symbol(sym_get_choice_prop(sym2)) == choice)
- sym2 = choice;
-
- dep_stack_remove();
-
- return sym2;
-}
-
-struct symbol *sym_check_deps(struct symbol *sym)
-{
- struct symbol *sym2;
- struct property *prop;
-
- if (sym->flags & SYMBOL_CHECK) {
- sym_check_print_recursive(sym);
- return sym;
- }
- if (sym->flags & SYMBOL_CHECKED)
- return NULL;
-
- if (sym_is_choice_value(sym)) {
- struct dep_stack stack;
-
- /* for choice groups start the check with main choice symbol */
- dep_stack_insert(&stack, sym);
- prop = sym_get_choice_prop(sym);
- sym2 = sym_check_deps(prop_get_symbol(prop));
- dep_stack_remove();
- } else if (sym_is_choice(sym)) {
- sym2 = sym_check_choice_deps(sym);
- } else {
- sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);
- sym2 = sym_check_sym_deps(sym);
- sym->flags &= ~SYMBOL_CHECK;
- }
-
- if (sym2 && sym2 == sym)
- sym2 = NULL;
-
- return sym2;
-}
-
-struct property *prop_alloc(enum prop_type type, struct symbol *sym)
-{
- struct property *prop;
- struct property **propp;
-
- prop = malloc(sizeof(*prop));
- memset(prop, 0, sizeof(*prop));
- prop->type = type;
- prop->sym = sym;
- prop->file = current_file;
- prop->lineno = zconf_lineno();
-
- /* append property to the prop list of symbol */
- if (sym) {
- for (propp = &sym->prop; *propp; propp = &(*propp)->next)
- ;
- *propp = prop;
- }
-
- return prop;
-}
-
-struct symbol *prop_get_symbol(struct property *prop)
-{
- if (prop->expr && (prop->expr->type == E_SYMBOL ||
- prop->expr->type == E_LIST))
- return prop->expr->left.sym;
- return NULL;
-}
-
-const char *prop_get_type_name(enum prop_type type)
-{
- switch (type) {
- case P_PROMPT:
- return "prompt";
- case P_ENV:
- return "env";
- case P_COMMENT:
- return "comment";
- case P_MENU:
- return "menu";
- case P_DEFAULT:
- return "default";
- case P_CHOICE:
- return "choice";
- case P_SELECT:
- return "select";
- case P_RANGE:
- return "range";
- case P_SYMBOL:
- return "symbol";
- case P_UNKNOWN:
- break;
- }
- return "unknown";
-}
-
-static void prop_add_env(const char *env)
-{
- struct symbol *sym, *sym2;
- struct property *prop;
- char *p;
-
- sym = current_entry->sym;
- sym->flags |= SYMBOL_AUTO;
- for_all_properties(sym, prop, P_ENV) {
- sym2 = prop_get_symbol(prop);
- if (strcmp(sym2->name, env))
- menu_warn(current_entry, "redefining environment symbol from %s",
- sym2->name);
- return;
- }
-
- prop = prop_alloc(P_ENV, sym);
- prop->expr = expr_alloc_symbol(sym_lookup(env, SYMBOL_CONST));
-
- sym_env_list = expr_alloc_one(E_LIST, sym_env_list);
- sym_env_list->right.sym = sym;
-
- p = getenv(env);
- if (p)
- sym_add_default(sym, p);
- else
- menu_warn(current_entry, "environment variable %s undefined", env);
-}
+++ /dev/null
-/*
- * Copyright (C) 2002-2005 Roman Zippel <zippel@linux-m68k.org>
- * Copyright (C) 2002-2005 Sam Ravnborg <sam@ravnborg.org>
- *
- * Released under the terms of the GNU GPL v2.0.
- */
-
-#include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
-#include "lkc.h"
-
-/* file already present in list? If not add it */
-struct file *file_lookup(const char *name)
-{
- struct file *file;
- const char *file_name = sym_expand_string_value(name);
-
- for (file = file_list; file; file = file->next) {
- if (!strcmp(name, file->name)) {
- free((void *)file_name);
- return file;
- }
- }
-
- file = malloc(sizeof(*file));
- memset(file, 0, sizeof(*file));
- file->name = file_name;
- file->next = file_list;
- file_list = file;
- return file;
-}
-
-/* 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 gs;
- gs.s = malloc(sizeof(char) * 64);
- gs.len = 64;
- gs.max_width = 0;
- strcpy(gs.s, "\0");
- return gs;
-}
-
-/* Allocate and assign growable string */
-struct gstr str_assign(const char *s)
-{
- struct gstr gs;
- gs.s = strdup(s);
- gs.len = strlen(s) + 1;
- gs.max_width = 0;
- return gs;
-}
-
-/* Free storage for growable string */
-void str_free(struct gstr *gs)
-{
- if (gs->s)
- free(gs->s);
- gs->s = NULL;
- gs->len = 0;
-}
-
-/* Append to growable string */
-void str_append(struct gstr *gs, const char *s)
-{
- size_t l;
- if (s) {
- l = strlen(gs->s) + strlen(s) + 1;
- if (l > gs->len) {
- gs->s = realloc(gs->s, l);
- gs->len = l;
- }
- strcat(gs->s, s);
- }
-}
-
-/* Append printf formatted string to growable string */
-void str_printf(struct gstr *gs, const char *fmt, ...)
-{
- va_list ap;
- char s[10000]; /* big enough... */
- va_start(ap, fmt);
- vsnprintf(s, sizeof(s), fmt, ap);
- str_append(gs, s);
- va_end(ap);
-}
-
-/* Retrieve value of growable string */
-const char *str_get(struct gstr *gs)
-{
- return gs->s;
-}
-
+++ /dev/null
-%{
-/*
- * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
- * Released under the terms of the GNU GPL v2.0.
- */
-
-#include <ctype.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdbool.h>
-
-#include "lkc.h"
-
-#define printd(mask, fmt...) if (cdebug & (mask)) printf(fmt)
-
-#define PRINTD 0x0001
-#define DEBUG_PARSE 0x0002
-
-int cdebug = PRINTD;
-
-extern int zconflex(void);
-static void zconfprint(const char *err, ...);
-static void zconf_error(const char *err, ...);
-static void zconferror(const char *err);
-static bool zconf_endtoken(const struct kconf_id *id, int starttoken, int endtoken);
-
-struct symbol *symbol_hash[SYMBOL_HASHSIZE];
-
-static struct menu *current_menu, *current_entry;
-
-%}
-%expect 30
-
-%union
-{
- char *string;
- struct file *file;
- struct symbol *symbol;
- struct expr *expr;
- struct menu *menu;
- const struct kconf_id *id;
-}
-
-%token <id>T_MAINMENU
-%token <id>T_MENU
-%token <id>T_ENDMENU
-%token <id>T_SOURCE
-%token <id>T_CHOICE
-%token <id>T_ENDCHOICE
-%token <id>T_COMMENT
-%token <id>T_CONFIG
-%token <id>T_MENUCONFIG
-%token <id>T_HELP
-%token <string> T_HELPTEXT
-%token <id>T_IF
-%token <id>T_ENDIF
-%token <id>T_DEPENDS
-%token <id>T_OPTIONAL
-%token <id>T_PROMPT
-%token <id>T_TYPE
-%token <id>T_DEFAULT
-%token <id>T_SELECT
-%token <id>T_RANGE
-%token <id>T_VISIBLE
-%token <id>T_OPTION
-%token <id>T_ON
-%token <string> T_WORD
-%token <string> T_WORD_QUOTE
-%token T_UNEQUAL
-%token T_CLOSE_PAREN
-%token T_OPEN_PAREN
-%token T_EOL
-
-%left T_OR
-%left T_AND
-%left T_EQUAL T_UNEQUAL
-%nonassoc T_NOT
-
-%type <string> prompt
-%type <symbol> symbol
-%type <expr> expr
-%type <expr> if_expr
-%type <id> end
-%type <id> option_name
-%type <menu> if_entry menu_entry choice_entry
-%type <string> symbol_option_arg word_opt
-
-%destructor {
- fprintf(stderr, "%s:%d: missing end statement for this entry\n",
- $$->file->name, $$->lineno);
- if (current_menu == $$)
- menu_end_menu();
-} if_entry menu_entry choice_entry
-
-%{
-/* Include zconf.hash.c here so it can see the token constants. */
-#include "hconf.c"
-%}
-
-%%
-input: nl start | start;
-
-start: mainmenu_stmt stmt_list | stmt_list;
-
-stmt_list:
- /* empty */
- | stmt_list common_stmt
- | stmt_list choice_stmt
- | stmt_list menu_stmt
- | stmt_list end { zconf_error("unexpected end statement"); }
- | stmt_list T_WORD error T_EOL { zconf_error("unknown statement \"%s\"", $2); }
- | stmt_list option_name error T_EOL
-{
- zconf_error("unexpected option \"%s\"", kconf_id_strings + $2->name);
-}
- | stmt_list error T_EOL { zconf_error("invalid statement"); }
-;
-
-option_name:
- T_DEPENDS | T_PROMPT | T_TYPE | T_SELECT | T_OPTIONAL | T_RANGE | T_DEFAULT | T_VISIBLE
-;
-
-common_stmt:
- T_EOL
- | if_stmt
- | comment_stmt
- | config_stmt
- | menuconfig_stmt
- | source_stmt
-;
-
-option_error:
- T_WORD error T_EOL { zconf_error("unknown option \"%s\"", $1); }
- | error T_EOL { zconf_error("invalid option"); }
-;
-
-
-/* config/menuconfig entry */
-
-config_entry_start: T_CONFIG T_WORD T_EOL
-{
- struct symbol *sym = sym_lookup($2, 0);
- sym->flags |= SYMBOL_OPTIONAL;
- menu_add_entry(sym);
- printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), $2);
-};
-
-config_stmt: config_entry_start config_option_list
-{
- menu_end_entry();
- printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno());
-};
-
-menuconfig_entry_start: T_MENUCONFIG T_WORD T_EOL
-{
- struct symbol *sym = sym_lookup($2, 0);
- sym->flags |= SYMBOL_OPTIONAL;
- menu_add_entry(sym);
- printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), $2);
-};
-
-menuconfig_stmt: menuconfig_entry_start config_option_list
-{
- if (current_entry->prompt)
- current_entry->prompt->type = P_MENU;
- else
- zconfprint("warning: menuconfig statement without prompt");
- menu_end_entry();
- printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno());
-};
-
-config_option_list:
- /* empty */
- | config_option_list config_option
- | config_option_list symbol_option
- | config_option_list depends
- | config_option_list help
- | config_option_list option_error
- | config_option_list T_EOL
-;
-
-config_option: T_TYPE prompt_stmt_opt T_EOL
-{
- menu_set_type($1->stype);
- printd(DEBUG_PARSE, "%s:%d:type(%u)\n",
- zconf_curname(), zconf_lineno(),
- $1->stype);
-};
-
-config_option: T_PROMPT prompt if_expr T_EOL
-{
- menu_add_prompt(P_PROMPT, $2, $3);
- printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
-};
-
-config_option: T_DEFAULT expr if_expr T_EOL
-{
- menu_add_expr(P_DEFAULT, $2, $3);
- if ($1->stype != S_UNKNOWN)
- menu_set_type($1->stype);
- printd(DEBUG_PARSE, "%s:%d:default(%u)\n",
- zconf_curname(), zconf_lineno(),
- $1->stype);
-};
-
-config_option: T_SELECT T_WORD if_expr T_EOL
-{
- menu_add_symbol(P_SELECT, sym_lookup($2, 0), $3);
- printd(DEBUG_PARSE, "%s:%d:select\n", zconf_curname(), zconf_lineno());
-};
-
-config_option: T_RANGE symbol symbol if_expr T_EOL
-{
- menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,$2, $3), $4);
- 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: T_CHOICE word_opt T_EOL
-{
- struct symbol *sym = sym_lookup($2, SYMBOL_CHOICE);
- sym->flags |= SYMBOL_AUTO;
- menu_add_entry(sym);
- menu_add_expr(P_CHOICE, NULL, NULL);
- printd(DEBUG_PARSE, "%s:%d:choice\n", zconf_curname(), zconf_lineno());
-};
-
-choice_entry: choice choice_option_list
-{
- $$ = menu_add_menu();
-};
-
-choice_end: end
-{
- if (zconf_endtoken($1, T_CHOICE, T_ENDCHOICE)) {
- menu_end_menu();
- printd(DEBUG_PARSE, "%s:%d:endchoice\n", zconf_curname(), zconf_lineno());
- }
-};
-
-choice_stmt: choice_entry choice_block choice_end
-;
-
-choice_option_list:
- /* empty */
- | choice_option_list choice_option
- | choice_option_list depends
- | choice_option_list help
- | choice_option_list T_EOL
- | choice_option_list option_error
-;
-
-choice_option: T_PROMPT prompt if_expr T_EOL
-{
- menu_add_prompt(P_PROMPT, $2, $3);
- printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
-};
-
-choice_option: T_TYPE prompt_stmt_opt T_EOL
-{
- if ($1->stype == S_BOOLEAN || $1->stype == S_TRISTATE) {
- menu_set_type($1->stype);
- printd(DEBUG_PARSE, "%s:%d:type(%u)\n",
- zconf_curname(), zconf_lineno(),
- $1->stype);
- } else
- YYERROR;
-};
-
-choice_option: T_OPTIONAL T_EOL
-{
- current_entry->sym->flags |= SYMBOL_OPTIONAL;
- printd(DEBUG_PARSE, "%s:%d:optional\n", zconf_curname(), zconf_lineno());
-};
-
-choice_option: T_DEFAULT T_WORD if_expr T_EOL
-{
- if ($1->stype == S_UNKNOWN) {
- menu_add_symbol(P_DEFAULT, sym_lookup($2, 0), $3);
- printd(DEBUG_PARSE, "%s:%d:default\n",
- zconf_curname(), zconf_lineno());
- } else
- YYERROR;
-};
-
-choice_block:
- /* empty */
- | choice_block common_stmt
-;
-
-/* if entry */
-
-if_entry: T_IF expr nl
-{
- printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno());
- menu_add_entry(NULL);
- menu_add_dep($2);
- $$ = menu_add_menu();
-};
-
-if_end: end
-{
- if (zconf_endtoken($1, T_IF, T_ENDIF)) {
- menu_end_menu();
- printd(DEBUG_PARSE, "%s:%d:endif\n", zconf_curname(), zconf_lineno());
- }
-};
-
-if_stmt: if_entry if_block if_end
-;
-
-if_block:
- /* empty */
- | if_block common_stmt
- | if_block menu_stmt
- | if_block choice_stmt
-;
-
-/* mainmenu entry */
-
-mainmenu_stmt: T_MAINMENU prompt nl
-{
- menu_add_prompt(P_MENU, $2, NULL);
-};
-
-/* menu entry */
-
-menu: T_MENU prompt T_EOL
-{
- menu_add_entry(NULL);
- menu_add_prompt(P_MENU, $2, NULL);
- printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno());
-};
-
-menu_entry: menu visibility_list depends_list
-{
- $$ = menu_add_menu();
-};
-
-menu_end: end
-{
- if (zconf_endtoken($1, T_MENU, T_ENDMENU)) {
- menu_end_menu();
- printd(DEBUG_PARSE, "%s:%d:endmenu\n", zconf_curname(), zconf_lineno());
- }
-};
-
-menu_stmt: menu_entry menu_block menu_end
-;
-
-menu_block:
- /* empty */
- | menu_block common_stmt
- | menu_block menu_stmt
- | menu_block choice_stmt
-;
-
-source_stmt: T_SOURCE prompt T_EOL
-{
- printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), $2);
- zconf_nextfile($2);
-};
-
-/* comment entry */
-
-comment: T_COMMENT prompt T_EOL
-{
- menu_add_entry(NULL);
- menu_add_prompt(P_COMMENT, $2, NULL);
- printd(DEBUG_PARSE, "%s:%d:comment\n", zconf_curname(), zconf_lineno());
-};
-
-comment_stmt: comment depends_list
-{
- menu_end_entry();
-};
-
-/* help option */
-
-help_start: T_HELP T_EOL
-{
- printd(DEBUG_PARSE, "%s:%d:help\n", zconf_curname(), zconf_lineno());
- zconf_starthelp();
-};
-
-help: help_start T_HELPTEXT
-{
- current_entry->help = $2;
-};
-
-/* depends option */
-
-depends_list:
- /* empty */
- | depends_list depends
- | depends_list T_EOL
- | depends_list option_error
-;
-
-depends: T_DEPENDS T_ON expr T_EOL
-{
- menu_add_dep($3);
- printd(DEBUG_PARSE, "%s:%d:depends on\n", zconf_curname(), zconf_lineno());
-};
-
-/* visibility option */
-
-visibility_list:
- /* empty */
- | visibility_list visible
- | visibility_list T_EOL
-;
-
-visible: T_VISIBLE if_expr
-{
- menu_add_visibility($2);
-};
-
-/* prompt statement */
-
-prompt_stmt_opt:
- /* empty */
- | prompt if_expr
-{
- menu_add_prompt(P_PROMPT, $1, $2);
-};
-
-prompt: T_WORD
- | T_WORD_QUOTE
-;
-
-end: T_ENDMENU T_EOL { $$ = $1; }
- | T_ENDCHOICE T_EOL { $$ = $1; }
- | T_ENDIF T_EOL { $$ = $1; }
-;
-
-nl:
- T_EOL
- | nl T_EOL
-;
-
-if_expr: /* empty */ { $$ = NULL; }
- | T_IF expr { $$ = $2; }
-;
-
-expr: symbol { $$ = expr_alloc_symbol($1); }
- | symbol T_EQUAL symbol { $$ = expr_alloc_comp(E_EQUAL, $1, $3); }
- | symbol T_UNEQUAL symbol { $$ = expr_alloc_comp(E_UNEQUAL, $1, $3); }
- | T_OPEN_PAREN expr T_CLOSE_PAREN { $$ = $2; }
- | T_NOT expr { $$ = expr_alloc_one(E_NOT, $2); }
- | expr T_OR expr { $$ = expr_alloc_two(E_OR, $1, $3); }
- | expr T_AND expr { $$ = expr_alloc_two(E_AND, $1, $3); }
-;
-
-symbol: T_WORD { $$ = sym_lookup($1, 0); free($1); }
- | T_WORD_QUOTE { $$ = sym_lookup($1, SYMBOL_CONST); free($1); }
-;
-
-word_opt: /* empty */ { $$ = NULL; }
- | T_WORD
-
-%%
-
-void conf_parse(const char *name)
-{
- struct symbol *sym;
- int i;
-
- zconf_initscan(name);
-
- sym_init();
- _menu_init();
- modules_sym = sym_lookup(NULL, 0);
- modules_sym->type = S_BOOLEAN;
- modules_sym->flags |= SYMBOL_AUTO;
- rootmenu.prompt = menu_add_prompt(P_MENU, "Linux Kernel Configuration", NULL);
-
- if (getenv("ZCONF_DEBUG"))
- zconfdebug = 1;
- zconfparse();
- if (zconfnerrs)
- 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);
- for_all_symbols(i, sym) {
- if (sym_check_deps(sym))
- zconfnerrs++;
- }
- if (zconfnerrs)
- exit(1);
- sym_set_change_count(1);
-}
-
-static const char *zconf_tokenname(int token)
-{
- switch (token) {
- case T_MENU: return "menu";
- case T_ENDMENU: return "endmenu";
- case T_CHOICE: return "choice";
- case T_ENDCHOICE: return "endchoice";
- case T_IF: return "if";
- case T_ENDIF: return "endif";
- case T_DEPENDS: return "depends";
- case T_VISIBLE: return "visible";
- }
- return "<token>";
-}
-
-static bool zconf_endtoken(const struct kconf_id *id, int starttoken, int endtoken)
-{
- if (id->token != endtoken) {
- zconf_error("unexpected '%s' within %s block",
- kconf_id_strings + id->name, zconf_tokenname(starttoken));
- zconfnerrs++;
- return false;
- }
- if (current_menu->file != current_file) {
- zconf_error("'%s' in different file than '%s'",
- kconf_id_strings + id->name, zconf_tokenname(starttoken));
- fprintf(stderr, "%s:%d: location of the '%s'\n",
- current_menu->file->name, current_menu->lineno,
- zconf_tokenname(starttoken));
- zconfnerrs++;
- return false;
- }
- return true;
-}
-
-static void zconfprint(const char *err, ...)
-{
- va_list ap;
-
- fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno());
- va_start(ap, err);
- vfprintf(stderr, err, ap);
- va_end(ap);
- fprintf(stderr, "\n");
-}
-
-static void zconf_error(const char *err, ...)
-{
- va_list ap;
-
- zconfnerrs++;
- fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno());
- va_start(ap, err);
- vfprintf(stderr, err, ap);
- va_end(ap);
- fprintf(stderr, "\n");
-}
-
-static void zconferror(const char *err)
-{
- fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno() + 1, err);
-}
-
-static void print_quoted_string(FILE *out, const char *str)
-{
- const char *p;
- int len;
-
- putc('"', out);
- while ((p = strchr(str, '"'))) {
- len = p - str;
- if (len)
- fprintf(out, "%.*s", len, str);
- fputs("\\\"", out);
- str = p + 1;
- }
- fputs(str, out);
- putc('"', out);
-}
-
-static void print_symbol(FILE *out, struct menu *menu)
-{
- struct symbol *sym = menu->sym;
- struct property *prop;
-
- if (sym_is_choice(sym))
- fprintf(out, "\nchoice\n");
- else
- fprintf(out, "\nconfig %s\n", sym->name);
- switch (sym->type) {
- case S_BOOLEAN:
- fputs(" boolean\n", out);
- break;
- case S_TRISTATE:
- fputs(" tristate\n", out);
- break;
- case S_STRING:
- fputs(" string\n", out);
- break;
- case S_INT:
- fputs(" integer\n", out);
- break;
- case S_HEX:
- fputs(" hex\n", out);
- break;
- default:
- fputs(" ???\n", out);
- break;
- }
- for (prop = sym->prop; prop; prop = prop->next) {
- if (prop->menu != menu)
- continue;
- switch (prop->type) {
- case P_PROMPT:
- fputs(" prompt ", out);
- print_quoted_string(out, prop->text);
- if (!expr_is_yes(prop->visible.expr)) {
- fputs(" if ", out);
- expr_fprint(prop->visible.expr, out);
- }
- fputc('\n', out);
- break;
- case P_DEFAULT:
- fputs( " default ", out);
- expr_fprint(prop->expr, out);
- if (!expr_is_yes(prop->visible.expr)) {
- fputs(" if ", out);
- expr_fprint(prop->visible.expr, out);
- }
- fputc('\n', out);
- break;
- case P_CHOICE:
- fputs(" #choice value\n", out);
- 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:
- fprintf(out, " unknown prop %d!\n", prop->type);
- break;
- }
- }
- if (menu->help) {
- int len = strlen(menu->help);
- while (menu->help[--len] == '\n')
- menu->help[len] = 0;
- fprintf(out, " help\n%s\n", menu->help);
- }
-}
-
-void zconfdump(FILE *out)
-{
- struct property *prop;
- struct symbol *sym;
- struct menu *menu;
-
- menu = rootmenu.list;
- while (menu) {
- if ((sym = menu->sym))
- print_symbol(out, menu);
- else if ((prop = menu->prompt)) {
- switch (prop->type) {
- case P_COMMENT:
- fputs("\ncomment ", out);
- print_quoted_string(out, prop->text);
- fputs("\n", out);
- break;
- case P_MENU:
- fputs("\nmenu ", out);
- print_quoted_string(out, prop->text);
- fputs("\n", out);
- break;
- default:
- ;
- }
- if (!expr_is_yes(prop->visible.expr)) {
- fputs(" depends ", out);
- expr_fprint(prop->visible.expr, out);
- fputc('\n', out);
- }
- }
-
- if (menu->list)
- menu = menu->list;
- else if (menu->next)
- menu = menu->next;
- else while ((menu = menu->parent)) {
- if (menu->prompt && menu->prompt->type == P_MENU)
- fputs("\nendmenu\n", out);
- if (menu->next) {
- menu = menu->next;
- break;
- }
- }
- }
-}
-
-#include "lconf.c"
-#include "util.c"
-#include "confdata.c"
-#include "expr.c"
-#include "symbol.c"
-#include "menu.c"