Daniel Veillard | d2897fd | 2002-01-30 16:37:32 +0000 | [diff] [blame] | 1 | #!/usr/bin/python -u |
| 2 | # |
| 3 | # generate python wrappers from the XML API description |
| 4 | # |
| 5 | |
| 6 | functions = {} |
| 7 | |
| 8 | import os |
Daniel Veillard | 36ed529 | 2002-01-30 23:49:06 +0000 | [diff] [blame^] | 9 | import string |
Daniel Veillard | d2897fd | 2002-01-30 16:37:32 +0000 | [diff] [blame] | 10 | import xmllib |
| 11 | try: |
| 12 | import sgmlop |
| 13 | except ImportError: |
| 14 | sgmlop = None # accelerator not available |
| 15 | |
| 16 | debug = 0 |
| 17 | |
| 18 | if sgmlop: |
| 19 | class FastParser: |
| 20 | """sgmlop based XML parser. this is typically 15x faster |
| 21 | than SlowParser...""" |
| 22 | |
| 23 | def __init__(self, target): |
| 24 | |
| 25 | # setup callbacks |
| 26 | self.finish_starttag = target.start |
| 27 | self.finish_endtag = target.end |
| 28 | self.handle_data = target.data |
| 29 | |
| 30 | # activate parser |
| 31 | self.parser = sgmlop.XMLParser() |
| 32 | self.parser.register(self) |
| 33 | self.feed = self.parser.feed |
| 34 | self.entity = { |
| 35 | "amp": "&", "gt": ">", "lt": "<", |
| 36 | "apos": "'", "quot": '"' |
| 37 | } |
| 38 | |
| 39 | def close(self): |
| 40 | try: |
| 41 | self.parser.close() |
| 42 | finally: |
| 43 | self.parser = self.feed = None # nuke circular reference |
| 44 | |
| 45 | def handle_entityref(self, entity): |
| 46 | # <string> entity |
| 47 | try: |
| 48 | self.handle_data(self.entity[entity]) |
| 49 | except KeyError: |
| 50 | self.handle_data("&%s;" % entity) |
| 51 | |
| 52 | else: |
| 53 | FastParser = None |
| 54 | |
| 55 | |
| 56 | class SlowParser(xmllib.XMLParser): |
| 57 | """slow but safe standard parser, based on the XML parser in |
| 58 | Python's standard library.""" |
| 59 | |
| 60 | def __init__(self, target): |
| 61 | self.unknown_starttag = target.start |
| 62 | self.handle_data = target.data |
| 63 | self.unknown_endtag = target.end |
| 64 | xmllib.XMLParser.__init__(self) |
| 65 | |
| 66 | def getparser(target = None): |
| 67 | # get the fastest available parser, and attach it to an |
| 68 | # unmarshalling object. return both objects. |
| 69 | if target == None: |
| 70 | target = docParser() |
| 71 | if FastParser: |
| 72 | return FastParser(target), target |
| 73 | return SlowParser(target), target |
| 74 | |
| 75 | class docParser: |
| 76 | def __init__(self): |
| 77 | self._methodname = None |
| 78 | self._data = [] |
| 79 | self.in_function = 0 |
| 80 | |
| 81 | def close(self): |
| 82 | if debug: |
| 83 | print "close" |
| 84 | |
| 85 | def getmethodname(self): |
| 86 | return self._methodname |
| 87 | |
| 88 | def data(self, text): |
| 89 | if debug: |
| 90 | print "data %s" % text |
| 91 | self._data.append(text) |
| 92 | |
| 93 | def start(self, tag, attrs): |
| 94 | if debug: |
| 95 | print "start %s, %s" % (tag, attrs) |
| 96 | if tag == 'function': |
| 97 | self._data = [] |
| 98 | self.in_function = 1 |
| 99 | self.function = None |
| 100 | self.function_args = [] |
| 101 | self.function_descr = None |
| 102 | self.function_return = None |
| 103 | self.function_file = None |
| 104 | if attrs.has_key('name'): |
| 105 | self.function = attrs['name'] |
| 106 | if attrs.has_key('file'): |
| 107 | self.function_file = attrs['file'] |
| 108 | elif tag == 'info': |
| 109 | self._data = [] |
| 110 | elif tag == 'arg': |
| 111 | if self.in_function == 1: |
| 112 | self.function_arg_name = None |
| 113 | self.function_arg_type = None |
| 114 | self.function_arg_info = None |
| 115 | if attrs.has_key('name'): |
| 116 | self.function_arg_name = attrs['name'] |
| 117 | if attrs.has_key('type'): |
| 118 | self.function_arg_type = attrs['type'] |
| 119 | if attrs.has_key('info'): |
| 120 | self.function_arg_info = attrs['info'] |
| 121 | elif tag == 'return': |
| 122 | if self.in_function == 1: |
| 123 | self.function_return_type = None |
| 124 | self.function_return_info = None |
| 125 | if attrs.has_key('type'): |
| 126 | self.function_return_type = attrs['type'] |
| 127 | if attrs.has_key('info'): |
| 128 | self.function_return_info = attrs['info'] |
| 129 | |
| 130 | |
| 131 | def end(self, tag): |
| 132 | if debug: |
| 133 | print "end %s" % tag |
| 134 | if tag == 'function': |
| 135 | if self.function != None: |
| 136 | function(self.function, self.function_descr, |
| 137 | self.function_return, self.function_args, |
| 138 | self.function_file) |
| 139 | self.in_function = 0 |
| 140 | elif tag == 'arg': |
| 141 | if self.in_function == 1: |
| 142 | self.function_args.append([self.function_arg_name, |
| 143 | self.function_arg_type, |
| 144 | self.function_arg_info]) |
| 145 | elif tag == 'return': |
| 146 | if self.in_function == 1: |
| 147 | self.function_return = [self.function_return_type, |
| 148 | self.function_return_info] |
| 149 | elif tag == 'info': |
| 150 | str = '' |
| 151 | for c in self._data: |
| 152 | str = str + c |
| 153 | if self.in_function == 1: |
| 154 | self.function_descr = str |
| 155 | |
| 156 | |
| 157 | def function(name, desc, ret, args, file): |
| 158 | global functions |
| 159 | |
| 160 | functions[name] = (desc, ret, args, file) |
| 161 | |
Daniel Veillard | 36ed529 | 2002-01-30 23:49:06 +0000 | [diff] [blame^] | 162 | |
Daniel Veillard | d2897fd | 2002-01-30 16:37:32 +0000 | [diff] [blame] | 163 | skipped_modules = { |
| 164 | 'xmlmemory': None, |
Daniel Veillard | 96fe095 | 2002-01-30 20:52:23 +0000 | [diff] [blame] | 165 | 'DOCBparser': None, |
| 166 | 'SAX': None, |
| 167 | 'hash': None, |
| 168 | 'list': None, |
| 169 | 'threads': None, |
| 170 | } |
| 171 | skipped_types = { |
| 172 | 'int *': "usually a return type", |
| 173 | 'xmlSAXHandlerPtr': "not the proper interface for SAX", |
| 174 | 'htmlSAXHandlerPtr': "not the proper interface for SAX", |
| 175 | 'xmlParserCtxtPtr': "not the proper interface for the parser", |
| 176 | 'htmlParserCtxtPtr': "not the proper interface for the parser", |
| 177 | 'xmlRMutexPtr': "thread specific, skipped", |
| 178 | 'xmlMutexPtr': "thread specific, skipped", |
| 179 | 'xmlGlobalStatePtr': "thread specific, skipped", |
| 180 | 'xmlListPtr': "internal representation not suitable for python", |
| 181 | 'xmlBufferPtr': "internal representation not suitable for python", |
| 182 | 'FILE *': None, |
Daniel Veillard | d2897fd | 2002-01-30 16:37:32 +0000 | [diff] [blame] | 183 | } |
| 184 | py_types = { |
Daniel Veillard | 96fe095 | 2002-01-30 20:52:23 +0000 | [diff] [blame] | 185 | 'void': (None, None, None, None), |
| 186 | 'int': ('i', None, "int", "int"), |
| 187 | 'long': ('i', None, "int", "int"), |
| 188 | 'double': ('d', None, "double", "double"), |
| 189 | 'unsigned int': ('i', None, "int", "int"), |
| 190 | 'xmlChar': ('c', None, "int", "int"), |
| 191 | 'unsigned char *': ('s', None, "charPtr", "char *"), |
| 192 | 'char *': ('s', None, "charPtr", "char *"), |
| 193 | 'const char *': ('s', None, "charPtr", "char *"), |
| 194 | 'xmlChar *': ('s', None, "xmlCharPtr", "xmlChar *"), |
| 195 | 'const xmlChar *': ('s', None, "xmlCharPtr", "xmlChar *"), |
| 196 | 'xmlNodePtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), |
| 197 | 'const xmlNodePtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), |
| 198 | 'xmlNode *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), |
| 199 | 'const xmlNode *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), |
| 200 | 'xmlDtdPtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), |
| 201 | 'const xmlDtdPtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), |
| 202 | 'xmlDtd *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), |
| 203 | 'const xmlDtd *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), |
| 204 | 'xmlAttrPtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), |
| 205 | 'const xmlAttrPtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), |
| 206 | 'xmlAttr *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), |
| 207 | 'const xmlAttr *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), |
| 208 | 'xmlEntityPtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), |
| 209 | 'const xmlEntityPtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), |
| 210 | 'xmlEntity *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), |
| 211 | 'const xmlEntity *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), |
| 212 | 'xmlElementPtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), |
| 213 | 'const xmlElementPtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), |
| 214 | 'xmlElement *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), |
| 215 | 'const xmlElement *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), |
| 216 | 'xmlAttributePtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), |
| 217 | 'const xmlAttributePtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), |
| 218 | 'xmlAttribute *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), |
| 219 | 'const xmlAttribute *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), |
| 220 | 'xmlNsPtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), |
| 221 | 'const xmlNsPtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), |
| 222 | 'xmlNs *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), |
| 223 | 'const xmlNs *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), |
| 224 | 'xmlDocPtr': ('O', "xmlNode", "xmlDocPtr", "xmlDocPtr"), |
| 225 | 'const xmlDocPtr': ('O', "xmlNode", "xmlDocPtr", "xmlDocPtr"), |
| 226 | 'xmlDoc *': ('O', "xmlNode", "xmlDocPtr", "xmlDocPtr"), |
| 227 | 'const xmlDoc *': ('O', "xmlNode", "xmlDocPtr", "xmlDocPtr"), |
| 228 | 'htmlDocPtr': ('O', "xmlNode", "xmlDocPtr", "xmlDocPtr"), |
| 229 | 'const htmlDocPtr': ('O', "xmlNode", "xmlDocPtr", "xmlDocPtr"), |
| 230 | 'htmlDoc *': ('O', "xmlNode", "xmlDocPtr", "xmlDocPtr"), |
| 231 | 'const htmlDoc *': ('O', "xmlNode", "xmlDocPtr", "xmlDocPtr"), |
| 232 | 'htmlNodePtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), |
| 233 | 'const htmlNodePtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), |
| 234 | 'htmlNode *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), |
| 235 | 'const htmlNode *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), |
Daniel Veillard | d2897fd | 2002-01-30 16:37:32 +0000 | [diff] [blame] | 236 | } |
| 237 | |
| 238 | unknown_types = {} |
| 239 | |
Daniel Veillard | 96fe095 | 2002-01-30 20:52:23 +0000 | [diff] [blame] | 240 | def print_function_wrapper(name, output, export, include): |
Daniel Veillard | d2897fd | 2002-01-30 16:37:32 +0000 | [diff] [blame] | 241 | global py_types |
| 242 | global unknown_types |
| 243 | global functions |
| 244 | global skipped_modules |
| 245 | |
| 246 | try: |
| 247 | (desc, ret, args, file) = functions[name] |
| 248 | except: |
| 249 | print "failed to get function %s infos" |
| 250 | return |
| 251 | |
| 252 | if skipped_modules.has_key(file): |
| 253 | return 0 |
| 254 | |
| 255 | c_call = ""; |
| 256 | format="" |
| 257 | format_args="" |
| 258 | c_args="" |
| 259 | c_return="" |
Daniel Veillard | 96fe095 | 2002-01-30 20:52:23 +0000 | [diff] [blame] | 260 | c_convert="" |
Daniel Veillard | d2897fd | 2002-01-30 16:37:32 +0000 | [diff] [blame] | 261 | for arg in args: |
Daniel Veillard | 96fe095 | 2002-01-30 20:52:23 +0000 | [diff] [blame] | 262 | # This should be correct |
| 263 | if arg[1][0:6] == "const ": |
| 264 | arg[1] = arg[1][6:] |
Daniel Veillard | d2897fd | 2002-01-30 16:37:32 +0000 | [diff] [blame] | 265 | c_args = c_args + " %s %s;\n" % (arg[1], arg[0]) |
| 266 | if py_types.has_key(arg[1]): |
Daniel Veillard | 96fe095 | 2002-01-30 20:52:23 +0000 | [diff] [blame] | 267 | (f, t, n, c) = py_types[arg[1]] |
Daniel Veillard | d2897fd | 2002-01-30 16:37:32 +0000 | [diff] [blame] | 268 | if f != None: |
| 269 | format = format + f |
| 270 | if t != None: |
Daniel Veillard | 96fe095 | 2002-01-30 20:52:23 +0000 | [diff] [blame] | 271 | format_args = format_args + ", &pyobj_%s" % (arg[0]) |
| 272 | c_args = c_args + " PyObject *pyobj_%s;\n" % (arg[0]) |
| 273 | c_convert = c_convert + \ |
| 274 | " %s = (%s) Py%s_Get(pyobj_%s);\n" % (arg[0], |
| 275 | arg[1], t, arg[0]); |
| 276 | else: |
| 277 | format_args = format_args + ", &%s" % (arg[0]) |
Daniel Veillard | d2897fd | 2002-01-30 16:37:32 +0000 | [diff] [blame] | 278 | if c_call != "": |
| 279 | c_call = c_call + ", "; |
| 280 | c_call = c_call + "%s" % (arg[0]) |
| 281 | else: |
Daniel Veillard | 96fe095 | 2002-01-30 20:52:23 +0000 | [diff] [blame] | 282 | if skipped_types.has_key(arg[1]): |
| 283 | return 0 |
Daniel Veillard | d2897fd | 2002-01-30 16:37:32 +0000 | [diff] [blame] | 284 | if unknown_types.has_key(arg[1]): |
| 285 | lst = unknown_types[arg[1]] |
| 286 | lst.append(name) |
| 287 | else: |
| 288 | unknown_types[arg[1]] = [name] |
| 289 | return -1 |
| 290 | if format != "": |
| 291 | format = format + ":%s" % (name) |
| 292 | |
| 293 | if ret[0] == 'void': |
| 294 | c_call = "\n %s(%s);\n" % (name, c_call); |
| 295 | ret_convert = " Py_INCREF(Py_None);\n return(Py_None);\n" |
| 296 | elif py_types.has_key(ret[0]): |
Daniel Veillard | 96fe095 | 2002-01-30 20:52:23 +0000 | [diff] [blame] | 297 | (f, t, n, c) = py_types[ret[0]] |
Daniel Veillard | d2897fd | 2002-01-30 16:37:32 +0000 | [diff] [blame] | 298 | c_return = " %s c_retval;\n" % (ret[0]) |
| 299 | c_call = "\n c_retval = %s(%s);\n" % (name, c_call); |
Daniel Veillard | 96fe095 | 2002-01-30 20:52:23 +0000 | [diff] [blame] | 300 | ret_convert = " py_retval = libxml_%sWrap((%s) c_retval);\n" % (n,c) |
| 301 | ret_convert = ret_convert + " return(py_retval);\n" |
Daniel Veillard | d2897fd | 2002-01-30 16:37:32 +0000 | [diff] [blame] | 302 | else: |
Daniel Veillard | 96fe095 | 2002-01-30 20:52:23 +0000 | [diff] [blame] | 303 | if skipped_types.has_key(ret[0]): |
| 304 | return 0 |
Daniel Veillard | d2897fd | 2002-01-30 16:37:32 +0000 | [diff] [blame] | 305 | if unknown_types.has_key(ret[0]): |
| 306 | lst = unknown_types[ret[0]] |
| 307 | lst.append(name) |
| 308 | else: |
| 309 | unknown_types[ret[0]] = [name] |
| 310 | return -1 |
| 311 | |
Daniel Veillard | 96fe095 | 2002-01-30 20:52:23 +0000 | [diff] [blame] | 312 | include.write("PyObject * ") |
| 313 | include.write("libxml_%s(PyObject *self, PyObject *args);\n" % (name)) |
| 314 | export.write(" { \"%s\", libxml_%s, METH_VARARGS },\n" % (name, name)) |
Daniel Veillard | d2897fd | 2002-01-30 16:37:32 +0000 | [diff] [blame] | 315 | output.write("PyObject *\n") |
| 316 | output.write("libxml_%s(PyObject *self, PyObject *args) {\n" % (name)) |
| 317 | if ret[0] != 'void': |
| 318 | output.write(" PyObject *py_retval;\n") |
| 319 | if c_return != "": |
| 320 | output.write(c_return) |
| 321 | if c_args != "": |
| 322 | output.write(c_args) |
| 323 | if format != "": |
| 324 | output.write("\n if (!PyArg_ParseTuple(args, \"%s\"%s))\n" % |
| 325 | (format, format_args)) |
| 326 | output.write(" return(NULL);\n") |
Daniel Veillard | 96fe095 | 2002-01-30 20:52:23 +0000 | [diff] [blame] | 327 | if c_convert != "": |
| 328 | output.write(c_convert) |
Daniel Veillard | d2897fd | 2002-01-30 16:37:32 +0000 | [diff] [blame] | 329 | |
| 330 | output.write(c_call) |
| 331 | output.write(ret_convert) |
| 332 | output.write("}\n\n") |
| 333 | return 1 |
| 334 | |
| 335 | try: |
| 336 | f = open("libxml2-api.xml") |
| 337 | data = f.read() |
| 338 | (parser, target) = getparser() |
| 339 | parser.feed(data) |
| 340 | parser.close() |
| 341 | except IOError, msg: |
| 342 | print file, ":", msg |
| 343 | |
| 344 | print "Found %d functions in libxml2-api.xml" % (len(functions.keys())) |
| 345 | nb_wrap = 0 |
| 346 | failed = 0 |
| 347 | skipped = 0 |
| 348 | |
Daniel Veillard | 96fe095 | 2002-01-30 20:52:23 +0000 | [diff] [blame] | 349 | include = open("libxml2-py.h", "w") |
| 350 | include.write("/* Generated */\n\n") |
| 351 | export = open("libxml2-export.c", "w") |
| 352 | export.write("/* Generated */\n\n") |
Daniel Veillard | d2897fd | 2002-01-30 16:37:32 +0000 | [diff] [blame] | 353 | wrapper = open("libxml2-py.c", "w") |
| 354 | wrapper.write("/* Generated */\n\n") |
| 355 | wrapper.write("#include <Python.h>\n") |
| 356 | wrapper.write("#include <libxml/tree.h>\n") |
| 357 | wrapper.write("#include \"libxml_wrap.h\"\n") |
| 358 | wrapper.write("#include \"libxml2-py.h\"\n\n") |
| 359 | for function in functions.keys(): |
Daniel Veillard | 96fe095 | 2002-01-30 20:52:23 +0000 | [diff] [blame] | 360 | ret = print_function_wrapper(function, wrapper, export, include) |
Daniel Veillard | d2897fd | 2002-01-30 16:37:32 +0000 | [diff] [blame] | 361 | if ret < 0: |
| 362 | failed = failed + 1 |
Daniel Veillard | 36ed529 | 2002-01-30 23:49:06 +0000 | [diff] [blame^] | 363 | del functions[function] |
Daniel Veillard | d2897fd | 2002-01-30 16:37:32 +0000 | [diff] [blame] | 364 | if ret == 0: |
| 365 | skipped = skipped + 1 |
Daniel Veillard | 36ed529 | 2002-01-30 23:49:06 +0000 | [diff] [blame^] | 366 | del functions[function] |
| 367 | if ret == 1: |
| 368 | nb_wrap = nb_wrap + 1 |
Daniel Veillard | 96fe095 | 2002-01-30 20:52:23 +0000 | [diff] [blame] | 369 | include.close() |
| 370 | export.close() |
Daniel Veillard | d2897fd | 2002-01-30 16:37:32 +0000 | [diff] [blame] | 371 | wrapper.close() |
| 372 | |
| 373 | print "Generated %d wrapper functions, %d failed, %d skipped\n" % (nb_wrap, |
| 374 | failed, skipped); |
| 375 | print "Missing type converters: %s" % (unknown_types.keys()) |
Daniel Veillard | 36ed529 | 2002-01-30 23:49:06 +0000 | [diff] [blame^] | 376 | |
| 377 | function_classes = {} |
| 378 | for name in functions.keys(): |
| 379 | (desc, ret, args, file) = functions[name] |
| 380 | if name[0:3] == "xml" and len(args) >= 1 and args[0][1] == "xmlNodePtr": |
| 381 | if name[0:11] == "xmlNodeList": |
| 382 | func = name[11:] |
| 383 | func = string.lower(func[0:1]) + func[1:] |
| 384 | info = (0, func, name, ret, args, file) |
| 385 | if function_classes.has_key('xmlNode'): |
| 386 | function_classes['xmlNode'].append(info) |
| 387 | else: |
| 388 | function_classes['xmlNode'] = [info] |
| 389 | elif name[0:7] == "xmlNode": |
| 390 | func = name[7:] |
| 391 | func = string.lower(func[0:1]) + func[1:] |
| 392 | info = (0, func, name, ret, args, file) |
| 393 | if function_classes.has_key('xmlNode'): |
| 394 | function_classes['xmlNode'].append(info) |
| 395 | else: |
| 396 | function_classes['xmlNode'] = [info] |
| 397 | elif name[0:6] == "xmlGet": |
| 398 | func = name[6:] |
| 399 | func = string.lower(func[0:1]) + func[1:] |
| 400 | info = (0, func, name, ret, args, file) |
| 401 | if function_classes.has_key('xmlNode'): |
| 402 | function_classes['xmlNode'].append(info) |
| 403 | else: |
| 404 | function_classes['xmlNode'] = [info] |
| 405 | else: |
| 406 | func = name[3:] |
| 407 | func = string.lower(func[0:1]) + func[1:] |
| 408 | info = (0, func, name, ret, args, file) |
| 409 | if function_classes.has_key('xmlNode'): |
| 410 | function_classes['xmlNode'].append(info) |
| 411 | else: |
| 412 | function_classes['xmlNode'] = [info] |
| 413 | elif name[0:3] == "xml" and len(args) >= 2 and args[1][1] == "xmlNodePtr": |
| 414 | if name[0:11] == "xmlNodeList": |
| 415 | func = name[11:] |
| 416 | func = string.lower(func[0:1]) + func[1:] |
| 417 | info = (1, func, name, ret, args, file) |
| 418 | if function_classes.has_key('xmlNode'): |
| 419 | function_classes['xmlNode'].append(info) |
| 420 | else: |
| 421 | function_classes['xmlNode'] = [info] |
| 422 | elif name[0:7] == "xmlNode": |
| 423 | func = name[7:] |
| 424 | func = string.lower(func[0:1]) + func[1:] |
| 425 | info = (1, func, name, ret, args, file) |
| 426 | if function_classes.has_key('xmlNode'): |
| 427 | function_classes['xmlNode'].append(info) |
| 428 | else: |
| 429 | function_classes['xmlNode'] = [info] |
| 430 | elif name[0:6] == "xmlGet": |
| 431 | func = name[6:] |
| 432 | func = string.lower(func[0:1]) + func[1:] |
| 433 | info = (1, func, name, ret, args, file) |
| 434 | if function_classes.has_key('xmlNode'): |
| 435 | function_classes['xmlNode'].append(info) |
| 436 | else: |
| 437 | function_classes['xmlNode'] = [info] |
| 438 | else: |
| 439 | func = name[3:] |
| 440 | func = string.lower(func[0:1]) + func[1:] |
| 441 | info = (1, func, name, ret, args, file) |
| 442 | if function_classes.has_key('xmlNode'): |
| 443 | function_classes['xmlNode'].append(info) |
| 444 | else: |
| 445 | function_classes['xmlNode'] = [info] |
| 446 | elif name[0:3] == "xml" and len(args) >= 1 and args[0][1] == "xmlDocPtr": |
| 447 | if name[0:6] == "xmlDoc": |
| 448 | func = name[6:] |
| 449 | func = string.lower(func[0:1]) + func[1:] |
| 450 | info = (0, func, name, ret, args, file) |
| 451 | if function_classes.has_key('xmlDoc'): |
| 452 | function_classes['xmlDoc'].append(info) |
| 453 | else: |
| 454 | function_classes['xmlDoc'] = [info] |
| 455 | elif name[0:6] == "xmlGet": |
| 456 | func = name[6:] |
| 457 | func = string.lower(func[0:1]) + func[1:] |
| 458 | info = (0, func, name, ret, args, file) |
| 459 | if function_classes.has_key('xmlDoc'): |
| 460 | function_classes['xmlDoc'].append(info) |
| 461 | else: |
| 462 | function_classes['xmlDoc'] = [info] |
| 463 | else: |
| 464 | func = name[3:] |
| 465 | func = string.lower(func[0:1]) + func[1:] |
| 466 | info = (0, func, name, ret, args, file) |
| 467 | if function_classes.has_key('xmlDoc'): |
| 468 | function_classes['xmlDoc'].append(info) |
| 469 | else: |
| 470 | function_classes['xmlDoc'] = [info] |
| 471 | elif name[0:3] == "xml" and len(args) >= 2 and args[1][1] == "xmlDocPtr": |
| 472 | if name[0:6] == "xmlDoc": |
| 473 | func = name[6:] |
| 474 | func = string.lower(func[0:1]) + func[1:] |
| 475 | info = (1, func, name, ret, args, file) |
| 476 | if function_classes.has_key('xmlDoc'): |
| 477 | function_classes['xmlDoc'].append(info) |
| 478 | else: |
| 479 | function_classes['xmlDoc'] = [info] |
| 480 | elif name[0:6] == "xmlGet": |
| 481 | func = name[6:] |
| 482 | func = string.lower(func[0:1]) + func[1:] |
| 483 | info = (1, func, name, ret, args, file) |
| 484 | if function_classes.has_key('xmlDoc'): |
| 485 | function_classes['xmlDoc'].append(info) |
| 486 | else: |
| 487 | function_classes['xmlDoc'] = [info] |
| 488 | else: |
| 489 | func = name[3:] |
| 490 | func = string.lower(func[0:1]) + func[1:] |
| 491 | info = (1, func, name, ret, args, file) |
| 492 | if function_classes.has_key('xmlDoc'): |
| 493 | function_classes['xmlDoc'].append(info) |
| 494 | else: |
| 495 | function_classes['xmlDoc'] = [info] |
| 496 | elif ret[0] == "xmlDocPtr" or ret[0] == "xmlDtdPtr": |
| 497 | func = name[3:] |
| 498 | func = string.lower(func[0:1]) + func[1:] |
| 499 | info = (0, func, name, ret, args, file) |
| 500 | if function_classes.has_key('None'): |
| 501 | function_classes['None'].append(info) |
| 502 | else: |
| 503 | function_classes['None'] = [info] |
| 504 | else: |
| 505 | print "unable to guess class for %s:%s" % (file,name) |
| 506 | |
| 507 | classes_type = { |
| 508 | "xmlNodePtr": ("._o", "xmlNode(_obj=%s)"), |
| 509 | "xmlNode *": ("._o", "xmlNode(_obj=%s)"), |
| 510 | "xmlDocPtr": ("._o", "xmlDoc(_obj=%s)"), |
| 511 | "xmlDocPtr *": ("._o", "xmlDoc(_obj=%s)"), |
| 512 | "xmlAttrPtr": ("._o", "xmlNode(_obj=%s)"), |
| 513 | "xmlAttr *": ("._o", "xmlNode(_obj=%s)"), |
| 514 | "xmlNsPtr": ("._o", "xmlNode(_obj=%s)"), |
| 515 | "xmlNs *": ("._o", "xmlNode(_obj=%s)"), |
| 516 | "xmlDtdPtr": ("._o", "xmlNode(_obj=%s)"), |
| 517 | "xmlDtd *": ("._o", "xmlNode(_obj=%s)"), |
| 518 | "xmlEntityPtr": ("._o", "xmlNode(_obj=%s)"), |
| 519 | "xmlEntity *": ("._o", "xmlNode(_obj=%s)"), |
| 520 | } |
| 521 | |
| 522 | classes = open("libxml2class.py", "w") |
| 523 | |
| 524 | if function_classes.has_key("None"): |
| 525 | for info in function_classes["None"]: |
| 526 | (index, func, name, ret, args, file) = info |
| 527 | classes.write("def %s(" % func) |
| 528 | n = 0 |
| 529 | for arg in args: |
| 530 | if n != 0: |
| 531 | classes.write(", ") |
| 532 | classes.write("%s" % arg[0]) |
| 533 | n = n + 1 |
| 534 | classes.write("):\n") |
| 535 | if ret[0] != "void": |
| 536 | classes.write(" ret = "); |
| 537 | else: |
| 538 | classes.write(" "); |
| 539 | classes.write("_libxml.%s(" % name) |
| 540 | n = 0 |
| 541 | for arg in args: |
| 542 | if n != 0: |
| 543 | classes.write(", "); |
| 544 | classes.write("%s" % arg[0]) |
| 545 | if classes_type.has_key(arg[1]): |
| 546 | classes.write(classes_type[arg[1]][0]) |
| 547 | n = n + 1 |
| 548 | classes.write(")\n"); |
| 549 | if ret[0] != "void": |
| 550 | if classes_type.has_key(ret[0]): |
| 551 | classes.write(" if ret == None: return None\n"); |
| 552 | classes.write(" return "); |
| 553 | classes.write(classes_type[ret[0]][1] % ("ret")); |
| 554 | classes.write("\n"); |
| 555 | else: |
| 556 | classes.write(" return ret\n"); |
| 557 | classes.write("\n"); |
| 558 | |
| 559 | for classname in function_classes.keys(): |
| 560 | if classname == "None": |
| 561 | pass |
| 562 | else: |
| 563 | classes.write("class %s(xmlCore):\n" % classname); |
| 564 | if classname == "xmlNode": |
| 565 | classes.write(" def __init__(self, _obj=None):\n") |
| 566 | classes.write(" self._o = None\n") |
| 567 | classes.write(" xmlCore.__init__(self, _obj=_obj)\n\n") |
| 568 | elif classname == "xmlDoc": |
| 569 | classes.write(" def __init__(self, _obj=None):\n") |
| 570 | classes.write(" self._o = None\n") |
| 571 | classes.write(" xmlCore.__init__(self, _obj=_obj)\n\n") |
| 572 | else: |
| 573 | classes.write(" def __init__(self, _obj=None):\n") |
| 574 | classes.write(" if _obj != None:self._o = _obj;return\n") |
| 575 | classes.write(" self._o = None\n\n"); |
| 576 | for info in function_classes[classname]: |
| 577 | (index, func, name, ret, args, file) = info |
| 578 | classes.write(" def %s(self" % func) |
| 579 | n = 0 |
| 580 | for arg in args: |
| 581 | if n != index: |
| 582 | classes.write(", %s" % arg[0]) |
| 583 | n = n + 1 |
| 584 | classes.write("):\n") |
| 585 | if ret[0] != "void": |
| 586 | classes.write(" ret = "); |
| 587 | else: |
| 588 | classes.write(" "); |
| 589 | classes.write("_libxml.%s(" % name) |
| 590 | n = 0 |
| 591 | for arg in args: |
| 592 | if n != 0: |
| 593 | classes.write(", "); |
| 594 | if n != index: |
| 595 | classes.write("%s" % arg[0]) |
| 596 | else: |
| 597 | classes.write("self"); |
| 598 | if classes_type.has_key(arg[1]): |
| 599 | classes.write(classes_type[arg[1]][0]) |
| 600 | n = n + 1 |
| 601 | classes.write(")\n"); |
| 602 | if ret[0] != "void": |
| 603 | if classes_type.has_key(ret[0]): |
| 604 | classes.write(" if ret == None: return None\n"); |
| 605 | classes.write(" return "); |
| 606 | classes.write(classes_type[ret[0]][1] % ("ret")); |
| 607 | classes.write("\n"); |
| 608 | else: |
| 609 | classes.write(" return ret\n"); |
| 610 | classes.write("\n"); |
| 611 | |
| 612 | classes.close() |