1# 2# Copyright 2021 Espressif Systems (Shanghai) CO LTD 3# 4# Licensed under the Apache License, Version 2.0 (the "License"); 5# you may not use this file except in compliance with the License. 6# You may obtain a copy of the License at 7# 8# http://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an "AS IS" BASIS, 12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13# See the License for the specific language governing permissions and 14# limitations under the License. 15# 16 17import collections 18import os 19 20from fragments import Fragment 21from generation import GenerationException 22from pyparsing import ParseException, Suppress, White 23 24 25class LinkerScript: 26 """ 27 Process a linker script template, which contains markers with grammar: 28 29 [<target>] 30 31 The <target> is where output commands (see output_commands.py) are placed. 32 """ 33 34 Marker = collections.namedtuple('Marker', 'target indent rules') 35 36 def __init__(self, template_file): 37 self.members = [] 38 self.file = os.path.realpath(template_file.name) 39 40 self._generate_members(template_file) 41 42 def _generate_members(self, template_file): 43 lines = template_file.readlines() 44 45 target = Fragment.IDENTIFIER 46 reference = Suppress('mapping') + Suppress('[') + target.setResultsName('target') + Suppress(']') 47 pattern = White(' \t').setResultsName('indent') + reference 48 49 # Find the markers in the template file line by line. If line does not match marker grammar, 50 # set it as a literal to be copied as is to the output file. 51 for line in lines: 52 try: 53 parsed = pattern.parseString(line) 54 55 indent = parsed.indent 56 target = parsed.target 57 58 marker = LinkerScript.Marker(target, indent, []) 59 60 self.members.append(marker) 61 except ParseException: 62 # Does not match marker syntax 63 self.members.append(line) 64 65 def fill(self, mapping_rules): 66 for member in self.members: 67 target = None 68 try: 69 target = member.target 70 rules = member.rules 71 72 del rules[:] 73 74 rules.extend(mapping_rules[target]) 75 except KeyError: 76 message = GenerationException.UNDEFINED_REFERENCE + " to target '" + target + "'." 77 raise GenerationException(message) 78 except AttributeError: 79 pass 80 81 def write(self, output_file): 82 # Add information that this is a generated file. 83 output_file.write('/* Automatically generated file; DO NOT EDIT */\n') 84 output_file.write('/* Espressif IoT Development Framework Linker Script */\n') 85 output_file.write('/* Generated from: %s */\n' % self.file) 86 output_file.write('\n') 87 88 # Do the text replacement 89 for member in self.members: 90 try: 91 indent = member.indent 92 rules = member.rules 93 94 for rule in rules: 95 generated_line = ''.join([indent, str(rule), '\n']) 96 output_file.write(generated_line) 97 except AttributeError: 98 output_file.write(member) 99