summaryrefslogtreecommitdiff
path: root/rules/compat
diff options
context:
space:
mode:
authorPeter Hutterer <peter.hutterer@who-t.net>2019-09-02 10:51:42 +1000
committerPeter Hutterer <peter.hutterer@who-t.net>2019-11-14 05:06:13 +0000
commit57c745a9a373b4c9d272d00ff4f16dbcc6d3c48b (patch)
treeb257b55b223d99f0a28657ae59734183668caa2a /rules/compat
parent98579545b2293e91d9969575b36257121b003db6 (diff)
downloadxkeyboard-config-57c745a9a373b4c9d272d00ff4f16dbcc6d3c48b.tar.gz
rules/compat: switch compat rule generation to a python script
The current generation is a bunch of awk scripts that parse files and spit out the final rules. This is hard to debug because the knowledge what to parse and how is in each script (though largely duplicated). Plus, shell scripts are terrible to read in general. Move this to a python script instead where debugging is a lot easier and all the parsing and printing is now in one file. This immediately made obvious that the special layout/variant 1 handling is just a different base+suffix, so we can drop that easily. And let's be more precise in the Makefile too, only give each script the files it wants. Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Diffstat (limited to 'rules/compat')
-rw-r--r--rules/compat/Makefile.am48
-rwxr-xr-xrules/compat/map-variants.py133
2 files changed, 156 insertions, 25 deletions
diff --git a/rules/compat/Makefile.am b/rules/compat/Makefile.am
index fc33ce9..de3eb0f 100644
--- a/rules/compat/Makefile.am
+++ b/rules/compat/Makefile.am
@@ -1,5 +1,5 @@
-
-transform_files=layoutsMapping.lst variantsMapping.lst
+layout_mappings=$(srcdir)/layoutsMapping.lst
+variant_mappings=$(srcdir)/variantsMapping.lst
dist_parts=base.o_s.part \
base.lv_c.part \
@@ -8,8 +8,6 @@ base.l2v2_c.part \
base.l3v3_c.part \
base.l4v4_c.part
-scripts_dir=$(srcdir)/../bin
-
scripts= \
base.ml2_s.part \
base.ml3_s.part \
@@ -32,36 +30,36 @@ noinst_SCRIPTS=
endif
-base.ml2_s.part: $(scripts_dir)/mln_s.sh $(transform_files)
- sh $(scripts_dir)/mln_s.sh 2 $(srcdir)
+base.ml1_s.part: map-variants.py $(layout_mappings) $(variant_mappings)
+ $(srcdir)/map-variants.py --want=mls --number=1 $@ $(layout_mappings) $(variant_mappings)
-base.ml3_s.part: $(scripts_dir)/mln_s.sh $(transform_files)
- sh $(scripts_dir)/mln_s.sh 3 $(srcdir)
+base.ml2_s.part: map-variants.py $(layout_mappings) $(variant_mappings)
+ $(srcdir)/map-variants.py --want=mls --number=2 $@ $(layout_mappings) $(variant_mappings)
-base.ml4_s.part: $(scripts_dir)/mln_s.sh $(transform_files)
- sh $(scripts_dir)/mln_s.sh 4 $(srcdir)
+base.ml3_s.part: map-variants.py $(layout_mappings) $(variant_mappings)
+ $(srcdir)/map-variants.py --want=mls --number=3 $@ $(layout_mappings) $(variant_mappings)
-base.ml2v2_s.part: $(scripts_dir)/mlnvn_s.sh $(transform_files)
- sh $(scripts_dir)/mlnvn_s.sh 2 $(srcdir)
+base.ml4_s.part: map-variants.py $(layout_mappings) $(variant_mappings)
+ $(srcdir)/map-variants.py --want=mls --number=4 $@ $(layout_mappings) $(variant_mappings)
-base.ml3v3_s.part: $(scripts_dir)/mlnvn_s.sh $(transform_files)
- sh $(scripts_dir)/mlnvn_s.sh 3 $(srcdir)
+base.ml1v1_s.part: map-variants.py $(variant_mappings)
+ $(srcdir)/map-variants.py --want=mlvs --number=1 $@ $(variant_mappings)
-base.ml4v4_s.part: $(scripts_dir)/mlnvn_s.sh $(transform_files)
- sh $(scripts_dir)/mlnvn_s.sh 4 $(srcdir)
+base.ml2v2_s.part: map-variants.py $(variant_mappings)
+ $(srcdir)/map-variants.py --want=mlvs --number=2 $@ $(variant_mappings)
-base.ml_s.part: $(scripts_dir)/ml_s.sh $(transform_files)
- sh $(scripts_dir)/ml_s.sh $(srcdir)
+base.ml3v3_s.part: map-variants.py $(variant_mappings)
+ $(srcdir)/map-variants.py --want=mlvs --number=3 $@ $(variant_mappings)
-base.ml1_s.part: $(scripts_dir)/ml1_s.sh $(transform_files)
- sh $(scripts_dir)/ml1_s.sh $(srcdir)
+base.ml4v4_s.part: map-variants.py $(variant_mappings)
+ $(srcdir)/map-variants.py --want=mlvs --number=4 $@ $(variant_mappings)
-base.mlv_s.part: $(scripts_dir)/mlv_s.sh $(transform_files)
- sh $(scripts_dir)/mlv_s.sh $(srcdir)
+base.ml_s.part: map-variants.py $(layout_mappings) $(variant_mappings)
+ $(srcdir)/map-variants.py --want=mls $@ $(layout_mappings) $(variant_mappings)
-base.ml1v1_s.part: $(scripts_dir)/ml1v1_s.sh $(transform_files)
- sh $(scripts_dir)/ml1v1_s.sh $(srcdir)
+base.mlv_s.part: map-variants.py $(layout_mappings) $(variant_mappings)
+ $(srcdir)/map-variants.py --want=mlvs $@ $(variant_mappings)
-EXTRA_DIST=base.lists.part $(transform_files) $(dist_parts)
+EXTRA_DIST=base.lists.part $(layout_mappings) $(variant_mappings) $(dist_parts) map-variants.py
CLEANFILES=$(scripts)
diff --git a/rules/compat/map-variants.py b/rules/compat/map-variants.py
new file mode 100755
index 0000000..ebbfec9
--- /dev/null
+++ b/rules/compat/map-variants.py
@@ -0,0 +1,133 @@
+#!/usr/bin/python3
+
+import argparse
+import re
+
+
+class Layout(object):
+ def __init__(self, layout, variant=None):
+ self.layout = layout
+ self.variant = variant
+ if '(' in layout:
+ assert variant is None
+ # parse a layout(variant) string
+ match = re.match(r'([^(]+)\(([^)]+)\)', layout)
+ self.layout = match[1]
+ self.variant = match[2]
+
+ def __str__(self):
+ if self.variant:
+ return '{}({})'.format(self.layout, self.variant)
+ else:
+ return '{}'.format(self.layout)
+
+
+def read_file(path):
+ '''Returns a list of two-layout tuples [(layout1, layout2), ...]'''
+
+ # This parses both input files, one with two elements, one with four elements,
+ # all separated by tabs
+ pattern = re.compile(r'([^\t]+)\s+([^\t]+)\s*([^\t]*)\s*([^\t]*)')
+
+ layouts = []
+ for line in open(path):
+ match = re.match(pattern, line.strip())
+ groups = [g for g in match.groups() if g] # drop empty groups
+ if len(groups) == 2:
+ l1 = Layout(groups[0])
+ l2 = Layout(groups[1])
+ else:
+ l1 = Layout(groups[0], groups[1])
+ l2 = Layout(groups[2], groups[3])
+ layouts.append((l1, l2))
+ return layouts
+
+
+# ml_s
+def write_fixed_layout(dest, mappings, write_header):
+ if write_header:
+ dest.write('! model layout = symbols\n')
+ for l1, l2 in mappings:
+ dest.write(' * {} = pc+{}\n'.format(l1, l2))
+
+
+# mln_s
+def write_layout_n(dest, mappings, number, write_header):
+ if write_header:
+ dest.write('! model layout[{}] = symbols\n'.format(number))
+
+ # symbols is one of
+ # +layout(variant):2 ... where the map-to-layout has a proper variant
+ # +layout%(v[2]):2 ... where the map-to-layout does not have a variant
+ # and where the number is 1, we have a base and drop the suffix, i.e.
+ # the above becomes
+ # pc+layout(variant)
+ # pc+layout%(v[1])
+
+ base = 'pc' if number == 1 else ''
+ suffix = '' if number == 1 else ':{}'.format(number)
+
+ for l1, l2 in mappings:
+ second_layout = str(l2) if l2.variant else '{}%(v[{}])'.format(l2.layout, number)
+ dest.write(' * {} = {}+{}{}\n'.format(l1, base, second_layout, suffix))
+
+
+# mlv_s
+def write_fixed_layout_variant(dest, mappings, write_header):
+ if write_header:
+ dest.write('! model layout variant = symbols\n')
+ for l1, l2 in mappings:
+ dest.write(' * {} {} = pc+{}\n'.format(l1.layout, l1.variant, l2))
+
+
+# mlnvn_s
+def write_layout_n_variant_n(dest, mappings, number, write_header):
+ if write_header:
+ dest.write('! model layout[{}] variant[{}] = symbols\n'.format(number, number))
+
+ # symbols is
+ # +layout(variant):2
+ # and where the number is 1, we have a base and drop the suffix, i.e.
+ # the above becomes
+ # pc+layout(variant)
+ # This part is only executed for the variantMappings.lst
+
+ base = 'pc' if number == 1 else ''
+ suffix = '' if number == 1 else ':{}'.format(number)
+
+ for l1, l2 in mappings:
+ second_layout = str(l2) if l2.variant else '{}%(v[{}])'.format(l2.layout, number)
+ dest.write(' * {} {} = {}+{}{}\n'.format(l1.layout, l1.variant, base, second_layout, suffix))
+
+
+def map_variant(dest, files, want='mls', number=None):
+ for idx, f in enumerate(files):
+ write_header = idx == 0
+
+ mappings = read_file(f)
+ if want == 'mls':
+ if number is None:
+ write_fixed_layout(dest, mappings, write_header)
+ else:
+ write_layout_n(dest, mappings, number, write_header)
+ elif want == 'mlvs':
+ if number is None:
+ write_fixed_layout_variant(dest, mappings, write_header)
+ else:
+ write_layout_n_variant_n(dest, mappings, number, write_header)
+ else:
+ raise NotImplementedError()
+
+
+if __name__ == '__main__':
+ parser = argparse.ArgumentParser('variant mapping script')
+ parser.add_argument('--want', type=str,
+ choices=['mls', 'mlvs'])
+ parser.add_argument('--number', type=int, default=None)
+
+ parser.add_argument('dest', type=str)
+ parser.add_argument('files', nargs='+', type=str)
+ ns = parser.parse_args()
+
+ with open(ns.dest, 'w') as fd:
+ map_variant(fd, ns.files, ns.want, ns.number)