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
|
#!/usr/bin/python
import sys
import os
import re
from xml.dom.minidom import parse
def safe(str):
return str.replace('-', '_')
class AMQPType:
def __init__(self, dom):
self.name = safe(dom.getAttribute('name'))
self.source = dom.getAttribute('source')
self.desc = dom.getElementsByTagName('descriptor')[0].getAttribute('name')
self.code = dom.getElementsByTagName('descriptor')[0].getAttribute('code')
self.number = parse_code(self.code)
self.fields = [safe(el.getAttribute('name')) for el in
dom.getElementsByTagName('field')]
# These are 'restricted' types, rather than composite, so they
# do not have defined fields.
if self.desc in ['amqp:data:binary', 'amqp:amqp-sequence:list',
'amqp:amqp-value:*', 'amqp:application-properties:map',
'amqp:delivery-annotations:map',
'amqp:message-annotations:map', 'amqp:footer:map']:
self.fields = ['content']
def define(self):
return ('SYMBOL_%s' % self.name.upper(), self.desc)
class AMQPDefines:
def __init__(self, dom):
self.name = safe(dom.getAttribute('name'))
self.source = dom.getAttribute('source')
self.options = [(self.name.upper() + '_' +
(safe(el.getAttribute('name')).upper()),
el.getAttribute('value')) for el in
dom.getElementsByTagName('choice')]
def print_erl(types):
print """-module(rabbit_amqp1_0_framing0).
-export([record_for/1, fields/1, encode/1, symbol_for/1, number_for/1]).
-include("rabbit_amqp1_0.hrl")."""
for t in types:
print """record_for({symbol, <<"%s">>}) ->
#'v1_0.%s'{};""" % (t.desc, t.name)
if t.code:
print """record_for({_, %d}) ->
#'v1_0.%s'{};""" % (t.number, t.name)
print "%% %s\n" % t.code
print """record_for(Other) -> exit({unknown, Other}).
"""
for t in types:
print """fields(#'v1_0.%s'{}) -> record_info(fields, 'v1_0.%s');""" % (t.name, t.name)
print """fields(_Other) -> unknown.
"""
for t in types:
print """encode(Frame = #'v1_0.%s'{}) ->
rabbit_amqp1_0_framing:encode_described('%s', %s, Frame);""" % (t.name, t.source, t.number)
print """encode(undefined) -> null;
encode(Other) -> Other.
"""
for t in types:
print """symbol_for(#'v1_0.%s'{}) ->
{symbol, <<"%s">>};""" % (t.name, t.desc)
print """symbol_for(Other) -> exit({unknown, Other}).
"""
for t in types:
print """number_for(#'v1_0.%s'{}) ->
{ulong, %s};""" % (t.name, t.number)
print """number_for(Other) -> exit({unknown, Other})."""
def print_hrl(types, defines):
for t in types:
print """-record('v1_0.%s', {%s}).""" % (t.name, ", ".join(t.fields))
print_define(t.define(), 'symbol')
for d in defines:
if len(d.options) > 0:
print """ %% %s""" % (d.name)
for opt in d.options:
print_define(opt, d.source)
def print_define(opt, source):
(name, value) = opt
if source == 'symbol':
quoted = '"%s"' % value
else:
quoted = value
print """-define(V_1_0_%s, {%s, %s}).""" % (name, source, quoted)
def want_type(el):
descriptors = el.getElementsByTagName('descriptor')
return len(descriptors) > 0
def want_define(el):
klass = el.getAttribute('class')
return klass == 'restricted'
def parse_code(code):
res = re.match('0x([0-9a-fA-F]{8,8}):0x([0-9a-fA-F]{8,8})', code)
return res and int(res.group(1) + res.group(2), 16)
types = []
defines = []
mode = sys.argv[1]
for file in sys.argv[2:]:
tree = parse(file)
types.extend([AMQPType(el) for el in tree.getElementsByTagName('type')
if want_type(el)])
defines.extend([AMQPDefines(el) for el in tree.getElementsByTagName('type')
if want_define(el)])
if mode == 'erl':
print_erl(types)
elif mode == 'hrl':
print_hrl(types, defines)
else:
raise "Mode != erl or hrl"
|