blob: decd4202a09de6ef0427d38855db5536d42f5cc6 [file] [log] [blame]
Daniel Veillardd2897fd2002-01-30 16:37:32 +00001#!/usr/bin/python -u
2#
3# generate python wrappers from the XML API description
4#
5
6functions = {}
7
Daniel Veillard36ed5292002-01-30 23:49:06 +00008import string
Daniel Veillard1971ee22002-01-31 20:29:19 +00009
10#######################################################################
11#
12# That part if purely the API acquisition phase from the
13# XML API description
14#
15#######################################################################
16import os
Daniel Veillardd2897fd2002-01-30 16:37:32 +000017import xmllib
18try:
19 import sgmlop
20except ImportError:
21 sgmlop = None # accelerator not available
22
23debug = 0
24
25if sgmlop:
26 class FastParser:
27 """sgmlop based XML parser. this is typically 15x faster
28 than SlowParser..."""
29
30 def __init__(self, target):
31
32 # setup callbacks
33 self.finish_starttag = target.start
34 self.finish_endtag = target.end
35 self.handle_data = target.data
36
37 # activate parser
38 self.parser = sgmlop.XMLParser()
39 self.parser.register(self)
40 self.feed = self.parser.feed
41 self.entity = {
42 "amp": "&", "gt": ">", "lt": "<",
43 "apos": "'", "quot": '"'
44 }
45
46 def close(self):
47 try:
48 self.parser.close()
49 finally:
50 self.parser = self.feed = None # nuke circular reference
51
52 def handle_entityref(self, entity):
53 # <string> entity
54 try:
55 self.handle_data(self.entity[entity])
56 except KeyError:
57 self.handle_data("&%s;" % entity)
58
59else:
60 FastParser = None
61
62
63class SlowParser(xmllib.XMLParser):
64 """slow but safe standard parser, based on the XML parser in
65 Python's standard library."""
66
67 def __init__(self, target):
68 self.unknown_starttag = target.start
69 self.handle_data = target.data
70 self.unknown_endtag = target.end
71 xmllib.XMLParser.__init__(self)
72
73def getparser(target = None):
74 # get the fastest available parser, and attach it to an
75 # unmarshalling object. return both objects.
76 if target == None:
77 target = docParser()
78 if FastParser:
79 return FastParser(target), target
80 return SlowParser(target), target
81
82class docParser:
83 def __init__(self):
84 self._methodname = None
85 self._data = []
86 self.in_function = 0
87
88 def close(self):
89 if debug:
90 print "close"
91
92 def getmethodname(self):
93 return self._methodname
94
95 def data(self, text):
96 if debug:
97 print "data %s" % text
98 self._data.append(text)
99
100 def start(self, tag, attrs):
101 if debug:
102 print "start %s, %s" % (tag, attrs)
103 if tag == 'function':
104 self._data = []
105 self.in_function = 1
106 self.function = None
107 self.function_args = []
108 self.function_descr = None
109 self.function_return = None
110 self.function_file = None
111 if attrs.has_key('name'):
112 self.function = attrs['name']
113 if attrs.has_key('file'):
114 self.function_file = attrs['file']
115 elif tag == 'info':
116 self._data = []
117 elif tag == 'arg':
118 if self.in_function == 1:
119 self.function_arg_name = None
120 self.function_arg_type = None
121 self.function_arg_info = None
122 if attrs.has_key('name'):
123 self.function_arg_name = attrs['name']
124 if attrs.has_key('type'):
125 self.function_arg_type = attrs['type']
126 if attrs.has_key('info'):
127 self.function_arg_info = attrs['info']
128 elif tag == 'return':
129 if self.in_function == 1:
130 self.function_return_type = None
131 self.function_return_info = None
132 if attrs.has_key('type'):
133 self.function_return_type = attrs['type']
134 if attrs.has_key('info'):
135 self.function_return_info = attrs['info']
136
137
138 def end(self, tag):
139 if debug:
140 print "end %s" % tag
141 if tag == 'function':
142 if self.function != None:
143 function(self.function, self.function_descr,
144 self.function_return, self.function_args,
145 self.function_file)
146 self.in_function = 0
147 elif tag == 'arg':
148 if self.in_function == 1:
149 self.function_args.append([self.function_arg_name,
150 self.function_arg_type,
151 self.function_arg_info])
152 elif tag == 'return':
153 if self.in_function == 1:
154 self.function_return = [self.function_return_type,
155 self.function_return_info]
156 elif tag == 'info':
157 str = ''
158 for c in self._data:
159 str = str + c
160 if self.in_function == 1:
161 self.function_descr = str
162
163
164def function(name, desc, ret, args, file):
165 global functions
166
167 functions[name] = (desc, ret, args, file)
168
Daniel Veillard1971ee22002-01-31 20:29:19 +0000169#######################################################################
170#
171# Some filtering rukes to drop functions/types which should not
172# be exposed as-is on the Python interface
173#
174#######################################################################
Daniel Veillard36ed5292002-01-30 23:49:06 +0000175
Daniel Veillardd2897fd2002-01-30 16:37:32 +0000176skipped_modules = {
177 'xmlmemory': None,
Daniel Veillard96fe0952002-01-30 20:52:23 +0000178 'DOCBparser': None,
179 'SAX': None,
180 'hash': None,
181 'list': None,
182 'threads': None,
Daniel Veillard1971ee22002-01-31 20:29:19 +0000183 'xpointer': None,
Daniel Veillard96fe0952002-01-30 20:52:23 +0000184}
185skipped_types = {
186 'int *': "usually a return type",
187 'xmlSAXHandlerPtr': "not the proper interface for SAX",
188 'htmlSAXHandlerPtr': "not the proper interface for SAX",
189 'xmlParserCtxtPtr': "not the proper interface for the parser",
190 'htmlParserCtxtPtr': "not the proper interface for the parser",
191 'xmlRMutexPtr': "thread specific, skipped",
192 'xmlMutexPtr': "thread specific, skipped",
193 'xmlGlobalStatePtr': "thread specific, skipped",
194 'xmlListPtr': "internal representation not suitable for python",
195 'xmlBufferPtr': "internal representation not suitable for python",
196 'FILE *': None,
Daniel Veillardd2897fd2002-01-30 16:37:32 +0000197}
Daniel Veillard1971ee22002-01-31 20:29:19 +0000198
199#######################################################################
200#
201# Table of remapping to/from the python type or class to the C
202# counterpart.
203#
204#######################################################################
205
Daniel Veillardd2897fd2002-01-30 16:37:32 +0000206py_types = {
Daniel Veillard96fe0952002-01-30 20:52:23 +0000207 'void': (None, None, None, None),
208 'int': ('i', None, "int", "int"),
209 'long': ('i', None, "int", "int"),
210 'double': ('d', None, "double", "double"),
211 'unsigned int': ('i', None, "int", "int"),
212 'xmlChar': ('c', None, "int", "int"),
213 'unsigned char *': ('s', None, "charPtr", "char *"),
214 'char *': ('s', None, "charPtr", "char *"),
215 'const char *': ('s', None, "charPtr", "char *"),
216 'xmlChar *': ('s', None, "xmlCharPtr", "xmlChar *"),
217 'const xmlChar *': ('s', None, "xmlCharPtr", "xmlChar *"),
218 'xmlNodePtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"),
219 'const xmlNodePtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"),
220 'xmlNode *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"),
221 'const xmlNode *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"),
222 'xmlDtdPtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"),
223 'const xmlDtdPtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"),
224 'xmlDtd *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"),
225 'const xmlDtd *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"),
226 'xmlAttrPtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"),
227 'const xmlAttrPtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"),
228 'xmlAttr *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"),
229 'const xmlAttr *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"),
230 'xmlEntityPtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"),
231 'const xmlEntityPtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"),
232 'xmlEntity *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"),
233 'const xmlEntity *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"),
Daniel Veillard1971ee22002-01-31 20:29:19 +0000234 'xmlElementPtr': ('O', "xmlElement", "xmlElementPtr", "xmlElementPtr"),
235 'const xmlElementPtr': ('O', "xmlElement", "xmlElementPtr", "xmlElementPtr"),
236 'xmlElement *': ('O', "xmlElement", "xmlElementPtr", "xmlElementPtr"),
237 'const xmlElement *': ('O', "xmlElement", "xmlElementPtr", "xmlElementPtr"),
238 'xmlAttributePtr': ('O', "xmlAttribute", "xmlAttributePtr", "xmlAttributePtr"),
239 'const xmlAttributePtr': ('O', "xmlAttribute", "xmlAttributePtr", "xmlAttributePtr"),
240 'xmlAttribute *': ('O', "xmlAttribute", "xmlAttributePtr", "xmlAttributePtr"),
241 'const xmlAttribute *': ('O', "xmlAttribute", "xmlAttributePtr", "xmlAttributePtr"),
242 'xmlNsPtr': ('O', "xmlNode", "xmlNsPtr", "xmlNsPtr"),
243 'const xmlNsPtr': ('O', "xmlNode", "xmlNsPtr", "xmlNsPtr"),
244 'xmlNs *': ('O', "xmlNode", "xmlNsPtr", "xmlNsPtr"),
245 'const xmlNs *': ('O', "xmlNode", "xmlNsPtr", "xmlNsPtr"),
Daniel Veillard96fe0952002-01-30 20:52:23 +0000246 'xmlDocPtr': ('O', "xmlNode", "xmlDocPtr", "xmlDocPtr"),
247 'const xmlDocPtr': ('O', "xmlNode", "xmlDocPtr", "xmlDocPtr"),
248 'xmlDoc *': ('O', "xmlNode", "xmlDocPtr", "xmlDocPtr"),
249 'const xmlDoc *': ('O', "xmlNode", "xmlDocPtr", "xmlDocPtr"),
250 'htmlDocPtr': ('O', "xmlNode", "xmlDocPtr", "xmlDocPtr"),
251 'const htmlDocPtr': ('O', "xmlNode", "xmlDocPtr", "xmlDocPtr"),
252 'htmlDoc *': ('O', "xmlNode", "xmlDocPtr", "xmlDocPtr"),
253 'const htmlDoc *': ('O', "xmlNode", "xmlDocPtr", "xmlDocPtr"),
254 'htmlNodePtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"),
255 'const htmlNodePtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"),
256 'htmlNode *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"),
257 'const htmlNode *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"),
Daniel Veillard1971ee22002-01-31 20:29:19 +0000258 'xmlXPathContextPtr': ('O', "xmlXPathContext", "xmlXPathContextPtr", "xmlXPathContextPtr"),
259 'xmlXPathContext *': ('O', "xpathContext", "xmlXPathContextPtr", "xmlXPathContextPtr"),
260}
261
262py_return_types = {
263 'xmlXPathObjectPtr': ('O', "foo", "xmlXPathObjectPtr", "xmlXPathObjectPtr"),
Daniel Veillardd2897fd2002-01-30 16:37:32 +0000264}
265
266unknown_types = {}
267
Daniel Veillard1971ee22002-01-31 20:29:19 +0000268#######################################################################
269#
270# This part writes the C <-> Python stubs libxml2-py.[ch] and
271# the table libxml2-export.c to add when registrering the Python module
272#
273#######################################################################
274
275def skip_function(name):
276 if name[0:12] == "xmlXPathWrap":
277 return 1
278# if name[0:11] == "xmlXPathNew":
279# return 1
280 return 0
281
Daniel Veillard96fe0952002-01-30 20:52:23 +0000282def print_function_wrapper(name, output, export, include):
Daniel Veillardd2897fd2002-01-30 16:37:32 +0000283 global py_types
284 global unknown_types
285 global functions
286 global skipped_modules
287
288 try:
289 (desc, ret, args, file) = functions[name]
290 except:
291 print "failed to get function %s infos"
292 return
293
294 if skipped_modules.has_key(file):
295 return 0
Daniel Veillard1971ee22002-01-31 20:29:19 +0000296 if skip_function(name) == 1:
297 return 0
Daniel Veillardd2897fd2002-01-30 16:37:32 +0000298
299 c_call = "";
300 format=""
301 format_args=""
302 c_args=""
303 c_return=""
Daniel Veillard96fe0952002-01-30 20:52:23 +0000304 c_convert=""
Daniel Veillardd2897fd2002-01-30 16:37:32 +0000305 for arg in args:
Daniel Veillard96fe0952002-01-30 20:52:23 +0000306 # This should be correct
307 if arg[1][0:6] == "const ":
308 arg[1] = arg[1][6:]
Daniel Veillardd2897fd2002-01-30 16:37:32 +0000309 c_args = c_args + " %s %s;\n" % (arg[1], arg[0])
310 if py_types.has_key(arg[1]):
Daniel Veillard96fe0952002-01-30 20:52:23 +0000311 (f, t, n, c) = py_types[arg[1]]
Daniel Veillardd2897fd2002-01-30 16:37:32 +0000312 if f != None:
313 format = format + f
314 if t != None:
Daniel Veillard96fe0952002-01-30 20:52:23 +0000315 format_args = format_args + ", &pyobj_%s" % (arg[0])
316 c_args = c_args + " PyObject *pyobj_%s;\n" % (arg[0])
317 c_convert = c_convert + \
318 " %s = (%s) Py%s_Get(pyobj_%s);\n" % (arg[0],
319 arg[1], t, arg[0]);
320 else:
321 format_args = format_args + ", &%s" % (arg[0])
Daniel Veillardd2897fd2002-01-30 16:37:32 +0000322 if c_call != "":
323 c_call = c_call + ", ";
324 c_call = c_call + "%s" % (arg[0])
325 else:
Daniel Veillard96fe0952002-01-30 20:52:23 +0000326 if skipped_types.has_key(arg[1]):
327 return 0
Daniel Veillardd2897fd2002-01-30 16:37:32 +0000328 if unknown_types.has_key(arg[1]):
329 lst = unknown_types[arg[1]]
330 lst.append(name)
331 else:
332 unknown_types[arg[1]] = [name]
333 return -1
334 if format != "":
335 format = format + ":%s" % (name)
336
337 if ret[0] == 'void':
338 c_call = "\n %s(%s);\n" % (name, c_call);
339 ret_convert = " Py_INCREF(Py_None);\n return(Py_None);\n"
340 elif py_types.has_key(ret[0]):
Daniel Veillard96fe0952002-01-30 20:52:23 +0000341 (f, t, n, c) = py_types[ret[0]]
Daniel Veillardd2897fd2002-01-30 16:37:32 +0000342 c_return = " %s c_retval;\n" % (ret[0])
343 c_call = "\n c_retval = %s(%s);\n" % (name, c_call);
Daniel Veillard96fe0952002-01-30 20:52:23 +0000344 ret_convert = " py_retval = libxml_%sWrap((%s) c_retval);\n" % (n,c)
345 ret_convert = ret_convert + " return(py_retval);\n"
Daniel Veillard1971ee22002-01-31 20:29:19 +0000346 elif py_return_types.has_key(ret[0]):
347 (f, t, n, c) = py_return_types[ret[0]]
348 c_return = " %s c_retval;\n" % (ret[0])
349 c_call = "\n c_retval = %s(%s);\n" % (name, c_call);
350 ret_convert = " py_retval = libxml_%sWrap((%s) c_retval);\n" % (n,c)
351 ret_convert = ret_convert + " return(py_retval);\n"
Daniel Veillardd2897fd2002-01-30 16:37:32 +0000352 else:
Daniel Veillard96fe0952002-01-30 20:52:23 +0000353 if skipped_types.has_key(ret[0]):
354 return 0
Daniel Veillardd2897fd2002-01-30 16:37:32 +0000355 if unknown_types.has_key(ret[0]):
356 lst = unknown_types[ret[0]]
357 lst.append(name)
358 else:
359 unknown_types[ret[0]] = [name]
360 return -1
361
Daniel Veillard96fe0952002-01-30 20:52:23 +0000362 include.write("PyObject * ")
363 include.write("libxml_%s(PyObject *self, PyObject *args);\n" % (name))
364 export.write(" { \"%s\", libxml_%s, METH_VARARGS },\n" % (name, name))
Daniel Veillardd2897fd2002-01-30 16:37:32 +0000365 output.write("PyObject *\n")
366 output.write("libxml_%s(PyObject *self, PyObject *args) {\n" % (name))
367 if ret[0] != 'void':
368 output.write(" PyObject *py_retval;\n")
369 if c_return != "":
370 output.write(c_return)
371 if c_args != "":
372 output.write(c_args)
373 if format != "":
374 output.write("\n if (!PyArg_ParseTuple(args, \"%s\"%s))\n" %
375 (format, format_args))
376 output.write(" return(NULL);\n")
Daniel Veillard96fe0952002-01-30 20:52:23 +0000377 if c_convert != "":
378 output.write(c_convert)
Daniel Veillardd2897fd2002-01-30 16:37:32 +0000379
380 output.write(c_call)
381 output.write(ret_convert)
382 output.write("}\n\n")
383 return 1
384
385try:
386 f = open("libxml2-api.xml")
387 data = f.read()
388 (parser, target) = getparser()
389 parser.feed(data)
390 parser.close()
391except IOError, msg:
392 print file, ":", msg
393
394print "Found %d functions in libxml2-api.xml" % (len(functions.keys()))
395nb_wrap = 0
396failed = 0
397skipped = 0
398
Daniel Veillard96fe0952002-01-30 20:52:23 +0000399include = open("libxml2-py.h", "w")
400include.write("/* Generated */\n\n")
401export = open("libxml2-export.c", "w")
402export.write("/* Generated */\n\n")
Daniel Veillardd2897fd2002-01-30 16:37:32 +0000403wrapper = open("libxml2-py.c", "w")
404wrapper.write("/* Generated */\n\n")
405wrapper.write("#include <Python.h>\n")
406wrapper.write("#include <libxml/tree.h>\n")
407wrapper.write("#include \"libxml_wrap.h\"\n")
408wrapper.write("#include \"libxml2-py.h\"\n\n")
409for function in functions.keys():
Daniel Veillard96fe0952002-01-30 20:52:23 +0000410 ret = print_function_wrapper(function, wrapper, export, include)
Daniel Veillardd2897fd2002-01-30 16:37:32 +0000411 if ret < 0:
412 failed = failed + 1
Daniel Veillard36ed5292002-01-30 23:49:06 +0000413 del functions[function]
Daniel Veillardd2897fd2002-01-30 16:37:32 +0000414 if ret == 0:
415 skipped = skipped + 1
Daniel Veillard36ed5292002-01-30 23:49:06 +0000416 del functions[function]
417 if ret == 1:
418 nb_wrap = nb_wrap + 1
Daniel Veillard96fe0952002-01-30 20:52:23 +0000419include.close()
420export.close()
Daniel Veillardd2897fd2002-01-30 16:37:32 +0000421wrapper.close()
422
423print "Generated %d wrapper functions, %d failed, %d skipped\n" % (nb_wrap,
424 failed, skipped);
425print "Missing type converters: %s" % (unknown_types.keys())
Daniel Veillard36ed5292002-01-30 23:49:06 +0000426
Daniel Veillard1971ee22002-01-31 20:29:19 +0000427#######################################################################
428#
429# This part writes part of the Python front-end classes based on
430# mapping rules between types and classes and also based on function
431# renaming to get consistent function names at the Python level
432#
433#######################################################################
434
435#
436# The type automatically remapped to generated classes
437#
438classes_type = {
439 "xmlNodePtr": ("._o", "xmlNode(_obj=%s)", "xmlNode"),
440 "xmlNode *": ("._o", "xmlNode(_obj=%s)", "xmlNode"),
441 "xmlDocPtr": ("._o", "xmlDoc(_obj=%s)", "xmlDoc"),
442 "xmlDocPtr *": ("._o", "xmlDoc(_obj=%s)", "xmlDoc"),
443 "htmlDocPtr": ("._o", "xmlDoc(_obj=%s)", "xmlDoc"),
444 "htmlxmlDocPtr *": ("._o", "xmlDoc(_obj=%s)", "xmlDoc"),
445 "xmlAttrPtr": ("._o", "xmlAttr(_obj=%s)", "xmlAttr"),
446 "xmlAttr *": ("._o", "xmlAttr(_obj=%s)", "xmlAttr"),
447 "xmlNsPtr": ("._o", "xmlNs(_obj=%s)", "xmlNs"),
448 "xmlNs *": ("._o", "xmlNs(_obj=%s)", "xmlNs"),
449 "xmlDtdPtr": ("._o", "xmlDtd(_obj=%s)", "xmlDtd"),
450 "xmlDtd *": ("._o", "xmlDtd(_obj=%s)", "xmlDtd"),
451 "xmlEntityPtr": ("._o", "xmlEntity(_obj=%s)", "xmlEntity"),
452 "xmlEntity *": ("._o", "xmlEntity(_obj=%s)", "xmlEntity"),
453 "xmlElementPtr": ("._o", "xmlElement(_obj=%s)", "xmlElement"),
454 "xmlElement *": ("._o", "xmlElement(_obj=%s)", "xmlElement"),
455 "xmlAttributePtr": ("._o", "xmlAttribute(_obj=%s)", "xmlAttribute"),
456 "xmlAttribute *": ("._o", "xmlAttribute(_obj=%s)", "xmlAttribute"),
457 "xmlXPathContextPtr": ("._o", "xpathContext(_obj=%s)", "xpathContext"),
458}
459
460converter_type = {
461 "xmlXPathObjectPtr": "xpathObjectRet(%s)",
462}
463
464primary_classes = ["xmlNode", "xmlDoc"]
465
466classes_ancestor = {
467 "xmlNode" : "xmlCore",
468 "xmlDoc" : "xmlCore",
469 "xmlAttr" : "xmlCore",
470 "xmlNs" : "xmlCore",
471 "xmlDtd" : "xmlCore",
472 "xmlEntity" : "xmlCore",
473 "xmlElement" : "xmlCore",
474 "xmlAttribute" : "xmlCore",
475}
476classes_destructors = {
477 "xpathContext": "xmlXPathFreeContext",
478}
479
Daniel Veillard36ed5292002-01-30 23:49:06 +0000480function_classes = {}
Daniel Veillard1971ee22002-01-31 20:29:19 +0000481
482function_classes["None"] = []
483for type in classes_type.keys():
484 function_classes[classes_type[type][2]] = []
485
486#
487# Build the list of C types to look for ordered to start with primary classes
488#
489ctypes = []
490ctypes_processed = {}
491for classe in primary_classes:
492 for type in classes_type.keys():
493 tinfo = classes_type[type]
494 if tinfo[2] == classe:
495 ctypes.append(type)
496 ctypes_processed[type] = ()
497for type in classes_type.keys():
498 if ctypes_processed.has_key(type):
499 continue
500 tinfo = classes_type[type]
501 ctypes.append(type)
502 ctypes_processed[type] = ()
503
504def nameFixup(function, classe, type):
505 listname = classe + "List"
506 ll = len(listname)
507 l = len(classe)
508 if name[0:l] == listname:
509 func = name[l:]
510 func = string.lower(func[0:1]) + func[1:]
511 elif name[0:l] == classe:
512 func = name[l:]
513 func = string.lower(func[0:1]) + func[1:]
514 elif name[0:6] == "xmlGet":
515 func = name[6:]
516 func = string.lower(func[0:1]) + func[1:]
517 elif name[0:3] == "xml":
Daniel Veillard36ed5292002-01-30 23:49:06 +0000518 func = name[3:]
519 func = string.lower(func[0:1]) + func[1:]
Daniel Veillard36ed5292002-01-30 23:49:06 +0000520 else:
Daniel Veillard1971ee22002-01-31 20:29:19 +0000521 func = name
522 if func[0:5] == "xPath":
523 func = "xpath" + func[5:]
524 elif func[0:4] == "xPtr":
525 func = "xpointer" + func[4:]
526 elif func[0:8] == "xInclude":
527 func = "xinclude" + func[8:]
528 elif func[0:2] == "iD":
529 func = "ID" + func[2:]
530 elif func[0:3] == "uRI":
531 func = "URI" + func[3:]
532 elif func[0:4] == "uTF8":
533 func = "UTF8" + func[4:]
534 return func
Daniel Veillard36ed5292002-01-30 23:49:06 +0000535
Daniel Veillard1971ee22002-01-31 20:29:19 +0000536for name in functions.keys():
537 found = 0;
538 (desc, ret, args, file) = functions[name]
539 for type in ctypes:
540 classe = classes_type[type][2]
541
542 if name[0:3] == "xml" and len(args) >= 1 and args[0][1] == type:
543 found = 1
544 func = nameFixup(name, classe, type)
545 info = (0, func, name, ret, args, file)
546 function_classes[classe].append(info)
547 elif name[0:3] == "xml" and len(args) >= 2 and args[1][1] == type:
548 found = 1
549 func = nameFixup(name, classe, type)
550 info = (1, func, name, ret, args, file)
551 function_classes[classe].append(info)
552 elif name[0:4] == "html" and len(args) >= 1 and args[0][1] == type:
553 found = 1
554 func = nameFixup(name, classe, type)
555 info = (0, func, name, ret, args, file)
556 function_classes[classe].append(info)
557 elif name[0:4] == "html" and len(args) >= 2 and args[1][1] == type:
558 found = 1
559 func = nameFixup(name, classe, type)
560 info = (1, func, name, ret, args, file)
561 function_classes[classe].append(info)
562 if found == 1:
563 break
564 if found == 1:
565 continue
566 if name[0:8] == "xmlXPath":
567 continue
568 if name[0:6] == "xmlStr":
569 continue
570 if name[0:10] == "xmlCharStr":
571 continue
572 func = nameFixup(name, "None", file)
573 info = (0, func, name, ret, args, file)
574 function_classes['None'].append(info)
Daniel Veillard36ed5292002-01-30 23:49:06 +0000575
576classes = open("libxml2class.py", "w")
577
Daniel Veillard1971ee22002-01-31 20:29:19 +0000578def functionCompare(info1, info2):
579 (index1, func1, name1, ret1, args1, file1) = info1
580 (index2, func2, name2, ret2, args2, file2) = info2
581 if file1 < file2:
582 return -1
583 if file1 > file2:
584 return 1
585 if func1 < func2:
586 return -1
587 if func1 > func2:
588 return 1
589 return 0
590
591def writeDoc(name, args, indent, output):
592 if functions[name][0] == None or functions[name][0] == "":
593 return
594 val = functions[name][0]
595 val = string.replace(val, "NULL", "None");
596 output.write(indent)
597 output.write('"""')
598 while len(val) > 60:
599 str = val[0:60]
600 i = string.rfind(str, " ");
601 if i < 0:
602 i = 60
603 str = val[0:i]
604 val = val[i:]
605 output.write(str)
606 output.write('\n ');
607 output.write(indent)
608 output.write(val);
609 output.write('"""\n')
610
Daniel Veillard36ed5292002-01-30 23:49:06 +0000611if function_classes.has_key("None"):
Daniel Veillard1971ee22002-01-31 20:29:19 +0000612 flist = function_classes["None"]
613 flist.sort(functionCompare)
614 oldfile = ""
615 for info in flist:
Daniel Veillard36ed5292002-01-30 23:49:06 +0000616 (index, func, name, ret, args, file) = info
Daniel Veillard1971ee22002-01-31 20:29:19 +0000617 if file != oldfile:
618 classes.write("#\n# Functions from module %s\n#\n\n" % file)
619 oldfile = file
Daniel Veillard36ed5292002-01-30 23:49:06 +0000620 classes.write("def %s(" % func)
621 n = 0
622 for arg in args:
623 if n != 0:
624 classes.write(", ")
625 classes.write("%s" % arg[0])
626 n = n + 1
627 classes.write("):\n")
Daniel Veillard1971ee22002-01-31 20:29:19 +0000628 writeDoc(name, args, ' ', classes);
Daniel Veillard36ed5292002-01-30 23:49:06 +0000629 if ret[0] != "void":
630 classes.write(" ret = ");
631 else:
632 classes.write(" ");
633 classes.write("_libxml.%s(" % name)
634 n = 0
635 for arg in args:
636 if n != 0:
637 classes.write(", ");
638 classes.write("%s" % arg[0])
639 if classes_type.has_key(arg[1]):
640 classes.write(classes_type[arg[1]][0])
641 n = n + 1
642 classes.write(")\n");
643 if ret[0] != "void":
644 if classes_type.has_key(ret[0]):
645 classes.write(" if ret == None: return None\n");
646 classes.write(" return ");
647 classes.write(classes_type[ret[0]][1] % ("ret"));
648 classes.write("\n");
649 else:
650 classes.write(" return ret\n");
651 classes.write("\n");
652
653for classname in function_classes.keys():
654 if classname == "None":
655 pass
656 else:
Daniel Veillard1971ee22002-01-31 20:29:19 +0000657 if classes_ancestor.has_key(classname):
658 classes.write("class %s(%s):\n" % (classname,
659 classes_ancestor[classname]))
Daniel Veillard36ed5292002-01-30 23:49:06 +0000660 classes.write(" def __init__(self, _obj=None):\n")
661 classes.write(" self._o = None\n")
Daniel Veillard1971ee22002-01-31 20:29:19 +0000662 classes.write(" %s.__init__(self, _obj=_obj)\n\n" % (
663 classes_ancestor[classname]))
Daniel Veillard36ed5292002-01-30 23:49:06 +0000664 else:
Daniel Veillard1971ee22002-01-31 20:29:19 +0000665 classes.write("class %s:\n" % (classname))
Daniel Veillard36ed5292002-01-30 23:49:06 +0000666 classes.write(" def __init__(self, _obj=None):\n")
667 classes.write(" if _obj != None:self._o = _obj;return\n")
668 classes.write(" self._o = None\n\n");
Daniel Veillard1971ee22002-01-31 20:29:19 +0000669 if classes_destructors.has_key(classname):
670 classes.write(" def __del__(self):\n")
671 classes.write(" if self._o != None:\n")
672 classes.write(" _libxml.%s(self._o)\n" %
673 classes_destructors[classname]);
674 classes.write(" self._o = None\n\n");
675 flist = function_classes[classname]
676 flist.sort(functionCompare)
677 oldfile = ""
678 for info in flist:
Daniel Veillard36ed5292002-01-30 23:49:06 +0000679 (index, func, name, ret, args, file) = info
Daniel Veillard1971ee22002-01-31 20:29:19 +0000680 if file != oldfile:
681 classes.write(" #\n")
682 classes.write(" # %s functions from module %s\n" % (
683 classname, file))
684 classes.write(" #\n\n")
685 oldfile = file
Daniel Veillard36ed5292002-01-30 23:49:06 +0000686 classes.write(" def %s(self" % func)
687 n = 0
688 for arg in args:
689 if n != index:
690 classes.write(", %s" % arg[0])
691 n = n + 1
692 classes.write("):\n")
Daniel Veillard1971ee22002-01-31 20:29:19 +0000693 writeDoc(name, args, ' ', classes);
Daniel Veillard36ed5292002-01-30 23:49:06 +0000694 if ret[0] != "void":
695 classes.write(" ret = ");
696 else:
697 classes.write(" ");
698 classes.write("_libxml.%s(" % name)
699 n = 0
700 for arg in args:
701 if n != 0:
702 classes.write(", ");
703 if n != index:
704 classes.write("%s" % arg[0])
705 else:
706 classes.write("self");
707 if classes_type.has_key(arg[1]):
708 classes.write(classes_type[arg[1]][0])
709 n = n + 1
710 classes.write(")\n");
711 if ret[0] != "void":
712 if classes_type.has_key(ret[0]):
713 classes.write(" if ret == None: return None\n");
714 classes.write(" return ");
715 classes.write(classes_type[ret[0]][1] % ("ret"));
716 classes.write("\n");
Daniel Veillard1971ee22002-01-31 20:29:19 +0000717 elif converter_type.has_key(ret[0]):
718 classes.write(" if ret == None: return None\n");
719 classes.write(" return ");
720 classes.write(converter_type[ret[0]] % ("ret"));
721 classes.write("\n");
Daniel Veillard36ed5292002-01-30 23:49:06 +0000722 else:
723 classes.write(" return ret\n");
724 classes.write("\n");
725
726classes.close()