1#!/usr/bin/env python 2 3""" 4Various formatting classes for Ada code 5""" 6 7import sys 8import re 9import copy 10from collections import namedtuple, defaultdict 11 12# A lot of subprograms below take a "lang" parameter, which indicates how 13# values should be converted: 14# 15# LANG should be one of: 16# "ada": the value of the parameter is read from an Ada 17# value (as subprogram whose code is Ada) and passed to a 18# similar subprogram. No conversion needed. 19# "ada->c": all Ada values will be converted to their C equivalent, 20# since the target subprogram's code is written in C. 21# "c->ada": case of C callbacks: the value is passed from C to 22# an Ada subprogram in the user application. 23# 24# As an example, here is what the types for a list of strings 25# would look like in all languages: 26# 27# "ada" -> String_List 28# "c->ada" -> chars_ptr_array_access (no bounds given by C) 29# "ada->c" -> chars_ptr_array (bounds will be ignored anyway, 30# and it is simpler to pass this type). 31 32 33class CType(object): 34 35 """Describes the types in the various cases where they can be used. 36 37 A type applies either to an Ada subprogram written in Ada, or to an 38 Ada subprogram implemented via a pragma Import. The latter case is 39 abbreviated to a "c" subprogram below. 40 41 For returned values, various pieces of information are needed: 42 (adatype, ctype, converter, tmpvars=[]) 43 They are used as: 44 function ... (...) return adatype is 45 function ... (...) return ctype; 46 pragma Import (C, ..., "..."); 47 Tmp : ctype; 48 tmpvars; 49 begin 50 ...; -- pre-call code 51 Tmp := ... (...); 52 ...; -- post-call code 53 return <converter % Tmp> 54 end; 55 In the example above, "Tmp" is only created if there is some post-call 56 code, otherwise we avoid the temporary variable. 57 The variable "Tmp" is automatically added, and does not need to 58 be specified manually in tmpvars. 59 60 if converted contains the string "%(tmp)s", then we always use a 61 temporary variable of type adatype. This is used for instance when the 62 variable is initialized through a procedure call rather than a function 63 call. 64 function ... (...) return adatype is 65 function ... (...) return ctype; 66 pragma Import (C, ..., "...") 67 Tmp_Result : adatype; 68 tmpvars; 69 begin 70 ... -- pre-call code 71 convert % {"var":..., "tmp":"Tmp_Result"}; -- proc call 72 ... -- post-call code 73 return Tmp_Result; 74 end; 75 The variable "Tmp_Result" is automatically added, and does not need to 76 be specified manually in tmpvars. 77 78 Converter will contain a single %s which will be replaced by the 79 name of the temporary variable that holds the result of the call 80 to the function. 81 """ 82 83 def __init__(self, ada, property): 84 self.set_ada_name(ada) 85 self.property = property 86 self.default_record_field_value = None 87 88 self.is_ptr = False 89 90 self.cleanup = None 91 # If set, a tmp variable is created to hold the result of convert 92 # during the call, and is then free by calling this cleanup. Use 93 # "%s" as the name of the variable. 94 95 self.isArray = False 96 97 # In some cases, Ada provides a special value for a parameter that 98 # indicates that NULL should be passed to C. Such a test is only done 99 # when allow_none is True. val_or_null is then a function in charge 100 # of converting the value to a System.Address unless it is equal to 101 # a specific null value. 102 103 self.allow_none = False 104 self.val_or_null = None 105 106 # If True, the value returned from C must be freed by the caller 107 108 self.transfer_ownership = False 109 110 def set_ada_name(self, ada): 111 self.ada = ada # Fully qualified Ada type 112 self.param = ada # type as parameter 113 self.cparam = ada # type for Ada subprograms binding to C 114 115 def convert_from_c(self): 116 """How to convert the value returned from C to Ada. 117 This function returns a tuple: 118 [0] = name of the Ada type 119 [1] = name of the C type 120 [2] = Conversion from C type to Ada type. The value is read 121 from "%(var)s". It can also use "%(tmp)s" if a temporary 122 variable is needed. 123 [3] = List of needed temporary variables (except for the one 124 corresponding to "%(tmp)s". 125 [4] = Name of the C type, for "out" parameters. Often same as [1] 126 [5] = Convert from [4] to the Ada type. Often same as [2] 127 """ 128 return (self.param, self.cparam, "%(var)s", [], self.cparam, "%(var)s") 129 130 def convert_from_c_add_with(self, pkg, specs=False): 131 """Add the "with" statements needed to do the conversion stated 132 in convert_from_c(). 133 """ 134 pass 135 136 def convert_to_c(self, pkg=None): 137 """How to convert from Ada parameter to C parameter. If it uses %(tmp)s, 138 we assume the converter sets the value of the temporary variable 139 itself. 140 It can also use %(var)s which will be substituted by the name of the 141 parameter. 142 Otherwise, it is used as " Tmp := <convert>". 143 It might be necessary to also override add_with() to add the 144 necessary with statements. 145 """ 146 147 if self.allow_none and self.val_or_null: 148 self.cparam = "System.Address" 149 return "%s (%%(var)s'Address)" % self.val_or_null 150 else: 151 return "%(var)s" 152 153 def direct_c_map(self): 154 """Whether the parameter can be passed as is to C""" 155 return self.convert_to_c(pkg=None) == "%(var)s" 156 157 def as_property(self): 158 """The type to use for the property""" 159 return self.property 160 161 def as_return(self, pkg=None): 162 """See CType documentation for a description of the returned tuple""" 163 164 returns = self.convert_from_c() 165 166 if returns and pkg: 167 # Avoid full dotted notation when inside the package itself 168 return (returns[0].replace("%s." % pkg.name, ""), 169 returns[1].replace("%s." % pkg.name, ""), 170 returns[2], 171 returns[3], 172 returns[4], 173 returns[5]) 174 else: 175 return returns 176 177 def record_field_type(self, pkg=None): 178 """The type to use when self is used in a record. 179 [pkg] should be the current package, to avoid fully qualified name 180 that reference that package. 181 """ 182 return self.as_c_param(pkg=pkg) 183 184 def as_ada_param(self, pkg): 185 """Converts self to a description for an Ada parameter to a 186 subprogram. 187 `pkg` is the package in which we insert the name. It is used to 188 avoid qualified name when in the same package 189 """ 190 # Do not fully qualify within the current package 191 p = self.ada[:self.ada.rfind(".")] 192 return self.param.replace("%s." % pkg.name, "") 193 194 def as_c_param(self, pkg=None): 195 """Returns the C type (as a parameter to a subprogram that imports 196 a C function) 197 """ 198 if pkg: 199 return self.cparam.replace("%s." % pkg.name, "") 200 else: 201 return self.cparam 202 203 def as_call( 204 self, name, pkg, wrapper="%s", lang="ada", mode="in", value=None, 205 is_temporary_variable=True): 206 """'name' represents a parameter of type 'self'. 207 'pkg' is the Package instance in which the call occurs. 208 'wrapper' is used in the call itself, and %s is replaced by the 209 name of the variable (or the temporary variable). 210 'mode' is the mode for the Ada subprogram, and is automatically 211 converted when generating a subprogram as a direct C import. 212 :param is_temporary_variable: should be true if the corresponding 213 variable is a variable local to the subprogram, as opposed to a 214 parameter. In this case, we can sometimes avoid creating a second 215 temporary variable, thus increasing efficiency. 216 Returns an instance of VariableCall. 217 See comments at the beginning of this package for valid LANG values 218 """ 219 assert lang in ("ada", "c->ada", "ada->c") 220 assert mode in ("in", "out", "access", "not null access", 221 "in out"), "Incorrect mode: %s" % mode 222 223 if lang == "ada": 224 return VariableCall( 225 call=wrapper % name, precall='', postcall='', tmpvars=[]) 226 227 elif lang == "ada->c": 228 returns = self.convert_from_c() 229 ret = returns and returns[2] 230 231 additional_tmp_vars = [] if not returns else returns[3] 232 233 # An "out" parameter for an enumeration requires a temporary 234 # variable: Internal(Enum'Pos(Param)) is invalid 235 # Unless we are already using a temporary variable. 236 237 if (ret 238 and ret != "%(var)s" 239 and mode != "in" 240 and not is_temporary_variable): 241 242 tmp = "Tmp_%s" % name 243 244 if mode in ("out", "access"): 245 tmpvars = [Local_Var( 246 name=tmp, type=returns[4], aliased=True)] 247 else: 248 tmpvars = [ 249 Local_Var(name=tmp, type=returns[4], aliased=True, 250 default=self.convert_to_c(pkg=pkg) % { 251 "var": name})] 252 253 if "%(tmp)s" in ret: 254 tmp2 = "Tmp2_%s" % name 255 tmpvars += [Local_Var(name=tmp2, type=returns[4])] 256 postcall = "%s; %s := %s;" % ( 257 returns[5] % {"var": tmp, "tmp": tmp2}, 258 name, 259 tmp2) 260 else: 261 postcall = "%s := %s;" % ( 262 name, 263 returns[5] % {"var": tmp}) 264 265 call = VariableCall( 266 call=wrapper % tmp, 267 precall="", 268 postcall=postcall, 269 tmpvars=tmpvars + additional_tmp_vars) 270 271 elif "%(tmp)" in self.convert_to_c(pkg=pkg): 272 # The conversion sets the temporary variable itself 273 tmp = "Tmp_%s" % name 274 call = VariableCall( 275 call=wrapper % tmp, 276 precall=self.convert_to_c(pkg=pkg) % { 277 "var": name, "tmp": tmp}, 278 postcall=self.cleanup % tmp, 279 tmpvars=[Local_Var(name=tmp, type=self.cparam)] + []) 280 281 elif self.cleanup: 282 tmp = "Tmp_%s" % name 283 conv = self.convert_to_c(pkg=pkg) % {"var": name} 284 285 # Initialize the temporary variable with a default value, in 286 # case it is an unconstrained type (a chars_ptr_array for 287 # instance) 288 call = VariableCall( 289 call=wrapper % tmp, 290 precall='', 291 postcall=self.cleanup % tmp, 292 tmpvars=[Local_Var( 293 name=tmp, type=AdaType(self.cparam), default=conv)]) 294 295 else: 296 conv = self.convert_to_c(pkg=pkg) % {"var": name} 297 call = VariableCall( 298 call=wrapper % conv, precall='', postcall="", tmpvars=[]) 299 300 return call 301 302 elif lang == "c->ada": 303 ret = self.convert_from_c() 304 self.convert_from_c_add_with(pkg=pkg) 305 306 # Do we need a temporary variable ? 307 # An "out" parameter for an enumeration requires a temporary 308 # variable: Internal(Enum'Pos (Param)) is invalid 309 310 ret_convert = ret and ret[2] 311 312 if ret_convert and ret_convert != "%(var)s" and mode != "in": 313 tmp = "Tmp_%s" % name 314 tmpvars = [Local_Var(name=tmp, type=self.ada)] + ret[3] 315 316 if "%(tmp)s" in ret_convert: 317 tmp2 = "Tmp2_%s" % name 318 tmpvars += [Local_Var(name=tmp2, type=self.cparam)] 319 postcall = "%s; %s := %s;" % ( 320 ret_convert % {"var": tmp, "tmp": tmp2}, 321 name, 322 tmp2) 323 else: 324 postcall = "%s := %s;" % ( 325 name, 326 self.convert_to_c(pkg=pkg) % {"var": tmp}) 327 328 return VariableCall( 329 call=wrapper % tmp, 330 precall="", 331 postcall=postcall, 332 tmpvars=tmpvars) 333 334 else: 335 return VariableCall( 336 call=wrapper % (ret[2] % {"var": name}), 337 precall='', postcall='', tmpvars=ret[3]) 338 339 def add_with(self, pkg=None, specs=False): 340 """Add required withs for this type""" 341 if pkg: 342 pkg.add_with(package_name(self.ada)) 343 344 if pkg and self.allow_none and self.val_or_null: 345 base = self.val_or_null 346 pkg.add_with(package_name(base), specs=specs) 347 348 def copy(self): 349 """Return a copy of self, possibly modifying some properties.""" 350 return copy.deepcopy(self) 351 352 353class Enum(CType): 354 355 def __init__(self, ada, property=None): 356 base = ada[ada.rfind(".") + 1:] or ada 357 if property is None: 358 CType.__init__(self, ada, "Gtk.Enums.Property_%s" % base) 359 else: 360 CType.__init__(self, ada, property) 361 362 if self.ada.lower() == "boolean": 363 self.cparam = "Glib.Gboolean" 364 else: 365 # Do not convert enumerations to integers. We want to pass the 366 # associated literal in case the enumeration in C does not start 367 # at 0, or as holes in the series. 368 self.cparam = self.ada 369 370 def convert_from_c(self): 371 if self.ada.lower() == "boolean": 372 if self.ada == "Boolean": 373 # Do not use Boolean'Val for more flexibility, in case C 374 # returns another value than 0 and 1 (as is the case for 375 # gtk_status_icon_position_menu on OSX for instance). 376 conv = "%(var)s /= 0" 377 else: 378 conv = "%s'Val (%%(var)s)" % self.ada 379 return (self.param, self.cparam, conv, [], 380 381 # for out parameters 382 self.cparam, conv) 383 else: 384 return super(Enum, self).convert_from_c() 385 386 def convert_to_c(self, pkg=None): 387 if self.ada.lower() == "boolean": 388 return "%s'Pos (%%(var)s)" % self.ada 389 else: 390 return super(Enum, self).convert_to_c(pkg=pkg) 391 392 def record_field_type(self, pkg=None): 393 if pkg: 394 return self.ada.replace("%s." % pkg.name, "") 395 else: 396 return self.ada 397 398 @staticmethod 399 def register_ada_decl(pkg, ctype, ada=None): 400 """Register an enumeration type. 401 :param pkg: is the name of the current package in which the enumeration 402 will be defined. 403 """ 404 405 # Compute the Ada name automatically if needed. 406 if not ada: 407 ada = naming.type(name="", cname=ctype).ada 408 409 full_name = "%s.%s" % (pkg, ada) 410 t = Enum(full_name, "%s.Property_%s" % (pkg, ada)) 411 naming.add_type_exception(cname=ctype, type=t) 412 413 # Add the special cases for properties that GIR file use 414 t = ctype.replace("Pango", "Pango.").replace("Gdk", "Gdk.") 415 naming.girname_to_ctype[t] = ctype 416 417 418class GObject(CType): 419 420 def __init__(self, ada, userecord=True, allow_none=False, classwide=False): 421 CType.__init__(self, ada, "Glib.Properties.Property_Object") 422 self.cparam = "System.Address" 423 self.is_ptr = False 424 self.classwide = classwide # Parameter should include "'Class" 425 self.userecord = userecord # Parameter should be "access .._Record" 426 self.allow_none = allow_none 427 428 def convert_from_c(self): 429 stub = "Stub_%s" % (base_name(self.ada), ) 430 431 if self.ada == "Glib.Object.GObject": 432 conv = "Get_User_Data (%%(var)s, %s)" % stub 433 else: 434 conv = "%s (Get_User_Data (%%(var)s, %s))" % (self.ada, stub) 435 436 return (self.param, 437 self.cparam, 438 conv, 439 [Local_Var( 440 stub, AdaType("%s_Record" % self.ada, in_spec=False))], 441 442 # for out parameters 443 self.cparam, conv) 444 445 def convert_to_c(self, pkg=None): 446 if self.allow_none: 447 return "Get_Object_Or_Null (GObject (%(var)s))" 448 else: 449 return "Get_Object (%(var)s)" 450 451 def as_ada_param(self, pkg): 452 if self.userecord: 453 prefix = "" if self.allow_none else "not null " 454 455 if self.classwide: 456 self.param = "%saccess %s_Record'Class" % (prefix, self.ada) 457 else: 458 self.param = "%saccess %s_Record" % (prefix, self.ada) 459 460 return super(GObject, self).as_ada_param(pkg) 461 462 def copy(self): 463 result = CType.copy(self) 464 return result 465 466 467class Tagged(GObject): 468 469 """Tagged types that map C objects, but do not derive from GObject""" 470 471 def convert_from_c(self): 472 return (self.param, self.cparam, "From_Object (%(var)s)", [], 473 474 # for out parameters 475 self.cparam, "From_Object (%(var)s)") 476 477 def convert_to_c(self, pkg=None): 478 return "Get_Object (%(var)s)" 479 480 def as_ada_param(self, pkg): 481 # Make sure to bind as a CType here, not as a GOBject 482 return CType.as_ada_param(self, pkg) 483 484 485class UTF8(CType): 486 487 def __init__(self): 488 CType.__init__(self, "UTF8_String", "Glib.Properties.Property_String") 489 self.cparam = "Interfaces.C.Strings.chars_ptr" 490 self.cleanup = "Free (%s);" 491 492 def convert_from_c(self): 493 conv = "Gtkada.Bindings.Value_Allowing_Null (%(var)s)" 494 495 if self.transfer_ownership: 496 conv = "Gtkada.Bindings.Value_And_Free (%(var)s)" 497 498 return (self.param, self.cparam, conv, [], 499 500 # for out parameters 501 self.cparam, conv) 502 503 def convert_from_c_add_with(self, pkg, specs=False): 504 if pkg: 505 pkg.add_with("Gtkada.Bindings", specs=specs) 506 507 def convert_to_c(self, pkg=None): 508 if self.allow_none: 509 return 'if %(var)s = "" then %(tmp)s :=' \ 510 + ' Interfaces.C.Strings.Null_Ptr; else'\ 511 + ' %(tmp)s := New_String (%(var)s); end if;' 512 else: 513 return "New_String (%(var)s)" 514 515 def add_with(self, pkg, specs=False): 516 super(UTF8, self).add_with(pkg) 517 if pkg: 518 pkg.add_with("Interfaces.C.Strings", specs=specs, 519 might_be_unused=True) 520 521 522class SignalName(UTF8): 523 """ 524 A special kind of utf8 used for signal names 525 """ 526 def __init__(self): 527 super(SignalName, self).__init__() 528 self.set_ada_name("Glib.Signal_Name") 529 self.cparam = "Interfaces.C.Strings.chars_ptr" 530 531 def convert_to_c(self, pkg=None): 532 return "New_String (String (%(var)s))" 533 534 535class UTF8_List(CType): 536 537 def __init__(self): 538 CType.__init__(self, "GNAT.Strings.String_List", "") 539 self.cparam = "Interfaces.C.Strings.chars_ptr_array" 540 self.cleanup = "GtkAda.Types.Free (%s);" 541 542 def convert_from_c(self): 543 # Use a temporary variable to store the result of To_String_List, 544 # because in some cases the result will need to be freed. For instance, 545 # when a callback from C receives a list of strings as 546 # chars_ptr_array_access, we create a temporary String_List to call the 547 # Ada callback, and then need to free the temporary String_List. 548 549 conv = "To_String_List (%(var)s.all)" 550 551 if self.transfer_ownership: 552 conv = "To_String_List_And_Free (%(var)s)" 553 554 return (self.param, "chars_ptr_array_access", conv, [], 555 556 # for out parameters 557 "chars_ptr_array_access", conv) 558 559 def record_field_type(self, pkg=None): 560 return "Interfaces.C.Strings.char_array_access" 561 562 def convert_to_c(self, pkg=None): 563 if pkg: 564 pkg.add_with("GtkAda.Types", specs=False) 565 return "From_String_List (%(var)s)" 566 567 def add_with(self, pkg=None, specs=False): 568 super(UTF8_List, self).add_with(pkg=pkg) 569 if pkg: 570 pkg.add_with("GNAT.Strings", specs=True) 571 pkg.add_with("Interfaces.C.Strings", specs=specs) 572 pkg.add_with("Gtkada.Bindings", specs=specs, might_be_unused=True) 573 574 575class Record(CType): 576 577 def __init__(self, ada, property=None, val_or_null=None): 578 """ 579 :param val_or_null: if specified, and the null constant is passed 580 as a parameter, then System.Null_Address is passed to C. If 581 unspecified, any value passed by the user is given as is to C. 582 """ 583 584 if property is None: 585 CType.__init__(self, ada, "Glib.Properties.Property_Boxed") 586 else: 587 CType.__init__(self, ada, property) 588 589 self.val_or_null = val_or_null 590 591 # Do not change self.cparam: when passing a read-only parameter to 592 # C, GNAT will automatically pass the address of the record 593 self.cparam = ada 594 595 def convert_from_c(self): 596 conv = "%(var)s.all" # convert C -> Ada, 597 if self.transfer_ownership: 598 conv = "From_Object_Free (%(var)s)" 599 600 return (self.ada, 601 "access %s" % self.ada, 602 conv, 603 [], 604 605 # for out parameters 606 self.ada, "%(var)s") 607 608 def convert_to_c(self, pkg=None): 609 if self.allow_none and self.val_or_null: 610 self.cparam = "System.Address" 611 return "%s (%%(var)s'Address)" % self.val_or_null 612 else: 613 return "%(var)s" 614 615 @staticmethod 616 def register_ada_record(pkg, ctype, ada=None): 617 """Register a <record> type. 618 [pkg] is the name of the current package in which the enumeration 619 will be defined. 620 """ 621 622 adaname = base_name(ada or naming.type(name="", cname=ctype).ada) 623 full_name = "%s.%s" % (pkg, adaname) 624 t = Record(full_name) 625 naming.add_type_exception(cname="%s*" % ctype, type=t) 626 naming.add_type_exception(cname=ctype, type=t) 627 628 629class Proxy(CType): 630 631 def __init__(self, ada, property=None, val_or_null=None, 632 from_gvalue=None, default_record_field=None): 633 """:param val_or_null: is used when GIR indicates the parameter has 634 allow-none=1, and is used to test whether we should pass NULL 635 to C or a pointer to the Ada data. 636 637 :param from_gvalue: is the function used to retrieve this type from 638 a GValue, in particular when processing callbacks. The default is to 639 retrieve a C_Proxy and Cast as appropriate. 640 641 :param str default_record_field: the default value to set in record 642 type declarations for fields of that type. No default value set 643 if this is None. 644 """ 645 646 if property is None: 647 CType.__init__(self, ada, "Glib.Properties.Property_Boxed") 648 else: 649 CType.__init__(self, ada, property) 650 651 self.val_or_null = val_or_null 652 self.default_record_field_value = default_record_field 653 654 def record_field_type(self, pkg=None): 655 if self.isArray and self.array_fixed_size is not None: 656 return "%s (1 .. %s)" % ( 657 self.as_c_param(pkg=pkg), 658 self.array_fixed_size) 659 elif self.is_ptr or self.isArray: 660 return "access %s" % self.as_c_param(pkg=pkg) 661 else: 662 return self.as_c_param(pkg=pkg) 663 664 665class Callback(CType): 666 667 def __init__(self, ada): 668 CType.__init__(self, ada, "") 669 self.cparam = "System.Address" 670 671 def __repr__(self): 672 return "<Callback %s>" % self.ada 673 674 def convert_from_c(self): 675 # Never return such a callback to Ada (because in fact we are pointing 676 # to a function in one of the bodies of GtkAda, not the actual user 677 # callback. 678 return None 679 680 def convert_to_c(self, pkg=None): 681 return "%(var)s'Address" 682 683 684class Interface(CType): 685 686 def __init__(self, ada): 687 CType.__init__(self, ada, "Glib.Properties.Property_Interface") 688 self.cparam = ada 689 self.is_ptr = False 690 691 692class List(CType): 693 694 def __init__(self, ada): 695 CType.__init__(self, ada, "Glib.Properties.Property_Object") 696 self.__adapkg = ada[:ada.rfind(".")] 697 self.cparam = "System.Address" 698 self.is_ptr = False 699 700 def convert_from_c(self): 701 conv = "%s.Set_Object (%%(tmp)s, %%(var)s)" % self.__adapkg 702 return ( # Use %(tmp)s so forces the use of temporary var. 703 self.param, self.cparam, conv, [], 704 705 # for out parameters 706 self.cparam, conv) 707 708 @staticmethod 709 def register_ada_list(pkg, ada, ctype, single=False): 710 """Register a list of GObject instantiated in Ada""" 711 if single: 712 gtype = "GSlist" 713 name = "SList" 714 else: 715 gtype = "Glist" 716 name = "List" 717 718 listCname = "%s%s" % (ctype, name) # Default list name 719 ada = ada or naming.type(cname=listCname).ada 720 721 t = List("%s.%s.%s" % (pkg, ada, gtype)) 722 naming.add_type_exception(listCname, t) 723 724 def convert_to_c(self, pkg=None): 725 return "%s.Get_Object (%%(var)s)" % self.__adapkg 726 727 def add_with(self, pkg=None, specs=False): 728 # A list comes from an instantiation (pkg.instance.glist), so we need 729 # to skip backward two "." 730 if pkg: 731 p = self.ada.rfind(".") 732 if p != -1: 733 p = self.ada[:p].rfind(".") 734 if p != -1: 735 pkg.add_with(self.ada[:p], specs=True) 736 737 738class AdaType(CType): 739 740 def __init__(self, adatype, pkg=None, in_spec=True, ctype="", 741 convert="%(var)s"): 742 """The 'adatype' type is represented as 'ctype' for subprograms 743 that import C functions. The parameters of that type are converted 744 from Ada to C by using 'convert'. 'convert' must use '%s' once 745 to indicate where the name of the parameter should go 746 """ 747 CType.__init__(self, adatype, "") 748 self.param = adatype 749 self.cparam = ctype or adatype 750 self.__convert = convert 751 self.cleanup = None 752 self.is_ptr = adatype.startswith("access ") 753 754 # ??? Why do we need to call this explicitly ? 755 if pkg: 756 self.add_with(pkg) 757 758 def convert_to_c(self, pkg=None): 759 return self.__convert 760 761 762class AdaTypeArray(CType): 763 764 """An array of scalar types""" 765 766 def __init__(self, adatype): 767 CType.__init__(self, adatype, "") 768 self.param = "%s_Array" % naming.case(adatype) 769 self.cparam = "System.Address" 770 self.isArray = True 771 772 def convert_to_c(self, pkg=None): 773 return "%(var)s (%(var)s'First)'Address" 774 775 def convert_from_c(self): 776 # ??? This implementation is specialized for the Gtk.Clipboard pkg, 777 # which is the only place where we use it 778 c = ("Atom_Arrays.To_Array " + 779 "(Atom_Arrays.Convert (%(var)s), Integer (N_Atoms))") 780 781 return (self.param, # name of Ada type 782 self.cparam, # name of C type 783 c, # convert from C to Ada 784 [ # list of temporary variables needed 785 ], 786 self.cparam, # name of C type for out parameters 787 c) # convert from previous line to Ada type 788 789 790class AdaNaming(object): 791 792 def __init__(self): 793 self.cname_to_adaname = {} # c methods to Ada subprograms 794 self.girname_to_ctype = {} # gir names to C types 795 self.exceptions = {} # naming exceptions 796 self.type_exceptions = {} # C types to CType instances 797 798 def add_type_exception(self, cname, type, override=False): 799 """Declares a new type exception, unless there already existed 800 one for that cname. 801 """ 802 assert(isinstance(type, CType)) 803 if override or cname not in self.type_exceptions: 804 self.type_exceptions[cname] = type 805 806 def add_cmethod(self, cname, adaname): 807 """Register the mapping from c method's name to Ada subprogram. 808 This is used to replace C function names in the documentation 809 with their Ada equivalent""" 810 self.cname_to_adaname[cname] = adaname 811 812 def add_girname(self, girname, ctype): 813 """Maps a GIR's "name" attribute to its matching C type. 814 This is used to resolve such names in the documentation and in 815 properties types. 816 """ 817 self.girname_to_ctype[girname] = ctype 818 819 def ctype_from_girname(self, girname): 820 """Return the C type corresponding to a GIR name""" 821 822 if not girname: 823 return "" 824 elif girname.startswith("Gdk") or girname.startswith("Gtk"): 825 default = girname 826 else: 827 default = "Gtk%s" % girname 828 829 return self.girname_to_ctype.get(girname, default) 830 831 def adamethod_name(self, cname, warning_if_not_found=True): 832 """Return the ada name corresponding to the C method's name""" 833 try: 834 return self.cname_to_adaname[cname] 835 except KeyError: 836 if warning_if_not_found and cname.lower().startswith("gtk_"): 837 print "Name quoted in doc has no Ada binding: %s" % cname 838 self.cname_to_adaname[cname] = cname # Display warning once only 839 return cname 840 841 def case(self, name, protect=True): 842 """Return the proper casing to use for 'name', taking keywords 843 into account. This is for packages. 844 """ 845 name = self.__camel_case_to_ada(name.replace("-", "_")).title() 846 if name.endswith("_"): 847 name = name[:-1] 848 849 if protect: 850 return self.protect_keywords(name) 851 else: 852 return name 853 854 def protect_keywords(self, name): 855 return ".".join(self.exceptions.get(n, n) for n in name.split(".")) 856 857 def __camel_case_to_ada(self, name): 858 """Converts a name with CamelCase to Camel_Case""" 859 860 if not name: 861 return name 862 863 result = name[0] 864 prev = result 865 prev_is_underscore = False 866 prev_is_upper = True 867 868 for r in name[1:]: 869 if prev != "_" \ 870 and prev != "." \ 871 and not prev.isupper() \ 872 and r.isupper(): 873 result += "_%s" % r 874 else: 875 result += r 876 877 prev = r 878 879 return result 880 881 def __full_type_from_girname(self, girname): 882 """Return the type description from a GIR name""" 883 return self.type_exceptions.get( 884 girname, # First try GIR name as is in the table (gint, ...) 885 self.type_exceptions.get( 886 self.ctype_from_girname(girname), # Else the C type 887 888 # Else return the GIR name itself 889 Proxy(self.__camel_case_to_ada(girname)))) 890 891 def type(self, name="", cname=None, pkg=None, isArray=False, 892 allow_access=True, allow_none=False, userecord=True, 893 useclass=True, 894 array_fixed_size=None, 895 transfer_ownership=False): 896 """Build an instance of CType for the corresponding cname. 897 A type a described in a .gir file 898 899 :param pkg: an instance of Package, to which extra 900 with clauses will be added if needed. 901 :param allow_none: if True, then an empty string maps to a 902 NULL pointer in C, rather than an empty C string. For a GObject, 903 the parameter is passed as "access" rather than 904 "not null access". 905 :param use_record: is only used for GObject types. 906 :param isArray: should be true for an array of the simple type 907 'name'. 908 :param allow_access: should be True if the parameter can be 909 represented as 'access Type', rather than an explicit type, in 910 the case of GObject descendants. 911 :param array_fixed_size: if specified, this is the size of the 912 array. The binding is different in this case, since we can't use 913 a fat pointer. 914 915 """ 916 917 if cname is None: 918 cname = self.girname_to_ctype.get(name, None) 919 920 if (cname == "gchar**" 921 or name == "array_of_utf8" 922 or name == "array_of_filename"): 923 t = UTF8_List() 924 elif (cname in ("gint**", "int**") 925 or name in ("array_of_gint", "array_of_guint", "array_of_gint8", 926 "array_of_guint8", "array_of_guint16")): 927 t = AdaTypeArray("gint") 928 isArray = True 929 elif name in ("array_of_Gdk.Atom", ): 930 t = AdaTypeArray("Gdk_Atom") 931 isArray = True 932 elif name in ("array_of_gdouble", ): 933 t = AdaTypeArray("gdouble") 934 isArray = True 935 elif cname == "void": 936 return None 937 elif name == "utf8" or cname == "gchar*" or cname == "char*": 938 t = UTF8() 939 elif name == "SignalName": 940 t = SignalName() 941 elif cname: 942 # Check whether the C type, including trailing "*", maps 943 # directly to an Ada type. 944 # t = self.type_exceptions.get( 945 # cname, 946 # Proxy(self.__camel_case_to_ada(cname))) 947 t = self.__full_type_from_girname(cname) 948 is_ptr = False 949 950 if t.ada[-1] == "*": 951 # No, try without the trailing "*" 952 t = self.__full_type_from_girname(cname[0:-1]) 953 954 if t.ada[-1] != "*": 955 is_ptr = True # Yes, so we had a pointer 956 else: 957 basename = cname[0:-1] # Remove all "*" 958 if basename[-1] == "*": 959 basename = basename[0:-1] 960 t = self.__full_type_from_girname(basename) 961 962 if not isinstance(t, GObject) \ 963 and not isinstance(t, Interface): 964 t.is_ptr = is_ptr 965 else: 966 t = self.__full_type_from_girname(name) 967 t.is_ptr = cname and cname[-1] == '*' 968 969 t = t.copy() 970 t.isArray = isArray 971 t.array_fixed_size = array_fixed_size 972 t.classwide = useclass 973 t.allow_none = allow_none 974 t.userecord = userecord 975 t.transfer_ownership = transfer_ownership 976 977 # Needs to be called last, since the output might depend on all the 978 # attributes set above 979 980 t.add_with(pkg) 981 982 return t 983 984 985naming = AdaNaming() 986 987 988def max_length(iter): 989 """Return the length of the longuest element in iter""" 990 longuest = 0 991 for f in iter: 992 longuest = max(longuest, len(f)) 993 return longuest 994 995 996def fill_text(text, prefix, length, firstLineLength=0): 997 """Split TEXT on several lines (with a given max length and a prefix). 998 """ 999 1000 line = "" 1001 result = [] 1002 maxLen = firstLineLength or length - len(prefix) 1003 1004 text = text.replace("\n\n", "\n<br>") 1005 1006 # Do we have a list item ? If yes, preserve the indentation 1007 1008 if text.lstrip().startswith("* "): 1009 line += text[:text.find("*")] 1010 1011 for w in text.split(): # for each word (this loses whitespaces) 1012 if w.startswith("<br>"): 1013 result.append(line) 1014 maxLen = length - len(prefix) 1015 line = w[4:] 1016 1017 elif len(line) + len(w) + 1 > maxLen: 1018 result.append(line) 1019 maxLen = length - len(prefix) 1020 line = w 1021 1022 elif w: 1023 line += " " + w 1024 1025 if line != "": 1026 result.append(line) 1027 1028 return ("\n" + prefix).join(result) 1029 1030 1031def cleanup_doc(doc): 1032 """Replaces C features in the doc with appropriate Ada equivalents""" 1033 1034 def replace_type(x): 1035 t = naming.type(x.group(1)) 1036 t.userecord = False 1037 return t.ada 1038 1039 # get_package might have been called before we had the XML node 1040 # from the Gir file, and therefore no doc for the package. We can 1041 # now override it, unless it came from binding.xml 1042 1043 subp = re.compile("([\S_]+)\(\)") 1044 doc = subp.sub(lambda x: naming.adamethod_name(x.group(1)), doc) 1045 1046 types = re.compile("#([\w_]+)") 1047 doc = types.sub(replace_type, doc) 1048 1049 params = re.compile("@([\w_]+)") 1050 doc = params.sub(lambda x: x.group(1).title(), doc) 1051 1052 enums = re.compile("%([A-Z][\w_]+)") 1053 doc = enums.sub(lambda x: naming.adamethod_name(x.group(1)), doc) 1054 1055 doc = doc.replace("<emphasis>", "*") \ 1056 .replace("</emphasis>", "*") \ 1057 .replace("<literal>", "'") \ 1058 .replace("</literal>", "'") \ 1059 .replace("<firstterm>", "'") \ 1060 .replace("</firstterm>", "'") \ 1061 .replace("<![CDATA[", "") \ 1062 .replace("]]>", "") \ 1063 .replace(" ", " ") \ 1064 .replace("<parameter>", "'") \ 1065 .replace("</parameter>", "'") \ 1066 .replace("<filename>", "'") \ 1067 .replace("</filename>", "'") \ 1068 .replace("<footnote>", "[") \ 1069 .replace("</footnote>", "]") \ 1070 .replace("<keycap>", "'") \ 1071 .replace("</keycap>", "'") \ 1072 .replace("<keycombo>", "[") \ 1073 .replace("</keycombo>", "]") \ 1074 .replace("<entry>", "\n\n") \ 1075 .replace("</entry>", "") \ 1076 .replace("<row>", "") \ 1077 .replace("</row>", "") \ 1078 .replace("<tbody>", "") \ 1079 .replace("</tbody>", "") \ 1080 .replace("</tgroup>", "") \ 1081 .replace("<informaltable>", "") \ 1082 .replace("</informaltable>", "") \ 1083 .replace("<note>", "\nNote: ") \ 1084 .replace("</note>", "") 1085 1086 doc = re.sub("<tgroup[^>]*>", "", doc) 1087 doc = re.sub("<term><parameter>(.*?)</parameter> :</term>", 1088 r"\1:", doc) 1089 1090 # Lists 1091 1092 doc = re.sub("<listitem>(\n?<simpara>|\n?<para>)?", "\n\n * ", doc) 1093 1094 doc = doc.replace("</para></listitem>", "") \ 1095 .replace("</listitem>", "") \ 1096 .replace("<simpara>", "") \ 1097 .replace("</simpara>", "") \ 1098 .replace("<para>", "\n\n") \ 1099 .replace("</para>", "") 1100 1101 # Definition of terms (variablelists) 1102 1103 doc = doc.replace("<variablelist>", "") \ 1104 .replace("</variablelist>", "") \ 1105 .replace("<varlistentry>", "") \ 1106 .replace("</varlistentry>", "") \ 1107 .replace("<term>", "'") \ 1108 .replace("</term>", "'") 1109 1110 doc = re.sub("<variablelist[^>]*>", "", doc) 1111 doc = re.sub("<title>(.*?)</title>", r"\n\n== \1 ==\n\n", doc) 1112 doc = re.sub("<refsect\d[^>]*>", "", doc) 1113 doc = re.sub("</refsect\d>", "", doc) 1114 1115 doc = doc.replace("<example>", "") \ 1116 .replace("</example>", "") \ 1117 .replace("<informalexample>", "") \ 1118 .replace("</informalexample>", "") \ 1119 .replace("<itemizedlist>", "").replace("</itemizedlist>", "") \ 1120 .replace("<orderedlist>", "").replace("</orderedlist>", "") \ 1121 .replace("%", "%") \ 1122 .replace("<", "<").replace(">", ">") \ 1123 .replace("*", "*") \ 1124 .replace("<programlisting>", "\n\n__PRE__<programlisting>") 1125 1126 doc = re.sub("<programlisting>(.*?)</programlisting>", 1127 lambda m: re.sub( 1128 "\n\n+", "\n", 1129 indent_code(m.group(1), addnewlines=False)), 1130 doc, 1131 flags=re.DOTALL or re.MULTILINE) 1132 1133 doc = re.sub("\n\n\n+", "\n\n", doc) 1134 1135 return doc 1136 1137 1138def format_doc(doc, indent, separate_paragraphs=True, fill=True): 1139 """Transform the doc from a list of strings to a single string""" 1140 1141 result = "" 1142 prev = "" 1143 1144 # Make sure the doc is a list of paragraphs 1145 1146 if not isinstance(doc, list): 1147 doc = [doc] 1148 1149 # Cleanup the XML tags in each paragraph. This could result in 1150 # new paragraphs being created 1151 1152 cleaned = [] 1153 1154 for d in doc: 1155 d = cleanup_doc(d) 1156 if fill: 1157 cleaned.extend(d.split("\n\n")) 1158 else: 1159 cleaned.append(d) 1160 1161 prefix = "\n" + indent + "--" 1162 1163 for d in cleaned: 1164 1165 # Separate paragraphs with an empty line, unless it is a markup 1166 # or we are at the end 1167 if separate_paragraphs: 1168 if prev != "" and not prev.lstrip().startswith("<"): 1169 result += prefix 1170 1171 if d: 1172 if d.lstrip().startswith("__PRE__"): 1173 d = d.lstrip()[7:] 1174 result += "".join(prefix + " " + p for p in d.splitlines()) 1175 elif fill: 1176 result += prefix + " " 1177 result += fill_text(d, indent + "-- ", 79) 1178 else: 1179 result += "".join(prefix + " " + p for p in d.splitlines()) 1180 1181 prev = d 1182 1183 if result and separate_paragraphs and result[0] == "\n": 1184 result = result[1:] 1185 1186 return result 1187 1188 1189def box(name, indent=" "): 1190 return indent + "-" * (len(name) + 6) + "\n" \ 1191 + indent + "-- " + name + " --\n" \ 1192 + indent + "-" * (len(name) + 6) 1193 1194 1195def indent_code(code, indent=3, addnewlines=True): 1196 """Return code properly indented and split on several lines. 1197 These are heuristics only, not perfect. 1198 """ 1199 body = code.strip() 1200 if not body: 1201 return "" 1202 1203 if addnewlines: 1204 # Add newlines where needed, but preserve existing blank lines 1205 body = re.sub(";(?!\s*\n)", ";\n", body) 1206 body = re.sub("(?<!and )then(?!\s*\n)", "then\n", body) 1207 body = re.sub("(?<!or )else(?!\s*\n)", "else\n", body) 1208 body = re.sub("declare", "\ndeclare", body) 1209 body = re.sub(r"\bdo\b", "do\n", body) 1210 body = re.sub("\n\s*\n+", "\n\n", body) 1211 1212 parent_count = 0 1213 result = "" 1214 1215 for l in body.splitlines(): 1216 if l.find("--") != -1: 1217 eol_comment = l[l.find("--"):].strip() 1218 l = l[:l.find("--")] 1219 else: 1220 eol_comment = "" 1221 1222 l = l.strip() 1223 1224 if l.startswith("end") \ 1225 or l.startswith("elsif") \ 1226 or l.startswith("else") \ 1227 or l.startswith("begin") \ 1228 or l.startswith("}"): # for C 1229 indent -= 3 1230 1231 old_parent = parent_count 1232 parent_count = parent_count + l.count("(") - l.count(")") 1233 1234 if not l: 1235 if eol_comment: 1236 result += " " * indent 1237 1238 elif l[0] == '(': 1239 result += " " * (indent + 2) 1240 if parent_count > old_parent: 1241 indent += (parent_count - old_parent) * 3 1242 elif not old_parent: 1243 result += " " * indent 1244 if parent_count > old_parent: 1245 indent += (parent_count - old_parent) * 3 1246 else: 1247 if parent_count > old_parent: 1248 indent += (parent_count - old_parent) * 3 1249 result += " " * indent 1250 1251 if old_parent > parent_count: 1252 indent -= (old_parent - parent_count) * 3 1253 1254 result += l + eol_comment + "\n" 1255 1256 if (l.endswith("then") and not l.endswith("and then")) \ 1257 or l.endswith("loop") \ 1258 or(l.endswith("else") and not l.endswith("or else"))\ 1259 or l.endswith("begin") \ 1260 or l.endswith("{") \ 1261 or l.endswith("record") \ 1262 or l.endswith("is") \ 1263 or l.endswith("do") \ 1264 or l.endswith("declare"): 1265 indent += 3 1266 1267 # Case of generic instantiation: 1268 # package A is 1269 # new B (); 1270 if l.startswith("new"): 1271 indent -= 3 1272 1273 return result 1274 1275 1276# The necessary setup to use a variable in a subprogram call. The returned 1277# values map to the following Ada code: 1278# declare 1279# $(tmpvars) # A list of LocalVar 1280# begin 1281# $(precall) 1282# Call ($(call), ...) 1283# (postcall) 1284# end; 1285# and are used in case temporary variables are needed. If not, only 'call' 1286# will have a non-null value 1287 1288VariableCall = namedtuple('VariableCall', 1289 ['call', 'precall', 'postcall', 'tmpvars']) 1290 1291 1292class Local_Var(object): 1293 __slots__ = ["name", "type", "default", "aliased", "constant"] 1294 1295 def __init__(self, name, type, default="", aliased=False, constant=False): 1296 self.set_type(type) 1297 self.name = name 1298 self.default = default 1299 self.aliased = aliased 1300 self.constant = constant 1301 1302 def __repr__(self): 1303 return "<Local_Var name=%s type=%s>" % (self.name, self.type) 1304 1305 def set_type(self, type): 1306 if isinstance(type, str): 1307 self.type = AdaType(type) 1308 else: 1309 self.type = type 1310 1311 def _type(self, lang, pkg): 1312 """`pkg` is the package in which we insert the variable, and is used 1313 to add necessary with statements, if any. 1314 """ 1315 if lang == "ada": 1316 return self.type.as_ada_param(pkg) 1317 elif lang == "ada->c": 1318 return self.type.as_c_param(pkg) 1319 elif lang == "c->ada": 1320 return self.type.convert_from_c()[1] 1321 1322 def spec(self, pkg, length=0, lang="ada", show_default=True): 1323 """Format the declaration for the variable or parameter. 1324 'length' is the minimum length that the name should occupy (for 1325 proper alignment when there are several variables. 1326 """ 1327 t = self._type(lang=lang, pkg=pkg) 1328 aliased = "" 1329 if self.aliased: 1330 aliased = "aliased " 1331 1332 if self.default and show_default: 1333 return "%-*s : %s%s%s := %s" % ( 1334 length, self.name, 1335 "constant " if self.constant else "", 1336 aliased, t, self.default) 1337 else: 1338 return "%-*s : %s%s" % (length, self.name, aliased, t) 1339 1340 def as_call(self, pkg, lang="ada", value=None): 1341 """Pass self (or the value) as a parameter to an Ada subprogram call, 1342 implemented in the given language. See comments at the beginning 1343 of this package for valid values of LANG. 1344 'pkg' is the instance of Package in which the call occurs. 1345 :return: an instance of VariableCall 1346 """ 1347 n = value or self.name 1348 if isinstance(self.type, CType): 1349 return self.type.as_call( 1350 name=n, pkg=pkg, lang=lang, wrapper="%s", 1351 is_temporary_variable=True) 1352 else: 1353 return VariableCall(call=n, precall='', postcall='', tmpvars=[]) 1354 1355 1356class Parameter(Local_Var): 1357 __slots__ = ["name", "type", "default", "aliased", "mode", "doc", 1358 "ada_binding", "for_function", "is_temporary_variable"] 1359 1360 def __init__(self, name, type, default="", doc="", mode="in", 1361 for_function=False, ada_binding=True, 1362 is_temporary_variable=False): 1363 """ 1364 'mode' is the mode for the Ada subprogram, and is automatically 1365 converted when generating a subprogram as a direct C import. 1366 1367 :param for_function: whether the parameter belongs to a procedure 1368 or a function. 1369 1370 :param ada_binding: if False, the parameter will not be displayed 1371 in the profile of Ada subprograms (although, of course, it will 1372 be passed to the C subprograms) 1373 1374 :param is_temporary_variable: True if this parameter represents a 1375 local variable. In this case, we can sometimes avoid creating 1376 other such variables, a minor optimization. 1377 """ 1378 assert mode in ("in", "out", "in out", "not null access", 1379 "access"), "Incorrect mode: %s" % mode 1380 1381 super(Parameter, self).__init__(name, type, default=default) 1382 self.mode = mode 1383 self.doc = doc 1384 self.ada_binding = ada_binding 1385 self.for_function = for_function 1386 self.is_temporary_variable = is_temporary_variable 1387 1388 def _type(self, lang, pkg): 1389 mode = self.mode 1390 1391 if lang == "ada->c" and mode != "in" and self.for_function: 1392 mode = "access" 1393 1394 if mode in ("in out", "out") and hasattr(self.type, "userecord"): 1395 userec = self.type.userecord 1396 self.type.userecord = False 1397 t = super(Parameter, self)._type(lang=lang, pkg=pkg) 1398 self.type.userecord = userec 1399 else: 1400 t = super(Parameter, self)._type(lang=lang, pkg=pkg) 1401 1402 if mode != "in": 1403 return "%s %s" % (mode, t) 1404 return t 1405 1406 def as_call(self, pkg, lang="ada", value=None): 1407 """'pkg' is the package instance in which the call occurs.""" 1408 1409 assert lang in ("ada", "c->ada", "ada->c") 1410 1411 if not self.ada_binding: 1412 if self.default is not None: 1413 return VariableCall(call=self.default, 1414 precall='', postcall='', tmpvars=[]) 1415 else: 1416 return VariableCall(call="Parameter not bound in Ada", 1417 precall='', postcall='', tmpvars=[]) 1418 else: 1419 wrapper = "%s" 1420 n = value or self.name 1421 1422 # We know that for a C function, an "in out" parameter is 1423 # implemented as an "access parameter", so we'll need to take a 1424 # 'Access. In the call to as_call() below, though, we still pass 1425 # the original mode ("in out") not "access", so that as_call() 1426 # knows whether we need to make a copy of the parameter or not. 1427 1428 if lang == "ada->c" and self.mode != "in" and self.for_function: 1429 wrapper = "%s'Access" 1430 1431 if isinstance(self.type, CType): 1432 return self.type.as_call( 1433 name=n, pkg=pkg, lang=lang, mode=self.mode, 1434 wrapper=wrapper, 1435 is_temporary_variable=self.is_temporary_variable) 1436 else: 1437 return VariableCall( 1438 call=n, precall='', postcall='', tmpvars=[]) 1439 1440 def direct_c_map(self): 1441 """Whether the parameter can be passed as is to C""" 1442 return self.type.direct_c_map() 1443 1444 def value(self): 1445 if not self.ada_binding: 1446 if self.default is not None: 1447 return self.default 1448 else: 1449 return "Parameter not bound in Ada" 1450 else: 1451 return self.ada_binding 1452 1453 1454def base_name(qname): 1455 """Return the basename for a fully qualified name: 1456 Pkg.Name => Name 1457 """ 1458 if "." in qname: 1459 return qname[qname.rfind(".") + 1:] 1460 else: 1461 return qname 1462 1463 1464def package_name(qname): 1465 """Return the package part of a fully qualified name: 1466 Pkg.Child.Name => Pkg.Child 1467 Name => "" 1468 """ 1469 if "." in qname: 1470 index = qname.rfind(".") 1471 if qname[index - 1] != '.': # ignore ".." in ranges 1472 return qname[:index] 1473 return "" 1474 1475 1476max_profile_length = 79 - len(" is") 1477 1478 1479class Subprogram(object): 1480 1481 """An Ada subprogram that we are generating""" 1482 1483 def __init__(self, name, code="", plist=[], local_vars=[], 1484 returns=None, doc=[], showdoc=True, convention=None, 1485 lang="ada", allow_none=True): 1486 """Create a new subprogram. 1487 'plist' is a list of Parameter. 1488 'local_vars' is a list of Local_Var. 1489 'doc' is a string or a list of paragraphs. 1490 'code' can be the empty string, in which case no body is output. 1491 'lang' is the language for the types of parameters (see comment at 1492 the top of this file). 1493 'allow_none': when this is an anonymous subprogram (and therefore 1494 used for a callback), this indicates whether the callback can be 1495 null or not). 1496 The code will be automatically pretty-printed, and the appropriate 1497 pragma Unreferenced are also added automatically. 1498 """ 1499 assert(returns is None or isinstance(returns, CType)) 1500 assert(lang in ("ada", "c->ada", "ada->c")) 1501 1502 self.name = name 1503 self.plist = plist 1504 self.returns = returns 1505 self.local = local_vars 1506 self.showdoc = showdoc 1507 self.convention = convention # "lang" 1508 self.allow_none = allow_none 1509 self._import = None 1510 self._nested = [] # nested subprograms 1511 self._deprecated = (False, "") # True if deprecated 1512 self._manual_body = None # Written by user explicitly 1513 1514 self.lang = lang # Language for the types of parameters 1515 1516 if code and code[-1] != ";": 1517 self.code = code + ";" 1518 else: 1519 self.code = code 1520 1521 if isinstance(doc, list): 1522 self.doc = doc 1523 else: 1524 self.doc = [doc] 1525 1526 def import_c(self, cname): 1527 """Declares that 'self' is implemented as a pragma Import. 1528 This returns 'self' so that it can be chained: 1529 s = Subprogram(...).import_c('...') 1530 """ 1531 self._import = 'pragma Import (C, %s, "%s");' % (self.name, cname) 1532 return self 1533 1534 def mark_deprecated(self, msg): 1535 """Mark the subprogram as deprecated""" 1536 1537 self._deprecated = (True, msg) 1538 1539 def add_nested(self, *args): 1540 """Add some nested subprograms""" 1541 for subp in args: 1542 self._nested.append(subp) 1543 return self 1544 1545 def set_body(self, body): 1546 """Overrides the body of the subprogram (after "is")""" 1547 self._manual_body = body 1548 1549 def profile(self, pkg, indent=" ", maxlen=max_profile_length, 1550 as_type=False, specs=False): 1551 """Compute the profile for the subprogram""" 1552 1553 returns = self.returns and self.returns.as_return(pkg=pkg) 1554 1555 if returns: 1556 prefix = "function" 1557 if self.lang == "ada->c": 1558 suffix = " return %s" % returns[1] 1559 elif self.lang == "c->ada": 1560 suffix = " return %s" % returns[1] 1561 else: 1562 suffix = " return %s" % returns[0] 1563 else: 1564 prefix = "procedure" 1565 suffix = "" 1566 1567 if (not as_type) and self.name: 1568 prefix = indent + prefix + " " + base_name(self.name) 1569 elif self.allow_none: 1570 prefix = "access %s" % prefix 1571 else: 1572 prefix = "not null access %s" % prefix 1573 1574 if self.plist: 1575 # First test: all parameters on same line 1576 plist = [p.spec(pkg=pkg, lang=self.lang) for p in self.plist] 1577 p = " (" + "; ".join(plist) + ")" 1578 1579 # If too long, split on several lines 1580 if len(p) + len(prefix) + len(suffix) > maxlen: 1581 max = max_length([p.name for p in self.plist]) 1582 plist = [p.spec(pkg=pkg, length=max, lang=self.lang, 1583 show_default=self.lang == "ada") 1584 for p in self.plist] 1585 p = "\n " + indent + "(" \ 1586 + (";\n " + indent).join(plist) + ")" 1587 1588 else: 1589 p = "" 1590 1591 # Should the "return" go on a separate line ? 1592 if p and suffix and len(p.splitlines()[-1]) + len(suffix) > maxlen: 1593 return prefix + p + "\n " + indent + suffix 1594 else: 1595 return prefix + p + suffix 1596 1597 def add_withs_for_subprogram(self, pkg, in_specs): 1598 """ 1599 Add required withs to the package (either in specs or body) 1600 """ 1601 if self.returns: 1602 r = self.returns.as_return(pkg=pkg) 1603 if self.lang == "ada->c": 1604 self.returns.add_with(pkg=pkg, specs=in_specs) 1605 elif self.lang == "c->ada": 1606 self.returns.add_with(pkg=pkg, specs=in_specs) 1607 else: 1608 pkg.add_with(package_name(r[0]), specs=in_specs) 1609 1610 if self.plist: 1611 for p in self.plist: 1612 p.type.add_with(pkg=pkg, specs=in_specs) 1613 1614 def formatted_doc(self, indent=" "): 1615 if self.showdoc: 1616 doc = [d for d in self.doc] 1617 if self._deprecated[0]: 1618 doc += [self._deprecated[1]] 1619 doc += [p.doc for p in self.plist] 1620 else: 1621 doc = [] 1622 1623 return format_doc(doc, indent=indent, separate_paragraphs=False) 1624 1625 def spec(self, pkg, indent=" ", show_doc=True, 1626 maxlen=max_profile_length, as_type=False): 1627 """Return the spec of the subprogram""" 1628 1629 result = self.profile( 1630 pkg=pkg, indent=indent, maxlen=maxlen, as_type=as_type) + ";" 1631 1632 if self._import: 1633 result += "\n" + indent + self._import 1634 1635 if self._deprecated[0]: 1636 result += "\n" + indent + "pragma Obsolescent (%s);" % self.name 1637 1638 if self.convention: 1639 result += "\n" + indent \ 1640 + "pragma Convention (%s, %s);" % (self.convention, self.name) 1641 1642 if show_doc: 1643 doc = self.formatted_doc(indent=indent) 1644 else: 1645 doc = "" 1646 1647 return result + doc 1648 1649 def _find_unreferenced(self, local_vars="", indent=" "): 1650 """List the pragma Unreferenced statements that are needed for this 1651 subprogram. 1652 """ 1653 unreferenced = [] 1654 for p in self.plist: 1655 if not re.search( 1656 r'\b%s\b' % p.name, self.code + local_vars, re.IGNORECASE): 1657 unreferenced.append(p.name) 1658 1659 if unreferenced: 1660 return indent + " pragma Unreferenced (%s);\n" % ( 1661 ", ".join(unreferenced)) 1662 else: 1663 return "" 1664 1665 def _format_local_vars(self, pkg, indent=" "): 1666 """The list of local variable declarations""" 1667 if self.local: 1668 max = max_length([p.name for p in self.local]) 1669 result = [] 1670 seen = set() 1671 1672 for v in self.local: 1673 if v.name not in seen: 1674 seen.add(v.name) 1675 result.append(v.spec(pkg=pkg, length=max)) 1676 1677 return indent + " " + (";\n " + indent).join(result) + ";\n" 1678 else: 1679 return "" 1680 1681 def body(self, pkg, indent=" "): 1682 if not self.code and not self._manual_body: 1683 return "" 1684 1685 result = box(base_name(self.name), indent=indent) + "\n\n" 1686 profile = self.profile(pkg=pkg, indent=indent) 1687 result += profile 1688 1689 if profile.find("\n") != -1: 1690 result += "\n" + indent + "is\n" 1691 else: 1692 result += " is\n" 1693 1694 local = self._format_local_vars(pkg=pkg, indent=indent) 1695 auto = self._find_unreferenced(local_vars=local, indent=indent) 1696 1697 for s in self._nested: 1698 auto += s.spec(pkg=pkg, indent=indent + " ") + "\n" 1699 auto += s.body(pkg=pkg, indent=indent + " ") 1700 1701 auto += local 1702 auto += indent + "begin\n" 1703 auto += indent_code(self.code, indent=len(indent) + 3) 1704 1705 if self._manual_body: 1706 result += indent + self._manual_body % {"auto": auto} 1707 else: 1708 result += auto 1709 1710 return result + indent + "end %s;\n" % base_name(self.name) 1711 1712 def call(self, in_pkg=None, extra_postcall="", values=dict(), lang=None): 1713 """A call to 'self'. 1714 The parameters that are passed to self are assumed to have the 1715 same name as in self's declaration. When 'self' is implemented 1716 as a pragma Import, proper conversions are done. 1717 'in_pkg' is used to fully qualify the name of the subprogram, to 1718 avoid ambiguities. This is optional. This is an instance of Package. 1719 1720 Returned value is a tuple: 1721 ("code", "variable_for_return", tmpvars=[]) 1722 where "code" is the code to execute for the call, including 1723 creation of temporary variables, and "variable_for_return" is 1724 either None, or the code to get the result of the subprogram. 1725 So a call is: 1726 declare 1727 tmp_vars; 1728 begin 1729 code; 1730 extra_postcall; 1731 return variable_for_return; -- Omitted for procedures 1732 end; 1733 1734 See comments at the beginning of this package for valid LANG values. 1735 """ 1736 1737 assert(in_pkg is not None) 1738 assert(isinstance(in_pkg, Package)) 1739 1740 if lang: 1741 pass 1742 elif self._import: 1743 lang = "ada->c" 1744 else: 1745 lang = "ada" 1746 1747 assert(lang in ("ada", "c->ada", "ada->c")) 1748 1749 tmpvars = [] 1750 precall = "" 1751 params = [] 1752 postcall = extra_postcall 1753 1754 for arg in self.plist: 1755 c = arg.as_call( 1756 pkg=in_pkg, 1757 lang=lang, # An instance of VariableCall 1758 value=values.get(arg.name.lower(), None)) 1759 params.append(c.call) 1760 tmpvars.extend(c.tmpvars) 1761 precall += c.precall 1762 postcall = c.postcall + postcall 1763 1764 if params: 1765 call = "%s (%s)" % (self.name, ", ".join(params)) 1766 else: 1767 call = self.name 1768 1769 returns = self.returns and self.returns.as_return(pkg=in_pkg) 1770 if returns is not None: 1771 if lang == "ada->c": 1772 self.returns.convert_from_c_add_with(pkg=in_pkg) 1773 1774 tmpvars.extend(returns[3]) 1775 if "%(tmp)s" in returns[2]: 1776 # Result of Internal is used to create a temp. variable, 1777 # which is then returned. This variable has the same type 1778 # as the Ada type (not necessarily same as Internal) 1779 call = returns[2] % {"var": call, "tmp": "Tmp_Return"} 1780 1781 tmpvars.append(Local_Var("Tmp_Return", returns[0])) 1782 result = ("%s%s;%s" % (precall, call, postcall), 1783 "Tmp_Return", 1784 tmpvars) 1785 1786 elif postcall: 1787 tmpvars.append(Local_Var("Tmp_Return", returns[1])) 1788 call = "Tmp_Return := %s" % call 1789 result = ("%s%s;%s" % (precall, call, postcall), 1790 returns[2] % {"var": "Tmp_Return"}, 1791 tmpvars) 1792 1793 else: 1794 # No need for a temporary variable 1795 result = (precall, returns[2] % {"var": call}, tmpvars) 1796 1797 else: # "ada" or "c->ada" 1798 if postcall: 1799 # We need to use a temporary variable, since there are 1800 # cleanups to perform. This will not work if the function 1801 # returns an unconstrained array though. 1802 tmpvars.append(Local_Var("Tmp_Return", returns[0])) 1803 call = "Tmp_Return := %s" % call 1804 result = ("%s%s;%s" % (precall, call, postcall), 1805 "Tmp_Return", 1806 tmpvars) 1807 else: 1808 # No need for a temporary variable 1809 result = (precall, call, tmpvars) 1810 1811 else: 1812 # A procedure 1813 result = ("%s%s;%s" % (precall, call, postcall), None, tmpvars) 1814 1815 return result 1816 1817 def call_to_string(self, call, pkg=None, lang="ada"): 1818 """CALL is the result of call() above. 1819 This function returns a string that contains the code for the 1820 subprogram. 1821 """ 1822 result = call[0] 1823 if call[1]: 1824 if lang == "c->ada": 1825 # The return value (Ada) needs to be converted back to C (this 1826 # is the returned value from a callback, for instance) 1827 result += "return %s" % ( 1828 self.returns.convert_to_c(pkg=pkg) % {"var": call[1]}, ) 1829 else: 1830 result += "return %s" % call[1] 1831 return result 1832 1833 1834class Code(object): 1835 """ 1836 Some text to insert in a package. This can be either some code, or the 1837 comments for the code. In the latter case, the comment will be 1838 automatically formatted (and C names substituted as appropriate). 1839 """ 1840 1841 def __init__(self, content, iscomment=False, fill=True): 1842 """:param:`fill` whether to reflow the text if this is a comment. 1843 :param:`add_newline` whether the block should have a leading newline 1844 """ 1845 self.content = content 1846 self.iscomment = iscomment 1847 self.fill = fill 1848 self.add_newline = True 1849 1850 def format(self, indent=""): 1851 """Return the code that should be written into a package""" 1852 if self.iscomment: 1853 return format_doc(self.content, indent=indent, fill=self.fill) 1854 else: 1855 return indent_code( 1856 self.content, indent=len(indent), addnewlines=False) 1857 1858 1859class Section(object): 1860 """A group of types and subprograms in an Ada package. 1861 There is a single section with a given name in the package 1862 """ 1863 1864 group_getters_and_setters = False 1865 # If true, a getter will be displayed with its corresponding setter. 1866 # Only one doc will be displayed for the two, and no separation line 1867 # will be output. 1868 1869 sort_alphabetically = False 1870 # If true, subprograms are all sorted alphabetically, otherwise the 1871 # order is alphabetical for getters, but setters appear just after the 1872 # getter. 1873 1874 def __init__(self, pkg, name): 1875 self.pkg = pkg # The instance of Package in which the section is 1876 self.name = name 1877 self.__comment = "" 1878 self.__objects = [] # List of objects. These are tuples: 1879 # (Code or Subprogram or Package instance, 1880 # in_spec) 1881 1882 # Whether we should sort the objects. If yes, code always comes before 1883 # subprograms. Otherwise, they are output in the order they were added 1884 self.sort_objects = ( 1885 not Section.sort_alphabetically 1886 or Section.group_getters_and_setters) 1887 1888 def add_comment(self, comment, fill=True): 1889 """If 'fill' is true, the comment is automatically split on several 1890 lines if needed. Otherwise, the comment is assumed to be already 1891 formatted properly, minus the leading -- 1892 """ 1893 if comment == "": 1894 self.__comment += " --\n" 1895 else: 1896 self.__comment += "".join( 1897 format_doc(comment, indent=" ", fill=fill)) + \ 1898 "\n" 1899 1900 def add(self, obj, in_spec=True, add_newline=True): 1901 """Add one or more objects to the section (subprogram, code,...). 1902 :param:`add_newline` indicates whether the object should be 1903 followed by a blank line. There is never a blank line between some 1904 code and the following comment. 1905 """ 1906 1907 iscode = False 1908 1909 if isinstance(obj, str) or isinstance(obj, unicode): 1910 obj = Code(obj) 1911 iscode = True 1912 elif isinstance(obj, Package): 1913 obj.isnested = True 1914 1915 obj.add_newline = add_newline 1916 1917 if iscode: 1918 # Take care of duplicated entries. May happen in case of 1919 # subpackages in GIR files 1920 for o, s in self.__objects: 1921 if s == in_spec and isinstance(o, Code): 1922 if o.content == obj.content: 1923 return False 1924 self.__objects.append((obj, in_spec)) 1925 1926 return True 1927 1928 def _group_objects(self): 1929 """Returns a list of subprograms for the specs. In each nested list, 1930 the subprograms are grouped and a single documentation is output for 1931 the whole group. At the same time, this preserves the order of 1932 groups, so they appear in the order in which the first subprogram 1933 in the group appeared. 1934 """ 1935 1936 if self.sort_objects: 1937 code = [] 1938 subprograms = [] 1939 tmp = dict() # group_name => [subprograms] 1940 1941 gtk_new_index = 0 1942 1943 for obj, in_spec in self.__objects: 1944 if not in_spec: 1945 continue 1946 1947 if isinstance(obj, Code) or isinstance(obj, unicode): 1948 code.append([obj]) 1949 1950 elif isinstance(obj, Subprogram) or isinstance(obj, Package): 1951 b = base_name(obj.name) 1952 name = b.replace("Get_", "") \ 1953 .replace("Query_", "") \ 1954 .replace("Gtk_New", "") \ 1955 .replace("Gdk_New", "") \ 1956 .replace("Initialize", "") \ 1957 .replace("Set_From_", "") \ 1958 .replace("Set_", "") 1959 1960 if b in ("Gtk_New", "Gdk_New", "G_New"): 1961 # Always create a new group for Gtk_New, since they all 1962 # have different parameters. But we still want to group 1963 # Gtk_New and Initialize. 1964 t = tmp["Gtk_New%d" % gtk_new_index] = [obj] 1965 subprograms.append(t) 1966 elif b == "Initialize": 1967 tmp["Gtk_New%d" % gtk_new_index].append(obj) 1968 gtk_new_index += 1 1969 elif name in tmp: 1970 tmp[name].append(obj) # Also modified in result 1971 else: 1972 tmp[name] = [obj] 1973 subprograms.append(tmp[name]) 1974 1975 else: 1976 print("Unexpected contents in package %s\n" % 1977 (type(obj), )) 1978 1979 return code + subprograms 1980 1981 else: 1982 return [[obj] 1983 for obj, in_spec in self.__objects 1984 if in_spec] 1985 1986 def spec(self, pkg, indent): 1987 """Return the spec of the section""" 1988 1989 result = "" 1990 add_newline = False 1991 1992 for group in self._group_objects(): 1993 for obj in group: 1994 # If the previous object requested a trailing newline, and the 1995 # current object is not a comment, then add the newline now. 1996 if (add_newline 1997 and (not isinstance(obj, Code) 1998 or not obj.iscomment)): 1999 2000 result += "\n" 2001 2002 if isinstance(obj, Code): 2003 result += obj.format(indent=indent).strip("\n") + "\n" 2004 add_newline = obj.add_newline 2005 2006 elif isinstance(obj, Subprogram): 2007 show_doc = ((not Section.group_getters_and_setters 2008 and not obj.name.startswith("Gtk_New")) 2009 or obj == group[-1]) 2010 result += obj.spec(pkg=pkg, 2011 show_doc=show_doc, 2012 indent=indent).strip("\n") + "\n" 2013 add_newline = (hasattr(obj, "add_newline") 2014 and obj.add_newline 2015 and show_doc) 2016 2017 elif isinstance(obj, Package): 2018 result += obj.spec().strip("\n") + "\n" 2019 add_newline = (hasattr(obj, "add_newline") 2020 and obj.add_newline) 2021 2022 elif isinstance(obj, unicode): 2023 print("Not adding unicode to package: %s\n" % ( 2024 obj.encode('UTF-8'), )) 2025 2026 if add_newline: 2027 result += "\n" 2028 2029 if result: 2030 if self.__comment: 2031 result = self.__comment + "\n" + result 2032 elif self.name: 2033 result = "\n" + result 2034 if self.name: 2035 result = box(self.name) + "\n" + result 2036 2037 return result 2038 2039 def body(self, pkg, indent): 2040 result = [] 2041 2042 for obj, in_spec in self.__objects: 2043 if in_spec or not isinstance(obj, Code): 2044 continue 2045 result.append(obj.format(indent=indent)) # ignores obj.add_newline 2046 2047 body_subprograms = [(obj, in_spec) for obj, in_spec in self.__objects 2048 if not isinstance(obj, Code)] 2049 body_subprograms.sort(key=lambda x: base_name(x[0].name)) 2050 2051 # First output for the subprograms only defined in the body 2052 2053 for obj, in_spec in body_subprograms: 2054 if not in_spec: 2055 if isinstance(obj, Subprogram): 2056 result.append(obj.spec(pkg=pkg, indent=indent)) 2057 else: 2058 result.append(obj.spec()) 2059 result.append("") 2060 2061 # Then output all the bodiesx 2062 2063 for obj, in_spec in body_subprograms: 2064 if isinstance(obj, Subprogram): 2065 b = obj.body(pkg=pkg, indent=indent) 2066 else: 2067 b = obj.body() + "\n" 2068 if b: 2069 result.append(b) 2070 2071 return "\n".join(result) 2072 2073 2074class Package(object): 2075 copyright_header = "" 2076 # Can be overridden by applications to change the copyright header 2077 2078 def __init__(self, name, doc=[], isnested=False): 2079 """'doc' is a list of strings, where each string is a paragraph""" 2080 self.name = name 2081 self.doc = doc 2082 2083 self.sections = [] # [Section] 2084 self.spec_withs = dict() # "pkg" -> use:Boolean 2085 self.body_withs = dict() # "pkg" -> use:Boolean 2086 self.private = [] # Private section 2087 self.language_version = "" # a pragma to be put just after the headers 2088 self.formal_params = "" # generic formal parameters 2089 self.isnested = isnested 2090 2091 def __repr__(self): 2092 return "<Package %s>" % self.name 2093 2094 def section(self, name): 2095 """Return an existing section (or create a new one) with the given 2096 name. 2097 """ 2098 for s in self.sections: 2099 if s.name == name: 2100 return s 2101 2102 s = Section(self, name) 2103 self.sections.append(s) 2104 return s 2105 2106 def add_with(self, pkg, specs=True, do_use=True, might_be_unused=False): 2107 """Add a with+use clause for pkg, where pkg can also be a list. 2108 Automatic casing is performed. If specs is True, the withs are 2109 added to the specs of the package, otherwise to the body. 2110 2111 :param:`might_be_unused` True if the package might not be used and 2112 requires a pragma Warnings Off. 2113 """ 2114 if pkg in ("", "System"): 2115 return 2116 2117 if type(pkg) == str: 2118 pkg = [pkg] 2119 for p in pkg: 2120 if p.lower() == self.name.lower(): 2121 continue # No dependence on self 2122 2123 p_info = ( 2124 do_use or self.spec_withs.get(p, False), # do_use 2125 might_be_unused) 2126 2127 if specs: 2128 self.spec_withs[p] = p_info 2129 self.body_withs.pop(p, None) # Remove same with in body 2130 elif p not in self.spec_withs: 2131 self.body_withs[p] = p_info 2132 2133 def add_private(self, code, at_end=False): 2134 if at_end: 2135 self.private.append(code) 2136 else: 2137 self.private.insert(0, code) 2138 2139 def _output_withs(self, withs): 2140 if withs: 2141 result = [] 2142 m = max_length(withs) 2143 had_warnings_off = False 2144 2145 # sort so that all packages for which 'might_be_unused' is True 2146 # are last in the list 2147 2148 for w in sorted(withs.keys(), 2149 key=lambda w: 'zz%s' % w if withs[w][1] else w): 2150 do_use, might_be_unused = withs[w] 2151 2152 if might_be_unused and not had_warnings_off: 2153 result.append("pragma Warnings(Off); -- might be unused") 2154 had_warnings_off = True 2155 2156 if do_use: 2157 result.append( 2158 "with %-*s use %s;" % (m + 1, w + ";", w)) 2159 else: 2160 result.append("with %s;" % w) 2161 2162 if had_warnings_off: 2163 result.append("pragma Warnings(On);") 2164 2165 return "\n".join(result) + "\n" 2166 return "" 2167 2168 def section_order(self, name): 2169 """Return a numerical order for sections""" 2170 order = {"": 0, 2171 "Callbacks": 1, 2172 "Enumeration Properties": 2, 2173 2174 # Primitive operations first 2175 "Constructors": 3, 2176 "Methods": 4, 2177 "GtkAda additions": 5, 2178 "Inherited subprograms (from interfaces)": 6, 2179 2180 # Then non-primitive (so that we can freeze the type, for 2181 # instance by instantiating lists) 2182 "Functions": 8, 2183 "Lists": 9, 2184 2185 # General data independent of the type 2186 "Properties": 10, 2187 "Signals": 11, 2188 2189 # Instantiating new generic packages freezes the types, so 2190 # should be last 2191 "Interfaces": 12, 2192 } 2193 return order.get(name, 1000) 2194 2195 def spec(self): 2196 """Returns the spec of the package, in the file `out`""" 2197 2198 result = [] 2199 2200 if not self.isnested: 2201 indent = "" 2202 if Package.copyright_header: 2203 result.append(Package.copyright_header) 2204 2205 if self.language_version: 2206 result.append(self.language_version) 2207 2208 if self.doc: 2209 result.append(format_doc(self.doc, indent="")) 2210 2211 result.append("pragma Ada_2005;\n") 2212 result.append('pragma Warnings (Off, "*is already use-visible*");') 2213 result.append(self._output_withs(self.spec_withs)) 2214 2215 else: 2216 indent = " " 2217 2218 if self.formal_params: 2219 result.append(indent + "generic") 2220 result.append(indent + " %s" % self.formal_params) 2221 result.append(indent + "package %s is\n" % self.name) 2222 2223 self.sections.sort(lambda x, y: cmp(self.section_order(x.name), 2224 self.section_order(y.name))) 2225 2226 for s in self.sections: 2227 sec = s.spec(pkg=self, indent=indent + " ") 2228 if sec: 2229 result.append(sec.strip("\n") + "\n") 2230 2231 if self.private: 2232 result.append(indent + "private") 2233 result.extend(self.private) 2234 2235 result.append(indent + "end %s;" % self.name) 2236 return "\n".join(result) 2237 2238 def body(self): 2239 """Returns the body of the package""" 2240 2241 result = [] 2242 body = "" 2243 2244 if self.isnested: 2245 indent = " " 2246 else: 2247 indent = "" 2248 2249 for s in self.sections: 2250 b = s.body(pkg=self, indent=indent + " ") 2251 if b: 2252 body += "\n" + b 2253 2254 if not body: 2255 return "" 2256 2257 if not self.isnested: 2258 if Package.copyright_header: 2259 result.append(Package.copyright_header) 2260 2261 if self.language_version: 2262 result.append(self.language_version) 2263 2264 result.append("pragma Style_Checks (Off);") 2265 result.append('pragma Warnings (Off, "*is already use-visible*");') 2266 result.append(self._output_withs(self.body_withs)) 2267 2268 result.append(indent + "package body %s is" % self.name) 2269 result.append(body) 2270 result.append(indent + "end %s;" % self.name) 2271 return "\n".join(result) 2272