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