Skip to content

Instantly share code, notes, and snippets.

Created November 4, 2012 00:12
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
What would you like to do?
Bitey Autogeneration of Struct Member Names with Ctags
#!/usr/bin/env python
"""Patch bitey to auto-generate struct member names with exuberant ctags."""
__author__ = ' (Adam R. Smith)'
from collections import OrderedDict
import logging as log
import os
import subprocess
import sys
import textwrap
import bitey
def parse_struct_members(path):
"""If exuberant ctags is installed, build struct member files."""
version = subprocess.check_output(['ctags', '--version'])
if not version.startswith('Exuberant'):
log.warning('You need to install exuberant ctags (not GNU).')
return None
ctags = subprocess.check_output(['ctags', '-f', '-', '--sort=no', path])
except subprocess.CalledProcessError:
log.warning('Unable to run exuberant ctags on "%s".', path)
return None
structs = OrderedDict()
for line in filter(None, ctags.split('\n')):
fields = line.split('\t')
if fields[3] == 'm':
_, struct = fields[4].split(':')
structs.setdefault(struct, []).append(fields[0])
return structs
def bitey_import(pkg, force_build=False):
"""Wrap bitey importing to generate struct definitions automatically."""
c_path, o_path = '%s.c' % pkg, '%s.o' % pkg
if not c_path:
return None
if force_build or (os.path.exists(o_path) and os.path.getmtime(o_path)
< os.path.getmtime(c_path)):
structs = parse_struct_members(c_path)
if structs:
py_pre_path = '' % pkg
prefix = ' _fields_ = '
wrapper = textwrap.TextWrapper(width=80, initial_indent=prefix,
subsequent_indent=' '*(len(prefix) + 1))
with open(py_pre_path, 'w') as py_pre:
py_pre.write('# This file auto-generated for bitey.')
for struct, members in structs.iteritems():
py_pre.write('\nclass %s:\n' % struct)
fields = wrapper.fill(str(members))
py_pre.write(fields + '\n')['clang', '-emit-llvm', '-c', c_path])
# Monkey-patch bitey to do our auto-generation first.
old_check_magic = bitey.loader._check_magic
def _check_magic(filename):
if filename.endswith('.o'):
pkg = filename[:-2]
return old_check_magic(filename)
bitey.loader._check_magic = _check_magic
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment