blob: c6eb87aec739960b737fa8cb36d6ff5659e36b81 [file] [log] [blame]
Simon Glassb8c26552023-06-01 10:23:03 -06001#!/usr/bin/env python3
2# SPDX-License-Identifier: GPL-2.0+
3
4"""
5Expo utility - used for testing of expo features
6
7Copyright 2023 Google LLC
8Written by Simon Glass <sjg@chromium.org>
9"""
10
11import argparse
12import collections
13import io
14import re
15import subprocess
16import sys
17
18#from u_boot_pylib import cros_subprocess
19from u_boot_pylib import tools
20
21# Parse:
22# SCENE1 = 7,
23# or SCENE2,
24RE_ENUM = re.compile(r'(\S*)(\s*= (\d))?,')
25
26# Parse #define <name> "string"
27RE_DEF = re.compile(r'#define (\S*)\s*"(.*)"')
28
29def 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
70def 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
100def 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
121def 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
129if __name__ == "__main__":
130 start_expo()