1#!/usr/bin/env python2
2
3from sys import argv, stdout, stderr
4import xml.dom.minidom
5
6from libtpcodegen import file_set_contents, u
7from libglibcodegen import NS_TP, get_docstring, \
8        get_descendant_text, get_by_path
9
10class Generator(object):
11    def __init__(self, prefix, implfile, declfile, dom):
12        self.prefix = prefix + '_'
13
14        assert declfile.endswith('.h')
15        docfile = declfile[:-2] + '-gtk-doc.h'
16
17        self.implfile = implfile
18        self.declfile = declfile
19        self.docfile = docfile
20
21        self.impls = []
22        self.decls = []
23        self.docs = []
24        self.spec = get_by_path(dom, "spec")[0]
25
26    def h(self, code):
27        self.decls.append(code)
28
29    def c(self, code):
30        self.impls.append(code)
31
32    def d(self, code):
33        self.docs.append(code)
34
35    def __call__(self):
36        for f in self.h, self.c:
37            self.do_header(f)
38        self.do_body()
39
40        file_set_contents(self.implfile, u('').join(self.impls).encode('utf-8'))
41        file_set_contents(self.declfile, u('').join(self.decls).encode('utf-8'))
42        file_set_contents(self.docfile, u('').join(self.docs).encode('utf-8'))
43
44    # Header
45    def do_header(self, f):
46        f('/* Generated from: ')
47        f(get_descendant_text(get_by_path(self.spec, 'title')))
48        version = get_by_path(self.spec, "version")
49        if version:
50            f(' version ' + get_descendant_text(version))
51        f('\n\n')
52        for copyright in get_by_path(self.spec, 'copyright'):
53            f(get_descendant_text(copyright))
54            f('\n')
55        f('\n')
56        f(get_descendant_text(get_by_path(self.spec, 'license')))
57        f(get_descendant_text(get_by_path(self.spec, 'docstring')))
58        f("""
59 */
60
61#include <glib.h>
62""")
63
64    # Body
65    def do_body(self):
66        for iface in self.spec.getElementsByTagName('interface'):
67            self.do_iface(iface)
68
69    def do_iface(self, iface):
70        parent_name = get_by_path(iface, '../@name')
71        self.d("""\
72/**
73 * %(IFACE_DEFINE)s:
74 *
75 * The interface name "%(name)s"
76 */
77""" % {'IFACE_DEFINE' : (self.prefix + 'IFACE_' + \
78            parent_name).upper().replace('/', ''),
79       'name' : iface.getAttribute('name')})
80
81        self.h("""
82#define %(IFACE_DEFINE)s \\
83"%(name)s"
84""" % {'IFACE_DEFINE' : (self.prefix + 'IFACE_' + \
85            parent_name).upper().replace('/', ''),
86       'name' : iface.getAttribute('name')})
87
88        self.d("""
89/**
90 * %(IFACE_QUARK_DEFINE)s:
91 *
92 * Expands to a call to a function that returns a quark for the interface \
93name "%(name)s"
94 */
95""" % {'IFACE_QUARK_DEFINE' : (self.prefix + 'IFACE_QUARK_' + \
96            parent_name).upper().replace('/', ''),
97       'iface_quark_func' : (self.prefix + 'iface_quark_' + \
98            parent_name).lower().replace('/', ''),
99       'name' : iface.getAttribute('name')})
100
101        self.h("""
102#define %(IFACE_QUARK_DEFINE)s \\
103  (%(iface_quark_func)s ())
104
105GQuark %(iface_quark_func)s (void);
106
107""" % {'IFACE_QUARK_DEFINE' : (self.prefix + 'IFACE_QUARK_' + \
108            parent_name).upper().replace('/', ''),
109       'iface_quark_func' : (self.prefix + 'iface_quark_' + \
110            parent_name).lower().replace('/', ''),
111       'name' : iface.getAttribute('name')})
112
113        self.c("""\
114GQuark
115%(iface_quark_func)s (void)
116{
117  static GQuark quark = 0;
118
119  if (G_UNLIKELY (quark == 0))
120    {
121      quark = g_quark_from_static_string ("%(name)s");
122    }
123
124  return quark;
125}
126
127""" % {'iface_quark_func' : (self.prefix + 'iface_quark_' + \
128            parent_name).lower().replace('/', ''),
129       'name' : iface.getAttribute('name')})
130
131        for prop in iface.getElementsByTagNameNS(None, 'property'):
132            self.d("""
133/**
134 * %(IFACE_PREFIX)s_%(PROP_UC)s:
135 *
136 * The fully-qualified property name "%(name)s.%(prop)s"
137 */
138""" % {'IFACE_PREFIX' : (self.prefix + 'PROP_' + \
139                parent_name).upper().replace('/', ''),
140           'PROP_UC': prop.getAttributeNS(NS_TP, "name-for-bindings").upper(),
141           'name' : iface.getAttribute('name'),
142           'prop' : prop.getAttribute('name'),
143           })
144
145            self.h("""
146#define %(IFACE_PREFIX)s_%(PROP_UC)s \\
147"%(name)s.%(prop)s"
148""" % {'IFACE_PREFIX' : (self.prefix + 'PROP_' + \
149                parent_name).upper().replace('/', ''),
150           'PROP_UC': prop.getAttributeNS(NS_TP, "name-for-bindings").upper(),
151           'name' : iface.getAttribute('name'),
152           'prop' : prop.getAttribute('name'),
153           })
154
155
156        for prop in iface.getElementsByTagNameNS(NS_TP, 'contact-attribute'):
157            self.d("""
158/**
159 * %(TOKEN_PREFIX)s_%(TOKEN_UC)s:
160 *
161 * The fully-qualified contact attribute token name "%(name)s/%(prop)s"
162 */
163""" % {'TOKEN_PREFIX' : (self.prefix + 'TOKEN_' + \
164                parent_name).upper().replace('/', ''),
165           'TOKEN_UC': prop.getAttributeNS(None, "name").upper().replace("-", "_").replace(".", "_"),
166           'name' : iface.getAttribute('name'),
167           'prop' : prop.getAttribute('name'),
168           })
169
170            self.h("""
171#define %(TOKEN_PREFIX)s_%(TOKEN_UC)s \\
172"%(name)s/%(prop)s"
173""" % {'TOKEN_PREFIX' : (self.prefix + 'TOKEN_' + \
174                parent_name).upper().replace('/', ''),
175           'TOKEN_UC': prop.getAttributeNS(None, "name").upper().replace("-", "_").replace(".", "_"),
176           'name' : iface.getAttribute('name'),
177           'prop' : prop.getAttribute('name'),
178           })
179
180        for prop in iface.getElementsByTagNameNS(NS_TP, 'hct'):
181            if (prop.getAttribute('is-family') != "yes"):
182                self.d("""
183/**
184 * %(TOKEN_PREFIX)s_%(TOKEN_UC)s:
185 *
186 * The fully-qualified capability token name "%(name)s/%(prop)s"
187 */
188""" % {'TOKEN_PREFIX' : (self.prefix + 'TOKEN_' + \
189                parent_name).upper().replace('/', ''),
190           'TOKEN_UC': prop.getAttributeNS(None, "name").upper().replace("-", "_").replace(".", "_"),
191           'name' : iface.getAttribute('name'),
192           'prop' : prop.getAttribute('name'),
193           })
194
195                self.h("""
196#define %(TOKEN_PREFIX)s_%(TOKEN_UC)s \\
197"%(name)s/%(prop)s"
198""" % {'TOKEN_PREFIX' : (self.prefix + 'TOKEN_' + \
199                parent_name).upper().replace('/', ''),
200           'TOKEN_UC': prop.getAttributeNS(None, "name").upper().replace("-", "_").replace(".", "_"),
201           'name' : iface.getAttribute('name'),
202           'prop' : prop.getAttribute('name'),
203           })
204
205if __name__ == '__main__':
206    argv = argv[1:]
207    Generator(argv[0], argv[1], argv[2], xml.dom.minidom.parse(argv[3]))()
208