1a8e1175bSopenharmony_ci#!/usr/bin/env python3
2a8e1175bSopenharmony_ci
3a8e1175bSopenharmony_ci"""Generate library/ssl_debug_helpers_generated.c
4a8e1175bSopenharmony_ci
5a8e1175bSopenharmony_ciThe code generated by this module includes debug helper functions that can not be
6a8e1175bSopenharmony_ciimplemented by fixed codes.
7a8e1175bSopenharmony_ci
8a8e1175bSopenharmony_ci"""
9a8e1175bSopenharmony_ci
10a8e1175bSopenharmony_ci# Copyright The Mbed TLS Contributors
11a8e1175bSopenharmony_ci# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
12a8e1175bSopenharmony_ciimport sys
13a8e1175bSopenharmony_ciimport re
14a8e1175bSopenharmony_ciimport os
15a8e1175bSopenharmony_ciimport textwrap
16a8e1175bSopenharmony_ciimport argparse
17a8e1175bSopenharmony_cifrom mbedtls_dev import build_tree
18a8e1175bSopenharmony_ci
19a8e1175bSopenharmony_ci
20a8e1175bSopenharmony_cidef remove_c_comments(string):
21a8e1175bSopenharmony_ci    """
22a8e1175bSopenharmony_ci        Remove C style comments from input string
23a8e1175bSopenharmony_ci    """
24a8e1175bSopenharmony_ci    string_pattern = r"(?P<string>\".*?\"|\'.*?\')"
25a8e1175bSopenharmony_ci    comment_pattern = r"(?P<comment>/\*.*?\*/|//[^\r\n]*$)"
26a8e1175bSopenharmony_ci    pattern = re.compile(string_pattern + r'|' + comment_pattern,
27a8e1175bSopenharmony_ci                         re.MULTILINE | re.DOTALL)
28a8e1175bSopenharmony_ci
29a8e1175bSopenharmony_ci    def replacer(match):
30a8e1175bSopenharmony_ci        if match.lastgroup == 'comment':
31a8e1175bSopenharmony_ci            return ""
32a8e1175bSopenharmony_ci        return match.group()
33a8e1175bSopenharmony_ci    return pattern.sub(replacer, string)
34a8e1175bSopenharmony_ci
35a8e1175bSopenharmony_ci
36a8e1175bSopenharmony_ciclass CondDirectiveNotMatch(Exception):
37a8e1175bSopenharmony_ci    pass
38a8e1175bSopenharmony_ci
39a8e1175bSopenharmony_ci
40a8e1175bSopenharmony_cidef preprocess_c_source_code(source, *classes):
41a8e1175bSopenharmony_ci    """
42a8e1175bSopenharmony_ci        Simple preprocessor for C source code.
43a8e1175bSopenharmony_ci
44a8e1175bSopenharmony_ci        Only processes condition directives without expanding them.
45a8e1175bSopenharmony_ci        Yield object according to the classes input. Most match firstly
46a8e1175bSopenharmony_ci
47a8e1175bSopenharmony_ci        If the directive pair does not match , raise CondDirectiveNotMatch.
48a8e1175bSopenharmony_ci
49a8e1175bSopenharmony_ci        Assume source code does not include comments and compile pass.
50a8e1175bSopenharmony_ci
51a8e1175bSopenharmony_ci    """
52a8e1175bSopenharmony_ci
53a8e1175bSopenharmony_ci    pattern = re.compile(r"^[ \t]*#[ \t]*" +
54a8e1175bSopenharmony_ci                         r"(?P<directive>(if[ \t]|ifndef[ \t]|ifdef[ \t]|else|endif))" +
55a8e1175bSopenharmony_ci                         r"[ \t]*(?P<param>(.*\\\n)*.*$)",
56a8e1175bSopenharmony_ci                         re.MULTILINE)
57a8e1175bSopenharmony_ci    stack = []
58a8e1175bSopenharmony_ci
59a8e1175bSopenharmony_ci    def _yield_objects(s, d, p, st, end):
60a8e1175bSopenharmony_ci        """
61a8e1175bSopenharmony_ci            Output matched source piece
62a8e1175bSopenharmony_ci        """
63a8e1175bSopenharmony_ci        nonlocal stack
64a8e1175bSopenharmony_ci        start_line, end_line = '', ''
65a8e1175bSopenharmony_ci        if stack:
66a8e1175bSopenharmony_ci            start_line = '#{} {}'.format(d, p)
67a8e1175bSopenharmony_ci            if d == 'if':
68a8e1175bSopenharmony_ci                end_line = '#endif /* {} */'.format(p)
69a8e1175bSopenharmony_ci            elif d == 'ifdef':
70a8e1175bSopenharmony_ci                end_line = '#endif /* defined({}) */'.format(p)
71a8e1175bSopenharmony_ci            else:
72a8e1175bSopenharmony_ci                end_line = '#endif /* !defined({}) */'.format(p)
73a8e1175bSopenharmony_ci        has_instance = False
74a8e1175bSopenharmony_ci        for cls in classes:
75a8e1175bSopenharmony_ci            for instance in cls.extract(s, st, end):
76a8e1175bSopenharmony_ci                if has_instance is False:
77a8e1175bSopenharmony_ci                    has_instance = True
78a8e1175bSopenharmony_ci                    yield pair_start, start_line
79a8e1175bSopenharmony_ci                yield instance.span()[0], instance
80a8e1175bSopenharmony_ci        if has_instance:
81a8e1175bSopenharmony_ci            yield start, end_line
82a8e1175bSopenharmony_ci
83a8e1175bSopenharmony_ci    for match in pattern.finditer(source):
84a8e1175bSopenharmony_ci
85a8e1175bSopenharmony_ci        directive = match.groupdict()['directive'].strip()
86a8e1175bSopenharmony_ci        param = match.groupdict()['param']
87a8e1175bSopenharmony_ci        start, end = match.span()
88a8e1175bSopenharmony_ci
89a8e1175bSopenharmony_ci        if directive in ('if', 'ifndef', 'ifdef'):
90a8e1175bSopenharmony_ci            stack.append((directive, param, start, end))
91a8e1175bSopenharmony_ci            continue
92a8e1175bSopenharmony_ci
93a8e1175bSopenharmony_ci        if not stack:
94a8e1175bSopenharmony_ci            raise CondDirectiveNotMatch()
95a8e1175bSopenharmony_ci
96a8e1175bSopenharmony_ci        pair_directive, pair_param, pair_start, pair_end = stack.pop()
97a8e1175bSopenharmony_ci        yield from _yield_objects(source,
98a8e1175bSopenharmony_ci                                  pair_directive,
99a8e1175bSopenharmony_ci                                  pair_param,
100a8e1175bSopenharmony_ci                                  pair_end,
101a8e1175bSopenharmony_ci                                  start)
102a8e1175bSopenharmony_ci
103a8e1175bSopenharmony_ci        if directive == 'endif':
104a8e1175bSopenharmony_ci            continue
105a8e1175bSopenharmony_ci
106a8e1175bSopenharmony_ci        if pair_directive == 'if':
107a8e1175bSopenharmony_ci            directive = 'if'
108a8e1175bSopenharmony_ci            param = "!( {} )".format(pair_param)
109a8e1175bSopenharmony_ci        elif pair_directive == 'ifdef':
110a8e1175bSopenharmony_ci            directive = 'ifndef'
111a8e1175bSopenharmony_ci            param = pair_param
112a8e1175bSopenharmony_ci        else:
113a8e1175bSopenharmony_ci            directive = 'ifdef'
114a8e1175bSopenharmony_ci            param = pair_param
115a8e1175bSopenharmony_ci
116a8e1175bSopenharmony_ci        stack.append((directive, param, start, end))
117a8e1175bSopenharmony_ci    assert not stack, len(stack)
118a8e1175bSopenharmony_ci
119a8e1175bSopenharmony_ci
120a8e1175bSopenharmony_ciclass EnumDefinition:
121a8e1175bSopenharmony_ci    """
122a8e1175bSopenharmony_ci        Generate helper functions around enumeration.
123a8e1175bSopenharmony_ci
124a8e1175bSopenharmony_ci        Currently, it generate translation function from enum value to string.
125a8e1175bSopenharmony_ci        Enum definition looks like:
126a8e1175bSopenharmony_ci        [typedef] enum [prefix name] { [body] } [suffix name];
127a8e1175bSopenharmony_ci
128a8e1175bSopenharmony_ci        Known limitation:
129a8e1175bSopenharmony_ci        - the '}' and ';' SHOULD NOT exist in different macro blocks. Like
130a8e1175bSopenharmony_ci        ```
131a8e1175bSopenharmony_ci        enum test {
132a8e1175bSopenharmony_ci            ....
133a8e1175bSopenharmony_ci        #if defined(A)
134a8e1175bSopenharmony_ci            ....
135a8e1175bSopenharmony_ci        };
136a8e1175bSopenharmony_ci        #else
137a8e1175bSopenharmony_ci            ....
138a8e1175bSopenharmony_ci        };
139a8e1175bSopenharmony_ci        #endif
140a8e1175bSopenharmony_ci        ```
141a8e1175bSopenharmony_ci    """
142a8e1175bSopenharmony_ci
143a8e1175bSopenharmony_ci    @classmethod
144a8e1175bSopenharmony_ci    def extract(cls, source_code, start=0, end=-1):
145a8e1175bSopenharmony_ci        enum_pattern = re.compile(r'enum\s*(?P<prefix_name>\w*)\s*' +
146a8e1175bSopenharmony_ci                                  r'{\s*(?P<body>[^}]*)}' +
147a8e1175bSopenharmony_ci                                  r'\s*(?P<suffix_name>\w*)\s*;',
148a8e1175bSopenharmony_ci                                  re.MULTILINE | re.DOTALL)
149a8e1175bSopenharmony_ci
150a8e1175bSopenharmony_ci        for match in enum_pattern.finditer(source_code, start, end):
151a8e1175bSopenharmony_ci            yield EnumDefinition(source_code,
152a8e1175bSopenharmony_ci                                 span=match.span(),
153a8e1175bSopenharmony_ci                                 group=match.groupdict())
154a8e1175bSopenharmony_ci
155a8e1175bSopenharmony_ci    def __init__(self, source_code, span=None, group=None):
156a8e1175bSopenharmony_ci        assert isinstance(group, dict)
157a8e1175bSopenharmony_ci        prefix_name = group.get('prefix_name', None)
158a8e1175bSopenharmony_ci        suffix_name = group.get('suffix_name', None)
159a8e1175bSopenharmony_ci        body = group.get('body', None)
160a8e1175bSopenharmony_ci        assert prefix_name or suffix_name
161a8e1175bSopenharmony_ci        assert body
162a8e1175bSopenharmony_ci        assert span
163a8e1175bSopenharmony_ci        # If suffix_name exists, it is a typedef
164a8e1175bSopenharmony_ci        self._prototype = suffix_name if suffix_name else 'enum ' + prefix_name
165a8e1175bSopenharmony_ci        self._name = suffix_name if suffix_name else prefix_name
166a8e1175bSopenharmony_ci        self._body = body
167a8e1175bSopenharmony_ci        self._source = source_code
168a8e1175bSopenharmony_ci        self._span = span
169a8e1175bSopenharmony_ci
170a8e1175bSopenharmony_ci    def __repr__(self):
171a8e1175bSopenharmony_ci        return 'Enum({},{})'.format(self._name, self._span)
172a8e1175bSopenharmony_ci
173a8e1175bSopenharmony_ci    def __str__(self):
174a8e1175bSopenharmony_ci        return repr(self)
175a8e1175bSopenharmony_ci
176a8e1175bSopenharmony_ci    def span(self):
177a8e1175bSopenharmony_ci        return self._span
178a8e1175bSopenharmony_ci
179a8e1175bSopenharmony_ci    def generate_translation_function(self):
180a8e1175bSopenharmony_ci        """
181a8e1175bSopenharmony_ci            Generate function for translating value to string
182a8e1175bSopenharmony_ci        """
183a8e1175bSopenharmony_ci        translation_table = []
184a8e1175bSopenharmony_ci
185a8e1175bSopenharmony_ci        for line in self._body.splitlines():
186a8e1175bSopenharmony_ci
187a8e1175bSopenharmony_ci            if line.strip().startswith('#'):
188a8e1175bSopenharmony_ci                # Preprocess directive, keep it in table
189a8e1175bSopenharmony_ci                translation_table.append(line.strip())
190a8e1175bSopenharmony_ci                continue
191a8e1175bSopenharmony_ci
192a8e1175bSopenharmony_ci            if not line.strip():
193a8e1175bSopenharmony_ci                continue
194a8e1175bSopenharmony_ci
195a8e1175bSopenharmony_ci            for field in line.strip().split(','):
196a8e1175bSopenharmony_ci                if not field.strip():
197a8e1175bSopenharmony_ci                    continue
198a8e1175bSopenharmony_ci                member = field.strip().split()[0]
199a8e1175bSopenharmony_ci                translation_table.append(
200a8e1175bSopenharmony_ci                    '{space}case {member}:\n{space}    return "{member}";'
201a8e1175bSopenharmony_ci                    .format(member=member, space=' '*8)
202a8e1175bSopenharmony_ci                )
203a8e1175bSopenharmony_ci
204a8e1175bSopenharmony_ci        body = textwrap.dedent('''\
205a8e1175bSopenharmony_ci            const char *{name}_str( {prototype} in )
206a8e1175bSopenharmony_ci            {{
207a8e1175bSopenharmony_ci                switch (in) {{
208a8e1175bSopenharmony_ci            {translation_table}
209a8e1175bSopenharmony_ci                    default:
210a8e1175bSopenharmony_ci                        return "UNKNOWN_VALUE";
211a8e1175bSopenharmony_ci                }}
212a8e1175bSopenharmony_ci            }}
213a8e1175bSopenharmony_ci                    ''')
214a8e1175bSopenharmony_ci        body = body.format(translation_table='\n'.join(translation_table),
215a8e1175bSopenharmony_ci                           name=self._name,
216a8e1175bSopenharmony_ci                           prototype=self._prototype)
217a8e1175bSopenharmony_ci        return body
218a8e1175bSopenharmony_ci
219a8e1175bSopenharmony_ci
220a8e1175bSopenharmony_ciclass SignatureAlgorithmDefinition:
221a8e1175bSopenharmony_ci    """
222a8e1175bSopenharmony_ci        Generate helper functions for signature algorithms.
223a8e1175bSopenharmony_ci
224a8e1175bSopenharmony_ci        It generates translation function from signature algorithm define to string.
225a8e1175bSopenharmony_ci        Signature algorithm definition looks like:
226a8e1175bSopenharmony_ci        #define MBEDTLS_TLS1_3_SIG_[ upper case signature algorithm ] [ value(hex) ]
227a8e1175bSopenharmony_ci
228a8e1175bSopenharmony_ci        Known limitation:
229a8e1175bSopenharmony_ci        - the definitions SHOULD  exist in same macro blocks.
230a8e1175bSopenharmony_ci    """
231a8e1175bSopenharmony_ci
232a8e1175bSopenharmony_ci    @classmethod
233a8e1175bSopenharmony_ci    def extract(cls, source_code, start=0, end=-1):
234a8e1175bSopenharmony_ci        sig_alg_pattern = re.compile(r'#define\s+(?P<name>MBEDTLS_TLS1_3_SIG_\w+)\s+' +
235a8e1175bSopenharmony_ci                                     r'(?P<value>0[xX][0-9a-fA-F]+)$',
236a8e1175bSopenharmony_ci                                     re.MULTILINE | re.DOTALL)
237a8e1175bSopenharmony_ci        matches = list(sig_alg_pattern.finditer(source_code, start, end))
238a8e1175bSopenharmony_ci        if matches:
239a8e1175bSopenharmony_ci            yield SignatureAlgorithmDefinition(source_code, definitions=matches)
240a8e1175bSopenharmony_ci
241a8e1175bSopenharmony_ci    def __init__(self, source_code, definitions=None):
242a8e1175bSopenharmony_ci        if definitions is None:
243a8e1175bSopenharmony_ci            definitions = []
244a8e1175bSopenharmony_ci        assert isinstance(definitions, list) and definitions
245a8e1175bSopenharmony_ci        self._definitions = definitions
246a8e1175bSopenharmony_ci        self._source = source_code
247a8e1175bSopenharmony_ci
248a8e1175bSopenharmony_ci    def __repr__(self):
249a8e1175bSopenharmony_ci        return 'SigAlgs({})'.format(self._definitions[0].span())
250a8e1175bSopenharmony_ci
251a8e1175bSopenharmony_ci    def span(self):
252a8e1175bSopenharmony_ci        return self._definitions[0].span()
253a8e1175bSopenharmony_ci
254a8e1175bSopenharmony_ci    def __str__(self):
255a8e1175bSopenharmony_ci        """
256a8e1175bSopenharmony_ci            Generate function for translating value to string
257a8e1175bSopenharmony_ci        """
258a8e1175bSopenharmony_ci        translation_table = []
259a8e1175bSopenharmony_ci        for m in self._definitions:
260a8e1175bSopenharmony_ci            name = m.groupdict()['name']
261a8e1175bSopenharmony_ci            return_val = name[len('MBEDTLS_TLS1_3_SIG_'):].lower()
262a8e1175bSopenharmony_ci            translation_table.append(
263a8e1175bSopenharmony_ci                '    case {}:\n        return "{}";'.format(name, return_val))
264a8e1175bSopenharmony_ci
265a8e1175bSopenharmony_ci        body = textwrap.dedent('''\
266a8e1175bSopenharmony_ci            const char *mbedtls_ssl_sig_alg_to_str( uint16_t in )
267a8e1175bSopenharmony_ci            {{
268a8e1175bSopenharmony_ci                switch( in )
269a8e1175bSopenharmony_ci                {{
270a8e1175bSopenharmony_ci            {translation_table}
271a8e1175bSopenharmony_ci                }};
272a8e1175bSopenharmony_ci
273a8e1175bSopenharmony_ci                return "UNKNOWN";
274a8e1175bSopenharmony_ci            }}''')
275a8e1175bSopenharmony_ci        body = body.format(translation_table='\n'.join(translation_table))
276a8e1175bSopenharmony_ci        return body
277a8e1175bSopenharmony_ci
278a8e1175bSopenharmony_ci
279a8e1175bSopenharmony_ciclass NamedGroupDefinition:
280a8e1175bSopenharmony_ci    """
281a8e1175bSopenharmony_ci        Generate helper functions for named group
282a8e1175bSopenharmony_ci
283a8e1175bSopenharmony_ci        It generates translation function from named group define to string.
284a8e1175bSopenharmony_ci        Named group definition looks like:
285a8e1175bSopenharmony_ci        #define MBEDTLS_SSL_IANA_TLS_GROUP_[ upper case named group ] [ value(hex) ]
286a8e1175bSopenharmony_ci
287a8e1175bSopenharmony_ci        Known limitation:
288a8e1175bSopenharmony_ci        - the definitions SHOULD exist in same macro blocks.
289a8e1175bSopenharmony_ci    """
290a8e1175bSopenharmony_ci
291a8e1175bSopenharmony_ci    @classmethod
292a8e1175bSopenharmony_ci    def extract(cls, source_code, start=0, end=-1):
293a8e1175bSopenharmony_ci        named_group_pattern = re.compile(r'#define\s+(?P<name>MBEDTLS_SSL_IANA_TLS_GROUP_\w+)\s+' +
294a8e1175bSopenharmony_ci                                         r'(?P<value>0[xX][0-9a-fA-F]+)$',
295a8e1175bSopenharmony_ci                                         re.MULTILINE | re.DOTALL)
296a8e1175bSopenharmony_ci        matches = list(named_group_pattern.finditer(source_code, start, end))
297a8e1175bSopenharmony_ci        if matches:
298a8e1175bSopenharmony_ci            yield NamedGroupDefinition(source_code, definitions=matches)
299a8e1175bSopenharmony_ci
300a8e1175bSopenharmony_ci    def __init__(self, source_code, definitions=None):
301a8e1175bSopenharmony_ci        if definitions is None:
302a8e1175bSopenharmony_ci            definitions = []
303a8e1175bSopenharmony_ci        assert isinstance(definitions, list) and definitions
304a8e1175bSopenharmony_ci        self._definitions = definitions
305a8e1175bSopenharmony_ci        self._source = source_code
306a8e1175bSopenharmony_ci
307a8e1175bSopenharmony_ci    def __repr__(self):
308a8e1175bSopenharmony_ci        return 'NamedGroup({})'.format(self._definitions[0].span())
309a8e1175bSopenharmony_ci
310a8e1175bSopenharmony_ci    def span(self):
311a8e1175bSopenharmony_ci        return self._definitions[0].span()
312a8e1175bSopenharmony_ci
313a8e1175bSopenharmony_ci    def __str__(self):
314a8e1175bSopenharmony_ci        """
315a8e1175bSopenharmony_ci            Generate function for translating value to string
316a8e1175bSopenharmony_ci        """
317a8e1175bSopenharmony_ci        translation_table = []
318a8e1175bSopenharmony_ci        for m in self._definitions:
319a8e1175bSopenharmony_ci            name = m.groupdict()['name']
320a8e1175bSopenharmony_ci            iana_name = name[len('MBEDTLS_SSL_IANA_TLS_GROUP_'):].lower()
321a8e1175bSopenharmony_ci            translation_table.append('    case {}:\n        return "{}";'.format(name, iana_name))
322a8e1175bSopenharmony_ci
323a8e1175bSopenharmony_ci        body = textwrap.dedent('''\
324a8e1175bSopenharmony_ci            const char *mbedtls_ssl_named_group_to_str( uint16_t in )
325a8e1175bSopenharmony_ci            {{
326a8e1175bSopenharmony_ci                switch( in )
327a8e1175bSopenharmony_ci                {{
328a8e1175bSopenharmony_ci            {translation_table}
329a8e1175bSopenharmony_ci                }};
330a8e1175bSopenharmony_ci
331a8e1175bSopenharmony_ci                return "UNKOWN";
332a8e1175bSopenharmony_ci            }}''')
333a8e1175bSopenharmony_ci        body = body.format(translation_table='\n'.join(translation_table))
334a8e1175bSopenharmony_ci        return body
335a8e1175bSopenharmony_ci
336a8e1175bSopenharmony_ci
337a8e1175bSopenharmony_ciOUTPUT_C_TEMPLATE = '''\
338a8e1175bSopenharmony_ci/* Automatically generated by generate_ssl_debug_helpers.py. DO NOT EDIT. */
339a8e1175bSopenharmony_ci
340a8e1175bSopenharmony_ci/**
341a8e1175bSopenharmony_ci * \\file ssl_debug_helpers_generated.c
342a8e1175bSopenharmony_ci *
343a8e1175bSopenharmony_ci * \\brief Automatically generated helper functions for debugging
344a8e1175bSopenharmony_ci */
345a8e1175bSopenharmony_ci/*
346a8e1175bSopenharmony_ci *  Copyright The Mbed TLS Contributors
347a8e1175bSopenharmony_ci *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
348a8e1175bSopenharmony_ci *
349a8e1175bSopenharmony_ci */
350a8e1175bSopenharmony_ci
351a8e1175bSopenharmony_ci#include "common.h"
352a8e1175bSopenharmony_ci
353a8e1175bSopenharmony_ci#if defined(MBEDTLS_DEBUG_C)
354a8e1175bSopenharmony_ci
355a8e1175bSopenharmony_ci#include "ssl_debug_helpers.h"
356a8e1175bSopenharmony_ci
357a8e1175bSopenharmony_ci{functions}
358a8e1175bSopenharmony_ci
359a8e1175bSopenharmony_ci#endif /* MBEDTLS_DEBUG_C */
360a8e1175bSopenharmony_ci/* End of automatically generated file. */
361a8e1175bSopenharmony_ci
362a8e1175bSopenharmony_ci'''
363a8e1175bSopenharmony_ci
364a8e1175bSopenharmony_ci
365a8e1175bSopenharmony_cidef generate_ssl_debug_helpers(output_directory, mbedtls_root):
366a8e1175bSopenharmony_ci    """
367a8e1175bSopenharmony_ci        Generate functions of debug helps
368a8e1175bSopenharmony_ci    """
369a8e1175bSopenharmony_ci    mbedtls_root = os.path.abspath(
370a8e1175bSopenharmony_ci        mbedtls_root or build_tree.guess_mbedtls_root())
371a8e1175bSopenharmony_ci    with open(os.path.join(mbedtls_root, 'include/mbedtls/ssl.h')) as f:
372a8e1175bSopenharmony_ci        source_code = remove_c_comments(f.read())
373a8e1175bSopenharmony_ci
374a8e1175bSopenharmony_ci    definitions = dict()
375a8e1175bSopenharmony_ci    for start, instance in preprocess_c_source_code(source_code,
376a8e1175bSopenharmony_ci                                                    EnumDefinition,
377a8e1175bSopenharmony_ci                                                    SignatureAlgorithmDefinition,
378a8e1175bSopenharmony_ci                                                    NamedGroupDefinition):
379a8e1175bSopenharmony_ci        if start in definitions:
380a8e1175bSopenharmony_ci            continue
381a8e1175bSopenharmony_ci        if isinstance(instance, EnumDefinition):
382a8e1175bSopenharmony_ci            definition = instance.generate_translation_function()
383a8e1175bSopenharmony_ci        else:
384a8e1175bSopenharmony_ci            definition = instance
385a8e1175bSopenharmony_ci        definitions[start] = definition
386a8e1175bSopenharmony_ci
387a8e1175bSopenharmony_ci    function_definitions = [str(v) for _, v in sorted(definitions.items())]
388a8e1175bSopenharmony_ci    if output_directory == sys.stdout:
389a8e1175bSopenharmony_ci        sys.stdout.write(OUTPUT_C_TEMPLATE.format(
390a8e1175bSopenharmony_ci            functions='\n'.join(function_definitions)))
391a8e1175bSopenharmony_ci    else:
392a8e1175bSopenharmony_ci        with open(os.path.join(output_directory, 'ssl_debug_helpers_generated.c'), 'w') as f:
393a8e1175bSopenharmony_ci            f.write(OUTPUT_C_TEMPLATE.format(
394a8e1175bSopenharmony_ci                functions='\n'.join(function_definitions)))
395a8e1175bSopenharmony_ci
396a8e1175bSopenharmony_ci
397a8e1175bSopenharmony_cidef main():
398a8e1175bSopenharmony_ci    """
399a8e1175bSopenharmony_ci    Command line entry
400a8e1175bSopenharmony_ci    """
401a8e1175bSopenharmony_ci    parser = argparse.ArgumentParser()
402a8e1175bSopenharmony_ci    parser.add_argument('--mbedtls-root', nargs='?', default=None,
403a8e1175bSopenharmony_ci                        help='root directory of mbedtls source code')
404a8e1175bSopenharmony_ci    parser.add_argument('output_directory', nargs='?',
405a8e1175bSopenharmony_ci                        default='library', help='source/header files location')
406a8e1175bSopenharmony_ci
407a8e1175bSopenharmony_ci    args = parser.parse_args()
408a8e1175bSopenharmony_ci
409a8e1175bSopenharmony_ci    generate_ssl_debug_helpers(args.output_directory, args.mbedtls_root)
410a8e1175bSopenharmony_ci    return 0
411a8e1175bSopenharmony_ci
412a8e1175bSopenharmony_ci
413a8e1175bSopenharmony_ciif __name__ == '__main__':
414a8e1175bSopenharmony_ci    sys.exit(main())
415