Kevin Peng | d65629d | 2021-02-23 09:53:54 +0800 | [diff] [blame^] | 1 | #! /usr/bin/env python3 |
| 2 | # |
| 3 | # ----------------------------------------------------------------------------- |
| 4 | # Copyright (c) 2019, Arm Limited. All rights reserved. |
| 5 | # |
| 6 | # SPDX-License-Identifier: BSD-3-Clause |
| 7 | # |
| 8 | # ----------------------------------------------------------------------------- |
| 9 | |
| 10 | |
| 11 | import re |
| 12 | import os |
| 13 | |
| 14 | expression_re = re.compile(r"[(]?(([(]?(((0x)[0-9a-fA-F]+)|([0-9]+))[)]?)\s*([\+\-]\s*([(]?(((0x)[0-9a-fA-F]+)|([0-9]+))[)]?)\s*)*)[)]?") |
| 15 | |
| 16 | # Simple parser that takes a string and evaluates an expression from it. |
| 17 | # The expression might contain additions and subtractions amongst numbers that |
| 18 | # are written in decimal or hexadecimal form. |
| 19 | # The parses can process expressions in which the parentheses does not change |
| 20 | # the sign of the following number or numbers in an expression. |
| 21 | # Thus the parser can process the following expression: (x + y) |
| 22 | # However it will not calculate the correct sum for the expression below: |
| 23 | # (x - (y + z)) |
| 24 | def parse_and_sum(text): |
| 25 | m = expression_re.match(text) |
| 26 | if m is None: |
| 27 | msg = "The script was probably invoked manually" |
| 28 | msg += " with having certain macros nested in flash_layouts.h.\n" |
| 29 | msg += "Please revisit the flash_layout.h file and hardcode values" |
| 30 | msg += " for the (NON-)SECURE_IMAGE_OFFSET and" |
| 31 | msg += " (NON-)SECURE_IMAGE_MAX_SIZE macros" |
| 32 | raise Exception(msg) |
| 33 | |
| 34 | nums = re.findall(r'(0x[A-Fa-f0-9]+)|[\d]+', m.group(0)) |
| 35 | for i in range(len(nums)): |
| 36 | nums[i] = int(nums[i], 0) |
| 37 | ops = re.findall(r'\+|\-', m.group(0)) |
| 38 | sum = nums[0] |
| 39 | for i in range(len(ops)): |
| 40 | if ops[i] == '+': |
| 41 | sum += nums[i+1] |
| 42 | else: |
| 43 | sum -= nums[i+1] |
| 44 | return sum |
| 45 | |
| 46 | |
| 47 | # Opens a file that contains the macro of interest, then finds the macro with |
| 48 | # a regular expression, parses the expression that is defined for the given |
| 49 | # macro. Lastly it evaluates the expression with the parse_and_sum function |
| 50 | def evaluate_macro(file, regexp, matchGroupKey, matchGroupData, bracketless=False): |
| 51 | regexp_compiled = re.compile(regexp) |
| 52 | |
| 53 | if os.path.isabs(file): |
| 54 | configFile = file |
| 55 | else: |
| 56 | scriptsDir = os.path.dirname(os.path.abspath(__file__)) |
| 57 | configFile = os.path.join(scriptsDir, file) |
| 58 | |
| 59 | macroValue = {} |
| 60 | with open(configFile, 'r') as macros_preprocessed_file: |
| 61 | for line in macros_preprocessed_file: |
| 62 | if bracketless: |
| 63 | line=line.replace("(","") |
| 64 | line=line.replace(")","") |
| 65 | m = regexp_compiled.match(line) |
| 66 | if m is not None: |
| 67 | macroValue[m.group(matchGroupKey)] = \ |
| 68 | parse_and_sum(m.group(matchGroupData)) |
| 69 | |
| 70 | if (matchGroupKey == 0 and not macroValue): |
| 71 | macroValue["None"] = None |
| 72 | |
| 73 | return list(macroValue.values())[0] if (matchGroupKey == 0) else macroValue |