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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
|
#!/usr/bin/python
# takes templated file .xxx.src and produces .xxx file where .xxx is .i or .c or .h
# using the following template rules
# /**begin repeat on a line by itself marks the beginning of a segment of code to be repeated
# /**end repeat**/ on a line by itself marks it's end
# after the /**begin repeat and before the */
# all the named templates are placed
# these should all have the same number of replacements
# in the main body, the names are used.
# Each replace will use one entry from the list of named replacements
# Note that all #..# forms in a block must have the same number of
# comma-separated entries.
__all__ = ['process_str', 'process_file']
import string,os,sys
if sys.version[:3]>='2.3':
import re
else:
import pre as re
False = 0
True = 1
def parse_structure(astr):
spanlist = []
# subroutines
ind = 0
while 1:
start = astr.find("/**begin repeat", ind)
if start == -1:
break
start2 = astr.find("*/",start)
start2 = astr.find("\n",start2)
fini1 = astr.find("/**end repeat**/",start2)
fini2 = astr.find("\n",fini1)
spanlist.append((start, start2+1, fini1, fini2+1))
ind = fini2
spanlist.sort()
return spanlist
# return n copies of substr with template replacement
_special_names = {}
template_re = re.compile(r"@([\w]+)@")
named_re = re.compile(r"#([\w]*)=([^#]*?)#")
parenrep = re.compile(r"[(]([^)]*?)[)]\*(\d+)")
def paren_repl(obj):
torep = obj.group(1)
numrep = obj.group(2)
return ','.join([torep]*int(numrep))
plainrep = re.compile(r"([^*]+)\*(\d+)")
def conv(astr):
# replaces all occurrences of '(a,b,c)*4' in astr
# with 'a,b,c,a,b,c,a,b,c,a,b,c'
astr = parenrep.sub(paren_repl,astr)
# replaces occurences of xxx*3 with xxx, xxx, xxx
astr = ','.join([plainrep.sub(paren_repl,x.strip()) for x in astr.split(',')])
return astr
def unique_key(adict):
# this obtains a unique key given a dictionary
# currently it works by appending together n of the letters of the
# current keys and increasing n until a unique key is found
# -- not particularly quick
allkeys = adict.keys()
done = False
n = 1
while not done:
newkey = "".join([x[:n] for x in allkeys])
if newkey in allkeys:
n += 1
else:
done = True
return newkey
def namerepl(match):
global _names, _thissub
name = match.group(1)
return _names[name][_thissub]
def expand_sub(substr,namestr):
global _names, _thissub
# find all named replacements
reps = named_re.findall(namestr)
_names = {}
_names.update(_special_names)
numsubs = None
for rep in reps:
name = rep[0].strip()
thelist = conv(rep[1])
_names[name] = thelist
# make lists out of string entries in name dictionary
for name in _names.keys():
entry = _names[name]
entrylist = entry.split(',')
_names[name] = entrylist
num = len(entrylist)
if numsubs is None:
numsubs = num
elif (numsubs != num):
print namestr
print substr
raise ValueError, "Mismatch in number to replace"
# now replace all keys for each of the lists
mystr = ''
for k in range(numsubs):
_thissub = k
mystr += template_re.sub(namerepl, substr)
mystr += "\n\n"
return mystr
_head = \
"""/* This file was autogenerated from a template DO NOT EDIT!!!!
Changes should be made to the original source (.src) file
*/
"""
def get_line_header(str,beg):
extra = []
ind = beg-1
char = str[ind]
while (ind > 0) and (char != '\n'):
extra.insert(0,char)
ind = ind - 1
char = str[ind]
return ''.join(extra)
def process_str(allstr):
newstr = allstr
writestr = _head
struct = parse_structure(newstr)
# return a (sorted) list of tuples for each begin repeat section
# each tuple is the start and end of a region to be template repeated
oldend = 0
for sub in struct:
writestr += newstr[oldend:sub[0]]
expanded = expand_sub(newstr[sub[1]:sub[2]],newstr[sub[0]:sub[1]])
writestr += expanded
oldend = sub[3]
writestr += newstr[oldend:]
return writestr
include_src_re = re.compile(r"(\n|\A)#include\s*['\"](?P<name>[\w\d./\\]+[.]src)['\"]",re.I)
def resolve_includes(source):
d = os.path.dirname(source)
fid = open(source)
lines = []
for line in fid.readlines():
m = include_src_re.match(line)
if m:
fn = m.group('name')
if not os.path.isabs(fn):
fn = os.path.join(d,fn)
if os.path.isfile(fn):
print 'Including file',fn
lines.extend(resolve_includes(fn))
else:
lines.append(line)
else:
lines.append(line)
fid.close()
return lines
def process_file(source):
lines = resolve_includes(source)
return process_str(''.join(lines))
if __name__ == "__main__":
try:
file = sys.argv[1]
except IndexError:
fid = sys.stdin
outfile = sys.stdout
else:
fid = open(file,'r')
(base, ext) = os.path.splitext(file)
newname = base
outfile = open(newname,'w')
allstr = fid.read()
writestr = process_str(allstr)
outfile.write(writestr)
|