Project

General

Profile

Download (2.65 KB) Statistics
| Branch: | Tag: | Revision:
import sys

from clang.cindex import Config
from clang.cindex import CursorKind
from clang.cindex import Index
from clang.cindex import TranslationUnit

# Set these according to the location and version of libclang on your system
LIBCLANG_PATH = '/usr/lib/llvm-3.4/lib'
LIBCLANG_NAME = 'libclang-3.4.so'


def display_node(node):
""" A helper function to pretty print the particulars of the passed in
Cursor object
"""
start_line = node.extent.start.line
start_col = node.extent.start.column
end_line = node.extent.end.line
end_col = node.extent.end.column
print '{:s} ({:d}:{:d} - {:d}:{:d})'.format(node.displayname,
start_line, start_col,
end_line, end_col)

def find_function_calls(node):
""" A recursive function call to find all function calls that are children
of the passed in Cursor object
"""
results = []
for child_node in node.get_children():
if child_node.kind == CursorKind.CALL_EXPR:
results.append(child_node)
else:
results.extend(find_function_calls(child_node))
return results

def main():
""" This is a very simple utility that uses the Clang compiler frontend
to parse a C source file and return a list of function declarations within
that file along with the lines on which each declaration starts and ends.
"""
if len(sys.argv) < 2:
print 'ERROR: not enough arguments provided\n'
print 'USAGE: python ddc_preproc.py <file.c>'
return -1
# Configure the library (not sure why this has to be done manually)
Config.set_library_path(LIBCLANG_PATH)
Config.set_library_file(LIBCLANG_NAME)
# Build the TU from the passed file argument
source_file = sys.argv[1]
tu = TranslationUnit.from_source(source_file)

# Loop through all of the children nodes and extract function definitions
# along with their start and end lines from the specified source file
print 'Function declarations:'
print '-' * 80
main_func = None
for child in tu.cursor.get_children():
if str(child.location.file) == source_file and \
child.kind == CursorKind.FUNCTION_DECL:
# Store a reference to the main function
if child.spelling == 'main':
main_func = child
display_node(child)
print '\n'
# Find all function calls originating from the main function
print 'Function calls:'
print '-' * 80
for child in find_function_calls(main_func):
display_node(child)

if __name__ == '__main__':
sys.exit(main())
(11-11/17)