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 / rtsfind.adb < prev    next >
Text File  |  1996-09-28  |  15KB  |  418 lines

  1. ------------------------------------------------------------------------------
  2. --                                                                          --
  3. --                         GNAT COMPILER COMPONENTS                         --
  4. --                                                                          --
  5. --                              R T S F I N D                               --
  6. --                                                                          --
  7. --                                 B o d y                                  --
  8. --                                                                          --
  9. --                            $Revision: 1.47 $                             --
  10. --                                                                          --
  11. --        Copyright (c) 1992,1993,1994,1995 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 Casing;   use Casing;
  27. with Csets;    use Csets;
  28. with Einfo;    use Einfo;
  29. with Fname;    use Fname;
  30. with Lib;      use Lib;
  31. with Lib.Load; use Lib.Load;
  32. with Namet;    use Namet;
  33. with Nlists;   use Nlists;
  34. with Nmake;    use Nmake;
  35. with Output;   use Output;
  36. with Sem;      use Sem;
  37. with Sem_Util; use Sem_Util;
  38. with Sinfo;    use Sinfo;
  39. with Snames;   use Snames;
  40. with Tbuild;   use Tbuild;
  41.  
  42. package body Rtsfind is
  43.  
  44.    ----------------
  45.    -- Unit table --
  46.    ----------------
  47.  
  48.    --  The unit table has one entry for each unit included in the definition
  49.    --  of the type RTU_Id in the spec. The table entries are initialized in
  50.    --  Initialize to set the Entity field to Empty, indicating that the
  51.    --  corresponding unit has not yet been loaded. The fields are set when
  52.    --  a unit is loaded to contain the defining entity for the unit, the
  53.    --  unit name, and the unit number.
  54.  
  55.    type RT_Unit_Table_Record is record
  56.       Entity : Entity_Id;
  57.       Uname  : Unit_Name_Type;
  58.       Unum   : Unit_Number_Type;
  59.    end record;
  60.  
  61.    RT_Unit_Table : array (RTU_Id) of RT_Unit_Table_Record;
  62.  
  63.    --------------------------
  64.    -- Runtime Entity Table --
  65.    --------------------------
  66.  
  67.    --  There is one entry in the runtime entity table for each entity that is
  68.    --  included in the definition of the RE_Id type in the spec. The entries
  69.    --  are set by Initialize_Rtsfind to contain Empty, indicating that the
  70.    --  entity has not yet been located. Once the entity is located for the
  71.    --  first time, its ID is stored in this array, so that subsequent calls
  72.    --  for the same entity can be satisfied immediately.
  73.  
  74.    RE_Table : array (RE_Id) of Entity_Id;
  75.  
  76.    -----------------------
  77.    -- Local Subprograms --
  78.    -----------------------
  79.  
  80.    procedure Load_Fail (S : String; U_Id : RTU_Id; Ent_Name : String := "");
  81.    --  Internal procedure called if we can't find the entity or unit.
  82.    --  The parameter is a detailed error message that is to be given.
  83.    --  S is a reason for failing to compile the file. U_Id is the unit
  84.    --  id, and Ent_Name, if non-null, is the associated entity name.
  85.  
  86.    procedure Load_RTU (U_Id : RTU_Id; Use_Setting : Boolean := False);
  87.    --  Load the unit whose Id is given if not already loaded. The unit is
  88.    --  loaded, analyzed, and added to the with list, and the entry in
  89.    --  RT_Unit_Table is updated to reflect the load. The second parameter
  90.    --  indicates the initial setting for the Is_Potentially_Use_Visible
  91.    --  flag of the entity for the loaded unit (if it is indeed loaded).
  92.    --  A value of False means nothing special need be done. A value of
  93.    --  True indicates that this flag must be set to True. It is needed
  94.    --  only in the Text_IO_Kludge procedure, which may materialize an
  95.    --  entity of Text_IO (or Wide_Text_IO) that was previously unknown.
  96.  
  97.    ----------------
  98.    -- Initialize --
  99.    ----------------
  100.  
  101.    procedure Initialize is
  102.    begin
  103.       --  Initialize the unit table
  104.  
  105.       for J in RTU_Id loop
  106.          RT_Unit_Table (J).Entity := Empty;
  107.       end loop;
  108.  
  109.       for J in RE_Id loop
  110.          RE_Table (J) := Empty;
  111.       end loop;
  112.    end Initialize;
  113.  
  114.    ---------------
  115.    -- Load_Fail --
  116.    ---------------
  117.  
  118.    procedure Load_Fail (S : String; U_Id : RTU_Id; Ent_Name : String := "") is
  119.    begin
  120.       Set_Standard_Error;
  121.  
  122.       Write_Str ("fatal error: runtime library configuration error");
  123.       Write_Eol;
  124.  
  125.       if Ent_Name /= "" then
  126.          Write_Str ("cannot locate """);
  127.  
  128.          --  Copy name skipping initial RE_ or RO_XX characters
  129.  
  130.          if Ent_Name (1 .. 2) = "RE" then
  131.             for J in 4 .. Ent_Name'Length loop
  132.                Name_Buffer (J - 3) := Ent_Name (J);
  133.             end loop;
  134.          else
  135.             for J in 7 .. Ent_Name'Length loop
  136.                Name_Buffer (J - 6) := Ent_Name (J);
  137.             end loop;
  138.          end if;
  139.  
  140.          Name_Len := Ent_Name'Length - 3;
  141.          Set_Casing (Mixed_Case);
  142.          Write_Str (Name_Buffer (1 .. Name_Len));
  143.          Write_Str (""" in file """);
  144.  
  145.       else
  146.          Write_Str ("cannot load file """);
  147.       end if;
  148.  
  149.       Write_Name (Get_File_Name (RT_Unit_Table (U_Id).Uname));
  150.       Write_Str (""" (");
  151.       Write_Str (S);
  152.       Write_Char (')');
  153.       Write_Eol;
  154.       Set_Standard_Output;
  155.       raise Unrecoverable_Error;
  156.    end Load_Fail;
  157.  
  158.    --------------
  159.    -- Load_RTU --
  160.    --------------
  161.  
  162.    procedure Load_RTU (U_Id : RTU_Id; Use_Setting : Boolean := False) is
  163.       Lib_Unit : Node_Id;
  164.       Loaded   : Boolean;
  165.       U        : RT_Unit_Table_Record renames RT_Unit_Table (U_Id);
  166.       Withn    : Node_Id;
  167.  
  168.    begin
  169.       --  Nothing to do if unit is already loaded
  170.  
  171.       if Present (U.Entity) then
  172.          return;
  173.       end if;
  174.  
  175.       --  Otherwise we need to load the unit, First build unit name
  176.       --  from the enumeration literal name in type RTU_Id.
  177.  
  178.       declare
  179.          Uname_Chars : constant String := RTU_Id'Image (U_Id);
  180.  
  181.       begin
  182.          Name_Len := Uname_Chars'Length;
  183.          Name_Buffer (1 .. Name_Len) := Uname_Chars;
  184.          Set_Casing (All_Lower_Case);
  185.  
  186.          if U_Id in Ada_Child then
  187.             Name_Buffer (4) := '.';
  188.  
  189.             if U_Id in Ada_Calendar_Child then
  190.                Name_Buffer (13) := '.';
  191.  
  192.             elsif U_Id in Ada_Real_Time_Child then
  193.                Name_Buffer (14) := '.';
  194.  
  195.             elsif U_Id in Ada_Text_IO_Child then
  196.                Name_Buffer (12) := '.';
  197.  
  198.             elsif U_Id in Ada_Wide_Text_IO_Child then
  199.                Name_Buffer (17) := '.';
  200.             end if;
  201.  
  202.          elsif U_Id in Interfaces_Child then
  203.             Name_Buffer (11) := '.';
  204.  
  205.          elsif U_Id in System_Child then
  206.             Name_Buffer (7) := '.';
  207.  
  208.             if U_Id in System_Tasking_Child then
  209.                Name_Buffer (15) := '.';
  210.             end if;
  211.          end if;
  212.       end;
  213.  
  214.       --  Add %s at end for spec
  215.  
  216.       Name_Buffer (Name_Len + 1) := '%';
  217.       Name_Buffer (Name_Len + 2) := 's';
  218.       Name_Len := Name_Len + 2;
  219.  
  220.       U.Uname := Name_Find;
  221.       Loaded := Is_Loaded (U.Uname);
  222.       U.Unum := Load_Unit (U.Uname, False, Empty);
  223.  
  224.       if U.Unum = No_Unit then
  225.          Load_Fail ("unit not found", U_Id);
  226.       elsif Fatal_Error (U.Unum) then
  227.          Load_Fail ("parser errors", U_Id);
  228.       end if;
  229.  
  230.       --  Make sure that the unit is analyzed
  231.  
  232.       if not Analyzed (Cunit (U.Unum)) then
  233.          Semantics (Cunit (U.Unum));
  234.  
  235.          if Fatal_Error (U.Unum) then
  236.             Load_Fail ("semantic errors", U_Id);
  237.          end if;
  238.       end if;
  239.  
  240.       Lib_Unit := Unit (Cunit (U.Unum));
  241.       U.Entity := Defining_Unit_Simple_Name (Specification (Lib_Unit));
  242.  
  243.       if Use_Setting then
  244.          Set_Is_Potentially_Use_Visible (U.Entity, True);
  245.       end if;
  246.  
  247.       --  Add to with list if we loaded the unit
  248.  
  249.       if not Loaded then
  250.          Withn :=
  251.            Make_With_Clause (Standard_Location,
  252.              Name => New_Reference_To (U.Entity, Standard_Location));
  253.          Set_Library_Unit          (Withn, Cunit (U.Unum));
  254.          Set_Corresponding_Spec    (Withn, U.Entity);
  255.          Set_First_Name            (Withn, True);
  256.          Set_Implicit_With         (Withn, True);
  257.  
  258.          Mark_Rewrite_Insertion (Withn);
  259.          Append (Withn, Context_Items (Cunit (Current_Sem_Unit)));
  260.       end if;
  261.    end Load_RTU;
  262.  
  263.    ---------
  264.    -- RTE --
  265.    ---------
  266.  
  267.    function RTE (E : RE_Id) return Entity_Id is
  268.       U_Id : constant RTU_Id := RE_Unit_Table (E);
  269.       U    : RT_Unit_Table_Record renames RT_Unit_Table (U_Id);
  270.  
  271.       Lib_Unit : Node_Id;
  272.       Pkg_Ent  : Entity_Id;
  273.       Ename    : Name_Id;
  274.  
  275.    begin
  276.       --  Immediate return if entity previously located
  277.  
  278.       if Present (RE_Table (E)) then
  279.          return RE_Table (E);
  280.       end if;
  281.  
  282.       --  Otherwise load the unit
  283.  
  284.       Load_RTU (U_Id);
  285.       Lib_Unit := Unit (Cunit (U.Unum));
  286.  
  287.       --  In the subprogram case, we are all done, the entity we want is
  288.       --  the entity for the subprogram itself. Note that we do not bother
  289.       --  to check that it is in fact the entity that was requested, the
  290.       --  only way that could fail to be the case is if runtime is hopelessly
  291.       --  misconfigured, and it isn't worth testing for this.
  292.  
  293.       if Nkind (Lib_Unit) = N_Subprogram_Declaration then
  294.          RE_Table (E) := U.Entity;
  295.          return RE_Table (E);
  296.  
  297.       --  Otherwise we must have the package case, and here we have to search
  298.       --  the package entity chain for the entity we want. The entity we want
  299.       --  must be present in this chain, or we have a misconfigured runtime.
  300.  
  301.       else
  302.          pragma Assert (Nkind (Lib_Unit) = N_Package_Declaration);
  303.  
  304.          declare
  305.             RE_Name_Chars : constant String := RE_Id'Image (E);
  306.  
  307.          begin
  308.             --  Copy name skipping initial RE_ or RO_XX characters
  309.  
  310.             if RE_Name_Chars (1 .. 2) = "RE" then
  311.                for J in 4 .. RE_Name_Chars'Last loop
  312.                   Name_Buffer (J - 3) := Fold_Lower (RE_Name_Chars (J));
  313.                end loop;
  314.  
  315.                Name_Len := RE_Name_Chars'Length - 3;
  316.  
  317.             else
  318.                for J in 7 .. RE_Name_Chars'Last loop
  319.                   Name_Buffer (J - 6) := Fold_Lower (RE_Name_Chars (J));
  320.                end loop;
  321.  
  322.                Name_Len := RE_Name_Chars'Length - 6;
  323.             end if;
  324.  
  325.             Ename := Name_Find;
  326.  
  327.             Pkg_Ent := First_Entity (U.Entity);
  328.  
  329.             while Present (Pkg_Ent) loop
  330.                if Ename = Chars (Pkg_Ent) then
  331.                   RE_Table (E) := Pkg_Ent;
  332.                   return Pkg_Ent;
  333.                end if;
  334.  
  335.                Pkg_Ent := Next_Entity (Pkg_Ent);
  336.             end loop;
  337.  
  338.             --  If we didn't find the unit we want, something is wrong!
  339.  
  340.             Load_Fail ("entity not in package", U_Id, RE_Name_Chars);
  341.          end;
  342.       end if;
  343.  
  344.    end RTE;
  345.  
  346.    --------------------
  347.    -- Text_IO_Kludge --
  348.    --------------------
  349.  
  350.    procedure Text_IO_Kludge (Nam : Node_Id) is
  351.       Chrs : Name_Id;
  352.  
  353.       type Name_Map_Type is array (Text_IO_Package_Name) of RTU_Id;
  354.  
  355.       Name_Map : Name_Map_Type := Name_Map_Type'(
  356.         Name_Decimal_IO     => Ada_Text_IO_Decimal_IO,
  357.         Name_Enumeration_IO => Ada_Text_IO_Enumeration_IO,
  358.         Name_Fixed_IO       => Ada_Text_IO_Fixed_IO,
  359.         Name_Float_IO       => Ada_Text_IO_Float_IO,
  360.         Name_Integer_IO     => Ada_Text_IO_Integer_IO,
  361.         Name_Modular_IO     => Ada_Text_IO_Modular_IO);
  362.  
  363.       Wide_Name_Map : Name_Map_Type := Name_Map_Type'(
  364.         Name_Decimal_IO     => Ada_Wide_Text_IO_Decimal_IO,
  365.         Name_Enumeration_IO => Ada_Wide_Text_IO_Enumeration_IO,
  366.         Name_Fixed_IO       => Ada_Wide_Text_IO_Fixed_IO,
  367.         Name_Float_IO       => Ada_Wide_Text_IO_Float_IO,
  368.         Name_Integer_IO     => Ada_Wide_Text_IO_Integer_IO,
  369.         Name_Modular_IO     => Ada_Wide_Text_IO_Modular_IO);
  370.  
  371.    begin
  372.       --  Nothing to do if name is not identifier or a selected component
  373.       --  whose selector_name is not an identifier.
  374.  
  375.       if Nkind (Nam) = N_Identifier then
  376.          Chrs := Chars (Nam);
  377.  
  378.       elsif Nkind (Nam) = N_Selected_Component
  379.         and then Nkind (Selector_Name (Nam)) = N_Identifier
  380.       then
  381.          Chrs := Chars (Selector_Name (Nam));
  382.  
  383.       else
  384.          return;
  385.       end if;
  386.  
  387.       --  Nothing to do if name is not one of the Text_IO subpackages
  388.       --  Otherwise look through loaded units, and if we find Text_IO
  389.       --  or Wide_Text_IO already loaded, then load the proper child.
  390.  
  391.       if Chrs in Text_IO_Package_Name then
  392.          for U in Main_Unit .. Last_Unit loop
  393.             Get_Name_String (Unit_File_Name (U));
  394.  
  395.             if Name_Len = 12 then
  396.  
  397.                --  Here is where we do the loads if we find one of the
  398.                --  units Ada.Text_IO or Ada.Wide_Text_IO. An interesting
  399.                --  detail is that these units may already be used (i.e.
  400.                --  their In_Use flags may be set). Normally when the In_Use
  401.                --  flag is set, the Is_Potentially_Use_Visible flag of all
  402.                --  entities in the package is set, but the new entity we
  403.                --  are mysteriously adding was not there to have its flag
  404.                --  set at the time. So that's why we pass the extra parameter
  405.                --  to RTU_Find, to make sure the flag does get set now.
  406.  
  407.                if Name_Buffer (1 .. 12) = "a-textio.ads" then
  408.                   Load_RTU (Name_Map (Chrs), In_Use (Cunit_Entity (U)));
  409.                elsif Name_Buffer (1 .. 12) = "a-witeio.ads" then
  410.                   Load_RTU (Wide_Name_Map (Chrs), In_Use (Cunit_Entity (U)));
  411.                end if;
  412.             end if;
  413.          end loop;
  414.       end if;
  415.    end Text_IO_Kludge;
  416.  
  417. end Rtsfind;
  418.