This is an automatic generated email to let you know that the following patch 
were queued at the 
http://git.linuxtv.org/cgit.cgi/v4l-utils.git tree:

Subject: keytable: move keymap parsing into its own file
Author:  Sean Young <s...@mess.org>
Date:    Sat Aug 24 21:06:39 2019 +0100

We would like to reuse keymap parsing for transmitting IR based on keymap
in ir-ctl.

This also reduces the size of our huge keytable.c, and keeps knowledge
toml localised to the keymap parser.

Signed-off-by: Sean Young <s...@mess.org>

 utils/keytable/Makefile.am    |   2 +-
 utils/keytable/bpf_load.c     |  21 +-
 utils/keytable/bpf_load.h     |   4 +-
 utils/keytable/keymap.c       | 459 +++++++++++++++++++++++++++++++++++
 utils/keytable/keymap.h       |  26 ++
 utils/keytable/keytable.c     | 545 +++++++++---------------------------------
 utils/keytable/rc_keymap.5.in |   4 +-
 7 files changed, 612 insertions(+), 449 deletions(-)

---

http://git.linuxtv.org/cgit.cgi/v4l-utils.git/commit/?id=83bfb96dc35e103854ef9494dd996b85261bb449
diff --git a/utils/keytable/Makefile.am b/utils/keytable/Makefile.am
index 18e6574e14f0..58c94a47ced0 100644
--- a/utils/keytable/Makefile.am
+++ b/utils/keytable/Makefile.am
@@ -4,7 +4,7 @@ sysconf_DATA = rc_maps.cfg
 keytablesystem_DATA = $(srcdir)/rc_keymaps/*
 udevrules_DATA = 70-infrared.rules
 
-ir_keytable_SOURCES = keytable.c parse.h ir-encode.c ir-encode.h toml.c toml.h 
keymap.h
+ir_keytable_SOURCES = keytable.c parse.h ir-encode.c ir-encode.h toml.c toml.h 
keymap.c keymap.h
 
 if WITH_BPF
 ir_keytable_SOURCES += bpf.c bpf_load.c bpf.h bpf_load.h
diff --git a/utils/keytable/bpf_load.c b/utils/keytable/bpf_load.c
index b6032ed1e9c7..e301aa97604e 100644
--- a/utils/keytable/bpf_load.c
+++ b/utils/keytable/bpf_load.c
@@ -13,7 +13,6 @@
 #include <stdlib.h>
 #include <linux/bpf.h>
 #include <assert.h>
-#include "toml.h"
 #include "keymap.h"
 #include "bpf.h"
 #include "bpf_load.h"
@@ -55,7 +54,7 @@ struct bpf_file {
        Elf_Data *data;
        int strtabidx;
        Elf_Data *symbols;
-       struct toml_table_t *toml;
+       struct protocol_param *param;
 };
 
 static int load_and_attach(int lirc_fd, struct bpf_file *bpf_file, const char 
*name, struct bpf_insn *prog, int size)
@@ -271,23 +270,11 @@ static int parse_relo_and_apply(struct bpf_file 
*bpf_file, GElf_Shdr *shdr,
                        const char *raw = NULL;
                        int value = 0;
 
-                       if (!bpf_param(sym_name, &value)) {
-                               // done
-                       } else if (bpf_file->toml &&
-                                  (raw = toml_raw_in(bpf_file->toml, 
sym_name)) != NULL) {
-                               int64_t val64;
-
-                               if (toml_rtoi(raw, &val64)) {
-                                       printf(_("variable %s not a integer: 
%s\n"), sym_name, raw);
-                                       return 1;
-                               }
-
+                       if (!bpf_param(bpf_file->param, sym_name, &value)) {
                                if (value < INT_MIN && value > UINT_MAX) {
                                        printf(_("variable %s out of range: 
%s\n"), sym_name, raw);
                                        return 1;
                                }
-
-                               value = val64;
                        } else if (sym.st_shndx == bpf_file->dataidx) {
                                // Value is not overridden on command line
                                // or toml file. For the raw decoder, the
@@ -436,10 +423,10 @@ static int load_elf_maps_section(struct bpf_file 
*bpf_file)
        return nr_maps;
 }
 
-int load_bpf_file(const char *path, int lirc_fd, struct toml_table_t *toml,
+int load_bpf_file(const char *path, int lirc_fd, struct protocol_param *param,
                  struct raw_entry *raw)
 {
-       struct bpf_file bpf_file = { .toml = toml };
+       struct bpf_file bpf_file = { .param = param };
        int fd, i, ret;
        Elf *elf;
        GElf_Ehdr ehdr;
diff --git a/utils/keytable/bpf_load.h b/utils/keytable/bpf_load.h
index 4ec0a9344f63..47b57b25d91f 100644
--- a/utils/keytable/bpf_load.h
+++ b/utils/keytable/bpf_load.h
@@ -36,8 +36,8 @@ struct bpf_map_data {
  *
  * returns zero on success
  */
-int load_bpf_file(const char *path, int lirc_fd, struct toml_table_t *toml, 
struct raw_entry *raw);
+int load_bpf_file(const char *path, int lirc_fd, struct protocol_param *param, 
struct raw_entry *raw);
 
-int bpf_param(const char *name, int *val);
+int bpf_param(struct protocol_param *param, const char *name, int *val);
 
 #endif
diff --git a/utils/keytable/keymap.c b/utils/keytable/keymap.c
new file mode 100644
index 000000000000..bb193131164a
--- /dev/null
+++ b/utils/keytable/keymap.c
@@ -0,0 +1,459 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+// Read a toml keymap or plain text keymap (ir-keytable 1.14 or earlier
+// format).
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <limits.h>
+#include <stdbool.h>
+
+#include "keymap.h"
+#include "toml.h"
+
+#ifdef ENABLE_NLS
+# define _(string) gettext(string)
+# include "gettext.h"
+# include <locale.h>
+# include <langinfo.h>
+# include <iconv.h>
+#else
+# define _(string) string
+#endif
+
+void free_keymap(struct keymap *map)
+{
+       struct scancode_entry *se;
+       struct raw_entry *re;
+       struct protocol_param *param;
+       struct keymap *next;
+
+       while (map) {
+               re = map->raw;
+
+               while (re) {
+                       struct raw_entry *next = re->next;
+                       free(re->keycode);
+                       free(re);
+                       re = next;
+               }
+
+
+               se = map->scancode;
+
+               while (se) {
+                       struct scancode_entry *next = se->next;
+                       free(se->keycode);
+                       free(se);
+                       se = next;
+               }
+
+               param = map->param;
+
+               while (param) {
+                       struct protocol_param *next = param->next;
+                       free(param->name);
+                       free(param);
+                       param = next;
+               }
+
+               next = map->next;
+
+               free(map->name);
+               free(map->protocol);
+               free(map->variant);
+               free(map);
+
+               map = next;
+       }
+}
+
+static error_t parse_plain_keyfile(char *fname, struct keymap **keymap, bool 
verbose)
+{
+       FILE *fin;
+       int line = 0;
+       char *scancode, *keycode, s[2048];
+       struct scancode_entry *se;
+       struct keymap *map;
+
+       map = calloc(1, sizeof(*map));
+       if (!map) {
+               perror("parse_keyfile");
+               return ENOMEM;
+       }
+
+       if (verbose)
+               fprintf(stderr, _("Parsing %s keycode file as plain text\n"), 
fname);
+
+       fin = fopen(fname, "r");
+       if (!fin) {
+               return errno;
+       }
+
+       while (fgets(s, sizeof(s), fin)) {
+               char *p = s;
+
+               line++;
+               while (*p == ' ' || *p == '\t')
+                       p++;
+               if (line==1 && p[0] == '#') {
+                       p++;
+                       p = strtok(p, "\n\t =:");
+                       do {
+                               if (!p)
+                                       goto err_einval;
+                               if (!strcmp(p, "table")) {
+                                       p = strtok(NULL,"\n, ");
+                                       if (!p)
+                                               goto err_einval;
+                                       map->name = strdup(p);
+                               } else if (!strcmp(p, "type")) {
+                                       p = strtok(NULL, " ,\n");
+                                       if (!p)
+                                               goto err_einval;
+
+                                       while (p) {
+                                               if (map->protocol) {
+                                                       map->protocol = 
strdup(p);
+                                               } else {
+                                                       struct keymap *k;
+
+                                                       k = calloc(1, 
sizeof(k));
+                                                       k->protocol = strdup(p);
+                                                       k->next = map->next;
+                                                       map->next = k;
+                                               }
+
+                                               p = strtok(NULL, " ,\n");
+                                       }
+                               } else {
+                                       goto err_einval;
+                               }
+                               p = strtok(NULL, "\n\t =:");
+                       } while (p);
+                       continue;
+               }
+
+               if (*p == '\n' || *p == '#')
+                       continue;
+
+               scancode = strtok(p, "\n\t =:");
+               if (!scancode)
+                       goto err_einval;
+               if (!strcasecmp(scancode, "scancode")) {
+                       scancode = strtok(NULL, "\n\t =:");
+                       if (!scancode)
+                               goto err_einval;
+               }
+
+               keycode = strtok(NULL, "\n\t =:(");
+               if (!keycode)
+                       goto err_einval;
+
+               se = calloc(1, sizeof(*se));
+               if (!se) {
+                       free_keymap(map);
+                       perror("parse_keyfile");
+                       fclose(fin);
+                       return ENOMEM;
+               }
+
+               se->scancode = strtoul(scancode, NULL, 0);
+               se->keycode  = keycode;
+               se->next = map->scancode;
+               map->scancode = se;
+       }
+       fclose(fin);
+
+       *keymap = map;
+
+       return 0;
+
+err_einval:
+       free_keymap(map);
+       fprintf(stderr, _("Invalid parameter on line %d of %s\n"),
+               line, fname);
+       return EINVAL;
+}
+
+static error_t parse_toml_raw_part(const char *fname, struct toml_array_t 
*raw, struct keymap *map)
+{
+       struct toml_table_t *t;
+       struct toml_array_t *rawarray;
+       struct raw_entry *re;
+       const char *rkeycode;
+       int ind = 0, length;
+       char *keycode;
+
+       while ((t = toml_table_at(raw, ind++)) != NULL) {
+               rkeycode = toml_raw_in(t, "keycode");
+               if (!rkeycode) {
+                       fprintf(stderr, _("%s: invalid keycode for raw entry 
%d\n"),
+                               fname, ind);
+                       return EINVAL;
+               }
+
+               if (toml_rtos(rkeycode, &keycode)) {
+                       fprintf(stderr, _("%s: bad value `%s' for keycode\n"),
+                               fname, rkeycode);
+                       return EINVAL;
+               }
+
+               rawarray = toml_array_in(t, "raw");
+               if (!rawarray) {
+                       fprintf(stderr, _("%s: missing raw array for entry 
%d\n"),
+                               fname, ind);
+                       return EINVAL;
+               }
+
+               // determine length of array
+               length = 0;
+               while (toml_raw_at(rawarray, length) != NULL)
+                       length++;
+
+               if (!(length % 2)) {
+                       fprintf(stderr, _("%s: raw array must have odd length 
rather than %d\n"),
+                               fname, length);
+                       return EINVAL;
+               }
+
+               re = calloc(1, sizeof(*re) + sizeof(re->raw[0]) * length);
+               if (!re) {
+                       fprintf(stderr, _("Failed to allocate memory"));
+                       return EINVAL;
+               }
+
+               for (int i=0; i<length; i++) {
+                       const char *s = toml_raw_at(rawarray, i);
+                       int64_t v;
+
+                       if (toml_rtoi(s, &v) || v == 0) {
+                               fprintf(stderr, _("%s: incorrect raw value 
`%s'"),
+                                       fname, s);
+                               return EINVAL;
+                       }
+
+                       if (v <= 0 || v > USHRT_MAX) {
+                               fprintf(stderr, _("%s: raw value %ld out of 
range"),
+                                       fname, v);
+                               return EINVAL;
+                       }
+
+                       re->raw[i] = v;
+               }
+
+               re->raw_length = length;
+               re->keycode = keycode;
+               re->next = map->raw;
+               map->raw = re;
+       }
+
+       return 0;
+}
+
+
+static error_t parse_toml_protocol(const char *fname, struct toml_table_t 
*proot, struct keymap **keymap, bool verbose)
+{
+       struct toml_table_t *scancodes;
+       struct toml_array_t *rawarray;
+       const char *raw, *key;
+       bool have_raw_protocol = false;
+       struct keymap *map;
+       char *p;
+       int i = 0;
+
+       map = calloc(1, sizeof(*map));
+       if (!map) {
+               perror("parse_toml_protocol");
+               return ENOMEM;
+       }
+       *keymap = map;
+
+       raw = toml_raw_in(proot, "protocol");
+       if (!raw) {
+               fprintf(stderr, _("%s: protocol missing\n"), fname);
+               return EINVAL;
+       }
+
+       if (toml_rtos(raw, &p)) {
+               fprintf(stderr, _("%s: bad value `%s' for protocol\n"), fname, 
raw);
+               return EINVAL;
+       }
+
+       map->protocol = strdup(p);
+       if (!strcmp(p, "raw"))
+               have_raw_protocol = true;
+
+       raw = toml_raw_in(proot, "variant");
+       if (raw) {
+               if (toml_rtos(raw, &p)) {
+                       fprintf(stderr, _("%s: bad value `%s' for variant\n"), 
fname, raw);
+                       return EINVAL;
+               }
+
+               map->variant = strdup(p);
+       }
+
+       raw = toml_raw_in(proot, "name");
+       if (raw) {
+               if (toml_rtos(raw, &p)) {
+                       fprintf(stderr, _("%s: bad value `%s' for name\n"), 
fname, raw);
+                       return EINVAL;
+               }
+
+               map->name = strdup(p);
+       }
+
+       rawarray = toml_array_in(proot, "raw");
+       if (rawarray) {
+               if (toml_raw_in(proot, "scancodes")) {
+                       fprintf(stderr, _("Cannot have both [raw] and 
[scancode] sections"));
+                       return EINVAL;
+               }
+               if (!have_raw_protocol) {
+                       fprintf(stderr, _("Keymap with raw entries must have 
raw protocol"));
+                       return EINVAL;
+               }
+               error_t err = parse_toml_raw_part(fname, rawarray, map);
+               if (err != 0)
+                       return err;
+
+       } else if (have_raw_protocol) {
+               fprintf(stderr, _("Keymap with raw protocol must have raw 
entries"));
+               return EINVAL;
+       }
+
+       scancodes = toml_table_in(proot, "scancodes");
+       if (!scancodes) {
+               if (verbose)
+                       fprintf(stderr, _("%s: no [protocols.scancodes] 
section\n"), fname);
+               return 0;
+       }
+
+       for (i = 0; (key = toml_key_in(proot, i)) != NULL; i++) {
+               long int value;
+
+               raw = toml_raw_in(proot, key);
+               if (!toml_rtoi(raw, &value)) {
+                       struct protocol_param *param;
+
+                       param = malloc(sizeof(*param));
+                       param->name = strdup(key);
+                       param->value = value;
+                       param->next = map->param;
+                       map->param = param;
+                       if (verbose)
+                               fprintf(stderr, _("%s: protocol parameter 
%s=%ld\n"), fname, param->name, param->value);
+               }
+       }
+
+       for (;;) {
+               struct scancode_entry *se;
+               const char *scancode;
+               char *keycode;
+
+               scancode = toml_key_in(scancodes, i++);
+               if (!scancode)
+                       break;
+
+               raw = toml_raw_in(scancodes, scancode);
+               if (!raw) {
+                       fprintf(stderr, _("%s: invalid value `%s'\n"), fname, 
scancode);
+                       return EINVAL;
+               }
+
+               if (toml_rtos(raw, &keycode)) {
+                       fprintf(stderr, _("%s: bad value `%s' for keycode\n"),
+                               fname, keycode);
+                       return EINVAL;
+               }
+
+               se = calloc(1, sizeof(*se));
+               if (!se) {
+                       perror("parse_keyfile");
+                       return ENOMEM;
+               }
+
+               se->scancode = strtoul(scancode, NULL, 0);
+               se->keycode = keycode;
+               se->next = map->scancode;
+               map->scancode = se;
+       }
+
+       return 0;
+}
+
+static error_t parse_toml_keyfile(char *fname, struct keymap **keymap, bool 
verbose)
+{
+       struct toml_table_t *root, *proot;
+       struct toml_array_t *arr;
+       int ret, i = 0;
+       char buf[200];
+       FILE *fin;
+
+       if (verbose)
+               fprintf(stderr, _("Parsing %s keycode file as toml\n"), fname);
+
+       fin = fopen(fname, "r");
+       if (!fin)
+               return errno;
+
+       root = toml_parse_file(fin, buf, sizeof(buf));
+       fclose(fin);
+       if (!root) {
+               fprintf(stderr, _("%s: failed to parse toml: %s\n"), fname, 
buf);
+               return EINVAL;
+       }
+
+       arr = toml_array_in(root, "protocols");
+       if (!arr) {
+               fprintf(stderr, _("%s: missing [protocols] section\n"), fname);
+               return EINVAL;
+       }
+
+       struct keymap *map = NULL;
+
+       for (;;) {
+               struct keymap *cur_map;
+
+               proot = toml_table_at(arr, i);
+               if (!proot)
+                       break;
+
+               ret = parse_toml_protocol(fname, proot, &cur_map, verbose);
+               if (ret)
+                       goto out;
+
+               if (!map) {
+                       map = cur_map;
+               } else {
+                       cur_map->next = map->next;
+                       map->next = cur_map;
+               }
+               i++;
+       }
+
+       if (i == 0) {
+               fprintf(stderr, _("%s: no protocols found\n"), fname);
+               goto out;
+       }
+
+       toml_free(root);
+       *keymap = map;
+       return 0;
+out:
+       toml_free(root);
+       return EINVAL;
+}
+
+error_t parse_keyfile(char *fname, struct keymap **keymap, bool verbose)
+{
+       size_t len = strlen(fname);
+
+       if (len >= 5 && strcasecmp(fname + len - 5, ".toml") == 0)
+               return parse_toml_keyfile(fname, keymap, verbose);
+       else
+               return parse_plain_keyfile(fname, keymap, verbose);
+}
diff --git a/utils/keytable/keymap.h b/utils/keytable/keymap.h
index 645a9bd06340..df0ba814d654 100644
--- a/utils/keytable/keymap.h
+++ b/utils/keytable/keymap.h
@@ -2,11 +2,37 @@
 #ifndef __KEYMAP_H
 #define __KEYMAP_H
 
+struct keymap {
+       struct keymap *next;
+       char *name;
+       char *protocol;
+       char *variant;
+       struct protocol_param *param;
+       struct scancode_entry *scancode;
+       struct raw_entry *raw;
+};
+
+struct protocol_param {
+       struct protocol_param *next;
+       char *name;
+       long int value;
+};
+
+struct scancode_entry {
+       struct scancode_entry *next;
+       u_int32_t scancode;
+       char *keycode;
+};
+
 struct raw_entry {
        struct raw_entry *next;
        u_int32_t scancode;
        u_int32_t raw_length;
+       char *keycode;
        u_int32_t raw[1];
 };
 
+void free_keymap(struct keymap *map);
+error_t parse_keyfile(char *fname, struct keymap **keymap, bool verbose);
+
 #endif
diff --git a/utils/keytable/keytable.c b/utils/keytable/keytable.c
index 3c4031b034b3..95584449a8cb 100644
--- a/utils/keytable/keytable.c
+++ b/utils/keytable/keytable.c
@@ -33,7 +33,6 @@
 
 #include "ir-encode.h"
 #include "parse.h"
-#include "toml.h"
 #include "keymap.h"
 
 #ifdef HAVE_BPF
@@ -291,18 +290,12 @@ static enum sysfs_protocols ch_proto = 0;
 
 struct bpf_protocol {
        struct bpf_protocol *next;
-       struct toml_table_t *toml;
+       struct protocol_param *param;
        char *name;
 };
 
-struct bpf_parameter {
-       struct bpf_parameter *next;
-       int value;
-       char name[0];
-};
-
 static struct bpf_protocol *bpf_protocol;
-static struct bpf_parameter *bpf_parameter;
+static struct protocol_param *bpf_parameter;
 
 struct cfgfile cfg = {
        NULL, NULL, NULL, NULL
@@ -331,33 +324,21 @@ struct rc_device {
        enum sysfs_protocols supported, current; /* Current and supported IR 
protocols */
 };
 
-static bool compare_parameters(struct toml_table_t *a, struct toml_table_t *b)
+static bool compare_parameters(struct protocol_param *a, struct protocol_param 
*b)
 {
-       int i = 0;
-       int64_t avalue, bvalue;
-       const char *name, *raw;
-
-       if (a == NULL || b == NULL) {
-               return true;
-       }
-
-       while ((name = toml_key_in(a, i++)) != NULL) {
-               raw = toml_raw_in(a, name);
-               if (!raw)
-                       continue;
+       struct protocol_param *b2;
 
-               if (toml_rtoi(raw, &avalue))
-                       continue;
-
-               raw = toml_raw_in(b, name);
-               if (!raw)
-                       return false;
-
-               if (toml_rtoi(raw, &bvalue))
-                       return false;
+       for (; a; a = a->next) {
+               for (b2 = b; b2; b2 = b2->next) {
+                       if (!strcmp(a->name, b2->name) &&
+                           a->value == b2->value) {
+                               break;
+                       }
+               }
 
-               if (avalue != bvalue)
+               if (!b2) {
                        return false;
+               }
        }
 
        return true;
@@ -376,8 +357,8 @@ static void add_bpf_protocol(struct bpf_protocol *new)
                if (strcmp(a->name, new->name))
                        continue;
 
-               if (compare_parameters(a->toml, new->toml) &&
-                   compare_parameters(new->toml, a->toml))
+               if (compare_parameters(a->param, new->param) &&
+                   compare_parameters(new->param, a->param))
                        return;
        }
 
@@ -385,401 +366,89 @@ static void add_bpf_protocol(struct bpf_protocol *new)
        bpf_protocol = new;
 }
 
-static error_t parse_plain_keyfile(char *fname, char **table)
+static int add_keymap(struct keymap *map, const char *fname)
 {
-       FILE *fin;
-       int value, line = 0;
-       char *scancode, *keycode, s[2048];
-       struct keytable_entry *ke;
-
-       *table = NULL;
-
-       if (debug)
-               fprintf(stderr, _("Parsing %s keycode file as plain text\n"), 
fname);
-
-       fin = fopen(fname, "r");
-       if (!fin) {
-               return errno;
-       }
-
-       while (fgets(s, sizeof(s), fin)) {
-               char *p = s;
-
-               line++;
-               while (*p == ' ' || *p == '\t')
-                       p++;
-               if (line==1 && p[0] == '#') {
-                       p++;
-                       p = strtok(p, "\n\t =:");
-                       do {
-                               if (!p)
-                                       goto err_einval;
-                               if (!strcmp(p, "table")) {
-                                       p = strtok(NULL,"\n, ");
-                                       if (!p)
-                                               goto err_einval;
-                                       *table = malloc(strlen(p) + 1);
-                                       strcpy(*table, p);
-                               } else if (!strcmp(p, "type")) {
-                                       p = strtok(NULL, " ,\n");
-                                       if (!p)
-                                               goto err_einval;
-
-                                       while (p) {
-                                               enum sysfs_protocols protocol;
-
-                                               protocol = 
parse_sysfs_protocol(p, false);
-                                               if (protocol == SYSFS_INVALID) {
-                                                       fprintf(stderr, _("%s: 
protocol %s invalid\n"), fname, p);
-                                                       goto err_einval;
-                                               }
-                                               ch_proto |= protocol;
-                                               p = strtok(NULL, " ,\n");
-                                       }
-                               } else {
-                                       goto err_einval;
-                               }
-                               p = strtok(NULL, "\n\t =:");
-                       } while (p);
-                       continue;
-               }
-
-               if (*p == '\n' || *p == '#')
-                       continue;
-
-               scancode = strtok(p, "\n\t =:");
-               if (!scancode)
-                       goto err_einval;
-               if (!strcasecmp(scancode, "scancode")) {
-                       scancode = strtok(NULL, "\n\t =:");
-                       if (!scancode)
-                               goto err_einval;
-               }
-
-               keycode = strtok(NULL, "\n\t =:(");
-               if (!keycode)
-                       goto err_einval;
-
-               if (debug)
-                       fprintf(stderr, _("parsing %s=%s:"), scancode, keycode);
-               value = parse_code(keycode);
-               if (debug)
-                       fprintf(stderr, _("\tvalue=%d\n"), value);
-
-               if (value == -1) {
-                       value = strtol(keycode, NULL, 0);
-                       if (errno)
-                               perror(_("value"));
-               }
-
-               ke = calloc(1, sizeof(*ke));
-               if (!ke) {
-                       perror("parse_keyfile");
-                       return ENOMEM;
+       for (; map; map = map->next) {
+               enum sysfs_protocols protocol;
+               struct keytable_entry *ke;
+               struct scancode_entry *se;
+               struct raw_entry *re, *re_next;
+
+               protocol = parse_sysfs_protocol(map->protocol, false);
+               if (protocol == SYSFS_INVALID) {
+                       struct bpf_protocol *b;
+
+                       b = malloc(sizeof(*b));
+                       b->name = strdup(map->protocol);
+                       b->param = map->param;
+                       /* steal param */
+                       map->param = NULL;
+                       add_bpf_protocol(b);
+               } else {
+                       ch_proto |= protocol;
                }
 
-               ke->scancode    = strtoul(scancode, NULL, 0);
-               ke->keycode     = value;
-               ke->next        = keytable;
-               keytable        = ke;
-       }
-       fclose(fin);
-
-       return 0;
+               for (se = map->scancode; se; se = se->next) {
+                       int value;
+                       char *p;
 
-err_einval:
-       fprintf(stderr, _("Invalid parameter on line %d of %s\n"),
-               line, fname);
-       return EINVAL;
-}
-
-static error_t parse_toml_raw_part(const char *fname, struct toml_array_t *raw)
-{
-       struct toml_table_t *t;
-       struct toml_array_t *rawarray;
-       struct raw_entry *re;
-       struct keytable_entry *ke;
-       const char *rkeycode;
-       char *keycode, *p;
-       int ind = 0, length;
-       int value;
-
-       while ((t = toml_table_at(raw, ind++)) != NULL) {
-               rkeycode = toml_raw_in(t, "keycode");
-               if (!rkeycode) {
-                       fprintf(stderr, _("%s: invalid keycode for raw entry 
%d\n"),
-                               fname, ind);
-                       return EINVAL;
-               }
-
-               if (toml_rtos(rkeycode, &keycode)) {
-                       fprintf(stderr, _("%s: bad value `%s' for keycode\n"),
-                               fname, rkeycode);
-                       return EINVAL;
-               }
+                       value = parse_code(se->keycode);
+                       if (debug)
+                               fprintf(stderr, _("\tvalue=%d\n"), value);
 
-               value = parse_code(keycode);
-               if (debug)
-                       fprintf(stderr, _("\tvalue=%d\n"), value);
-
-               if (value == -1) {
-                       value = strtol(keycode, &p, 0);
-                       if (errno || *p) {
-                               free(keycode);
-                               fprintf(stderr, _("%s: Keycode `%s' not 
recognised\n"),
-                                       fname, keycode);
-                               continue;
+                       if (value == -1) {
+                               value = strtol(se->keycode, &p, 0);
+                               if (errno || *p) {
+                                       fprintf(stderr, _("%s: keycode `%s' not 
recognised, no mapping for scancode %d\n"), fname, se->keycode, se->scancode);
+                                       continue;
+                               }
                        }
-               }
-               free(keycode);
 
-               rawarray = toml_array_in(t, "raw");
-               if (!rawarray) {
-                       fprintf(stderr, _("%s: missing raw array for entry 
%d\n"),
-                               fname, ind);
-                       return EINVAL;
-               }
-
-               // determine length of array
-               length = 0;
-               while (toml_raw_at(rawarray, length) != NULL)
-                       length++;
+                       ke = malloc(sizeof(*ke));
+                       ke->scancode = se->scancode;
+                       ke->keycode = value;
+                       ke->next = keytable;
 
-               if (!(length % 2)) {
-                       fprintf(stderr, _("%s: raw array must have odd length 
rather than %d\n"),
-                               fname, length);
-                       return EINVAL;
+                       keytable = ke;
                }
 
-               re = calloc(1, sizeof(*re) + sizeof(re->raw[0]) * length);
-               if (!re) {
-                       fprintf(stderr, _("Failed to allocate memory"));
-                       return EINVAL;
-               }
+               for (re = map->raw; re; re = re_next) {
+                       int value;
+                       char *p;
 
-               for (int i=0; i<length; i++) {
-                       const char *s = toml_raw_at(rawarray, i);
-                       int64_t v;
+                       re_next = re->next;
 
-                       if (toml_rtoi(s, &v) || v == 0) {
-                               fprintf(stderr, _("%s: incorrect raw value 
`%s'"),
-                                       fname, s);
-                               return EINVAL;
-                       }
+                       value = parse_code(re->keycode);
+                       if (debug)
+                               fprintf(stderr, _("\tvalue=%d\n"), value);
 
-                       if (v <= 0 || v > USHRT_MAX) {
-                               fprintf(stderr, _("%s: raw value %d out of 
range"),
-                                       fname, value);
-                               return EINVAL;
+                       if (value == -1) {
+                               value = strtol(re->keycode, &p, 0);
+                               if (errno || *p) {
+                                       fprintf(stderr, _("%s: keycode `%s' not 
recognised, no mapping\n"), fname, re->keycode);
+                                       continue;
+                               }
                        }
 
-                       re->raw[i] = v;
-               }
-
-               re->raw_length = length;
-
-               ke = calloc(1, sizeof(*ke));
-               if (!re) {
-                       fprintf(stderr, _("Failed to allocate memory"));
-                       return EINVAL;
-               }
-
-               ke->scancode = raw_scancode;
-               ke->keycode = value;
-               ke->next = keytable;
-               keytable = ke;
-
-               re->scancode = raw_scancode;
-               re->next = rawtable;
-               rawtable = re;
-
-               raw_scancode++;
-       }
-
-       return 0;
-}
-
-
-static error_t parse_toml_protocol(const char *fname, struct toml_table_t 
*proot)
-{
-       struct toml_table_t *scancodes;
-       struct toml_array_t *rawarray;
-       enum sysfs_protocols protocol;
-       const char *raw;
-       bool have_raw_protocol = false;
-       char *p;
-       int i = 0;
-
-       raw = toml_raw_in(proot, "protocol");
-       if (!raw) {
-               fprintf(stderr, _("%s: protocol missing\n"), fname);
-               return EINVAL;
-       }
-
-       if (toml_rtos(raw, &p)) {
-               fprintf(stderr, _("%s: bad value `%s' for protocol\n"), fname, 
raw);
-               return EINVAL;
-       }
-
-       protocol = parse_sysfs_protocol(p, false);
-       if (protocol == SYSFS_INVALID) {
-               struct bpf_protocol *b;
-
-               b = malloc(sizeof(*b));
-               if (!strcmp(p, "raw"))
-                       have_raw_protocol = true;
+                       ke = malloc(sizeof(*ke));
+                       ke->scancode = raw_scancode;
+                       ke->keycode = value;
+                       ke->next = keytable;
 
-               b->name = p;
-               b->toml = proot;
-               add_bpf_protocol(b);
-       }
-       else {
-               ch_proto |= protocol;
-               free(p);
-       }
+                       keytable = ke;
 
-       rawarray = toml_array_in(proot, "raw");
-       if (rawarray) {
-               if (toml_raw_in(proot, "scancodes")) {
-                       fprintf(stderr, _("Cannot have both [raw] and 
[scancode] sections"));
-                       return EINVAL;
-               }
-               if (!have_raw_protocol) {
-                       fprintf(stderr, _("Keymap with raw entries must have 
raw protocol"));
-                       return EINVAL;
+                       re->scancode = raw_scancode++;
+                       re->next = rawtable;
+                       rawtable = re;
                }
-               error_t err = parse_toml_raw_part(fname, rawarray);
-               if (err != 0)
-                       return err;
 
-       } else if (have_raw_protocol) {
-               fprintf(stderr, _("Keymap with raw protocol must have raw 
entries"));
-               return EINVAL;
-       }
-
-       scancodes = toml_table_in(proot, "scancodes");
-       if (!scancodes) {
-               if (debug)
-                       fprintf(stderr, _("%s: no [protocols.scancodes] 
section\n"), fname);
-               return 0;
-       }
-
-       for (;;) {
-               struct keytable_entry *ke;
-               const char *scancode;
-               char *keycode;
-               int value;
-
-               scancode = toml_key_in(scancodes, i++);
-               if (!scancode)
-                       break;
-
-               raw = toml_raw_in(scancodes, scancode);
-               if (!raw) {
-                       fprintf(stderr, _("%s: invalid value `%s'\n"), fname, 
scancode);
-                       return EINVAL;
-               }
-
-               if (toml_rtos(raw, &keycode)) {
-                       fprintf(stderr, _("%s: bad value `%s' for keycode\n"),
-                               fname, keycode);
-                       return EINVAL;
-               }
-
-               if (debug)
-                       fprintf(stderr, _("parsing %s=%s:"), scancode, keycode);
-
-               value = parse_code(keycode);
-               if (debug)
-                       fprintf(stderr, _("\tvalue=%d\n"), value);
-
-               if (value == -1) {
-                       value = strtol(keycode, &p, 0);
-                       if (errno || *p)
-                               fprintf(stderr, _("%s: keycode `%s' not 
recognised, no mapping for scancode %s\n"), fname, keycode, scancode);
-               }
-               free(keycode);
-
-               ke = calloc(1, sizeof(*ke));
-               if (!ke) {
-                       perror("parse_keyfile");
-                       return ENOMEM;
-               }
-
-               ke->scancode    = strtoul(scancode, NULL, 0);
-               ke->keycode     = value;
-               ke->next        = keytable;
-               keytable        = ke;
+               /* Steal the raw entries */
+               map->raw = NULL;
        }
 
        return 0;
 }
 
-static error_t parse_toml_keyfile(char *fname, char **table)
-{
-       struct toml_table_t *root, *proot;
-       struct toml_array_t *arr;
-       int ret, i = 0;
-       char buf[200];
-       FILE *fin;
-
-       *table = NULL;
-
-       if (debug)
-               fprintf(stderr, _("Parsing %s keycode file as toml\n"), fname);
-
-       fin = fopen(fname, "r");
-       if (!fin)
-               return errno;
-
-       root = toml_parse_file(fin, buf, sizeof(buf));
-       fclose(fin);
-       if (!root) {
-               fprintf(stderr, _("%s: failed to parse toml: %s\n"), fname, 
buf);
-               return EINVAL;
-       }
-
-       arr = toml_array_in(root, "protocols");
-       if (!arr) {
-               fprintf(stderr, _("%s: missing [protocols] section\n"), fname);
-               return EINVAL;
-       }
-
-       for (;;) {
-               proot = toml_table_at(arr, i);
-               if (!proot)
-                       break;
-
-               ret = parse_toml_protocol(fname, proot);
-               if (ret)
-                       goto out;
-
-               i++;
-       }
-
-       if (i == 0) {
-               fprintf(stderr, _("%s: no protocols found\n"), fname);
-               goto out;
-       }
-
-       // Don't free toml, this is used during bpf loading
-       //toml_free(root);
-       return 0;
-out:
-       toml_free(root);
-       return EINVAL;
-}
-
-static error_t parse_keyfile(char *fname, char **table)
-{
-       size_t len = strlen(fname);
-
-       if (len >= 5 && strcasecmp(fname + len - 5, ".toml") == 0)
-               return parse_toml_keyfile(fname, table);
-       else
-               return parse_plain_keyfile(fname, table);
-}
-
 static error_t parse_cfgfile(char *fname)
 {
        FILE *fin;
@@ -883,13 +552,18 @@ static error_t parse_opt(int k, char *arg, struct 
argp_state *state)
                readtable++;
                break;
        case 'w': {
-               char *name = NULL;
+               struct keymap *map = NULL;
 
-               rc = parse_keyfile(arg, &name);
-               if (rc)
+               rc = parse_keyfile(arg, &map, debug);
+               if (rc) {
                        argp_error(state, _("Failed to read table file %s"), 
arg);
-               if (name)
-                       fprintf(stderr, _("Read %s table\n"), name);
+                       break;
+               }
+               if (map->name)
+                       fprintf(stderr, _("Read %s table\n"), map->name);
+
+               add_keymap(map, arg);
+               free_keymap(map);
                break;
        }
        case 'a': {
@@ -960,7 +634,7 @@ static error_t parse_opt(int k, char *arg, struct 
argp_state *state)
 
                                b = malloc(sizeof(*b));
                                b->name = strdup(p);
-                               b->toml = NULL;
+                               b->param = NULL;
                                b->next = bpf_protocol;
                                bpf_protocol = b;
                        }
@@ -972,20 +646,20 @@ static error_t parse_opt(int k, char *arg, struct 
argp_state *state)
        case 'e':
                p = strtok(arg, ":=");
                do {
-                       struct bpf_parameter *param;
+                       struct protocol_param *param;
 
                        if (!p) {
                                argp_error(state, _("Missing parameter name: 
%s"), arg);
                                break;
                        }
 
-                       param = calloc(1, sizeof(*param) + strlen(p) + 1);
+                       param = malloc(sizeof(*param));
                        if (!p) {
                                perror(_("No memory!\n"));
                                return ENOMEM;
                        }
 
-                       strcpy(param->name, p);
+                       param->name = strdup(p);
 
                        p = strtok(NULL, ",;");
                        if (!p) {
@@ -1002,7 +676,7 @@ static error_t parse_opt(int k, char *arg, struct 
argp_state *state)
                        }
 
                        if (debug)
-                               fprintf(stderr, _("parameter %s=%d\n"),
+                               fprintf(stderr, _("parameter %s=%ld\n"),
                                        param->name, param->value);
 
                        param->next = bpf_parameter;
@@ -1013,11 +687,13 @@ static error_t parse_opt(int k, char *arg, struct 
argp_state *state)
                break;
        case 1:
                test_keymap++;
-               char *name = NULL;
+               struct keymap *map ;
 
-               rc = parse_keyfile(arg, &name);
+               rc = parse_keyfile(arg, &map, debug);
                if (rc)
                        argp_error(state, _("Failed to read table file %s"), 
arg);
+               add_keymap(map, arg);
+               free_keymap(map);
                break;
        case '?':
                argp_state_help(state, state->out_stream,
@@ -1275,7 +951,7 @@ static enum sysfs_protocols load_bpf_for_unsupported(enum 
sysfs_protocols protoc
 
                b = malloc(sizeof(*b));
                b->name = strdup(pme->name);
-               b->toml = NULL;
+               b->param = NULL;
                add_bpf_protocol(b);
 
                protocols &= ~pme->sysfs_protocol;
@@ -2022,7 +1698,7 @@ static void device_info(int fd, char *prepend)
 
 #ifdef HAVE_BPF
 #define MAX_PROGS 64
-static void attach_bpf(const char *lirc_name, const char *bpf_prog, struct 
toml_table_t *toml)
+static void attach_bpf(const char *lirc_name, const char *bpf_prog, struct 
protocol_param *param)
 {
        unsigned int features;
        int fd;
@@ -2045,7 +1721,7 @@ static void attach_bpf(const char *lirc_name, const char 
*bpf_prog, struct toml_
                return;
        }
 
-       load_bpf_file(bpf_prog, fd, toml, rawtable);
+       load_bpf_file(bpf_prog, fd, param, rawtable);
        close(fd);
 }
 
@@ -2238,9 +1914,9 @@ static char *find_bpf_file(const char *name)
        return fname;
 }
 
-int bpf_param(const char *name, int *val)
+int bpf_param(struct protocol_param *protocol_param, const char *name, int 
*val)
 {
-       struct bpf_parameter *param = bpf_parameter;
+       struct protocol_param *param = bpf_parameter;
 
        while (param) {
                if (strcmp(name, param->name) == 0) {
@@ -2250,6 +1926,14 @@ int bpf_param(const char *name, int *val)
                param = param->next;
        }
 
+       while (protocol_param) {
+               if (strcmp(name, protocol_param->name) == 0) {
+                       *val = protocol_param->value;
+                       return 0;
+               }
+               protocol_param = protocol_param->next;
+       }
+
        return -ENOENT;
 }
 
@@ -2302,7 +1986,7 @@ int main(int argc, char *argv[])
 
        if (cfg.next) {
                struct cfgfile *cur;
-               char *fname, *name;
+               char *fname;
                int rc;
                int matches = 0;
 
@@ -2318,29 +2002,36 @@ int main(int argc, char *argv[])
                                        cur->fname);
 
                        if (cur->fname[0] == '/' || ((cur->fname[0] == '.') && 
strchr(cur->fname, '/'))) {
+                               struct keymap *map;
                                fname = cur->fname;
-                               rc = parse_keyfile(fname, &name);
+                               rc = parse_keyfile(fname, &map, debug);
                                if (rc < 0) {
                                        fprintf(stderr, _("Can't load %s 
table\n"), fname);
                                        return -1;
                                }
+                               add_keymap(map, fname);
+                               free_keymap(map);
                        } else {
+                               struct keymap *map;
                                fname = malloc(strlen(cur->fname) + 
strlen(IR_KEYTABLE_USER_DIR) + 2);
                                strcpy(fname, IR_KEYTABLE_USER_DIR);
                                strcat(fname, "/");
                                strcat(fname, cur->fname);
-                               rc = parse_keyfile(fname, &name);
+                               rc = parse_keyfile(fname, &map, debug);
                                if (rc != 0) {
                                        fname = malloc(strlen(cur->fname) + 
strlen(IR_KEYTABLE_SYSTEM_DIR) + 2);
                                        strcpy(fname, IR_KEYTABLE_SYSTEM_DIR);
                                        strcat(fname, "/");
                                        strcat(fname, cur->fname);
-                                       rc = parse_keyfile(fname, &name);
+                                       rc = parse_keyfile(fname, &map, debug);
                                }
                                if (rc != 0) {
                                        fprintf(stderr, _("Can't load %s table 
from %s or %s\n"), cur->fname, IR_KEYTABLE_USER_DIR, IR_KEYTABLE_SYSTEM_DIR);
                                        return -1;
                                }
+
+                               add_keymap(map, fname);
+                               free_keymap(map);
                        }
                        if (!keytable) {
                                fprintf(stderr, _("Empty table %s\n"), fname);
@@ -2414,7 +2105,7 @@ int main(int argc, char *argv[])
                        char *fname = find_bpf_file(b->name);
 
                        if (fname) {
-                               attach_bpf(rc_dev.lirc_name, fname, b->toml);
+                               attach_bpf(rc_dev.lirc_name, fname, b->param);
                                fprintf(stderr, _("Loaded BPF protocol %s\n"), 
b->name);
                                free(fname);
                        }
diff --git a/utils/keytable/rc_keymap.5.in b/utils/keytable/rc_keymap.5.in
index d5de657adb57..00599755e41e 100644
--- a/utils/keytable/rc_keymap.5.in
+++ b/utils/keytable/rc_keymap.5.in
@@ -4,7 +4,7 @@ rc_keymap \- toml file describing remote control keymap
 .SH DESCRIPTION
 An rc_keymap describes a remote control. It list the protocols used, and the
 mapping from decoded IR to linux input events. This file is used by
-ir\-keytable(1).
+ir\-keytable(1) for IR decoding, and by ir-ctl(1) for sending IR.
 .PP
 The file format is toml. Since a remote control can use multiple protocols,
 the top level is an array of protocols. The vast majority of remotes only use
@@ -308,7 +308,7 @@ License GPLv2: GNU GPL version 2 
<http://gnu.org/licenses/gpl.html>.
 This is free software: you are free to change and redistribute it.
 There is NO WARRANTY, to the extent permitted by law.
 .SH SEE ALSO
-ir\-keytable(1).
+ir\-keytable(1) and ir\-ctl(1)
 .PP
 https://lwn.net/Articles/759188/
 .PP

_______________________________________________
linuxtv-commits mailing list
linuxtv-commits@linuxtv.org
https://www.linuxtv.org/cgi-bin/mailman/listinfo/linuxtv-commits

Reply via email to