2 from clang.cindex import *
5 libt4_path = '/Users/peteriannucci/invirt/third/libt4/'
7 STDLIB = ['-stdlib=libc++']
8 PEDANTRY = ['-Werror', '-Weverything', '-Wall', '-Wextra', '-pedantic-errors', '-pedantic',
9 '-Wno-c++98-compat-pedantic', '-Wno-padded', '-Weffc++',
10 '-Wno-non-virtual-dtor', '-Wno-weak-vtables']
11 CXXFLAGS = ['-x', 'c++', '-I', libt4_path, '-std=c++1y'] + STDLIB + PEDANTRY + OPTFLAGS
12 CXXFLAGS += ['-DMARSHALL_RAW_NETWORK_ORDER_AS(a,b)=static void macro_marshall_##a##_as_##b(a first, b second);']
16 libdir = subprocess.Popen(['llvm-config-mp-3.4', '--libdir'], stdout=subprocess.PIPE).communicate()[0].strip()
17 Config.set_library_path(libdir)
18 index = Index.create()
19 tu = index.parse(os.path.join(libt4_path, target), args=CXXFLAGS)
21 def dive_all(cursor, kinds, pred=None, depth_limit=-1):
22 if cursor.kind in kinds and (pred is None or pred(cursor)):
25 for c in cursor.get_children():
26 for d in dive_all(c, kinds, pred, depth_limit-1):
29 def get_label(cursor):
31 cursor = dive_all(cursor, (CursorKind.CONVERSION_FUNCTION,), lambda c: c.displayname == 'operator label()', 1).next()
32 cursor = dive_all(cursor, (CursorKind.STRING_LITERAL,)).next()
33 return eval(cursor.get_tokens().next().spelling)
37 def get_members(cursor):
39 adapter = dive_all(cursor, (CursorKind.CXX_METHOD,), lambda c: c.displayname == '_tuple_()', 1).next()
40 fields = {x.displayname:x for x in dive_all(cursor, (CursorKind.FIELD_DECL,))}
41 return [fields[m.displayname] for m in dive_all(adapter, (CursorKind.MEMBER_REF_EXPR,))]
46 def __init__(self, m, u):
50 def MarshallRawNetworkOrderAs(what, as_what):
51 as_what = np.dtype(as_what).newbyteorder('B')
53 return np.array([x], as_what).tostring()
55 return np.fromstring(s[:as_what.itemsize], as_what).astype(what)[0], s[as_what.itemsize:]
56 mu = Marshallable(m, u)
57 mu.__repr__ = lambda : '<Marshallable(%s)>' % np.dtype(what).name
60 def RecordClass(displayname, members):
61 member_names = [f.displayname for f in members]
62 member_types = [f.type.get_canonical().spelling for f in members]
63 member_types_nice = [f.type.spelling for f in members]
64 member_marshallers = [types[t] for t in member_types]
66 def __init__(self, *args, **kwargs):
68 assert len(args) == len(member_names)
69 self.__dict__.update(dict(zip(member_names, args)))
71 assert set(kwargs.keys()) == set(member_names)
72 self.__dict__.update(kwargs)
73 __init__.__doc__ = 'Required arguments:\n' + '\n'.join('%s (%s)' % (n,t) for t,n in zip(member_types_nice, member_names))
76 return ''.join(marshaller.marshall(getattr(self, name)) for name, marshaller in zip(member_names, member_marshallers))
80 for marshaller in member_marshallers:
81 member_value, s = marshaller.unmarshall(s)
82 member_values.append(member_value)
83 return Record(**dict(zip(member_names, member_values))), s
85 return '<%s ' % displayname + ' '.join('%s=%s' % (k, repr(getattr(self, k))) for k in member_names) + '>'
86 Record.__name__ = displayname
92 def marshall(self, s):
93 return types['unsigned int'].marshall(len(s)) + s
94 def unmarshall(self, s):
95 l, s = types['unsigned int'].unmarshall(s)
100 types['std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >'] = MarshallString()
102 numpy_type = {'bool': np.bool, 'char': np.int8, 'signed char': np.int8, 'unsigned char': np.uint8, 'short': np.short, 'unsigned short': np.ushort,
103 'int': np.intc, 'unsigned int': np.uintc, 'long': np.int_, 'unsigned long': np.uint, 'long long': np.longlong, 'unsigned long long': np.ulonglong}
105 def processDeclaration(cursor):
106 if cursor.kind == CursorKind.ENUM_DECL:
107 enum_type = cursor.enum_type.get_canonical().spelling
108 if enum_type != '<dependent type>':
109 processDeclaration(cursor.enum_type.get_canonical().get_declaration())
110 assert enum_type in types, enum_type
111 types[cursor.type.get_canonical().spelling] = types[enum_type]
112 elif cursor.kind == CursorKind.FUNCTION_DECL:
113 if cursor.displayname.startswith('macro_marshall_'):
114 what, as_what = [x.type.get_canonical().spelling for x in cursor.get_arguments()]
115 types[what] = MarshallRawNetworkOrderAs(numpy_type[what], numpy_type[as_what])
117 members = get_members(cursor)
118 label = get_label(cursor)
119 if members is not None:
121 field_type = f.type.get_canonical().spelling
122 processDeclaration(f.type.get_canonical().get_declaration())
123 assert field_type in types, field_type
124 types[cursor.type.get_canonical().spelling] = RecordClass(cursor.displayname, members)
125 if label is not None:
126 labels[cursor.type.get_canonical().spelling] = label
128 for cursor in dive_all(tu.cursor, (CursorKind.FUNCTION_DECL,)):
129 processDeclaration(cursor)
131 for cursor in dive_all(tu.cursor, set([CursorKind.STRUCT_DECL, CursorKind.CLASS_DECL, CursorKind.ENUM_DECL])):
132 processDeclaration(cursor)