#! /usr/bin/env python3 # # ----------------------------------------------------------------------------- # Copyright (c) 2019-2021, Arm Limited. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # # ----------------------------------------------------------------------------- import re import os # Match (((x) + (y))) mode and ((x) + (y)) mode. x, y can be HEX or DEC value. expression_re = re.compile(r"([(]?[(]?[(]?(([(]?(((0x)[0-9a-fA-F]+)|([0-9]+))[)]?)\s*([\+\-]\s*([(]?(((0x)[0-9a-fA-F]+)|([0-9]+))[)]?)\s*)*)[)]?\s*([\+\-])\s*[(]?(([(]?(((0x)[0-9a-fA-F]+)|([0-9]+))[)]?)\s*([\+\-]\s*([(]?(((0x)[0-9a-fA-F]+)|([0-9]+))[)]?)\s*)*)[)]?[)]?[)]?)|([(]?[(]?[(]?(([(]?(((0x)[0-9a-fA-F]+)|([0-9]+))[)]?)\s*([\+\-]\s*([(]?(((0x)[0-9a-fA-F]+)|([0-9]+))[)]?)\s*)*)[)]?[)]?[)]?)") # Simple parser that takes a string and evaluates an expression from it. # The expression might contain additions and subtractions amongst numbers that # are written in decimal or hexadecimal form. # The parses can process expressions in which the parentheses does not change # the sign of the following number or numbers in an expression. # Thus the parser can process the following expression: (x + y) # However it will not calculate the correct sum for the expression below: # (x - (y + z)) def parse_and_sum(text): m = expression_re.match(text) if m is None: msg = "The script was probably invoked manually" msg += " with having certain macros nested in flash_layouts.h.\n" msg += "Please revisit the flash_layout.h file and hardcode values" msg += " for the (NON-)SECURE_IMAGE_OFFSET and" msg += " (NON-)SECURE_IMAGE_MAX_SIZE macros" raise Exception(msg) nums = re.findall(r'0x[A-Fa-f0-9]+|[\d]+', m.group(0)) for i in range(len(nums)): nums[i] = int(nums[i], 0) ops = re.findall(r'\+|\-', m.group(0)) sum = nums[0] for i in range(len(ops)): if ops[i] == '+': sum += nums[i+1] else: sum -= nums[i+1] return sum # Opens a file that contains the macro of interest, then finds the macro with # a regular expression, parses the expression that is defined for the given # macro. Lastly it evaluates the expression with the parse_and_sum function def evaluate_macro(file, regexp, matchGroupKey, matchGroupData, bracketless=False): regexp_compiled = re.compile(regexp) if os.path.isabs(file): configFile = file else: scriptsDir = os.path.dirname(os.path.abspath(__file__)) configFile = os.path.join(scriptsDir, file) macroValue = {} with open(configFile, 'r') as macros_preprocessed_file: for line in macros_preprocessed_file: if bracketless: line=line.replace("(","") line=line.replace(")","") m = regexp_compiled.match(line) if m is not None: macroValue[m.group(matchGroupKey)] = \ parse_and_sum(m.group(matchGroupData)) if (matchGroupKey == 0 and not macroValue): macroValue["None"] = None return list(macroValue.values())[0] if (matchGroupKey == 0) else macroValue