1#!/usr/bin/env python3
2
3# Copyright (C) 2019-2021 Internet Systems Consortium, Inc. ("ISC")
4#
5# This Source Code Form is subject to the terms of the Mozilla Public
6# License, v. 2.0. If a copy of the MPL was not distributed with this
7# file, You can obtain one at http:#mozilla.org/MPL/2.0/.
8
9# Produce System Messages Manual
10#
11# This tool reads all the message files given on the command line.
12# It pulls all the messages and description out, sorts them by
13# message ID, and writes them out as a single (formatted) file.
14#
15# Invocation:
16# The code is invoked using the command line:
17#
18# system_messages.py [-o <output-file>] <files>
19#
20# If no output file is specified, output is written to stdout.
21# The produced format is ReStructuredText.
22
23import re
24import argparse
25
26
27def parse_args():
28    parser = argparse.ArgumentParser(description='Convert set of *.mes files to .rst documentation format')
29    parser.add_argument('-o', '--output', help='Output file name (default to stdout).')
30    parser.add_argument('files', help='Input .mes files.', nargs='+')
31
32    args = parser.parse_args()
33    return args
34
35
36def read_input_files(files):
37    messages = {}
38    for f in files:
39        with open(f) as fp:
40            print("Processing %s" % f)
41            namespace = None
42            msg_descr = None
43            msg_id = None
44            msg_text = None
45            for line in fp.readlines():
46                line = line.strip()
47
48                if not line or line.startswith('#'):
49                    pass
50
51                elif line.startswith('$'):
52                    pass
53
54                elif line.startswith('%'):
55                    # end previous message
56                    if msg_id is not None:
57                        section = msg_id.split('_')[0]
58                        messages[msg_id] = (section, msg_id, msg_text, msg_descr)
59
60                    # start next message
61                    m = re.search('^%\s?([A-Z0-9_]+)\s+(.*)', line);
62                    msg_id, msg_text = m.groups()
63                    msg_descr = []
64
65                else:
66                    msg_descr.append(line)
67
68    return messages
69
70
71def generate_rst(messages):
72    rst = '''.. _kea-messages:
73
74###################
75Kea Messages Manual
76###################
77
78Kea is an open source implementation of the Dynamic Host Configuration
79Protocol (DHCP) servers, developed and maintained by Internet Systems
80Consortium (ISC).
81
82This is the reference guide for Kea version |release|.
83Links to the most up-to-date version of this document (in PDF, HTML,
84and plain text formats), along with other useful information about
85Kea, can be found in ISC's `Knowledgebase <https://kea.readthedocs.io>`_.
86
87Please note that in the messages below, the percent sign ("%") followed by a number is
88used to indicate a placeholder for data that is provided by the Kea code during its operation.
89
90
91.. toctree::
92   :numbered:
93   :maxdepth: 5
94
95'''
96
97    prev_section = None
98    for _, msg in sorted(messages.items()):
99        section, msg_id, msg_text, msg_descr = msg
100
101        if section != prev_section:
102            prev_section = section
103            rst += section + '\n'
104            rst += '~' * len(section) + '\n\n'
105
106        rst += '**' + msg_id + '**\n\n'
107
108        rst += msg_text + '\n\n'
109
110        rst += ''.join(['  ' + l + '\n' for l in msg_descr])
111        rst += '\n'
112
113
114    return rst
115
116def generate(in_files, out_file):
117    messages = read_input_files(in_files)
118
119    rst = generate_rst(messages)
120
121    if out_file:
122        with open(out_file, 'w') as f:
123            f.write(rst)
124        print('Wrote generated RST content to: %s' % out_file)
125    else:
126        print(rst)
127
128
129def main():
130    args = parse_args()
131    generate(args.files, args.output)
132
133
134if __name__ == '__main__':
135    main()
136