File : gnatlink.adb


   1 ------------------------------------------------------------------------------
   2 --                                                                          --
   3 --                         GNAT COMPILER COMPONENTS                         --
   4 --                                                                          --
   5 --                             G N A T L I N K                              --
   6 --                                                                          --
   7 --                                 B o d y                                  --
   8 --                                                                          --
   9 --          Copyright (C) 1996-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 --  Gnatlink usage: please consult the gnat documentation
  27 
  28 with ALI;      use ALI;
  29 with Csets;
  30 with Gnatvsn;  use Gnatvsn;
  31 with Indepsw;  use Indepsw;
  32 with Namet;    use Namet;
  33 with Opt;
  34 with Osint;    use Osint;
  35 with Output;   use Output;
  36 with Snames;
  37 with Switch;   use Switch;
  38 with System;   use System;
  39 with Table;
  40 with Targparm; use Targparm;
  41 with Types;
  42 
  43 with Ada.Command_Line; use Ada.Command_Line;
  44 with Ada.Exceptions;   use Ada.Exceptions;
  45 
  46 with System.OS_Lib; use System.OS_Lib;
  47 with System.CRTL;
  48 
  49 with Interfaces.C_Streams; use Interfaces.C_Streams;
  50 with Interfaces.C.Strings; use Interfaces.C.Strings;
  51 
  52 procedure Gnatlink is
  53    pragma Ident (Gnatvsn.Gnat_Static_Version_String);
  54 
  55    Shared_Libgcc_String : constant String := "-shared-libgcc";
  56    Shared_Libgcc        : constant String_Access :=
  57                             new String'(Shared_Libgcc_String);
  58    --  Used to invoke gcc when the binder is invoked with -shared
  59 
  60    Static_Libgcc_String : constant String := "-static-libgcc";
  61    Static_Libgcc        : constant String_Access :=
  62                             new String'(Static_Libgcc_String);
  63    --  Used to invoke gcc when shared libs are not used
  64 
  65    package Gcc_Linker_Options is new Table.Table (
  66      Table_Component_Type => String_Access,
  67      Table_Index_Type     => Integer,
  68      Table_Low_Bound      => 1,
  69      Table_Initial        => 20,
  70      Table_Increment      => 100,
  71      Table_Name           => "Gnatlink.Gcc_Linker_Options");
  72    --  Comments needed ???
  73 
  74    package Libpath is new Table.Table (
  75      Table_Component_Type => Character,
  76      Table_Index_Type     => Integer,
  77      Table_Low_Bound      => 1,
  78      Table_Initial        => 4096,
  79      Table_Increment      => 100,
  80      Table_Name           => "Gnatlink.Libpath");
  81    --  Comments needed ???
  82 
  83    package Linker_Options is new Table.Table (
  84      Table_Component_Type => String_Access,
  85      Table_Index_Type     => Integer,
  86      Table_Low_Bound      => 1,
  87      Table_Initial        => 20,
  88      Table_Increment      => 100,
  89      Table_Name           => "Gnatlink.Linker_Options");
  90    --  Comments needed ???
  91 
  92    package Linker_Objects is new Table.Table (
  93      Table_Component_Type => String_Access,
  94      Table_Index_Type     => Integer,
  95      Table_Low_Bound      => 1,
  96      Table_Initial        => 20,
  97      Table_Increment      => 100,
  98      Table_Name           => "Gnatlink.Linker_Objects");
  99    --  This table collects the objects file to be passed to the linker. In the
 100    --  case where the linker command line is too long then programs objects
 101    --  are put on the Response_File_Objects table. Note that the binder object
 102    --  file and the user's objects remain in this table. This is very
 103    --  important because on the GNU linker command line the -L switch is not
 104    --  used to look for objects files but -L switch is used to look for
 105    --  objects listed in the response file. This is not a problem with the
 106    --  applications objects as they are specified with a full name.
 107 
 108    package Response_File_Objects is new Table.Table (
 109      Table_Component_Type => String_Access,
 110      Table_Index_Type     => Integer,
 111      Table_Low_Bound      => 1,
 112      Table_Initial        => 20,
 113      Table_Increment      => 100,
 114      Table_Name           => "Gnatlink.Response_File_Objects");
 115    --  This table collects the objects file that are to be put in the response
 116    --  file. Only application objects are collected there (see details in
 117    --  Linker_Objects table comments)
 118 
 119    package Binder_Options_From_ALI is new Table.Table (
 120      Table_Component_Type => String_Access,
 121      Table_Index_Type     => Integer,
 122      Table_Low_Bound      => 1, -- equals low bound of Argument_List for Spawn
 123      Table_Initial        => 20,
 124      Table_Increment      => 100,
 125      Table_Name           => "Gnatlink.Binder_Options_From_ALI");
 126    --  This table collects the switches from the ALI file of the main
 127    --  subprogram.
 128 
 129    package Binder_Options is new Table.Table (
 130      Table_Component_Type => String_Access,
 131      Table_Index_Type     => Integer,
 132      Table_Low_Bound      => 1, -- equals low bound of Argument_List for Spawn
 133      Table_Initial        => 20,
 134      Table_Increment      => 100,
 135      Table_Name           => "Gnatlink.Binder_Options");
 136    --  This table collects the arguments to be passed to compile the binder
 137    --  generated file.
 138 
 139    Gcc : String_Access := Program_Name ("gcc", "gnatlink");
 140 
 141    Read_Mode : constant String := "r" & ASCII.NUL;
 142 
 143    Begin_Info : constant String := "--  BEGIN Object file/option list";
 144    End_Info   : constant String := "--  END Object file/option list   ";
 145 
 146    Gcc_Path             : String_Access;
 147    Linker_Path          : String_Access;
 148    Output_File_Name     : String_Access;
 149    Ali_File_Name        : String_Access;
 150    Binder_Spec_Src_File : String_Access;
 151    Binder_Body_Src_File : String_Access;
 152    Binder_Ali_File      : String_Access;
 153    Binder_Obj_File      : String_Access;
 154 
 155    Base_Command_Name    : String_Access;
 156 
 157    Target_Debuggable_Suffix : String_Access;
 158 
 159    Tname    : Temp_File_Name;
 160    Tname_FD : File_Descriptor := Invalid_FD;
 161    --  Temporary file used by linker to pass list of object files on
 162    --  certain systems with limitations on size of arguments.
 163 
 164    Debug_Flag_Present : Boolean := False;
 165    Verbose_Mode       : Boolean := False;
 166    Very_Verbose_Mode  : Boolean := False;
 167 
 168    Standard_Gcc : Boolean := True;
 169 
 170    Compile_Bind_File : Boolean := True;
 171    --  Set to False if bind file is not to be compiled
 172 
 173    Create_Map_File : Boolean := False;
 174    --  Set to True by switch -M. The map file name is derived from
 175    --  the ALI file name (mainprog.ali => mainprog.map).
 176 
 177    Object_List_File_Supported : Boolean;
 178    for Object_List_File_Supported'Size use Character'Size;
 179    pragma Import
 180      (C, Object_List_File_Supported, "__gnat_objlist_file_supported");
 181    --  Predicate indicating whether the linker has an option whereby the
 182    --  names of object files can be passed to the linker in a file.
 183 
 184    Object_File_Option_Ptr : Interfaces.C.Strings.chars_ptr;
 185    pragma Import (C, Object_File_Option_Ptr, "__gnat_object_file_option");
 186    --  Pointer to a string representing the linker option which specifies
 187    --  the response file.
 188 
 189    Object_File_Option : constant String := Value (Object_File_Option_Ptr);
 190    --  The linker option which specifies the response file as a string
 191 
 192    Using_GNU_response_file : constant Boolean :=
 193      Object_File_Option'Length > 0
 194        and then Object_File_Option (Object_File_Option'Last) = '@';
 195    --  Whether a GNU response file is used
 196 
 197    Object_List_File_Required : Boolean := False;
 198    --  Set to True to force generation of a response file
 199 
 200    Shared_Libgcc_Default : Character;
 201    for Shared_Libgcc_Default'Size use Character'Size;
 202    pragma Import
 203      (C, Shared_Libgcc_Default, "__gnat_shared_libgcc_default");
 204    --  Indicates wether libgcc should be statically linked (use 'T') or
 205    --  dynamically linked (use 'H') by default.
 206 
 207    function Base_Name (File_Name : String) return String;
 208    --  Return just the file name part without the extension (if present)
 209 
 210    procedure Check_Existing_Executable (File_Name : String);
 211    --  Delete any existing executable to avoid accidentally updating the target
 212    --  of a symbolic link, but produce a Fatail_Error if File_Name matches any
 213    --  of the source file names. This avoids overwriting of extensionless
 214    --  source files by accident on systems where executables do not have
 215    --  extensions.
 216 
 217    procedure Delete (Name : String);
 218    --  Wrapper to unlink as status is ignored by this application
 219 
 220    procedure Error_Msg (Message : String);
 221    --  Output the error or warning Message
 222 
 223    procedure Exit_With_Error (Error : String);
 224    --  Output Error and exit program with a fatal condition
 225 
 226    procedure Process_Args;
 227    --  Go through all the arguments and build option tables
 228 
 229    procedure Process_Binder_File (Name : String);
 230    --  Reads the binder file and extracts linker arguments
 231 
 232    procedure Usage;
 233    --  Display usage
 234 
 235    procedure Write_Header;
 236    --  Show user the program name, version and copyright
 237 
 238    procedure Write_Usage;
 239    --  Show user the program options
 240 
 241    ---------------
 242    -- Base_Name --
 243    ---------------
 244 
 245    function Base_Name (File_Name : String) return String is
 246       Findex1 : Natural;
 247       Findex2 : Natural;
 248 
 249    begin
 250       Findex1 := File_Name'First;
 251 
 252       --  The file might be specified by a full path name. However,
 253       --  we want the path to be stripped away.
 254 
 255       for J in reverse File_Name'Range loop
 256          if Is_Directory_Separator (File_Name (J)) then
 257             Findex1 := J + 1;
 258             exit;
 259          end if;
 260       end loop;
 261 
 262       Findex2 := File_Name'Last;
 263       while Findex2 > Findex1 and then File_Name (Findex2) /=  '.' loop
 264          Findex2 := Findex2 - 1;
 265       end loop;
 266 
 267       if Findex2 = Findex1 then
 268          Findex2 := File_Name'Last + 1;
 269       end if;
 270 
 271       return File_Name (Findex1 .. Findex2 - 1);
 272    end Base_Name;
 273 
 274    -------------------------------
 275    -- Check_Existing_Executable --
 276    -------------------------------
 277 
 278    procedure Check_Existing_Executable (File_Name : String) is
 279       Ename : String := File_Name;
 280       Efile : File_Name_Type;
 281       Sfile : File_Name_Type;
 282 
 283    begin
 284       Canonical_Case_File_Name (Ename);
 285       Name_Len := 0;
 286       Add_Str_To_Name_Buffer (Ename);
 287       Efile := Name_Find;
 288 
 289       for J in Units.Table'First .. Units.Last loop
 290          Sfile := Units.Table (J).Sfile;
 291          if Sfile = Efile then
 292             Exit_With_Error
 293               ("executable name """ & File_Name & """ matches "
 294                & "source file name """ & Get_Name_String (Sfile) & """");
 295          end if;
 296       end loop;
 297 
 298       Delete (File_Name);
 299    end Check_Existing_Executable;
 300 
 301    ------------
 302    -- Delete --
 303    ------------
 304 
 305    procedure Delete (Name : String) is
 306       Status : int;
 307       pragma Unreferenced (Status);
 308    begin
 309       Status := unlink (Name'Address);
 310       --  Is it really right to ignore an error here ???
 311    end Delete;
 312 
 313    ---------------
 314    -- Error_Msg --
 315    ---------------
 316 
 317    procedure Error_Msg (Message : String) is
 318    begin
 319       Write_Str (Base_Command_Name.all);
 320       Write_Str (": ");
 321       Write_Str (Message);
 322       Write_Eol;
 323    end Error_Msg;
 324 
 325    ---------------------
 326    -- Exit_With_Error --
 327    ---------------------
 328 
 329    procedure Exit_With_Error (Error : String) is
 330    begin
 331       Error_Msg (Error);
 332       Exit_Program (E_Fatal);
 333    end Exit_With_Error;
 334 
 335    ------------------
 336    -- Process_Args --
 337    ------------------
 338 
 339    procedure Process_Args is
 340       Next_Arg : Integer;
 341 
 342       Skip_Next : Boolean := False;
 343       --  Set to true if the next argument is to be added into the list of
 344       --  linker's argument without parsing it.
 345 
 346       procedure Check_Version_And_Help is new Check_Version_And_Help_G (Usage);
 347 
 348       --  Start of processing for Process_Args
 349 
 350    begin
 351       --  First, check for --version and --help
 352 
 353       Check_Version_And_Help ("GNATLINK", "1996");
 354 
 355       --  Loop through arguments of gnatlink command
 356 
 357       Next_Arg := 1;
 358       loop
 359          exit when Next_Arg > Argument_Count;
 360 
 361          Process_One_Arg : declare
 362             Arg : constant String := Argument (Next_Arg);
 363 
 364          begin
 365             --  Case of argument which is a switch
 366 
 367             --  We definitely need section by section comments here ???
 368 
 369             if Skip_Next then
 370 
 371                --  This argument must not be parsed, just add it to the
 372                --  list of linker's options.
 373 
 374                Skip_Next := False;
 375 
 376                Linker_Options.Increment_Last;
 377                Linker_Options.Table (Linker_Options.Last) :=
 378                  new String'(Arg);
 379 
 380             elsif Arg'Length /= 0 and then Arg (1) = '-' then
 381                if Arg'Length > 4 and then Arg (2 .. 5) = "gnat" then
 382                   Exit_With_Error
 383                     ("invalid switch: """ & Arg & """ (gnat not needed here)");
 384                end if;
 385 
 386                if Arg = "-Xlinker" then
 387 
 388                   --  Next argument should be sent directly to the linker.
 389                   --  We do not want to parse it here.
 390 
 391                   Skip_Next := True;
 392 
 393                   Linker_Options.Increment_Last;
 394                   Linker_Options.Table (Linker_Options.Last) :=
 395                     new String'(Arg);
 396 
 397                elsif Arg (2) = 'g'
 398                  and then (Arg'Length < 5 or else Arg (2 .. 5) /= "gnat")
 399                then
 400                   Debug_Flag_Present := True;
 401 
 402                   Linker_Options.Increment_Last;
 403                   Linker_Options.Table (Linker_Options.Last) :=
 404                    new String'(Arg);
 405 
 406                   Binder_Options.Increment_Last;
 407                   Binder_Options.Table (Binder_Options.Last) :=
 408                     Linker_Options.Table (Linker_Options.Last);
 409 
 410                elsif Arg'Length >= 3 and then Arg (2) = 'M' then
 411                   declare
 412                      Switches : String_List_Access;
 413 
 414                   begin
 415                      Convert (Map_File, Arg (3 .. Arg'Last), Switches);
 416 
 417                      if Switches /= null then
 418                         for J in Switches'Range loop
 419                            Linker_Options.Increment_Last;
 420                            Linker_Options.Table (Linker_Options.Last) :=
 421                              Switches (J);
 422                         end loop;
 423                      end if;
 424                   end;
 425 
 426                elsif Arg'Length = 2 then
 427                   case Arg (2) is
 428                      when 'b' =>
 429                         Linker_Options.Increment_Last;
 430                         Linker_Options.Table (Linker_Options.Last) :=
 431                           new String'(Arg);
 432 
 433                         Binder_Options.Increment_Last;
 434                         Binder_Options.Table (Binder_Options.Last) :=
 435                           Linker_Options.Table (Linker_Options.Last);
 436 
 437                         Next_Arg := Next_Arg + 1;
 438 
 439                         if Next_Arg > Argument_Count then
 440                            Exit_With_Error ("Missing argument for -b");
 441                         end if;
 442 
 443                         Get_Machine_Name : declare
 444                            Name_Arg : constant String_Access :=
 445                                         new String'(Argument (Next_Arg));
 446 
 447                         begin
 448                            Linker_Options.Increment_Last;
 449                            Linker_Options.Table (Linker_Options.Last) :=
 450                              Name_Arg;
 451 
 452                            Binder_Options.Increment_Last;
 453                            Binder_Options.Table (Binder_Options.Last) :=
 454                              Name_Arg;
 455 
 456                         end Get_Machine_Name;
 457 
 458                      when 'f' =>
 459                         if Object_List_File_Supported then
 460                            Object_List_File_Required := True;
 461                         else
 462                            Exit_With_Error
 463                              ("Object list file not supported on this target");
 464                         end if;
 465 
 466                      when 'M' =>
 467                         Create_Map_File := True;
 468 
 469                      when 'n' =>
 470                         Compile_Bind_File := False;
 471 
 472                      when 'o' =>
 473                         Next_Arg := Next_Arg + 1;
 474 
 475                         if Next_Arg > Argument_Count then
 476                            Exit_With_Error ("Missing argument for -o");
 477                         end if;
 478 
 479                         Output_File_Name :=
 480                           new String'(Executable_Name
 481                                         (Argument (Next_Arg),
 482                                          Only_If_No_Suffix => True));
 483 
 484                      when 'P' =>
 485                         Opt.CodePeer_Mode := True;
 486 
 487                      when 'R' =>
 488                         Opt.Run_Path_Option := False;
 489 
 490                      when 'v' =>
 491 
 492                         --  Support "double" verbose mode.  Second -v
 493                         --  gets sent to the linker and binder phases.
 494 
 495                         if Verbose_Mode then
 496                            Very_Verbose_Mode := True;
 497 
 498                            Linker_Options.Increment_Last;
 499                            Linker_Options.Table (Linker_Options.Last) :=
 500                             new String'(Arg);
 501 
 502                            Binder_Options.Increment_Last;
 503                            Binder_Options.Table (Binder_Options.Last) :=
 504                              Linker_Options.Table (Linker_Options.Last);
 505 
 506                         else
 507                            Verbose_Mode := True;
 508 
 509                         end if;
 510 
 511                      when others =>
 512                         Linker_Options.Increment_Last;
 513                         Linker_Options.Table (Linker_Options.Last) :=
 514                          new String'(Arg);
 515 
 516                   end case;
 517 
 518                elsif Arg (2) = 'B' then
 519                   Linker_Options.Increment_Last;
 520                   Linker_Options.Table (Linker_Options.Last) :=
 521                     new String'(Arg);
 522 
 523                   Binder_Options.Increment_Last;
 524                   Binder_Options.Table (Binder_Options.Last) :=
 525                     Linker_Options.Table (Linker_Options.Last);
 526 
 527                elsif Arg'Length >= 7 and then Arg (1 .. 7) = "--LINK=" then
 528                   if Arg'Length = 7 then
 529                      Exit_With_Error ("Missing argument for --LINK=");
 530                   end if;
 531 
 532                   Linker_Path :=
 533                     System.OS_Lib.Locate_Exec_On_Path (Arg (8 .. Arg'Last));
 534 
 535                   if Linker_Path = null then
 536                      Exit_With_Error
 537                        ("Could not locate linker: " & Arg (8 .. Arg'Last));
 538                   end if;
 539 
 540                elsif Arg'Length > 6 and then Arg (1 .. 6) = "--GCC=" then
 541                   declare
 542                      Program_Args : constant Argument_List_Access :=
 543                                       Argument_String_To_List
 544                                                  (Arg (7 .. Arg'Last));
 545 
 546                   begin
 547                      if Program_Args.all (1).all /= Gcc.all then
 548                         Gcc := new String'(Program_Args.all (1).all);
 549                         Standard_Gcc := False;
 550                      end if;
 551 
 552                      --  Set appropriate flags for switches passed
 553 
 554                      for J in 2 .. Program_Args.all'Last loop
 555                         declare
 556                            Arg : constant String := Program_Args.all (J).all;
 557                            AF  : constant Integer := Arg'First;
 558 
 559                         begin
 560                            if Arg'Length /= 0 and then Arg (AF) = '-' then
 561                               if Arg (AF + 1) = 'g'
 562                                 and then (Arg'Length = 2
 563                                   or else Arg (AF + 2) in '0' .. '3'
 564                                   or else Arg (AF + 2 .. Arg'Last) = "coff")
 565                               then
 566                                  Debug_Flag_Present := True;
 567                               end if;
 568                            end if;
 569 
 570                            --  Add directory to source search dirs so that
 571                            --  Get_Target_Parameters can find system.ads
 572 
 573                            if Arg (AF .. AF + 1) = "-I"
 574                              and then Arg'Length > 2
 575                            then
 576                               Add_Src_Search_Dir (Arg (AF + 2 .. Arg'Last));
 577                            end if;
 578 
 579                            --  Pass to gcc for compiling binder generated file
 580                            --  No use passing libraries, it will just generate
 581                            --  a warning
 582 
 583                            if not (Arg (AF .. AF + 1) = "-l"
 584                              or else Arg (AF .. AF + 1) = "-L")
 585                            then
 586                               Binder_Options.Increment_Last;
 587                               Binder_Options.Table (Binder_Options.Last) :=
 588                                 new String'(Arg);
 589                            end if;
 590 
 591                            --  Pass to gcc for linking program
 592 
 593                            Gcc_Linker_Options.Increment_Last;
 594                            Gcc_Linker_Options.Table
 595                              (Gcc_Linker_Options.Last) := new String'(Arg);
 596                         end;
 597                      end loop;
 598                   end;
 599 
 600                --  Send all multi-character switches not recognized as
 601                --  a special case by gnatlink to the linker/loader stage.
 602 
 603                else
 604                   Linker_Options.Increment_Last;
 605                   Linker_Options.Table (Linker_Options.Last) :=
 606                     new String'(Arg);
 607                end if;
 608 
 609             --  Here if argument is a file name rather than a switch
 610 
 611             else
 612                --  If explicit ali file, capture it
 613 
 614                if Arg'Length > 4
 615                  and then Arg (Arg'Last - 3 .. Arg'Last) = ".ali"
 616                then
 617                   if Ali_File_Name = null then
 618                      Ali_File_Name := new String'(Arg);
 619                   else
 620                      Exit_With_Error ("cannot handle more than one ALI file");
 621                   end if;
 622 
 623                --  If target object file, record object file
 624 
 625                elsif Arg'Length > Get_Target_Object_Suffix.all'Length
 626                  and then Arg
 627                    (Arg'Last -
 628                     Get_Target_Object_Suffix.all'Length + 1 .. Arg'Last)
 629                    = Get_Target_Object_Suffix.all
 630                then
 631                   Linker_Objects.Increment_Last;
 632                   Linker_Objects.Table (Linker_Objects.Last) :=
 633                     new String'(Arg);
 634 
 635                --  If host object file, record object file
 636 
 637                elsif Arg'Length > Get_Object_Suffix.all'Length
 638                  and then Arg
 639                    (Arg'Last - Get_Object_Suffix.all'Length + 1 .. Arg'Last)
 640                                                 = Get_Object_Suffix.all
 641                then
 642                   Linker_Objects.Increment_Last;
 643                   Linker_Objects.Table (Linker_Objects.Last) :=
 644                     new String'(Arg);
 645 
 646                --  If corresponding ali file exists, capture it
 647 
 648                elsif Ali_File_Name = null
 649                  and then Is_Regular_File (Arg & ".ali")
 650                then
 651                   Ali_File_Name := new String'(Arg & ".ali");
 652 
 653                --  Otherwise assume this is a linker options entry, but
 654                --  see below for interesting adjustment to this assumption.
 655 
 656                else
 657                   Linker_Options.Increment_Last;
 658                   Linker_Options.Table (Linker_Options.Last) :=
 659                     new String'(Arg);
 660                end if;
 661             end if;
 662          end Process_One_Arg;
 663 
 664          Next_Arg := Next_Arg + 1;
 665       end loop;
 666 
 667       --  Compile the bind file with warnings suppressed, because
 668       --  otherwise the with of the main program may cause junk warnings.
 669 
 670       Binder_Options.Increment_Last;
 671       Binder_Options.Table (Binder_Options.Last) := new String'("-gnatws");
 672 
 673       --  If we did not get an ali file at all, and we had at least one
 674       --  linker option, then assume that was the intended ali file after
 675       --  all, so that we get a nicer message later on.
 676 
 677       if Ali_File_Name = null
 678         and then Linker_Options.Last >= Linker_Options.First
 679       then
 680          Ali_File_Name :=
 681            new String'(Linker_Options.Table (Linker_Options.First).all
 682                        & ".ali");
 683       end if;
 684    end Process_Args;
 685 
 686    -------------------------
 687    -- Process_Binder_File --
 688    -------------------------
 689 
 690    procedure Process_Binder_File (Name : String) is
 691       Fd : FILEs;
 692       --  Binder file's descriptor
 693 
 694       Link_Bytes : Integer := 0;
 695       --  Projected number of bytes for the linker command line
 696 
 697       Link_Max : Integer;
 698       pragma Import (C, Link_Max, "__gnat_link_max");
 699       --  Maximum number of bytes on the command line supported by the OS
 700       --  linker. Passed this limit the response file mechanism must be used
 701       --  if supported.
 702 
 703       Next_Line : String (1 .. 1000);
 704       --  Current line value
 705 
 706       Nlast  : Integer;
 707       Nfirst : Integer;
 708       --  Current line slice (the slice does not contain line terminator)
 709 
 710       Last : Integer;
 711       --  Current line last character for shared libraries (without version)
 712 
 713       Objs_Begin : Integer := 0;
 714       --  First object file index in Linker_Objects table
 715 
 716       Objs_End : Integer := 0;
 717       --  Last object file index in Linker_Objects table
 718 
 719       Status : int;
 720       pragma Warnings (Off, Status);
 721       --  Used for various Interfaces.C_Streams calls
 722 
 723       Closing_Status : Boolean;
 724       pragma Warnings (Off, Closing_Status);
 725       --  For call to Close
 726 
 727       GNAT_Static : Boolean := False;
 728       --  Save state of -static option
 729 
 730       GNAT_Shared : Boolean := False;
 731       --  Save state of -shared option
 732 
 733       Xlinker_Was_Previous : Boolean := False;
 734       --  Indicate that "-Xlinker" was the option preceding the current option.
 735       --  If True, then the current option is never suppressed.
 736 
 737       --  Rollback data
 738 
 739       --  These data items are used to store current binder file context. The
 740       --  context is composed of the file descriptor position and the current
 741       --  line together with the slice indexes (first and last position) for
 742       --  this line. The rollback data are used by the Store_File_Context and
 743       --  Rollback_File_Context routines below. The file context mechanism
 744       --  interact only with the Get_Next_Line call. For example:
 745 
 746       --     Store_File_Context;
 747       --     Get_Next_Line;
 748       --     Rollback_File_Context;
 749       --     Get_Next_Line;
 750 
 751       --  Both Get_Next_Line calls above will read the exact same data from
 752       --  the file. In other words, Next_Line, Nfirst and Nlast variables
 753       --  will be set with the exact same values.
 754 
 755       RB_File_Pos  : long;                -- File position
 756       RB_Next_Line : String (1 .. 1000);  -- Current line content
 757       RB_Nlast     : Integer;             -- Slice last index
 758       RB_Nfirst    : Integer;             -- Slice first index
 759 
 760       Run_Path_Option_Ptr : Interfaces.C.Strings.chars_ptr;
 761       pragma Import (C, Run_Path_Option_Ptr, "__gnat_run_path_option");
 762       --  Pointer to string representing the native linker option which
 763       --  specifies the path where the dynamic loader should find shared
 764       --  libraries. Equal to null string if this system doesn't support it.
 765 
 766       Libgcc_Subdir_Ptr : Interfaces.C.Strings.chars_ptr;
 767       pragma Import (C, Libgcc_Subdir_Ptr, "__gnat_default_libgcc_subdir");
 768       --  Pointer to string indicating the installation subdirectory where
 769       --  a default shared libgcc might be found.
 770 
 771       Object_Library_Ext_Ptr : Interfaces.C.Strings.chars_ptr;
 772       pragma Import
 773         (C, Object_Library_Ext_Ptr, "__gnat_object_library_extension");
 774       --  Pointer to string specifying the default extension for
 775       --  object libraries, e.g. Unix uses ".a".
 776 
 777       Separate_Run_Path_Options : Boolean;
 778       for Separate_Run_Path_Options'Size use Character'Size;
 779       pragma Import
 780         (C, Separate_Run_Path_Options, "__gnat_separate_run_path_options");
 781       --  Whether separate rpath options should be emitted for each directory
 782 
 783       procedure Get_Next_Line;
 784       --  Read the next line from the binder file without the line
 785       --  terminator.
 786 
 787       function Index (S, Pattern : String) return Natural;
 788       --  Return the last occurrence of Pattern in S, or 0 if none
 789 
 790       procedure Store_File_Context;
 791       --  Store current file context, Fd position and current line data.
 792       --  The file context is stored into the rollback data above (RB_*).
 793       --  Store_File_Context can be called at any time, only the last call
 794       --  will be used (i.e. this routine overwrites the file context).
 795 
 796       procedure Rollback_File_Context;
 797       --  Restore file context from rollback data. This routine must be called
 798       --  after Store_File_Context. The binder file context will be restored
 799       --  with the data stored by the last Store_File_Context call.
 800 
 801       procedure Write_RF (S : String);
 802       --  Write a string to the response file and check if it was successful.
 803       --  Fail the program if it was not successful (disk full).
 804 
 805       -------------------
 806       -- Get_Next_Line --
 807       -------------------
 808 
 809       procedure Get_Next_Line is
 810          Fchars : chars;
 811 
 812       begin
 813          Fchars := fgets (Next_Line'Address, Next_Line'Length, Fd);
 814 
 815          if Fchars = System.Null_Address then
 816             Exit_With_Error ("Error reading binder output");
 817          end if;
 818 
 819          Nfirst := Next_Line'First;
 820          Nlast := Nfirst;
 821          while Nlast <= Next_Line'Last
 822            and then Next_Line (Nlast) /= ASCII.LF
 823            and then Next_Line (Nlast) /= ASCII.CR
 824          loop
 825             Nlast := Nlast + 1;
 826          end loop;
 827 
 828          Nlast := Nlast - 1;
 829       end Get_Next_Line;
 830 
 831       -----------
 832       -- Index --
 833       -----------
 834 
 835       function Index (S, Pattern : String) return Natural is
 836          Len : constant Natural := Pattern'Length;
 837 
 838       begin
 839          for J in reverse S'First .. S'Last - Len + 1 loop
 840             if Pattern = S (J .. J + Len - 1) then
 841                return J;
 842             end if;
 843          end loop;
 844 
 845          return 0;
 846       end Index;
 847 
 848       ---------------------------
 849       -- Rollback_File_Context --
 850       ---------------------------
 851 
 852       procedure Rollback_File_Context is
 853       begin
 854          Next_Line := RB_Next_Line;
 855          Nfirst    := RB_Nfirst;
 856          Nlast     := RB_Nlast;
 857          Status    := fseek (Fd, RB_File_Pos, Interfaces.C_Streams.SEEK_SET);
 858 
 859          if Status = -1 then
 860             Exit_With_Error ("Error setting file position");
 861          end if;
 862       end Rollback_File_Context;
 863 
 864       ------------------------
 865       -- Store_File_Context --
 866       ------------------------
 867 
 868       procedure Store_File_Context is
 869          use type System.CRTL.long;
 870 
 871       begin
 872          RB_Next_Line := Next_Line;
 873          RB_Nfirst    := Nfirst;
 874          RB_Nlast     := Nlast;
 875          RB_File_Pos  := ftell (Fd);
 876 
 877          if RB_File_Pos = -1 then
 878             Exit_With_Error ("Error getting file position");
 879          end if;
 880       end Store_File_Context;
 881 
 882       --------------
 883       -- Write_RF --
 884       --------------
 885 
 886       procedure Write_RF (S : String) is
 887          Success    : Boolean            := True;
 888          Back_Slash : constant Character := '\';
 889 
 890       begin
 891          --  If a GNU response file is used, space and backslash need to be
 892          --  escaped because they are interpreted as a string separator and
 893          --  an escape character respectively by the underlying mechanism.
 894          --  On the other hand, quote and double-quote are not escaped since
 895          --  they are interpreted as string delimiters on both sides.
 896 
 897          if Using_GNU_response_file then
 898             for J in S'Range loop
 899                if S (J) = ' ' or else S (J) = '\' then
 900                   if Write (Tname_FD, Back_Slash'Address, 1) /= 1 then
 901                      Success := False;
 902                   end if;
 903                end if;
 904 
 905                if Write (Tname_FD, S (J)'Address, 1) /= 1 then
 906                   Success := False;
 907                end if;
 908             end loop;
 909 
 910          else
 911             if Write (Tname_FD, S'Address, S'Length) /= S'Length then
 912                Success := False;
 913             end if;
 914          end if;
 915 
 916          if Write (Tname_FD, ASCII.LF'Address, 1) /= 1 then
 917             Success := False;
 918          end if;
 919 
 920          if not Success then
 921             Exit_With_Error ("Error generating response file: disk full");
 922          end if;
 923       end Write_RF;
 924 
 925    --  Start of processing for Process_Binder_File
 926 
 927    begin
 928       Fd := fopen (Name'Address, Read_Mode'Address);
 929 
 930       if Fd = NULL_Stream then
 931          Exit_With_Error ("Failed to open binder output");
 932       end if;
 933 
 934       --  Skip up to the Begin Info line
 935 
 936       loop
 937          Get_Next_Line;
 938          exit when Next_Line (Nfirst .. Nlast) = Begin_Info;
 939       end loop;
 940 
 941       loop
 942          Get_Next_Line;
 943 
 944          --  Go to end when end line is reached (this will happen in
 945          --  High_Integrity_Mode where no -L switches are generated)
 946 
 947          exit when Next_Line (Nfirst .. Nlast) = End_Info;
 948 
 949          Next_Line (Nfirst .. Nlast - 8) := Next_Line (Nfirst + 8 .. Nlast);
 950          Nlast := Nlast - 8;
 951 
 952          --  Go to next section when switches are reached
 953 
 954          exit when Next_Line (1) = '-';
 955 
 956          --  Otherwise we have another object file to collect
 957 
 958          Linker_Objects.Increment_Last;
 959 
 960          --  Mark the positions of first and last object files in case they
 961          --  need to be placed with a named file on systems having linker
 962          --  line limitations.
 963 
 964          if Objs_Begin = 0 then
 965             Objs_Begin := Linker_Objects.Last;
 966          end if;
 967 
 968          Linker_Objects.Table (Linker_Objects.Last) :=
 969            new String'(Next_Line (Nfirst .. Nlast));
 970 
 971          --  Nlast - Nfirst + 1, for the size, plus one for the space between
 972          --  each arguments.
 973 
 974          Link_Bytes := Link_Bytes + Nlast - Nfirst + 2;
 975       end loop;
 976 
 977       Objs_End := Linker_Objects.Last;
 978 
 979       --  Continue to compute the Link_Bytes, the linker options are part of
 980       --  command line length.
 981 
 982       Store_File_Context;
 983 
 984       while Next_Line (Nfirst .. Nlast) /= End_Info loop
 985          Link_Bytes := Link_Bytes + Nlast - Nfirst + 2;
 986          Get_Next_Line;
 987       end loop;
 988 
 989       Rollback_File_Context;
 990 
 991       --  On systems that have limitations on handling very long linker lines
 992       --  we make use of the system linker option which takes a list of object
 993       --  file names from a file instead of the command line itself. What we do
 994       --  is to replace the list of object files by the special linker option
 995       --  which then reads the object file list from a file instead. The option
 996       --  to read from a file instead of the command line is only triggered if
 997       --  a conservative threshold is passed.
 998 
 999       if Object_List_File_Required
1000         or else (Object_List_File_Supported
1001                    and then Link_Bytes > Link_Max)
1002       then
1003          --  Create a temporary file containing the Ada user object files
1004          --  needed by the link. This list is taken from the bind file and is
1005          --  output one object per line for maximal compatibility with linkers
1006          --  supporting this option.
1007 
1008          Create_Temp_File (Tname_FD, Tname);
1009 
1010          --  ??? File descriptor should be checked to not be Invalid_FD.
1011          --  ??? Status of Write and Close operations should be checked, and
1012          --  failure should occur if a status is wrong.
1013 
1014          for J in Objs_Begin .. Objs_End loop
1015             Write_RF (Linker_Objects.Table (J).all);
1016 
1017             Response_File_Objects.Increment_Last;
1018             Response_File_Objects.Table (Response_File_Objects.Last) :=
1019               Linker_Objects.Table (J);
1020          end loop;
1021 
1022          Close (Tname_FD, Closing_Status);
1023 
1024          --  Add the special objects list file option together with the name
1025          --  of the temporary file (removing the null character) to the objects
1026          --  file table.
1027 
1028          Linker_Objects.Table (Objs_Begin) :=
1029            new String'(Object_File_Option &
1030                        Tname (Tname'First .. Tname'Last - 1));
1031 
1032          --  The slots containing these object file names are then removed
1033          --  from the objects table so they do not appear in the link. They are
1034          --  removed by moving up the linker options and non-Ada object files
1035          --  appearing after the Ada object list in the table.
1036 
1037          declare
1038             N : Integer;
1039 
1040          begin
1041             N := Objs_End - Objs_Begin + 1;
1042 
1043             for J in Objs_End + 1 .. Linker_Objects.Last loop
1044                Linker_Objects.Table (J - N + 1) := Linker_Objects.Table (J);
1045             end loop;
1046 
1047             Linker_Objects.Set_Last (Linker_Objects.Last - N + 1);
1048          end;
1049       end if;
1050 
1051       --  Process switches and options
1052 
1053       if Next_Line (Nfirst .. Nlast) /= End_Info then
1054          Xlinker_Was_Previous := False;
1055 
1056          loop
1057             if Xlinker_Was_Previous
1058               or else Next_Line (Nfirst .. Nlast) = "-Xlinker"
1059             then
1060                Linker_Options.Increment_Last;
1061                Linker_Options.Table (Linker_Options.Last) :=
1062                  new String'(Next_Line (Nfirst .. Nlast));
1063 
1064             elsif Next_Line (Nfirst .. Nlast) = "-static" then
1065                GNAT_Static := True;
1066 
1067             elsif Next_Line (Nfirst .. Nlast) = "-shared" then
1068                GNAT_Shared := True;
1069 
1070             --  Add binder options only if not already set on the command line.
1071             --  This rule is a way to control the linker options order.
1072 
1073             else
1074                if Nlast > Nfirst + 2 and then
1075                  Next_Line (Nfirst .. Nfirst + 1) = "-L"
1076                then
1077                   --  Construct a library search path for use later to locate
1078                   --  static gnatlib libraries.
1079 
1080                   if Libpath.Last > 1 then
1081                      Libpath.Increment_Last;
1082                      Libpath.Table (Libpath.Last) := Path_Separator;
1083                   end if;
1084 
1085                   for I in Nfirst + 2 .. Nlast loop
1086                      Libpath.Increment_Last;
1087                      Libpath.Table (Libpath.Last) := Next_Line (I);
1088                   end loop;
1089 
1090                   Linker_Options.Increment_Last;
1091 
1092                   Linker_Options.Table (Linker_Options.Last) :=
1093                     new String'(Next_Line (Nfirst .. Nlast));
1094 
1095                elsif Next_Line (Nfirst .. Nlast) = "-lgnarl"
1096                  or else Next_Line (Nfirst .. Nlast) = "-lgnat"
1097                  or else
1098                    Next_Line
1099                      (1 .. Natural'Min (Nlast, 8 + Library_Version'Length)) =
1100                        Shared_Lib ("gnarl")
1101                  or else
1102                    Next_Line
1103                      (1 .. Natural'Min (Nlast, 7 + Library_Version'Length)) =
1104                        Shared_Lib ("gnat")
1105                then
1106                   --  If it is a shared library, remove the library version.
1107                   --  We will be looking for the static version of the library
1108                   --  as it is in the same directory as the shared version.
1109 
1110                   if Next_Line (Nlast - Library_Version'Length + 1 .. Nlast) =
1111                        Library_Version
1112                   then
1113                      --  Set Last to point to last character before the
1114                      --  library version.
1115 
1116                      Last := Nlast - Library_Version'Length - 1;
1117                   else
1118                      Last := Nlast;
1119                   end if;
1120 
1121                   --  Given a Gnat standard library, search the library path to
1122                   --  find the library location.
1123 
1124                   --  Shouldn't we abstract a proc here, we are getting awfully
1125                   --  heavily nested ???
1126 
1127                   declare
1128                      File_Path : String_Access;
1129 
1130                      Object_Lib_Extension : constant String :=
1131                        Value (Object_Library_Ext_Ptr);
1132 
1133                      File_Name : constant String := "lib" &
1134                        Next_Line (Nfirst + 2 .. Last) & Object_Lib_Extension;
1135 
1136                      Run_Path_Opt : constant String :=
1137                        Value (Run_Path_Option_Ptr);
1138 
1139                      GCC_Index          : Natural;
1140                      Run_Path_Opt_Index : Natural := 0;
1141 
1142                   begin
1143                      File_Path :=
1144                        Locate_Regular_File (File_Name,
1145                          String (Libpath.Table (1 .. Libpath.Last)));
1146 
1147                      if File_Path /= null then
1148                         if GNAT_Static then
1149 
1150                            --  If static gnatlib found, explicitly specify to
1151                            --  overcome possible linker default usage of shared
1152                            --  version.
1153 
1154                            Linker_Options.Increment_Last;
1155 
1156                            Linker_Options.Table (Linker_Options.Last) :=
1157                              new String'(File_Path.all);
1158 
1159                         elsif GNAT_Shared then
1160                            if Opt.Run_Path_Option then
1161 
1162                               --  If shared gnatlib desired, add appropriate
1163                               --  system specific switch so that it can be
1164                               --  located at runtime.
1165 
1166                               if Run_Path_Opt'Length /= 0 then
1167 
1168                                  --  Output the system specific linker command
1169                                  --  that allows the image activator to find
1170                                  --  the shared library at runtime. Also add
1171                                  --  path to find libgcc_s.so, if relevant.
1172 
1173                                  declare
1174                                     Path : String (1 .. File_Path'Length + 15);
1175 
1176                                     Path_Last : constant Natural :=
1177                                                   File_Path'Length;
1178 
1179                                  begin
1180                                     Path (1 .. File_Path'Length) :=
1181                                       File_Path.all;
1182 
1183                                  --  To find the location of the shared version
1184                                  --  of libgcc, we look for "gcc-lib" in the
1185                                  --  path of the library. However, this
1186                                  --  subdirectory is no longer present in
1187                                  --  recent versions of GCC. So, we look for
1188                                  --  the last subdirectory "lib" in the path.
1189 
1190                                     GCC_Index :=
1191                                       Index (Path (1 .. Path_Last), "gcc-lib");
1192 
1193                                     if GCC_Index /= 0 then
1194 
1195                                        --  The shared version of libgcc is
1196                                        --  located in the parent directory.
1197 
1198                                        GCC_Index := GCC_Index - 1;
1199 
1200                                     else
1201                                        GCC_Index :=
1202                                          Index
1203                                            (Path (1 .. Path_Last),
1204                                             "/lib/");
1205 
1206                                        if GCC_Index = 0 then
1207                                           GCC_Index :=
1208                                             Index (Path (1 .. Path_Last),
1209                                                    Directory_Separator & "lib"
1210                                                    & Directory_Separator);
1211                                        end if;
1212 
1213                                        --  If we have found a "lib" subdir in
1214                                        --  the path to libgnat, the possible
1215                                        --  shared libgcc of interest by default
1216                                        --  is in libgcc_subdir at the same
1217                                        --  level.
1218 
1219                                        if GCC_Index /= 0 then
1220                                           declare
1221                                              Subdir : constant String :=
1222                                                Value (Libgcc_Subdir_Ptr);
1223                                           begin
1224                                              Path
1225                                                (GCC_Index + 1 ..
1226                                                 GCC_Index + Subdir'Length) :=
1227                                                Subdir;
1228                                              GCC_Index :=
1229                                                GCC_Index + Subdir'Length;
1230                                           end;
1231                                        end if;
1232                                     end if;
1233 
1234                                  --  Look for an eventual run_path_option in
1235                                  --  the linker switches.
1236 
1237                                     if Separate_Run_Path_Options then
1238                                        Linker_Options.Increment_Last;
1239                                        Linker_Options.Table
1240                                          (Linker_Options.Last) :=
1241                                            new String'
1242                                              (Run_Path_Opt
1243                                               & File_Path
1244                                                 (1 .. File_Path'Length
1245                                                  - File_Name'Length));
1246 
1247                                        if GCC_Index /= 0 then
1248                                           Linker_Options.Increment_Last;
1249                                           Linker_Options.Table
1250                                             (Linker_Options.Last) :=
1251                                             new String'
1252                                               (Run_Path_Opt
1253                                                & Path (1 .. GCC_Index));
1254                                        end if;
1255 
1256                                     else
1257                                        for J in reverse
1258                                          1 .. Linker_Options.Last
1259                                        loop
1260                                           if Linker_Options.Table (J) /= null
1261                                             and then
1262                                               Linker_Options.Table (J)'Length
1263                                                         > Run_Path_Opt'Length
1264                                             and then
1265                                               Linker_Options.Table (J)
1266                                                 (1 .. Run_Path_Opt'Length) =
1267                                                                  Run_Path_Opt
1268                                           then
1269                                              --  We have found an already
1270                                              --  specified run_path_option:
1271                                              --  we will add to this
1272                                              --  switch, because only one
1273                                              --  run_path_option should be
1274                                              --  specified.
1275 
1276                                              Run_Path_Opt_Index := J;
1277                                              exit;
1278                                           end if;
1279                                        end loop;
1280 
1281                                        --  If there is no run_path_option, we
1282                                        --  need to add one.
1283 
1284                                        if Run_Path_Opt_Index = 0 then
1285                                           Linker_Options.Increment_Last;
1286                                        end if;
1287 
1288                                        if GCC_Index = 0 then
1289                                           if Run_Path_Opt_Index = 0 then
1290                                              Linker_Options.Table
1291                                                (Linker_Options.Last) :=
1292                                                  new String'
1293                                                    (Run_Path_Opt
1294                                                     & File_Path
1295                                                       (1 .. File_Path'Length
1296                                                        - File_Name'Length));
1297 
1298                                           else
1299                                              Linker_Options.Table
1300                                                (Run_Path_Opt_Index) :=
1301                                                  new String'
1302                                                    (Linker_Options.Table
1303                                                      (Run_Path_Opt_Index).all
1304                                                     & Path_Separator
1305                                                     & File_Path
1306                                                       (1 .. File_Path'Length
1307                                                        - File_Name'Length));
1308                                           end if;
1309 
1310                                        else
1311                                           if Run_Path_Opt_Index = 0 then
1312                                              Linker_Options.Table
1313                                                (Linker_Options.Last) :=
1314                                                  new String'
1315                                                    (Run_Path_Opt
1316                                                     & File_Path
1317                                                       (1 .. File_Path'Length
1318                                                        - File_Name'Length)
1319                                                     & Path_Separator
1320                                                     & Path (1 .. GCC_Index));
1321 
1322                                           else
1323                                              Linker_Options.Table
1324                                                (Run_Path_Opt_Index) :=
1325                                                  new String'
1326                                                    (Linker_Options.Table
1327                                                      (Run_Path_Opt_Index).all
1328                                                     & Path_Separator
1329                                                     & File_Path
1330                                                       (1 .. File_Path'Length
1331                                                        - File_Name'Length)
1332                                                     & Path_Separator
1333                                                     & Path (1 .. GCC_Index));
1334                                           end if;
1335                                        end if;
1336                                     end if;
1337                                  end;
1338                               end if;
1339                            end if;
1340 
1341                            --  Then we add the appropriate -l switch
1342 
1343                            Linker_Options.Increment_Last;
1344                            Linker_Options.Table (Linker_Options.Last) :=
1345                              new String'(Next_Line (Nfirst .. Nlast));
1346                         end if;
1347 
1348                      else
1349                         --  If gnatlib library not found, then add it anyway in
1350                         --  case some other mechanism may find it.
1351 
1352                         Linker_Options.Increment_Last;
1353                         Linker_Options.Table (Linker_Options.Last) :=
1354                           new String'(Next_Line (Nfirst .. Nlast));
1355                      end if;
1356                   end;
1357                else
1358                   Linker_Options.Increment_Last;
1359                   Linker_Options.Table (Linker_Options.Last) :=
1360                     new String'(Next_Line (Nfirst .. Nlast));
1361                end if;
1362             end if;
1363 
1364             Xlinker_Was_Previous := Next_Line (Nfirst .. Nlast) = "-Xlinker";
1365 
1366             Get_Next_Line;
1367             exit when Next_Line (Nfirst .. Nlast) = End_Info;
1368 
1369             Next_Line (Nfirst .. Nlast - 8) := Next_Line (Nfirst + 8 .. Nlast);
1370             Nlast := Nlast - 8;
1371          end loop;
1372       end if;
1373 
1374       --  If -shared was specified, invoke gcc with -shared-libgcc
1375 
1376       if GNAT_Shared then
1377          Linker_Options.Increment_Last;
1378          Linker_Options.Table (Linker_Options.Last) := Shared_Libgcc;
1379       end if;
1380 
1381       Status := fclose (Fd);
1382    end Process_Binder_File;
1383 
1384    -----------
1385    -- Usage --
1386    -----------
1387 
1388    procedure Usage is
1389    begin
1390       Write_Str ("Usage: ");
1391       Write_Str (Base_Command_Name.all);
1392       Write_Str (" switches mainprog.ali [non-Ada-objects] [linker-options]");
1393       Write_Eol;
1394       Write_Eol;
1395       Write_Line ("  mainprog.ali   the ALI file of the main program");
1396       Write_Eol;
1397       Write_Eol;
1398       Display_Usage_Version_And_Help;
1399       Write_Line ("  -f    Force object file list to be generated");
1400       Write_Line ("  -g    Compile binder source file with debug information");
1401       Write_Line ("  -n    Do not compile the binder source file");
1402       Write_Line ("  -P    Process files for use by CodePeer");
1403       Write_Line ("  -R    Do not use a run_path_option");
1404       Write_Line ("  -v    Verbose mode");
1405       Write_Line ("  -v -v Very verbose mode");
1406       Write_Eol;
1407       Write_Line ("  -o nam     Use 'nam' as the name of the executable");
1408       Write_Line ("  -b target  Compile the binder source to run on target");
1409       Write_Line ("  -Bdir      Load compiler executables from dir");
1410 
1411       if Is_Supported (Map_File) then
1412          Write_Line ("  -Mmap      Create map file map");
1413          Write_Line ("  -M         Create map file mainprog.map");
1414       end if;
1415 
1416       Write_Line ("  --GCC=comp Use comp as the compiler");
1417       Write_Line ("  --LINK=nam Use 'nam' for the linking rather than 'gcc'");
1418       Write_Eol;
1419       Write_Line ("  [non-Ada-objects]  list of non Ada object files");
1420       Write_Line ("  [linker-options]   other options for the linker");
1421    end Usage;
1422 
1423    ------------------
1424    -- Write_Header --
1425    ------------------
1426 
1427    procedure Write_Header is
1428    begin
1429       if Verbose_Mode then
1430          Write_Eol;
1431          Display_Version ("GNATLINK", "1995");
1432       end if;
1433    end Write_Header;
1434 
1435    -----------------
1436    -- Write_Usage --
1437    -----------------
1438 
1439    procedure Write_Usage is
1440    begin
1441       Write_Header;
1442       Usage;
1443    end Write_Usage;
1444 
1445 --  Start of processing for Gnatlink
1446 
1447 begin
1448    --  Add the directory where gnatlink is invoked in front of the path, if
1449    --  gnatlink is invoked with directory information.
1450 
1451    declare
1452       Command : constant String := Command_Name;
1453    begin
1454       for Index in reverse Command'Range loop
1455          if Command (Index) = Directory_Separator then
1456             declare
1457                Absolute_Dir : constant String :=
1458                  Normalize_Pathname
1459                    (Command (Command'First .. Index));
1460 
1461                PATH : constant String :=
1462                  Absolute_Dir &
1463                  Path_Separator &
1464                  Getenv ("PATH").all;
1465 
1466             begin
1467                Setenv ("PATH", PATH);
1468             end;
1469 
1470             exit;
1471          end if;
1472       end loop;
1473    end;
1474 
1475    Base_Command_Name := new String'(Base_Name (Command_Name));
1476    Process_Args;
1477 
1478    if Argument_Count = 0
1479      or else (Verbose_Mode and then Argument_Count = 1)
1480    then
1481       Write_Usage;
1482       Exit_Program (E_Fatal);
1483    end if;
1484 
1485    --  Initialize packages to be used
1486 
1487    Csets.Initialize;
1488    Snames.Initialize;
1489 
1490    --  We always compile with -c
1491 
1492    Binder_Options_From_ALI.Increment_Last;
1493    Binder_Options_From_ALI.Table (Binder_Options_From_ALI.Last) :=
1494      new String'("-c");
1495 
1496    if Ali_File_Name = null then
1497       Exit_With_Error ("no ali file given for link");
1498    end if;
1499 
1500    if not Is_Regular_File (Ali_File_Name.all) then
1501       Exit_With_Error (Ali_File_Name.all & " not found");
1502    end if;
1503 
1504    --  Read the ALI file of the main subprogram if the binder generated file
1505    --  needs to be compiled and no --GCC= switch has been specified. Fetch the
1506    --  back end switches from this ALI file and use these switches to compile
1507    --  the binder generated file
1508 
1509    if Compile_Bind_File and then Standard_Gcc then
1510       Initialize_ALI;
1511       Name_Len := Ali_File_Name'Length;
1512       Name_Buffer (1 .. Name_Len) := Ali_File_Name.all;
1513 
1514       declare
1515          use Types;
1516          F : constant File_Name_Type := Name_Find;
1517          T : Text_Buffer_Ptr;
1518          A : ALI_Id;
1519 
1520       begin
1521          --  Load the ALI file
1522 
1523          T := Read_Library_Info (F, True);
1524 
1525          --  Read it. Note that we ignore errors, since we only want very
1526          --  limited information from the ali file, and likely a slightly
1527          --  wrong version will be just fine, though in normal operation
1528          --  we don't expect this to happen.
1529 
1530          A := Scan_ALI
1531                (F,
1532                 T,
1533                 Ignore_ED     => False,
1534                 Err           => False,
1535                 Ignore_Errors => True);
1536 
1537          if A /= No_ALI_Id then
1538             for
1539               Index in Units.Table (ALIs.Table (A).First_Unit).First_Arg ..
1540                        Units.Table (ALIs.Table (A).First_Unit).Last_Arg
1541             loop
1542                --  Do not compile with the front end switches. However, --RTS
1543                --  is to be dealt with specially because it needs to be passed
1544                --  to compile the file generated by the binder.
1545 
1546                declare
1547                   Arg : String_Ptr renames Args.Table (Index);
1548                begin
1549                   if not Is_Front_End_Switch (Arg.all) then
1550                      Binder_Options_From_ALI.Increment_Last;
1551                      Binder_Options_From_ALI.Table
1552                        (Binder_Options_From_ALI.Last) := String_Access (Arg);
1553 
1554                      --  GNAT doesn't support GCC's multilib mechanism when it
1555                      --  is configured with --disable-libada. This means that,
1556                      --  when a multilib switch is used to request a particular
1557                      --  compilation mode, the corresponding --RTS switch must
1558                      --  also be specified. It is convenient to eliminate the
1559                      --  redundancy by keying the compilation mode on a single
1560                      --  switch, namely --RTS, and have the compiler reinstate
1561                      --  the multilib switch (see gcc-interface/lang-specs.h).
1562                      --  This switch must be passed to the driver at link time.
1563 
1564                      if Arg'Length = 5
1565                        and then Arg (Arg'First + 1 .. Arg'First + 4) = "mrtp"
1566                      then
1567                         Linker_Options.Increment_Last;
1568                         Linker_Options.Table
1569                           (Linker_Options.Last) := String_Access (Arg);
1570                      end if;
1571 
1572                   elsif Arg'Length > 5
1573                     and then Arg (Arg'First + 2 .. Arg'First + 5) = "RTS="
1574                   then
1575                      Binder_Options_From_ALI.Increment_Last;
1576                      Binder_Options_From_ALI.Table
1577                        (Binder_Options_From_ALI.Last) := String_Access (Arg);
1578 
1579                      --  Set the RTS_*_Path_Name variables, so that
1580                      --  the correct directories will be set when
1581                      --  Osint.Add_Default_Search_Dirs will be called later.
1582 
1583                      Opt.RTS_Src_Path_Name :=
1584                        Get_RTS_Search_Dir
1585                          (Arg (Arg'First + 6 .. Arg'Last), Include);
1586 
1587                      Opt.RTS_Lib_Path_Name :=
1588                        Get_RTS_Search_Dir
1589                          (Arg (Arg'First + 6 .. Arg'Last), Objects);
1590                   end if;
1591                end;
1592             end loop;
1593 
1594             --  Pass -fsjlj to the linker with back-end SJLJ exceptions
1595 
1596             if not ALIs.Table (A).Frontend_Exceptions
1597               and then not ALIs.Table (A).Zero_Cost_Exceptions
1598             then
1599                Linker_Options.Increment_Last;
1600                Linker_Options.Table
1601                 (Linker_Options.Last) := new String'("-fsjlj");
1602             end if;
1603          end if;
1604       end;
1605    end if;
1606 
1607    --  Get target parameters
1608 
1609    Osint.Add_Default_Search_Dirs;
1610    Targparm.Get_Target_Parameters;
1611 
1612    --  Compile the bind file with the following switches:
1613 
1614    --    -gnatA   stops reading gnat.adc, since we don't know what
1615    --             pragmas would work, and we do not need it anyway.
1616 
1617    --    -gnatWb  allows brackets coding for wide characters
1618 
1619    --    -gnatiw  allows wide characters in identifiers. This is needed
1620    --             because bindgen uses brackets encoding for all upper
1621    --             half and wide characters in identifier names.
1622 
1623    --  In addition, in CodePeer mode compile with -x adascil -gnatcC
1624 
1625    Binder_Options_From_ALI.Increment_Last;
1626    Binder_Options_From_ALI.Table (Binder_Options_From_ALI.Last) :=
1627         new String'("-gnatA");
1628    Binder_Options_From_ALI.Increment_Last;
1629    Binder_Options_From_ALI.Table (Binder_Options_From_ALI.Last) :=
1630         new String'("-gnatWb");
1631    Binder_Options_From_ALI.Increment_Last;
1632    Binder_Options_From_ALI.Table (Binder_Options_From_ALI.Last) :=
1633         new String'("-gnatiw");
1634 
1635    if Opt.CodePeer_Mode then
1636       Binder_Options_From_ALI.Increment_Last;
1637       Binder_Options_From_ALI.Table (Binder_Options_From_ALI.Last) :=
1638         new String'("-x");
1639       Binder_Options_From_ALI.Increment_Last;
1640       Binder_Options_From_ALI.Table (Binder_Options_From_ALI.Last) :=
1641         new String'("adascil");
1642       Binder_Options_From_ALI.Increment_Last;
1643       Binder_Options_From_ALI.Table (Binder_Options_From_ALI.Last) :=
1644         new String'("-gnatcC");
1645    end if;
1646 
1647    --  Locate all the necessary programs and verify required files are present
1648 
1649    Gcc_Path := System.OS_Lib.Locate_Exec_On_Path (Gcc.all);
1650 
1651    if Gcc_Path = null then
1652       Exit_With_Error ("Couldn't locate " & Gcc.all);
1653    end if;
1654 
1655    if Linker_Path = null then
1656       Linker_Path := Gcc_Path;
1657    end if;
1658 
1659    Write_Header;
1660 
1661    Target_Debuggable_Suffix := Get_Target_Debuggable_Suffix;
1662 
1663    --  If no output name specified, then use the base name of .ali file name
1664 
1665    if Output_File_Name = null then
1666       Output_File_Name :=
1667         new String'(Base_Name (Ali_File_Name.all)
1668                       & Target_Debuggable_Suffix.all);
1669    end if;
1670 
1671    Linker_Options.Increment_Last;
1672    Linker_Options.Table (Linker_Options.Last) := new String'("-o");
1673 
1674    Linker_Options.Increment_Last;
1675    Linker_Options.Table (Linker_Options.Last) :=
1676      new String'(Output_File_Name.all);
1677 
1678    Check_Existing_Executable (Output_File_Name.all);
1679 
1680    --  Warn if main program is called "test", as that may be a built-in command
1681    --  on Unix. On non-Unix systems executables have a suffix, so the warning
1682    --  will not appear. However, do not warn in the case of a cross compiler.
1683 
1684    --  Assume this is a cross tool if the executable name is not gnatlink.
1685    --  Note that the executable name is also gnatlink on windows, but in that
1686    --  case the output file name will be test.exe rather than test.
1687 
1688    if Base_Command_Name.all = "gnatlink"
1689      and then Output_File_Name.all = "test"
1690    then
1691       Error_Msg ("warning: executable name """ & Output_File_Name.all
1692                  & """ may conflict with shell command");
1693    end if;
1694 
1695    --  Special warnings for worrisome file names on windows
1696 
1697    --  Recent versions of Windows by default cause privilege escalation if an
1698    --  executable file name contains substrings "install", "setup", "update"
1699    --  or "patch". A console application will typically fail to load as a
1700    --  result, so we should warn the user.
1701 
1702    Bad_File_Names_On_Windows : declare
1703       FN : String := Output_File_Name.all;
1704 
1705       procedure Check_File_Name (S : String);
1706       --  Warn if file name has the substring S
1707 
1708       procedure Check_File_Name (S : String) is
1709       begin
1710          for J in 1 .. FN'Length - (S'Length - 1) loop
1711             if FN (J .. J + (S'Length - 1)) = S then
1712                Error_Msg
1713                  ("warning: executable file name """ & Output_File_Name.all
1714                   & """ contains substring """ & S & '"');
1715                Error_Msg
1716                  ("admin privileges may be required to run this file");
1717             end if;
1718          end loop;
1719       end Check_File_Name;
1720 
1721    --  Start of processing for Bad_File_Names_On_Windows
1722 
1723    begin
1724       for J in FN'Range loop
1725             FN (J) := Csets.Fold_Lower (FN (J));
1726       end loop;
1727 
1728       --  For now we detect Windows by its executable suffix of .exe
1729 
1730       if Target_Debuggable_Suffix.all = ".exe" then
1731          Check_File_Name ("install");
1732          Check_File_Name ("setup");
1733          Check_File_Name ("update");
1734          Check_File_Name ("patch");
1735       end if;
1736    end Bad_File_Names_On_Windows;
1737 
1738    --  If -M switch was specified, add the switches to create the map file
1739 
1740    if Create_Map_File then
1741       declare
1742          Map_Name : constant String := Base_Name (Ali_File_Name.all) & ".map";
1743          Switches : String_List_Access;
1744 
1745       begin
1746          Convert (Map_File, Map_Name, Switches);
1747 
1748          if Switches /= null then
1749             for J in Switches'Range loop
1750                Linker_Options.Increment_Last;
1751                Linker_Options.Table (Linker_Options.Last) := Switches (J);
1752             end loop;
1753          end if;
1754       end;
1755    end if;
1756 
1757    --  Perform consistency checks
1758 
1759    --  Transform the .ali file name into the binder output file name
1760 
1761    Make_Binder_File_Names : declare
1762       Fname     : constant String  := Base_Name (Ali_File_Name.all);
1763       Fname_Len : Integer := Fname'Length;
1764 
1765       function Get_Maximum_File_Name_Length return Integer;
1766       pragma Import (C, Get_Maximum_File_Name_Length,
1767                         "__gnat_get_maximum_file_name_length");
1768 
1769       Maximum_File_Name_Length : constant Integer :=
1770                                    Get_Maximum_File_Name_Length;
1771 
1772       Bind_File_Prefix : Types.String_Ptr;
1773       --  Contains prefix used for bind files
1774 
1775    begin
1776       --  Set prefix
1777 
1778       Bind_File_Prefix := new String'("b~");
1779 
1780       --  If the length of the binder file becomes too long due to
1781       --  the addition of the "b?" prefix, then truncate it.
1782 
1783       if Maximum_File_Name_Length > 0 then
1784          while Fname_Len >
1785                  Maximum_File_Name_Length - Bind_File_Prefix.all'Length
1786          loop
1787             Fname_Len := Fname_Len - 1;
1788          end loop;
1789       end if;
1790 
1791       declare
1792          Fnam : constant String :=
1793                   Bind_File_Prefix.all &
1794                     Fname (Fname'First .. Fname'First + Fname_Len - 1);
1795 
1796       begin
1797          Binder_Spec_Src_File := new String'(Fnam & ".ads");
1798          Binder_Body_Src_File := new String'(Fnam & ".adb");
1799          Binder_Ali_File      := new String'(Fnam & ".ali");
1800 
1801          Binder_Obj_File := new String'(Fnam & Get_Target_Object_Suffix.all);
1802       end;
1803 
1804       if Fname_Len /= Fname'Length then
1805          Binder_Options.Increment_Last;
1806          Binder_Options.Table (Binder_Options.Last) := new String'("-o");
1807          Binder_Options.Increment_Last;
1808          Binder_Options.Table (Binder_Options.Last) := Binder_Obj_File;
1809       end if;
1810    end Make_Binder_File_Names;
1811 
1812    Process_Binder_File (Binder_Body_Src_File.all & ASCII.NUL);
1813 
1814    --  Compile the binder file. This is fast, so we always do it, unless
1815    --  specifically told not to by the -n switch
1816 
1817    if Compile_Bind_File then
1818       Bind_Step : declare
1819          Success : Boolean;
1820 
1821          Args : Argument_List
1822                  (1 .. Binder_Options_From_ALI.Last + Binder_Options.Last + 1);
1823 
1824       begin
1825          for J in 1 .. Binder_Options_From_ALI.Last loop
1826             Args (J) := Binder_Options_From_ALI.Table (J);
1827          end loop;
1828 
1829          for J in 1 .. Binder_Options.Last loop
1830             Args (Binder_Options_From_ALI.Last + J) :=
1831               Binder_Options.Table (J);
1832          end loop;
1833 
1834          --  Use the full path of the binder generated source, so that it is
1835          --  guaranteed that the debugger will find this source, even with
1836          --  STABS.
1837 
1838          Args (Args'Last) :=
1839            new String'(Normalize_Pathname (Binder_Body_Src_File.all));
1840 
1841          if Verbose_Mode then
1842             Write_Str (Base_Name (Gcc_Path.all));
1843 
1844             for J in Args'Range loop
1845                Write_Str (" ");
1846                Write_Str (Args (J).all);
1847             end loop;
1848 
1849             Write_Eol;
1850          end if;
1851 
1852          System.OS_Lib.Spawn (Gcc_Path.all, Args, Success);
1853 
1854          if not Success then
1855             Exit_Program (E_Fatal);
1856          end if;
1857       end Bind_Step;
1858    end if;
1859 
1860    --  In CodePeer mode, there's nothing left to do after the binder file has
1861    --  been compiled.
1862 
1863    if Opt.CodePeer_Mode then
1864       if Tname_FD /= Invalid_FD then
1865          Delete (Tname);
1866       end if;
1867 
1868       return;
1869    end if;
1870 
1871    --  Now, actually link the program
1872 
1873    Link_Step : declare
1874       Num_Args : Natural :=
1875         (Linker_Options.Last - Linker_Options.First + 1) +
1876         (Gcc_Linker_Options.Last - Gcc_Linker_Options.First + 1) +
1877         (Linker_Objects.Last - Linker_Objects.First + 1);
1878       Stack_Op : Boolean := False;
1879 
1880    begin
1881       --  Remove duplicate stack size setting from the Linker_Options table.
1882       --  The stack setting option "-Xlinker --stack=R,C" can be found
1883       --  in one line when set by a pragma Linker_Options or in two lines
1884       --  ("-Xlinker" then "--stack=R,C") when set on the command line. We
1885       --  also check for the "-Wl,--stack=R" style option.
1886 
1887       --  We must remove the second stack setting option instance because
1888       --  the one on the command line will always be the first one. And any
1889       --  subsequent stack setting option will overwrite the previous one.
1890       --  This is done especially for GNAT/NT where we set the stack size
1891       --  for tasking programs by a pragma in the NT specific tasking
1892       --  package System.Task_Primitives.Operations.
1893 
1894       --  Note: This is not a FOR loop that runs from Linker_Options.First
1895       --  to Linker_Options.Last, since operations within the loop can
1896       --  modify the length of the table.
1897 
1898       Clean_Link_Option_Set : declare
1899          J                  : Natural;
1900          Shared_Libgcc_Seen : Boolean := False;
1901 
1902       begin
1903          J := Linker_Options.First;
1904          while J <= Linker_Options.Last loop
1905             if Linker_Options.Table (J).all = "-Xlinker"
1906               and then J < Linker_Options.Last
1907               and then Linker_Options.Table (J + 1)'Length > 8
1908               and then Linker_Options.Table (J + 1) (1 .. 8) = "--stack="
1909             then
1910                if Stack_Op then
1911                   Linker_Options.Table (J .. Linker_Options.Last - 2) :=
1912                     Linker_Options.Table (J + 2 .. Linker_Options.Last);
1913                   Linker_Options.Decrement_Last;
1914                   Linker_Options.Decrement_Last;
1915                   Num_Args := Num_Args - 2;
1916 
1917                else
1918                   Stack_Op := True;
1919                end if;
1920             end if;
1921 
1922             --  Remove duplicate -shared-libgcc switch
1923 
1924             if Linker_Options.Table (J).all = Shared_Libgcc_String then
1925                if Shared_Libgcc_Seen then
1926                   Linker_Options.Table (J .. Linker_Options.Last - 1) :=
1927                     Linker_Options.Table (J + 1 .. Linker_Options.Last);
1928                   Linker_Options.Decrement_Last;
1929                   Num_Args := Num_Args - 1;
1930 
1931                else
1932                   Shared_Libgcc_Seen := True;
1933                end if;
1934             end if;
1935 
1936             --  Here we just check for a canonical form that matches the
1937             --  pragma Linker_Options set in the NT runtime.
1938 
1939             if (Linker_Options.Table (J)'Length > 17
1940                 and then Linker_Options.Table (J) (1 .. 17) =
1941                   "-Xlinker --stack=")
1942               or else
1943                 (Linker_Options.Table (J)'Length > 12
1944                  and then Linker_Options.Table (J) (1 .. 12) =
1945                        "-Wl,--stack=")
1946             then
1947                if Stack_Op then
1948                   Linker_Options.Table (J .. Linker_Options.Last - 1) :=
1949                     Linker_Options.Table (J + 1 .. Linker_Options.Last);
1950                   Linker_Options.Decrement_Last;
1951                   Num_Args := Num_Args - 1;
1952 
1953                else
1954                   Stack_Op := True;
1955                end if;
1956             end if;
1957 
1958             J := J + 1;
1959          end loop;
1960 
1961          if Linker_Path = Gcc_Path then
1962 
1963             --  For systems where the default is to link statically with
1964             --  libgcc, if gcc is not called with -shared-libgcc, call it
1965             --  with -static-libgcc, as there are some platforms where one
1966             --  of these two switches is compulsory to link.
1967 
1968             if Shared_Libgcc_Default = 'T'
1969               and then not Shared_Libgcc_Seen
1970             then
1971                Linker_Options.Increment_Last;
1972                Linker_Options.Table (Linker_Options.Last) := Static_Libgcc;
1973                Num_Args := Num_Args + 1;
1974             end if;
1975          end if;
1976       end Clean_Link_Option_Set;
1977 
1978       --  Prepare arguments for call to linker
1979 
1980       Call_Linker : declare
1981          Success  : Boolean;
1982          Args     : Argument_List (1 .. Num_Args + 1);
1983          Index    : Integer := Args'First;
1984 
1985       begin
1986          Args (Index) := Binder_Obj_File;
1987 
1988          --  Add the object files and any -largs libraries
1989 
1990          for J in Linker_Objects.First .. Linker_Objects.Last loop
1991             Index := Index + 1;
1992             Args (Index) := Linker_Objects.Table (J);
1993          end loop;
1994 
1995          --  Add the linker options from the binder file
1996 
1997          for J in Linker_Options.First .. Linker_Options.Last loop
1998             Index := Index + 1;
1999             Args (Index) := Linker_Options.Table (J);
2000          end loop;
2001 
2002          --  Finally add the libraries from the --GCC= switch
2003 
2004          for J in Gcc_Linker_Options.First .. Gcc_Linker_Options.Last loop
2005             Index := Index + 1;
2006             Args (Index) := Gcc_Linker_Options.Table (J);
2007          end loop;
2008 
2009          if Verbose_Mode then
2010             Write_Str (Linker_Path.all);
2011 
2012             for J in Args'Range loop
2013                Write_Str (" ");
2014                Write_Str (Args (J).all);
2015             end loop;
2016 
2017             Write_Eol;
2018 
2019             --  If we are on very verbose mode (-v -v) and a response file
2020             --  is used we display its content.
2021 
2022             if Very_Verbose_Mode and then Tname_FD /= Invalid_FD then
2023                Write_Eol;
2024                Write_Str ("Response file (" &
2025                             Tname (Tname'First .. Tname'Last - 1) &
2026                             ") content : ");
2027                Write_Eol;
2028 
2029                for J in
2030                  Response_File_Objects.First .. Response_File_Objects.Last
2031                loop
2032                   Write_Str (Response_File_Objects.Table (J).all);
2033                   Write_Eol;
2034                end loop;
2035 
2036                Write_Eol;
2037             end if;
2038          end if;
2039 
2040          System.OS_Lib.Spawn (Linker_Path.all, Args, Success);
2041 
2042          --  Delete the temporary file used in conjunction with linking if one
2043          --  was created. See Process_Bind_File for details.
2044 
2045          if Tname_FD /= Invalid_FD then
2046             Delete (Tname);
2047          end if;
2048 
2049          if not Success then
2050             Error_Msg ("error when calling " & Linker_Path.all);
2051             Exit_Program (E_Fatal);
2052          end if;
2053       end Call_Linker;
2054    end Link_Step;
2055 
2056    --  Only keep the binder output file and it's associated object
2057    --  file if compiling with the -g option.  These files are only
2058    --  useful if debugging.
2059 
2060    if not Debug_Flag_Present then
2061       Delete (Binder_Ali_File.all & ASCII.NUL);
2062       Delete (Binder_Spec_Src_File.all & ASCII.NUL);
2063       Delete (Binder_Body_Src_File.all & ASCII.NUL);
2064       Delete (Binder_Obj_File.all & ASCII.NUL);
2065    end if;
2066 
2067    Exit_Program (E_Success);
2068 
2069 exception
2070    when X : others =>
2071       Write_Line (Exception_Information (X));
2072       Exit_With_Error ("INTERNAL ERROR. Please report");
2073 end Gnatlink;