forked from micropython/micropython-esp32-ulp
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpreprocess.py
107 lines (88 loc) · 3.14 KB
/
preprocess.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
from . import nocomment
from .util import split_tokens
class RTC_Macros:
@staticmethod
def READ_RTC_REG(rtc_reg, low_bit, bit_width):
return '\treg_rd ' + ', '.join((
rtc_reg,
'%s + %s - 1' % (low_bit, bit_width),
low_bit
))
@staticmethod
def WRITE_RTC_REG(rtc_reg, low_bit, bit_width, value):
args = (
rtc_reg,
'%s + %s - 1' % (low_bit, bit_width),
low_bit,
value
)
return '\treg_wr ' + ', '.join(args)
@staticmethod
def READ_RTC_FIELD(rtc_reg, low_bit):
return RTC_Macros.READ_RTC_REG(rtc_reg, low_bit, 1)
@staticmethod
def WRITE_RTC_FIELD(rtc_reg, low_bit, value):
return RTC_Macros.WRITE_RTC_REG(rtc_reg, low_bit, 1, value + ' & 1')
class Preprocessor:
def __init__(self):
self._defines = {}
def parse_defines(self, content):
result = {}
for line in content.splitlines():
line = line.strip()
if not line.startswith("#define"):
# skip lines not containing #define
continue
line = line[8:].strip() # remove #define
parts = line.split(None, 1)
if len(parts) != 2:
# skip defines without value
continue
identifier, value = parts
tmp = identifier.split('(', 1)
if len(tmp) == 2:
# skip parameterised defines (macros)
continue
value = "".join(nocomment.remove_comments(value)).strip()
result[identifier] = value
self._defines = result
return result
def expand_defines(self, line):
found = True
while found: # do as many passed as needed, until nothing was replaced anymore
found = False
tokens = split_tokens(line)
line = ""
for t in tokens:
lu = self._defines.get(t, t)
if lu != t:
found = True
line += lu
return line
def expand_rtc_macros(self, line):
clean_line = line.strip()
if not clean_line:
return line
macro = clean_line.split('(', 1)
if len(macro) != 2:
return line
macro_name, macro_args = macro
macro_fn = getattr(RTC_Macros, macro_name, None)
if macro_fn is None:
return line
macro_args, _ = macro_args.rsplit(')', 1) # trim away right bracket. safe as comments already stripped
macro_args = macro_args.split(',') # not safe when args contain ',' but we should not have those
macro_args = [x.strip() for x in macro_args]
return macro_fn(*macro_args)
def preprocess(self, content):
self.parse_defines(content)
lines = nocomment.remove_comments(content)
result = []
for line in lines:
line = self.expand_defines(line)
line = self.expand_rtc_macros(line)
result.append(line)
result = "\n".join(result)
return result
def preprocess(content):
return Preprocessor().preprocess(content)