#!/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 <source file> <arguments>" % 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:])
Comments