chiark / gitweb /
6f6347fe5e503d8c5a9addd1a837bd6765e3aa10
[elogind.git] / tools / make-man-rules.py
1 #!/usr/bin/env python3
2 #  -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */
3 #  SPDX-License-Identifier: LGPL-2.1+
4 #
5 #  Copyright © 2013, 2017 Zbigniew Jędrzejewski-Szmek
6
7 from __future__ import print_function
8 import collections
9 import sys
10 import os.path
11 import pprint
12 from xml_helper import xml_parse
13
14 def man(page, number):
15     return '{}.{}'.format(page, number)
16
17 def xml(file):
18     return os.path.basename(file)
19
20 def add_rules(rules, name):
21     xml = xml_parse(name)
22     # print('parsing {}'.format(name), file=sys.stderr)
23     if xml.getroot().tag != 'refentry':
24         return
25     conditional = xml.getroot().get('conditional') or ''
26     rulegroup = rules[conditional]
27     refmeta = xml.find('./refmeta')
28     title = refmeta.find('./refentrytitle').text
29     number = refmeta.find('./manvolnum').text
30     refnames = xml.findall('./refnamediv/refname')
31     target = man(refnames[0].text, number)
32     if title != refnames[0].text:
33         raise ValueError('refmeta and refnamediv disagree: ' + name)
34     for refname in refnames:
35         assert all(refname not in group
36                    for group in rules.values()), "duplicate page name"
37         alias = man(refname.text, number)
38         rulegroup[alias] = target
39         # print('{} => {} [{}]'.format(alias, target, conditional), file=sys.stderr)
40
41 def create_rules(xml_files):
42     " {conditional => {alias-name => source-name}} "
43     rules = collections.defaultdict(dict)
44     for name in xml_files:
45         try:
46             add_rules(rules, name)
47         except Exception:
48             print("Failed to process", name, file=sys.stderr)
49             raise
50     return rules
51
52 def mjoin(files):
53     return ' \\\n\t'.join(sorted(files) or '#')
54
55 MESON_HEADER = '''\
56 # Do not edit. Generated by make-man-rules.py.
57 manpages = ['''
58
59 MESON_FOOTER = '''\
60 ]
61 # Really, do not edit.'''
62
63 def make_mesonfile(rules, dist_files):
64     # reformat rules as
65     # grouped = [ [name, section, [alias...], condition], ...]
66     #
67     # but first create a dictionary like
68     # lists = { (name, condition) => [alias...]
69     grouped = collections.defaultdict(list)
70     for condition, items in rules.items():
71         for alias, name in items.items():
72             group = grouped[(name, condition)]
73             if name != alias:
74                 group.append(alias)
75
76     lines = [ [p[0][:-2], p[0][-1], sorted(a[:-2] for a in aliases), p[1]]
77               for p, aliases in sorted(grouped.items()) ]
78     return '\n'.join((MESON_HEADER, pprint.pformat(lines)[1:-1], MESON_FOOTER))
79
80 if __name__ == '__main__':
81     pages = sys.argv[1:]
82
83     rules = create_rules(pages)
84     dist_files = (xml(file) for file in pages
85                   if not file.endswith(".directives.xml") and
86                      not file.endswith(".index.xml"))
87     print(make_mesonfile(rules, dist_files))