2008-05-30 Vladimir Makarov <vmakarov@redhat.com>
[official-gcc.git] / gcc / ada / gnatbind.adb
blob48eceb0ff774d0809cff8e6a141942a98bee3493
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-2008, 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 Targparm; use Targparm;
49 with Types; use Types;
51 with System.Case_Util; use System.Case_Util;
52 with System.OS_Lib; use System.OS_Lib;
54 with Ada.Command_Line.Response_File; use Ada.Command_Line;
56 procedure Gnatbind is
58 Total_Errors : Nat := 0;
59 -- Counts total errors in all files
61 Total_Warnings : Nat := 0;
62 -- Total warnings in all files
64 Main_Lib_File : File_Name_Type;
65 -- Current main library file
67 First_Main_Lib_File : File_Name_Type := No_File;
68 -- The first library file, that should be a main subprogram if neither -n
69 -- nor -z are used.
71 Std_Lib_File : File_Name_Type;
72 -- Standard library
74 Text : Text_Buffer_Ptr;
75 Next_Arg : Positive;
77 Output_File_Name_Seen : Boolean := False;
78 Output_File_Name : String_Ptr := new String'("");
80 L_Switch_Seen : Boolean := False;
82 Mapping_File : String_Ptr := null;
84 function Gnatbind_Supports_Auto_Init return Boolean;
85 -- Indicates if automatic initialization of elaboration procedure
86 -- through the constructor mechanism is possible on the platform.
88 procedure List_Applicable_Restrictions;
89 -- List restrictions that apply to this partition if option taken
91 procedure Scan_Bind_Arg (Argv : String);
92 -- Scan and process binder specific arguments. Argv is a single argument.
93 -- All the one character arguments are still handled by Switch. This
94 -- routine handles -aO -aI and -I-. The lower bound of Argv must be 1.
96 function Is_Cross_Compiler return Boolean;
97 -- Returns True iff this is a cross-compiler
99 ---------------------------------
100 -- Gnatbind_Supports_Auto_Init --
101 ---------------------------------
103 function Gnatbind_Supports_Auto_Init return Boolean is
104 function gnat_binder_supports_auto_init return Integer;
105 pragma Import (C, gnat_binder_supports_auto_init,
106 "__gnat_binder_supports_auto_init");
107 begin
108 return gnat_binder_supports_auto_init /= 0;
109 end Gnatbind_Supports_Auto_Init;
111 -----------------------
112 -- Is_Cross_Compiler --
113 -----------------------
115 function Is_Cross_Compiler return Boolean is
116 Cross_Compiler : Integer;
117 pragma Import (C, Cross_Compiler, "__gnat_is_cross_compiler");
118 begin
119 return Cross_Compiler = 1;
120 end Is_Cross_Compiler;
122 ----------------------------------
123 -- List_Applicable_Restrictions --
124 ----------------------------------
126 procedure List_Applicable_Restrictions is
128 -- Define those restrictions that should be output if the gnatbind
129 -- -r switch is used. Not all restrictions are output for the reasons
130 -- given below in the list, and this array is used to test whether
131 -- the corresponding pragma should be listed. True means that it
132 -- should not be listed.
134 No_Restriction_List : constant array (All_Restrictions) of Boolean :=
135 (No_Exception_Propagation => True,
136 -- Modifies code resulting in different exception semantics
138 No_Exceptions => True,
139 -- Has unexpected Suppress (All_Checks) effect
141 No_Implicit_Conditionals => True,
142 -- This could modify and pessimize generated code
144 No_Implicit_Dynamic_Code => True,
145 -- This could modify and pessimize generated code
147 No_Implicit_Loops => True,
148 -- This could modify and pessimize generated code
150 No_Recursion => True,
151 -- Not checkable at compile time
153 No_Reentrancy => True,
154 -- Not checkable at compile time
156 Max_Entry_Queue_Length => True,
157 -- Not checkable at compile time
159 Max_Storage_At_Blocking => True,
160 -- Not checkable at compile time
162 others => False);
164 Additional_Restrictions_Listed : Boolean := False;
165 -- Set True if we have listed header for restrictions
167 function Restriction_Could_Be_Set (R : Restriction_Id) return Boolean;
168 -- Returns True if the given restriction can be listed as an additional
169 -- restriction that could be set.
171 ------------------------------
172 -- Restriction_Could_Be_Set --
173 ------------------------------
175 function Restriction_Could_Be_Set (R : Restriction_Id) return Boolean is
176 CR : Restrictions_Info renames Cumulative_Restrictions;
178 begin
179 case R is
181 -- Boolean restriction
183 when All_Boolean_Restrictions =>
185 -- The condition for listing a boolean restriction as an
186 -- additional restriction that could be set is that it is
187 -- not violated by any unit, and not already set.
189 return CR.Violated (R) = False and then CR.Set (R) = False;
191 -- Parameter restriction
193 when All_Parameter_Restrictions =>
195 -- If the restriction is violated and the level of violation is
196 -- unknown, the restriction can definitely not be listed.
198 if CR.Violated (R) and then CR.Unknown (R) then
199 return False;
201 -- We can list the restriction if it is not set
203 elsif not CR.Set (R) then
204 return True;
206 -- We can list the restriction if is set to a greater value
207 -- than the maximum value known for the violation.
209 else
210 return CR.Value (R) > CR.Count (R);
211 end if;
213 -- No other values for R possible
215 when others =>
216 raise Program_Error;
218 end case;
219 end Restriction_Could_Be_Set;
221 -- Start of processing for List_Applicable_Restrictions
223 begin
224 -- Loop through restrictions
226 for R in All_Restrictions loop
227 if not No_Restriction_List (R)
228 and then Restriction_Could_Be_Set (R)
229 then
230 if not Additional_Restrictions_Listed then
231 Write_Eol;
232 Write_Line
233 ("The following additional restrictions may be" &
234 " applied to this partition:");
235 Additional_Restrictions_Listed := True;
236 end if;
238 Write_Str ("pragma Restrictions (");
240 declare
241 S : constant String := Restriction_Id'Image (R);
242 begin
243 Name_Len := S'Length;
244 Name_Buffer (1 .. Name_Len) := S;
245 end;
247 Set_Casing (Mixed_Case);
248 Write_Str (Name_Buffer (1 .. Name_Len));
250 if R in All_Parameter_Restrictions then
251 Write_Str (" => ");
252 Write_Int (Int (Cumulative_Restrictions.Count (R)));
253 end if;
255 Write_Str (");");
256 Write_Eol;
257 end if;
258 end loop;
259 end List_Applicable_Restrictions;
261 -------------------
262 -- Scan_Bind_Arg --
263 -------------------
265 procedure Scan_Bind_Arg (Argv : String) is
266 pragma Assert (Argv'First = 1);
268 begin
269 -- Now scan arguments that are specific to the binder and are not
270 -- handled by the common circuitry in Switch.
272 if Opt.Output_File_Name_Present
273 and then not Output_File_Name_Seen
274 then
275 Output_File_Name_Seen := True;
277 if Argv'Length = 0
278 or else (Argv'Length >= 1 and then Argv (1) = '-')
279 then
280 Fail ("output File_Name missing after -o");
282 else
283 Output_File_Name := new String'(Argv);
284 end if;
286 elsif Argv'Length >= 2 and then Argv (1) = '-' then
288 -- -I-
290 if Argv (2 .. Argv'Last) = "I-" then
291 Opt.Look_In_Primary_Dir := False;
293 -- -Idir
295 elsif Argv (2) = 'I' then
296 Add_Src_Search_Dir (Argv (3 .. Argv'Last));
297 Add_Lib_Search_Dir (Argv (3 .. Argv'Last));
299 -- -Ldir
301 elsif Argv (2) = 'L' then
302 if Argv'Length >= 3 then
304 -- Remember that the -L switch was specified, so that if this
305 -- is on OpenVMS, the export names are put in uppercase.
306 -- This is not known before the target parameters are read.
308 L_Switch_Seen := True;
310 Opt.Bind_For_Library := True;
311 Opt.Ada_Init_Name :=
312 new String'(Argv (3 .. Argv'Last) & Opt.Ada_Init_Suffix);
313 Opt.Ada_Final_Name :=
314 new String'(Argv (3 .. Argv'Last) & Opt.Ada_Final_Suffix);
315 Opt.Ada_Main_Name :=
316 new String'(Argv (3 .. Argv'Last) & Opt.Ada_Main_Name_Suffix);
318 -- This option (-Lxxx) implies -n
320 Opt.Bind_Main_Program := False;
322 else
323 Fail
324 ("Prefix of initialization and finalization " &
325 "procedure names missing in -L");
326 end if;
328 -- -Sin -Slo -Shi -Sxx -Sev
330 elsif Argv'Length = 4
331 and then Argv (2) = 'S'
332 then
333 declare
334 C1 : Character := Argv (3);
335 C2 : Character := Argv (4);
337 begin
338 -- Fold to upper case
340 if C1 in 'a' .. 'z' then
341 C1 := Character'Val (Character'Pos (C1) - 32);
342 end if;
344 if C2 in 'a' .. 'z' then
345 C2 := Character'Val (Character'Pos (C2) - 32);
346 end if;
348 -- Test valid option and set mode accordingly
350 if C1 = 'E' and then C2 = 'V' then
351 null;
353 elsif C1 = 'I' and then C2 = 'N' then
354 null;
356 elsif C1 = 'L' and then C2 = 'O' then
357 null;
359 elsif C1 = 'H' and then C2 = 'I' then
360 null;
362 elsif (C1 in '0' .. '9' or else C1 in 'A' .. 'F')
363 and then
364 (C2 in '0' .. '9' or else C2 in 'A' .. 'F')
365 then
366 null;
368 -- Invalid -S switch, let Switch give error, set default of IN
370 else
371 Scan_Binder_Switches (Argv);
372 C1 := 'I';
373 C2 := 'N';
374 end if;
376 Initialize_Scalars_Mode1 := C1;
377 Initialize_Scalars_Mode2 := C2;
378 end;
380 -- -aIdir
382 elsif Argv'Length >= 3
383 and then Argv (2 .. 3) = "aI"
384 then
385 Add_Src_Search_Dir (Argv (4 .. Argv'Last));
387 -- -aOdir
389 elsif Argv'Length >= 3
390 and then Argv (2 .. 3) = "aO"
391 then
392 Add_Lib_Search_Dir (Argv (4 .. Argv'Last));
394 -- -nostdlib
396 elsif Argv (2 .. Argv'Last) = "nostdlib" then
397 Opt.No_Stdlib := True;
399 -- -nostdinc
401 elsif Argv (2 .. Argv'Last) = "nostdinc" then
402 Opt.No_Stdinc := True;
404 -- -static
406 elsif Argv (2 .. Argv'Last) = "static" then
407 Opt.Shared_Libgnat := False;
409 -- -shared
411 elsif Argv (2 .. Argv'Last) = "shared" then
412 Opt.Shared_Libgnat := True;
414 -- -F=mapping_file
416 elsif Argv'Length >= 4 and then Argv (2 .. 3) = "F=" then
417 if Mapping_File /= null then
418 Fail ("cannot specify several mapping files");
419 end if;
421 Mapping_File := new String'(Argv (4 .. Argv'Last));
423 -- -Mname
425 elsif Argv'Length >= 3 and then Argv (2) = 'M' then
426 if not Is_Cross_Compiler then
427 Write_Line
428 ("gnatbind: -M not expected to be used on native platforms");
429 end if;
431 Opt.Bind_Alternate_Main_Name := True;
432 Opt.Alternate_Main_Name := new String'(Argv (3 .. Argv'Last));
434 -- All other options are single character and are handled by
435 -- Scan_Binder_Switches.
437 else
438 Scan_Binder_Switches (Argv);
439 end if;
441 -- Not a switch, so must be a file name (if non-empty)
443 elsif Argv'Length /= 0 then
444 if Argv'Length > 4
445 and then Argv (Argv'Last - 3 .. Argv'Last) = ".ali"
446 then
447 Add_File (Argv);
448 else
449 Add_File (Argv & ".ali");
450 end if;
451 end if;
452 end Scan_Bind_Arg;
454 procedure Check_Version_And_Help is
455 new Check_Version_And_Help_G (Bindusg.Display);
457 -- Start of processing for Gnatbind
459 begin
461 -- Set default for Shared_Libgnat option
463 declare
464 Shared_Libgnat_Default : Character;
465 pragma Import
466 (C, Shared_Libgnat_Default, "__gnat_shared_libgnat_default");
468 SHARED : constant Character := 'H';
469 STATIC : constant Character := 'T';
471 begin
472 pragma Assert
473 (Shared_Libgnat_Default = SHARED
474 or else
475 Shared_Libgnat_Default = STATIC);
476 Shared_Libgnat := (Shared_Libgnat_Default = SHARED);
477 end;
479 -- Scan the switches and arguments
481 -- First, scan to detect --version and/or --help
483 Check_Version_And_Help ("GNATBIND", "1995");
485 -- Use low level argument routines to avoid dragging in the secondary stack
487 Next_Arg := 1;
488 Scan_Args : while Next_Arg < Arg_Count loop
489 declare
490 Next_Argv : String (1 .. Len_Arg (Next_Arg));
491 begin
492 Fill_Arg (Next_Argv'Address, Next_Arg);
494 if Next_Argv'Length > 0 then
495 if Next_Argv (1) = '@' then
496 if Next_Argv'Length > 1 then
497 declare
498 Arguments : constant Argument_List :=
499 Response_File.Arguments_From
500 (Response_File_Name =>
501 Next_Argv (2 .. Next_Argv'Last),
502 Recursive => True,
503 Ignore_Non_Existing_Files => True);
504 begin
505 for J in Arguments'Range loop
506 Scan_Bind_Arg (Arguments (J).all);
507 end loop;
508 end;
509 end if;
511 else
512 Scan_Bind_Arg (Next_Argv);
513 end if;
514 end if;
515 end;
517 Next_Arg := Next_Arg + 1;
518 end loop Scan_Args;
520 if Use_Pragma_Linker_Constructor then
521 if Bind_Main_Program then
522 Fail ("switch -a must be used in conjunction with -n or -Lxxx");
524 elsif not Gnatbind_Supports_Auto_Init then
525 Fail ("automatic initialisation of elaboration " &
526 "not supported on this platform");
527 end if;
528 end if;
530 -- Test for trailing -o switch
532 if Opt.Output_File_Name_Present
533 and then not Output_File_Name_Seen
534 then
535 Fail ("output file name missing after -o");
536 end if;
538 -- Output usage if requested
540 if Usage_Requested then
541 Bindusg.Display;
542 end if;
544 -- Check that the Ada binder file specified has extension .adb and that
545 -- the C binder file has extension .c
547 if Opt.Output_File_Name_Present
548 and then Output_File_Name_Seen
549 then
550 Check_Extensions : declare
551 Length : constant Natural := Output_File_Name'Length;
552 Last : constant Natural := Output_File_Name'Last;
554 begin
555 if Ada_Bind_File then
556 if Length <= 4
557 or else Output_File_Name (Last - 3 .. Last) /= ".adb"
558 then
559 Fail ("output file name should have .adb extension");
560 end if;
562 else
563 if Length <= 2
564 or else Output_File_Name (Last - 1 .. Last) /= ".c"
565 then
566 Fail ("output file name should have .c extension");
567 end if;
568 end if;
569 end Check_Extensions;
570 end if;
572 Osint.Add_Default_Search_Dirs;
574 -- Carry out package initializations. These are initializations which
575 -- might logically be performed at elaboration time, but Namet at least
576 -- can't be done that way (because it is used in the Compiler), and we
577 -- decide to be consistent. Like elaboration, the order in which these
578 -- calls are made is in some cases important.
580 Csets.Initialize;
581 Namet.Initialize;
582 Snames.Initialize;
584 -- Acquire target parameters
586 Targparm.Get_Target_Parameters;
588 -- Initialize Cumulative_Restrictions with the restrictions on the target
589 -- scanned from the system.ads file. Then as we read ALI files, we will
590 -- accumulate additional restrictions specified in other files.
592 Cumulative_Restrictions := Targparm.Restrictions_On_Target;
594 -- On OpenVMS, when -L is used, all external names used in pragmas Export
595 -- are in upper case. The reason is that on OpenVMS, the macro-assembler
596 -- MACASM-32, used to build Stand-Alone Libraries, only understands
597 -- uppercase.
599 if L_Switch_Seen and then OpenVMS_On_Target then
600 To_Upper (Opt.Ada_Init_Name.all);
601 To_Upper (Opt.Ada_Final_Name.all);
602 To_Upper (Opt.Ada_Main_Name.all);
603 end if;
605 -- Acquire configurable run-time mode
607 if Configurable_Run_Time_On_Target then
608 Configurable_Run_Time_Mode := True;
609 end if;
611 -- Output copyright notice if in verbose mode
613 if Verbose_Mode then
614 Write_Eol;
615 Display_Version ("GNATBIND", "1995");
616 end if;
618 -- Output usage information if no files
620 if not More_Lib_Files then
621 Bindusg.Display;
622 Exit_Program (E_Fatal);
623 end if;
625 -- If a mapping file was specified, initialize the file mapping
627 if Mapping_File /= null then
628 Fmap.Initialize (Mapping_File.all);
629 end if;
631 -- The block here is to catch the Unrecoverable_Error exception in the
632 -- case where we exceed the maximum number of permissible errors or some
633 -- other unrecoverable error occurs.
635 begin
636 -- Initialize binder packages
638 Initialize_Binderr;
639 Initialize_ALI;
640 Initialize_ALI_Source;
642 if Verbose_Mode then
643 Write_Eol;
644 end if;
646 -- Input ALI files
648 while More_Lib_Files loop
649 Main_Lib_File := Next_Main_Lib_File;
651 if First_Main_Lib_File = No_File then
652 First_Main_Lib_File := Main_Lib_File;
653 end if;
655 if Verbose_Mode then
656 if Check_Only then
657 Write_Str ("Checking: ");
658 else
659 Write_Str ("Binding: ");
660 end if;
662 Write_Name (Main_Lib_File);
663 Write_Eol;
664 end if;
666 Text := Read_Library_Info (Main_Lib_File, True);
668 declare
669 Id : ALI_Id;
670 pragma Warnings (Off, Id);
672 begin
673 Id := Scan_ALI
674 (F => Main_Lib_File,
675 T => Text,
676 Ignore_ED => False,
677 Err => False,
678 Ignore_Errors => Debug_Flag_I);
679 end;
681 Free (Text);
682 end loop;
684 -- No_Run_Time mode
686 if No_Run_Time_Mode then
688 -- Set standard configuration parameters
690 Suppress_Standard_Library_On_Target := True;
691 Configurable_Run_Time_Mode := True;
692 end if;
694 -- For main ALI files, even if they are interfaces, we get their
695 -- dependencies. To be sure, we reset the Interface flag for all main
696 -- ALI files.
698 for Index in ALIs.First .. ALIs.Last loop
699 ALIs.Table (Index).SAL_Interface := False;
700 end loop;
702 -- Add System.Standard_Library to list to ensure that these files are
703 -- included in the bind, even if not directly referenced from Ada code
704 -- This is suppressed if the appropriate targparm switch is set.
706 if not Suppress_Standard_Library_On_Target then
707 Name_Buffer (1 .. 12) := "s-stalib.ali";
708 Name_Len := 12;
709 Std_Lib_File := Name_Find;
710 Text := Read_Library_Info (Std_Lib_File, True);
712 declare
713 Id : ALI_Id;
714 pragma Warnings (Off, Id);
716 begin
717 Id :=
718 Scan_ALI
719 (F => Std_Lib_File,
720 T => Text,
721 Ignore_ED => False,
722 Err => False,
723 Ignore_Errors => Debug_Flag_I);
724 end;
726 Free (Text);
727 end if;
729 -- Acquire all information in ALI files that have been read in
731 for Index in ALIs.First .. ALIs.Last loop
732 Read_ALI (Index);
733 end loop;
735 -- Quit if some file needs compiling
737 if No_Object_Specified then
738 raise Unrecoverable_Error;
739 end if;
741 -- Build source file table from the ALI files we have read in
743 Set_Source_Table;
745 -- If there is main program to bind, set Main_Lib_File to the first
746 -- library file, and the name from which to derive the binder generate
747 -- file to the first ALI file.
749 if Bind_Main_Program then
750 Main_Lib_File := First_Main_Lib_File;
751 Set_Current_File_Name_Index (To => 1);
752 end if;
754 -- Check that main library file is a suitable main program
756 if Bind_Main_Program
757 and then ALIs.Table (ALIs.First).Main_Program = None
758 and then not No_Main_Subprogram
759 then
760 Error_Msg_File_1 := Main_Lib_File;
761 Error_Msg ("{ does not contain a unit that can be a main program");
762 end if;
764 -- Perform consistency and correctness checks
766 Check_Duplicated_Subunits;
767 Check_Versions;
768 Check_Consistency;
769 Check_Configuration_Consistency;
771 -- List restrictions that could be applied to this partition
773 if List_Restrictions then
774 List_Applicable_Restrictions;
775 end if;
777 -- Complete bind if no errors
779 if Errors_Detected = 0 then
780 Find_Elab_Order;
782 if Errors_Detected = 0 then
783 -- Display elaboration order if -l was specified
785 if Elab_Order_Output then
786 if not Zero_Formatting then
787 Write_Eol;
788 Write_Str ("ELABORATION ORDER");
789 Write_Eol;
790 end if;
792 for J in Elab_Order.First .. Elab_Order.Last loop
793 if not Units.Table (Elab_Order.Table (J)).SAL_Interface then
794 if not Zero_Formatting then
795 Write_Str (" ");
796 end if;
798 Write_Unit_Name
799 (Units.Table (Elab_Order.Table (J)).Uname);
800 Write_Eol;
801 end if;
802 end loop;
804 if not Zero_Formatting then
805 Write_Eol;
806 end if;
807 end if;
809 if not Check_Only then
810 Gen_Output_File (Output_File_Name.all);
811 end if;
813 -- Display list of sources in the closure (except predefined
814 -- sources) if -R was used.
816 if List_Closure then
817 if not Zero_Formatting then
818 Write_Eol;
819 Write_Str ("REFERENCED SOURCES");
820 Write_Eol;
821 end if;
823 for J in reverse Elab_Order.First .. Elab_Order.Last loop
825 -- Do not include the sources of the runtime
827 if not Is_Internal_File_Name
828 (Units.Table (Elab_Order.Table (J)).Sfile)
829 then
830 if not Zero_Formatting then
831 Write_Str (" ");
832 end if;
834 Write_Str
835 (Get_Name_String
836 (Units.Table (Elab_Order.Table (J)).Sfile));
837 Write_Eol;
838 end if;
839 end loop;
841 if not Zero_Formatting then
842 Write_Eol;
843 end if;
844 end if;
845 end if;
846 end if;
848 Total_Errors := Total_Errors + Errors_Detected;
849 Total_Warnings := Total_Warnings + Warnings_Detected;
851 exception
852 when Unrecoverable_Error =>
853 Total_Errors := Total_Errors + Errors_Detected;
854 Total_Warnings := Total_Warnings + Warnings_Detected;
855 end;
857 -- All done. Set proper exit status
859 Finalize_Binderr;
860 Namet.Finalize;
862 if Total_Errors > 0 then
863 Exit_Program (E_Errors);
865 elsif Total_Warnings > 0 then
866 Exit_Program (E_Warnings);
868 else
869 -- Do not call Exit_Program (E_Success), so that finalization occurs
870 -- normally.
872 null;
873 end if;
875 end Gnatbind;