User | Revision | Line number | New contents of line |
switches |
0:0e018d759a2a
|
1
|
import json
|
switches |
0:0e018d759a2a
|
2
|
import os
|
switches |
0:0e018d759a2a
|
3
|
import stat
|
switches |
0:0e018d759a2a
|
4
|
import re
|
switches |
0:0e018d759a2a
|
5
|
from collections import OrderedDict
|
switches |
0:0e018d759a2a
|
6
|
from subprocess import Popen
|
switches |
0:0e018d759a2a
|
7
|
|
switches |
0:0e018d759a2a
|
8
|
git_processes = []
|
switches |
0:0e018d759a2a
|
9
|
|
switches |
0:0e018d759a2a
|
10
|
class MyJSONEncoder(json.JSONEncoder):
|
switches |
0:0e018d759a2a
|
11
|
def __init__(self, *args, **kwargs):
|
switches |
0:0e018d759a2a
|
12
|
super(MyJSONEncoder, self).__init__(*args, **kwargs)
|
switches |
0:0e018d759a2a
|
13
|
self.current_indent = 0
|
switches |
0:0e018d759a2a
|
14
|
self.current_indent_str = ""
|
switches |
0:0e018d759a2a
|
15
|
|
switches |
0:0e018d759a2a
|
16
|
|
switches |
0:0e018d759a2a
|
17
|
def encode(self, o):
|
switches |
0:0e018d759a2a
|
18
|
#Special Processing for lists
|
switches |
0:0e018d759a2a
|
19
|
if isinstance(o, (list, tuple)):
|
switches |
0:0e018d759a2a
|
20
|
primitives_only = True
|
switches |
0:0e018d759a2a
|
21
|
for item in o:
|
switches |
0:0e018d759a2a
|
22
|
if isinstance(item, (list, tuple, dict)):
|
switches |
0:0e018d759a2a
|
23
|
primitives_only = False
|
switches |
0:0e018d759a2a
|
24
|
break
|
switches |
0:0e018d759a2a
|
25
|
output = []
|
switches |
0:0e018d759a2a
|
26
|
if primitives_only:
|
switches |
0:0e018d759a2a
|
27
|
for item in o:
|
switches |
0:0e018d759a2a
|
28
|
output.append(json.dumps(item))
|
switches |
0:0e018d759a2a
|
29
|
return "[" + ", ".join(output) + "]"
|
switches |
0:0e018d759a2a
|
30
|
else:
|
switches |
0:0e018d759a2a
|
31
|
self.current_indent += self.indent
|
switches |
0:0e018d759a2a
|
32
|
self.current_indent_str = " " * self.current_indent
|
switches |
0:0e018d759a2a
|
33
|
for item in o:
|
switches |
0:0e018d759a2a
|
34
|
output.append(self.current_indent_str + self.encode(item))
|
switches |
0:0e018d759a2a
|
35
|
self.current_indent -= self.indent
|
switches |
0:0e018d759a2a
|
36
|
self.current_indent_str = " " * self.current_indent
|
switches |
0:0e018d759a2a
|
37
|
return "[\n" + ",\n".join(output) + "\n" + self.current_indent_str + "]"
|
switches |
0:0e018d759a2a
|
38
|
elif isinstance(o, dict):
|
switches |
0:0e018d759a2a
|
39
|
primitives_only = True
|
switches |
0:0e018d759a2a
|
40
|
for item in o.values():
|
switches |
0:0e018d759a2a
|
41
|
if isinstance(item, (list, tuple, dict)):
|
switches |
0:0e018d759a2a
|
42
|
primitives_only = False
|
switches |
0:0e018d759a2a
|
43
|
break
|
switches |
0:0e018d759a2a
|
44
|
output = []
|
switches |
0:0e018d759a2a
|
45
|
if primitives_only and len(o) < 3:
|
switches |
0:0e018d759a2a
|
46
|
for key, value in o.iteritems():
|
switches |
0:0e018d759a2a
|
47
|
output.append(json.dumps(key) + ": " + self.encode(value))
|
switches |
0:0e018d759a2a
|
48
|
return "{" + ", ".join(output) + "}"
|
switches |
0:0e018d759a2a
|
49
|
else:
|
switches |
0:0e018d759a2a
|
50
|
self.current_indent += self.indent
|
switches |
0:0e018d759a2a
|
51
|
self.current_indent_str = " " * self.current_indent
|
switches |
0:0e018d759a2a
|
52
|
for key, value in o.iteritems():
|
switches |
0:0e018d759a2a
|
53
|
output.append(self.current_indent_str + json.dumps(key) + ": " + self.encode(value))
|
switches |
0:0e018d759a2a
|
54
|
self.current_indent -= self.indent
|
switches |
0:0e018d759a2a
|
55
|
self.current_indent_str = " " * self.current_indent
|
switches |
0:0e018d759a2a
|
56
|
return "{\n" + ",\n".join(output) + "\n" + self.current_indent_str + "}"
|
switches |
0:0e018d759a2a
|
57
|
else:
|
switches |
0:0e018d759a2a
|
58
|
return json.dumps(o)
|
switches |
0:0e018d759a2a
|
59
|
|
switches |
0:0e018d759a2a
|
60
|
def load(path):
|
switches |
0:0e018d759a2a
|
61
|
with open(path, 'r') as f :
|
switches |
0:0e018d759a2a
|
62
|
return json.load(f, object_pairs_hook=OrderedDict)
|
switches |
0:0e018d759a2a
|
63
|
|
switches |
0:0e018d759a2a
|
64
|
def dump(path, obj):
|
switches |
0:0e018d759a2a
|
65
|
with os.fdopen(os.open(path, os.O_WRONLY | os.O_CREAT, stat.S_IRUSR | stat.S_IWUSR), 'w') as f :
|
switches |
0:0e018d759a2a
|
66
|
os.chmod(path, stat.S_IRUSR | stat.S_IWUSR)
|
switches |
0:0e018d759a2a
|
67
|
f.write(MyJSONEncoder(indent=4).encode(obj))
|
switches |
0:0e018d759a2a
|
68
|
f.write(u'\n')
|
switches |
0:0e018d759a2a
|
69
|
f.truncate()
|
switches |
0:0e018d759a2a
|
70
|
|
switches |
0:0e018d759a2a
|
71
|
def find(stem, path) :
|
switches |
0:0e018d759a2a
|
72
|
for root, directories, files in os.walk(path, followlinks=True) :
|
switches |
0:0e018d759a2a
|
73
|
[dir for dir in directories if dir[0] != '.']
|
switches |
0:0e018d759a2a
|
74
|
if (stem_match(stem,os.path.basename(os.path.normpath(root))) and
|
switches |
0:0e018d759a2a
|
75
|
"device.h" in files) :
|
switches |
0:0e018d759a2a
|
76
|
return os.path.join(root, "device.h")
|
switches |
0:0e018d759a2a
|
77
|
|
switches |
0:0e018d759a2a
|
78
|
def find_all_devices(path, verbose=False) :
|
switches |
0:0e018d759a2a
|
79
|
for root, directories, files in os.walk(path, followlinks=True) :
|
switches |
0:0e018d759a2a
|
80
|
[dir for dir in directories if dir[0] != '.']
|
switches |
0:0e018d759a2a
|
81
|
if "device.h" in files :
|
switches |
0:0e018d759a2a
|
82
|
if verbose : print("[VERBOSE] found a device.h file in {}".format(root))
|
switches |
0:0e018d759a2a
|
83
|
yield os.path.join(root, "device.h")
|
switches |
0:0e018d759a2a
|
84
|
|
switches |
0:0e018d759a2a
|
85
|
mbed_matcher = re.compile('mbed', re.IGNORECASE)
|
switches |
0:0e018d759a2a
|
86
|
def stem_match(stem, thing) :
|
switches |
0:0e018d759a2a
|
87
|
return (stem in thing or
|
switches |
0:0e018d759a2a
|
88
|
re.sub(mbed_matcher, '', stem) in thing)
|
switches |
0:0e018d759a2a
|
89
|
|
switches |
0:0e018d759a2a
|
90
|
attr_matcher = re.compile('^#define\W+DEVICE_(\w+)\W+1.*$')
|
switches |
0:0e018d759a2a
|
91
|
def parse_attributes(path) :
|
switches |
0:0e018d759a2a
|
92
|
with open(path) as input :
|
switches |
0:0e018d759a2a
|
93
|
for line in input :
|
switches |
0:0e018d759a2a
|
94
|
m = re.match(attr_matcher, line)
|
switches |
0:0e018d759a2a
|
95
|
if m: yield m.group(1)
|
switches |
0:0e018d759a2a
|
96
|
|
switches |
0:0e018d759a2a
|
97
|
remove_matcher = re.compile('^#define\W+DEVICE_(\w+)\W+[10].*$')
|
switches |
0:0e018d759a2a
|
98
|
def remove_attributes(path) :
|
switches |
0:0e018d759a2a
|
99
|
with open(path) as input :
|
switches |
0:0e018d759a2a
|
100
|
remainder = filter(lambda l: not re.match(remove_matcher, l), input)
|
switches |
0:0e018d759a2a
|
101
|
with open(path,"wb") as output :
|
switches |
0:0e018d759a2a
|
102
|
output.truncate(0)
|
switches |
0:0e018d759a2a
|
103
|
output.write("// The 'provides' section in 'target.json' is now used"+
|
switches |
0:0e018d759a2a
|
104
|
" to create the device's hardware preprocessor switches.\n")
|
switches |
0:0e018d759a2a
|
105
|
output.write("// Check the 'provides' section of the target description"+
|
switches |
0:0e018d759a2a
|
106
|
" in 'targets.json' for more details.\n")
|
switches |
0:0e018d759a2a
|
107
|
output.writelines(remainder)
|
switches |
0:0e018d759a2a
|
108
|
|
switches |
0:0e018d759a2a
|
109
|
def user_select(things, message) :
|
switches |
0:0e018d759a2a
|
110
|
print(message)
|
switches |
0:0e018d759a2a
|
111
|
for thing, number in zip(things, range(len(things))):
|
switches |
0:0e018d759a2a
|
112
|
print("{} : {}".format(number, thing))
|
switches |
0:0e018d759a2a
|
113
|
selection = None
|
switches |
0:0e018d759a2a
|
114
|
while selection is None :
|
switches |
0:0e018d759a2a
|
115
|
print("please select an integer [0..{}] or specify all".format(len(things) - 1))
|
switches |
0:0e018d759a2a
|
116
|
try :
|
switches |
0:0e018d759a2a
|
117
|
i = raw_input()
|
switches |
0:0e018d759a2a
|
118
|
if i == "all" :
|
switches |
0:0e018d759a2a
|
119
|
selection = "all"
|
switches |
0:0e018d759a2a
|
120
|
else :
|
switches |
0:0e018d759a2a
|
121
|
selection = int(i)
|
switches |
0:0e018d759a2a
|
122
|
if (selection > len(things) or
|
switches |
0:0e018d759a2a
|
123
|
selection < 0) :
|
switches |
0:0e018d759a2a
|
124
|
print("selection {} out of range".format(selection))
|
switches |
0:0e018d759a2a
|
125
|
selection = None
|
switches |
0:0e018d759a2a
|
126
|
except (ValueError, SyntaxError) :
|
switches |
0:0e018d759a2a
|
127
|
print("selection not understood")
|
switches |
0:0e018d759a2a
|
128
|
if selection == "all" :
|
switches |
0:0e018d759a2a
|
129
|
return things
|
switches |
0:0e018d759a2a
|
130
|
else :
|
switches |
0:0e018d759a2a
|
131
|
return [things[selection]]
|
switches |
0:0e018d759a2a
|
132
|
|
switches |
0:0e018d759a2a
|
133
|
target_matcher = re.compile("TARGET_")
|
switches |
0:0e018d759a2a
|
134
|
def strip_target(str) :
|
switches |
0:0e018d759a2a
|
135
|
return re.sub(target_matcher, "", str)
|
switches |
0:0e018d759a2a
|
136
|
|
switches |
0:0e018d759a2a
|
137
|
def add_to_targets(targets, device_file, verbose=False, remove=False) :
|
switches |
0:0e018d759a2a
|
138
|
if verbose : print("[VERBOSE] trying target {}".format(device_file))
|
switches |
0:0e018d759a2a
|
139
|
device = strip_target(os.path.basename(os.path.normpath(os.path.dirname(device_file))))
|
switches |
0:0e018d759a2a
|
140
|
if not device :
|
switches |
0:0e018d759a2a
|
141
|
print("[WARNING] device {} did not have an associated device.h".format(device))
|
switches |
0:0e018d759a2a
|
142
|
else :
|
switches |
0:0e018d759a2a
|
143
|
possible_matches = set([key for key in targets.keys() if stem_match(device, key)])
|
switches |
0:0e018d759a2a
|
144
|
for key, value in targets.iteritems() :
|
switches |
0:0e018d759a2a
|
145
|
for alt in value['extra_labels'] if 'extra_labels' in value else [] :
|
switches |
0:0e018d759a2a
|
146
|
if stem_match(device, alt) : possible_matches.add(key)
|
switches |
0:0e018d759a2a
|
147
|
for alt in value['extra_labels_add'] if 'extra_labels_add' in value else [] :
|
switches |
0:0e018d759a2a
|
148
|
if stem_match(device, alt) : possible_matches.add(key)
|
switches |
0:0e018d759a2a
|
149
|
possible_matches = list(possible_matches)
|
switches |
0:0e018d759a2a
|
150
|
for match in possible_matches :
|
switches |
0:0e018d759a2a
|
151
|
if device == match : possible_matches = [match]
|
switches |
0:0e018d759a2a
|
152
|
if not possible_matches :
|
switches |
0:0e018d759a2a
|
153
|
print("[WARNING] device {} did not have an associated entry in targets.json".format(device))
|
switches |
0:0e018d759a2a
|
154
|
return None
|
switches |
0:0e018d759a2a
|
155
|
elif len(possible_matches) > 1 :
|
switches |
0:0e018d759a2a
|
156
|
message = ("possible matches for file {}".format(device_file))
|
switches |
0:0e018d759a2a
|
157
|
target = user_select(possible_matches, message)
|
switches |
0:0e018d759a2a
|
158
|
else :
|
switches |
0:0e018d759a2a
|
159
|
target = possible_matches
|
switches |
0:0e018d759a2a
|
160
|
attrs = list(parse_attributes(device_file))
|
switches |
0:0e018d759a2a
|
161
|
if attrs :
|
switches |
0:0e018d759a2a
|
162
|
for t in target :
|
switches |
0:0e018d759a2a
|
163
|
targets[t]["device_has"] = sorted(list(set(targets[t].setdefault("device_has",[]) + attrs)))
|
switches |
0:0e018d759a2a
|
164
|
if verbose : print("[VERBOSE] target {} now device_has {}".format(t, attrs))
|
switches |
0:0e018d759a2a
|
165
|
if remove is True:
|
switches |
0:0e018d759a2a
|
166
|
remove_attributes(device_file)
|
switches |
0:0e018d759a2a
|
167
|
|
switches |
0:0e018d759a2a
|
168
|
if __name__ == '__main__' :
|
switches |
0:0e018d759a2a
|
169
|
import argparse
|
switches |
0:0e018d759a2a
|
170
|
parser = argparse.ArgumentParser(description='A helpful little script for converting' +
|
switches |
0:0e018d759a2a
|
171
|
' device.h files to parts of the targets.json file')
|
switches |
0:0e018d759a2a
|
172
|
parser.add_argument('-a', '--all', action='store_true',
|
switches |
0:0e018d759a2a
|
173
|
help='find and convert all available device.h files in the'+
|
switches |
0:0e018d759a2a
|
174
|
' directory tree starting at the current directory')
|
switches |
0:0e018d759a2a
|
175
|
parser.add_argument('-f', '--file', nargs='+', help='specify an individual file to '+
|
switches |
0:0e018d759a2a
|
176
|
'convert from device.h format to a piece of targets.json')
|
switches |
0:0e018d759a2a
|
177
|
parser.add_argument('-t', '--target', nargs='+', help='specify an individual target'+
|
switches |
0:0e018d759a2a
|
178
|
' to convert from device.h format to a piece of targets.json')
|
switches |
0:0e018d759a2a
|
179
|
parser.add_argument('-v', '--verbose', action='store_true',
|
switches |
0:0e018d759a2a
|
180
|
help="print out every target that is updated in the targets.json")
|
switches |
0:0e018d759a2a
|
181
|
parser.add_argument('-r', '--rm', action='store_true',
|
switches |
0:0e018d759a2a
|
182
|
help="remove the used attributes from a device.h file")
|
switches |
0:0e018d759a2a
|
183
|
args = parser.parse_args()
|
switches |
0:0e018d759a2a
|
184
|
if not args.target and not args.file and not args.all :
|
switches |
0:0e018d759a2a
|
185
|
print("[WARNING] no action specified; auto-formatting targets.json")
|
switches |
0:0e018d759a2a
|
186
|
|
switches |
0:0e018d759a2a
|
187
|
targets_file_name = os.path.join(os.curdir, "hal", "targets.json")
|
switches |
0:0e018d759a2a
|
188
|
try :
|
switches |
0:0e018d759a2a
|
189
|
targets = load(targets_file_name)
|
switches |
0:0e018d759a2a
|
190
|
except OSError :
|
switches |
0:0e018d759a2a
|
191
|
print("[ERROR] did not find targets.json where I expected it {}".format(targets_file_name))
|
switches |
0:0e018d759a2a
|
192
|
exit(1)
|
switches |
0:0e018d759a2a
|
193
|
except ValueError :
|
switches |
0:0e018d759a2a
|
194
|
print("[ERROR] invalid json found in {}".format(targets_file_name))
|
switches |
0:0e018d759a2a
|
195
|
exit(2)
|
switches |
0:0e018d759a2a
|
196
|
|
switches |
0:0e018d759a2a
|
197
|
if args.target :
|
switches |
0:0e018d759a2a
|
198
|
for target in args.target :
|
switches |
0:0e018d759a2a
|
199
|
device_file = find(target, os.curdir)
|
switches |
0:0e018d759a2a
|
200
|
if device_file :
|
switches |
0:0e018d759a2a
|
201
|
add_to_targets(targets, device_file, verbose=args.verbose, remove=args.rm)
|
switches |
0:0e018d759a2a
|
202
|
else :
|
switches |
0:0e018d759a2a
|
203
|
print("[WARNING] could not locate a device file for target {}".format(target))
|
switches |
0:0e018d759a2a
|
204
|
|
switches |
0:0e018d759a2a
|
205
|
if args.file :
|
switches |
0:0e018d759a2a
|
206
|
for file in args.file :
|
switches |
0:0e018d759a2a
|
207
|
add_to_targets(targets, file, verbose=args.verbose, remove=args.rm)
|
switches |
0:0e018d759a2a
|
208
|
|
switches |
0:0e018d759a2a
|
209
|
if args.all :
|
switches |
0:0e018d759a2a
|
210
|
for file in find_all_devices(os.curdir, verbose=args.verbose) :
|
switches |
0:0e018d759a2a
|
211
|
add_to_targets(targets, file, verbose=args.verbose, remove=args.rm)
|
switches |
0:0e018d759a2a
|
212
|
|
switches |
0:0e018d759a2a
|
213
|
dump(targets_file_name, targets)
|
switches |
0:0e018d759a2a
|
214
|
|
switches |
0:0e018d759a2a
|
215
|
for process in git_processes :
|
switches |
0:0e018d759a2a
|
216
|
process.wait()
|