Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of mbed-os by
Diff: tools/misc/remove-device-h.py
- Revision:
- 0:f269e3021894
diff -r 000000000000 -r f269e3021894 tools/misc/remove-device-h.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/misc/remove-device-h.py Sun Oct 23 15:10:02 2016 +0000 @@ -0,0 +1,216 @@ +import json +import os +import stat +import re +from collections import OrderedDict +from subprocess import Popen + +git_processes = [] + +class MyJSONEncoder(json.JSONEncoder): + def __init__(self, *args, **kwargs): + super(MyJSONEncoder, self).__init__(*args, **kwargs) + self.current_indent = 0 + self.current_indent_str = "" + + + def encode(self, o): + #Special Processing for lists + if isinstance(o, (list, tuple)): + primitives_only = True + for item in o: + if isinstance(item, (list, tuple, dict)): + primitives_only = False + break + output = [] + if primitives_only: + for item in o: + output.append(json.dumps(item)) + return "[" + ", ".join(output) + "]" + else: + self.current_indent += self.indent + self.current_indent_str = " " * self.current_indent + for item in o: + output.append(self.current_indent_str + self.encode(item)) + self.current_indent -= self.indent + self.current_indent_str = " " * self.current_indent + return "[\n" + ",\n".join(output) + "\n" + self.current_indent_str + "]" + elif isinstance(o, dict): + primitives_only = True + for item in o.values(): + if isinstance(item, (list, tuple, dict)): + primitives_only = False + break + output = [] + if primitives_only and len(o) < 3: + for key, value in o.iteritems(): + output.append(json.dumps(key) + ": " + self.encode(value)) + return "{" + ", ".join(output) + "}" + else: + self.current_indent += self.indent + self.current_indent_str = " " * self.current_indent + for key, value in o.iteritems(): + output.append(self.current_indent_str + json.dumps(key) + ": " + self.encode(value)) + self.current_indent -= self.indent + self.current_indent_str = " " * self.current_indent + return "{\n" + ",\n".join(output) + "\n" + self.current_indent_str + "}" + else: + return json.dumps(o) + +def load(path): + with open(path, 'r') as f : + return json.load(f, object_pairs_hook=OrderedDict) + +def dump(path, obj): + with os.fdopen(os.open(path, os.O_WRONLY | os.O_CREAT, stat.S_IRUSR | stat.S_IWUSR), 'w') as f : + os.chmod(path, stat.S_IRUSR | stat.S_IWUSR) + f.write(MyJSONEncoder(indent=4).encode(obj)) + f.write(u'\n') + f.truncate() + +def find(stem, path) : + for root, directories, files in os.walk(path, followlinks=True) : + [dir for dir in directories if dir[0] != '.'] + if (stem_match(stem,os.path.basename(os.path.normpath(root))) and + "device.h" in files) : + return os.path.join(root, "device.h") + +def find_all_devices(path, verbose=False) : + for root, directories, files in os.walk(path, followlinks=True) : + [dir for dir in directories if dir[0] != '.'] + if "device.h" in files : + if verbose : print("[VERBOSE] found a device.h file in {}".format(root)) + yield os.path.join(root, "device.h") + +mbed_matcher = re.compile('mbed', re.IGNORECASE) +def stem_match(stem, thing) : + return (stem in thing or + re.sub(mbed_matcher, '', stem) in thing) + +attr_matcher = re.compile('^#define\W+DEVICE_(\w+)\W+1.*$') +def parse_attributes(path) : + with open(path) as input : + for line in input : + m = re.match(attr_matcher, line) + if m: yield m.group(1) + +remove_matcher = re.compile('^#define\W+DEVICE_(\w+)\W+[10].*$') +def remove_attributes(path) : + with open(path) as input : + remainder = filter(lambda l: not re.match(remove_matcher, l), input) + with open(path,"wb") as output : + output.truncate(0) + output.write("// The 'provides' section in 'target.json' is now used"+ + " to create the device's hardware preprocessor switches.\n") + output.write("// Check the 'provides' section of the target description"+ + " in 'targets.json' for more details.\n") + output.writelines(remainder) + +def user_select(things, message) : + print(message) + for thing, number in zip(things, range(len(things))): + print("{} : {}".format(number, thing)) + selection = None + while selection is None : + print("please select an integer [0..{}] or specify all".format(len(things) - 1)) + try : + i = raw_input() + if i == "all" : + selection = "all" + else : + selection = int(i) + if (selection > len(things) or + selection < 0) : + print("selection {} out of range".format(selection)) + selection = None + except (ValueError, SyntaxError) : + print("selection not understood") + if selection == "all" : + return things + else : + return [things[selection]] + +target_matcher = re.compile("TARGET_") +def strip_target(str) : + return re.sub(target_matcher, "", str) + +def add_to_targets(targets, device_file, verbose=False, remove=False) : + if verbose : print("[VERBOSE] trying target {}".format(device_file)) + device = strip_target(os.path.basename(os.path.normpath(os.path.dirname(device_file)))) + if not device : + print("[WARNING] device {} did not have an associated device.h".format(device)) + else : + possible_matches = set([key for key in targets.keys() if stem_match(device, key)]) + for key, value in targets.iteritems() : + for alt in value['extra_labels'] if 'extra_labels' in value else [] : + if stem_match(device, alt) : possible_matches.add(key) + for alt in value['extra_labels_add'] if 'extra_labels_add' in value else [] : + if stem_match(device, alt) : possible_matches.add(key) + possible_matches = list(possible_matches) + for match in possible_matches : + if device == match : possible_matches = [match] + if not possible_matches : + print("[WARNING] device {} did not have an associated entry in targets.json".format(device)) + return None + elif len(possible_matches) > 1 : + message = ("possible matches for file {}".format(device_file)) + target = user_select(possible_matches, message) + else : + target = possible_matches + attrs = list(parse_attributes(device_file)) + if attrs : + for t in target : + targets[t]["device_has"] = sorted(list(set(targets[t].setdefault("device_has",[]) + attrs))) + if verbose : print("[VERBOSE] target {} now device_has {}".format(t, attrs)) + if remove is True: + remove_attributes(device_file) + +if __name__ == '__main__' : + import argparse + parser = argparse.ArgumentParser(description='A helpful little script for converting' + + ' device.h files to parts of the targets.json file') + parser.add_argument('-a', '--all', action='store_true', + help='find and convert all available device.h files in the'+ + ' directory tree starting at the current directory') + parser.add_argument('-f', '--file', nargs='+', help='specify an individual file to '+ + 'convert from device.h format to a piece of targets.json') + parser.add_argument('-t', '--target', nargs='+', help='specify an individual target'+ + ' to convert from device.h format to a piece of targets.json') + parser.add_argument('-v', '--verbose', action='store_true', + help="print out every target that is updated in the targets.json") + parser.add_argument('-r', '--rm', action='store_true', + help="remove the used attributes from a device.h file") + args = parser.parse_args() + if not args.target and not args.file and not args.all : + print("[WARNING] no action specified; auto-formatting targets.json") + + targets_file_name = os.path.join(os.curdir, "hal", "targets.json") + try : + targets = load(targets_file_name) + except OSError : + print("[ERROR] did not find targets.json where I expected it {}".format(targets_file_name)) + exit(1) + except ValueError : + print("[ERROR] invalid json found in {}".format(targets_file_name)) + exit(2) + + if args.target : + for target in args.target : + device_file = find(target, os.curdir) + if device_file : + add_to_targets(targets, device_file, verbose=args.verbose, remove=args.rm) + else : + print("[WARNING] could not locate a device file for target {}".format(target)) + + if args.file : + for file in args.file : + add_to_targets(targets, file, verbose=args.verbose, remove=args.rm) + + if args.all : + for file in find_all_devices(os.curdir, verbose=args.verbose) : + add_to_targets(targets, file, verbose=args.verbose, remove=args.rm) + + dump(targets_file_name, targets) + + for process in git_processes : + process.wait()