Changeset 2616

Show
Ignore:
Timestamp:
02/01/08 17:19:42 (1 year ago)
Author:
ogorod
Message:

partial implemented
Semantic_Dependence_Order (Ancestors | Descendants)

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/tendra/src/producers/ada/asis/asis-compilation_units-relations.adb

    r2455 r2616  
    1313with Asis.Exceptions; 
    1414with Asis.Implementation; 
     15with Asis.Ada_Environments; 
     16 
     17with Ada.Finalization; 
     18with Ada.Unchecked_Deallocation; 
     19with System; 
    1520 
    1621package body Asis.Compilation_Units.Relations is 
    1722 
    18    ----------------------- 
    19    -- Elaboration_Order -- 
    20    ----------------------- 
     23   package Utils is 
     24 
     25      --  Compilation_Unit_List_Access  -- 
     26      type Compilation_Unit_List_Access is 
     27        access all Compilation_Unit_List; 
     28 
     29      procedure Deallocate is 
     30        new Ada.Unchecked_Deallocation 
     31          (Compilation_Unit_List, Compilation_Unit_List_Access); 
     32 
     33      function In_List 
     34        (List : in Compilation_Unit_List_Access; 
     35         Last : in ASIS_Integer; 
     36         Unit : in Compilation_Unit) 
     37         return Boolean; 
     38 
     39      procedure Remove_From_List 
     40        (List : in out Compilation_Unit_List; 
     41         From : in     List_Index; 
     42         Unit : in     Compilation_Unit); 
     43 
     44      function Append 
     45        (List : in Compilation_Unit_List_Access; 
     46         Unit : in Compilation_Unit) 
     47         return Compilation_Unit_List_Access; 
     48 
     49      function Append 
     50        (List  : in Compilation_Unit_List_Access; 
     51         Units : in Compilation_Unit_List) 
     52         return Compilation_Unit_List_Access; 
     53 
     54      --  Tree_Node  -- 
     55      type Tree_Node is 
     56        new Ada.Finalization.Limited_Controlled with private; 
     57 
     58      type Tree_Node_Access is access all Tree_Node; 
     59 
     60      function Is_Empty 
     61        (This : in Tree_Node) 
     62         return Boolean; 
     63 
     64      function Append_Parent 
     65        (This : in Tree_Node_Access; 
     66         Unit : in Compilation_Unit) 
     67         return Tree_Node_Access; 
     68 
     69      procedure Add_Tread 
     70        (This      : in     Tree_Node_Access; 
     71         To_Node   : in     Tree_Node_Access; 
     72         From_Tree : in out Tree_Node_Access); 
     73 
     74      function Add_Child 
     75        (This      : in Tree_Node_Access; 
     76         Node      : in Tree_Node_Access; 
     77         Spec_Unit : in Compilation_Unit; 
     78         Body_Unit : in Compilation_Unit) 
     79         return Tree_Node_Access; 
     80 
     81      procedure Glue_Nodes 
     82        (This    : in Tree_Node_Access; 
     83         Node    : in Tree_Node_Access; 
     84         To_Node : in Tree_Node_Access); 
     85 
     86      procedure Clear 
     87        (This : in out Tree_Node); 
     88 
     89      function Find 
     90        (This : in Tree_Node; 
     91         Unit : in Compilation_Unit) 
     92         return Tree_Node_Access; 
     93 
     94      function Close_Find 
     95        (This : in Tree_Node; 
     96         Unit : in Compilation_Unit) 
     97         return Tree_Node_Access; 
     98 
     99      type Orders is (From_Child, From_Parent); 
     100 
     101      function Generate_Relationship 
     102        (This  : in Tree_Node_Access; 
     103         Order : in Orders) 
     104         return Relationship; 
     105 
     106      Use_Error : exception; 
     107 
     108   private 
     109 
     110      type Tree_Node_Array is array (Positive range <>) of Tree_Node_Access; 
     111      type Tree_Node_Array_Access is access all Tree_Node_Array; 
     112 
     113      type Unit_Node is record 
     114         Unit : Compilation_Unit; 
     115         Node : Tree_Node_Access; 
     116      end record; 
     117 
     118      type Unit_Node_Array is array (Positive range <>) of Unit_Node; 
     119      type Unit_Node_Array_Access is access all Unit_Node_Array; 
     120 
     121      type Tree_Node is 
     122        new Ada.Finalization.Limited_Controlled with record 
     123         Self : Tree_Node_Access := Tree_Node'Unchecked_Access; 
     124 
     125         --  ссылка Ма преЎыЎущОй елеЌеМт 
     126         Prev : Tree_Node_Access := null; 
     127 
     128         --  ЌПЎуль_кПЌпОляцОО 
     129         Unit      : Compilation_Unit := Nil_Compilation_Unit; 
     130         Unit_Body : Compilation_Unit := Nil_Compilation_Unit; 
     131 
     132         --  пПслеЎующОе елеЌеМты 0-Ñ 
     133 
     134         Next : Tree_Node_Array_Access := null; 
     135 
     136         --  спОсПк ПкПМчаМОя "ветвей", 
     137         --  Ўля быстрПгП ОзыЌаМОя ПМыѠ
     138 
     139         --  а Ме перебПрПЌ всеѠ
     140 Ð²ÐµÑ‚вей 
     141         --  запПлМяет тПлькП кПрМевПй елеЌеМт 
     142         Last_Nodes : Tree_Node_Array_Access := null; 
     143 
     144         --  сПртОрПваММый спОсПк всеѠ
     145 
     146         --  елеЌеМтПв Ўля быстрПгП 
     147         --  ПпреЎелеМОя МалОчОя елеЌеМта 
     148         --  в спОске 
     149         --  запПлМяет тПлькП кПрМевПй елеЌеМт 
     150         Units : Unit_Node_Array_Access := null; 
     151 
     152         Circular       : Compilation_Unit_List_Access := null; 
     153         Circular_Added : Boolean := False; 
     154 
     155         Missing       : Compilation_Unit_List_Access := null; 
     156         Missing_Added : Boolean := False; 
     157 
     158         Added : Boolean := False; 
     159      end record; 
     160 
     161      procedure Finalize 
     162        (This : in out Tree_Node); 
     163 
     164      procedure Deallocate is 
     165        new Ada.Unchecked_Deallocation 
     166          (Unit_Node_Array, Unit_Node_Array_Access); 
     167 
     168      type Positive_Access is access all Positive; 
     169 
     170      function Add_Node 
     171        (List : in Tree_Node_Array_Access; 
     172         Node : in Tree_Node_Access) 
     173         return Tree_Node_Array_Access; 
     174 
     175      function Add_Node_Ordered 
     176        (List : in Unit_Node_Array_Access; 
     177         Node : in Tree_Node_Access) 
     178         return Unit_Node_Array_Access; 
     179 
     180      function Find 
     181        (List  : in Unit_Node_Array_Access; 
     182         Unit  : in Compilation_Unit; 
     183         From  : in Positive; 
     184         To    : in Positive; 
     185         Index : in Positive_Access) 
     186         return Boolean; 
     187 
     188      function Compare 
     189        (Left  : in Compilation_Unit; 
     190         Right : in Compilation_Unit) 
     191         return Integer; 
     192 
     193   end Utils; 
     194 
     195   procedure Deallocate is 
     196     new Ada.Unchecked_Deallocation 
     197       (Utils.Tree_Node, Utils.Tree_Node_Access); 
     198 
     199   function Get_Ancestors 
     200     (List        : in Asis.Compilation_Unit_List; 
     201      The_Context : in Asis.Context) 
     202      return Utils.Tree_Node_Access; 
     203 
     204   function Get_Descendants 
     205     (List        : in Asis.Compilation_Unit_List; 
     206      The_Context : in Asis.Context) 
     207      return Utils.Tree_Node_Access; 
     208 
     209   ------------------------- 
     210   --  Elaboration_Order  -- * 
     211   ------------------------- 
    21212 
    22213   function Elaboration_Order 
     
    30221      raise Asis.Exceptions.ASIS_Failed; 
    31222 
    32       return Elaboration_Order (Compilation_Units, The_Context)
     223      return Nil_Relationship
    33224   end Elaboration_Order; 
    34225 
    35    ------------------------------- 
    36    -- Semantic_Dependence_Order -- 
    37    ------------------------------- 
     226   --------------------------------- 
     227   -- Semantic_Dependence_Order  -- * 
     228   --------------------------------- 
    38229 
    39230   function Semantic_Dependence_Order 
     
    44235      return Relationship 
    45236   is 
     237      Current_Unit_Kind : Asis.Unit_Kinds; 
     238 
     239      -- Check_Compilation_Unit -- 
     240      procedure Check_Compilation_Unit 
     241         (Unit    : in Compilation_Unit; 
     242          Message : in Wide_String) 
     243      is 
     244      begin 
     245         Current_Unit_Kind := Unit_Kind (Unit); 
     246 
     247         if Current_Unit_Kind = Not_A_Unit 
     248            or else Current_Unit_Kind = A_Nonexistent_Declaration 
     249            or else Current_Unit_Kind = A_Nonexistent_Body 
     250            or else Current_Unit_Kind = A_Configuration_Compilation 
     251         then 
     252            Asis.Implementation.Set_Status 
     253              (Data_Error, "Semantic_Dependence_Order " 
     254               & Message & " invalid"); 
     255 
     256            raise Asis.Exceptions.ASIS_Inappropriate_Compilation_Unit; 
     257         end if; 
     258 
     259         if not Asis.Ada_Environments.Is_Equal 
     260           (Enclosing_Context (Unit), The_Context) 
     261         then 
     262            Asis.Implementation.Set_Status 
     263              (Data_Error, "Semantic_Dependence_Order " 
     264               & Message & " invalid context"); 
     265 
     266            raise Asis.Exceptions.ASIS_Inappropriate_Compilation_Unit; 
     267         end if; 
     268      end Check_Compilation_Unit; 
     269 
     270      Compilation_Units_Last : ASIS_Integer := 0; 
     271 
     272      Normalized_Compilation_Units : 
     273         Utils.Compilation_Unit_List_Access := null; 
     274 
     275      Dependent_Units_Last : ASIS_Integer := 0; 
     276 
     277      Normalized_Dependent_Units : 
     278         Utils.Compilation_Unit_List_Access := null; 
     279 
     280      -- Normalize -- 
     281      procedure Normalize 
     282         (List   : in     Asis.Compilation_Unit_List; 
     283          Result : in     Utils.Compilation_Unit_List_Access; 
     284          Last   :    out ASIS_Integer) 
     285      is 
     286         Unit : Compilation_Unit; 
     287      begin 
     288         Last := 0; 
     289 
     290         for Index in List'Range loop 
     291            Unit := List (Index); 
     292 
     293            if Assigned (Unit) 
     294               and then Unit_Kind (Unit) /= An_Unknown_Unit 
     295            then 
     296               if not Utils.In_List (Result, Last, Unit) then 
     297                  Last := Last + 1; 
     298                  Result (Last) := List (Index); 
     299               end if; 
     300            end if; 
     301         end loop; 
     302      end Normalize; 
     303 
     304      Tree   : Utils.Tree_Node_Access := null; 
     305      Result : Relationship := Nil_Relationship; 
    46306   begin 
    47       Asis.Implementation.Set_Status 
    48         (Not_Implemented_Error, "Semantic_Dependence_Order not implemented"); 
    49       raise Asis.Exceptions.ASIS_Failed; 
    50  
    51       return Semantic_Dependence_Order 
    52         (Compilation_Units, Dependent_Units, The_Context, Relation); 
     307      if Compilation_Units = Nil_Compilation_Unit_List then 
     308         return Nil_Relationship; 
     309      end if; 
     310 
     311      for Index in Compilation_Units'Range loop 
     312         Check_Compilation_Unit 
     313           (Compilation_Units (Index), "Compilation_Unit"); 
     314      end loop; 
     315 
     316      Normalized_Compilation_Units := new 
     317        Asis.Compilation_Unit_List (1 .. Compilation_Units'Length); 
     318 
     319      Normalized_Compilation_Units.all := (others => Nil_Compilation_Unit); 
     320 
     321      Normalize (Compilation_Units, 
     322                 Normalized_Compilation_Units, 
     323                 Compilation_Units_Last); 
     324 
     325      --  Dependent_Units are ignored unless the Relation 
     326      --  is Descendants or Dependents 
     327      if Relation = Descendants 
     328         or else Relation = Dependents 
     329      then 
     330         for Index in Dependent_Units'Range loop 
     331            Check_Compilation_Unit (Dependent_Units (Index), "Dependent_Unit"); 
     332         end loop; 
     333 
     334         Normalized_Dependent_Units := new 
     335           Asis.Compilation_Unit_List (1 .. Dependent_Units'Length); 
     336 
     337         Normalized_Dependent_Units.all := (others => Nil_Compilation_Unit); 
     338 
     339         Normalize (Dependent_Units, 
     340                    Normalized_Dependent_Units, 
     341                    Dependent_Units_Last); 
     342      end if; 
     343 
     344      case Relation is 
     345         when Ancestors => 
     346            Tree := Get_Ancestors 
     347              (Normalized_Compilation_Units (1 .. Compilation_Units_Last), 
     348               The_Context); 
     349 
     350            Result := Utils.Generate_Relationship (Tree, Utils.From_Child); 
     351 
     352         when Descendants => 
     353            Tree := Get_Descendants 
     354              (Normalized_Compilation_Units (1 .. Compilation_Units_Last), 
     355               The_Context); 
     356 
     357            Result := Utils.Generate_Relationship (Tree, Utils.From_Parent); 
     358 
     359            raise Asis.Exceptions.ASIS_Failed; 
     360 
     361         when Supporters => 
     362            Asis.Implementation.Set_Status 
     363              (Not_Implemented_Error, 
     364               "Semantic_Dependence_Order not implemented"); 
     365 
     366            raise Asis.Exceptions.ASIS_Failed; 
     367 
     368         when Dependents => 
     369            Asis.Implementation.Set_Status 
     370              (Not_Implemented_Error, 
     371               "Semantic_Dependence_Order not implemented"); 
     372 
     373            raise Asis.Exceptions.ASIS_Failed; 
     374 
     375         when Family => 
     376            Asis.Implementation.Set_Status 
     377              (Not_Implemented_Error, 
     378               "Semantic_Dependence_Order not implemented"); 
     379            raise Asis.Exceptions.ASIS_Failed; 
     380 
     381         when Needed_Units => 
     382            Asis.Implementation.Set_Status 
     383              (Not_Implemented_Error, 
     384               "Semantic_Dependence_Order not implemented"); 
     385            raise Asis.Exceptions.ASIS_Failed; 
     386      end case; 
     387 
     388      Deallocate (Tree); 
     389      Utils.Deallocate (Normalized_Compilation_Units); 
     390      Utils.Deallocate (Normalized_Dependent_Units); 
     391 
     392      return Result; 
     393 
     394   exception 
     395      when others => 
     396         Deallocate (Tree); 
     397         Utils.Deallocate (Normalized_Compilation_Units); 
     398         Utils.Deallocate (Normalized_Dependent_Units); 
     399 
     400         raise; 
    53401   end Semantic_Dependence_Order; 
    54402 
     403   ------------------- 
     404   -- Get_Ancestors -- 
     405   ------------------- 
     406 
     407   function Get_Ancestors 
     408     (List        : in Asis.Compilation_Unit_List; 
     409      The_Context : in Asis.Context) 
     410      return Utils.Tree_Node_Access 
     411   is 
     412      use Utils; 
     413 
     414      Unit  : Compilation_Unit; 
     415      Kinds : Unit_Kinds; 
     416 
     417      Result   : Tree_Node_Access := null; 
     418      Tmp_Tree : Tree_Node_Access := new Tree_Node; 
     419      Node     : Tree_Node_Access := null; 
     420 
     421      -- Append_Node -- 
     422      function Append_Node 
     423        (Unit : in Compilation_Unit) 
     424         return Boolean 
     425      is 
     426      begin 
     427         if Result /= null then 
     428            Node := Find (Result.all, Unit); 
     429         else 
     430            Node := null; 
     431         end if; 
     432 
     433         if Node /= null then 
     434            Add_Tread (Result, Node, Tmp_Tree); 
     435            Tmp_Tree := new Tree_Node; 
     436            return True; 
     437         else 
     438            Tmp_Tree := Append_Parent (Tmp_Tree, Unit); 
     439            return False; 
     440         end if; 
     441      end Append_Node; 
     442 
     443      -- Retrive_Declarations -- 
     444      procedure Retrive_Declarations is 
     445      begin 
     446         Kinds := Unit_Kind (Unit); 
     447 
     448         while Kinds in A_Procedure .. A_Generic_Package_Renaming loop 
     449            if Append_Node (Unit) then 
     450               return; 
     451            end if; 
     452 
     453            Unit  := Corresponding_Parent_Declaration (Unit); 
     454            Kinds := Unit_Kind (Unit); 
     455         end loop; 
     456 
     457         if not Is_Nil (Unit) then 
     458            if Append_Node (Unit) then 
     459               return; 
     460            end if; 
     461 
     462            --  add Standart as root 
     463            if Append_Node 
     464              (Compilation_Unit_Body ("Standard", The_Context)) 
     465            then 
     466               return; 
     467            end if; 
     468         end if; 
     469      end Retrive_Declarations; 
     470 
     471      --  Retrive_Subunit  -- 
     472      procedure Retrive_Subunit is 
     473      begin 
     474         --  RM 10.1.3 (8/2) 
     475         if Append_Node (Unit) then 
     476            return; 
     477         end if; 
     478 
     479         loop 
     480            Unit := Corresponding_Subunit_Parent_Body (Unit); 
     481            exit when Unit_Kind (Unit) not in A_Subunit; 
     482            if Append_Node (Unit) then 
     483               return; 
     484            end if; 
     485         end loop; 
     486 
     487         if Append_Node (Unit) then 
     488            return; 
     489         end if; 
     490 
     491         if Unit_Kind (Unit) /= A_Nonexistent_Body then 
     492            Unit := Corresponding_Parent_Declaration (Unit, The_Context); 
     493            Retrive_Declarations; 
     494         else 
     495            --  add Standart as root 
     496            if Append_Node 
     497              (Compilation_Unit_Body ("Standard", The_Context)) 
     498            then 
     499               return; 
     500            end if; 
     501         end if; 
     502      end Retrive_Subunit; 
     503 
     504   begin 
     505      for Index in List'Range loop 
     506         Clear (Tmp_Tree.all); 
     507         Unit  := List (Index); 
     508         Kinds := Unit_Kind (Unit); 
     509 
     510         if Kinds in A_Subunit then 
     511            Retrive_Subunit; 
     512 
     513         elsif Kinds in A_Library_Unit_Body then 
     514            Unit := Corresponding_Parent_Declaration (Unit, The_Context); 
     515            Retrive_Declarations; 
     516 
     517         else 
     518            Retrive_Declarations; 
     519         end if; 
     520 
     521         if Result = null then 
     522            Result := Tmp_Tree; 
     523         end if; 
     524      end loop; 
     525 
     526      Deallocate (Tmp_Tree); 
     527      return Result; 
     528   exception 
     529      when others => 
     530         Deallocate (Tmp_Tree); 
     531         Deallocate (Result); 
     532         raise; 
     533   end Get_Ancestors; 
     534 
     535   --------------------- 
     536   -- Get_Descendants -- 
     537   --------------------- 
     538 
     539   function Get_Descendants 
     540     (List        : in Asis.Compilation_Unit_List; 
     541      The_Context : in Asis.Context) 
     542      return Utils.Tree_Node_Access 
     543   is 
     544      use Utils; 
     545 
     546      Result : Tree_Node_Access := new Tree_Node; 
     547      Unit   : Compilation_Unit; 
     548      Kinds  : Unit_Kinds; 
     549 
     550      -- Retrive -- 
     551      procedure Retrive 
     552        (Target : in Compilation_Unit; 
     553         Node   : in Utils.Tree_Node_Access) 
     554      is 
     555         Children_List : Asis.Compilation_Unit_List := 
     556           Corresponding_Children (Target, The_Context); 
     557         Exist_Node : Utils.Tree_Node_Access; 
     558 
     559         Second_Unit : Compilation_Unit; 
     560      begin 
     561         for Index in Children_List'Range loop 
     562            Unit := Children_List (Index); 
     563 
     564            if not Is_Nil (Unit) then 
     565               Exist_Node := null; 
     566 
     567               if Node /= null then 
     568                  Exist_Node := Close_Find (Node.all, Unit); 
     569               end if; 
     570 
     571               if Exist_Node = null then 
     572                  Exist_Node := Find (Result.all, Unit); 
     573 
     574                  if Exist_Node = null then 
     575                     Kinds := Unit_Kind (Unit); 
     576 
     577                     if Kinds in 
     578                       A_Procedure_Instance .. A_Generic_Package_Renaming 
     579                     then 
     580                        Exist_Node := Add_Child (Result, Node, Unit, null); 
     581 
     582                     elsif Kinds in A_Procedure .. A_Generic_Package then 
     583                        Second_Unit := Corresponding_Body (Unit, The_Context); 
     584 
     585                        Exist_Node := Add_Child 
     586                          (Result, Node, Unit, Second_Unit); 
     587 
     588                        Remove_From_List 
     589                          (Children_List, Index + 1, Second_Unit); 
     590 
     591                     elsif Kinds in A_Library_Unit_Body then 
     592                        Second_Unit := Corresponding_Declaration 
     593                          (Unit, The_Context); 
     594 
     595                        Exist_Node := Add_Child 
     596                          (Result, Node, Second_Unit, Unit); 
     597 
     598                        Remove_From_List 
     599                          (Children_List, Index + 1, Second_Unit); 
     600                     else 
     601                        Exist_Node := Add_Child 
     602                          (Result, Node, Unit, null); 
     603                     end if; 
     604 
     605                     if Kinds = A_Package 
     606                       or else Kinds = A_Generic_Package 
     607                       or else Kinds = A_Package_Instance 
     608                     then 
     609                        Retrive (Unit, Exist_Node); 
     610                     end if; 
     611                  else 
     612                     Glue_Nodes (Result, Node, Exist_Node); 
     613                  end if; 
     614               end if; 
     615            end if; 
     616         end loop; 
     617      end Retrive; 
     618 
     619      Declarations_List : 
     620         Utils.Compilation_Unit_List_Access := null; 
     621      Declarations_Last : ASIS_Integer := 0; 
     622 
     623   begin 
     624      Declarations_List := new Asis.Compilation_Unit_List (1 .. List'Length); 
     625 
     626      for Index in List'Range loop 
     627         Unit  := List (Index); 
     628         Kinds := Unit_Kind (Unit); 
     629 
     630         --  eliminate A_Subunit 
     631         if Kinds not in A_Subunit then 
     632            if Kinds in A_Library_Unit_Body then 
     633               --  get declaration 
     634               Unit  := Corresponding_Declaration (Unit); 
     635               Kinds := Unit_Kind (Unit); 
     636            end if; 
     637 
     638            if Kinds = A_Package 
     639              or else Kinds = A_Generic_Package 
     640              or else Kinds = A_Package_Instance 
     641            then 
     642               if not In_List 
     643                 (Declarations_List, Declarations_Last, Unit) 
     644               then 
     645                  Declarations_Last := Declarations_Last + 1; 
     646                  Declarations_List (Declarations_Last) := Unit; 
     647               end if; 
     648            end if; 
     649         end if; 
     650      end loop; 
     651 
     652      for Index in 1 .. Declarations_Last loop 
     653         Retrive (Declarations_List (Index), null); 
     654      end loop; 
     655 
     656      Deallocate (Declarations_List); 
     657      return Result; 
     658 
     659   exception 
     660      when others => 
     661         Deallocate (Declarations_List); 
     662         Deallocate (Result); 
     663         raise; 
     664   end Get_Descendants; 
     665 
     666   ------------ 
     667   --  Utils -- 
     668   ------------ 
     669 
     670   package body Utils is 
     671 
     672      procedure Deallocate is 
     673        new Ada.Unchecked_Deallocation 
     674          (Tree_Node_Array, Tree_Node_Array_Access); 
     675 
     676      -------------- 
     677      -- Is_Empty -- 
     678      -------------- 
     679 
     680      function Is_Empty 
     681        (This : in Tree_Node) 
     682         return Boolean 
     683      is 
     684      begin 
     685         return Asis.Compilation_Units.Is_Nil (This.Unit); 
     686      end Is_Empty; 
     687 
     688      ------------------- 
     689      -- Append_Parent -- 
     690      ------------------- 
     691 
     692      function Append_Parent 
     693        (This : in Tree_Node_Access; 
     694         Unit : in Compilation_Unit) 
     695         return Tree_Node_Access 
     696      is 
     697         Node : Tree_Node_Access; 
     698      begin 
     699         if Is_Empty (This.all) then 
     700            This.Unit := Unit; 
     701 
     702            This.Last_Nodes := Add_Node (This.Last_Nodes, This.Self); 
     703            This.Units      := Add_Node_Ordered (This.Units, This.Self); 
     704            return This; 
     705         end if; 
     706 
     707         if This.Prev /= null then 
     708            raise Use_Error; 
     709         end if; 
     710 
     711         Node := Find (This.all, Unit); 
     712 
     713         if Node /= null then 
     714            --  circular 
     715            raise Use_Error; 
     716         end if; 
     717 
     718         Node := new Tree_Node; 
     719 
     720         Node.Unit := Unit; 
     721         This.Prev := Node.Self; 
     722         Node.Next := Add_Node (Node.Next, This.Self); 
     723 
     724         Node.Last_Nodes := This.Last_Nodes; 
     725         This.Last_Nodes := null; 
     726 
     727         Node.Units := This.Units; 
     728         This.Units := null; 
     729         Node.Units := Add_Node_Ordered (Node.Units, Node.Self); 
     730 
     731         return Node; 
     732      end Append_Parent; 
     733 
     734      --------------- 
     735      -- Add_Tread -- 
     736      --------------- 
     737 
     738      procedure Add_Tread 
     739        (This      : in     Tree_Node_Access; 
     740         To_Node   : in     Tree_Node_Access; 
     741         From_Tree : in out Tree_Node_Access) 
     742      is 
     743      begin 
     744         if Is_Empty (From_Tree.all) 
     745           or else Is_Empty (This.all) 
     746         then 
     747            --  empty tree(s) 
     748            raise Use_Error; 
     749         end if; 
     750 
     751         if From_Tree.Prev /= null 
     752           or else This.Prev /= null 
     753         then 
     754            --  not root 
     755            raise Use_Error; 
     756         end if; 
     757 
     758         for Index in From_Tree.Units.all'Range loop 
     759            if Find (This.all, From_Tree.Units.all (Index).Unit) /= null then 
     760               raise Use_Error; 
     761            end if; 
     762         end loop; 
     763 
     764         To_Node.Next := Add_Node (To_Node.Next, From_Tree.Self); 
     765 
     766         for Index in From_Tree.Last_Nodes.all'Range loop 
     767            This.Last_Nodes := Add_Node 
     768              (This.Last_Nodes, From_Tree.Last_Nodes.all (Index)); 
     769         end loop; 
     770 
     771         Deallocate (From_Tree.Last_Nodes); 
     772 
     773         for Index in From_Tree.Units.all'Range loop 
     774            This.Units := Add_Node_Ordered 
     775              (This.Units, From_Tree.Units.all (Index).Node); 
     776         end loop; 
     777 
     778         Deallocate (From_Tree.Units); 
     779         From_Tree := null; 
     780      end Add_Tread; 
     781 
     782      --------------- 
     783      -- Add_Child -- 
     784      --------------- 
     785 
     786      function Add_Child 
     787        (This      : in Tree_Node_Access; 
     788         Node      : in Tree_Node_Access; 
     789         Spec_Unit : in Compilation_Unit; 
     790         Body_Unit : in Compilation_Unit) 
     791         return Tree_Node_Access 
     792      is 
     793         New_Node : Tree_Node_Access := new Tree_Node; 
     794      begin 
     795         if This.Prev /= null 
     796         then 
     797            --  not root 
     798            raise Use_Error; 
     799         end if; 
     800 
     801         New_Node.Unit      := Spec_Unit; 
     802         New_Node.Unit_Body := Body_Unit; 
     803 
     804         if Node = null then 
     805            This.Next     := Add_Node (This.Next, New_Node.Self); 
     806            New_Node.Prev := This.Self; 
     807         else 
     808            Node.Next     := Add_Node (Node.Next, New_Node.Self); 
     809            New_Node.Prev := Node.Self; 
     810         end if; 
     811 
     812         This.Units := Add_Node_Ordered (This.Units, New_Node.Self); 
     813         return New_Node; 
     814      end Add_Child; 
     815 
     816      ---------------- 
     817      -- Glue_Nodes -- 
     818      ---------------- 
     819 
     820      procedure Glue_Nodes 
     821        (This    : in Tree_Node_Access; 
     822         Node    : in Tree_Node_Access; 
     823         To_Node : in Tree_Node_Access) 
     824      is 
     825      begin 
     826         if This.Prev /= null 
     827         then 
     828            --  not root 
     829            raise Use_Error; 
     830         end if; 
     831 
     832         Node.Next := Add_Node (Node.Next, To_Node.Self); 
     833      end Glue_Nodes; 
     834 
     835      ----------- 
     836      -- Clear -- 
     837      ----------- 
     838 
     839      procedure Deallocate is 
     840        new Ada.Unchecked_Deallocation 
     841          (Tree_Node, Tree_Node_Access); 
     842 
     843      procedure Clear 
     844        (This : in out Tree_Node) 
     845      is 
     846         Node : Tree_Node_Access; 
     847      begin 
     848         if This.Next /= null then 
     849            for Index in This.Next.all'Range loop 
     850               Node := This.Next.all (Index); 
     851               Clear (Node.all); 
     852               Deallocate (Node); 
     853            end loop; 
     854 
     855            Deallocate (This.Next); 
     856         end if; 
     857 
     858         Deallocate (This.Last_Nodes); 
     859         Deallocate (This.Units); 
     860         Deallocate (This.Circular); 
     861         Deallocate (This.Missing); 
     862      end Clear; 
     863 
     864      --------------------------- 
     865      -- Generate_Relationship -- 
     866      --------------------------- 
     867 
     868      function Generate_Relationship 
     869        (This  : in Tree_Node_Access; 
     870         Order : in Orders) 
     871         return Relationship 
     872      is 
     873         Consistent_List   : Compilation_Unit_List_Access := null; 
     874         Missing_List      : Compilation_Unit_List_Access := null; 
     875         Circular_List     : Compilation_Unit_List_Access := null; 
     876 
     877         Consistent_Length   : Asis.ASIS_Natural := 0; 
     878         Missing_Length      : Asis.ASIS_Natural := 0; 
     879         Circular_Length     : Asis.ASIS_Natural := 0; 
     880 
     881         -- Genegate_Circular -- 
     882         procedure Genegate_Circular 
     883           (List : Compilation_Unit_List_Access) 
     884         is 
     885         begin 
     886            for Index in List.all'Range loop 
     887               Circular_List := Append (Circular_List, List.all (Index)); 
     888 
     889               if Index < List.all'Last then 
     890                  Circular_List := Append 
     891                    (Circular_List, List.all (Index + 1)); 
     892               else 
     893                  Circular_List := Append (Circular_List, List.all (1)); 
     894               end if; 
     895            end loop; 
     896         end Genegate_Circular; 
     897 
     898         -- Genegate_Missing -- 
     899         procedure Genegate_Missing 
     900           (List : Compilation_Unit_List_Access) 
     901         is 
     902         begin 
     903            for Index in List.all'Range loop 
     904               Missing_List := Append (Missing_List, List.all (Index)); 
     905            end loop; 
     906         end Genegate_Missing; 
     907 
     908         -- Process_Asc -- 
     909         procedure Process_Asc 
     910           (Node : in Tree_Node_Access) 
     911         is 
     912            Internal_Node : Tree_Node_Access := Node; 
     913            Prev_Node     : Tree_Node_Access; 
     914 
     915         begin 
     916            while Internal_Node /= null loop 
     917               if not Is_Empty (Internal_Node.all) then 
     918                  if Internal_Node.Added then 
     919                     return; 
     920                  end if; 
     921 
     922                  Internal_Node.Added := True; 
     923 
     924                  Consistent_List := Append 
     925                    (Consistent_List, Internal_Node.Unit); 
     926 
     927                  if Internal_Node.Missing /= null 
     928                    and then not Internal_Node.Missing_Added 
     929                  then 
     930                     Genegate_Missing (Internal_Node.Missing); 
     931                     Internal_Node.Missing_Added := True; 
     932                  end if; 
     933 
     934                  if Internal_Node.Circular /= null 
     935                    and then not Internal_Node.Circular_Added 
     936                  then 
     937                     Genegate_Circular (Internal_Node.Circular); 
     938                     Internal_Node.Circular_Added := True; 
     939                  end if; 
     940 
     941                  Prev_Node := Internal_Node; 
     942               end if; 
     943 
     944               Internal_Node := Internal_Node.Prev; 
     945            end loop; 
     946         end Process_Asc; 
     947 
     948         -- Process_Dsc -- 
     949         procedure Process_Dsc 
     950           (Target : in Tree_Node_Access) 
     951         is 
     952         begin 
     953            if Target.Added then 
     954               return; 
     955            end if; 
     956 
     957            Target.Added := True; 
     958 
     959            Consistent_List := Append (Consistent_List, Target.Unit); 
     960 
     961            if not Is_Nil (Target.Unit_Body) then 
     962               Consistent_List := Append (Consistent_List, Target.Unit); 
     963            end if; 
     964 
     965            if Target.Missing /= null 
     966              and then not Target.Missing_Added 
     967            then 
     968               Genegate_Missing (Target.Missing); 
     969               Target.Missing_Added := True; 
     970            end if; 
     971 
     972            if Target.Circular /= null 
     973              and then not Target.Circular_Added 
     974            then 
     975               Genegate_Circular (Target.Circular); 
     976               Target.Circular_Added := True; 
     977            end if; 
     978 
     979            if Target.Next /= null then 
     980               for Index in Target.Next.all'Range loop 
     981                  Process_Dsc (Target.Next.all (Index)); 
     982               end loop; 
     983            end if; 
     984         end Process_Dsc; 
     985 
     986      begin 
     987         if Order = From_Child then 
     988            if Is_Empty (This.all) 
     989              and then This.Next = null 
     990            then 
     991               return Nil_Relationship; 
     992            end if; 
     993 
     994            declare 
     995               Lasts : Tree_Node_Array_Access := This.Last_Nodes; 
     996            begin 
     997               for Index in Lasts.all'Range loop 
     998                  Process_Asc (Lasts.all (Index)); 
     999               end loop; 
     1000            end; 
     1001         else 
     1002            if not Is_Nil (This.Unit) then 
     1003               Process_Dsc (This); 
     1004            else 
     1005               if This.Next = null then 
     1006                  return Nil_Relationship; 
     1007               end if; 
     1008 
     1009               for Index in This.Next.all'Range loop 
     1010                  Process_Dsc (This.Next.all (Index)); 
     1011               end loop; 
     1012            end if; 
     1013         end if; 
     1014 
     1015         if Consistent_List /= null then 
     1016            Consistent_Length := Consistent_List.all'Length; 
     1017         end if; 
     1018 
     1019         if Missing_List /= null then 
     1020            Missing_Length := Missing_List.all'Length; 
     1021         end if; 
     1022 
     1023         if Circular_List /= null then 
     1024            Circular_Length := Circular_List.all'Length; 
     1025         end if; 
     1026 
     1027         declare 
     1028            Result : Relationship 
     1029              (Consistent_Length, 0, Missing_Length, Circular_Length); 
     1030         begin 
     1031            if Consistent_List /= null then 
     1032               Result.Consistent := Consistent_List.all; 
     1033