1#!/usr/bin/env python 2 3""" 4Parse a .gir file for any of the gtk+ libraries (gtk+, glib,...) 5and generate Ada bindings. 6""" 7 8# Issues: 9# - Missing handling of <field> nodes (see GtkArrow for instance) 10# - Some comments contain xref like "#GtkMisc". Not sure what to do with 11# those. Likewise for names of subprograms in comments. 12# 13# Backward incompatibility: 14# - Missing documentation for some properties. 15# SOLVE: we could point to the corresponding Set_* and Get_* subprograms, 16# or simply ignore the missing doc 17 18from xml.etree.cElementTree import parse, Element, QName, tostring, fromstring 19from adaformat import * 20import copy 21from binding_gtkada import GtkAda 22from data import enums, interfaces, binding, user_data_params 23from data import destroy_data_params 24 25# Unfortunately, generating the slot marshallers in a separate package 26# does not work since we end up with circularities in a number of 27# cases. For now, we simply duplicate them as needed 28SHARED_SLOT_MARSHALLERS = False 29 30# For parsing command line options 31from optparse import OptionParser 32 33# Python interpreter version check: this script does not work with Python 34# version 2.6 or earlier! 35from sys import version_info 36version_string = '.'.join(map(str, version_info[0:3])) 37if version_info[0] < 2: 38 print('Need at least Python 2.7, got version ' + version_string) 39 quit(1) 40if version_info[0] == 2 and version_info[1] < 7: 41 print('Need at least Python 2.7, got version ' + version_string) 42 quit(1) 43 44uri = "http://www.gtk.org/introspection/core/1.0" 45glib_uri = "http://www.gtk.org/introspection/glib/1.0" 46c_uri = "http://www.gtk.org/introspection/c/1.0" 47 48cidentifier = QName(c_uri, "identifier").text 49cidentifier_prefix = QName(c_uri, "identifier-prefixes").text 50ctype_qname = QName(c_uri, "type").text 51ggettype = QName(glib_uri, "get-type").text 52gsignal = QName(glib_uri, "signal").text 53glib_type_struct = QName(glib_uri, "type-struct").text 54glib_type_name = QName(glib_uri, "type-name").text 55namespace = QName(uri, "namespace").text 56narray = QName(uri, "array").text 57nbitfield = QName(uri, "bitfield").text 58ncallback = QName(uri, "callback").text 59nclass = QName(uri, "class").text 60ndoc = QName(uri, "doc").text 61nenumeration = QName(uri, "enumeration").text 62nfield = QName(uri, "field").text 63nfunction = QName(uri, "function").text 64nimplements = QName(uri, "implements").text 65ninterface = QName(uri, "interface").text 66nmember = QName(uri, "member").text 67nmethod = QName(uri, "method").text 68nvirtualmethod = QName(uri, "virtual-method").text 69nparam = QName(uri, "parameter").text 70nparams = QName(uri, "parameters").text 71nrecord = QName(uri, "record").text 72nunion = QName(uri, "union").text 73nreturn = QName(uri, "return-value").text 74ntype = QName(uri, "type").text 75nvalue = QName(uri, "value").text 76nvarargs = QName(uri, "varargs").text 77nconstant = QName(uri, "constant").text 78ninstanceparam = QName(uri, "instance-parameter").text 79 80 81class GIR(object): 82 83 def __init__(self, files): 84 """Parse filename and initializes SELF""" 85 86 self.packages = dict() # Ada name (lower case) -> Package instance 87 self.ccode = "" 88 self.classes = dict() # Maps C name to a GIRClass instance 89 self.interfaces = dict() # Maps GIR's "name" to an interface 90 self.ctype_interfaces = dict() # Maps GIR's c:type to an interface 91 self.callbacks = dict() # Ada name to GIR XML node 92 self.enums = dict() # Maps C "name" to a GIR XML node 93 self.globals = GlobalsBinder(self) # global vars 94 self.records = dict() # Maps C "name" to a GIR XML node 95 # Maps C "name" to a GIR XML node for constants 96 self.constants = dict() 97 98 self.bound = set() # C names for the entities that have an Ada binding 99 100 # The marshallers that have been generated when we use a slot object. 101 # These can be shared among all packages, since the profiles of the 102 # handlers are the same. 103 if SHARED_SLOT_MARSHALLERS: 104 self.slot_marshallers = set() 105 self.slot_marshaller_pkg = self.get_package( 106 name="Gtkada.Marshallers", 107 ctype=None, 108 doc="Automatically generated, used internally by GtkAda") 109 self.slot_marshaller_section = self.slot_marshaller_pkg.section("") 110 111 for filename in files: 112 _tree = parse(filename) 113 root = _tree.getroot() 114 115 identifier_prefix = root.find(namespace).get(cidentifier_prefix) 116 117 k = "%s/%s" % (namespace, ncallback) 118 for cl in root.findall(k): 119 ct = cl.get(ctype_qname) 120 type = Callback(naming.case(ct)) 121 naming.add_type_exception(cname=ct, type=type) 122 ct = naming.type(ct).ada 123 self.callbacks[ct] = cl 124 125 k = "%s/%s" % (namespace, ninterface) 126 for cl in root.findall(k): 127 self.ctype_interfaces[cl.get(ctype_qname)] = \ 128 self.interfaces[cl.get("name")] = \ 129 self._create_class( 130 root, cl, is_interface=True, is_gobject=False, 131 identifier_prefix=identifier_prefix) 132 133 k = "%s/%s" % (namespace, nclass) 134 for cl in root.findall(k): 135 self.classes[cl.get(ctype_qname)] = self._create_class( 136 root, cl, is_interface=False, 137 identifier_prefix=identifier_prefix) 138 139 k = "%s/%s" % (namespace, nconstant) 140 for cl in root.findall(k): 141 self.constants[cl.get(ctype_qname)] = cl 142 143 # Some <record> are defined with methods. They are bound the same 144 # way in GtkAda, except that they do not derive from GObject 145 146 k = "%s/%s" % (namespace, nrecord) 147 for cl in root.findall(k): 148 if cl.findall(nmethod): 149 self.classes[cl.get(ctype_qname)] = self._create_class( 150 root, cl, is_interface=False, is_gobject=False, 151 identifier_prefix=identifier_prefix) 152 self.records[cl.get(ctype_qname)] = cl 153 154 k = "%s/%s" % (namespace, nunion) 155 for cl in root.findall(k): 156 if cl.findall(nmethod): 157 self.classes[cl.get(ctype_qname)] = self._create_class( 158 root, cl, is_interface=False, is_gobject=False, 159 identifier_prefix=identifier_prefix) 160 self.records[cl.get(ctype_qname)] = cl 161 162 for enums in (nenumeration, nbitfield): 163 k = "%s/%s" % (namespace, enums) 164 for cl in root.findall(k): 165 self.enums[cl.get(ctype_qname)] = cl 166 167 self.globals.add(root) 168 169 def show_unbound(self): 170 """Display the list of entities known in the GIR files, but that have 171 no Ada binding. 172 """ 173 174 print "Missing bindings:" 175 count = 0 176 for name in sorted(gir.interfaces.iterkeys()): 177 if name not in self.bound: 178 sys.stdout.write("%-28s" % (name + "(intf)", )) 179 count += 1 180 if (count % 4) == 0: 181 sys.stdout.write("\n") 182 183 for name in sorted(gir.classes.iterkeys()): 184 if name not in self.bound: 185 sys.stdout.write("%-28s" % name) 186 # print ' "--%s", # Not tested yet, from Gio' % name 187 count += 1 188 if (count % 4) == 0: 189 sys.stdout.write("\n") 190 191 print 192 193 def _get_class_node(self, rootNode, girname): 194 """Find the <class> node in the same XML document as node that matches 195 [girname]. 196 """ 197 k = "{%(uri)s}namespace/{%(uri)s}class" % {"uri": uri} 198 for cl in rootNode.findall(k): 199 if cl.get("name") == girname: 200 return cl 201 return None 202 203 def _create_class(self, rootNode, node, is_interface, 204 identifier_prefix, is_gobject=True, 205 has_toplevel_type=True): 206 return GIRClass(self, rootNode=rootNode, node=node, 207 is_interface=is_interface, 208 is_gobject=is_gobject, 209 identifier_prefix=identifier_prefix, 210 has_toplevel_type=has_toplevel_type) 211 212 def debug(self, element): 213 """A debug form of element""" 214 return tostring(element) 215 216 def get_package(self, name, ctype, doc=""): 217 """Return a handle to an Ada package""" 218 if not name.lower() in self.packages: 219 pkg = self.packages[name.lower()] = Package( 220 name=name, 221 doc=gtkada.get_pkg(ctype).get_doc()) 222 else: 223 pkg = self.packages[name.lower()] 224 225 if doc: 226 pkg.doc = ["<description>", doc, "</description>"] + pkg.doc 227 228 return pkg 229 230 def generate(self, out, cout): 231 """Generate Ada code for all packages""" 232 for pkg in self.packages.itervalues(): 233 out.write(pkg.spec().encode('UTF-8')) 234 out.write("\n") 235 out.write(pkg.body().encode('UTF-8')) 236 out.write("\n") 237 238 cout.write(self.ccode) 239 240 241class GlobalsBinder(object): 242 243 def __init__(self, gir): 244 self.gir = gir 245 self.globals = dict() 246 247 def add(self, node): 248 k = "{%(uri)s}namespace/{%(uri)s}function" % {"uri": uri} 249 all = node.findall(k) 250 if all is not None: 251 for c in all: 252 id = c.get(cidentifier) 253 self.globals[id] = c 254 255 def get_function(self, id): 256 """Return the XML node corresponding to a global function""" 257 return self.globals[id] 258 259 260def _get_clean_doc(node): 261 """ 262 Get the <doc> child node, and replace common unicode characters by their 263 ASCII equivalent to keep the Ada specs more readable in a terminal. 264 """ 265 266 doc = node.findtext(ndoc, "") 267 if doc: 268 doc = doc.replace(u"\u2019", "'").replace( 269 u"\u201c", '"').replace(u"\u201d", '"') 270 return doc 271 272 273def _get_type(nodeOrType, allow_access=True, allow_none=False, 274 transfer_ownership=False, userecord=True, pkg=None): 275 """Return the type of the GIR XML node. 276 nodeOrType can be one of: 277 * a string, given the name of the C type 278 * an instance of CType, which is returned as is. 279 * An XML node from which the information is gathered. 280 281 `allow_access' should be False if "access Type" parameters should 282 not be allowed, and an explicit type is needed instead. 283 `allow_none': see doc for CType. 284 `pkg' is used to add with statements, if specified 285 """ 286 if isinstance(nodeOrType, CType): 287 return nodeOrType 288 289 elif isinstance(nodeOrType, str): 290 return naming.type(name=nodeOrType, 291 cname=nodeOrType, 292 userecord=userecord, 293 transfer_ownership=transfer_ownership, 294 allow_access=allow_access, 295 allow_none=allow_none, pkg=pkg) 296 297 else: 298 t = nodeOrType.find(ntype) 299 if t is not None: 300 if t.get("name") == "none": 301 return None 302 303 ctype_name = t.get(ctype_qname) 304 if ctype_name: 305 ctype_name = ctype_name.replace("const ", "") 306 return naming.type(name=t.get("name"), 307 cname=ctype_name, 308 userecord=userecord, 309 transfer_ownership=transfer_ownership, 310 allow_access=allow_access, 311 allow_none=allow_none, pkg=pkg) 312 313 a = nodeOrType.find(narray) 314 if a is not None: 315 t = a.find(ntype) 316 if a: 317 type = t.get(ctype_qname) 318 name = t.get("name") or type # Sometimes name is not set 319 320 size = a.get("fixed-size", None) 321 322 if type: 323 type = "array_of_%s" % (type, ) 324 325 return naming.type(name="array_of_%s" % name, 326 cname=type, 327 pkg=pkg, isArray=True, 328 array_fixed_size=size, 329 transfer_ownership=transfer_ownership, 330 allow_none=allow_none, 331 userecord=userecord, 332 allow_access=allow_access) 333 334 a = nodeOrType.find(nvarargs) 335 if a is not None: 336 # A function with multiple arguments cannot be bound 337 # No need for an error message, we will already let the user know 338 # that the function is not bound. 339 return None 340 341 print("Error: XML Node has unknown type: %s (%s)" % (nodeOrType, nodeOrType.attrib)) 342 return None 343 344 345class SubprogramProfile(object): 346 347 """A class that groups info on the parameters of a function and 348 its return type. 349 """ 350 351 def __init__(self): 352 self.node = None # the XML node for this profile 353 self.gtkmethod = None 354 self.params = None # list of parameters (None if we have varargs) 355 self.returns = None # return value (None for a procedure) 356 self.returns_doc = "" # documentation for returned value 357 self.doc = "" # documentation for the subprogram 358 359 # The following fields are used to handle callback parameters 360 # and generate an Ada generic 361 362 self.callback_param = [] # indexes of the callback parameter 363 self.user_data_param = -1 # index of the "user data" parameter 364 self.destroy_param = -1 # index of the parameter to destroy data 365 366 def __repr__(self): 367 return "<SubprogramProfile %s>" % self.node 368 369 @staticmethod 370 def parse(node, gtkmethod, pkg=None, ignore_return=False): 371 """Parse the parameter info and return type info from the XML 372 GIR node, overriding with binding.xml. 373 gtkmethod is the GtkAdaMethod that contains the overriding for the 374 various method attributes. 375 If pkg is specified, with statements are added as necessary. 376 377 If ignore_return is True, the return type is not parsed. This is 378 used for constructors, so that we do not end up adding extra 'with' 379 statements in the generated package. 380 """ 381 profile = SubprogramProfile() 382 profile.node = node 383 profile.gtkmethod = gtkmethod 384 385 # make sure to init the 'returns' field before the parameters, to be 386 # able to correctly set the parameters direction ('in out' or 'out' 387 # case) 388 if not ignore_return: 389 profile.returns = profile._returns(node, gtkmethod, pkg=pkg) 390 391 profile.params = profile._parameters(node, gtkmethod, pkg=pkg) 392 393 profile.doc = profile._getdoc(gtkmethod, node) 394 return profile 395 396 @staticmethod 397 def setter(node, pkg=None): 398 """Create a new SubprogramProfile for a getter""" 399 profile = SubprogramProfile() 400 profile.node = node 401 profile.params = [Parameter("Value", _get_type(node, pkg))] 402 return profile 403 404 def callback_param_info(self): 405 """If there is one or more callback parameters in this profile, return 406 them so that we can generate the appropriate function. Returns None 407 if there are no such parameters. 408 """ 409 if not self.callback_param: 410 return None 411 return [self.params[p] for p in self.callback_param] 412 413 def callback_destroy(self): 414 if self.destroy_param < 0: 415 return None 416 return self.params[self.destroy_param] 417 418 def callback_user_data(self): 419 """Returns the name of the "user_data" parameter""" 420 421 if self.user_data_param == -1: 422 return None 423 return self.params[self.user_data_param].name 424 425 def has_varargs(self): 426 return self.params is None 427 428 def direct_c_map(self): 429 """Wether all parameters and return value can be mapped directly from 430 C to Ada. 431 """ 432 for p in self.params: 433 # If a parameter is not mapped in Ada, we need an actual body 434 if not p.direct_c_map() or not p.ada_binding: 435 return False 436 return self.returns is None or self.returns.direct_c_map() 437 438 def c_params(self, localvars, code): 439 """Returns the list of parameters for an Ada function that would be 440 a direct pragma Import. local variables or additional code will 441 be extended as needed to handle conversions. 442 """ 443 assert(isinstance(localvars, list)) 444 assert(isinstance(code, list)) 445 446 result = [] 447 for p in self.params: 448 n = p.name 449 is_temporary = False 450 451 if self.returns is not None and p.mode != "in" and p.ada_binding: 452 n = "Acc_%s" % p.name 453 var = Local_Var( 454 name=n, 455 aliased=True, 456 default="" if p.mode != "in out" else p.name, 457 type=p.type) 458 var.type.userecord = False 459 localvars.append(var) 460 461 if p.mode == "access": 462 if p.type.allow_none: 463 code.append( 464 "if %s /= null then %s.all := %s; end if;" 465 % (p.name, p.name, var.name)) 466 else: 467 code.append("%s.all := %s;" % (p.name, var.name)) 468 else: 469 is_temporary = p.mode != "out" 470 code.append("%s := %s;" % (p.name, var.name)) 471 472 # If we do not bind the parameter in the Ada profile, we will need 473 # to substitute its default value instead. But we don't want to 474 # systematically put the default value, which is in Ada. We would 475 # end up with Interfaces.C.Strings.chars_ptr="" 476 477 result.append(Parameter( 478 name=n, mode=p.mode, type=p.type, 479 for_function=self.returns is not None, 480 default=p.default if not p.ada_binding else None, 481 is_temporary_variable=is_temporary, 482 ada_binding=p.ada_binding)) 483 484 return result 485 486 def set_class_wide(self): 487 """This profile is not for a primitive operation, but for a class-wide 488 operation. 489 """ 490 if isinstance(self.params[0].type, GObject): 491 self.params[0].type.classwide = True 492 493 def add_param(self, pos, param): 494 """Add a new parameter in the list, at the given position""" 495 self.params.insert(pos, param) 496 if self.callback_param: 497 self.callback_param = [p + 1 if p >= pos else p 498 for p in self.callback_param] 499 if self.user_data_param >= 0 and self.user_data_param >= pos: 500 self.user_data_param += 1 501 if self.destroy_param >= 0 and self.destroy_param >= pos: 502 self.destroy_param += 1 503 504 def replace_param(self, name_or_index, type): 505 """Overrides the type of a parameter""" 506 if name_or_index is None: 507 return 508 509 if isinstance(name_or_index, int): 510 self.params[name_or_index].set_type(type) 511 else: 512 for idx, p in enumerate(self.params): 513 if p.name.lower() == name_or_index.lower(): 514 self.params[idx].set_type(type) 515 return 516 517 def remove_param(self, names): 518 """Remove the parameter with the given names from the list""" 519 assert(isinstance(names, list)) 520 521 for n in names: 522 if n is not None: 523 n = n.lower() 524 for p in self.params: 525 if p.name.lower() == n: 526 self.params.remove(p) 527 break 528 529 def find_param(self, names): 530 """Return the first name for which there is a parameter""" 531 for n in names: 532 lo = n.lower() 533 for p in self.params: 534 if p.name.lower() == lo: 535 return n 536 return None 537 538 def unset_default_values(self): 539 """Remove the default values for the parameters""" 540 for p in self.params: 541 p.default = None 542 543 def subprogram(self, name, showdoc=True, local_vars=[], code=[], 544 convention=None, lang="ada"): 545 """Return an instance of Subprogram with the corresponding profile. 546 lang is one of "ada", "c->ada" or "ada->c". 547 """ 548 549 params = self.params 550 if lang == "ada": 551 params = [p for p in self.params if p.ada_binding] 552 553 subp = Subprogram( 554 name=name, 555 plist=params, 556 returns=self.returns, 557 showdoc=showdoc, 558 doc=self.doc, 559 lang=lang, 560 local_vars=local_vars, 561 code=code) 562 subp.convention = convention or self.gtkmethod.convention() 563 564 if name != "": 565 depr = self.node.get("deprecated") 566 if depr is not None: 567 subp.mark_deprecated( 568 "\nDeprecated since %s, %s" 569 % (self.node.get("deprecated-version"), depr)) 570 elif self.gtkmethod and self.gtkmethod.is_obsolete(): 571 subp.mark_deprecated("Deprecated") 572 573 return subp 574 575 def _getdoc(self, gtkmethod, node): 576 doc = gtkmethod.get_doc(default=_get_clean_doc(node)) 577 if node.get("version"): 578 doc.append("Since: gtk+ %s" % node.get("version")) 579 return doc 580 581 def _parameters(self, c, gtkmethod, pkg): 582 """Parse the <parameters> child node of c""" 583 if c is None: 584 return [] 585 586 params = c.find(nparams) 587 if params is None: 588 return [] 589 590 # Check whether we'll bind to a procedure or to a function 591 is_function = self.returns and not gtkmethod.return_as_param() 592 593 result = [] 594 595 for p_index, p in enumerate(params.findall(nparam)): 596 name = p.get("name") 597 if name == "...": 598 name = "varargs" 599 600 gtkparam = gtkmethod.get_param(name=name) 601 adan = gtkparam.ada_name() 602 603 ada_binding = adan is None or adan != "" 604 name = adan or name # override default computed name 605 606 default = gtkparam.get_default() 607 allow_access = not default 608 allow_none = gtkparam.allow_none(girnode=p) or default == 'null' 609 nodeOrType = gtkparam.get_type(pkg=pkg) or p 610 611 type = _get_type( 612 nodeOrType=nodeOrType, 613 allow_none=allow_none, 614 userecord=default != 'null', 615 allow_access=allow_access, 616 pkg=pkg) 617 618 if type is None: 619 if nodeOrType.find(nvarargs) is not None: 620 type = gtkmethod.get_param("varargs").get_type(pkg=pkg) 621 else: 622 type = gtkmethod.get_param(name).get_type(pkg=pkg) 623 if type is None: 624 return None 625 type = _get_type(type) 626 627 if not default and allow_none and isinstance(type, UTF8): 628 default = '""' 629 630 if (p.get("scope", "") in ("notified", "call", "async") 631 or p.get("closure", "") != ""): 632 633 # "async" means a callback with no closure. As a special case, 634 # we ignore it for destroy callbacks, since they are already 635 # handled specially. 636 637 if p.get("scope") != "async" \ 638 or type.ada != "Glib.G_Destroy_Notify_Address": 639 self.callback_param.append(p_index) 640 self.user_data_param = int(p.get("closure", "-1")) 641 self.destroy_param = int(p.get("destroy", "-1")) - 1 642 643 direction = gtkparam.get_direction() or p.get("direction", "in") 644 assert direction in ("in", "out", "inout", "access"), \ 645 "Invalid value for direction: '%s'" % direction 646 647 if direction == "inout": 648 mode = "in out" 649 elif direction in ("out", "access"): 650 mode = direction 651 elif type.is_ptr: 652 mode = "in out" 653 else: 654 mode = "in" 655 656 if is_function and direction not in ("in", "access"): 657 mode = "access" 658 659 doc = _get_clean_doc(p) 660 if doc: 661 doc = '"%s": %s' % (name, doc) 662 663 result.append( 664 Parameter(name=naming.case(name), 665 type=type, 666 mode=mode, 667 default=default, 668 ada_binding=ada_binding, 669 doc=doc)) 670 671 return result 672 673 def _returns(self, node, gtkmethod, pkg): 674 """Parse the method's return type""" 675 676 returns = gtkmethod.returned_c_type() 677 if returns is None: 678 ret = node.find(nreturn) 679 if ret is None: 680 # For a <field>, the method's return value will be the type 681 # of the field itself 682 ret = node 683 else: 684 self.returns_doc = _get_clean_doc(ret) 685 if self.returns_doc: 686 self.returns_doc = "Returns %s" % self.returns_doc 687 688 return _get_type( 689 ret, allow_access=False, pkg=pkg, 690 transfer_ownership=gtkmethod.transfer_ownership(ret)) 691 else: 692 return naming.type(name=None, cname=returns, pkg=pkg) 693 694 695class GIRClass(object): 696 697 """Represents a gtk class""" 698 699 def __init__(self, gir, rootNode, node, identifier_prefix, 700 is_interface=False, is_gobject=True, has_toplevel_type=True): 701 """If has_toplevel_type is False, no widget type is generated""" 702 703 self.gir = gir 704 self.node = node 705 self.rootNode = rootNode 706 self.ctype = self.node.get(ctype_qname) 707 if not self.ctype: 708 print("no c:type defined for %s" % (self.node.get(glib_type_name, ))) 709 return 710 711 self._private = "" 712 self._generated = False 713 self.identifier_prefix = identifier_prefix 714 self.implements = dict() # Implemented interfaces 715 self.is_gobject = is_gobject 716 self.is_interface = is_interface 717 self.has_toplevel_type = has_toplevel_type 718 self.callbacks = set() # The callback functions 719 self.pkg = None # Instance of Package(), that we are generating 720 721 # List of Convert(...) functions that were implemented 722 self.conversions = dict() 723 724 self.__marshallers = set() # The generated marshallers 725 726 # Search for the GtkAda binding information 727 728 self.gtkpkg = gtkada.get_pkg(self.ctype) 729 if not self.gtkpkg.bindtype: 730 self.has_toplevel_type = False 731 self.is_gobject = False 732 733 # Is this a binding for an opaque C record (not a GObject). In this 734 # case, we bind it as an Ada tagged type so that we can use the 735 # convenient dot notation for primitive operations. This is only doable 736 # if there is no public field that should be user visible in the 737 # record. Otherwise, we'll map to a standard Ada record 738 # (self.is_record) 739 740 self.is_proxy = False 741 self.is_boxed = (self.node.tag == nrecord 742 and (not self.node.findall(nfield) 743 or self.node.get("introspectable", "1") == "0")) 744 self.is_record = self.node.tag == nrecord and not self.is_boxed 745 746 if (self.is_boxed 747 and naming.type_exceptions.get(self.ctype) is not None 748 and isinstance(naming.type_exceptions.get(self.ctype), Proxy)): 749 self.is_proxy = True 750 self.is_boxed = False 751 752 # Register naming exceptions for this class 753 754 n = naming.case(self.ctype) 755 756 into = self.gtkpkg.into() 757 ada = self.gtkpkg.ada_name() 758 if ada: 759 pkg = ada 760 elif into: 761 into = naming.case(into) 762 pkg = naming.protect_keywords(into.replace("_", ".", 1)) 763 else: 764 pkg = naming.protect_keywords(n.replace("_", ".", 1)) 765 766 pkg = "%s.%s" % (pkg, n) 767 naming.add_girname(girname=n, ctype=self.ctype) 768 769 if has_toplevel_type: 770 ctype = node.get(ctype_qname) 771 if is_interface: 772 t = Interface(pkg) 773 elif is_gobject: 774 t = GObject(pkg) 775 elif self.is_proxy: 776 t = Proxy(pkg) 777 elif self.is_boxed: 778 t = Tagged(pkg) 779 else: 780 t = Record(pkg) 781 782 naming.add_type_exception(cname=ctype, type=t) 783 classtype = naming.type(name=self.ctype) 784 typename = classtype.ada 785 self.name = package_name(typename) 786 if ada is not None: 787 self.name = ada 788 789 self.ada_package_name = self.name 790 791 if not self.has_toplevel_type: 792 # Compute the package name ignoring the type_exceptions. For 793 # instance, we have defined that GdkWindow is mapped to 794 # Gdk.Gdk_Window, but the operations should go into the package 795 # Gdk.Window.Gdk_Window. 796 self.ada_package_name = package_name(pkg) 797 798 else: 799 typename = "" 800 self.name = package_name(pkg) 801 self.ada_package_name = self.name 802 803 self.gtkpkg.register_types(adapkg=self.ada_package_name) 804 805 # Compute information that will be used for the binding 806 807 self._subst = { # for substitution in string templates 808 "name": self.name, 809 "typename": base_name(typename), 810 "cname": self.ctype or ""} 811 812 def _handle_function(self, section, c, ismethod=False, gtkmethod=None, 813 showdoc=True, isinherited=False): 814 cname = c.get(cidentifier) 815 816 if gtkmethod is None: 817 gtkmethod = self.gtkpkg.get_method(cname=cname) 818 819 if gtkmethod.bind(): 820 profile = SubprogramProfile.parse( 821 node=c, gtkmethod=gtkmethod, pkg=self.pkg) 822 self._handle_function_internal( 823 section, node=c, cname=cname, 824 gtkmethod=gtkmethod, 825 profile=profile, 826 showdoc=showdoc, 827 ismethod=ismethod, 828 isinherited=isinherited) 829 else: 830 naming.add_cmethod( 831 cname, gtkmethod.ada_name() or cname) # Avoid warning later on 832 833 def _func_is_direct_import(self, profile): 834 """Whether a function with this profile 835 should be implemented directly as a pragma Import, rather than 836 require its own body. 837 """ 838 return not self.is_gobject \ 839 and not self.is_boxed \ 840 and profile.direct_c_map() 841 842 def _add_self_param(self, adaname, node, gtkmethod, profile, inherited): 843 """Add a Self parameter to the list of parameters in profile. 844 The exact type of the parameter depends on several criteria. 845 846 :param bool inherited: should be true if this is for a subprogram 847 inherited from an interface (in which case we force the type of 848 Self to be that of the child, not the interface type as described 849 in the gir file) 850 """ 851 852 # Try to extract the type of the parameter from the instance-parameter 853 # node. 854 t = None 855 if not inherited: 856 try: 857 ip = node.iter(ninstanceparam).next() 858 ipt = ip.find(ntype) 859 if ipt is not None: 860 ctype_name = ipt.get(ctype_qname) 861 if ctype_name: 862 ctype_name = ctype_name.replace('const ', '') 863 t = naming.type(name=ipt.get('name'), 864 cname=ctype_name, 865 useclass=gtkmethod.is_class_wide()) 866 except StopIteration: 867 t = None 868 869 # There was no instance-parameter node, guess the type from the 870 # package name 871 872 if t is None: 873 t = naming.type(self._subst["cname"], 874 cname=self._subst["cname"], 875 useclass=gtkmethod.is_class_wide()) 876 877 gtkparam = gtkmethod.get_param("self") 878 pname = gtkparam.ada_name() or "Self" 879 880 direction = gtkparam.get_direction() or "in" 881 if direction in ("out", "access"): 882 mode = direction 883 elif direction == "inout": 884 mode = "in out" 885 else: 886 mode = "in" 887 888 profile.add_param(0, Parameter(name=pname, type=t, mode=mode)) 889 890 def _handle_function_internal(self, section, node, cname, 891 gtkmethod, 892 profile=None, 893 showdoc=True, 894 adaname=None, 895 ismethod=False, 896 isinherited=False): 897 """Generate a binding for a function., 898 This returns None if no binding was made, an instance of Subprogram 899 otherwise. 900 `adaname' is the name of the generated Ada subprograms. By default, 901 it is computed automatically from either binding.xml or the "name" 902 attribute of `node'. 903 `profile' is an instance of SubprogramProfile 904 """ 905 assert(profile is None or isinstance(profile, SubprogramProfile)) 906 907 if profile.has_varargs() \ 908 and gtkmethod.get_param("varargs").node is None: 909 naming.add_cmethod(cname, cname) # Avoid warning later on. 910 print "No binding for %s: varargs" % cname 911 return None 912 913 is_import = self._func_is_direct_import(profile) \ 914 and not gtkmethod.get_body() \ 915 and not gtkmethod.return_as_param() 916 adaname = adaname or gtkmethod.ada_name() or node.get("name").title() 917 adaname = naming.protect_keywords(adaname) 918 919 if not isinherited: 920 naming.add_cmethod(cname, "%s.%s" % (self.pkg.name, adaname)) 921 922 if ismethod: 923 self._add_self_param( 924 adaname, node, gtkmethod, profile, inherited=isinherited) 925 926 if adaname.startswith("Gtk_New"): 927 # Overrides the GIR file even if it reported a function or method 928 self._handle_constructor( 929 node, gtkmethod=gtkmethod, cname=cname, profile=profile) 930 return 931 932 local_vars = [] 933 call = "" 934 935 body = gtkmethod.get_body() 936 if not is_import: 937 # Prepare the Internal C function 938 939 internal_call = [] 940 internal = Subprogram( 941 name="Internal", 942 returns=profile.returns, 943 lang="ada->c", 944 plist=profile.c_params(local_vars, internal_call) 945 ).import_c(cname) 946 947 # Should we transform the return value into a parameter ? 948 949 ret_as_param = gtkmethod.return_as_param() 950 if ret_as_param is not None: 951 profile.params.append( 952 Parameter(name=ret_as_param, 953 type=profile.returns, mode="out")) 954 profile.returns = None 955 956 # Is this a function that takes a callback parameter ? 957 958 cb = profile.callback_param_info() 959 if cb is not None: 960 if ret_as_param: 961 # ??? We would need to change _callback_support to 962 # have additional code to set the return value. One 963 # issue is that the profile has already been changed 964 raise Exception("Cannot bind function with callback" 965 + " and return value as parameter: %s" 966 % cname) 967 968 return self._callback_support(adaname, cname, profile, cb) 969 970 execute = internal.call( 971 in_pkg=self.pkg, extra_postcall="".join(internal_call)) 972 973 if ret_as_param is not None: 974 assert execute[1] is not None, \ 975 "Must have a return value in %s => %s" % (cname, execute) 976 call = "%s%s := %s;" % (execute[0], ret_as_param, execute[1]) 977 978 else: 979 if execute[1]: # A function, with a standard "return" 980 call = "%sreturn %s;" % (execute[0], execute[1]) 981 else: 982 call = execute[0] 983 984 local_vars += execute[2] 985 986 subp = profile.subprogram(name=adaname, showdoc=showdoc, 987 local_vars=local_vars, code=call) 988 989 if is_import: 990 subp.import_c(cname) 991 else: 992 subp.add_nested(internal) 993 if body: 994 subp.set_body(" " + body.strip() + "\n") 995 996 section.add(subp) 997 return subp 998 999 def _callback_support(self, adaname, cname, profile, cb): 1000 """Add support for a function with a callback parameter and user data. 1001 We generate multiple bindings for such a function: 1002 * One version that doesn't take a user_data. This looks like: 1003 type My_Callback is access function (Self, other_params); 1004 procedure Gtk_Func (Self : ...; Cb : My_Callback); 1005 1006 since My_Callback doesn't have exactly the same profile as 1007 required by gtk+, we in fact go through an intermediate function 1008 in the body, to which we pass, as user_data, a pointer to the 1009 user's callback: 1010 1011 function Internal_Callback (same_profile_as_c, user_data) is 1012 User_Func : My_Callback := convert (user_data); 1013 begin 1014 return User_Func (...); 1015 end Internal_Callback; 1016 pragma Convention (C, Internal_Callback); 1017 1018 * Ideally we want to generate a generic package to which users 1019 can pass their own user data type. We then need to generate the 1020 proper Destroy callback that C will call to free that user data. 1021 1022 :profile: is an instance of SubprogramProfile. 1023 :cname: is the name of the gtk+ C function. 1024 :adaname: is the name of the corresponding Ada function. 1025 :cb: is a list of Parameter instances representing the callback 1026 parameters. 1027 """ 1028 1029 if len(cb) > 1: 1030 print "No binding for %s: multiple callback parameters" % cname 1031 return 1032 cb = cb[0] 1033 1034 def call_to_c(gtk_func, values): 1035 """Implement the call to the C function. 1036 If the user passes a null callback, we always want to pass null 1037 to C rather than passing our Internal_Callback'Address. 1038 1039 :param values: a dictionary of the parameters to pass to call(). 1040 :return: the code for the Ada function's body 1041 """ 1042 1043 values_if_null = copy.deepcopy(values) 1044 values_if_null[cb.name.lower()] = "System.Null_Address" 1045 1046 if user_data is not None: 1047 values_if_null[user_data.lower()] = "System.Null_Address" 1048 1049 exec1 = gtk_func.call( 1050 in_pkg=self.pkg, 1051 extra_postcall="".join(call), values=values_if_null) 1052 1053 call1 = gtk_func.call_to_string(exec1, lang="ada->c") 1054 if not call1.endswith(";"): 1055 call1 += ";" 1056 1057 exec2 = gtk_func.call( 1058 in_pkg=self.pkg, 1059 extra_postcall="".join(call), values=values) 1060 1061 call2 = gtk_func.call_to_string(exec2, lang="ada->c") 1062 if not call2.endswith(";"): 1063 call2 += ";" 1064 1065 return ("""if %s = null then 1066 %s 1067else 1068 %s 1069end if;""" % (cb.name, call1, call2), exec2[2]) 1070 1071 cbname = cb.type.param 1072 1073 # Compute the name of the Ada type representing the user callback 1074 1075 cb_type_name = naming.type(name=cb.type.ada, cname=cbname).ada 1076 funcname = base_name(cb_type_name) 1077 1078 destroy = profile.find_param(destroy_data_params) 1079 1080 # Compute the profile of the callback (will all its arguments) 1081 1082 gtkmethod = self.gtkpkg.get_method(cname=cname) 1083 1084 try: 1085 cb_gir_node = self.gir.callbacks[cb.type.ada] 1086 except: 1087 raise Exception( 1088 "No GIR node for %s in callback %s" % (cb.type.ada, cname)) 1089 1090 cbgtk = self.gtkpkg.get_method(cbname) 1091 1092 cb_profile = SubprogramProfile.parse( 1093 cb_gir_node, gtkmethod=cbgtk, pkg=self.pkg) 1094 1095 user_data = profile.callback_user_data() 1096 cb_user_data = cb_profile.find_param(user_data_params) 1097 if user_data is None and cb_user_data is not None: 1098 user_data = cb_user_data 1099 1100 # Generate the access-to-subprogram type for the user callback, unless 1101 # we have already done so. This is the type that doesn't receive 1102 # user data. 1103 1104 if cbname not in self.callbacks: 1105 self.callbacks.add(cbname) # Prevent multiple generations 1106 1107 section = self.pkg.section("Callbacks") 1108 1109 if cb_user_data is None: 1110 print "callback has no user data: %s" % cbname 1111 # If the C function has no user data, we do not know how to 1112 # generate a high-level binding, since we cannot go through an 1113 # intermediate C function that transforms the parameters into 1114 # their Ada equivalent. 1115 # 1116 # Instead, we just generate a low-level C callback passing 1117 # System.Address for widgets. 1118 1119 nouser_cb_profile = copy.deepcopy(cb_profile) 1120 subp = nouser_cb_profile.subprogram(name="", lang="ada->c") 1121 section.add( 1122 "\ntype %s is %s" % (funcname, subp.spec(pkg=self.pkg))) 1123 section.add( 1124 "\npragma Convention (C, %s);" % funcname) 1125 1126 else: 1127 # Generate a simpler version of the callback, without 1128 # user data, that the Ada applications can use 1129 1130 nouser_cb_profile = copy.deepcopy(cb_profile) 1131 nouser_cb_profile.remove_param( 1132 destroy_data_params + [cb_user_data]) 1133 subp = nouser_cb_profile.subprogram(name="") 1134 section.add( 1135 "\ntype %s is %s" % (funcname, subp.spec(pkg=self.pkg))) 1136 1137 # Generate a subprogram in the body to act as the C callback. 1138 # This subprogram is responsible for calling the user's 1139 # callback. In the call to the user's callback, we need to 1140 # convert the parameters from the C values to the 1141 # corresponding Ada values. 1142 1143 self.pkg.add_with( 1144 "Ada.Unchecked_Conversion", do_use=False, specs=False) 1145 section.add( 1146 ("function To_%s is new Ada.Unchecked_Conversion\n" 1147 + " (System.Address, %s);\n") % (funcname, funcname), 1148 in_spec=False) 1149 section.add( 1150 ("function To_Address is new Ada.Unchecked_Conversion\n" 1151 + " (%s, System.Address);\n") % (cb_type_name,), 1152 in_spec=False) 1153 1154 ada_func = copy.deepcopy(subp) 1155 1156 if ada_func.plist: 1157 ada_func.name = "Func" 1158 else: 1159 ada_func.name = "Func.all" 1160 1161 ada_func_call = ada_func.call(in_pkg=self.pkg, lang="c->ada") 1162 body_cb = cb_profile.subprogram( 1163 name="Internal_%s" % funcname, 1164 local_vars=[Local_Var( 1165 "Func", "constant %s" % funcname, 1166 "To_%s (%s)" % (funcname, cb_user_data))] 1167 + ada_func_call[2], 1168 lang="c->ada", 1169 code=ada_func.call_to_string(ada_func_call, lang="c->ada")) 1170 body_cb.convention = "C" 1171 body_cb.doc = [] 1172 section.add(body_cb, in_spec=False) 1173 1174 # The gtk C function, will all parameters. 1175 # This will be used to generate the "Internal" nested subprogram. 1176 1177 local_vars = [] 1178 call = [] 1179 gtk_func_profile = copy.deepcopy(profile) 1180 1181 if cb is not None: 1182 gtk_func_profile.replace_param(cb.name, "System.Address") 1183 1184 if cb_user_data is not None: 1185 gtk_func_profile.replace_param(destroy, "System.Address") 1186 1187 gtk_func = gtk_func_profile.subprogram( 1188 name=naming.case("C_%s" % cname), lang="ada->c").import_c(cname) 1189 1190 # This function is shared both by the version without user_data and by 1191 # the generic package, so we need to put it directly in the package, 1192 # not a nested subprogram. 1193 1194 self.pkg.section("").add(gtk_func, in_spec=False) 1195 1196 # Create a version of the function without a user data. 1197 1198 section = self.pkg.section("Methods") 1199 1200 nouser_profile = copy.deepcopy(profile) 1201 1202 if user_data is None: 1203 values = {destroy: "System.Null_Address", 1204 cb.name.lower(): "%s'Address" % cb.name} 1205 elif cb_user_data is None: 1206 values = {destroy: "System.Null_Address", 1207 cb.name.lower(): "Internal_%s'Address" % funcname, 1208 user_data.lower(): "%s'Address" % cb.name} 1209 else: 1210 nouser_profile.remove_param(destroy_data_params + [user_data]) 1211 values = {destroy: "System.Null_Address", 1212 cb.name.lower(): "Internal_%s'Address" % funcname, 1213 user_data.lower(): "To_Address (%s)" % cb.name} 1214 1215 c_call = call_to_c(gtk_func, values) 1216 1217 subp = nouser_profile.subprogram( 1218 name=adaname, local_vars=c_call[1], 1219 code=c_call[0]) 1220 section.add(subp) 1221 1222 # Now create a generic package that will provide access to 1223 # user_data. The function can no longer be a primitive operation of the 1224 # object, since it is in a nested package. 1225 # It is possible that the function doesn't accept a user data in fact 1226 # (for instance when scope="async"). In this case, no need for a 1227 # generic package. 1228 1229 user_data2 = cb_profile.find_param(user_data_params) 1230 1231 if user_data2 is not None: 1232 self.pkg.add_with("Glib.Object", do_use=False, specs=False) 1233 1234 pkg2 = Package(name="%s_User_Data" % adaname) 1235 section.add(pkg2) 1236 pkg2.formal_params = """type User_Data_Type (<>) is private; 1237 with procedure Destroy (Data : in out User_Data_Type) is null;""" 1238 1239 sect2 = pkg2.section("") 1240 sect2.add("""package Users is new Glib.Object.User_Data_Closure 1241 (User_Data_Type, Destroy);""", in_spec=False) 1242 1243 sect2.add( 1244 ("function To_%s is new Ada.Unchecked_Conversion\n" 1245 + " (System.Address, %s);\n") % (funcname, funcname), 1246 in_spec=False) 1247 sect2.add( 1248 ("function To_Address is new Ada.Unchecked_Conversion\n" 1249 + " (%s, System.Address);\n") % (funcname,), 1250 in_spec=False) 1251 1252 cb_profile2 = copy.deepcopy(cb_profile) 1253 cb_profile2.replace_param(user_data2, "User_Data_Type") 1254 cb2 = cb_profile2.subprogram(name="") 1255 sect2.add( 1256 "\ntype %s is %s" % (funcname, cb2.spec(pkg=pkg2))) 1257 1258 values = {user_data2.lower(): "D.Data.all"} 1259 user_cb = cb_profile2.subprogram(name="To_%s (D.Func)" % funcname) 1260 user_cb_call = user_cb.call( 1261 in_pkg=self.pkg, 1262 lang="c->ada", 1263 extra_postcall="".join(call), values=values) 1264 1265 internal_cb = cb_profile.subprogram( 1266 name="Internal_Cb", 1267 local_vars=[ 1268 Local_Var("D", "constant Users.Internal_Data_Access", 1269 "Users.Convert (%s)" % user_data2)] 1270 + user_cb_call[2], 1271 convention="C", 1272 lang="c->ada", 1273 code=user_cb.call_to_string(user_cb_call, lang="c->ada")) 1274 sect2.add(internal_cb, in_spec=False) 1275 1276 values = {destroy: "Users.Free_Data'Address", 1277 cb.name.lower(): "%s'Address" % internal_cb.name, 1278 user_data.lower(): 1279 "Users.Build (To_Address (%s), %s)" % ( 1280 cb.name, user_data)} 1281 1282 full_profile = copy.deepcopy(profile) 1283 full_profile.set_class_wide() 1284 full_profile.remove_param(destroy_data_params) 1285 full_profile.replace_param(cb.name, funcname) 1286 full_profile.replace_param(user_data, "User_Data_Type") 1287 c_call = call_to_c(gtk_func, values) 1288 subp2 = full_profile.subprogram( 1289 name=adaname, local_vars=c_call[1], 1290 code=c_call[0]) 1291 sect2.add(subp2) 1292 1293 return subp 1294 1295 def _constructors(self): 1296 n = QName(uri, "constructor").text 1297 for c in self.node.findall(n): 1298 cname = c.get(cidentifier) 1299 gtkmethod = self.gtkpkg.get_method(cname=cname) 1300 if not gtkmethod.bind(): 1301 naming.add_cmethod( 1302 cname, gtkmethod.ada_name() or cname) # Avoid warning 1303 continue 1304 1305 profile = SubprogramProfile.parse( 1306 node=c, gtkmethod=gtkmethod, pkg=self.pkg, 1307 ignore_return=True) 1308 if profile.has_varargs() \ 1309 and gtkmethod.get_param("varargs").node is None: 1310 1311 naming.add_cmethod(cname, cname) # Avoid warning later on. 1312 print "No binding for %s: varargs" % cname 1313 continue 1314 1315 self._handle_constructor( 1316 c, gtkmethod=gtkmethod, cname=cname, profile=profile) 1317 1318 def _handle_constructor(self, c, cname, gtkmethod, profile=None): 1319 assert(profile is None or isinstance(profile, SubprogramProfile)) 1320 1321 section = self.pkg.section("Constructors") 1322 name = c.get("name").title() 1323 1324 assert profile.params is not None, "No profile defined for %s" % cname 1325 1326 format_params = ", ".join(p.name for p in profile.params) 1327 if format_params: 1328 self._subst["internal_params"] = " (%s)" % format_params 1329 format_params = ", " + format_params 1330 self._subst["params"] = format_params 1331 else: 1332 self._subst["params"] = "" 1333 self._subst["internal_params"] = "" 1334 1335 if self.is_gobject or self.is_boxed: 1336 profile.returns = AdaType( 1337 "System.Address", pkg=self.pkg, in_spec=False) 1338 else: 1339 profile.returns = AdaType( 1340 "%(typename)s" % self._subst, 1341 pkg=self.pkg, in_spec=False) 1342 1343 local_vars = [] 1344 code = [] 1345 internal = Subprogram( 1346 name="Internal", 1347 lang="ada->c", 1348 plist=profile.c_params(local_vars, code), 1349 returns=profile.returns).import_c(cname) 1350 1351 call = internal.call(in_pkg=self.pkg) 1352 assert(call[1] is not None) # A function 1353 1354 gtk_new_prefix = "Gtk_New" 1355 1356 adaname = gtkmethod.ada_name() 1357 if not adaname: 1358 if cname.startswith("gdk_") or cname.startswith("pango_"): 1359 gtk_new_prefix = "Gdk_New" 1360 adaname = "Gdk_%s" % name # e.g. Gdk_New 1361 elif cname.startswith("g_"): 1362 gtk_new_prefix = "G_New" 1363 adaname = "G_%s" % name # e.g. G_New 1364 else: 1365 adaname = "Gtk_%s" % name # e.g. Gtk_New 1366 1367 selfname = gtkmethod.get_param("self").ada_name() or "Self" 1368 1369 if self.is_gobject: 1370 selftype = "%(typename)s_Record'Class" % self._subst 1371 else: 1372 selftype = "%(typename)s" % self._subst 1373 1374 if self.is_gobject: 1375 filtered_params = [p for p in profile.params if p.ada_binding] 1376 1377 initialize_params = [Parameter( 1378 name=selfname, 1379 type=AdaType(selftype, pkg=self.pkg, in_spec=True), 1380 mode="not null access")] + filtered_params 1381 initialize = Subprogram( 1382 name=adaname.replace( 1383 gtk_new_prefix, "%s.Initialize" % self.pkg.name), 1384 plist=initialize_params, 1385 local_vars=local_vars + call[2], 1386 doc=profile.doc, 1387 code="if not %s.Is_Created then %sSet_Object (%s, %s); end if" % ( 1388 selfname, call[0], selfname, call[1]), 1389 ).add_nested(internal) 1390 1391 call = initialize.call(in_pkg=self.pkg) 1392 assert(call[1] is None) # This is a procedure 1393 1394 naming.add_cmethod(cname, "%s.%s" % (self.pkg.name, adaname)) 1395 gtk_new = Subprogram( 1396 name=adaname, 1397 plist=[Parameter( 1398 name=selfname, 1399 type=AdaType("%(typename)s" % self._subst, 1400 pkg=self.pkg, in_spec=True), 1401 mode="out")] + filtered_params, 1402 local_vars=call[2], 1403 code=selfname + " := new %(typename)s_Record;" % self._subst 1404 + call[0], 1405 doc=profile.doc) 1406 1407 section.add(gtk_new) 1408 section.add(initialize) 1409 1410 # Gtk_New as a function 1411 gtk_new = Subprogram( 1412 name="%s_%s" % (self._subst["typename"], name), 1413 returns=AdaType("%(typename)s" % self._subst, 1414 pkg=self.pkg, in_spec=True), 1415 plist=filtered_params, 1416 local_vars=call[2] + 1417 [Local_Var(selfname, 1418 "constant %(typename)s" % self._subst, 1419 "new %(typename)s_Record" % self._subst)], 1420 code=call[0] + "return %s;" % selfname, 1421 doc=profile.doc) 1422 section.add(gtk_new) 1423 1424 elif self.is_boxed: 1425 gtk_new = Subprogram( 1426 name=adaname, 1427 plist=[Parameter( 1428 name=selfname, 1429 type=AdaType("%(typename)s" % self._subst, 1430 pkg=self.pkg, in_spec=True), 1431 mode="out")] + profile.params, 1432 local_vars=local_vars + call[2], 1433 code="%s%s.Set_Object (%s)" % (call[0], selfname, call[1]), 1434 doc=profile.doc) 1435 1436 gtk_new.add_nested(internal) 1437 section.add(gtk_new) 1438 1439 # Now as a function 1440 gtk_new = Subprogram( 1441 name="%s_%s" % (self._subst["typename"], name), 1442 returns=AdaType("%(typename)s" % self._subst, 1443 pkg=self.pkg, in_spec=True), 1444 plist=profile.params, 1445 local_vars=local_vars + call[2] + 1446 [Local_Var(selfname, 1447 "%(typename)s" % self._subst)], 1448 code="%s%s.Set_Object (%s); return %s" % ( 1449 call[0], selfname, call[1], selfname), 1450 doc=profile.doc) 1451 gtk_new.add_nested(internal) 1452 section.add(gtk_new) 1453 1454 else: 1455 # likely a Proxy 1456 gtk_new = Subprogram( 1457 name=adaname, 1458 plist=[Parameter( 1459 name=selfname, 1460 type=AdaType("%(typename)s" % self._subst, 1461 pkg=self.pkg, in_spec=True), 1462 mode="out")] + profile.params, 1463 local_vars=local_vars + call[2], 1464 code="%s%s := %s" % (call[0], selfname, call[1]), 1465 doc=profile.doc) 1466 gtk_new.add_nested(internal) 1467 section.add(gtk_new) 1468 1469 # Now as a function 1470 gtk_new = Subprogram( 1471 name="%s_%s" % (self._subst["typename"], name), 1472 returns=AdaType("%(typename)s" % self._subst, 1473 pkg=self.pkg, in_spec=True), 1474 plist=profile.params, 1475 local_vars=local_vars + call[2] + 1476 [Local_Var(selfname, 1477 "%(typename)s" % self._subst)], 1478 code="%s%s := %s; return %s;" % ( 1479 call[0], selfname, call[1], selfname), 1480 doc=profile.doc) 1481 gtk_new.add_nested(internal) 1482 section.add(gtk_new) 1483 1484 def _methods(self): 1485 all = self.node.findall(nmethod) 1486 if all is not None: 1487 section = self.pkg.section("Methods") 1488 for c in all: 1489 self._handle_function(section, c, ismethod=True) 1490 1491 def _functions(self): 1492 all = self.node.findall(nfunction) 1493 if all is not None: 1494 section = self.pkg.section("Functions") 1495 for c in all: 1496 self._handle_function(section, c) 1497 1498 def _virtual_methods(self): 1499 all = self.node.findall(nvirtualmethod) 1500 has_iface = False 1501 1502 if all is not None: 1503 ifacename = base_name(self.name) 1504 info = '' 1505 1506 for c in all: 1507 if not self.gtkpkg.bind_virtual_method( 1508 c.get('name'), default=self.is_interface): 1509 continue 1510 1511 gtkmethod = self.gtkpkg.get_method(cname=c.get('name')) 1512 basename = gtkmethod.ada_name() or c.get('name').title() 1513 adaname = "Virtual_%s" % basename 1514 1515 if not has_iface: 1516 has_iface = True 1517 section = self.pkg.section("Virtual Methods") 1518 1519 info += 'procedure Set_%s\n' % basename 1520 1521 if self.is_interface: 1522 info += ' (Self : %s_Interface_Descr;\n' % ifacename 1523 else: 1524 info += ' (Self : Glib.Object.GObject_Class;\n' 1525 1526 info += ' Handler : %s);\n' % adaname 1527 info += 'pragma Import (C, Set_%s, "gtkada_%s_set_%s");\n' % ( 1528 basename, ifacename, basename.lower()) 1529 1530 c_iface = '%s%s' % ( 1531 self.identifier_prefix, 1532 self.node.get(glib_type_struct)) 1533 1534 self.gir.ccode += """ 1535void gtkada_%s_set_%s(%s* iface, %s* handler) { 1536 iface->%s = handler; 1537}""" % (ifacename, basename.lower(), 1538 c_iface, 1539 'void', 1540 c.get('name')) 1541 1542 profile = SubprogramProfile.parse( 1543 node=c, 1544 gtkmethod=gtkmethod, 1545 pkg=self.pkg) 1546 self._add_self_param( 1547 adaname=adaname, node=c, gtkmethod=gtkmethod, profile=profile, 1548 inherited=False) 1549 subp = profile.subprogram( 1550 name=adaname, 1551 lang="ada->c", 1552 convention="C", 1553 showdoc=True) 1554 section.add( 1555 '\ntype %s is %s' % ( 1556 adaname, 1557 subp.spec(pkg=self.pkg, as_type=True))) 1558 subp.add_withs_for_subprogram(pkg=self.pkg, in_specs=True) 1559 1560 if has_iface: 1561 info = ('subtype %s_Interface_Descr is ' % ifacename 1562 + 'Glib.Object.Interface_Description;\n' 1563 + info 1564 + '-- See Glib.Object.Add_Interface\n') 1565 section.add(info) 1566 self.pkg.add_with('Glib.Object') 1567 1568 def _globals(self): 1569 funcs = self.gtkpkg.get_global_functions() # List of binding.xml nodes 1570 if funcs: 1571 section = self.pkg.section("Functions") # Make sure section exists 1572 for f in funcs: 1573 c = self.gir.globals.get_function( 1574 f.cname()) # Node in gir file 1575 self._handle_function(section, c, gtkmethod=f) 1576 1577 def _method_get_type(self): 1578 """Generate the Get_Type subprogram""" 1579 1580 n = self.node.get(ggettype) 1581 if n is not None: 1582 section = self.pkg.section("Constructors") 1583 1584 gtkmethod = self.gtkpkg.get_method(cname=n) 1585 if not gtkmethod.bind(): 1586 return 1587 1588 self.pkg.add_with("Glib") 1589 get_type_name = gtkmethod.ada_name() or "Get_Type" 1590 section.add( 1591 Subprogram( 1592 name=get_type_name, 1593 returns=AdaType("Glib.GType", pkg=self.pkg, in_spec=True)) 1594 .import_c(n)) 1595 1596 if not self.gtktype.is_subtype() \ 1597 and not self.is_interface \ 1598 and self.is_gobject \ 1599 and self._subst["parent"] is not None: 1600 1601 self.pkg.add_with("Glib.Type_Conversion_Hooks", specs=False) 1602 1603 self._subst["get_type"] = get_type_name 1604 1605 section.add( 1606 ("package Type_Conversion_%(typename)s is new" 1607 + " Glib.Type_Conversion_Hooks.Hook_Registrator\n" 1608 + " (%(get_type)s'Access, %(typename)s_Record);\n" 1609 + "pragma Unreferenced (Type_Conversion_%(typename)s);""") 1610 % self._subst, in_spec=False) 1611 1612 def _get_c_type(self, node): 1613 t = node.find(ntype) 1614 if t is not None: 1615 return t.get(ctype_qname) 1616 return None 1617 1618 def _fields(self): 1619 fields = self.node.findall(nfield) 1620 if fields: 1621 section = self.pkg.section("Fields") 1622 for f in fields: 1623 name = f.get("name") 1624 1625 # Getter 1626 1627 if f.get("readable", "1") != "0": 1628 cname = "gtkada_%(cname)s_get_%(name)s" % { 1629 "cname": self._subst["cname"], "name": name} 1630 gtkmethod = self.gtkpkg.get_method(cname=cname) 1631 if gtkmethod.bind(default="false"): 1632 profile = SubprogramProfile.parse( 1633 node=f, gtkmethod=gtkmethod, pkg=self.pkg) 1634 func = self._handle_function_internal( 1635 section, 1636 node=f, 1637 cname=cname, 1638 adaname="Get_%s" % name, 1639 ismethod=True, 1640 profile=profile, 1641 gtkmethod=gtkmethod) 1642 1643 if func is not None: 1644 ctype = self._get_c_type(f) 1645 if ctype is None: 1646 continue 1647 1648 self.gir.ccode += """ 1649%(ctype)s %(cname)s (%(self)s* self) { 1650 return self->%(name)s; 1651} 1652""" % {"ctype": ctype, "cname": cname, "self": self.ctype, "name": name} 1653 1654 # Setter 1655 1656 if f.get("writable", "1") != "0": 1657 cname = "gtkada_%(cname)s_set_%(name)s" % { 1658 "cname": self._subst["cname"], "name": name} 1659 gtkmethod = self.gtkpkg.get_method(cname=cname) 1660 if gtkmethod.bind("false"): 1661 profile = SubprogramProfile.setter( 1662 node=f, pkg=self.pkg) 1663 func = self._handle_function_internal( 1664 section, 1665 node=f, 1666 cname=cname, 1667 adaname="Set_%s" % name, 1668 ismethod=True, 1669 gtkmethod=gtkmethod, 1670 profile=profile) 1671 1672 if func is not None: 1673 ctype = self._get_c_type(f) 1674 if ctype is None: 1675 continue 1676 1677 self.gir.ccode += """ 1678void %(cname)s (%(self)s* self, %(ctype)s val) { 1679 self->%(name)s = val; 1680} 1681""" % {"ctype": ctype, "cname": cname, "self": self.ctype, "name": name} 1682 1683 def _properties(self): 1684 n = QName(uri, "property") 1685 1686 props = list(self.node.findall(n.text)) 1687 if props is not None: 1688 adaprops = [] 1689 for p in props: 1690 flags = [] 1691 if p.get("readable", "1") != "0": 1692 flags.append("read") 1693 if p.get("writable", "1") != "0": 1694 flags.append("write") 1695 1696 # Do not provide a "pkg=self.pkg" parameter, since we do 1697 # not want to generate a with for the actual property type 1698 # (for instance a Gtk_Cell_Area), just for the actual type 1699 # (Property_Object). 1700 1701 tp = _get_type(p) 1702 tp.userecord = False 1703 ptype = tp.as_property() 1704 if ptype: 1705 pkg = ptype[:ptype.rfind(".")] 1706 if pkg: 1707 self.pkg.add_with(pkg) 1708 else: 1709 section = self.pkg.section("Properties") 1710 section.add( 1711 (' %(name)s_Property : constant ' 1712 + 'Glib.Properties.Property_String :=\n' 1713 + ' Glib.Properties.Build ("%(cname)s");' 1714 + ' -- Unknown type: %(type)s') % { 1715 "name": naming.case(p.get("name")), 1716 "type": (p.find(ntype).get("name") 1717 if p.find(ntype) is not None 1718 else "unspecified"), 1719 "cname": p.get("name")}) 1720 self.pkg.add_with("Glib.Properties") 1721 continue 1722 1723 adaprops.append({ 1724 "cname": p.get("name"), 1725 "name": naming.case(p.get("name")), 1726 "flags": "-".join(flags), 1727 "doc": _get_clean_doc(p), 1728 "pkg": pkg, 1729 "ptype": ptype, 1730 "type": tp.as_ada_param(self.pkg)}) 1731 1732 if adaprops: 1733 section = self.pkg.section("Properties") 1734 section.add_comment( 1735 """The following properties are defined for this widget. 1736See Glib.Properties for more information on properties)""") 1737 1738 adaprops.sort(lambda x, y: cmp(x["name"], y["name"])) 1739 1740 for p in adaprops: 1741 prop_str = ' %(name)s_Property : constant %(ptype)s;' % p 1742 if not section.add(prop_str): 1743 continue 1744 1745 # Only display the type if it isn't obvious from the actual 1746 # type of the property. 1747 if p["type"] not in ("Boolean", "UTF8_String", "Gfloat", 1748 "Gint", "Guint") \ 1749 and not p["type"].startswith("Gtk.Enums."): 1750 section.add( 1751 Code("Type: %(type)s" % p, iscomment=True)) 1752 1753 if p["flags"] != "read-write": 1754 section.add( 1755 Code("Flags: %(flags)s" % p, iscomment=True)) 1756 if p["doc"]: 1757 section.add(Code("%s" % p["doc"], iscomment=True)) 1758 1759 d = ' %(name)s_Property : constant %(ptype)s' % p 1760 self.pkg.add_private( 1761 d + ' :=\n %(pkg)s.Build ("%(cname)s");' % p) 1762 1763 def _compute_marshaller_suffix(self, selftype, profile): 1764 """Computes the suffix for the connect and marshallers types based on 1765 the profile of the signal. 1766 """ 1767 return "_".join( 1768 [base_name(selftype.ada)] 1769 + [base_name(p.type.ada) for p in profile.params] 1770 + [(base_name(profile.returns.ada) 1771 if profile.returns else "Void")]) 1772 1773 def _marshall_gvalue(self, profile): 1774 """Return the arguments to parse to an Ada callback, after extracting 1775 them from a GValue. Returns a list of local variables for the 1776 marshaller, and its body 1777 """ 1778 call_params = [] 1779 for index, p in enumerate(profile.params): 1780 if isinstance(p.type, Tagged): 1781 call_params.append( 1782 "%s.From_Object (Unchecked_To_Address (Params, %d))" % 1783 (package_name(p.type.ada), index + 1)) 1784 elif isinstance(p.type, Interface): 1785 call_params.append( 1786 "%s (Unchecked_To_Interface (Params, %d))" % 1787 (p.type.ada, index + 1)) 1788 elif isinstance(p.type, GObject): 1789 if p.type.ada != "Glib.Object.GObject": 1790 call_params.append( 1791 "%s (Unchecked_To_Object (Params, %d))" % ( 1792 p.type.ada, index + 1)) 1793 else: 1794 call_params.append( 1795 "Unchecked_To_Object (Params, %d)" % (index + 1, )) 1796 else: 1797 if p.mode != "in": 1798 call_params.append( 1799 "Unchecked_To_%s_Access (Params, %d)" % ( 1800 base_name(p.type.ada), index + 1)) 1801 else: 1802 call_params.append( 1803 "Unchecked_To_%s (Params, %d)" % ( 1804 base_name(p.type.ada), index + 1)) 1805 1806 if call_params: 1807 call = "H (Obj, %s)" % ", ".join(call_params) 1808 else: 1809 call = "H (Obj)" 1810 1811 if profile.returns: 1812 marsh_local = [ 1813 Local_Var("V", profile.returns, aliased=True, default=call)] 1814 marsh_body = "Set_Value (Return_Value, V'Address);" 1815 else: 1816 marsh_local = [] 1817 marsh_body = "%s;" % call 1818 1819 marsh_body += "exception when E : others => Process_Exception (E);" 1820 1821 return marsh_local, marsh_body 1822 1823 def _generate_slot_marshaller(self, section, selftype, node, gtkmethod): 1824 """Generate connect+marshaller when connect takes a slot object. These 1825 procedure are independent of the specific widget, and can be shared. 1826 Returns the name for the hander type. 1827 """ 1828 1829 if SHARED_SLOT_MARSHALLERS: 1830 pkg = gir.slot_marshaller_pkg 1831 section = gir.slot_marshaller_section 1832 existing_marshallers = gir.slot_marshallers 1833 else: 1834 pkg = self.pkg 1835 section = section 1836 existing_marshallers = self.__marshallers 1837 1838 profile = SubprogramProfile.parse( 1839 node=node, gtkmethod=gtkmethod, pkg=pkg) 1840 1841 callback_selftype = GObject( 1842 "Glib.Object.GObject", classwide=True, allow_none=True) 1843 1844 name_suffix = self._compute_marshaller_suffix( 1845 callback_selftype, profile) 1846 slot_name = "Cb_%s" % name_suffix 1847 marshname = "Marsh_%s" % name_suffix 1848 1849 callback = Subprogram( 1850 name="", 1851 plist=[Parameter(name="Self", type=callback_selftype)] 1852 + profile.params, 1853 code="null", 1854 allow_none=False, 1855 returns=profile.returns) 1856 1857 if slot_name not in existing_marshallers: 1858 existing_marshallers.add(slot_name) 1859 1860 slot_handler_type = "type %s is %s;" % ( 1861 slot_name, callback.profile( 1862 pkg=pkg, 1863 maxlen=69, indent=" ")) 1864 section.add(Code(slot_handler_type), in_spec=True) 1865 1866 section.add(Code( 1867 """function Cb_To_Address is new Ada.Unchecked_Conversion 1868 (%s, System.Address); 1869function Address_To_Cb is new Ada.Unchecked_Conversion 1870 (System.Address, %s); 1871""" % (slot_name, slot_name)), 1872 in_spec=False) 1873 1874 if isinstance(selftype, Interface): 1875 obj_in_body = "Glib.Types.GType_Interface (Object)" 1876 else: 1877 obj_in_body = "Object" 1878 1879 connect_slot_body = """ 1880 Unchecked_Do_Signal_Connect 1881 (Object => %s, 1882 C_Name => C_Name, 1883 Marshaller => %s'Access, 1884 Handler => Cb_To_Address (Handler), -- Set in the closure 1885 Slot_Object => Slot, 1886 After => After)""" % (obj_in_body, marshname) 1887 1888 marsh_local, marsh_body = self._marshall_gvalue(profile) 1889 1890 connect_slot = Subprogram( 1891 name="Connect_Slot", 1892 plist=[Parameter("Object", selftype), 1893 Parameter("C_Name", "Glib.Signal_Name"), 1894 Parameter("Handler", slot_name), 1895 Parameter("After", "Boolean"), 1896 Parameter("Slot", GObject( 1897 "Glib.Object.GObject", allow_none=True, 1898 classwide=True), default="null") 1899 ], 1900 code=connect_slot_body) 1901 section.add(connect_slot, in_spec=False) 1902 1903 addr_to_obj = "Glib.Object.Convert (Get_Data (Closure))" 1904 1905 marsh = Subprogram( 1906 name=marshname, 1907 plist=[Parameter("Closure", "GClosure"), 1908 Parameter("Return_Value", "Glib.Values.GValue"), 1909 Parameter("N_Params", "Glib.Guint"), 1910 Parameter("Params", "Glib.Values.C_GValues"), 1911 Parameter("Invocation_Hint", "System.Address"), 1912 Parameter("User_Data", "System.Address")], 1913 local_vars=[ 1914 Local_Var("H", "constant %s" % slot_name, 1915 "Address_To_Cb (Get_Callback (Closure))"), 1916 Local_Var("Obj", "Glib.Object.GObject", constant=True, 1917 default=addr_to_obj) 1918 ] + marsh_local, 1919 convention="C", 1920 code=marsh_body) 1921 section.add(marsh, in_spec=False) 1922 1923 return slot_name, callback 1924 1925 def _generate_marshaller(self, section, selftype, node, gtkmethod): 1926 """Generate, if needed, a connect+marshaller for signals with this 1927 profile. 1928 Returns the name of the type that contains the subprogram profile 1929 """ 1930 1931 profile = SubprogramProfile.parse( 1932 node=node, gtkmethod=gtkmethod, 1933 pkg=self.pkg if gtkmethod.bind() else None) 1934 1935 name_suffix = self._compute_marshaller_suffix(selftype, profile) 1936 marshname = "Marsh_%s" % name_suffix 1937 name = "Cb_%s" % name_suffix 1938 1939 callback = Subprogram( 1940 name="", 1941 plist=[Parameter(name="Self", type=selftype)] + profile.params, 1942 code="null", 1943 allow_none=False, 1944 returns=profile.returns) 1945 1946 if gtkmethod.bind() and name not in self.__marshallers: 1947 self.__marshallers.add(name) 1948 1949 handler_type = "type %s is %s;" % ( 1950 name, callback.profile( 1951 pkg=self.pkg, maxlen=69, indent=" ")) 1952 section.add(Code(handler_type), in_spec=True) 1953 1954 section.add(Code( 1955 """function Cb_To_Address is new Ada.Unchecked_Conversion 1956 (%s, System.Address); 1957function Address_To_Cb is new Ada.Unchecked_Conversion 1958 (System.Address, %s); 1959""" % (name, name)), 1960 in_spec=False) 1961 1962 if isinstance(selftype, Interface): 1963 obj_in_body = "Glib.Types.GType_Interface (Object)" 1964 else: 1965 obj_in_body = "Object" 1966 1967 connect_body = """ 1968 Unchecked_Do_Signal_Connect 1969 (Object => %s, 1970 C_Name => C_Name, 1971 Marshaller => %s'Access, 1972 Handler => Cb_To_Address (Handler), -- Set in the closure 1973 After => After)""" % (obj_in_body, marshname) 1974 1975 marsh_local, marsh_body = self._marshall_gvalue(profile) 1976 1977 connect = Subprogram( 1978 name="Connect", 1979 plist=[Parameter("Object", selftype), 1980 Parameter("C_Name", "Glib.Signal_Name"), 1981 Parameter("Handler", name), 1982 Parameter("After", "Boolean"), 1983 ], 1984 code=connect_body) 1985 section.add(connect, in_spec=False) 1986 1987 if isinstance(selftype, Interface): 1988 addr_to_obj = \ 1989 "%s (Unchecked_To_Interface (Params, 0))" % selftype.ada 1990 else: 1991 addr_to_obj = \ 1992 "%s (Unchecked_To_Object (Params, 0))" % selftype.ada 1993 1994 marsh = Subprogram( 1995 name=marshname, 1996 plist=[Parameter("Closure", "GClosure"), 1997 Parameter("Return_Value", "Glib.Values.GValue"), 1998 Parameter("N_Params", "Glib.Guint"), 1999 Parameter("Params", "Glib.Values.C_GValues"), 2000 Parameter("Invocation_Hint", "System.Address"), 2001 Parameter("User_Data", "System.Address")], 2002 local_vars=[ 2003 Local_Var("H", "constant %s" % name, 2004 "Address_To_Cb (Get_Callback (Closure))"), 2005 Local_Var("Obj", selftype.ada, constant=True, 2006 default=addr_to_obj) 2007 ] + marsh_local, 2008 convention="C", 2009 code=marsh_body) 2010 section.add(marsh, in_spec=False) 2011 2012 return name, callback, profile 2013 2014 def _signals(self): 2015 signals = list(self.node.findall(gsignal)) 2016 if signals: 2017 adasignals = [] 2018 section = self.pkg.section("Signals") 2019 section.sort_objects = False # preserve insertion order 2020 2021 # If at least one signal gets a On_* procedure 2022 for s in signals: 2023 if self.gtkpkg.get_method( 2024 cname="::%s" % s.get("name")).bind(): 2025 section.add( 2026 Code("use type System.Address;"), in_spec=False) 2027 self.pkg.add_with("Gtkada.Bindings", specs=False) 2028 self.pkg.add_with("Glib.Values", specs=False) 2029 self.pkg.add_with("Gtk.Arguments", specs=False) 2030 2031 if SHARED_SLOT_MARSHALLERS: 2032 self.pkg.add_with("Gtkada.Marshallers") 2033 self.pkg.add_with( 2034 "Ada.Unchecked_Conversion", specs=False, do_use=False) 2035 break 2036 2037 signals.sort(key=lambda x: x.get("name")) 2038 2039 for s in signals: 2040 gtkmethod = self.gtkpkg.get_method( 2041 cname="::%s" % (s.get("name"))) 2042 bind = gtkmethod.bind() 2043 2044 name = s.get("name") 2045 2046 if self.is_gobject: 2047 selftype = GObject("%(typename)s" % self._subst, 2048 allow_none=True, classwide=True) 2049 on_selftype = GObject("%(typename)s" % self._subst, 2050 allow_none=False, classwide=False) 2051 elif self.is_interface: 2052 on_selftype = selftype = Interface( 2053 "%(typename)s" % self._subst) 2054 else: 2055 on_selftype = selftype = Proxy( 2056 "%(typename)s" % self._subst) 2057 2058 # We need to parse the profile twice, so that the with 2059 # statements are set both in self.pkg and in 2060 # gtkada.marshallers 2061 handler_type_name, sub, profile = \ 2062 self._generate_marshaller( 2063 section, selftype, node=s, gtkmethod=gtkmethod) 2064 2065 if bind: 2066 slot_handler_type_name, obj_sub = \ 2067 self._generate_slot_marshaller( 2068 section, selftype, node=s, gtkmethod=gtkmethod) 2069 2070 section.add( 2071 Code(' Signal_%s : constant Glib.Signal_Name := "%s";' % 2072 (naming.case(name, protect=False), name)), 2073 add_newline=False) 2074 2075 if bind: 2076 connect = Subprogram( 2077 name="On_%s" % naming.case(name, protect=False), 2078 plist=[Parameter(name="Self", type=on_selftype), 2079 Parameter( 2080 name="Call", 2081 type=Proxy(handler_type_name)), 2082 Parameter( 2083 name="After", 2084 type="Boolean", 2085 default="False")], 2086 code='Connect (Self, "%s" & ASCII.NUL, Call, After);' % 2087 name) 2088 section.add(connect, add_newline=False) 2089 2090 self.pkg.add_with("Glib.Object") 2091 obj_connect = Subprogram( 2092 name="On_%s" % naming.case(name, protect=False), 2093 plist=[Parameter(name="Self", type=on_selftype), 2094 Parameter( 2095 name="Call", 2096 type=Proxy(slot_handler_type_name)), 2097 Parameter( 2098 name="Slot", 2099 type=GObject("Glib.Object.GObject", 2100 allow_none=False, 2101 classwide=True)), 2102 Parameter( 2103 name="After", 2104 type="Boolean", 2105 default="False")], 2106 code=('Connect_Slot (Self, "%s" & ASCII.NUL,' 2107 + ' Call, After, Slot);') % name) 2108 section.add(obj_connect) 2109 2110 doc = _get_clean_doc(s) 2111 if doc: 2112 section.add(Code(" %s""" % doc, iscomment=True)) 2113 2114 if not bind: 2115 sub.name = "Handler" 2116 section.add( 2117 Code( 2118 sub.profile(pkg=self.pkg, maxlen=69), 2119 fill=False, iscomment=True)) 2120 2121 if profile.returns_doc or len(profile.params) > 1: 2122 doc = "\n Callback parameters:" + sub.formatted_doc() 2123 if profile.returns_doc: 2124 doc += "\n -- %s" % profile.returns_doc 2125 section.add(Code(doc, fill=False, iscomment=True)) 2126 2127 def _implements(self): 2128 """Bind the interfaces that a class implements""" 2129 2130 implements = list(self.node.findall(nimplements)) or [] 2131 2132 for impl in implements: 2133 name = impl.get("name") 2134 2135 # Special case, because the GIR file are inconsistent 2136 if name == "Gio.Icon": 2137 name = "Icon" 2138 2139 # If the interface is purposefully not bound 2140 if "--%s" % name in interfaces: 2141 continue 2142 2143 try: 2144 intf = self.gir.interfaces[name] 2145 except KeyError: 2146 intf = self.gir.interfaces[naming.girname_to_ctype[name]] 2147 2148 type = naming.type(intf.ctype) 2149 if "." in type.ada: 2150 self.pkg.add_with(type.ada[:type.ada.rfind(".")]) 2151 self.pkg.add_with("Glib.Types") 2152 2153 impl = dict( 2154 name=name, 2155 adatype=base_name(type.ada), 2156 impl=type.ada, 2157 interface=intf, 2158 body="", 2159 pkg="%(typename)s" % self._subst) 2160 impl["code"] = \ 2161 """package Implements_%(adatype)s is new Glib.Types.Implements 2162 (%(impl)s, %(pkg)s_Record, %(pkg)s); 2163 function "+" 2164 (Widget : access %(pkg)s_Record'Class) 2165 return %(impl)s 2166 renames Implements_%(adatype)s.To_Interface; 2167 function "-" 2168 (Interf : %(impl)s) 2169 return %(pkg)s 2170 renames Implements_%(adatype)s.To_Object; 2171""" % impl 2172 2173 self.implements[name] = impl 2174 2175 # For an interface, we also define "+" to cast to itself. This is used 2176 # when writting custom bodies for the methods of the interface, so that 2177 # those bodies can be reused for the types that implement the 2178 # interface. See GtkTreeModel. 2179 2180 if self.is_interface: 2181 self.implements[""] = { 2182 "name": self._subst["typename"], 2183 "interface": None, 2184 "code": """function "+" (W : %(typename)s) return %(typename)s; 2185 pragma Inline ("+"); """ % self._subst, 2186 "body": """function "+" (W : %(typename)s) return %(typename)s is 2187begin 2188 return W; 2189end "+";""" % self._subst, 2190 } 2191 2192 if self.implements: 2193 2194 # Duplicate the subprograms from the interfaces. This doesn't 2195 # quite work: for instance, Gtk.About_Dialog already has a 2196 # Get_Name, so we can't redefine the one inherited from Buildable. 2197 section = self.pkg.section( 2198 "Inherited subprograms (from interfaces)") 2199 2200 for impl in sorted(self.implements.iterkeys()): 2201 impl = self.implements[impl] 2202 if impl["name"] == "Buildable": 2203 # Do not repeat for buildable, that's rarely used 2204 2205 section.add_comment( 2206 "Methods inherited from the Buildable interface are" 2207 + " not duplicated here since they are meant to be" 2208 + " used by tools, mostly. If you need to call them," 2209 + ' use an explicit cast through the "-" operator' 2210 + " below.") 2211 2212 continue 2213 2214 interf = impl["interface"] 2215 2216 # Ignore interfaces that we haven't bound 2217 if interf is not None and not hasattr(interf, "gtkpkg"): 2218 print "%s: methods for interface %s were not bound" % ( 2219 self.name, impl["name"]) 2220 elif interf is not None: 2221 all = interf.node.findall(nmethod) 2222 for c in all: 2223 cname = c.get(cidentifier) 2224 gtkmethod = interf.gtkpkg.get_method(cname) 2225 interfmethod = self.gtkpkg.get_method(cname) 2226 2227 if interfmethod.bind(): 2228 self._handle_function( 2229 section, c, showdoc=False, gtkmethod=gtkmethod, 2230 ismethod=True, isinherited=True) 2231 2232 section = self.pkg.section("Interfaces") 2233 section.add_comment( 2234 "This class implements several interfaces. See Glib.Types") 2235 2236 for impl in sorted(self.implements.iterkeys()): 2237 impl = self.implements[impl] 2238 section.add_comment("") 2239 section.add_comment('- "%(name)s"' % impl) 2240 section.add(impl["code"]) 2241 if impl["body"]: 2242 section.add(impl["body"], in_spec=False) 2243 2244 def add_list_binding(self, section, adaname, ctype, singleList): 2245 """Generate a list instance""" 2246 2247 conv = "%s->Address" % ctype.ada 2248 decl = "" 2249 body = "" 2250 2251 if conv not in self.conversions: 2252 self.conversions[conv] = True 2253 2254 base = "function Convert (R : %s) return System.Address" % ( 2255 ctype.ada) 2256 2257 decl += base + ';\n' 2258 body += base + " is\nbegin\n" 2259 2260 if isinstance(ctype, Proxy): 2261 body += "return Glib.To_Address (Glib.C_Proxy (R));" 2262 else: 2263 body += "return Get_Object (R);" 2264 2265 body += "\nend Convert;\n\n" 2266 2267 conv = "Address->%s" % ctype.ada 2268 if conv not in self.conversions: 2269 self.conversions[conv] = True 2270 2271 decl += "function Convert (R : System.Address) return %s;\n" % ( 2272 ctype.ada) 2273 body += "function Convert (R : System.Address) return %s is\n" % ( 2274 ctype.ada) 2275 2276 if isinstance(ctype, Proxy): 2277 body += "begin\nreturn %s" % ctype.ada \ 2278 + "(Glib.C_Proxy'(Glib.To_Proxy (R)));" 2279 2280 elif isinstance(ctype, Tagged): 2281 # Not a GObject ? 2282 body += "begin\nreturn From_Object(R);" 2283 2284 else: 2285 body += "Stub : %s_Record;" % ctype.ada 2286 body += "begin\n" 2287 body += "return %s (Glib.Object.Get_User_Data (R, Stub));" % ( 2288 ctype.ada) 2289 2290 body += "\nend Convert;" 2291 2292 if singleList: 2293 pkg = "GSlist" 2294 generic = "Generic_SList" 2295 else: 2296 pkg = "Glist" 2297 generic = "Generic_List" 2298 2299 self.pkg.add_with("Glib.%s" % pkg) 2300 2301 decl += "package %s is new %s (%s);\n" % (adaname, generic, ctype.ada) 2302 section.add(decl) 2303 section.add(body, in_spec=False) 2304 2305 def record_binding( 2306 self, section, ctype, adaname, type, override_fields, 2307 unions, private): 2308 """Create the binding for a <record> or <union> type. 2309 override_fields has the same format as returned by 2310 GtkAdaPackage.records() 2311 """ 2312 base = adaname or base_name(type.ada) 2313 2314 try: 2315 node = gir.records[ctype] 2316 except KeyError: 2317 # The package doesn't contain a type (for instance GtkMain) 2318 return 2319 2320 gir.bound.add(ctype) 2321 2322 is_union = node.tag == nunion 2323 first_field_ctype = None 2324 2325 fields = [] # array of (name,type,default) tuples 2326 2327 # Check if we have forced the mapping as a C proxy ? 2328 2329 if (naming.type_exceptions.get(ctype, None) is None 2330 or not isinstance(naming.type_exceptions[ctype], Proxy)): 2331 2332 for field in node.findall(nfield): 2333 name = field.get("name") 2334 2335 ftype = None 2336 type = _get_type(field) 2337 cb = field.findall(ncallback) 2338 2339 if type: 2340 ftype = override_fields.get(name, None) 2341 if ftype is None: 2342 2343 if not first_field_ctype: 2344 t = field.findall(ntype) 2345 assert t, "No type info for %s.%s" % (ctype, name) 2346 2347 ctype = t[0].get(ctype_qname) 2348 if not ctype: 2349 # <type name="..."> has no c:type attribute, 2350 # so we try to map the name to a Girname 2351 ctype = naming.girname_to_ctype[ 2352 t[0].get("name")] 2353 2354 first_field_ctype = ctype 2355 2356 ftype = type 2357 2358 elif cb: 2359 # ??? JL: Should properly bind the callback here. 2360 # For now, we just use a System.Address to maintain the 2361 # record integrity 2362 ftype = override_fields.get(name, None) 2363 if ftype is None: 2364 ftype = AdaType( 2365 "System.Address", pkg=self.pkg) 2366 2367 else: 2368 print "WARNING: Field '%s.%s' has no type" % (name, base) 2369 print " generated record is most certainly incorrect" 2370 2371 if ftype is not None: 2372 if ftype.ada in ("GSList", "GList") and private: 2373 ftype = "System.Address" 2374 default_value = "System.Null_Address" 2375 else: 2376 default_value = ftype.default_record_field_value 2377 ftype = ftype.record_field_type(pkg=self.pkg) 2378 2379 self.pkg.add_with(package_name(ftype)) 2380 fields.append((naming.case(name), ftype, default_value)) 2381 2382 if not fields: 2383 section.add( 2384 ("\ntype %(typename)s is new Glib.C_Proxy;\n" 2385 + "function From_Object_Free (B : access %(typename)s) " 2386 + "return %(typename)s;\npragma Inline (From_Object_Free);") 2387 % {"typename": base}) 2388 section.add(""" 2389function From_Object_Free (B : access %(typename)s) return %(typename)s is 2390 Result : constant %(typename)s := B.all; 2391begin 2392 Glib.g_free (B.all'Address); 2393 return Result; 2394end From_Object_Free;""" % {"typename": base}, in_spec=False) 2395 2396 else: 2397 if private: 2398 section.add( 2399 ("\ntype %(typename)s is private;\n" 2400 + "function From_Object_Free (B : access %(typename)s)" 2401 + " return %(typename)s;\n" 2402 + "pragma Inline (From_Object_Free);") 2403 % {"typename": base}) 2404 adder = self.pkg.add_private 2405 else: 2406 adder = section.add 2407 2408 if is_union: 2409 enums = self.get_enumeration_values(first_field_ctype) 2410 enums_dict = {ctype: adatype for ctype, adatype in enums} 2411 text = "\ntype %s (%s : %s := %s) is record\n" % ( 2412 base, fields[0][0], fields[0][1], 2413 enums[0][1]) + \ 2414 " case %s is\n" % fields[0][0] 2415 for index, f in enumerate(fields): 2416 if index != 0: 2417 when_stmt = [] 2418 if unions: 2419 for v, key in unions: 2420 # applies to field 2421 if key.lower() == f[0].lower(): 2422 when_stmt.append(enums_dict[v]) 2423 else: 2424 when_stmt = [enums[index][1]] 2425 2426 if not when_stmt: 2427 print("ERROR: no discrimant value for field %s" 2428 % f[0]) 2429 2430 text += "\n when %s =>\n %s : %s;\n" % ( 2431 "\n | ".join(when_stmt), f[0], f[1]) 2432 2433 text += " end case;\nend record;\n" 2434 text += "pragma Convention (C, %s);\n" % base 2435 text += "pragma Unchecked_Union(%s);\n" % base 2436 adder("\n" + Code(text).format()) 2437 2438 else: 2439 c = [] 2440 for f in fields: 2441 if f[2]: 2442 c.append('%s : %s := %s;' % (f[0], f[1], f[2])) 2443 else: 2444 c.append('%s : %s;' % (f[0], f[1])) 2445 2446 c = Code('\ntype %s is record\n' % base 2447 + '\n'.join(c) 2448 + '\nend record;\npragma Convention (C, %s);\n' % base) 2449 adder(c.format()) 2450 2451 if not private: 2452 section.add( 2453 ("\nfunction From_Object_Free (B : access %(type)s)" 2454 + " return %(type)s;\n" 2455 + "pragma Inline (From_Object_Free);") % {"type": base}) 2456 2457 section.add(""" 2458function From_Object_Free (B : access %(typename)s) return %(typename)s is 2459 Result : constant %(typename)s := B.all; 2460begin 2461 Glib.g_free (B.all'Address); 2462 return Result; 2463end From_Object_Free;""" % {"typename": base}, in_spec=False) 2464 2465 section.add(Code(_get_clean_doc(node), iscomment=True)) 2466 2467 def get_enumeration_values(sef, enum_ctype): 2468 """Return the list of enumeration values for the given enum, as a list 2469 of tuples (C identifier, ada identifier)""" 2470 2471 node = gir.enums[enum_ctype] 2472 return [(m.get(cidentifier), naming.adamethod_name(m.get(cidentifier))) 2473 for m in node.findall(nmember)] 2474 2475 def constants_binding(self, section, regexp, prefix): 2476 constants = [] 2477 r = re.compile(regexp) 2478 2479 for name, node in gir.constants.iteritems(): 2480 if r.match(name): 2481 name = name.replace(prefix, "").title() 2482 2483 gir.bound.add(node.get(ctype_qname)) 2484 2485 type = node.findall(ntype) 2486 ctype = type[0].get(ctype_qname) 2487 ftype = naming.type(name="", cname=ctype) 2488 2489 constants.append( 2490 '%s : constant %s := "%s";' % 2491 (name, ftype.ada, node.get("value"))) 2492 2493 constants.sort() 2494 section.add("\n".join(constants)) 2495 2496 def enumeration_binding(self, section, ctype, type, prefix, 2497 asbitfield=False, ignore=""): 2498 """Add to the section the Ada type definition for the <enumeration> 2499 ctype. type is the corresponding instance of CType(). 2500 This function also handles <bitfield> types. 2501 2502 :param prefix: is removed from the values to get the default Ada name, 2503 which can be overridden in data.cname_to_adaname. 2504 :param ignore: space-separated list of values that should not be 2505 bound. 2506 """ 2507 base = base_name(type.ada) 2508 node = gir.enums[ctype] 2509 2510 current = 0 2511 is_default_representation = True 2512 2513 gir.bound.add(ctype) 2514 2515 members = [] 2516 ignore = set(ignore.split()) 2517 2518 for member in node.findall(nmember): 2519 cname = member.get(cidentifier) 2520 2521 if cname in ignore: 2522 continue 2523 2524 m = naming.adamethod_name(cname, warning_if_not_found=False) 2525 if m is None: 2526 continue 2527 2528 if cname == m: 2529 # No special case ? Attempt a simple rule (remove leading 2530 # Gtk prefix, and capitalize the value) 2531 m = cname.replace(prefix, "").title() 2532 2533 else: 2534 m = base_name(m) 2535 2536 # For proper substitution in docs 2537 naming.add_cmethod( 2538 cname=cname, 2539 adaname="%s.%s" % (self.name, m)) 2540 2541 value = int(member.get("value")) 2542 if value != current: 2543 is_default_representation = False 2544 current += 1 2545 2546 members.append((m, value)) 2547 2548 decl = "" 2549 2550 if node.tag == nenumeration and not asbitfield: 2551 section.add( 2552 "type %s is " % base 2553 + "(\n" + ",\n".join(m[0] 2554 for m in sorted(members, key=lambda m: m[1])) 2555 + ");\n" 2556 + "pragma Convention (C, %s);\n" % base) 2557 section.add(Code(_get_clean_doc(node), iscomment=True)) 2558 2559 if not is_default_representation: 2560 repr = (" for %s use (\n" % base 2561 + ",\n".join(" %s => %s" % m 2562 for m in sorted(members, key=lambda m: m[1])) 2563 + ");\n") 2564 section.add(repr) 2565 2566 elif node.tag == nbitfield or asbitfield: 2567 section.add( 2568 "\ntype %s is " % base 2569 + "mod 2 ** Integer'Size;\n" 2570 + "pragma Convention (C, %s);\n" % base) 2571 section.add(Code(_get_clean_doc(node), iscomment=True)) 2572 2573 for m, value in members: 2574 decl += "%s : constant %s := %s;\n" % (m, base, value) 2575 section.add(decl) 2576 2577 section.pkg.section("Enumeration Properties").add( 2578 "package %s_Properties is\n" % base 2579 + " new Generic_Internal_Discrete_Property (%s);\n" % base 2580 + "type Property_%s is new %s_Properties.Property;\n\n" % ( 2581 base, base)) 2582 2583 self.pkg.add_with("Glib.Generic_Properties") 2584 2585 def generate(self, gir): 2586 if self._generated: 2587 return 2588 2589 extra = self.gtkpkg.extra() 2590 if extra: 2591 self.node.extend(extra) 2592 2593 # The parent is unfortunately specified as a GIR name. But that creates 2594 # ambiguities when loading both Gtk and Gdk, which for instance both 2595 # define "Window". So we first look in the same file as the current 2596 # Class. 2597 2598 parent = gir._get_class_node( 2599 self.rootNode, 2600 girname=self.gtkpkg.parent_type() or self.node.get("parent")) 2601 parent = naming.type( 2602 name=self.gtkpkg.parent_type() or self.node.get( 2603 "parent"), # GIRName 2604 cname=parent and parent.get(ctype_qname)).ada 2605 2606 if parent and parent.rfind(".") != -1: 2607 self._subst["parent_pkg"] = package_name(parent) 2608 self._subst["parent"] = base_name(parent) 2609 else: 2610 self._subst["parent_pkg"] = None 2611 self._subst["parent"] = parent 2612 2613 self._generated = True 2614 2615 girdoc = _get_clean_doc(self.node) 2616 2617 into = self.gtkpkg.into() 2618 if into: 2619 # Make sure we have already generated the other package, so that 2620 # its types go first. 2621 klass = gir.classes.get(into, None) or gir.ctype_interfaces[into] 2622 klass.generate(gir) 2623 into = klass.name # from now on, we want the Ada name 2624 2625 # Do not integrate the documentation from the other package, it 2626 # is likely useless anyway 2627 2628 girdoc = "" 2629 2630 # Override the type exception. For instance, from now on we 2631 # want to use "Gtk.Box.Gtk_HBox" rather than "Gtk.HBox.Gtk_HBox" 2632 # which doesn't exist 2633 typename = "%s.%s" % (into, self._subst["typename"]) 2634 2635 # retrieve the old type 2636 oldtype = naming.type(cname=self.ctype) 2637 newtype = None 2638 # and create the new one accordingly 2639 if isinstance(oldtype, Tagged): 2640 newtype = Tagged(typename) 2641 elif isinstance(oldtype, GObject): 2642 newtype = GObject(typename) 2643 elif isinstance(oldtype, Proxy): 2644 newtype = Proxy(typename) 2645 elif isinstance(oldtype, Record): 2646 newtype = Record(typename) 2647 else: 2648 raise Exception("Can't override %s for a package with 'into'" 2649 % oldtype) 2650 naming.add_type_exception( 2651 override=True, 2652 cname=self.ctype, 2653 type=newtype) 2654 2655 self.pkg = gir.get_package(into or self.ada_package_name, 2656 ctype=self.ctype, 2657 doc=girdoc) 2658 2659 if self._subst["parent_pkg"]: 2660 self.pkg.add_with("%(parent_pkg)s" % self._subst) 2661 2662 self.gtktype = self.gtkpkg.get_type(self._subst["typename"]) 2663 2664 section = self.pkg.section("") 2665 2666 if self.gtkpkg.is_obsolete(): 2667 section.add("pragma Obsolescent;") 2668 2669 if not self.has_toplevel_type: 2670 pass 2671 2672 elif self.is_interface: 2673 self.pkg.add_with("Glib.Types") 2674 section.add( 2675 """type %(typename)s is new Glib.Types.GType_Interface; 2676Null_%(typename)s : constant %(typename)s;""" % self._subst) 2677 2678 self.pkg.add_private(""" 2679Null_%(typename)s : constant %(typename)s := 2680 %(typename)s (Glib.Types.Null_Interface);""" % 2681 self._subst) 2682 2683 elif self.gtktype.is_subtype(): 2684 section.add( 2685 """ 2686subtype %(typename)s_Record is %(parent)s_Record; 2687subtype %(typename)s is %(parent)s;""" % self._subst) 2688 2689 elif self.is_proxy: 2690 section.add(""" 2691 type %(typename)s is new Glib.C_Proxy;""" % self._subst) 2692 2693 elif self.is_boxed: 2694 # The type is not private so that we can directly instantiate 2695 # generic packages for lists of this type. 2696 2697 section.add(""" 2698 type %(typename)s is new Glib.C_Boxed with null record; 2699 Null_%(typename)s : constant %(typename)s; 2700 2701 function From_Object (Object : System.Address) return %(typename)s; 2702 function From_Object_Free (B : access %(typename)s'Class) return %(typename)s; 2703 pragma Inline (From_Object_Free, From_Object); 2704""" % self._subst) 2705 2706 # Insert constant declaration at the end of the package, to avoid 2707 # freezing issues 2708 self.pkg.add_private( 2709 ("\n Null_%(typename)s : constant %(typename)s :=" 2710 + " (Glib.C_Boxed with null record);\n") % 2711 self._subst, at_end=True) 2712 2713 section.add(""" 2714 function From_Object_Free 2715 (B : access %(typename)s'Class) return %(typename)s 2716 is 2717 Result : constant %(typename)s := %(typename)s (B.all); 2718 begin 2719 Glib.g_free (B.all'Address); 2720 return Result; 2721 end From_Object_Free; 2722 2723 function From_Object (Object : System.Address) return %(typename)s is 2724 S : %(typename)s; 2725 begin 2726 S.Set_Object (Object); 2727 return S; 2728 end From_Object; 2729""" % self._subst, in_spec=False) 2730 2731 elif self._subst["parent"] is None: 2732 # Likely a public record type (ie with visible fields). 2733 # Automatically add it to the list of records to bind. 2734 2735 self.gtkpkg.add_record_type(self.ctype) 2736 2737 else: 2738 section.add(""" 2739type %(typename)s_Record is new %(parent)s_Record with null record; 2740type %(typename)s is access all %(typename)s_Record'Class;""" 2741 % self._subst) 2742 2743 for ctype, enum, prefix, asbitfield, ignore in \ 2744 self.gtkpkg.enumerations(): 2745 2746 self.enumeration_binding( 2747 section, ctype, enum, prefix, asbitfield=asbitfield, 2748 ignore=ignore) 2749 2750 for regexp, prefix in self.gtkpkg.constants(): 2751 self.constants_binding(section, regexp, prefix) 2752 2753 for ctype, enum, adaname, fields, unions, private in \ 2754 self.gtkpkg.records(): 2755 2756 self.record_binding( 2757 section, ctype, adaname, enum, fields, unions, private) 2758 2759 for ada, ctype, single, sect_name in self.gtkpkg.lists(): 2760 sect = self.pkg.section(sect_name) 2761 self.add_list_binding(sect, ada, ctype, single) 2762 2763 if extra: 2764 for p in extra: 2765 if p.tag == "with_spec": 2766 self.pkg.add_with( 2767 p.get("pkg", "Missing package name in <extra>"), 2768 do_use=p.get("use", "true").lower() == "true") 2769 elif p.tag == "with_body": 2770 self.pkg.add_with( 2771 p.get("pkg"), specs=False, 2772 do_use=p.get("use", "true").lower() == "true") 2773 elif p.tag == "type": 2774 naming.add_type_exception( 2775 cname=p.get("ctype"), 2776 type=Proxy(p.get("ada"), p.get("properties", None))) 2777 section.add(p.text) 2778 elif p.tag == "body": 2779 if p.get("before", "true").lower() == "true": 2780 # Go before the body of generated subprograms, so that 2781 # we can add type definition 2782 section.add(p.text, in_spec=False) 2783 2784 self._constructors() 2785 self._method_get_type() 2786 self._methods() 2787 2788 if extra: 2789 s = None 2790 for p in extra: 2791 if p.tag == "spec": 2792 if p.get("private", "False").lower() == "true": 2793 self.pkg.add_private(p.text, at_end=True) 2794 else: 2795 s = s or self.pkg.section("GtkAda additions") 2796 s.add(p.text) 2797 elif p.tag == "body" \ 2798 and p.get("before", "true").lower() != "true": 2799 s.add(p.text, in_spec=False) 2800 2801 self._functions() 2802 self._globals() 2803 self._fields() 2804 2805 self._virtual_methods() 2806 2807 if not into and self.name != "Gtk.Widget": 2808 self._implements() 2809 self._properties() 2810 self._signals() 2811 2812 2813# Set up and invoke our command line parser 2814parser = OptionParser() 2815parser.add_option( 2816 "--gir-file", 2817 help="input GTK .gir file", 2818 action="append", 2819 dest="gir_file", 2820 metavar="FILE") 2821parser.add_option( 2822 "--xml-file", 2823 help="input GtkAda binding.xml file", 2824 dest="xml_file", 2825 metavar="FILE") 2826parser.add_option( 2827 "--ada-output", 2828 help="Ada language output file", 2829 dest="ada_outfile", 2830 metavar="FILE") 2831parser.add_option( 2832 "--c-output", 2833 help="C language output file", 2834 dest="c_outfile", 2835 metavar="FILE") 2836(options, args) = parser.parse_args() 2837 2838# Command line argument sanity checking: make sure that all of our 2839# inputs and outputs are specified. 2840missing_files = [] 2841if options.gir_file is None: 2842 missing_files.append("GIR file") 2843if options.xml_file is None: 2844 missing_files.append("binding.xml file") 2845if options.ada_outfile is None: 2846 missing_files.append("Ada output file") 2847if options.c_outfile is None: 2848 missing_files.append("C output file") 2849if missing_files: 2850 parser.error('Must specify files:\n\t' + ', '.join(missing_files)) 2851 2852gtkada = GtkAda(options.xml_file) 2853gir = GIR(options.gir_file) 2854 2855Package.copyright_header = \ 2856 """------------------------------------------------------------------------------ 2857-- -- 2858-- Copyright (C) 1998-2000 E. Briot, J. Brobecker and A. Charlet -- 2859-- Copyright (C) 2000-2015, AdaCore -- 2860-- -- 2861-- This library is free software; you can redistribute it and/or modify it -- 2862-- under terms of the GNU General Public License as published by the Free -- 2863-- Software Foundation; either version 3, or (at your option) any later -- 2864-- version. This library is distributed in the hope that it will be useful, -- 2865-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- 2866-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- 2867-- -- 2868-- As a special exception under Section 7 of GPL version 3, you are granted -- 2869-- additional permissions described in the GCC Runtime Library Exception, -- 2870-- version 3.1, as published by the Free Software Foundation. -- 2871-- -- 2872-- You should have received a copy of the GNU General Public License and -- 2873-- a copy of the GCC Runtime Library Exception along with this program; -- 2874-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- 2875-- <http://www.gnu.org/licenses/>. -- 2876-- -- 2877------------------------------------------------------------------------------ 2878""" 2879 2880gir.ccode = \ 2881 """/***************************************************************************** 2882 * GtkAda - Ada95 binding for Gtk+/Gnome * 2883 * * 2884 * Copyright (C) 1998-2000 E. Briot, J. Brobecker and A. Charlet * 2885 * Copyright (C) 2000-2015, AdaCore * 2886 * * 2887 * This library is free software; you can redistribute it and/or modify it * 2888 * under terms of the GNU General Public License as published by the Free * 2889 * Software Foundation; either version 3, or (at your option) any later * 2890 * version. This library is distributed in the hope that it will be useful, * 2891 * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- * 2892 * TABILITY or FITNESS FOR A PARTICULAR PURPOSE. * 2893 * * 2894 * As a special exception under Section 7 of GPL version 3, you are granted * 2895 * additional permissions described in the GCC Runtime Library Exception, * 2896 * version 3.1, as published by the Free Software Foundation. * 2897 * * 2898 * You should have received a copy of the GNU General Public License and * 2899 * a copy of the GCC Runtime Library Exception along with this program; * 2900 * see the files COPYING3 and COPYING.RUNTIME respectively. If not, see * 2901 * <http://www.gnu.org/licenses/>. * 2902 * 2903 ***************************************************************************** 2904 2905This file is automatically generated from the .gir files 2906*/ 2907#include <gtk/gtk.h> 2908""" 2909 2910 2911for the_ctype in enums: 2912 node = Element( 2913 nclass, 2914 {ctype_qname: the_ctype}) 2915 root = Element(nclass) 2916 2917 cl = gir._create_class(rootNode=root, node=node, 2918 identifier_prefix='', 2919 is_interface=False, 2920 is_gobject=False, 2921 has_toplevel_type=False) 2922 cl.generate(gir) 2923 2924for name in interfaces: 2925 if name.startswith("--"): 2926 gir.bound.add(name[2:]) 2927 continue 2928 2929 gir.interfaces[name].generate(gir) 2930 gir.bound.add(name) 2931 2932for the_ctype in binding: 2933 if the_ctype.startswith("--"): 2934 gir.bound.add(the_ctype[2:]) 2935 continue 2936 2937 try: 2938 e = gir.classes[the_ctype] 2939 except KeyError: 2940 cl = gtkada.get_pkg(the_ctype) 2941 if not cl: 2942 raise 2943 node = Element(nclass, {ctype_qname: the_ctype}) 2944 e = gir.classes[the_ctype] = gir._create_class( 2945 rootNode=root, node=node, is_interface=False, 2946 identifier_prefix='') 2947 2948 e.generate(gir) 2949 gir.bound.add(the_ctype) 2950 2951 2952out = file(options.ada_outfile, "w") 2953cout = file(options.c_outfile, "w") 2954gir.generate(out, cout) 2955 2956gir.show_unbound() 2957