File: codegen.py

package info (click to toggle)
rabbitmq-server 3.3.5-1.1
  • links: PTS
  • area: main
  • in suites: jessie-kfreebsd
  • size: 12,004 kB
  • sloc: erlang: 78,203; python: 3,187; xml: 2,843; makefile: 903; sh: 831; java: 660; perl: 64; ruby: 63
file content (123 lines) | stat: -rwxr-xr-x 4,111 bytes parent folder | download | duplicates (2)
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"