home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / adav313.zip / gnat-3_13p-os2-bin-20010916.zip / emx / gnatlib / a-tags.adb < prev    next >
Text File  |  2000-07-19  |  15KB  |  502 lines

  1. ------------------------------------------------------------------------------
  2. --                                                                          --
  3. --                         GNAT RUNTIME COMPONENTS                          --
  4. --                                                                          --
  5. --                             A D A . T A G S                              --
  6. --                                                                          --
  7. --                                 B o d y                                  --
  8. --                                                                          --
  9. --                            $Revision: 1.27 $
  10. --                                                                          --
  11. --          Copyright (C) 1992-2000 Free Software Foundation, Inc.          --
  12. --                                                                          --
  13. -- GNAT is free software;  you can  redistribute it  and/or modify it under --
  14. -- terms of the  GNU General Public License as published  by the Free Soft- --
  15. -- ware  Foundation;  either version 2,  or (at your option) any later ver- --
  16. -- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
  17. -- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
  18. -- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
  19. -- for  more details.  You should have  received  a copy of the GNU General --
  20. -- Public License  distributed with GNAT;  see file COPYING.  If not, write --
  21. -- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
  22. -- MA 02111-1307, USA.                                                      --
  23. --                                                                          --
  24. -- As a special exception,  if other files  instantiate  generics from this --
  25. -- unit, or you link  this unit with other files  to produce an executable, --
  26. -- this  unit  does not  by itself cause  the resulting  executable  to  be --
  27. -- covered  by the  GNU  General  Public  License.  This exception does not --
  28. -- however invalidate  any other reasons why  the executable file  might be --
  29. -- covered by the  GNU Public License.                                      --
  30. --                                                                          --
  31. -- GNAT was originally developed  by the GNAT team at  New York University. --
  32. -- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
  33. --                                                                          --
  34. ------------------------------------------------------------------------------
  35.  
  36. with Ada.Exceptions;
  37. with Unchecked_Conversion;
  38. with GNAT.HTable;
  39.  
  40. pragma Elaborate_All (GNAT.HTable);
  41.  
  42. package body Ada.Tags is
  43.  
  44. --  Structure of the GNAT Dispatch Table
  45.  
  46. --   +----------------------+
  47. --   |      TSD pointer  ---|-----> Type Specific Data
  48. --   +----------------------+       +-------------------+
  49. --   | table of             |       | inheritance depth |
  50. --   :   primitive ops      :       +-------------------+
  51. --   |     pointers         |       |   expanded name   |
  52. --   +----------------------+       +-------------------+
  53. --                                  |   external tag    |
  54. --                                  +-------------------+
  55. --                                  |   Hash table link |
  56. --                                  +-------------------+
  57. --                                  | Remotely Callable |
  58. --                                  +-------------------+
  59. --                                  | Rec Ctrler offset |
  60. --                                  +-------------------+
  61. --                                  | table of          |
  62. --                                  :   ancestor        :
  63. --                                  |      tags         |
  64. --                                  +-------------------+
  65.  
  66.    use System;
  67.  
  68.    subtype Cstring is String (Positive);
  69.    type Cstring_Ptr is access all Cstring;
  70.    type Tag_Table is array (Natural range <>) of Tag;
  71.    pragma Suppress_Initialization (Tag_Table);
  72.  
  73.    type Wide_Boolean is (False, True);
  74.    for Wide_Boolean'Size use Standard'Address_Size;
  75.  
  76.    type Type_Specific_Data is record
  77.       Idepth             : Natural;
  78.       Expanded_Name      : Cstring_Ptr;
  79.       External_Tag       : Cstring_Ptr;
  80.       HT_Link            : Tag;
  81.       Remotely_Callable  : Wide_Boolean;
  82.       RC_Offset          : SSE.Storage_Offset;
  83.       Ancestor_Tags      : Tag_Table (Natural);
  84.    end record;
  85.  
  86.  
  87.    type Dispatch_Table is record
  88.       TSD       : Type_Specific_Data_Ptr;
  89.       Prims_Ptr : Address_Array (Positive);
  90.    end record;
  91.  
  92.    -------------------------------------------
  93.    -- Unchecked Conversions for Tag and TSD --
  94.    -------------------------------------------
  95.  
  96.    function To_Type_Specific_Data_Ptr is
  97.      new Unchecked_Conversion (Address, Type_Specific_Data_Ptr);
  98.  
  99.    function To_Address is new Unchecked_Conversion (Tag, Address);
  100.    function To_Address is
  101.      new Unchecked_Conversion (Type_Specific_Data_Ptr, Address);
  102.  
  103.    ---------------------------------------------
  104.    -- Unchecked Conversions for String Fields --
  105.    ---------------------------------------------
  106.  
  107.    function To_Cstring_Ptr is
  108.      new Unchecked_Conversion (Address, Cstring_Ptr);
  109.  
  110.    function To_Address is
  111.      new Unchecked_Conversion (Cstring_Ptr, Address);
  112.  
  113.    -----------------------
  114.    -- Local Subprograms --
  115.    -----------------------
  116.  
  117.    function Length (Str : Cstring_Ptr) return Natural;
  118.    --  Length of string represented by the given pointer (treating the
  119.    --  string as a C-style string, which is Nul terminated).
  120.  
  121.    -------------------------
  122.    -- External_Tag_HTable --
  123.    -------------------------
  124.  
  125.    type HTable_Headers is range 1 .. 64;
  126.  
  127.    procedure Set_HT_Link (T : Tag; Next : Tag);
  128.    function  Get_HT_Link (T : Tag) return Tag;
  129.  
  130.    function Hash (F : Address) return HTable_Headers;
  131.    function Equal (A, B : Address) return Boolean;
  132.  
  133.    package External_Tag_HTable is new GNAT.HTable.Static_HTable (
  134.      Header_Num => HTable_Headers,
  135.      Element    => Dispatch_Table,
  136.      Elmt_Ptr   => Tag,
  137.      Null_Ptr   => null,
  138.      Set_Next   => Set_HT_Link,
  139.      Next       => Get_HT_Link,
  140.      Key        => Address,
  141.      Get_Key    => Get_External_Tag,
  142.      Hash       => Hash,
  143.      Equal      => Equal);
  144.  
  145.    --  Subprograms for above instantiation
  146.  
  147.    function Equal (A, B : Address) return Boolean is
  148.       Str1 : Cstring_Ptr := To_Cstring_Ptr (A);
  149.       Str2 : Cstring_Ptr := To_Cstring_Ptr (B);
  150.       J    : Integer := 1;
  151.  
  152.    begin
  153.       loop
  154.          if Str1 (J) /= Str2 (J) then
  155.             return False;
  156.  
  157.          elsif Str1 (J) = ASCII.NUL then
  158.             return True;
  159.  
  160.          else
  161.             J := J + 1;
  162.          end if;
  163.       end loop;
  164.    end Equal;
  165.  
  166.    function Get_HT_Link (T : Tag) return Tag is
  167.    begin
  168.       return T.TSD.HT_Link;
  169.    end Get_HT_Link;
  170.  
  171.    function Hash (F : Address) return HTable_Headers is
  172.       function H is new GNAT.HTable.Hash (HTable_Headers);
  173.       Str : Cstring_Ptr := To_Cstring_Ptr (F);
  174.       Res : constant HTable_Headers := H (Str (1 .. Length (Str)));
  175.  
  176.    begin
  177.       return Res;
  178.    end Hash;
  179.  
  180.    procedure Set_HT_Link (T : Tag; Next : Tag) is
  181.    begin
  182.       T.TSD.HT_Link := Next;
  183.    end Set_HT_Link;
  184.  
  185.    ----------------
  186.    -- Inherit_DT --
  187.    ----------------
  188.  
  189.    procedure Inherit_DT
  190.     (Old_T   : Tag;
  191.      New_T   : Tag;
  192.      Entry_Count : Natural)
  193.    is
  194.    begin
  195.       if Old_T /= null then
  196.          New_T.Prims_Ptr (1 .. Entry_Count) :=
  197.            Old_T.Prims_Ptr (1 .. Entry_Count);
  198.       end if;
  199.    end Inherit_DT;
  200.  
  201.    --------------------
  202.    --  CW_Membership --
  203.    --------------------
  204.  
  205.    --  Canonical implementation of Classwide Membership corresponding to:
  206.  
  207.    --     Obj in Typ'Class
  208.  
  209.    --  Each dispatch table contains a reference to a table of ancestors
  210.    --  (Ancestor_Tags) and a count of the level of inheritance "Idepth" .
  211.  
  212.    --  Obj is in Typ'Class if Typ'Tag is in the table of ancestors that are
  213.    --  contained in the dispatch table referenced by Obj'Tag . Knowing the
  214.    --  level of inheritance of both types, this can be computed in constant
  215.    --  time by the formula:
  216.  
  217.    --   Obj'tag.TSD.Ancestor_Tags (Obj'tag.TSD.Idepth - Typ'tag.TSD.Idepth)
  218.    --     = Typ'tag
  219.  
  220.    function CW_Membership (Obj_Tag : Tag; Typ_Tag : Tag) return Boolean is
  221.       Pos : constant Integer := Obj_Tag.TSD.Idepth - Typ_Tag.TSD.Idepth;
  222.  
  223.    begin
  224.       return Pos >= 0 and then Obj_Tag.TSD.Ancestor_Tags (Pos) = Typ_Tag;
  225.    end CW_Membership;
  226.  
  227.    -------------------
  228.    -- Expanded_Name --
  229.    -------------------
  230.  
  231.    function Expanded_Name (T : Tag) return String is
  232.       Result : Cstring_Ptr := T.TSD.Expanded_Name;
  233.  
  234.    begin
  235.       return Result (1 .. Length (Result));
  236.    end Expanded_Name;
  237.  
  238.    ------------------
  239.    -- External_Tag --
  240.    ------------------
  241.  
  242.    function External_Tag (T : Tag) return String is
  243.       Result : Cstring_Ptr := T.TSD.External_Tag;
  244.  
  245.    begin
  246.       return Result (1 .. Length (Result));
  247.    end External_Tag;
  248.  
  249.    -----------------------
  250.    -- Get_Expanded_Name --
  251.    -----------------------
  252.  
  253.    function Get_Expanded_Name (T : Tag) return Address is
  254.    begin
  255.       return To_Address (T.TSD.Expanded_Name);
  256.    end Get_Expanded_Name;
  257.  
  258.    ----------------------
  259.    -- Get_External_Tag --
  260.    ----------------------
  261.  
  262.    function Get_External_Tag (T : Tag) return Address is
  263.    begin
  264.       return To_Address (T.TSD.External_Tag);
  265.    end Get_External_Tag;
  266.  
  267.    ---------------------------
  268.    -- Get_Inheritance_Depth --
  269.    ---------------------------
  270.  
  271.    function Get_Inheritance_Depth (T : Tag) return Natural is
  272.    begin
  273.       return T.TSD.Idepth;
  274.    end Get_Inheritance_Depth;
  275.  
  276.    -------------------------
  277.    -- Get_Prim_Op_Address --
  278.    -------------------------
  279.  
  280.    function Get_Prim_Op_Address
  281.      (T        : Tag;
  282.       Position : Positive)
  283.       return     Address
  284.    is
  285.    begin
  286.       return T.Prims_Ptr (Position);
  287.    end Get_Prim_Op_Address;
  288.  
  289.    ---------------------------
  290.    -- Get_Remotely_Callable --
  291.    ---------------------------
  292.  
  293.    function Get_Remotely_Callable (T : Tag) return Boolean is
  294.    begin
  295.       return T.TSD.Remotely_Callable = True;
  296.    end Get_Remotely_Callable;
  297.  
  298.    -------------------
  299.    -- Get_RC_Offset --
  300.    -------------------
  301.  
  302.    function Get_RC_Offset (T : Tag) return SSE.Storage_Offset is
  303.    begin
  304.       return T.TSD.RC_Offset;
  305.    end Get_RC_Offset;
  306.  
  307.    -------------
  308.    -- Get_TSD --
  309.    -------------
  310.  
  311.    function Get_TSD  (T : Tag) return Address is
  312.    begin
  313.       return To_Address (T.TSD);
  314.    end Get_TSD;
  315.  
  316.    -----------------
  317.    -- Inherit_TSD --
  318.    -----------------
  319.  
  320.    procedure Inherit_TSD (Old_TSD : Address; New_Tag : Tag) is
  321.       TSD     : constant Type_Specific_Data_Ptr :=
  322.                   To_Type_Specific_Data_Ptr (Old_TSD);
  323.       New_TSD : Type_Specific_Data renames New_Tag.TSD.all;
  324.  
  325.    begin
  326.       if TSD /= null then
  327.          New_TSD.Idepth := TSD.Idepth + 1;
  328.          New_TSD.Ancestor_Tags (1 .. New_TSD.Idepth)
  329.                             := TSD.Ancestor_Tags (0 .. TSD.Idepth);
  330.       else
  331.          New_TSD.Idepth := 0;
  332.       end if;
  333.  
  334.       New_TSD.Ancestor_Tags (0) := New_Tag;
  335.    end Inherit_TSD;
  336.  
  337.    ------------------
  338.    -- Internal_Tag --
  339.    ------------------
  340.  
  341.    function Internal_Tag (External : String) return Tag is
  342.       Ext_Copy : aliased String (External'First .. External'Last + 1);
  343.       Res      : Tag;
  344.  
  345.    begin
  346.  
  347.       --  Make a copy of the string representing the external tag with
  348.       --  a null at the end
  349.  
  350.       Ext_Copy (External'Range) := External;
  351.       Ext_Copy (Ext_Copy'Last) := ASCII.NUL;
  352.       Res := External_Tag_HTable.Get (Ext_Copy'Address);
  353.  
  354.       if Res = null then
  355.          Ada.Exceptions.Raise_Exception
  356.            (Tag_Error'Identity,
  357.             "unknown tagged type: " & External);
  358.       end if;
  359.  
  360.       return Res;
  361.    end Internal_Tag;
  362.  
  363.    ------------
  364.    -- Length --
  365.    ------------
  366.  
  367.    function Length (Str : Cstring_Ptr) return Natural is
  368.       Len : Integer := 1;
  369.  
  370.    begin
  371.       while Str (Len) /= ASCII.Nul loop
  372.          Len := Len + 1;
  373.       end loop;
  374.  
  375.       return Len - 1;
  376.    end Length;
  377.  
  378.    ------------------
  379.    -- Register_Tag --
  380.    ------------------
  381.  
  382.    procedure Register_Tag (T : Tag) is
  383.    begin
  384.       External_Tag_HTable.Set (T);
  385.    end Register_Tag;
  386.  
  387.    -----------------------
  388.    -- Set_Expanded_Name --
  389.    -----------------------
  390.  
  391.    procedure Set_Expanded_Name (T : Tag; Value : Address) is
  392.    begin
  393.       T.TSD.Expanded_Name := To_Cstring_Ptr (Value);
  394.    end Set_Expanded_Name;
  395.  
  396.    ----------------------
  397.    -- Set_External_Tag --
  398.    ----------------------
  399.  
  400.    procedure Set_External_Tag (T : Tag; Value : Address) is
  401.    begin
  402.       T.TSD.External_Tag := To_Cstring_Ptr (Value);
  403.    end Set_External_Tag;
  404.  
  405.    ---------------------------
  406.    -- Set_Inheritance_Depth --
  407.    ---------------------------
  408.  
  409.    procedure Set_Inheritance_Depth
  410.      (T     : Tag;
  411.       Value : Natural)
  412.    is
  413.    begin
  414.       T.TSD.Idepth := Value;
  415.    end Set_Inheritance_Depth;
  416.  
  417.    -------------------------
  418.    -- Set_Prim_Op_Address --
  419.    -------------------------
  420.  
  421.    procedure Set_Prim_Op_Address
  422.      (T        : Tag;
  423.       Position : Positive;
  424.       Value    : Address)
  425.    is
  426.    begin
  427.       T.Prims_Ptr (Position) := Value;
  428.    end Set_Prim_Op_Address;
  429.  
  430.    -------------------
  431.    -- Set_RC_Offset --
  432.    -------------------
  433.  
  434.    procedure Set_RC_Offset (T : Tag; Value : SSE.Storage_Offset) is
  435.    begin
  436.       T.TSD.RC_Offset := Value;
  437.    end Set_RC_Offset;
  438.  
  439.    ---------------------------
  440.    -- Set_Remotely_Callable --
  441.    ---------------------------
  442.  
  443.    procedure Set_Remotely_Callable (T : Tag; Value : Boolean) is
  444.    begin
  445.       if Value then
  446.          T.TSD.Remotely_Callable := True;
  447.       else
  448.          T.TSD.Remotely_Callable := False;
  449.       end if;
  450.    end Set_Remotely_Callable;
  451.  
  452.    -------------
  453.    -- Set_TSD --
  454.    -------------
  455.  
  456.    procedure Set_TSD (T : Tag; Value : Address) is
  457.    begin
  458.       T.TSD := To_Type_Specific_Data_Ptr (Value);
  459.    end Set_TSD;
  460.  
  461.    -----------------
  462.    -- Parent_Size --
  463.    -----------------
  464.  
  465.    --  fake type with a tag as first component. Should match the layout of
  466.    --  all tagged types.
  467.  
  468.    type T is record
  469.       A : Tag;
  470.    end record;
  471.    type T_Ptr is access all T;
  472.    function To_T_Ptr is new Unchecked_Conversion (Address, T_Ptr);
  473.  
  474.  
  475.    --  The profile of the implicitly defined _size primitive
  476.  
  477.    type Acc_Size is access function (A : Address) return Long_Long_Integer;
  478.    function To_Acc_Size is new Unchecked_Conversion (Address, Acc_Size);
  479.  
  480.    function Parent_Size (Obj : Address) return SSE.Storage_Count is
  481.  
  482.       --  Get the tag of the object
  483.  
  484.       Obj_Tag    : constant Tag      := To_T_Ptr (Obj).A;
  485.  
  486.       --  Get the tag of the parent type through the dispatch table
  487.  
  488.       Parent_Tag : constant Tag      := Obj_Tag.TSD.Ancestor_Tags (1);
  489.  
  490.       --  Get an access to the _size primitive of the parent. We assume that
  491.       --  it is always in the first slot of the distatch table
  492.  
  493.       F          : constant Acc_Size := To_Acc_Size (Parent_Tag.Prims_Ptr (1));
  494.  
  495.    begin
  496.  
  497.       --  Here we compute the size of the _parent field of the object
  498.  
  499.       return SSE.Storage_Count (F.all (Obj));
  500.    end Parent_Size;
  501. end Ada.Tags;
  502.