2017-05-01 02:26:56 +02:00
#!/usr/bin/env python3
2017-11-18 17:32:46 +01:00
# SPDX-License-Identifier: LGPL-2.1+
2012-11-13 18:39:18 +01:00
2012-08-09 18:08:14 +02:00
import sys
import collections
2013-01-26 10:47:16 -05:00
import re
2017-07-02 20:26:32 -04:00
from xml_helper import xml_parse , xml_print , tree
2013-05-29 22:31:20 -04:00
from copy import deepcopy
2012-08-09 18:08:14 +02:00
TEMPLATE = ''' \
2013-02-02 22:47:47 -05:00
< refentry id = " systemd.directives " conditional = " HAVE_PYTHON " >
2012-08-09 18:08:14 +02:00
< refentryinfo >
< title > systemd . directives < / title >
< productname > systemd < / productname >
< / refentryinfo >
< refmeta >
< refentrytitle > systemd . directives < / refentrytitle >
2013-01-14 22:08:33 -05:00
< manvolnum > 7 < / manvolnum >
2012-08-09 18:08:14 +02:00
< / refmeta >
< refnamediv >
< refname > systemd . directives < / refname >
< refpurpose > Index of configuration directives < / refpurpose >
< / refnamediv >
< refsect1 >
< title > Unit directives < / title >
< para > Directives for configuring units , used in unit
files . < / para >
< variablelist id = ' unit-directives ' / >
< / refsect1 >
2012-09-16 11:11:34 +02:00
2013-01-14 21:58:22 -05:00
< refsect1 >
< title > Options on the kernel command line < / title >
< para > Kernel boot options for configuring the behaviour of the
systemd process . < / para >
2013-01-26 10:47:16 -05:00
< variablelist id = ' kernel-commandline-options ' / >
2013-01-14 21:58:22 -05:00
< / refsect1 >
< refsect1 >
< title > Environment variables < / title >
2019-02-13 10:36:26 +01:00
< para > Environment variables understood by the systemd manager
and other programs and environment variable - compatible settings . < / para >
2013-01-14 21:58:22 -05:00
< variablelist id = ' environment-variables ' / >
< / refsect1 >
2019-02-13 11:09:02 +01:00
< refsect1 >
< title > EFI variables < / title >
< para > EFI variables understood by
< citerefentry > < refentrytitle > systemd - boot < / refentrytitle > < manvolnum > 7 < / manvolnum > < / citerefentry >
and other programs . < / para >
< variablelist id = ' efi-variables ' / >
< / refsect1 >
2012-09-16 11:11:34 +02:00
< refsect1 >
< title > UDEV directives < / title >
< para > Directives for configuring systemd units through the
udev database . < / para >
< variablelist id = ' udev-directives ' / >
< / refsect1 >
2012-08-10 19:35:43 +02:00
2013-11-10 19:33:18 +01:00
< refsect1 >
< title > Network directives < / title >
< para > Directives for configuring network links through the
2013-11-10 20:52:53 +01:00
net - setup - link udev builtin and networks through
systemd - networkd . < / para >
2013-11-10 19:33:18 +01:00
< variablelist id = ' network-directives ' / >
< / refsect1 >
2012-08-10 19:35:43 +02:00
< refsect1 >
2013-01-26 10:47:16 -05:00
< title > Journal fields < / title >
2012-08-10 19:35:43 +02:00
2013-01-26 10:47:16 -05:00
< para > Fields in the journal events with a well known meaning . < / para >
2012-08-10 19:35:43 +02:00
< variablelist id = ' journal-directives ' / >
< / refsect1 >
2013-01-14 20:18:36 -05:00
2013-01-26 10:47:16 -05:00
< refsect1 >
< title > PAM configuration directives < / title >
< para > Directives for configuring PAM behaviour . < / para >
< variablelist id = ' pam-directives ' / >
< / refsect1 >
< refsect1 >
2014-06-30 09:27:16 -04:00
< title > < filename > / etc / crypttab < / filename > and
< filename > / etc / fstab < / filename > options < / title >
2013-01-26 10:47:16 -05:00
< para > Options which influence mounted filesystems and
encrypted volumes . < / para >
2014-06-30 09:27:16 -04:00
< variablelist id = ' fstab-options ' / >
2013-01-26 10:47:16 -05:00
< / refsect1 >
2019-02-13 10:57:49 +01:00
< refsect1 >
< title > < citerefentry > < refentrytitle > systemd . nspawn < / refentrytitle > < manvolnum > 5 < / manvolnum > < / citerefentry >
directives < / title >
< para > Directives for configuring systemd - nspawn containers . < / para >
< variablelist id = ' nspawn-directives ' / >
< / refsect1 >
2013-01-26 10:47:16 -05:00
< refsect1 >
2019-02-13 10:49:47 +01:00
< title > Program configuration options < / title >
2013-01-26 10:47:16 -05:00
< para > Directives for configuring the behaviour of the
2019-02-13 10:49:47 +01:00
systemd process and other tools through configuration files . < / para >
2013-01-26 10:47:16 -05:00
2019-02-13 10:49:47 +01:00
< variablelist id = ' config-directives ' / >
2013-01-26 10:47:16 -05:00
< / refsect1 >
< refsect1 >
2019-02-13 10:57:49 +01:00
< title > Command line options < / title >
2013-01-26 10:47:16 -05:00
< para > Command - line options accepted by programs in the
systemd suite . < / para >
< variablelist id = ' options ' / >
< / refsect1 >
2013-06-26 19:48:19 -04:00
< refsect1 >
< title > Constants < / title >
< para > Various constant used and / or defined by systemd . < / para >
< variablelist id = ' constants ' / >
< / refsect1 >
2013-01-26 10:47:16 -05:00
< refsect1 >
< title > Miscellaneous options and directives < / title >
< para > Other configuration elements which don ' t fit in
any of the above groups . < / para >
< variablelist id = ' miscellaneous ' / >
< / refsect1 >
2013-02-13 21:51:31 -05:00
< refsect1 >
< title > Files and directories < / title >
< para > Paths and file names referred to in the
documentation . < / para >
< variablelist id = ' filenames ' / >
< / refsect1 >
2013-01-14 21:34:19 -05:00
< refsect1 >
< title > Colophon < / title >
< para id = ' colophon ' / >
< / refsect1 >
2012-08-09 18:08:14 +02:00
< / refentry >
'''
2013-01-14 21:34:19 -05:00
COLOPHON = ''' \
This index contains { count } entries in { sections } sections ,
referring to { pages } individual manual pages .
'''
2013-01-26 11:27:35 -05:00
def _extract_directives ( directive_groups , formatting , page ) :
2013-03-29 14:22:27 -04:00
t = xml_parse ( page )
2012-08-09 18:08:14 +02:00
section = t . find ( ' ./refmeta/manvolnum ' ) . text
pagename = t . find ( ' ./refmeta/refentrytitle ' ) . text
2013-02-13 21:51:31 -05:00
storopt = directive_groups [ ' options ' ]
2012-08-09 18:08:14 +02:00
for variablelist in t . iterfind ( ' .//variablelist ' ) :
2013-01-26 10:47:16 -05:00
klass = variablelist . attrib . get ( ' class ' )
storvar = directive_groups [ klass or ' miscellaneous ' ]
# <option>s go in OPTIONS, unless class is specified
for xpath , stor in ( ( ' ./varlistentry/term/varname ' , storvar ) ,
( ' ./varlistentry/term/option ' ,
storvar if klass else storopt ) ) :
for name in variablelist . iterfind ( xpath ) :
text = re . sub ( r ' ([= ]).* ' , r ' \ 1 ' , name . text ) . rstrip ( )
stor [ text ] . append ( ( pagename , section ) )
2013-01-26 11:27:35 -05:00
if text not in formatting :
# use element as formatted display
2013-02-27 21:31:02 -05:00
if name . text [ - 1 ] in ' = ' :
name . clear ( )
else :
name . tail = ' '
2013-01-26 11:27:35 -05:00
name . text = text
formatting [ text ] = name
2012-08-09 18:08:14 +02:00
2013-02-13 21:51:31 -05:00
storfile = directive_groups [ ' filenames ' ]
2013-05-03 00:55:20 -04:00
for xpath , absolute_only in ( ( ' .//refsynopsisdiv//filename ' , False ) ,
( ' .//refsynopsisdiv//command ' , False ) ,
( ' .//filename ' , True ) ) :
2013-02-13 21:51:31 -05:00
for name in t . iterfind ( xpath ) :
2013-05-03 00:55:20 -04:00
if absolute_only and not ( name . text and name . text . startswith ( ' / ' ) ) :
continue
if name . attrib . get ( ' noindex ' ) :
continue
2013-02-13 21:51:31 -05:00
name . tail = ' '
if name . text :
2013-05-03 00:55:20 -04:00
if name . text . endswith ( ' * ' ) :
name . text = name . text [ : - 1 ]
2013-02-13 21:51:31 -05:00
if not name . text . startswith ( ' . ' ) :
text = name . text . partition ( ' ' ) [ 0 ]
if text != name . text :
name . clear ( )
name . text = text
2013-05-03 00:55:20 -04:00
if text . endswith ( ' / ' ) :
text = text [ : - 1 ]
2013-02-13 21:51:31 -05:00
storfile [ text ] . append ( ( pagename , section ) )
if text not in formatting :
# use element as formatted display
formatting [ text ] = name
else :
text = ' ' . join ( name . itertext ( ) )
storfile [ text ] . append ( ( pagename , section ) )
formatting [ text ] = name
2013-06-26 19:48:19 -04:00
storfile = directive_groups [ ' constants ' ]
for name in t . iterfind ( ' .//constant ' ) :
if name . attrib . get ( ' noindex ' ) :
continue
name . tail = ' '
if name . text . startswith ( ' ( ' ) : # a cast, strip it
name . text = name . text . partition ( ' ' ) [ 2 ]
storfile [ name . text ] . append ( ( pagename , section ) )
formatting [ name . text ] = name
2013-01-26 11:27:35 -05:00
def _make_section ( template , name , directives , formatting ) :
2013-01-14 21:02:49 -05:00
varlist = template . find ( " .//*[@id= ' {} ' ] " . format ( name ) )
2012-08-09 18:08:14 +02:00
for varname , manpages in sorted ( directives . items ( ) ) :
entry = tree . SubElement ( varlist , ' varlistentry ' )
2013-01-26 11:27:35 -05:00
term = tree . SubElement ( entry , ' term ' )
2013-05-29 22:31:20 -04:00
display = deepcopy ( formatting [ varname ] )
term . append ( display )
2013-01-26 11:27:35 -05:00
2012-08-09 18:08:14 +02:00
para = tree . SubElement ( tree . SubElement ( entry , ' listitem ' ) , ' para ' )
b = None
2013-01-26 10:47:16 -05:00
for manpage , manvolume in sorted ( set ( manpages ) ) :
2013-05-29 22:31:20 -04:00
if b is not None :
b . tail = ' , '
b = tree . SubElement ( para , ' citerefentry ' )
c = tree . SubElement ( b , ' refentrytitle ' )
c . text = manpage
2015-11-22 23:43:36 -05:00
c . attrib [ ' target ' ] = varname
2013-05-29 22:31:20 -04:00
d = tree . SubElement ( b , ' manvolnum ' )
d . text = manvolume
2012-08-09 18:08:14 +02:00
entry . tail = ' \n \n '
2013-01-14 21:34:19 -05:00
def _make_colophon ( template , groups ) :
count = 0
pages = set ( )
for group in groups :
count + = len ( group )
for pagelist in group . values ( ) :
pages | = set ( pagelist )
para = template . find ( " .//para[@id= ' colophon ' ] " )
para . text = COLOPHON . format ( count = count ,
sections = len ( groups ) ,
pages = len ( pages ) )
2013-01-26 11:27:35 -05:00
def _make_page ( template , directive_groups , formatting ) :
2012-08-09 18:08:14 +02:00
""" Create an XML tree from directive_groups.
directive_groups = {
' class ' : { ' variable ' : [ ( ' manpage ' , ' manvolume ' ) , . . . ] ,
' variable2 ' : . . . } ,
. . .
}
"""
for name , directives in directive_groups . items ( ) :
2013-05-29 22:31:20 -04:00
_make_section ( template , name , directives , formatting )
2012-08-09 18:08:14 +02:00
2013-01-14 21:34:19 -05:00
_make_colophon ( template , directive_groups . values ( ) )
2013-01-14 21:02:49 -05:00
return template
2012-08-09 18:08:14 +02:00
2013-01-26 10:47:16 -05:00
def make_page ( * xml_files ) :
2012-08-09 18:08:14 +02:00
" Extract directives from xml_files and return XML index tree. "
2013-01-14 21:02:49 -05:00
template = tree . fromstring ( TEMPLATE )
names = [ vl . get ( ' id ' ) for vl in template . iterfind ( ' .//variablelist ' ) ]
2012-08-09 18:08:14 +02:00
directive_groups = { name : collections . defaultdict ( list )
2013-01-14 21:02:49 -05:00
for name in names }
2013-01-26 11:27:35 -05:00
formatting = { }
2012-08-09 18:08:14 +02:00
for page in xml_files :
2013-01-26 10:47:16 -05:00
try :
2013-01-26 11:27:35 -05:00
_extract_directives ( directive_groups , formatting , page )
2013-01-26 10:47:16 -05:00
except Exception :
raise ValueError ( " failed to process " + page )
2012-08-09 18:08:14 +02:00
2013-01-26 11:27:35 -05:00
return _make_page ( template , directive_groups , formatting )
2012-08-09 18:08:14 +02:00
if __name__ == ' __main__ ' :
2013-03-29 14:22:27 -04:00
with open ( sys . argv [ 1 ] , ' wb ' ) as f :
f . write ( xml_print ( make_page ( * sys . argv [ 2 : ] ) ) )