* Lots of codec updates
authorRick van Rein <vanrein@hwdev.(none)>
Mon, 5 Dec 2011 12:33:33 +0000 (12:33 +0000)
committerRick van Rein <vanrein@hwdev.(none)>
Mon, 5 Dec 2011 12:33:33 +0000 (12:33 +0000)
* New kconfig version (from latest Linux kernel)
* Sound is finally starting to work on the BT-200 phone!!!

Re. sound:  When it boots the echo program that sends 1 kHz samples over the McBSP #1
it starts up silently.  The Codec has not been initialised at that time:

Channel 0 registers (slave 0x40): 1A=90 2A=20 3C=88 3D=c0 3A=01 3B=40 4A=08 4B=9e 5A=00 5B=40 5C=bf 5D=c0 6A=02 6B=82
Channel 1 registers (slave 0x41): 1A=90 2A=20 3C=88 3D=c0 3A=01 3B=40 4A=08 4B=9e 5A=00 5B=40 5C=bf 5D=c0 6A=00 6B=80

Then, run the following commands:

./bin/i2cp/aic2x-config /dev/i2c-2 0x40 0x49 0xa0 0x01 0x40 0x88 0xff 0x08 0x9e 0x1f 0x40 0xbf 0xc0 0x02 0x82
./bin/i2cp/aic2x-config /dev/i2c-2 0x41 0x49 0xa0 0x31 0x60 0x88 0xff 0x08 0x9e 0x12 0x50 0xbf 0xc0 0x00 0x80

This will raise sound (not through DMA but "manual" writes to McBSP); the codec reads:

Channel 0 registers (slave 0x40): 1A=49 2A=a0 3A=01 3B=40 3C=88 3D=ff 4A=08 4B=9e 5C=bf 5D=c0 5A=1f 5B=40 6A=02 6B=82
Channel 1 registers (slave 0x41): 1A=49 2A=a0 3A=31 3B=60 3C=88 3D=ff 4A=08 4B=9e 5C=bf 5D=c0 5A=12 5B=50 6A=00 6B=80

Note that the volume is not always the same; apparently there is still some form of
sync problem.  Things to explore are now:

1. Whether the TLV should be reset before setting up McBSP #1
2. Whether the data to the Codec is stable as long as SCLK is low
3. Whether FS changes when SCLK is high (max 6 ns after going up, no min specified)

84 files changed:
Makefile
TODO
bin/i2cp/aic2x-setup.c
bin/kconfig/conf.c
bin/kconfig/confdata.c
bin/kconfig/expr.c
bin/kconfig/expr.h
bin/kconfig/gconf.c
bin/kconfig/kconfig-language.txt [new file with mode: 0644]
bin/kconfig/kxgettext.c
bin/kconfig/lkc.h
bin/kconfig/lkc_proto.h
bin/kconfig/mconf.c
bin/kconfig/menu.c
bin/kconfig/qconf.cc
bin/kconfig/qconf.h
bin/kconfig/symbol.c
bin/kconfig/util.c
bin/kconfig/zconf.l
bin/kconfig/zconf.tab.c_shipped
bin/kconfig/zconf.y
bin/lex.zconf.c
bin/mconf
bin/zconf.tab.c
configure [new file with mode: 0755]
doc/howto.rst [new file with mode: 0644]
include/0cpm/netinet.h
include/bottom/devel.h
include/bottom/grandstream.h
include/bottom/ksz8842.h
include/bottom/tic55x.h
include/tic55x/malloc.h [new file with mode: 0644]
include/tic55x/memory.h [new file with mode: 0644]
include/tic55x/stdint.h
include/tic55x/stdlib.h
include/tic55x/string.h
src/codec/README
src/codec/codec2/AUTHORS [new file with mode: 0644]
src/codec/codec2/COPYING [new file with mode: 0644]
src/codec/codec2/ChangeLog [new file with mode: 0644]
src/codec/codec2/INSTALL [new file with mode: 0644]
src/codec/codec2/NEWS [new file with mode: 0644]
src/codec/codec2/README [new file with mode: 0644]
src/codec/codec2/src/codec2.h [new file with mode: 0644]
src/codec/codec2/src/codec2_internal.h [new file with mode: 0644]
src/codec/codec2/src/comp.h [new file with mode: 0644]
src/codec/codec2/src/defines.h [new file with mode: 0644]
src/codec/rtt/Makefile.desktop
src/codec/rtt/desktop.c
src/codec/rtt/recvkeys.c
src/codec/rtt/sendkeys.c
src/codec/spandsp/README.0cpm-Firmerware
src/codec/spandsp/src/bitstream.c [new file with mode: 0644]
src/codec/spandsp/src/floating_fudge.h
src/codec/spandsp/src/g711.c
src/codec/spandsp/src/g722.c
src/codec/spandsp/src/g726.c
src/codec/spandsp/src/mmx_sse_decs.h [new file with mode: 0644]
src/codec/spandsp/src/spandsp/fast_convert.h
src/codec/spandsp/src/spandsp/logging.h [new file with mode: 0644]
src/codec/spandsp/src/vector_int.c [new file with mode: 0644]
src/codec/speex/include/speex/speex.h [new file with mode: 0644]
src/codec/speex/include/speex/speex_bits.h [new file with mode: 0644]
src/codec/speex/include/speex/speex_types.h [new file with mode: 0644]
src/codec/wrap.c [new file with mode: 0644]
src/driver/ksz8842.c
src/driver/tic55x/grandstream-bt20x.c
src/driver/tic55x/linker.cmd [new file with mode: 0644]
src/driver/tlv320aic2x.c
src/function/Kconfig
src/function/Makefile
src/function/develtest/echo.c
src/function/develtest/switch2led.c
src/function/develtest/timer2led.c
src/kernel/app.c
src/kernel/cpu.c
src/kernel/led.c
src/kernel/net.c
src/kernel/resource.c
src/kernel/timer.c
src/net/input.c
src/sip/dialog.c
src/target/Kconfig.grandstream
src/target/Kconfig.platform

index b70a523..8920d0b 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -50,6 +50,7 @@ include src/kernel/Makefile
 include src/net/Makefile
 include src/sip/Makefile
 include src/phone/Makefile
+include src/codec/Makefile
 
 include src/target/Makefile
 include src/function/Makefile
@@ -74,6 +75,7 @@ configincludes: include/config.h
 -include $(objs-top-kernel-y:.o=.d)
 -include $(objs-top-net-y:.o=.d)
 -include $(objs-top-phone-y:.o=.d)
+-include $(objs-top-codec-y:.o=.d)
 -include $(objs-top-bottom-y:.o=.d)
 
 #
@@ -96,8 +98,11 @@ bin/top-net.o: $(objs-top-net-y)
 bin/top-phone.o: $(objs-top-phone-y)
        PATH=$(BINPATH) $(LD) $(LDFLAGS) -r -o $@ $(objs-top-phone-y)
 
-# bin/top.o: bin/top-kernel.o bin/top-net.o bin/top-phone.o
-#      $(LD) $(LDFLAGS) -r -o $@ bin/top-kernel.o bin/top-net.o bin/top-phone.o
+bin/top-codec.o: $(objs-top-codec-y)
+       PATH=$(BINPATH) $(LD) $(LDFLAGS) -r -o $@ $(objs-top-codec-y)
+
+# bin/top.o: bin/top-kernel.o bin/top-net.o bin/top-phone.o bin/top-codec.o
+#      $(LD) $(LDFLAGS) -r -o $@ bin/top-kernel.o bin/top-net.o bin/top-phone.o bin/top-codec.o
 bin/top.o: $(objs-top-y)
        PATH=$(BINPATH) $(LD) $(LDFLAGS) -r -o $@ $(objs-top-y)
 
@@ -110,12 +115,20 @@ bin/bottom.o: $(objs-bottom-y)
 tags: src/net/6bed4.c
        ctags $(objs-top-kernel-y:.o=.c) $(objs-top-net-y:.o=.c) $(objs-top-phone-y:.o=.c) $(objs-bottom-y:.o=.c) include/0cpm/*.h include/config.h
 
+#
+# Create API documentation with doxygen
+#
+.PHONY += apidoc
+apidoc:
+       doxygen doc/doxygen.conf
+
 .PHONY += clean
 clean:
        rm -f $(objs-top-y) $(objs-top-n) $(objs-top-)
        rm -f $(objs-top-kernel-y) $(objs-top-kernel-n) $(objs-top-kernel-)
        rm -f $(objs-top-net-y) $(objs-top-net-n) $(objs-top-net-)
        rm -f $(objs-top-phone-y) $(objs-top-phone-n) $(objs-top-phone-)
+       rm -f $(objs-top-codec-y) $(objs-top-codec-n) $(objs-top-codec-)
        # rm -f $(objs-top-net-y)
        # rm -f $(objs-top-phone-y)
        rm -f $(objs-bottom-y) $(objs-bottom-n) $(objs-bottom-)
@@ -145,6 +158,10 @@ size:
        @echo
        @size $(objs-top-phone-y) || true
        @echo
+       @echo '*** Top half codec sizes:'
+       @echo
+       @size $(objs-top-codec-y) || true
+       @echo
        @echo '*** Bottom half sizes:'
        @echo
        @size $(objs-bottom-y) || true
diff --git a/TODO b/TODO
index ce1c152..8c65bc6 100644 (file)
--- a/TODO
+++ b/TODO
@@ -47,3 +47,9 @@ look at:
 
 * test RTP sound playback.  The retrocast tools can help with that:
   basicast /etc/hosts 2001:980:420a:1:020b:82ff:fe19:a0f4 32768
+
+* RTT handling:
+   - consider replacing the call to rtt_recv_keys() with a textapp wakeup
+
+* Transcoding: Now supported in spandsp (for G.711) -- this can go.
+
index c9dce36..74197a2 100644 (file)
@@ -70,7 +70,6 @@ uint8_t argval (char *strval) {
 
 int main (int argc, char *argv []) {
        int i;
-       uint8_t regs [13];
        uint8_t slave;
 
        if (argc < 4) {
@@ -121,7 +120,7 @@ int main (int argc, char *argv []) {
                uint8_t intval = argval (strval + reglen + 1);
                int j;
                bool found = false;
-               for (j=0; j < 13; j++) {
+               for (j=0; j < 14; j++) {
                        if (reglen != strlen (regname [j])) {
                                continue;
                        }
index fda6313..f208f90 100644 (file)
 #include <string.h>
 #include <time.h>
 #include <unistd.h>
+#include <getopt.h>
 #include <sys/stat.h>
+#include <sys/time.h>
 
-#define LKC_DIRECT_LINK
 #include "lkc.h"
 
 static void conf(struct menu *menu);
 static void check_conf(struct menu *menu);
-
-enum {
-       ask_all,
-       ask_new,
-       ask_silent,
-       set_default,
-       set_yes,
-       set_mod,
-       set_no,
-       set_random
-} input_mode = ask_all;
-char *defconfig_file;
+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 char nohelp_text[] = N_("Sorry, no help available for this option yet.\n");
-
-static const char *get_help(struct menu *menu)
+static void print_help(struct menu *menu)
 {
-       if (menu_has_help(menu))
-               return _(menu_get_help(menu));
-       else
-               return nohelp_text;
+       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)
@@ -65,7 +71,7 @@ static void strip(char *str)
 
 static void check_stdin(void)
 {
-       if (!valid_stdin && input_mode == ask_silent) {
+       if (!valid_stdin) {
                printf(_("aborted!\n\n"));
                printf(_("Console input/output is redirected. "));
                printf(_("Run 'make oldconfig' to update configuration.\n\n"));
@@ -76,7 +82,6 @@ static void check_stdin(void)
 static int conf_askvalue(struct symbol *sym, const char *def)
 {
        enum symbol_type type = sym_get_type(sym);
-       tristate val;
 
        if (!sym_has_value(sym))
                printf(_("(NEW) "));
@@ -92,28 +97,17 @@ static int conf_askvalue(struct symbol *sym, const char *def)
        }
 
        switch (input_mode) {
-       case set_no:
-       case set_mod:
-       case set_yes:
-       case set_random:
-               if (sym_has_value(sym)) {
-                       printf("%s\n", def);
-                       return 0;
-               }
-               break;
-       case ask_new:
-       case ask_silent:
+       case oldconfig:
+       case silentoldconfig:
                if (sym_has_value(sym)) {
                        printf("%s\n", def);
                        return 0;
                }
                check_stdin();
-       case ask_all:
+               /* fall through */
+       case oldaskconfig:
                fflush(stdout);
-               fgets(line, 128, stdin);
-               return 1;
-       case set_default:
-               printf("%s\n", def);
+               xfgets(line, 128, stdin);
                return 1;
        default:
                break;
@@ -128,57 +122,11 @@ static int conf_askvalue(struct symbol *sym, const char *def)
        default:
                ;
        }
-       switch (input_mode) {
-       case set_yes:
-               if (sym_tristate_within_range(sym, yes)) {
-                       line[0] = 'y';
-                       line[1] = '\n';
-                       line[2] = 0;
-                       break;
-               }
-       case set_mod:
-               if (type == S_TRISTATE) {
-                       if (sym_tristate_within_range(sym, mod)) {
-                               line[0] = 'm';
-                               line[1] = '\n';
-                               line[2] = 0;
-                               break;
-                       }
-               } else {
-                       if (sym_tristate_within_range(sym, yes)) {
-                               line[0] = 'y';
-                               line[1] = '\n';
-                               line[2] = 0;
-                               break;
-                       }
-               }
-       case set_no:
-               if (sym_tristate_within_range(sym, no)) {
-                       line[0] = 'n';
-                       line[1] = '\n';
-                       line[2] = 0;
-                       break;
-               }
-       case set_random:
-               do {
-                       val = (tristate)(rand() % 3);
-               } while (!sym_tristate_within_range(sym, val));
-               switch (val) {
-               case no: line[0] = 'n'; break;
-               case mod: line[0] = 'm'; break;
-               case yes: line[0] = 'y'; break;
-               }
-               line[1] = '\n';
-               line[2] = 0;
-               break;
-       default:
-               break;
-       }
        printf("%s", line);
        return 1;
 }
 
-int conf_string(struct menu *menu)
+static int conf_string(struct menu *menu)
 {
        struct symbol *sym = menu->sym;
        const char *def;
@@ -197,10 +145,11 @@ int conf_string(struct menu *menu)
                case '?':
                        /* print help */
                        if (line[1] == '\n') {
-                               printf("\n%s\n", get_help(menu));
+                               print_help(menu);
                                def = NULL;
                                break;
                        }
+                       /* fall through */
                default:
                        line[strlen(line)-1] = 0;
                        def = line;
@@ -213,14 +162,12 @@ int conf_string(struct menu *menu)
 static int conf_sym(struct menu *menu)
 {
        struct symbol *sym = menu->sym;
-       int type;
        tristate oldval, newval;
 
        while (1) {
                printf("%*s%s ", indent - 1, "", _(menu->prompt->text));
                if (sym->name)
                        printf("(%s) ", sym->name);
-               type = sym_get_type(sym);
                putchar('[');
                oldval = sym_get_tristate_value(sym);
                switch (oldval) {
@@ -277,7 +224,7 @@ static int conf_sym(struct menu *menu)
                if (sym_set_tristate_value(sym, newval))
                        return 0;
 help:
-               printf("\n%s\n", get_help(menu));
+               print_help(menu);
        }
 }
 
@@ -285,11 +232,9 @@ static int conf_choice(struct menu *menu)
 {
        struct symbol *sym, *def_sym;
        struct menu *child;
-       int type;
        bool is_new;
 
        sym = menu->sym;
-       type = sym_get_type(sym);
        is_new = !sym_has_value(sym);
        if (sym_is_changable(sym)) {
                conf_sym(menu);
@@ -351,20 +296,21 @@ static int conf_choice(struct menu *menu)
                        printf("?");
                printf("]: ");
                switch (input_mode) {
-               case ask_new:
-               case ask_silent:
+               case oldconfig:
+               case silentoldconfig:
                        if (!is_new) {
                                cnt = def;
                                printf("%d\n", cnt);
                                break;
                        }
                        check_stdin();
-               case ask_all:
+                       /* fall through */
+               case oldaskconfig:
                        fflush(stdout);
-                       fgets(line, 128, stdin);
+                       xfgets(line, 128, stdin);
                        strip(line);
                        if (line[0] == '?') {
-                               printf("\n%s\n", get_help(menu));
+                               print_help(menu);
                                continue;
                        }
                        if (!line[0])
@@ -374,15 +320,7 @@ static int conf_choice(struct menu *menu)
                        else
                                continue;
                        break;
-               case set_random:
-                       if (is_new)
-                               def = (rand() % cnt) + 1;
-               case set_default:
-               case set_yes:
-               case set_mod:
-               case set_no:
-                       cnt = def;
-                       printf("%d\n", cnt);
+               default:
                        break;
                }
 
@@ -395,8 +333,8 @@ static int conf_choice(struct menu *menu)
                }
                if (!child)
                        continue;
-               if (line[strlen(line) - 1] == '?') {
-                       printf("\n%s\n", get_help(child));
+               if (line[0] && line[strlen(line) - 1] == '?') {
+                       print_help(child);
                        continue;
                }
                sym_set_choice_value(sym, child->sym);
@@ -425,10 +363,14 @@ static void conf(struct menu *menu)
 
                switch (prop->type) {
                case P_MENU:
-                       if (input_mode == ask_silent && rootEntry != 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)
@@ -483,10 +425,16 @@ static void check_conf(struct menu *menu)
        if (sym && !sym_has_value(sym)) {
                if (sym_is_changable(sym) ||
                    (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)) {
-                       if (!conf_cnt++)
-                               printf(_("*\n* Restart config...\n*\n"));
-                       rootEntry = menu_get_parent_menu(menu);
-                       conf(rootEntry);
+                       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);
+                       }
                }
        }
 
@@ -494,63 +442,115 @@ static void check_conf(struct menu *menu)
                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;
+       const char *name, *defconfig_file = NULL /* gcc uninit */;
        struct stat tmpstat;
 
        setlocale(LC_ALL, "");
        bindtextdomain(PACKAGE, LOCALEDIR);
        textdomain(PACKAGE);
 
-       while ((opt = getopt(ac, av, "osdD:nmyrh")) != -1) {
+       while ((opt = getopt_long(ac, av, "", long_opts, NULL)) != -1) {
+               input_mode = (enum input_mode)opt;
                switch (opt) {
-               case 'o':
-                       input_mode = ask_new;
+               case silentoldconfig:
+                       sync_kconfig = 1;
                        break;
-               case 's':
-                       input_mode = ask_silent;
-                       valid_stdin = isatty(0) && isatty(1) && isatty(2);
-                       break;
-               case 'd':
-                       input_mode = set_default;
-                       break;
-               case 'D':
-                       input_mode = set_default;
+               case defconfig:
+               case savedefconfig:
                        defconfig_file = optarg;
                        break;
-               case 'n':
-                       input_mode = set_no;
-                       break;
-               case 'm':
-                       input_mode = set_mod;
+               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 'y':
-                       input_mode = set_yes;
-                       break;
-               case 'r':
-                       input_mode = set_random;
-                       srand(time(NULL));
-                       break;
-               case 'h':
-                       printf(_("See README for usage info\n"));
-                       exit(0);
+               }
+               case oldaskconfig:
+               case oldconfig:
+               case allnoconfig:
+               case allyesconfig:
+               case allmodconfig:
+               case alldefconfig:
+               case listnewconfig:
+               case oldnoconfig:
                        break;
-               default:
-                       fprintf(stderr, _("See README for usage info\n"));
+               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 set_default:
+       case defconfig:
                if (!defconfig_file)
                        defconfig_file = conf_get_default_confname();
                if (conf_read(defconfig_file)) {
@@ -560,35 +560,30 @@ int main(int ac, char **av)
                        exit(1);
                }
                break;
-       case ask_silent:
-               if (stat(".config", &tmpstat)) {
-                       printf(_("***\n"
-                               "*** You have not yet configured your kernel!\n"
-                               "*** (missing kernel .config file)\n"
-                               "***\n"
-                               "*** Please run some configurator (e.g. \"make oldconfig\" or\n"
-                               "*** \"make menuconfig\" or \"make xconfig\").\n"
-                               "***\n"));
-                       exit(1);
-               }
-       case ask_all:
-       case ask_new:
+       case savedefconfig:
+       case silentoldconfig:
+       case oldaskconfig:
+       case oldconfig:
+       case listnewconfig:
+       case oldnoconfig:
                conf_read(NULL);
                break;
-       case set_no:
-       case set_mod:
-       case set_yes:
-       case set_random:
+       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 set_no:     name = "allno.config"; break;
-               case set_mod:    name = "allmod.config"; break;
-               case set_yes:    name = "allyes.config"; break;
-               case set_random: name = "allrandom.config"; break;
+               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))
@@ -600,35 +595,90 @@ int main(int ac, char **av)
                break;
        }
 
-       if (input_mode != ask_silent) {
+       if (sync_kconfig) {
+               if (conf_get_changed()) {
+                       name = getenv("KCONFIG_NOSILENTUPDATE");
+                       if (name && *name) {
+                               fprintf(stderr,
+                                       _("\n*** The configuration requires explicit update.\n\n"));
+                               return 1;
+                       }
+               }
+               valid_stdin = 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);
-               if (input_mode == ask_all) {
-                       input_mode = ask_silent;
-                       valid_stdin = 1;
+               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);
                }
-       } else if (conf_get_changed()) {
-               name = getenv("KCONFIG_NOSILENTUPDATE");
-               if (name && *name) {
-                       fprintf(stderr, _("\n*** Kernel configuration requires explicit update.\n\n"));
+               if (conf_write_autoconf()) {
+                       fprintf(stderr, _("\n*** Error during update of the configuration.\n\n"));
                        return 1;
                }
-       } else
-               goto skip_check;
-
-       do {
-               conf_cnt = 0;
-               check_conf(&rootmenu);
-       } while (conf_cnt);
-       if (conf_write(NULL)) {
-               fprintf(stderr, _("\n*** Error during writing of the kernel configuration.\n\n"));
-               return 1;
-       }
-skip_check:
-       if (input_mode == ask_silent && conf_write_autoconf()) {
-               fprintf(stderr, _("\n*** Error during writing of the kernel 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");
+}
index 1ab48f0..5a58965 100644 (file)
@@ -5,19 +5,23 @@
 
 #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>
 
-#define LKC_DIRECT_LINK
 #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;
 
@@ -34,6 +38,29 @@ static void conf_warning(const char *fmt, ...)
        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");
@@ -41,6 +68,13 @@ const char *conf_get_configname(void)
        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;
@@ -94,6 +128,7 @@ static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
                        sym->flags |= def_flags;
                        break;
                }
+               /* fall through */
        case S_BOOLEAN:
                if (p[0] == 'y') {
                        sym->def[def].tri = yes;
@@ -106,7 +141,7 @@ static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
                        break;
                }
                conf_warning("symbol value '%s' invalid for %s", p, sym->name);
-               break;
+               return 1;
        case S_OTHER:
                if (*p != '"') {
                        for (p2 = p; *p2 && !isspace(*p2); p2++)
@@ -114,6 +149,7 @@ static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
                        sym->type = S_STRING;
                        goto done;
                }
+               /* fall through */
        case S_STRING:
                if (*p++ != '"')
                        break;
@@ -128,6 +164,7 @@ static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
                        conf_warning("invalid string found");
                        return 1;
                }
+               /* fall through */
        case S_INT:
        case S_HEX:
        done:
@@ -163,8 +200,11 @@ int conf_read_simple(const char *name, int def)
                if (in)
                        goto load;
                sym_add_change_count(1);
-               if (!sym_defconfig_list)
+               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 ||
@@ -173,9 +213,8 @@ int conf_read_simple(const char *name, int def)
                        name = conf_expand_value(prop->expr->left.sym->name);
                        in = zconf_fopen(name);
                        if (in) {
-                               printf(_("#\n"
-                                        "# using defaults found in %s\n"
-                                        "#\n"), name);
+                               conf_message(_("using defaults found in %s"),
+                                        name);
                                goto load;
                        }
                }
@@ -201,6 +240,7 @@ load:
                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;
@@ -210,24 +250,23 @@ load:
        while (fgets(line, sizeof(line), in)) {
                conf_lineno++;
                sym = NULL;
-               switch (line[0]) {
-               case '#':
-                       if (memcmp(line + 2, "CONFIG_", 7))
+               if (line[0] == '#') {
+                       if (memcmp(line + 2, CONFIG_, strlen(CONFIG_)))
                                continue;
-                       p = strchr(line + 9, ' ');
+                       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 + 9);
+                               sym = sym_find(line + 2 + strlen(CONFIG_));
                                if (!sym) {
-                                       conf_warning("trying to assign nonexistent symbol %s", line + 9);
-                                       break;
+                                       sym_add_change_count(1);
+                                       goto setsym;
                                }
                        } else {
-                               sym = sym_lookup(line + 9, 0);
+                               sym = sym_lookup(line + 2 + strlen(CONFIG_), 0);
                                if (sym->type == S_UNKNOWN)
                                        sym->type = S_BOOLEAN;
                        }
@@ -243,13 +282,8 @@ load:
                        default:
                                ;
                        }
-                       break;
-               case 'C':
-                       if (memcmp(line, "CONFIG_", 7)) {
-                               conf_warning("unexpected data");
-                               continue;
-                       }
-                       p = strchr(line + 7, '=');
+               } else if (memcmp(line, CONFIG_, strlen(CONFIG_)) == 0) {
+                       p = strchr(line + strlen(CONFIG_), '=');
                        if (!p)
                                continue;
                        *p++ = 0;
@@ -260,13 +294,13 @@ load:
                                        *p2 = 0;
                        }
                        if (def == S_DEF_USER) {
-                               sym = sym_find(line + 7);
+                               sym = sym_find(line + strlen(CONFIG_));
                                if (!sym) {
-                                       conf_warning("trying to assign nonexistent symbol %s", line + 7);
-                                       break;
+                                       sym_add_change_count(1);
+                                       goto setsym;
                                }
                        } else {
-                               sym = sym_lookup(line + 7, 0);
+                               sym = sym_lookup(line + strlen(CONFIG_), 0);
                                if (sym->type == S_UNKNOWN)
                                        sym->type = S_OTHER;
                        }
@@ -275,14 +309,12 @@ load:
                        }
                        if (conf_set_sym_val(sym, def, def_flags, p))
                                continue;
-                       break;
-               case '\r':
-               case '\n':
-                       break;
-               default:
-                       conf_warning("unexpected data");
+               } 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) {
@@ -335,6 +367,7 @@ int conf_read(const char *name)
                                        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;
@@ -389,17 +422,305 @@ int conf_read(const char *name)
        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, " ");
+                       fwrite(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, " ");
+                       fwrite(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;
-       char dirname[128], tmpname[128], newname[128];
-       int type, l;
        const char *str;
-       time_t now;
-       int use_timestamp = 1;
+       char dirname[PATH_MAX+1], tmpname[PATH_MAX+1], newname[PATH_MAX+1];
        char *env;
 
        dirname[0] = 0;
@@ -436,21 +757,7 @@ int conf_write(const char *name)
        if (!out)
                return 1;
 
-       sym = sym_lookup("KERNELVERSION", 0);
-       sym_calc_value(sym);
-       time(&now);
-       env = getenv("KCONFIG_NOTIMESTAMP");
-       if (env && *env)
-               use_timestamp = 0;
-
-       fprintf(out, _("#\n"
-                      "# Automatically generated make config: don't edit\n"
-                      "# firmly.0cpm version: %s\n"
-                      "%s%s"
-                      "#\n"),
-                    sym_get_string_value(sym),
-                    use_timestamp ? "# " : "",
-                    use_timestamp ? ctime(&now) : "");
+       conf_write_heading(out, &kconfig_printer_cb, NULL);
 
        if (!conf_get_changed())
                sym_clear_all_valid();
@@ -471,56 +778,11 @@ int conf_write(const char *name)
                        if (!(sym->flags & SYMBOL_WRITE))
                                goto next;
                        sym->flags &= ~SYMBOL_WRITE;
-                       type = sym->type;
-                       if (type == S_TRISTATE) {
-                               sym_calc_value(modules_sym);
-                               if (modules_sym->curr.tri == no)
-                                       type = S_BOOLEAN;
-                       }
-                       switch (type) {
-                       case S_BOOLEAN:
-                       case S_TRISTATE:
-                               switch (sym_get_tristate_value(sym)) {
-                               case no:
-                                       fprintf(out, "# CONFIG_%s is not set\n", sym->name);
-                                       break;
-                               case mod:
-                                       fprintf(out, "CONFIG_%s=m\n", sym->name);
-                                       break;
-                               case yes:
-                                       fprintf(out, "CONFIG_%s=y\n", sym->name);
-                                       break;
-                               }
-                               break;
-                       case S_STRING:
-                               str = sym_get_string_value(sym);
-                               fprintf(out, "CONFIG_%s=\"", sym->name);
-                               while (1) {
-                                       l = strcspn(str, "\"\\");
-                                       if (l) {
-                                               fwrite(str, l, 1, out);
-                                               str += l;
-                                       }
-                                       if (!*str)
-                                               break;
-                                       fprintf(out, "\\%c", *str++);
-                               }
-                               fputs("\"\n", out);
-                               break;
-                       case S_HEX:
-                               str = sym_get_string_value(sym);
-                               if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) {
-                                       fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
-                                       break;
-                               }
-                       case S_INT:
-                               str = sym_get_string_value(sym);
-                               fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
-                               break;
-                       }
+
+                       conf_write_symbol(out, sym, &kconfig_printer_cb, NULL);
                }
 
-       next:
+next:
                if (menu->list) {
                        menu = menu->list;
                        continue;
@@ -544,26 +806,23 @@ int conf_write(const char *name)
                        return 1;
        }
 
-       printf(_("#\n"
-                "# configuration written to %s\n"
-                "#\n"), newname);
+       conf_message(_("configuration written to %s"), newname);
 
        sym_set_change_count(0);
 
        return 0;
 }
 
-int conf_split_config(void)
+static int conf_split_config(void)
 {
-       char *name, path[128];
+       const char *name;
+       char path[PATH_MAX+1];
        char *s, *d, c;
        struct symbol *sym;
        struct stat sb;
        int res, i, fd;
 
-       name = getenv("KCONFIG_AUTOCONFIG");
-       if (!name)
-               name = "include/config/auto.conf";
+       name = conf_get_autoconfig_name();
        conf_read_simple(name, S_DEF_AUTO);
 
        if (chdir("include/config"))
@@ -669,11 +928,9 @@ out:
 int conf_write_autoconf(void)
 {
        struct symbol *sym;
-       const char *str;
-       char *name;
-       FILE *out, *out_h;
-       time_t now;
-       int i, l;
+       const char *name;
+       FILE *out, *tristate, *out_h;
+       int i;
 
        sym_clear_all_valid();
 
@@ -686,96 +943,57 @@ int conf_write_autoconf(void)
        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;
        }
 
-       sym = sym_lookup("KERNELVERSION", 0);
-       sym_calc_value(sym);
-       time(&now);
-       fprintf(out, "#\n"
-                    "# Automatically generated make config: don't edit\n"
-                    "# firmly.0cpm version: %s\n"
-                    "# %s"
-                    "#\n",
-                    sym_get_string_value(sym), ctime(&now));
-       fprintf(out_h, "/*\n"
-                      " * Automatically generated C config: don't edit\n"
-                      " * firmly.0cpm version: %s\n"
-                      " * %s"
-                      " */\n"
-                      "#define AUTOCONF_INCLUDED\n",
-                      sym_get_string_value(sym), ctime(&now));
+       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);
-               if (!(sym->flags & SYMBOL_WRITE) || !sym->name)
+
+               conf_write_symbol(out_h, sym, &header__enabled_printer_cb, NULL);
+
+               if (!(sym->flags & SYMBOL_WRITE))
                        continue;
-               switch (sym->type) {
-               case S_BOOLEAN:
-               case S_TRISTATE:
-                       switch (sym_get_tristate_value(sym)) {
-                       case no:
-                               break;
-                       case mod:
-                               fprintf(out, "CONFIG_%s=m\n", sym->name);
-                               fprintf(out_h, "#define CONFIG_%s_MODULE 1\n", sym->name);
-                               break;
-                       case yes:
-                               fprintf(out, "CONFIG_%s=y\n", sym->name);
-                               fprintf(out_h, "#define CONFIG_%s 1\n", sym->name);
-                               break;
-                       }
-                       break;
-               case S_STRING:
-                       str = sym_get_string_value(sym);
-                       fprintf(out, "CONFIG_%s=\"", sym->name);
-                       fprintf(out_h, "#define CONFIG_%s \"", sym->name);
-                       while (1) {
-                               l = strcspn(str, "\"\\");
-                               if (l) {
-                                       fwrite(str, l, 1, out);
-                                       fwrite(str, l, 1, out_h);
-                                       str += l;
-                               }
-                               if (!*str)
-                                       break;
-                               fprintf(out, "\\%c", *str);
-                               fprintf(out_h, "\\%c", *str);
-                               str++;
-                       }
-                       fputs("\"\n", out);
-                       fputs("\"\n", out_h);
-                       break;
-               case S_HEX:
-                       str = sym_get_string_value(sym);
-                       if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) {
-                               fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
-                               fprintf(out_h, "#define CONFIG_%s 0x%s\n", sym->name, str);
-                               break;
-                       }
-               case S_INT:
-                       str = sym_get_string_value(sym);
-                       fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
-                       fprintf(out_h, "#define CONFIG_%s %s\n", sym->name, str);
-                       break;
-               default:
-                       break;
-               }
+
+               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/linux/autoconf.h";
+               name = "include/generated/autoconf.h";
        if (rename(".tmpconfig.h", name))
                return 1;
-       name = getenv("KCONFIG_AUTOCONFIG");
+       name = getenv("KCONFIG_TRISTATE");
        if (!name)
-               name = "include/config/auto.conf";
+               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.
@@ -812,3 +1030,126 @@ 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);
+       }
+}
index 579ece4..290ce41 100644 (file)
@@ -7,15 +7,13 @@
 #include <stdlib.h>
 #include <string.h>
 
-#define LKC_DIRECT_LINK
 #include "lkc.h"
 
 #define DEBUG_EXPR     0
 
 struct expr *expr_alloc_symbol(struct symbol *sym)
 {
-       struct expr *e = malloc(sizeof(*e));
-       memset(e, 0, sizeof(*e));
+       struct expr *e = calloc(1, sizeof(*e));
        e->type = E_SYMBOL;
        e->left.sym = sym;
        return e;
@@ -23,8 +21,7 @@ struct expr *expr_alloc_symbol(struct symbol *sym)
 
 struct expr *expr_alloc_one(enum expr_type type, struct expr *ce)
 {
-       struct expr *e = malloc(sizeof(*e));
-       memset(e, 0, sizeof(*e));
+       struct expr *e = calloc(1, sizeof(*e));
        e->type = type;
        e->left.expr = ce;
        return e;
@@ -32,8 +29,7 @@ struct expr *expr_alloc_one(enum expr_type type, struct expr *ce)
 
 struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e2)
 {
-       struct expr *e = malloc(sizeof(*e));
-       memset(e, 0, sizeof(*e));
+       struct expr *e = calloc(1, sizeof(*e));
        e->type = type;
        e->left.expr = e1;
        e->right.expr = e2;
@@ -42,8 +38,7 @@ struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e
 
 struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2)
 {
-       struct expr *e = malloc(sizeof(*e));
-       memset(e, 0, sizeof(*e));
+       struct expr *e = calloc(1, sizeof(*e));
        e->type = type;
        e->left.sym = s1;
        e->right.sym = s2;
@@ -64,7 +59,7 @@ struct expr *expr_alloc_or(struct expr *e1, struct expr *e2)
        return e2 ? expr_alloc_two(E_OR, e1, e2) : e1;
 }
 
-struct expr *expr_copy(struct expr *org)
+struct expr *expr_copy(const struct expr *org)
 {
        struct expr *e;
 
@@ -348,7 +343,7 @@ struct expr *expr_trans_bool(struct expr *e)
 /*
  * e1 || e2 -> ?
  */
-struct expr *expr_join_or(struct expr *e1, struct expr *e2)
+static struct expr *expr_join_or(struct expr *e1, struct expr *e2)
 {
        struct expr *tmp;
        struct symbol *sym1, *sym2;
@@ -412,7 +407,7 @@ struct expr *expr_join_or(struct expr *e1, struct expr *e2)
        return NULL;
 }
 
-struct expr *expr_join_and(struct expr *e1, struct expr *e2)
+static struct expr *expr_join_and(struct expr *e1, struct expr *e2)
 {
        struct expr *tmp;
        struct symbol *sym1, *sym2;
@@ -1013,6 +1008,48 @@ int expr_compare_type(enum expr_type t1, enum expr_type t2)
 #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) {
@@ -1087,7 +1124,7 @@ void expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char *
 
 static void expr_print_file_helper(void *data, struct symbol *sym, const char *str)
 {
-       fwrite(str, strlen(str), 1, data);
+       xfwrite(str, strlen(str), 1, data);
 }
 
 void expr_fprint(struct expr *e, FILE *out)
@@ -1097,7 +1134,32 @@ void expr_fprint(struct expr *e, FILE *out)
 
 static void expr_print_gstr_helper(void *data, struct symbol *sym, const char *str)
 {
-       str_append((struct gstr*)data, 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)
index 9d4cba1..80fce57 100644 (file)
@@ -18,14 +18,10 @@ extern "C" {
 struct file {
        struct file *next;
        struct file *parent;
-       char *name;
+       const char *name;
        int lineno;
-       int flags;
 };
 
-#define FILE_BUSY              0x0001
-#define FILE_SCANNED           0x0002
-
 typedef enum tristate {
        no, mod, yes
 } tristate;
@@ -65,9 +61,13 @@ 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,
+       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 {
@@ -75,51 +75,74 @@ struct symbol {
        char *name;
        enum symbol_type type;
        struct symbol_value curr;
-       struct symbol_value def[4];
+       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 < 257; i++) for (sym = symbol_hash[i]; sym; sym = sym->next) if (sym->type != S_OTHER)
-
-#define SYMBOL_CONST           0x0001
-#define SYMBOL_CHECK           0x0008
-#define SYMBOL_CHOICE          0x0010
-#define SYMBOL_CHOICEVAL       0x0020
-#define SYMBOL_VALID           0x0080
-#define SYMBOL_OPTIONAL                0x0100
-#define SYMBOL_WRITE           0x0200
-#define SYMBOL_CHANGED         0x0400
-#define SYMBOL_AUTO            0x1000
-#define SYMBOL_CHECKED         0x2000
-#define SYMBOL_WARNED          0x8000
-#define SYMBOL_DEF             0x10000
-#define SYMBOL_DEF_USER                0x10000
-#define SYMBOL_DEF_AUTO                0x20000
-#define SYMBOL_DEF3            0x40000
-#define SYMBOL_DEF4            0x80000
+#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                257
-#define SYMBOL_HASHMASK                0xff
-
+#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, P_COMMENT, P_MENU, P_DEFAULT, P_CHOICE,
-       P_SELECT, P_RANGE, P_ENV
+       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;
-       struct symbol *sym;
-       enum prop_type type;
-       const char *text;
+       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;
-       struct menu *menu;
-       struct file *file;
-       int lineno;
+       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) \
@@ -137,6 +160,7 @@ struct menu {
        struct menu *list;
        struct symbol *sym;
        struct property *prompt;
+       struct expr *visibility;
        struct expr *dep;
        unsigned int flags;
        char *help;
@@ -148,8 +172,6 @@ struct menu {
 #define MENU_CHANGED           0x0001
 #define MENU_ROOT              0x0002
 
-#ifndef SWIG
-
 extern struct file *file_list;
 extern struct file *current_file;
 struct file *lookup_file(const char *name);
@@ -164,7 +186,7 @@ struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e
 struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2);
 struct expr *expr_alloc_and(struct expr *e1, struct expr *e2);
 struct expr *expr_alloc_or(struct expr *e1, struct expr *e2);
-struct expr *expr_copy(struct expr *org);
+struct expr *expr_copy(const struct expr *org);
 void expr_free(struct expr *e);
 int expr_eq(struct expr *e1, struct expr *e2);
 void expr_eliminate_eq(struct expr **ep1, struct expr **ep2);
@@ -179,6 +201,7 @@ struct expr *expr_extract_eq_and(struct expr **ep1, struct expr **ep2);
 struct expr *expr_extract_eq_or(struct expr **ep1, struct expr **ep2);
 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 */
@@ -193,7 +216,6 @@ static inline int expr_is_no(struct expr *e)
 {
        return e && (e->type == E_SYMBOL && e->left.sym == &symbol_no);
 }
-#endif
 
 #ifdef __cplusplus
 }
index f00ef41..9f44380 100644 (file)
@@ -30,13 +30,16 @@ 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 show_all = FALSE;
-static gboolean show_debug = FALSE;
 static gboolean resizeable = FALSE;
+static int opt_mode = OPT_NORMAL;
 
 GtkWidget *main_wnd = NULL;
 GtkWidget *tree1_w = NULL;     // left  frame
@@ -76,36 +79,7 @@ static void conf_changed(void);
 
 /* Helping/Debugging Functions */
 
-
-const char *dbg_print_stype(int val)
-{
-       static char buf[256];
-
-       bzero(buf, 256);
-
-       if (val == S_UNKNOWN)
-               strcpy(buf, "unknown");
-       if (val == S_BOOLEAN)
-               strcpy(buf, "boolean");
-       if (val == S_TRISTATE)
-               strcpy(buf, "tristate");
-       if (val == S_INT)
-               strcpy(buf, "int");
-       if (val == S_HEX)
-               strcpy(buf, "hex");
-       if (val == S_STRING)
-               strcpy(buf, "string");
-       if (val == S_OTHER)
-               strcpy(buf, "other");
-
-#ifdef DEBUG
-       printf("%s", buf);
-#endif
-
-       return buf;
-}
-
-const char *dbg_print_flags(int val)
+const char *dbg_sym_flags(int val)
 {
        static char buf[256];
 
@@ -131,40 +105,10 @@ const char *dbg_print_flags(int val)
                strcat(buf, "auto/");
 
        buf[strlen(buf) - 1] = '\0';
-#ifdef DEBUG
-       printf("%s", buf);
-#endif
 
        return buf;
 }
 
-const char *dbg_print_ptype(int val)
-{
-       static char buf[256];
-
-       bzero(buf, 256);
-
-       if (val == P_UNKNOWN)
-               strcpy(buf, "unknown");
-       if (val == P_PROMPT)
-               strcpy(buf, "prompt");
-       if (val == P_COMMENT)
-               strcpy(buf, "comment");
-       if (val == P_MENU)
-               strcpy(buf, "menu");
-       if (val == P_DEFAULT)
-               strcpy(buf, "default");
-       if (val == P_CHOICE)
-               strcpy(buf, "choice");
-
-#ifdef DEBUG
-       printf("%s", buf);
-#endif
-
-       return buf;
-}
-
-
 void replace_button_icon(GladeXML * xml, GdkDrawable * window,
                         GtkStyle * style, gchar * btn_name, gchar ** xpm)
 {
@@ -189,7 +133,6 @@ void init_main_window(const gchar * glade_file)
        GladeXML *xml;
        GtkWidget *widget;
        GtkTextBuffer *txtbuf;
-       char title[256];
        GtkStyle *style;
 
        xml = glade_xml_new(glade_file, "window1", NULL);
@@ -266,9 +209,7 @@ void init_main_window(const gchar * glade_file)
                                          /*"style", PANGO_STYLE_OBLIQUE, */
                                          NULL);
 
-       sprintf(title, _("firmly.0cpm v%s Configuration"),
-               getenv("KERNELVERSION"));
-       gtk_window_set_title(GTK_WINDOW(main_wnd), title);
+       gtk_window_set_title(GTK_WINDOW(main_wnd), rootmenu.prompt->text);
 
        gtk_widget_show(main_wnd);
 }
@@ -312,7 +253,7 @@ void init_left_tree(void)
 
        gtk_tree_view_set_model(view, model1);
        gtk_tree_view_set_headers_visible(view, TRUE);
-       gtk_tree_view_set_rules_hint(view, FALSE);
+       gtk_tree_view_set_rules_hint(view, TRUE);
 
        column = gtk_tree_view_column_new();
        gtk_tree_view_append_column(view, column);
@@ -344,8 +285,6 @@ void init_left_tree(void)
 static void renderer_edited(GtkCellRendererText * cell,
                            const gchar * path_string,
                            const gchar * new_text, gpointer user_data);
-static void renderer_toggled(GtkCellRendererToggle * cellrenderertoggle,
-                            gchar * arg1, gpointer user_data);
 
 void init_right_tree(void)
 {
@@ -357,7 +296,7 @@ void init_right_tree(void)
 
        gtk_tree_view_set_model(view, model2);
        gtk_tree_view_set_headers_visible(view, TRUE);
-       gtk_tree_view_set_rules_hint(view, FALSE);
+       gtk_tree_view_set_rules_hint(view, TRUE);
 
        column = gtk_tree_view_column_new();
        gtk_tree_view_append_column(view, column);
@@ -379,8 +318,6 @@ void init_right_tree(void)
                                            "inconsistent", COL_BTNINC,
                                            "visible", COL_BTNVIS,
                                            "radio", COL_BTNRAD, NULL);
-       /*g_signal_connect(G_OBJECT(renderer), "toggled",
-          G_CALLBACK(renderer_toggled), NULL); */
        renderer = gtk_cell_renderer_text_new();
        gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
                                        renderer, FALSE);
@@ -456,19 +393,9 @@ static void text_insert_help(struct menu *menu)
        GtkTextBuffer *buffer;
        GtkTextIter start, end;
        const char *prompt = _(menu_get_prompt(menu));
-       gchar *name;
-       const char *help;
-
-       help = menu_get_help(menu);
+       struct gstr help = str_new();
 
-       /* Gettextize if the help text not empty */
-       if ((help != 0) && (help[0] != 0))
-               help = _(help);
-
-       if (menu->sym && menu->sym->name)
-               name = g_strdup_printf(menu->sym->name);
-       else
-               name = g_strdup("");
+       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);
@@ -478,14 +405,11 @@ static void text_insert_help(struct menu *menu)
        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, " ", 1);
-       gtk_text_buffer_get_end_iter(buffer, &end);
-       gtk_text_buffer_insert_with_tags(buffer, &end, name, -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, help, -1, tag2,
+       gtk_text_buffer_insert_with_tags(buffer, &end, str_get(&help), -1, tag2,
                                         NULL);
+       str_free(&help);
 }
 
 
@@ -710,20 +634,29 @@ void on_show_data1_activate(GtkMenuItem * menuitem, gpointer user_data)
 
 
 void
-on_show_all_options1_activate(GtkMenuItem * menuitem, gpointer user_data)
+on_set_option_mode1_activate(GtkMenuItem *menuitem, gpointer user_data)
 {
-       show_all = GTK_CHECK_MENU_ITEM(menuitem)->active;
+       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
+       display_tree(&rootmenu);        /* instead of update_tree to speed-up */
 }
 
 
 void
-on_show_debug_info1_activate(GtkMenuItem * menuitem, gpointer user_data)
+on_set_option_mode3_activate(GtkMenuItem *menuitem, gpointer user_data)
 {
-       show_debug = GTK_CHECK_MENU_ITEM(menuitem)->active;
-       update_tree(&rootmenu, NULL);
+       opt_mode = OPT_PROMPT;
+       gtk_tree_store_clear(tree2);
+       display_tree(&rootmenu);        /* instead of update_tree to speed-up */
 }
 
 
@@ -731,8 +664,7 @@ void on_introduction1_activate(GtkMenuItem * menuitem, gpointer user_data)
 {
        GtkWidget *dialog;
        const gchar *intro_text = _(
-           "Welcome to gkc, the GTK+ graphical kernel configuration tool\n"
-           "for firmly.0cpm.\n"
+           "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"
@@ -820,7 +752,6 @@ void on_load_clicked(GtkButton * button, gpointer user_data)
 void on_single_clicked(GtkButton * button, gpointer user_data)
 {
        view_mode = SINGLE_VIEW;
-       gtk_paned_set_position(GTK_PANED(hpaned), 0);
        gtk_widget_hide(tree1_w);
        current = &rootmenu;
        display_tree_part();
@@ -846,7 +777,6 @@ void on_split_clicked(GtkButton * button, gpointer user_data)
 void on_full_clicked(GtkButton * button, gpointer user_data)
 {
        view_mode = FULL_VIEW;
-       gtk_paned_set_position(GTK_PANED(hpaned), 0);
        gtk_widget_hide(tree1_w);
        if (tree2)
                gtk_tree_store_clear(tree2);
@@ -954,35 +884,6 @@ static void toggle_sym_value(struct menu *menu)
                display_tree_part();    //fixme: keep exp/coll
 }
 
-static void renderer_toggled(GtkCellRendererToggle * cell,
-                            gchar * path_string, gpointer user_data)
-{
-       GtkTreePath *path, *sel_path = NULL;
-       GtkTreeIter iter, sel_iter;
-       GtkTreeSelection *sel;
-       struct menu *menu;
-
-       path = gtk_tree_path_new_from_string(path_string);
-       if (!gtk_tree_model_get_iter(model2, &iter, path))
-               return;
-
-       sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree2_w));
-       if (gtk_tree_selection_get_selected(sel, NULL, &sel_iter))
-               sel_path = gtk_tree_model_get_path(model2, &sel_iter);
-       if (!sel_path)
-               goto out1;
-       if (gtk_tree_path_compare(path, sel_path))
-               goto out2;
-
-       gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
-       toggle_sym_value(menu);
-
-      out2:
-       gtk_tree_path_free(sel_path);
-      out1:
-       gtk_tree_path_free(path);
-}
-
 static gint column2index(GtkTreeViewColumn * column)
 {
        gint i;
@@ -1174,9 +1075,12 @@ static gchar **fill_row(struct menu *menu)
 
        row[COL_OPTION] =
            g_strdup_printf("%s %s", _(menu_get_prompt(menu)),
-                           sym && sym_has_value(sym) ? "(NEW)" : "");
+                           sym && !sym_has_value(sym) ? "(NEW)" : "");
 
-       if (show_all && !menu_is_visible(menu))
+       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");
@@ -1235,6 +1139,7 @@ static gchar **fill_row(struct menu *menu)
                        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) {
@@ -1399,16 +1304,20 @@ static void update_tree(struct menu *src, GtkTreeIter * dst)
                       menu2 ? menu_get_prompt(menu2) : "nil");
 #endif
 
-               if (!menu_is_visible(child1) && !show_all) {    // remove node
+               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
+                                       return;         /* next parent */
                                else
-                                       goto reparse;   // next child
+                                       goto reparse;   /* next child */
                        } else
                                continue;
                }
@@ -1477,17 +1386,19 @@ static void display_tree(struct menu *menu)
                    && (tree == tree2))
                        continue;
 
-               if (menu_is_visible(child) || show_all)
+               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 | " : "");
-               dbg_print_ptype(ptype);
+               printf("%s", prop_get_type_name(ptype));
                printf(" | ");
                if (sym) {
-                       dbg_print_stype(sym->type);
+                       printf("%s", sym_type_name(sym->type));
                        printf(" | ");
-                       dbg_print_flags(sym->flags);
+                       printf("%s", dbg_sym_flags(sym->flags));
                        printf("\n");
                } else
                        printf("\n");
@@ -1499,6 +1410,12 @@ static void display_tree(struct menu *menu)
                 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)) {
@@ -1557,10 +1474,6 @@ int main(int ac, char *av[])
        char *env;
        gchar *glade_file;
 
-#ifndef LKC_DIRECT_LINK
-       kconfig_load();
-#endif
-
        bindtextdomain(PACKAGE, LOCALEDIR);
        bind_textdomain_codeset(PACKAGE, "UTF-8");
        textdomain(PACKAGE);
@@ -1582,12 +1495,6 @@ int main(int ac, char *av[])
        else
                glade_file = g_strconcat(g_get_current_dir(), "/", av[0], ".glade", NULL);
 
-       /* Load the interface and connect signals */
-       init_main_window(glade_file);
-       init_tree_model();
-       init_left_tree();
-       init_right_tree();
-
        /* Conf stuffs */
        if (ac > 1 && av[1][0] == '-') {
                switch (av[1][1]) {
@@ -1607,6 +1514,12 @@ int main(int ac, char *av[])
        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();
diff --git a/bin/kconfig/kconfig-language.txt b/bin/kconfig/kconfig-language.txt
new file mode 100644 (file)
index 0000000..44e2649
--- /dev/null
@@ -0,0 +1,413 @@
+Introduction
+------------
+
+The configuration database is a collection of configuration options
+organized in a tree structure:
+
+       +- Code maturity level options
+       |  +- Prompt for development and/or incomplete code/drivers
+       +- General setup
+       |  +- Networking support
+       |  +- System V IPC
+       |  +- BSD Process Accounting
+       |  +- Sysctl support
+       +- Loadable module support
+       |  +- Enable loadable module support
+       |     +- Set version information on all module symbols
+       |     +- Kernel module loader
+       +- ...
+
+Every entry has its own dependencies. These dependencies are used
+to determine the visibility of an entry. Any child entry is only
+visible if its parent entry is also visible.
+
+Menu entries
+------------
+
+Most entries define a config option; all other entries help to organize
+them. A single configuration option is defined like this:
+
+config MODVERSIONS
+       bool "Set version information on all module symbols"
+       depends on MODULES
+       help
+         Usually, modules have to be recompiled whenever you switch to a new
+         kernel.  ...
+
+Every line starts with a key word and can be followed by multiple
+arguments.  "config" starts a new config entry. The following lines
+define attributes for this config option. Attributes can be the type of
+the config option, input prompt, dependencies, help text and default
+values. A config option can be defined multiple times with the same
+name, but every definition can have only a single input prompt and the
+type must not conflict.
+
+Menu attributes
+---------------
+
+A menu entry can have a number of attributes. Not all of them are
+applicable everywhere (see syntax).
+
+- type definition: "bool"/"tristate"/"string"/"hex"/"int"
+  Every config option must have a type. There are only two basic types:
+  tristate and string; the other types are based on these two. The type
+  definition optionally accepts an input prompt, so these two examples
+  are equivalent:
+
+       bool "Networking support"
+  and
+       bool
+       prompt "Networking support"
+
+- input prompt: "prompt" <prompt> ["if" <expr>]
+  Every menu entry can have at most one prompt, which is used to display
+  to the user. Optionally dependencies only for this prompt can be added
+  with "if".
+
+- default value: "default" <expr> ["if" <expr>]
+  A config option can have any number of default values. If multiple
+  default values are visible, only the first defined one is active.
+  Default values are not limited to the menu entry where they are
+  defined. This means the default can be defined somewhere else or be
+  overridden by an earlier definition.
+  The default value is only assigned to the config symbol if no other
+  value was set by the user (via the input prompt above). If an input
+  prompt is visible the default value is presented to the user and can
+  be overridden by him.
+  Optionally, dependencies only for this default value can be added with
+  "if".
+
+- type definition + default value:
+       "def_bool"/"def_tristate" <expr> ["if" <expr>]
+  This is a shorthand notation for a type definition plus a value.
+  Optionally dependencies for this default value can be added with "if".
+
+- dependencies: "depends on" <expr>
+  This defines a dependency for this menu entry. If multiple
+  dependencies are defined, they are connected with '&&'. Dependencies
+  are applied to all other options within this menu entry (which also
+  accept an "if" expression), so these two examples are equivalent:
+
+       bool "foo" if BAR
+       default y if BAR
+  and
+       depends on BAR
+       bool "foo"
+       default y
+
+- reverse dependencies: "select" <symbol> ["if" <expr>]
+  While normal dependencies reduce the upper limit of a symbol (see
+  below), reverse dependencies can be used to force a lower limit of
+  another symbol. The value of the current menu symbol is used as the
+  minimal value <symbol> can be set to. If <symbol> is selected multiple
+  times, the limit is set to the largest selection.
+  Reverse dependencies can only be used with boolean or tristate
+  symbols.
+  Note:
+       select should be used with care. select will force
+       a symbol to a value without visiting the dependencies.
+       By abusing select you are able to select a symbol FOO even
+       if FOO depends on BAR that is not set.
+       In general use select only for non-visible symbols
+       (no prompts anywhere) and for symbols with no dependencies.
+       That will limit the usefulness but on the other hand avoid
+       the illegal configurations all over.
+
+- limiting menu display: "visible if" <expr>
+  This attribute is only applicable to menu blocks, if the condition is
+  false, the menu block is not displayed to the user (the symbols
+  contained there can still be selected by other symbols, though). It is
+  similar to a conditional "prompt" attribude for individual menu
+  entries. Default value of "visible" is true.
+
+- numerical ranges: "range" <symbol> <symbol> ["if" <expr>]
+  This allows to limit the range of possible input values for int
+  and hex symbols. The user can only input a value which is larger than
+  or equal to the first symbol and smaller than or equal to the second
+  symbol.
+
+- help text: "help" or "---help---"
+  This defines a help text. The end of the help text is determined by
+  the indentation level, this means it ends at the first line which has
+  a smaller indentation than the first line of the help text.
+  "---help---" and "help" do not differ in behaviour, "---help---" is
+  used to help visually separate configuration logic from help within
+  the file as an aid to developers.
+
+- misc options: "option" <symbol>[=<value>]
+  Various less common options can be defined via this option syntax,
+  which can modify the behaviour of the menu entry and its config
+  symbol. These options are currently possible:
+
+  - "defconfig_list"
+    This declares a list of default entries which can be used when
+    looking for the default configuration (which is used when the main
+    .config doesn't exists yet.)
+
+  - "modules"
+    This declares the symbol to be used as the MODULES symbol, which
+    enables the third modular state for all config symbols.
+
+  - "env"=<value>
+    This imports the environment variable into Kconfig. It behaves like
+    a default, except that the value comes from the environment, this
+    also means that the behaviour when mixing it with normal defaults is
+    undefined at this point. The symbol is currently not exported back
+    to the build environment (if this is desired, it can be done via
+    another symbol).
+
+Menu dependencies
+-----------------
+
+Dependencies define the visibility of a menu entry and can also reduce
+the input range of tristate symbols. The tristate logic used in the
+expressions uses one more state than normal boolean logic to express the
+module state. Dependency expressions have the following syntax:
+
+<expr> ::= <symbol>                             (1)
+           <symbol> '=' <symbol>                (2)
+           <symbol> '!=' <symbol>               (3)
+           '(' <expr> ')'                       (4)
+           '!' <expr>                           (5)
+           <expr> '&&' <expr>                   (6)
+           <expr> '||' <expr>                   (7)
+
+Expressions are listed in decreasing order of precedence. 
+
+(1) Convert the symbol into an expression. Boolean and tristate symbols
+    are simply converted into the respective expression values. All
+    other symbol types result in 'n'.
+(2) If the values of both symbols are equal, it returns 'y',
+    otherwise 'n'.
+(3) If the values of both symbols are equal, it returns 'n',
+    otherwise 'y'.
+(4) Returns the value of the expression. Used to override precedence.
+(5) Returns the result of (2-/expr/).
+(6) Returns the result of min(/expr/, /expr/).
+(7) Returns the result of max(/expr/, /expr/).
+
+An expression can have a value of 'n', 'm' or 'y' (or 0, 1, 2
+respectively for calculations). A menu entry becomes visible when its
+expression evaluates to 'm' or 'y'.
+
+There are two types of symbols: constant and non-constant symbols.
+Non-constant symbols are the most common ones and are defined with the
+'config' statement. Non-constant symbols consist entirely of alphanumeric
+characters or underscores.
+Constant symbols are only part of expressions. Constant symbols are
+always surrounded by single or double quotes. Within the quote, any
+other character is allowed and the quotes can be escaped using '\'.
+
+Menu structure
+--------------
+
+The position of a menu entry in the tree is determined in two ways. First
+it can be specified explicitly:
+
+menu "Network device support"
+       depends on NET
+
+config NETDEVICES
+       ...
+
+endmenu
+
+All entries within the "menu" ... "endmenu" block become a submenu of
+"Network device support". All subentries inherit the dependencies from
+the menu entry, e.g. this means the dependency "NET" is added to the
+dependency list of the config option NETDEVICES.
+
+The other way to generate the menu structure is done by analyzing the
+dependencies. If a menu entry somehow depends on the previous entry, it
+can be made a submenu of it. First, the previous (parent) symbol must
+be part of the dependency list and then one of these two conditions
+must be true:
+- the child entry must become invisible, if the parent is set to 'n'
+- the child entry must only be visible, if the parent is visible
+
+config MODULES
+       bool "Enable loadable module support"
+
+config MODVERSIONS
+       bool "Set version information on all module symbols"
+       depends on MODULES
+
+comment "module support disabled"
+       depends on !MODULES
+
+MODVERSIONS directly depends on MODULES, this means it's only visible if
+MODULES is different from 'n'. The comment on the other hand is always
+visible when MODULES is visible (the (empty) dependency of MODULES is
+also part of the comment dependencies).
+
+
+Kconfig syntax
+--------------
+
+The configuration file describes a series of menu entries, where every
+line starts with a keyword (except help texts). The following keywords
+end a menu entry:
+- config
+- menuconfig
+- choice/endchoice
+- comment
+- menu/endmenu
+- if/endif
+- source
+The first five also start the definition of a menu entry.
+
+config:
+
+       "config" <symbol>
+       <config options>
+
+This defines a config symbol <symbol> and accepts any of above
+attributes as options.
+
+menuconfig:
+       "menuconfig" <symbol>
+       <config options>
+
+This is similar to the simple config entry above, but it also gives a
+hint to front ends, that all suboptions should be displayed as a
+separate list of options.
+
+choices:
+
+       "choice" [symbol]
+       <choice options>
+       <choice block>
+       "endchoice"
+
+This defines a choice group and accepts any of the above attributes as
+options. A choice can only be of type bool or tristate, while a boolean
+choice only allows a single config entry to be selected, a tristate
+choice also allows any number of config entries to be set to 'm'. This
+can be used if multiple drivers for a single hardware exists and only a
+single driver can be compiled/loaded into the kernel, but all drivers
+can be compiled as modules.
+A choice accepts another option "optional", which allows to set the
+choice to 'n' and no entry needs to be selected.
+If no [symbol] is associated with a choice, then you can not have multiple
+definitions of that choice. If a [symbol] is associated to the choice,
+then you may define the same choice (ie. with the same entries) in another
+place.
+
+comment:
+
+       "comment" <prompt>
+       <comment options>
+
+This defines a comment which is displayed to the user during the
+configuration process and is also echoed to the output files. The only
+possible options are dependencies.
+
+menu:
+
+       "menu" <prompt>
+       <menu options>
+       <menu block>
+       "endmenu"
+
+This defines a menu block, see "Menu structure" above for more
+information. The only possible options are dependencies and "visible"
+attributes.
+
+if:
+
+       "if" <expr>
+       <if block>
+       "endif"
+
+This defines an if block. The dependency expression <expr> is appended
+to all enclosed menu entries.
+
+source:
+
+       "source" <prompt>
+
+This reads the specified configuration file. This file is always parsed.
+
+mainmenu:
+
+       "mainmenu" <prompt>
+
+This sets the config program's title bar if the config program chooses
+to use it. It should be placed at the top of the configuration, before any
+other statement.
+
+
+Kconfig hints
+-------------
+This is a collection of Kconfig tips, most of which aren't obvious at
+first glance and most of which have become idioms in several Kconfig
+files.
+
+Adding common features and make the usage configurable
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+It is a common idiom to implement a feature/functionality that are
+relevant for some architectures but not all.
+The recommended way to do so is to use a config variable named HAVE_*
+that is defined in a common Kconfig file and selected by the relevant
+architectures.
+An example is the generic IOMAP functionality.
+
+We would in lib/Kconfig see:
+
+# Generic IOMAP is used to ...
+config HAVE_GENERIC_IOMAP
+
+config GENERIC_IOMAP
+       depends on HAVE_GENERIC_IOMAP && FOO
+
+And in lib/Makefile we would see:
+obj-$(CONFIG_GENERIC_IOMAP) += iomap.o
+
+For each architecture using the generic IOMAP functionality we would see:
+
+config X86
+       select ...
+       select HAVE_GENERIC_IOMAP
+       select ...
+
+Note: we use the existing config option and avoid creating a new
+config variable to select HAVE_GENERIC_IOMAP.
+
+Note: the use of the internal config variable HAVE_GENERIC_IOMAP, it is
+introduced to overcome the limitation of select which will force a
+config option to 'y' no matter the dependencies.
+The dependencies are moved to the symbol GENERIC_IOMAP and we avoid the
+situation where select forces a symbol equals to 'y'.
+
+Build as module only
+~~~~~~~~~~~~~~~~~~~~
+To restrict a component build to module-only, qualify its config symbol
+with "depends on m".  E.g.:
+
+config FOO
+       depends on BAR && m
+
+limits FOO to module (=m) or disabled (=n).
+
+Kconfig symbol existence
+~~~~~~~~~~~~~~~~~~~~~~~~
+The following two methods produce the same kconfig symbol dependencies
+but differ greatly in kconfig symbol existence (production) in the
+generated config file.
+
+case 1:
+
+config FOO
+       tristate "about foo"
+       depends on BAR
+
+vs. case 2:
+
+if BAR
+config FOO
+       tristate "about foo"
+endif
+
+In case 1, the symbol FOO will always exist in the config file (given
+no other dependencies).  In case 2, the symbol FOO will only exist in
+the config file if BAR is enabled.
index 6eb72a7..2858738 100644 (file)
@@ -7,7 +7,6 @@
 #include <stdlib.h>
 #include <string.h>
 
-#define LKC_DIRECT_LINK
 #include "lkc.h"
 
 static char *escape(const char* text, char *bf, int len)
@@ -43,6 +42,10 @@ static char *escape(const char* text, char *bf, int len)
                        ++text;
                        goto next;
                }
+               else if (*text == '\\') {
+                       *bfp++ = '\\';
+                       len--;
+               }
                *bfp++ = *text++;
 next:
                --len;
@@ -59,11 +62,11 @@ next:
 
 struct file_line {
        struct file_line *next;
-       char*            file;
-       int              lineno;
+       const char *file;
+       int lineno;
 };
 
-static struct file_line *file_line__new(char *file, int lineno)
+static struct file_line *file_line__new(const char *file, int lineno)
 {
        struct file_line *self = malloc(sizeof(*self));
 
@@ -86,7 +89,8 @@ struct message {
 
 static struct message *message__list;
 
-static struct message *message__new(const char *msg, char *option, char *file, int lineno)
+static struct message *message__new(const char *msg, char *option,
+                                   const char *file, int lineno)
 {
        struct message *self = malloc(sizeof(*self));
 
@@ -126,7 +130,8 @@ static struct message *mesage__find(const char *msg)
        return m;
 }
 
-static int message__add_file_line(struct message *self, char *file, int lineno)
+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);
@@ -141,7 +146,8 @@ out:
        return rc;
 }
 
-static int message__add(const char *msg, char *option, char *file, int lineno)
+static int message__add(const char *msg, char *option, const char *file,
+                       int lineno)
 {
        int rc = 0;
        char bf[16384];
@@ -162,7 +168,7 @@ static int message__add(const char *msg, char *option, char *file, int lineno)
        return rc;
 }
 
-void menu_build_message_list(struct menu *menu)
+static void menu_build_message_list(struct menu *menu)
 {
        struct menu *child;
 
@@ -207,7 +213,7 @@ static void message__print_gettext_msgid_msgstr(struct message *self)
               "msgstr \"\"\n", self->msg);
 }
 
-void menu__xgettext(void)
+static void menu__xgettext(void)
 {
        struct message *m = message__list;
 
index 96521cb..b633bdb 100644 (file)
 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
 
-#ifdef LKC_DIRECT_LINK
 #define P(name,type,arg)       extern type name arg
-#else
-#include "lkc_defs.h"
-#define P(name,type,arg)       extern type (*name ## _p) arg
-#endif
 #include "lkc_proto.h"
 #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
@@ -53,34 +63,46 @@ struct kconf_id {
        enum symbol_type stype;
 };
 
+extern int zconfdebug;
+
 int zconfparse(void);
 void zconfdump(FILE *out);
-
-extern int zconfdebug;
 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);
-char *zconf_curname(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);
 
-/* kconfig_load.c */
-void kconfig_load(void);
+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)
+{
+       if (fwrite(str, len, count, out) < count)
+               fprintf(stderr, "\nError in writing or end of file.\n");
+}
 
 /* menu.c */
-void menu_init(void);
+void _menu_init(void);
 void menu_warn(struct menu *menu, const char *fmt, ...);
 struct menu *menu_add_menu(void);
 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);
@@ -96,6 +118,11 @@ 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);
@@ -111,6 +138,8 @@ 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);
index 8e69461..72e275a 100644 (file)
@@ -1,28 +1,37 @@
+#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_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]);
+//RvR// 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));
index 598ce2c..19e200d 100644 (file)
 #include <stdarg.h>
 #include <stdlib.h>
 #include <string.h>
+#include <signal.h>
 #include <unistd.h>
 #include <locale.h>
 
-#define LKC_DIRECT_LINK
 #include "lkc.h"
 #include "lxdialog/dialog.h"
 
 static const char mconf_readme[] = N_(
 "Overview\n"
 "--------\n"
-"Some kernel features may be built directly into the kernel.\n"
-"Some may be made into loadable runtime modules.  Some features\n"
-"may be completely removed altogether.  There are also certain\n"
-"kernel parameters which are not really features, but must be\n"
-"entered in as decimal or hexadecimal numbers or possibly text.\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"
@@ -67,13 +65,15 @@ static const char mconf_readme[] = 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"
+"   <Exit> and <Help>.\n"
 "\n"
 "o  To get help with an item, use the cursor keys to highlight <Help>\n"
-"   and Press <ENTER>.\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"
@@ -115,7 +115,7 @@ static const char mconf_readme[] = 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 kernel configurations.\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"
@@ -148,9 +148,9 @@ static const char mconf_readme[] = N_(
 "\n"
 "Optional personality available\n"
 "------------------------------\n"
-"If you prefer to have all of the kernel options listed in a single\n"
-"menu, rather than the default multimenu hierarchy, run the menuconfig\n"
-"with MENUCONFIG_MODE environment variable set to single_menu. Example:\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"
@@ -199,30 +199,28 @@ inputbox_instructions_string[] = N_(
 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."),
-nohelp_text[] = N_(
-       "There is no help available for this kernel option.\n"),
 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 kernel\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"
-       "kernel's default, entering the name of the file here will allow you\n"
-       "to modify that configuration.\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"),
+       "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 kernel\n"
-       "configurations available on a single machine.\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"
@@ -232,7 +230,7 @@ save_config_help[] = N_(
        "leave this blank.\n"),
 search_help[] = N_(
        "\n"
-       "Search for CONFIG_ symbols and display their relations.\n"
+       "Search for symbols and display their relations.\n"
        "Regular expressions are allowed.\n"
        "Example: search for \"^FOO\"\n"
        "Result:\n"
@@ -249,7 +247,7 @@ search_help[] = N_(
        "Selected by: BAR\n"
        "-----------------------------------------------------------------\n"
        "o The line 'Prompt:' shows the text used in the menu structure for\n"
-       "  this CONFIG_ symbol\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"
@@ -265,15 +263,17 @@ search_help[] = N_(
        "Only relevant lines are shown.\n"
        "\n\n"
        "Search examples:\n"
-       "Examples: USB  => find all CONFIG_ symbols containing USB\n"
-       "          ^USB => find all CONFIG_ symbols starting with USB\n"
-       "          USB$ => find all CONFIG_ symbols ending with USB\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);
@@ -284,91 +284,14 @@ 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 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");
-               }
-       }
-}
-
-static 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));
-       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");
-}
-
-static 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;
-}
-
 static char filename[PATH_MAX+1];
 static void set_config_filename(const char *config_filename)
 {
        static char menu_backtitle[PATH_MAX+128];
        int size;
-       struct symbol *sym;
 
-       sym = sym_lookup("KERNELVERSION", 0);
-       sym_calc_value(sym);
        size = snprintf(menu_backtitle, sizeof(menu_backtitle),
-                       _("%s - firmly.0cpm v%s Configuration"),
-                       config_filename, sym_get_string_value(sym));
+                       "%s - %s", config_filename, rootmenu.prompt->text);
        if (size >= sizeof(menu_backtitle))
                menu_backtitle[sizeof(menu_backtitle)-1] = '\0';
        set_dialog_backtitle(menu_backtitle);
@@ -388,8 +311,8 @@ static void search_conf(void)
 again:
        dialog_clear();
        dres = dialog_inputbox(_("Search Configuration Parameter"),
-                             _("Enter CONFIG_ (sub)string to search for "
-                               "(with or without \"CONFIG\")"),
+                             _("Enter " CONFIG_ " (sub)string to search for "
+                               "(with or without \"" CONFIG_ "\")"),
                              10, 75, "");
        switch (dres) {
        case 0:
@@ -401,10 +324,10 @@ again:
                return;
        }
 
-       /* strip CONFIG_ if necessary */
+       /* strip the prefix if necessary */
        dialog_input = dialog_input_result;
-       if (strncasecmp(dialog_input_result, "CONFIG_", 7) == 0)
-               dialog_input += 7;
+       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);
@@ -421,8 +344,16 @@ static void build_conf(struct menu *menu)
        int type, tmp, doint = 2;
        tristate val;
        char ch;
-
-       if (!menu_is_visible(menu))
+       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;
@@ -681,6 +612,9 @@ static void conf(struct menu *menu)
                case 7:
                        search_conf();
                        break;
+               case 8:
+                       show_all_options = !show_all_options;
+                       break;
                }
        }
 }
@@ -699,19 +633,10 @@ static void show_helptext(const char *title, const char *text)
 static void show_help(struct menu *menu)
 {
        struct gstr help = str_new();
-       struct symbol *sym = menu->sym;
-
-       if (menu_has_help(menu))
-       {
-               if (sym->name) {
-                       str_printf(&help, "CONFIG_%s:\n\n", sym->name);
-                       str_append(&help, _(menu_get_help(menu)));
-                       str_append(&help, "\n");
-               }
-       } else {
-               str_append(&help, nohelp_text);
-       }
-       get_symbol_str(&help, sym);
+
+       help.max_width = getmaxx(stdscr) - 10;
+       menu_get_ext_help(menu, &help);
+
        show_helptext(_(menu_get_prompt(menu)), str_get(&help));
        str_free(&help);
 }
@@ -732,7 +657,12 @@ static void conf_choice(struct menu *menu)
                for (child = menu->list; child; child = child->next) {
                        if (!menu_is_visible(child))
                                continue;
-                       item_make("%s", _(menu_get_prompt(child)));
+                       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);
@@ -748,6 +678,9 @@ static void conf_choice(struct menu *menu)
                case 0:
                        if (selected) {
                                child = item_data();
+                               if (!child->sym)
+                                       break;
+
                                sym_set_tristate_value(child->sym, yes);
                        }
                        return;
@@ -861,9 +794,54 @@ static void conf_save(void)
        }
 }
 
+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"));
+       }
+
+       return res;
+}
+
+static void sig_handler(int signo)
+{
+       exit(handle_exit());
+}
+
 int main(int ac, char **av)
 {
-       int saved_x, saved_y;
        char *mode;
        int res;
 
@@ -871,6 +849,8 @@ int main(int ac, char **av)
        bindtextdomain(PACKAGE, LOCALEDIR);
        textdomain(PACKAGE);
 
+       signal(SIGINT, sig_handler);
+
        conf_parse(av[1]);
        conf_read(NULL);
 
@@ -880,6 +860,8 @@ int main(int ac, char **av)
                        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"));
@@ -890,39 +872,9 @@ int main(int ac, char **av)
        set_config_filename(conf_get_configname());
        do {
                conf(&rootmenu);
-               dialog_clear();
-               if (conf_get_changed())
-                       res = dialog_yesno(NULL,
-                                          _("Do you wish to save your "
-                                            "new kernel configuration?\n"
-                                            "<ESC><ESC> to continue."),
-                                          6, 60);
-               else
-                       res = -1;
+               res = handle_exit();
        } while (res == KEY_ESC);
-       end_dialog(saved_x, saved_y);
-
-       switch (res) {
-       case 0:
-               if (conf_write(filename)) {
-                       fprintf(stderr, _("\n\n"
-                               "Error during writing of the kernel configuration.\n"
-                               "Your kernel configuration changes were NOT saved."
-                               "\n\n"));
-                       return 1;
-               }
-       case -1:
-               printf(_("\n\n"
-                       "*** End of firmly.0cpm configuration.\n"
-                       "*** Execute 'make' to build the kernel or try 'make help'."
-                       "\n\n"));
-               break;
-       default:
-               fprintf(stderr, _("\n\n"
-                       "Your kernel configuration changes were NOT saved."
-                       "\n\n"));
-       }
 
-       return 0;
+       return res;
 }
 
index 07ff8d1..8c2a97e 100644 (file)
@@ -3,12 +3,15 @@
  * Released under the terms of the GNU GPL v2.0.
  */
 
+#include <ctype.h>
+#include <stdarg.h>
 #include <stdlib.h>
 #include <string.h>
 
-#define LKC_DIRECT_LINK
 #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;
 
@@ -35,7 +38,7 @@ static void prop_warn(struct property *prop, const char *fmt, ...)
        va_end(ap);
 }
 
-void menu_init(void)
+void _menu_init(void)
 {
        current_entry = current_menu = &rootmenu;
        last_entry_ptr = &rootmenu.list;
@@ -55,6 +58,8 @@ void menu_add_entry(struct symbol *sym)
        *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)
@@ -74,7 +79,7 @@ void menu_end_menu(void)
        current_menu = current_menu->parent;
 }
 
-struct expr *menu_check_dep(struct expr *e)
+static struct expr *menu_check_dep(struct expr *e)
 {
        if (!e)
                return e;
@@ -133,8 +138,22 @@ struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *e
                        while (isspace(*prompt))
                                prompt++;
                }
-               if (current_entry->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;
@@ -147,6 +166,12 @@ struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr
        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);
@@ -178,13 +203,13 @@ void menu_add_option(int token, char *arg)
        }
 }
 
-static int menu_range_valid_sym(struct symbol *sym, struct symbol *sym2)
+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));
 }
 
-void sym_check_prop(struct symbol *sym)
+static void sym_check_prop(struct symbol *sym)
 {
        struct property *prop;
        struct symbol *sym2;
@@ -194,8 +219,17 @@ void sym_check_prop(struct symbol *sym)
                        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 '%'"
+                                   "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);
@@ -215,8 +249,8 @@ void sym_check_prop(struct symbol *sym)
                        if (sym->type != S_INT && sym->type != S_HEX)
                                prop_warn(prop, "range is only allowed "
                                                "for int or hex symbols");
-                       if (!menu_range_valid_sym(sym, prop->expr->left.sym) ||
-                           !menu_range_valid_sym(sym, prop->expr->right.sym))
+                       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:
@@ -315,6 +349,8 @@ void menu_finalize(struct menu *parent)
                        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) &&
@@ -387,6 +423,13 @@ void menu_finalize(struct menu *parent)
        }
 }
 
+bool menu_has_prompt(struct menu *menu)
+{
+       if (!menu->prompt)
+               return false;
+       return true;
+}
+
 bool menu_is_visible(struct menu *menu)
 {
        struct menu *child;
@@ -395,6 +438,12 @@ bool menu_is_visible(struct menu *menu)
 
        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);
@@ -404,12 +453,18 @@ bool menu_is_visible(struct menu *menu)
 
        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))
+       for (child = menu->list; child; child = child->next) {
+               if (menu_is_visible(child)) {
+                       if (sym)
+                               sym->flags |= SYMBOL_DEF_USER;
                        return true;
+               }
+       }
+
        return false;
 }
 
@@ -451,3 +506,102 @@ const char *menu_get_help(struct menu *menu)
        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);
+}
index 72b5ad8..df274fe 100644 (file)
@@ -3,24 +3,42 @@
  * Released under the terms of the GNU GPL v2.0.
  */
 
-#include <qapplication.h>
+#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 <qvbox.h>
 #include <qsplitter.h>
-#include <qlistview.h>
-#include <qtextbrowser.h>
 #include <qlineedit.h>
 #include <qlabel.h>
 #include <qpushbutton.h>
 #include <qmenubar.h>
 #include <qmessagebox.h>
-#include <qaction.h>
-#include <qheader.h>
-#include <qfiledialog.h>
-#include <qdragobject.h>
 #include <qregexp.h>
+#include <qevent.h>
 
 #include <stdlib.h>
 
@@ -38,7 +56,7 @@
 static QApplication *configApp;
 static ConfigSettings *configSettings;
 
-QAction *ConfigMainWindow::saveAction;
+Q3Action *ConfigMainWindow::saveAction;
 
 static inline QString qgettext(const char* str)
 {
@@ -53,15 +71,14 @@ static inline QString qgettext(const QString& str)
 /**
  * Reads a list of integer values from the application settings.
  */
-QValueList<int> ConfigSettings::readSizes(const QString& key, bool *ok)
+Q3ValueList<int> ConfigSettings::readSizes(const QString& key, bool *ok)
 {
-       QValueList<int> result;
+       Q3ValueList<int> result;
        QStringList entryList = readListEntry(key, ok);
-       if (ok) {
-               QStringList::Iterator it;
-               for (it = entryList.begin(); it != entryList.end(); ++it)
-                       result.push_back((*it).toInt());
-       }
+       QStringList::Iterator it;
+
+       for (it = entryList.begin(); it != entryList.end(); ++it)
+               result.push_back((*it).toInt());
 
        return result;
 }
@@ -69,10 +86,10 @@ QValueList<int> ConfigSettings::readSizes(const QString& key, bool *ok)
 /**
  * Writes a list of integer values to the application settings.
  */
-bool ConfigSettings::writeSizes(const QString& key, const QValueList<int>& value)
+bool ConfigSettings::writeSizes(const QString& key, const Q3ValueList<int>& value)
 {
        QStringList stringList;
-       QValueList<int>::ConstIterator it;
+       Q3ValueList<int>::ConstIterator it;
 
        for (it = value.begin(); it != value.end(); ++it)
                stringList.push_back(QString::number(*it));
@@ -80,7 +97,6 @@ bool ConfigSettings::writeSizes(const QString& key, const QValueList<int>& value
 }
 
 
-#if QT_VERSION >= 300
 /*
  * set the new data
  * TODO check the value
@@ -91,7 +107,6 @@ void ConfigItem::okRename(int col)
        sym_set_string_value(menu->sym, text(dataColIdx).latin1());
        listView()->updateList(this);
 }
-#endif
 
 /*
  * update the displayed of a menu entry
@@ -148,7 +163,7 @@ void ConfigItem::updateMenu(void)
        case S_TRISTATE:
                char ch;
 
-               if (!sym_is_changable(sym) && !list->showAll) {
+               if (!sym_is_changable(sym) && list->optMode == normalOpt) {
                        setPixmap(promptColIdx, 0);
                        setText(noColIdx, QString::null);
                        setText(modColIdx, QString::null);
@@ -195,11 +210,9 @@ void ConfigItem::updateMenu(void)
 
                data = sym_get_string_value(sym);
 
-#if QT_VERSION >= 300
                int i = list->mapIdx(dataColIdx);
                if (i >= 0)
                        setRenameEnabled(i, TRUE);
-#endif
                setText(dataColIdx, data);
                if (type == S_STRING)
                        prompt = QString("%1: %2").arg(prompt).arg(data);
@@ -297,10 +310,10 @@ void ConfigLineEdit::show(ConfigItem* i)
 void ConfigLineEdit::keyPressEvent(QKeyEvent* e)
 {
        switch (e->key()) {
-       case Key_Escape:
+       case Qt::Key_Escape:
                break;
-       case Key_Return:
-       case Key_Enter:
+       case Qt::Key_Return:
+       case Qt::Key_Enter:
                sym_set_string_value(item->menu->sym, text().latin1());
                parent()->updateList(item);
                break;
@@ -319,7 +332,7 @@ ConfigList::ConfigList(ConfigView* p, const char *name)
          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),
-         showAll(false), showName(false), showRange(false), showData(false),
+         showName(false), showRange(false), showData(false), optMode(normalOpt),
          rootEntry(0), headerPopup(0)
 {
        int i;
@@ -336,10 +349,10 @@ ConfigList::ConfigList(ConfigView* p, const char *name)
 
        if (name) {
                configSettings->beginGroup(name);
-               showAll = configSettings->readBoolEntry("/showAll", false);
                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()));
        }
@@ -351,6 +364,17 @@ ConfigList::ConfigList(ConfigView* p, const char *name)
        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);
@@ -379,7 +403,7 @@ void ConfigList::saveSettings(void)
                configSettings->writeEntry("/showName", showName);
                configSettings->writeEntry("/showRange", showRange);
                configSettings->writeEntry("/showData", showData);
-               configSettings->writeEntry("/showAll", showAll);
+               configSettings->writeEntry("/optionMode", (int)optMode);
                configSettings->endGroup();
        }
 }
@@ -421,7 +445,7 @@ void ConfigList::updateList(ConfigItem* item)
        if (!rootEntry) {
                if (mode != listMode)
                        goto update;
-               QListViewItemIterator it(this);
+               Q3ListViewItemIterator it(this);
                ConfigItem* item;
 
                for (; it.current(); ++it) {
@@ -516,11 +540,9 @@ void ConfigList::changeValue(ConfigItem* item)
        case S_INT:
        case S_HEX:
        case S_STRING:
-#if QT_VERSION >= 300
                if (colMap[dataColIdx] >= 0)
                        item->startRename(colMap[dataColIdx]);
                else
-#endif
                        parent()->lineEdit->show(item);
                break;
        }
@@ -552,7 +574,7 @@ void ConfigList::setParentMenu(void)
                return;
        setRootMenu(menu_get_parent_menu(rootEntry->parent));
 
-       QListViewItemIterator it(this);
+       Q3ListViewItemIterator it(this);
        for (; (item = (ConfigItem*)it.current()); it++) {
                if (item->menu == oldroot) {
                        setCurrentItem(item);
@@ -605,7 +627,7 @@ void ConfigList::updateMenuList(P* parent, struct menu* menu)
                }
 
                visible = menu_is_visible(child);
-               if (showAll || visible) {
+               if (!menuSkip(child)) {
                        if (!child->sym && !child->list && !child->prompt)
                                continue;
                        if (!item || item->menu != child)
@@ -634,12 +656,12 @@ void ConfigList::updateMenuList(P* parent, struct menu* menu)
 
 void ConfigList::keyPressEvent(QKeyEvent* ev)
 {
-       QListViewItem* i = currentItem();
+       Q3ListViewItem* i = currentItem();
        ConfigItem* item;
        struct menu *menu;
        enum prop_type type;
 
-       if (ev->key() == Key_Escape && mode != fullMode && mode != listMode) {
+       if (ev->key() == Qt::Key_Escape && mode != fullMode && mode != listMode) {
                emit parentSelected();
                ev->accept();
                return;
@@ -652,8 +674,8 @@ void ConfigList::keyPressEvent(QKeyEvent* ev)
        item = (ConfigItem*)i;
 
        switch (ev->key()) {
-       case Key_Return:
-       case Key_Enter:
+       case Qt::Key_Return:
+       case Qt::Key_Enter:
                if (item->goParent) {
                        emit parentSelected();
                        break;
@@ -667,16 +689,16 @@ void ConfigList::keyPressEvent(QKeyEvent* ev)
                        emit menuSelected(menu);
                        break;
                }
-       case Key_Space:
+       case Qt::Key_Space:
                changeValue(item);
                break;
-       case Key_N:
+       case Qt::Key_N:
                setValue(item, no);
                break;
-       case Key_M:
+       case Qt::Key_M:
                setValue(item, mod);
                break;
-       case Key_Y:
+       case Qt::Key_Y:
                setValue(item, yes);
                break;
        default:
@@ -800,10 +822,10 @@ void ConfigList::contextMenuEvent(QContextMenuEvent *e)
 {
        if (e->y() <= header()->geometry().bottom()) {
                if (!headerPopup) {
-                       QAction *action;
+                       Q3Action *action;
 
-                       headerPopup = new QPopupMenu(this);
-                       action = new QAction(NULL, _("Show Name"), 0, this);
+                       headerPopup = new Q3PopupMenu(this);
+                       action = new Q3Action(NULL, _("Show Name"), 0, this);
                          action->setToggleAction(TRUE);
                          connect(action, SIGNAL(toggled(bool)),
                                  parent(), SLOT(setShowName(bool)));
@@ -811,7 +833,7 @@ void ConfigList::contextMenuEvent(QContextMenuEvent *e)
                                  action, SLOT(setOn(bool)));
                          action->setOn(showName);
                          action->addTo(headerPopup);
-                       action = new QAction(NULL, _("Show Range"), 0, this);
+                       action = new Q3Action(NULL, _("Show Range"), 0, this);
                          action->setToggleAction(TRUE);
                          connect(action, SIGNAL(toggled(bool)),
                                  parent(), SLOT(setShowRange(bool)));
@@ -819,7 +841,7 @@ void ConfigList::contextMenuEvent(QContextMenuEvent *e)
                                  action, SLOT(setOn(bool)));
                          action->setOn(showRange);
                          action->addTo(headerPopup);
-                       action = new QAction(NULL, _("Show Data"), 0, this);
+                       action = new Q3Action(NULL, _("Show Data"), 0, this);
                          action->setToggleAction(TRUE);
                          connect(action, SIGNAL(toggled(bool)),
                                  parent(), SLOT(setShowData(bool)));
@@ -834,7 +856,10 @@ void ConfigList::contextMenuEvent(QContextMenuEvent *e)
                e->ignore();
 }
 
-ConfigView* ConfigView::viewList;
+ConfigView*ConfigView::viewList;
+QAction *ConfigView::showNormalAction;
+QAction *ConfigView::showAllAction;
+QAction *ConfigView::showPromptAction;
 
 ConfigView::ConfigView(QWidget* parent, const char *name)
        : Parent(parent, name)
@@ -859,13 +884,16 @@ ConfigView::~ConfigView(void)
        }
 }
 
-void ConfigView::setShowAll(bool b)
+void ConfigView::setOptionMode(QAction *act)
 {
-       if (list->showAll != b) {
-               list->showAll = b;
-               list->updateListAll();
-               emit showAllChanged(b);
-       }
+       if (act == showNormalAction)
+               list->optMode = normalOpt;
+       else if (act == showAllAction)
+               list->optMode = allOpt;
+       else
+               list->optMode = promptOpt;
+
+       list->updateListAll();
 }
 
 void ConfigView::setShowName(bool b)
@@ -897,7 +925,7 @@ void ConfigView::setShowData(bool b)
 
 void ConfigList::setAllOpen(bool open)
 {
-       QListViewItemIterator it(this);
+       Q3ListViewItemIterator it(this);
 
        for (; it.current(); it++)
                it.current()->setOpen(open);
@@ -920,7 +948,7 @@ void ConfigView::updateListAll(void)
 }
 
 ConfigInfoView::ConfigInfoView(QWidget* parent, const char *name)
-       : Parent(parent, name), menu(0), sym(0)
+       : Parent(parent, name), sym(0), _menu(0)
 {
        if (name) {
                configSettings->beginGroup(name);
@@ -943,7 +971,7 @@ void ConfigInfoView::setShowDebug(bool b)
 {
        if (_showDebug != b) {
                _showDebug = b;
-               if (menu)
+               if (_menu)
                        menuInfo();
                else if (sym)
                        symbolInfo();
@@ -953,44 +981,16 @@ void ConfigInfoView::setShowDebug(bool b)
 
 void ConfigInfoView::setInfo(struct menu *m)
 {
-       if (menu == m)
+       if (_menu == m)
                return;
-       menu = m;
+       _menu = m;
        sym = NULL;
-       if (!menu)
+       if (!_menu)
                clear();
        else
                menuInfo();
 }
 
-void ConfigInfoView::setSource(const QString& name)
-{
-       const char *p = name.latin1();
-
-       menu = NULL;
-       sym = NULL;
-
-       switch (p[0]) {
-       case 'm':
-               struct menu *m;
-
-               if (sscanf(p, "m%p", &m) == 1 && menu != m) {
-                       menu = m;
-                       menuInfo();
-                       emit menuSelected(menu);
-               }
-               break;
-       case 's':
-               struct symbol *s;
-
-               if (sscanf(p, "s%p", &s) == 1 && sym != s) {
-                       sym = s;
-                       symbolInfo();
-               }
-               break;
-       }
-}
-
 void ConfigInfoView::symbolInfo(void)
 {
        QString str;
@@ -1012,11 +1012,11 @@ void ConfigInfoView::menuInfo(void)
        struct symbol* sym;
        QString head, debug, help;
 
-       sym = menu->sym;
+       sym = _menu->sym;
        if (sym) {
-               if (menu->prompt) {
+               if (_menu->prompt) {
                        head += "<big><b>";
-                       head += print_filter(_(menu->prompt->text));
+                       head += print_filter(_(_menu->prompt->text));
                        head += "</b></big>";
                        if (sym->name) {
                                head += " (";
@@ -1041,26 +1041,24 @@ void ConfigInfoView::menuInfo(void)
                if (showDebug())
                        debug = debug_info(sym);
 
-               help = menu_get_help(menu);
-               /* Gettextize if the help text not empty */
-               if (help.isEmpty())
-                       help = print_filter(menu_get_help(menu));
-               else
-                       help = print_filter(_(menu_get_help(menu)));
-       } else if (menu->prompt) {
+               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 += print_filter(_(_menu->prompt->text));
                head += "</b></big><br><br>";
                if (showDebug()) {
-                       if (menu->prompt->visible.expr) {
+                       if (_menu->prompt->visible.expr) {
                                debug += "&nbsp;&nbsp;dep: ";
-                               expr_print(menu->prompt->visible.expr, expr_print_help, &debug, E_NONE);
+                               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);
+               debug += QString().sprintf("defined at %s:%d<br><br>", _menu->file->name, _menu->lineno);
 
        setText(head + debug + help);
 }
@@ -1163,10 +1161,10 @@ void ConfigInfoView::expr_print_help(void *data, struct symbol *sym, const char
                *text += str2;
 }
 
-QPopupMenu* ConfigInfoView::createPopupMenu(const QPoint& pos)
+Q3PopupMenu* ConfigInfoView::createPopupMenu(const QPoint& pos)
 {
-       QPopupMenu* popup = Parent::createPopupMenu(pos);
-       QAction* action = new QAction(NULL, _("Show Debug Info"), 0, popup);
+       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)));
@@ -1199,7 +1197,7 @@ ConfigSearchWindow::ConfigSearchWindow(ConfigMainWindow* parent, const char *nam
        layout1->addLayout(layout2);
 
        split = new QSplitter(this);
-       split->setOrientation(QSplitter::Vertical);
+       split->setOrientation(Qt::Vertical);
        list = new ConfigView(split, name);
        list->list->mode = listMode;
        info = new ConfigInfoView(split, name);
@@ -1223,7 +1221,7 @@ ConfigSearchWindow::ConfigSearchWindow(ConfigMainWindow* parent, const char *nam
                        y = configSettings->readNumEntry("/window y", 0, &ok);
                if (ok)
                        move(x, y);
-               QValueList<int> sizes = configSettings->readSizes("/split", &ok);
+               Q3ValueList<int> sizes = configSettings->readSizes("/split", &ok);
                if (ok)
                        split->setSizes(sizes);
                configSettings->endGroup();
@@ -1275,9 +1273,15 @@ ConfigMainWindow::ConfigMainWindow(void)
        int x, y, width, height;
        char title[256];
 
-       QWidget *d = configApp->desktop();
-       snprintf(title, sizeof(title), _("firmly.0cpm v%s Configuration"),
-               getenv("KERNELVERSION"));
+       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);
@@ -1290,14 +1294,14 @@ ConfigMainWindow::ConfigMainWindow(void)
                move(x, y);
 
        split1 = new QSplitter(this);
-       split1->setOrientation(QSplitter::Horizontal);
+       split1->setOrientation(Qt::Horizontal);
        setCentralWidget(split1);
 
        menuView = new ConfigView(split1, "menu");
        menuList = menuView->list;
 
        split2 = new QSplitter(split1);
-       split2->setOrientation(QSplitter::Vertical);
+       split2->setOrientation(Qt::Vertical);
 
        // create config tree
        configView = new ConfigView(split2, "config");
@@ -1310,60 +1314,79 @@ ConfigMainWindow::ConfigMainWindow(void)
        configList->setFocus();
 
        menu = menuBar();
-       toolBar = new QToolBar("Tools", this);
+       toolBar = new Q3ToolBar("Tools", this);
 
-       backAction = new QAction("Back", QPixmap(xpm_back), _("Back"), 0, this);
+       backAction = new Q3Action("Back", QPixmap(xpm_back), _("Back"), 0, this);
          connect(backAction, SIGNAL(activated()), SLOT(goBack()));
          backAction->setEnabled(FALSE);
-       QAction *quitAction = new QAction("Quit", _("&Quit"), CTRL+Key_Q, this);
+       Q3Action *quitAction = new Q3Action("Quit", _("&Quit"), Qt::CTRL + Qt::Key_Q, this);
          connect(quitAction, SIGNAL(activated()), SLOT(close()));
-       QAction *loadAction = new QAction("Load", QPixmap(xpm_load), _("&Load"), CTRL+Key_L, this);
+       Q3Action *loadAction = new Q3Action("Load", QPixmap(xpm_load), _("&Load"), Qt::CTRL + Qt::Key_L, this);
          connect(loadAction, SIGNAL(activated()), SLOT(loadConfig()));
-       saveAction = new QAction("Save", QPixmap(xpm_save), _("&Save"), CTRL+Key_S, this);
+       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();
-       QAction *saveAsAction = new QAction("Save As...", _("Save &As..."), 0, this);
+       Q3Action *saveAsAction = new Q3Action("Save As...", _("Save &As..."), 0, this);
          connect(saveAsAction, SIGNAL(activated()), SLOT(saveConfigAs()));
-       QAction *searchAction = new QAction("Find", _("&Find"), CTRL+Key_F, this);
+       Q3Action *searchAction = new Q3Action("Find", _("&Find"), Qt::CTRL + Qt::Key_F, this);
          connect(searchAction, SIGNAL(activated()), SLOT(searchConfig()));
-       QAction *singleViewAction = new QAction("Single View", QPixmap(xpm_single_view), _("Single View"), 0, this);
+       Q3Action *singleViewAction = new Q3Action("Single View", QPixmap(xpm_single_view), _("Single View"), 0, this);
          connect(singleViewAction, SIGNAL(activated()), SLOT(showSingleView()));
-       QAction *splitViewAction = new QAction("Split View", QPixmap(xpm_split_view), _("Split View"), 0, this);
+       Q3Action *splitViewAction = new Q3Action("Split View", QPixmap(xpm_split_view), _("Split View"), 0, this);
          connect(splitViewAction, SIGNAL(activated()), SLOT(showSplitView()));
-       QAction *fullViewAction = new QAction("Full View", QPixmap(xpm_tree_view), _("Full View"), 0, this);
+       Q3Action *fullViewAction = new Q3Action("Full View", QPixmap(xpm_tree_view), _("Full View"), 0, this);
          connect(fullViewAction, SIGNAL(activated()), SLOT(showFullView()));
 
-       QAction *showNameAction = new QAction(NULL, _("Show Name"), 0, this);
+       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());
-       QAction *showRangeAction = new QAction(NULL, _("Show Range"), 0, this);
+       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);
-       QAction *showDataAction = new QAction(NULL, _("Show Data"), 0, this);
+       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);
-       QAction *showAllAction = new QAction(NULL, _("Show All Options"), 0, this);
-         showAllAction->setToggleAction(TRUE);
-         connect(showAllAction, SIGNAL(toggled(bool)), configView, SLOT(setShowAll(bool)));
-         connect(showAllAction, SIGNAL(toggled(bool)), menuView, SLOT(setShowAll(bool)));
-         showAllAction->setOn(configList->showAll);
-       QAction *showDebugAction = new QAction(NULL, _("Show Debug Info"), 0, this);
+
+       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());
 
-       QAction *showIntroAction = new QAction(NULL, _("Introduction"), 0, this);
+       Q3Action *showIntroAction = new Q3Action(NULL, _("Introduction"), 0, this);
          connect(showIntroAction, SIGNAL(activated()), SLOT(showIntro()));
-       QAction *showAboutAction = new QAction(NULL, _("About"), 0, this);
+       Q3Action *showAboutAction = new Q3Action(NULL, _("About"), 0, this);
          connect(showAboutAction, SIGNAL(activated()), SLOT(showAbout()));
 
        // init tool bar
@@ -1377,7 +1400,7 @@ ConfigMainWindow::ConfigMainWindow(void)
        fullViewAction->addTo(toolBar);
 
        // create config menu
-       QPopupMenu* config = new QPopupMenu(this);
+       Q3PopupMenu* config = new Q3PopupMenu(this);
        menu->insertItem(_("&File"), config);
        loadAction->addTo(config);
        saveAction->addTo(config);
@@ -1386,22 +1409,22 @@ ConfigMainWindow::ConfigMainWindow(void)
        quitAction->addTo(config);
 
        // create edit menu
-       QPopupMenu* editMenu = new QPopupMenu(this);
+       Q3PopupMenu* editMenu = new Q3PopupMenu(this);
        menu->insertItem(_("&Edit"), editMenu);
        searchAction->addTo(editMenu);
 
        // create options menu
-       QPopupMenu* optionMenu = new QPopupMenu(this);
+       Q3PopupMenu* optionMenu = new Q3PopupMenu(this);
        menu->insertItem(_("&Option"), optionMenu);
        showNameAction->addTo(optionMenu);
        showRangeAction->addTo(optionMenu);
        showDataAction->addTo(optionMenu);
        optionMenu->insertSeparator();
-       showAllAction->addTo(optionMenu);
-       showDebugAction->addTo(optionMenu);
+       optGroup->addTo(optionMenu);
+       optionMenu->insertSeparator();
 
        // create help menu
-       QPopupMenu* helpMenu = new QPopupMenu(this);
+       Q3PopupMenu* helpMenu = new Q3PopupMenu(this);
        menu->insertSeparator();
        menu->insertItem(_("&Help"), helpMenu);
        showIntroAction->addTo(helpMenu);
@@ -1436,7 +1459,7 @@ ConfigMainWindow::ConfigMainWindow(void)
                showSplitView();
 
        // UI setup done, restore splitter positions
-       QValueList<int> sizes = configSettings->readSizes("/split1", &ok);
+       Q3ValueList<int> sizes = configSettings->readSizes("/split1", &ok);
        if (ok)
                split1->setSizes(sizes);
 
@@ -1447,7 +1470,7 @@ ConfigMainWindow::ConfigMainWindow(void)
 
 void ConfigMainWindow::loadConfig(void)
 {
-       QString s = QFileDialog::getOpenFileName(".config", NULL, this);
+       QString s = Q3FileDialog::getOpenFileName(conf_get_configname(), NULL, this);
        if (s.isNull())
                return;
        if (conf_read(QFile::encodeName(s)))
@@ -1455,19 +1478,21 @@ void ConfigMainWindow::loadConfig(void)
        ConfigView::updateListAll();
 }
 
-void ConfigMainWindow::saveConfig(void)
+bool ConfigMainWindow::saveConfig(void)
 {
-       if (conf_write(NULL))
+       if (conf_write(NULL)) {
                QMessageBox::information(this, "qconf", _("Unable to save configuration!"));
+               return false;
+       }
+       return true;
 }
 
 void ConfigMainWindow::saveConfigAs(void)
 {
-       QString s = QFileDialog::getSaveFileName(".config", NULL, this);
+       QString s = Q3FileDialog::getSaveFileName(conf_get_configname(), NULL, this);
        if (s.isNull())
                return;
-       if (conf_write(QFile::encodeName(s)))
-               QMessageBox::information(this, "qconf", _("Unable to save configuration!"));
+       saveConfig();
 }
 
 void ConfigMainWindow::searchConfig(void)
@@ -1492,7 +1517,7 @@ void ConfigMainWindow::setMenuLink(struct menu *menu)
        ConfigList* list = NULL;
        ConfigItem* item;
 
-       if (!menu_is_visible(menu) && !configView->showAll())
+       if (configList->menuSkip(menu))
                return;
 
        switch (configList->mode) {
@@ -1524,6 +1549,8 @@ void ConfigMainWindow::setMenuLink(struct menu *menu)
        case fullMode:
                list = configList;
                break;
+       default:
+               break;
        }
 
        if (list) {
@@ -1618,7 +1645,11 @@ void ConfigMainWindow::closeEvent(QCloseEvent* e)
        mb.setButtonText(QMessageBox::Cancel, _("Cancel Exit"));
        switch (mb.exec()) {
        case QMessageBox::Yes:
-               conf_write(NULL);
+               if (saveConfig())
+                       e->accept();
+               else
+                       e->ignore();
+               break;
        case QMessageBox::No:
                e->accept();
                break;
@@ -1630,7 +1661,7 @@ void ConfigMainWindow::closeEvent(QCloseEvent* e)
 
 void ConfigMainWindow::showIntro(void)
 {
-       static const QString str = _("Welcome to the qconf graphical kernel configuration tool for firmly.0cpm.\n\n"
+       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"
@@ -1673,6 +1704,9 @@ void ConfigMainWindow::saveSettings(void)
        case fullMode :
                entry = "full";
                break;
+
+       default:
+               break;
        }
        configSettings->writeEntry("/listMode", entry);
 
@@ -1718,10 +1752,6 @@ int main(int ac, char** av)
        bindtextdomain(PACKAGE, LOCALEDIR);
        textdomain(PACKAGE);
 
-#ifndef LKC_DIRECT_LINK
-       kconfig_load();
-#endif
-
        progname = av[0];
        configApp = new QApplication(ac, av);
        if (ac > 1 && av[1][0] == '-') {
index b3b5657..3715b3e 100644 (file)
@@ -3,26 +3,25 @@
  * Released under the terms of the GNU GPL v2.0.
  */
 
+#if QT_VERSION < 0x040000
 #include <qlistview.h>
-#if QT_VERSION >= 300
-#include <qsettings.h>
 #else
-class QSettings {
-public:
-       void beginGroup(const QString& group) { }
-       void endGroup(void) { }
-       bool readBoolEntry(const QString& key, bool def = FALSE, bool* ok = 0) const
-       { if (ok) *ok = FALSE; return def; }
-       int readNumEntry(const QString& key, int def = 0, bool* ok = 0) const
-       { if (ok) *ok = FALSE; return def; }
-       QString readEntry(const QString& key, const QString& def = QString::null, bool* ok = 0) const
-       { if (ok) *ok = FALSE; return def; }
-       QStringList readListEntry(const QString& key, bool* ok = 0) const
-       { if (ok) *ok = FALSE; return QStringList(); }
-       template <class t>
-       bool writeEntry(const QString& key, t value)
-       { return TRUE; }
-};
+#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;
@@ -31,11 +30,10 @@ class ConfigItem;
 class ConfigLineEdit;
 class ConfigMainWindow;
 
-
 class ConfigSettings : public QSettings {
 public:
-       QValueList<int> readSizes(const QString& key, bool *ok);
-       bool writeSizes(const QString& key, const QValueList<int>& value);
+       Q3ValueList<int> readSizes(const QString& key, bool *ok);
+       bool writeSizes(const QString& key, const Q3ValueList<int>& value);
 };
 
 enum colIdx {
@@ -44,10 +42,13 @@ enum colIdx {
 enum listMode {
        singleMode, menuMode, symbolMode, fullMode, listMode
 };
+enum optionMode {
+       normalOpt = 0, allOpt, promptOpt
+};
 
-class ConfigList : public QListView {
+class ConfigList : public Q3ListView {
        Q_OBJECT
-       typedef class QListView Parent;
+       typedef class Q3ListView Parent;
 public:
        ConfigList(ConfigView* p, const char *name = 0);
        void reinit(void);
@@ -115,6 +116,8 @@ public:
        void setAllOpen(bool open);
        void setParentMenu(void);
 
+       bool menuSkip(struct menu *);
+
        template <class P>
        void updateMenuList(P*, struct menu*);
 
@@ -124,22 +127,23 @@ public:
        QPixmap choiceYesPix, choiceNoPix;
        QPixmap menuPix, menuInvPix, menuBackPix, voidPix;
 
-       bool showAll, showName, showRange, showData;
+       bool showName, showRange, showData;
        enum listMode mode;
+       enum optionMode optMode;
        struct menu *rootEntry;
        QColorGroup disabledColorGroup;
        QColorGroup inactivedColorGroup;
-       QPopupMenu* headerPopup;
+       Q3PopupMenu* headerPopup;
 
 private:
        int colMap[colNr];
        int colRevMap[colNr];
 };
 
-class ConfigItem : public QListViewItem {
-       typedef class QListViewItem Parent;
+class ConfigItem : public Q3ListViewItem {
+       typedef class Q3ListViewItem Parent;
 public:
-       ConfigItem(QListView *parent, ConfigItem *after, struct menu *m, bool v)
+       ConfigItem(Q3ListView *parent, ConfigItem *after, struct menu *m, bool v)
        : Parent(parent, after), menu(m), visible(v), goParent(false)
        {
                init();
@@ -149,16 +153,14 @@ public:
        {
                init();
        }
-       ConfigItem(QListView *parent, ConfigItem *after, bool v)
+       ConfigItem(Q3ListView *parent, ConfigItem *after, bool v)
        : Parent(parent, after), menu(0), visible(v), goParent(true)
        {
                init();
        }
        ~ConfigItem(void);
        void init(void);
-#if QT_VERSION >= 300
        void okRename(int col);
-#endif
        void updateMenu(void);
        void testUpdateMenu(bool v);
        ConfigList* listView() const
@@ -213,26 +215,24 @@ public:
        ConfigItem *item;
 };
 
-class ConfigView : public QVBox {
+class ConfigView : public Q3VBox {
        Q_OBJECT
-       typedef class QVBox Parent;
+       typedef class Q3VBox Parent;
 public:
        ConfigView(QWidget* parent, const char *name = 0);
        ~ConfigView(void);
        static void updateList(ConfigItem* item);
        static void updateListAll(void);
 
-       bool showAll(void) const { return list->showAll; }
        bool showName(void) const { return list->showName; }
        bool showRange(void) const { return list->showRange; }
        bool showData(void) const { return list->showData; }
 public slots:
-       void setShowAll(bool);
        void setShowName(bool);
        void setShowRange(bool);
        void setShowData(bool);
+       void setOptionMode(QAction *);
 signals:
-       void showAllChanged(bool);
        void showNameChanged(bool);
        void showRangeChanged(bool);
        void showDataChanged(bool);
@@ -242,11 +242,15 @@ public:
 
        static ConfigView* viewList;
        ConfigView* nextView;
+
+       static QAction *showNormalAction;
+       static QAction *showAllAction;
+       static QAction *showPromptAction;
 };
 
-class ConfigInfoView : public QTextBrowser {
+class ConfigInfoView : public Q3TextBrowser {
        Q_OBJECT
-       typedef class QTextBrowser Parent;
+       typedef class Q3TextBrowser Parent;
 public:
        ConfigInfoView(QWidget* parent, const char *name = 0);
        bool showDebug(void) const { return _showDebug; }
@@ -254,7 +258,6 @@ public:
 public slots:
        void setInfo(struct menu *menu);
        void saveSettings(void);
-       void setSource(const QString& name);
        void setShowDebug(bool);
 
 signals:
@@ -267,11 +270,11 @@ protected:
        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);
-       QPopupMenu* createPopupMenu(const QPoint& pos);
+       Q3PopupMenu* createPopupMenu(const QPoint& pos);
        void contentsContextMenuEvent(QContextMenuEvent *e);
 
        struct symbol *sym;
-       struct menu *menu;
+       struct menu *_menu;
        bool _showDebug;
 };
 
@@ -295,10 +298,10 @@ protected:
        struct symbol **result;
 };
 
-class ConfigMainWindow : public QMainWindow {
+class ConfigMainWindow : public Q3MainWindow {
        Q_OBJECT
 
-       static QAction *saveAction;
+       static Q3Action *saveAction;
        static void conf_changed(void);
 public:
        ConfigMainWindow(void);
@@ -308,7 +311,7 @@ public slots:
        void listFocusChanged(void);
        void goBack(void);
        void loadConfig(void);
-       void saveConfig(void);
+       bool saveConfig(void);
        void saveConfigAs(void);
        void searchConfig(void);
        void showSingleView(void);
@@ -327,8 +330,8 @@ protected:
        ConfigView *configView;
        ConfigList *configList;
        ConfigInfoView *helpText;
-       QToolBar *toolBar;
-       QAction *backAction;
+       Q3ToolBar *toolBar;
+       Q3Action *backAction;
        QSplitter* split1;
        QSplitter* split2;
 };
index 18f3e5c..071f00c 100644 (file)
@@ -9,7 +9,6 @@
 #include <regex.h>
 #include <sys/utsname.h>
 
-#define LKC_DIRECT_LINK
 #include "lkc.h"
 
 struct symbol symbol_yes = {
@@ -36,7 +35,7 @@ tristate modules_val;
 
 struct expr *sym_env_list;
 
-void sym_add_default(struct symbol *sym, const char *def)
+static void sym_add_default(struct symbol *sym, const char *def)
 {
        struct property *prop = prop_alloc(P_DEFAULT, sym);
 
@@ -125,7 +124,7 @@ struct property *sym_get_default_prop(struct symbol *sym)
        return NULL;
 }
 
-struct property *sym_get_range_prop(struct symbol *sym)
+static struct property *sym_get_range_prop(struct symbol *sym)
 {
        struct property *prop;
 
@@ -205,6 +204,16 @@ static void sym_calc_visibility(struct symbol *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);
@@ -216,44 +225,63 @@ static void sym_calc_visibility(struct symbol *sym)
        }
 }
 
-static struct symbol *sym_calc_choice(struct symbol *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;
 
-       /* is the user choice visible? */
-       def_sym = sym->def[S_DEF_USER].val;
-       if (def_sym) {
-               sym_calc_visibility(def_sym);
-               if (def_sym->visible != no)
-                       return def_sym;
-       }
-
        /* 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);
-               sym_calc_visibility(def_sym);
                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) {
-               sym_calc_visibility(def_sym);
+       expr_list_for_each_sym(prop->expr, e, def_sym)
                if (def_sym->visible != no)
                        return def_sym;
-       }
 
-       /* no choice? reset tristate value */
-       sym->curr.tri = no;
+       /* 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;
@@ -321,6 +349,18 @@ void sym_calc_value(struct symbol *sym)
                                }
                        }
                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)
@@ -365,12 +405,13 @@ void sym_calc_value(struct symbol *sym)
 
        if (sym_is_choice(sym)) {
                struct symbol *choice_sym;
-               int flags = sym->flags & (SYMBOL_CHANGED | SYMBOL_WRITE);
 
                prop = sym_get_choice_prop(sym);
                expr_list_for_each_sym(prop->expr, e, choice_sym) {
-                       choice_sym->flags |= flags;
-                       if (flags & SYMBOL_CHANGED)
+                       if ((sym->flags & SYMBOL_WRITE) &&
+                           choice_sym->visible != no)
+                               choice_sym->flags |= SYMBOL_WRITE;
+                       if (sym->flags & SYMBOL_CHANGED)
                                sym_set_changed(choice_sym);
                }
        }
@@ -623,6 +664,80 @@ bool sym_set_string_value(struct symbol *sym, const char *newval)
        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;
@@ -635,7 +750,8 @@ const char *sym_get_string_value(struct symbol *sym)
                case no:
                        return "n";
                case mod:
-                       return "m";
+                       sym_calc_value(modules_sym);
+                       return (modules_sym->curr.tri == no) ? "n" : "m";
                case yes:
                        return "y";
                }
@@ -651,12 +767,20 @@ 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;
-       const char *ptr;
        char *new_name;
-       int hash = 0;
+       int hash;
 
        if (name) {
                if (name[0] && !name[1]) {
@@ -666,12 +790,11 @@ struct symbol *sym_lookup(const char *name, int flags)
                        case 'n': return &symbol_no;
                        }
                }
-               for (ptr = name; *ptr; ptr++)
-                       hash += *ptr;
-               hash &= 0xff;
+               hash = strhash(name) % SYMBOL_HASHSIZE;
 
                for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
-                       if (!strcmp(symbol->name, name) &&
+                       if (symbol->name &&
+                           !strcmp(symbol->name, name) &&
                            (flags ? symbol->flags & flags
                                   : !(symbol->flags & (SYMBOL_CONST|SYMBOL_CHOICE))))
                                return symbol;
@@ -679,7 +802,7 @@ struct symbol *sym_lookup(const char *name, int flags)
                new_name = strdup(name);
        } else {
                new_name = NULL;
-               hash = 256;
+               hash = 0;
        }
 
        symbol = malloc(sizeof(*symbol));
@@ -697,7 +820,6 @@ struct symbol *sym_lookup(const char *name, int flags)
 struct symbol *sym_find(const char *name)
 {
        struct symbol *symbol = NULL;
-       const char *ptr;
        int hash = 0;
 
        if (!name)
@@ -710,12 +832,11 @@ struct symbol *sym_find(const char *name)
                case 'n': return &symbol_no;
                }
        }
-       for (ptr = name; *ptr; ptr++)
-               hash += *ptr;
-       hash &= 0xff;
+       hash = strhash(name) % SYMBOL_HASHSIZE;
 
        for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
-               if (!strcmp(symbol->name, name) &&
+               if (symbol->name &&
+                   !strcmp(symbol->name, name) &&
                    !(symbol->flags & SYMBOL_CONST))
                                break;
        }
@@ -723,6 +844,98 @@ struct symbol *sym_find(const char *name)
        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;
@@ -750,6 +963,7 @@ struct symbol **sym_re_search(const char *pattern)
                                return NULL;
                        }
                }
+               sym_calc_value(sym);
                sym_arr[cnt++] = sym;
        }
        if (sym_arr)
@@ -759,6 +973,112 @@ struct symbol **sym_re_search(const char *pattern)
        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)
 {
@@ -795,24 +1115,33 @@ 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)
-               return 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;
 }
 
@@ -821,6 +1150,9 @@ 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)
@@ -834,10 +1166,8 @@ static struct symbol *sym_check_choice_deps(struct symbol *choice)
 
        expr_list_for_each_sym(prop->expr, e, sym) {
                sym2 = sym_check_sym_deps(sym);
-               if (sym2) {
-                       fprintf(stderr, " -> %s", sym->name);
+               if (sym2)
                        break;
-               }
        }
 out:
        expr_list_for_each_sym(prop->expr, e, sym)
@@ -847,6 +1177,8 @@ out:
            prop_get_symbol(sym_get_choice_prop(sym2)) == choice)
                sym2 = choice;
 
+       dep_stack_remove();
+
        return sym2;
 }
 
@@ -856,18 +1188,20 @@ struct symbol *sym_check_deps(struct symbol *sym)
        struct property *prop;
 
        if (sym->flags & SYMBOL_CHECK) {
-               fprintf(stderr, "%s:%d:error: found recursive dependency: %s",
-                       sym->prop->file->name, sym->prop->lineno,
-                       sym->name ? sym->name : "<choice>");
+               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 {
@@ -876,14 +1210,8 @@ struct symbol *sym_check_deps(struct symbol *sym)
                sym->flags &= ~SYMBOL_CHECK;
        }
 
-       if (sym2) {
-               fprintf(stderr, " -> %s", sym->name ? sym->name : "<choice>");
-               if (sym2 == sym) {
-                       fprintf(stderr, "\n");
-                       zconfnerrs++;
-                       sym2 = NULL;
-               }
-       }
+       if (sym2 && sym2 == sym)
+               sym2 = NULL;
 
        return sym2;
 }
@@ -937,13 +1265,15 @@ const char *prop_get_type_name(enum prop_type type)
                return "select";
        case P_RANGE:
                return "range";
+       case P_SYMBOL:
+               return "symbol";
        case P_UNKNOWN:
                break;
        }
        return "unknown";
 }
 
-void prop_add_env(const char *env)
+static void prop_add_env(const char *env)
 {
        struct symbol *sym, *sym2;
        struct property *prop;
index 3cc9f93..d0b8b23 100644 (file)
@@ -5,6 +5,8 @@
  * Released under the terms of the GNU GPL v2.0.
  */
 
+#include <stdarg.h>
+#include <stdlib.h>
 #include <string.h>
 #include "lkc.h"
 
 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))
+               if (!strcmp(name, file->name)) {
+                       free((void *)file_name);
                        return file;
+               }
        }
 
        file = malloc(sizeof(*file));
        memset(file, 0, sizeof(*file));
-       file->name = strdup(name);
+       file->name = file_name;
        file->next = file_list;
        file_list = file;
        return file;
@@ -46,8 +51,8 @@ int file_write_dep(const char *name)
                else
                        fprintf(out, "\t%s\n", file->name);
        }
-       fprintf(out, "\ninclude/config/auto.conf: \\\n"
-                    "\t$(deps_config)\n\n");
+       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;
@@ -61,7 +66,7 @@ int file_write_dep(const char *name)
                if (!value)
                        value = "";
                fprintf(out, "ifneq \"$(%s)\" \"%s\"\n", env_sym->name, value);
-               fprintf(out, "include/config/auto.conf: FORCE\n");
+               fprintf(out, "%s: FORCE\n", conf_get_autoconfig_name());
                fprintf(out, "endif\n");
        }
 
@@ -72,12 +77,13 @@ int file_write_dep(const char *name)
 }
 
 
-/* Allocate initial growable sting */
+/* 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;
 }
@@ -88,6 +94,7 @@ 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;
 }
 
index 4cea5c8..00f9d3a 100644 (file)
@@ -1,5 +1,6 @@
-%option backup nostdinit noyywrap never-interactive full ecs
-%option 8bit backup nodefault perf-report perf-report
+%option nostdinit noyywrap never-interactive full ecs
+%option 8bit nodefault perf-report perf-report
+%option noinput
 %x COMMAND HELP STRING PARAM
 %{
 /*
@@ -13,7 +14,6 @@
 #include <string.h>
 #include <unistd.h>
 
-#define LKC_DIRECT_LINK
 #include "lkc.h"
 
 #define START_STRSIZE  16
@@ -38,7 +38,7 @@ static int last_ts, first_ts;
 static void zconf_endhelp(void);
 static void zconf_endfile(void);
 
-void new_string(void)
+static void new_string(void)
 {
        text = malloc(START_STRSIZE);
        text_asize = START_STRSIZE;
@@ -46,7 +46,7 @@ void new_string(void)
        *text = 0;
 }
 
-void append_string(const char *str, int size)
+static void append_string(const char *str, int size)
 {
        int new_size = text_size + size + 1;
        if (new_size > text_asize) {
@@ -60,7 +60,7 @@ void append_string(const char *str, int size)
        text[text_size] = 0;
 }
 
-void alloc_string(const char *str, int size)
+static void alloc_string(const char *str, int size)
 {
        text = malloc(size + 1);
        memcpy(text, str, size);
@@ -95,7 +95,7 @@ n     [A-Za-z0-9_]
 
 <COMMAND>{
        {n}+    {
-               struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
+               const struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
                BEGIN(PARAM);
                current_pos.file = current_file;
                current_pos.lineno = current_file->lineno;
@@ -131,7 +131,7 @@ n   [A-Za-z0-9_]
        \n      BEGIN(INITIAL); current_file->lineno++; return T_EOL;
        ---     /* ignore */
        ({n}|[-/.])+    {
-               struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
+               const struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
                if (id && id->flags & TF_PARAM) {
                        zconflval.id = id;
                        return id->token;
@@ -293,34 +293,45 @@ void zconf_initscan(const char *name)
 
        current_file = file_lookup(name);
        current_file->lineno = 1;
-       current_file->flags = FILE_BUSY;
 }
 
 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(name);
+       yyin = zconf_fopen(file->name);
        if (!yyin) {
-               printf("%s:%d: can't open file \"%s\"\n", zconf_curname(), zconf_lineno(), name);
+               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;
 
-       if (file->flags & FILE_BUSY) {
-               printf("recursive scan (%s)?\n", name);
-               exit(1);
-       }
-       if (file->flags & FILE_SCANNED) {
-               printf("file %s already scanned?\n", name);
-               exit(1);
+       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->flags |= FILE_BUSY;
        file->lineno = 1;
        file->parent = current_file;
        current_file = file;
@@ -330,8 +341,6 @@ static void zconf_endfile(void)
 {
        struct buffer *parent;
 
-       current_file->flags |= FILE_SCANNED;
-       current_file->flags &= ~FILE_BUSY;
        current_file = current_file->parent;
 
        parent = current_buf->parent;
@@ -349,7 +358,7 @@ int zconf_lineno(void)
        return current_pos.lineno;
 }
 
-char *zconf_curname(void)
+const char *zconf_curname(void)
 {
        return current_pos.file ? current_pos.file->name : "<none>";
 }
index e77ed67..f636141 100644 (file)
@@ -1,24 +1,22 @@
-/* A Bison parser, made by GNU Bison 2.3.  */
+/* A Bison parser, made by GNU Bison 2.4.3.  */
 
 /* Skeleton implementation for Bison's Yacc-like parsers in C
-
-   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
-   Free Software Foundation, Inc.
-
-   This program is free software; you can redistribute it and/or modify
+   
+      Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
+   2009, 2010 Free Software Foundation, Inc.
+   
+   This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
-
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+   
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
-
+   
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor,
-   Boston, MA 02110-1301, USA.  */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 /* As a special exception, you may create a larger work that contains
    part or all of the Bison parser skeleton and distribute that work
@@ -29,7 +27,7 @@
    special exception, which will cause the skeleton and the resulting
    Bison output files to be licensed under the GNU General Public
    License without this special exception.
-
+   
    This special exception was added by the Free Software Foundation in
    version 2.2 of Bison.  */
 
@@ -47,7 +45,7 @@
 #define YYBISON 1
 
 /* Bison version.  */
-#define YYBISON_VERSION "2.3"
+#define YYBISON_VERSION "2.4.3"
 
 /* Skeleton name.  */
 #define YYSKELETON_NAME "yacc.c"
 /* Pure parsers.  */
 #define YYPURE 0
 
+/* Push parsers.  */
+#define YYPUSH 0
+
+/* Pull parsers.  */
+#define YYPULL 1
+
 /* Using locations.  */
 #define YYLSP_NEEDED 0
 
 /* Substitute the variable and function names.  */
-#define yyparse zconfparse
-#define yylex   zconflex
-#define yyerror zconferror
-#define yylval  zconflval
-#define yychar  zconfchar
-#define yydebug zconfdebug
-#define yynerrs zconfnerrs
-
-
-/* Tokens.  */
-#ifndef YYTOKENTYPE
-# define YYTOKENTYPE
-   /* Put the tokens into the symbol table, so that GDB and other debuggers
-      know about them.  */
-   enum yytokentype {
-     T_MAINMENU = 258,
-     T_MENU = 259,
-     T_ENDMENU = 260,
-     T_SOURCE = 261,
-     T_CHOICE = 262,
-     T_ENDCHOICE = 263,
-     T_COMMENT = 264,
-     T_CONFIG = 265,
-     T_MENUCONFIG = 266,
-     T_HELP = 267,
-     T_HELPTEXT = 268,
-     T_IF = 269,
-     T_ENDIF = 270,
-     T_DEPENDS = 271,
-     T_OPTIONAL = 272,
-     T_PROMPT = 273,
-     T_TYPE = 274,
-     T_DEFAULT = 275,
-     T_SELECT = 276,
-     T_RANGE = 277,
-     T_OPTION = 278,
-     T_ON = 279,
-     T_WORD = 280,
-     T_WORD_QUOTE = 281,
-     T_UNEQUAL = 282,
-     T_CLOSE_PAREN = 283,
-     T_OPEN_PAREN = 284,
-     T_EOL = 285,
-     T_OR = 286,
-     T_AND = 287,
-     T_EQUAL = 288,
-     T_NOT = 289
-   };
-#endif
-/* Tokens.  */
-#define T_MAINMENU 258
-#define T_MENU 259
-#define T_ENDMENU 260
-#define T_SOURCE 261
-#define T_CHOICE 262
-#define T_ENDCHOICE 263
-#define T_COMMENT 264
-#define T_CONFIG 265
-#define T_MENUCONFIG 266
-#define T_HELP 267
-#define T_HELPTEXT 268
-#define T_IF 269
-#define T_ENDIF 270
-#define T_DEPENDS 271
-#define T_OPTIONAL 272
-#define T_PROMPT 273
-#define T_TYPE 274
-#define T_DEFAULT 275
-#define T_SELECT 276
-#define T_RANGE 277
-#define T_OPTION 278
-#define T_ON 279
-#define T_WORD 280
-#define T_WORD_QUOTE 281
-#define T_UNEQUAL 282
-#define T_CLOSE_PAREN 283
-#define T_OPEN_PAREN 284
-#define T_EOL 285
-#define T_OR 286
-#define T_AND 287
-#define T_EQUAL 288
-#define T_NOT 289
-
-
+#define yyparse         zconfparse
+#define yylex           zconflex
+#define yyerror         zconferror
+#define yylval          zconflval
+#define yychar          zconfchar
+#define yydebug         zconfdebug
+#define yynerrs         zconfnerrs
 
 
 /* Copy the first part of user declarations.  */
 #include <string.h>
 #include <stdbool.h>
 
-#define LKC_DIRECT_LINK
 #include "lkc.h"
 
-#include "zconf.hash.c"
-
 #define printd(mask, fmt...) if (cdebug & (mask)) printf(fmt)
 
 #define PRINTD         0x0001
@@ -176,21 +100,18 @@ 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(struct kconf_id *id, int starttoken, int endtoken);
+static bool zconf_endtoken(const struct kconf_id *id, int starttoken, int endtoken);
 
-struct symbol *symbol_hash[257];
+struct symbol *symbol_hash[SYMBOL_HASHSIZE];
 
 static struct menu *current_menu, *current_entry;
 
-#define YYDEBUG 0
-#if YYDEBUG
-#define YYERROR_VERBOSE
-#endif
+
 
 
 /* Enabling traces.  */
 #ifndef YYDEBUG
-# define YYDEBUG 0
+# define YYDEBUG 1
 #endif
 
 /* Enabling verbose error messages.  */
@@ -206,31 +127,78 @@ static struct menu *current_menu, *current_entry;
 # define YYTOKEN_TABLE 0
 #endif
 
+
+/* Tokens.  */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+   /* Put the tokens into the symbol table, so that GDB and other debuggers
+      know about them.  */
+   enum yytokentype {
+     T_MAINMENU = 258,
+     T_MENU = 259,
+     T_ENDMENU = 260,
+     T_SOURCE = 261,
+     T_CHOICE = 262,
+     T_ENDCHOICE = 263,
+     T_COMMENT = 264,
+     T_CONFIG = 265,
+     T_MENUCONFIG = 266,
+     T_HELP = 267,
+     T_HELPTEXT = 268,
+     T_IF = 269,
+     T_ENDIF = 270,
+     T_DEPENDS = 271,
+     T_OPTIONAL = 272,
+     T_PROMPT = 273,
+     T_TYPE = 274,
+     T_DEFAULT = 275,
+     T_SELECT = 276,
+     T_RANGE = 277,
+     T_VISIBLE = 278,
+     T_OPTION = 279,
+     T_ON = 280,
+     T_WORD = 281,
+     T_WORD_QUOTE = 282,
+     T_UNEQUAL = 283,
+     T_CLOSE_PAREN = 284,
+     T_OPEN_PAREN = 285,
+     T_EOL = 286,
+     T_OR = 287,
+     T_AND = 288,
+     T_EQUAL = 289,
+     T_NOT = 290
+   };
+#endif
+
+
+
 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
 typedef union YYSTYPE
-
 {
+
+
        char *string;
        struct file *file;
        struct symbol *symbol;
        struct expr *expr;
        struct menu *menu;
-       struct kconf_id *id;
-}
-/* Line 187 of yacc.c.  */
+       const struct kconf_id *id;
 
-       YYSTYPE;
+
+
+} YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
 # define YYSTYPE_IS_DECLARED 1
-# define YYSTYPE_IS_TRIVIAL 1
 #endif
 
 
-
 /* Copy the second part of user declarations.  */
 
 
-/* Line 216 of yacc.c.  */
+/* Include zconf.hash.c here so it can see the token constants. */
+#include "zconf.hash.c"
+
 
 
 #ifdef short
@@ -281,7 +249,7 @@ typedef short int yytype_int16;
 #define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
 
 #ifndef YY_
-# if YYENABLE_NLS
+# if defined YYENABLE_NLS && YYENABLE_NLS
 #  if ENABLE_NLS
 #   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
 #   define YY_(msgid) dgettext ("bison-runtime", msgid)
@@ -306,14 +274,14 @@ typedef short int yytype_int16;
 #if (defined __STDC__ || defined __C99__FUNC__ \
      || defined __cplusplus || defined _MSC_VER)
 static int
-YYID (int i)
+YYID (int yyi)
 #else
 static int
-YYID (i)
-    int i;
+YYID (yyi)
+    int yyi;
 #endif
 {
-  return i;
+  return yyi;
 }
 #endif
 
@@ -394,9 +362,9 @@ void free (void *); /* INFRINGES ON USER NAME SPACE */
 /* A type that is properly aligned for any stack member.  */
 union yyalloc
 {
-  yytype_int16 yyss;
-  YYSTYPE yyvs;
-  };
+  yytype_int16 yyss_alloc;
+  YYSTYPE yyvs_alloc;
+};
 
 /* The size of the maximum gap between one aligned stack and the next.  */
 # define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
@@ -430,12 +398,12 @@ union yyalloc
    elements in the stack, and YYPTR gives the new location of the
    stack.  Advance YYPTR to a properly aligned location for the next
    stack.  */
-# define YYSTACK_RELOCATE(Stack)                                       \
+# define YYSTACK_RELOCATE(Stack_alloc, Stack)                          \
     do                                                                 \
       {                                                                        \
        YYSIZE_T yynewbytes;                                            \
-       YYCOPY (&yyptr->Stack, Stack, yysize);                          \
-       Stack = &yyptr->Stack;                                          \
+       YYCOPY (&yyptr->Stack_alloc, Stack, yysize);                    \
+       Stack = &yyptr->Stack_alloc;                                    \
        yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
        yyptr += yynewbytes / sizeof (*yyptr);                          \
       }                                                                        \
@@ -444,22 +412,22 @@ union yyalloc
 #endif
 
 /* YYFINAL -- State number of the termination state.  */
-#define YYFINAL  3
+#define YYFINAL  11
 /* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   259
+#define YYLAST   290
 
 /* YYNTOKENS -- Number of terminals.  */
-#define YYNTOKENS  35
+#define YYNTOKENS  36
 /* YYNNTS -- Number of nonterminals.  */
-#define YYNNTS  46
+#define YYNNTS  50
 /* YYNRULES -- Number of rules.  */
-#define YYNRULES  110
+#define YYNRULES  118
 /* YYNRULES -- Number of states.  */
-#define YYNSTATES  180
+#define YYNSTATES  191
 
 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
 #define YYUNDEFTOK  2
-#define YYMAXUTOK   289
+#define YYMAXUTOK   290
 
 #define YYTRANSLATE(YYX)                                               \
   ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
@@ -495,7 +463,8 @@ static const yytype_uint8 yytranslate[] =
        2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
        5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
       15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
-      25,    26,    27,    28,    29,    30,    31,    32,    33,    34
+      25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
+      35
 };
 
 #if YYDEBUG
@@ -503,73 +472,75 @@ static const yytype_uint8 yytranslate[] =
    YYRHS.  */
 static const yytype_uint16 yyprhs[] =
 {
-       0,     0,     3,     5,     6,     9,    12,    15,    20,    23,
-      28,    33,    37,    39,    41,    43,    45,    47,    49,    51,
-      53,    55,    57,    59,    61,    63,    67,    70,    74,    77,
-      81,    84,    85,    88,    91,    94,    97,   100,   103,   107,
-     112,   117,   122,   128,   132,   133,   137,   138,   141,   145,
-     148,   150,   154,   155,   158,   161,   164,   167,   170,   175,
-     179,   182,   187,   188,   191,   195,   197,   201,   202,   205,
-     208,   211,   215,   218,   220,   224,   225,   228,   231,   234,
-     238,   242,   245,   248,   251,   252,   255,   258,   261,   266,
-     267,   270,   272,   274,   277,   280,   283,   285,   288,   289,
-     292,   294,   298,   302,   306,   309,   313,   317,   319,   321,
-     322
+       0,     0,     3,     6,     8,    11,    13,    14,    17,    20,
+      23,    26,    31,    36,    40,    42,    44,    46,    48,    50,
+      52,    54,    56,    58,    60,    62,    64,    66,    68,    72,
+      75,    79,    82,    86,    89,    90,    93,    96,    99,   102,
+     105,   108,   112,   117,   122,   127,   133,   137,   138,   142,
+     143,   146,   150,   153,   155,   159,   160,   163,   166,   169,
+     172,   175,   180,   184,   187,   192,   193,   196,   200,   202,
+     206,   207,   210,   213,   216,   220,   224,   228,   230,   234,
+     235,   238,   241,   244,   248,   252,   255,   258,   261,   262,
+     265,   268,   271,   276,   277,   280,   283,   286,   287,   290,
+     292,   294,   297,   300,   303,   305,   308,   309,   312,   314,
+     318,   322,   326,   329,   333,   337,   339,   341,   342
 };
 
 /* YYRHS -- A `-1'-separated list of the rules' RHS.  */
 static const yytype_int8 yyrhs[] =
 {
-      36,     0,    -1,    37,    -1,    -1,    37,    39,    -1,    37,
-      53,    -1,    37,    64,    -1,    37,     3,    74,    76,    -1,
-      37,    75,    -1,    37,    25,     1,    30,    -1,    37,    38,
-       1,    30,    -1,    37,     1,    30,    -1,    16,    -1,    18,
-      -1,    19,    -1,    21,    -1,    17,    -1,    22,    -1,    20,
-      -1,    30,    -1,    59,    -1,    68,    -1,    42,    -1,    44,
-      -1,    66,    -1,    25,     1,    30,    -1,     1,    30,    -1,
-      10,    25,    30,    -1,    41,    45,    -1,    11,    25,    30,
-      -1,    43,    45,    -1,    -1,    45,    46,    -1,    45,    47,
-      -1,    45,    72,    -1,    45,    70,    -1,    45,    40,    -1,
-      45,    30,    -1,    19,    73,    30,    -1,    18,    74,    77,
-      30,    -1,    20,    78,    77,    30,    -1,    21,    25,    77,
-      30,    -1,    22,    79,    79,    77,    30,    -1,    23,    48,
-      30,    -1,    -1,    48,    25,    49,    -1,    -1,    33,    74,
-      -1,     7,    80,    30,    -1,    50,    54,    -1,    75,    -1,
-      51,    56,    52,    -1,    -1,    54,    55,    -1,    54,    72,
-      -1,    54,    70,    -1,    54,    30,    -1,    54,    40,    -1,
-      18,    74,    77,    30,    -1,    19,    73,    30,    -1,    17,
-      30,    -1,    20,    25,    77,    30,    -1,    -1,    56,    39,
-      -1,    14,    78,    76,    -1,    75,    -1,    57,    60,    58,
-      -1,    -1,    60,    39,    -1,    60,    64,    -1,    60,    53,
-      -1,     4,    74,    30,    -1,    61,    71,    -1,    75,    -1,
-      62,    65,    63,    -1,    -1,    65,    39,    -1,    65,    64,
-      -1,    65,    53,    -1,     6,    74,    30,    -1,     9,    74,
-      30,    -1,    67,    71,    -1,    12,    30,    -1,    69,    13,
-      -1,    -1,    71,    72,    -1,    71,    30,    -1,    71,    40,
-      -1,    16,    24,    78,    30,    -1,    -1,    74,    77,    -1,
-      25,    -1,    26,    -1,     5,    30,    -1,     8,    30,    -1,
-      15,    30,    -1,    30,    -1,    76,    30,    -1,    -1,    14,
-      78,    -1,    79,    -1,    79,    33,    79,    -1,    79,    27,
-      79,    -1,    29,    78,    28,    -1,    34,    78,    -1,    78,
-      31,    78,    -1,    78,    32,    78,    -1,    25,    -1,    26,
-      -1,    -1,    25,    -1
+      37,     0,    -1,    81,    38,    -1,    38,    -1,    63,    39,
+      -1,    39,    -1,    -1,    39,    41,    -1,    39,    55,    -1,
+      39,    67,    -1,    39,    80,    -1,    39,    26,     1,    31,
+      -1,    39,    40,     1,    31,    -1,    39,     1,    31,    -1,
+      16,    -1,    18,    -1,    19,    -1,    21,    -1,    17,    -1,
+      22,    -1,    20,    -1,    23,    -1,    31,    -1,    61,    -1,
+      71,    -1,    44,    -1,    46,    -1,    69,    -1,    26,     1,
+      31,    -1,     1,    31,    -1,    10,    26,    31,    -1,    43,
+      47,    -1,    11,    26,    31,    -1,    45,    47,    -1,    -1,
+      47,    48,    -1,    47,    49,    -1,    47,    75,    -1,    47,
+      73,    -1,    47,    42,    -1,    47,    31,    -1,    19,    78,
+      31,    -1,    18,    79,    82,    31,    -1,    20,    83,    82,
+      31,    -1,    21,    26,    82,    31,    -1,    22,    84,    84,
+      82,    31,    -1,    24,    50,    31,    -1,    -1,    50,    26,
+      51,    -1,    -1,    34,    79,    -1,     7,    85,    31,    -1,
+      52,    56,    -1,    80,    -1,    53,    58,    54,    -1,    -1,
+      56,    57,    -1,    56,    75,    -1,    56,    73,    -1,    56,
+      31,    -1,    56,    42,    -1,    18,    79,    82,    31,    -1,
+      19,    78,    31,    -1,    17,    31,    -1,    20,    26,    82,
+      31,    -1,    -1,    58,    41,    -1,    14,    83,    81,    -1,
+      80,    -1,    59,    62,    60,    -1,    -1,    62,    41,    -1,
+      62,    67,    -1,    62,    55,    -1,     3,    79,    81,    -1,
+       4,    79,    31,    -1,    64,    76,    74,    -1,    80,    -1,
+      65,    68,    66,    -1,    -1,    68,    41,    -1,    68,    67,
+      -1,    68,    55,    -1,     6,    79,    31,    -1,     9,    79,
+      31,    -1,    70,    74,    -1,    12,    31,    -1,    72,    13,
+      -1,    -1,    74,    75,    -1,    74,    31,    -1,    74,    42,
+      -1,    16,    25,    83,    31,    -1,    -1,    76,    77,    -1,
+      76,    31,    -1,    23,    82,    -1,    -1,    79,    82,    -1,
+      26,    -1,    27,    -1,     5,    31,    -1,     8,    31,    -1,
+      15,    31,    -1,    31,    -1,    81,    31,    -1,    -1,    14,
+      83,    -1,    84,    -1,    84,    34,    84,    -1,    84,    28,
+      84,    -1,    30,    83,    29,    -1,    35,    83,    -1,    83,
+      32,    83,    -1,    83,    33,    83,    -1,    26,    -1,    27,
+      -1,    -1,    26,    -1
 };
 
 /* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
 static const yytype_uint16 yyrline[] =
 {
-       0,   104,   104,   106,   108,   109,   110,   111,   112,   113,
-     114,   118,   122,   122,   122,   122,   122,   122,   122,   126,
-     127,   128,   129,   130,   131,   135,   136,   142,   150,   156,
-     164,   174,   176,   177,   178,   179,   180,   181,   184,   192,
-     198,   208,   214,   220,   223,   225,   236,   237,   242,   251,
-     256,   264,   267,   269,   270,   271,   272,   273,   276,   282,
-     293,   299,   309,   311,   316,   324,   332,   335,   337,   338,
-     339,   344,   351,   356,   364,   367,   369,   370,   371,   374,
-     382,   389,   396,   402,   409,   411,   412,   413,   416,   424,
-     426,   431,   432,   435,   436,   437,   441,   442,   445,   446,
-     449,   450,   451,   452,   453,   454,   455,   458,   459,   462,
-     463
+       0,   104,   104,   104,   106,   106,   108,   110,   111,   112,
+     113,   114,   115,   119,   123,   123,   123,   123,   123,   123,
+     123,   123,   127,   128,   129,   130,   131,   132,   136,   137,
+     143,   151,   157,   165,   175,   177,   178,   179,   180,   181,
+     182,   185,   193,   199,   209,   215,   221,   224,   226,   237,
+     238,   243,   252,   257,   265,   268,   270,   271,   272,   273,
+     274,   277,   283,   294,   300,   310,   312,   317,   325,   333,
+     336,   338,   339,   340,   345,   352,   359,   364,   372,   375,
+     377,   378,   379,   382,   390,   397,   404,   410,   417,   419,
+     420,   421,   424,   432,   434,   435,   438,   445,   447,   452,
+     453,   456,   457,   458,   462,   463,   466,   467,   470,   471,
+     472,   473,   474,   475,   476,   479,   480,   483,   484
 };
 #endif
 
@@ -582,19 +553,19 @@ static const char *const yytname[] =
   "T_SOURCE", "T_CHOICE", "T_ENDCHOICE", "T_COMMENT", "T_CONFIG",
   "T_MENUCONFIG", "T_HELP", "T_HELPTEXT", "T_IF", "T_ENDIF", "T_DEPENDS",
   "T_OPTIONAL", "T_PROMPT", "T_TYPE", "T_DEFAULT", "T_SELECT", "T_RANGE",
-  "T_OPTION", "T_ON", "T_WORD", "T_WORD_QUOTE", "T_UNEQUAL",
+  "T_VISIBLE", "T_OPTION", "T_ON", "T_WORD", "T_WORD_QUOTE", "T_UNEQUAL",
   "T_CLOSE_PAREN", "T_OPEN_PAREN", "T_EOL", "T_OR", "T_AND", "T_EQUAL",
-  "T_NOT", "$accept", "input", "stmt_list", "option_name", "common_stmt",
-  "option_error", "config_entry_start", "config_stmt",
+  "T_NOT", "$accept", "input", "start", "stmt_list", "option_name",
+  "common_stmt", "option_error", "config_entry_start", "config_stmt",
   "menuconfig_entry_start", "menuconfig_stmt", "config_option_list",
   "config_option", "symbol_option", "symbol_option_list",
   "symbol_option_arg", "choice", "choice_entry", "choice_end",
   "choice_stmt", "choice_option_list", "choice_option", "choice_block",
-  "if_entry", "if_end", "if_stmt", "if_block", "menu", "menu_entry",
-  "menu_end", "menu_stmt", "menu_block", "source_stmt", "comment",
-  "comment_stmt", "help_start", "help", "depends_list", "depends",
-  "prompt_stmt_opt", "prompt", "end", "nl", "if_expr", "expr", "symbol",
-  "word_opt", 0
+  "if_entry", "if_end", "if_stmt", "if_block", "mainmenu_stmt", "menu",
+  "menu_entry", "menu_end", "menu_stmt", "menu_block", "source_stmt",
+  "comment", "comment_stmt", "help_start", "help", "depends_list",
+  "depends", "visibility_list", "visible", "prompt_stmt_opt", "prompt",
+  "end", "nl", "if_expr", "expr", "symbol", "word_opt", 0
 };
 #endif
 
@@ -606,42 +577,42 @@ static const yytype_uint16 yytoknum[] =
        0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
      265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
      275,   276,   277,   278,   279,   280,   281,   282,   283,   284,
-     285,   286,   287,   288,   289
+     285,   286,   287,   288,   289,   290
 };
 # endif
 
 /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
 static const yytype_uint8 yyr1[] =
 {
-       0,    35,    36,    37,    37,    37,    37,    37,    37,    37,
-      37,    37,    38,    38,    38,    38,    38,    38,    38,    39,
-      39,    39,    39,    39,    39,    40,    40,    41,    42,    43,
-      44,    45,    45,    45,    45,    45,    45,    45,    46,    46,
-      46,    46,    46,    47,    48,    48,    49,    49,    50,    51,
-      52,    53,    54,    54,    54,    54,    54,    54,    55,    55,
-      55,    55,    56,    56,    57,    58,    59,    60,    60,    60,
-      60,    61,    62,    63,    64,    65,    65,    65,    65,    66,
-      67,    68,    69,    70,    71,    71,    71,    71,    72,    73,
-      73,    74,    74,    75,    75,    75,    76,    76,    77,    77,
-      78,    78,    78,    78,    78,    78,    78,    79,    79,    80,
-      80
+       0,    36,    37,    37,    38,    38,    39,    39,    39,    39,
+      39,    39,    39,    39,    40,    40,    40,    40,    40,    40,
+      40,    40,    41,    41,    41,    41,    41,    41,    42,    42,
+      43,    44,    45,    46,    47,    47,    47,    47,    47,    47,
+      47,    48,    48,    48,    48,    48,    49,    50,    50,    51,
+      51,    52,    53,    54,    55,    56,    56,    56,    56,    56,
+      56,    57,    57,    57,    57,    58,    58,    59,    60,    61,
+      62,    62,    62,    62,    63,    64,    65,    66,    67,    68,
+      68,    68,    68,    69,    70,    71,    72,    73,    74,    74,
+      74,    74,    75,    76,    76,    76,    77,    78,    78,    79,
+      79,    80,    80,    80,    81,    81,    82,    82,    83,    83,
+      83,    83,    83,    83,    83,    84,    84,    85,    85
 };
 
 /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
 static const yytype_uint8 yyr2[] =
 {
-       0,     2,     1,     0,     2,     2,     2,     4,     2,     4,
-       4,     3,     1,     1,     1,     1,     1,     1,     1,     1,
-       1,     1,     1,     1,     1,     3,     2,     3,     2,     3,
-       2,     0,     2,     2,     2,     2,     2,     2,     3,     4,
-       4,     4,     5,     3,     0,     3,     0,     2,     3,     2,
-       1,     3,     0,     2,     2,     2,     2,     2,     4,     3,
-       2,     4,     0,     2,     3,     1,     3,     0,     2,     2,
-       2,     3,     2,     1,     3,     0,     2,     2,     2,     3,
-       3,     2,     2,     2,     0,     2,     2,     2,     4,     0,
-       2,     1,     1,     2,     2,     2,     1,     2,     0,     2,
-       1,     3,     3,     3,     2,     3,     3,     1,     1,     0,
-       1
+       0,     2,     2,     1,     2,     1,     0,     2,     2,     2,
+       2,     4,     4,     3,     1,     1,     1,     1,     1,     1,
+       1,     1,     1,     1,     1,     1,     1,     1,     3,     2,
+       3,     2,     3,     2,     0,     2,     2,     2,     2,     2,
+       2,     3,     4,     4,     4,     5,     3,     0,     3,     0,
+       2,     3,     2,     1,     3,     0,     2,     2,     2,     2,
+       2,     4,     3,     2,     4,     0,     2,     3,     1,     3,
+       0,     2,     2,     2,     3,     3,     3,     1,     3,     0,
+       2,     2,     2,     3,     3,     2,     2,     2,     0,     2,
+       2,     2,     4,     0,     2,     2,     2,     0,     2,     1,
+       1,     2,     2,     2,     1,     2,     0,     2,     1,     3,
+       3,     3,     2,     3,     3,     1,     1,     0,     1
 };
 
 /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
@@ -649,158 +620,172 @@ static const yytype_uint8 yyr2[] =
    means the default is an error.  */
 static const yytype_uint8 yydefact[] =
 {
-       3,     0,     0,     1,     0,     0,     0,     0,     0,   109,
-       0,     0,     0,     0,     0,     0,    12,    16,    13,    14,
-      18,    15,    17,     0,    19,     0,     4,    31,    22,    31,
-      23,    52,    62,     5,    67,    20,    84,    75,     6,    24,
-      84,    21,     8,    11,    91,    92,     0,     0,    93,     0,
-     110,     0,    94,     0,     0,     0,   107,   108,     0,     0,
-       0,   100,    95,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,    96,     7,    71,    79,    48,    80,    27,
-      29,     0,   104,     0,     0,    64,     0,     0,     9,    10,
-       0,     0,     0,     0,    89,     0,     0,     0,    44,     0,
-      37,    36,    32,    33,     0,    35,    34,     0,     0,    89,
-       0,    56,    57,    53,    55,    54,    63,    51,    50,    68,
-      70,    66,    69,    65,    86,    87,    85,    76,    78,    74,
-      77,    73,    97,   103,   105,   106,   102,   101,    26,    82,
-       0,    98,     0,    98,    98,    98,     0,     0,     0,    83,
-      60,    98,     0,    98,     0,     0,     0,    38,    90,     0,
-       0,    98,    46,    43,    25,     0,    59,     0,    88,    99,
-      39,    40,    41,     0,     0,    45,    58,    61,    42,    47
+       6,     0,   104,     0,     3,     0,     6,     6,    99,   100,
+       0,     1,     0,     0,     0,     0,   117,     0,     0,     0,
+       0,     0,     0,    14,    18,    15,    16,    20,    17,    19,
+      21,     0,    22,     0,     7,    34,    25,    34,    26,    55,
+      65,     8,    70,    23,    93,    79,     9,    27,    88,    24,
+      10,     0,   105,     2,    74,    13,     0,   101,     0,   118,
+       0,   102,     0,     0,     0,   115,   116,     0,     0,     0,
+     108,   103,     0,     0,     0,     0,     0,     0,     0,    88,
+       0,     0,    75,    83,    51,    84,    30,    32,     0,   112,
+       0,     0,    67,     0,     0,    11,    12,     0,     0,     0,
+       0,    97,     0,     0,     0,    47,     0,    40,    39,    35,
+      36,     0,    38,    37,     0,     0,    97,     0,    59,    60,
+      56,    58,    57,    66,    54,    53,    71,    73,    69,    72,
+      68,   106,    95,     0,    94,    80,    82,    78,    81,    77,
+      90,    91,    89,   111,   113,   114,   110,   109,    29,    86,
+       0,   106,     0,   106,   106,   106,     0,     0,     0,    87,
+      63,   106,     0,   106,     0,    96,     0,     0,    41,    98,
+       0,     0,   106,    49,    46,    28,     0,    62,     0,   107,
+      92,    42,    43,    44,     0,     0,    48,    61,    64,    45,
+      50
 };
 
 /* YYDEFGOTO[NTERM-NUM].  */
 static const yytype_int16 yydefgoto[] =
 {
-      -1,     1,     2,    25,    26,   101,    27,    28,    29,    30,
-      65,   102,   103,   147,   175,    31,    32,   117,    33,    67,
-     113,    68,    34,   121,    35,    69,    36,    37,   129,    38,
-      71,    39,    40,    41,   104,   105,    70,   106,   142,   143,
-      42,    74,   156,    60,    61,    51
+      -1,     3,     4,     5,    33,    34,   108,    35,    36,    37,
+      38,    74,   109,   110,   157,   186,    39,    40,   124,    41,
+      76,   120,    77,    42,   128,    43,    78,     6,    44,    45,
+     137,    46,    80,    47,    48,    49,   111,   112,    81,   113,
+      79,   134,   152,   153,    50,     7,   165,    69,    70,    60
 };
 
 /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
    STATE-NUM.  */
-#define YYPACT_NINF -80
+#define YYPACT_NINF -90
 static const yytype_int16 yypact[] =
 {
-     -80,     2,   132,   -80,   -13,    -1,    -1,    -2,    -1,     9,
-      33,    -1,    27,    40,    -3,    38,   -80,   -80,   -80,   -80,
-     -80,   -80,   -80,    71,   -80,    77,   -80,   -80,   -80,   -80,
-     -80,   -80,   -80,   -80,   -80,   -80,   -80,   -80,   -80,   -80,
-     -80,   -80,   -80,   -80,   -80,   -80,    57,    61,   -80,    63,
-     -80,    76,   -80,    87,   101,   133,   -80,   -80,    -3,    -3,
-     195,    -6,   -80,   136,   149,    39,   104,    65,   150,     5,
-     194,     5,   167,   -80,   176,   -80,   -80,   -80,   -80,   -80,
-     -80,    68,   -80,    -3,    -3,   176,    72,    72,   -80,   -80,
-     177,   187,    78,    -1,    -1,    -3,   196,    72,   -80,   222,
-     -80,   -80,   -80,   -80,   221,   -80,   -80,   205,    -1,    -1,
-     211,   -80,   -80,   -80,   -80,   -80,   -80,   -80,   -80,   -80,
-     -80,   -80,   -80,   -80,   -80,   -80,   -80,   -80,   -80,   -80,
-     -80,   -80,   -80,   -80,   206,   -80,   -80,   -80,   -80,   -80,
-      -3,   223,   209,   223,   197,   223,    72,     7,   210,   -80,
-     -80,   223,   212,   223,   201,    -3,   213,   -80,   -80,   214,
-     215,   223,   208,   -80,   -80,   216,   -80,   217,   -80,   113,
-     -80,   -80,   -80,   218,    -1,   -80,   -80,   -80,   -80,   -80
+       4,    42,   -90,    96,   -90,   111,   -90,    15,   -90,   -90,
+      75,   -90,    82,    42,   104,    42,   110,   107,    42,   115,
+     125,    -4,   121,   -90,   -90,   -90,   -90,   -90,   -90,   -90,
+     -90,   162,   -90,   163,   -90,   -90,   -90,   -90,   -90,   -90,
+     -90,   -90,   -90,   -90,   -90,   -90,   -90,   -90,   -90,   -90,
+     -90,   139,   -90,   -90,   138,   -90,   142,   -90,   143,   -90,
+     152,   -90,   164,   167,   168,   -90,   -90,    -4,    -4,    77,
+     -18,   -90,   177,   185,    33,    71,   195,   247,   236,    -2,
+     236,   171,   -90,   -90,   -90,   -90,   -90,   -90,    41,   -90,
+      -4,    -4,   138,    97,    97,   -90,   -90,   186,   187,   194,
+      42,    42,    -4,   196,    97,   -90,   219,   -90,   -90,   -90,
+     -90,   210,   -90,   -90,   204,    42,    42,   199,   -90,   -90,
+     -90,   -90,   -90,   -90,   -90,   -90,   -90,   -90,   -90,   -90,
+     -90,   222,   -90,   223,   -90,   -90,   -90,   -90,   -90,   -90,
+     -90,   -90,   -90,   -90,   215,   -90,   -90,   -90,   -90,   -90,
+      -4,   222,   228,   222,    -5,   222,    97,    35,   229,   -90,
+     -90,   222,   232,   222,    -4,   -90,   135,   233,   -90,   -90,
+     234,   235,   222,   240,   -90,   -90,   237,   -90,   239,   -13,
+     -90,   -90,   -90,   -90,   244,    42,   -90,   -90,   -90,   -90,
+     -90
 };
 
 /* YYPGOTO[NTERM-NUM].  */
 static const yytype_int16 yypgoto[] =
 {
-     -80,   -80,   -80,   -80,   122,   -34,   -80,   -80,   -80,   -80,
-     220,   -80,   -80,   -80,   -80,   -80,   -80,   -80,    59,   -80,
-     -80,   -80,   -80,   -80,   -80,   -80,   -80,   -80,   -80,   125,
-     -80,   -80,   -80,   -80,   -80,   183,   219,    22,   142,    -5,
-     147,   192,    69,   -54,   -79,   -80
+     -90,   -90,   269,   271,   -90,    23,   -70,   -90,   -90,   -90,
+     -90,   243,   -90,   -90,   -90,   -90,   -90,   -90,   -90,   -48,
+     -90,   -90,   -90,   -90,   -90,   -90,   -90,   -90,   -90,   -90,
+     -90,   -20,   -90,   -90,   -90,   -90,   -90,   206,   205,   -68,
+     -90,   -90,   169,    -1,    27,    -7,   118,   -66,   -89,   -90
 };
 
 /* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
    positive, shift that token.  If negative, reduce the rule which
    number is the opposite.  If zero, do what YYDEFACT says.
    If YYTABLE_NINF, syntax error.  */
-#define YYTABLE_NINF -82
+#define YYTABLE_NINF -86
 static const yytype_int16 yytable[] =
 {
-      46,    47,     3,    49,    81,    82,    53,   136,   137,     6,
-       7,     8,     9,    10,    11,    12,    13,    43,   146,    14,
-      15,    86,    56,    57,    44,    45,    58,    87,    48,   134,
-     135,    59,   162,   112,    50,    24,   125,   163,   125,   -28,
-      90,   144,   -28,   -28,   -28,   -28,   -28,   -28,   -28,   -28,
-     -28,    91,    54,   -28,   -28,    92,   -28,    93,    94,    95,
-      96,    97,    98,    52,    99,    55,    90,   161,    62,   100,
-     -49,   -49,    63,   -49,   -49,   -49,   -49,    91,    64,   -49,
-     -49,    92,   107,   108,   109,   110,   154,    73,   141,   115,
-      99,    75,   126,    76,   126,   111,   133,    56,    57,    83,
-      84,   169,   140,   151,   -30,    90,    77,   -30,   -30,   -30,
-     -30,   -30,   -30,   -30,   -30,   -30,    91,    78,   -30,   -30,
-      92,   -30,    93,    94,    95,    96,    97,    98,   120,    99,
-     128,    79,    -2,     4,   100,     5,     6,     7,     8,     9,
-      10,    11,    12,    13,    83,    84,    14,    15,    16,    17,
-      18,    19,    20,    21,    22,     7,     8,    23,    10,    11,
-      12,    13,    24,    80,    14,    15,    88,   -81,    90,   179,
-     -81,   -81,   -81,   -81,   -81,   -81,   -81,   -81,   -81,    89,
-      24,   -81,   -81,    92,   -81,   -81,   -81,   -81,   -81,   -81,
-     116,   119,    99,   127,   122,    90,   130,   124,   -72,   -72,
-     -72,   -72,   -72,   -72,   -72,   -72,   132,   138,   -72,   -72,
-      92,   155,   158,   159,   160,   118,   123,   139,   131,    99,
-     165,   145,   167,   148,   124,    73,    83,    84,    83,    84,
-     173,   168,    83,    84,   149,   150,   153,   155,    84,   157,
-     164,   174,   166,   170,   171,   172,   176,   177,   178,    66,
-     114,   152,    85,     0,     0,     0,     0,     0,     0,    72
+      10,    88,    89,    54,   146,   147,   119,     1,   122,   164,
+      93,   141,    56,   142,    58,   156,    94,    62,     1,    90,
+      91,   131,    65,    66,   144,   145,    67,    90,    91,   132,
+     127,    68,   136,   -31,    97,     2,   154,   -31,   -31,   -31,
+     -31,   -31,   -31,   -31,   -31,    98,    52,   -31,   -31,    99,
+     -31,   100,   101,   102,   103,   104,   -31,   105,   129,   106,
+     138,   173,    92,   141,   107,   142,   174,   172,     8,     9,
+     143,   -33,    97,    90,    91,   -33,   -33,   -33,   -33,   -33,
+     -33,   -33,   -33,    98,   166,   -33,   -33,    99,   -33,   100,
+     101,   102,   103,   104,   -33,   105,    11,   106,   179,   151,
+     123,   126,   107,   135,   125,   130,     2,   139,     2,    90,
+      91,    -5,    12,    55,   161,    13,    14,    15,    16,    17,
+      18,    19,    20,    65,    66,    21,    22,    23,    24,    25,
+      26,    27,    28,    29,    30,    57,    59,    31,    61,    -4,
+      12,    63,    32,    13,    14,    15,    16,    17,    18,    19,
+      20,    64,    71,    21,    22,    23,    24,    25,    26,    27,
+      28,    29,    30,    72,    73,    31,   180,    90,    91,    52,
+      32,   -85,    97,    82,    83,   -85,   -85,   -85,   -85,   -85,
+     -85,   -85,   -85,    84,   190,   -85,   -85,    99,   -85,   -85,
+     -85,   -85,   -85,   -85,   -85,    85,    97,   106,    86,    87,
+     -52,   -52,   140,   -52,   -52,   -52,   -52,    98,    95,   -52,
+     -52,    99,   114,   115,   116,   117,    96,   148,   149,   150,
+     158,   106,   155,   159,    97,   163,   118,   -76,   -76,   -76,
+     -76,   -76,   -76,   -76,   -76,   160,   164,   -76,   -76,    99,
+      13,    14,    15,    16,    17,    18,    19,    20,    91,   106,
+      21,    22,    14,    15,   140,    17,    18,    19,    20,   168,
+     175,    21,    22,   177,   181,   182,   183,    32,   187,   167,
+     188,   169,   170,   171,   185,   189,    53,    51,    32,   176,
+      75,   178,   121,     0,   133,   162,     0,     0,     0,     0,
+     184
 };
 
 static const yytype_int16 yycheck[] =
 {
-       5,     6,     0,     8,    58,    59,    11,    86,    87,     4,
-       5,     6,     7,     8,     9,    10,    11,    30,    97,    14,
-      15,    27,    25,    26,    25,    26,    29,    33,    30,    83,
-      84,    34,    25,    67,    25,    30,    70,    30,    72,     0,
-       1,    95,     3,     4,     5,     6,     7,     8,     9,    10,
-      11,    12,    25,    14,    15,    16,    17,    18,    19,    20,
-      21,    22,    23,    30,    25,    25,     1,   146,    30,    30,
-       5,     6,     1,     8,     9,    10,    11,    12,     1,    14,
-      15,    16,    17,    18,    19,    20,   140,    30,    93,    67,
-      25,    30,    70,    30,    72,    30,    28,    25,    26,    31,
-      32,   155,    24,   108,     0,     1,    30,     3,     4,     5,
-       6,     7,     8,     9,    10,    11,    12,    30,    14,    15,
-      16,    17,    18,    19,    20,    21,    22,    23,    69,    25,
-      71,    30,     0,     1,    30,     3,     4,     5,     6,     7,
-       8,     9,    10,    11,    31,    32,    14,    15,    16,    17,
-      18,    19,    20,    21,    22,     5,     6,    25,     8,     9,
-      10,    11,    30,    30,    14,    15,    30,     0,     1,   174,
-       3,     4,     5,     6,     7,     8,     9,    10,    11,    30,
-      30,    14,    15,    16,    17,    18,    19,    20,    21,    22,
-      68,    69,    25,    71,    69,     1,    71,    30,     4,     5,
-       6,     7,     8,     9,    10,    11,    30,    30,    14,    15,
-      16,    14,   143,   144,   145,    68,    69,    30,    71,    25,
-     151,    25,   153,     1,    30,    30,    31,    32,    31,    32,
-     161,    30,    31,    32,    13,    30,    25,    14,    32,    30,
-      30,    33,    30,    30,    30,    30,    30,    30,    30,    29,
-      67,   109,    60,    -1,    -1,    -1,    -1,    -1,    -1,    40
+       1,    67,    68,    10,    93,    94,    76,     3,    76,    14,
+      28,    81,    13,    81,    15,   104,    34,    18,     3,    32,
+      33,    23,    26,    27,    90,    91,    30,    32,    33,    31,
+      78,    35,    80,     0,     1,    31,   102,     4,     5,     6,
+       7,     8,     9,    10,    11,    12,    31,    14,    15,    16,
+      17,    18,    19,    20,    21,    22,    23,    24,    78,    26,
+      80,    26,    69,   133,    31,   133,    31,   156,    26,    27,
+      29,     0,     1,    32,    33,     4,     5,     6,     7,     8,
+       9,    10,    11,    12,   150,    14,    15,    16,    17,    18,
+      19,    20,    21,    22,    23,    24,     0,    26,   164,   100,
+      77,    78,    31,    80,    77,    78,    31,    80,    31,    32,
+      33,     0,     1,    31,   115,     4,     5,     6,     7,     8,
+       9,    10,    11,    26,    27,    14,    15,    16,    17,    18,
+      19,    20,    21,    22,    23,    31,    26,    26,    31,     0,
+       1,    26,    31,     4,     5,     6,     7,     8,     9,    10,
+      11,    26,    31,    14,    15,    16,    17,    18,    19,    20,
+      21,    22,    23,     1,     1,    26,    31,    32,    33,    31,
+      31,     0,     1,    31,    31,     4,     5,     6,     7,     8,
+       9,    10,    11,    31,   185,    14,    15,    16,    17,    18,
+      19,    20,    21,    22,    23,    31,     1,    26,    31,    31,
+       5,     6,    31,     8,     9,    10,    11,    12,    31,    14,
+      15,    16,    17,    18,    19,    20,    31,    31,    31,    25,
+       1,    26,    26,    13,     1,    26,    31,     4,     5,     6,
+       7,     8,     9,    10,    11,    31,    14,    14,    15,    16,
+       4,     5,     6,     7,     8,     9,    10,    11,    33,    26,
+      14,    15,     5,     6,    31,     8,     9,    10,    11,    31,
+      31,    14,    15,    31,    31,    31,    31,    31,    31,   151,
+      31,   153,   154,   155,    34,    31,     7,     6,    31,   161,
+      37,   163,    76,    -1,    79,   116,    -1,    -1,    -1,    -1,
+     172
 };
 
 /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
    symbol of state STATE-NUM.  */
 static const yytype_uint8 yystos[] =
 {
-       0,    36,    37,     0,     1,     3,     4,     5,     6,     7,
-       8,     9,    10,    11,    14,    15,    16,    17,    18,    19,
-      20,    21,    22,    25,    30,    38,    39,    41,    42,    43,
-      44,    50,    51,    53,    57,    59,    61,    62,    64,    66,
-      67,    68,    75,    30,    25,    26,    74,    74,    30,    74,
-      25,    80,    30,    74,    25,    25,    25,    26,    29,    34,
-      78,    79,    30,     1,     1,    45,    45,    54,    56,    60,
-      71,    65,    71,    30,    76,    30,    30,    30,    30,    30,
-      30,    78,    78,    31,    32,    76,    27,    33,    30,    30,
-       1,    12,    16,    18,    19,    20,    21,    22,    23,    25,
-      30,    40,    46,    47,    69,    70,    72,    17,    18,    19,
-      20,    30,    40,    55,    70,    72,    39,    52,    75,    39,
-      53,    58,    64,    75,    30,    40,    72,    39,    53,    63,
-      64,    75,    30,    28,    78,    78,    79,    79,    30,    30,
-      24,    74,    73,    74,    78,    25,    79,    48,     1,    13,
-      30,    74,    73,    25,    78,    14,    77,    30,    77,    77,
-      77,    79,    25,    30,    30,    77,    30,    77,    30,    78,
-      30,    30,    30,    77,    33,    49,    30,    30,    30,    74
+       0,     3,    31,    37,    38,    39,    63,    81,    26,    27,
+      79,     0,     1,     4,     5,     6,     7,     8,     9,    10,
+      11,    14,    15,    16,    17,    18,    19,    20,    21,    22,
+      23,    26,    31,    40,    41,    43,    44,    45,    46,    52,
+      53,    55,    59,    61,    64,    65,    67,    69,    70,    71,
+      80,    39,    31,    38,    81,    31,    79,    31,    79,    26,
+      85,    31,    79,    26,    26,    26,    27,    30,    35,    83,
+      84,    31,     1,     1,    47,    47,    56,    58,    62,    76,
+      68,    74,    31,    31,    31,    31,    31,    31,    83,    83,
+      32,    33,    81,    28,    34,    31,    31,     1,    12,    16,
+      18,    19,    20,    21,    22,    24,    26,    31,    42,    48,
+      49,    72,    73,    75,    17,    18,    19,    20,    31,    42,
+      57,    73,    75,    41,    54,    80,    41,    55,    60,    67,
+      80,    23,    31,    74,    77,    41,    55,    66,    67,    80,
+      31,    42,    75,    29,    83,    83,    84,    84,    31,    31,
+      25,    79,    78,    79,    83,    26,    84,    50,     1,    13,
+      31,    79,    78,    26,    14,    82,    83,    82,    31,    82,
+      82,    82,    84,    26,    31,    31,    82,    31,    82,    83,
+      31,    31,    31,    31,    82,    34,    51,    31,    31,    31,
+      79
 };
 
 #define yyerrok                (yyerrstatus = 0)
@@ -815,9 +800,18 @@ static const yytype_uint8 yystos[] =
 
 /* Like YYERROR except do call yyerror.  This remains here temporarily
    to ease the transition to the new meaning of YYERROR, for GCC.
-   Once GCC version 2 has supplanted version 1, this can go.  */
+   Once GCC version 2 has supplanted version 1, this can go.  However,
+   YYFAIL appears to be in use.  Nevertheless, it is formally deprecated
+   in Bison 2.4.2's NEWS entry, where a plan to phase it out is
+   discussed.  */
 
 #define YYFAIL         goto yyerrlab
+#if defined YYFAIL
+  /* This is here to suppress warnings from the GCC cpp's
+     -Wunused-macros.  Normally we don't worry about that warning, but
+     some users do, and we want to make it easy for users to remove
+     YYFAIL uses, which will produce warnings from Bison 2.5.  */
+#endif
 
 #define YYRECOVERING()  (!!yyerrstatus)
 
@@ -874,7 +868,7 @@ while (YYID (0))
    we won't break user code: when these are the locations we know.  */
 
 #ifndef YY_LOCATION_PRINT
-# if YYLTYPE_IS_TRIVIAL
+# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
 #  define YY_LOCATION_PRINT(File, Loc)                 \
      fprintf (File, "%d.%d-%d.%d",                     \
              (Loc).first_line, (Loc).first_column,     \
@@ -985,17 +979,20 @@ yy_symbol_print (yyoutput, yytype, yyvaluep)
 #if (defined __STDC__ || defined __C99__FUNC__ \
      || defined __cplusplus || defined _MSC_VER)
 static void
-yy_stack_print (yytype_int16 *bottom, yytype_int16 *top)
+yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
 #else
 static void
-yy_stack_print (bottom, top)
-    yytype_int16 *bottom;
-    yytype_int16 *top;
+yy_stack_print (yybottom, yytop)
+    yytype_int16 *yybottom;
+    yytype_int16 *yytop;
 #endif
 {
   YYFPRINTF (stderr, "Stack now");
-  for (; bottom <= top; ++bottom)
-    YYFPRINTF (stderr, " %d", *bottom);
+  for (; yybottom <= yytop; yybottom++)
+    {
+      int yybot = *yybottom;
+      YYFPRINTF (stderr, " %d", yybot);
+    }
   YYFPRINTF (stderr, "\n");
 }
 
@@ -1029,11 +1026,11 @@ yy_reduce_print (yyvsp, yyrule)
   /* The symbols being reduced.  */
   for (yyi = 0; yyi < yynrhs; yyi++)
     {
-      fprintf (stderr, "   $%d = ", yyi + 1);
+      YYFPRINTF (stderr, "   $%d = ", yyi + 1);
       yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
                       &(yyvsp[(yyi + 1) - (yynrhs)])
                                       );
-      fprintf (stderr, "\n");
+      YYFPRINTF (stderr, "\n");
     }
 }
 
@@ -1308,7 +1305,7 @@ yydestruct (yymsg, yytype, yyvaluep)
 
   switch (yytype)
     {
-      case 51: /* "choice_entry" */
+      case 53: /* "choice_entry" */
 
        {
        fprintf(stderr, "%s:%d: missing end statement for this entry\n",
@@ -1318,7 +1315,7 @@ yydestruct (yymsg, yytype, yyvaluep)
 };
 
        break;
-      case 57: /* "if_entry" */
+      case 59: /* "if_entry" */
 
        {
        fprintf(stderr, "%s:%d: missing end statement for this entry\n",
@@ -1328,7 +1325,7 @@ yydestruct (yymsg, yytype, yyvaluep)
 };
 
        break;
-      case 62: /* "menu_entry" */
+      case 65: /* "menu_entry" */
 
        {
        fprintf(stderr, "%s:%d: missing end statement for this entry\n",
@@ -1343,10 +1340,8 @@ yydestruct (yymsg, yytype, yyvaluep)
        break;
     }
 }
-\f
 
 /* Prevent warnings from -Wmissing-prototypes.  */
-
 #ifdef YYPARSE_PARAM
 #if defined __STDC__ || defined __cplusplus
 int yyparse (void *YYPARSE_PARAM);
@@ -1362,11 +1357,10 @@ int yyparse ();
 #endif /* ! YYPARSE_PARAM */
 
 
-
-/* The look-ahead symbol.  */
+/* The lookahead symbol.  */
 int yychar;
 
-/* The semantic value of the look-ahead symbol.  */
+/* The semantic value of the lookahead symbol.  */
 YYSTYPE yylval;
 
 /* Number of syntax errors so far.  */
@@ -1374,9 +1368,9 @@ int yynerrs;
 
 
 
-/*----------.
-| yyparse.  |
-`----------*/
+/*-------------------------.
+| yyparse or yypush_parse.  |
+`-------------------------*/
 
 #ifdef YYPARSE_PARAM
 #if (defined __STDC__ || defined __C99__FUNC__ \
@@ -1400,66 +1394,68 @@ yyparse ()
 #endif
 #endif
 {
-  
-  int yystate;
-  int yyn;
-  int yyresult;
-  /* Number of tokens to shift before error messages enabled.  */
-  int yyerrstatus;
-  /* Look-ahead token as an internal (translated) token number.  */
-  int yytoken = 0;
-#if YYERROR_VERBOSE
-  /* Buffer for error messages, and its allocated size.  */
-  char yymsgbuf[128];
-  char *yymsg = yymsgbuf;
-  YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
-#endif
 
-  /* Three stacks and their tools:
-     `yyss': related to states,
-     `yyvs': related to semantic values,
-     `yyls': related to locations.
 
-     Refer to the stacks thru separate pointers, to allow yyoverflow
-     to reallocate them elsewhere.  */
+    int yystate;
+    /* Number of tokens to shift before error messages enabled.  */
+    int yyerrstatus;
 
-  /* The state stack.  */
-  yytype_int16 yyssa[YYINITDEPTH];
-  yytype_int16 *yyss = yyssa;
-  yytype_int16 *yyssp;
+    /* The stacks and their tools:
+       `yyss': related to states.
+       `yyvs': related to semantic values.
 
-  /* The semantic value stack.  */
-  YYSTYPE yyvsa[YYINITDEPTH];
-  YYSTYPE *yyvs = yyvsa;
-  YYSTYPE *yyvsp;
+       Refer to the stacks thru separate pointers, to allow yyoverflow
+       to reallocate them elsewhere.  */
 
+    /* The state stack.  */
+    yytype_int16 yyssa[YYINITDEPTH];
+    yytype_int16 *yyss;
+    yytype_int16 *yyssp;
 
+    /* The semantic value stack.  */
+    YYSTYPE yyvsa[YYINITDEPTH];
+    YYSTYPE *yyvs;
+    YYSTYPE *yyvsp;
 
-#define YYPOPSTACK(N)   (yyvsp -= (N), yyssp -= (N))
-
-  YYSIZE_T yystacksize = YYINITDEPTH;
+    YYSIZE_T yystacksize;
 
+  int yyn;
+  int yyresult;
+  /* Lookahead token as an internal (translated) token number.  */
+  int yytoken;
   /* The variables used to return semantic value and location from the
      action routines.  */
   YYSTYPE yyval;
 
+#if YYERROR_VERBOSE
+  /* Buffer for error messages, and its allocated size.  */
+  char yymsgbuf[128];
+  char *yymsg = yymsgbuf;
+  YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
+#endif
+
+#define YYPOPSTACK(N)   (yyvsp -= (N), yyssp -= (N))
 
   /* The number of symbols on the RHS of the reduced rule.
      Keep to zero when no symbol should be popped.  */
   int yylen = 0;
 
+  yytoken = 0;
+  yyss = yyssa;
+  yyvs = yyvsa;
+  yystacksize = YYINITDEPTH;
+
   YYDPRINTF ((stderr, "Starting parse\n"));
 
   yystate = 0;
   yyerrstatus = 0;
   yynerrs = 0;
-  yychar = YYEMPTY;            /* Cause a token to be read.  */
+  yychar = YYEMPTY; /* Cause a token to be read.  */
 
   /* Initialize stack pointers.
      Waste one element of value and location stack
      so that they stay on the same level as the state stack.
      The wasted elements are never initialized.  */
-
   yyssp = yyss;
   yyvsp = yyvs;
 
@@ -1489,7 +1485,6 @@ yyparse ()
        YYSTYPE *yyvs1 = yyvs;
        yytype_int16 *yyss1 = yyss;
 
-
        /* Each stack pointer address is followed by the size of the
           data in use in that stack, in bytes.  This used to be a
           conditional around just the two extra args, but that might
@@ -1497,7 +1492,6 @@ yyparse ()
        yyoverflow (YY_("memory exhausted"),
                    &yyss1, yysize * sizeof (*yyssp),
                    &yyvs1, yysize * sizeof (*yyvsp),
-
                    &yystacksize);
 
        yyss = yyss1;
@@ -1520,9 +1514,8 @@ yyparse ()
          (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
        if (! yyptr)
          goto yyexhaustedlab;
-       YYSTACK_RELOCATE (yyss);
-       YYSTACK_RELOCATE (yyvs);
-
+       YYSTACK_RELOCATE (yyss_alloc, yyss);
+       YYSTACK_RELOCATE (yyvs_alloc, yyvs);
 #  undef YYSTACK_RELOCATE
        if (yyss1 != yyssa)
          YYSTACK_FREE (yyss1);
@@ -1533,7 +1526,6 @@ yyparse ()
       yyssp = yyss + yysize - 1;
       yyvsp = yyvs + yysize - 1;
 
-
       YYDPRINTF ((stderr, "Stack size increased to %lu\n",
                  (unsigned long int) yystacksize));
 
@@ -1543,6 +1535,9 @@ yyparse ()
 
   YYDPRINTF ((stderr, "Entering state %d\n", yystate));
 
+  if (yystate == YYFINAL)
+    YYACCEPT;
+
   goto yybackup;
 
 /*-----------.
@@ -1551,16 +1546,16 @@ yyparse ()
 yybackup:
 
   /* Do appropriate processing given the current state.  Read a
-     look-ahead token if we need one and don't already have one.  */
+     lookahead token if we need one and don't already have one.  */
 
-  /* First try to decide what to do without reference to look-ahead token.  */
+  /* First try to decide what to do without reference to lookahead token.  */
   yyn = yypact[yystate];
   if (yyn == YYPACT_NINF)
     goto yydefault;
 
-  /* Not known => get a look-ahead token if don't already have one.  */
+  /* Not known => get a lookahead token if don't already have one.  */
 
-  /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol.  */
+  /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol.  */
   if (yychar == YYEMPTY)
     {
       YYDPRINTF ((stderr, "Reading a token: "));
@@ -1592,20 +1587,16 @@ yybackup:
       goto yyreduce;
     }
 
-  if (yyn == YYFINAL)
-    YYACCEPT;
-
   /* Count tokens shifted since error; after three, turn off error
      status.  */
   if (yyerrstatus)
     yyerrstatus--;
 
-  /* Shift the look-ahead token.  */
+  /* Shift the lookahead token.  */
   YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
 
-  /* Discard the shifted token unless it is eof.  */
-  if (yychar != YYEOF)
-    yychar = YYEMPTY;
+  /* Discard the shifted token.  */
+  yychar = YYEMPTY;
 
   yystate = yyn;
   *++yyvsp = yylval;
@@ -1644,39 +1635,39 @@ yyreduce:
   YY_REDUCE_PRINT (yyn);
   switch (yyn)
     {
-        case 8:
+        case 10:
 
     { zconf_error("unexpected end statement"); ;}
     break;
 
-  case 9:
+  case 11:
 
     { zconf_error("unknown statement \"%s\"", (yyvsp[(2) - (4)].string)); ;}
     break;
 
-  case 10:
+  case 12:
 
     {
        zconf_error("unexpected option \"%s\"", kconf_id_strings + (yyvsp[(2) - (4)].id)->name);
 ;}
     break;
 
-  case 11:
+  case 13:
 
     { zconf_error("invalid statement"); ;}
     break;
 
-  case 25:
+  case 28:
 
     { zconf_error("unknown option \"%s\"", (yyvsp[(1) - (3)].string)); ;}
     break;
 
-  case 26:
+  case 29:
 
     { zconf_error("invalid option"); ;}
     break;
 
-  case 27:
+  case 30:
 
     {
        struct symbol *sym = sym_lookup((yyvsp[(2) - (3)].string), 0);
@@ -1686,7 +1677,7 @@ yyreduce:
 ;}
     break;
 
-  case 28:
+  case 31:
 
     {
        menu_end_entry();
@@ -1694,7 +1685,7 @@ yyreduce:
 ;}
     break;
 
-  case 29:
+  case 32:
 
     {
        struct symbol *sym = sym_lookup((yyvsp[(2) - (3)].string), 0);
@@ -1704,7 +1695,7 @@ yyreduce:
 ;}
     break;
 
-  case 30:
+  case 33:
 
     {
        if (current_entry->prompt)
@@ -1716,7 +1707,7 @@ yyreduce:
 ;}
     break;
 
-  case 38:
+  case 41:
 
     {
        menu_set_type((yyvsp[(1) - (3)].id)->stype);
@@ -1726,7 +1717,7 @@ yyreduce:
 ;}
     break;
 
-  case 39:
+  case 42:
 
     {
        menu_add_prompt(P_PROMPT, (yyvsp[(2) - (4)].string), (yyvsp[(3) - (4)].expr));
@@ -1734,7 +1725,7 @@ yyreduce:
 ;}
     break;
 
-  case 40:
+  case 43:
 
     {
        menu_add_expr(P_DEFAULT, (yyvsp[(2) - (4)].expr), (yyvsp[(3) - (4)].expr));
@@ -1746,7 +1737,7 @@ yyreduce:
 ;}
     break;
 
-  case 41:
+  case 44:
 
     {
        menu_add_symbol(P_SELECT, sym_lookup((yyvsp[(2) - (4)].string), 0), (yyvsp[(3) - (4)].expr));
@@ -1754,7 +1745,7 @@ yyreduce:
 ;}
     break;
 
-  case 42:
+  case 45:
 
     {
        menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,(yyvsp[(2) - (5)].symbol), (yyvsp[(3) - (5)].symbol)), (yyvsp[(4) - (5)].expr));
@@ -1762,10 +1753,10 @@ yyreduce:
 ;}
     break;
 
-  case 45:
+  case 48:
 
     {
-       struct kconf_id *id = kconf_id_lookup((yyvsp[(2) - (3)].string), strlen((yyvsp[(2) - (3)].string)));
+       const struct kconf_id *id = kconf_id_lookup((yyvsp[(2) - (3)].string), strlen((yyvsp[(2) - (3)].string)));
        if (id && id->flags & TF_OPTION)
                menu_add_option(id->token, (yyvsp[(3) - (3)].string));
        else
@@ -1774,17 +1765,17 @@ yyreduce:
 ;}
     break;
 
-  case 46:
+  case 49:
 
     { (yyval.string) = NULL; ;}
     break;
 
-  case 47:
+  case 50:
 
     { (yyval.string) = (yyvsp[(2) - (2)].string); ;}
     break;
 
-  case 48:
+  case 51:
 
     {
        struct symbol *sym = sym_lookup((yyvsp[(2) - (3)].string), SYMBOL_CHOICE);
@@ -1795,14 +1786,14 @@ yyreduce:
 ;}
     break;
 
-  case 49:
+  case 52:
 
     {
        (yyval.menu) = menu_add_menu();
 ;}
     break;
 
-  case 50:
+  case 53:
 
     {
        if (zconf_endtoken((yyvsp[(1) - (1)].id), T_CHOICE, T_ENDCHOICE)) {
@@ -1812,7 +1803,7 @@ yyreduce:
 ;}
     break;
 
-  case 58:
+  case 61:
 
     {
        menu_add_prompt(P_PROMPT, (yyvsp[(2) - (4)].string), (yyvsp[(3) - (4)].expr));
@@ -1820,7 +1811,7 @@ yyreduce:
 ;}
     break;
 
-  case 59:
+  case 62:
 
     {
        if ((yyvsp[(1) - (3)].id)->stype == S_BOOLEAN || (yyvsp[(1) - (3)].id)->stype == S_TRISTATE) {
@@ -1833,7 +1824,7 @@ yyreduce:
 ;}
     break;
 
-  case 60:
+  case 63:
 
     {
        current_entry->sym->flags |= SYMBOL_OPTIONAL;
@@ -1841,7 +1832,7 @@ yyreduce:
 ;}
     break;
 
-  case 61:
+  case 64:
 
     {
        if ((yyvsp[(1) - (4)].id)->stype == S_UNKNOWN) {
@@ -1853,7 +1844,7 @@ yyreduce:
 ;}
     break;
 
-  case 64:
+  case 67:
 
     {
        printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno());
@@ -1863,7 +1854,7 @@ yyreduce:
 ;}
     break;
 
-  case 65:
+  case 68:
 
     {
        if (zconf_endtoken((yyvsp[(1) - (1)].id), T_IF, T_ENDIF)) {
@@ -1873,7 +1864,14 @@ yyreduce:
 ;}
     break;
 
-  case 71:
+  case 74:
+
+    {
+       menu_add_prompt(P_MENU, (yyvsp[(2) - (3)].string), NULL);
+;}
+    break;
+
+  case 75:
 
     {
        menu_add_entry(NULL);
@@ -1882,14 +1880,14 @@ yyreduce:
 ;}
     break;
 
-  case 72:
+  case 76:
 
     {
        (yyval.menu) = menu_add_menu();
 ;}
     break;
 
-  case 73:
+  case 77:
 
     {
        if (zconf_endtoken((yyvsp[(1) - (1)].id), T_MENU, T_ENDMENU)) {
@@ -1899,7 +1897,7 @@ yyreduce:
 ;}
     break;
 
-  case 79:
+  case 83:
 
     {
        printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), (yyvsp[(2) - (3)].string));
@@ -1907,7 +1905,7 @@ yyreduce:
 ;}
     break;
 
-  case 80:
+  case 84:
 
     {
        menu_add_entry(NULL);
@@ -1916,14 +1914,14 @@ yyreduce:
 ;}
     break;
 
-  case 81:
+  case 85:
 
     {
        menu_end_entry();
 ;}
     break;
 
-  case 82:
+  case 86:
 
     {
        printd(DEBUG_PARSE, "%s:%d:help\n", zconf_curname(), zconf_lineno());
@@ -1931,14 +1929,14 @@ yyreduce:
 ;}
     break;
 
-  case 83:
+  case 87:
 
     {
        current_entry->help = (yyvsp[(2) - (2)].string);
 ;}
     break;
 
-  case 88:
+  case 92:
 
     {
        menu_add_dep((yyvsp[(3) - (4)].expr));
@@ -1946,90 +1944,96 @@ yyreduce:
 ;}
     break;
 
-  case 90:
+  case 96:
+
+    {
+       menu_add_visibility((yyvsp[(2) - (2)].expr));
+;}
+    break;
+
+  case 98:
 
     {
        menu_add_prompt(P_PROMPT, (yyvsp[(1) - (2)].string), (yyvsp[(2) - (2)].expr));
 ;}
     break;
 
-  case 93:
+  case 101:
 
     { (yyval.id) = (yyvsp[(1) - (2)].id); ;}
     break;
 
-  case 94:
+  case 102:
 
     { (yyval.id) = (yyvsp[(1) - (2)].id); ;}
     break;
 
-  case 95:
+  case 103:
 
     { (yyval.id) = (yyvsp[(1) - (2)].id); ;}
     break;
 
-  case 98:
+  case 106:
 
     { (yyval.expr) = NULL; ;}
     break;
 
-  case 99:
+  case 107:
 
     { (yyval.expr) = (yyvsp[(2) - (2)].expr); ;}
     break;
 
-  case 100:
+  case 108:
 
     { (yyval.expr) = expr_alloc_symbol((yyvsp[(1) - (1)].symbol)); ;}
     break;
 
-  case 101:
+  case 109:
 
     { (yyval.expr) = expr_alloc_comp(E_EQUAL, (yyvsp[(1) - (3)].symbol), (yyvsp[(3) - (3)].symbol)); ;}
     break;
 
-  case 102:
+  case 110:
 
     { (yyval.expr) = expr_alloc_comp(E_UNEQUAL, (yyvsp[(1) - (3)].symbol), (yyvsp[(3) - (3)].symbol)); ;}
     break;
 
-  case 103:
+  case 111:
 
     { (yyval.expr) = (yyvsp[(2) - (3)].expr); ;}
     break;
 
-  case 104:
+  case 112:
 
     { (yyval.expr) = expr_alloc_one(E_NOT, (yyvsp[(2) - (2)].expr)); ;}
     break;
 
-  case 105:
+  case 113:
 
     { (yyval.expr) = expr_alloc_two(E_OR, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
     break;
 
-  case 106:
+  case 114:
 
     { (yyval.expr) = expr_alloc_two(E_AND, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
     break;
 
-  case 107:
+  case 115:
 
     { (yyval.symbol) = sym_lookup((yyvsp[(1) - (1)].string), 0); free((yyvsp[(1) - (1)].string)); ;}
     break;
 
-  case 108:
+  case 116:
 
     { (yyval.symbol) = sym_lookup((yyvsp[(1) - (1)].string), SYMBOL_CONST); free((yyvsp[(1) - (1)].string)); ;}
     break;
 
-  case 109:
+  case 117:
 
     { (yyval.string) = NULL; ;}
     break;
 
 
-/* Line 1267 of yacc.c.  */
 
       default: break;
     }
@@ -2041,7 +2045,6 @@ yyreduce:
 
   *++yyvsp = yyval;
 
-
   /* Now `shift' the result of the reduction.  Determine what state
      that goes to, based on the state we popped back to and the rule
      number reduced by.  */
@@ -2106,7 +2109,7 @@ yyerrlab:
 
   if (yyerrstatus == 3)
     {
-      /* If just tried and failed to reuse look-ahead token after an
+      /* If just tried and failed to reuse lookahead token after an
         error, discard it.  */
 
       if (yychar <= YYEOF)
@@ -2123,7 +2126,7 @@ yyerrlab:
        }
     }
 
-  /* Else will try to reuse look-ahead token after shifting the error
+  /* Else will try to reuse lookahead token after shifting the error
      token.  */
   goto yyerrlab1;
 
@@ -2180,9 +2183,6 @@ yyerrlab1:
       YY_STACK_PRINT (yyss, yyssp);
     }
 
-  if (yyn == YYFINAL)
-    YYACCEPT;
-
   *++yyvsp = yylval;
 
 
@@ -2207,7 +2207,7 @@ yyabortlab:
   yyresult = 1;
   goto yyreturn;
 
-#ifndef yyoverflow
+#if !defined(yyoverflow) || YYERROR_VERBOSE
 /*-------------------------------------------------.
 | yyexhaustedlab -- memory exhaustion comes here.  |
 `-------------------------------------------------*/
@@ -2218,7 +2218,7 @@ yyexhaustedlab:
 #endif
 
 yyreturn:
-  if (yychar != YYEOF && yychar != YYEMPTY)
+  if (yychar != YYEMPTY)
      yydestruct ("Cleanup: discarding lookahead",
                 yytoken, &yylval);
   /* Do not reclaim the symbols of the rule which action triggered
@@ -2255,16 +2255,14 @@ void conf_parse(const char *name)
        zconf_initscan(name);
 
        sym_init();
-       menu_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, "firmly.0cpm Configuration", NULL);
+       rootmenu.prompt = menu_add_prompt(P_MENU, "Linux Kernel Configuration", NULL);
 
-#if YYDEBUG
        if (getenv("ZCONF_DEBUG"))
                zconfdebug = 1;
-#endif
        zconfparse();
        if (zconfnerrs)
                exit(1);
@@ -2274,6 +2272,10 @@ void conf_parse(const char *name)
                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))
@@ -2284,7 +2286,7 @@ void conf_parse(const char *name)
        sym_set_change_count(1);
 }
 
-const char *zconf_tokenname(int token)
+static const char *zconf_tokenname(int token)
 {
        switch (token) {
        case T_MENU:            return "menu";
@@ -2294,11 +2296,12 @@ const char *zconf_tokenname(int token)
        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(struct kconf_id *id, int starttoken, int endtoken)
+static bool zconf_endtoken(const struct kconf_id *id, int starttoken, int endtoken)
 {
        if (id->token != endtoken) {
                zconf_error("unexpected '%s' within %s block",
@@ -2343,12 +2346,10 @@ static void zconf_error(const char *err, ...)
 
 static void zconferror(const char *err)
 {
-#if YYDEBUG
        fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno() + 1, err);
-#endif
 }
 
-void print_quoted_string(FILE *out, const char *str)
+static void print_quoted_string(FILE *out, const char *str)
 {
        const char *p;
        int len;
@@ -2365,15 +2366,15 @@ void print_quoted_string(FILE *out, const char *str)
        putc('"', out);
 }
 
-void print_symbol(FILE *out, struct menu *menu)
+static void print_symbol(FILE *out, struct menu *menu)
 {
        struct symbol *sym = menu->sym;
        struct property *prop;
 
        if (sym_is_choice(sym))
-               fprintf(out, "choice\n");
+               fprintf(out, "\nchoice\n");
        else
-               fprintf(out, "config %s\n", sym->name);
+               fprintf(out, "\nconfig %s\n", sym->name);
        switch (sym->type) {
        case S_BOOLEAN:
                fputs("  boolean\n", out);
@@ -2419,6 +2420,21 @@ void print_symbol(FILE *out, struct menu *menu)
                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;
@@ -2430,7 +2446,6 @@ void print_symbol(FILE *out, struct menu *menu)
                        menu->help[len] = 0;
                fprintf(out, "  help\n%s\n", menu->help);
        }
-       fputc('\n', out);
 }
 
 void zconfdump(FILE *out)
@@ -2463,7 +2478,6 @@ void zconfdump(FILE *out)
                                expr_fprint(prop->visible.expr, out);
                                fputc('\n', out);
                        }
-                       fputs("\n", out);
                }
 
                if (menu->list)
@@ -2481,7 +2495,7 @@ void zconfdump(FILE *out)
        }
 }
 
-#include "lex.zconf.c"
+#include "zconf.lex.c"
 #include "util.c"
 #include "confdata.c"
 #include "expr.c"
index 39d0335..864da07 100644 (file)
 #include <string.h>
 #include <stdbool.h>
 
-#define LKC_DIRECT_LINK
 #include "lkc.h"
 
-#include "zconf.hash.c"
-
 #define printd(mask, fmt...) if (cdebug & (mask)) printf(fmt)
 
 #define PRINTD         0x0001
@@ -27,18 +24,14 @@ 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(struct kconf_id *id, int starttoken, int endtoken);
+static bool zconf_endtoken(const struct kconf_id *id, int starttoken, int endtoken);
 
-struct symbol *symbol_hash[257];
+struct symbol *symbol_hash[SYMBOL_HASHSIZE];
 
 static struct menu *current_menu, *current_entry;
 
-#define YYDEBUG 0
-#if YYDEBUG
-#define YYERROR_VERBOSE
-#endif
 %}
-%expect 26
+%expect 30
 
 %union
 {
@@ -47,7 +40,7 @@ static struct menu *current_menu, *current_entry;
        struct symbol *symbol;
        struct expr *expr;
        struct menu *menu;
-       struct kconf_id *id;
+       const struct kconf_id *id;
 }
 
 %token <id>T_MAINMENU
@@ -70,6 +63,7 @@ static struct menu *current_menu, *current_entry;
 %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
@@ -100,15 +94,21 @@ static struct menu *current_menu, *current_entry;
                menu_end_menu();
 } if_entry menu_entry choice_entry
 
+%{
+/* Include zconf.hash.c here so it can see the token constants. */
+#include "zconf.hash.c"
+%}
+
 %%
-input: stmt_list;
+input: nl start | start;
+
+start: mainmenu_stmt stmt_list | stmt_list;
 
 stmt_list:
          /* empty */
        | stmt_list common_stmt
        | stmt_list choice_stmt
        | stmt_list menu_stmt
-       | stmt_list T_MAINMENU prompt nl
        | 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
@@ -119,7 +119,7 @@ stmt_list:
 ;
 
 option_name:
-       T_DEPENDS | T_PROMPT | T_TYPE | T_SELECT | T_OPTIONAL | T_RANGE | T_DEFAULT
+       T_DEPENDS | T_PROMPT | T_TYPE | T_SELECT | T_OPTIONAL | T_RANGE | T_DEFAULT | T_VISIBLE
 ;
 
 common_stmt:
@@ -224,7 +224,7 @@ symbol_option_list:
          /* empty */
        | symbol_option_list T_WORD symbol_option_arg
 {
-       struct kconf_id *id = kconf_id_lookup($2, strlen($2));
+       const struct kconf_id *id = kconf_id_lookup($2, strlen($2));
        if (id && id->flags & TF_OPTION)
                menu_add_option(id->token, $3);
        else
@@ -339,6 +339,13 @@ if_block:
        | 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
@@ -348,7 +355,7 @@ menu: T_MENU prompt T_EOL
        printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno());
 };
 
-menu_entry: menu depends_list
+menu_entry: menu visibility_list depends_list
 {
        $$ = menu_add_menu();
 };
@@ -419,6 +426,19 @@ depends: T_DEPENDS T_ON expr T_EOL
        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:
@@ -472,16 +492,14 @@ void conf_parse(const char *name)
        zconf_initscan(name);
 
        sym_init();
-       menu_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, "firmly.0cpm Configuration", NULL);
+       rootmenu.prompt = menu_add_prompt(P_MENU, "Linux Kernel Configuration", NULL);
 
-#if YYDEBUG
        if (getenv("ZCONF_DEBUG"))
                zconfdebug = 1;
-#endif
        zconfparse();
        if (zconfnerrs)
                exit(1);
@@ -491,6 +509,10 @@ void conf_parse(const char *name)
                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))
@@ -501,7 +523,7 @@ void conf_parse(const char *name)
        sym_set_change_count(1);
 }
 
-const char *zconf_tokenname(int token)
+static const char *zconf_tokenname(int token)
 {
        switch (token) {
        case T_MENU:            return "menu";
@@ -511,11 +533,12 @@ const char *zconf_tokenname(int token)
        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(struct kconf_id *id, int starttoken, int endtoken)
+static bool zconf_endtoken(const struct kconf_id *id, int starttoken, int endtoken)
 {
        if (id->token != endtoken) {
                zconf_error("unexpected '%s' within %s block",
@@ -560,12 +583,10 @@ static void zconf_error(const char *err, ...)
 
 static void zconferror(const char *err)
 {
-#if YYDEBUG
        fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno() + 1, err);
-#endif
 }
 
-void print_quoted_string(FILE *out, const char *str)
+static void print_quoted_string(FILE *out, const char *str)
 {
        const char *p;
        int len;
@@ -582,15 +603,15 @@ void print_quoted_string(FILE *out, const char *str)
        putc('"', out);
 }
 
-void print_symbol(FILE *out, struct menu *menu)
+static void print_symbol(FILE *out, struct menu *menu)
 {
        struct symbol *sym = menu->sym;
        struct property *prop;
 
        if (sym_is_choice(sym))
-               fprintf(out, "choice\n");
+               fprintf(out, "\nchoice\n");
        else
-               fprintf(out, "config %s\n", sym->name);
+               fprintf(out, "\nconfig %s\n", sym->name);
        switch (sym->type) {
        case S_BOOLEAN:
                fputs("  boolean\n", out);
@@ -636,6 +657,21 @@ void print_symbol(FILE *out, struct menu *menu)
                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;
@@ -647,7 +683,6 @@ void print_symbol(FILE *out, struct menu *menu)
                        menu->help[len] = 0;
                fprintf(out, "  help\n%s\n", menu->help);
        }
-       fputc('\n', out);
 }
 
 void zconfdump(FILE *out)
@@ -680,7 +715,6 @@ void zconfdump(FILE *out)
                                expr_fprint(prop->visible.expr, out);
                                fputc('\n', out);
                        }
-                       fputs("\n", out);
                }
 
                if (menu->list)
@@ -698,7 +732,7 @@ void zconfdump(FILE *out)
        }
 }
 
-#include "lex.zconf.c"
+#include "zconf.lex.c"
 #include "util.c"
 #include "confdata.c"
 #include "expr.c"
index 112f0a0..ec163da 100644 (file)
@@ -755,8 +755,9 @@ int yy_flex_debug = 0;
 #define YY_RESTORE_YY_MORE_OFFSET
 char *yytext;
 #line 1 "bin/kconfig/zconf.l"
+#define YY_NO_INPUT 1
 
-#line 5 "bin/kconfig/zconf.l"
+#line 6 "bin/kconfig/zconf.l"
 /*
  * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
  * Released under the terms of the GNU GPL v2.0.
@@ -768,7 +769,6 @@ char *yytext;
 #include <string.h>
 #include <unistd.h>
 
-#define LKC_DIRECT_LINK
 #include "lkc.h"
 
 #define START_STRSIZE  16
@@ -793,7 +793,7 @@ static int last_ts, first_ts;
 static void zconf_endhelp(void);
 static void zconf_endfile(void);
 
-void new_string(void)
+static void new_string(void)
 {
        text = malloc(START_STRSIZE);
        text_asize = START_STRSIZE;
@@ -801,7 +801,7 @@ void new_string(void)
        *text = 0;
 }
 
-void append_string(const char *str, int size)
+static void append_string(const char *str, int size)
 {
        int new_size = text_size + size + 1;
        if (new_size > text_asize) {
@@ -815,7 +815,7 @@ void append_string(const char *str, int size)
        text[text_size] = 0;
 }
 
-void alloc_string(const char *str, int size)
+static void alloc_string(const char *str, int size)
 {
        text = malloc(size + 1);
        memcpy(text, str, size);
@@ -1094,7 +1094,7 @@ case 6:
 YY_RULE_SETUP
 #line 97 "bin/kconfig/zconf.l"
 {
-               struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
+               const struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
                BEGIN(PARAM);
                current_pos.file = current_file;
                current_pos.lineno = current_file->lineno;
@@ -1183,7 +1183,7 @@ case 19:
 YY_RULE_SETUP
 #line 133 "bin/kconfig/zconf.l"
 {
-               struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
+               const struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
                if (id && id->flags & TF_PARAM) {
                        zconflval.id = id;
                        return id->token;
@@ -2396,34 +2396,45 @@ void zconf_initscan(const char *name)
 
        current_file = file_lookup(name);
        current_file->lineno = 1;
-       current_file->flags = FILE_BUSY;
 }
 
 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(name);
+       yyin = zconf_fopen(file->name);
        if (!yyin) {
-               printf("%s:%d: can't open file \"%s\"\n", zconf_curname(), zconf_lineno(), name);
+               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;
 
-       if (file->flags & FILE_BUSY) {
-               printf("recursive scan (%s)?\n", name);
-               exit(1);
-       }
-       if (file->flags & FILE_SCANNED) {
-               printf("file %s already scanned?\n", name);
-               exit(1);
+       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->flags |= FILE_BUSY;
        file->lineno = 1;
        file->parent = current_file;
        current_file = file;
@@ -2433,8 +2444,6 @@ static void zconf_endfile(void)
 {
        struct buffer *parent;
 
-       current_file->flags |= FILE_SCANNED;
-       current_file->flags &= ~FILE_BUSY;
        current_file = current_file->parent;
 
        parent = current_buf->parent;
@@ -2452,7 +2461,7 @@ int zconf_lineno(void)
        return current_pos.lineno;
 }
 
-char *zconf_curname(void)
+const char *zconf_curname(void)
 {
        return current_pos.file ? current_pos.file->name : "<none>";
 }
index 6232bac..9620b35 100755 (executable)
Binary files a/bin/mconf and b/bin/mconf differ
index e77ed67..f636141 100644 (file)
@@ -1,24 +1,22 @@
-/* A Bison parser, made by GNU Bison 2.3.  */
+/* A Bison parser, made by GNU Bison 2.4.3.  */
 
 /* Skeleton implementation for Bison's Yacc-like parsers in C
-
-   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
-   Free Software Foundation, Inc.
-
-   This program is free software; you can redistribute it and/or modify
+   
+      Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
+   2009, 2010 Free Software Foundation, Inc.
+   
+   This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
-
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+   
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
-
+   
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor,
-   Boston, MA 02110-1301, USA.  */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 /* As a special exception, you may create a larger work that contains
    part or all of the Bison parser skeleton and distribute that work
@@ -29,7 +27,7 @@
    special exception, which will cause the skeleton and the resulting
    Bison output files to be licensed under the GNU General Public
    License without this special exception.
-
+   
    This special exception was added by the Free Software Foundation in
    version 2.2 of Bison.  */
 
@@ -47,7 +45,7 @@
 #define YYBISON 1
 
 /* Bison version.  */
-#define YYBISON_VERSION "2.3"
+#define YYBISON_VERSION "2.4.3"
 
 /* Skeleton name.  */
 #define YYSKELETON_NAME "yacc.c"
 /* Pure parsers.  */
 #define YYPURE 0
 
+/* Push parsers.  */
+#define YYPUSH 0
+
+/* Pull parsers.  */
+#define YYPULL 1
+
 /* Using locations.  */
 #define YYLSP_NEEDED 0
 
 /* Substitute the variable and function names.  */
-#define yyparse zconfparse
-#define yylex   zconflex
-#define yyerror zconferror
-#define yylval  zconflval
-#define yychar  zconfchar
-#define yydebug zconfdebug
-#define yynerrs zconfnerrs
-
-
-/* Tokens.  */
-#ifndef YYTOKENTYPE
-# define YYTOKENTYPE
-   /* Put the tokens into the symbol table, so that GDB and other debuggers
-      know about them.  */
-   enum yytokentype {
-     T_MAINMENU = 258,
-     T_MENU = 259,
-     T_ENDMENU = 260,
-     T_SOURCE = 261,
-     T_CHOICE = 262,
-     T_ENDCHOICE = 263,
-     T_COMMENT = 264,
-     T_CONFIG = 265,
-     T_MENUCONFIG = 266,
-     T_HELP = 267,
-     T_HELPTEXT = 268,
-     T_IF = 269,
-     T_ENDIF = 270,
-     T_DEPENDS = 271,
-     T_OPTIONAL = 272,
-     T_PROMPT = 273,
-     T_TYPE = 274,
-     T_DEFAULT = 275,
-     T_SELECT = 276,
-     T_RANGE = 277,
-     T_OPTION = 278,
-     T_ON = 279,
-     T_WORD = 280,
-     T_WORD_QUOTE = 281,
-     T_UNEQUAL = 282,
-     T_CLOSE_PAREN = 283,
-     T_OPEN_PAREN = 284,
-     T_EOL = 285,
-     T_OR = 286,
-     T_AND = 287,
-     T_EQUAL = 288,
-     T_NOT = 289
-   };
-#endif
-/* Tokens.  */
-#define T_MAINMENU 258
-#define T_MENU 259
-#define T_ENDMENU 260
-#define T_SOURCE 261
-#define T_CHOICE 262
-#define T_ENDCHOICE 263
-#define T_COMMENT 264
-#define T_CONFIG 265
-#define T_MENUCONFIG 266
-#define T_HELP 267
-#define T_HELPTEXT 268
-#define T_IF 269
-#define T_ENDIF 270
-#define T_DEPENDS 271
-#define T_OPTIONAL 272
-#define T_PROMPT 273
-#define T_TYPE 274
-#define T_DEFAULT 275
-#define T_SELECT 276
-#define T_RANGE 277
-#define T_OPTION 278
-#define T_ON 279
-#define T_WORD 280
-#define T_WORD_QUOTE 281
-#define T_UNEQUAL 282
-#define T_CLOSE_PAREN 283
-#define T_OPEN_PAREN 284
-#define T_EOL 285
-#define T_OR 286
-#define T_AND 287
-#define T_EQUAL 288
-#define T_NOT 289
-
-
+#define yyparse         zconfparse
+#define yylex           zconflex
+#define yyerror         zconferror
+#define yylval          zconflval
+#define yychar          zconfchar
+#define yydebug         zconfdebug
+#define yynerrs         zconfnerrs
 
 
 /* Copy the first part of user declarations.  */
 #include <string.h>
 #include <stdbool.h>
 
-#define LKC_DIRECT_LINK
 #include "lkc.h"
 
-#include "zconf.hash.c"
-
 #define printd(mask, fmt...) if (cdebug & (mask)) printf(fmt)
 
 #define PRINTD         0x0001
@@ -176,21 +100,18 @@ 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(struct kconf_id *id, int starttoken, int endtoken);
+static bool zconf_endtoken(const struct kconf_id *id, int starttoken, int endtoken);
 
-struct symbol *symbol_hash[257];
+struct symbol *symbol_hash[SYMBOL_HASHSIZE];
 
 static struct menu *current_menu, *current_entry;
 
-#define YYDEBUG 0
-#if YYDEBUG
-#define YYERROR_VERBOSE
-#endif
+
 
 
 /* Enabling traces.  */
 #ifndef YYDEBUG
-# define YYDEBUG 0
+# define YYDEBUG 1
 #endif
 
 /* Enabling verbose error messages.  */
@@ -206,31 +127,78 @@ static struct menu *current_menu, *current_entry;
 # define YYTOKEN_TABLE 0
 #endif
 
+
+/* Tokens.  */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+   /* Put the tokens into the symbol table, so that GDB and other debuggers
+      know about them.  */
+   enum yytokentype {
+     T_MAINMENU = 258,
+     T_MENU = 259,
+     T_ENDMENU = 260,
+     T_SOURCE = 261,
+     T_CHOICE = 262,
+     T_ENDCHOICE = 263,
+     T_COMMENT = 264,
+     T_CONFIG = 265,
+     T_MENUCONFIG = 266,
+     T_HELP = 267,
+     T_HELPTEXT = 268,
+     T_IF = 269,
+     T_ENDIF = 270,
+     T_DEPENDS = 271,
+     T_OPTIONAL = 272,
+     T_PROMPT = 273,
+     T_TYPE = 274,
+     T_DEFAULT = 275,
+     T_SELECT = 276,
+     T_RANGE = 277,
+     T_VISIBLE = 278,
+     T_OPTION = 279,
+     T_ON = 280,
+     T_WORD = 281,
+     T_WORD_QUOTE = 282,
+     T_UNEQUAL = 283,
+     T_CLOSE_PAREN = 284,
+     T_OPEN_PAREN = 285,
+     T_EOL = 286,
+     T_OR = 287,
+     T_AND = 288,
+     T_EQUAL = 289,
+     T_NOT = 290
+   };
+#endif
+
+
+
 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
 typedef union YYSTYPE
-
 {
+
+
        char *string;
        struct file *file;
        struct symbol *symbol;
        struct expr *expr;
        struct menu *menu;
-       struct kconf_id *id;
-}
-/* Line 187 of yacc.c.  */
+       const struct kconf_id *id;
 
-       YYSTYPE;
+
+
+} YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
 # define YYSTYPE_IS_DECLARED 1
-# define YYSTYPE_IS_TRIVIAL 1
 #endif
 
 
-
 /* Copy the second part of user declarations.  */
 
 
-/* Line 216 of yacc.c.  */
+/* Include zconf.hash.c here so it can see the token constants. */
+#include "zconf.hash.c"
+
 
 
 #ifdef short
@@ -281,7 +249,7 @@ typedef short int yytype_int16;
 #define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
 
 #ifndef YY_
-# if YYENABLE_NLS
+# if defined YYENABLE_NLS && YYENABLE_NLS
 #  if ENABLE_NLS
 #   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
 #   define YY_(msgid) dgettext ("bison-runtime", msgid)
@@ -306,14 +274,14 @@ typedef short int yytype_int16;
 #if (defined __STDC__ || defined __C99__FUNC__ \
      || defined __cplusplus || defined _MSC_VER)
 static int
-YYID (int i)
+YYID (int yyi)
 #else
 static int
-YYID (i)
-    int i;
+YYID (yyi)
+    int yyi;
 #endif
 {
-  return i;
+  return yyi;
 }
 #endif
 
@@ -394,9 +362,9 @@ void free (void *); /* INFRINGES ON USER NAME SPACE */
 /* A type that is properly aligned for any stack member.  */
 union yyalloc
 {
-  yytype_int16 yyss;
-  YYSTYPE yyvs;
-  };
+  yytype_int16 yyss_alloc;
+  YYSTYPE yyvs_alloc;
+};
 
 /* The size of the maximum gap between one aligned stack and the next.  */
 # define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
@@ -430,12 +398,12 @@ union yyalloc
    elements in the stack, and YYPTR gives the new location of the
    stack.  Advance YYPTR to a properly aligned location for the next
    stack.  */
-# define YYSTACK_RELOCATE(Stack)                                       \
+# define YYSTACK_RELOCATE(Stack_alloc, Stack)                          \
     do                                                                 \
       {                                                                        \
        YYSIZE_T yynewbytes;                                            \
-       YYCOPY (&yyptr->Stack, Stack, yysize);                          \
-       Stack = &yyptr->Stack;                                          \
+       YYCOPY (&yyptr->Stack_alloc, Stack, yysize);                    \
+       Stack = &yyptr->Stack_alloc;                                    \
        yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
        yyptr += yynewbytes / sizeof (*yyptr);                          \
       }                                                                        \
@@ -444,22 +412,22 @@ union yyalloc
 #endif
 
 /* YYFINAL -- State number of the termination state.  */
-#define YYFINAL  3
+#define YYFINAL  11
 /* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   259
+#define YYLAST   290
 
 /* YYNTOKENS -- Number of terminals.  */
-#define YYNTOKENS  35
+#define YYNTOKENS  36
 /* YYNNTS -- Number of nonterminals.  */
-#define YYNNTS  46
+#define YYNNTS  50
 /* YYNRULES -- Number of rules.  */
-#define YYNRULES  110
+#define YYNRULES  118
 /* YYNRULES -- Number of states.  */
-#define YYNSTATES  180
+#define YYNSTATES  191
 
 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
 #define YYUNDEFTOK  2
-#define YYMAXUTOK   289
+#define YYMAXUTOK   290
 
 #define YYTRANSLATE(YYX)                                               \
   ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
@@ -495,7 +463,8 @@ static const yytype_uint8 yytranslate[] =
        2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
        5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
       15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
-      25,    26,    27,    28,    29,    30,    31,    32,    33,    34
+      25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
+      35
 };
 
 #if YYDEBUG
@@ -503,73 +472,75 @@ static const yytype_uint8 yytranslate[] =
    YYRHS.  */
 static const yytype_uint16 yyprhs[] =
 {
-       0,     0,     3,     5,     6,     9,    12,    15,    20,    23,
-      28,    33,    37,    39,    41,    43,    45,    47,    49,    51,
-      53,    55,    57,    59,    61,    63,    67,    70,    74,    77,
-      81,    84,    85,    88,    91,    94,    97,   100,   103,   107,
-     112,   117,   122,   128,   132,   133,   137,   138,   141,   145,
-     148,   150,   154,   155,   158,   161,   164,   167,   170,   175,
-     179,   182,   187,   188,   191,   195,   197,   201,   202,   205,
-     208,   211,   215,   218,   220,   224,   225,   228,   231,   234,
-     238,   242,   245,   248,   251,   252,   255,   258,   261,   266,
-     267,   270,   272,   274,   277,   280,   283,   285,   288,   289,
-     292,   294,   298,   302,   306,   309,   313,   317,   319,   321,
-     322
+       0,     0,     3,     6,     8,    11,    13,    14,    17,    20,
+      23,    26,    31,    36,    40,    42,    44,    46,    48,    50,
+      52,    54,    56,    58,    60,    62,    64,    66,    68,    72,
+      75,    79,    82,    86,    89,    90,    93,    96,    99,   102,
+     105,   108,   112,   117,   122,   127,   133,   137,   138,   142,
+     143,   146,   150,   153,   155,   159,   160,   163,   166,   169,
+     172,   175,   180,   184,   187,   192,   193,   196,   200,   202,
+     206,   207,   210,   213,   216,   220,   224,   228,   230,   234,
+     235,   238,   241,   244,   248,   252,   255,   258,   261,   262,
+     265,   268,   271,   276,   277,   280,   283,   286,   287,   290,
+     292,   294,   297,   300,   303,   305,   308,   309,   312,   314,
+     318,   322,   326,   329,   333,   337,   339,   341,   342
 };
 
 /* YYRHS -- A `-1'-separated list of the rules' RHS.  */
 static const yytype_int8 yyrhs[] =
 {
-      36,     0,    -1,    37,    -1,    -1,    37,    39,    -1,    37,
-      53,    -1,    37,    64,    -1,    37,     3,    74,    76,    -1,
-      37,    75,    -1,    37,    25,     1,    30,    -1,    37,    38,
-       1,    30,    -1,    37,     1,    30,    -1,    16,    -1,    18,
-      -1,    19,    -1,    21,    -1,    17,    -1,    22,    -1,    20,
-      -1,    30,    -1,    59,    -1,    68,    -1,    42,    -1,    44,
-      -1,    66,    -1,    25,     1,    30,    -1,     1,    30,    -1,
-      10,    25,    30,    -1,    41,    45,    -1,    11,    25,    30,
-      -1,    43,    45,    -1,    -1,    45,    46,    -1,    45,    47,
-      -1,    45,    72,    -1,    45,    70,    -1,    45,    40,    -1,
-      45,    30,    -1,    19,    73,    30,    -1,    18,    74,    77,
-      30,    -1,    20,    78,    77,    30,    -1,    21,    25,    77,
-      30,    -1,    22,    79,    79,    77,    30,    -1,    23,    48,
-      30,    -1,    -1,    48,    25,    49,    -1,    -1,    33,    74,
-      -1,     7,    80,    30,    -1,    50,    54,    -1,    75,    -1,
-      51,    56,    52,    -1,    -1,    54,    55,    -1,    54,    72,
-      -1,    54,    70,    -1,    54,    30,    -1,    54,    40,    -1,
-      18,    74,    77,    30,    -1,    19,    73,    30,    -1,    17,
-      30,    -1,    20,    25,    77,    30,    -1,    -1,    56,    39,
-      -1,    14,    78,    76,    -1,    75,    -1,    57,    60,    58,
-      -1,    -1,    60,    39,    -1,    60,    64,    -1,    60,    53,
-      -1,     4,    74,    30,    -1,    61,    71,    -1,    75,    -1,
-      62,    65,    63,    -1,    -1,    65,    39,    -1,    65,    64,
-      -1,    65,    53,    -1,     6,    74,    30,    -1,     9,    74,
-      30,    -1,    67,    71,    -1,    12,    30,    -1,    69,    13,
-      -1,    -1,    71,    72,    -1,    71,    30,    -1,    71,    40,
-      -1,    16,    24,    78,    30,    -1,    -1,    74,    77,    -1,
-      25,    -1,    26,    -1,     5,    30,    -1,     8,    30,    -1,
-      15,    30,    -1,    30,    -1,    76,    30,    -1,    -1,    14,
-      78,    -1,    79,    -1,    79,    33,    79,    -1,    79,    27,
-      79,    -1,    29,    78,    28,    -1,    34,    78,    -1,    78,
-      31,    78,    -1,    78,    32,    78,    -1,    25,    -1,    26,
-      -1,    -1,    25,    -1
+      37,     0,    -1,    81,    38,    -1,    38,    -1,    63,    39,
+      -1,    39,    -1,    -1,    39,    41,    -1,    39,    55,    -1,
+      39,    67,    -1,    39,    80,    -1,    39,    26,     1,    31,
+      -1,    39,    40,     1,    31,    -1,    39,     1,    31,    -1,
+      16,    -1,    18,    -1,    19,    -1,    21,    -1,    17,    -1,
+      22,    -1,    20,    -1,    23,    -1,    31,    -1,    61,    -1,
+      71,    -1,    44,    -1,    46,    -1,    69,    -1,    26,     1,
+      31,    -1,     1,    31,    -1,    10,    26,    31,    -1,    43,
+      47,    -1,    11,    26,    31,    -1,    45,    47,    -1,    -1,
+      47,    48,    -1,    47,    49,    -1,    47,    75,    -1,    47,
+      73,    -1,    47,    42,    -1,    47,    31,    -1,    19,    78,
+      31,    -1,    18,    79,    82,    31,    -1,    20,    83,    82,
+      31,    -1,    21,    26,    82,    31,    -1,    22,    84,    84,
+      82,    31,    -1,    24,    50,    31,    -1,    -1,    50,    26,
+      51,    -1,    -1,    34,    79,    -1,     7,    85,    31,    -1,
+      52,    56,    -1,    80,    -1,    53,    58,    54,    -1,    -1,
+      56,    57,    -1,    56,    75,    -1,    56,    73,    -1,    56,
+      31,    -1,    56,    42,    -1,    18,    79,    82,    31,    -1,
+      19,    78,    31,    -1,    17,    31,    -1,    20,    26,    82,
+      31,    -1,    -1,    58,    41,    -1,    14,    83,    81,    -1,
+      80,    -1,    59,    62,    60,    -1,    -1,    62,    41,    -1,
+      62,    67,    -1,    62,    55,    -1,     3,    79,    81,    -1,
+       4,    79,    31,    -1,    64,    76,    74,    -1,    80,    -1,
+      65,    68,    66,    -1,    -1,    68,    41,    -1,    68,    67,
+      -1,    68,    55,    -1,     6,    79,    31,    -1,     9,    79,
+      31,    -1,    70,    74,    -1,    12,    31,    -1,    72,    13,
+      -1,    -1,    74,    75,    -1,    74,    31,    -1,    74,    42,
+      -1,    16,    25,    83,    31,    -1,    -1,    76,    77,    -1,
+      76,    31,    -1,    23,    82,    -1,    -1,    79,    82,    -1,
+      26,    -1,    27,    -1,     5,    31,    -1,     8,    31,    -1,
+      15,    31,    -1,    31,    -1,    81,    31,    -1,    -1,    14,
+      83,    -1,    84,    -1,    84,    34,    84,    -1,    84,    28,
+      84,    -1,    30,    83,    29,    -1,    35,    83,    -1,    83,
+      32,    83,    -1,    83,    33,    83,    -1,    26,    -1,    27,
+      -1,    -1,    26,    -1
 };
 
 /* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
 static const yytype_uint16 yyrline[] =
 {
-       0,   104,   104,   106,   108,   109,   110,   111,   112,   113,
-     114,   118,   122,   122,   122,   122,   122,   122,   122,   126,
-     127,   128,   129,   130,   131,   135,   136,   142,   150,   156,
-     164,   174,   176,   177,   178,   179,   180,   181,   184,   192,
-     198,   208,   214,   220,   223,   225,   236,   237,   242,   251,
-     256,   264,   267,   269,   270,   271,   272,   273,   276,   282,
-     293,   299,   309,   311,   316,   324,   332,   335,   337,   338,
-     339,   344,   351,   356,   364,   367,   369,   370,   371,   374,
-     382,   389,   396,   402,   409,   411,   412,   413,   416,   424,
-     426,   431,   432,   435,   436,   437,   441,   442,   445,   446,
-     449,   450,   451,   452,   453,   454,   455,   458,   459,   462,
-     463
+       0,   104,   104,   104,   106,   106,   108,   110,   111,   112,
+     113,   114,   115,   119,   123,   123,   123,   123,   123,   123,
+     123,   123,   127,   128,   129,   130,   131,   132,   136,   137,
+     143,   151,   157,   165,   175,   177,   178,   179,   180,   181,
+     182,   185,   193,   199,   209,   215,   221,   224,   226,   237,
+     238,   243,   252,   257,   265,   268,   270,   271,   272,   273,
+     274,   277,   283,   294,   300,   310,   312,   317,   325,   333,
+     336,   338,   339,   340,   345,   352,   359,   364,   372,   375,
+     377,   378,   379,   382,   390,   397,   404,   410,   417,   419,
+     420,   421,   424,   432,   434,   435,   438,   445,   447,   452,
+     453,   456,   457,   458,   462,   463,   466,   467,   470,   471,
+     472,   473,   474,   475,   476,   479,   480,   483,   484
 };
 #endif
 
@@ -582,19 +553,19 @@ static const char *const yytname[] =
   "T_SOURCE", "T_CHOICE", "T_ENDCHOICE", "T_COMMENT", "T_CONFIG",
   "T_MENUCONFIG", "T_HELP", "T_HELPTEXT", "T_IF", "T_ENDIF", "T_DEPENDS",
   "T_OPTIONAL", "T_PROMPT", "T_TYPE", "T_DEFAULT", "T_SELECT", "T_RANGE",
-  "T_OPTION", "T_ON", "T_WORD", "T_WORD_QUOTE", "T_UNEQUAL",
+  "T_VISIBLE", "T_OPTION", "T_ON", "T_WORD", "T_WORD_QUOTE", "T_UNEQUAL",
   "T_CLOSE_PAREN", "T_OPEN_PAREN", "T_EOL", "T_OR", "T_AND", "T_EQUAL",
-  "T_NOT", "$accept", "input", "stmt_list", "option_name", "common_stmt",
-  "option_error", "config_entry_start", "config_stmt",
+  "T_NOT", "$accept", "input", "start", "stmt_list", "option_name",
+  "common_stmt", "option_error", "config_entry_start", "config_stmt",
   "menuconfig_entry_start", "menuconfig_stmt", "config_option_list",
   "config_option", "symbol_option", "symbol_option_list",
   "symbol_option_arg", "choice", "choice_entry", "choice_end",
   "choice_stmt", "choice_option_list", "choice_option", "choice_block",
-  "if_entry", "if_end", "if_stmt", "if_block", "menu", "menu_entry",
-  "menu_end", "menu_stmt", "menu_block", "source_stmt", "comment",
-  "comment_stmt", "help_start", "help", "depends_list", "depends",
-  "prompt_stmt_opt", "prompt", "end", "nl", "if_expr", "expr", "symbol",
-  "word_opt", 0
+  "if_entry", "if_end", "if_stmt", "if_block", "mainmenu_stmt", "menu",
+  "menu_entry", "menu_end", "menu_stmt", "menu_block", "source_stmt",
+  "comment", "comment_stmt", "help_start", "help", "depends_list",
+  "depends", "visibility_list", "visible", "prompt_stmt_opt", "prompt",
+  "end", "nl", "if_expr", "expr", "symbol", "word_opt", 0
 };
 #endif
 
@@ -606,42 +577,42 @@ static const yytype_uint16 yytoknum[] =
        0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
      265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
      275,   276,   277,   278,   279,   280,   281,   282,   283,   284,
-     285,   286,   287,   288,   289
+     285,   286,   287,   288,   289,   290
 };
 # endif
 
 /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
 static const yytype_uint8 yyr1[] =
 {
-       0,    35,    36,    37,    37,    37,    37,    37,    37,    37,
-      37,    37,    38,    38,    38,    38,    38,    38,    38,    39,
-      39,    39,    39,    39,    39,    40,    40,    41,    42,    43,
-      44,    45,    45,    45,    45,    45,    45,    45,    46,    46,
-      46,    46,    46,    47,    48,    48,    49,    49,    50,    51,
-      52,    53,    54,    54,    54,    54,    54,    54,    55,    55,
-      55,    55,    56,    56,    57,    58,    59,    60,    60,    60,
-      60,    61,    62,    63,    64,    65,    65,    65,    65,    66,
-      67,    68,    69,    70,    71,    71,    71,    71,    72,    73,
-      73,    74,    74,    75,    75,    75,    76,    76,    77,    77,
-      78,    78,    78,    78,    78,    78,    78,    79,    79,    80,
-      80
+       0,    36,    37,    37,    38,    38,    39,    39,    39,    39,
+      39,    39,    39,    39,    40,    40,    40,    40,    40,    40,
+      40,    40,    41,    41,    41,    41,    41,    41,    42,    42,
+      43,    44,    45,    46,    47,    47,    47,    47,    47,    47,
+      47,    48,    48,    48,    48,    48,    49,    50,    50,    51,
+      51,    52,    53,    54,    55,    56,    56,    56,    56,    56,
+      56,    57,    57,    57,    57,    58,    58,    59,    60,    61,
+      62,    62,    62,    62,    63,    64,    65,    66,    67,    68,
+      68,    68,    68,    69,    70,    71,    72,    73,    74,    74,
+      74,    74,    75,    76,    76,    76,    77,    78,    78,    79,
+      79,    80,    80,    80,    81,    81,    82,    82,    83,    83,
+      83,    83,    83,    83,    83,    84,    84,    85,    85
 };
 
 /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
 static const yytype_uint8 yyr2[] =
 {
-       0,     2,     1,     0,     2,     2,     2,     4,     2,     4,
-       4,     3,     1,     1,     1,     1,     1,     1,     1,     1,
-       1,     1,     1,     1,     1,     3,     2,     3,     2,     3,
-       2,     0,     2,     2,     2,     2,     2,     2,     3,     4,
-       4,     4,     5,     3,     0,     3,     0,     2,     3,     2,
-       1,     3,     0,     2,     2,     2,     2,     2,     4,     3,
-       2,     4,     0,     2,     3,     1,     3,     0,     2,     2,
-       2,     3,     2,     1,     3,     0,     2,     2,     2,     3,
-       3,     2,     2,     2,     0,     2,     2,     2,     4,     0,
-       2,     1,     1,     2,     2,     2,     1,     2,     0,     2,
-       1,     3,     3,     3,     2,     3,     3,     1,     1,     0,
-       1
+       0,     2,     2,     1,     2,     1,     0,     2,     2,     2,
+       2,     4,     4,     3,     1,     1,     1,     1,     1,     1,
+       1,     1,     1,     1,     1,     1,     1,     1,     3,     2,
+       3,     2,     3,     2,     0,     2,     2,     2,     2,     2,
+       2,     3,     4,     4,     4,     5,     3,     0,     3,     0,
+       2,     3,     2,     1,     3,     0,     2,     2,     2,     2,
+       2,     4,     3,     2,     4,     0,     2,     3,     1,     3,
+       0,     2,     2,     2,     3,     3,     3,     1,     3,     0,
+       2,     2,     2,     3,     3,     2,     2,     2,     0,     2,
+       2,     2,     4,     0,     2,     2,     2,     0,     2,     1,
+       1,     2,     2,     2,     1,     2,     0,     2,     1,     3,
+       3,     3,     2,     3,     3,     1,     1,     0,     1
 };
 
 /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
@@ -649,158 +620,172 @@ static const yytype_uint8 yyr2[] =
    means the default is an error.  */
 static const yytype_uint8 yydefact[] =
 {
-       3,     0,     0,     1,     0,     0,     0,     0,     0,   109,
-       0,     0,     0,     0,     0,     0,    12,    16,    13,    14,
-      18,    15,    17,     0,    19,     0,     4,    31,    22,    31,
-      23,    52,    62,     5,    67,    20,    84,    75,     6,    24,
-      84,    21,     8,    11,    91,    92,     0,     0,    93,     0,
-     110,     0,    94,     0,     0,     0,   107,   108,     0,     0,
-       0,   100,    95,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,    96,     7,    71,    79,    48,    80,    27,
-      29,     0,   104,     0,     0,    64,     0,     0,     9,    10,
-       0,     0,     0,     0,    89,     0,     0,     0,    44,     0,
-      37,    36,    32,    33,     0,    35,    34,     0,     0,    89,
-       0,    56,    57,    53,    55,    54,    63,    51,    50,    68,
-      70,    66,    69,    65,    86,    87,    85,    76,    78,    74,
-      77,    73,    97,   103,   105,   106,   102,   101,    26,    82,
-       0,    98,     0,    98,    98,    98,     0,     0,     0,    83,
-      60,    98,     0,    98,     0,     0,     0,    38,    90,     0,
-       0,    98,    46,    43,    25,     0,    59,     0,    88,    99,
-      39,    40,    41,     0,     0,    45,    58,    61,    42,    47
+       6,     0,   104,     0,     3,     0,     6,     6,    99,   100,
+       0,     1,     0,     0,     0,     0,   117,     0,     0,     0,
+       0,     0,     0,    14,    18,    15,    16,    20,    17,    19,
+      21,     0,    22,     0,     7,    34,    25,    34,    26,    55,
+      65,     8,    70,    23,    93,    79,     9,    27,    88,    24,
+      10,     0,   105,     2,    74,    13,     0,   101,     0,   118,
+       0,   102,     0,     0,     0,   115,   116,     0,     0,     0,
+     108,   103,     0,     0,     0,     0,     0,     0,     0,    88,
+       0,     0,    75,    83,    51,    84,    30,    32,     0,   112,
+       0,     0,    67,     0,     0,    11,    12,     0,     0,     0,
+       0,    97,     0,     0,     0,    47,     0,    40,    39,    35,
+      36,     0,    38,    37,     0,     0,    97,     0,    59,    60,
+      56,    58,    57,    66,    54,    53,    71,    73,    69,    72,
+      68,   106,    95,     0,    94,    80,    82,    78,    81,    77,
+      90,    91,    89,   111,   113,   114,   110,   109,    29,    86,
+       0,   106,     0,   106,   106,   106,     0,     0,     0,    87,
+      63,   106,     0,   106,     0,    96,     0,     0,    41,    98,
+       0,     0,   106,    49,    46,    28,     0,    62,     0,   107,
+      92,    42,    43,    44,     0,     0,    48,    61,    64,    45,
+      50
 };
 
 /* YYDEFGOTO[NTERM-NUM].  */
 static const yytype_int16 yydefgoto[] =
 {
-      -1,     1,     2,    25,    26,   101,    27,    28,    29,    30,
-      65,   102,   103,   147,   175,    31,    32,   117,    33,    67,
-     113,    68,    34,   121,    35,    69,    36,    37,   129,    38,
-      71,    39,    40,    41,   104,   105,    70,   106,   142,   143,
-      42,    74,   156,    60,    61,    51
+      -1,     3,     4,     5,    33,    34,   108,    35,    36,    37,
+      38,    74,   109,   110,   157,   186,    39,    40,   124,    41,
+      76,   120,    77,    42,   128,    43,    78,     6,    44,    45,
+     137,    46,    80,    47,    48,    49,   111,   112,    81,   113,
+      79,   134,   152,   153,    50,     7,   165,    69,    70,    60
 };
 
 /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
    STATE-NUM.  */
-#define YYPACT_NINF -80
+#define YYPACT_NINF -90
 static const yytype_int16 yypact[] =
 {
-     -80,     2,   132,   -80,   -13,    -1,    -1,    -2,    -1,     9,
-      33,    -1,    27,    40,    -3,    38,   -80,   -80,   -80,   -80,
-     -80,   -80,   -80,    71,   -80,    77,   -80,   -80,   -80,   -80,
-     -80,   -80,   -80,   -80,   -80,   -80,   -80,   -80,   -80,   -80,
-     -80,   -80,   -80,   -80,   -80,   -80,    57,    61,   -80,    63,
-     -80,    76,   -80,    87,   101,   133,   -80,   -80,    -3,    -3,
-     195,    -6,   -80,   136,   149,    39,   104,    65,   150,     5,
-     194,     5,   167,   -80,   176,   -80,   -80,   -80,   -80,   -80,
-     -80,    68,   -80,    -3,    -3,   176,    72,    72,   -80,   -80,
-     177,   187,    78,    -1,    -1,    -3,   196,    72,   -80,   222,
-     -80,   -80,   -80,   -80,   221,   -80,   -80,   205,    -1,    -1,
-     211,   -80,   -80,   -80,   -80,   -80,   -80,   -80,   -80,   -80,
-     -80,   -80,   -80,   -80,   -80,   -80,   -80,   -80,   -80,   -80,
-     -80,   -80,   -80,   -80,   206,   -80,   -80,   -80,   -80,   -80,
-      -3,   223,   209,   223,   197,   223,    72,     7,   210,   -80,
-     -80,   223,   212,   223,   201,    -3,   213,   -80,   -80,   214,
-     215,   223,   208,   -80,   -80,   216,   -80,   217,   -80,   113,
-     -80,   -80,   -80,   218,    -1,   -80,   -80,   -80,   -80,   -80
+       4,    42,   -90,    96,   -90,   111,   -90,    15,   -90,   -90,
+      75,   -90,    82,    42,   104,    42,   110,   107,    42,   115,
+     125,    -4,   121,   -90,   -90,   -90,   -90,   -90,   -90,   -90,
+     -90,   162,   -90,   163,   -90,   -90,   -90,   -90,   -90,   -90,
+     -90,   -90,   -90,   -90,   -90,   -90,   -90,   -90,   -90,   -90,
+     -90,   139,   -90,   -90,   138,   -90,   142,   -90,   143,   -90,
+     152,   -90,   164,   167,   168,   -90,   -90,    -4,    -4,    77,
+     -18,   -90,   177,   185,    33,    71,   195,   247,   236,    -2,
+     236,   171,   -90,   -90,   -90,   -90,   -90,   -90,    41,   -90,
+      -4,    -4,   138,    97,    97,   -90,   -90,   186,   187,   194,
+      42,    42,    -4,   196,    97,   -90,   219,   -90,   -90,   -90,
+     -90,   210,   -90,   -90,   204,    42,    42,   199,   -90,   -90,
+     -90,   -90,   -90,   -90,   -90,   -90,   -90,   -90,   -90,   -90,
+     -90,   222,   -90,   223,   -90,   -90,   -90,   -90,   -90,   -90,
+     -90,   -90,   -90,   -90,   215,   -90,   -90,   -90,   -90,   -90,
+      -4,   222,   228,   222,    -5,   222,    97,    35,   229,   -90,
+     -90,   222,   232,   222,    -4,   -90,   135,   233,   -90,   -90,
+     234,   235,   222,   240,   -90,   -90,   237,   -90,   239,   -13,
+     -90,   -90,   -90,   -90,   244,    42,   -90,   -90,   -90,   -90,
+     -90
 };
 
 /* YYPGOTO[NTERM-NUM].  */
 static const yytype_int16 yypgoto[] =
 {
-     -80,   -80,   -80,   -80,   122,   -34,   -80,   -80,   -80,   -80,
-     220,   -80,   -80,   -80,   -80,   -80,   -80,   -80,    59,   -80,
-     -80,   -80,   -80,   -80,   -80,   -80,   -80,   -80,   -80,   125,
-     -80,   -80,   -80,   -80,   -80,   183,   219,    22,   142,    -5,
-     147,   192,    69,   -54,   -79,   -80
+     -90,   -90,   269,   271,   -90,    23,   -70,   -90,   -90,   -90,
+     -90,   243,   -90,   -90,   -90,   -90,   -90,   -90,   -90,   -48,
+     -90,   -90,   -90,   -90,   -90,   -90,   -90,   -90,   -90,   -90,
+     -90,   -20,   -90,   -90,   -90,   -90,   -90,   206,   205,   -68,
+     -90,   -90,   169,    -1,    27,    -7,   118,   -66,   -89,   -90
 };
 
 /* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
    positive, shift that token.  If negative, reduce the rule which
    number is the opposite.  If zero, do what YYDEFACT says.
    If YYTABLE_NINF, syntax error.  */
-#define YYTABLE_NINF -82
+#define YYTABLE_NINF -86
 static const yytype_int16 yytable[] =
 {
-      46,    47,     3,    49,    81,    82,    53,   136,   137,     6,
-       7,     8,     9,    10,    11,    12,    13,    43,   146,    14,
-      15,    86,    56,    57,    44,    45,    58,    87,    48,   134,
-     135,    59,   162,   112,    50,    24,   125,   163,   125,   -28,
-      90,   144,   -28,   -28,   -28,   -28,   -28,   -28,   -28,   -28,
-     -28,    91,    54,   -28,   -28,    92,   -28,    93,    94,    95,
-      96,    97,    98,    52,    99,    55,    90,   161,    62,   100,
-     -49,   -49,    63,   -49,   -49,   -49,   -49,    91,    64,   -49,
-     -49,    92,   107,   108,   109,   110,   154,    73,   141,   115,
-      99,    75,   126,    76,   126,   111,   133,    56,    57,    83,
-      84,   169,   140,   151,   -30,    90,    77,   -30,   -30,   -30,
-     -30,   -30,   -30,   -30,   -30,   -30,    91,    78,   -30,   -30,
-      92,   -30,    93,    94,    95,    96,    97,    98,   120,    99,
-     128,    79,    -2,     4,   100,     5,     6,     7,     8,     9,
-      10,    11,    12,    13,    83,    84,    14,    15,    16,    17,
-      18,    19,    20,    21,    22,     7,     8,    23,    10,    11,
-      12,    13,    24,    80,    14,    15,    88,   -81,    90,   179,
-     -81,   -81,   -81,   -81,   -81,   -81,   -81,   -81,   -81,    89,
-      24,   -81,   -81,    92,   -81,   -81,   -81,   -81,   -81,   -81,
-     116,   119,    99,   127,   122,    90,   130,   124,   -72,   -72,
-     -72,   -72,   -72,   -72,   -72,   -72,   132,   138,   -72,   -72,
-      92,   155,   158,   159,   160,   118,   123,   139,   131,    99,
-     165,   145,   167,   148,   124,    73,    83,    84,    83,    84,
-     173,   168,    83,    84,   149,   150,   153,   155,    84,   157,
-     164,   174,   166,   170,   171,   172,   176,   177,   178,    66,
-     114,   152,    85,     0,     0,     0,     0,     0,     0,    72
+      10,    88,    89,    54,   146,   147,   119,     1,   122,   164,
+      93,   141,    56,   142,    58,   156,    94,    62,     1,    90,
+      91,   131,    65,    66,   144,   145,    67,    90,    91,   132,
+     127,    68,   136,   -31,    97,     2,   154,   -31,   -31,   -31,
+     -31,   -31,   -31,   -31,   -31,    98,    52,   -31,   -31,    99,
+     -31,   100,   101,   102,   103,   104,   -31,   105,   129,   106,
+     138,   173,    92,   141,   107,   142,   174,   172,     8,     9,
+     143,   -33,    97,    90,    91,   -33,   -33,   -33,   -33,   -33,
+     -33,   -33,   -33,    98,   166,   -33,   -33,    99,   -33,   100,
+     101,   102,   103,   104,   -33,   105,    11,   106,   179,   151,
+     123,   126,   107,   135,   125,   130,     2,   139,     2,    90,
+      91,    -5,    12,    55,   161,    13,    14,    15,    16,    17,
+      18,    19,    20,    65,    66,    21,    22,    23,    24,    25,
+      26,    27,    28,    29,    30,    57,    59,    31,    61,    -4,
+      12,    63,    32,    13,    14,    15,    16,    17,    18,    19,
+      20,    64,    71,    21,    22,    23,    24,    25,    26,    27,
+      28,    29,    30,    72,    73,    31,   180,    90,    91,    52,
+      32,   -85,    97,    82,    83,   -85,   -85,   -85,   -85,   -85,
+     -85,   -85,   -85,    84,   190,   -85,   -85,    99,   -85,   -85,
+     -85,   -85,   -85,   -85,   -85,    85,    97,   106,    86,    87,
+     -52,   -52,   140,   -52,   -52,   -52,   -52,    98,    95,   -52,
+     -52,    99,   114,   115,   116,   117,    96,   148,   149,   150,
+     158,   106,   155,   159,    97,   163,   118,   -76,   -76,   -76,
+     -76,   -76,   -76,   -76,   -76,   160,   164,   -76,   -76,    99,
+      13,    14,    15,    16,    17,    18,    19,    20,    91,   106,
+      21,    22,    14,    15,   140,    17,    18,    19,    20,   168,
+     175,    21,    22,   177,   181,   182,   183,    32,   187,   167,
+     188,   169,   170,   171,   185,   189,    53,    51,    32,   176,
+      75,   178,   121,     0,   133,   162,     0,     0,     0,     0,
+     184
 };
 
 static const yytype_int16 yycheck[] =
 {
-       5,     6,     0,     8,    58,    59,    11,    86,    87,     4,
-       5,     6,     7,     8,     9,    10,    11,    30,    97,    14,
-      15,    27,    25,    26,    25,    26,    29,    33,    30,    83,
-      84,    34,    25,    67,    25,    30,    70,    30,    72,     0,
-       1,    95,     3,     4,     5,     6,     7,     8,     9,    10,
-      11,    12,    25,    14,    15,    16,    17,    18,    19,    20,
-      21,    22,    23,    30,    25,    25,     1,   146,    30,    30,
-       5,     6,     1,     8,     9,    10,    11,    12,     1,    14,
-      15,    16,    17,    18,    19,    20,   140,    30,    93,    67,
-      25,    30,    70,    30,    72,    30,    28,    25,    26,    31,
-      32,   155,    24,   108,     0,     1,    30,     3,     4,     5,
-       6,     7,     8,     9,    10,    11,    12,    30,    14,    15,
-      16,    17,    18,    19,    20,    21,    22,    23,    69,    25,
-      71,    30,     0,     1,    30,     3,     4,     5,     6,     7,
-       8,     9,    10,    11,    31,    32,    14,    15,    16,    17,
-      18,    19,    20,    21,    22,     5,     6,    25,     8,     9,
-      10,    11,    30,    30,    14,    15,    30,     0,     1,   174,
-       3,     4,     5,     6,     7,     8,     9,    10,    11,    30,
-      30,    14,    15,    16,    17,    18,    19,    20,    21,    22,
-      68,    69,    25,    71,    69,     1,    71,    30,     4,     5,
-       6,     7,     8,     9,    10,    11,    30,    30,    14,    15,
-      16,    14,   143,   144,   145,    68,    69,    30,    71,    25,
-     151,    25,   153,     1,    30,    30,    31,    32,    31,    32,
-     161,    30,    31,    32,    13,    30,    25,    14,    32,    30,
-      30,    33,    30,    30,    30,    30,    30,    30,    30,    29,
-      67,   109,    60,    -1,    -1,    -1,    -1,    -1,    -1,    40
+       1,    67,    68,    10,    93,    94,    76,     3,    76,    14,
+      28,    81,    13,    81,    15,   104,    34,    18,     3,    32,
+      33,    23,    26,    27,    90,    91,    30,    32,    33,    31,
+      78,    35,    80,     0,     1,    31,   102,     4,     5,     6,
+       7,     8,     9,    10,    11,    12,    31,    14,    15,    16,
+      17,    18,    19,    20,    21,    22,    23,    24,    78,    26,
+      80,    26,    69,   133,    31,   133,    31,   156,    26,    27,
+      29,     0,     1,    32,    33,     4,     5,     6,     7,     8,
+       9,    10,    11,    12,   150,    14,    15,    16,    17,    18,
+      19,    20,    21,    22,    23,    24,     0,    26,   164,   100,
+      77,    78,    31,    80,    77,    78,    31,    80,    31,    32,
+      33,     0,     1,    31,   115,     4,     5,     6,     7,     8,
+       9,    10,    11,    26,    27,    14,    15,    16,    17,    18,
+      19,    20,    21,    22,    23,    31,    26,    26,    31,     0,
+       1,    26,    31,     4,     5,     6,     7,     8,     9,    10,
+      11,    26,    31,    14,    15,    16,    17,    18,    19,    20,
+      21,    22,    23,     1,     1,    26,    31,    32,    33,    31,
+      31,     0,     1,    31,    31,     4,     5,     6,     7,     8,
+       9,    10,    11,    31,   185,    14,    15,    16,    17,    18,
+      19,    20,    21,    22,    23,    31,     1,    26,    31,    31,
+       5,     6,    31,     8,     9,    10,    11,    12,    31,    14,
+      15,    16,    17,    18,    19,    20,    31,    31,    31,    25,
+       1,    26,    26,    13,     1,    26,    31,     4,     5,     6,
+       7,     8,     9,    10,    11,    31,    14,    14,    15,    16,
+       4,     5,     6,     7,     8,     9,    10,    11,    33,    26,
+      14,    15,     5,     6,    31,     8,     9,    10,    11,    31,
+      31,    14,    15,    31,    31,    31,    31,    31,    31,   151,
+      31,   153,   154,   155,    34,    31,     7,     6,    31,   161,
+      37,   163,    76,    -1,    79,   116,    -1,    -1,    -1,    -1,
+     172
 };
 
 /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
    symbol of state STATE-NUM.  */
 static const yytype_uint8 yystos[] =
 {
-       0,    36,    37,     0,     1,     3,     4,     5,     6,     7,
-       8,     9,    10,    11,    14,    15,    16,    17,    18,    19,
-      20,    21,    22,    25,    30,    38,    39,    41,    42,    43,
-      44,    50,    51,    53,    57,    59,    61,    62,    64,    66,
-      67,    68,    75,    30,    25,    26,    74,    74,    30,    74,
-      25,    80,    30,    74,    25,    25,    25,    26,    29,    34,
-      78,    79,    30,     1,     1,    45,    45,    54,    56,    60,
-      71,    65,    71,    30,    76,    30,    30,    30,    30,    30,
-      30,    78,    78,    31,    32,    76,    27,    33,    30,    30,
-       1,    12,    16,    18,    19,    20,    21,    22,    23,    25,
-      30,    40,    46,    47,    69,    70,    72,    17,    18,    19,
-      20,    30,    40,    55,    70,    72,    39,    52,    75,    39,
-      53,    58,    64,    75,    30,    40,    72,    39,    53,    63,
-      64,    75,    30,    28,    78,    78,    79,    79,    30,    30,
-      24,    74,    73,    74,    78,    25,    79,    48,     1,    13,
-      30,    74,    73,    25,    78,    14,    77,    30,    77,    77,
-      77,    79,    25,    30,    30,    77,    30,    77,    30,    78,
-      30,    30,    30,    77,    33,    49,    30,    30,    30,    74
+       0,     3,    31,    37,    38,    39,    63,    81,    26,    27,
+      79,     0,     1,     4,     5,     6,     7,     8,     9,    10,
+      11,    14,    15,    16,    17,    18,    19,    20,    21,    22,
+      23,    26,    31,    40,    41,    43,    44,    45,    46,    52,
+      53,    55,    59,    61,    64,    65,    67,    69,    70,    71,
+      80,    39,    31,    38,    81,    31,    79,    31,    79,    26,
+      85,    31,    79,    26,    26,    26,    27,    30,    35,    83,
+      84,    31,     1,     1,    47,    47,    56,    58,    62,    76,
+      68,    74,    31,    31,    31,    31,    31,    31,    83,    83,
+      32,    33,    81,    28,    34,    31,    31,     1,    12,    16,
+      18,    19,    20,    21,    22,    24,    26,    31,    42,    48,
+      49,    72,    73,    75,    17,    18,    19,    20,    31,    42,
+      57,    73,    75,    41,    54,    80,    41,    55,    60,    67,
+      80,    23,    31,    74,    77,    41,    55,    66,    67,    80,
+      31,    42,    75,    29,    83,    83,    84,    84,    31,    31,
+      25,    79,    78,    79,    83,    26,    84,    50,     1,    13,
+      31,    79,    78,    26,    14,    82,    83,    82,    31,    82,
+      82,    82,    84,    26,    31,    31,    82,    31,    82,    83,
+      31,    31,    31,    31,    82,    34,    51,    31,    31,    31,
+      79
 };
 
 #define yyerrok                (yyerrstatus = 0)
@@ -815,9 +800,18 @@ static const yytype_uint8 yystos[] =
 
 /* Like YYERROR except do call yyerror.  This remains here temporarily
    to ease the transition to the new meaning of YYERROR, for GCC.
-   Once GCC version 2 has supplanted version 1, this can go.  */
+   Once GCC version 2 has supplanted version 1, this can go.  However,
+   YYFAIL appears to be in use.  Nevertheless, it is formally deprecated
+   in Bison 2.4.2's NEWS entry, where a plan to phase it out is
+   discussed.  */
 
 #define YYFAIL         goto yyerrlab
+#if defined YYFAIL
+  /* This is here to suppress warnings from the GCC cpp's
+     -Wunused-macros.  Normally we don't worry about that warning, but
+     some users do, and we want to make it easy for users to remove
+     YYFAIL uses, which will produce warnings from Bison 2.5.  */
+#endif
 
 #define YYRECOVERING()  (!!yyerrstatus)
 
@@ -874,7 +868,7 @@ while (YYID (0))
    we won't break user code: when these are the locations we know.  */
 
 #ifndef YY_LOCATION_PRINT
-# if YYLTYPE_IS_TRIVIAL
+# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
 #  define YY_LOCATION_PRINT(File, Loc)                 \
      fprintf (File, "%d.%d-%d.%d",                     \
              (Loc).first_line, (Loc).first_column,     \
@@ -985,17 +979,20 @@ yy_symbol_print (yyoutput, yytype, yyvaluep)
 #if (defined __STDC__ || defined __C99__FUNC__ \
      || defined __cplusplus || defined _MSC_VER)
 static void
-yy_stack_print (yytype_int16 *bottom, yytype_int16 *top)
+yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
 #else
 static void
-yy_stack_print (bottom, top)
-    yytype_int16 *bottom;
-    yytype_int16 *top;
+yy_stack_print (yybottom, yytop)
+    yytype_int16 *yybottom;
+    yytype_int16 *yytop;
 #endif
 {
   YYFPRINTF (stderr, "Stack now");
-  for (; bottom <= top; ++bottom)
-    YYFPRINTF (stderr, " %d", *bottom);
+  for (; yybottom <= yytop; yybottom++)
+    {
+      int yybot = *yybottom;
+      YYFPRINTF (stderr, " %d", yybot);
+    }
   YYFPRINTF (stderr, "\n");
 }
 
@@ -1029,11 +1026,11 @@ yy_reduce_print (yyvsp, yyrule)
   /* The symbols being reduced.  */
   for (yyi = 0; yyi < yynrhs; yyi++)
     {
-      fprintf (stderr, "   $%d = ", yyi + 1);
+      YYFPRINTF (stderr, "   $%d = ", yyi + 1);
       yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
                       &(yyvsp[(yyi + 1) - (yynrhs)])
                                       );
-      fprintf (stderr, "\n");
+      YYFPRINTF (stderr, "\n");
     }
 }
 
@@ -1308,7 +1305,7 @@ yydestruct (yymsg, yytype, yyvaluep)
 
   switch (yytype)
     {
-      case 51: /* "choice_entry" */
+      case 53: /* "choice_entry" */
 
        {
        fprintf(stderr, "%s:%d: missing end statement for this entry\n",
@@ -1318,7 +1315,7 @@ yydestruct (yymsg, yytype, yyvaluep)
 };
 
        break;
-      case 57: /* "if_entry" */
+      case 59: /* "if_entry" */
 
        {
        fprintf(stderr, "%s:%d: missing end statement for this entry\n",
@@ -1328,7 +1325,7 @@ yydestruct (yymsg, yytype, yyvaluep)
 };
 
        break;
-      case 62: /* "menu_entry" */
+      case 65: /* "menu_entry" */
 
        {
        fprintf(stderr, "%s:%d: missing end statement for this entry\n",
@@ -1343,10 +1340,8 @@ yydestruct (yymsg, yytype, yyvaluep)
        break;
     }
 }
-\f
 
 /* Prevent warnings from -Wmissing-prototypes.  */
-
 #ifdef YYPARSE_PARAM
 #if defined __STDC__ || defined __cplusplus
 int yyparse (void *YYPARSE_PARAM);
@@ -1362,11 +1357,10 @@ int yyparse ();
 #endif /* ! YYPARSE_PARAM */
 
 
-
-/* The look-ahead symbol.  */
+/* The lookahead symbol.  */
 int yychar;
 
-/* The semantic value of the look-ahead symbol.  */
+/* The semantic value of the lookahead symbol.  */
 YYSTYPE yylval;
 
 /* Number of syntax errors so far.  */
@@ -1374,9 +1368,9 @@ int yynerrs;
 
 
 
-/*----------.
-| yyparse.  |
-`----------*/
+/*-------------------------.
+| yyparse or yypush_parse.  |
+`-------------------------*/
 
 #ifdef YYPARSE_PARAM
 #if (defined __STDC__ || defined __C99__FUNC__ \
@@ -1400,66 +1394,68 @@ yyparse ()
 #endif
 #endif
 {
-  
-  int yystate;
-  int yyn;
-  int yyresult;
-  /* Number of tokens to shift before error messages enabled.  */
-  int yyerrstatus;
-  /* Look-ahead token as an internal (translated) token number.  */
-  int yytoken = 0;
-#if YYERROR_VERBOSE
-  /* Buffer for error messages, and its allocated size.  */
-  char yymsgbuf[128];
-  char *yymsg = yymsgbuf;
-  YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
-#endif
 
-  /* Three stacks and their tools:
-     `yyss': related to states,
-     `yyvs': related to semantic values,
-     `yyls': related to locations.
 
-     Refer to the stacks thru separate pointers, to allow yyoverflow
-     to reallocate them elsewhere.  */
+    int yystate;
+    /* Number of tokens to shift before error messages enabled.  */
+    int yyerrstatus;
 
-  /* The state stack.  */
-  yytype_int16 yyssa[YYINITDEPTH];
-  yytype_int16 *yyss = yyssa;
-  yytype_int16 *yyssp;
+    /* The stacks and their tools:
+       `yyss': related to states.
+       `yyvs': related to semantic values.
 
-  /* The semantic value stack.  */
-  YYSTYPE yyvsa[YYINITDEPTH];
-  YYSTYPE *yyvs = yyvsa;
-  YYSTYPE *yyvsp;
+       Refer to the stacks thru separate pointers, to allow yyoverflow
+       to reallocate them elsewhere.  */
 
+    /* The state stack.  */
+    yytype_int16 yyssa[YYINITDEPTH];
+    yytype_int16 *yyss;
+    yytype_int16 *yyssp;
 
+    /* The semantic value stack.  */
+    YYSTYPE yyvsa[YYINITDEPTH];
+    YYSTYPE *yyvs;
+    YYSTYPE *yyvsp;
 
-#define YYPOPSTACK(N)   (yyvsp -= (N), yyssp -= (N))
-
-  YYSIZE_T yystacksize = YYINITDEPTH;
+    YYSIZE_T yystacksize;
 
+  int yyn;
+  int yyresult;
+  /* Lookahead token as an internal (translated) token number.  */
+  int yytoken;
   /* The variables used to return semantic value and location from the
      action routines.  */
   YYSTYPE yyval;
 
+#if YYERROR_VERBOSE
+  /* Buffer for error messages, and its allocated size.  */
+  char yymsgbuf[128];
+  char *yymsg = yymsgbuf;
+  YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
+#endif
+
+#define YYPOPSTACK(N)   (yyvsp -= (N), yyssp -= (N))
 
   /* The number of symbols on the RHS of the reduced rule.
      Keep to zero when no symbol should be popped.  */
   int yylen = 0;
 
+  yytoken = 0;
+  yyss = yyssa;
+  yyvs = yyvsa;
+  yystacksize = YYINITDEPTH;
+
   YYDPRINTF ((stderr, "Starting parse\n"));
 
   yystate = 0;
   yyerrstatus = 0;
   yynerrs = 0;
-  yychar = YYEMPTY;            /* Cause a token to be read.  */
+  yychar = YYEMPTY; /* Cause a token to be read.  */
 
   /* Initialize stack pointers.
      Waste one element of value and location stack
      so that they stay on the same level as the state stack.
      The wasted elements are never initialized.  */
-
   yyssp = yyss;
   yyvsp = yyvs;
 
@@ -1489,7 +1485,6 @@ yyparse ()
        YYSTYPE *yyvs1 = yyvs;
        yytype_int16 *yyss1 = yyss;
 
-
        /* Each stack pointer address is followed by the size of the
           data in use in that stack, in bytes.  This used to be a
           conditional around just the two extra args, but that might
@@ -1497,7 +1492,6 @@ yyparse ()
        yyoverflow (YY_("memory exhausted"),
                    &yyss1, yysize * sizeof (*yyssp),
                    &yyvs1, yysize * sizeof (*yyvsp),
-
                    &yystacksize);
 
        yyss = yyss1;
@@ -1520,9 +1514,8 @@ yyparse ()
          (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
        if (! yyptr)
          goto yyexhaustedlab;
-       YYSTACK_RELOCATE (yyss);
-       YYSTACK_RELOCATE (yyvs);
-
+       YYSTACK_RELOCATE (yyss_alloc, yyss);
+       YYSTACK_RELOCATE (yyvs_alloc, yyvs);
 #  undef YYSTACK_RELOCATE
        if (yyss1 != yyssa)
          YYSTACK_FREE (yyss1);
@@ -1533,7 +1526,6 @@ yyparse ()
       yyssp = yyss + yysize - 1;
       yyvsp = yyvs + yysize - 1;
 
-
       YYDPRINTF ((stderr, "Stack size increased to %lu\n",
                  (unsigned long int) yystacksize));
 
@@ -1543,6 +1535,9 @@ yyparse ()
 
   YYDPRINTF ((stderr, "Entering state %d\n", yystate));
 
+  if (yystate == YYFINAL)
+    YYACCEPT;
+
   goto yybackup;
 
 /*-----------.
@@ -1551,16 +1546,16 @@ yyparse ()
 yybackup:
 
   /* Do appropriate processing given the current state.  Read a
-     look-ahead token if we need one and don't already have one.  */
+     lookahead token if we need one and don't already have one.  */
 
-  /* First try to decide what to do without reference to look-ahead token.  */
+  /* First try to decide what to do without reference to lookahead token.  */
   yyn = yypact[yystate];
   if (yyn == YYPACT_NINF)
     goto yydefault;
 
-  /* Not known => get a look-ahead token if don't already have one.  */
+  /* Not known => get a lookahead token if don't already have one.  */
 
-  /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol.  */
+  /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol.  */
   if (yychar == YYEMPTY)
     {
       YYDPRINTF ((stderr, "Reading a token: "));
@@ -1592,20 +1587,16 @@ yybackup:
       goto yyreduce;
     }
 
-  if (yyn == YYFINAL)
-    YYACCEPT;
-
   /* Count tokens shifted since error; after three, turn off error
      status.  */
   if (yyerrstatus)
     yyerrstatus--;
 
-  /* Shift the look-ahead token.  */
+  /* Shift the lookahead token.  */
   YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
 
-  /* Discard the shifted token unless it is eof.  */
-  if (yychar != YYEOF)
-    yychar = YYEMPTY;
+  /* Discard the shifted token.  */
+  yychar = YYEMPTY;
 
   yystate = yyn;
   *++yyvsp = yylval;
@@ -1644,39 +1635,39 @@ yyreduce:
   YY_REDUCE_PRINT (yyn);
   switch (yyn)
     {
-        case 8:
+        case 10:
 
     { zconf_error("unexpected end statement"); ;}
     break;
 
-  case 9:
+  case 11:
 
     { zconf_error("unknown statement \"%s\"", (yyvsp[(2) - (4)].string)); ;}
     break;
 
-  case 10:
+  case 12:
 
     {
        zconf_error("unexpected option \"%s\"", kconf_id_strings + (yyvsp[(2) - (4)].id)->name);
 ;}
     break;
 
-  case 11:
+  case 13:
 
     { zconf_error("invalid statement"); ;}
     break;
 
-  case 25:
+  case 28:
 
     { zconf_error("unknown option \"%s\"", (yyvsp[(1) - (3)].string)); ;}
     break;
 
-  case 26:
+  case 29:
 
     { zconf_error("invalid option"); ;}
     break;
 
-  case 27:
+  case 30:
 
     {
        struct symbol *sym = sym_lookup((yyvsp[(2) - (3)].string), 0);
@@ -1686,7 +1677,7 @@ yyreduce:
 ;}
     break;
 
-  case 28:
+  case 31:
 
     {
        menu_end_entry();
@@ -1694,7 +1685,7 @@ yyreduce:
 ;}
     break;
 
-  case 29:
+  case 32:
 
     {
        struct symbol *sym = sym_lookup((yyvsp[(2) - (3)].string), 0);
@@ -1704,7 +1695,7 @@ yyreduce:
 ;}
     break;
 
-  case 30:
+  case 33:
 
     {
        if (current_entry->prompt)
@@ -1716,7 +1707,7 @@ yyreduce:
 ;}
     break;
 
-  case 38:
+  case 41:
 
     {
        menu_set_type((yyvsp[(1) - (3)].id)->stype);
@@ -1726,7 +1717,7 @@ yyreduce:
 ;}
     break;
 
-  case 39:
+  case 42:
 
     {
        menu_add_prompt(P_PROMPT, (yyvsp[(2) - (4)].string), (yyvsp[(3) - (4)].expr));
@@ -1734,7 +1725,7 @@ yyreduce:
 ;}
     break;
 
-  case 40:
+  case 43:
 
     {
        menu_add_expr(P_DEFAULT, (yyvsp[(2) - (4)].expr), (yyvsp[(3) - (4)].expr));
@@ -1746,7 +1737,7 @@ yyreduce:
 ;}
     break;
 
-  case 41:
+  case 44:
 
     {
        menu_add_symbol(P_SELECT, sym_lookup((yyvsp[(2) - (4)].string), 0), (yyvsp[(3) - (4)].expr));
@@ -1754,7 +1745,7 @@ yyreduce:
 ;}
     break;
 
-  case 42:
+  case 45:
 
     {
        menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,(yyvsp[(2) - (5)].symbol), (yyvsp[(3) - (5)].symbol)), (yyvsp[(4) - (5)].expr));
@@ -1762,10 +1753,10 @@ yyreduce:
 ;}
     break;
 
-  case 45:
+  case 48:
 
     {
-       struct kconf_id *id = kconf_id_lookup((yyvsp[(2) - (3)].string), strlen((yyvsp[(2) - (3)].string)));
+       const struct kconf_id *id = kconf_id_lookup((yyvsp[(2) - (3)].string), strlen((yyvsp[(2) - (3)].string)));
        if (id && id->flags & TF_OPTION)
                menu_add_option(id->token, (yyvsp[(3) - (3)].string));
        else
@@ -1774,17 +1765,17 @@ yyreduce:
 ;}
     break;
 
-  case 46:
+  case 49:
 
     { (yyval.string) = NULL; ;}
     break;
 
-  case 47:
+  case 50:
 
     { (yyval.string) = (yyvsp[(2) - (2)].string); ;}
     break;
 
-  case 48:
+  case 51:
 
     {
        struct symbol *sym = sym_lookup((yyvsp[(2) - (3)].string), SYMBOL_CHOICE);
@@ -1795,14 +1786,14 @@ yyreduce:
 ;}
     break;
 
-  case 49:
+  case 52:
 
     {
        (yyval.menu) = menu_add_menu();
 ;}
     break;
 
-  case 50:
+  case 53:
 
     {
        if (zconf_endtoken((yyvsp[(1) - (1)].id), T_CHOICE, T_ENDCHOICE)) {
@@ -1812,7 +1803,7 @@ yyreduce:
 ;}
     break;
 
-  case 58:
+  case 61:
 
     {
        menu_add_prompt(P_PROMPT, (yyvsp[(2) - (4)].string), (yyvsp[(3) - (4)].expr));
@@ -1820,7 +1811,7 @@ yyreduce:
 ;}
     break;
 
-  case 59:
+  case 62:
 
     {
        if ((yyvsp[(1) - (3)].id)->stype == S_BOOLEAN || (yyvsp[(1) - (3)].id)->stype == S_TRISTATE) {
@@ -1833,7 +1824,7 @@ yyreduce:
 ;}
     break;
 
-  case 60:
+  case 63:
 
     {
        current_entry->sym->flags |= SYMBOL_OPTIONAL;
@@ -1841,7 +1832,7 @@ yyreduce:
 ;}
     break;
 
-  case 61:
+  case 64:
 
     {
        if ((yyvsp[(1) - (4)].id)->stype == S_UNKNOWN) {
@@ -1853,7 +1844,7 @@ yyreduce:
 ;}
     break;
 
-  case 64:
+  case 67:
 
     {
        printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno());
@@ -1863,7 +1854,7 @@ yyreduce:
 ;}
     break;
 
-  case 65:
+  case 68:
 
     {
        if (zconf_endtoken((yyvsp[(1) - (1)].id), T_IF, T_ENDIF)) {
@@ -1873,7 +1864,14 @@ yyreduce:
 ;}
     break;
 
-  case 71:
+  case 74:
+
+    {
+       menu_add_prompt(P_MENU, (yyvsp[(2) - (3)].string), NULL);
+;}
+    break;
+
+  case 75:
 
     {
        menu_add_entry(NULL);
@@ -1882,14 +1880,14 @@ yyreduce:
 ;}
     break;
 
-  case 72:
+  case 76:
 
     {
        (yyval.menu) = menu_add_menu();
 ;}
     break;
 
-  case 73:
+  case 77:
 
     {
        if (zconf_endtoken((yyvsp[(1) - (1)].id), T_MENU, T_ENDMENU)) {
@@ -1899,7 +1897,7 @@ yyreduce:
 ;}
     break;
 
-  case 79:
+  case 83:
 
     {
        printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), (yyvsp[(2) - (3)].string));
@@ -1907,7 +1905,7 @@ yyreduce:
 ;}
     break;
 
-  case 80:
+  case 84:
 
     {
        menu_add_entry(NULL);
@@ -1916,14 +1914,14 @@ yyreduce:
 ;}
     break;
 
-  case 81:
+  case 85:
 
     {
        menu_end_entry();
 ;}
     break;
 
-  case 82:
+  case 86:
 
     {
        printd(DEBUG_PARSE, "%s:%d:help\n", zconf_curname(), zconf_lineno());
@@ -1931,14 +1929,14 @@ yyreduce:
 ;}
     break;
 
-  case 83:
+  case 87:
 
     {
        current_entry->help = (yyvsp[(2) - (2)].string);
 ;}
     break;
 
-  case 88:
+  case 92:
 
     {
        menu_add_dep((yyvsp[(3) - (4)].expr));
@@ -1946,90 +1944,96 @@ yyreduce:
 ;}
     break;
 
-  case 90:
+  case 96:
+
+    {
+       menu_add_visibility((yyvsp[(2) - (2)].expr));
+;}
+    break;
+
+  case 98:
 
     {
        menu_add_prompt(P_PROMPT, (yyvsp[(1) - (2)].string), (yyvsp[(2) - (2)].expr));
 ;}
     break;
 
-  case 93:
+  case 101:
 
     { (yyval.id) = (yyvsp[(1) - (2)].id); ;}
     break;
 
-  case 94:
+  case 102:
 
     { (yyval.id) = (yyvsp[(1) - (2)].id); ;}
     break;
 
-  case 95:
+  case 103:
 
     { (yyval.id) = (yyvsp[(1) - (2)].id); ;}
     break;
 
-  case 98:
+  case 106:
 
     { (yyval.expr) = NULL; ;}
     break;
 
-  case 99:
+  case 107:
 
     { (yyval.expr) = (yyvsp[(2) - (2)].expr); ;}
     break;
 
-  case 100:
+  case 108:
 
     { (yyval.expr) = expr_alloc_symbol((yyvsp[(1) - (1)].symbol)); ;}
     break;
 
-  case 101:
+  case 109:
 
     { (yyval.expr) = expr_alloc_comp(E_EQUAL, (yyvsp[(1) - (3)].symbol), (yyvsp[(3) - (3)].symbol)); ;}
     break;
 
-  case 102:
+  case 110:
 
     { (yyval.expr) = expr_alloc_comp(E_UNEQUAL, (yyvsp[(1) - (3)].symbol), (yyvsp[(3) - (3)].symbol)); ;}
     break;
 
-  case 103:
+  case 111:
 
     { (yyval.expr) = (yyvsp[(2) - (3)].expr); ;}
     break;
 
-  case 104:
+  case 112:
 
     { (yyval.expr) = expr_alloc_one(E_NOT, (yyvsp[(2) - (2)].expr)); ;}
     break;
 
-  case 105:
+  case 113:
 
     { (yyval.expr) = expr_alloc_two(E_OR, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
     break;
 
-  case 106:
+  case 114:
 
     { (yyval.expr) = expr_alloc_two(E_AND, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
     break;
 
-  case 107:
+  case 115:
 
     { (yyval.symbol) = sym_lookup((yyvsp[(1) - (1)].string), 0); free((yyvsp[(1) - (1)].string)); ;}
     break;
 
-  case 108:
+  case 116:
 
     { (yyval.symbol) = sym_lookup((yyvsp[(1) - (1)].string), SYMBOL_CONST); free((yyvsp[(1) - (1)].string)); ;}
     break;
 
-  case 109:
+  case 117:
 
     { (yyval.string) = NULL; ;}
     break;
 
 
-/* Line 1267 of yacc.c.  */
 
       default: break;
     }
@@ -2041,7 +2045,6 @@ yyreduce:
 
   *++yyvsp = yyval;
 
-
   /* Now `shift' the result of the reduction.  Determine what state
      that goes to, based on the state we popped back to and the rule
      number reduced by.  */
@@ -2106,7 +2109,7 @@ yyerrlab:
 
   if (yyerrstatus == 3)
     {
-      /* If just tried and failed to reuse look-ahead token after an
+      /* If just tried and failed to reuse lookahead token after an
         error, discard it.  */
 
       if (yychar <= YYEOF)
@@ -2123,7 +2126,7 @@ yyerrlab:
        }
     }
 
-  /* Else will try to reuse look-ahead token after shifting the error
+  /* Else will try to reuse lookahead token after shifting the error
      token.  */
   goto yyerrlab1;
 
@@ -2180,9 +2183,6 @@ yyerrlab1:
       YY_STACK_PRINT (yyss, yyssp);
     }
 
-  if (yyn == YYFINAL)
-    YYACCEPT;
-
   *++yyvsp = yylval;
 
 
@@ -2207,7 +2207,7 @@ yyabortlab:
   yyresult = 1;
   goto yyreturn;
 
-#ifndef yyoverflow
+#if !defined(yyoverflow) || YYERROR_VERBOSE
 /*-------------------------------------------------.
 | yyexhaustedlab -- memory exhaustion comes here.  |
 `-------------------------------------------------*/
@@ -2218,7 +2218,7 @@ yyexhaustedlab:
 #endif
 
 yyreturn:
-  if (yychar != YYEOF && yychar != YYEMPTY)
+  if (yychar != YYEMPTY)
      yydestruct ("Cleanup: discarding lookahead",
                 yytoken, &yylval);
   /* Do not reclaim the symbols of the rule which action triggered
@@ -2255,16 +2255,14 @@ void conf_parse(const char *name)
        zconf_initscan(name);
 
        sym_init();
-       menu_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, "firmly.0cpm Configuration", NULL);
+       rootmenu.prompt = menu_add_prompt(P_MENU, "Linux Kernel Configuration", NULL);
 
-#if YYDEBUG
        if (getenv("ZCONF_DEBUG"))
                zconfdebug = 1;
-#endif
        zconfparse();
        if (zconfnerrs)
                exit(1);
@@ -2274,6 +2272,10 @@ void conf_parse(const char *name)
                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))
@@ -2284,7 +2286,7 @@ void conf_parse(const char *name)
        sym_set_change_count(1);
 }
 
-const char *zconf_tokenname(int token)
+static const char *zconf_tokenname(int token)
 {
        switch (token) {
        case T_MENU:            return "menu";
@@ -2294,11 +2296,12 @@ const char *zconf_tokenname(int token)
        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(struct kconf_id *id, int starttoken, int endtoken)
+static bool zconf_endtoken(const struct kconf_id *id, int starttoken, int endtoken)
 {
        if (id->token != endtoken) {
                zconf_error("unexpected '%s' within %s block",
@@ -2343,12 +2346,10 @@ static void zconf_error(const char *err, ...)
 
 static void zconferror(const char *err)
 {
-#if YYDEBUG
        fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno() + 1, err);
-#endif
 }
 
-void print_quoted_string(FILE *out, const char *str)
+static void print_quoted_string(FILE *out, const char *str)
 {
        const char *p;
        int len;
@@ -2365,15 +2366,15 @@ void print_quoted_string(FILE *out, const char *str)
        putc('"', out);
 }
 
-void print_symbol(FILE *out, struct menu *menu)
+static void print_symbol(FILE *out, struct menu *menu)
 {
        struct symbol *sym = menu->sym;
        struct property *prop;
 
        if (sym_is_choice(sym))
-               fprintf(out, "choice\n");
+               fprintf(out, "\nchoice\n");
        else
-               fprintf(out, "config %s\n", sym->name);
+               fprintf(out, "\nconfig %s\n", sym->name);
        switch (sym->type) {
        case S_BOOLEAN:
                fputs("  boolean\n", out);
@@ -2419,6 +2420,21 @@ void print_symbol(FILE *out, struct menu *menu)
                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;
@@ -2430,7 +2446,6 @@ void print_symbol(FILE *out, struct menu *menu)
                        menu->help[len] = 0;
                fprintf(out, "  help\n%s\n", menu->help);
        }
-       fputc('\n', out);
 }
 
 void zconfdump(FILE *out)
@@ -2463,7 +2478,6 @@ void zconfdump(FILE *out)
                                expr_fprint(prop->visible.expr, out);
                                fputc('\n', out);
                        }
-                       fputs("\n", out);
                }
 
                if (menu->list)
@@ -2481,7 +2495,7 @@ void zconfdump(FILE *out)
        }
 }
 
-#include "lex.zconf.c"
+#include "zconf.lex.c"
 #include "util.c"
 #include "confdata.c"
 #include "expr.c"
diff --git a/configure b/configure
new file mode 100755 (executable)
index 0000000..392091c
--- /dev/null
+++ b/configure
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+echo 'Please run "make menuconfig" for interactive configuration (as with Linux, BusyBox, ...)'
+
diff --git a/doc/howto.rst b/doc/howto.rst
new file mode 100644 (file)
index 0000000..9664d64
--- /dev/null
@@ -0,0 +1,474 @@
+==================================
+HOWTO: Try out the 0cpm Firmerware
+==================================
+
+Please read this entire document before getting started.
+
+.. contents::
+
+
+Before you start
+================
+
+**Warning:** This is premature for most users.  The 0cpm Firmerware is pre-alpha,
+        and not everything about it is working.  Developers however, may enjoy
+        trying it.  Some hardware work is involved, though.
+
+**Platform:** The 0cpm Firmerware is developed on a `Grandstream BT-200`_, but its
+        configuration menus are already prepared for other models, and even
+        other manufacturers.  If you cannot source a BT-200 anymore (they are
+        not sold any longer) then you may want to try another device, like
+        the GXP-1200 or a more advanced model with an EXT connector.  The EXT
+        connector that I've seen is an externalised I2C connector.  The GXP
+        and recent BT-200 platforms are all pretty much constant in structure,
+        their main differences being the wiring and the new LCD on the GXP
+        series.
+
+.. _`Grandstream BT-200` : http://devel.0cpm.org/firmerware/pix/bt200-twohalves.jpg
+
+Chips supported in the 0cpm Firmerware
+--------------------------------------
+
+First, you may want to check a few things:
+
+* The DSP chip is a TMS320VC5501PGF
+* The Codec chip is a TLV320AIC20K
+* The Network chip is a KSZ8842-16MQL
+
+A few older models were different:
+
+* BT-100 uses a tic54x DSP, which boots over SPI instead of I2C.
+  SPI is not a bus, making the development process less comfortable.
+  It is quite possible, though.
+* Older BT-200 and GXP-2020 used RTL8019AS network chips, and possibly
+  an RTL8035SC switch.  It should be trivial to add support for those,
+  although I've also seen very early devices with two network chips and
+  switching done in the DSP, that would be a bit harder.
+
+
+Study the hardware information
+------------------------------
+
+The documentation for the BT 200 is the most extensive, and since
+it is similar to all other models, you should probably start there.
+There are separate pages to describe the PCB_ and GPIO_.  You may
+also want to read a bit about the Connectors_ found on board.
+Finally, I keep a `datasheet archive`_ for your reference.  Please
+spare my bandwidth by downloading the entire set to your local system
+once?
+
+.. _PCB : http://reverse.0cpm.org/grandstream/pcb-bt200.html
+
+.. _GPIO : http://reverse.0cpm.org/grandstream/gpio-bt200.html
+
+.. _Connectors : http://reverse.0cpm.org/grandstream/connect.html
+
+.. _`datasheet archive` : http://reverse.0cpm.org/grandstream/datasheet/
+
+Setting up the hardware
+=======================
+
+Let's get the soldering iron out first.
+
+
+Tip: Solder a switch in the powerline
+-------------------------------------
+
+The design of the phone is made to be always-on.  You want to reset a lot more
+often than designed though, so you probably should solder a switch in the 5V-side
+of your phone's power supply.  It's very simple but extremely useful.
+
+
+
+Create your I2C bootstrapping setup
+-----------------------------------
+
+Get a number (up to eight) I2C EEPROMs of 64 kB each, and stack them
+as shown below.  You can connect most pins, as these constitute a bus,
+but an exception must be made for the pins A0/A1/A2, which must each
+have a differnt combination of ones and zeroes.  I've used a Gray
+coded addressing scheme, and could therebby set different values to
+all pins without crossing wires and without even needing more wire
+than the clipped-off or bent-aside address pins ``;-)``
+
+.. figure:: pix/bootfloppy-i2c-busside.jpg
+
+   The "bus side" of the EEPROM stack simply connects all lines.
+
+.. figure:: pix/bootfloppy-i2c-graycodedside.jpg
+
+   The "address side" of the EEPROM stack offers different values to A0/A1/A2.
+
+The Gray code for this example would be:
+
+        ==== ==== ====
+        A0   A1   A2
+        ==== ==== ====
+        0    0    0
+        0    0    1
+        0    1    1
+        0    1    0
+        1    1    0
+        1    1    1
+        1    0    1
+        1    0    0
+        ==== ==== ====
+
+Now solder a cable to the I2C connector on the phone's PCB.  This
+looks like a single line of 6 pins that are 2mm (!) apart:
+
+        ======  ===========
+        Pin     Signal
+        ======  ===========
+        1       VTref
+        2       SDA
+        3       SCL
+        4       BOOTM[0]
+        5       BOOTM[2]
+        6       GND
+        ======  ===========
+
+The device normally boots with BOOTM[2:0] temporarily pulled to 011 during system reset, causing it to boot from the Flash chip on the PCB.  When booting over I2C is preferred, the I2C EEPROMs can be connected as a consecutive address range. To activate this boot mode, BOOTM[2:0] must be set to 110, so pin 5 of J402 must be pulled high and pin 4 must be pulled low.  The build environment for the 0cpm Firmerware constructs an image properly formatted for boot over I2C.
+
+
+I've created a sequence of connectors that turned out to be really helpful::
+
+                         A  /---- bootkey
+   phone I2C --------------<                   /----- EEPROM stack
+                            \-----------------<
+                                            B  \----------------------- parport-i2c
+
+The splits are made from 2x6 recptors for pin headers.  I bent the pins so that
+the same signals appear on adjacent pins; this is connector A:
+
+        =========== ===========
+        Signal      Signal
+        =========== ===========
+        VTref       VTref
+        SDA         SDA
+        SCL         SCL
+        BOOTM[0]    BOOTM[0]
+        BOOTM[2]    BOOTM[2]
+        GND         GND
+        =========== ===========
+
+And this is connector B:
+
+        =========== ===========
+        Signal      Signal
+        =========== ===========
+        SCL         SCL
+        GND         GND
+        SDA         SDA
+        VTref       VTref
+        =========== ===========
+
+The bootkey can be inserted to boot from the I2C EEPROM stack, or
+retracted to boot the standard firmware.  Being able to do the
+latter is a big help if you are ever in doubt whether you've
+destroyed the hardware.  If you did, usually you've pulled a
+connector loose, or pushed so hard on pins that they've flown
+to touch each other.  In the latter case, get a needle and
+scratch the pins apart again.  This happened to me fairly
+regularly; other than that, the hardware is rock-solid.
+
+The connections of the boot key are:
+
+        =========== ===========
+        Signal      Signal
+        =========== ===========
+        VTref       wire 1
+        SDA         n/c
+        SCL         n/c
+        BOOTM[0]    wire 2
+        BOOTM[2]    wire 1
+        GND         wire 2
+        =========== ===========
+
+Be sure to mark the "1" sides on all your connectors, and to
+attach labels to each cable explaining what they do and what
+signals they are made for.
+
+For parport-i2c, please construct an I2C interface as documented
+in the Linux kernel.  The 0cpm Firmerware contains a programming
+utility under ``bin/i2cp``.  I've found that the TTL logic of
+the 5V-based parallel port on my PC naturally yielded levels
+that would work for I2C at 3V3.  Be careful though, you may
+end up blowing more than your mind away.
+
+.. figure:: pix/bootfloppy-i2c-parport_pc.jpg
+
+   The entire parport-i2c interface fits inside a D-BUS plug.
+
+
+Getting started with development
+================================
+
+Time to get all soft now.
+
+
+Setting up your development environment
+---------------------------------------
+
+Get the toolchain from TI.  They make it available at no cost.
+Unfortunately their license is a bit tight about distributing the
+toolchain alongside software that is not purely intended for their
+chips.  I intend to wiggle this a bit and get a special arrangement
+for the 0cpm Firmerware in light of the GPLv3 requirements.
+
+The toolchain can be found on ti.com, but may take some searching;
+its location is not constant and they are more eager in showing
+their more complete (and much more pricy) Code Composer Studio.
+But TI is motivated to support open source projects, and will even
+help you out if you cannot find it.  (Or I could, of course.)
+
+I installed to toolchain into ``/opt/tic55x-ti/`` and this may
+actually be reflected in these early build environments.  Other
+than this, you would need the usual suspects -- notably, ``make``.
+
+
+Checking out the 0cpm Firmerware
+--------------------------------
+
+I hope to have all that is required for an outsider build available
+in GIT; the only exception may be a few booting scripts that setup
+the BSS and STATIC areas, and a number of registers that need to be
+setup early in the hardware.
+
+Sorry I haven't taken the time to check outsider builds yet, that
+is one reason why this is pre-alphe software.  If you end up in
+unsolveable trouble, contact me and I can probably help you out.
+
+Note that the reason that these parts are missing is because I don't
+want to break anyone's copyrights, which publication in GIT would
+do.  I can proably talk you through finding it in your local setup though.
+
+
+Anyhow, this is the GIT repository for the 0cpm Firmerware:
+
+        git://git.0cpm.org/firmerware/
+
+You should be able to clone it and continue from there.
+Once again, this is pre-alpha software, I aim to checkin only
+compiling versions but in this phase I suppose I'm allowed to
+be human.  Please don't expand on my mistakes by checking in
+your non-compiling versions into my repository.
+
+
+Configuring the 0cpm Firmerware
+-------------------------------
+
+In the root directory of the 0cpm Firmerware, type::
+
+        make menuconfig
+
+You will recognise the same build system as used by Linux
+and BusyBox, which I've shamelessly, ehm... shared.
+
+Make the following setup:
+
+* Configuration meta: Setup your toolchain prefix, and use
+  the 6bed4 address announced on http://devel.0cpm.org/6bed4/
+  and development build options shown to you.
+  or --at some point hopefully-- in the RFC.
+* Hardware manufacturer: Grandstream
+* Phone models: Budgetone 200/201
+* Hardware platform: tic55x
+* Under Firmware Functions, start with the first primary
+  function and work your way up to the SIP phone over IPv6.
+  Read the respective Help page to see what it is doing.
+
+Note that various functions claimed in the configuration
+are not implemented yet; pre-alpha, remember?
+
+
+Building the 0cpm Firmerware
+----------------------------
+
+Couldn't be simpler::
+
+        make
+
+The resulting firmware is found in ``bin/firmerware.bin``.
+
+
+Testing the 0cpm Firmerware on the phone
+----------------------------------------
+
+Assuming you've soldered the EEPROM stack that I suggested,
+you could use the ``i2cp`` utility.  You may need to build
+it first::
+
+        pushd bin/i2cp
+        make
+        popd
+
+Then you can upload it as follows, but possibly with a
+different I2C bus::
+
+        i2cp bin/firmerware.bin /dev/i2c-2
+
+Now reboot the phone with the boot key inserted.  The
+bootloader will recognise your wish to bootstrap the
+DSP from the I2C EEPROMs.  Permit a few seconds for the
+I2C download and DSP setup.  Still, it's a lot faster
+than the original firmware, mostly because it is smaller.
+
+You can now conduct the tests described for the main
+function that you selected.
+
+
+
+Observing the phone's console
+-----------------------------
+
+Go ahead and stare at the display.
+
+No, seriously, the phone can keep a log, although not in the
+simplest test programs and otherwise as a configurable option.
+
+The logs are accessed over LLC2_.  You will need the tool
+``llcio`` contained in by hexio_ package.  You may find more
+utilities in this package useful when working with hardware;
+for example, if you need a binary variation of ``minicom``.
+
+.. _LLC2 : llc.html
+
+.. _hexio : http://rick.vanrein.org/linux/hexio/
+
+
+
+Download the Flash memory to your PC
+------------------------------------
+
+When built with a bootloader main function, it is possible
+to extract the entire contents of flash from the phone.
+This is done over LLC1_, using an adapted TFTP utility
+described under that link.
+
+.. _LLC1 : llc.html
+
+
+Making changes to the 0cpm Firmerware
+=====================================
+
+You are going to accept the 0cpm Firmerware without
+a further thought, right?  No bright ideas or wish
+to innovate and extend?
+
+Oh, so you *do* have ideas... well then... read on!
+
+
+Legal hoops to jump through
+---------------------------
+
+I welcome patches with whole my heart ``;-)`` but must
+tell you right away: the TI compiler license is a bit
+silly; it can only be distributed alongside software
+that is strictly targeted for their chips.  This means
+that distributing the 0cpm Firmerware is either a breach
+of their agreement, or GPLv3.  As the code originator,
+only I am not bound by the GPLv3 and can hand out the
+code with a reference to the TI website for the tools.
+
+I am asking all submitters to agree that I continue to
+do this.  In other words, they would not be providing
+their updates under the GPL but under a more liberal
+agreement.  This is what I need to keep the code
+generally available.  I am sorry about this loophole
+and will ask TI for more freedom as soon as the firmware
+is stable, and something that TI would be proud of supporting.
+
+If TI wouldn't want to bend, we could always move over to
+opener architectures, like Blackfin.  I want to use the
+GPLv3 so there is no risk of manufacutrers legally
+splitting off a closed fork.  To be honest, at the time
+this project started I was already quite happy to have
+an initial platform to get the work going.  Already now,
+the firmware is much more solid and would probably be
+simple to port.
+
+
+Submissions of changes
+----------------------
+
+For now, email should do fine.  I'll scale up to
+automatic things when I have to.  Perhaps you could
+publish your work in GIT and tell me about it.
+
+
+Porting to other hardware
+-------------------------
+
+If you want to port to other infrastructure you should really
+read the porting guide, contained in the ``doc`` directory of the
+0cpm Firmerware.
+
+
+Manufacturing phones for the 0cpm Firmerware
+--------------------------------------------
+
+Please read the hardware design manual, contained in the ``doc``
+directory of the 0cpm Firmerware.
+
+
+Chores waiting for you to jump at them
+--------------------------------------
+
+There are a couple of chores that give me the feeling
+that this project is growing over my head.  Perhaps you
+could help out with those:
+
+* Personally, I've tried for months (on and off) to get
+  the codec chip TLV320AIC20K working.  I have not given
+  up hope, but am wondering why I cannot get it to work.
+  Your input on that may be useful.
+
+* The flash contains firmware that can be upgraded, but
+  the updates for code portions are somehow signed.  It
+  would be tremendously useful if someone sent me the
+  algorithm.  I would be happy to accept an anonymous
+  donation of such an algorithm from a determined code
+  analyst.
+
+* Various GXP models should be supported.  So, rather than
+  purchasing the GXP1200, you could consider getting another
+  model, and adapting the firmware to match it.
+
+* There are exciting extension possibilities; Grandstream
+  has a GXV series involving a camera, colour display and
+  sometimes even a touch screen.  It would be lovely if
+  someone found the time to look into those.  They use
+  a tic6x architecture AFAIK.
+
+* DECT is not as open as Ethernet, so I may need help from
+  others in developing that area.  Also, the model of DECT
+  is somewhat different -- a base station runs as a
+  multi-headed dragon, servicing multiple users who each
+  hold their own terminal.
+
+* ATAs are useful devices to those who are just getting
+  started with SIP, and also as intermediaries for textphones
+  in use by the deaf.  Supporting the chips used in those
+  should be a treat in tone recognition and sound handling.
+  I mean it, the chips used look very interesting.
+
+* In a second phase of ATA support, a very special piece of
+  hardware to support could be Rowetel's `$10 ATA`_,
+  designed as an extension to OpenWRT.  Rowetel is doing
+  great work by supporting telecommunications for development
+  countries; this is a vital piece of technology to enable
+  people to plan and arrange things, and helps to set them
+  free.  You may also find an extremely low bitrate codec
+  named Codec2 as part of the 0cpm Firmerware; it is there
+  to enable these developing countries to connect to the
+  rest of the world at the low bitrates that they are
+  dependent upon over there.
+
+* The new GXP series has graphical displays that need
+  reverse engineering; I've done some work on it but
+  am not ready.
+
+.. _`$10 ATA` : http://www.rowetel.com/blog/?p=1987
+
+
index 210b472..d85f961 100644 (file)
@@ -47,9 +47,9 @@
  * and so on instead of manipulating values with htons, ntohs and so on.
  */
 
-typedef struct { uint8_t b0             } nint8_t;
-typedef struct { uint8_t b0, b1         } nint16_t;
-typedef struct { uint8_t b0, b1, b2, b3 } nint32_t;
+typedef struct { uint8_t b0;             } nint8_t ;
+typedef struct { uint8_t b0, b1;         } nint16_t;
+typedef struct { uint8_t b0, b1, b2, b3; } nint32_t;
 
 #ifndef netget8
 #define netget8(a) ((uint8_t) (a).b0)
index 807a752..eb6faac 100644 (file)
  */
 
 
+#ifndef HEADER_BOTTOM_DEVEL
+#define HEADER_BOTTOM_DEVEL
+
 // TODO: The following nethandlers have not been implemented yet
 #include <stdlib.h>
-inline uint8_t *net_rtp (uint8_t *pkt, intptr_t *mem) { return NULL; }
-inline uint8_t *net_rtcp (uint8_t *pkt, intptr_t *mem) { return NULL; }
-inline uint8_t *net_mdns_resp_error (uint8_t *pkt, intptr_t *mem) { return NULL; }
-inline uint8_t *net_mdns_resp_dyn (uint8_t *pkt, intptr_t *mem) { return NULL; }
-inline uint8_t *net_mdns_resp_std (uint8_t *pkt, intptr_t *mem) { return NULL; }
-inline uint8_t *net_mdns_query_error (uint8_t *pkt, intptr_t *mem) { return NULL; }
-inline uint8_t *net_mdns_query_ok (uint8_t *pkt, intptr_t *mem) { return NULL; }
+static inline uint8_t *net_rtp (uint8_t *pkt, intptr_t *mem) { return NULL; }
+static inline uint8_t *net_rtcp (uint8_t *pkt, intptr_t *mem) { return NULL; }
+static inline uint8_t *net_mdns_resp_error (uint8_t *pkt, intptr_t *mem) { return NULL; }
+static inline uint8_t *net_mdns_resp_dyn (uint8_t *pkt, intptr_t *mem) { return NULL; }
+static inline uint8_t *net_mdns_resp_std (uint8_t *pkt, intptr_t *mem) { return NULL; }
+static inline uint8_t *net_mdns_query_error (uint8_t *pkt, intptr_t *mem) { return NULL; }
+static inline uint8_t *net_mdns_query_ok (uint8_t *pkt, intptr_t *mem) { return NULL; }
 
+#endif
index f77511e..5c80775 100644 (file)
@@ -22,7 +22,7 @@
 #define HEADER_GRANDSTREAM
 
 /* Settings for Budgetone devices */
-#if defined CONFIG_TARGET_GRANDSTREAM_BT20x || defined CONFIG_TARGET_GRANDSTREAM_BT10x
+#if defined (CONFIG_TARGET_GRANDSTREAM_BT20x) || defined (CONFIG_TARGET_GRANDSTREAM_BT10x)
 
 #define HAVE_LED_MESSAGE 1
 #define HAVE_LED_BACKLIGHT 1
 #define NEED_KBD_SCANNER_BETWEEN_KEYS 1
 #define NEED_KBD_SCANNER_DURING_KEYPRESS 1
 
+
+#ifdef BOTTOM
+
+
 #pragma FAR(kbdisp)
 extern volatile uint8_t kbdisp;
 asm ("_kbdisp .set 0x666CDA");
@@ -109,3 +113,4 @@ void bottom_flash_get_mac (uint8_t mac [6]);
 
 #endif
 
+#endif
index 4af10aa..695a3c7 100644 (file)
@@ -119,3 +119,4 @@ void ksz8842_setup_network (void);
  * Retrieve the ISR register and handle each interrupt reason.
  */
 void ksz8842_interrupt_handler (void);
+
index bca0f8a..4450ab2 100644 (file)
@@ -54,9 +54,40 @@ typedef uint32_t timing_t;
 #define bzero(p,n) memset((p),0,(n))
 
 
-/* Following definitions are only available if BOTTOM is defined */
+/* A number of object allocation qualifiers.  As defined
+ * in SPRU281F, these basically redirect large portions of
+ * data to their own segments.  This solves the linker
+ * message "section XYZ spans page boundary: not allowed
+ * before CPU revision 3.0" by limiting each to 64k max.
+ * The format is DATA_SECTION(_symbol, "sectionname") and
+ * a section named .sectionname must then be defined in
+ * source file src/driver/tic55x/linker.cmd
+ * Also see this webpage explaining the need for this:
+ * http://www.dsprelated.com/groups/c55x/show/2049.php
+ */
+#pragma DATA_SECTION(codes0, ".const_codebook_codec2");
+#pragma DATA_SECTION(codes1, ".const_codebook_codec2");
+#pragma DATA_SECTION(codes2, ".const_codebook_codec2");
+#pragma DATA_SECTION(codes3, ".const_codebook_codec2");
+#pragma DATA_SECTION(codes4, ".const_codebook_codec2");
+#pragma DATA_SECTION(codes5, ".const_codebook_codec2");
+#pragma DATA_SECTION(codes6, ".const_codebook_codec2");
+#pragma DATA_SECTION(codes7, ".const_codebook_codec2");
+#pragma DATA_SECTION(codes8, ".const_codebook_codec2");
+#pragma DATA_SECTION(codes9, ".const_codebook_codec2");
+
+
+/* A number of code object allocations, that aim to place
+ * high-speed code into on-board static RAM, as this is a
+ * much faster resource than all the other forms of memory.
+ * See SPRU281F and this webpage:
+ * http://www.dsprelated.com/groups/c55x/show/2049.php
+ */
+#pragma CODE_SECTION(netinput, ".text_fast");
 
 
+/* Following definitions are only available if BOTTOM is defined */
+
 #ifdef BOTTOM
 
 /* Interrupt Enable Registers (memory-mapped) */
diff --git a/include/tic55x/malloc.h b/include/tic55x/malloc.h
new file mode 100644 (file)
index 0000000..36efcba
--- /dev/null
@@ -0,0 +1,2 @@
+void *malloc(size_t);
+void free(void*);
diff --git a/include/tic55x/memory.h b/include/tic55x/memory.h
new file mode 100644 (file)
index 0000000..e91ec2c
--- /dev/null
@@ -0,0 +1,2 @@
+#include <stddef.h>
+#include <string.h>
index c7ca802..55e9030 100644 (file)
@@ -27,3 +27,6 @@ typedef long int int32_t;
 
 typedef uint32_t intptr_t;
 
+typedef  int32_t  intmax_t;
+typedef uint32_t uintmax_t;
+
index 7e4c8e2..da19558 100644 (file)
@@ -21,3 +21,4 @@
 
 typedef unsigned int size_t;
 
+#define RAND_MAX 65535
index 66a4910..72b712a 100644 (file)
@@ -17,6 +17,8 @@
  * along with 0cpm Firmerware.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <stdlib.h>
+
 int memcmp(const void *s1, const void *s2, size_t n);
 void *memcpy(void *dest, const void *src, size_t n);
 void *memset(void *s, int c, size_t n);
index 5902e1f..5ca0b6d 100644 (file)
@@ -18,9 +18,15 @@ The codecs in this tree have been defined with a number of goals in mind:
   - Ogg/RTP can play radio stations from multicast sources
   - L16 can play PCM and replace computer sound devices
 
-
-Codecs that are large are made optional:
-
-* Ogg decoding (Internet radio support) could be done by the multicasting node
-* Speex encoder/decoder which consumes about 100 kB of code size
-
+Codecs that are large or contraversial are optional:
+
+* Ogg decoding is computationally heavy, and could be done by a central node
+* Speex encoder/decoder consumes about 100 kB of code size
+* L16 as it might not be to everyone's taste to have an open sound player next to them
+
+Note that RTT is hardly contraversial -- it is about 1 kB of code, and can add great
+benefit to all users -- not just the deaf or speech impaired.  Making it available
+by default not only creates a World were handicaps cause less isolation, but it also
+sends a strong signal to PBX developers to start texting their IVR menus so we can
+get on wading through lists of options.  The only case where RTT is not to be built
+into the 0cpm Firmerware is actually when there is no display to use.
diff --git a/src/codec/codec2/AUTHORS b/src/codec/codec2/AUTHORS
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/codec/codec2/COPYING b/src/codec/codec2/COPYING
new file mode 100644 (file)
index 0000000..cc40a46
--- /dev/null
@@ -0,0 +1,502 @@
+                  GNU LESSER GENERAL PUBLIC LICENSE
+                       Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+                            Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+  When we speak of free software, we are referring to freedom of use,
+not price.  Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+  To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights.  These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+\f
+  Finally, software patents pose a constant threat to the existence of
+any free program.  We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder.  Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+  Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License.  This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License.  We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+  When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library.  The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom.  The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+  We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License.  It also provides other free software developers Less
+of an advantage over competing non-free programs.  These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries.  However, the Lesser license provides advantages in certain
+special circumstances.
+
+  For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard.  To achieve this, non-free programs must be
+allowed to use the library.  A more frequent case is that a free
+library does the same job as widely used non-free libraries.  In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+  In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software.  For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+  Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+\f
+                  GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+\f
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+\f
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+\f
+  6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    e) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+\f
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+\f
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+\f
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+                            NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+                     END OF TERMS AND CONDITIONS
+\f
+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library 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
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, see 
+    <http://www.gnu.org/licenses/>. 
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/src/codec/codec2/ChangeLog b/src/codec/codec2/ChangeLog
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/codec/codec2/INSTALL b/src/codec/codec2/INSTALL
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/codec/codec2/NEWS b/src/codec/codec2/NEWS
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/codec/codec2/README b/src/codec/codec2/README
new file mode 100644 (file)
index 0000000..4cdb409
--- /dev/null
@@ -0,0 +1,69 @@
+Codec 2 README
+--------------
+
+Codec 2 is an open source 2400 bit/s speech codec (LGPL licensed).
+For more information please see:
+
+    http://rowetel.com/codec2.html
+
+Quickstart
+----------
+
+1/ Listen to Codec 2:
+
+   $ cd codec2/src
+   $ ./configure && make
+   $ ./c2demo ../raw/hts1a.raw hts1a_c2.raw
+   $ ../script/menu.sh ../raw/hts1a.raw hts1a_c2.raw
+
+   NOTE: For playback testing, menu.sh requires either the 'play',
+   'aplay' or 'ossplay' programs to be installed (see
+   http://sox.sourceforge.net/, http://www.alsa-project.org/, or
+   http://www.opensound.com/ respectively).
+
+2/ Compress and Decompress a file:
+
+   $ ./c2enc ../raw/hts1a.raw hts1a_c2.bit
+   $ ./c2dec hts1a_c2.bit hts1a_c2.raw 
+
+Programs
+--------
+1/ c2demo encodes a file of speech samples, then decodes them and
+saves the result.
+
+2/ c2enc encodes a file of speech samples to a compressed file of
+encoded bits.
+
+3/ c2dec decodes a compressed file of bits to a file of speech
+samples.
+
+4/ c2sim is a simulation/development version of Codec 2.  It allows
+selective use of the various Codec 2 algorithms.  For example
+switching phase modelling or LSP quantisation on and off.
+
+Debugging
+---------
+
+1/ For dump file support:
+
+  $ cd codec2
+  $ CFLAGS=-DDUMP ./configure
+  $ make clean && make
+
+2/ To use gdb:
+
+  $ $ libtool --mode=execute gdb c2sim
+
+Directories
+-----------
+
+  script   - shell scripts for playing and converting raw files
+  src      - C source code
+  octave   - Octave scripts used for visualising internal signals 
+             during development
+  raw      - speech files in raw format (16 bits signed linear 8 kHz)
+  unittest - unit test source code
+  voicing  - hand-estimated voicing files, used for development
+  wav      - speech files in wave file format
+
diff --git a/src/codec/codec2/src/codec2.h b/src/codec/codec2/src/codec2.h
new file mode 100644 (file)
index 0000000..946dedc
--- /dev/null
@@ -0,0 +1,41 @@
+/*---------------------------------------------------------------------------*\
+
+  FILE........: codec2.h
+  AUTHOR......: David Rowe
+  DATE CREATED: 21/8/2010
+
+  Codec2 fully quantised encoder and decoder functions.  If you want use 
+  codec2, these are the functions you need to call.
+
+\*---------------------------------------------------------------------------*/
+
+/*
+  Copyright (C) 2010 David Rowe
+
+  All rights reserved.
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU Lesser General Public License version 2.1, 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.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with this program; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef __CODEC2__
+#define  __CODEC2__
+
+#define CODEC2_SAMPLES_PER_FRAME 160
+#define CODEC2_BITS_PER_FRAME     50
+
+void *codec2_create();
+void codec2_destroy(void *codec2_state);
+void codec2_encode(void *codec2_state, unsigned char * bits, short speech_in[]);
+void codec2_decode(void *codec2_state, short speech_out[],
+      const unsigned char * bits);
+
+#endif
diff --git a/src/codec/codec2/src/codec2_internal.h b/src/codec/codec2/src/codec2_internal.h
new file mode 100644 (file)
index 0000000..3943ac2
--- /dev/null
@@ -0,0 +1,63 @@
+/*---------------------------------------------------------------------------*\
+
+  FILE........: codec2_internal.h
+  AUTHOR......: David Rowe
+  DATE CREATED: 22 March 2011
+
+  Some internal structures and states broken out here as they are useful for
+  testing and development.
+
+\*---------------------------------------------------------------------------*/
+
+/*
+  Copyright (C) 2011 David Rowe
+
+  All rights reserved.
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU Lesser General Public License version 2.1, 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.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with this program; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef __CODEC2_INTERNAL__
+#define  __CODEC2_INTERNAL__
+
+/*---------------------------------------------------------------------------*\
+                                                       
+                             STATES
+
+\*---------------------------------------------------------------------------*/
+
+typedef struct {
+    float  w[M];              /* time domain hamming window                */
+    COMP   W[FFT_ENC];        /* DFT of w[]                                */
+    float  Pn[2*N];           /* trapezoidal synthesis window              */
+    float  Sn[M];              /* input speech                              */
+    float  hpf_states[2];      /* high pass filter states                   */
+    void  *nlp;                /* pitch predictor states                    */
+    float  Sn_[2*N];          /* synthesised output speech                 */
+    float  ex_phase;           /* excitation model phase track              */
+    float  bg_est;             /* background noise estimate for post filter */
+    float  prev_Wo;            /* previous frame's pitch estimate           */
+    MODEL  prev_model;         /* previous frame's model parameters         */
+    float  prev_lsps[LPC_ORD]; /* previous frame's LSPs                     */
+    float  prev_energy;        /* previous frame's LPC energy               */
+} CODEC2;
+
+/*---------------------------------------------------------------------------*\
+                                                       
+                             FUNCTION HEADERS
+
+\*---------------------------------------------------------------------------*/
+
+void analyse_one_frame(CODEC2 *c2, MODEL *model, short speech[]);
+void synthesise_one_frame(CODEC2 *c2, short speech[], MODEL *model,float ak[]);
+
+#endif
diff --git a/src/codec/codec2/src/comp.h b/src/codec/codec2/src/comp.h
new file mode 100644 (file)
index 0000000..cedcab3
--- /dev/null
@@ -0,0 +1,38 @@
+/*---------------------------------------------------------------------------*\
+                                                                             
+  FILE........: comp.h
+  AUTHOR......: David Rowe                                                          
+  DATE CREATED: 24/08/09
+                                                                             
+  Complex number definition.
+                                                                             
+\*---------------------------------------------------------------------------*/
+
+/*
+  Copyright (C) 2009 David Rowe
+
+  All rights reserved.
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU Lesser General Public License version 2.1, 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.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with this program; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef __COMP__
+#define __COMP__
+
+/* Complex number */
+
+typedef struct {
+  float real;
+  float imag;
+} COMP;
+
+#endif
diff --git a/src/codec/codec2/src/defines.h b/src/codec/codec2/src/defines.h
new file mode 100644 (file)
index 0000000..2dcd527
--- /dev/null
@@ -0,0 +1,88 @@
+/*---------------------------------------------------------------------------*\
+
+  FILE........: defines.h                                                     
+  AUTHOR......: David Rowe 
+  DATE CREATED: 23/4/93                                                       
+                                                                             
+  Defines and structures used throughout the codec.                         
+                                                                             
+\*---------------------------------------------------------------------------*/
+
+/*
+  Copyright (C) 2009 David Rowe
+
+  All rights reserved.
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU Lesser General Public License version 2.1, 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.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with this program; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef __DEFINES__
+#define __DEFINES__
+
+/*---------------------------------------------------------------------------*\
+                                                                             
+                               DEFINES                                       
+                                                                             
+\*---------------------------------------------------------------------------*/
+
+/* General defines */
+
+#define N          80          /* number of samples per frame          */
+#define MAX_AMP    80          /* maximum number of harmonics          */
+#define PI         3.141592654 /* mathematical constant                */
+#define TWO_PI     6.283185307 /* mathematical constant                */
+#define FS         8000                /* sample rate in Hz                    */
+#define MAX_STR    256          /* maximum string size                  */
+
+#define NW         279          /* analysis window size                 */
+#define FFT_ENC    512         /* size of FFT used for encoder         */
+#define FFT_DEC    512         /* size of FFT used in decoder          */
+#define TW         40          /* Trapezoidal synthesis window overlap */
+#define V_THRESH   6.0          /* voicing threshold in dB              */
+#define LPC_MAX    20          /* maximum LPC order                    */
+#define LPC_ORD    10          /* phase modelling LPC order            */
+
+/* Pitch estimation defines */
+
+#define M        320           /* pitch analysis frame size            */
+#define P_MIN    20            /* minimum pitch                        */
+#define P_MAX    160           /* maximum pitch                        */
+
+/*---------------------------------------------------------------------------*\
+                                                                             
+                               TYPEDEFS                                      
+                                                                             
+\*---------------------------------------------------------------------------*/
+
+/* Structure to hold model parameters for one frame */
+
+typedef struct {
+  float Wo;            /* fundamental frequency estimate in radians  */
+  int   L;             /* number of harmonics                        */
+  float A[MAX_AMP];    /* amplitiude of each harmonic                */
+  float phi[MAX_AMP];  /* phase of each harmonic                     */
+  int   voiced;                /* non-zero if this frame is voiced           */
+} MODEL;
+
+/* describes each codebook  */
+
+struct lsp_codebook {
+    int                        k;        /* dimension of vector        */
+    int                        log2m;    /* number of bits in m        */
+    int                        m;        /* elements in codebook       */
+    const float        *       cb;       /* The elements               */
+};
+extern const struct lsp_codebook lsp_cb[];
+extern const struct lsp_codebook lsp_cbd[];
+extern const struct lsp_codebook lsp_cbdvq[];
+
+#endif
index 7e0c25c..152054a 100644 (file)
@@ -1,8 +1,8 @@
 TARGET=rtt_desktop_test
 OBJS=recvkeys.o sendkeys.o desktop.o
 
-# CFLAGS=-m32
-CFLAGS=-m64
+CFLAGS=-m32 -L.
+# CFLAGS=-m64
 
 # CFLAGS+=-ggdb3
 
@@ -17,7 +17,7 @@ anew: clean all
        gcc $(CFLAGS) -I/usr/include -I../../../include -c -o $@ $<
 
 $(TARGET): $(OBJS)
-       gcc $(CFLAGS) -o $@ $(OBJS)
+       gcc $(CFLAGS) -o $@ $(OBJS) -lncurses
 
 tags:
        ctags *.c
index c38acac..57e94e5 100644 (file)
@@ -48,12 +48,15 @@ typedef uint32_t nint32_t;
 #include <fcntl.h>
 #include <termios.h>
 #include <stdio.h>
+#include <errno.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <arpa/inet.h>
 #include <netinet/in.h>
 #include <sys/timeb.h>
 
+#include <ncurses.h>
+
 
 extern uint8_t rtt_paytp_red;
 extern uint8_t rtt_paytp_t140;
@@ -70,6 +73,9 @@ irq_handler_t timer_hdl;
 int sox;
 
 
+WINDOW *top, *bot;
+
+
 struct termios stdin_oldstate;
 
 
@@ -98,10 +104,24 @@ void netcore_send_buffer (intptr_t *mem, uint8_t *wbuf) {
 
 /* RTT received key presses -- process them by printing on the output tty */
 void rtt_recv_keys (uint8_t *text, uint16_t len) {
-       ssize_t shown = write (1, text, len);
+       // ssize_t shown = write (1, text, len);
+       ssize_t shown = len;
+       while (len-- > 0) {
+               if (*text == 127) {
+                       *text = 0x08;
+               } else if (*text == '\r') {
+                       *text = '\n';
+               }
+               if (wprintw (top, "%c", *text++) != ERR) {
+                       shown--;
+               }
+       }
+#if 0
        if (shown != (ssize_t) len) {
-               fprintf (stderr, "\nWarning: Only %d out of %d characters shown\n", (int) shown, (int) len);
+               wprintw (top, "\nWarning: Only %d out of %d characters shown\n", (int) shown, (int) len);
        }
+#endif
+       wrefresh (top);
 }
 
 
@@ -162,6 +182,13 @@ void stdin_reset(void) { /* set it to normal! */
        tcsetattr(0, TCSAFLUSH, &stdin_oldstate);
 }
 
+/* Return the screen to normal mode */
+void screen_reset (void) {
+       if (bot) delwin (bot);
+       if (top) delwin (top);
+       endwin ();
+}
+
 /* Code based on online demonstration code */
 void stdin_raw(void) {       /* RAW! mode */
        struct termios  stdin_newstate;
@@ -185,6 +212,9 @@ void stdin_raw(void) {       /* RAW! mode */
                        ouput flow control off;
                       retain CR-toNL off */
 
+       stdin_newstate.c_iflag |= ICRNL;
+                   /* Translate CR to newline on input */
+
        stdin_newstate.c_lflag |= ISIG;
                    /* recognise and process specials like ^C */
 
@@ -197,7 +227,7 @@ void stdin_raw(void) {       /* RAW! mode */
        // stdin_newstate.c_oflag &= ~(OPOST);
                     /* output processing off */
 
-       // stdin_newstate.c_oflag |= ONLCR;
+       stdin_newstate.c_oflag |= ONLCR;
                    /* map newline to CR-LF on output  */
 
        stdin_newstate.c_cc[VMIN] = 1;  /* 1 byte at a time */
@@ -220,9 +250,9 @@ int main (int argc, char *argv []) {
        struct sockaddr_in6 local, remot;
        //
        // Test arguments
-       if (argc != 6) {
-               fprintf (stderr, "Usage: %s /dev/ttyN myAddr myPort remoteAddr remotePort\n"
-                               "   Where /dev/ttyN is an output terminal, and addresses are IPv6.\n"
+       if (argc != 5) {
+               fprintf (stderr, "Usage: %s myAddr myPort remoteAddr remotePort\n"
+                               "   Where is an output terminal, and addresses are IPv6 (as RTP would deliver).\n"
                                "   This is not a fancy interface, but rather demonstrates the protocol.\n",
                        argv [0]);
                exit (1);
@@ -239,21 +269,21 @@ int main (int argc, char *argv []) {
        bzero (&remot, sizeof (remot));
        local.sin6_family = AF_INET6;
        remot.sin6_family = AF_INET6;
-       if (inet_pton (AF_INET6, argv [2], &local.sin6_addr) != 1) {
+       if (inet_pton (AF_INET6, argv [1], &local.sin6_addr) != 1) {
                fprintf (stderr, "Failed to parse local IPv6 address\n");
                exit (1);
        }
-       if (inet_pton (AF_INET6, argv [4], &remot.sin6_addr) != 1) {
+       if (inet_pton (AF_INET6, argv [3], &remot.sin6_addr) != 1) {
                fprintf (stderr, "Failed to parse remote IPv6 address\n");
                exit (1);
        }
-       port = atoi (argv [3]);
+       port = atoi (argv [2]);
        if ((port <= 0) || (port > 65535)) {
                fprintf (stderr, "Invalid local port\n");
                exit (1);
        }
        local.sin6_port = htons (port);
-       port = atoi (argv [5]);
+       port = atoi (argv [4]);
        if ((port <= 0) || (port > 65535)) {
                fprintf (stderr, "Invalid remote port\n");
                exit (1);
@@ -278,22 +308,25 @@ int main (int argc, char *argv []) {
        // An empty UDP message will open any local firewalls for return traffic
        open_local_firewalls ();
        //
-       // Replace stdout with provided terminal handle
-       fdo = open (argv [1], O_RDWR);
-       if (fdo == -1) {
-               fprintf (stderr, "Failed to write output to %s\n", argv [1]);
-               exit (1);
-       }
-       close (1);
-       if (dup2 (fdo, 1) == -1) {
-               perror ("Failed to redirect output");
-               exit (1);
-       }
-       close (fdo);
-       //
        // Change input to raw mode (and have it returned to normal upon exit)
        stdin_raw ();
        //
+       // Split the screen, using ncurses
+       top = NULL;
+       bot = NULL;
+       initscr ();
+       atexit (screen_reset);
+       mvhline (LINES/2, 0, ACS_HLINE, COLS);
+       refresh ();
+       top = newwin (LINES/2, COLS, 0, 0);
+       bot = newwin (LINES - LINES/2 - 1, COLS, LINES/2 + 1, 0);
+       wprintw (top, "Remote:\n");
+       wprintw (bot, "Your input:\n");
+       wrefresh (top);
+       wrefresh (bot);
+       scrollok (bot, true);
+       scrollok (top, true);
+       //
        // Main loop -- wait for input from stdin or the UDP port, and relay it
        while (true) {
                fd_set ears;
@@ -322,7 +355,17 @@ int main (int argc, char *argv []) {
                if (FD_ISSET (0, &ears)) {
                        /* If no input awaits sending, pickup new data */
                        if (inlen == 0) {
+                               uint16_t inecho = 0;
                                inlen = read (0, input, sizeof (input));
+                               while (inecho < inlen) {
+                                       if (input [inecho] == 127) {
+                                               input [inecho] = 0x08;
+                                       } else if (input [inecho] == '\r') {
+                                               input [inecho] = '\n';
+                                       }
+                                       wprintw (bot, "%c", input [inecho++]);
+                               }
+                               wrefresh (bot);
                                inofs = 0;
                                if (inlen == -1) {
                                        perror ("Error reading from stdin");
@@ -340,8 +383,13 @@ int main (int argc, char *argv []) {
                        uint8_t rtpbuf [2048];
                        size_t rtplen = recv (sox, rtpbuf, sizeof (rtpbuf), 0);
                        if (rtplen == -1) {
-                               perror ("Failed to receive realtime text");
-                               //TODO:WAIT4PEER// exit (1);
+                               if (errno != ECONNREFUSED) {
+                                       perror ("Failed to receive realtime text");
+                                       exit (1);
+                               } else {
+                                       wprintw (top, "** NOT CONNECTED TO REMOTE PARTY **\n");
+                                       wrefresh (top);
+                               }
                        }
                        if (rtplen < 12) {
                                continue;
index 2de2ce4..8a01242 100644 (file)
@@ -55,6 +55,11 @@ typedef unsigned char uint8_t;
 #include <0cpm/netfun.h>
 
 
+#ifndef CONFIG_CODEC_RTT
+#warning "Overriding deselection of Realtime Text codec -- see help in configuration menus"
+#endif
+
+
 /* The missing character code 0xfffd, encoded in UTF-8 */
 uint8_t rtt_missing_text [] = { 0xef, 0xbf, 0xbd };
 
@@ -96,7 +101,7 @@ static void rtt_skipheader (uint8_t **msg, uint16_t *len, uint16_t *newseqptr, u
 
 void rtp_paytype_text_t140 (uint8_t *msg, uint16_t len) {
        uint16_t newseq;
-       void rtt_recv_keys (uint8_t *text, uint16_t len);
+       //TODO:WAKEUP-TEXTSHOW-PROCESS// void rtt_recv_keys (uint8_t *text, uint16_t len);
        rtt_skipheader (&msg, &len, &newseq, NULL);
        switch ((int16_t) (newseq - rtt_seqnr)) {
        case -2:
@@ -106,11 +111,11 @@ void rtp_paytype_text_t140 (uint8_t *msg, uint16_t len) {
                return;
        default:
                /* Packets out of sync, report missing text */
-               rtt_recv_keys (rtt_missing_text, sizeof (rtt_missing_text));
+               //TODO:WAKEUP-TEXTSHOW-PROCESS// rtt_recv_keys (rtt_missing_text, sizeof (rtt_missing_text));
                // ...continue into handling the one extension...
        case 1:
                /* Packets properly ordered */
-               rtt_recv_keys (msg, len);
+               //TODO:WAKEUP-TEXTSHOW-PROCESS// rtt_recv_keys (msg, len);
                rtt_seqnr = newseq;
        }
 }
@@ -119,13 +124,13 @@ void rtp_paytype_text_t140 (uint8_t *msg, uint16_t len) {
 void rtp_paytype_text_red (uint8_t *msg, uint16_t len) {
        uint16_t newseq;
        uint16_t gencount, skipcount, skipbytes;
-       void rtt_recv_keys (uint8_t *text, uint16_t len);
+       //TODO:WAKEUP-TEXTSHOW-PROCESS// void rtt_recv_keys (uint8_t *text, uint16_t len);
        rtt_skipheader (&msg, &len, &newseq, &gencount);
        //
        // Skip the redundant parts that were processed before
        if (gencount < (newseq - rtt_seqnr)) {
                /* Packets are missing -- report and use what is supplied */
-               rtt_recv_keys (rtt_missing_text, sizeof (rtt_missing_text));
+               //TODO:WAKEUP-TEXTSHOW-PROCESS// rtt_recv_keys (rtt_missing_text, sizeof (rtt_missing_text));
                skipcount = 0;
        } else {
                /* No missing packets -- skip 0 or more redundant generations */
@@ -154,7 +159,7 @@ void rtp_paytype_text_red (uint8_t *msg, uint16_t len) {
        //
        // Copy the redundant parts that are new
        if (((int16_t) len) > 0) {
-               rtt_recv_keys (msg, len);
+               //TODO:WAKEUP-TEXTSHOW-PROCESS// rtt_recv_keys (msg, len);
        }
 }
 
index 86b7a94..48ab096 100644 (file)
 #include <0cpm/netfun.h>
 
 
+#ifndef CONFIG_CODEC_RTT
+#warning "Overriding deselection of Realtime Text codec -- see help in configuration menus"
+#endif
+
+
 
 /* The number of historic versions kept for resending */
 #ifndef RTT_GENERATIONS
index f124a29..ea09531 100644 (file)
@@ -7,7 +7,7 @@ that works about these codecs is undoubtly their work and all that fails is prob
 integrated into the 0cpm Firmerware.
 
 Specifically worth mentioning is the team's effort to collect a useful set of protocols that
-are unencumbered by patents or other methods to constipate progress.  This is exactly the
+are unencumbered by patents or other tricks that constipate progress.  This is exactly the
 sort of thing needed in the 0cpm Firmerware, if not for the fact that the firmware must
 remain open, then at least for the reason that most phone manufacturers seem to make the
 same choice.  If you want to retract your software from daily use, be sure to patent it!
@@ -21,7 +21,12 @@ for the 0cpm Firmerware, according to this table:
 
 http://www.gnu.org/licenses/gpl-faq.html#AllCompatibility
 
-In line with this table, the complete 0cpm Firmerware is shipped under GPL v3.
+In line with this table, the complete 0cpm Firmerware, including parts taken from
+spandsp, is shipped under GPL v3.
+
+Aside from this legal verification, we've also read up on the intentions of Steve and his
+team; they seem to approve of applications like the 0cpm Firmerware because it evolves
+the use of open software in the World.
 
 
 Changes to files
@@ -32,6 +37,23 @@ We've edited several files to make them fit better with the embedded architectur
 and, where possible, target-specific implementations of heavy-duty mathematics.
 
 
+Parts selected
+--------------
+
+The spandsp code implements a lot of codecs, not just the ones we need for telephony.
+So we've made a selection of those codecs that we could use in the 0cpm Firmerware:
+
+* G.711 for direct exchanges with ISDN
+* G.726 for direct exchanges with DECT
+* G.722 for direct exchanges with CAT-iq and wideband VoIP
+
+We have not included GSM-FR, for a number of reasons:
+
+* It's patent-free status is not completely clear
+* The quality of this early GSM standard is not very good
+* Newer GSM standards are incompatible, it'd become a confusing mess
+
+
 Original file versions
 ----------------------
 
diff --git a/src/codec/spandsp/src/bitstream.c b/src/codec/spandsp/src/bitstream.c
new file mode 100644 (file)
index 0000000..9a8c0bc
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * SpanDSP - a series of DSP components for telephony
+ *
+ * bitstream.c - Bitstream composition and decomposition routines.
+ *
+ * Written by Steve Underwood <steveu@coppice.org>
+ *
+ * Copyright (C) 2006 Steve Underwood
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1,
+ * 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*! \file */
+
+#if defined(HAVE_CONFIG_H)
+#include "config.h"
+#endif
+
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "spandsp/telephony.h"
+#include "spandsp/bitstream.h"
+
+#include "spandsp/private/bitstream.h"
+
+SPAN_DECLARE(void) bitstream_put(bitstream_state_t *s, uint8_t **c, uint32_t value, int bits)
+{
+    value &= ((1 << bits) - 1);
+    if (s->lsb_first)
+    {
+        if (s->residue + bits <= 32)
+        {
+            s->bitstream |= (value << s->residue);
+            s->residue += bits;
+        }
+        while (s->residue >= 8)
+        {
+            s->residue -= 8;
+            *(*c)++ = (uint8_t) (s->bitstream & 0xFF);
+            s->bitstream >>= 8;
+        }
+    }
+    else
+    {
+        if (s->residue + bits <= 32)
+        {
+            s->bitstream = (s->bitstream << bits) | value;
+            s->residue += bits;
+        }
+        while (s->residue >= 8)
+        {
+            s->residue -= 8;
+            *(*c)++ = (uint8_t) ((s->bitstream >> s->residue) & 0xFF);
+        }
+    }
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(void) bitstream_emit(bitstream_state_t *s, uint8_t **c)
+{
+    uint32_t bitstream;
+
+    if (s->residue > 0)
+    {
+        bitstream = s->bitstream & ((1 << s->residue) - 1);
+        if (s->lsb_first)
+            *(*c) = (uint8_t) bitstream;
+        else
+            *(*c) = (uint8_t) (bitstream << (8 - s->residue));
+    }
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(void) bitstream_flush(bitstream_state_t *s, uint8_t **c)
+{
+    if (s->residue > 0)
+    {
+        bitstream_emit(s, c);
+        (*c)++;
+        s->residue = 0;
+    }
+    s->bitstream = 0;
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(uint32_t) bitstream_get(bitstream_state_t *s, const uint8_t **c, int bits)
+{
+    uint32_t x;
+
+    if (s->lsb_first)
+    {
+        while (s->residue < bits)
+        {
+            s->bitstream |= (((uint32_t) *(*c)++) << s->residue);
+            s->residue += 8;
+        }
+        s->residue -= bits;
+        x = s->bitstream & ((1 << bits) - 1);
+        s->bitstream >>= bits;
+    }
+    else
+    {
+        while (s->residue < bits)
+        {
+            s->bitstream = (s->bitstream << 8) | ((uint32_t) *(*c)++);
+            s->residue += 8;
+        }
+        s->residue -= bits;
+        x = (s->bitstream >> s->residue) & ((1 << bits) - 1);
+    }
+    return x;
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(bitstream_state_t *) bitstream_init(bitstream_state_t *s, int lsb_first)
+{
+    if (s == NULL)
+    {
+        if ((s = (bitstream_state_t *) malloc(sizeof(*s))) == NULL)
+            return NULL;
+    }
+    s->bitstream = 0;
+    s->residue = 0;
+    s->lsb_first = lsb_first;
+    return s;
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(int) bitstream_release(bitstream_state_t *s)
+{
+    return 0;
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(int) bitstream_free(bitstream_state_t *s)
+{
+    if (s)
+        free(s);
+    return 0;
+}
+/*- End of function --------------------------------------------------------*/
+/*- End of file ------------------------------------------------------------*/
index 2ef0423..df95e42 100644 (file)
@@ -1,137 +1 @@
-/*
- * SpanDSP - a series of DSP components for telephony
- *
- * floating_fudge.h - A bunch of shims, to use double maths
- *                    functions on platforms which lack the
- *                    float versions with an 'f' at the end,
- *                    and to deal with the vaguaries of lrint().
- *
- * Written by Steve Underwood <steveu@coppice.org>
- *
- * Copyright (C) 2008 Steve Underwood
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License version 2.1,
- * 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#if !defined(_FLOATING_FUDGE_H_)
-#define _FLOATING_FUDGE_H_
-
-#if defined(__cplusplus)
-extern "C"
-{
-#endif
-
-#if !defined(HAVE_SINF)
-static __inline__ float sinf(float x)
-{
-       return (float) sin((double) x);
-}
-#endif
-
-#if !defined(HAVE_COSF)
-static __inline__ float cosf(float x)
-{
-       return (float) cos((double) x);
-}
-#endif
-
-#if !defined(HAVE_TANF)
-static __inline__ float tanf(float x)
-{
-       return (float) tan((double) x);
-}
-#endif
-
-#if !defined(HAVE_ASINF)
-static __inline__ float asinf(float x)
-{
-       return (float) asin((double) x);
-}
-#endif
-
-#if !defined(HAVE_ACOSF)
-static __inline__ float acosf(float x)
-{
-       return (float) acos((double) x);
-}
-#endif
-
-#if !defined(HAVE_ATANF)
-static __inline__ float atanf(float x)
-{
-       return (float) atan((double) x);
-}
-
-#endif
-
-#if !defined(HAVE_ATAN2F)
-static __inline__ float atan2f(float y, float x)
-{
-       return (float) atan2((double) y, (double) x);
-}
-
-#endif
-
-#if !defined(HAVE_CEILF)
-static __inline__ float ceilf(float x)
-{
-       return (float) ceil((double) x);
-}
-#endif
-
-#if !defined(HAVE_FLOORF)
-static __inline__ float floorf(float x)
-{
-       return (float) floor((double) x);
-}
-
-#endif
-
-#if !defined(HAVE_POWF)
-static __inline__ float powf(float x, float y)
-{
-    return (float) pow((double) x, (double) y);
-}
-#endif
-
-#if !defined(HAVE_EXPF)
-static __inline__ float expf(float x)
-{
-    return (float) expf((double) x);
-}
-#endif
-
-#if !defined(HAVE_LOGF)
-static __inline__ float logf(float x)
-{
-       return (float) logf((double) x);
-}
-#endif
-
-#if !defined(HAVE_LOG10F)
-static __inline__ float log10f(float x)
-{
-    return (float) log10((double) x);
-}
-#endif
-
-#if defined(__cplusplus)
-}
-#endif
-
-#endif
-
-/*- End of file ------------------------------------------------------------*/
+/* This file is empty for 0cpm Firmerware -- in lieu of any floating point facilities. */
index 8077334..d967ee7 100644 (file)
@@ -34,6 +34,8 @@
 #include <string.h>
 #include <assert.h>
 
+#include <spandsp/0cpm.h>
+
 #include "spandsp/telephony.h"
 #include "spandsp/bit_operations.h"
 #include "spandsp/g711.h"
index 796895b..e872906 100644 (file)
@@ -46,6 +46,8 @@
 #endif
 #include "floating_fudge.h"
 
+#include <spandsp/0cpm.h>
+
 #include "spandsp/telephony.h"
 #include "spandsp/fast_convert.h"
 #include "spandsp/saturated.h"
index 166a529..e57667c 100644 (file)
@@ -66,6 +66,8 @@
 #endif
 #include "floating_fudge.h"
 
+#include <spandsp/0cpm.h>
+
 #include "spandsp/telephony.h"
 #include "spandsp/dc_restore.h"
 #include "spandsp/bitstream.h"
diff --git a/src/codec/spandsp/src/mmx_sse_decs.h b/src/codec/spandsp/src/mmx_sse_decs.h
new file mode 100644 (file)
index 0000000..4dff6fe
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * SpanDSP - a series of DSP components for telephony
+ *
+ * mmx_sse_decs.h - Pull in the appropriate systems headers for the MMX/SSE settings.
+ *
+ * Written by Steve Underwood <steveu@coppice.org>
+ *
+ * Copyright (C) 2009 Steve Underwood
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1,
+ * 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#if !defined(_MMX_SSE_DECS_H_)
+#define _MMX_SSE_DECS_H_
+
+#if defined(SPANDSP_USE_MMX)
+#include <mmintrin.h>
+#endif
+#if defined(SPANDSP_USE_SSE)
+#include <xmmintrin.h>
+#endif
+#if defined(SPANDSP_USE_SSE2)
+#include <emmintrin.h>
+#endif
+#if defined(SPANDSP_USE_SSE3)
+#include <pmmintrin.h>
+#endif
+#if defined(SPANDSP_USE_SSSE3)
+#include <tmmintrin.h>
+#endif
+#if defined(SPANDSP_USE_SSE4_1)
+#include <smmintrin.h>
+#endif
+#if defined(SPANDSP_USE_SSE4_2)
+#include <nmmintrin.h>
+#endif
+#if defined(SPANDSP_USE_SSE4A)
+#include <ammintrin.h>
+#endif
+#if defined(SPANDSP_USE_SSE5)
+#include <bmmintrin.h>
+#endif
+
+#endif
+
+/*- End of include ---------------------------------------------------------*/
index 10679ea..f00c5b9 100644 (file)
@@ -401,9 +401,9 @@ extern "C"
        the accuracy issues related to changing the rounding scheme are of little concern
        to us. */
 
-    #if !defined(__sgi)  &&  !defined(__sunos)  &&  !defined(__solaris)  &&  !defined(__sun)
-        #warning "No usable lrint() and lrintf() functions available."
-        #warning "Replacing these functions with a simple C cast."
+    #if !defined(__sgi)  &&  !defined(__sunos)  &&  !defined(__solaris)  &&  !defined(__sun)  &&  !defined(CONFIG_PLATFORM_TIC55x)
+       #warning "No usable lrint() and lrintf() functions available."
+       #warning "Replacing these functions with a simple C cast."
     #endif
 
     static __inline__ long int lrint(double x)
diff --git a/src/codec/spandsp/src/spandsp/logging.h b/src/codec/spandsp/src/spandsp/logging.h
new file mode 100644 (file)
index 0000000..0133b80
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * SpanDSP - a series of DSP components for telephony
+ *
+ * logging.h - definitions for error and debug logging.
+ *
+ * Written by Steve Underwood <steveu@coppice.org>
+ *
+ * Copyright (C) 2005 Steve Underwood
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1,
+ * 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*! \file */
+
+/*! \page logging_page Logging
+\section logging_page_sec_1 What does it do?
+???.
+*/
+
+#if !defined(_SPANDSP_LOGGING_H_)
+#define _SPANDSP_LOGGING_H_
+
+/*! General logging function for spandsp logging. */
+typedef void (*message_handler_func_t)(int level, const char *text);
+
+/*! Error logging function for spandsp logging. */
+typedef void (*error_handler_func_t)(const char *text);
+
+/* Logging elements */
+enum
+{
+    SPAN_LOG_SEVERITY_MASK              = 0x00FF,
+    SPAN_LOG_SHOW_DATE                  = 0x0100,
+    SPAN_LOG_SHOW_SAMPLE_TIME           = 0x0200,
+    SPAN_LOG_SHOW_SEVERITY              = 0x0400,
+    SPAN_LOG_SHOW_PROTOCOL              = 0x0800,
+    SPAN_LOG_SHOW_VARIANT               = 0x1000,
+    SPAN_LOG_SHOW_TAG                   = 0x2000,
+    SPAN_LOG_SUPPRESS_LABELLING         = 0x8000
+};
+
+/* Logging severity levels */
+enum
+{
+    SPAN_LOG_NONE                       = 0,
+    SPAN_LOG_ERROR                      = 1,
+    SPAN_LOG_WARNING                    = 2,
+    SPAN_LOG_PROTOCOL_ERROR             = 3,
+    SPAN_LOG_PROTOCOL_WARNING           = 4,
+    SPAN_LOG_FLOW                       = 5,
+    SPAN_LOG_FLOW_2                     = 6,
+    SPAN_LOG_FLOW_3                     = 7,
+    SPAN_LOG_DEBUG                      = 8,
+    SPAN_LOG_DEBUG_2                    = 9,
+    SPAN_LOG_DEBUG_3                    = 10
+};
+
+/*!
+    Logging descriptor. This defines the working state for a single instance of
+    the logging facility for spandsp.
+*/
+typedef struct logging_state_s logging_state_t;
+
+#if defined(__cplusplus)
+extern "C"
+{
+#endif
+
+/*! Test if logging of a specified severity level is enabled.
+    \brief Test if logging of a specified severity level is enabled.
+    \param s The logging context.
+    \param level The severity level to be tested.
+    \return TRUE if logging is enable, else FALSE.
+*/
+SPAN_DECLARE(int) span_log_test(logging_state_t *s, int level);
+
+/*! Generate a log entry.
+    \brief Generate a log entry.
+    \param s The logging context.
+    \param level The severity level of the entry.
+    \param format ???
+    \return 0 if no output generated, else 1.
+*/
+SPAN_DECLARE(int) span_log(logging_state_t *s, int level, const char *format, ...);
+
+/*! Generate a log entry displaying the contents of a buffer.
+    \brief Generate a log entry displaying the contents of a buffer
+    \param s The logging context.
+    \param level The severity level of the entry.
+    \param tag A label for the log entry.
+    \param buf The buffer to be dumped to the log.
+    \param len The length of buf.
+    \return 0 if no output generated, else 1.
+*/
+SPAN_DECLARE(int) span_log_buf(logging_state_t *s, int level, const char *tag, const uint8_t *buf, int len);
+
+SPAN_DECLARE(int) span_log_set_level(logging_state_t *s, int level);
+
+SPAN_DECLARE(int) span_log_set_tag(logging_state_t *s, const char *tag);
+
+SPAN_DECLARE(int) span_log_set_protocol(logging_state_t *s, const char *protocol);
+
+SPAN_DECLARE(int) span_log_set_sample_rate(logging_state_t *s, int samples_per_second);
+
+SPAN_DECLARE(int) span_log_bump_samples(logging_state_t *s, int samples);
+
+SPAN_DECLARE(void) span_log_set_message_handler(logging_state_t *s, message_handler_func_t func);
+
+SPAN_DECLARE(void) span_log_set_error_handler(logging_state_t *s, error_handler_func_t func);
+
+SPAN_DECLARE(void) span_set_message_handler(message_handler_func_t func);
+
+SPAN_DECLARE(void) span_set_error_handler(error_handler_func_t func);
+
+SPAN_DECLARE(logging_state_t *) span_log_init(logging_state_t *s, int level, const char *tag);
+
+SPAN_DECLARE(int) span_log_release(logging_state_t *s);
+
+SPAN_DECLARE(int) span_log_free(logging_state_t *s);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
+/*- End of file ------------------------------------------------------------*/
diff --git a/src/codec/spandsp/src/vector_int.c b/src/codec/spandsp/src/vector_int.c
new file mode 100644 (file)
index 0000000..9eff8e8
--- /dev/null
@@ -0,0 +1,628 @@
+/*
+ * SpanDSP - a series of DSP components for telephony
+ *
+ * vector_int.c - Integer vector arithmetic
+ *
+ * Written by Steve Underwood <steveu@coppice.org>
+ *
+ * Copyright (C) 2006 Steve Underwood
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1,
+ * 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*! \file */
+
+#if defined(HAVE_CONFIG_H)
+#include "config.h"
+#endif
+
+#include <inttypes.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#if defined(HAVE_TGMATH_H)
+#include <tgmath.h>
+#endif
+#if defined(HAVE_MATH_H)
+#include <math.h>
+#endif
+#include <assert.h>
+
+#include "floating_fudge.h"
+#include "mmx_sse_decs.h"
+
+#include <spandsp/0cpm.h>
+
+#include "spandsp/telephony.h"
+#include "spandsp/vector_int.h"
+
+SPAN_DECLARE(int32_t) vec_dot_prodi16(const int16_t x[], const int16_t y[], int n)
+{
+    int32_t z;
+
+#if defined(__GNUC__)  &&  defined(SPANDSP_USE_MMX)  &&  defined(__x86_64__)
+    __asm__ __volatile__(
+        " emms;\n"
+        " pxor %%mm0,%%mm0;\n"
+        " leaq -32(%%rsi,%%rax,2),%%rdx;\n"     /* rdx = top - 32 */
+
+        " cmpq %%rdx,%%rsi;\n"
+        " ja 1f;\n"
+
+        /* Work in blocks of 16 int16_t's until we are near the end */
+        " .p2align 2;\n"
+        "2:\n"
+        " movq (%%rdi),%%mm1;\n"
+        " movq (%%rsi),%%mm2;\n"
+        " pmaddwd %%mm2,%%mm1;\n"
+        " paddd %%mm1,%%mm0;\n"
+        " movq 8(%%rdi),%%mm1;\n"
+        " movq 8(%%rsi),%%mm2;\n"
+        " pmaddwd %%mm2,%%mm1;\n"
+        " paddd %%mm1,%%mm0;\n"
+        " movq 16(%%rdi),%%mm1;\n"
+        " movq 16(%%rsi),%%mm2;\n"
+        " pmaddwd %%mm2,%%mm1;\n"
+        " paddd %%mm1,%%mm0;\n"
+        " movq 24(%%rdi),%%mm1;\n"
+        " movq 24(%%rsi),%%mm2;\n"
+        " pmaddwd %%mm2,%%mm1;\n"
+        " paddd %%mm1,%%mm0;\n"
+
+        " addq $32,%%rsi;\n"
+        " addq $32,%%rdi;\n"
+        " cmpq %%rdx,%%rsi;\n"
+        " jbe 2b;\n"
+
+        " .p2align 2;\n"
+        "1:\n"
+        " addq $24,%%rdx;\n"                  /* Now edx = top - 8 */
+        " cmpq %%rdx,%%rsi;\n"
+        " ja 3f;\n"
+
+        /* Work in blocks of 4 int16_t's until we are near the end */
+        " .p2align 2;\n"
+        "4:\n"
+        " movq (%%rdi),%%mm1;\n"
+        " movq (%%rsi),%%mm2;\n"
+        " pmaddwd %%mm2,%%mm1;\n"
+        " paddd %%mm1,%%mm0;\n"
+
+        " addq $8,%%rsi;\n"
+        " addq $8,%%rdi;\n"
+        " cmpq %%rdx,%%rsi;"
+        " jbe 4b;\n"
+
+        " .p2align 2;\n"
+        "3:\n"
+        " addq $4,%%rdx;\n"                  /* Now edx = top - 4 */
+        " cmpq %%rdx,%%rsi;\n"
+        " ja 5f;\n"
+
+        /* Work in a block of 2 int16_t's */
+        " movd (%%rdi),%%mm1;\n"
+        " movd (%%rsi),%%mm2;\n"
+        " pmaddwd %%mm2,%%mm1;\n"
+        " paddd %%mm1,%%mm0;\n"
+
+        " addq $4,%%rsi;\n"
+        " addq $4,%%rdi;\n"
+
+        " .p2align 2;\n"
+        "5:\n"
+        " addq $2,%%rdx;\n"                  /* Now edx = top - 2 */
+        " cmpq %%rdx,%%rsi;\n"
+        " ja 6f;\n"
+
+        /* Deal with the very last int16_t, when n is odd */
+        " movswl (%%rdi),%%eax;\n"
+        " andl $65535,%%eax;\n"
+        " movd %%eax,%%mm1;\n"
+        " movswl (%%rsi),%%eax;\n"
+        " andl $65535,%%eax;\n"
+        " movd %%eax,%%mm2;\n"
+        " pmaddwd %%mm2,%%mm1;\n"
+        " paddd %%mm1,%%mm0;\n"
+
+        " .p2align 2;\n"
+        "6:\n"
+        /* Merge the pieces of the answer */
+        " movq %%mm0,%%mm1;\n"
+        " punpckhdq %%mm0,%%mm1;\n"
+        " paddd %%mm1,%%mm0;\n"
+        /* Et voila, eax has the final result */
+        " movd %%mm0,%%eax;\n"
+
+        " emms;\n"
+        : "=a" (z)
+        : "S" (x), "D" (y), "a" (n)
+        : "cc"
+    );
+#elif defined(__GNUC__)  &&  defined(SPANDSP_USE_MMX)  &&  defined(__i386__)
+    __asm__ __volatile__(
+        " emms;\n"
+        " pxor %%mm0,%%mm0;\n"
+        " leal -32(%%esi,%%eax,2),%%edx;\n"     /* edx = top - 32 */
+
+        " cmpl %%edx,%%esi;\n"
+        " ja 1f;\n"
+
+        /* Work in blocks of 16 int16_t's until we are near the end */
+        " .p2align 2;\n"
+        "2:\n"
+        " movq (%%edi),%%mm1;\n"
+        " movq (%%esi),%%mm2;\n"
+        " pmaddwd %%mm2,%%mm1;\n"
+        " paddd %%mm1,%%mm0;\n"
+        " movq 8(%%edi),%%mm1;\n"
+        " movq 8(%%esi),%%mm2;\n"
+        " pmaddwd %%mm2,%%mm1;\n"
+        " paddd %%mm1,%%mm0;\n"
+        " movq 16(%%edi),%%mm1;\n"
+        " movq 16(%%esi),%%mm2;\n"
+        " pmaddwd %%mm2,%%mm1;\n"
+        " paddd %%mm1,%%mm0;\n"
+        " movq 24(%%edi),%%mm1;\n"
+        " movq 24(%%esi),%%mm2;\n"
+        " pmaddwd %%mm2,%%mm1;\n"
+        " paddd %%mm1,%%mm0;\n"
+
+        " addl $32,%%esi;\n"
+        " addl $32,%%edi;\n"
+        " cmpl %%edx,%%esi;\n"
+        " jbe 2b;\n"
+
+        " .p2align 2;\n"
+        "1:\n"
+        " addl $24,%%edx;\n"                  /* Now edx = top - 8 */
+        " cmpl %%edx,%%esi;\n"
+        " ja 3f;\n"
+
+        /* Work in blocks of 4 int16_t's until we are near the end */
+        " .p2align 2;\n"
+        "4:\n"
+        " movq (%%edi),%%mm1;\n"
+        " movq (%%esi),%%mm2;\n"
+        " pmaddwd %%mm2,%%mm1;\n"
+        " paddd %%mm1,%%mm0;\n"
+
+        " addl $8,%%esi;\n"
+        " addl $8,%%edi;\n"
+        " cmpl %%edx,%%esi;"
+        " jbe 4b;\n"
+
+        " .p2align 2;\n"
+        "3:\n"
+        " addl $4,%%edx;\n"                  /* Now edx = top - 4 */
+        " cmpl %%edx,%%esi;\n"
+        " ja 5f;\n"
+
+        /* Work in a block of 2 int16_t's */
+        " movd (%%edi),%%mm1;\n"
+        " movd (%%esi),%%mm2;\n"
+        " pmaddwd %%mm2,%%mm1;\n"
+        " paddd %%mm1,%%mm0;\n"
+
+        " addl $4,%%esi;\n"
+        " addl $4,%%edi;\n"
+
+        " .p2align 2;\n"
+        "5:\n"
+        " addl $2,%%edx;\n"                  /* Now edx = top - 2 */
+        " cmpl %%edx,%%esi;\n"
+        " ja 6f;\n"
+
+        /* Deal with the very last int16_t, when n is odd */
+        " movswl (%%edi),%%eax;\n"
+        " andl $65535,%%eax;\n"
+        " movd %%eax,%%mm1;\n"
+        " movswl (%%esi),%%eax;\n"
+        " andl $65535,%%eax;\n"
+        " movd %%eax,%%mm2;\n"
+        " pmaddwd %%mm2,%%mm1;\n"
+        " paddd %%mm1,%%mm0;\n"
+
+        " .p2align 2;\n"
+        "6:\n"
+        /* Merge the pieces of the answer */
+        " movq %%mm0,%%mm1;\n"
+        " punpckhdq %%mm0,%%mm1;\n"
+        " paddd %%mm1,%%mm0;\n"
+        /* Et voila, eax has the final result */
+        " movd %%mm0,%%eax;\n"
+
+        " emms;\n"
+        : "=a" (z)
+        : "S" (x), "D" (y), "a" (n)
+        : "cc"
+    );
+#else
+    int i;
+
+    z = 0;
+    for (i = 0;  i < n;  i++)
+        z += (int32_t) x[i]*(int32_t) y[i];
+#endif
+    return z;
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(int32_t) vec_circular_dot_prodi16(const int16_t x[], const int16_t y[], int n, int pos)
+{
+    int32_t z;
+
+    z = vec_dot_prodi16(&x[pos], &y[0], n - pos);
+    z += vec_dot_prodi16(&x[0], &y[n - pos], pos);
+    return z;
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(void) vec_lmsi16(const int16_t x[], int16_t y[], int n, int16_t error)
+{
+    int i;
+
+    for (i = 0;  i < n;  i++)
+        y[i] += (int16_t) (((int32_t) x[i]*(int32_t) error) >> 15);
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(void) vec_circular_lmsi16(const int16_t x[], int16_t y[], int n, int pos, int16_t error)
+{
+    vec_lmsi16(&x[pos], &y[0], n - pos, error);
+    vec_lmsi16(&x[0], &y[n - pos], pos, error);
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(int32_t) vec_min_maxi16(const int16_t x[], int n, int16_t out[])
+{
+#if defined(__GNUC__)  &&  defined(SPANDSP_USE_MMX)  &&  defined(__x86_64__)
+    static const int32_t lower_bound = 0x80008000;
+    static const int32_t upper_bound = 0x7FFF7FFF;
+    int32_t max;
+
+    __asm__ __volatile__(
+        " emms;\n"
+        " pushq %%rdx;\n"
+        " leaq -8(%%rsi,%%rax,2),%%rdx;\n"
+
+        " cmpq %%rdx,%%rsi;\n"
+        " jbe 2f;\n"
+        " movd %[lower],%%mm0;\n"
+        " movd %[upper],%%mm1;\n"
+        " jmp 1f;\n"
+
+        " .p2align 2;\n"
+        "2:\n"
+        " movq (%%rsi),%%mm0;\n"   /* mm0 will be max's */
+        " movq %%mm0,%%mm1;\n"     /* mm1 will be min's */
+        " addq $8,%%rsi;\n"
+        " cmpq %%rdx,%%rsi;\n"
+        " ja 4f;\n"
+
+        "3:\n"
+        " movq (%%rsi),%%mm2;\n"
+
+        " movq %%mm2,%%mm3;\n"
+        " pcmpgtw %%mm0,%%mm3;\n"  /* mm3 is bitmask for words where mm2 > mm0 */ 
+        " movq %%mm3,%%mm4;\n"
+        " pand %%mm2,%%mm3;\n"     /* mm3 is mm2 masked to new max's */
+        " pandn %%mm0,%%mm4;\n"    /* mm4 is mm0 masked to its max's */
+        " por %%mm3,%%mm4;\n"
+        " movq %%mm4,%%mm0;\n"     /* Now mm0 is updated max's */
+        
+        " movq %%mm1,%%mm3;\n"
+        " pcmpgtw %%mm2,%%mm3;\n"  /* mm3 is bitmask for words where mm2 < mm1 */ 
+        " pand %%mm3,%%mm2;\n"     /* mm2 is mm2 masked to new min's */
+        " pandn %%mm1,%%mm3;\n"    /* mm3 is mm1 masked to its min's */
+        " por %%mm3,%%mm2;\n"
+        " movq %%mm2,%%mm1;\n"     /* now mm1 is updated min's */
+
+        " addq $8,%%rsi;\n"
+        " cmpq %%rdx,%%rsi;\n"
+        " jbe 3b;\n"
+
+        " .p2align 2;\n"
+        "4:\n"
+        /* Merge down the 4-word max/mins to lower 2 words */
+        " movq %%mm0,%%mm2;\n"
+        " psrlq $32,%%mm2;\n"
+        " movq %%mm2,%%mm3;\n"
+        " pcmpgtw %%mm0,%%mm3;\n"  /* mm3 is bitmask for words where mm2 > mm0 */ 
+        " pand %%mm3,%%mm2;\n"     /* mm2 is mm2 masked to new max's */
+        " pandn %%mm0,%%mm3;\n"    /* mm3 is mm0 masked to its max's */
+        " por %%mm3,%%mm2;\n"
+        " movq %%mm2,%%mm0;\n"     /* now mm0 is updated max's */
+
+        " movq %%mm1,%%mm2;\n"
+        " psrlq $32,%%mm2;\n"
+        " movq %%mm1,%%mm3;\n"
+        " pcmpgtw %%mm2,%%mm3;\n"  /* mm3 is bitmask for words where mm2 < mm1 */ 
+        " pand %%mm3,%%mm2;\n"     /* mm2 is mm2 masked to new min's */
+        " pandn %%mm1,%%mm3;\n"    /* mm3 is mm1 masked to its min's */
+        " por %%mm3,%%mm2;\n"
+        " movq %%mm2,%%mm1;\n"     /* now mm1 is updated min's */
+
+        " .p2align 2;\n"
+        "1:\n"
+        " addq $4,%%rdx;\n"        /* now dx = top-4 */
+        " cmpq %%rdx,%%rsi;\n"
+        " ja 5f;\n"
+        /* Here, there are >= 2 words of input remaining */
+        " movd (%%rsi),%%mm2;\n"
+
+        " movq %%mm2,%%mm3;\n"
+        " pcmpgtw %%mm0,%%mm3;\n"  /* mm3 is bitmask for words where mm2 > mm0 */ 
+        " movq %%mm3,%%mm4;\n"
+        " pand %%mm2,%%mm3;\n"     /* mm3 is mm2 masked to new max's */
+        " pandn %%mm0,%%mm4;\n"    /* mm4 is mm0 masked to its max's */
+        " por %%mm3,%%mm4;\n"
+        " movq %%mm4,%%mm0;\n"     /* now mm0 is updated max's */
+
+        " movq %%mm1,%%mm3;\n"
+        " pcmpgtw %%mm2,%%mm3;\n"  /* mm3 is bitmask for words where mm2 < mm1 */ 
+        " pand %%mm3,%%mm2;\n"     /* mm2 is mm2 masked to new min's */
+        " pandn %%mm1,%%mm3;\n"    /* mm3 is mm1 masked to its min's */
+        " por %%mm3,%%mm2;\n"
+        " movq %%mm2,%%mm1;\n"     /* now mm1 is updated min's */
+
+        " addq $4,%%rsi;\n"
+
+        " .p2align 2;\n"
+        "5:\n"
+        /* Merge down the 2-word max/mins to 1 word */
+        " movq %%mm0,%%mm2;\n"
+        " psrlq $16,%%mm2;\n"
+        " movq %%mm2,%%mm3;\n"
+        " pcmpgtw %%mm0,%%mm3;\n"  /* mm3 is bitmask for words where mm2 > mm0 */ 
+        " pand %%mm3,%%mm2;\n"     /* mm2 is mm2 masked to new max's */
+        " pandn %%mm0,%%mm3;\n"    /* mm3 is mm0 masked to its max's */
+        " por %%mm3,%%mm2;\n"
+        " movd %%mm2,%%ecx;\n"     /* cx is max so far */
+
+        " movq %%mm1,%%mm2;\n"
+        " psrlq $16,%%mm2;\n"
+        " movq %%mm1,%%mm3;\n"
+        " pcmpgtw %%mm2,%%mm3;\n"  /* mm3 is bitmask for words where mm2 < mm1 */ 
+        " pand %%mm3,%%mm2;\n"     /* mm2 is mm2 masked to new min's */
+        " pandn %%mm1,%%mm3;\n"    /* mm3 is mm1 masked to its min's */
+        " por %%mm3,%%mm2;\n"
+        " movd %%mm2,%%eax;\n"     /* ax is min so far */
+        
+        " addq $2,%%rdx;\n"        /* now dx = top-2 */
+        " cmpq %%rdx,%%rsi;\n"
+        " ja 6f;\n"
+
+        /* Here, there is one word of input left */
+        " cmpw (%%rsi),%%cx;\n"
+        " jge 9f;\n"
+        " movw (%%rsi),%%cx;\n"
+        " .p2align 2;\n"
+        "9:\n"
+        " cmpw (%%rsi),%%ax;\n"
+        " jle 6f;\n"
+        " movw (%%rsi),%%ax;\n"
+
+        " .p2align 2;\n"
+        "6:\n"
+        /* (finally!) cx is the max, ax the min */
+        " movswl %%cx,%%ecx;\n"
+        " movswl %%ax,%%eax;\n"
+
+        " popq %%rdx;\n"            /* ptr to output max,min vals */
+        " andq %%rdx,%%rdx;\n"
+        " jz 7f;\n"
+        " movw %%cx,(%%rdx);\n"    /* max */
+        " movw %%ax,2(%%rdx);\n"   /* min */
+        " .p2align 2;\n"
+        "7:\n"
+        /* Now calculate max absolute value */
+        " negl %%eax;\n"
+        " cmpl %%ecx,%%eax;\n"
+        " jge 8f;\n"
+        " movl %%ecx,%%eax;\n"
+        " .p2align 2;\n"
+        "8:\n"
+        " emms;\n"
+        : "=a" (max)
+        : "S" (x), "a" (n), "d" (out), [lower] "m" (lower_bound), [upper] "m" (upper_bound)
+        : "ecx"
+    );
+#elif defined(__GNUC__)  &&  defined(SPANDSP_USE_MMX)  &&  defined(__i386__)
+    static const int32_t lower_bound = 0x80008000;
+    static const int32_t upper_bound = 0x7FFF7FFF;
+    int32_t max;
+
+    __asm__ __volatile__(
+        " emms;\n"
+        " pushl %%edx;\n"
+        " leal -8(%%esi,%%eax,2),%%edx;\n"
+
+        " cmpl %%edx,%%esi;\n"
+        " jbe 2f;\n"
+        " movd %[lower],%%mm0;\n"
+        " movd %[upper],%%mm1;\n"
+        " jmp 1f;\n"
+
+        " .p2align 2;\n"
+        "2:\n"
+        " movq (%%esi),%%mm0;\n"   /* mm0 will be max's */
+        " movq %%mm0,%%mm1;\n"     /* mm1 will be min's */
+        " addl $8,%%esi;\n"
+        " cmpl %%edx,%%esi;\n"
+        " ja 4f;\n"
+
+        " .p2align 2;\n"
+        "3:\n"
+        " movq (%%esi),%%mm2;\n"
+
+        " movq %%mm2,%%mm3;\n"
+        " pcmpgtw %%mm0,%%mm3;\n"  /* mm3 is bitmask for words where mm2 > mm0 */ 
+        " movq %%mm3,%%mm4;\n"
+        " pand %%mm2,%%mm3;\n"     /* mm3 is mm2 masked to new max's */
+        " pandn %%mm0,%%mm4;\n"    /* mm4 is mm0 masked to its max's */
+        " por %%mm3,%%mm4;\n"
+        " movq %%mm4,%%mm0;\n"     /* Now mm0 is updated max's */
+        
+        " movq %%mm1,%%mm3;\n"
+        " pcmpgtw %%mm2,%%mm3;\n"  /* mm3 is bitmask for words where mm2 < mm1 */ 
+        " pand %%mm3,%%mm2;\n"     /* mm2 is mm2 masked to new min's */
+        " pandn %%mm1,%%mm3;\n"    /* mm3 is mm1 masked to its min's */
+        " por %%mm3,%%mm2;\n"
+        " movq %%mm2,%%mm1;\n"     /* now mm1 is updated min's */
+
+        " addl $8,%%esi;\n"
+        " cmpl %%edx,%%esi;\n"
+        " jbe 3b;\n"
+
+        " .p2align 2;\n"
+        "4:\n"
+        /* Merge down the 4-word max/mins to lower 2 words */
+        " movq %%mm0,%%mm2;\n"
+        " psrlq $32,%%mm2;\n"
+        " movq %%mm2,%%mm3;\n"
+        " pcmpgtw %%mm0,%%mm3;\n"  /* mm3 is bitmask for words where mm2 > mm0 */ 
+        " pand %%mm3,%%mm2;\n"     /* mm2 is mm2 masked to new max's */
+        " pandn %%mm0,%%mm3;\n"    /* mm3 is mm0 masked to its max's */
+        " por %%mm3,%%mm2;\n"
+        " movq %%mm2,%%mm0;\n"     /* now mm0 is updated max's */
+
+        " movq %%mm1,%%mm2;\n"
+        " psrlq $32,%%mm2;\n"
+        " movq %%mm1,%%mm3;\n"
+        " pcmpgtw %%mm2,%%mm3;\n"  /* mm3 is bitmask for words where mm2 < mm1 */ 
+        " pand %%mm3,%%mm2;\n"     /* mm2 is mm2 masked to new min's */
+        " pandn %%mm1,%%mm3;\n"    /* mm3 is mm1 masked to its min's */
+        " por %%mm3,%%mm2;\n"
+        " movq %%mm2,%%mm1;\n"     /* now mm1 is updated min's */
+
+        " .p2align 2;\n"
+        "1:\n"
+        " addl $4,%%edx;\n"        /* now dx = top-4 */
+        " cmpl %%edx,%%esi;\n"
+        " ja 5f;\n"
+        /* Here, there are >= 2 words of input remaining */
+        " movd (%%esi),%%mm2;\n"
+
+        " movq %%mm2,%%mm3;\n"
+        " pcmpgtw %%mm0,%%mm3;\n"  /* mm3 is bitmask for words where mm2 > mm0 */ 
+        " movq %%mm3,%%mm4;\n"
+        " pand %%mm2,%%mm3;\n"     /* mm3 is mm2 masked to new max's */
+        " pandn %%mm0,%%mm4;\n"    /* mm4 is mm0 masked to its max's */
+        " por %%mm3,%%mm4;\n"
+        " movq %%mm4,%%mm0;\n"     /* now mm0 is updated max's */
+
+        " movq %%mm1,%%mm3;\n"
+        " pcmpgtw %%mm2,%%mm3;\n"  /* mm3 is bitmask for words where mm2 < mm1 */ 
+        " pand %%mm3,%%mm2;\n"     /* mm2 is mm2 masked to new min's */
+        " pandn %%mm1,%%mm3;\n"    /* mm3 is mm1 masked to its min's */
+        " por %%mm3,%%mm2;\n"
+        " movq %%mm2,%%mm1;\n"     /* now mm1 is updated min's */
+
+        " addl $4,%%esi;\n"
+
+        " .p2align 2;\n"
+        "5:\n"
+        /* Merge down the 2-word max/mins to 1 word */
+        " movq %%mm0,%%mm2;\n"
+        " psrlq $16,%%mm2;\n"
+        " movq %%mm2,%%mm3;\n"
+        " pcmpgtw %%mm0,%%mm3;\n"  /* mm3 is bitmask for words where mm2 > mm0 */ 
+        " pand %%mm3,%%mm2;\n"     /* mm2 is mm2 masked to new max's */
+        " pandn %%mm0,%%mm3;\n"    /* mm3 is mm0 masked to its max's */
+        " por %%mm3,%%mm2;\n"
+        " movd %%mm2,%%ecx;\n"     /* cx is max so far */
+
+        " movq %%mm1,%%mm2;\n"
+        " psrlq $16,%%mm2;\n"
+        " movq %%mm1,%%mm3;\n"
+        " pcmpgtw %%mm2,%%mm3;\n"  /* mm3 is bitmask for words where mm2 < mm1 */ 
+        " pand %%mm3,%%mm2;\n"     /* mm2 is mm2 masked to new min's */
+        " pandn %%mm1,%%mm3;\n"    /* mm3 is mm1 masked to its min's */
+        " por %%mm3,%%mm2;\n"
+        " movd %%mm2,%%eax;\n"     /* ax is min so far */
+        
+        " addl $2,%%edx;\n"        /* now dx = top-2 */
+        " cmpl %%edx,%%esi;\n"
+        " ja 6f;\n"
+
+        /* Here, there is one word of input left */
+        " cmpw (%%esi),%%cx;\n"
+        " jge 9f;\n"
+        " movw (%%esi),%%cx;\n"
+        " .p2align 2;\n"
+        "9:\n"
+        " cmpw (%%esi),%%ax;\n"
+        " jle 6f;\n"
+        " movw (%%esi),%%ax;\n"
+
+        " .p2align 2;\n"
+        "6:\n"
+        /* (finally!) cx is the max, ax the min */
+        " movswl %%cx,%%ecx;\n"
+        " movswl %%ax,%%eax;\n"
+
+        " popl %%edx;\n"            /* ptr to output max,min vals */
+        " andl %%edx,%%edx;\n"
+        " jz 7f;\n"
+        " movw %%cx,(%%edx);\n"    /* max */
+        " movw %%ax,2(%%edx);\n"   /* min */
+        " .p2align 2;\n"
+        "7:\n"
+        /* Now calculate max absolute value */
+        " negl %%eax;\n"
+        " cmpl %%ecx,%%eax;\n"
+        " jge 8f;\n"
+        " movl %%ecx,%%eax;\n"
+        " .p2align 2;\n"
+        "8:\n"
+        " emms;\n"
+        : "=a" (max)
+        : "S" (x), "a" (n), "d" (out), [lower] "m" (lower_bound), [upper] "m" (upper_bound)
+        : "ecx"
+    );
+#else
+    int i;
+    int16_t min;
+    int16_t max;
+    int16_t temp;
+    int32_t z;
+    
+    max = INT16_MIN;
+    min = INT16_MAX;
+    for (i = 0;  i < n;  i++)
+    {
+        temp = x[i];
+        if (temp > max)
+            max = temp;
+        /*endif*/
+        if (temp < min)
+            min = temp;
+        /*endif*/
+    }
+    /*endfor*/
+    if (out)
+    {
+        out[0] = max;
+        out[1] = min;
+    }
+    z = abs(min);
+    if (z > max)
+        return z;
+#endif
+    return max;
+}
+/*- End of function --------------------------------------------------------*/
+/*- End of file ------------------------------------------------------------*/
diff --git a/src/codec/speex/include/speex/speex.h b/src/codec/speex/include/speex/speex.h
new file mode 100644 (file)
index 0000000..82ba016
--- /dev/null
@@ -0,0 +1,424 @@
+/* Copyright (C) 2002-2006 Jean-Marc Valin*/
+/**
+  @file speex.h
+  @brief Describes the different modes of the codec
+*/
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+   
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+   
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+   
+   - Neither the name of the Xiph.org Foundation nor the names of its
+   contributors may be used to endorse or promote products derived from
+   this software without specific prior written permission.
+   
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
+   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef SPEEX_H
+#define SPEEX_H
+/** @defgroup Codec Speex encoder and decoder
+ *  This is the Speex codec itself.
+ *  @{
+ */
+
+#include "speex/speex_bits.h"
+#include "speex/speex_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Values allowed for *ctl() requests */
+
+/** Set enhancement on/off (decoder only) */
+#define SPEEX_SET_ENH 0
+/** Get enhancement state (decoder only) */
+#define SPEEX_GET_ENH 1
+
+/*Would be SPEEX_SET_FRAME_SIZE, but it's (currently) invalid*/
+/** Obtain frame size used by encoder/decoder */
+#define SPEEX_GET_FRAME_SIZE 3
+
+/** Set quality value */
+#define SPEEX_SET_QUALITY 4
+/** Get current quality setting */
+/* #define SPEEX_GET_QUALITY 5 -- Doesn't make much sense, does it? */
+
+/** Set sub-mode to use */
+#define SPEEX_SET_MODE 6
+/** Get current sub-mode in use */
+#define SPEEX_GET_MODE 7
+
+/** Set low-band sub-mode to use (wideband only)*/
+#define SPEEX_SET_LOW_MODE 8
+/** Get current low-band mode in use (wideband only)*/
+#define SPEEX_GET_LOW_MODE 9
+
+/** Set high-band sub-mode to use (wideband only)*/
+#define SPEEX_SET_HIGH_MODE 10
+/** Get current high-band mode in use (wideband only)*/
+#define SPEEX_GET_HIGH_MODE 11
+
+/** Set VBR on (1) or off (0) */
+#define SPEEX_SET_VBR 12
+/** Get VBR status (1 for on, 0 for off) */
+#define SPEEX_GET_VBR 13
+
+/** Set quality value for VBR encoding (0-10) */
+#define SPEEX_SET_VBR_QUALITY 14
+/** Get current quality value for VBR encoding (0-10) */
+#define SPEEX_GET_VBR_QUALITY 15
+
+/** Set complexity of the encoder (0-10) */
+#define SPEEX_SET_COMPLEXITY 16
+/** Get current complexity of the encoder (0-10) */
+#define SPEEX_GET_COMPLEXITY 17
+
+/** Set bit-rate used by the encoder (or lower) */
+#define SPEEX_SET_BITRATE 18
+/** Get current bit-rate used by the encoder or decoder */
+#define SPEEX_GET_BITRATE 19
+
+/** Define a handler function for in-band Speex request*/
+#define SPEEX_SET_HANDLER 20
+
+/** Define a handler function for in-band user-defined request*/
+#define SPEEX_SET_USER_HANDLER 22
+
+/** Set sampling rate used in bit-rate computation */
+#define SPEEX_SET_SAMPLING_RATE 24
+/** Get sampling rate used in bit-rate computation */
+#define SPEEX_GET_SAMPLING_RATE 25
+
+/** Reset the encoder/decoder memories to zero*/
+#define SPEEX_RESET_STATE 26
+
+/** Get VBR info (mostly used internally) */
+#define SPEEX_GET_RELATIVE_QUALITY 29
+
+/** Set VAD status (1 for on, 0 for off) */
+#define SPEEX_SET_VAD 30
+
+/** Get VAD status (1 for on, 0 for off) */
+#define SPEEX_GET_VAD 31
+
+/** Set Average Bit-Rate (ABR) to n bits per seconds */
+#define SPEEX_SET_ABR 32
+/** Get Average Bit-Rate (ABR) setting (in bps) */
+#define SPEEX_GET_ABR 33
+
+/** Set DTX status (1 for on, 0 for off) */
+#define SPEEX_SET_DTX 34
+/** Get DTX status (1 for on, 0 for off) */
+#define SPEEX_GET_DTX 35
+
+/** Set submode encoding in each frame (1 for yes, 0 for no, setting to no breaks the standard) */
+#define SPEEX_SET_SUBMODE_ENCODING 36
+/** Get submode encoding in each frame */
+#define SPEEX_GET_SUBMODE_ENCODING 37
+
+/*#define SPEEX_SET_LOOKAHEAD 38*/
+/** Returns the lookahead used by Speex */
+#define SPEEX_GET_LOOKAHEAD 39
+
+/** Sets tuning for packet-loss concealment (expected loss rate) */
+#define SPEEX_SET_PLC_TUNING 40
+/** Gets tuning for PLC */
+#define SPEEX_GET_PLC_TUNING 41
+
+/** Sets the max bit-rate allowed in VBR mode */
+#define SPEEX_SET_VBR_MAX_BITRATE 42
+/** Gets the max bit-rate allowed in VBR mode */
+#define SPEEX_GET_VBR_MAX_BITRATE 43
+
+/** Turn on/off input/output high-pass filtering */
+#define SPEEX_SET_HIGHPASS 44
+/** Get status of input/output high-pass filtering */
+#define SPEEX_GET_HIGHPASS 45
+
+/** Get "activity level" of the last decoded frame, i.e.
+    how much damage we cause if we remove the frame */
+#define SPEEX_GET_ACTIVITY 47
+
+
+/* Preserving compatibility:*/
+/** Equivalent to SPEEX_SET_ENH */
+#define SPEEX_SET_PF 0
+/** Equivalent to SPEEX_GET_ENH */
+#define SPEEX_GET_PF 1
+
+
+
+
+/* Values allowed for mode queries */
+/** Query the frame size of a mode */
+#define SPEEX_MODE_FRAME_SIZE 0
+
+/** Query the size of an encoded frame for a particular sub-mode */
+#define SPEEX_SUBMODE_BITS_PER_FRAME 1
+
+
+
+/** Get major Speex version */
+#define SPEEX_LIB_GET_MAJOR_VERSION 1
+/** Get minor Speex version */
+#define SPEEX_LIB_GET_MINOR_VERSION 3
+/** Get micro Speex version */
+#define SPEEX_LIB_GET_MICRO_VERSION 5
+/** Get extra Speex version */
+#define SPEEX_LIB_GET_EXTRA_VERSION 7
+/** Get Speex version string */
+#define SPEEX_LIB_GET_VERSION_STRING 9
+
+/*#define SPEEX_LIB_SET_ALLOC_FUNC 10
+#define SPEEX_LIB_GET_ALLOC_FUNC 11
+#define SPEEX_LIB_SET_FREE_FUNC 12
+#define SPEEX_LIB_GET_FREE_FUNC 13
+
+#define SPEEX_LIB_SET_WARNING_FUNC 14
+#define SPEEX_LIB_GET_WARNING_FUNC 15
+#define SPEEX_LIB_SET_ERROR_FUNC 16
+#define SPEEX_LIB_GET_ERROR_FUNC 17
+*/
+
+/** Number of defined modes in Speex */
+#define SPEEX_NB_MODES 3
+
+/** modeID for the defined narrowband mode */
+#define SPEEX_MODEID_NB 0
+
+/** modeID for the defined wideband mode */
+#define SPEEX_MODEID_WB 1
+
+/** modeID for the defined ultra-wideband mode */
+#define SPEEX_MODEID_UWB 2
+
+struct SpeexMode;
+
+
+/* Prototypes for mode function pointers */
+
+/** Encoder state initialization function */
+typedef void *(*encoder_init_func)(const struct SpeexMode *mode);
+
+/** Encoder state destruction function */
+typedef void (*encoder_destroy_func)(void *st);
+
+/** Main encoding function */
+typedef int (*encode_func)(void *state, void *in, SpeexBits *bits);
+
+/** Function for controlling the encoder options */
+typedef int (*encoder_ctl_func)(void *state, int request, void *ptr);
+
+/** Decoder state initialization function */
+typedef void *(*decoder_init_func)(const struct SpeexMode *mode);
+
+/** Decoder state destruction function */
+typedef void (*decoder_destroy_func)(void *st);
+
+/** Main decoding function */
+typedef int  (*decode_func)(void *state, SpeexBits *bits, void *out);
+
+/** Function for controlling the decoder options */
+typedef int (*decoder_ctl_func)(void *state, int request, void *ptr);
+
+
+/** Query function for a mode */
+typedef int (*mode_query_func)(const void *mode, int request, void *ptr);
+
+/** Struct defining a Speex mode */ 
+typedef struct SpeexMode {
+   /** Pointer to the low-level mode data */
+   const void *mode;
+
+   /** Pointer to the mode query function */
+   mode_query_func query;
+   
+   /** The name of the mode (you should not rely on this to identify the mode)*/
+   const char *modeName;
+
+   /**ID of the mode*/
+   int modeID;
+
+   /**Version number of the bitstream (incremented every time we break
+    bitstream compatibility*/
+   int bitstream_version;
+
+   /** Pointer to encoder initialization function */
+   encoder_init_func enc_init;
+
+   /** Pointer to encoder destruction function */
+   encoder_destroy_func enc_destroy;
+
+   /** Pointer to frame encoding function */
+   encode_func enc;
+
+   /** Pointer to decoder initialization function */
+   decoder_init_func dec_init;
+
+   /** Pointer to decoder destruction function */
+   decoder_destroy_func dec_destroy;
+
+   /** Pointer to frame decoding function */
+   decode_func dec;
+
+   /** ioctl-like requests for encoder */
+   encoder_ctl_func enc_ctl;
+
+   /** ioctl-like requests for decoder */
+   decoder_ctl_func dec_ctl;
+
+} SpeexMode;
+
+/**
+ * Returns a handle to a newly created Speex encoder state structure. For now, 
+ * the "mode" argument can be &nb_mode or &wb_mode . In the future, more modes 
+ * may be added. Note that for now if you have more than one channels to 
+ * encode, you need one state per channel.
+ *
+ * @param mode The mode to use (either speex_nb_mode or speex_wb.mode) 
+ * @return A newly created encoder state or NULL if state allocation fails
+ */
+void *speex_encoder_init(const SpeexMode *mode);
+
+/** Frees all resources associated to an existing Speex encoder state. 
+ * @param state Encoder state to be destroyed */
+void speex_encoder_destroy(void *state);
+
+/** Uses an existing encoder state to encode one frame of speech pointed to by
+    "in". The encoded bit-stream is saved in "bits".
+ @param state Encoder state
+ @param in Frame that will be encoded with a +-2^15 range. This data MAY be 
+        overwritten by the encoder and should be considered uninitialised 
+        after the call.
+ @param bits Bit-stream where the data will be written
+ @return 0 if frame needs not be transmitted (DTX only), 1 otherwise
+ */
+int speex_encode(void *state, float *in, SpeexBits *bits);
+
+/** Uses an existing encoder state to encode one frame of speech pointed to by
+    "in". The encoded bit-stream is saved in "bits".
+ @param state Encoder state
+ @param in Frame that will be encoded with a +-2^15 range
+ @param bits Bit-stream where the data will be written
+ @return 0 if frame needs not be transmitted (DTX only), 1 otherwise
+ */
+int speex_encode_int(void *state, spx_int16_t *in, SpeexBits *bits);
+
+/** Used like the ioctl function to control the encoder parameters
+ *
+ * @param state Encoder state
+ * @param request ioctl-type request (one of the SPEEX_* macros)
+ * @param ptr Data exchanged to-from function
+ * @return 0 if no error, -1 if request in unknown, -2 for invalid parameter
+ */
+int speex_encoder_ctl(void *state, int request, void *ptr);
+
+
+/** Returns a handle to a newly created decoder state structure. For now, 
+ * the mode argument can be &nb_mode or &wb_mode . In the future, more modes
+ * may be added.  Note that for now if you have more than one channels to
+ * decode, you need one state per channel.
+ *
+ * @param mode Speex mode (one of speex_nb_mode or speex_wb_mode)
+ * @return A newly created decoder state or NULL if state allocation fails
+ */ 
+void *speex_decoder_init(const SpeexMode *mode);
+
+/** Frees all resources associated to an existing decoder state.
+ *
+ * @param state State to be destroyed
+ */
+void speex_decoder_destroy(void *state);
+
+/** Uses an existing decoder state to decode one frame of speech from
+ * bit-stream bits. The output speech is saved written to out.
+ *
+ * @param state Decoder state
+ * @param bits Bit-stream from which to decode the frame (NULL if the packet was lost)
+ * @param out Where to write the decoded frame
+ * @return return status (0 for no error, -1 for end of stream, -2 corrupt stream)
+ */
+int speex_decode(void *state, SpeexBits *bits, float *out);
+
+/** Uses an existing decoder state to decode one frame of speech from
+ * bit-stream bits. The output speech is saved written to out.
+ *
+ * @param state Decoder state
+ * @param bits Bit-stream from which to decode the frame (NULL if the packet was lost)
+ * @param out Where to write the decoded frame
+ * @return return status (0 for no error, -1 for end of stream, -2 corrupt stream)
+ */
+int speex_decode_int(void *state, SpeexBits *bits, spx_int16_t *out);
+
+/** Used like the ioctl function to control the encoder parameters
+ *
+ * @param state Decoder state
+ * @param request ioctl-type request (one of the SPEEX_* macros)
+ * @param ptr Data exchanged to-from function
+ * @return 0 if no error, -1 if request in unknown, -2 for invalid parameter
+ */
+int speex_decoder_ctl(void *state, int request, void *ptr);
+
+
+/** Query function for mode information
+ *
+ * @param mode Speex mode
+ * @param request ioctl-type request (one of the SPEEX_* macros)
+ * @param ptr Data exchanged to-from function
+ * @return 0 if no error, -1 if request in unknown, -2 for invalid parameter
+ */
+int speex_mode_query(const SpeexMode *mode, int request, void *ptr);
+
+/** Functions for controlling the behavior of libspeex
+ * @param request ioctl-type request (one of the SPEEX_LIB_* macros)
+ * @param ptr Data exchanged to-from function
+ * @return 0 if no error, -1 if request in unknown, -2 for invalid parameter
+ */
+int speex_lib_ctl(int request, void *ptr);
+
+/** Default narrowband mode */
+extern const SpeexMode speex_nb_mode;
+
+/** Default wideband mode */
+extern const SpeexMode speex_wb_mode;
+
+/** Default "ultra-wideband" mode */
+extern const SpeexMode speex_uwb_mode;
+
+/** List of all modes available */
+extern const SpeexMode * const speex_mode_list[SPEEX_NB_MODES];
+
+/** Obtain one of the modes available */
+const SpeexMode * speex_lib_get_mode (int mode);
+
+#ifndef WIN32
+/* We actually override the function in the narrowband case so that we can avoid linking in the wideband stuff */
+#define speex_lib_get_mode(mode) ((mode)==SPEEX_MODEID_NB ? &speex_nb_mode : speex_lib_get_mode (mode))
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+/** @}*/
+#endif
diff --git a/src/codec/speex/include/speex/speex_bits.h b/src/codec/speex/include/speex/speex_bits.h
new file mode 100644 (file)
index 0000000..a26fb4c
--- /dev/null
@@ -0,0 +1,174 @@
+/* Copyright (C) 2002 Jean-Marc Valin */
+/**
+   @file speex_bits.h
+   @brief Handles bit packing/unpacking
+*/
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+   
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+   
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+   
+   - Neither the name of the Xiph.org Foundation nor the names of its
+   contributors may be used to endorse or promote products derived from
+   this software without specific prior written permission.
+   
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
+   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef BITS_H
+#define BITS_H
+/** @defgroup SpeexBits SpeexBits: Bit-stream manipulations
+ *  This is the structure that holds the bit-stream when encoding or decoding
+ * with Speex. It allows some manipulations as well.
+ *  @{
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Bit-packing data structure representing (part of) a bit-stream. */
+typedef struct SpeexBits {
+   char *chars;   /**< "raw" data */
+   int   nbBits;  /**< Total number of bits stored in the stream*/
+   int   charPtr; /**< Position of the byte "cursor" */
+   int   bitPtr;  /**< Position of the bit "cursor" within the current char */
+   int   owner;   /**< Does the struct "own" the "raw" buffer (member "chars") */
+   int   overflow;/**< Set to one if we try to read past the valid data */
+   int   buf_size;/**< Allocated size for buffer */
+   int   reserved1; /**< Reserved for future use */
+   void *reserved2; /**< Reserved for future use */
+} SpeexBits;
+
+/** Initializes and allocates resources for a SpeexBits struct */
+void speex_bits_init(SpeexBits *bits);
+
+/** Initializes SpeexBits struct using a pre-allocated buffer*/
+void speex_bits_init_buffer(SpeexBits *bits, void *buff, int buf_size);
+
+/** Sets the bits in a SpeexBits struct to use data from an existing buffer (for decoding without copying data) */
+void speex_bits_set_bit_buffer(SpeexBits *bits, void *buff, int buf_size);
+
+/** Frees all resources associated to a SpeexBits struct. Right now this does nothing since no resources are allocated, but this could change in the future.*/
+void speex_bits_destroy(SpeexBits *bits);
+
+/** Resets bits to initial value (just after initialization, erasing content)*/
+void speex_bits_reset(SpeexBits *bits);
+
+/** Rewind the bit-stream to the beginning (ready for read) without erasing the content */
+void speex_bits_rewind(SpeexBits *bits);
+
+/** Initializes the bit-stream from the data in an area of memory */
+void speex_bits_read_from(SpeexBits *bits, char *bytes, int len);
+
+/** Append bytes to the bit-stream
+ * 
+ * @param bits Bit-stream to operate on
+ * @param bytes pointer to the bytes what will be appended
+ * @param len Number of bytes of append
+ */
+void speex_bits_read_whole_bytes(SpeexBits *bits, char *bytes, int len);
+
+/** Write the content of a bit-stream to an area of memory
+ * 
+ * @param bits Bit-stream to operate on
+ * @param bytes Memory location where to write the bits
+ * @param max_len Maximum number of bytes to write (i.e. size of the "bytes" buffer)
+ * @return Number of bytes written to the "bytes" buffer
+*/
+int speex_bits_write(SpeexBits *bits, char *bytes, int max_len);
+
+/** Like speex_bits_write, but writes only the complete bytes in the stream. Also removes the written bytes from the stream */
+int speex_bits_write_whole_bytes(SpeexBits *bits, char *bytes, int max_len);
+
+/** Append bits to the bit-stream
+ * @param bits Bit-stream to operate on
+ * @param data Value to append as integer
+ * @param nbBits number of bits to consider in "data"
+ */
+void speex_bits_pack(SpeexBits *bits, int data, int nbBits);
+
+/** Interpret the next bits in the bit-stream as a signed integer
+ *
+ * @param bits Bit-stream to operate on
+ * @param nbBits Number of bits to interpret
+ * @return A signed integer represented by the bits read
+ */
+int speex_bits_unpack_signed(SpeexBits *bits, int nbBits);
+
+/** Interpret the next bits in the bit-stream as an unsigned integer
+ *
+ * @param bits Bit-stream to operate on
+ * @param nbBits Number of bits to interpret
+ * @return An unsigned integer represented by the bits read
+ */
+unsigned int speex_bits_unpack_unsigned(SpeexBits *bits, int nbBits);
+
+/** Returns the number of bytes in the bit-stream, including the last one even if it is not "full"
+ *
+ * @param bits Bit-stream to operate on
+ * @return Number of bytes in the stream
+ */
+int speex_bits_nbytes(SpeexBits *bits);
+
+/** Same as speex_bits_unpack_unsigned, but without modifying the cursor position 
+ * 
+ * @param bits Bit-stream to operate on
+ * @param nbBits Number of bits to look for
+ * @return Value of the bits peeked, interpreted as unsigned
+ */
+unsigned int speex_bits_peek_unsigned(SpeexBits *bits, int nbBits);
+
+/** Get the value of the next bit in the stream, without modifying the
+ * "cursor" position 
+ * 
+ * @param bits Bit-stream to operate on
+ * @return Value of the bit peeked (one bit only)
+ */
+int speex_bits_peek(SpeexBits *bits);
+
+/** Advances the position of the "bit cursor" in the stream 
+ *
+ * @param bits Bit-stream to operate on
+ * @param n Number of bits to advance
+ */
+void speex_bits_advance(SpeexBits *bits, int n);
+
+/** Returns the number of bits remaining to be read in a stream
+ *
+ * @param bits Bit-stream to operate on
+ * @return Number of bits that can still be read from the stream
+ */
+int speex_bits_remaining(SpeexBits *bits);
+
+/** Insert a terminator so that the data can be sent as a packet while auto-detecting 
+ * the number of frames in each packet 
+ *
+ * @param bits Bit-stream to operate on
+ */
+void speex_bits_insert_terminator(SpeexBits *bits);
+
+#ifdef __cplusplus
+}
+#endif
+
+/* @} */
+#endif
diff --git a/src/codec/speex/include/speex/speex_types.h b/src/codec/speex/include/speex/speex_types.h
new file mode 100644 (file)
index 0000000..852fed8
--- /dev/null
@@ -0,0 +1,126 @@
+/* speex_types.h taken from libogg */
+/********************************************************************
+ *                                                                  *
+ * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE.   *
+ * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
+ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
+ * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
+ *                                                                  *
+ * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2002             *
+ * by the Xiph.Org Foundation http://www.xiph.org/                  *
+ *                                                                  *
+ ********************************************************************
+
+ function: #ifdef jail to whip a few platforms into the UNIX ideal.
+ last mod: $Id: os_types.h 7524 2004-08-11 04:20:36Z conrad $
+
+ ********************************************************************/
+/**
+   @file speex_types.h
+   @brief Speex types
+*/
+#ifndef _SPEEX_TYPES_H
+#define _SPEEX_TYPES_H
+
+#if defined(_WIN32) 
+
+#  if defined(__CYGWIN__)
+#    include <_G_config.h>
+     typedef _G_int32_t spx_int32_t;
+     typedef _G_uint32_t spx_uint32_t;
+     typedef _G_int16_t spx_int16_t;
+     typedef _G_uint16_t spx_uint16_t;
+#  elif defined(__MINGW32__)
+     typedef short spx_int16_t;
+     typedef unsigned short spx_uint16_t;
+     typedef int spx_int32_t;
+     typedef unsigned int spx_uint32_t;
+#  elif defined(__MWERKS__)
+     typedef int spx_int32_t;
+     typedef unsigned int spx_uint32_t;
+     typedef short spx_int16_t;
+     typedef unsigned short spx_uint16_t;
+#  else
+     /* MSVC/Borland */
+     typedef __int32 spx_int32_t;
+     typedef unsigned __int32 spx_uint32_t;
+     typedef __int16 spx_int16_t;
+     typedef unsigned __int16 spx_uint16_t;
+#  endif
+
+#elif defined(__MACOS__)
+
+#  include <sys/types.h>
+   typedef SInt16 spx_int16_t;
+   typedef UInt16 spx_uint16_t;
+   typedef SInt32 spx_int32_t;
+   typedef UInt32 spx_uint32_t;
+
+#elif (defined(__APPLE__) && defined(__MACH__)) /* MacOS X Framework build */
+
+#  include <sys/types.h>
+   typedef int16_t spx_int16_t;
+   typedef u_int16_t spx_uint16_t;
+   typedef int32_t spx_int32_t;
+   typedef u_int32_t spx_uint32_t;
+
+#elif defined(__BEOS__)
+
+   /* Be */
+#  include <inttypes.h>
+   typedef int16_t spx_int16_t;
+   typedef u_int16_t spx_uint16_t;
+   typedef int32_t spx_int32_t;
+   typedef u_int32_t spx_uint32_t;
+
+#elif defined (__EMX__)
+
+   /* OS/2 GCC */
+   typedef short spx_int16_t;
+   typedef unsigned short spx_uint16_t;
+   typedef int spx_int32_t;
+   typedef unsigned int spx_uint32_t;
+
+#elif defined (DJGPP)
+
+   /* DJGPP */
+   typedef short spx_int16_t;
+   typedef int spx_int32_t;
+   typedef unsigned int spx_uint32_t;
+
+#elif defined(R5900)
+
+   /* PS2 EE */
+   typedef int spx_int32_t;
+   typedef unsigned spx_uint32_t;
+   typedef short spx_int16_t;
+
+#elif defined(__SYMBIAN32__)
+
+   /* Symbian GCC */
+   typedef signed short spx_int16_t;
+   typedef unsigned short spx_uint16_t;
+   typedef signed int spx_int32_t;
+   typedef unsigned int spx_uint32_t;
+
+#elif defined(CONFIG_TI_C54X) || defined (CONFIG_TI_C55X)
+
+   typedef short spx_int16_t;
+   typedef unsigned short spx_uint16_t;
+   typedef long spx_int32_t;
+   typedef unsigned long spx_uint32_t;
+
+#elif defined(CONFIG_TI_C6X)
+
+   typedef short spx_int16_t;
+   typedef unsigned short spx_uint16_t;
+   typedef int spx_int32_t;
+   typedef unsigned int spx_uint32_t;
+
+#else
+
+#  include <speex/speex_config_types.h>
+
+#endif
+
+#endif  /* _SPEEX_TYPES_H */
diff --git a/src/codec/wrap.c b/src/codec/wrap.c
new file mode 100644 (file)
index 0000000..10ec7f8
--- /dev/null
@@ -0,0 +1,640 @@
+/* wrap.c -- API wrappers for the selected codecs.
+ *
+ * "Een beetje van jezelf, een beetje is magisch."
+ * (Maar wij kunnen het zonder GSM of MSG.)
+ *
+ * This file is part of 0cpm Firmerware.
+ *
+ * 0cpm Firmerware is Copyright (c)2011 Rick van Rein, OpenFortress.
+ *
+ * 0cpm Firmerware is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 3.
+ *
+ * 0cpm Firmerware is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with 0cpm Firmerware.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#include <0cpm/codec.h>
+
+
+/** \defgroup codec
+ * Codecs pack and unpack media streams for delivery over RTP.
+ * The abilities of codecs are negotiated using SDP-descriptions,
+ * commonly sent in the body of a SIP or SAP message.
+ */
+
+/** \ingroup codec
+ * The codec-wrapper functionality aligns the internal API used
+ * by the 0cpm Firmerware with codec software used from other
+ * open source projects.
+ */
+
+
+
+/********** PAYLOAD TYPE ALLOCATIONS **********/
+
+// Pay Mime-type               Rate    Registry
+//
+// 0   audio/PCMU              8000    IANA
+// 8   audio/PCMA              8000    IANA
+// 99  audio/L16               var.    LOCAL (arbitrary sample rate)
+// 98  text/t140               1000    LOCAL
+// 100  text/red               1000    LOCAL
+// 101 audio/telephone-event   8000    LOCAL (but commonly used)
+// 110 audio/G726-32           8000    LOCAL
+// 111 audio/AAL2-G726-32      8000    LOCAL
+// 125  audio/x-codec2         2550    LOCAL
+// 124  audio/x-codec2         2400    LOCAL
+// 123  audio/x-codec2         2000    LOCAL
+// 122  audio/x-codec2         1500    LOCAL
+// 121  audio/x-codec2         1000?   RESERVED
+// 126 audio/speex             var.    LOCAL
+// 127 audio/vorbis            var.    LOCAL
+
+
+
+/********** G.711 DEFINITIONS **********/
+
+#ifdef CONFIG_CODEC_G711
+
+
+static void g711_init_ulaw (struct codec *hdl, uint32_t samplerate) {
+       g711_init (&hdl->state.state_g711, G711_ULAW);
+}
+
+
+static void g711_init_alaw (struct codec *hdl, uint32_t samplerate) {
+       g711_init (&hdl->state.state_g711, G711_ALAW);
+}
+
+static void g711_finish (struct codec *hdl) {
+       g711_release (&hdl->state.state_g711);
+}
+
+static void g711_transform_encode (struct codec *hdl,
+                       int16_t *pcm, uint16_t *pcmlen,
+                       uint8_t *pkt, uint16_t *pktlen) {
+       uint16_t len = *pcmlen;
+       if (*pktlen < *pcmlen) {
+               len = *pktlen;
+       }
+       len = g711_encode (&hdl->state.state_g711, pkt, pcm, len);
+       *pcmlen = *pktlen = len;
+}
+
+static void g711_transform_decode (struct codec *hdl,
+                       int16_t *pcm, uint16_t *pcmlen,
+                       uint8_t *pkt, uint16_t *pktlen) {
+       uint16_t len = *pcmlen;
+       if (*pktlen < *pcmlen) {
+               len = *pktlen;
+       }
+       len = g711_decode (&hdl->state.state_g711, pcm, pkt, len);
+       *pcmlen = *pktlen = len;
+}
+
+struct codec_fun encoder_g711_ulaw = {
+       "audio", "PCMU", NULL,
+       "PCMU",
+       g711_init_ulaw, g711_finish, g711_transform_encode,
+       8000, 0
+};
+
+struct codec_fun decoder_g711_ulaw = {
+       "audio", "PCMU", NULL,
+       "PCMU",
+       g711_init_ulaw, g711_finish, g711_transform_decode,
+       8000, 0
+};
+
+struct codec_fun encoder_g711_alaw = {
+       "audio", "PCMA", NULL,
+       "PCMA",
+       g711_init_alaw, g711_finish, g711_transform_encode,
+       8000, 8
+};
+
+struct codec_fun decoder_g711_alaw = {
+       "audio", "PCMA", NULL,
+       "PCMA",
+       g711_init_alaw, g711_finish, g711_transform_decode,
+       8000, 8
+};
+
+#endif
+
+
+
+/********** G.722 DEFINITIONS **********/
+
+#ifdef CONFIG_CODEC_G722
+
+static void g722_init_encode (struct codec *hdl, uint32_t samplerate) {
+       g722_encode_init (&hdl->state.state_g722_encode, 64000, 0);
+}
+
+static void g722_init_decode (struct codec *hdl, uint32_t samplerate) {
+       g722_decode_init (&hdl->state.state_g722_decode, 64000, 0);
+}
+
+static void g722_finish_encode (struct codec *hdl) {
+       g722_encode_release (&hdl->state.state_g722_encode);
+}
+
+static void g722_finish_decode (struct codec *hdl) {
+       g722_decode_release (&hdl->state.state_g722_decode);
+}
+
+static void g722_transform_encode (struct codec *hdl,
+                       int16_t *pcm, uint16_t *pcmlen,
+                       uint8_t *pkt, uint16_t *pktlen) {
+       uint16_t len = *pcmlen;
+       if (*pktlen < *pcmlen) {
+               len = *pktlen;
+       }
+       len = g722_encode (&hdl->state.state_g722_encode, pkt, pcm, len);
+       *pcmlen = *pktlen = len;
+}
+
+static void g722_transform_decode (struct codec *hdl,
+                       int16_t *pcm, uint16_t *pcmlen,
+                       uint8_t *pkt, uint16_t *pktlen) {
+       uint16_t len = *pcmlen;
+       if (*pktlen < *pcmlen) {
+               len = *pktlen;
+       }
+       len = g722_decode (&hdl->state.state_g722_decode, pcm, pkt, len);
+       *pcmlen = *pktlen = len;
+}
+
+struct codec_fun encoder_g722_historically_incorrect = {
+       "audio", "G722", NULL,
+       "HD-G722",
+       g722_init_encode, g722_finish_encode, g722_transform_encode,
+       8000 /*history error*/, 9
+};
+struct codec_fun decoder_g722_historically_incorrect = {
+       "audio", "G722", NULL,
+       "HD-G722",
+       g722_init_decode, g722_finish_decode, g722_transform_decode,
+       8000 /*history error*/, 9
+};
+struct codec_fun encoder_g722 = {
+       "audio", "G722", NULL,
+       "HD-G722",
+       g722_init_encode, g722_finish_encode, g722_transform_encode,
+       16000, 9
+};
+struct codec_fun decoder_g722 = {
+       "audio", "G722", NULL,
+       "HD-G722",
+       g722_init_decode, g722_finish_decode, g722_transform_decode,
+       16000, 9
+};
+#endif
+
+
+
+/********** G.726 DEFINITIONS **********/
+
+
+#ifdef CONFIG_CODEC_G726
+
+
+static void g726_init_encode (struct codec *hdl, uint32_t samplerate) {
+       /* TODO: G726_ENCODING_ULAW... and/or _ALAW? RTP profile? */
+       g726_init (&hdl->state.state_g726_encode, 32000, G726_ENCODING_ULAW, G726_PACKING_LEFT);
+}
+
+static void g726_init_decode (struct codec *hdl, uint32_t samplerate) {
+       /* TODO: G726_ENCODING_ULAW... and/or _ALAW? RTP profile? */
+       g726_init (&hdl->state.state_g726_decode, 32000, G726_ENCODING_ULAW, G726_PACKING_LEFT);
+}
+
+static void g726aal2_init_encode (struct codec *hdl, uint32_t samplerate) {
+       /* TODO: G726_ENCODING_ULAW... and/or _ALAW? RTP profile? */
+       g726_init (&hdl->state.state_g726_encode, 32000, G726_ENCODING_ULAW, G726_PACKING_RIGHT);
+}
+
+static void g726aal2_init_decode (struct codec *hdl, uint32_t samplerate) {
+       /* TODO: G726_ENCODING_ULAW... and/or _ALAW? RTP profile? */
+       g726_init (&hdl->state.state_g726_decode, 32000, G726_ENCODING_ULAW, G726_PACKING_RIGHT);
+}
+
+
+static void g726_finish_encode (struct codec *hdl) {
+       g726_release (&hdl->state.state_g726_encode);
+}
+
+static void g726_finish_decode (struct codec *hdl) {
+       g726_release (&hdl->state.state_g726_decode);
+}
+
+static void g726_transform_encode (struct codec *hdl,
+                       int16_t *pcm, uint16_t *pcmlen,
+                       uint8_t *pkt, uint16_t *pktlen) {
+       uint16_t len = *pcmlen;
+       if (*pktlen < *pcmlen) {
+               len = *pktlen;
+       }
+       len = g726_encode (&hdl->state.state_g726_encode, pkt, pcm, len);
+       *pcmlen = *pktlen = len;
+}
+
+static void g726_transform_decode (struct codec *hdl,
+                       int16_t *pcm, uint16_t *pcmlen,
+                       uint8_t *pkt, uint16_t *pktlen) {
+       uint16_t len = *pcmlen;
+       if (*pktlen < *pcmlen) {
+               len = *pktlen;
+       }
+       len = g726_decode (&hdl->state.state_g726_decode, pcm, pkt, len);
+       *pcmlen = *pktlen = len;
+}
+
+
+
+struct codec_fun encoder_g726 = {
+       "audio", "G726-32", NULL,
+       "DECT",
+       g726_init_encode, g726_finish_encode, g726_transform_encode,
+       8000, 110
+};
+struct codec_fun decoder_g726 = {
+       "audio", "G726-32", NULL,
+       "DECT",
+       g726_init_decode, g726_finish_decode, g726_transform_decode,
+       8000, 110
+};
+
+struct codec_fun encoder_g726aal2 = {
+       "audio", "AAL2-G726-32", NULL,
+       "DECT",
+       g726aal2_init_encode, g726_finish_encode, g726_transform_encode,
+       8000, 111
+};
+struct codec_fun decoder_g726aal2 = {
+       "audio", "AAL2-G726-32", NULL,
+       "DECT",
+       g726aal2_init_decode, g726_finish_decode, g726_transform_decode,
+       8000, 111
+};
+#endif
+
+
+
+/********** SPEEX DEFINITIONS **********/
+
+#if defined (CONFIG_CODEC_SPEEX_NARROWBAND) || defined (CONFIG_CODEC_SPEEX_WIDEBAND) || defined (CONFIG_CODEC_SPEEX_ULTRAWIDEBAND)
+
+void speex_init_encode (struct codec *hdl, uint32_t samplerate) {
+       speex_encoder_init (&hdl->state.state_speex_encode);
+}
+void speex_finish_encode (struct codec *hdl) {
+       speex_encoder_destroy (&hdl->state.state_speex_encode);
+}
+void speex_transform_encode (struct codec *hdl,
+                       uint16_t *pcm, uint16_t *pcmlen,
+                       uint8_t  *pkt, uint16_t *pktlen) {
+       speex_encode (&hdl->state.state_speex_encode, NULL /*TODO*/);
+}
+void speex_init_decode (struct codec *hdl, uint32_t samplerate) {
+       speex_decoder_init (&hdl->state.state_speex_decode);
+}
+void speex_finish_decode (struct codec *hdl) {
+       speex_decoder_destroy (&hdl->state.state_speex_decode);
+}
+void speex_transform_decode (struct codec *hdl, uint16_t *pktlen) {
+       speex_decode (&hdl->state.state_speex_decode, NULL /*TODO*/);
+}
+
+#endif
+
+#ifdef CONFIG_CODEC_SPEEX_NARROWBAND
+struct codec_fun encoder_speex_narrow = {
+       "audio", "speex", "mode=any;vbr=on;cng=on",
+       "SPEEX",
+       speex_init_encode, speex_finish_encode, speex_transform_encode,
+       8000, 126
+};
+struct codec_fun decoder_speex_narrow = {
+       "audio", "speex", "mode=any;vbr=on;cng=on",
+       "SPEEX",
+       speex_init_decode, speex_finish_decode, speex_transform_decode,
+       8000, 126
+};
+#endif
+
+#ifdef CONFIG_CODEC_SPEEX_WIDEBAND
+struct codec_fun encoder_speex_wide = {
+       "audio", "speex", "mode=any;vbr=on;cng=on",
+       "SPEEX",
+       speex_init_encode, speex_finish_encode, speex_transform_encode,
+       16000, 126
+};
+struct codec_fun decoder_speex_wide = {
+       "audio", "speex", "mode=any;vbr=on;cng=on",
+       "SPEEX",
+       speex_init_decode, speex_finish_decode, speex_transform_decode,
+       16000, 126
+};
+#endif
+
+#ifdef CONFIG_CODEC_SPEEX_ULTRAWIDEBAND
+struct codec_fun encoder_speex_ultra = {
+       "audio", "speex", "mode=any;vbr=on;cng=on",
+       "SPEEX",
+       speex_init_encode, speex_finish_encode, speex_transform_encode,
+       32000, 126
+};
+struct codec_fun decoder_speex_ultra = {
+       "audio", "speex", "mode=any;vbr=on;cng=on",
+       "SPEEX",
+       speex_init_decode, speex_finish_decode, speex_transform_decode,
+       32000, 126
+};
+#endif
+
+
+/********** CODEC2 DEFINITIONS **********/
+
+static void codec2_init (struct codec *hdl, uint32_t samplerate) {
+       //TODO// Static allocation
+       codec2_create (&hdl->state.codec2_state);
+}
+
+static void codec2_finish (struct codec *hdl, uint32_t samplerate) {
+       codec2_destroy (&hdl->state.codec2_state);
+}
+
+static void codec2_transform_encode (struct codec *hdl,
+                       int16_t *pcm, uint16_t *pcmlen,
+                       uint8_t *pkt, uint16_t *pktlen) {
+       codec2_encode (hdl, pkt, pcm);
+       *pcmlen = CODEC2_SAMPLES_PER_FRAME;
+       *pktlen = (CODEC2_BITS_PER_FRAME + 7) >> 3;
+}
+
+static void codec2_transform_decode (struct codec *hdl,
+                       int16_t *pcm, uint16_t *pcmlen,
+                       uint8_t *pkt, uint16_t *pktlen) {
+       codec2_decode (hdl, pcm, pkt);
+       *pcmlen = CODEC2_SAMPLES_PER_FRAME;
+       *pktlen = (CODEC2_BITS_PER_FRAME + 7) >> 3;
+}
+
+
+#ifdef CONFIG_CODEC_CODEC2
+struct codec_fun encoder_codec2_1500 = {
+       "audio", "x-codec2", NULL,
+       "CODEC2",
+       codec2_init, codec2_finish, codec2_transform_encode,
+       1500, 122
+};
+struct codec_fun decoder_codec2_1500 = {
+       "audio", "x-codec2", NULL,
+       "CODEC2",
+       codec2_init, codec2_finish, codec2_transform_decode,
+       1500, 122
+};
+struct codec_fun encoder_codec2_2000 = {
+       "audio", "x-codec2", NULL,
+       "CODEC2",
+       codec2_init, codec2_finish, codec2_transform_encode,
+       2000, 123
+};
+struct codec_fun decoder_codec2_2000 = {
+       "audio", "x-codec2", NULL,
+       "CODEC2",
+       codec2_init, codec2_finish, codec2_transform_decode,
+       2000, 123
+};
+struct codec_fun encoder_codec2_2400 = {
+       "audio", "x-codec2", NULL,
+       "CODEC2",
+       codec2_init, codec2_finish, codec2_transform_encode,
+       2400, 124
+};
+struct codec_fun decoder_codec2_2400 = {
+       "audio", "x-codec2", NULL,
+       "CODEC2",
+       codec2_init, codec2_finish, codec2_transform_decode,
+       2400, 124
+};
+struct codec_fun encoder_codec2_2550 = {
+       "audio", "x-codec2", NULL,
+       "CODEC2",
+       codec2_init, codec2_finish, codec2_transform_encode,
+       2550, 125
+};
+struct codec_fun decoder_codec2_2550 = {
+       "audio", "x-codec2", NULL,
+       "CODEC2",
+       codec2_init, codec2_finish, codec2_transform_decode,
+       2550, 125
+};
+#endif
+
+
+/********** TELEPHONE EVENT DEFINITIONS **********/
+
+#ifdef CONFIG_SIP_PHONE
+struct codec_fun encodor_televt = {
+       "audio", "telephone-event", "0-16",
+       "DTMF",
+       NULL, NULL, NULL, /*TODO*/
+       8000, 101
+};
+struct codec_fun decoder_televt = {
+       "audio", "telephone-event", "0-16",
+       "DTMF",
+       NULL, NULL, NULL, /*TODO*/
+       8000, 101
+};
+#endif
+
+/********** REALTIME TEXT DEFINITIONS **********/
+
+#ifdef CONFIG_CODEC_RTT
+struct codec_fun encoder_rtt = {
+       "text", "t140", "cps=1000",
+       "TEXT",
+       NULL, NULL, NULL, /*TODO*/
+       1000, 98
+};
+struct codec_fun decoder_rtt = {
+       "text", "t140", "cps=1000",
+       "TEXT",
+       NULL, NULL, NULL, /*TODO*/
+       1000, 98
+};
+struct codec_fun encoder_rtt_red = {
+       "text", "red", "98/98/98",
+       "TEXT",
+       NULL, NULL, NULL, /*TODO*/
+       1000, 100
+};
+struct codec_fun decoder_rtt_red = {
+       "text", "red", "98/98/98",
+       "TEXT",
+       NULL, NULL, NULL, /*TODO*/
+       1000, 100
+};
+#endif
+
+#ifdef CONFIG_MULTICAST_CODEC_RTT
+struct codec_fun decoder_mcast_rtt = {
+       "text", "t140", "cps=1000",
+       "TEXT",
+       NULL, NULL, NULL, /*TODO*/
+       1000, 98
+};
+struct codec_fun decoder_mcast_rtt_red = {
+       "text", "red", "98/98/98",
+       "TEXT",
+       NULL, NULL, NULL, /*TODO*/
+       1000, 100
+};
+#endif
+
+#ifdef CONFIG_MULTICAST_CODEC_L16
+struct codec_fun decoder_mcast_l16 = {
+       "audio", "L16", NULL,
+       "L16",
+       NULL, NULL, NULL, /*TODO*/
+       0, 99
+};
+#endif
+
+#ifdef CONFIG_MULTICAST_CODEC_VORBIS
+struct codec_fun decoder_mcast_vorbis = {
+       "audio", "vorbis", "configuration=TODO:RFC5215",
+       "VORBIS",
+       NULL, NULL, NULL, /*TODO*/
+       0, 127
+};
+#endif
+
+
+
+/********** SDP SUPPORT THROUGH CODEC LIST STRUCTURES **********/
+
+struct codec_fun *codec_phone_audio_encoders [] = {
+#ifdef CONFIG_CODEC_SPEEX_ULTRAWIDEBAND
+       &encoder_speex_ultra,
+#endif
+#ifdef CONFIG_CODEC_SPEEX_WIDEBAND
+       &encoder_speex_wide,
+#endif
+#ifdef CONFIG_CODEC_G722
+       &encoder_g722,
+       &encoder_g722_historically_incorrect,
+#endif
+#ifdef CONFIG_CODEC_SPEEX_NARROWBAND
+       &encoder_speex_narrow,
+#endif
+#ifdef CONFIG_CODEC_G726
+       &encoder_g726,
+#endif
+#ifdef CONFIG_CODEC_G711
+       &encoder_g711_ulaw,     /* 14 bits */
+       &encoder_g711_alaw,     /* 13 bits */
+#endif
+#ifdef CONFIG_CODEC_CODEC2
+       &encoder_codec2,
+#endif
+#ifdef CONFIG_SIP_PHONE
+       &encoder_televt,
+#endif
+       NULL
+};
+
+struct codec_fun *codec_phone_audio_decoders [] = {
+#ifdef CONFIG_CODEC_SPEEX_ULTRAWIDEBAND
+       &decoder_speex_ultra,
+#endif
+#ifdef CONFIG_CODEC_SPEEX_WIDEBAND
+       &decoder_speex_wide,
+#endif
+#ifdef CONFIG_CODEC_G722
+       &decoder_g722,
+       &decoder_g722_historically_incorrect,
+#endif
+#ifdef CONFIG_CODEC_SPEEX_NARROWBAND
+       &decoder_speex_narrow,
+#endif
+#ifdef CONFIG_CODEC_G726
+       &decoder_g726,
+#endif
+#ifdef CONFIG_CODEC_G711
+       &decoder_g711_ulaw,     /* 14 bits */
+       &decoder_g711_alaw,     /* 13 bits */
+#endif
+#ifdef CONFIG_CODEC_CODEC2
+       &decoder_codec2,
+#endif
+#ifdef CONFIG_SIP_PHONE
+       &decoder_televt,
+#endif
+       NULL
+};
+
+struct codec_fun *codec_phone_video_encoders [] = {
+       NULL
+};
+
+struct codec_fun *codec_phone_video_decoders [] = {
+       NULL
+};
+
+struct codec_fun *codec_phone_text_encoders [] = {
+#ifdef CONFIG_CODEC_RTT
+       &encoder_rtt_red,
+       &encoder_rtt,
+#endif
+       NULL
+};
+
+struct codec_fun *codec_phone_text_decoders [] = {
+#ifdef CONFIG_CODEC_RTT
+       &decoder_rtt_red,
+       &decoder_rtt,
+#endif
+       NULL
+};
+
+struct codec_fun *codec_mcast_audio_decoders [] = {
+#ifdef CONFIG_MULTICAST_CODEC_L16
+       &decoder_mcast_l16,
+#endif
+#ifdef CONFIG_MULTICAST_CODEC_VORBIS
+       &decoder_mcast_vorbis,
+#endif
+#ifdef CONFIG_MULTICAST_CODEC_SPEEX
+       &decoder_mcast_speex,
+#endif
+       NULL
+};
+
+struct codec_fun *codec_mcast_video_decoders [] = {
+       NULL
+};
+
+struct codec_fun *codec_mcast_text_decoders [] = {
+#ifdef CONFIG_CODEC_RTT
+       &encoder_rtt_red,
+       &encoder_rtt,
+#endif
+       NULL
+};
+
index bac3c52..aa9d67c 100644 (file)
@@ -46,6 +46,8 @@
 #include <stdint.h>
 #include <stdbool.h>
 
+#define BOTTOM
+
 #include <config.h>
 #include <bottom/ksz8842.h>
 
index 5103bf6..7743d81 100644 (file)
@@ -1,5 +1,14 @@
 /* Grandstream BT20x driver as an extension to the tic55x driver
  *
+ * Ideally, all this would be is wiring to the generic functions of
+ * chips connected to the DSP.  And of course a lot of register setup
+ * code.  In practice, it is not as sharply divided, sometimes for
+ * reasons of efficiency, sometimes for other reasons.  The ideal is
+ * the best judgement however, and any debate on where code should go
+ * should be based on this ideal plus the realism that too much
+ * indirection will slow down a program that is going to deal with
+ * static hardware anyway.
+ *
  * This file is part of 0cpm Firmerware.
  *
  * 0cpm Firmerware is Copyright (c)2011 Rick van Rein, OpenFortress.
@@ -355,12 +364,78 @@ int16_t codec_encode (codec_t codec, uint16_t *in, uint16_t inlen, uint8_t *out,
        return outlen - inlen;
 }
 
+/* If the chip has not been brought up yet, do it now */
+void tlv320aic2x_setup_chip (void) {
+       // Now, if not done yet, unreset and setup the TLV320AIC20K codec
+       if ((IODATA & (1 << 7)) == 0) {
+               volatile uint16_t ctr;
+               for (ctr=0; ctr < 7 * (600 / 12); ctr++) /* Wait 7x MCLK */ ;
+for (ctr=0; ctr < 7 * (600 / 12); ctr++) /* Wait 7x MCLK */ ;
+for (ctr=0; ctr < 7 * (600 / 12); ctr++) /* Wait 7x MCLK */ ;
+for (ctr=0; ctr < 7 * (600 / 12); ctr++) /* Wait 7x MCLK */ ;
+for (ctr=0; ctr < 7 * (600 / 12); ctr++) /* Wait 7x MCLK */ ;
+               IODATA |= (1 << 7);
+               for (ctr=0; ctr < 132 * (600 / 12); ctr++) /* Wait at least 132 MCLK cycles */ ;
+for (ctr=0; ctr < 132 * (600 / 12); ctr++) /* Wait at least 132 MCLK cycles */ ;
+for (ctr=0; ctr < 132 * (600 / 12); ctr++) /* Wait at least 132 MCLK cycles */ ;
+for (ctr=0; ctr < 132 * (600 / 12); ctr++) /* Wait at least 132 MCLK cycles */ ;
+for (ctr=0; ctr < 132 * (600 / 12); ctr++) /* Wait at least 132 MCLK cycles */ ;
+       }
+}
+
+static int TODO_setratectr = 0;
+
 /* Set a frequency divisor for the intended sample rate */
+//TODO// Not all this code is properly split between generic TLV and specific BT200
 void tlv320aic2x_set_samplerate (uint32_t samplerate) {
+       uint16_t m, n, p;
 int chan = 0;
-#ifndef TODO_FS_ONLY_DURING_SOUND_IO
+       SPCR2_1 |= REGVAL_SPCR2_GRST_NOTRESET | REGVAL_SPCR2_FRST_NOTRESET;
+{ uint32_t ctr = 100; while (ctr-- > 0) ; }
+       SPCR1_1 |= REGVAL_SPCR1_RRST_NOTRESET;
+       SPCR2_1 |= REGVAL_SPCR2_XRST_NOTRESET;
+{ uint32_t ctr = 10000; while (ctr-- > 0) ; }
+       DXR1_1 = DXR1_1;        // Flag down XEMPTY
+tlv320aic2x_setreg (chan, 3, 0x31);    // Channel offline
+{ uint32_t ctr = 1000; while (ctr-- > 0) ; }
+       (void) DRR1_1;          // Flag down RFULL
+       (void) DRR1_1;
+       // Determine the dividors m, n and p
+       n = 1;
+       p = 2;
+       m = ( 30720000 / 16 ) / ( n * p * samplerate );
+// #ifdef TODO_OPTIMISE_PLL_AWAY
+       if (m % 8 == 0) {
+               // Save PLL energy without compromising accuracy
+               p = 8;          // Factor 2 -> 8 so multiplied by 8
+               m >>= 2;        // Divide by 4
+       }
+// #endif
+       while (m > 128) {
+               m >>= 1;
+               n <<= 1;
+       }
+{ uint8_t ip4 [4]; ip4 [0] = m; ip4 [1] = n; ip4 [2] = p; ip4 [3] = ++TODO_setratectr; bottom_show_ip4 (APP_LEVEL_CONNECTING, ip4); }
+bottom_printf ("TLV320AIC20K setting: M=%d, N=%d, P=%d\n", (intptr_t) m, (intptr_t) n, (intptr_t) p);
+       m &= 0x7f;
+       n &= 0x0f;      // Ignore range problems?
+       p &= 0x07;
+       // With the codec up and running, configure the sample rate
+       tlv320aic2x_setreg (chan, 4, 0x00 | (n << 3) | p);
+       tlv320aic2x_setreg (chan, 4, 0x80 | m);
+{ uint32_t ctr = 1000; while (ctr-- > 0) ; }
+// #ifndef TODO_FS_ONLY_DURING_SOUND_IO
+       // SPCR2_1 |= REGVAL_SPCR2_GRST_NOTRESET | REGVAL_SPCR2_FRST_NOTRESET;
+       // SPCR1_1 |= REGVAL_SPCR1_RRST_NOTRESET;
+       // SPCR2_1 |= REGVAL_SPCR2_XRST_NOTRESET;
+       SPCR1_1 &= ~REGVAL_SPCR1_RRST_NOTRESET;
+       SPCR2_1 &= ~REGVAL_SPCR2_XRST_NOTRESET;
+{ uint32_t ctr = 10000; while (ctr-- > 0) ; }
        SPCR2_1 &= ~ ( REGVAL_SPCR2_GRST_NOTRESET | REGVAL_SPCR2_FRST_NOTRESET );
-#endif
+{ uint32_t ctr = 10000; while (ctr-- > 0) ; }
+       // SPCR2_1 &= ~ ( REGVAL_SPCR2_FRST_NOTRESET );
+{ uint32_t ctr = 10000; while (ctr-- > 0) ; }
+// #endif
        samplerate = 12288000 / samplerate;
        if (samplerate >= 4096) {
                samplerate = 4096;
@@ -368,24 +443,24 @@ int chan = 0;
                samplerate = 1;
        }
        SRGR2_1 = REGVAL_SRGR2_CLKSM | REGVAL_SRGR2_FSGM | (samplerate - 1);
-//TODO// tlv320aic2x_setreg (chan, 4, 0x00 | ((6 & 0x0f) << 3) | (2 & 0x07));  // N:=6, P:=2
-//TODO// tlv320aic2x_setreg (chan, 4, 0x80 | (16 & 0x7f));                     // M:=16
-#ifndef TODO_FS_ONLY_DURING_SOUND_IO
-       SPCR2_1 |= REGVAL_SPCR2_GRST_NOTRESET | REGVAL_SPCR2_FRST_NOTRESET;
+// #ifndef TODO_FS_ONLY_DURING_SOUND_IO
+       // SPCR2_1 |= REGVAL_SPCR2_GRST_NOTRESET | REGVAL_SPCR2_FRST_NOTRESET;
+       SPCR2_1 |= REGVAL_SPCR2_GRST_NOTRESET;
+tlv320aic2x_setreg (chan, 3, 0x01);    // Channel online
+{ uint32_t ctr = 1000; while (ctr-- > 0) ; }
+       // tlv320aic2x_setreg (chan, 4, 0x00 | (n << 3) | p);
+       // tlv320aic2x_setreg (chan, 4, 0x80 | m);
+// { uint32_t ctr = 10000; while (ctr-- > 0) ; }
        SPCR1_1 |= REGVAL_SPCR1_RRST_NOTRESET;
        SPCR2_1 |= REGVAL_SPCR2_XRST_NOTRESET;
-#endif
-       // Now, if not done yet, unreset and setup the TLV320AIC20K codec
-       if ((IODATA & (1 << 7)) == 0) {
-               volatile uint8_t ctr;
-               IODATA |= (1 << 7);
-               for (ctr=0; ctr < 132; ctr++) {
-                       asm (" nop");  /* Wait at least 132 MCLK cycles */
-                       asm (" nop");
-                       asm (" nop");
-                       asm (" nop");
-               }
-       }
+{ uint32_t ctr = 1000; while (ctr-- > 0) ; }
+       SPCR2_1 |= REGVAL_SPCR2_FRST_NOTRESET;
+{ uint32_t ctr = 10000; while (ctr-- > 0) ; }
+       DXR1_1 = DXR1_1;        // Flag down XEMPTY
+       (void) DRR1_1;  // Flag down RFULL
+       (void) DRR1_1;
+{ uint32_t ctr = 10000; while (ctr-- > 0) ; }
+// #endif
 }
 
 /* A full frame of 64 samples has been recorded.  See if space exists for
@@ -398,12 +473,12 @@ interrupt void tic55x_dmac0_isr (void) {
                SPCR2_1 &= ~REGVAL_SPCR2_XRST_NOTRESET;
                SPCR2_1 |=  REGVAL_SPCR2_XRST_NOTRESET;
                DMACCR_0 &= ~REGVAL_DMACCR_EN;
-#ifdef TODO_FS_ONLY_DURING_SOUND_IO
-               SPCR1_1 &= ~REGVAL_SPCR1_RRST_NOTRESET;
-               if ((SPCR2_1 & REGVAL_SPCR2_XRST_NOTRESET) == 0) {
-                       SPCR2_1 &= ~ (REGVAL_SPCR2_GRST_NOTRESET | REGVAL_SPCR2_FRST_NOTRESET);
-               }
-#endif
+// #ifdef TODO_FS_ONLY_DURING_SOUND_IO
+               // SPCR1_1 &= ~REGVAL_SPCR1_RRST_NOTRESET;
+               // if ((SPCR2_1 & REGVAL_SPCR2_XRST_NOTRESET) == 0) {
+                       // SPCR2_1 &= ~ (REGVAL_SPCR2_GRST_NOTRESET | REGVAL_SPCR2_FRST_NOTRESET);
+               // }
+// #endif
        }
        if (available_record >= threshold_record) {
                top_can_record (available_record);
@@ -418,12 +493,12 @@ interrupt void tic55x_dmac1_isr (void) {
        uint16_t toplay;
        tic55x_top_has_been_interrupted = true;
        if ((available_play -= 64) < 64) {
-#ifdef TODO_FS_ONLY_DURING_SOUND_IO
-               SPCR2_1 &= ~REGVAL_SPCR2_XRST_NOTRESET;
-               if ((SPCR1_1 & REGVAL_SPCR1_RRST_NOTRESET) == 0) {
-                       SPCR2_1 &= ~ (REGVAL_SPCR2_GRST_NOTRESET | REGVAL_SPCR2_FRST_NOTRESET);
-               }
-#endif
+// #ifdef TODO_FS_ONLY_DURING_SOUND_IO
+               // SPCR2_1 &= ~REGVAL_SPCR2_XRST_NOTRESET;
+               // if ((SPCR1_1 & REGVAL_SPCR1_RRST_NOTRESET) == 0) {
+                       // SPCR2_1 &= ~ (REGVAL_SPCR2_GRST_NOTRESET | REGVAL_SPCR2_FRST_NOTRESET);
+               // }
+// #endif
                DMACCR_1 &= ~REGVAL_DMACCR_EN;
        }
        toplay = BUFSZ - available_play;
@@ -436,16 +511,17 @@ interrupt void tic55x_dmac1_isr (void) {
  * it may be possible to restart DMA channel 1 if it was disabled.
  */
 void dmahint_record (void) {
+return; //TODO// TMP-DISABLE DMAHINTS
        if (! (DMACCR_0 & REGVAL_DMACCR_EN)) {
                if (available_record <= (BUFSZ - 64)) {
                        if (!(DMACCR_0 & REGVAL_DMACCR_EN)) {
                                (void) DRR1_1;  // Flag down RFULL
                                (void) DRR1_1;
                                DMACCR_0 |= REGVAL_DMACCR_EN;
-#ifdef TODO_FS_ONLY_DURING_SOUND_IO
-                               SPCR1_1 |= REGVAL_SPCR1_RRST_NOTRESET;
-                               SPCR2_1 |= REGVAL_SPCR2_GRST_NOTRESET | REGVAL_SPCR2_FRST_NOTRESET;
-#endif
+// #ifdef TODO_FS_ONLY_DURING_SOUND_IO
+                               // SPCR1_1 |= REGVAL_SPCR1_RRST_NOTRESET;
+                               // SPCR2_1 |= REGVAL_SPCR2_GRST_NOTRESET | REGVAL_SPCR2_FRST_NOTRESET;
+// #endif
                        }
 // bottom_printf ("dmahint_record() enabled DMA from %d bytes out of %d\n", (intptr_t) available_record, (intptr_t) BUFSZ);
                }
@@ -456,13 +532,14 @@ void dmahint_record (void) {
  * be possible to restart DMA channel 0 if it was disabled.
  */
 void dmahint_play (void) {
+return; //TODO// TMP-DISABLE DMAHINTS
        if ((available_play >= 64) && ! (DMACCR_1 & REGVAL_DMACCR_EN)) {
                DXR1_1 = DXR1_1;        // Flag down XEMPTY
                DMACCR_1 |= REGVAL_DMACCR_EN;
 bottom_printf ("dmahint_play() started playing DMA\n");
-#ifdef TODO_FS_ONLY_DURING_SOUND_IO
-               SPCR2_1 |= REGVAL_SPCR2_XRST_NOTRESET | REGVAL_SPCR2_GRST_NOTRESET | REGVAL_SPCR2_FRST_NOTRESET;
-#endif
+// #ifdef TODO_FS_ONLY_DURING_SOUND_IO
+               // SPCR2_1 |= REGVAL_SPCR2_XRST_NOTRESET | REGVAL_SPCR2_GRST_NOTRESET | REGVAL_SPCR2_FRST_NOTRESET;
+// #endif
        }
 //TODO:DEBUG// else bottom_printf ("dmahint_play() did not start playing -- available_play = %d\n", (intptr_t) available_play);
 }
@@ -939,7 +1016,8 @@ void main (void) {
        PLLCSR |= REGVAL_PLLCSR_PLLEN;
        PLLDIV1 = REGVAL_PLLDIVx_DxEN | REGVAL_PLLDIVx_PLLDIVx_2;
        PLLDIV2 = REGVAL_PLLDIVx_DxEN | REGVAL_PLLDIVx_PLLDIVx_4;
-       //TODO// PLLDIV3 = REGVAL_PLLDIVx_DxEN | REGVAL_PLLDIVx_PLLDIVx_4;
+       PLLDIV3 = REGVAL_PLLDIVx_DxEN | REGVAL_PLLDIVx_PLLDIVx_4;
+       //TODO// PLLDIV3 = REGVAL_PLLDIVx_DxEN | REGVAL_PLLDIVx_PLLDIVx_2;
        //TODO// PLLCSR |= REGVAL_PLLCSR_PLLEN;
        // Now we have:
        //      CPU clock is 245.76 MHz
@@ -949,7 +1027,9 @@ void main (void) {
        // EMIF settings, see SPRU621F, section 2.12 on "EMIF Registers"
        //
        EGCR1 = 0xff7f;
-       EGCR2 = 0x0009;
+       // EGCR2 = 0x0009; // ECLKOUT2-DIV-4
+// EGCR2 = 0x0001;     //ECLKOUT2-DIV-1//
+EGCR2 = 0x0005;        //ECLKOUT2-DIV-2//
        // EGCR1 = ...;   // (defaults)
        // EGCR2 = ...;   // (defaults)
        // CESCR1 = ...;   // (defaults)
@@ -1005,7 +1085,10 @@ void main (void) {
        SPCR2_1 = 0x0000;       // Disable/reset sample rate generator
        SRGR1_1 = REGVAL_SRGR1_FWID_1 | REGVAL_SRGR1_CLKGDIV_4;
        SRGR2_1 = REGVAL_SRGR2_CLKSM | REGVAL_SRGR2_FSGM | REGVAL_SRGR2_FPER_1535;
-       PCR1 = /*TODO: (1 << REGBIT_PCR_IDLEEN) | */ (1 << REGBIT_PCR_FSXM) /* | (1 << REGBIT_PCR_FSRM) */ | (1 << REGBIT_PCR_CLKXM) /* | (1 << REGBIT_PCR_CLKRM) */ /* receive on falling, xmit on rising edge -- | (1 << REGBIT_PCR_CLKXP) | (1 << REGBIT_PCR_CLKRP) */;
+       //COPIED_BELOW// PCR1 = /*TODO: (1 << REGBIT_PCR_IDLEEN) | */ (1 << REGBIT_PCR_FSXM) /* | (1 << REGBIT_PCR_FSRM) */ | (1 << REGBIT_PCR_CLKXM) /* | (1 << REGBIT_PCR_CLKRM) */ /* receive on falling, xmit on rising edge -- | (1 << REGBIT_PCR_CLKXP) | (1 << REGBIT_PCR_CLKRP) */ ;
+       PCR1 = (1 << REGBIT_PCR_FSXM) | (1 << REGBIT_PCR_CLKXM);
+{ uint32_t ctr = 10000; while (ctr-- > 0) ; }
+// SPCR2_1 |= REGVAL_SPCR2_GRST_NOTRESET | REGVAL_SPCR2_FRST_NOTRESET;
        RCR1_1 = (0 << 8) | (2 << 5);   // Read  1 frame of 16 bits per FS
        XCR1_1 = (0 << 8) | (2 << 5);   // Write 1 frame of 16 bits per FS
        RCR2_1 = 0x0001;                // Read  with 1 clockcycle delay
@@ -1034,7 +1117,7 @@ void main (void) {
        // The total buffer is 1600 samples of 16 bits long.  Each time a
        // frame send finishes, an interrupt checks if there is another
        // frame of 64 samples ready to go; if not, it will disable the
-       // DMA channel.  Hint routines service to restart DMA after that.
+       // DMA channel.  Hint routines serve to restart DMA after that.
        // Conversely, the DMA interrupt handlers can make top-calls to
        // indicate that data is ready for reading or that space is
        // available for writing.
@@ -1043,6 +1126,7 @@ void main (void) {
        //
        DMAGCR = REGVAL_DMAGCR_FREE;
        DMAGTCR = 0x00;         // No timeout support
+#ifdef TODO_DMA_CONFIGUREREN_BIJ_OPSTART
        DMACCR_0 = REGVAL_DMACCR_SRCAMODE_CONST | REGVAL_DMACCR_DSTAMODE_POSTINC | REGVAL_DMACCR_PRIO | REGVAL_DMACCR_SYNC_MCBSP1_REV | REGVAL_DMACCR_REPEAT | REGVAL_DMACCR_AUTOINIT;
        DMACCR_1 = REGVAL_DMACCR_SRCAMODE_POSTINC | REGVAL_DMACCR_DSTAMODE_CONST | REGVAL_DMACCR_PRIO | REGVAL_DMACCR_SYNC_MCBSP1_TEV | REGVAL_DMACCR_REPEAT | REGVAL_DMACCR_AUTOINIT;
        DMACICR_0 = REGVAL_DMACICR_FRAMEIE;
@@ -1070,15 +1154,17 @@ void main (void) {
        DMACFN_0 = 1;
        DMACFN_1 = 1;
 #endif
+#endif
        /* TODO? */
        //
        // Further initiation follows
        //
+       IODIR  |= (1 << 7) | (1 << 1);
+       IODATA  =            (1 << 1);  // Updated below small delay
        for (idx = 0; idx < APP_LEVEL_COUNT; idx++) {
                bt200_level_active [idx] = false;
        }
-       IODIR  |= (1 << 7) | (1 << 1);
-       IODATA |=            (1 << 1);
+       IODATA |= (1 << 7) | (1 << 1);  // See above small delay
        asm (" bclr xf");  // Switch off MESSAGE LED
 { uint16_t ctr = 250; while (ctr > 0) { ctr--; } }     
        bottom_critical_region_begin (); // _disable_interrupts ();
@@ -1086,6 +1172,7 @@ void main (void) {
        tic55x_setup_timers ();
        tic55x_setup_interrupts ();
        ht162x_setup_lcd ();
+       // tlv320aic2x_set_samplerate (8000);
        tlv320aic2x_setup_sound ();
        ksz8842_setup_network ();
        // Enable INT0..INT3
diff --git a/src/driver/tic55x/linker.cmd b/src/driver/tic55x/linker.cmd
new file mode 100644 (file)
index 0000000..5b1ad9f
--- /dev/null
@@ -0,0 +1,32 @@
+-m bin/firmerware.map
+
+MEMORY {
+       ISRMAP (RWIX)   : origin = 0x000100,    length = 0x000300
+       STACK (RWI)     : origin = 0x000400,    length = 0x000c00
+       ROM (RIX)       : origin = 0x001000,    length = 0x006000
+       DARAM (RWIX)    : origin = 0x007000,    length = 0x001000
+       RAM (RWIX)      : origin = 0x800000,    length = 0x080000
+       CONSTRAM (RWIX) : origin = 0x880000,    length = 0x040000
+       BSSRAM (RWIX)   : origin = 0x8c0000,    length = 0x040000
+       VECTOR (RIX)    : origin = 0xffff00,    length = 0x000100
+}
+
+SECTIONS {
+       // .text                        > ROM
+       .text                   > RAM
+       .text_quick             > DARAM
+       .switch                 > ROM
+       .const                  > ROM
+       // .const                       > CONSTRAM
+       .const_codec2_codebook  > CONSTRAM
+       .cinit                  > ROM
+       .interrupts             > VECTOR
+       .isrmap                 > ISRMAP
+       .data                   > RAM
+       .bss                    > BSSRAM
+       .sysmem                 > RAM
+       .stack                  > STACK
+       .sysstack               > STACK
+       .cio                    > DARAM
+}
+
index e437926..a9a7d21 100644 (file)
@@ -114,6 +114,8 @@ static uint16_t nextread_record  = 0;
 void bottom_soundchannel_device (uint8_t chan, sounddev_t dev) {
        if (dev != SOUNDDEV_NONE) {
                tlv320aic2x_setreg (chan, 3, 0x00 | 0x01); /* power up */
+               tlv320aic2x_setreg (chan, 6, 0x00 | 0x00); /* no input or in=out */
+               tlv320aic2x_setreg (chan, 6, 0x80 | 0x00); /* no output */
        }
        switch (dev) {
        case SOUNDDEV_NONE:
@@ -125,7 +127,7 @@ void bottom_soundchannel_device (uint8_t chan, sounddev_t dev) {
                tlv320aic2x_setreg (chan, 3, 0x00 | 0x31); /* power down */
                break;
        case SOUNDDEV_HANDSET:
-               tlv320aic2x_setreg (chan, 6, 0x00 | 0x22);
+               tlv320aic2x_setreg (chan, 6, 0x00 | 0x02);
                tlv320aic2x_setreg (chan, 6, 0x80 | 0x02);
                break;
        case SOUNDDEV_HEADSET:
@@ -180,6 +182,7 @@ void bottom_soundchannel_setvolume (uint8_t chan, uint8_t vol) {
 
 int16_t codec_decode (codec_t codec, uint8_t *in, uint16_t inlen, uint16_t *out, uint16_t outlen);
 int16_t codec_encode (codec_t codec, uint16_t *in, uint16_t inlen, uint8_t *out, uint16_t outlen);
+void tlv320aic2x_setup_chip (void);
 void tlv320aic2x_set_samplerate (uint32_t samplerate);
 
 
@@ -265,7 +268,20 @@ void bottom_codec_play_skip (codec_t codec, uint16_t samples) {
  */
 void tlv320aic2x_setup_sound (void) {
        uint8_t chan;
+#if 0
+       tlv320aic2x_setreg (0, 3, 0x08);                        /* Software reset */
+{ uint32_t ctr;
+       for (ctr=0; ctr < 132 * (600 / 12); ctr++) /* Wait at least 132 MCLK cycles */ ;
+for (ctr=0; ctr < 132 * (600 / 12); ctr++) /* Wait at least 132 MCLK cycles */ ;
+for (ctr=0; ctr < 132 * (600 / 12); ctr++) /* Wait at least 132 MCLK cycles */ ;
+for (ctr=0; ctr < 132 * (600 / 12); ctr++) /* Wait at least 132 MCLK cycles */ ;
+for (ctr=0; ctr < 132 * (600 / 12); ctr++) /* Wait at least 132 MCLK cycles */ ; }
+#endif
+#if 1
+       tlv320aic2x_setup_chip ();
+#else
        tlv320aic2x_set_samplerate (8000);
+#endif
        // Setup the various registers in the TLV320AIC2x
        for (chan = 0; chan < 2; chan++) {
                tlv320aic2x_setreg (chan, 1,        0x49);      /* Continuous 16-bit, 2.35V bias */
@@ -276,8 +292,8 @@ void tlv320aic2x_setup_sound (void) {
                /* Register 3C resets ok to 0x80 | (chip_id << 2) */
                /* Register 3D resets ok to 0xc0: no LCD DAC */
                /* TODO: Skip MNP setup, but samplerate-setup per phone may override */
-tlv320aic2x_setreg (chan, 4, 0x00 | ((6 & 0x0f) << 3) | (2 & 0x07));   // N:=6, P:=2
-tlv320aic2x_setreg (chan, 4, 0x80 | (16 & 0x7f));                      // M:=16
+// tlv320aic2x_setreg (chan, 4, 0x00 | ((6 & 0x0f) << 3) | (2 & 0x07));        // N:=6, P:=2
+// tlv320aic2x_setreg (chan, 4, 0x80 | (16 & 0x7f));                   // M:=16
                tlv320aic2x_setreg (chan, 5, 0x00 | 0x12);      /* ADC gain 27 dB -- ok? */
                bottom_soundchannel_setvolume (chan, 15);       /* DAC gain -24 dB initially */
                tlv320aic2x_setreg (chan, 5, 0x80 | 0x00);      /* No sidetones */
index cb29dfe..148bbcd 100644 (file)
@@ -10,12 +10,14 @@ source "src/function/Kconfig.devel"
 
 config MAINFUNCTION_SIP_PHONE
        bool "SIP phone over IPv6"
+       select CODEC_G711 if !CODEC_CODEC2
+       select CODEC_RTT
+       select CODEC_ZRTP
        help
          This is the customary primary function for the 0cpm firmerware.
           It implements SIP phone functionality over IPv6.  Included are
          facilities to obtain IPv6 connectivity on all networks.
 
-
 config MAINFUNCTION_SIP_DOORBELL
        bool "SIP doorbell over IPv6"
        help
@@ -95,7 +97,8 @@ config FUNCTION_SOUND_PLAYER
          PulseAudio in your software, see http://www.pulseaudio.org/
 
 config FUNCTION_RADIO
-       bool "Internet radio"
+       bool "Internet radio (multicast reception)"
+       depends on UNIMPLEMENTED
        default y
        help
          Enable Internet Radio functions.  This makes the phone pickup
@@ -128,79 +131,9 @@ config FUNCTION_RADIO_CHANNELS
          fixed.  You can specify a high enough upper limit to be
          on the safe side.
 
-config FUNCTION_RADIO_L16
-       bool "Internet radio with RTP/L16"
-       default y
-       depends on FUNCTION_RADIO
-       help
-         Support 16-bit linear audio coding over RTP.  This is a
-         standard audio/video codec intended for uncompressed
-         exchange of audio.  This is a lightweight version of an
-         Internet Radio, that should work well enough on any
-         speaker phone.  To feed the stream, you will probably
-         need a decoder near your multicast router.  You could
-         setup a gstreamer pipeline for this.
-
-         TODO - not implemented yet.
-         
-config FUNCTION_RADIO_VORBIS
-       bool "Internet radio with RTP/Vorbis (read help)"
-       default n
-       depends on FUNCTION_RADIO
-       help
-         Support Vorbis over RTP (not Vorbis in the file format Ogg)
-         as a radio codec.  Any such streams announced through SAP
-         will be offered to the phone user, who can select a favourite
-         station and tune into others as they please.
-
-         Your mileage may vary -- not all phones are powerful enough
-         to decode Vorbis, and in fact some Vorbis streams could be
-         too complex to decode live.  Furthermore, this codec may
-         occupy more program memory than available on your phone.
-         You can safely try it, and enjoy it if/when it works.
-
-         TODO - not implemented yet.
-
-config FUNCTION_RADIO_MP3
-       bool "Internet radio with RTP/MP3 (READ HELP)"
-       default n
-       depends on FUNCTION_RADIO
-       help
-         This toggle does not include MP3 support, it is a placeholder
-         to explain why it is NOT SUPPORTED.
-
-         MP3 is a tightly controlled codec, with patent license costs
-         for every single device.  It is problematic to combine patents
-         and expenses with an open source solution.  Although we would
-         have liked to support MP3, you should probably resolve matters
-         near your multicast router.  More info on MP3 licensing costs
-         can be found on http://mp3licensing.com/royalty/hardware.html
-
-         What you can do is setup a gstreamer pipeline that decodes MP3
-         and re-encodes as RTP/L16, and multicasts that over IPv6.  Note
-         that an MP3 plugin for gstreamer is kindly provided by Fluendo,
-         on http://www.fluendo.com/shop/product/fluendo-mp3-decoder/
-
-config FUNCTION_RADIO_AAC
-       bool "Internet radio with RTP/AAC (READ HELP)"
-       default n
-       depends on FUNCTION_RADIO
-       help
-         This toggle does not include AAC support, it is a placeholder
-         to explain why it is NOT SUPPORTED.
-
-         AAC is a controlled codec, although not as badly as MP3.  To
-         avoid breaking the licenses for the codec, they may only be
-         distributed as source code, which seems too restrictive to be
-         worth the effort of adding it.  (Somewhat open for discussion.)
-
-         What you can do is setup a gstreamer pipeline that decodes AAC
-         and re-encodes as RTP/L16, and multicasts that over IPv6.  Note
-         that a plugin for gstreamer is made available in the "bad"
-         plugins collection for gstreamer, in a module named faad.
-
 config FUNCTION_NETCONSOLE
        bool "LAN-based console"
+       depends on !MAINFUNCTION_DEVEL_GPIO && !MAINFUNCTION_DEVEL_TIMER && !MAINFUNCTION_DEVEL_KEYBOARD
        default y if DEVEL=n
        help
          Direct console traffic for the main application to the network.
@@ -221,6 +154,7 @@ config FUNCTION_NETCONSOLE
 
 config FUNCTION_FIRMWARE_UPGRADES
        bool "Support firmware upgrades"
+       depends on !MAINFUNCTION_DEVEL_GPIO && !MAINFUNCTION_DEVEL_TIMER && !MAINFUNCTION_DEVEL_KEYBOARD && !MAINFUNCTION_DEVEL_SOUND
        default y if MAINFUNCTION_BOOTLOADER=y
        help
          It is possible, though not strictly required, to support
@@ -252,4 +186,6 @@ config FUNCTION_FIRMWARE_UPGRADES_BOOTLOADER
 
          TODO: a polling TFTP client may in fact be better?
 
+source "src/codec/Kconfig"
+
 endmenu
index 3f0416d..fa4437d 100644 (file)
 
 # Function-dependent construction of top-objs list
 
-objs-top-$(CONFIG_FUNCTION_NETCONSOLE) += src/net/llconly.o src/function/netconsole.o
+objs-top-$(CONFIG_FUNCTION_NETCONSOLE) += src/function/netconsole.o
+objs-top-$(CONFIG_MAINFUNCTION_NETCONSOLE) += src/net/llconly.o
+objs-top-$(CONFIG_MAINFUNCTION_DEVEL_NETWORK) += src/net/llconly.o
+objs-top-$(CONFIG_MAINFUNCTION_DEVEL_SOUND) += src/net/llconly.o
 
 #
 # Actual targets and their constituent object files
 #
-objs-top-$(CONFIG_MAINFUNCTION_SIP_PHONE) += src/function/sip6phone/topmain.o bin/top-kernel.o bin/top-net.o bin/top-phone.o
+objs-top-$(CONFIG_MAINFUNCTION_SIP_PHONE) += src/function/sip6phone/topmain.o bin/top-kernel.o bin/top-net.o bin/top-phone.o bin/top-codec.o
 
 # objs-top-$(CONFIG_MAINFUNCTION_BOOTLOADER) += src/function/bootload.o bin/top-kernel.o bin/top-simplenet.o function
 
index c080f7a..174431a 100644 (file)
@@ -135,7 +135,10 @@ uint8_t sinewaveL8 [8] = {
 
 uint16_t sinewaveL16 [8] = {
        // 0x0000, 0x5a82, 0x7fff, 0x5a82, 0x0000, 0xa57e, 0x8001, 0xa57e
-       4096+0x0000, 4096+0x05a8, 4096+0x07ff, 4096+0x05a8, 4096+0x0000, 4096+0xfa57, 4096+0xf801, 409+0xfa57
+       // 0x0000 + 32768, 0x5a82 + 32768, 0x7fff + 32768, 0x5a82 + 32768, 0x0000 + 32768, 0xa57e - 32768, 0x8001 - 32768, 0xa57e - 32768
+       0x0000, 0x2d41, 0x3fff, 0x2d41, 0x0000, 0xdabf, 0xc000, 0xdabf
+       // 0x0000, 0x002d, 0x0040, 0x002d, 0x0000, 0xffda, 0xffc0, 0xffda
+       // 4096+0x0000, 4096+0x05a8, 4096+0x07ff, 4096+0x05a8, 4096+0x0000, 4096+0xfa57, 4096+0xf801, 4096+0xfa57
 };
 
 void top_main_sine_1khz (void) {
@@ -159,6 +162,7 @@ uint8_t l16ctr = 1;
                }
 #if 1
 if (SPCR2_1 & REGVAL_SPCR2_XRDY) { DXR1_1 = sinewaveL16 [l16ctr++]; if (l16ctr == 8) { l16ctr = 0; } }
+{ uint16_t _ = DRR1_1; }
 #else
                while (newplayed >= 8) {
                        bottom_codec_play (0, CODEC_L8, sinewaveL8, 8, 8);
index 55eb8a2..18181dc 100644 (file)
@@ -39,6 +39,15 @@ timing_t top_timer_expiration (timing_t timeout) {
        return timeout;
 }
 
+void irqtimer_start   (irqtimer_t *tmr, timing_t delay, irq_handler_t hdl, priority_t prio) {
+}
+
+void irqtimer_restart (irqtimer_t *tmr, timing_t intval) {
+}
+
+void irqtimer_stop    (irqtimer_t *tmr) {
+}
+
 void top_hook_update (bool offhook) {
        /* Keep the linker happy */ ;
 }
index a459950..e5c4e7d 100644 (file)
@@ -41,6 +41,15 @@ void top_hook_update (bool offhook) {
        /* Keep the linker happy */ ;
 }
 
+void irqtimer_start   (irqtimer_t *tmr, timing_t delay, irq_handler_t hdl, priority_t prio) {
+}
+
+void irqtimer_restart (irqtimer_t *tmr, timing_t intval) {
+}
+
+void irqtimer_stop    (irqtimer_t *tmr) {
+}
+
 void top_button_press (buttonclass_t bcl, buttoncode_t cde) {
        /* Keep the linker happy */ ;
 }
index 1f0a484..360e550 100644 (file)
@@ -25,6 +25,9 @@
 #include <0cpm/app.h>
 
 
+/** \ingroup kernel */
+
+
 /* Applications are the parties that scream for resources.
  * They may wish or demand resources.  If they ask for it at
  * the same strength, then the application with the highest
index 8f10644..e6c16cf 100644 (file)
 #include <0cpm/cons.h>
 
 
-/* Round-robin queues with interrupts and closures, ordered by priority.
+/** \defgroup kernel
+ * The kernel is the basic housekeeping unit of the 0cpm Firmerware.
+ * It constitutes a main loop that switches between short tasks,
+ * and makes bottom functions such as timers, interrupts and the
+ * network interface generally available.
+ */
+
+/** \ingroup kernel
+ * The CPU part of the kernel focusses the attention of the phone.
+ * Tasks are placed in round-robin lists, at different priority
+ * levels, and are scheduled in a co-operative multitasking manner.
+ * There is no pre-emption, which results in childishly simple
+ * programming that has no need for locks -- not even for getting
+ * into a deadlocked state!
+ */
+
+
+/** Round-robin queue with interrupts, ordered by priority.
  * To be fair, the elements pointed at have already been completed
  * and are awaiting roll-over or removal.
  * TODO: Make the array contents volatile
  */
 irq_t     *irqs     [CPU_PRIO_COUNT] = { NULL, NULL, NULL, NULL };
+
+/** Round-robin queue with closures, ordered by priority.
+ * To be fair, the elements pointed at have already been completed
+ * and are awaiting roll-over or removal.
+ * TODO: Make the array contents volatile
+ */
 closure_t *closures [CPU_PRIO_COUNT] = { NULL, NULL, NULL, NULL };
 #if CPU_PRIO_COUNT != 4
 //TODO// #  error "Update the number of NULL value initialisations above"
 #endif
 
-/* The current priority is an optimisation; it tells what the highest
+/** The current priority is an optimisation; it tells what the highest
  * active priority is, so as to avoid too much searching.  The priority
  * starts at the low value CPU_PRIO_ZERO at which nothing runs; as soon
  * as anything is scheduled, the value is increased to signal work is to
@@ -50,7 +73,7 @@ closure_t *closures [CPU_PRIO_COUNT] = { NULL, NULL, NULL, NULL };
 volatile priority_t cur_prio = CPU_PRIO_ZERO;
 
 
-/* Add an IRQ to the round-robin task queue to be scheduled.
+/** Add an IRQ to the round-robin task queue to be scheduled.
  * This routine must always be called with interrupts inactive;
  * either as part of an interrupt routine, or when called in the
  * course of the main program, from within a critical region.
@@ -72,7 +95,7 @@ void irq_fire (irq_t *irq) {
 }
 
 
-/* Hop jobs until there is nothing left to do.  This is actually the main
+/** Hop jobs until there is nothing left to do.  This is actually the main
  * procedure for the scheduler.  If it ends, then all the work has been
  * enqueued somewhere, and is awaiting a response.  In other words, it
  * is then time to sleep.  This assumes that no task or IRQ will ever
index 84ce1bd..58adfc3 100644 (file)
 #include <0cpm/led.h>
 
 
-/* Refer to the top handler state storage structures for LED information.
+/** \ingroup kernel
+ * LED handling in the kernel takes care of the visualisation
+ * of state on the LEDs of a phone.  These may either show a
+ * constant colour or flash between two colours.
+ */
+
+
+/** The state of a LED; its current and alternate colour, and flashing.
+ * Refer to the top handler state storage structures for LED information.
  * The size of the array is LED_IDX_COUNT as derived above.  The embedded
  * timer is used to make the LED flash in its own pace.  The timer is
  * started from the main program, and the corresponding interrupt is
@@ -42,10 +50,11 @@ struct led_state {
         led_flashtime_t led_flashtime;
 };
 
+/** A static structure holding all LED state. */
 static struct led_state leds [LED_IDX_COUNT];
 
 
-/* LED interrupts will change the state of a LED.
+/** LED interrupts will change the state of a LED.
  */
 static bool led_irq (irq_t *irq) {
        struct led_state *this = (struct led_state *) irq;
@@ -58,7 +67,7 @@ static bool led_irq (irq_t *irq) {
 
 
 
-/* Set the state of a LED.  If the current colour matches the initial colour of a
+/** Set the state of a LED.  If the current colour matches the initial colour of a
  * flashing LED, that a flash operation is immediately performed.
  */
 void led_set (led_idx_t ledidx, led_colour_t col, led_flashtime_t ft) {
@@ -79,13 +88,13 @@ void led_set (led_idx_t ledidx, led_colour_t col, led_flashtime_t ft) {
 }
 
 
-/* Get the colour currently shown on the LED.
+/** Get the colour currently shown on the LED.
  */
 led_colour_t led_getcolour (led_idx_t ledidx) {
        return LED_FLASHING_CURRENT (leds [ledidx].led_colour);
 }
 
-/* Get the flashing time for a given LED.
+/** Get the flashing time for a given LED.
  */
 led_flashtime_t led_getflashtime (led_idx_t ledidx) {
        return leds [ledidx].led_flashtime;
index e2a35f0..6d4a1df 100644 (file)
 #include <0cpm/cons.h>
 
 
+/** \ingroup kernel */
+
+
 /* TODO: Current return function from netinput
  */
 typedef void *retfn (uint8_t *pout, intptr_t *mem);
 
 
-/* The can_recv and can_send flags store whether
- * the network is in a state to permit either of
- * these operations on the network interface.
+/** The can_send flag stores whether
+ * the network is in a state to permit sending
+ * on the network interface.
  */
 static bool can_send = false;
+
+/** The can_recv flag stores whether
+ * the network is in a state to permit receiving
+ * over the network interface.
+ */
 static bool can_recv = false;
 
 
@@ -66,7 +74,7 @@ static irq_t send_irq = { network_send_handler, NULL, CPU_PRIO_UNKNOWN };
 
 
 
-/* This upcall is used to report that the network
+/** This upcall is used to report that the network
  * has new data available.  The bottom half will
  * call this for the first packet to arrive after
  * having failed an attempt to read input.
@@ -82,7 +90,7 @@ void top_network_can_recv (void) {
        }
 }
 
-/* This upcall is used to report that the network
+/** This upcall is used to report that the network
  * is certain to accept a full-size network packet.
  * It is called by the bottom half after having
  * failed an attempt to send output.
@@ -97,7 +105,7 @@ void top_network_can_send (void) {
 }
 
 
-/* This upcall is made to report that the network
+/** This upcall is made to report that the network
  * has gone offline.  This may be detected at the
  * hardware level, as a result of unplugging the
  * cable and/or loosing sync.
@@ -110,7 +118,7 @@ void top_network_offline (void) {
 }
 
 
-/* This upcall is made to report that the network
+/** This upcall is made to report that the network
  * has come online.  This is also called when the
  * network card has been initialised properly.
  */
@@ -174,7 +182,7 @@ if (irq)
 }
 
 
-/* As the processor now has time for it, process
+/** As the processor now has time for it, process
  * the sending of network packets.
  */
 static void network_send_handler (irq_t *irq) {
index 5e05881..a134532 100644 (file)
@@ -25,6 +25,9 @@
 #include <0cpm/resource.h>
 
 
+/** \ingroup kernel */
+
+
 /* Refresh a resource, meaning if it has any output aspects, ask it to
  * refresh that output.  This is used if re-ordering resources may have
  * caused another party to be assigned control over the resource.
index bd04387..db439d6 100644 (file)
 #include <0cpm/cons.h>
 
 
-
-/* Timers are deferred actions.  Some of those actions may be of a
+/** \ingroup kernel
+ * The timer function of the kernel helps to (re)schedule tasks
+ * that have been inactive for a while.
+ *
+ * Timers are deferred actions.  Some of those actions may be of a
  * repetitive nature (at fixed intervals) and others may be oneshots.
  *
  * The actions triggered after the specified time has passed are
@@ -72,7 +75,7 @@
  */
 
 
-/* The queue for waiting timer events.  There is no queue for ready
+/** The queue for waiting timer events.  There is no queue for ready
  * timer events; those are sent to general IRQ queues.
  */
 static irqtimer_t *irqtimer_wait_queue = NULL;
@@ -81,7 +84,7 @@ static bool irqtimer_interrupt_blocked = true;
 static bool irqtimer_interrupt_occurred = false;
 
 
-/* Process a timer interrupt.
+/** Process a timer interrupt.
  */
 timing_t top_timer_expiration (timing_t exptime) {
        if (irqtimer_interrupt_blocked) {
@@ -101,7 +104,7 @@ timing_t top_timer_expiration (timing_t exptime) {
 }
 
 
-/* Enable or disable a timer interrupt.  This does not actually
+/** Enable or disable a timer interrupt.  This does not actually
  * stop the hardware interrupt from occurring, but it does stop
  * the queue from being observed or modified in the interrupt
  * handler routine.  This facility is useful to allow modifying
@@ -128,7 +131,7 @@ static void irqtimer_enable (void) {
 }
 
 
-/* Enqueue an initialised timer structure to the timer wait queue.
+/** Enqueue an initialised timer structure to the timer wait queue.
  */
 static void irqtimer_enqueue (irqtimer_t *tmr) {
        irqtimer_t **here;
@@ -145,7 +148,7 @@ static void irqtimer_enqueue (irqtimer_t *tmr) {
        irqtimer_enable ();
 }
 
-/* Setup a new timer by enqueueing its structure in the timer list.
+/** Setup a new timer by enqueueing its structure in the timer list.
  */
 void irqtimer_start (irqtimer_t *tmr, timing_t delay, irq_handler_t hdl, priority_t prio) {
        tmr->tmr_irq.irq_next = NULL;
@@ -161,7 +164,7 @@ void irqtimer_start (irqtimer_t *tmr, timing_t delay, irq_handler_t hdl, priorit
 }
 
 
-/* Continue a repeating timer by adding the interval delay to the
+/** Continue a repeating timer by adding the interval delay to the
  * last expiry time.  If more than the timer interval has passed
  * since the last timer expiration, the timer will fire immediately.
  */
@@ -171,7 +174,7 @@ void irqtimer_restart (irqtimer_t *tmr, timing_t intval) {
 }
 
 
-/* Prematurely remove a timer from the timer queue.  If it is not
+/** Prematurely remove a timer from the timer queue.  If it is not
  * there, ignore that fact silently.  Note that there may still
  * be interrupts that were caused by the timer that is now being
  * stopped.  That may actually revive an interval timer.  TODO...
index 2551d77..90f6027 100644 (file)
@@ -369,8 +369,8 @@ netin_LLC1_sel:
                        return (intptr_t) netllc_tftp;
                }
                break;
-#endif // NETCONSOLE
-#ifdef CONFIG_FUNCTION_FIRMWARE_UPGRADES
+#endif // FIRMWARE_UPGRADES
+#ifdef CONFIG_FUNCTION_NETCONSOLE
        case 0x7f:
                if (mem [MEM_LLC_DSAP] == 20) {
                        return (intptr_t) netllc_console_sabme;
@@ -386,7 +386,7 @@ netin_LLC1_sel:
                        return (intptr_t) netllc_console_frmr;
                }
                break;
-#endif // FIRMWARE_UPGRADES
+#endif // NETCONSOLE
        default:
                break;
        }
@@ -401,8 +401,8 @@ netin_LLC2_sel:
                return (intptr_t) netllc_console_receiverfeedback;
        }
        return (intptr_t) NULL;
-}
 #endif // NETCONSOLE
 
 #endif // NETCONSOLE || FIRMWARE_UPGRADES
 
+}
index 9225873..3b116e6 100644 (file)
@@ -264,13 +264,13 @@ bool sipdia_invite (dialog_t *dia, textptr_t *branch) {
        msg = (char *) netsend_udp6 (wbuf.data, mem);
        //
        // StartLine: INVITE to_uri SIP/2.0
-{textptr_t to_uri = { "sip:2020*880@welcome.0cpm.nl:5060", 33 };       //FIXED//
+{textptr_t to_uri = { "sip:7425*880@welcome.0cpm.nl:5060", 33 };       //FIXED//
        msg = sipgen_request (msg, &invite_m, &to_uri, branch);
 }
        //
        // Further headers
        msg = sipgen_from (msg, dia);
-{textptr_t callee = { "2020*880", 8 }; //FIXED//
+{textptr_t callee = { "7425*880", 8 }; //FIXED//
        msg = sipgen_to (msg, &callee, dia);
 }
 msg = sipgen_contact (msg, dia);       //TODO// Only needed for SIPproxy64?
@@ -323,13 +323,13 @@ bool sipdia_cancel (dialog_t *dia, textptr_t *branch) {
        msg = (char *) netsend_udp6 (wbuf.data, mem);
        //
        // StartLine: CANCEL to_uri SIP/2.0
-{textptr_t to_uri = { "sip:2020*880@welcome.0cpm.nl:5060", 33 };       //FIXED//
+{textptr_t to_uri = { "sip:7425*880@welcome.0cpm.nl:5060", 33 };       //FIXED//
        msg = sipgen_request (msg, &cancel_m, &to_uri, branch);
 }
        //
        // Further headers 
        msg = sipgen_from (msg, dia);
-{textptr_t callee = { "2020*880", 8 }; //FIXED//
+{textptr_t callee = { "7425*880", 8 }; //FIXED//
        msg = sipgen_to (msg, &callee, dia);
 }
 msg = sipgen_contact (msg, dia);       //TODO// Only needed for SIPproxy64?
@@ -386,13 +386,13 @@ bool sipdia_bye (dialog_t *dia, textptr_t *branch) {
        mem [MEM_UDP6_SRC_PORT] = 5060;
        msg = (char *) netsend_udp6 (wbuf.data, mem);
        // StartLine: BYE to_uri SIP/2.0
-{textptr_t to_uri = { "sip:2020*880@welcome.0cpm.nl:5060", 33 };       //FIXED//
+{textptr_t to_uri = { "sip:7425*880@welcome.0cpm.nl:5060", 33 };       //FIXED//
        msg = sipgen_request (msg, &bye_m, &to_uri, branch);
 }
        //
        // Further headers 
        msg = sipgen_from (msg, dia);
-{textptr_t callee = { "2020*880", 8 }; //FIXED//
+{textptr_t callee = { "7425*880", 8 }; //FIXED//
        msg = sipgen_to (msg, &callee, dia);
 }
 msg = sipgen_contact (msg, dia);       //TODO// Only needed for SIPproxy64?
@@ -449,13 +449,13 @@ bottom_printf ("Constructing ACK\n");
        msg = (char *) netsend_udp6 (wbuf.data, mem);
        //
        // StartLine: ACK to_uri SIP/2.0
-{textptr_t to_uri = { "sip:2020*880@welcome.0cpm.nl", 28 };    //FIXED//
+{textptr_t to_uri = { "sip:7425*880@welcome.0cpm.nl", 28 };    //FIXED//
        msg = sipgen_request (msg, &ack_m, &to_uri, branch);
 }
        //
        // Further headers
        msg = sipgen_from (msg, dia);
-{textptr_t callee = { "2020*880", 8 }; //FIXED//
+{textptr_t callee = { "7425*880", 8 }; //FIXED//
        msg = sipgen_to (msg, &callee, dia);
 }
        msg = sipgen_cseq (msg, &ack_m, dia->cseqnr);
index 31d05ac..2ee9ffa 100644 (file)
@@ -1,4 +1,10 @@
 # Grandstream phone models
+#
+# When adding a new model, please include it also in the Kconfig.platform
+# listing for automatic selection of the SoC type.  That is the kind of
+# thing that other users can feel rather uncertain about.  Supposedly,
+# not everyone opens devices before starting to use them ;-)
+#
 
 choice
        prompt "2. Grandstream phone models"
@@ -19,20 +25,66 @@ config TARGET_GRANDSTREAM_BT10x
 
 config TARGET_GRANDSTREAM_BT20x
        bool "Budgetone 200, 201"
-       select PLATFORM_TIC54x
+       select PLATFORM_TIC55x
        help
          Budgetone is the entry-level speaker phone from Grandstream.
          The older models were numbered 10x, the newer ones are 20x.
          These newer models have one or two 100 Mbps ethernet jacks.
 
+         Note that the models with KSZ8842 network chips are supported,
+         but older models with RTL8019 currently are not.
+
          They look like simple phones, with no line selection facilities
          beyond a simple flash button.  They do however have buttons for
          conferences and call transfer and hold.
 
-config TARGET_GRANDSTREAM_GXP20xx
-       bool "GXP 2000, 2010, 2020"
+config TARGET_GRANDSTREAM_GXP1200
+       bool "Grandstream GXP 1200"
+       depends on UNIMPLEMENTED
+       select PLATFORM_TIC55x
+       select TARGET_GRANDSTREAM_GXP
+       help
+         These platforms are very similar to Budgetone 200 devices.
+         The differences are different wiring and an undocumented
+         graphical LCD.  The displays offer superior interfacing
+         compared to the Budgetone's 7-segment displays, so expect
+         some forthcoming work in this area.
+
+config TARGET_GRANDSTREAM_GXP2020
+       bool "Grandstream GXP 2020"
        depends on UNIMPLEMENTED
        select PLATFORM_TIC55x
+       select TARGET_GRANDSTREAM_GXP
+       help
+         Note that the models with KSZ8842 network chips are supported,
+         but older models with RTL8019 currently are not.  This is at
+         least a concern for (some) GXP2020 models.
+
+config TARGET_GRANDSTREAM_GXP_OTHER
+       bool "Grandstream GXP series"
+       help
+         The GXP series from Grandstream is very consistent in its
+         architecture.  If you are not afraid of a bit of probing
+         with an ohm-meter and minor editing of this code, then you
+         are probably capable of adding your favourite GXP phone to
+         this software.  And of course we will gladly integrate your
+         changes, so you don't have to keep your own code forked.
+
+config TARGET_GRANDSTREAM_GXV
+       bool "Grandstream GXV series (video phones)"
+       select PLATFORM_TIC55X
+       help
+         These platforms are more advancaed than Grandstream's GXP
+         platforms, and include various new hardware components that
+         are not currently supported:
+
+          * TIC6x DSP processor
+          * colour display
+          * camera
+          * touch screen (on some models)
+
+         Support for these models is not planned at this time.
 
 endchoice
 
+
index def213e..6b598f7 100644 (file)
@@ -7,13 +7,15 @@ config PLATFORM_LOCAL
        bool "Local POSIX system"
        depends on TARGET_POSIX
 
+# Include all manufacturers / models in the "depends on" clause, connected with ||
 config PLATFORM_TIC54x
        bool "tic54x"
        depends on TARGET_GRANDSTREAM_BT10x
 
+# Include all manufacturers / models in the "depends on" clause, connected with ||
 config PLATFORM_TIC55x
        bool "tic55x (READ HELP)"
-       depends on TARGET_GRANDSTREAM_BT20x || TARGET_GRANDSTREAM_GXP20xx
+       depends on TARGET_GRANDSTREAM_BT20x || TARGET_GRANDSTREAM_GXP1200 || TARGET_GRANDSTREAM_GXP2020
        help
          **Please be careful**
          The TIC55x platform is not supported by gcc or lvmm compilers.
@@ -24,6 +26,7 @@ config PLATFORM_TIC55x
          the incompatibility problem between TI's toolchain license and
          the open source license of the 0cpm firmerware.
 
+# Include all manufacturers in the "depends on" clause, connected with ||
 config PLATFORM_BLACKFIN
        bool "Analog Devices' Blackfin"
        depends on TARGET_IMAGINARY