#!/usr/bin/python import sys import clang import popen2 from clang.cindex import Diagnostic, CursorKind, TokenKind #------------------------------------------------------------------------------- def severity2text(severity): if severity == Diagnostic.Ignored: return "" elif severity == Diagnostic.Note: return "note" elif severity == Diagnostic.Warning: return "warning" elif severity == Diagnostic.Error: return "error" elif severity == Diagnostic.Fatal: return "fatal" else: return "unknown" #------------------------------------------------------------------------------- INLINE_NAMES = ["inline", "__inline", "__inline__", "__forceinline", "always_inline"] def is_inline(cursor): if cursor.kind != CursorKind.FUNCTION_DECL: return False for token in cursor.get_tokens(): tkn = token.spelling if tkn in INLINE_NAMES: return True if tkn == "{": break return False #------------------------------------------------------------------------------- def is_static(cursor): if cursor.kind != CursorKind.FUNCTION_DECL: return False token = next(cursor.get_tokens(), None) return token.spelling == "static" #------------------------------------------------------------------------------- def dump_ast(filename, cursor, level = 0): fileobj = cursor.location.file if fileobj is not None and fileobj.name != filename: return prototype = None if cursor.kind == CursorKind.FUNCTION_DECL: try: args = [] for arg in cursor.get_arguments(): args.append("%s %s" % (arg.type.spelling, arg.spelling)) #prototype = "%s %s" % (cursor.get_definition().result_type.spelling, cursor.get_definition().displayname) definition = cursor.get_definition() if definition is not None: prototype = "%s %s(%s)" % (cursor.get_definition().result_type.spelling, cursor.spelling, ", ".join(args)) except: pass inlined = is_inline(cursor) token = next(cursor.get_tokens(), None) if token is not None: token = token.spelling if prototype is not None: print " "*level, cursor.kind, "INLINED?", inlined, repr(prototype), repr(token), cursor.location else: print " "*level, cursor.kind, repr(cursor.spelling), repr(token), cursor.location for children in cursor.get_children(): dump_ast(filename, children, level+1) #------------------------------------------------------------------------------- def resolve_clang_includes(): cmd = "clang -print-file-name=include" rfd, wfd = popen2.popen2(cmd) return rfd.read().strip("\n") #------------------------------------------------------------------------------- def usage(): print "Usage: %s " % sys.argv[0] #------------------------------------------------------------------------------- def main(src, args): clang_includes = resolve_clang_includes() args.append("-I%s" % clang_includes) index = clang.cindex.Index.create() tu = index.parse(path=src, args=args) diags = tu.diagnostics for diag in diags: print("%s:%d,%d: %s: %s" % (diag.location.file, diag.location.line, diag.location.column, severity2text(diag.severity), diag.spelling)) dump_ast(src, tu.cursor) if __name__ == "__main__": args = [] if len(sys.argv) != 3: usage() else: main(sys.argv[1], sys.argv[2:])