commited early version of a python binding for private use only ATM Daniel

* python/generator.py python/libxml.c python/libxml.py
  python/libxml_wrap.h: commited early version of a python binding
  for private use only ATM
Daniel
diff --git a/python/generator.py b/python/generator.py
new file mode 100755
index 0000000..2942854
--- /dev/null
+++ b/python/generator.py
@@ -0,0 +1,284 @@
+#!/usr/bin/python -u
+#
+# generate python wrappers from the XML API description
+#
+
+functions = {}
+
+import os
+import xmllib
+try:
+    import sgmlop
+except ImportError:
+    sgmlop = None # accelerator not available
+
+debug = 0
+
+if sgmlop:
+    class FastParser:
+	"""sgmlop based XML parser.  this is typically 15x faster
+	   than SlowParser..."""
+
+	def __init__(self, target):
+
+	    # setup callbacks
+	    self.finish_starttag = target.start
+	    self.finish_endtag = target.end
+	    self.handle_data = target.data
+
+	    # activate parser
+	    self.parser = sgmlop.XMLParser()
+	    self.parser.register(self)
+	    self.feed = self.parser.feed
+	    self.entity = {
+		"amp": "&", "gt": ">", "lt": "<",
+		"apos": "'", "quot": '"'
+		}
+
+	def close(self):
+	    try:
+		self.parser.close()
+	    finally:
+		self.parser = self.feed = None # nuke circular reference
+
+	def handle_entityref(self, entity):
+	    # <string> entity
+	    try:
+		self.handle_data(self.entity[entity])
+	    except KeyError:
+		self.handle_data("&%s;" % entity)
+
+else:
+    FastParser = None
+
+
+class SlowParser(xmllib.XMLParser):
+    """slow but safe standard parser, based on the XML parser in
+       Python's standard library."""
+
+    def __init__(self, target):
+	self.unknown_starttag = target.start
+	self.handle_data = target.data
+	self.unknown_endtag = target.end
+	xmllib.XMLParser.__init__(self)
+
+def getparser(target = None):
+    # get the fastest available parser, and attach it to an
+    # unmarshalling object.  return both objects.
+    if target == None:
+	target = docParser()
+    if FastParser:
+	return FastParser(target), target
+    return SlowParser(target), target
+
+class docParser:
+    def __init__(self):
+        self._methodname = None
+	self._data = []
+	self.in_function = 0
+
+    def close(self):
+        if debug:
+	    print "close"
+
+    def getmethodname(self):
+        return self._methodname
+
+    def data(self, text):
+        if debug:
+	    print "data %s" % text
+        self._data.append(text)
+
+    def start(self, tag, attrs):
+        if debug:
+	    print "start %s, %s" % (tag, attrs)
+	if tag == 'function':
+	    self._data = []
+	    self.in_function = 1
+	    self.function = None
+	    self.function_args = []
+	    self.function_descr = None
+	    self.function_return = None
+	    self.function_file = None
+	    if attrs.has_key('name'):
+	        self.function = attrs['name']
+	    if attrs.has_key('file'):
+	        self.function_file = attrs['file']
+	elif tag == 'info':
+	    self._data = []
+	elif tag == 'arg':
+	    if self.in_function == 1:
+	        self.function_arg_name = None
+	        self.function_arg_type = None
+	        self.function_arg_info = None
+		if attrs.has_key('name'):
+		    self.function_arg_name = attrs['name']
+		if attrs.has_key('type'):
+		    self.function_arg_type = attrs['type']
+		if attrs.has_key('info'):
+		    self.function_arg_info = attrs['info']
+	elif tag == 'return':
+	    if self.in_function == 1:
+	        self.function_return_type = None
+	        self.function_return_info = None
+		if attrs.has_key('type'):
+		    self.function_return_type = attrs['type']
+		if attrs.has_key('info'):
+		    self.function_return_info = attrs['info']
+
+
+    def end(self, tag):
+        if debug:
+	    print "end %s" % tag
+	if tag == 'function':
+	    if self.function != None:
+	        function(self.function, self.function_descr,
+		         self.function_return, self.function_args,
+			 self.function_file)
+		self.in_function = 0
+	elif tag == 'arg':
+	    if self.in_function == 1:
+	        self.function_args.append([self.function_arg_name,
+		                           self.function_arg_type,
+					   self.function_arg_info])
+	elif tag == 'return':
+	    if self.in_function == 1:
+	        self.function_return = [self.function_return_type,
+		                        self.function_return_info]
+	elif tag == 'info':
+	    str = ''
+	    for c in self._data:
+		str = str + c
+	    if self.in_function == 1:
+	        self.function_descr = str
+	        
+	        
+def function(name, desc, ret, args, file):
+    global functions
+
+    functions[name] = (desc, ret, args, file)
+
+skipped_modules = {
+    'xmlmemory': None,
+}
+py_types = {
+    'void': (None, None, None),
+    'int':  ('i', None, "int"),
+    'xmlChar':  ('c', None, "int"),
+    'char *':  ('s', None, "charPtr"),
+    'const char *':  ('s', None, "charPtr"),
+    'xmlChar *':  ('s', None, "xmlCharPtr"),
+    'const xmlChar *':  ('s', None, "xmlCharPtr"),
+}
+
+unknown_types = {}
+
+def print_function_wrapper(name, output):
+    global py_types
+    global unknown_types
+    global functions
+    global skipped_modules
+
+    try:
+	(desc, ret, args, file) = functions[name]
+    except:
+        print "failed to get function %s infos"
+        return
+
+    if skipped_modules.has_key(file):
+        return 0
+
+    c_call = "";
+    format=""
+    format_args=""
+    c_args=""
+    c_return=""
+    for arg in args:
+        c_args = c_args + "    %s %s;\n" % (arg[1], arg[0])
+	if py_types.has_key(arg[1]):
+	    (f, t, n) = py_types[arg[1]]
+	    if f != None:
+		format = format + f
+	    if t != None:
+	        format_args = format_args + ", &%s" % (t)
+	    format_args = format_args + ", &%s" % (arg[0])
+	    if c_call != "":
+	        c_call = c_call + ", ";
+	    c_call = c_call + "%s" % (arg[0])
+	else:
+	    if unknown_types.has_key(arg[1]):
+	        lst = unknown_types[arg[1]]
+		lst.append(name)
+	    else:
+	        unknown_types[arg[1]] = [name]
+	    return -1
+    if format != "":
+        format = format + ":%s" % (name)
+
+    if ret[0] == 'void':
+        c_call = "\n    %s(%s);\n" % (name, c_call);
+	ret_convert = "    Py_INCREF(Py_None);\n    return(Py_None);\n"
+    elif py_types.has_key(ret[0]):
+	(f, t, n) = py_types[ret[0]]
+	c_return = "    %s c_retval;\n" % (ret[0])
+        c_call = "\n    c_retval = %s(%s);\n" % (name, c_call);
+	ret_convert = "    py_retval = libxml_%sWrap(c_retval);\n    return(py_retval);\n" % (n)
+    else:
+	if unknown_types.has_key(ret[0]):
+	    lst = unknown_types[ret[0]]
+	    lst.append(name)
+	else:
+	    unknown_types[ret[0]] = [name]
+	return -1
+
+    output.write("PyObject *\n")
+    output.write("libxml_%s(PyObject *self, PyObject *args) {\n" % (name))
+    if ret[0] != 'void':
+	output.write("    PyObject *py_retval;\n")
+    if c_return != "":
+	output.write(c_return)
+    if c_args != "":
+	output.write(c_args)
+    if format != "":
+	output.write("\n    if (!PyArg_ParseTuple(args, \"%s\"%s))\n" %
+	             (format, format_args))
+	output.write("        return(NULL);\n")
+                                                              
+    output.write(c_call)
+    output.write(ret_convert)
+    output.write("}\n\n")
+    return 1
+
+try:
+    f = open("libxml2-api.xml")
+    data = f.read()
+    (parser, target)  = getparser()
+    parser.feed(data)
+    parser.close()
+except IOError, msg:
+    print file, ":", msg
+
+print "Found %d functions in libxml2-api.xml" % (len(functions.keys()))
+nb_wrap = 0
+failed = 0
+skipped = 0
+
+wrapper = open("libxml2-py.c", "w")
+wrapper.write("/* Generated */\n\n")
+wrapper.write("#include <Python.h>\n")
+wrapper.write("#include <libxml/tree.h>\n")
+wrapper.write("#include \"libxml_wrap.h\"\n")
+wrapper.write("#include \"libxml2-py.h\"\n\n")
+for function in functions.keys():
+    ret = print_function_wrapper(function, wrapper)
+    if ret < 0:
+        failed = failed + 1
+    if ret == 1:
+        nb_wrap = nb_wrap + 1
+    if ret == 0:
+        skipped = skipped + 1
+wrapper.close()
+
+print "Generated %d wrapper functions, %d failed, %d skipped\n" % (nb_wrap,
+							  failed, skipped);
+print "Missing type converters: %s" % (unknown_types.keys())