Merge tag 'doc-2023-10-rc5-3' of https://source.denx.de/u-boot/custodians/u-boot-efi
[platform/kernel/u-boot.git] / tools / expo.py
1 #!/usr/bin/env python3
2 # SPDX-License-Identifier: GPL-2.0+
3
4 """
5 Expo utility - used for testing of expo features
6
7 Copyright 2023 Google LLC
8 Written by Simon Glass <sjg@chromium.org>
9 """
10
11 import argparse
12 import collections
13 import io
14 import re
15 import subprocess
16 import sys
17
18 #from u_boot_pylib import cros_subprocess
19 from u_boot_pylib import tools
20
21 # Parse:
22 #       SCENE1          = 7,
23 # or    SCENE2,
24 RE_ENUM = re.compile(r'(\S*)(\s*= (\d))?,')
25
26 # Parse #define <name>  "string"
27 RE_DEF = re.compile(r'#define (\S*)\s*"(.*)"')
28
29 def calc_ids(fname):
30     """Figure out the value of the enums in a C file
31
32     Args:
33         fname (str): Filename to parse
34
35     Returns:
36         OrderedDict():
37             key (str): enum name
38             value (int or str):
39                 Value of enum, if int
40                 Value of #define, if string
41     """
42     vals = collections.OrderedDict()
43     with open(fname, 'r', encoding='utf-8') as inf:
44         in_enum = False
45         cur_id = 0
46         for line in inf.readlines():
47             line = line.strip()
48             if line == 'enum {':
49                 in_enum = True
50                 continue
51             if in_enum and line == '};':
52                 in_enum = False
53
54             if in_enum:
55                 if not line or line.startswith('/*'):
56                     continue
57                 m_enum = RE_ENUM.match(line)
58                 if m_enum.group(3):
59                     cur_id = int(m_enum.group(3))
60                 vals[m_enum.group(1)] = cur_id
61                 cur_id += 1
62             else:
63                 m_def = RE_DEF.match(line)
64                 if m_def:
65                     vals[m_def.group(1)] = tools.to_bytes(m_def.group(2))
66
67     return vals
68
69
70 def run_expo(args):
71     """Run the expo program"""
72     ids = calc_ids(args.enum_fname)
73
74     indata = tools.read_file(args.layout)
75
76     outf = io.BytesIO()
77
78     for name, val in ids.items():
79         if isinstance(val, int):
80             outval = b'%d' % val
81         else:
82             outval = b'"%s"' % val
83         find_str = r'\b%s\b' % name
84         indata = re.sub(tools.to_bytes(find_str), outval, indata)
85
86     outf.write(indata)
87     data = outf.getvalue()
88
89     with open('/tmp/asc', 'wb') as outf:
90         outf.write(data)
91     proc = subprocess.run('dtc', input=data, capture_output=True, check=True)
92     edtb = proc.stdout
93     if proc.stderr:
94         print(proc.stderr)
95         return 1
96     tools.write_file(args.outfile, edtb)
97     return 0
98
99
100 def parse_args(argv):
101     """Parse the command-line arguments
102
103     Args:
104         argv (list of str): List of string arguments
105
106     Returns:
107         tuple: (options, args) with the command-line options and arugments.
108             options provides access to the options (e.g. option.debug)
109             args is a list of string arguments
110     """
111     parser = argparse.ArgumentParser()
112     parser.add_argument('-e', '--enum-fname', type=str,
113         help='C file containing enum declaration for expo items')
114     parser.add_argument('-l', '--layout', type=str,
115         help='Devicetree file source .dts for expo layout')
116     parser.add_argument('-o', '--outfile', type=str,
117         help='Filename to write expo layout dtb')
118
119     return parser.parse_args(argv)
120
121 def start_expo():
122     """Start the expo program"""
123     args = parse_args(sys.argv[1:])
124
125     ret_code = run_expo(args)
126     sys.exit(ret_code)
127
128
129 if __name__ == "__main__":
130     start_expo()