File : lib-writ.adb


   1 ------------------------------------------------------------------------------
   2 --                                                                          --
   3 --                         GNAT COMPILER COMPONENTS                         --
   4 --                                                                          --
   5 --                             L I B . W R I T                              --
   6 --                                                                          --
   7 --                                 B o d y                                  --
   8 --                                                                          --
   9 --          Copyright (C) 1992-2016, Free Software Foundation, Inc.         --
  10 --                                                                          --
  11 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
  12 -- terms of the  GNU General Public License as published  by the Free Soft- --
  13 -- ware  Foundation;  either version 3,  or (at your option) any later ver- --
  14 -- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
  15 -- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
  16 -- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
  17 -- for  more details.  You should have  received  a copy of the GNU General --
  18 -- Public License  distributed with GNAT; see file COPYING3.  If not, go to --
  19 -- http://www.gnu.org/licenses for a complete copy of the license.          --
  20 --                                                                          --
  21 -- GNAT was originally developed  by the GNAT team at  New York University. --
  22 -- Extensive contributions were provided by Ada Core Technologies Inc.      --
  23 --                                                                          --
  24 ------------------------------------------------------------------------------
  25 
  26 with ALI;      use ALI;
  27 with Atree;    use Atree;
  28 with Casing;   use Casing;
  29 with Debug;    use Debug;
  30 with Einfo;    use Einfo;
  31 with Errout;   use Errout;
  32 with Fname;    use Fname;
  33 with Fname.UF; use Fname.UF;
  34 with Lib.Util; use Lib.Util;
  35 with Lib.Xref; use Lib.Xref;
  36 with Nlists;   use Nlists;
  37 with Gnatvsn;  use Gnatvsn;
  38 with Opt;      use Opt;
  39 with Osint;    use Osint;
  40 with Osint.C;  use Osint.C;
  41 with Output;   use Output;
  42 with Par;
  43 with Par_SCO;  use Par_SCO;
  44 with Restrict; use Restrict;
  45 with Rident;   use Rident;
  46 with Stand;    use Stand;
  47 with Scn;      use Scn;
  48 with Sem_Eval; use Sem_Eval;
  49 with Sinfo;    use Sinfo;
  50 with Sinput;   use Sinput;
  51 with Snames;   use Snames;
  52 with Stringt;  use Stringt;
  53 with Tbuild;   use Tbuild;
  54 with Uname;    use Uname;
  55 
  56 with System.Case_Util; use System.Case_Util;
  57 with System.WCh_Con;   use System.WCh_Con;
  58 
  59 package body Lib.Writ is
  60 
  61    -----------------------
  62    -- Local Subprograms --
  63    -----------------------
  64 
  65    procedure Write_Unit_Name (N : Node_Id);
  66    --  Used to write out the unit name for R (pragma Restriction) lines
  67    --  for uses of Restriction (No_Dependence => unit-name).
  68 
  69    ----------------------------------
  70    -- Add_Preprocessing_Dependency --
  71    ----------------------------------
  72 
  73    procedure Add_Preprocessing_Dependency (S : Source_File_Index) is
  74    begin
  75       Units.Increment_Last;
  76       Units.Table (Units.Last) :=
  77         (Unit_File_Name    => File_Name (S),
  78          Unit_Name         => No_Unit_Name,
  79          Expected_Unit     => No_Unit_Name,
  80          Source_Index      => S,
  81          Cunit             => Empty,
  82          Cunit_Entity      => Empty,
  83          Dependency_Num    => 0,
  84          Dynamic_Elab      => False,
  85          Fatal_Error       => None,
  86          Generate_Code     => False,
  87          Has_RACW          => False,
  88          Filler            => False,
  89          Ident_String      => Empty,
  90          Loading           => False,
  91          Main_Priority     => -1,
  92          Main_CPU          => -1,
  93          Munit_Index       => 0,
  94          No_Elab_Code_All  => False,
  95          Serial_Number     => 0,
  96          Version           => 0,
  97          Error_Location    => No_Location,
  98          OA_Setting        => 'O',
  99          SPARK_Mode_Pragma => Empty);
 100    end Add_Preprocessing_Dependency;
 101 
 102    ------------------------------
 103    -- Ensure_System_Dependency --
 104    ------------------------------
 105 
 106    procedure Ensure_System_Dependency is
 107       System_Uname : Unit_Name_Type;
 108       --  Unit name for system spec if needed for dummy entry
 109 
 110       System_Fname : File_Name_Type;
 111       --  File name for system spec if needed for dummy entry
 112 
 113    begin
 114       --  Nothing to do if we already compiled System
 115 
 116       for Unum in Units.First .. Last_Unit loop
 117          if Units.Table (Unum).Source_Index = System_Source_File_Index then
 118             return;
 119          end if;
 120       end loop;
 121 
 122       --  If no entry for system.ads in the units table, then add a entry
 123       --  to the units table for system.ads, which will be referenced when
 124       --  the ali file is generated. We need this because every unit depends
 125       --  on system as a result of Targparm scanning the system.ads file to
 126       --  determine the target dependent parameters for the compilation.
 127 
 128       Name_Len := 6;
 129       Name_Buffer (1 .. 6) := "system";
 130       System_Uname := Name_To_Unit_Name (Name_Enter);
 131       System_Fname := File_Name (System_Source_File_Index);
 132 
 133       Units.Increment_Last;
 134       Units.Table (Units.Last) := (
 135         Unit_File_Name    => System_Fname,
 136         Unit_Name         => System_Uname,
 137         Expected_Unit     => System_Uname,
 138         Source_Index      => System_Source_File_Index,
 139         Cunit             => Empty,
 140         Cunit_Entity      => Empty,
 141         Dependency_Num    => 0,
 142         Dynamic_Elab      => False,
 143         Fatal_Error       => None,
 144         Generate_Code     => False,
 145         Has_RACW          => False,
 146         Filler            => False,
 147         Ident_String      => Empty,
 148         Loading           => False,
 149         Main_Priority     => -1,
 150         Main_CPU          => -1,
 151         Munit_Index       => 0,
 152         No_Elab_Code_All  => False,
 153         Serial_Number     => 0,
 154         Version           => 0,
 155         Error_Location    => No_Location,
 156         OA_Setting        => 'O',
 157         SPARK_Mode_Pragma => Empty);
 158 
 159       --  Parse system.ads so that the checksum is set right. Style checks are
 160       --  not applied. The Ekind is set to ensure that this reference is always
 161       --  present in the ali file.
 162 
 163       declare
 164          Save_Mindex : constant Nat := Multiple_Unit_Index;
 165          Save_Style  : constant Boolean := Style_Check;
 166       begin
 167          Multiple_Unit_Index := 0;
 168          Style_Check := False;
 169          Initialize_Scanner (Units.Last, System_Source_File_Index);
 170          Discard_List (Par (Configuration_Pragmas => False));
 171          Set_Ekind (Cunit_Entity (Units.Last), E_Package);
 172          Set_Scope (Cunit_Entity (Units.Last), Standard_Standard);
 173          Style_Check := Save_Style;
 174          Multiple_Unit_Index := Save_Mindex;
 175       end;
 176    end Ensure_System_Dependency;
 177 
 178    ---------------
 179    -- Write_ALI --
 180    ---------------
 181 
 182    procedure Write_ALI (Object : Boolean) is
 183 
 184       ----------------
 185       -- Local Data --
 186       ----------------
 187 
 188       Last_Unit : constant Unit_Number_Type := Units.Last;
 189       --  Record unit number of last unit. We capture this in case we
 190       --  have to add a dummy entry to the unit table for package System.
 191 
 192       With_Flags : array (Units.First .. Last_Unit) of Boolean;
 193       --  Array of flags to show which units are with'ed
 194 
 195       Elab_Flags : array (Units.First .. Last_Unit) of Boolean;
 196       --  Array of flags to show which units have pragma Elaborate set
 197 
 198       Elab_All_Flags : array (Units.First .. Last_Unit) of Boolean;
 199       --  Array of flags to show which units have pragma Elaborate All set
 200 
 201       Elab_Des_Flags : array (Units.First .. Last_Unit) of Boolean;
 202       --  Array of flags to show which units have Elaborate_Desirable set
 203 
 204       Elab_All_Des_Flags : array (Units.First .. Last_Unit) of Boolean;
 205       --  Array of flags to show which units have Elaborate_All_Desirable set
 206 
 207       type Yes_No is (Unknown, Yes, No);
 208       Implicit_With : array (Units.First .. Last_Unit) of Yes_No;
 209       --  Indicates if an implicit with has been given for the unit. Yes if
 210       --  certainly present, no if certainly absent, unkonwn if not known.
 211 
 212       Sdep_Table : Unit_Ref_Table (1 .. Pos (Last_Unit - Units.First + 2));
 213       --  Sorted table of source dependencies. One extra entry in case we
 214       --  have to add a dummy entry for System.
 215 
 216       Num_Sdep : Nat := 0;
 217       --  Number of active entries in Sdep_Table
 218 
 219       -----------------------
 220       -- Local Subprograms --
 221       -----------------------
 222 
 223       procedure Collect_Withs (Cunit : Node_Id);
 224       --  Collect with lines for entries in the context clause of the
 225       --  given compilation unit, Cunit.
 226 
 227       procedure Update_Tables_From_ALI_File;
 228       --  Given an up to date ALI file (see Up_To_Date_ALI_file_Exists
 229       --  function), update tables from the ALI information, including
 230       --  specifically the Compilation_Switches table.
 231 
 232       function Up_To_Date_ALI_File_Exists return Boolean;
 233       --  If there exists an ALI file that is up to date, then this function
 234       --  initializes the tables in the ALI spec to contain information on
 235       --  this file (using Scan_ALI) and returns True. If no file exists,
 236       --  or the file is not up to date, then False is returned.
 237 
 238       procedure Write_Unit_Information (Unit_Num : Unit_Number_Type);
 239       --  Write out the library information for one unit for which code is
 240       --  generated (includes unit line and with lines).
 241 
 242       procedure Write_With_Lines;
 243       --  Write out with lines collected by calls to Collect_Withs
 244 
 245       -------------------
 246       -- Collect_Withs --
 247       -------------------
 248 
 249       procedure Collect_Withs (Cunit : Node_Id) is
 250          Item : Node_Id;
 251          Unum : Unit_Number_Type;
 252 
 253       begin
 254          Item := First (Context_Items (Cunit));
 255          while Present (Item) loop
 256 
 257             --  Process with clause
 258 
 259             --  Ada 2005 (AI-50217): limited with_clauses do not create
 260             --  dependencies, but must be recorded as components of the
 261             --  partition, in case there is no regular with_clause for
 262             --  the unit anywhere else.
 263 
 264             if Nkind (Item) = N_With_Clause then
 265                Unum := Get_Cunit_Unit_Number (Library_Unit (Item));
 266                With_Flags (Unum) := True;
 267 
 268                if not Limited_Present (Item) then
 269                   if Elaborate_Present (Item) then
 270                      Elab_Flags (Unum) := True;
 271                   end if;
 272 
 273                   if Elaborate_All_Present (Item) then
 274                      Elab_All_Flags (Unum) := True;
 275                   end if;
 276 
 277                   if Elaborate_All_Desirable (Item) then
 278                      Elab_All_Des_Flags (Unum) := True;
 279                   end if;
 280 
 281                   if Elaborate_Desirable (Item) then
 282                      Elab_Des_Flags (Unum) := True;
 283                   end if;
 284 
 285                else
 286                   Set_From_Limited_With (Cunit_Entity (Unum));
 287                end if;
 288 
 289                if Implicit_With (Unum) /= Yes then
 290                   if Implicit_With_From_Instantiation (Item) then
 291                      Implicit_With (Unum) := Yes;
 292                   else
 293                      Implicit_With (Unum) := No;
 294                   end if;
 295                end if;
 296             end if;
 297 
 298             Next (Item);
 299          end loop;
 300       end Collect_Withs;
 301 
 302       --------------------------------
 303       -- Up_To_Date_ALI_File_Exists --
 304       --------------------------------
 305 
 306       function Up_To_Date_ALI_File_Exists return Boolean is
 307          Name : File_Name_Type;
 308          Text : Text_Buffer_Ptr;
 309          Id   : Sdep_Id;
 310          Sind : Source_File_Index;
 311 
 312       begin
 313          Opt.Check_Object_Consistency := True;
 314          Read_Library_Info (Name, Text);
 315 
 316          --  Return if we could not find an ALI file
 317 
 318          if Text = null then
 319             return False;
 320          end if;
 321 
 322          --  Return if ALI file has bad format
 323 
 324          Initialize_ALI;
 325 
 326          if Scan_ALI (Name, Text, False, Err => True) = No_ALI_Id then
 327             return False;
 328          end if;
 329 
 330          --  If we have an OK ALI file, check if it is up to date
 331          --  Note that we assume that the ALI read has all the entries
 332          --  we have in our table, plus some additional ones (that can
 333          --  come from expansion).
 334 
 335          Id := First_Sdep_Entry;
 336          for J in 1 .. Num_Sdep loop
 337             Sind := Units.Table (Sdep_Table (J)).Source_Index;
 338 
 339             while Sdep.Table (Id).Sfile /= File_Name (Sind) loop
 340                if Id = Sdep.Last then
 341                   return False;
 342                else
 343                   Id := Id + 1;
 344                end if;
 345             end loop;
 346 
 347             if Sdep.Table (Id).Stamp /= Time_Stamp (Sind) then
 348                return False;
 349             end if;
 350          end loop;
 351 
 352          return True;
 353       end Up_To_Date_ALI_File_Exists;
 354 
 355       ---------------------------------
 356       -- Update_Tables_From_ALI_File --
 357       ---------------------------------
 358 
 359       procedure Update_Tables_From_ALI_File is
 360       begin
 361          --  Build Compilation_Switches table
 362 
 363          Compilation_Switches.Init;
 364 
 365          for J in First_Arg_Entry .. Args.Last loop
 366             Compilation_Switches.Increment_Last;
 367             Compilation_Switches.Table (Compilation_Switches.Last) :=
 368               Args.Table (J);
 369          end loop;
 370       end Update_Tables_From_ALI_File;
 371 
 372       ----------------------------
 373       -- Write_Unit_Information --
 374       ----------------------------
 375 
 376       procedure Write_Unit_Information (Unit_Num : Unit_Number_Type) is
 377          Unode : constant Node_Id   := Cunit (Unit_Num);
 378          Ukind : constant Node_Kind := Nkind (Unit (Unode));
 379          Uent  : constant Entity_Id := Cunit_Entity (Unit_Num);
 380          Pnode : Node_Id;
 381 
 382       begin
 383          Write_Info_Initiate ('U');
 384          Write_Info_Char (' ');
 385          Write_Info_Name (Unit_Name (Unit_Num));
 386          Write_Info_Tab (25);
 387          Write_Info_Name (Unit_File_Name (Unit_Num));
 388 
 389          Write_Info_Tab (49);
 390          Write_Info_Str (Version_Get (Unit_Num));
 391 
 392          --  Add BD parameter if Elaborate_Body pragma desirable
 393 
 394          if Ekind (Uent) = E_Package
 395            and then Elaborate_Body_Desirable (Uent)
 396          then
 397             Write_Info_Str (" BD");
 398          end if;
 399 
 400          --  Add BN parameter if body needed for SAL
 401 
 402          if (Is_Subprogram (Uent)
 403               or else Ekind (Uent) = E_Package
 404               or else Is_Generic_Unit (Uent))
 405            and then Body_Needed_For_SAL (Uent)
 406          then
 407             Write_Info_Str (" BN");
 408          end if;
 409 
 410          if Dynamic_Elab (Unit_Num) then
 411             Write_Info_Str (" DE");
 412          end if;
 413 
 414          --  Set the Elaborate_Body indication if either an explicit pragma
 415          --  was present, or if this is an instantiation.
 416 
 417          if Has_Pragma_Elaborate_Body (Uent)
 418            or else (Ukind = N_Package_Declaration
 419                      and then Is_Generic_Instance (Uent)
 420                      and then Present (Corresponding_Body (Unit (Unode))))
 421          then
 422             Write_Info_Str (" EB");
 423          end if;
 424 
 425          --  Now see if we should tell the binder that an elaboration entity
 426          --  is present, which must be set to true during elaboration.
 427          --  We generate the indication if the following condition is met:
 428 
 429          --  If this is a spec ...
 430 
 431          if (Is_Subprogram (Uent)
 432               or else Ekind (Uent) = E_Package
 433               or else Is_Generic_Unit (Uent))
 434 
 435             --  and an elaboration entity was declared ...
 436 
 437             and then Present (Elaboration_Entity (Uent))
 438 
 439             --  and either the elaboration flag is required ...
 440 
 441             and then (Elaboration_Entity_Required (Uent)
 442 
 443                --  or this unit has elaboration code ...
 444 
 445                or else not Has_No_Elaboration_Code (Unode)
 446 
 447                --  or this unit has a separate body and this
 448                --  body has elaboration code.
 449 
 450                or else
 451                  (Ekind (Uent) = E_Package
 452                    and then Present (Body_Entity (Uent))
 453                    and then
 454                      not Has_No_Elaboration_Code
 455                            (Parent (Declaration_Node (Body_Entity (Uent))))))
 456          then
 457             Write_Info_Str (" EE");
 458          end if;
 459 
 460          if Has_No_Elaboration_Code (Unode) then
 461             Write_Info_Str (" NE");
 462          end if;
 463 
 464          Write_Info_Str (" O");
 465          Write_Info_Char (OA_Setting (Unit_Num));
 466 
 467          if Ekind_In (Uent, E_Package, E_Package_Body)
 468            and then Present (Finalizer (Uent))
 469          then
 470             Write_Info_Str (" PF");
 471          end if;
 472 
 473          if Is_Preelaborated (Uent) then
 474             Write_Info_Str (" PR");
 475          end if;
 476 
 477          if Is_Pure (Uent) then
 478             Write_Info_Str (" PU");
 479          end if;
 480 
 481          if Has_RACW (Unit_Num) then
 482             Write_Info_Str (" RA");
 483          end if;
 484 
 485          if Is_Remote_Call_Interface (Uent) then
 486             Write_Info_Str (" RC");
 487          end if;
 488 
 489          if Is_Remote_Types (Uent) then
 490             Write_Info_Str (" RT");
 491          end if;
 492 
 493          if Serious_Errors_Detected /= 0 then
 494             Write_Info_Str (" SE");
 495          end if;
 496 
 497          if Is_Shared_Passive (Uent) then
 498             Write_Info_Str (" SP");
 499          end if;
 500 
 501          if Ukind = N_Subprogram_Declaration
 502            or else Ukind = N_Subprogram_Body
 503          then
 504             Write_Info_Str (" SU");
 505 
 506          elsif Ukind = N_Package_Declaration
 507                  or else
 508                Ukind = N_Package_Body
 509          then
 510             --  If this is a wrapper package for a subprogram instantiation,
 511             --  the user view is the subprogram. Note that in this case the
 512             --  ali file contains both the spec and body of the instance.
 513 
 514             if Is_Wrapper_Package (Uent) then
 515                Write_Info_Str (" SU");
 516             else
 517                Write_Info_Str (" PK");
 518             end if;
 519 
 520          elsif Ukind = N_Generic_Package_Declaration then
 521             Write_Info_Str (" PK");
 522 
 523          end if;
 524 
 525          if Ukind in N_Generic_Declaration
 526            or else
 527              (Present (Library_Unit (Unode))
 528                 and then
 529                   Nkind (Unit (Library_Unit (Unode))) in N_Generic_Declaration)
 530          then
 531             Write_Info_Str (" GE");
 532          end if;
 533 
 534          if not Is_Internal_File_Name (Unit_File_Name (Unit_Num), True) then
 535             case Identifier_Casing (Source_Index (Unit_Num)) is
 536                when All_Lower_Case => Write_Info_Str (" IL");
 537                when All_Upper_Case => Write_Info_Str (" IU");
 538                when others         => null;
 539             end case;
 540 
 541             case Keyword_Casing (Source_Index (Unit_Num)) is
 542                when Mixed_Case     => Write_Info_Str (" KM");
 543                when All_Upper_Case => Write_Info_Str (" KU");
 544                when others         => null;
 545             end case;
 546          end if;
 547 
 548          if Initialize_Scalars or else Invalid_Value_Used then
 549             Write_Info_Str (" IS");
 550          end if;
 551 
 552          Write_Info_EOL;
 553 
 554          --  Generate with lines, first those that are directly with'ed
 555 
 556          for J in With_Flags'Range loop
 557             With_Flags         (J) := False;
 558             Elab_Flags         (J) := False;
 559             Elab_All_Flags     (J) := False;
 560             Elab_Des_Flags     (J) := False;
 561             Elab_All_Des_Flags (J) := False;
 562             Implicit_With      (J) := Unknown;
 563          end loop;
 564 
 565          Collect_Withs (Unode);
 566 
 567          --  For a body, we must also check for any subunits which belong to
 568          --  it and which have context clauses of their own, since these
 569          --  with'ed units are part of its own elaboration dependencies.
 570 
 571          if Nkind (Unit (Unode)) in N_Unit_Body then
 572             for S in Units.First .. Last_Unit loop
 573 
 574                --  We are only interested in subunits. For preproc. data and
 575                --  def. files, Cunit is Empty, so we need to test that first.
 576 
 577                if Cunit (S) /= Empty
 578                  and then Nkind (Unit (Cunit (S))) = N_Subunit
 579                then
 580                   Pnode := Library_Unit (Cunit (S));
 581 
 582                   --  In gnatc mode, the errors in the subunits will not have
 583                   --  been recorded, but the analysis of the subunit may have
 584                   --  failed. There is no information to add to ALI file in
 585                   --  this case.
 586 
 587                   if No (Pnode) then
 588                      exit;
 589                   end if;
 590 
 591                   --  Find ultimate parent of the subunit
 592 
 593                   while Nkind (Unit (Pnode)) = N_Subunit loop
 594                      Pnode := Library_Unit (Pnode);
 595                   end loop;
 596 
 597                   --  See if it belongs to current unit, and if so, include
 598                   --  its with_clauses.
 599 
 600                   if Pnode = Unode then
 601                      Collect_Withs (Cunit (S));
 602                   end if;
 603                end if;
 604             end loop;
 605          end if;
 606 
 607          Write_With_Lines;
 608 
 609          --  Generate the linker option lines
 610 
 611          for J in 1 .. Linker_Option_Lines.Last loop
 612 
 613             --  Pragma Linker_Options is not allowed in predefined generic
 614             --  units. This is because they won't be read, due to the fact that
 615             --  with lines for generic units lack the file name and lib name
 616             --  parameters (see Lib_Writ spec for an explanation).
 617 
 618             if Is_Generic_Unit (Cunit_Entity (Main_Unit))
 619               and then
 620                 Is_Predefined_File_Name (Unit_File_Name (Current_Sem_Unit))
 621               and then Linker_Option_Lines.Table (J).Unit = Unit_Num
 622             then
 623                Set_Standard_Error;
 624                Write_Line
 625                  ("linker options not allowed in predefined generic unit");
 626                raise Unrecoverable_Error;
 627             end if;
 628 
 629             --  Output one linker option line
 630 
 631             declare
 632                S : Linker_Option_Entry renames Linker_Option_Lines.Table (J);
 633             begin
 634                if S.Unit = Unit_Num then
 635                   Write_Info_Initiate ('L');
 636                   Write_Info_Char (' ');
 637                   Write_Info_Slit (S.Option);
 638                   Write_Info_EOL;
 639                end if;
 640             end;
 641          end loop;
 642 
 643          --  Output notes
 644 
 645          for J in 1 .. Notes.Last loop
 646             declare
 647                N : constant Node_Id          := Notes.Table (J);
 648                L : constant Source_Ptr       := Sloc (N);
 649                U : constant Unit_Number_Type :=
 650                      Unit (Get_Source_File_Index (L));
 651                C : Character;
 652 
 653                Note_Unit : Unit_Number_Type;
 654                --  The unit in whose U section this note must be emitted:
 655                --  notes for subunits are emitted along with the main unit;
 656                --  all other notes are emitted as part of the enclosing
 657                --  compilation unit.
 658 
 659             begin
 660                if U /= No_Unit and then Nkind (Unit (Cunit (U))) = N_Subunit
 661                then
 662                   Note_Unit := Main_Unit;
 663                else
 664                   Note_Unit := U;
 665                end if;
 666 
 667                if Note_Unit = Unit_Num then
 668                   Write_Info_Initiate ('N');
 669                   Write_Info_Char (' ');
 670 
 671                   case Chars (Pragma_Identifier (N)) is
 672                      when Name_Annotate =>
 673                         C := 'A';
 674                      when Name_Comment =>
 675                         C := 'C';
 676                      when Name_Ident =>
 677                         C := 'I';
 678                      when Name_Title =>
 679                         C := 'T';
 680                      when Name_Subtitle =>
 681                         C := 'S';
 682                      when others =>
 683                         raise Program_Error;
 684                   end case;
 685 
 686                   Write_Info_Char (C);
 687                   Write_Info_Int (Int (Get_Logical_Line_Number (L)));
 688                   Write_Info_Char (':');
 689                   Write_Info_Int (Int (Get_Column_Number (L)));
 690 
 691                   --  Indicate source file of annotation if different from
 692                   --  compilation unit source file (case of annotation coming
 693                   --  from a separate).
 694 
 695                   if Get_Source_File_Index (L) /= Source_Index (Unit_Num) then
 696                      Write_Info_Char (':');
 697                      Write_Info_Name (File_Name (Get_Source_File_Index (L)));
 698                   end if;
 699 
 700                   declare
 701                      A : Node_Id;
 702 
 703                   begin
 704                      A := First (Pragma_Argument_Associations (N));
 705                      while Present (A) loop
 706                         Write_Info_Char (' ');
 707 
 708                         if Chars (A) /= No_Name then
 709                            Write_Info_Name (Chars (A));
 710                            Write_Info_Char (':');
 711                         end if;
 712 
 713                         declare
 714                            Expr : constant Node_Id := Expression (A);
 715 
 716                         begin
 717                            if Nkind (Expr) = N_Identifier then
 718                               Write_Info_Name (Chars (Expr));
 719 
 720                            elsif Nkind (Expr) = N_Integer_Literal
 721                              and then Is_OK_Static_Expression (Expr)
 722                            then
 723                               Write_Info_Uint (Intval (Expr));
 724 
 725                            elsif Nkind (Expr) = N_String_Literal
 726                              and then Is_OK_Static_Expression (Expr)
 727                            then
 728                               Write_Info_Slit (Strval (Expr));
 729 
 730                            else
 731                               Write_Info_Str ("<expr>");
 732                            end if;
 733                         end;
 734 
 735                         Next (A);
 736                      end loop;
 737                   end;
 738 
 739                   Write_Info_EOL;
 740                end if;
 741             end;
 742          end loop;
 743       end Write_Unit_Information;
 744 
 745       ----------------------
 746       -- Write_With_Lines --
 747       ----------------------
 748 
 749       procedure Write_With_Lines is
 750          Pname      : constant Unit_Name_Type :=
 751                         Get_Parent_Spec_Name (Unit_Name (Main_Unit));
 752          Body_Fname : File_Name_Type;
 753          Body_Index : Nat;
 754          Cunit      : Node_Id;
 755          Fname      : File_Name_Type;
 756          Num_Withs  : Int := 0;
 757          Unum       : Unit_Number_Type;
 758          Uname      : Unit_Name_Type;
 759          With_Table : Unit_Ref_Table (1 .. Pos (Last_Unit - Units.First + 1));
 760 
 761          procedure Write_With_File_Names
 762            (Nam : in out File_Name_Type;
 763             Idx : Nat);
 764          --  Write source file name Nam and ALI file name for unit index Idx.
 765          --  Possibly change Nam to lowercase (generating a new file name).
 766 
 767          --------------------------
 768          -- Write_With_File_Name --
 769          --------------------------
 770 
 771          procedure Write_With_File_Names
 772            (Nam : in out File_Name_Type;
 773             Idx : Nat)
 774          is
 775          begin
 776             if not File_Names_Case_Sensitive then
 777                Get_Name_String (Nam);
 778                To_Lower (Name_Buffer (1 .. Name_Len));
 779                Nam := Name_Find;
 780             end if;
 781 
 782             Write_Info_Name (Nam);
 783             Write_Info_Tab (49);
 784             Write_Info_Name (Lib_File_Name (Nam, Idx));
 785          end Write_With_File_Names;
 786 
 787       --  Start of processing for Write_With_Lines
 788 
 789       begin
 790          --  Loop to build the with table. A with on the main unit itself
 791          --  is ignored (AARM 10.2(14a)). Such a with-clause can occur if
 792          --  the main unit is a subprogram with no spec, and a subunit of
 793          --  it unnecessarily withs the parent.
 794 
 795          for J in Units.First + 1 .. Last_Unit loop
 796 
 797             --  Add element to with table if it is with'ed or if it is the
 798             --  parent spec of the main unit (case of main unit is a child
 799             --  unit). The latter with is not needed for semantic purposes,
 800             --  but is required by the binder for elaboration purposes. For
 801             --  preprocessing data and definition files, there is no Unit_Name,
 802             --  check for that first.
 803 
 804             if Unit_Name (J) /= No_Unit_Name
 805               and then (With_Flags (J) or else Unit_Name (J) = Pname)
 806             then
 807                Num_Withs := Num_Withs + 1;
 808                With_Table (Num_Withs) := J;
 809             end if;
 810          end loop;
 811 
 812          --  Sort and output the table
 813 
 814          Sort (With_Table (1 .. Num_Withs));
 815 
 816          for J in 1 .. Num_Withs loop
 817             Unum := With_Table (J);
 818 
 819             --  Do not generate a with line for an ignored Ghost unit because
 820             --  the unit does not have an ALI file.
 821 
 822             if Is_Ignored_Ghost_Entity (Cunit_Entity (Unum)) then
 823                goto Next_With_Line;
 824             end if;
 825 
 826             Cunit := Units.Table (Unum).Cunit;
 827             Uname := Units.Table (Unum).Unit_Name;
 828             Fname := Units.Table (Unum).Unit_File_Name;
 829 
 830             if Implicit_With (Unum) = Yes then
 831                Write_Info_Initiate ('Z');
 832 
 833             elsif Ekind (Cunit_Entity (Unum)) = E_Package
 834               and then From_Limited_With (Cunit_Entity (Unum))
 835             then
 836                Write_Info_Initiate ('Y');
 837 
 838             else
 839                Write_Info_Initiate ('W');
 840             end if;
 841 
 842             Write_Info_Char (' ');
 843             Write_Info_Name (Uname);
 844 
 845             --  Now we need to figure out the names of the files that contain
 846             --  the with'ed unit. These will usually be the files for the body,
 847             --  except in the case of a package that has no body. Note that we
 848             --  have a specific exemption here for predefined library generics
 849             --  (see comments for Generic_May_Lack_ALI). We do not generate
 850             --  dependency upon the ALI file for such units. Older compilers
 851             --  used to not support generating code (and ALI) for generics, and
 852             --  we want to avoid having different processing (namely, different
 853             --  lists of files to be compiled) for different stages of the
 854             --  bootstrap.
 855 
 856             if not ((Nkind (Unit (Cunit)) in N_Generic_Declaration
 857                       or else
 858                      Nkind (Unit (Cunit)) in N_Generic_Renaming_Declaration)
 859                     and then Generic_May_Lack_ALI (Fname))
 860 
 861               --  In SPARK mode, always generate the dependencies on ALI
 862               --  files, which are required to compute frame conditions
 863               --  of subprograms.
 864 
 865               or else GNATprove_Mode
 866             then
 867                Write_Info_Tab (25);
 868 
 869                if Is_Spec_Name (Uname) then
 870                   Body_Fname :=
 871                     Get_File_Name
 872                       (Get_Body_Name (Uname),
 873                        Subunit => False, May_Fail => True);
 874 
 875                   Body_Index :=
 876                     Get_Unit_Index
 877                       (Get_Body_Name (Uname));
 878 
 879                   if Body_Fname = No_File then
 880                      Body_Fname := Get_File_Name (Uname, Subunit => False);
 881                      Body_Index := Get_Unit_Index (Uname);
 882                   end if;
 883 
 884                else
 885                   Body_Fname := Get_File_Name (Uname, Subunit => False);
 886                   Body_Index := Get_Unit_Index (Uname);
 887                end if;
 888 
 889                --  A package is considered to have a body if it requires
 890                --  a body or if a body is present in Ada 83 mode.
 891 
 892                if Body_Required (Cunit)
 893                  or else (Ada_Version = Ada_83
 894                            and then Full_Source_Name (Body_Fname) /= No_File)
 895                then
 896                   Write_With_File_Names (Body_Fname, Body_Index);
 897                else
 898                   Write_With_File_Names (Fname, Munit_Index (Unum));
 899                end if;
 900 
 901                if Ekind (Cunit_Entity (Unum)) = E_Package
 902                   and then From_Limited_With (Cunit_Entity (Unum))
 903                then
 904                   null;
 905                else
 906                   if Elab_Flags (Unum) then
 907                      Write_Info_Str ("  E");
 908                   end if;
 909 
 910                   if Elab_All_Flags (Unum) then
 911                      Write_Info_Str ("  EA");
 912                   end if;
 913 
 914                   if Elab_Des_Flags (Unum) then
 915                      Write_Info_Str ("  ED");
 916                   end if;
 917 
 918                   if Elab_All_Des_Flags (Unum) then
 919                      Write_Info_Str ("  AD");
 920                   end if;
 921                end if;
 922             end if;
 923 
 924             Write_Info_EOL;
 925 
 926          <<Next_With_Line>>
 927             null;
 928          end loop;
 929 
 930          --  Finally generate the special lines for cases of Restriction_Set
 931          --  with No_Dependence and no restriction present.
 932 
 933          declare
 934             Unam : Unit_Name_Type;
 935 
 936          begin
 937             for J in Restriction_Set_Dependences.First ..
 938                      Restriction_Set_Dependences.Last
 939             loop
 940                Unam := Restriction_Set_Dependences.Table (J);
 941 
 942                --  Don't need an entry if already in the unit table
 943 
 944                for U in 0 .. Last_Unit loop
 945                   if Unit_Name (U) = Unam then
 946                      goto Next_Restriction_Set;
 947                   end if;
 948                end loop;
 949 
 950                --  Otherwise generate the entry
 951 
 952                Write_Info_Initiate ('W');
 953                Write_Info_Char (' ');
 954                Write_Info_Name (Unam);
 955                Write_Info_EOL;
 956 
 957             <<Next_Restriction_Set>>
 958                null;
 959             end loop;
 960          end;
 961       end Write_With_Lines;
 962 
 963    --  Start of processing for Write_ALI
 964 
 965    begin
 966       --  We never write an ALI file if the original operating mode was
 967       --  syntax-only (-gnats switch used in compiler invocation line)
 968 
 969       if Original_Operating_Mode = Check_Syntax then
 970          return;
 971       end if;
 972 
 973       --  Generation of ALI files may be disabled, e.g. for formal verification
 974       --  back-end.
 975 
 976       if Disable_ALI_File then
 977          return;
 978       end if;
 979 
 980       --  Build sorted source dependency table. We do this right away, because
 981       --  it is referenced by Up_To_Date_ALI_File_Exists.
 982 
 983       for Unum in Units.First .. Last_Unit loop
 984          if Cunit_Entity (Unum) = Empty
 985            or else not From_Limited_With (Cunit_Entity (Unum))
 986          then
 987             Num_Sdep := Num_Sdep + 1;
 988             Sdep_Table (Num_Sdep) := Unum;
 989          end if;
 990       end loop;
 991 
 992       --  Sort the table so that the D lines are in order
 993 
 994       Lib.Sort (Sdep_Table (1 .. Num_Sdep));
 995 
 996       --  If we are not generating code, and there is an up to date ALI file
 997       --  file accessible, read it, and acquire the compilation arguments from
 998       --  this file. In GNATprove mode, always generate the ALI file, which
 999       --  contains a special section for formal verification.
1000 
1001       if Operating_Mode /= Generate_Code and then not GNATprove_Mode then
1002          if Up_To_Date_ALI_File_Exists then
1003             Update_Tables_From_ALI_File;
1004             return;
1005          end if;
1006       end if;
1007 
1008       --  Otherwise acquire compilation arguments and prepare to write out a
1009       --  new ali file.
1010 
1011       Create_Output_Library_Info;
1012 
1013       --  Output version line
1014 
1015       Write_Info_Initiate ('V');
1016       Write_Info_Str (" """);
1017       Write_Info_Str (Verbose_Library_Version);
1018       Write_Info_Char ('"');
1019 
1020       Write_Info_EOL;
1021 
1022       --  Output main program line if this is acceptable main program
1023 
1024       Output_Main_Program_Line : declare
1025          U : Node_Id := Unit (Units.Table (Main_Unit).Cunit);
1026          S : Node_Id;
1027 
1028          procedure M_Parameters;
1029          --  Output parameters for main program line
1030 
1031          ------------------
1032          -- M_Parameters --
1033          ------------------
1034 
1035          procedure M_Parameters is
1036          begin
1037             if Main_Priority (Main_Unit) /= Default_Main_Priority then
1038                Write_Info_Char (' ');
1039                Write_Info_Nat (Main_Priority (Main_Unit));
1040             end if;
1041 
1042             if Opt.Time_Slice_Set then
1043                Write_Info_Str (" T=");
1044                Write_Info_Nat (Opt.Time_Slice_Value);
1045             end if;
1046 
1047             if Main_CPU (Main_Unit) /= Default_Main_CPU then
1048                Write_Info_Str (" C=");
1049                Write_Info_Nat (Main_CPU (Main_Unit));
1050             end if;
1051 
1052             Write_Info_Str (" W=");
1053             Write_Info_Char
1054               (WC_Encoding_Letters (Wide_Character_Encoding_Method));
1055 
1056             Write_Info_EOL;
1057          end M_Parameters;
1058 
1059       --  Start of processing for Output_Main_Program_Line
1060 
1061       begin
1062          if Nkind (U) = N_Subprogram_Body
1063            or else
1064              (Nkind (U) = N_Package_Body
1065                and then
1066                  Nkind (Original_Node (U)) in N_Subprogram_Instantiation)
1067          then
1068             --  If the unit is a subprogram instance, the entity for the
1069             --  subprogram is the alias of the visible entity, which is the
1070             --  related instance of the wrapper package. We retrieve the
1071             --  subprogram declaration of the desired entity.
1072 
1073             if Nkind (U) = N_Package_Body then
1074                U := Parent (Parent (
1075                    Alias (Related_Instance (Defining_Unit_Name
1076                      (Specification (Unit (Library_Unit (Parent (U)))))))));
1077             end if;
1078 
1079             S := Specification (U);
1080 
1081             --  A generic subprogram is never a main program
1082 
1083             if Nkind (U) = N_Subprogram_Body
1084               and then Present (Corresponding_Spec (U))
1085               and then
1086                 Ekind_In (Corresponding_Spec (U), E_Generic_Procedure,
1087                                                   E_Generic_Function)
1088             then
1089                null;
1090 
1091             elsif No (Parameter_Specifications (S)) then
1092                if Nkind (S) = N_Procedure_Specification then
1093                   Write_Info_Initiate ('M');
1094                   Write_Info_Str (" P");
1095                   M_Parameters;
1096 
1097                else
1098                   declare
1099                      Nam : Node_Id := Defining_Unit_Name (S);
1100 
1101                   begin
1102                      --  If it is a child unit, get its simple name
1103 
1104                      if Nkind (Nam) = N_Defining_Program_Unit_Name then
1105                         Nam := Defining_Identifier (Nam);
1106                      end if;
1107 
1108                      if Is_Integer_Type (Etype (Nam)) then
1109                         Write_Info_Initiate ('M');
1110                         Write_Info_Str (" F");
1111                         M_Parameters;
1112                      end if;
1113                   end;
1114                end if;
1115             end if;
1116          end if;
1117       end Output_Main_Program_Line;
1118 
1119       --  Write command argument ('A') lines
1120 
1121       for A in 1 .. Compilation_Switches.Last loop
1122          Write_Info_Initiate ('A');
1123          Write_Info_Char (' ');
1124          Write_Info_Str (Compilation_Switches.Table (A).all);
1125          Write_Info_Terminate;
1126       end loop;
1127 
1128       --  Output parameters ('P') line
1129 
1130       Write_Info_Initiate ('P');
1131 
1132       if Compilation_Errors then
1133          Write_Info_Str (" CE");
1134       end if;
1135 
1136       if Opt.Detect_Blocking then
1137          Write_Info_Str (" DB");
1138       end if;
1139 
1140       if Tasking_Used
1141         and then not Is_Predefined_File_Name (Unit_File_Name (Main_Unit))
1142       then
1143          if Locking_Policy /= ' ' then
1144             Write_Info_Str  (" L");
1145             Write_Info_Char (Locking_Policy);
1146          end if;
1147 
1148          if Queuing_Policy /= ' ' then
1149             Write_Info_Str  (" Q");
1150             Write_Info_Char (Queuing_Policy);
1151          end if;
1152 
1153          if Task_Dispatching_Policy /= ' ' then
1154             Write_Info_Str  (" T");
1155             Write_Info_Char (Task_Dispatching_Policy);
1156             Write_Info_Char (' ');
1157          end if;
1158       end if;
1159 
1160       if GNATprove_Mode then
1161          Write_Info_Str (" GP");
1162       end if;
1163 
1164       if Partition_Elaboration_Policy /= ' ' then
1165          Write_Info_Str  (" E");
1166          Write_Info_Char (Partition_Elaboration_Policy);
1167       end if;
1168 
1169       if not Object then
1170          Write_Info_Str (" NO");
1171       end if;
1172 
1173       if No_Run_Time_Mode then
1174          Write_Info_Str (" NR");
1175       end if;
1176 
1177       if Normalize_Scalars then
1178          Write_Info_Str (" NS");
1179       end if;
1180 
1181       if Default_SSO_Config /= ' ' then
1182          Write_Info_Str (" O");
1183          Write_Info_Char (Default_SSO_Config);
1184       end if;
1185 
1186       if Sec_Stack_Used then
1187          Write_Info_Str (" SS");
1188       end if;
1189 
1190       if Unreserve_All_Interrupts then
1191          Write_Info_Str (" UA");
1192       end if;
1193 
1194       if Front_End_Exceptions then
1195          Write_Info_Str (" FX");
1196       end if;
1197 
1198       if ZCX_Exceptions then
1199          Write_Info_Str (" ZX");
1200       end if;
1201 
1202       Write_Info_EOL;
1203 
1204       --  Before outputting the restrictions line, update the setting of
1205       --  the No_Elaboration_Code flag. Violations of this restriction
1206       --  cannot be detected until after the backend has been called since
1207       --  it is the backend that sets this flag. We have to check all units
1208       --  for which we have generated code
1209 
1210       for Unit in Units.First .. Last_Unit loop
1211          if Units.Table (Unit).Generate_Code or else Unit = Main_Unit then
1212             if not Has_No_Elaboration_Code (Cunit (Unit)) then
1213                Main_Restrictions.Violated (No_Elaboration_Code) := True;
1214             end if;
1215          end if;
1216       end loop;
1217 
1218       --  Positional case (only if debug flag -gnatd.R is set)
1219 
1220       if Debug_Flag_Dot_RR then
1221 
1222          --  Output first restrictions line
1223 
1224          Write_Info_Initiate ('R');
1225          Write_Info_Char (' ');
1226 
1227          --  First the information for the boolean restrictions
1228 
1229          for R in All_Boolean_Restrictions loop
1230             if Main_Restrictions.Set (R)
1231               and then not Restriction_Warnings (R)
1232             then
1233                Write_Info_Char ('r');
1234             elsif Main_Restrictions.Violated (R) then
1235                Write_Info_Char ('v');
1236             else
1237                Write_Info_Char ('n');
1238             end if;
1239          end loop;
1240 
1241          --  And now the information for the parameter restrictions
1242 
1243          for RP in All_Parameter_Restrictions loop
1244             if Main_Restrictions.Set (RP)
1245               and then not Restriction_Warnings (RP)
1246             then
1247                Write_Info_Char ('r');
1248                Write_Info_Nat (Nat (Main_Restrictions.Value (RP)));
1249             else
1250                Write_Info_Char ('n');
1251             end if;
1252 
1253             if not Main_Restrictions.Violated (RP)
1254               or else RP not in Checked_Parameter_Restrictions
1255             then
1256                Write_Info_Char ('n');
1257             else
1258                Write_Info_Char ('v');
1259                Write_Info_Nat (Nat (Main_Restrictions.Count (RP)));
1260 
1261                if Main_Restrictions.Unknown (RP) then
1262                   Write_Info_Char ('+');
1263                end if;
1264             end if;
1265          end loop;
1266 
1267          Write_Info_EOL;
1268 
1269       --  Named case (if debug flag -gnatd.R is not set)
1270 
1271       else
1272          declare
1273             C : Character;
1274 
1275          begin
1276             --  Write RN header line with preceding blank line
1277 
1278             Write_Info_EOL;
1279             Write_Info_Initiate ('R');
1280             Write_Info_Char ('N');
1281             Write_Info_EOL;
1282 
1283             --  First the lines for the boolean restrictions
1284 
1285             for R in All_Boolean_Restrictions loop
1286                if Main_Restrictions.Set (R)
1287                  and then not Restriction_Warnings (R)
1288                then
1289                   C := 'R';
1290                elsif Main_Restrictions.Violated (R) then
1291                   C := 'V';
1292                else
1293                   goto Continue;
1294                end if;
1295 
1296                Write_Info_Initiate ('R');
1297                Write_Info_Char (C);
1298                Write_Info_Char (' ');
1299                Write_Info_Str (All_Boolean_Restrictions'Image (R));
1300                Write_Info_EOL;
1301 
1302             <<Continue>>
1303                null;
1304             end loop;
1305          end;
1306 
1307          --  And now the lines for the parameter restrictions
1308 
1309          for RP in All_Parameter_Restrictions loop
1310             if Main_Restrictions.Set (RP)
1311               and then not Restriction_Warnings (RP)
1312             then
1313                Write_Info_Initiate ('R');
1314                Write_Info_Str ("R ");
1315                Write_Info_Str (All_Parameter_Restrictions'Image (RP));
1316                Write_Info_Char ('=');
1317                Write_Info_Nat (Nat (Main_Restrictions.Value (RP)));
1318                Write_Info_EOL;
1319             end if;
1320 
1321             if not Main_Restrictions.Violated (RP)
1322               or else RP not in Checked_Parameter_Restrictions
1323             then
1324                null;
1325             else
1326                Write_Info_Initiate ('R');
1327                Write_Info_Str ("V ");
1328                Write_Info_Str (All_Parameter_Restrictions'Image (RP));
1329                Write_Info_Char ('=');
1330                Write_Info_Nat (Nat (Main_Restrictions.Count (RP)));
1331 
1332                if Main_Restrictions.Unknown (RP) then
1333                   Write_Info_Char ('+');
1334                end if;
1335 
1336                Write_Info_EOL;
1337             end if;
1338          end loop;
1339       end if;
1340 
1341       --  Output R lines for No_Dependence entries
1342 
1343       for J in No_Dependences.First .. No_Dependences.Last loop
1344          if In_Extended_Main_Source_Unit (No_Dependences.Table (J).Unit)
1345            and then not No_Dependences.Table (J).Warn
1346          then
1347             Write_Info_Initiate ('R');
1348             Write_Info_Char (' ');
1349             Write_Unit_Name (No_Dependences.Table (J).Unit);
1350             Write_Info_EOL;
1351          end if;
1352       end loop;
1353 
1354       --  Output interrupt state lines
1355 
1356       for J in Interrupt_States.First .. Interrupt_States.Last loop
1357          Write_Info_Initiate ('I');
1358          Write_Info_Char (' ');
1359          Write_Info_Nat (Interrupt_States.Table (J).Interrupt_Number);
1360          Write_Info_Char (' ');
1361          Write_Info_Char (Interrupt_States.Table (J).Interrupt_State);
1362          Write_Info_Char (' ');
1363          Write_Info_Nat
1364            (Nat (Get_Logical_Line_Number
1365                    (Interrupt_States.Table (J).Pragma_Loc)));
1366          Write_Info_EOL;
1367       end loop;
1368 
1369       --  Output priority specific dispatching lines
1370 
1371       for J in Specific_Dispatching.First .. Specific_Dispatching.Last loop
1372          Write_Info_Initiate ('S');
1373          Write_Info_Char (' ');
1374          Write_Info_Char (Specific_Dispatching.Table (J).Dispatching_Policy);
1375          Write_Info_Char (' ');
1376          Write_Info_Nat (Specific_Dispatching.Table (J).First_Priority);
1377          Write_Info_Char (' ');
1378          Write_Info_Nat (Specific_Dispatching.Table (J).Last_Priority);
1379          Write_Info_Char (' ');
1380          Write_Info_Nat
1381            (Nat (Get_Logical_Line_Number
1382                    (Specific_Dispatching.Table (J).Pragma_Loc)));
1383          Write_Info_EOL;
1384       end loop;
1385 
1386       --  Loop through file table to output information for all units for which
1387       --  we have generated code, as marked by the Generate_Code flag.
1388 
1389       for Unit in Units.First .. Last_Unit loop
1390          if Units.Table (Unit).Generate_Code
1391            or else Unit = Main_Unit
1392          then
1393             Write_Info_EOL; -- blank line
1394             Write_Unit_Information (Unit);
1395          end if;
1396       end loop;
1397 
1398       Write_Info_EOL; -- blank line
1399 
1400       --  Output external version reference lines
1401 
1402       for J in 1 .. Version_Ref.Last loop
1403          Write_Info_Initiate ('E');
1404          Write_Info_Char (' ');
1405 
1406          for K in 1 .. String_Length (Version_Ref.Table (J)) loop
1407             Write_Info_Char_Code (Get_String_Char (Version_Ref.Table (J), K));
1408          end loop;
1409 
1410          Write_Info_EOL;
1411       end loop;
1412 
1413       --  Prepare to output the source dependency lines
1414 
1415       declare
1416          Unum : Unit_Number_Type;
1417          --  Number of unit being output
1418 
1419          Sind : Source_File_Index;
1420          --  Index of corresponding source file
1421 
1422          Fname : File_Name_Type;
1423 
1424       begin
1425          for J in 1 .. Num_Sdep loop
1426             Unum := Sdep_Table (J);
1427             Units.Table (Unum).Dependency_Num := J;
1428             Sind := Units.Table (Unum).Source_Index;
1429 
1430             --  The dependency table also contains units that appear in the
1431             --  context of a unit loaded through a limited_with clause. These
1432             --  units are never analyzed, and thus the main unit does not
1433             --  really have a dependency on them. Subunits are always compiled
1434             --  in the context of the parent, and their file table entries are
1435             --  not properly decorated, they are recognized syntactically.
1436 
1437             if Present (Cunit_Entity (Unum))
1438               and then Ekind (Cunit_Entity (Unum)) = E_Void
1439               and then Nkind (Unit (Cunit (Unum))) /= N_Subunit
1440             then
1441                goto Next_Unit;
1442             end if;
1443 
1444             Write_Info_Initiate ('D');
1445             Write_Info_Char (' ');
1446 
1447             --  Normal case of a unit entry with a source index
1448 
1449             if Sind /= No_Source_File then
1450                Fname := File_Name (Sind);
1451 
1452                --  Ensure that on platforms where the file names are not case
1453                --  sensitive, the recorded file name is in lower case.
1454 
1455                if not File_Names_Case_Sensitive then
1456                   Get_Name_String (Fname);
1457                   To_Lower (Name_Buffer (1 .. Name_Len));
1458                   Fname := Name_Find;
1459                end if;
1460 
1461                Write_Info_Name_May_Be_Quoted (Fname);
1462                Write_Info_Tab (25);
1463                Write_Info_Str (String (Time_Stamp (Sind)));
1464                Write_Info_Char (' ');
1465                Write_Info_Str (Get_Hex_String (Source_Checksum (Sind)));
1466 
1467                --  If the dependency comes from a limited_with clause, record
1468                --  limited_checksum. This is disabled until full checksum
1469                --  changes are checked.
1470 
1471                --  if Present (Cunit_Entity (Unum))
1472                --    and then From_Limited_With (Cunit_Entity (Unum))
1473                --  then
1474                --     Write_Info_Char (' ');
1475                --     Write_Info_Char ('Y');
1476                --     Write_Info_Str (Get_Hex_String (Limited_Chk_Sum (Sind)));
1477                --  end if;
1478 
1479                --  If subunit, add unit name, omitting the %b at the end
1480 
1481                if Present (Cunit (Unum)) then
1482                   Get_Decoded_Name_String (Unit_Name (Unum));
1483                   Write_Info_Char (' ');
1484 
1485                   if Nkind (Unit (Cunit (Unum))) = N_Subunit then
1486                      Write_Info_Str (Name_Buffer (1 .. Name_Len - 2));
1487                   else
1488                      Write_Info_Str (Name_Buffer (1 .. Name_Len));
1489                   end if;
1490                end if;
1491 
1492                --  If Source_Reference pragma used, output information
1493 
1494                if Num_SRef_Pragmas (Sind) > 0 then
1495                   Write_Info_Char (' ');
1496 
1497                   if Num_SRef_Pragmas (Sind) = 1 then
1498                      Write_Info_Nat (Int (First_Mapped_Line (Sind)));
1499                   else
1500                      Write_Info_Nat (0);
1501                   end if;
1502 
1503                   Write_Info_Char (':');
1504                   Write_Info_Name (Reference_Name (Sind));
1505                end if;
1506 
1507                --  Case where there is no source index (happens for missing
1508                --  files). In this case we write a dummy time stamp.
1509 
1510             else
1511                Write_Info_Name (Unit_File_Name (Unum));
1512                Write_Info_Tab (25);
1513                Write_Info_Str (String (Dummy_Time_Stamp));
1514                Write_Info_Char (' ');
1515                Write_Info_Str (Get_Hex_String (0));
1516             end if;
1517 
1518             Write_Info_EOL;
1519 
1520          <<Next_Unit>>
1521             null;
1522          end loop;
1523       end;
1524 
1525       --  Output cross-references
1526 
1527       if Opt.Xref_Active then
1528          Output_References;
1529       end if;
1530 
1531       --  Output SCO information if present
1532 
1533       if Generate_SCO then
1534          SCO_Record_Filtered;
1535          SCO_Output;
1536       end if;
1537 
1538       --  Output SPARK cross-reference information if needed
1539 
1540       if Opt.Xref_Active and then GNATprove_Mode then
1541          SPARK_Specific.Collect_SPARK_Xrefs (Sdep_Table => Sdep_Table,
1542                                              Num_Sdep   => Num_Sdep);
1543          SPARK_Specific.Output_SPARK_Xrefs;
1544       end if;
1545 
1546       --  Output final blank line and we are done. This final blank line is
1547       --  probably junk, but we don't feel like making an incompatible change.
1548 
1549       Write_Info_Terminate;
1550       Close_Output_Library_Info;
1551    end Write_ALI;
1552 
1553    ---------------------
1554    -- Write_Unit_Name --
1555    ---------------------
1556 
1557    procedure Write_Unit_Name (N : Node_Id) is
1558    begin
1559       if Nkind (N) = N_Identifier then
1560          Write_Info_Name (Chars (N));
1561 
1562       else
1563          pragma Assert (Nkind (N) = N_Selected_Component);
1564          Write_Unit_Name (Prefix (N));
1565          Write_Info_Char ('.');
1566          Write_Unit_Name (Selector_Name (N));
1567       end if;
1568    end Write_Unit_Name;
1569 
1570 end Lib.Writ;