1#!/usr/bin/env python3
2#
3# Copyright (c) 2022 Meta
4#
5# SPDX-License-Identifier: Apache-2.0
6
7import argparse
8import os
9import re
10
11
12def front_matter(sys_nerr):
13    return f'''
14/*
15 * This file generated by {__file__}
16 */
17
18#include <errno.h>
19#include <stdint.h>
20#include <string.h>
21
22#include <zephyr/sys/util.h>
23
24#define sys_nerr {sys_nerr}'''
25
26
27def gen_strerror_table(input, output):
28    with open(input) as inf:
29        highest_errno = 0
30        symbols = []
31        msgs = {}
32
33        for line in inf.readlines():
34            # Select items of the form below (note: ERRNO is numeric)
35            # #define SYMBOL ERRNO /**< MSG */
36            pat = r'^#define[\s]+(E[A-Z_]*)[\s]+([1-9][0-9]*)[\s]+/\*\*<[\s]+(.*)[\s]+\*/[\s]*$'
37            match = re.match(pat, line)
38
39            if not match:
40                continue
41
42            symbol = match[1]
43            errno = int(match[2])
44            msg = match[3]
45
46            symbols.append(symbol)
47            msgs[symbol] = msg
48
49            highest_errno = max(int(errno), highest_errno)
50
51        os.makedirs(os.path.dirname(output), exist_ok=True)
52
53        with open(output, 'w') as outf:
54            print(front_matter(highest_errno + 1), file=outf)
55
56            # Generate string table
57            print('static const char *const sys_errlist[sys_nerr] = {', file=outf)
58            print('[0] = "Success",', file=outf)
59            for symbol in symbols:
60                print(f'[{symbol}] = "{msgs[symbol]}",', file=outf)
61
62            print('};', file=outf)
63
64            # Generate string lengths (includes trailing '\0')
65            print('static const uint8_t sys_errlen[sys_nerr] = {', file=outf)
66            print('[0] = 8,', file=outf)
67            for symbol in symbols:
68                print(f'[{symbol}] = {len(msgs[symbol]) + 1},', file=outf)
69
70            print('};', file=outf)
71
72
73def parse_args():
74    parser = argparse.ArgumentParser(allow_abbrev=False)
75    parser.add_argument(
76        '-i',
77        '--input',
78        dest='input',
79        required=True,
80        help='input file (e.g. lib/libc/minimal/include/errno.h)',
81    )
82    parser.add_argument(
83        '-o',
84        '--output',
85        dest='output',
86        required=True,
87        help='output file (e.g. build/zephyr/misc/generated/libc/minimal/strerror_table.h)',
88    )
89
90    args = parser.parse_args()
91
92    return args
93
94
95def main():
96    args = parse_args()
97    gen_strerror_table(args.input, args.output)
98
99
100if __name__ == '__main__':
101    main()
102