aboutsummaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2019-08-12 09:48:55 +0200
committerdec05eba <dec05eba@protonmail.com>2020-07-25 14:36:46 +0200
commitea97370f973374f863e4296c2bb872be8b5235a3 (patch)
treebcf74846c250dd5b1f84049622ed2766605365e7 /tools
parent4ca3b74621c3608de42a91730a71892d9d7c27b5 (diff)
Before interpreter. Cleanup build script. Begin writing code analyzer tool to find common mistakes
Diffstat (limited to 'tools')
-rwxr-xr-xtools/highlevel_c.py81
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()
+