1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 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)
|