make-man-rules.py revision e4f42f9d1eb609a515ad1434512d5ad3d96c9b72
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering# -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering# This file is part of systemd.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering# Copyright 2013 Zbigniew Jędrzejewski-Szmek
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering# systemd is free software; you can redistribute it and/or modify it
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering# under the terms of the GNU Lesser General Public License as published by
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering# the Free Software Foundation; either version 2.1 of the License, or
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering# (at your option) any later version.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering# systemd is distributed in the hope that it will be useful, but
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering# WITHOUT ANY WARRANTY; without even the implied warranty of
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering# Lesser General Public License for more details.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering# You should have received a copy of the GNU Lesser General Public License
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering# along with systemd; If not, see <http://www.gnu.org/licenses/>.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringfrom __future__ import print_function
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringimport collections
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poetteringimport sys
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringimport os.path
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poetteringfrom xml_helper import *
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering
be808ea083fa07271116b4519c3c27fd20c5f077Tom GundersenSECTION = '''\
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart PoetteringMANPAGES += \\
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering {manpages}
9df3ba6c6cb65eecec06f39dfe85a3596cedac4eTom GundersenMANPAGES_ALIAS += \\
9df3ba6c6cb65eecec06f39dfe85a3596cedac4eTom Gundersen {aliases}
9df3ba6c6cb65eecec06f39dfe85a3596cedac4eTom Gundersen{rules}
9df3ba6c6cb65eecec06f39dfe85a3596cedac4eTom Gundersen{htmlrules}
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen'''
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen
be808ea083fa07271116b4519c3c27fd20c5f077Tom GundersenCONDITIONAL = '''\
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersenif {conditional}
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen''' \
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen+ SECTION + \
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen'''\
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringendif
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering'''
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart PoetteringHEADER = '''\
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering# Do not edit. Generated by make-man-rules.py.
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering# To regenerate:
3c0cf502796be355431d4a64d738e75f543aa51dLennart Poettering# 1. Create, update, or remove source .xml files in man/
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering# 2. Run 'make update-man-list'
eed857b71702f8551b46b66b31fa0d08583cf23cLennart Poettering# 3. Run 'make man' to generate manpages
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering# To make a man page conditional on a configure switch add
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering# attribute conditional="ENABLE_WHAT" or conditional="WITH_WHAT"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering# to <refentry> element.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering'''
eed857b71702f8551b46b66b31fa0d08583cf23cLennart Poettering
eed857b71702f8551b46b66b31fa0d08583cf23cLennart PoetteringHTML_ALIAS_RULE = '''\
eed857b71702f8551b46b66b31fa0d08583cf23cLennart Poettering{}.html: {}.html
eed857b71702f8551b46b66b31fa0d08583cf23cLennart Poettering $(html-alias)
eed857b71702f8551b46b66b31fa0d08583cf23cLennart Poettering'''
eed857b71702f8551b46b66b31fa0d08583cf23cLennart Poettering
eed857b71702f8551b46b66b31fa0d08583cf23cLennart PoetteringFOOTER = '''\
eed857b71702f8551b46b66b31fa0d08583cf23cLennart Poettering
eed857b71702f8551b46b66b31fa0d08583cf23cLennart Poettering# Really, do not edit this file.
eed857b71702f8551b46b66b31fa0d08583cf23cLennart Poettering
eed857b71702f8551b46b66b31fa0d08583cf23cLennart PoetteringEXTRA_DIST += \\
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering {dist_files}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering'''
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringdef man(page, number):
91b14d6ff362b938a72db17b095ee9903d07381bTom Gundersen return 'man/{}.{}'.format(page, number)
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering
f4461e5641d53f27d6e76e0607bdaa9c0c58c1f6Lennart Poetteringdef xml(file):
f4461e5641d53f27d6e76e0607bdaa9c0c58c1f6Lennart Poettering return 'man/{}'.format(os.path.basename(file))
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen
d74fb368b18f0fbd9a4fe6f15691bbea7f3c4a01Tom Gundersendef add_rules(rules, name):
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering xml = xml_parse(name)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering # print('parsing {}'.format(name), file=sys.stderr)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if xml.getroot().tag != 'refentry':
9df3ba6c6cb65eecec06f39dfe85a3596cedac4eTom Gundersen return
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering conditional = xml.getroot().get('conditional') or ''
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering rulegroup = rules[conditional]
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering refmeta = xml.find('./refmeta')
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering title = refmeta.find('./refentrytitle').text
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering number = refmeta.find('./manvolnum').text
eed857b71702f8551b46b66b31fa0d08583cf23cLennart Poettering refnames = xml.findall('./refnamediv/refname')
eed857b71702f8551b46b66b31fa0d08583cf23cLennart Poettering target = man(refnames[0].text, number)
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering if title != refnames[0].text:
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering raise ValueError('refmeta and refnamediv disagree: ' + name)
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering for refname in refnames:
eed857b71702f8551b46b66b31fa0d08583cf23cLennart Poettering assert all(refname not in group
eed857b71702f8551b46b66b31fa0d08583cf23cLennart Poettering for group in rules.values()), "duplicate page name"
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering alias = man(refname.text, number)
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering rulegroup[alias] = target
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering # print('{} => {} [{}]'.format(alias, target, conditional), file=sys.stderr)
eed857b71702f8551b46b66b31fa0d08583cf23cLennart Poettering
eed857b71702f8551b46b66b31fa0d08583cf23cLennart Poetteringdef create_rules(xml_files):
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering " {conditional => {alias-name => source-name}} "
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering rules = collections.defaultdict(dict)
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering for name in xml_files:
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering try:
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering add_rules(rules, name)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering except Exception:
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering print("Failed to process", name, file=sys.stderr)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering raise
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering return rules
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poetteringdef mjoin(files):
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering return ' \\\n\t'.join(sorted(files) or '#')
3e684349c2cead2e6fd2f816c34eb17daba23a49Lennart Poettering
3e684349c2cead2e6fd2f816c34eb17daba23a49Lennart Poetteringdef make_makefile(rules, dist_files):
3e684349c2cead2e6fd2f816c34eb17daba23a49Lennart Poettering return HEADER + '\n'.join(
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering (CONDITIONAL if conditional else SECTION).format(
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering manpages=mjoin(set(rulegroup.values())),
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering aliases=mjoin(k for k,v in rulegroup.items() if k != v),
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering rules='\n'.join('{}: {}'.format(k,v)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering for k,v in sorted(rulegroup.items())
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if k != v),
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering htmlrules='\n'.join(HTML_ALIAS_RULE.format(k[:-2],v[:-2])
91b14d6ff362b938a72db17b095ee9903d07381bTom Gundersen for k,v in sorted(rulegroup.items())
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if k != v),
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering conditional=conditional)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering for conditional,rulegroup in sorted(rules.items())
91b14d6ff362b938a72db17b095ee9903d07381bTom Gundersen ) + FOOTER.format(dist_files=mjoin(sorted(dist_files)))
91b14d6ff362b938a72db17b095ee9903d07381bTom Gundersen
cab5b05903096e1c9cf5575ccc73f89d15c8db69Lennart Poetteringif __name__ == '__main__':
91b14d6ff362b938a72db17b095ee9903d07381bTom Gundersen rules = create_rules(sys.argv[1:])
91b14d6ff362b938a72db17b095ee9903d07381bTom Gundersen dist_files = (xml(file) for file in sys.argv[1:]
91b14d6ff362b938a72db17b095ee9903d07381bTom Gundersen if not file.endswith(".directives.xml") and
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering not file.endswith(".index.xml"))
91b14d6ff362b938a72db17b095ee9903d07381bTom Gundersen print(make_makefile(rules, dist_files), end='')
91b14d6ff362b938a72db17b095ee9903d07381bTom Gundersen