linker_script.py 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. #
  2. # SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
  3. # SPDX-License-Identifier: Apache-2.0
  4. #
  5. import collections
  6. import os
  7. from fragments import Fragment
  8. from generation import GenerationException
  9. from pyparsing import ParseException, Suppress, White
  10. class LinkerScript:
  11. """
  12. Process a linker script template, which contains markers with grammar:
  13. [<target>]
  14. The <target> is where output commands (see output_commands.py) are placed.
  15. """
  16. Marker = collections.namedtuple('Marker', 'target indent rules')
  17. def __init__(self, template_file):
  18. self.members = []
  19. self.file = os.path.realpath(template_file.name)
  20. self._generate_members(template_file)
  21. def _generate_members(self, template_file):
  22. lines = template_file.readlines()
  23. target = Fragment.IDENTIFIER
  24. reference = Suppress('mapping') + Suppress('[') + target.setResultsName('target') + Suppress(']')
  25. pattern = White(' \t').setResultsName('indent') + reference
  26. # Find the markers in the template file line by line. If line does not match marker grammar,
  27. # set it as a literal to be copied as is to the output file.
  28. for line in lines:
  29. try:
  30. parsed = pattern.parseString(line)
  31. indent = parsed.indent
  32. target = parsed.target
  33. marker = LinkerScript.Marker(target, indent, [])
  34. self.members.append(marker)
  35. except ParseException:
  36. # Does not match marker syntax
  37. self.members.append(line)
  38. def fill(self, mapping_rules):
  39. for member in self.members:
  40. target = None
  41. try:
  42. target = member.target
  43. rules = member.rules
  44. rules.extend(mapping_rules[target])
  45. except KeyError:
  46. message = GenerationException.UNDEFINED_REFERENCE + " to target '" + target + "'."
  47. raise GenerationException(message)
  48. except AttributeError:
  49. pass
  50. def write(self, output_file):
  51. # Add information that this is a generated file.
  52. output_file.write('/* Automatically generated file; DO NOT EDIT */\n')
  53. output_file.write('/* Espressif IoT Development Framework Linker Script */\n')
  54. output_file.write('/* Generated from: %s */\n' % self.file)
  55. output_file.write('\n')
  56. # Do the text replacement
  57. for member in self.members:
  58. try:
  59. indent = member.indent
  60. rules = member.rules
  61. for rule in rules:
  62. generated_line = ''.join([indent, str(rule), '\n'])
  63. output_file.write(generated_line)
  64. except AttributeError:
  65. output_file.write(member)