File indexing completed on 2024-04-21 05:01:51

0001 #!/usr/bin/python
0002 
0003 from sys import argv, stdout, stderr
0004 import xml.dom.minidom
0005 
0006 from libtpcodegen import file_set_contents, u
0007 from libglibcodegen import NS_TP, get_docstring, \
0008         get_descendant_text, get_by_path
0009 
0010 class Generator(object):
0011     def __init__(self, prefix, dom, output_base):
0012         self.prefix = prefix + '_'
0013         self.spec = get_by_path(dom, "spec")[0]
0014 
0015         self.output_base = output_base
0016         self.__header = []
0017         self.__docs = []
0018 
0019     def __call__(self):
0020         self.do_header()
0021         self.do_body()
0022         self.do_footer()
0023 
0024         file_set_contents(self.output_base + '.h', u('').join(self.__header).encode('utf-8'))
0025         file_set_contents(self.output_base + '-gtk-doc.h', u('').join(self.__docs).encode('utf-8'))
0026 
0027     def write(self, code):
0028         self.__header.append(code)
0029 
0030     def d(self, code):
0031         self.__docs.append(code)
0032 
0033     # Header
0034     def do_header(self):
0035         self.write('/* Generated from ')
0036         self.write(get_descendant_text(get_by_path(self.spec, 'title')))
0037         version = get_by_path(self.spec, "version")
0038         if version:
0039             self.write(', version ' + get_descendant_text(version))
0040         self.write('\n\n')
0041         for copyright in get_by_path(self.spec, 'copyright'):
0042             self.write(get_descendant_text(copyright))
0043             self.write('\n')
0044         self.write(get_descendant_text(get_by_path(self.spec, 'license')))
0045         self.write('\n')
0046         self.write(get_descendant_text(get_by_path(self.spec, 'docstring')))
0047         self.write("""
0048  */
0049 
0050 #ifdef __cplusplus
0051 extern "C" {
0052 #endif
0053 \n""")
0054 
0055     # Body
0056     def do_body(self):
0057         for elem in self.spec.getElementsByTagNameNS(NS_TP, '*'):
0058             if elem.localName == 'flags':
0059                 self.do_flags(elem)
0060             elif elem.localName == 'enum':
0061                 self.do_enum(elem)
0062 
0063     def do_flags(self, flags):
0064         name = flags.getAttribute('plural') or flags.getAttribute('name')
0065         value_prefix = flags.getAttribute('singular') or \
0066                        flags.getAttribute('value-prefix') or \
0067                        flags.getAttribute('name')
0068         self.d("""\
0069 /**
0070  * %s:
0071 """ % (self.prefix + name).replace('_', ''))
0072         for flag in get_by_path(flags, 'flag'):
0073             self.do_gtkdoc(flag, value_prefix)
0074         self.d(' *\n')
0075         docstrings = get_by_path(flags, 'docstring')
0076         if docstrings:
0077             self.d("""\
0078  * <![CDATA[%s]]>
0079  *
0080 """ % get_descendant_text(docstrings).replace('\n', ' '))
0081         self.d("""\
0082  * Bitfield/set of flags generated from the Telepathy specification.
0083  */
0084 """)
0085 
0086         self.write("typedef enum /*< flags >*/ {\n")
0087 
0088         for flag in get_by_path(flags, 'flag'):
0089             self.do_val(flag, value_prefix)
0090         self.write("""\
0091 } %s;
0092 
0093 """ % (self.prefix + name).replace('_', ''))
0094 
0095     def do_enum(self, enum):
0096         name = enum.getAttribute('singular') or enum.getAttribute('name')
0097         value_prefix = enum.getAttribute('singular') or \
0098                        enum.getAttribute('value-prefix') or \
0099                        enum.getAttribute('name')
0100         name_plural = enum.getAttribute('plural') or \
0101                       enum.getAttribute('name') + 's'
0102         self.d("""\
0103 /**
0104  * %s:
0105 """ % (self.prefix + name).replace('_', ''))
0106         vals = get_by_path(enum, 'enumvalue')
0107         for val in vals:
0108             self.do_gtkdoc(val, value_prefix)
0109         self.d(' *\n')
0110         docstrings = get_by_path(enum, 'docstring')
0111         if docstrings:
0112             self.d("""\
0113  * <![CDATA[%s]]>
0114  *
0115 """ % get_descendant_text(docstrings).replace('\n', ' '))
0116         self.d("""\
0117  * Bitfield/set of flags generated from the Telepathy specification.
0118  */
0119 """)
0120 
0121         self.write("typedef enum {\n")
0122 
0123         for val in vals:
0124             self.do_val(val, value_prefix)
0125         self.write("} %s;\n" % (self.prefix + name).replace('_', ''))
0126 
0127         self.d("""\
0128 /**
0129  * %(upper-prefix)sNUM_%(upper-plural)s:
0130  *
0131  * 1 higher than the highest valid value of #%(mixed-name)s.
0132  */
0133 
0134 /**
0135  * NUM_%(upper-prefix)s%(upper-plural)s: (skip)
0136  *
0137  * 1 higher than the highest valid value of #%(mixed-name)s.
0138  * In new code, use %(upper-prefix)sNUM_%(upper-plural)s instead.
0139  */
0140 """ % {'mixed-name' : (self.prefix + name).replace('_', ''),
0141        'upper-prefix' : self.prefix.upper(),
0142        'upper-plural' : name_plural.upper(),
0143        'last-val' : vals[-1].getAttribute('value')})
0144 
0145         self.write("""\
0146 #define %(upper-prefix)sNUM_%(upper-plural)s (%(last-val)s+1)
0147 #define NUM_%(upper-prefix)s%(upper-plural)s %(upper-prefix)sNUM_%(upper-plural)s
0148 
0149 """ % {'mixed-name' : (self.prefix + name).replace('_', ''),
0150        'upper-prefix' : self.prefix.upper(),
0151        'upper-plural' : name_plural.upper(),
0152        'last-val' : vals[-1].getAttribute('value')})
0153 
0154     def do_val(self, val, value_prefix):
0155         name = val.getAttribute('name')
0156         suffix = val.getAttribute('suffix')
0157         use_name = (self.prefix + value_prefix + '_' + \
0158                 (suffix or name)).upper()
0159         assert not (name and suffix) or name == suffix, \
0160                 'Flag/enumvalue name %s != suffix %s' % (name, suffix)
0161         self.write('    %s = %s,\n' % (use_name, val.getAttribute('value')))
0162 
0163     def do_gtkdoc(self, node, value_prefix):
0164         self.d(' * @')
0165         self.d((self.prefix + value_prefix + '_' +
0166             node.getAttribute('suffix')).upper())
0167         self.d(': <![CDATA[')
0168         docstring = get_by_path(node, 'docstring')
0169         self.d(get_descendant_text(docstring).replace('\n', ' '))
0170         self.d(']]>\n')
0171 
0172     # Footer
0173     def do_footer(self):
0174         self.write("""
0175 #ifdef __cplusplus
0176 }
0177 #endif
0178 """)
0179 
0180 if __name__ == '__main__':
0181     argv = argv[1:]
0182     Generator(argv[0], xml.dom.minidom.parse(argv[1]), argv[2])()