hop-2012/experiments/cmsg/codegen.py

96 lines
3.0 KiB
Python

from __future__ import with_statement
# Copyright (C) 2010, 2011 Tony Garnock-Jones. All rights reserved.
copyright_stmt = '/* Copyright (C) 2010, 2011 Tony Garnock-Jones. All rights reserved. */'
import sys
import json
def cify(s):
s = s.replace('-', '_')
s = s.replace(' ', '_')
return s
class MessageType:
def __init__(self, j):
self.wire_selector = j['selector']
self.selector = cify(self.wire_selector)
self.wire_argnames = j['args']
self.argnames = map(cify, self.wire_argnames)
def format_args(self, template, separator = ', '):
return separator.join([template % (x,) for x in self.argnames])
with file("../../protocol/messages.json") as f:
spec = map(MessageType, json.load(f)['definitions'])
def entrypoint_header():
print copyright_stmt
print
print '#ifndef cmsg_messages_h'
print '#define cmsg_messages_h'
print
print 'extern void init_messages(void);'
print
for t in spec:
print 'extern sexp_t *selector_%s;' % (t.selector,)
print
for t in spec:
print 'extern sexp_t *message_%s(%s);' % (t.selector, t.format_args('sexp_t *%s'))
print
print 'typedef union parsed_message_t_ {'
for t in spec:
if t.argnames:
print ' struct { sexp_t %s; } %s;' % (t.format_args('*%s'), t.selector)
print '} parsed_message_t;'
for t in spec:
print
print 'static inline int parse_%s(sexp_t *message, parsed_message_t *out) {' % \
(t.selector,)
print ' if (!sexp_pairp(message)) return 0;'
print ' if (sexp_cmp(sexp_head(message), selector_%s) != 0) return 0;' % (t.selector,)
for n in t.argnames:
print ' if (!sexp_pseudo_pop(&message)) return 0;'
print ' out->%s.%s = sexp_head(message);' % (t.selector, n)
print ' return sexp_tail(message) == NULL;'
print '}'
print
print '#endif'
def entrypoint_body():
print copyright_stmt
print
print '#include <stdlib.h>'
print '#include <string.h>'
print '#include <stdio.h>'
print '#include <signal.h>'
print
print '#include <assert.h>'
print
print '#include "cmsg_private.h"'
print '#include "ref.h"'
print '#include "sexp.h"'
print '#include "messages.h"'
print
for t in spec:
print 'sexp_t *selector_%s = NULL;' % (t.selector,)
print
print 'void init_messages(void) {'
for t in spec:
print ' selector_%s = sexp_cstring("%s");' % (t.selector, t.wire_selector)
for t in spec:
print ' INCREF(selector_%s);' % (t.selector,)
print '}'
for t in spec:
print
print 'sexp_t *message_%s(%s) {' % (t.selector, t.format_args('sexp_t *%s'))
print ' sexp_t *m = NULL;'
for n in reversed(t.argnames):
print ' m = sexp_cons(%s, m);' % (n,)
print ' return sexp_cons(selector_%s, m);' % (t.selector,)
print '}'
if __name__ == '__main__':
drivername = sys.argv[1]
globals()['entrypoint_' + drivername]()