2012-08-15 Segher Boessenkool <segher@kernel.crashing.org>
[official-gcc.git] / gcc / ada / gnatbind.adb
blob0382371b6888192d26a31b8862336cfb7b12ac84
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT COMPILER COMPONENTS --
4 -- --
5 -- G N A T B I N D --
6 -- --
7 -- B o d y --
8 -- --
9 -- Copyright (C) 1992-2011, 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 ------------------------------------------------------------------------------
26 with ALI; use ALI;
27 with ALI.Util; use ALI.Util;
28 with Bcheck; use Bcheck;
29 with Binde; use Binde;
30 with Binderr; use Binderr;
31 with Bindgen; use Bindgen;
32 with Bindusg;
33 with Butil; use Butil;
34 with Casing; use Casing;
35 with Csets;
36 with Debug; use Debug;
37 with Fmap;
38 with Fname; use Fname;
39 with Namet; use Namet;
40 with Opt; use Opt;
41 with Osint; use Osint;
42 with Osint.B; use Osint.B;
43 with Output; use Output;
44 with Rident; use Rident;
45 with Snames;
46 with Switch; use Switch;
47 with Switch.B; use Switch.B;
48 with Table;
49 with Targparm; use Targparm;
50 with Types; use Types;
52 with System.Case_Util; use System.Case_Util;
53 with System.OS_Lib; use System.OS_Lib;
55 with Ada.Command_Line.Response_File; use Ada.Command_Line;
57 procedure Gnatbind is
59 Total_Errors : Nat := 0;
60 -- Counts total errors in all files
62 Total_Warnings : Nat := 0;
63 -- Total warnings in all files
65 Main_Lib_File : File_Name_Type;
66 -- Current main library file
68 First_Main_Lib_File : File_Name_Type := No_File;
69 -- The first library file, that should be a main subprogram if neither -n
70 -- nor -z are used.
72 Std_Lib_File : File_Name_Type;
73 -- Standard library
75 Text : Text_Buffer_Ptr;
76 Next_Arg : Positive;
78 Output_File_Name_Seen : Boolean := False;
79 Output_File_Name : String_Ptr := new String'("");
81 L_Switch_Seen : Boolean := False;
83 Mapping_File : String_Ptr := null;
85 package Closure_Sources is new Table.Table
86 (Table_Component_Type => File_Name_Type,
87 Table_Index_Type => Natural,
88 Table_Low_Bound => 1,
89 Table_Initial => 10,
90 Table_Increment => 100,
91 Table_Name => "Gnatbind.Closure_Sources");
92 -- Table to record the sources in the closure, to avoid duplications. Used
93 -- only with switch -R.
95 function Gnatbind_Supports_Auto_Init return Boolean;
96 -- Indicates if automatic initialization of elaboration procedure
97 -- through the constructor mechanism is possible on the platform.
99 procedure List_Applicable_Restrictions;
100 -- List restrictions that apply to this partition if option taken
102 procedure Scan_Bind_Arg (Argv : String);
103 -- Scan and process binder specific arguments. Argv is a single argument.
104 -- All the one character arguments are still handled by Switch. This
105 -- routine handles -aO -aI and -I-. The lower bound of Argv must be 1.
107 function Is_Cross_Compiler return Boolean;
108 -- Returns True iff this is a cross-compiler
110 ---------------------------------
111 -- Gnatbind_Supports_Auto_Init --
112 ---------------------------------
114 function Gnatbind_Supports_Auto_Init return Boolean is
115 function gnat_binder_supports_auto_init return Integer;
116 pragma Import (C, gnat_binder_supports_auto_init,
117 "__gnat_binder_supports_auto_init");
118 begin
119 return gnat_binder_supports_auto_init /= 0;
120 end Gnatbind_Supports_Auto_Init;
122 -----------------------
123 -- Is_Cross_Compiler --
124 -----------------------
126 function Is_Cross_Compiler return Boolean is
127 Cross_Compiler : Integer;
128 pragma Import (C, Cross_Compiler, "__gnat_is_cross_compiler");
129 begin
130 return Cross_Compiler = 1;
131 end Is_Cross_Compiler;
133 ----------------------------------
134 -- List_Applicable_Restrictions --
135 ----------------------------------
137 procedure List_Applicable_Restrictions is
139 -- Define those restrictions that should be output if the gnatbind
140 -- -r switch is used. Not all restrictions are output for the reasons
141 -- given below in the list, and this array is used to test whether
142 -- the corresponding pragma should be listed. True means that it
143 -- should not be listed.
145 No_Restriction_List : constant array (All_Restrictions) of Boolean :=
146 (No_Allocators_After_Elaboration => True,
147 -- This involves run-time conditions not checkable at compile time
149 No_Anonymous_Allocators => True,
150 -- Premature, since we have not implemented this yet
152 No_Exception_Propagation => True,
153 -- Modifies code resulting in different exception semantics
155 No_Exceptions => True,
156 -- Has unexpected Suppress (All_Checks) effect
158 No_Implicit_Conditionals => True,
159 -- This could modify and pessimize generated code
161 No_Implicit_Dynamic_Code => True,
162 -- This could modify and pessimize generated code
164 No_Implicit_Loops => True,
165 -- This could modify and pessimize generated code
167 No_Recursion => True,
168 -- Not checkable at compile time
170 No_Reentrancy => True,
171 -- Not checkable at compile time
173 Max_Entry_Queue_Length => True,
174 -- Not checkable at compile time
176 Max_Storage_At_Blocking => True,
177 -- Not checkable at compile time
179 others => False);
181 Additional_Restrictions_Listed : Boolean := False;
182 -- Set True if we have listed header for restrictions
184 function Restriction_Could_Be_Set (R : Restriction_Id) return Boolean;
185 -- Returns True if the given restriction can be listed as an additional
186 -- restriction that could be set.
188 ------------------------------
189 -- Restriction_Could_Be_Set --
190 ------------------------------
192 function Restriction_Could_Be_Set (R : Restriction_Id) return Boolean is
193 CR : Restrictions_Info renames Cumulative_Restrictions;
195 begin
196 case R is
198 -- Boolean restriction
200 when All_Boolean_Restrictions =>
202 -- The condition for listing a boolean restriction as an
203 -- additional restriction that could be set is that it is
204 -- not violated by any unit, and not already set.
206 return CR.Violated (R) = False and then CR.Set (R) = False;
208 -- Parameter restriction
210 when All_Parameter_Restrictions =>
212 -- If the restriction is violated and the level of violation is
213 -- unknown, the restriction can definitely not be listed.
215 if CR.Violated (R) and then CR.Unknown (R) then
216 return False;
218 -- We can list the restriction if it is not set
220 elsif not CR.Set (R) then
221 return True;
223 -- We can list the restriction if is set to a greater value
224 -- than the maximum value known for the violation.
226 else
227 return CR.Value (R) > CR.Count (R);
228 end if;
230 -- No other values for R possible
232 when others =>
233 raise Program_Error;
235 end case;
236 end Restriction_Could_Be_Set;
238 -- Start of processing for List_Applicable_Restrictions
240 begin
241 -- Loop through restrictions
243 for R in All_Restrictions loop
244 if not No_Restriction_List (R)
245 and then Restriction_Could_Be_Set (R)
246 then
247 if not Additional_Restrictions_Listed then
248 Write_Eol;
249 Write_Line
250 ("The following additional restrictions may be" &
251 " applied to this partition:");
252 Additional_Restrictions_Listed := True;
253 end if;
255 Write_Str ("pragma Restrictions (");
257 declare
258 S : constant String := Restriction_Id'Image (R);
259 begin
260 Name_Len := S'Length;
261 Name_Buffer (1 .. Name_Len) := S;
262 end;
264 Set_Casing (Mixed_Case);
265 Write_Str (Name_Buffer (1 .. Name_Len));
267 if R in All_Parameter_Restrictions then
268 Write_Str (" => ");
269 Write_Int (Int (Cumulative_Restrictions.Count (R)));
270 end if;
272 Write_Str (");");
273 Write_Eol;
274 end if;
275 end loop;
276 end List_Applicable_Restrictions;
278 -------------------
279 -- Scan_Bind_Arg --
280 -------------------
282 procedure Scan_Bind_Arg (Argv : String) is
283 pragma Assert (Argv'First = 1);
285 begin
286 -- Now scan arguments that are specific to the binder and are not
287 -- handled by the common circuitry in Switch.
289 if Opt.Output_File_Name_Present
290 and then not Output_File_Name_Seen
291 then
292 Output_File_Name_Seen := True;
294 if Argv'Length = 0
295 or else (Argv'Length >= 1 and then Argv (1) = '-')
296 then
297 Fail ("output File_Name missing after -o");
299 else
300 Output_File_Name := new String'(Argv);
301 end if;
303 elsif Argv'Length >= 2 and then Argv (1) = '-' then
305 -- -I-
307 if Argv (2 .. Argv'Last) = "I-" then
308 Opt.Look_In_Primary_Dir := False;
310 -- -Idir
312 elsif Argv (2) = 'I' then
313 Add_Src_Search_Dir (Argv (3 .. Argv'Last));
314 Add_Lib_Search_Dir (Argv (3 .. Argv'Last));
316 -- -Ldir
318 elsif Argv (2) = 'L' then
319 if Argv'Length >= 3 then
321 -- Remember that the -L switch was specified, so that if this
322 -- is on OpenVMS, the export names are put in uppercase.
323 -- This is not known before the target parameters are read.
325 L_Switch_Seen := True;
327 Opt.Bind_For_Library := True;
328 Opt.Ada_Init_Name :=
329 new String'(Argv (3 .. Argv'Last) & Opt.Ada_Init_Suffix);
330 Opt.Ada_Final_Name :=
331 new String'(Argv (3 .. Argv'Last) & Opt.Ada_Final_Suffix);
332 Opt.Ada_Main_Name :=
333 new String'(Argv (3 .. Argv'Last) & Opt.Ada_Main_Name_Suffix);
335 -- This option (-Lxxx) implies -n
337 Opt.Bind_Main_Program := False;
339 else
340 Fail
341 ("Prefix of initialization and finalization " &
342 "procedure names missing in -L");
343 end if;
345 -- -Sin -Slo -Shi -Sxx -Sev
347 elsif Argv'Length = 4
348 and then Argv (2) = 'S'
349 then
350 declare
351 C1 : Character := Argv (3);
352 C2 : Character := Argv (4);
354 begin
355 -- Fold to upper case
357 if C1 in 'a' .. 'z' then
358 C1 := Character'Val (Character'Pos (C1) - 32);
359 end if;
361 if C2 in 'a' .. 'z' then
362 C2 := Character'Val (Character'Pos (C2) - 32);
363 end if;
365 -- Test valid option and set mode accordingly
367 if C1 = 'E' and then C2 = 'V' then
368 null;
370 elsif C1 = 'I' and then C2 = 'N' then
371 null;
373 elsif C1 = 'L' and then C2 = 'O' then
374 null;
376 elsif C1 = 'H' and then C2 = 'I' then
377 null;
379 elsif (C1 in '0' .. '9' or else C1 in 'A' .. 'F')
380 and then
381 (C2 in '0' .. '9' or else C2 in 'A' .. 'F')
382 then
383 null;
385 -- Invalid -S switch, let Switch give error, set default of IN
387 else
388 Scan_Binder_Switches (Argv);
389 C1 := 'I';
390 C2 := 'N';
391 end if;
393 Initialize_Scalars_Mode1 := C1;
394 Initialize_Scalars_Mode2 := C2;
395 end;
397 -- -aIdir
399 elsif Argv'Length >= 3
400 and then Argv (2 .. 3) = "aI"
401 then
402 Add_Src_Search_Dir (Argv (4 .. Argv'Last));
404 -- -aOdir
406 elsif Argv'Length >= 3
407 and then Argv (2 .. 3) = "aO"
408 then
409 Add_Lib_Search_Dir (Argv (4 .. Argv'Last));
411 -- -nostdlib
413 elsif Argv (2 .. Argv'Last) = "nostdlib" then
414 Opt.No_Stdlib := True;
416 -- -nostdinc
418 elsif Argv (2 .. Argv'Last) = "nostdinc" then
419 Opt.No_Stdinc := True;
421 -- -static
423 elsif Argv (2 .. Argv'Last) = "static" then
424 Opt.Shared_Libgnat := False;
426 -- -shared
428 elsif Argv (2 .. Argv'Last) = "shared" then
429 Opt.Shared_Libgnat := True;
431 -- -F=mapping_file
433 elsif Argv'Length >= 4 and then Argv (2 .. 3) = "F=" then
434 if Mapping_File /= null then
435 Fail ("cannot specify several mapping files");
436 end if;
438 Mapping_File := new String'(Argv (4 .. Argv'Last));
440 -- -Mname
442 elsif Argv'Length >= 3 and then Argv (2) = 'M' then
443 if not Is_Cross_Compiler then
444 Write_Line
445 ("gnatbind: -M not expected to be used on native platforms");
446 end if;
448 Opt.Bind_Alternate_Main_Name := True;
449 Opt.Alternate_Main_Name := new String'(Argv (3 .. Argv'Last));
451 -- All other options are single character and are handled by
452 -- Scan_Binder_Switches.
454 else
455 Scan_Binder_Switches (Argv);
456 end if;
458 -- Not a switch, so must be a file name (if non-empty)
460 elsif Argv'Length /= 0 then
461 if Argv'Length > 4
462 and then Argv (Argv'Last - 3 .. Argv'Last) = ".ali"
463 then
464 Add_File (Argv);
465 else
466 Add_File (Argv & ".ali");
467 end if;
468 end if;
469 end Scan_Bind_Arg;
471 procedure Check_Version_And_Help is
472 new Check_Version_And_Help_G (Bindusg.Display);
474 -- Start of processing for Gnatbind
476 begin
477 -- Set default for Shared_Libgnat option
479 declare
480 Shared_Libgnat_Default : Character;
481 pragma Import
482 (C, Shared_Libgnat_Default, "__gnat_shared_libgnat_default");
484 SHARED : constant Character := 'H';
485 STATIC : constant Character := 'T';
487 begin
488 pragma Assert
489 (Shared_Libgnat_Default = SHARED
490 or else
491 Shared_Libgnat_Default = STATIC);
492 Shared_Libgnat := (Shared_Libgnat_Default = SHARED);
493 end;
495 -- Scan the switches and arguments
497 -- First, scan to detect --version and/or --help
499 Check_Version_And_Help ("GNATBIND", "1995");
501 -- Use low level argument routines to avoid dragging in the secondary stack
503 Next_Arg := 1;
504 Scan_Args : while Next_Arg < Arg_Count loop
505 declare
506 Next_Argv : String (1 .. Len_Arg (Next_Arg));
507 begin
508 Fill_Arg (Next_Argv'Address, Next_Arg);
510 if Next_Argv'Length > 0 then
511 if Next_Argv (1) = '@' then
512 if Next_Argv'Length > 1 then
513 declare
514 Arguments : constant Argument_List :=
515 Response_File.Arguments_From
516 (Response_File_Name =>
517 Next_Argv (2 .. Next_Argv'Last),
518 Recursive => True,
519 Ignore_Non_Existing_Files => True);
520 begin
521 for J in Arguments'Range loop
522 Scan_Bind_Arg (Arguments (J).all);
523 end loop;
524 end;
525 end if;
527 else
528 Scan_Bind_Arg (Next_Argv);
529 end if;
530 end if;
531 end;
533 Next_Arg := Next_Arg + 1;
534 end loop Scan_Args;
536 if Use_Pragma_Linker_Constructor then
537 if Bind_Main_Program then
538 Fail ("switch -a must be used in conjunction with -n or -Lxxx");
540 elsif not Gnatbind_Supports_Auto_Init then
541 Fail ("automatic initialisation of elaboration " &
542 "not supported on this platform");
543 end if;
544 end if;
546 -- Test for trailing -o switch
548 if Opt.Output_File_Name_Present
549 and then not Output_File_Name_Seen
550 then
551 Fail ("output file name missing after -o");
552 end if;
554 -- Output usage if requested
556 if Usage_Requested then
557 Bindusg.Display;
558 end if;
560 -- Check that the Ada binder file specified has extension .adb and that
561 -- the C binder file has extension .c
563 if Opt.Output_File_Name_Present
564 and then Output_File_Name_Seen
565 then
566 Check_Extensions : declare
567 Length : constant Natural := Output_File_Name'Length;
568 Last : constant Natural := Output_File_Name'Last;
569 begin
570 if Length <= 4
571 or else Output_File_Name (Last - 3 .. Last) /= ".adb"
572 then
573 Fail ("output file name should have .adb extension");
574 end if;
575 end Check_Extensions;
576 end if;
578 Osint.Add_Default_Search_Dirs;
580 -- Carry out package initializations. These are initializations which
581 -- might logically be performed at elaboration time, and we decide to be
582 -- consistent. Like elaboration, the order in which these calls are made
583 -- is in some cases important.
585 Csets.Initialize;
586 Snames.Initialize;
588 -- Acquire target parameters
590 Targparm.Get_Target_Parameters;
592 -- Initialize Cumulative_Restrictions with the restrictions on the target
593 -- scanned from the system.ads file. Then as we read ALI files, we will
594 -- accumulate additional restrictions specified in other files.
596 Cumulative_Restrictions := Targparm.Restrictions_On_Target;
598 -- On OpenVMS, when -L is used, all external names used in pragmas Export
599 -- are in upper case. The reason is that on OpenVMS, the macro-assembler
600 -- MACASM-32, used to build Stand-Alone Libraries, only understands
601 -- uppercase.
603 if L_Switch_Seen and then OpenVMS_On_Target then
604 To_Upper (Opt.Ada_Init_Name.all);
605 To_Upper (Opt.Ada_Final_Name.all);
606 To_Upper (Opt.Ada_Main_Name.all);
607 end if;
609 -- Acquire configurable run-time mode
611 if Configurable_Run_Time_On_Target then
612 Configurable_Run_Time_Mode := True;
613 end if;
615 -- Output copyright notice if in verbose mode
617 if Verbose_Mode then
618 Write_Eol;
619 Display_Version ("GNATBIND", "1995");
620 end if;
622 -- Output usage information if no files
624 if not More_Lib_Files then
625 Bindusg.Display;
626 Exit_Program (E_Fatal);
627 end if;
629 -- If a mapping file was specified, initialize the file mapping
631 if Mapping_File /= null then
632 Fmap.Initialize (Mapping_File.all);
633 end if;
635 -- The block here is to catch the Unrecoverable_Error exception in the
636 -- case where we exceed the maximum number of permissible errors or some
637 -- other unrecoverable error occurs.
639 begin
640 -- Initialize binder packages
642 Initialize_Binderr;
643 Initialize_ALI;
644 Initialize_ALI_Source;
646 if Verbose_Mode then
647 Write_Eol;
648 end if;
650 -- Input ALI files
652 while More_Lib_Files loop
653 Main_Lib_File := Next_Main_Lib_File;
655 if First_Main_Lib_File = No_File then
656 First_Main_Lib_File := Main_Lib_File;
657 end if;
659 if Verbose_Mode then
660 if Check_Only then
661 Write_Str ("Checking: ");
662 else
663 Write_Str ("Binding: ");
664 end if;
666 Write_Name (Main_Lib_File);
667 Write_Eol;
668 end if;
670 Text := Read_Library_Info (Main_Lib_File, True);
672 declare
673 Id : ALI_Id;
674 pragma Warnings (Off, Id);
676 begin
677 Id := Scan_ALI
678 (F => Main_Lib_File,
679 T => Text,
680 Ignore_ED => False,
681 Err => False,
682 Ignore_Errors => Debug_Flag_I,
683 Directly_Scanned => True);
684 end;
686 Free (Text);
687 end loop;
689 -- No_Run_Time mode
691 if No_Run_Time_Mode then
693 -- Set standard configuration parameters
695 Suppress_Standard_Library_On_Target := True;
696 Configurable_Run_Time_Mode := True;
697 end if;
699 -- For main ALI files, even if they are interfaces, we get their
700 -- dependencies. To be sure, we reset the Interface flag for all main
701 -- ALI files.
703 for Index in ALIs.First .. ALIs.Last loop
704 ALIs.Table (Index).SAL_Interface := False;
705 end loop;
707 -- Add System.Standard_Library to list to ensure that these files are
708 -- included in the bind, even if not directly referenced from Ada code
709 -- This is suppressed if the appropriate targparm switch is set.
711 if not Suppress_Standard_Library_On_Target then
712 Name_Buffer (1 .. 12) := "s-stalib.ali";
713 Name_Len := 12;
714 Std_Lib_File := Name_Find;
715 Text := Read_Library_Info (Std_Lib_File, True);
717 declare
718 Id : ALI_Id;
719 pragma Warnings (Off, Id);
721 begin
722 Id :=
723 Scan_ALI
724 (F => Std_Lib_File,
725 T => Text,
726 Ignore_ED => False,
727 Err => False,
728 Ignore_Errors => Debug_Flag_I);
729 end;
731 Free (Text);
732 end if;
734 -- Load ALIs for all dependent units
736 for Index in ALIs.First .. ALIs.Last loop
737 Read_Withed_ALIs (Index);
738 end loop;
740 -- Quit if some file needs compiling
742 if No_Object_Specified then
743 raise Unrecoverable_Error;
744 end if;
746 -- Output list of ALI files in closure
748 if Output_ALI_List then
749 if ALI_List_Filename /= null then
750 Set_List_File (ALI_List_Filename.all);
751 end if;
753 for Index in ALIs.First .. ALIs.Last loop
754 declare
755 Full_Afile : constant File_Name_Type :=
756 Find_File (ALIs.Table (Index).Afile, Library);
757 begin
758 Write_Name (Full_Afile);
759 Write_Eol;
760 end;
761 end loop;
763 if ALI_List_Filename /= null then
764 Close_List_File;
765 end if;
766 end if;
768 -- Build source file table from the ALI files we have read in
770 Set_Source_Table;
772 -- If there is main program to bind, set Main_Lib_File to the first
773 -- library file, and the name from which to derive the binder generate
774 -- file to the first ALI file.
776 if Bind_Main_Program then
777 Main_Lib_File := First_Main_Lib_File;
778 Set_Current_File_Name_Index (To => 1);
779 end if;
781 -- Check that main library file is a suitable main program
783 if Bind_Main_Program
784 and then ALIs.Table (ALIs.First).Main_Program = None
785 and then not No_Main_Subprogram
786 then
787 Get_Name_String
788 (Units.Table (ALIs.Table (ALIs.First).First_Unit).Uname);
790 declare
791 Unit_Name : String := Name_Buffer (1 .. Name_Len - 2);
792 begin
793 To_Mixed (Unit_Name);
794 Get_Name_String (ALIs.Table (ALIs.First).Sfile);
795 Add_Str_To_Name_Buffer (":1: ");
796 Add_Str_To_Name_Buffer (Unit_Name);
797 Add_Str_To_Name_Buffer (" cannot be used as a main program");
798 Write_Line (Name_Buffer (1 .. Name_Len));
799 Errors_Detected := Errors_Detected + 1;
800 end;
801 end if;
803 -- Perform consistency and correctness checks
805 Check_Duplicated_Subunits;
806 Check_Versions;
807 Check_Consistency;
808 Check_Configuration_Consistency;
810 -- List restrictions that could be applied to this partition
812 if List_Restrictions then
813 List_Applicable_Restrictions;
814 end if;
816 -- Complete bind if no errors
818 if Errors_Detected = 0 then
819 Find_Elab_Order;
821 if Errors_Detected = 0 then
822 -- Display elaboration order if -l was specified
824 if Elab_Order_Output then
825 if not Zero_Formatting then
826 Write_Eol;
827 Write_Str ("ELABORATION ORDER");
828 Write_Eol;
829 end if;
831 for J in Elab_Order.First .. Elab_Order.Last loop
832 if not Units.Table (Elab_Order.Table (J)).SAL_Interface then
833 if not Zero_Formatting then
834 Write_Str (" ");
835 end if;
837 Write_Unit_Name
838 (Units.Table (Elab_Order.Table (J)).Uname);
839 Write_Eol;
840 end if;
841 end loop;
843 if not Zero_Formatting then
844 Write_Eol;
845 end if;
846 end if;
848 if not Check_Only then
849 Gen_Output_File (Output_File_Name.all);
850 end if;
852 -- Display list of sources in the closure (except predefined
853 -- sources) if -R was used.
855 if List_Closure then
856 List_Closure_Display : declare
857 Source : File_Name_Type;
859 function Put_In_Sources (S : File_Name_Type) return Boolean;
860 -- Check if S is already in table Sources and put in Sources
861 -- if it is not. Return False if the source is already in
862 -- Sources, and True if it is added.
864 --------------------
865 -- Put_In_Sources --
866 --------------------
868 function Put_In_Sources
869 (S : File_Name_Type) return Boolean is
870 begin
871 for J in 1 .. Closure_Sources.Last loop
872 if Closure_Sources.Table (J) = S then
873 return False;
874 end if;
875 end loop;
877 Closure_Sources.Append (S);
878 return True;
879 end Put_In_Sources;
881 -- Start of processing for List_Closure_Display
883 begin
884 Closure_Sources.Init;
886 if not Zero_Formatting then
887 Write_Eol;
888 Write_Str ("REFERENCED SOURCES");
889 Write_Eol;
890 end if;
892 for J in reverse Elab_Order.First .. Elab_Order.Last loop
893 Source := Units.Table (Elab_Order.Table (J)).Sfile;
895 -- Do not include the sources of the runtime and do not
896 -- include the same source several times.
898 if Put_In_Sources (Source)
899 and then not Is_Internal_File_Name (Source)
900 then
901 if not Zero_Formatting then
902 Write_Str (" ");
903 end if;
905 Write_Str (Get_Name_String (Source));
906 Write_Eol;
907 end if;
908 end loop;
910 -- Subunits do not appear in the elaboration table because
911 -- they are subsumed by their parent units, but we need to
912 -- list them for other tools. For now they are listed after
913 -- other files, rather than right after their parent, since
914 -- there is no easy link between the elaboration table and
915 -- the ALIs table ??? As subunits may appear repeatedly in
916 -- the list, if the parent unit appears in the context of
917 -- several units in the closure, duplicates are suppressed.
919 for J in Sdep.First .. Sdep.Last loop
920 Source := Sdep.Table (J).Sfile;
922 if Sdep.Table (J).Subunit_Name /= No_Name
923 and then Put_In_Sources (Source)
924 and then not Is_Internal_File_Name (Source)
925 then
926 if not Zero_Formatting then
927 Write_Str (" ");
928 end if;
930 Write_Str (Get_Name_String (Source));
931 Write_Eol;
932 end if;
933 end loop;
935 if not Zero_Formatting then
936 Write_Eol;
937 end if;
938 end List_Closure_Display;
939 end if;
940 end if;
941 end if;
943 Total_Errors := Total_Errors + Errors_Detected;
944 Total_Warnings := Total_Warnings + Warnings_Detected;
946 exception
947 when Unrecoverable_Error =>
948 Total_Errors := Total_Errors + Errors_Detected;
949 Total_Warnings := Total_Warnings + Warnings_Detected;
950 end;
952 -- All done. Set proper exit status
954 Finalize_Binderr;
955 Namet.Finalize;
957 if Total_Errors > 0 then
958 Exit_Program (E_Errors);
960 elsif Total_Warnings > 0 then
961 Exit_Program (E_Warnings);
963 else
964 -- Do not call Exit_Program (E_Success), so that finalization occurs
965 -- normally.
967 null;
968 end if;
969 end Gnatbind;