expo.py 3.3 KB

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