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