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 / lib-writ.adb < prev    next >
Text File  |  1996-09-28  |  30KB  |  810 lines

  1. ------------------------------------------------------------------------------
  2. --                                                                          --
  3. --                         GNAT COMPILER COMPONENTS                         --
  4. --                                                                          --
  5. --                             L I B . W R I T                              --
  6. --                                                                          --
  7. --                                 B o d y                                  --
  8. --                                                                          --
  9. --                            $Revision: 1.60 $                             --
  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 Fname;   use Fname;
  28. with Namet;   use Namet;
  29. with Nlists;  use Nlists;
  30. with Gnatvsn; use Gnatvsn;
  31. with Osint;   use Osint;
  32. with Output;  use Output;
  33. with Sinfo;   use Sinfo;
  34. with Sinput;  use Sinput;
  35. with Stringt; use Stringt;
  36. with System;  use System;
  37. with Uname;   use Uname;
  38.  
  39. with System.Parameters;
  40.  
  41. package body Lib.Writ is
  42.  
  43.    -----------------------------
  44.    -- Increment_Serial_Number --
  45.    -----------------------------
  46.  
  47.    function Increment_Serial_Number return Int is
  48.       TSN : Int renames Units.Table (Current_Sem_Unit).Serial_Number;
  49.  
  50.    begin
  51.       TSN := TSN + 1;
  52.       return TSN;
  53.    end Increment_Serial_Number;
  54.  
  55.    --------------------------------
  56.    -- Store_Linker_Option_String --
  57.    --------------------------------
  58.  
  59.    procedure Store_Linker_Option_String (S : String_Id) is
  60.    begin
  61.       Linker_Option_Lines.Increment_Last;
  62.       Linker_Option_Lines.Table (Linker_Option_Lines.Last) := S;
  63.    end Store_Linker_Option_String;
  64.  
  65.    ------------------------
  66.    -- Write_Library_Info --
  67.    ------------------------
  68.  
  69.    procedure Write_Library_Info is
  70.  
  71.       -----------------------------------
  72.       -- Format of Library Information --
  73.       -----------------------------------
  74.  
  75.       --  This section  describes the format of the library information that is
  76.       --  associated with object files. The exact method of this association is
  77.       --  potentially implementation dependent and is described and implemented
  78.       --  in package From the point of view of the description here, all
  79.       --  we need to know is that the information is represented as a string of
  80.       --  characters that is somehow associated with an object file, and can be
  81.       --  retrieved. If no library information exists for a given object file,
  82.       --  then we take this as equivalent to the non-existence of the object
  83.       --  file, as if source file has not been previously compiled.
  84.  
  85.       --  The library information is written as a series of lines of the form:
  86.  
  87.       --    Key_Character parameter parameter ...
  88.  
  89.       --  The first two lines in the file identify the library output version
  90.       --  and standard version (these are required to be consistent across the
  91.       --  entire set of compilation units).
  92.  
  93.       --    V "xxxxxxxxxxxxxxxx"
  94.       --
  95.       --      This line indicates the library output version, as defined in
  96.       --      Gnatvsn. It ensures that separate object modules of a program are
  97.       --      consistent. It has to be changed if anything changes which would
  98.       --      affect successful binding of separately compiled modules.
  99.       --      Examples of such changes are modifications in the format of the
  100.       --      library info described in this package, or modifications to
  101.       --      calling sequences, or to the way that data is represented.
  102.  
  103.       --    S "xxxxxxxxxxxxxxxx"
  104.       --
  105.       --      This line contains information regarding types declared in
  106.       --      packages Standard, System as stored in Gnatvsn.Standard_Version.
  107.       --      The purpose is, on systems where for example the size of Integer
  108.       --      can be set by command line switches, to ensure that all units in
  109.       --      a program are compiled with a consistent set of options.
  110.  
  111.       --  The next line is present only for a unit that can be a main program
  112.       --  It has the form:
  113.  
  114.       --    M type [priority]
  115.  
  116.       --      The type parameter is either P for a parameterless procedure,
  117.       --      or F for a function returning a value of integral type (the
  118.       --      latter is for writing a main program that returns an exit status)
  119.       --      The priority parameter is present only if there was a valid
  120.       --      pragma Priority in the corresponding unit to set the main task
  121.       --      priority. It is an unsigned decimal integer.
  122.  
  123.       --    A argument
  124.  
  125.       --      One of these lines appears for each of the arguments present
  126.       --      in the call to the gnat1 program. This can be used if it is
  127.       --      necessary to reconstruct this call (e.g. for fix and continue)
  128.  
  129.       --  Following these header lines, a set of information lines appears for
  130.       --  each compilation unit that appears in the corresponding object file.
  131.       --  In particular, when a package body or subprogram body is compiled,
  132.       --  there will be two sets of information, one for the spec and one for
  133.       --  the body. with the entry for the body appearing first. This is the
  134.       --  only case in which a single ALI file contains more than one unit (in
  135.       --  particular note that subunits do *not* count as compilation units for
  136.       --  this purpose, and generate no library information, since they are
  137.       --  inlined).
  138.  
  139.       --  The lines for each compilation unit have the following form.
  140.  
  141.       --    U unit-name source-name version <<attributes>>
  142.       --
  143.       --      This line identifies the unit to which this section of the
  144.       --      library information file applies. The first three parameters are
  145.       --      the unit name in internal format, as described in package Uname,
  146.       --      and the name of the source file containing the unit.
  147.       --
  148.       --      Version is the version given as 8 hexadecimal characters with
  149.       --      lower case letters. This value is a hash code that includes
  150.       --      contributions from the time stamps of this unit and all its
  151.       --      sematically dependent units.
  152.       --
  153.       --      The <<attributes>> are a series of two letter codes indicating
  154.       --      information about the unit:
  155.       --
  156.       --         EB  Unit has pragma Elaborate_Body
  157.       --
  158.       --         NE  Unit has no elaboration routine. All subprogram bodies
  159.       --             and specs are in this category. Package bodies and specs
  160.       --             may or may not have NE set, depending on whether or not
  161.       --             elaboration code is required. Set if Has_No_Elab_Code
  162.       --             flag is set in the N_Compilation_Unit node.
  163.       --
  164.       --         PK  Unit is package, rather than a subprogram
  165.       --
  166.       --         PU  Unit has pragma Pure
  167.       --
  168.       --         PR  Unit has pragma Preelaborate
  169.       --
  170.       --         RC  Unit has pragma Remote_Call_Interface
  171.       --
  172.       --         RT  Unit has pragma Remote_Types
  173.       --
  174.       --         SP  Unit has pragma Shared_Passive.
  175.       --
  176.       --         SU  Unit is a subprogram, rather than a package
  177.       --
  178.       --      The attributes may appear in any order, separated by spaces.
  179.  
  180.       --    W unit-name [source-name lib-name [E] [EA]]
  181.       --
  182.       --      One of these lines is present for each unit that is mentioned in
  183.       --      an explicit with clause by the current unit. The first parameter
  184.       --      is the unit name in internal format. The second parameter is the
  185.       --      file name of the file that must be compiled to compile this unit
  186.       --      (which is usually the file for the body, except for packages
  187.       --      which have no body). The third parameter is the file name of the
  188.       --      library information file that contains the results of compiling
  189.       --      this unit. The E and EA parameters are present if the pragmas
  190.       --      Elaborate and Elaborate_All respectively apply to this unit. In
  191.       --      the case of generic units, only the first parameter is present,
  192.       --      since generic units do not need to be compiled, and generate no
  193.       --      library information. Note that the elaborate pragmas can be given
  194.       --      for generic units, but they are ignored.
  195.  
  196.       --  Following the unit information is an optional series of lines that
  197.       --  indicates the usage of pragma Library_Unit. For each appearence of
  198.       --  pragma Library_Unit in any of the units for which unit lines are
  199.       --  present, a line of the form:
  200.  
  201.       --    L "string"
  202.  
  203.       --  where string is the string from the unit line enclosed in quotes.
  204.       --  Within the quotes the following can occur:
  205.  
  206.       --    7-bit graphic characters other than " or {
  207.       --    "" (indicating a single " character)
  208.       --    {hh} indicating a character whose code is hex hh
  209.  
  210.       --  For further details, see Stringt.Write_String_Table_Entry. Note that
  211.       --  wide characters in the form {hhhh} cannot be produced, since pragma
  212.       --  Linker_Option accepts only String, not Wide_String.
  213.  
  214.       --  Finally at the end of the ali file is a series of lines that
  215.       --  indicates the source files on which the compiled units depend. This
  216.       --  is used by the binder for consistency checking.
  217.  
  218.       --    D source-name time-stamp optional-comments
  219.  
  220.       --  The optional comments, if present, must be separated from the time
  221.       --  stamp by at least one blank. Currently the optional-comments field
  222.       --  is not used.
  223.  
  224.       --  Note: blank lines are ignored when the library information is read,
  225.       --  and separate sections of the file are separated by blank lines to
  226.       --  ease readability. Blanks between fields are also ignored.
  227.  
  228.       -----------------------------------
  229.       -- Representation of Time Stamps --
  230.       -----------------------------------
  231.  
  232.       --  All compiled units are marked with a time stamp which is derived from
  233.       --  the source file (we assume that the host system has the concept of a
  234.       --  file time stamp which is modified when a file is modified). These
  235.       --  time stamps are used to ensure consistency of the set of units that
  236.       --  constitutes a library. Time stamps are 12 character strings with
  237.       --  with the following format:
  238.  
  239.       --     YYMMDDHHMMSS
  240.  
  241.       --       YY     year (2 low order digits)
  242.       --       MM     month (2 digits 01-12)
  243.       --       DD     day (2 digits 01-31)
  244.       --       HH     hour (2 digits 00-23)
  245.       --       MM     minutes (2 digits 00-59)
  246.       --       SS     seconds (2 digits 00-59)
  247.  
  248.       --  Time stamps may be compared lexicographically (i.e. Ada comparison
  249.       --  operations on strings) to determine which is later or earlier.
  250.       --  However, in normal mode, only equality comparisons have any effect
  251.       --  on the semantics of the library (later/earlier comparisons are used
  252.       --  only for determining the most informative error messages to be
  253.       --  given).
  254.  
  255.       --  In the case of Unix systems (and other systems which keep the time in
  256.       --  GMT), the time stamp is the GMT time of the file, not the local time.
  257.       --  This solves problems in using libraries across networks with clients
  258.       --  spread across multiple time-zones.
  259.  
  260.       ----------------
  261.       -- Local Data --
  262.       ----------------
  263.  
  264.       Info_Buffer : String (1 .. 2 * System.Parameters.Max_Name_Length + 64);
  265.       --  Info_Buffer used to prepare lines of library output
  266.  
  267.       Info_Buffer_Len : Natural;
  268.       --  Number of characters stored in Info_Buffer
  269.  
  270.       Info_Buffer_Col : Natural;
  271.       --  Column number of next character to be written (can be different from
  272.       --  Info_Buffer_Len because of tab characters written by Write_Info_Tab)
  273.  
  274.       With_Flags : array (Units.First .. Units.Last) of Boolean;
  275.       --  Array of flags used to show which units are with'ed
  276.  
  277.       Elab_Flags : array (Units.First .. Units.Last) of Boolean;
  278.       --  Array of flags used to show which units have pragma Elaborate set
  279.  
  280.       Elab_All_Flags : array (Units.First .. Units.Last) of Boolean;
  281.       --  Array of flags used to show which units have pragma Elaborate All set
  282.  
  283.       -----------------------
  284.       -- Local Subprograms --
  285.       -----------------------
  286.  
  287.       procedure Collect_Withs (Cunit : Node_Id);
  288.       --  Collect with lines for entries in the context clause of the
  289.       --  given compilation unit, Cunit.
  290.  
  291.       procedure Write_Info_Char (C : Character);
  292.       pragma Inline (Write_Info_Char);
  293.       --  Adds one character to Info_Buffer
  294.  
  295.       procedure Write_Info_Initiate (Key : Character);
  296.       --  Initiates write of new line to info file, the parameter is the
  297.       --  keyword character for the line.
  298.  
  299.       procedure Write_Info_Nat (N : Nat);
  300.       --  Adds image of N to Info_Buffer with no leading or trailing blanks
  301.  
  302.       procedure Write_Info_Name (Name : Name_Id);
  303.       --  Adds characters of Name to Info_Buffer
  304.  
  305.       procedure Write_Info_Str (Val : String);
  306.       --  Adds characters of Val to Info_Buffer surrounded by quotes
  307.  
  308.       procedure Write_Info_Tab (Col : Natural);
  309.       --  Tab out with blanks and HT's to column Col. If already at or past
  310.       --  Col, writes a single blank, so that we do get a required field
  311.       --  separation.
  312.  
  313.       procedure Write_Info_Terminate;
  314.       --  Terminate output of info line built in Info_Buffer
  315.  
  316.       procedure Write_Info_Version (Unit_Num : Unit_Number_Type);
  317.       --  Write version number of given unit as eight hexadecimal digits
  318.       --  with letters in lower case.
  319.  
  320.       procedure Write_Unit_Information (Unit_Num : Unit_Number_Type);
  321.       --  Write out the library information for one unit for which code is
  322.       --  generated (includes unit line and with lines).
  323.  
  324.       procedure Write_With_Lines;
  325.       --  Write out with lines collected by calls to Collect_Withs
  326.  
  327.       -------------------
  328.       -- Collect_Withs --
  329.       -------------------
  330.  
  331.       procedure Collect_Withs (Cunit : Node_Id) is
  332.          Item : Node_Id;
  333.          Unum : Unit_Number_Type;
  334.  
  335.       begin
  336.          Item := First (Context_Items (Cunit));
  337.          while Present (Item) loop
  338.  
  339.             if Nkind (Item) = N_With_Clause then
  340.                Unum := Get_Cunit_Unit_Number (Library_Unit (Item));
  341.                With_Flags (Unum) := True;
  342.  
  343.                if Elaborate_Present (Item) then
  344.                   Elab_Flags (Unum) := True;
  345.                end if;
  346.  
  347.                if Elaborate_All_Present (Item) then
  348.                   Elab_All_Flags (Unum) := True;
  349.                end if;
  350.             end if;
  351.  
  352.             Item := Next (Item);
  353.          end loop;
  354.       end Collect_Withs;
  355.  
  356.       ---------------------
  357.       -- Write_Info_Char --
  358.       ---------------------
  359.  
  360.       procedure Write_Info_Char (C : Character) is
  361.       begin
  362.          Info_Buffer_Len := Info_Buffer_Len + 1;
  363.          Info_Buffer (Info_Buffer_Len) := C;
  364.          Info_Buffer_Col := Info_Buffer_Col + 1;
  365.       end Write_Info_Char;
  366.  
  367.       -------------------------
  368.       -- Write_Info_Initiate --
  369.       -------------------------
  370.  
  371.       procedure Write_Info_Initiate (Key : Character) is
  372.       begin
  373.          Info_Buffer_Len := 0;
  374.          Info_Buffer_Col := 1;
  375.          Write_Info_Char (Key);
  376.          Write_Info_Char (' ');
  377.       end Write_Info_Initiate;
  378.  
  379.       --------------------
  380.       -- Write_Info_Nat --
  381.       --------------------
  382.  
  383.       procedure Write_Info_Nat (N : Nat) is
  384.       begin
  385.          if N > 9 then
  386.             Write_Info_Nat (N / 10);
  387.          end if;
  388.  
  389.          Write_Info_Char (Character'Val (N mod 10 + Character'Pos ('0')));
  390.       end Write_Info_Nat;
  391.  
  392.       ---------------------
  393.       -- Write_Info_Name --
  394.       ---------------------
  395.  
  396.       procedure Write_Info_Name (Name : Name_Id) is
  397.       begin
  398.          Get_Name_String (Name);
  399.          Info_Buffer (Info_Buffer_Len + 1 .. Info_Buffer_Len + Name_Len) :=
  400.            Name_Buffer (1 .. Name_Len);
  401.          Info_Buffer_Len := Info_Buffer_Len + Name_Len;
  402.          Info_Buffer_Col := Info_Buffer_Col + Name_Len;
  403.       end Write_Info_Name;
  404.  
  405.       --------------------
  406.       -- Write_Info_Str --
  407.       --------------------
  408.  
  409.       procedure Write_Info_Str (Val : String) is
  410.       begin
  411.          Info_Buffer (Info_Buffer_Len + 1 .. Info_Buffer_Len + Val'Length)
  412.                                                                      := Val;
  413.          Info_Buffer_Len := Info_Buffer_Len + Val'Length;
  414.          Info_Buffer_Col := Info_Buffer_Col + Val'Length;
  415.       end Write_Info_Str;
  416.  
  417.       --------------------
  418.       -- Write_Info_Tab --
  419.       --------------------
  420.  
  421.       procedure Write_Info_Tab (Col : Natural) is
  422.          Next_Tab : Natural;
  423.  
  424.       begin
  425.          if Col <= Info_Buffer_Col then
  426.             Write_Info_Str ("  ");
  427.          else
  428.             loop
  429.                Next_Tab := 8 * ((Info_Buffer_Col - 1) / 8) + 8 + 1;
  430.                exit when Col < Next_Tab;
  431.                Write_Info_Char (Ascii.HT);
  432.                Info_Buffer_Col := Next_Tab;
  433.             end loop;
  434.  
  435.             while Info_Buffer_Col < Col loop
  436.                Write_Info_Char (' ');
  437.             end loop;
  438.          end if;
  439.       end Write_Info_Tab;
  440.  
  441.       --------------------------
  442.       -- Write_Info_Terminate --
  443.       --------------------------
  444.  
  445.       procedure Write_Info_Terminate is
  446.       begin
  447.          Write_Library_Info (Info_Buffer (1 .. Info_Buffer_Len));
  448.          Info_Buffer_Len := 0;
  449.       end Write_Info_Terminate;
  450.  
  451.       ------------------------
  452.       -- Write_Info_Version --
  453.       ------------------------
  454.  
  455.       procedure Write_Info_Version (Unit_Num : Unit_Number_Type) is
  456.          V : Version_Id := Units.Table (Unit_Num).Version;
  457.          H : constant String := "0123456789abcdef";
  458.  
  459.       begin
  460.          for J in reverse Info_Buffer_Len + 1 .. Info_Buffer_Len + 8 loop
  461.             Info_Buffer (J) := H (Integer (V mod 16) + 1);
  462.             V := V / 16;
  463.          end loop;
  464.  
  465.          Info_Buffer_Len := Info_Buffer_Len + 8;
  466.          Info_Buffer_Col := Info_Buffer_Col + 8;
  467.       end Write_Info_Version;
  468.  
  469.       ----------------------------
  470.       -- Write_Unit_Information --
  471.       ----------------------------
  472.  
  473.       procedure Write_Unit_Information (Unit_Num : Unit_Number_Type) is
  474.          Ukind : constant Node_Kind := Nkind (Unit (Cunit (Unit_Num)));
  475.          Pnode : Node_Id;
  476.  
  477.       begin
  478.          Write_Info_Initiate ('U');
  479.          Write_Info_Name (Unit_Name (Unit_Num));
  480.          Write_Info_Tab (25);
  481.          Write_Info_Name (Unit_File_Name (Unit_Num));
  482.  
  483.          Write_Info_Tab (49);
  484.          Write_Info_Version (Unit_Num);
  485.  
  486.          if Is_Preelaborated (Cunit_Entity (Unit_Num)) then
  487.             Write_Info_Str ("  PR");
  488.          end if;
  489.  
  490.          if Has_No_Elab_Code (Cunit (Unit_Num)) then
  491.             Write_Info_Str ("  NE");
  492.          end if;
  493.  
  494.          if Elaborate_Body_Present (Cunit (Unit_Num)) then
  495.             Write_Info_Str ("  EB");
  496.          end if;
  497.  
  498.          if Is_Pure (Cunit_Entity (Unit_Num)) then
  499.             Write_Info_Str ("  PU");
  500.          end if;
  501.  
  502.          if Is_Remote_Call_Interface (Cunit_Entity (Unit_Num)) then
  503.             Write_Info_Str ("  RC");
  504.          end if;
  505.  
  506.          if Is_Remote_Types (Cunit_Entity (Unit_Num)) then
  507.             Write_Info_Str ("  RT");
  508.          end if;
  509.  
  510.          if Is_Shared_Passive (Cunit_Entity (Unit_Num)) then
  511.             Write_Info_Str ("  SP");
  512.          end if;
  513.  
  514.          if Ukind = N_Subprogram_Declaration
  515.            or else Ukind = N_Subprogram_Body
  516.          then
  517.             Write_Info_Str ("  SU");
  518.  
  519.          elsif Ukind = N_Package_Declaration
  520.            or else Ukind = N_Package_Body
  521.          then
  522.             Write_Info_Str ("  PK");
  523.          end if;
  524.  
  525.          Write_Info_Terminate;
  526.  
  527.          --  Generate with lines, first those that are directly with'ed
  528.  
  529.          for J in With_Flags'Range loop
  530.             With_Flags (J) := False;
  531.             Elab_Flags (J) := False;
  532.             Elab_All_Flags (J) := False;
  533.          end loop;
  534.  
  535.          Collect_Withs (Cunit (Unit_Num));
  536.  
  537.          --  For a body, we must also check for any subunits which belong to
  538.          --  us and which have context clauses of their own, since these
  539.          --  with'ed units our part of our elaboration dependencies.
  540.  
  541.          if Nkind (Unit (Cunit (Unit_Num))) in N_Unit_Body then
  542.             for S in Units.First .. Units.Last loop
  543.  
  544.                --  We are only interested in subunits
  545.  
  546.                if Nkind (Unit (Cunit (S))) = N_Subunit then
  547.                   Pnode := Library_Unit (Cunit (S));
  548.  
  549.                   --  Find ultimate parent of the subunit
  550.  
  551.                   while Nkind (Unit (Pnode)) = N_Subunit loop
  552.                      Pnode := Library_Unit (Pnode);
  553.                   end loop;
  554.  
  555.                   --  See if it belongs to us, and if so, include it's with's
  556.  
  557.                   if Pnode = Cunit (Unit_Num) then
  558.                      Collect_Withs (Cunit (S));
  559.                   end if;
  560.                end if;
  561.             end loop;
  562.          end if;
  563.  
  564.          Write_With_Lines;
  565.       end Write_Unit_Information;
  566.  
  567.       ----------------------
  568.       -- Write_With_Lines --
  569.       ----------------------
  570.  
  571.       procedure Write_With_Lines is
  572.          With_Table : Unit_Ref_Table (1 .. Pos (Units.Last - Units.First + 1));
  573.          Num_Withs  : Int := 0;
  574.          Cunit      : Node_Id;
  575.          Uname      : Unit_Name_Type;
  576.          Fname      : File_Name_Type;
  577.  
  578.       begin
  579.          --  Loop to build the with table
  580.  
  581.          for J in Units.First .. Units.Last loop
  582.             if With_Flags (J) then
  583.                Num_Withs := Num_Withs + 1;
  584.                With_Table (Num_Withs) := J;
  585.             end if;
  586.          end loop;
  587.  
  588.          --  Sort and output the table
  589.  
  590.          Sort (With_Table (1 .. Num_Withs));
  591.  
  592.          for J in 1 .. Num_Withs loop
  593.             Cunit := Units.Table (With_Table (J)).Cunit;
  594.             Uname := Units.Table (With_Table (J)).Unit_Name;
  595.             Fname := Units.Table (With_Table (J)).Unit_File_Name;
  596.  
  597.             Write_Info_Initiate ('W');
  598.             Write_Info_Name (Uname);
  599.  
  600.             --  Now we need to figure out the names of the files that contain
  601.             --  the with'ed unit. These will usually be the files for the body,
  602.             --  except except in the case of a package that has no body, as
  603.             --  indicated by the Body_Required flag in the compilation unit
  604.             --  node not being set. No names are output for a generic unit.
  605.  
  606.             if Nkind (Unit (Cunit)) not in N_Generic_Declaration
  607.               and then Nkind (Unit (Cunit)) not in
  608.                                       N_Generic_Renaming_Declaration
  609.             then
  610.                Write_Info_Tab (25);
  611.  
  612.                if Body_Required (Cunit)
  613.                  or else Nkind (Unit (Cunit)) = N_Subprogram_Declaration
  614.                then
  615.                   Write_Info_Name (Get_File_Name (Get_Body_Name (Uname)));
  616.                   Write_Info_Tab (49);
  617.                   Write_Info_Name
  618.                     (Lib_File_Name (Get_File_Name (Get_Body_Name (Uname))));
  619.                else
  620.                   Write_Info_Name (Fname);
  621.                   Write_Info_Tab (49);
  622.                   Write_Info_Name (Lib_File_Name (Fname));
  623.                end if;
  624.  
  625.                if Elab_Flags (With_Table (J)) then
  626.                   Write_Info_Str ("  E");
  627.                end if;
  628.  
  629.                if Elab_All_Flags (With_Table (J)) then
  630.                   Write_Info_Str ("  EA");
  631.                end if;
  632.             end if;
  633.             Write_Info_Terminate;
  634.          end loop;
  635.       end Write_With_Lines;
  636.  
  637.       ----------
  638.       -- Writ --
  639.       ----------
  640.  
  641.    begin
  642.       Create_Output_Library_Info;
  643.  
  644.       --  Output version line
  645.  
  646.       Write_Info_Initiate ('V');
  647.       Write_Info_Char ('"');
  648.       Write_Info_Str (Library_Version);
  649.       Write_Info_Char ('"');
  650.       Write_Info_Terminate;
  651.  
  652.       --  Output standard version line
  653.  
  654.       Write_Info_Initiate ('S');
  655.       Write_Info_Char ('"');
  656.       Write_Info_Str (Standard_Version);
  657.       Write_Info_Char ('"');
  658.       Write_Info_Terminate;
  659.  
  660.       --  Output main program line if this is acceptable main program
  661.  
  662.       declare
  663.          U : constant Node_Id := Unit (Units.Table (Main_Unit).Cunit);
  664.          S : Node_Id;
  665.  
  666.       begin
  667.          if Nkind (U) = N_Subprogram_Body
  668.            or else (Nkind (U) = N_Package_Body
  669.                       and then
  670.                         (Nkind (Original_Node (U)) = N_Function_Instantiation
  671.                            or else
  672.                          Nkind (Original_Node (U)) =
  673.                                                   N_Procedure_Instantiation))
  674.          then
  675.             --  If the unit is a subprogram instance, the entity for the
  676.             --  subprogram is the last visible one in the package spec,
  677.             --  appearing after the renamings for the generic actuals.
  678.  
  679.             if Nkind (U) = N_Package_Body then
  680.                S := Specification (Last (Visible_Declarations
  681.                            (Specification
  682.                              (Unit (Library_Unit (Parent (U)))))));
  683.             else
  684.                S := Specification (U);
  685.             end if;
  686.  
  687.             if not Present (Parameter_Specifications (S)) then
  688.                if Nkind (S) = N_Procedure_Specification then
  689.                   Write_Info_Initiate ('M');
  690.                   Write_Info_Char ('P');
  691.  
  692.                else
  693.                   declare
  694.                      Nam : Node_Id := Defining_Unit_Name (S);
  695.  
  696.                   begin
  697.                      --  if it is a child unit, get its simple name.
  698.  
  699.                      if Nkind (Nam) = N_Defining_Program_Unit_Name then
  700.                         Nam := Defining_Identifier (Nam);
  701.                      end if;
  702.  
  703.                      if Is_Integer_Type (Etype (Nam)) then
  704.                         Write_Info_Initiate ('M');
  705.                         Write_Info_Char ('F');
  706.                      end if;
  707.                   end;
  708.                end if;
  709.  
  710.                if Main_Priority (Main_Unit) /= Default_Main_Priority then
  711.                   Write_Info_Char (' ');
  712.                   Write_Info_Nat (Main_Priority (Main_Unit));
  713.                   Write_Info_Terminate;
  714.                end if;
  715.             end if;
  716.          end if;
  717.       end;
  718.  
  719.       --  Output command argument lines TBD ???
  720.  
  721. --      for J in 1 .. Osint.Arg_Count_Original loop
  722. --         declare
  723. --            S : aliased String (1 .. Osint.Len_Arg_Original (J));
  724. --
  725. --         begin
  726. --            Osint.Fill_Arg_Original (S'Address, J);
  727. --            Write_Info_Initiate ('A');
  728. --            Write_Info_Str (S);
  729. --            Write_Info_Terminate;
  730. --         end;
  731. --      end loop;
  732.  
  733.       --  Loop through file table to output information for all units for which
  734.       --  we have generated code, as marked by the Generate_Code flag.
  735.  
  736.       for Unit in Units.First .. Units.Last loop
  737.          if Units.Table (Unit).Generate_Code then
  738.             Write_Info_Terminate; -- blank line
  739.             Write_Unit_Information (Unit);
  740.          end if;
  741.       end loop;
  742.  
  743.       Write_Info_Terminate; -- blank line
  744.  
  745.       --  Output linker option lines
  746.  
  747.       for J in 1 .. Linker_Option_Lines.Last loop
  748.          declare
  749.             S : constant String_Id := Linker_Option_Lines.Table (J);
  750.             C : Character;
  751.  
  752.          begin
  753.             Write_Info_Initiate ('L');
  754.             Write_Info_Char ('"');
  755.  
  756.             for J in 1 .. String_Length (S) loop
  757.                C := Get_Character (Get_String_Char (S, J));
  758.  
  759.                if C in Character'Val (16#20#) .. Character'Val (16#7E#)
  760.                  and then C /= '{'
  761.                then
  762.                   Write_Info_Char (C);
  763.                end if;
  764.  
  765.                if C = '"' then
  766.                   Write_Info_Char (C);
  767.                end if;
  768.             end loop;
  769.  
  770.             Write_Info_Char ('"');
  771.             Write_Info_Terminate;
  772.          end;
  773.       end loop;
  774.  
  775.       --  Prepare to output the source dependency lines
  776.  
  777.       declare
  778.          Sdep_Table : Unit_Ref_Table (1 .. Pos (Units.Last - Units.First + 1));
  779.          --  Keeps track of sdep entries
  780.  
  781.          Num_Sdep : Nat := 0;
  782.          --  Number of active entries in Sdep_Table
  783.  
  784.          Sind : Source_File_Index;
  785.          --  Index of corresponding source file
  786.  
  787.       begin
  788.          for Unit in Units.First .. Units.Last loop
  789.             Num_Sdep := Num_Sdep + 1;
  790.             Sdep_Table (Num_Sdep) := Unit;
  791.          end loop;
  792.  
  793.          Lib.Sort (Sdep_Table (1 .. Num_Sdep));
  794.  
  795.          for J in 1 .. Num_Sdep loop
  796.             Sind := Units.Table (Sdep_Table (J)).Source_Index;
  797.             Write_Info_Initiate ('D');
  798.             Write_Info_Name (File_Name (Sind));
  799.             Write_Info_Tab (25);
  800.             Write_Info_Str (Time_Stamp (Sind));
  801.             Write_Info_Terminate;
  802.          end loop;
  803.       end;
  804.  
  805.       Close_Output_Library_Info;
  806.  
  807.    end Write_Library_Info;
  808.  
  809. end Lib.Writ;
  810.