1#!/usr/bin/python -u 2# 3# generate python wrappers from the XML API description 4# 5 6functions = {} 7enums = {} # { enumType: { enumConstant: enumValue } } 8 9import string 10 11####################################################################### 12# 13# That part if purely the API acquisition phase from the 14# XML API description 15# 16####################################################################### 17import os 18import xml.sax 19 20debug = 0 21srcdir = os.getenv("SRCDIR", ".") 22 23def getparser(): 24 # Attach parser to an unmarshalling object. return both objects. 25 target = docParser() 26 parser = xml.sax.make_parser() 27 parser.setContentHandler(target) 28 return parser, target 29 30class docParser(xml.sax.handler.ContentHandler): 31 def __init__(self): 32 self._methodname = None 33 self._data = [] 34 self.in_function = 0 35 36 self.startElement = self.start 37 self.endElement = self.end 38 self.characters = self.data 39 40 def close(self): 41 if debug: 42 print "close" 43 44 def getmethodname(self): 45 return self._methodname 46 47 def data(self, text): 48 if debug: 49 print "data %s" % text 50 self._data.append(text) 51 52 def start(self, tag, attrs): 53 if debug: 54 print "start %s, %s" % (tag, attrs) 55 if tag == 'function': 56 self._data = [] 57 self.in_function = 1 58 self.function = None 59 self.function_args = [] 60 self.function_descr = None 61 self.function_return = None 62 self.function_file = None 63 if attrs.has_key('name'): 64 self.function = attrs['name'] 65 if attrs.has_key('file'): 66 self.function_file = attrs['file'] 67 elif tag == 'info': 68 self._data = [] 69 elif tag == 'arg': 70 if self.in_function == 1: 71 self.function_arg_name = None 72 self.function_arg_type = None 73 self.function_arg_info = None 74 if attrs.has_key('name'): 75 self.function_arg_name = attrs['name'] 76 if attrs.has_key('type'): 77 self.function_arg_type = attrs['type'] 78 if attrs.has_key('info'): 79 self.function_arg_info = attrs['info'] 80 elif tag == 'return': 81 if self.in_function == 1: 82 self.function_return_type = None 83 self.function_return_info = None 84 self.function_return_field = None 85 if attrs.has_key('type'): 86 self.function_return_type = attrs['type'] 87 if attrs.has_key('info'): 88 self.function_return_info = attrs['info'] 89 if attrs.has_key('field'): 90 self.function_return_field = attrs['field'] 91 elif tag == 'enum': 92 enum(attrs['type'],attrs['name'],attrs['value']) 93 94 95 96 def end(self, tag): 97 if debug: 98 print "end %s" % tag 99 if tag == 'function': 100 if self.function != None: 101 function(self.function, self.function_descr, 102 self.function_return, self.function_args, 103 self.function_file) 104 self.in_function = 0 105 elif tag == 'arg': 106 if self.in_function == 1: 107 self.function_args.append([self.function_arg_name, 108 self.function_arg_type, 109 self.function_arg_info]) 110 elif tag == 'return': 111 if self.in_function == 1: 112 self.function_return = [self.function_return_type, 113 self.function_return_info, 114 self.function_return_field] 115 elif tag == 'info': 116 str = '' 117 for c in self._data: 118 str = str + c 119 if self.in_function == 1: 120 self.function_descr = str 121 122 123def function(name, desc, ret, args, file): 124 functions[name] = (desc, ret, args, file) 125 126def enum(type, name, value): 127 if not enums.has_key(type): 128 enums[type] = {} 129 enums[type][name] = value 130 131####################################################################### 132# 133# Some filtering rukes to drop functions/types which should not 134# be exposed as-is on the Python interface 135# 136####################################################################### 137 138skipped_modules = { 139 'xmlmemory': None, 140 'DOCBparser': None, 141 'SAX': None, 142 'hash': None, 143 'list': None, 144 'threads': None, 145 'xpointer': None, 146 'transform': None, 147} 148skipped_types = { 149 'int *': "usually a return type", 150 'xmlSAXHandlerPtr': "not the proper interface for SAX", 151 'htmlSAXHandlerPtr': "not the proper interface for SAX", 152 'xmlRMutexPtr': "thread specific, skipped", 153 'xmlMutexPtr': "thread specific, skipped", 154 'xmlGlobalStatePtr': "thread specific, skipped", 155 'xmlListPtr': "internal representation not suitable for python", 156 'xmlBufferPtr': "internal representation not suitable for python", 157 'FILE *': None, 158} 159 160####################################################################### 161# 162# Table of remapping to/from the python type or class to the C 163# counterpart. 164# 165####################################################################### 166 167py_types = { 168 'void': (None, None, None, None, None), 169 'int': ('i', None, "int", "int", "libxml_"), 170 'long': ('l', None, "long", "long", "libxml_"), 171 'double': ('d', None, "double", "double", "libxml_"), 172 'unsigned int': ('i', None, "int", "int", "libxml_"), 173 'xmlChar': ('c', None, "int", "int", "libxml_"), 174 'unsigned char *': ('z', None, "charPtr", "char *", "libxml_"), 175 'char *': ('z', None, "charPtr", "char *", "libxml_"), 176 'const char *': ('z', None, "charPtrConst", "const char *", "libxml_"), 177 'xmlChar *': ('z', None, "xmlCharPtr", "xmlChar *", "libxml_"), 178 'const xmlChar *': ('z', None, "xmlCharPtrConst", "const xmlChar *", "libxml_"), 179 'xmlNodePtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr", "libxml_"), 180 'const xmlNodePtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr", "libxml_"), 181 'xmlNode *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr", "libxml_"), 182 'const xmlNode *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr", "libxml_"), 183 'xmlDtdPtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr", "libxml_"), 184 'const xmlDtdPtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr", "libxml_"), 185 'xmlDtd *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr", "libxml_"), 186 'const xmlDtd *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr", "libxml_"), 187 'xmlAttrPtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr", "libxml_"), 188 'const xmlAttrPtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr", "libxml_"), 189 'xmlAttr *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr", "libxml_"), 190 'const xmlAttr *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr", "libxml_"), 191 'xmlEntityPtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr", "libxml_"), 192 'const xmlEntityPtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr", "libxml_"), 193 'xmlEntity *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr", "libxml_"), 194 'const xmlEntity *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr", "libxml_"), 195 'xmlElementPtr': ('O', "xmlElement", "xmlElementPtr", "xmlElementPtr", "libxml_"), 196 'const xmlElementPtr': ('O', "xmlElement", "xmlElementPtr", "xmlElementPtr", "libxml_"), 197 'xmlElement *': ('O', "xmlElement", "xmlElementPtr", "xmlElementPtr", "libxml_"), 198 'const xmlElement *': ('O', "xmlElement", "xmlElementPtr", "xmlElementPtr", "libxml_"), 199 'xmlAttributePtr': ('O', "xmlAttribute", "xmlAttributePtr", "xmlAttributePtr", "libxml_"), 200 'const xmlAttributePtr': ('O', "xmlAttribute", "xmlAttributePtr", "xmlAttributePtr", "libxml_"), 201 'xmlAttribute *': ('O', "xmlAttribute", "xmlAttributePtr", "xmlAttributePtr", "libxml_"), 202 'const xmlAttribute *': ('O', "xmlAttribute", "xmlAttributePtr", "xmlAttributePtr", "libxml_"), 203 'xmlNsPtr': ('O', "xmlNode", "xmlNsPtr", "xmlNsPtr", "libxml_"), 204 'const xmlNsPtr': ('O', "xmlNode", "xmlNsPtr", "xmlNsPtr", "libxml_"), 205 'xmlNs *': ('O', "xmlNode", "xmlNsPtr", "xmlNsPtr", "libxml_"), 206 'const xmlNs *': ('O', "xmlNode", "xmlNsPtr", "xmlNsPtr", "libxml_"), 207 'xmlDocPtr': ('O', "xmlNode", "xmlDocPtr", "xmlDocPtr", "libxml_"), 208 'const xmlDocPtr': ('O', "xmlNode", "xmlDocPtr", "xmlDocPtr", "libxml_"), 209 'xmlDoc *': ('O', "xmlNode", "xmlDocPtr", "xmlDocPtr", "libxml_"), 210 'const xmlDoc *': ('O', "xmlNode", "xmlDocPtr", "xmlDocPtr", "libxml_"), 211 'htmlDocPtr': ('O', "xmlNode", "xmlDocPtr", "xmlDocPtr", "libxml_"), 212 'const htmlDocPtr': ('O', "xmlNode", "xmlDocPtr", "xmlDocPtr", "libxml_"), 213 'htmlDoc *': ('O', "xmlNode", "xmlDocPtr", "xmlDocPtr", "libxml_"), 214 'const htmlDoc *': ('O', "xmlNode", "xmlDocPtr", "xmlDocPtr", "libxml_"), 215 'htmlNodePtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr", "libxml_"), 216 'const htmlNodePtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr", "libxml_"), 217 'htmlNode *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr", "libxml_"), 218 'const htmlNode *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr", "libxml_"), 219 'xmlXPathContextPtr': ('O', "xmlXPathContext", "xmlXPathContextPtr", "xmlXPathContextPtr", "libxml_"), 220 'xmlXPathParserContextPtr': ('O', "xmlXPathParserContext", "xmlXPathParserContextPtr", "xmlXPathParserContextPtr", "libxml_"), 221 'xmlParserCtxtPtr': ('O', "parserCtxt", "xmlParserCtxtPtr", "xmlParserCtxtPtr", "libxml_"), 222 'xmlParserCtxt *': ('O', "parserCtxt", "xmlParserCtxtPtr", "xmlParserCtxtPtr", "libxml_"), 223 'htmlParserCtxtPtr': ('O', "parserCtxt", "xmlParserCtxtPtr", "xmlParserCtxtPtr", "libxml_"), 224 'htmlParserCtxt *': ('O', "parserCtxt", "xmlParserCtxtPtr", "xmlParserCtxtPtr", "libxml_"), 225 'xmlCatalogPtr': ('O', "catalog", "xmlCatalogPtr", "xmlCatalogPtr"), 226 'FILE *': ('O', "File", "FILEPtr", "FILE *", "libxml_"), 227 'xsltTransformContextPtr': ('O', "transformCtxt", "xsltTransformContextPtr", "xsltTransformContextPtr", "libxslt_"), 228 'xsltTransformContext *': ('O', "transformCtxt", "xsltTransformContextPtr", "xsltTransformContextPtr", "libxslt_"), 229 'xsltStylePreCompPtr': ('O', "compiledStyle", "xsltStylePreCompPtr", "xsltStylePreCompPtr", "libxslt_"), 230 'xsltStylePreComp *': ('O', "compiledStyle", "xsltStylePreCompPtr", "xsltStylePreCompPtr", "libxslt_"), 231 'xsltStylesheetPtr': ('O', "stylesheet", "xsltStylesheetPtr", "xsltStylesheetPtr", "libxslt_"), 232 'xsltStylesheet *': ('O', "stylesheet", "xsltStylesheetPtr", "xsltStylesheetPtr", "libxslt_"), 233 'xmlXPathContext *': ('O', "xpathContext", "xmlXPathContextPtr", "xmlXPathContextPtr", "libxslt_"), 234} 235 236py_return_types = { 237 'xmlXPathObjectPtr': ('O', "foo", "xmlXPathObjectPtr", "xmlXPathObjectPtr", "libxml_"), 238} 239 240unknown_types = {} 241 242####################################################################### 243# 244# This part writes the C <-> Python stubs libxslt-py.[ch] and 245# the table libxslt-export.c to add when registrering the Python module 246# 247####################################################################### 248 249def skip_function(name): 250 if name[0:12] == "xmlXPathWrap": 251 return 1 252 if name == "xsltMatchPattern": 253 return 1 254# if name[0:11] == "xmlXPathNew": 255# return 1 256 return 0 257 258def print_function_wrapper(name, output, export, include): 259 global py_types 260 global unknown_types 261 global functions 262 global skipped_modules 263 264 try: 265 (desc, ret, args, file) = functions[name] 266 except: 267 print "failed to get function %s infos" 268 return 269 270 if skipped_modules.has_key(file): 271 return 0 272 if skip_function(name) == 1: 273 return 0 274 275 c_call = "" 276 format="" 277 format_args="" 278 c_args="" 279 c_return="" 280 c_convert="" 281 for arg in args: 282 # This should be correct 283 if arg[1][0:6] == "const ": 284 arg[1] = arg[1][6:] 285 c_args = c_args + " %s %s;\n" % (arg[1], arg[0]) 286 if py_types.has_key(arg[1]): 287 (f, t, n, c, p) = py_types[arg[1]] 288 if f != None: 289 format = format + f 290 if t != None: 291 format_args = format_args + ", &pyobj_%s" % (arg[0]) 292 c_args = c_args + " PyObject *pyobj_%s;\n" % (arg[0]) 293 c_convert = c_convert + \ 294 " %s = (%s) Py%s_Get(pyobj_%s);\n" % (arg[0], 295 arg[1], t, arg[0]) 296 else: 297 format_args = format_args + ", &%s" % (arg[0]) 298 if c_call != "": 299 c_call = c_call + ", " 300 c_call = c_call + "%s" % (arg[0]) 301 else: 302 if skipped_types.has_key(arg[1]): 303 return 0 304 if unknown_types.has_key(arg[1]): 305 lst = unknown_types[arg[1]] 306 lst.append(name) 307 else: 308 unknown_types[arg[1]] = [name] 309 return -1 310 if format != "": 311 format = format + ":%s" % (name) 312 313 if ret[0] == 'void': 314 if file == "python_accessor": 315 if args[1][1] == "char *" or args[1][1] == "xmlChar *": 316 c_call = "\n if (%s->%s != NULL) xmlFree(%s->%s);\n" % ( 317 args[0][0], args[1][0], args[0][0], args[1][0]) 318 c_call = c_call + " %s->%s = xmlStrdup((const xmlChar *)%s);\n" % (args[0][0], 319 args[1][0], args[1][0]) 320 else: 321 c_call = "\n %s->%s = %s;\n" % (args[0][0], args[1][0], 322 args[1][0]) 323 else: 324 c_call = "\n %s(%s);\n" % (name, c_call) 325 ret_convert = " Py_INCREF(Py_None);\n return(Py_None);\n" 326 elif py_types.has_key(ret[0]): 327 (f, t, n, c, p) = py_types[ret[0]] 328 c_return = " %s c_retval;\n" % (ret[0]) 329 if file == "python_accessor" and ret[2] != None: 330 c_call = "\n c_retval = %s->%s;\n" % (args[0][0], ret[2]) 331 else: 332 c_call = "\n c_retval = %s(%s);\n" % (name, c_call) 333 ret_convert = " py_retval = %s%sWrap((%s) c_retval);\n" % (p,n,c) 334 ret_convert = ret_convert + " return(py_retval);\n" 335 elif py_return_types.has_key(ret[0]): 336 (f, t, n, c, p) = py_return_types[ret[0]] 337 c_return = " %s c_retval;\n" % (ret[0]) 338 if file == "python_accessor" and ret[2] != None: 339 c_call = "\n c_retval = %s->%s;\n" % (args[0][0], ret[2]) 340 else: 341 c_call = "\n c_retval = %s(%s);\n" % (name, c_call) 342 ret_convert = " py_retval = %s%sWrap((%s) c_retval);\n" % (p,n,c) 343 ret_convert = ret_convert + " return(py_retval);\n" 344 else: 345 if skipped_types.has_key(ret[0]): 346 return 0 347 if unknown_types.has_key(ret[0]): 348 lst = unknown_types[ret[0]] 349 lst.append(name) 350 else: 351 unknown_types[ret[0]] = [name] 352 return -1 353 354 include.write("PyObject * ") 355 include.write("libxslt_%s(PyObject *self, PyObject *args);\n" % (name)) 356 357 export.write(" { (char *)\"%s\", libxslt_%s, METH_VARARGS, NULL },\n" % (name, name)) 358 359 if file == "python": 360 # Those have been manually generated 361 return 1 362 if file == "python_accessor" and ret[0] != "void" and ret[2] == None: 363 # Those have been manually generated 364 return 1 365 366 output.write("PyObject *\n") 367 output.write("libxslt_%s(PyObject *self ATTRIBUTE_UNUSED," % (name)) 368 output.write(" PyObject *args") 369 if format == "": 370 output.write(" ATTRIBUTE_UNUSED") 371 output.write(") {\n") 372 if ret[0] != 'void': 373 output.write(" PyObject *py_retval;\n") 374 if c_return != "": 375 output.write(c_return) 376 if c_args != "": 377 output.write(c_args) 378 if format != "": 379 output.write("\n if (!PyArg_ParseTuple(args, (char *)\"%s\"%s))\n" % 380 (format, format_args)) 381 output.write(" return(NULL);\n") 382 if c_convert != "": 383 output.write(c_convert) 384 385 output.write(c_call) 386 output.write(ret_convert) 387 output.write("}\n\n") 388 return 1 389 390def buildStubs(): 391 global py_types 392 global py_return_types 393 global unknown_types 394 395 try: 396 f = open("%s/libxslt-api.xml" % srcdir) 397 data = f.read() 398 (parser, target) = getparser() 399 parser.feed(data) 400 parser.close() 401 except IOError, msg: 402 try: 403 f = open("%s/../doc/libxslt-api.xml" % srcdir) 404 data = f.read() 405 (parser, target) = getparser() 406 parser.feed(data) 407 parser.close() 408 except IOError, msg: 409 print "../doc/libxslt-api.xml", ":", msg 410 411 n = len(functions.keys()) 412 print "Found %d functions in libxslt-api.xml" % (n) 413 414 py_types['pythonObject'] = ('O', "pythonObject", "pythonObject", 415 "pythonObject", "libxml_") 416 try: 417 f = open("%s/libxslt-python-api.xml" % srcdir) 418 data = f.read() 419 (parser, target) = getparser() 420 parser.feed(data) 421 parser.close() 422 except IOError, msg: 423 print "libxslt-python-api.xml", ":", msg 424 425 426 print "Found %d functions in libxslt-python-api.xml" % ( 427 len(functions.keys()) - n) 428 nb_wrap = 0 429 failed = 0 430 skipped = 0 431 432 include = open("libxslt-py.h", "w") 433 include.write("/* Generated */\n\n") 434 export = open("libxslt-export.c", "w") 435 export.write("/* Generated */\n\n") 436 wrapper = open("libxslt-py.c", "w") 437 wrapper.write("/* Generated */\n\n") 438# wrapper.write("#include \"config.h\"\n") 439 wrapper.write("#include <libxslt/xsltconfig.h>\n") 440 wrapper.write("#include \"libxslt_wrap.h\"\n") 441 wrapper.write("#include \"libxslt-py.h\"\n\n") 442 for function in functions.keys(): 443 ret = print_function_wrapper(function, wrapper, export, include) 444 if ret < 0: 445 failed = failed + 1 446 del functions[function] 447 if ret == 0: 448 skipped = skipped + 1 449 del functions[function] 450 if ret == 1: 451 nb_wrap = nb_wrap + 1 452 include.close() 453 export.close() 454 wrapper.close() 455 456 print "Generated %d wrapper functions, %d failed, %d skipped\n" % (nb_wrap, 457 failed, skipped) 458 print "Missing type converters:" 459 for type in unknown_types.keys(): 460 print "%s:%d " % (type, len(unknown_types[type])), 461 print 462 463####################################################################### 464# 465# This part writes part of the Python front-end classes based on 466# mapping rules between types and classes and also based on function 467# renaming to get consistent function names at the Python level 468# 469####################################################################### 470 471# 472# The type automatically remapped to generated classes 473# 474libxml2_classes_type = { 475 "xmlNodePtr": ("._o", "xmlNode(_obj=%s)", "xmlNode"), 476 "xmlNode *": ("._o", "xmlNode(_obj=%s)", "xmlNode"), 477 "xmlDocPtr": ("._o", "xmlDoc(_obj=%s)", "xmlDoc"), 478 "xmlDocPtr *": ("._o", "xmlDoc(_obj=%s)", "xmlDoc"), 479 "htmlDocPtr": ("._o", "xmlDoc(_obj=%s)", "xmlDoc"), 480 "htmlxmlDocPtr *": ("._o", "xmlDoc(_obj=%s)", "xmlDoc"), 481 "xmlAttrPtr": ("._o", "xmlAttr(_obj=%s)", "xmlAttr"), 482 "xmlAttr *": ("._o", "xmlAttr(_obj=%s)", "xmlAttr"), 483 "xmlNsPtr": ("._o", "xmlNs(_obj=%s)", "xmlNs"), 484 "xmlNs *": ("._o", "xmlNs(_obj=%s)", "xmlNs"), 485 "xmlDtdPtr": ("._o", "xmlDtd(_obj=%s)", "xmlDtd"), 486 "xmlDtd *": ("._o", "xmlDtd(_obj=%s)", "xmlDtd"), 487 "xmlEntityPtr": ("._o", "xmlEntity(_obj=%s)", "xmlEntity"), 488 "xmlEntity *": ("._o", "xmlEntity(_obj=%s)", "xmlEntity"), 489 "xmlElementPtr": ("._o", "xmlElement(_obj=%s)", "xmlElement"), 490 "xmlElement *": ("._o", "xmlElement(_obj=%s)", "xmlElement"), 491 "xmlAttributePtr": ("._o", "xmlAttribute(_obj=%s)", "xmlAttribute"), 492 "xmlAttribute *": ("._o", "xmlAttribute(_obj=%s)", "xmlAttribute"), 493 "xmlParserCtxtPtr": ("._o", "parserCtxt(_obj=%s)", "parserCtxt"), 494 "xmlParserCtxt *": ("._o", "parserCtxt(_obj=%s)", "parserCtxt"), 495 "xmlCatalogPtr": ("._o", "catalog(_obj=%s)", "catalog"), 496} 497 498classes_type = { 499 "xsltTransformContextPtr": ("._o", "transformCtxt(_obj=%s)", "transformCtxt"), 500 "xsltTransformContext *": ("._o", "transformCtxt(_obj=%s)", "transformCtxt"), 501 "xsltStylesheetPtr": ("._o", "stylesheet(_obj=%s)", "stylesheet"), 502 "xsltStylesheet *": ("._o", "stylesheet(_obj=%s)", "stylesheet"), 503 "xmlXPathContextPtr": ("._o", "xpathContext(_obj=%s)", "xpathContext"), 504 "xmlXPathContext *": ("._o", "xpathContext(_obj=%s)", "xpathContext"), 505 "xmlXPathParserContextPtr": ("._o", "xpathParserContext(_obj=%s)", "xpathParserContext"), 506 "xmlXPathParserContext *": ("._o", "xpathParserContext(_obj=%s)", "xpathParserContext"), 507} 508 509converter_type = { 510 "xmlXPathObjectPtr": "libxml2.xpathObjectRet(%s)", 511} 512 513primary_classes = ["xpathParserContext", "xpathContext", "transformCtxt", "stylesheet"] 514 515classes_ancestor = { 516 "xpathContext" : "libxml2.xpathContext", 517 "xpathParserContext" : "libxml2.xpathParserContext", 518 "transformCtxt": "transformCtxtBase", 519 "stylesheet": "stylesheetBase", 520} 521classes_destructors = { 522 "xpathContext" : "pass" 523} 524 525function_classes = {} 526ctypes = [] 527classes_list = [] 528 529 530def nameFixup(name, classe, type, file): 531 listname = classe + "List" 532 ll = len(listname) 533 l = len(classe) 534 if name[0:l] == listname: 535 func = name[l:] 536 func = string.lower(func[0:1]) + func[1:] 537 elif name[0:12] == "xmlParserGet" and file == "python_accessor": 538 func = name[12:] 539 func = string.lower(func[0:1]) + func[1:] 540 elif name[0:12] == "xmlParserSet" and file == "python_accessor": 541 func = name[12:] 542 func = string.lower(func[0:1]) + func[1:] 543 elif name[0:10] == "xmlNodeGet" and file == "python_accessor": 544 func = name[10:] 545 func = string.lower(func[0:1]) + func[1:] 546 elif name[0:18] == "xsltXPathParserGet" and file == "python_accessor": 547 func = name[18:] 548 func = string.lower(func[0:1]) + func[1:] 549 elif name[0:12] == "xsltXPathGet" and file == "python_accessor": 550 func = name[12:] 551 func = string.lower(func[0:1]) + func[1:] 552 elif name[0:16] == "xsltTransformGet" and file == "python_accessor": 553 func = name[16:] 554 func = string.lower(func[0:1]) + func[1:] 555 elif name[0:16] == "xsltTransformSet" and file == "python_accessor": 556 func = name[13:] 557 func = string.lower(func[0:1]) + func[1:] 558 elif name[0:17] == "xsltStylesheetGet" and file == "python_accessor": 559 func = name[17:] 560 func = string.lower(func[0:1]) + func[1:] 561 elif name[0:17] == "xsltStylesheetSet" and file == "python_accessor": 562 func = name[14:] 563 func = string.lower(func[0:1]) + func[1:] 564 elif name[0:l] == classe: 565 func = name[l:] 566 func = string.lower(func[0:1]) + func[1:] 567 elif name[0:7] == "libxml_": 568 func = name[7:] 569 func = string.lower(func[0:1]) + func[1:] 570 elif name[0:8] == "libxslt_": 571 func = name[8:] 572 func = string.lower(func[0:1]) + func[1:] 573 elif name[0:6] == "xmlGet": 574 func = name[6:] 575 func = string.lower(func[0:1]) + func[1:] 576 elif name[0:3] == "xml": 577 func = name[3:] 578 func = string.lower(func[0:1]) + func[1:] 579 elif name[0:7] == "xsltGet": 580 func = name[7:] 581 func = string.lower(func[0:1]) + func[1:] 582 elif name[0:4] == "xslt": 583 func = name[4:] 584 func = string.lower(func[0:1]) + func[1:] 585 else: 586 func = name 587 if func[0:5] == "xPath": 588 func = "xpath" + func[5:] 589 elif func[0:4] == "xPtr": 590 func = "xpointer" + func[4:] 591 elif func[0:8] == "xInclude": 592 func = "xinclude" + func[8:] 593 elif func[0:2] == "iD": 594 func = "ID" + func[2:] 595 elif func[0:3] == "uRI": 596 func = "URI" + func[3:] 597 elif func[0:4] == "uTF8": 598 func = "UTF8" + func[4:] 599 return func 600 601def functionCompare(info1, info2): 602 (index1, func1, name1, ret1, args1, file1) = info1 603 (index2, func2, name2, ret2, args2, file2) = info2 604 if file1 == file2: 605 if func1 < func2: 606 return -1 607 if func1 > func2: 608 return 1 609 if file1 == "python_accessor": 610 return -1 611 if file2 == "python_accessor": 612 return 1 613 if file1 < file2: 614 return -1 615 if file1 > file2: 616 return 1 617 return 0 618 619def writeDoc(name, args, indent, output): 620 if functions[name][0] == None or functions[name][0] == "": 621 return 622 val = functions[name][0] 623 val = string.replace(val, "NULL", "None") 624 output.write(indent) 625 output.write('"""') 626 while len(val) > 60: 627 if val[0] == " ": 628 val = val[1:] 629 continue 630 str = val[0:60] 631 i = string.rfind(str, " ") 632 if i < 0: 633 i = 60 634 str = val[0:i] 635 val = val[i:] 636 output.write(str) 637 output.write('\n ') 638 output.write(indent) 639 output.write(val) 640 output.write('"""\n') 641 642def buildWrappers(): 643 global ctypes 644 global py_types 645 global py_return_types 646 global unknown_types 647 global functions 648 global function_classes 649 global libxml2_classes_type 650 global classes_type 651 global classes_list 652 global converter_type 653 global primary_classes 654 global converter_type 655 global classes_ancestor 656 global converter_type 657 global primary_classes 658 global classes_ancestor 659 global classes_destructors 660 661 function_classes["None"] = [] 662 for type in classes_type.keys(): 663 function_classes[classes_type[type][2]] = [] 664 665 # 666 # Build the list of C types to look for ordered to start with 667 # primary classes 668 # 669 ctypes_processed = {} 670 classes_processed = {} 671 for classe in primary_classes: 672 classes_list.append(classe) 673 classes_processed[classe] = () 674 for type in classes_type.keys(): 675 tinfo = classes_type[type] 676 if tinfo[2] == classe: 677 ctypes.append(type) 678 ctypes_processed[type] = () 679 for type in classes_type.keys(): 680 if ctypes_processed.has_key(type): 681 continue 682 tinfo = classes_type[type] 683 if not classes_processed.has_key(tinfo[2]): 684 classes_list.append(tinfo[2]) 685 classes_processed[tinfo[2]] = () 686 687 ctypes.append(type) 688 ctypes_processed[type] = () 689 690 for name in functions.keys(): 691 found = 0 692 (desc, ret, args, file) = functions[name] 693 for type in ctypes: 694 classe = classes_type[type][2] 695 696 if name[0:4] == "xslt" and len(args) >= 1 and args[0][1] == type: 697 found = 1 698 func = nameFixup(name, classe, type, file) 699 info = (0, func, name, ret, args, file) 700 function_classes[classe].append(info) 701 elif name[0:4] == "xslt" and len(args) >= 2 and args[1][1] == type: 702 found = 1 703 func = nameFixup(name, classe, type, file) 704 info = (1, func, name, ret, args, file) 705 function_classes[classe].append(info) 706 elif name[0:4] == "xslt" and len(args) >= 3 and args[2][1] == type: 707 found = 1 708 func = nameFixup(name, classe, type, file) 709 info = (2, func, name, ret, args, file) 710 function_classes[classe].append(info) 711 if found == 1: 712 continue 713 if name[0:8] == "xmlXPath": 714 continue 715 if name[0:6] == "xmlStr": 716 continue 717 if name[0:10] == "xmlCharStr": 718 continue 719 func = nameFixup(name, "None", file, file) 720 info = (0, func, name, ret, args, file) 721 function_classes['None'].append(info) 722 723 classes = open("libxsltclass.py", "w") 724 txt = open("libxsltclass.txt", "w") 725 txt.write(" Generated Classes for libxslt-python\n\n") 726 727 txt.write("#\n# Global functions of the module\n#\n\n") 728 if function_classes.has_key("None"): 729 flist = function_classes["None"] 730 flist.sort(functionCompare) 731 oldfile = "" 732 for info in flist: 733 (index, func, name, ret, args, file) = info 734 if file != oldfile: 735 classes.write("#\n# Functions from module %s\n#\n\n" % file) 736 txt.write("\n# functions from module %s\n" % file) 737 oldfile = file 738 classes.write("def %s(" % func) 739 txt.write("%s()\n" % func) 740 n = 0 741 for arg in args: 742 if n != 0: 743 classes.write(", ") 744 classes.write("%s" % arg[0]) 745 n = n + 1 746 classes.write("):\n") 747 writeDoc(name, args, ' ', classes) 748 749 for arg in args: 750 if classes_type.has_key(arg[1]): 751 classes.write(" if %s == None: %s__o = None\n" % 752 (arg[0], arg[0])) 753 classes.write(" else: %s__o = %s%s\n" % 754 (arg[0], arg[0], classes_type[arg[1]][0])) 755 elif libxml2_classes_type.has_key(arg[1]): 756 classes.write(" if %s == None: %s__o = None\n" % 757 (arg[0], arg[0])) 758 classes.write(" else: %s__o = %s%s\n" % 759 (arg[0], arg[0], libxml2_classes_type[arg[1]][0])) 760 if ret[0] != "void": 761 classes.write(" ret = ") 762 else: 763 classes.write(" ") 764 classes.write("libxsltmod.%s(" % name) 765 n = 0 766 for arg in args: 767 if n != 0: 768 classes.write(", ") 769 classes.write("%s" % arg[0]) 770 if classes_type.has_key(arg[1]): 771 classes.write("__o") 772 if libxml2_classes_type.has_key(arg[1]): 773 classes.write("__o") 774 n = n + 1 775 classes.write(")\n") 776 if ret[0] != "void": 777 if classes_type.has_key(ret[0]): 778 classes.write(" if ret == None: return None\n") 779 classes.write(" return ") 780 classes.write(classes_type[ret[0]][1] % ("ret")) 781 classes.write("\n") 782 elif libxml2_classes_type.has_key(ret[0]): 783 classes.write(" if ret == None: return None\n") 784 classes.write(" return libxml2.") 785 classes.write(libxml2_classes_type[ret[0]][1] % ("ret")) 786 classes.write("\n") 787 else: 788 classes.write(" return ret\n") 789 classes.write("\n") 790 791 txt.write("\n\n#\n# Set of classes of the module\n#\n\n") 792 for classname in classes_list: 793 if classname == "None": 794 pass 795 else: 796 if classes_ancestor.has_key(classname): 797 txt.write("\n\nClass %s(%s)\n" % (classname, 798 classes_ancestor[classname])) 799 classes.write("class %s(%s):\n" % (classname, 800 classes_ancestor[classname])) 801 classes.write(" def __init__(self, _obj=None):\n") 802 classes.write(" self._o = None\n") 803 classes.write(" %s.__init__(self, _obj=_obj)\n\n" % ( 804 classes_ancestor[classname])) 805 if classes_ancestor[classname] == "xmlCore" or \ 806 classes_ancestor[classname] == "xmlNode": 807 classes.write(" def __repr__(self):\n") 808 format = "%s:%%s" % (classname) 809 classes.write(" return \"%s\" %% (self.name)\n\n" % ( 810 format)) 811 else: 812 txt.write("Class %s()\n" % (classname)) 813 classes.write("class %s:\n" % (classname)) 814 classes.write(" def __init__(self, _obj=None):\n") 815 classes.write(" if _obj != None:self._o = _obj;return\n") 816 classes.write(" self._o = None\n\n") 817 if classes_destructors.has_key(classname): 818 classes.write(" def __del__(self):\n") 819 if classes_destructors[classname] == "pass": 820 classes.write(" pass\n") 821 else: 822 classes.write(" if self._o != None:\n") 823 classes.write(" libxsltmod.%s(self._o)\n" % 824 classes_destructors[classname]) 825 classes.write(" self._o = None\n\n") 826 flist = function_classes[classname] 827 flist.sort(functionCompare) 828 oldfile = "" 829 for info in flist: 830 (index, func, name, ret, args, file) = info 831 if file != oldfile: 832 if file == "python_accessor": 833 classes.write(" # accessors for %s\n" % (classname)) 834 txt.write(" # accessors\n") 835 else: 836 classes.write(" #\n") 837 classes.write(" # %s functions from module %s\n" % ( 838 classname, file)) 839 txt.write("\n # functions from module %s\n" % file) 840 classes.write(" #\n\n") 841 oldfile = file 842 classes.write(" def %s(self" % func) 843 txt.write(" %s()\n" % func) 844 n = 0 845 for arg in args: 846 if n != index: 847 classes.write(", %s" % arg[0]) 848 n = n + 1 849 classes.write("):\n") 850 writeDoc(name, args, ' ', classes) 851 n = 0 852 for arg in args: 853 if classes_type.has_key(arg[1]): 854 if n != index: 855 classes.write(" if %s == None: %s__o = None\n" % 856 (arg[0], arg[0])) 857 classes.write(" else: %s__o = %s%s\n" % 858 (arg[0], arg[0], classes_type[arg[1]][0])) 859 elif libxml2_classes_type.has_key(arg[1]): 860 classes.write(" if %s == None: %s__o = None\n" % 861 (arg[0], arg[0])) 862 classes.write(" else: %s__o = %s%s\n" % 863 (arg[0], arg[0], 864 libxml2_classes_type[arg[1]][0])) 865 n = n + 1 866 if ret[0] != "void": 867 classes.write(" ret = ") 868 else: 869 classes.write(" ") 870 classes.write("libxsltmod.%s(" % name) 871 n = 0 872 for arg in args: 873 if n != 0: 874 classes.write(", ") 875 if n != index: 876 classes.write("%s" % arg[0]) 877 if classes_type.has_key(arg[1]): 878 classes.write("__o") 879 elif libxml2_classes_type.has_key(arg[1]): 880 classes.write("__o") 881 else: 882 classes.write("self") 883 if classes_type.has_key(arg[1]): 884 classes.write(classes_type[arg[1]][0]) 885 elif libxml2_classes_type.has_key(arg[1]): 886 classes.write(libxml2_classes_type[arg[1]][0]) 887 n = n + 1 888 classes.write(")\n") 889 if ret[0] != "void": 890 if classes_type.has_key(ret[0]): 891 classes.write(" if ret == None: return None\n") 892 classes.write(" return ") 893 classes.write(classes_type[ret[0]][1] % ("ret")) 894 classes.write("\n") 895 elif libxml2_classes_type.has_key(ret[0]): 896 classes.write(" if ret == None: return None\n") 897 classes.write(" return libxml2.") 898 classes.write(libxml2_classes_type[ret[0]][1] % ("ret")) 899 classes.write("\n") 900 elif converter_type.has_key(ret[0]): 901 classes.write(" if ret == None: return None\n") 902 classes.write(" return ") 903 classes.write(converter_type[ret[0]] % ("ret")) 904 classes.write("\n") 905 else: 906 classes.write(" return ret\n") 907 classes.write("\n") 908 909 # 910 # Generate enum constants 911 # 912 for type,enum in enums.items(): 913 classes.write("# %s\n" % type) 914 items = enum.items() 915 items.sort(lambda i1,i2: cmp(long(i1[1]),long(i2[1]))) 916 for name,value in items: 917 classes.write("%s = %s\n" % (name,value)) 918 classes.write("\n"); 919 920 txt.close() 921 classes.close() 922 923buildStubs() 924buildWrappers() 925