123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141 |
- #!/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):
- 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)
|