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