diff options
author | Peter Hutterer <peter.hutterer@who-t.net> | 2019-09-02 10:51:42 +1000 |
---|---|---|
committer | Peter Hutterer <peter.hutterer@who-t.net> | 2019-11-14 05:06:13 +0000 |
commit | 57c745a9a373b4c9d272d00ff4f16dbcc6d3c48b (patch) | |
tree | b257b55b223d99f0a28657ae59734183668caa2a /rules/compat | |
parent | 98579545b2293e91d9969575b36257121b003db6 (diff) | |
download | xkeyboard-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.am | 48 | ||||
-rwxr-xr-x | rules/compat/map-variants.py | 133 |
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) |