-
Notifications
You must be signed in to change notification settings - Fork 8
/
stat_makefile.py
151 lines (124 loc) · 4.47 KB
/
stat_makefile.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#!/usr/bin/env python
# SPDX-FileCopyrightText: (c) 2020 Western Digital Corporation or its affiliates,
# Arseniy Aharonov <[email protected]>
#
# SPDX-License-Identifier: MIT
import os
import re
_STAT_FILE_NAMES_TO_IGNORE = ["stat_build.mak"]
_REG_EXP_VARIABLE = r'\s*(?P<name>\w+)\s*(?P<operand>[:\+]?=)(?P<value>.*)$'
_REG_EXP_SUBSTITUTION = r'\$\((?P<variable>[^\(\)\$]+)\)'
_REG_EXP_INCLUDE = r'^(?:\s+)?(?:\binclude\b)\s+(?P<path>.+\S)(?:\s+)?$'
class StatMakefile(object):
"""
Parser for Makefiles formatted for STAT
"""
SOURCES = 'SOURCES'
INCLUDES = 'INCLUDES'
INTERFACES = 'DUMMY_INTERFACES'
DEFINES = 'DEFINES'
NAME = 'PRODUCT_FLAVOR'
EXEC = 'OUTPUT_EXEC'
OS = 'OS_NAME'
def __init__(self, filePath):
self.__name = os.path.splitext(os.path.basename(filePath))[0]
self.__file = _MakefileReader(filePath)
self.__items = {}
self.__parse()
@property
def name(self):
return self.__name
def __getitem__(self, key):
_key = key.upper()
return self.__items[_key] if _key in self else ''
def __setitem__(self, key, value):
_key = key.upper()
self.__items[_key] = (self.__interpretString(value)).strip()
def __contains__(self, key):
_key = key.upper()
return _key in self.__items
def __iter__(self):
for key in self.__items:
yield key
def __parse(self):
for line in self.__file.readLines():
if not self.__parseForInclude(line):
self.__parseForVariable(line)
def __parseForInclude(self, currentLine):
regexResults = re.search(_REG_EXP_INCLUDE, currentLine, re.IGNORECASE)
if regexResults:
names = regexResults.group('path').split()
for filename in names:
if os.path.basename(filename) not in _STAT_FILE_NAMES_TO_IGNORE:
self.__file.includeNestedFile(filename)
return True
else:
return False
def __parseForVariable(self, currentLine):
regexResults = re.search(_REG_EXP_VARIABLE, currentLine)
if regexResults:
name, operand, value = regexResults.groups()
if operand == "+=":
self[name] += value
else:
self[name] = value
def __interpretString(self, string):
def interpretVariable(regMatch):
variable = regMatch.group('variable')
return self[variable]
return re.sub(_REG_EXP_SUBSTITUTION, interpretVariable, string)
class _MakefileReader(object):
"""
Mak-file reader that allows reading with included files
"""
def __init__(self, filePath):
if not os.path.isfile(filePath):
raise StatMakFileException("Makefile '{fileName}' doesn't exist!".format(fileName=filePath))
self.__filePath = filePath
self.__nested = None
def includeNestedFile(self, filename):
if self.__nested is not None:
self.__nested.includeNestedFile(filename)
elif os.path.isfile(filename):
self.__nested = _MakefileReader(filename)
else:
raise StatMakFileException(
"Attempt to include not existing file '{0}' within '{1}'.".format(filename, self.__filePath))
def getCurrentFilePath(self):
if self.__nested is not None:
return self.__nested.getCurrentFilePath()
else:
return self.__filePath
def readLines(self):
for line in self.__readSyntacticLines():
yield line
for nested in self.__readNestedFileLines():
yield nested
def __readNestedFileLines(self):
if self.__nested is not None:
for line in self.__nested.readLines():
yield line
else:
self.__nested = None
def __readSyntacticLines(self):
line = ''
for nextLine in self.__readTextFileLines():
line = line + nextLine if line else nextLine
if line.endswith('\\'):
line = line[:-1]
continue
yield line
line = ''
else:
if line:
yield line
def __readTextFileLines(self):
_file = open(self.__filePath)
for line in _file:
yield line.rstrip()
else:
_file.close()
class StatMakFileException(Exception):
"""
Custom exception for STAT mak-file parser
"""