home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / gnat-2.06-src.tgz / tar.out / fsf / gnat / ada / xref.adb < prev    next >
Text File  |  1996-09-28  |  61KB  |  1,874 lines

  1. ------------------------------------------------------------------------------
  2. --                                                                          --
  3. --                         GNAT COMPILER COMPONENTS                         --
  4. --                                                                          --
  5. --                                 X R E F                                  --
  6. --                                                                          --
  7. --                                 B o d y                                  --
  8. --                                                                          --
  9. --                            $Revision: 1.97 $                             --
  10. --                                                                          --
  11. --           Copyright (c) 1992,1993,1994 NYU, All Rights Reserved          --
  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, 675 Mass Ave, Cambridge, MA 02139, USA. --
  22. --                                                                          --
  23. ------------------------------------------------------------------------------
  24.  
  25. with Atree;  use Atree;
  26. with Einfo;  use Einfo;
  27. with Elists; use Elists;
  28. with Lib;    use Lib;
  29. with Namet;  use Namet;
  30. with Nlists; use Nlists;
  31. with Osint;  use Osint;
  32. with Opt;    use Opt;
  33. with Output; use Output;
  34. with Sinfo;  use Sinfo;
  35. with Sinput; use Sinput;
  36. with Snames; use Snames;
  37. with Sprint; use Sprint;
  38. with Stand;  use Stand;
  39. with Unchecked_Deallocation;
  40. with Xref_Tab; use Xref_Tab;
  41. with Treepr; use Treepr;
  42.  
  43. package body Xref is
  44.  
  45.    ---------------------
  46.    --  File suffixes  --
  47.    ---------------------
  48.  
  49.    Spec_REQ_Suffix : constant String := ".r";
  50.    Body_REQ_Suffix : constant String := ".br";
  51.    Org_Spec_Suffix : constant String := ".org";
  52.  
  53.    --  ??? the whole idea of a file suffix is too target dependent, and
  54.    --  ??? the knowledge of suffixes should remain in OSINT.
  55.  
  56.    ------------------
  57.    --  Other data  --
  58.    ------------------
  59.  
  60.    type Phase_Type is (Add_Entities_And_Refs, Unmark_Refs);
  61.  
  62.    Phase : Phase_Type;
  63.    --  Used to signal the Traverse_Node procedure what we're doing.
  64.    --
  65.    --    Add_Entities_And_REfs : normal mode to build the Entity_Tables.
  66.    --
  67.    --    Unmark_Refs           : special mode for multipass removal of
  68.    --                            unused nodes within the program tree.
  69.  
  70.    type Hash_Record is record
  71.       Serial : Nat;
  72.       --  Serial number for hash table entry. A value of zero means that
  73.       --  the entry is currently unused. The serial number is used for
  74.       --  indexing tables of associated information for nodes.
  75.  
  76.       Id : Int;
  77.       --  If serial number field is non-zero, contains corresponding Id value
  78.  
  79.       Prev_Inc_Typ_Def : Boolean := False;
  80.       --  Set to True if the node corresponding to the serial
  81.       --  number is the full declaration of an entity having
  82.       --  a previous type definition.
  83.    end record;
  84.  
  85.    Internal_Node : Boolean;
  86.  
  87.    type Hash_Table_Type is array (Nat range <>) of Hash_Record;
  88.    type Access_Hash_Table_Type is access Hash_Table_Type;
  89.    Hash_Table : Access_Hash_Table_Type;
  90.    --  The hash table itself, see Serial_Number function for details of use
  91.  
  92.    Hash_Table_Len : Nat;
  93.    --  Range of Hash_Table is from 0 .. Hash_Table_Len - 1 so that dividing
  94.    --  by Hash_Table_Len gives a remainder that is in Hash_Table'Range.
  95.  
  96.    Hash_Slot : Nat;
  97.    --  Set by an unsuccessful call to Serial_Number (one which returns zero)
  98.    --  to save the slot that should be used if Set_Serial_Number is called.
  99.  
  100.    Next_Serial_Number : Nat;
  101.    --  Number of last visited node or list. Used during the marking phase to
  102.    --  set proper node numbers in the hash table.
  103.  
  104.    type Entity_Association_Type is array (Node_Id range <>) of Entity_Acc;
  105.    type Access_Entity_Association_Type is access Entity_Association_Type;
  106.    Entity_Association : Access_Entity_Association_Type;
  107.    --  Array to associate the entities in the program tree with their
  108.    --  Corresponding data structures.
  109.  
  110.    type File_Record is record
  111.       Create_REQ : Boolean := False;
  112.       Etbl       : Entity_Table_Acc;
  113.    end record;
  114.  
  115.    type File_Array_Type is array (Unit_Number_Type range <>) of File_Record;
  116.    type File_Array_Acc is access File_Array_Type;
  117.  
  118.    Loaded_Files : File_Array_Acc;
  119.    --  Array that associates the loaded files with the Entity_Tables.
  120.    --  Create_REQ is used in Write_Spec_REQs to build the REQ for a withed
  121.    --  spec.
  122.  
  123.    type Ref_Array_Type is array (Int range <>) of Node_Id;
  124.    type Ref_Array_Acc is access Ref_Array_Type;
  125.  
  126.    Ref_Buffer : Ref_Array_Acc;
  127.    Ref_Length : Int;
  128.    --  Array to buffer the found references until all entities are added
  129.    --  to our entity lists.
  130.  
  131.    -------------------------
  132.    --  Local subprograms  --
  133.    -------------------------
  134.  
  135.    procedure Allocate_Memory;
  136.    --  Allocates the memory on the heap which is needed for the dynamic
  137.    --  arrays.
  138.  
  139.    procedure Collect_Withs (Unum : Unit_Number_Type);
  140.    --  Collect with clauses in the context clause of the given compilation
  141.    --  unit.
  142.  
  143.    procedure Deallocate_Memory;
  144.    --  Frees the memory on the heap which is needed for the dynamic arrays.
  145.  
  146.    procedure Init_Numbers;
  147.    --  Clear Node_Numbers and List_Numbers to False (= unmarked).
  148.    --  Use Init_Numbers before each call of Traverse_Node_Hierarchic.
  149.  
  150.    procedure Link_Subunits (The_Unit : Unit_Number_Type);
  151.    --  Links the main Entity_Table with its loaded subunits.
  152.  
  153.    procedure Remove_Entities
  154.      (The_Etbl : Entity_Table_Acc;
  155.       Found    : in out Boolean);
  156.    --  Looks for entities with no references and removes both the fitting node
  157.    --  and all its parents which also get redundant. This is done by a loop
  158.    --  to provide succesive dead code removal.
  159.    --  ??? need to document the function of the parameters, and Found in
  160.    --  particular, what is it and why is it in out ???
  161.  
  162.    function Serial_Number (Id : Int) return Nat;
  163.    --  Given a Node_Id, List_Id or Elist_Id, returns the previously assigned
  164.    --  serial number, or zero if no serial number has yet been assigned.
  165.  
  166.    procedure Set_Serial_Number;
  167.    --  Can be called only immediately following a call to Serial_Number that
  168.    --  returned a value of zero. Causes the value of Next_Serial_Number to be
  169.    --  placed in the hash table (corresponding to the Id argument used in the
  170.    --  Serial_Number call), and increments Next_Serial_Number.
  171.  
  172.    procedure Set_Spec_REQ_Flags (The_Etbl : Entity_Table_Acc);
  173.    --  Sets the Create_REQ fields to create a required interface for all
  174.    --  withed specs as well as to select the transitive specs.
  175.  
  176.    procedure Traverse_Node_Hierarchic (N : Node_Id);
  177.    --  Recursive procedure traversing the program tree.
  178.    --  Can be used to add information to the Entity_Tables as well as
  179.    --  to remove references of a dead program part (for dead code elimination).
  180.    --  Before each call of Traverse_Node_Hierarchic the procedure
  181.    --  Init_Numbers must be called to initialize the node and list flags.
  182.    --  If an entity declaration is found, then the corresponding entity
  183.    --  information gets immediately added to the fitting Entity_Table.
  184.    --  Every reference which is found is buffered in Ref_Buffer to avoid
  185.    --  the case of adding a reference pointing to an entity that doesn't yet
  186.    --  appear in the fitting Entity_Table.
  187.  
  188.    procedure Write_Org (The_Etbl : Entity_Table_Acc);
  189.    --  Writes the original source of the given Entity_Table (GNAT -dw conform).
  190.    --  Used to compare the required interfaces with it and then to create the
  191.    --  correct provided interface. File suffix changes to Org_Spec_Suffix.
  192.  
  193.    procedure Write_Body_REQs;
  194.    --  Writes the REQs for the body and its subunits the disk.
  195.    --  The file name of a Body_REQ is the file name of the compilation unit,
  196.    --  the suffix '.adb' replaced by Body_REQ_Suffix.
  197.  
  198.    procedure Write_Spec_REQs;
  199.    --  Writes the REQs (one for each withed spec) to the disk.
  200.    --  The file name of a Spec_REQ is the file name of the withed
  201.    --  compilation unit, the suffix '.ads' replaced by
  202.    --  '.' & the name of the withing unit & Body_REQ_Suffix.
  203.    --  e.g.   with Pack1;
  204.    --         procedure Main is ...
  205.    --  then we have the source file name main.adb and would get pack1.main.r
  206.    --  with the Spec_REQ for Pack1 inside.
  207.  
  208.    procedure Write_Xref (The_Etbl : Entity_Table_Acc);
  209.    --  Creates a cross reference list, containing all the entities and their
  210.    --  corresponding references, which are found in the loaded files. The
  211.    --  references are printed by file name and line numbers of their source
  212.    --  locations. This call has no effect if the appropriate xref switchs
  213.    --  are not set. What is the parameter ???
  214.  
  215.    -------------------
  216.    -- Serial_Number --
  217.    -------------------
  218.  
  219.    function Serial_Number (Id : Int) return Nat is
  220.       H : Int := Id mod Hash_Table_Len;
  221.  
  222.    begin
  223.  
  224.       if Hash_Table (H).Id = Id and then Hash_Table (H).Prev_Inc_Typ_Def then
  225.          Internal_Node := True;
  226.          Hash_Slot := H;
  227.          return Hash_Table (H).Serial;
  228.       end if;
  229.  
  230.       while Hash_Table (H).Serial /= 0 loop
  231.  
  232.          if Id = Hash_Table (H).Id then
  233.             return Hash_Table (H).Serial;
  234.          end if;
  235.  
  236.          H := H + 1;
  237.  
  238.          if H > Hash_Table'Last then
  239.             H := 0;
  240.          end if;
  241.       end loop;
  242.  
  243.       --  Entry was not found, save slot number for possible subsequent call
  244.       --  to Set_Serial_Number, and unconditionally save the Id in this slot
  245.       --  in case of such a call (the Id field is never read if the serial
  246.       --  number of the slot is zero, so this is harmless in the case where
  247.       --  Set_Serial_Number is not subsequently called).
  248.  
  249.       Hash_Slot := H;
  250.       Hash_Table (H).Id := Id;
  251.       return 0;
  252.  
  253.    end Serial_Number;
  254.  
  255.    -----------------------
  256.    -- Set_Serial_Number --
  257.    -----------------------
  258.  
  259.    procedure Set_Serial_Number is
  260.    begin
  261.       Hash_Table (Hash_Slot).Serial := Next_Serial_Number;
  262.       Next_Serial_Number := Next_Serial_Number + 1;
  263.    end Set_Serial_Number;
  264.  
  265.    ---------------------
  266.    -- Allocate_Memory --
  267.    ---------------------
  268.  
  269.    procedure Allocate_Memory is
  270.    begin
  271.  
  272.       --  Pointers for direct entity access.
  273.  
  274.       Entity_Association := new Entity_Association_Type
  275.         (Last_Standard_Node_Id + 1 .. Last_Node_Id);
  276.       --  ??? THIS WON'T DO, YOU ARE ASSUMING Node_Id values are contiguous
  277.  
  278.       --  Array to associate the loaded files with their corresponding
  279.       --  Entity_Table.
  280.  
  281.       Loaded_Files := new File_Array_Type (Main_Unit .. Last_Unit);
  282.  
  283.       --  Buffer for found references.
  284.  
  285.       Ref_Buffer := new Ref_Array_Type (1 ..
  286.         Int (Last_Node_Id - Last_Standard_Node_Id));
  287.  
  288.       Ref_Length := 0;
  289.  
  290.       Hash_Table_Len := (150 * (Num_Nodes + Num_Lists + Num_Elists)) / 100;
  291.       Hash_Table := new Hash_Table_Type  (0 .. Hash_Table_Len - 1);
  292.  
  293.    end Allocate_Memory;
  294.  
  295.    -------------------
  296.    -- Collect_Withs --
  297.    -------------------
  298.  
  299.    procedure Collect_Withs (Unum : Unit_Number_Type) is
  300.       Item        : Node_Id;
  301.       Withed_Unit : Unit_Number_Type;
  302.  
  303.    begin
  304.       Item := First (Context_Items (Cunit (Unum)));
  305.       while Present (Item) loop
  306.  
  307.  
  308.          if Nkind (Item) = N_With_Clause
  309.            and then not Implicit_With (Item)
  310.          then
  311.             Withed_Unit := Get_Cunit_Unit_Number (Library_Unit (Item));
  312.  
  313.             Add_With
  314.               (Loaded_Files (Unum).Etbl, Loaded_Files (Withed_Unit).Etbl);
  315.          elsif Nkind (Item) = N_With_Clause
  316.            and then Implicit_With (Item)
  317.          then
  318.             Withed_Unit := Get_Cunit_Unit_Number (Library_Unit (Item));
  319.             if Chars (Name (Item)) in Text_IO_Package_Name then
  320.                Add_With
  321.                  (Loaded_Files (Unum).Etbl, Loaded_Files (Withed_Unit).Etbl,
  322.                   True);
  323.                null;
  324.             end if;
  325.          end if;
  326.  
  327.          Item := Next (Item);
  328.       end loop;
  329.    end Collect_Withs;
  330.  
  331.    -----------------------
  332.    -- Deallocate_Memory --
  333.    -----------------------
  334.  
  335.    procedure Deallocate_Memory is
  336.  
  337.       procedure Free is new Unchecked_Deallocation (Entity_Association_Type,
  338.         Access_Entity_Association_Type);
  339.  
  340.       procedure Free is new Unchecked_Deallocation (File_Array_Type,
  341.         File_Array_Acc);
  342.  
  343.       procedure Free is new Unchecked_Deallocation (Ref_Array_Type,
  344.         Ref_Array_Acc);
  345.  
  346.       procedure Free is new Unchecked_Deallocation (Hash_Table_Type,
  347.         Access_Hash_Table_Type);
  348.  
  349.    begin
  350.       Free (Entity_Association);
  351.       Free (Loaded_Files);
  352.       Free (Ref_Buffer);
  353.       Free (Hash_Table);
  354.    end Deallocate_Memory;
  355.  
  356.    --------------
  357.    -- Finalize --
  358.    --------------
  359.  
  360.    --  Could use some documentation explaining tests below ???
  361.  
  362.    procedure Finalize is
  363.    begin
  364.       --  If we already called Write_Xref from Gather_Xref_Info for each file
  365.       --  in the case where we want only smart information in the xref file
  366.       --  (switches x3 and x4 of gnatf), then nothing to do
  367.  
  368.       if Xref_Flag and then not Global_Xref_File then
  369.          return;
  370.  
  371.       --  Otherwise write the xref information now
  372.  
  373.       else
  374.          Write_Xref (Xref_Tab.First_Etbl);
  375.       end if;
  376.  
  377.    end Finalize;
  378.  
  379.    ----------------------
  380.    -- Gather_Xref_Info --
  381.    ----------------------
  382.  
  383.    procedure Gather_Xref_Info (Top : Node_Id) is
  384.       Spec          : Unit_Number_Type;
  385.       Unum          : Unit_Number_Type;
  386.       To_Unum       : Unit_Number_Type;
  387.       To_Entity     : Entity_Id;
  388.       The_Entity    : Entity_Acc;
  389.       Ref_Node      : Node_Id;
  390.       Main_Etbl     : Entity_Table_Acc;
  391.       Etbl_Tmp      : Entity_Table_Acc;
  392.       Etbl_List     : Entity_Table_Acc;
  393.       Renamed_Node  : Node_Id;
  394.       Renamed_Sloc  : Source_Ptr;
  395.       Renamed_Unit  : Unit_Number_Type;
  396.       Renamed_Found : Boolean;
  397.       Unit_Node     : Node_Id;
  398.  
  399.    begin
  400.       --  Immediate return if not collecting Xref information
  401.  
  402.       if not (With_Warnings or Xref_Flag
  403.         or Spec_REQs_Flag or Body_REQs_Flag) then
  404.          return;
  405.       end if;
  406.  
  407.       --  Allocate dynamic arrays
  408.  
  409.       Allocate_Memory;
  410.  
  411.       --  Associate the loaded files with the Entity_Tables.
  412.       --  Ignore Zombies (e.g. the spec for a body acting as spec)!
  413.  
  414.       Etbl_Tmp := Xref_Tab.Last_Etbl;
  415.       for J in Loaded_Files'Range loop
  416.          Add_Etbl (First_Etbl, Last_Etbl, J, Loaded_Files (J).Etbl);
  417.       end loop;
  418.  
  419.       Main_Etbl  := Loaded_Files (Main_Unit).Etbl;
  420.  
  421.       --  We perform research research only for the entity tables
  422.       --  that have been created in the current compilation.
  423.  
  424.       if Etbl_Tmp = null then
  425.          Etbl_Tmp := Main_Etbl;
  426.       else
  427.          Etbl_Tmp := Etbl_Tmp.Next_Etbl;
  428.       end if;
  429.  
  430.       while Etbl_Tmp /= null loop
  431.  
  432.          if Nkind (Unit (Etbl_Tmp.Top_Node)) =
  433.                              N_Package_Renaming_Declaration
  434.          then
  435.             Renamed_Node := Name (Unit (Etbl_Tmp.Top_Node));
  436.             Renamed_Found := False;
  437.  
  438.             --  Searches the node of the renamed package and the name of
  439.             --  the corresponding file where this package is declared.
  440.  
  441.             while not Renamed_Found loop
  442.                Renamed_Node := Parent (Node_Id (Entity (Renamed_Node)));
  443.  
  444.                if Nkind (Renamed_Node) =
  445.                   N_Package_Renaming_Declaration
  446.                then
  447.                   Renamed_Node := Name (Renamed_Node);
  448.                else
  449.                   Renamed_Found := True;
  450.                end if;
  451.             end loop;
  452.  
  453.             Renamed_Sloc := Sloc (Renamed_Node);
  454.             Renamed_Unit := Get_Sloc_Unit_Number (Renamed_Sloc);
  455.             Get_Name_String (Full_File_Name (Source_Index (Renamed_Unit)));
  456.  
  457.             --  Searches the corresponding Etbl
  458.  
  459.             Etbl_List := First_Etbl;
  460.             while Etbl_List /= null loop
  461.                if Etbl_List.File_Name.all = Name_Buffer (1 .. Name_Len) then
  462.                   Etbl_Tmp.Renamed_Etbl := Etbl_List;
  463.                   exit;
  464.                end if;
  465.  
  466.                Etbl_List := Etbl_List.Next_Etbl;
  467.             end loop;
  468.          end if;
  469.  
  470.          Etbl_Tmp := Etbl_Tmp.Next_Etbl;
  471.       end loop;
  472.  
  473.       --  We mark the main Entity_Table as a 'required unit', that is
  474.       --  we create a fully detailed Xref for it.
  475.  
  476.       Main_Etbl.RU := True;
  477.  
  478.       --  Look for with clauses within the loaded files.
  479.  
  480.       --  Ignore Zombies (e.g. the spec for a body acting as spec) and
  481.       --  do this only once ('Examined' signals a previous examination)!
  482.  
  483.       for J in Loaded_Files'Range loop
  484.          if not Loaded_Files (J).Etbl.Examined then
  485.             Collect_Withs (J);
  486.          end if;
  487.       end loop;
  488.  
  489.       --  Here we link the multiple parts of an object
  490.       --  (i.e. Spec/Body/Subunits) to give correct With_Warnings.
  491.  
  492.       case Main_Etbl.Status is
  493.  
  494.          when A_Body =>
  495.  
  496.             Spec := Get_Cunit_Unit_Number (Library_Unit (Top));
  497.  
  498.             if Spec_REQs_Flag then
  499.                Write_Org (Loaded_Files (Spec).Etbl);
  500.             end if;
  501.  
  502.             Loaded_Files (Spec).Etbl.RU := True;
  503.             Loaded_Files (Spec).Create_REQ := True;
  504.  
  505.             --  In multifile mode we create full output for this spec.
  506.             --  Otherwise we print only what is used.
  507.  
  508.             Loaded_Files (Spec).Etbl.Status := Withed_Spec;
  509.  
  510.             Loaded_Files (Spec).Etbl.Successor := Main_Etbl;
  511.  
  512.             Main_Etbl.Predecessor := Loaded_Files (Spec).Etbl;
  513.             Link_Subunits (Main_Unit);
  514.  
  515.          when Sub_Body =>
  516.  
  517.             Unum := Get_Cunit_Unit_Number (Library_Unit (Top));
  518.             Loaded_Files (Unum).Etbl.RU := True;
  519.  
  520.             if Loaded_Files (Unum).Etbl.Status = A_Body then
  521.                Spec := Get_Cunit_Unit_Number (Library_Unit (Cunit (Unum)));
  522.  
  523.                if Spec_REQs_Flag then
  524.                   Write_Org (Loaded_Files (Spec).Etbl);
  525.                end if;
  526.  
  527.                --  In multifile mode we create full output for this spec.
  528.                --  Otherwise we print only what is used.
  529.                Loaded_Files (Spec).Etbl.RU := True;
  530.  
  531.                Loaded_Files (Spec).Etbl.Status := Withed_Spec;
  532.  
  533.                Loaded_Files (Spec).Etbl.Successor :=
  534.                  Loaded_Files (Unum).Etbl;
  535.  
  536.                Loaded_Files (Unum).Etbl.Predecessor :=
  537.                  Loaded_Files (Spec).Etbl;
  538.             end if;
  539.  
  540.             Link_Subunits (Unum);
  541.  
  542.          when Body_As_Spec =>
  543.  
  544.             Link_Subunits (Main_Unit);
  545.  
  546.          when A_Spec | Withed_Spec =>
  547.  
  548.             if Spec_REQs_Flag then
  549.                Write_Org (Main_Etbl);
  550.             end if;
  551.  
  552.       end case;
  553.  
  554.       --  After linking the main unit with its predecessors and successors
  555.       --  some other units must also be examined
  556.       --     - bodies of generic packages must be linked
  557.       --     - Child spec must be linked with their parents
  558.  
  559.       for All_The_Units in Loaded_Files'Range loop
  560.  
  561.          --  if this entity table has not been linked yet then
  562.          --  we must examine it
  563.  
  564.          if not Loaded_Files (All_The_Units).Etbl.Linked then
  565.             case Loaded_Files (All_The_Units).Etbl.Status is
  566.                when A_Spec | Withed_Spec =>
  567.                   Unit_Node :=
  568.                     Unit (Loaded_Files (All_The_Units).Etbl.Top_Node);
  569.                   if Parent_Spec (Unit_Node) /= Empty then
  570.  
  571.                      --  If parent_spec is not empty then the current spec
  572.                      --  is a child spec. So we get the parent spec and set up
  573.                      --  the predecessor and successor links
  574.  
  575.                      Spec := Get_Cunit_Unit_Number (Parent_Spec (Unit_Node));
  576.  
  577.                      --  Adds Child_Spec to the list of children of the parent
  578.  
  579.                      Etbl_Tmp := Loaded_Files (Spec).Etbl;
  580.  
  581.                      if Etbl_Tmp.First_Child = null then
  582.                         Etbl_Tmp.First_Child := new Child_Spec;
  583.                         Etbl_Tmp.First_Child.Child_Etbl :=
  584.                           Loaded_Files (All_The_Units).Etbl;
  585.                      else
  586.                         declare
  587.                            Child_Units : Child_Spec_Acc :=
  588.                                             Etbl_Tmp.First_Child;
  589.                         begin
  590.                            while Child_Units.Next_Child /= null loop
  591.                               Child_Units := Child_Units.Next_Child;
  592.                            end loop;
  593.  
  594.                            Child_Units.Next_Child := new Child_Spec;
  595.                            Child_Units.Next_Child.Child_Etbl :=
  596.                              Loaded_Files (All_The_Units).Etbl;
  597.                         end;
  598.                      end if;
  599.  
  600.                      Loaded_Files (All_The_Units).Etbl.Predecessor :=
  601.                        Etbl_Tmp;
  602.  
  603.                   end if;
  604.  
  605.                when A_Body =>
  606.  
  607.                   --  We get the corresponding spec
  608.  
  609.                   Spec := Get_Cunit_Unit_Number
  610.                             (Library_Unit (Cunit (All_The_Units)));
  611.  
  612.                   --  We set up the predecessor and successor links
  613.  
  614.                   Loaded_Files (All_The_Units).Etbl.Predecessor :=
  615.                     Loaded_Files (Spec).Etbl;
  616.  
  617.                   Loaded_Files (Spec).Etbl.Successor :=
  618.                     Loaded_Files (All_The_Units).Etbl;
  619.  
  620.                when Sub_Body =>
  621.                   Unum := Get_Cunit_Unit_Number (Library_Unit
  622.                                                    (Cunit (All_The_Units)));
  623.                   Etbl_Tmp := Loaded_Files (Unum).Etbl;
  624.  
  625.                   Loaded_Files (All_The_Units).Etbl.Predecessor := Etbl_Tmp;
  626.  
  627.                   while Etbl_Tmp.Successor /= null loop
  628.                      Etbl_Tmp := Etbl_Tmp.Successor;
  629.                   end loop;
  630.  
  631.                   Etbl_Tmp.Successor := Loaded_Files (All_The_Units).Etbl;
  632.  
  633.                when others =>
  634.                   null;
  635.  
  636.             end case;
  637.  
  638.          end if;
  639.  
  640.          Loaded_Files (All_The_Units).Etbl.Linked := True;
  641.  
  642.       end loop;
  643.  
  644.       Set_Spec_REQ_Flags (Main_Etbl);
  645.  
  646.       --  Search and add the entities to the entity tables.
  647.  
  648.       Phase := Add_Entities_And_Refs;
  649.  
  650.       --  Hierarchic scan of the nodes instead of a linear scan
  651.       --  It must be checked that the hierarchic scan is not
  652.       --  too much slower than the linear onw
  653.  
  654.       for All_The_Units in Main_Unit .. Last_Unit loop
  655.          Init_Numbers;
  656.          Traverse_Node_Hierarchic (Cunit (All_The_Units));
  657.       end loop;
  658.  
  659.       --  Take the references from the buffer and add them to the
  660.       --  fitting entities.
  661.  
  662.       for J in 1 .. Ref_Length loop
  663.          Ref_Node := Ref_Buffer (J);
  664.  
  665.          --  if the reference node is matches a with clause. Then we skip
  666.          --  this reference if the with clause is implicit.
  667.          --  It's mainly the case when a child unit is withed. Implicit withs
  668.          --  are generated for all the parent specs.
  669.  
  670.          if not (Nkind (Parent (Ref_Node)) = N_With_Clause
  671.                    and then Implicit_With (Parent (Ref_Node)))
  672.          then
  673.  
  674.             To_Entity := Entity (Ref_Node);
  675.  
  676.             Unum    := Get_Sloc_Unit_Number (Sloc (Ref_Node));
  677.             To_Unum := Get_Sloc_Unit_Number (Sloc (Entity (Ref_Node)));
  678.  
  679.             --  We don't add reference :
  680.             --     - for entities declared in Specs that are referenced in a
  681.             --       successor of this spec
  682.             --     - for entities declared in bodies
  683.  
  684.             To_Entity := Entity (Ref_Node);
  685.  
  686.             if not All_Info_In_Xref
  687.               and then
  688.                 (Nkind (Parent (To_Entity)) = N_Enumeration_Type_Definition
  689.                   or else
  690.                     Nkind (Parent (To_Entity)) = N_Component_Declaration)
  691.             then
  692.                loop
  693.                   To_Entity := Parent (To_Entity);
  694.                   exit when Nkind (To_Entity) = N_Full_Type_Declaration;
  695.                end loop;
  696.  
  697.                To_Entity := Defining_Identifier (To_Entity);
  698.             end if;
  699.  
  700.             The_Entity := Entity_Association (To_Entity);
  701.  
  702.             if Unum = To_Unum
  703.               and then Loaded_Files (Unum).Etbl.Status in Body_Status
  704.               and then not All_Info_In_Xref
  705.               and then not Include_Inlined
  706.  
  707.             then
  708.                --  We update The_Entity.Length to avoid junk messages.
  709.  
  710.                if Nkind (Parent (Ref_Node)) /= N_Pragma_Argument_Association
  711.                  and then The_Entity /= null
  712.                then
  713.                   The_Entity.Length := The_Entity.Length + 1;
  714.                end if;
  715.  
  716.             else
  717.                if not Loaded_Files (Unum).Etbl.Examined then
  718.  
  719.                   Add_Reference
  720.                     (The_Entity, Loaded_Files (Unum).Etbl, Ref_Node);
  721.  
  722.                   if Nkind (Parent (Ref_Node)) in N_Generic_Instantiation then
  723.  
  724.                      declare
  725.                         Ref_Etbl : constant Entity_Table_Acc :=
  726.                                      Loaded_Files (Unum).Etbl;
  727.                         Ent_Etbl : constant Entity_Table_Acc :=
  728.                                      Loaded_Files (To_Unum).Etbl;
  729.                         I_Tmp    : Include_Acc;
  730.  
  731.                      begin
  732.                         I_Tmp := Ref_Etbl.First_Include;
  733.  
  734.                         if I_Tmp = null then
  735.                            Ref_Etbl.First_Include := new Include;
  736.                            Ref_Etbl.First_Include.Included_Etbl := Ent_Etbl;
  737.  
  738.                         else
  739.                            while I_Tmp.Included_Etbl /= Ent_Etbl
  740.                              and then I_Tmp.Next_Include /= null
  741.                            loop
  742.                               I_Tmp := I_Tmp.Next_Include;
  743.                            end loop;
  744.  
  745.                            if I_Tmp.Included_Etbl /= Ent_Etbl then
  746.                               I_Tmp.Next_Include := new Include;
  747.                               I_Tmp.Next_Include.Included_Etbl := Ent_Etbl;
  748.                            end if;
  749.                         end if;
  750.                      end;
  751.                   end if;
  752.  
  753.                elsif Spec_REQs_Flag
  754.                  and then Loaded_Files (Unum).Create_REQ
  755.                  and then Unum = To_Unum
  756.                then
  757.                   Update_Reference
  758.                     (The_Entity, Loaded_Files (Unum).Etbl, Ref_Node);
  759.                end if;
  760.             end if;
  761.          end if;
  762.       end loop;
  763.  
  764.  
  765.       --  Write the Spec_REQs.
  766.  
  767.       if Spec_REQs_Flag then
  768.          Write_Spec_REQs;
  769.       end if;
  770.  
  771.       --  Write the Body_REQs.
  772.  
  773.       if Body_REQs_Flag
  774.         and then Loaded_Files (Main_Unit).Etbl.Status in Body_Status
  775.       then
  776.          Write_Body_REQs;
  777.       end if;
  778.  
  779.       --  Mark the units to be Examined.
  780.  
  781.       for J in Loaded_Files'Range loop
  782.          if Loaded_Files (J).Etbl /= null then
  783.             Loaded_Files (J).Etbl.Examined := True;
  784.          end if;
  785.       end loop;
  786.  
  787.       if Xref_Flag and then not Global_Xref_File then
  788.          Write_Xref (Main_Etbl);
  789.       end if;
  790.  
  791.       --  Deallocate dynamic arrays
  792.  
  793.       Deallocate_Memory;
  794.  
  795.    end Gather_Xref_Info;
  796.  
  797.    ------------------
  798.    -- Init_Numbers --
  799.    ------------------
  800.  
  801.    procedure Init_Numbers is
  802.    begin
  803.       --  Set node flags to unvisited (except those of Standard).
  804.  
  805.       --  Allocate and clear serial number hash table. The size is 150% of
  806.       --  the maximum possible number of entries, so that the hash table
  807.       --  cannot get significantly overloaded.
  808.  
  809.       for J in Hash_Table'Range loop
  810.          Hash_Table (J).Serial := 0;
  811.       end loop;
  812.  
  813.       Next_Serial_Number := 1;
  814.  
  815.    end Init_Numbers;
  816.  
  817.    ----------------
  818.    -- Initialize --
  819.    ----------------
  820.  
  821.    procedure Initialize is
  822.    begin
  823.  
  824.       With_Warnings       := Xref_Flag_1 or Xref_Flag_2;
  825.  
  826.       Entity_Warnings     := Xref_Flag_2;
  827.  
  828.       Xref_Flag           := Xref_Flag_3 or Xref_Flag_4 or Xref_Flag_5
  829.                                or Xref_Flag_6;
  830.  
  831.       Entity_Info_In_Xref := Xref_Flag_6;
  832.  
  833.       All_Info_In_Xref    := Xref_Flag_5 or Xref_Flag_6;
  834.  
  835.       Global_Xref_File    := Xref_Flag_6;
  836.  
  837.       Include_Inlined     := Xref_Flag_4;
  838.  
  839.       Spec_REQs_Flag      := Xref_Flag_S;
  840.  
  841.       Body_REQs_Flag      := Xref_Flag_B;
  842.  
  843.       Xref_Analyze        := (With_Warnings
  844.                                 or else Spec_REQs_Flag
  845.                                 or else Body_REQs_Flag
  846.                                 or else Xref_Flag)
  847.                              and then Operating_Mode /= Check_Semantics;
  848.  
  849.    end Initialize;
  850.  
  851.    -------------------
  852.    -- Link_Subunits --
  853.    -------------------
  854.  
  855.    procedure Link_Subunits (The_Unit : Unit_Number_Type) is
  856.       Top_Node  : constant Node_Id := Cunit (The_Unit);
  857.       Etbl_Tmp  : Entity_Table_Acc;
  858.  
  859.    begin
  860.       Etbl_Tmp := Loaded_Files (The_Unit).Etbl;
  861.  
  862.       for J in Loaded_Files'Range loop
  863.          if Loaded_Files (J).Etbl /= null
  864.            and then Loaded_Files (J).Etbl.Kind = Subunit
  865.            and then J /= The_Unit
  866.            and then Library_Unit (Cunit (J)) = Top_Node
  867.            and then Loaded_Files (J).Etbl.Predecessor = null
  868.          then
  869.             while Etbl_Tmp.Successor /= null loop
  870.                Etbl_Tmp := Etbl_Tmp.Successor;
  871.             end loop;
  872.  
  873.             Etbl_Tmp.Successor := Loaded_Files (J).Etbl;
  874.  
  875.             --  Temporary The predecessor of a subunit is the body
  876.             --  where the stub is defined  ???
  877.  
  878.             Loaded_Files (J).Etbl.Predecessor := Loaded_Files (The_Unit).Etbl;
  879.             Loaded_Files (J).Etbl.Linked := True;
  880.          end if;
  881.       end loop;
  882.  
  883.       Loaded_Files (The_Unit).Etbl.Linked := True;
  884.    end Link_Subunits;
  885.  
  886.    ---------------------
  887.    -- Remove_Entities --
  888.    ---------------------
  889.  
  890.    procedure Remove_Entities
  891.      (The_Etbl : Entity_Table_Acc;
  892.       Found    : in out Boolean)
  893.    is
  894.       E_Tmp : Entity_Acc;
  895.       --  To store the current entity within the loop.
  896.  
  897.       procedure Remove_Element (The_Node : Node_Id);
  898.       --  Removes the given node and also the surrounding Ada construct.
  899.  
  900.       procedure Remove_Pragmas (The_Entity : Entity_Acc);
  901.       --  Removes all the pragma nodes within the program tree which
  902.       --  apply on the given entity.
  903.  
  904.       --------------------
  905.       -- Remove_Element --
  906.       --------------------
  907.  
  908.       procedure Remove_Element (The_Node : Node_Id) is
  909.          L_Tmp : List_Id;
  910.          P_Tmp : Node_Id;
  911.  
  912.          procedure Remove_List;
  913.  
  914.          procedure Remove_List is
  915.             L_Tmp : List_Id;
  916.             P_Tmp : Node_Id;
  917.  
  918.          begin
  919.             P_Tmp := Parent (The_Node);
  920.  
  921.             if Is_List_Member (The_Node) then
  922.                L_Tmp := List_Containing (The_Node);
  923.  
  924.                --  Cancel the references in the subtree of The_Node;
  925.  
  926.                Traverse_Node_Hierarchic (The_Node);
  927.                Remove (The_Node);
  928.  
  929.                if Is_Empty_List (L_Tmp) then
  930.                   Remove_Element (P_Tmp);
  931.                end if;
  932.  
  933.             else
  934.                --  Cancel the references in the subtree of The_Node
  935.  
  936.                Traverse_Node_Hierarchic (The_Node);
  937.                Remove_Element (P_Tmp);
  938.             end if;
  939.          end Remove_List;
  940.  
  941.       begin
  942.          if Nkind (The_Node) in N_Entity then
  943.  
  944.          --  If we get a N_Defining_Identifier, N_Defining_Character_Literal or
  945.          --  N_Defining_Operator_Symbol, then we have to distinguish between
  946.          --  the various kinds of entities.
  947.  
  948.             case Ekind (The_Node) is
  949.  
  950.                --  We don't remove void entities since they are used internally
  951.  
  952.                when E_Void =>
  953.                   null;
  954.  
  955.                --  Processing for variable (this is slightly different from the
  956.                --  processing for constant, is that really correct ???)
  957.  
  958.                when E_Variable =>
  959.  
  960.                   Remove_List;
  961.  
  962.                --  Don't do anything with components, since it is very tricky
  963.                --  to find a hidden reference for a record component (e.g. in
  964.                --  an aggregate, all components are implicitly referenced).
  965.  
  966.                when E_Component =>
  967.                   null;
  968.  
  969.                --  Main processing for most cases
  970.  
  971.                when E_Constant                      |
  972.                     E_Named_Integer                 |
  973.                     E_Named_Real                    |
  974.                     E_Enumeration_Type              |
  975.                     E_Enumeration_Subtype           |
  976.                     E_Signed_Integer_Type           |
  977.                     E_Signed_Integer_Subtype        |
  978.                     E_Modular_Integer_Type          |
  979.                     E_Modular_Integer_Subtype       |
  980.                     E_Floating_Point_Type           |
  981.                     E_Floating_Point_Subtype        |
  982.                     E_Ordinary_Fixed_Point_Type     |
  983.                     E_Ordinary_Fixed_Point_Subtype  |
  984.                     E_Decimal_Fixed_Point_Type      |
  985.                     E_Decimal_Fixed_Point_Subtype   |
  986.                     E_Array_Type                    |
  987.                     E_Array_Subtype                 |
  988.                     E_String_Type                   |
  989.                     E_String_Subtype                |
  990.                     E_String_Literal_Subtype        |
  991.                     E_Enum_Table_Type               |
  992.                     E_Class_Wide_Subtype            |
  993.                     E_Class_Wide_Type               |
  994.                     E_Record_Type                   |
  995.                     E_Record_Subtype                |
  996.                     E_Access_Type                   |
  997.                     E_Access_Subtype                |
  998.                     E_General_Access_Type           |
  999.                     E_Subprogram_Type               |
  1000.                     E_Incomplete_Type               |
  1001.                     E_Limited_Type                  |
  1002.                     E_Task_Type                     |
  1003.                     E_Task_Subtype                  |
  1004.                     E_Protected_Type                |
  1005.                     E_Protected_Subtype             |
  1006.                     E_Exception_Type                |
  1007.                     E_Discriminant                  |
  1008.                     E_Loop                          |
  1009.                     E_Loop_Parameter                |
  1010.                     E_Block                         |
  1011.                     E_Label                         |
  1012.                     E_Entry                         |
  1013.                     E_Protected_Object              |
  1014.                     E_Entry_Family                  |
  1015.                     E_Entry_Index_Parameter         |
  1016.                     E_Exception                     =>
  1017.  
  1018.                   Remove_List;
  1019.  
  1020.                --  Private type processing
  1021.  
  1022.                when E_Record_Type_With_Private    |
  1023.                     E_Record_Subtype_With_Private |
  1024.                     E_Private_Type                |
  1025.                     E_Private_Subtype             |
  1026.                     E_Limited_Private_Type        |
  1027.                     E_Limited_Private_Subtype     =>
  1028.  
  1029.                   Remove_Element (Full_View (The_Node));
  1030.                   Remove_List;
  1031.  
  1032.                when E_Enumeration_Literal =>
  1033.  
  1034.                   --  Since it's very tricky to find a hidden reference for an
  1035.                   --  enumeration literal we do nothing (e.g. in a loop from
  1036.                   --  type'First to type'Last all literals are automatically
  1037.                   --  referenced).
  1038.  
  1039.                   null;
  1040.  
  1041.                when E_Function  |
  1042.                     E_Operator  |
  1043.                     E_Procedure |
  1044.                     E_Package   =>
  1045.  
  1046.                   --  Compilation unit nodes are not removed since
  1047.                   --  this causes a lot of trouble.
  1048.  
  1049.                   if Scope (The_Node) > Last_Standard_Node_Id then
  1050.  
  1051.                      --  Cancel the references in the subtree of The_Node.
  1052.  
  1053.                      Traverse_Node_Hierarchic (The_Node);
  1054.  
  1055.                      P_Tmp := Parent (The_Node);
  1056.                      Remove_Element (P_Tmp);
  1057.  
  1058.                      --  There are only two possibilities in this case:
  1059.                      --  Either the parent is a N_Function_Specification or
  1060.                      --  a N_Procedure_Specification.
  1061.  
  1062.                   end if;
  1063.  
  1064.                --  Cannot delete a parameter of a subprogram (or at least not
  1065.                --  easily because it would have all sorts of consequences)
  1066.  
  1067.                when E_In_Parameter       |
  1068.                     E_Out_Parameter      |
  1069.                     E_In_Out_Parameter   =>
  1070.  
  1071.                   null;
  1072.  
  1073.                --  For the moment, forget the case of generics and their formal
  1074.                --  parameters. Might try to do something later here ???
  1075.  
  1076.                when E_Generic_Package              |
  1077.                     E_Generic_Function             |
  1078.                     E_Generic_Procedure            |
  1079.                     E_Generic_In_Parameter         |
  1080.                     E_Generic_In_Out_Parameter     =>
  1081.  
  1082.                   null;
  1083.  
  1084.                --  Body entities have no significance semantically, so ignore
  1085.  
  1086.                when E_Task_Body        |
  1087.                     E_Subprogram_Body  |
  1088.                     E_Package_Body     |
  1089.                     E_Protected_Body   =>
  1090.  
  1091.                   null;
  1092.  
  1093.                --  Internal allocator and access types should never appear
  1094.                --  at the stage a cross-reference is being computed
  1095.  
  1096.                when E_Allocator_Type          |
  1097.                     E_Access_Subprogram_Type  |
  1098.                     E_Anonymous_Access_Type   =>
  1099.  
  1100.                   pragma Assert (False); null;
  1101.             end case;
  1102.  
  1103.          else
  1104.             case Nkind (The_Node) is
  1105.  
  1106.                when N_Empty =>
  1107.                   null;
  1108.  
  1109.                when N_Function_Specification .. N_Procedure_Specification =>
  1110.  
  1111.                   --  There are only two possibilities in this case:
  1112.                   --  Either the parent is a N_Subprogram_Declaration or
  1113.                   --  a N_Subprogram_Body.
  1114.  
  1115.                   P_Tmp := Parent (The_Node);
  1116.                   Remove_Element (P_Tmp);
  1117.  
  1118.                when N_Component_List | N_Record_Definition =>
  1119.  
  1120.                   --  These are intermediate nodes.
  1121.                   --  In this cases we don't remove the parent
  1122.                   --  (e.g. N_Record_Definition for a N_Component_List)
  1123.                   --  since the Record identifier is treated separately.
  1124.  
  1125.                   null;
  1126.  
  1127.                when N_Object_Declaration =>
  1128.                   if Is_List_Member (The_Node) then
  1129.                      L_Tmp := List_Containing (The_Node);
  1130.                      P_Tmp := Parent (The_Node);
  1131.  
  1132.                      Traverse_Node_Hierarchic (The_Node);
  1133.                      --  To cancel the references in the subtree of The_Node.
  1134.  
  1135.                      Remove (The_Node);
  1136.  
  1137.                      --  Here we do *not* remove the parent since then we
  1138.                      --  would delete the whole subprogram.
  1139.                   end if;
  1140.  
  1141.                when others =>
  1142.                   Remove_List;
  1143.             end case;
  1144.          end if;
  1145.  
  1146.       end Remove_Element;
  1147.  
  1148.       --------------------
  1149.       -- Remove_Pragmas --
  1150.       --------------------
  1151.  
  1152.       procedure Remove_Pragmas (The_Entity : Entity_Acc) is
  1153.          R_Tmp : Ref_Acc := Xref_Tab.First (The_Entity);
  1154.  
  1155.       begin
  1156.          while not Is_Null (R_Tmp) loop
  1157.  
  1158.             if Is_Pragma (R_Tmp) then
  1159.                Remove_Element (Parent (Parent (The_Node (R_Tmp))));
  1160.             end if;
  1161.  
  1162.             R_Tmp := Next (R_Tmp);
  1163.          end loop;
  1164.  
  1165.       end Remove_Pragmas;
  1166.  
  1167.    -------------------------------------------
  1168.    --  Start Processing for Remove_Entities --
  1169.    -------------------------------------------
  1170.  
  1171.    begin
  1172.       E_Tmp := The_Etbl.First_Entity;
  1173.       Found := False;
  1174.  
  1175.       Phase := Unmark_Refs;
  1176.       Init_Numbers;
  1177.  
  1178.       while not Is_Null (E_Tmp) loop
  1179.  
  1180.          if Number_Of_Marks (E_Tmp) = 0
  1181.            and then Give_Warning (E_Tmp)
  1182.          then
  1183.             --  Update the Entity_Table:
  1184.  
  1185.             Found := True;
  1186.  
  1187.             --  We mark the entity in our entity table for the next pass
  1188.             --  to say: Don't remove this entity twice!
  1189.  
  1190.             Mark_Entity (E_Tmp);
  1191.  
  1192.             --  Update the program tree:
  1193.             --
  1194.             --  Since we need E_Tmp to find the pragmas, we have to
  1195.             --  remove the pragmas here rather than in Remove_Element
  1196.  
  1197.             if Entity_Type (E_Tmp) in E_Function .. E_Procedure then
  1198.                Remove_Pragmas (E_Tmp);
  1199.             end if;
  1200.  
  1201.             --  Remove the entities with no references.
  1202.  
  1203.             Remove_Element (Entity_Node (E_Tmp));
  1204.  
  1205.          end if;
  1206.  
  1207.          E_Tmp := Next (E_Tmp);
  1208.  
  1209.       end loop;
  1210.    end Remove_Entities;
  1211.  
  1212.    -------------------------
  1213.    -- Set_Spec_REQ_Flags  --
  1214.    -------------------------
  1215.  
  1216.    procedure Set_Spec_REQ_Flags (The_Etbl : Entity_Table_Acc) is
  1217.       Etbl_Tmp    : Entity_Table_Acc;
  1218.       With_Clause : With_Acc;
  1219.  
  1220.    begin
  1221.       --  Mark a spec withed by The_Etbl or a predecessor.
  1222.  
  1223.       Etbl_Tmp := The_Etbl;
  1224.       while Etbl_Tmp /= null loop
  1225.  
  1226.          With_Clause := Etbl_Tmp.First_With;
  1227.          while With_Clause /= null loop
  1228.  
  1229.             if With_Clause.Withed_Etbl.Kind /= Genr then
  1230.                Loaded_Files (Get_Cunit_Unit_Number
  1231.                  (With_Clause.Withed_Etbl.Top_Node)).Create_REQ := True;
  1232.             end if;
  1233.  
  1234.             --  Note: we don't create a REQ for a generic.
  1235.  
  1236.             With_Clause.Withed_Etbl.Status := Withed_Spec;
  1237.             With_Clause := With_Clause.Next_With;
  1238.          end loop;
  1239.  
  1240.          Etbl_Tmp := Etbl_Tmp.Predecessor;
  1241.       end loop;
  1242.  
  1243.       --  Mark a spec withed by a successor.
  1244.  
  1245.       Etbl_Tmp := The_Etbl.Successor;
  1246.  
  1247.       while Etbl_Tmp /= null loop
  1248.  
  1249.          With_Clause := Etbl_Tmp.First_With;
  1250.          while With_Clause /= null loop
  1251.  
  1252.             if With_Clause.Withed_Etbl.Kind /= Genr then
  1253.                Loaded_Files (Get_Cunit_Unit_Number
  1254.                  (With_Clause.Withed_Etbl.Top_Node)).Create_REQ := True;
  1255.             end if;
  1256.  
  1257.             --  Note: we don't create a REQ for a generic.
  1258.  
  1259.             With_Clause.Withed_Etbl.Status := Withed_Spec;
  1260.             With_Clause := With_Clause.Next_With;
  1261.          end loop;
  1262.  
  1263.          Etbl_Tmp := Etbl_Tmp.Successor;
  1264.       end loop;
  1265.  
  1266.    end Set_Spec_REQ_Flags;
  1267.  
  1268.    ------------------------------
  1269.    -- Traverse_Node_Hierarchic --
  1270.    ------------------------------
  1271.  
  1272.    procedure Traverse_Node_Hierarchic (N : Node_Id) is
  1273.       Kind        : Node_Kind;
  1274.       Unum        : Unit_Number_Type;
  1275.       To_Unum     : Unit_Number_Type;
  1276.       To_Entity   : Entity_Id;
  1277.       --  Only to reduce the length of some function calls.
  1278.  
  1279.       procedure Mark_Full_Declaration (N : Node_Id);
  1280.       --  Marks the node corresponding to the full declaration of N
  1281.       --  as having a previous incomplete definition
  1282.  
  1283.       procedure Visit_List (L : List_Id);
  1284.       --  Visits the nodes of a list in the program tree
  1285.  
  1286.       procedure Visit_Elist (E : Elist_Id);
  1287.  
  1288.       procedure Visit_Descendent (D : Union_Id);
  1289.       pragma Inline (Visit_Descendent);
  1290.       --  Visits a descendent of a node, where D is the descendent
  1291.  
  1292.       -------------------
  1293.       -- Mark_Internal --
  1294.       -------------------
  1295.  
  1296.       procedure Mark_Full_Declaration (N : Node_Id) is
  1297.          Parent_Node : constant Node_Id := Parent (N);
  1298.          H           : Nat;
  1299.  
  1300.       begin
  1301.          if Nkind (Parent_Node) = N_Private_Type_Declaration
  1302.            or else Nkind (Parent_Node) = N_Incomplete_Type_Declaration
  1303.            or else (Nkind (Parent_Node) = N_Object_Declaration
  1304.                     and then Constant_Present (Parent_Node)
  1305.                     and then Expression (Parent_Node) = Empty)
  1306.          then
  1307.             H := Int (Full_View (N)) mod Hash_Table_Len;
  1308.             Hash_Table (H).Id := Int (Full_View (N));
  1309.             Hash_Table (H).Prev_Inc_Typ_Def := True;
  1310.          end if;
  1311.       end Mark_Full_Declaration;
  1312.  
  1313.       -----------------
  1314.       -- Visit_Elist --
  1315.       -----------------
  1316.  
  1317.       procedure Visit_Elist (E : Elist_Id) is
  1318.          M : Elmt_Id;
  1319.          S : constant Nat := Serial_Number (Int (E));
  1320.  
  1321.       begin
  1322.          if S /= 0 then
  1323.             return;
  1324.          else
  1325.             Set_Serial_Number;
  1326.          end if;
  1327.  
  1328.          M := First_Elmt (E);
  1329.  
  1330.          while Present (M) loop
  1331.             Traverse_Node_Hierarchic (Node (M));
  1332.             M := Next_Elmt (M);
  1333.          end loop;
  1334.       end Visit_Elist;
  1335.  
  1336.       ----------------
  1337.       -- Visit_List --
  1338.       ----------------
  1339.  
  1340.       procedure Visit_List (L : List_Id) is
  1341.          N : Node_Id;
  1342.          S : constant Nat := Serial_Number (Int (L));
  1343.  
  1344.       begin
  1345.  
  1346.          if S /= 0 then
  1347.             return;
  1348.          else
  1349.             Set_Serial_Number;
  1350.          end if;
  1351.  
  1352.          N := First (L);
  1353.  
  1354.          if N /= Empty then
  1355.             while Next (N) /= Empty loop
  1356.                Traverse_Node_Hierarchic (N);
  1357.                N := Next (N);
  1358.             end loop;
  1359.          end if;
  1360.  
  1361.          Traverse_Node_Hierarchic (N);
  1362.       end Visit_List;
  1363.  
  1364.       ----------------------
  1365.       -- Visit_Descendent --
  1366.       ----------------------
  1367.  
  1368.       procedure Visit_Descendent (D : Union_Id) is
  1369.       begin
  1370.          if D in Node_Range then
  1371.             if D <= Union_Id (Empty_Or_Error) then
  1372.                return;
  1373.             end if;
  1374.  
  1375.             if Sloc (Node_Id (D)) <= Standard_Location then
  1376.                if Sloc (N) > Standard_Location then
  1377.                   return;
  1378.                end if;
  1379.             else
  1380.                if Sloc (N) <= Standard_Location
  1381.                  or else Sloc (N) = No_Location
  1382.                  or else Sloc (Node_Id (D)) = No_Location
  1383.                  or else Get_Sloc_Unit_Number (Sloc (Node_Id (D))) /=
  1384.                          Get_Sloc_Unit_Number (Sloc (N))
  1385.                then
  1386.                   return;
  1387.                end if;
  1388.             end if;
  1389.  
  1390.             if Parent (Node_Id (D)) /= Empty
  1391.               and then Parent (Node_Id (D)) /= N
  1392.             then
  1393.                return;
  1394.             end if;
  1395.  
  1396.             Traverse_Node_Hierarchic (Node_Id (D));
  1397.  
  1398.          elsif D in List_Range then
  1399.             if D = Union_Id (No_List)
  1400.               or else D = Union_Id (Error_List)
  1401.               or else Is_Empty_List (List_Id (D))
  1402.             then
  1403.                return;
  1404.             else
  1405.                Visit_List (List_Id (D));
  1406.             end if;
  1407.  
  1408.          elsif D in Elist_Range then
  1409.             if D = Union_Id (No_Elist)
  1410.               or else Is_Empty_Elmt_List (Elist_Id (D))
  1411.             then
  1412.                return;
  1413.             else
  1414.                Visit_Elist (Elist_Id (D));
  1415.             end if;
  1416.  
  1417.          else
  1418.             null;
  1419.          end if;
  1420.       end Visit_Descendent;
  1421.  
  1422.    ------------------------------------------------------
  1423.    -- Start of Processing for Traverse_Node_Hierarchic --
  1424.    ------------------------------------------------------
  1425.  
  1426.    begin
  1427.       if N = Empty then
  1428.          return;
  1429.       end if;
  1430.  
  1431.       Internal_Node := False;
  1432.  
  1433.       if Serial_Number (Int (N)) /= 0 then
  1434.          return; -- already visited
  1435.       else
  1436.          Set_Serial_Number;
  1437.       end if;
  1438.  
  1439.       Kind := Nkind (N);
  1440.  
  1441.       --  Look for named numbers or other constructs which get transformed
  1442.       --  into the corresponding litterals during semantics.
  1443.  
  1444.       if Is_Rewrite_Substitution (N) then
  1445.          Traverse_Node_Hierarchic (Original_Node (N));
  1446.       end if;
  1447.  
  1448.       if Kind in N_Entity
  1449.         and then (Ekind (N) /= E_Void
  1450.                    or else Nkind (Parent (N)) in N_Generic_Instantiation)
  1451.         and then Comes_From_Source (N)
  1452.         and then Parent (N) /= Empty
  1453.       then
  1454.          --  In the case we don't want the whole cross reference list to be
  1455.          --  generated we don't add declaration of :
  1456.          --     - enumeration litterals
  1457.          --     - record components
  1458.          --     - Parameters
  1459.  
  1460.          if (All_Info_In_Xref
  1461.               or else
  1462.                 (Nkind (Parent (N)) /= N_Enumeration_Type_Definition
  1463.                   and then Nkind (Parent (N)) /= N_Component_Declaration))
  1464.            and then not Internal_Node
  1465.          then
  1466.             Unum := Get_Sloc_Unit_Number (Sloc (N));
  1467.  
  1468.             case Phase is
  1469.  
  1470.                when Add_Entities_And_Refs =>
  1471.  
  1472.                   if Loaded_Files (Unum).Etbl.Examined then
  1473.                      Update_Entity (Loaded_Files (Unum).Etbl,
  1474.                        N, Entity_Association (N));
  1475.                   else
  1476.                      Add_Entity (Loaded_Files (Unum).Etbl,
  1477.                        N, Entity_Association (N));
  1478.                   end if;
  1479.  
  1480.                   Mark_Full_Declaration (N);
  1481.  
  1482.                when Unmark_Refs =>
  1483.  
  1484.                   --  We mark the entity and all its descendents in our
  1485.                   --  entity table for the next pass to say:
  1486.                   --  Don't remove this entity twice! It's already removed.
  1487.  
  1488.                Mark_Entity (In_E_List (Loaded_Files (Unum).Etbl, N));
  1489.  
  1490.             end case;
  1491.          end if;
  1492.  
  1493.       elsif Kind = N_Identifier then
  1494.  
  1495.          --  In the case we don't want the whole cross-reference list to be
  1496.          --  generated we don.t add reference to parameters.
  1497.  
  1498.          if Nkind (Parent (N)) = N_Range
  1499.            and then Parent (Parent (N)) = Empty
  1500.          then
  1501.             --  We don't accept things like an internal range declaration
  1502.  
  1503.             null;
  1504.  
  1505.          elsif Entity (N) > Last_Standard_Node_Id then
  1506.  
  1507.          --  We suppress references to standard entities (e.g. integer)
  1508.  
  1509.             case Phase is
  1510.                when Add_Entities_And_Refs =>
  1511.  
  1512.                   --  Check that we don't add an internal reference
  1513.  
  1514.                   if Sloc (N) > 0 then
  1515.                      Ref_Length := Ref_Length + 1;
  1516.                      Ref_Buffer (Ref_Length) := N;
  1517.                   end if;
  1518.  
  1519.                when Unmark_Refs          =>
  1520.                   To_Entity := Entity (N);
  1521.                   To_Unum := Get_Sloc_Unit_Number (Sloc (To_Entity));
  1522.                   Unmark_Reference (Entity_Association (To_Entity), N);
  1523.             end case;
  1524.          end if;
  1525.  
  1526.       elsif (Kind in N_Op
  1527.               or else Kind = N_Attribute_Reference
  1528.               or else Kind = N_Character_Literal
  1529.               or else Kind = N_Expanded_Name
  1530.               or else Kind = N_Operator_Symbol)
  1531.         and then Entity (N) > Last_Standard_Node_Id
  1532.       then
  1533.          case Phase is
  1534.             when Add_Entities_And_Refs =>
  1535.  
  1536.                --  Checks that we don't add an internal reference
  1537.  
  1538.                if Sloc (N) > 0 then
  1539.                   Ref_Length := Ref_Length + 1;
  1540.                   Ref_Buffer (Ref_Length) := N;
  1541.                end if;
  1542.  
  1543.             when Unmark_Refs =>
  1544.                To_Entity := Entity (N);
  1545.                To_Unum := Get_Sloc_Unit_Number (Sloc (To_Entity));
  1546.                Unmark_Reference (Entity_Association (To_Entity), N);
  1547.          end case;
  1548.       end if;
  1549.  
  1550.       declare
  1551.          use Unchecked_Access;
  1552.  
  1553.       begin
  1554.          Visit_Descendent (Field1 (N));
  1555.          Visit_Descendent (Field2 (N));
  1556.          Visit_Descendent (Field3 (N));
  1557.          Visit_Descendent (Field4 (N));
  1558.          Visit_Descendent (Field5 (N));
  1559.  
  1560.          if Atree.Has_Extension (N) then
  1561.             Visit_Descendent (Field6 (N));
  1562.             Visit_Descendent (Field7 (N));
  1563.             Visit_Descendent (Field8 (N));
  1564.             Visit_Descendent (Field9 (N));
  1565.             Visit_Descendent (Field10 (N));
  1566.             Visit_Descendent (Field11 (N));
  1567.             Visit_Descendent (Field12 (N));
  1568.             Visit_Descendent (Field13 (N));
  1569.             Visit_Descendent (Field14 (N));
  1570.          end if;
  1571.       end;
  1572.    end Traverse_Node_Hierarchic;
  1573.  
  1574.    ---------------
  1575.    -- Write_Org --
  1576.    ---------------
  1577.  
  1578.    procedure Write_Org (The_Etbl : Entity_Table_Acc) is
  1579.    begin
  1580.       Name_Len := The_Etbl.File_Name'Length;
  1581.       Name_Buffer (1 .. Name_Len) := The_Etbl.File_Name.all;
  1582.       Name_Buffer (Name_Len - 3 ..
  1583.                    Name_Len - 4 + Org_Spec_Suffix'Length) := Org_Spec_Suffix;
  1584.       Name_Buffer (Name_Len - 3 + Org_Spec_Suffix'Length) := Ascii.NUL;
  1585.  
  1586.       Create_Req_Output;
  1587.  
  1588.       Sprint_Node (The_Etbl.Top_Node);
  1589.  
  1590.       Write_Eol;
  1591.       Set_Standard_Output;
  1592.       Close_Xref_Output;
  1593.    end Write_Org;
  1594.  
  1595.    ---------------------
  1596.    -- Write_Body_REQs --
  1597.    ---------------------
  1598.  
  1599.    procedure Write_Body_REQs is
  1600.       Main_Etbl  : Entity_Table_Acc := Loaded_Files (Main_Unit).Etbl;
  1601.       Etbl_Tmp_1 : Entity_Table_Acc;
  1602.       Etbl_Tmp_2 : Entity_Table_Acc;
  1603.  
  1604.       First : Boolean;
  1605.       Found : Boolean;
  1606.  
  1607.       procedure Open_File (The_Etbl : Entity_Table_Acc);
  1608.       --  Open file to write Body_REQs
  1609.  
  1610.       procedure Close_File;
  1611.       --  Close the file after Body_REQs are written
  1612.  
  1613.       procedure Open_File (The_Etbl : Entity_Table_Acc) is
  1614.       begin
  1615.          --  Here we build the file name of the Body_REQ.
  1616.          --  The file name is the file name of the body,
  1617.          --  the suffix '.adb' changed into Body_REQ_Suffix !
  1618.  
  1619.          Name_Len := The_Etbl.File_Name.all'Length;
  1620.          Name_Buffer (1 .. Name_Len) := The_Etbl.File_Name.all;
  1621.          Name_Buffer (Name_Len - 3 .. Name_Len - 4 + Body_REQ_Suffix'Length)
  1622.            := Body_REQ_Suffix;
  1623.          Name_Buffer (Name_Len - 3 + Body_REQ_Suffix'Length) := Ascii.NUL;
  1624.  
  1625.          Create_Req_Output;
  1626.       end Open_File;
  1627.  
  1628.       procedure Close_File is
  1629.       begin
  1630.          Write_Eol;
  1631.          Set_Standard_Output;
  1632.          Close_Xref_Output;
  1633.       end Close_File;
  1634.  
  1635.    --  Start of processing for Write_Body_REQs
  1636.  
  1637.    begin
  1638.       Etbl_Tmp_1 := Main_Etbl;
  1639.       Etbl_Tmp_2 := Main_Etbl;
  1640.       First      := True;
  1641.  
  1642.       while Etbl_Tmp_1 /= null loop
  1643.  
  1644.          --  First we have to mark the body and its subunits across each
  1645.          --  others.
  1646.  
  1647.          while Etbl_Tmp_2 /= null loop
  1648.  
  1649.             Clear_And_Mark_Xrefs (Etbl_Tmp_1, Etbl_Tmp_2, First, False);
  1650.             First := False;
  1651.  
  1652.             Etbl_Tmp_2 := Etbl_Tmp_2.Successor;
  1653.          end loop;
  1654.  
  1655.          --  Then remove the entities with no references step by step until
  1656.          --  all the remaining entities have one or more references. This must
  1657.          --  be done within a loop because after having removed some entities
  1658.          --  an earlier defined entity may become removable.
  1659.  
  1660.          --  Write_Org (Etbl_Tmp_1);  can be inserted to measure dead code ???
  1661.  
  1662.          Found := True;
  1663.          while Found loop
  1664.             Remove_Entities (Etbl_Tmp_1, Found);
  1665.          end loop;
  1666.  
  1667.          Open_File (Etbl_Tmp_1);
  1668.  
  1669.          --  CC
  1670.          --  don't touch the indentation now.
  1671.          --  has to be fixed later  ???
  1672.          --
  1673.          --  Xsprint.Indent := 0;
  1674.  
  1675.          Sprint_Node (Etbl_Tmp_1.Top_Node);
  1676.          Close_File;
  1677.  
  1678.          Etbl_Tmp_1 := Etbl_Tmp_1.Successor;
  1679.          Etbl_Tmp_2 := Main_Etbl;
  1680.          First      := True;
  1681.       end loop;
  1682.    end Write_Body_REQs;
  1683.  
  1684.    ---------------------
  1685.    -- Write_Spec_REQs --
  1686.    ---------------------
  1687.  
  1688.    procedure Write_Spec_REQs is
  1689.       Buffer : String (1 .. 100);
  1690.       Length : Integer;
  1691.       Found  : Boolean;
  1692.  
  1693.       Etbl_Tmp   : Entity_Table_Acc;
  1694.  
  1695.       procedure Open_File (I : Unit_Number_Type);
  1696.       --  Open file to write Spec_REQs
  1697.  
  1698.       procedure Close_File;
  1699.       --  Close the file after Spec_REQs are written
  1700.  
  1701.       procedure Open_File (I : Unit_Number_Type) is
  1702.       begin
  1703.          --  Here we build the file name of the Spec_REQ.
  1704.          --  The file name is the file name of the withed unit,
  1705.          --  the suffix changed from '.ads' into
  1706.          --  '.' & withing_unit_name & Spec_REQ_Suffix !
  1707.  
  1708.          Get_Name_String (File_Name (Source_Index (Main_Unit)));
  1709.          Buffer (1 .. Name_Len) := Name_Buffer (1 .. Name_Len);
  1710.          Length := Name_Len - 3;
  1711.  
  1712.          Get_Name_String (File_Name (Source_Index (I)));
  1713.          Name_Buffer (Name_Len + 1 .. Length + Name_Len) :=
  1714.             Buffer (1 .. Length);
  1715.          Length := Length + Name_Len - 4;
  1716.  
  1717.          Name_Buffer (Length + 1 .. Length + Spec_REQ_Suffix'Length)
  1718.            := Spec_REQ_Suffix;
  1719.          Name_Buffer (Length + Spec_REQ_Suffix'Length + 1) := Ascii.NUL;
  1720.  
  1721.          Create_Req_Output;
  1722.       end Open_File;
  1723.  
  1724.       procedure Close_File is
  1725.       begin
  1726.          Write_Eol;
  1727.          Set_Standard_Output;
  1728.          Close_Xref_Output;
  1729.       end Close_File;
  1730.  
  1731.    --  Start of processing for Write_Spec_REQs
  1732.  
  1733.    begin
  1734.       for J in Loaded_Files'Range loop
  1735.  
  1736.          if Loaded_Files (J).Create_REQ then
  1737.  
  1738.             --  First we mark all the entities which are used by the withed
  1739.             --  spec itself.
  1740.  
  1741.             Clear_And_Mark_Xrefs (Loaded_Files (J).Etbl,
  1742.               Loaded_Files (J).Etbl, True, False);
  1743.  
  1744.             --  Then we mark all the entities which are used by the main object
  1745.             --  (Main_Unit, all predecessors and all successors).
  1746.  
  1747.             Etbl_Tmp := Loaded_Files (Main_Unit).Etbl;
  1748.             while Etbl_Tmp /= null loop
  1749.                Clear_And_Mark_Xrefs
  1750.                  (Loaded_Files (J).Etbl, Etbl_Tmp, False, False);
  1751.                Etbl_Tmp := Etbl_Tmp.Predecessor;
  1752.             end loop;
  1753.  
  1754.             Etbl_Tmp := Loaded_Files (Main_Unit).Etbl.Successor;
  1755.             while Etbl_Tmp /= null loop
  1756.                Clear_And_Mark_Xrefs
  1757.                  (Loaded_Files (J).Etbl, Etbl_Tmp, False, False);
  1758.                Etbl_Tmp := Etbl_Tmp.Successor;
  1759.             end loop;
  1760.  
  1761.             --  Then remove the entities with no references step by step until
  1762.             --  all the remaining entities have one or more references. This
  1763.             --  must be done within a loop because after having removed some
  1764.             --  entities an earlier defined entity may become removable.
  1765.  
  1766.             Found := True;
  1767.             while Found loop
  1768.                Remove_Entities (Loaded_Files (J).Etbl, Found);
  1769.             end loop;
  1770.  
  1771.             Open_File (J);
  1772.  
  1773.             --  CC
  1774.             --  don't touch the indentation now.
  1775.             --  has to be fixed later  ???
  1776.             --  Xsprint.Indent := 0;
  1777.  
  1778.             Sprint_Node (Cunit (J));
  1779.             Close_File;
  1780.          end if;
  1781.  
  1782.       end loop;
  1783.    end Write_Spec_REQs;
  1784.  
  1785.    ----------------
  1786.    -- Write_Xref --
  1787.    ----------------
  1788.  
  1789.    procedure Write_Xref (The_Etbl : Entity_Table_Acc) is
  1790.       Etbl_Tmp     : Entity_Table_Acc := The_Etbl;
  1791.       Etbl_Scanned : Entity_Table_Acc;
  1792.  
  1793.    begin
  1794.       if Xref_Flag then
  1795.  
  1796.          --  File and warning messages output
  1797.  
  1798.          Create_Xref_Output (Global_Xref_File);
  1799.  
  1800.          if Global_Xref_File then
  1801.  
  1802.             --  When we generate a complete Xref file then we scan
  1803.             --  all the entity table, but first do the requested units
  1804.             --  so that auxiliary units references will get marked.
  1805.  
  1806.             while Etbl_Tmp /= null loop
  1807.                if Etbl_Tmp.RU then
  1808.                   Writ (Etbl_Tmp, Full_Xref, False);
  1809.                end if;
  1810.  
  1811.                Etbl_Tmp := Etbl_Tmp.Next_Etbl;
  1812.             end loop;
  1813.  
  1814.             Etbl_Tmp := The_Etbl;
  1815.             while Etbl_Tmp /= null loop
  1816.                if not Etbl_Tmp.RU and then Etbl_Tmp.Status in Spec_Status then
  1817.                   Writ (Etbl_Tmp, Smart_Xref, False);
  1818.                end if;
  1819.  
  1820.                Etbl_Tmp := Etbl_Tmp.Next_Etbl;
  1821.             end loop;
  1822.  
  1823.             Close_Xref_Output;
  1824.  
  1825.          else
  1826.             --  Before writing any Informations in the xref file we write
  1827.             --  all the files names that have been loaded during the
  1828.             --  previous compilations
  1829.  
  1830.             Write_Version;
  1831.  
  1832.             for The_Units in Loaded_Files'Range loop
  1833.                Write_Files_Info (Loaded_Files (The_Units).Etbl);
  1834.             end loop;
  1835.  
  1836.             --  When we generate a .ref file for each amin file given in
  1837.             --  argument then we scan the main entity table and then all
  1838.             --  the successors and predecesssors which are required units.
  1839.  
  1840.             Writ (Etbl_Tmp, Full_Xref, True);
  1841.             Osint.Close_Xref_Output;
  1842.  
  1843.             Etbl_Scanned := Etbl_Tmp;
  1844.             while Etbl_Scanned.Predecessor /= null loop
  1845.                Etbl_Scanned := Etbl_Scanned.Predecessor;
  1846.             end loop;
  1847.  
  1848.             while Etbl_Scanned /= null loop
  1849.                if Etbl_Scanned.RU and then Etbl_Scanned /= Etbl_Tmp  then
  1850.                   Writ (Etbl_Scanned, Full_Xref, False);
  1851.                end if;
  1852.  
  1853.                Etbl_Scanned := Etbl_Scanned.Successor;
  1854.             end loop;
  1855.  
  1856.          end if;
  1857.  
  1858.       elsif With_Warnings or Entity_Warnings then
  1859.  
  1860.          --  Only warning messages output
  1861.  
  1862.          while Etbl_Tmp /= null loop
  1863.             if Etbl_Tmp.RU then
  1864.                Writ (Etbl_Tmp, Full_Only_Standout, False);
  1865.             end if;
  1866.  
  1867.             Etbl_Tmp := Etbl_Tmp.Next_Etbl;
  1868.          end loop;
  1869.       end if;
  1870.  
  1871.    end Write_Xref;
  1872.  
  1873. end Xref;
  1874.