You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
131 lines
4.7 KiB
131 lines
4.7 KiB
# -*- coding: utf-8 -*-
|
|
# This file is under GNU Affero General Public License 3.0
|
|
# see LICENSE.txt
|
|
|
|
import clang.cindex
|
|
from clang.cindex import CursorKind
|
|
|
|
|
|
class C2AST:
|
|
def __init__(self, library_file):
|
|
if not clang.cindex.Config.loaded:
|
|
# print("Using libclang from: %s", library_file)
|
|
clang.cindex.Config.set_library_file(library_file)
|
|
import sys
|
|
sys.setrecursionlimit(10000)
|
|
# print("max recursion limit set to:", sys.getrecursionlimit())
|
|
|
|
|
|
def parse(self, filename, content=None, follow_includes=False):
|
|
index = clang.cindex.Index.create()
|
|
arguments = ["-x", "c"]
|
|
options = clang.cindex.TranslationUnit.PARSE_SKIP_FUNCTION_BODIES
|
|
if content:
|
|
content = [(filename, content)]
|
|
|
|
ret = []
|
|
try:
|
|
translation_unit = index.parse(filename, unsaved_files=content, args=arguments, options=options)
|
|
ret = self._parse(translation_unit.cursor, filename, follow_includes)
|
|
except:
|
|
print(__file__,":: warning: error while processing header file: ", filename)
|
|
|
|
return ret
|
|
|
|
|
|
def _get_children(self, cursor, path, follow_includes=False):
|
|
if follow_includes:
|
|
return [c for c in cursor.get_children()]
|
|
else:
|
|
return [c for c in cursor.get_children() if c.location.file and c.location.file.name == path]
|
|
|
|
|
|
def _parse(self, cursor, path, follow_includes=False, parent_cursor=None):
|
|
item = None
|
|
dont_recurse = False
|
|
# dont parse excluded CursorKinds
|
|
excluded_cursortypes = [CursorKind.INTEGER_LITERAL]
|
|
if not cursor.kind in excluded_cursortypes:
|
|
item = {""
|
|
"tokens": "",
|
|
"kind": "",
|
|
"name": "",
|
|
"type": "",
|
|
"file": "",
|
|
"is_definition": "",
|
|
}
|
|
|
|
# generic info for all CursorKinds
|
|
if str(cursor.get_tokens()):
|
|
str_tok = ""
|
|
for tok in cursor.get_tokens():
|
|
str_tok += tok.spelling + " "
|
|
item["tokens"] = str_tok.rstrip()
|
|
|
|
if str(cursor.kind):
|
|
item["kind"] = str(cursor.kind)
|
|
|
|
if cursor.spelling:
|
|
item["name"] = cursor.spelling
|
|
|
|
# optional "displayname"
|
|
if cursor.displayname:
|
|
if cursor.displayname != item["name"]:
|
|
item["displayname"] = cursor.displayname
|
|
|
|
if cursor.type.spelling:
|
|
item["type"] = cursor.type.spelling
|
|
|
|
# optional "result_type"
|
|
if cursor.result_type.spelling != "":
|
|
item["result_type"] = cursor.result_type.spelling
|
|
|
|
item["file"] = str(cursor.location.file)
|
|
|
|
# optional "semantic_parent"
|
|
if cursor.semantic_parent:
|
|
if cursor.semantic_parent.kind.is_translation_unit():
|
|
item["semantic_parent"] = "global"
|
|
else:
|
|
item["semantic_parent"] = cursor.semantic_parent.spelling
|
|
|
|
item["is_definition"] = False
|
|
if cursor.is_definition():
|
|
item["is_definition"] = cursor.is_definition()
|
|
|
|
# ENUM specific info
|
|
# optional "value"
|
|
if cursor.kind == CursorKind.ENUM_CONSTANT_DECL:
|
|
item["value"] = cursor.enum_value
|
|
|
|
# TYPEDEF specific info
|
|
# optional "utype"
|
|
if cursor.kind == CursorKind.TYPEDEF_DECL:
|
|
item["utype"] = cursor.underlying_typedef_type.spelling
|
|
item["utypekind"] = cursor.underlying_typedef_type.kind.spelling
|
|
dont_recurse = True
|
|
|
|
# TYPE_REF specific info
|
|
# optional "typekind"
|
|
if cursor.kind == CursorKind.TYPE_REF:
|
|
item["utypekind"] = cursor.type.kind.spelling
|
|
|
|
if parent_cursor:
|
|
if (not cursor.kind == CursorKind.TYPE_REF
|
|
and parent_cursor.kind == CursorKind.FIELD_DECL):
|
|
return None
|
|
|
|
if not dont_recurse:
|
|
# get direct children
|
|
child_cursors = self._get_children(cursor, path, follow_includes)
|
|
if len(child_cursors) > 0:
|
|
child_arr = []
|
|
for child_cursor in child_cursors:
|
|
child_result = self._parse(child_cursor, path, follow_includes=follow_includes, parent_cursor=cursor)
|
|
if child_result:
|
|
child_arr.append(child_result)
|
|
|
|
if child_arr:
|
|
item["children"] = child_arr
|
|
|
|
return item
|
|
|