diff options
Diffstat (limited to 'scripts/stripdecls.py')
-rwxr-xr-x | scripts/stripdecls.py | 141 |
1 files changed, 141 insertions, 0 deletions
diff --git a/scripts/stripdecls.py b/scripts/stripdecls.py new file mode 100755 index 0000000000..34be2a1578 --- /dev/null +++ b/scripts/stripdecls.py @@ -0,0 +1,141 @@ +#!/usr/bin/python +# vim: set fileencoding=utf-8: + +from __future__ import print_function, unicode_literals, division + +from clang.cindex import Index, CursorKind +from collections import namedtuple, OrderedDict, defaultdict +import sys +import os + + +DECL_KINDS = { + CursorKind.FUNCTION_DECL, +} + + +Strip = namedtuple('Strip', 'start_line start_column end_line end_column') + + +def main(progname, cfname, only_static, move_all): + only_static = False + + cfname = os.path.abspath(os.path.normpath(cfname)) + + hfname1 = os.path.splitext(cfname)[0] + os.extsep + 'h' + hfname2 = os.path.splitext(cfname)[0] + '_defs' + os.extsep + 'h' + + files_to_modify = (cfname, hfname1, hfname2) + + index = Index.create() + src_dirname = os.path.join(os.path.dirname(__file__), '..', 'src') + src_dirname = os.path.abspath(os.path.normpath(src_dirname)) + relname = os.path.join(src_dirname, 'nvim') + unit = index.parse(cfname, args=('-I' + src_dirname, + '-DUNIX', + '-DEXITFREE', + '-DFEAT_USR_CMDS', + '-DFEAT_CMDL_COMPL', + '-DFEAT_COMPL_FUNC', + '-DPROTO', + '-DUSE_MCH_ERRMSG')) + cursor = unit.cursor + + tostrip = defaultdict(OrderedDict) + definitions = set() + + for child in cursor.get_children(): + if not (child.location and child.location.file): + continue + fname = os.path.abspath(os.path.normpath(child.location.file.name)) + if fname not in files_to_modify: + continue + if child.kind not in DECL_KINDS: + continue + if only_static and next(child.get_tokens()).spelling == 'static': + continue + + if child.is_definition() and fname == cfname: + definitions.add(child.spelling) + else: + stripdict = tostrip[fname] + assert(child.spelling not in stripdict) + stripdict[child.spelling] = Strip( + child.extent.start.line, + child.extent.start.column, + child.extent.end.line, + child.extent.end.column, + ) + + for (fname, stripdict) in tostrip.items(): + if not move_all: + for name in set(stripdict) - definitions: + stripdict.pop(name) + + if not stripdict: + continue + + if fname.endswith('.h'): + is_h_file = True + include_line = next(reversed(stripdict.values())).start_line + 1 + else: + is_h_file = False + include_line = next(iter(stripdict.values())).start_line + + lines = None + generated_existed = os.path.exists(fname + '.generated.h') + with open(fname, 'rb') as F: + lines = list(F) + + stripped = [] + + for name, position in reversed(stripdict.items()): + sl = slice(position.start_line - 1, position.end_line) + if is_h_file: + include_line -= sl.stop - sl.start + stripped += lines[sl] + lines[sl] = () + + if not generated_existed: + lines[include_line:include_line] = [ + '#ifdef INCLUDE_GENERATED_DECLARATIONS\n', + '# include "{0}.generated.h"\n'.format(os.path.relpath(fname, relname)), + '#endif\n', + ] + + with open(fname, 'wb') as F: + F.writelines(lines) + + +if __name__ == '__main__': + progname = sys.argv[0] + args = sys.argv[1:] + if not args or '--help' in args: + print('Usage:') + print('') + print(' {0} [--static [--all]] file.c...'.format(progname)) + print('') + print('Stripts all declarations from file.c, file.h and file_defs.h.') + print('If --static argument is given then only static declarations are') + print('stripped. Declarations are stripped only if corresponding') + print('definition is found unless --all argument was given.') + print('') + print('Note: it is assumed that static declarations starts with "static"') + print(' keyword.') + sys.exit(0 if args else 1) + + if args[0] == '--static': + only_static = True + args = args[1:] + else: + only_static = False + + if args[0] == '--all': + move_all = True + args = args[1:] + else: + move_all = False + + for cfname in args: + print('Processing {0}'.format(cfname)) + main(progname, cfname, only_static, move_all) |