diff options
Diffstat (limited to 'tools')
-rwxr-xr-x | tools/highlevel_c.py | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/tools/highlevel_c.py b/tools/highlevel_c.py new file mode 100755 index 0000000..2cff3b3 --- /dev/null +++ b/tools/highlevel_c.py @@ -0,0 +1,81 @@ +#!/usr/bin/env python2 + +import os +import sys +import json +import clang.cindex + +def find_child_of_kind(node, kind): + if node.kind == kind: + return node + for child in node.get_children(): + found_type = find_child_of_kind(child, kind) + if found_type: + return found_type + +def get_types_from_annotation(annotation): + return [t.replace(" ", "") for t in annotation.split(",")] + +def parse_call_expr(call_expr): + if call_expr.spelling == "hash_map_get" or call_expr.spelling == "hash_map_insert": + args = list(call_expr.get_arguments()) + + # First arg + self_obj = next(args[0].get_children(), None) + self_obj_def = self_obj.get_definition() + annotation = next(self_obj_def.get_children(), None) + if not annotation or annotation.kind != clang.cindex.CursorKind.ANNOTATE_ATTR: + print("WARNING: Hash map at %s is not annotated" % args[0].location) + return + + (hash_map_key_type, hash_map_value_type) = get_types_from_annotation(annotation.spelling) + hash_map_value_type = hash_map_value_type + "*" + + # Second arg + #key_arg_type = args[1].type.spelling.replace(" ", "") + #if key_arg_type != hash_map_key_type: + # print("Error: Incorrect usage of %s key argument found at %s." % (call_expr.spelling, args[1].location)) + # print(" Argument variable is of type %s, but the HashMap expects a value of type %s" % (key_arg_type, hash_map_key_type)) + + # Third arg + value_obj = next(args[2].get_children(), None) + value_arg_type = value_obj.type.spelling.replace(" ", "") + + if value_arg_type != hash_map_value_type: + print("ERROR: Incorrect usage of %s value argument found at %s." % (call_expr.spelling, args[2].location)) + print(" Argument variable is of type %s, but the HashMap expects a value of type %s" % (value_arg_type, hash_map_value_type)) + #print("def: %s, loc: %s" % (self_obj.get_definition(), self_obj.get_definition().location)) + +def parse(node): + if node.kind == clang.cindex.CursorKind.CALL_EXPR: + parse_call_expr(node) + for child in node.get_children(): + parse(child) + +def compile_commands_get_files(compile_commands_filepath): + files = [] + with open(compile_commands_filepath) as json_file: + data = json.load(json_file) + for obj in data: + filepath = os.path.join(obj["directory"], obj["file"]) + files.append(filepath) + return files + +def main(): + script_path = os.path.realpath(sys.argv[0]) + script_dir = os.path.dirname(script_path) + + compile_commands_file = os.path.join(script_dir, "..", "compile_commands.json") + if not os.path.isfile(compile_commands_file): + print("compile_commands.json file is missing! You need to compile amalgam before running this script") + exit(1) + + idx = clang.cindex.Index.create() + for filepath in compile_commands_get_files(compile_commands_file): + print("Parsing file: %s" % filepath) + tu = idx.parse(filepath, args=['-std=c89'], options=0) + parse(tu.cursor) + +if __name__ == "__main__": + main() + |