This is an ugly hack job I made last night and it barely works.  It
does two things:

1)  Sometimes I want to search for a config so I have to load
    menuconfig, then search for the config entry, then exit.  With
    this script I simply run:

        ./scripts/kconfig/kconfig search COMEDI

2)  I quite often try to enable something by doing:

        echo CONFIG_FOO=y >> .config
        make oldconfig
        grep CONFIG_FOO .config

    The grep is to see if the setting worked.  Now I can do:

        ./scripts/kconfig/kconfig set CONFIG_FOO=y

Parsing dependencies barely works, but that's just a matter of writing
some more code in expr_parse().

The main questions I have at this point are:

1)  If I have a symbol pointer, is it possible to get a help text from
    that?

2)  For some reason, when I do sym_set_tristate_value() it doesn't
    actually set anything until I write the config file so I have to do:

                if (sym_set_tristate_value(sym, newval)) {
                        /* FIXME: if I don't write it doesn't save */
                        conf_write(NULL);
                        return 1;
                }

    It makes the output really messy.

Signed-off-by: Dan Carpenter <[email protected]>

diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile
index d9b1fef..ae338a5 100644
--- a/scripts/kconfig/Makefile
+++ b/scripts/kconfig/Makefile
@@ -33,6 +33,9 @@ config: $(obj)/conf
 nconfig: $(obj)/nconf
        $< $(silent) $(Kconfig)
 
+lconfig: $(obj)/lconf
+       $< $(silent) $(Kconfig)
+
 silentoldconfig: $(obj)/conf
        $(Q)mkdir -p include/config include/generated
        $< $(silent) --$@ $(Kconfig)
@@ -169,12 +172,13 @@ lxdialog += lxdialog/textbox.o lxdialog/yesno.o 
lxdialog/menubox.o
 conf-objs      := conf.o  zconf.tab.o
 mconf-objs     := mconf.o zconf.tab.o $(lxdialog)
 nconf-objs     := nconf.o zconf.tab.o nconf.gui.o
+lconf-objs     := lconf.o zconf.tab.o
 kxgettext-objs := kxgettext.o zconf.tab.o
 qconf-cxxobjs  := qconf.o
 qconf-objs     := zconf.tab.o
 gconf-objs     := gconf.o zconf.tab.o
 
-hostprogs-y := conf nconf mconf kxgettext qconf gconf
+hostprogs-y := conf nconf mconf kxgettext qconf gconf lconf
 
 clean-files    := qconf.moc .tmp_qtcheck .tmp_gtkcheck
 clean-files    += zconf.tab.c zconf.lex.c zconf.hash.c gconf.glade.h
diff --git a/scripts/kconfig/kconfig b/scripts/kconfig/kconfig
new file mode 100755
index 0000000..beab8fc
--- /dev/null
+++ b/scripts/kconfig/kconfig
@@ -0,0 +1,33 @@
+#!/bin/sh
+
+usage() {
+       echo "kconfig [search|set] string"
+       exit 1;
+}
+
+if [ "$1" = "" ] ; then
+       usage
+fi
+
+if [ "$1" = "search" ] ; then
+
+       search=$2
+       NCONFIG_MODE=kconfig_search SEARCH=${search} make lconfig
+
+elif [ "$1" = "set" ] ; then
+
+       config=$2
+       setting=$3
+
+       if [ $config = "" ] ; then
+               echo "nothing to set"
+               exit 1
+       fi
+
+       NCONFIG_MODE=kconfig_set CONFIG=${config} SETTING=${setting} make 
lconfig
+
+else
+       usage
+fi
+
+
diff --git a/scripts/kconfig/lconf.c b/scripts/kconfig/lconf.c
new file mode 100644
index 0000000..aa8551e
--- /dev/null
+++ b/scripts/kconfig/lconf.c
@@ -0,0 +1,314 @@
+/*
+ * Copyright (C) 2015 Oracle
+ * Released under the terms of the GNU GPL v2.0.
+ *
+ */
+#define _GNU_SOURCE
+#include <string.h>
+#include <stdlib.h>
+
+#include "lkc.h"
+#include "nconf.h"
+#include <ctype.h>
+
+static int indent;
+static char line[128];
+
+static int get_depends(struct symbol *sym);
+
+static void strip(char *str)
+{
+       char *p = str;
+       int l;
+
+       while ((isspace(*p)))
+               p++;
+       l = strlen(p);
+       if (p != str)
+               memmove(str, p, l + 1);
+       if (!l)
+               return;
+       p = str + l - 1;
+       while ((isspace(*p)))
+               *p-- = 0;
+}
+
+static void xfgets(char *str, int size, FILE *in)
+{
+       if (fgets(str, size, in) == NULL)
+               fprintf(stderr, "\nError in reading or end of file.\n");
+}
+
+static int conf_askvalue(struct symbol *sym, const char *def)
+{
+       enum symbol_type type = sym_get_type(sym);
+
+       if (!sym_has_value(sym))
+               printf(_("(NEW) "));
+
+       line[0] = '\n';
+       line[1] = 0;
+
+       if (!sym_is_changable(sym)) {
+               printf("%s\n", def);
+               line[0] = '\n';
+               line[1] = 0;
+               return 0;
+       }
+
+       fflush(stdout);
+       xfgets(line, 128, stdin);
+
+       switch (type) {
+       case S_INT:
+       case S_HEX:
+       case S_STRING:
+               printf("%s\n", def);
+               return 1;
+       default:
+               ;
+       }
+       printf("%s", line);
+       return 1;
+}
+
+static struct property *get_symbol_prop(struct symbol *sym)
+{
+       struct property *prop = NULL;
+
+       for_all_properties(sym, prop, P_SYMBOL)
+               break;
+       return prop;
+}
+
+static int conf_sym(struct symbol *sym)
+{
+       tristate oldval, newval;
+       struct property *prop;
+
+       while (1) {
+               if (sym->name)
+                       printf("%s: ", sym->name);
+               for_all_prompts(sym, prop)
+                       printf("%*s%s ", indent - 1, "",  _(prop->text));
+               putchar('[');
+               oldval = sym_get_tristate_value(sym);
+               switch (oldval) {
+               case no:
+                       putchar('N');
+                       break;
+               case mod:
+                       putchar('M');
+                       break;
+               case yes:
+                       putchar('Y');
+                       break;
+               }
+               if (oldval != no && sym_tristate_within_range(sym, no))
+                       printf("/n");
+               if (oldval != mod && sym_tristate_within_range(sym, mod))
+                       printf("/m");
+               if (oldval != yes && sym_tristate_within_range(sym, yes))
+                       printf("/y");
+               /* FIXME: I don't know how to get the help text from the sym */
+               printf("] ");
+               if (!conf_askvalue(sym, sym_get_string_value(sym)))
+                       return 0;
+               strip(line);
+
+               switch (line[0]) {
+               case 'n':
+               case 'N':
+                       newval = no;
+                       if (!line[1] || !strcmp(&line[1], "o"))
+                               break;
+                       continue;
+               case 'm':
+               case 'M':
+                       newval = mod;
+                       if (!line[1])
+                               break;
+                       continue;
+               case 'y':
+               case 'Y':
+                       newval = yes;
+                       if (!line[1] || !strcmp(&line[1], "es"))
+                               break;
+                       continue;
+               case 0:
+                       newval = oldval;
+                       break;
+               default:
+                       continue;
+               }
+               if (sym_set_tristate_value(sym, newval)) {
+                       /* FIXME: if I don't write it doesn't save */
+                       conf_write(NULL);
+                       return 1;
+               }
+       }
+}
+
+static int enable_sym(struct symbol *sym)
+{
+       if (sym_get_tristate_value(sym) != no)
+               return 0;
+
+       if (!sym->visible) {
+               printf("%s: has missing dependencies\n", sym->name);
+               if (!get_depends(sym))
+                       return 0;
+       }
+
+       return conf_sym(sym);
+}
+
+static void expr_parse(struct expr *e)
+{
+       if (!e)
+               return;
+
+       switch (e->type) {
+       case E_EQUAL:
+               printf("set '%s' to '%s'\n", e->left.sym->name, 
e->right.sym->name);
+               break;
+
+       case E_AND:
+               expr_parse(e->left.expr);
+               expr_parse(e->right.expr);
+               break;
+
+       case E_SYMBOL:
+               enable_sym(e->left.sym);
+               break;
+
+       case E_NOT:
+       case E_UNEQUAL:
+       case E_OR:
+       case E_LIST:
+       case E_RANGE:
+       default:
+               printf("HELP.  Lot of unimplemented code\n");
+               break;
+       }
+}
+
+static int get_depends(struct symbol *sym)
+{
+       struct property *prop;
+       struct gstr res = str_new();
+
+       prop = get_symbol_prop(sym);
+       if (!prop)
+               return 0;
+
+       expr_gstr_print(prop->visible.expr, &res);
+       printf("%s\n\n", str_get(&res));
+
+       expr_parse(prop->visible.expr);
+
+       return 1;
+}
+
+static void kconfig_search(void)
+{
+       char *search_str;
+       struct symbol **sym_arr;
+       struct gstr res;
+
+       search_str = getenv("SEARCH");
+       if (!search_str)
+               return;
+
+       sym_arr = sym_re_search(search_str);
+       res = get_relations_str(sym_arr, NULL);
+       printf("%s", str_get(&res));
+}
+
+static void kconfig_set(void)
+{
+       struct symbol *sym;
+       char *config;
+       char *setting;
+       int res;
+
+       config = getenv("CONFIG");
+       if (!config)
+               return;
+       if (strncmp(config, "CONFIG_", 7) == 0)
+               config += 7;
+
+       setting = strchr(config, '=');
+       if (setting) {
+               *setting = '\0';
+               setting++;
+       } else {
+               setting = getenv("SETTING");
+               if (setting && *setting == '\0')
+                       setting = NULL;
+       }
+
+       sym = sym_find(config);
+       if (!sym) {
+               printf("Error: '%s' not found.\n", config);
+               return;
+       }
+
+       if (!sym->visible) {
+               printf("\n%s: has missing dependencies\n", sym->name);
+               if (!get_depends(sym))
+                       return;
+       }
+       if (!sym->visible) {
+               printf("Error: unmet dependencies\n");
+               return;
+       }
+
+       if (!setting) {
+               conf_sym(sym);
+       } else if (!sym_set_string_value(sym, setting)) {
+               printf("Error: setting '%s=%s' failed.\n", sym->name, setting);
+               return;
+       }
+
+       res = conf_write(NULL);
+       if (res) {
+               printf("Error during writing of configuration.\n"
+                       "Your configuration changes were NOT saved.\n");
+               return;
+       }
+
+       printf("set: %s=%s\n", config, sym_get_string_value(sym));
+}
+
+int main(int ac, char **av)
+{
+       char *mode;
+
+       setlocale(LC_ALL, "");
+       bindtextdomain(PACKAGE, LOCALEDIR);
+       textdomain(PACKAGE);
+
+       if (ac > 1 && strcmp(av[1], "-s") == 0) {
+               /* Silence conf_read() until the real callback is set up */
+               conf_set_message_callback(NULL);
+               av++;
+       }
+       conf_parse(av[1]);
+       conf_read(NULL);
+
+       mode = getenv("NCONFIG_MODE");
+       if (!mode)
+               return 1;
+
+       if (strcmp(mode, "kconfig_search") == 0) {
+               kconfig_search();
+               return 0;
+       }
+       if (strcmp(mode, "kconfig_set") == 0) {
+               kconfig_set();
+               return 0;
+       }
+
+       return 1;
+}
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to