summaryrefslogtreecommitdiff
path: root/doc/macro2rst.py
blob: e80f7edb153bda5a9a83c61007dfc0dc05f644c0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#!/usr/bin/env python3
'''
A utility script for generating documentation.

Preprocessor macro output from opts_macro.h is parsed and combined with
bcachefs.5.rst.tmpl to generate bcachefs.5.rst.

>=python3.6
'''

import sys
import re

INDENT = '       '
TEMPLATE = './doc/bcachefs.5.rst.tmpl'
RST_FILE= './doc/bcachefs.5.rst'
SANITIZE_CHARS = [
            '\\\\n',
            '\\n',
            '  ',
            '"',
            '\\',
        ]

def sanitize(text):
    '''
    Parses opts_macro.h preprocessor output
    :param text: text to sanitize
    :type text: str
    :returns: a list of options
    :rtype: list
    '''

    args = []
    reg = re.search('FMT_START_SECTION(.*)FMT_END_SECTION', text,
            flags=re.DOTALL)
    if not reg:
        raise re.error('no text found')

    # decoding would probably be better, but this works
    for char in SANITIZE_CHARS:
        text = text.replace(char, '')

    text = re.split(r'FMT_END_LINE', text)

    # this seemed easier than getting preprocessor macros to play nice
    # with python's builtin csv module
    for line in text:
        vals = line.split(';')
        if not vals:
            continue
        if len(vals) != 4:
            continue
        vals = list(map(str.strip, vals))
        name, is_bool, desc, arg_name = vals

        # this macro value from opts.h indicates that no values are passed
        if is_bool == 'OPT_BOOL()':
            args.append(f'--{name}\n{INDENT}{desc}')
        else:
            args.append(f'--{name} <{arg_name}>\n{INDENT}{desc}')
    if not args:
        raise re.error('no args found, likely parsing error')

    return args


def main():
    ''' Transform stdin to option list and write templated output to new file '''
    out = ''

    stdin = sys.stdin.read()
    opts = sanitize(stdin)
    opts = '\n'.join(opts)

    # Insert into template
    with open(TEMPLATE, 'r') as in_handle:
        in_handle = in_handle.read()
    out = in_handle.replace('OPTIONS_TABLE', opts)
    with open(RST_FILE, 'w') as out_handle:
        out_handle.write(out)


if __name__ == '__main__':
    main()