1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 1992-2014, Free Software Foundation, Inc. --
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. --
21 -- GNAT was originally developed by the GNAT team at New York University. --
22 -- Extensive contributions were provided by Ada Core Technologies Inc. --
24 ------------------------------------------------------------------------------
27 with ALI
.Util
; use ALI
.Util
;
28 with Binderr
; use Binderr
;
29 with Butil
; use Butil
;
30 with Csets
; use Csets
;
31 with Fname
; use Fname
;
32 with Gnatvsn
; use Gnatvsn
;
33 with GNAT
.OS_Lib
; use GNAT
.OS_Lib
;
34 with Namet
; use Namet
;
36 with Osint
; use Osint
;
37 with Osint
.L
; use Osint
.L
;
38 with Output
; use Output
;
39 with Prj
.Env
; use Prj
.Env
;
40 with Rident
; use Rident
;
44 with Switch
; use Switch
;
45 with Types
; use Types
;
47 with Ada
.Command_Line
; use Ada
.Command_Line
;
49 with GNAT
.Command_Line
; use GNAT
.Command_Line
;
50 with GNAT
.Case_Util
; use GNAT
.Case_Util
;
53 pragma Ident
(Gnat_Static_Version_String
);
55 -- NOTE : The following string may be used by other tools, such as GPS. So
56 -- it can only be modified if these other uses are checked and coordinated.
58 Project_Search_Path
: constant String := "Project Search Path:";
59 -- Label displayed in verbose mode before the directories in the project
60 -- search path. Do not modify without checking NOTE above.
62 Prj_Path
: Prj
.Env
.Project_Search_Path
;
64 Max_Column
: constant := 80;
66 No_Obj
: aliased String := "<no_obj>";
68 No_Runtime
: Boolean := False;
69 -- Set to True if there is no default runtime and --RTS= is not specified
72 OK
, -- matching timestamp
73 Checksum_OK
, -- only matching checksum
74 Not_Found
, -- file not found on source PATH
75 Not_Same
, -- neither checksum nor timestamp matching
76 Not_First_On_PATH
); -- matching file hidden by Not_Same file on path
79 type Dir_Ref
is access Dir_Data
;
81 type Dir_Data
is record
82 Value
: String_Access
;
85 -- Simply linked list of dirs
87 First_Source_Dir
: Dir_Ref
;
88 Last_Source_Dir
: Dir_Ref
;
89 -- The list of source directories from the command line.
90 -- These directories are added using Osint.Add_Src_Search_Dir
91 -- after those of the GNAT Project File, if any.
93 First_Lib_Dir
: Dir_Ref
;
94 Last_Lib_Dir
: Dir_Ref
;
95 -- The list of object directories from the command line.
96 -- These directories are added using Osint.Add_Lib_Search_Dir
97 -- after those of the GNAT Project File, if any.
99 Main_File
: File_Name_Type
;
100 Ali_File
: File_Name_Type
;
101 Text
: Text_Buffer_Ptr
;
104 Too_Long
: Boolean := False;
105 -- When True, lines are too long for multi-column output and each
106 -- item of information is on a different line.
108 Selective_Output
: Boolean := False;
109 Print_Usage
: Boolean := False;
110 Print_Unit
: Boolean := True;
111 Print_Source
: Boolean := True;
112 Print_Object
: Boolean := True;
113 -- Flags controlling the form of the output
115 Also_Predef
: Boolean := False; -- -a
116 Dependable
: Boolean := False; -- -d
117 License
: Boolean := False; -- -l
118 Very_Verbose_Mode
: Boolean := False; -- -V
119 -- Command line flags
121 Unit_Start
: Integer;
123 Source_Start
: Integer;
124 Source_End
: Integer;
125 Object_Start
: Integer;
126 Object_End
: Integer;
127 -- Various column starts and ends
129 Spaces
: constant String (1 .. Max_Column
) := (others => ' ');
131 RTS_Specified
: String_Access
:= null;
132 -- Used to detect multiple use of --RTS= switch
134 Exit_Status
: Exit_Code_Type
:= E_Success
;
135 -- Reset to E_Fatal if bad error found
137 -----------------------
138 -- Local Subprograms --
139 -----------------------
141 procedure Add_Lib_Dir
(Dir
: String);
142 -- Add an object directory in the list First_Lib_Dir-Last_Lib_Dir
144 procedure Add_Source_Dir
(Dir
: String);
145 -- Add a source directory in the list First_Source_Dir-Last_Source_Dir
147 procedure Find_General_Layout
;
148 -- Determine the structure of the output (multi columns or not, etc)
150 procedure Find_Status
151 (FS
: in out File_Name_Type
;
152 Stamp
: Time_Stamp_Type
;
154 Status
: out File_Status
);
155 -- Determine the file status (Status) of the file represented by FS with
156 -- the expected Stamp and checksum given as argument. FS will be updated
157 -- to the full file name if available.
159 function Corresponding_Sdep_Entry
(A
: ALI_Id
; U
: Unit_Id
) return Sdep_Id
;
160 -- Give the Sdep entry corresponding to the unit U in ali record A
162 procedure Output_Object
(O
: File_Name_Type
);
163 -- Print out the name of the object when requested
165 procedure Output_Source
(Sdep_I
: Sdep_Id
);
166 -- Print out the name and status of the source corresponding to this
169 procedure Output_Status
(FS
: File_Status
; Verbose
: Boolean);
170 -- Print out FS either in a coded form if verbose is false or in an
171 -- expanded form otherwise.
173 procedure Output_Unit
(ALI
: ALI_Id
; U_Id
: Unit_Id
);
174 -- Print out information on the unit when requested
176 procedure Reset_Print
;
177 -- Reset Print flags properly when selective output is chosen
179 procedure Scan_Ls_Arg
(Argv
: String);
180 -- Scan and process user specific arguments (Argv is a single argument)
182 procedure Search_RTS
(Name
: String);
183 -- Find include and objects path for the RTS name.
186 -- Print usage message
188 procedure Output_License_Information
;
189 -- Output license statement, and if not found, output reference to COPYING
191 function Image
(Restriction
: Restriction_Id
) return String;
192 -- Returns the capitalized image of Restriction
194 function Normalize
(Path
: String) return String;
195 -- Returns a normalized path name. On Windows, the directory separators are
196 -- set to '\' in Normalize_Pathname.
198 ------------------------------------------
199 -- GNATDIST specific output subprograms --
200 ------------------------------------------
204 -- Any modification to this subunit requires synchronization with the
207 procedure Output_ALI
(A
: ALI_Id
);
208 -- Comment required saying what this routine does ???
210 procedure Output_No_ALI
(Afile
: File_Name_Type
);
211 -- Comments required saying what this routine does ???
219 procedure Add_Lib_Dir
(Dir
: String) is
221 if First_Lib_Dir
= null then
224 (Value => new String'(Dir
),
226 Last_Lib_Dir
:= First_Lib_Dir
;
231 (Value => new String'(Dir
),
233 Last_Lib_Dir
:= Last_Lib_Dir
.Next
;
241 procedure Add_Source_Dir
(Dir
: String) is
243 if First_Source_Dir
= null then
246 (Value => new String'(Dir
),
248 Last_Source_Dir
:= First_Source_Dir
;
251 Last_Source_Dir
.Next
:=
253 (Value => new String'(Dir
),
255 Last_Source_Dir
:= Last_Source_Dir
.Next
;
259 ------------------------------
260 -- Corresponding_Sdep_Entry --
261 ------------------------------
263 function Corresponding_Sdep_Entry
265 U
: Unit_Id
) return Sdep_Id
268 for D
in ALIs
.Table
(A
).First_Sdep
.. ALIs
.Table
(A
).Last_Sdep
loop
269 if Sdep
.Table
(D
).Sfile
= Units
.Table
(U
).Sfile
then
274 Error_Msg_Unit_1
:= Units
.Table
(U
).Uname
;
275 Error_Msg_File_1
:= ALIs
.Table
(A
).Afile
;
277 Error_Msg
("wrong ALI format, can't find dependency line for $ in {");
278 Exit_Program
(E_Fatal
);
280 end Corresponding_Sdep_Entry
;
282 -------------------------
283 -- Find_General_Layout --
284 -------------------------
286 procedure Find_General_Layout
is
287 Max_Unit_Length
: Integer := 11;
288 Max_Src_Length
: Integer := 11;
289 Max_Obj_Length
: Integer := 11;
295 -- Compute maximum of each column
297 for Id
in ALIs
.First
.. ALIs
.Last
loop
298 Get_Name_String
(Units
.Table
(ALIs
.Table
(Id
).First_Unit
).Uname
);
299 if Also_Predef
or else not Is_Internal_Unit
then
303 Max_Unit_Length
:= Integer'Max (Max_Unit_Length
, Len
);
307 FS
:= Full_Source_Name
(ALIs
.Table
(Id
).Sfile
);
310 Get_Name_String
(ALIs
.Table
(Id
).Sfile
);
311 Name_Len
:= Name_Len
+ 13;
313 Get_Name_String
(FS
);
316 Max_Src_Length
:= Integer'Max (Max_Src_Length
, Name_Len
+ 1);
320 if ALIs
.Table
(Id
).No_Object
then
322 Integer'Max (Max_Obj_Length
, No_Obj
'Length);
324 Get_Name_String
(ALIs
.Table
(Id
).Ofile_Full_Name
);
325 Max_Obj_Length
:= Integer'Max (Max_Obj_Length
, Name_Len
+ 1);
331 -- Verify is output is not wider than maximum number of columns
336 (Max_Unit_Length
+ Max_Src_Length
+ Max_Obj_Length
) > Max_Column
;
338 -- Set start and end of columns
341 Object_End
:= Object_Start
- 1;
344 Object_End
:= Object_Start
+ Max_Obj_Length
;
347 Unit_Start
:= Object_End
+ 1;
348 Unit_End
:= Unit_Start
- 1;
351 Unit_End
:= Unit_Start
+ Max_Unit_Length
;
354 Source_Start
:= Unit_End
+ 1;
356 if Source_Start
> Spaces
'Last then
357 Source_Start
:= Spaces
'Last;
360 Source_End
:= Source_Start
- 1;
363 Source_End
:= Source_Start
+ Max_Src_Length
;
365 end Find_General_Layout
;
371 procedure Find_Status
372 (FS
: in out File_Name_Type
;
373 Stamp
: Time_Stamp_Type
;
375 Status
: out File_Status
)
377 Tmp1
: File_Name_Type
;
378 Tmp2
: File_Name_Type
;
381 Tmp1
:= Full_Source_Name
(FS
);
383 if Tmp1
= No_File
then
386 elsif File_Stamp
(Tmp1
) = Stamp
then
390 elsif Checksums_Match
(Get_File_Checksum
(FS
), Checksum
) then
392 Status
:= Checksum_OK
;
395 Tmp2
:= Matching_Full_Source_Name
(FS
, Stamp
);
397 if Tmp2
= No_File
then
402 Status
:= Not_First_On_PATH
;
412 package body GNATDIST
is
415 N_Indents
: Natural := 0;
446 Image
: constant array (Token_Type
) of String_Access
:=
447 (T_No_ALI
=> new String'("No_ALI"),
448 T_ALI => new String'("ALI"),
449 T_Unit
=> new String'("Unit"),
450 T_With => new String'("With"),
451 T_Source
=> new String'("Source"),
452 T_Afile => new String'("Afile"),
453 T_Ofile
=> new String'("Ofile"),
454 T_Sfile => new String'("Sfile"),
455 T_Name
=> new String'("Name"),
456 T_Main => new String'("Main"),
457 T_Kind
=> new String'("Kind"),
458 T_Flags => new String'("Flags"),
459 T_Preelaborated
=> new String'("Preelaborated"),
460 T_Pure => new String'("Pure"),
461 T_Has_RACW
=> new String'("Has_RACW"),
462 T_Remote_Types => new String'("Remote_Types"),
463 T_Shared_Passive
=> new String'("Shared_Passive"),
464 T_RCI => new String'("RCI"),
465 T_Predefined
=> new String'("Predefined"),
466 T_Internal => new String'("Internal"),
467 T_Is_Generic
=> new String'("Is_Generic"),
468 T_Procedure => new String'("procedure"),
469 T_Function
=> new String'("function"),
470 T_Package => new String'("package"),
471 T_Subprogram
=> new String'("subprogram"),
472 T_Spec => new String'("spec"),
473 T_Body
=> new String'("body"));
475 procedure Output_Name (N : Name_Id);
476 -- Remove any encoding info (%b and %s) and output N
478 procedure Output_Afile (A : File_Name_Type);
479 procedure Output_Ofile (O : File_Name_Type);
480 procedure Output_Sfile (S : File_Name_Type);
481 -- Output various names. Check that the name is different from no name.
482 -- Otherwise, skip the output.
484 procedure Output_Token (T : Token_Type);
485 -- Output token using specific format. That is several indentations and:
487 -- T_No_ALI .. T_With : <token> & " =>" & NL
488 -- T_Source .. T_Kind : <token> & " => "
489 -- T_Flags : <token> & " =>"
490 -- T_Preelab .. T_Body : " " & <token>
492 procedure Output_Sdep (S : Sdep_Id);
493 procedure Output_Unit (U : Unit_Id);
494 procedure Output_With (W : With_Id);
495 -- Output this entry as a global section (like ALIs)
501 procedure Output_Afile (A : File_Name_Type) is
504 Output_Token (T_Afile);
514 procedure Output_ALI (A : ALI_Id) is
516 Output_Token (T_ALI);
517 N_Indents := N_Indents + 1;
519 Output_Afile (ALIs.Table (A).Afile);
520 Output_Ofile (ALIs.Table (A).Ofile_Full_Name);
521 Output_Sfile (ALIs.Table (A).Sfile);
525 if ALIs.Table (A).Main_Program /= None then
526 Output_Token (T_Main);
528 if ALIs.Table (A).Main_Program = Proc then
529 Output_Token (T_Procedure);
531 Output_Token (T_Function);
539 for U in ALIs.Table (A).First_Unit .. ALIs.Table (A).Last_Unit loop
545 for S in ALIs.Table (A).First_Sdep .. ALIs.Table (A).Last_Sdep loop
549 N_Indents := N_Indents - 1;
556 procedure Output_No_ALI (Afile : File_Name_Type) is
558 Output_Token (T_No_ALI);
559 N_Indents := N_Indents + 1;
560 Output_Afile (Afile);
561 N_Indents := N_Indents - 1;
568 procedure Output_Name (N : Name_Id) is
570 -- Remove any encoding info (%s or %b)
575 and then Name_Buffer (Name_Len - 1) = '%'
577 Name_Len := Name_Len - 2;
580 Output_Token (T_Name);
581 Write_Str (Name_Buffer (1 .. Name_Len));
589 procedure Output_Ofile (O : File_Name_Type) is
592 Output_Token (T_Ofile);
602 procedure Output_Sdep (S : Sdep_Id) is
604 Output_Token (T_Source);
605 Write_Name (Sdep.Table (S).Sfile);
613 procedure Output_Sfile (S : File_Name_Type) is
614 FS : File_Name_Type := S;
617 if FS /= No_File then
619 -- We want to output the full source name
621 FS := Full_Source_Name (FS);
623 -- There is no full source name. This occurs for instance when a
624 -- withed unit has a spec file but no body file. This situation is
625 -- not a problem for GNATDIST since the unit may be located on a
626 -- partition we do not want to build. However, we need to locate
627 -- the spec file and to find its full source name. Replace the
628 -- body file name with the spec file name used to compile the
629 -- current unit when possible.
635 and then Name_Buffer (Name_Len - 3 .. Name_Len) = ".adb"
637 Name_Buffer (Name_Len) := 's
';
638 FS := Full_Source_Name (Name_Find);
643 if FS /= No_File then
644 Output_Token (T_Sfile);
654 procedure Output_Token (T : Token_Type) is
656 if T in T_No_ALI .. T_Flags then
657 for J in 1 .. N_Indents loop
661 Write_Str (Image (T).all);
663 for J in Image (T)'Length .. 12 loop
669 if T in T_No_ALI .. T_With then
671 elsif T in T_Source .. T_Name then
675 elsif T in T_Preelaborated .. T_Body then
676 if T in T_Preelaborated .. T_Is_Generic then
678 Output_Token (T_Flags);
681 N_Flags := N_Flags + 1;
685 Write_Str (Image (T).all);
688 Write_Str (Image (T).all);
696 procedure Output_Unit (U : Unit_Id) is
698 Output_Token (T_Unit);
699 N_Indents := N_Indents + 1;
703 Output_Name (Name_Id (Units.Table (U).Uname));
707 Output_Token (T_Kind);
709 if Units.Table (U).Unit_Kind = 'p
' then
710 Output_Token (T_Package);
712 Output_Token (T_Subprogram);
715 if Name_Buffer (Name_Len) = 's
' then
716 Output_Token (T_Spec);
718 Output_Token (T_Body);
723 -- Output source file name
725 Output_Sfile (Units.Table (U).Sfile);
731 if Units.Table (U).Preelab then
732 Output_Token (T_Preelaborated);
735 if Units.Table (U).Pure then
736 Output_Token (T_Pure);
739 if Units.Table (U).Has_RACW then
740 Output_Token (T_Has_RACW);
743 if Units.Table (U).Remote_Types then
744 Output_Token (T_Remote_Types);
747 if Units.Table (U).Shared_Passive then
748 Output_Token (T_Shared_Passive);
751 if Units.Table (U).RCI then
752 Output_Token (T_RCI);
755 if Units.Table (U).Predefined then
756 Output_Token (T_Predefined);
759 if Units.Table (U).Internal then
760 Output_Token (T_Internal);
763 if Units.Table (U).Is_Generic then
764 Output_Token (T_Is_Generic);
773 for W in Units.Table (U).First_With .. Units.Table (U).Last_With loop
777 N_Indents := N_Indents - 1;
784 procedure Output_With (W : With_Id) is
786 Output_Token (T_With);
787 N_Indents := N_Indents + 1;
789 Output_Name (Name_Id (Withs.Table (W).Uname));
793 Output_Token (T_Kind);
795 if Name_Buffer (Name_Len) = 's
' then
796 Output_Token (T_Spec);
798 Output_Token (T_Body);
803 Output_Afile (Withs.Table (W).Afile);
804 Output_Sfile (Withs.Table (W).Sfile);
806 N_Indents := N_Indents - 1;
815 function Image (Restriction : Restriction_Id) return String is
816 Result : String := Restriction'Img;
817 Skip : Boolean := True;
820 for J in Result'Range loop
823 Result (J) := To_Upper (Result (J));
825 elsif Result (J) = '_
' then
829 Result (J) := To_Lower (Result (J));
840 function Normalize (Path : String) return String is
842 return Normalize_Pathname (Path);
845 --------------------------------
846 -- Output_License_Information --
847 --------------------------------
849 procedure Output_License_Information is
853 Write_Str ("Please refer to file COPYING in your distribution"
854 & " for license terms.");
858 Exit_Program (E_Success);
859 end Output_License_Information;
865 procedure Output_Object (O : File_Name_Type) is
866 Object_Name : String_Access;
872 Object_Name := To_Host_File_Spec (Name_Buffer (1 .. Name_Len));
874 Object_Name := No_Obj'Unchecked_Access;
877 Write_Str (Object_Name.all);
879 if Print_Source or else Print_Unit then
885 (Object_Start + Object_Name'Length .. Object_End));
895 procedure Output_Source (Sdep_I : Sdep_Id) is
896 Stamp : Time_Stamp_Type;
899 Status : File_Status;
900 Object_Name : String_Access;
903 if Sdep_I = No_Sdep_Id then
907 Stamp := Sdep.Table (Sdep_I).Stamp;
908 Checksum := Sdep.Table (Sdep_I).Checksum;
909 FS := Sdep.Table (Sdep_I).Sfile;
912 Find_Status (FS, Stamp, Checksum, Status);
913 Get_Name_String (FS);
915 Object_Name := To_Host_File_Spec (Name_Buffer (1 .. Name_Len));
918 Write_Str (" Source => ");
919 Write_Str (Object_Name.all);
923 (Spaces (Source_Start + Object_Name'Length .. Source_End));
926 Output_Status (Status, Verbose => True);
931 if not Selective_Output then
932 Output_Status (Status, Verbose => False);
935 Write_Str (Object_Name.all);
944 procedure Output_Status (FS : File_Status; Verbose : Boolean) is
949 Write_Str (" unchanged");
952 Write_Str (" slightly modified");
955 Write_Str (" file not found");
958 Write_Str (" modified");
960 when Not_First_On_PATH =>
961 Write_Str (" unchanged version not first on PATH");
978 when Not_First_On_PATH =>
988 procedure Output_Unit (ALI : ALI_Id; U_Id : Unit_Id) is
990 U : Unit_Record renames Units.Table (U_Id);
994 Get_Name_String (U.Uname);
995 Kind := Name_Buffer (Name_Len);
996 Name_Len := Name_Len - 2;
998 if not Verbose_Mode then
999 Write_Str (Name_Buffer (1 .. Name_Len));
1002 Write_Str ("Unit => ");
1004 Write_Str (" Name => ");
1005 Write_Str (Name_Buffer (1 .. Name_Len));
1007 Write_Str (" Kind => ");
1009 if Units.Table (U_Id).Unit_Kind = 'p
' then
1010 Write_Str ("package ");
1012 Write_Str ("subprogram ");
1022 if Verbose_Mode then
1023 if U.Preelab or else
1026 U.Dynamic_Elab or else
1028 U.Remote_Types or else
1029 U.Shared_Passive or else
1031 U.Predefined or else
1033 U.Is_Generic or else
1034 U.Init_Scalars or else
1035 U.SAL_Interface or else
1036 U.Body_Needed_For_SAL or else
1040 Write_Str (" Flags =>");
1043 Write_Str (" Preelaborable");
1047 Write_Str (" No_Elab_Code");
1051 Write_Str (" Pure");
1054 if U.Dynamic_Elab then
1055 Write_Str (" Dynamic_Elab");
1059 Write_Str (" Has_RACW");
1062 if U.Remote_Types then
1063 Write_Str (" Remote_Types");
1066 if U.Shared_Passive then
1067 Write_Str (" Shared_Passive");
1074 if U.Predefined then
1075 Write_Str (" Predefined");
1079 Write_Str (" Internal");
1082 if U.Is_Generic then
1083 Write_Str (" Is_Generic");
1086 if U.Init_Scalars then
1087 Write_Str (" Init_Scalars");
1090 if U.SAL_Interface then
1091 Write_Str (" SAL_Interface");
1094 if U.Body_Needed_For_SAL then
1095 Write_Str (" Body_Needed_For_SAL");
1098 if U.Elaborate_Body then
1099 Write_Str (" Elaborate Body");
1102 if U.Remote_Types then
1103 Write_Str (" Remote_Types");
1106 if U.Shared_Passive then
1107 Write_Str (" Shared_Passive");
1110 if U.Predefined then
1111 Write_Str (" Predefined");
1116 Restrictions : constant Restrictions_Info :=
1117 ALIs.Table (ALI).Restrictions;
1120 -- If the source was compiled with pragmas Restrictions,
1121 -- Display these restrictions.
1123 if Restrictions.Set /= (All_Restrictions => False) then
1125 Write_Str (" pragma Restrictions =>");
1127 -- For boolean restrictions, just display the name of the
1128 -- restriction; for valued restrictions, also display the
1129 -- restriction value.
1131 for Restriction in All_Restrictions loop
1132 if Restrictions.Set (Restriction) then
1135 Write_Str (Image (Restriction));
1137 if Restriction in All_Parameter_Restrictions then
1139 Write_Str (Restrictions.Value (Restriction)'Img);
1145 -- If the unit violates some Restrictions, display the list of
1146 -- these restrictions.
1148 if Restrictions.Violated /= (All_Restrictions => False) then
1150 Write_Str (" Restrictions violated =>");
1152 -- For boolean restrictions, just display the name of the
1153 -- restriction. For valued restrictions, also display the
1154 -- restriction value.
1156 for Restriction in All_Restrictions loop
1157 if Restrictions.Violated (Restriction) then
1160 Write_Str (Image (Restriction));
1162 if Restriction in All_Parameter_Restrictions then
1163 if Restrictions.Count (Restriction) > 0 then
1166 if Restrictions.Unknown (Restriction) then
1167 Write_Str (" at least");
1170 Write_Str (Restrictions.Count (Restriction)'Img);
1179 if Print_Source then
1184 Write_Str (Spaces (Unit_Start + Name_Len + 1 .. Unit_End));
1194 procedure Reset_Print is
1196 if not Selective_Output then
1197 Selective_Output := True;
1198 Print_Source := False;
1199 Print_Object := False;
1200 Print_Unit := False;
1208 procedure Search_RTS (Name : String) is
1209 Src_Path : String_Ptr;
1210 Lib_Path : String_Ptr;
1211 -- Paths for source and include subdirs
1213 Rts_Full_Path : String_Access;
1214 -- Full path for RTS project
1217 -- Try to find the RTS
1219 Src_Path := Get_RTS_Search_Dir (Name, Include);
1220 Lib_Path := Get_RTS_Search_Dir (Name, Objects);
1222 -- For non-project RTS, both the include and the objects directories
1225 if Src_Path /= null and then Lib_Path /= null then
1226 Add_Search_Dirs (Src_Path, Include);
1227 Add_Search_Dirs (Lib_Path, Objects);
1231 if Lib_Path /= null then
1232 Osint.Fail ("RTS path not valid: missing adainclude directory");
1233 elsif Src_Path /= null then
1234 Osint.Fail ("RTS path not valid: missing adalib directory");
1237 -- Try to find the RTS on the project path. First setup the project path
1239 Initialize_Default_Project_Path
1240 (Prj_Path, Target_Name => Sdefault.Target_Name.all);
1242 Rts_Full_Path := Get_Runtime_Path (Prj_Path, Name);
1244 if Rts_Full_Path /= null then
1246 -- Directory name was found on the project path. Look for the
1247 -- include subdirectory(s).
1249 Src_Path := Get_RTS_Search_Dir (Rts_Full_Path.all, Include);
1251 if Src_Path /= null then
1252 Add_Search_Dirs (Src_Path, Include);
1254 -- Add the lib subdirectory if it exists
1256 Lib_Path := Get_RTS_Search_Dir (Rts_Full_Path.all, Objects);
1258 if Lib_Path /= null then
1259 Add_Search_Dirs (Lib_Path, Objects);
1267 ("RTS path not valid: missing adainclude and adalib directories");
1274 procedure Scan_Ls_Arg (Argv : String) is
1275 FD : File_Descriptor;
1280 pragma Assert (Argv'First = 1);
1282 if Argv'Length = 0 then
1287 if Argv (1) = '-' then
1288 if Argv'Length = 1 then
1289 Fail ("switch character cannot be followed by a blank");
1291 -- Processing for -I-
1293 elsif Argv (2 .. Argv'Last) = "I-" then
1294 Opt.Look_In_Primary_Dir := False;
1296 -- Forbid -?- or -??- where ? is any character
1298 elsif (Argv'Length = 3 and then Argv (3) = '-')
1299 or else (Argv'Length = 4 and then Argv (4) = '-')
1301 Fail ("Trailing ""-"" at the end of " & Argv & " forbidden.");
1303 -- Processing for -Idir
1305 elsif Argv (2) = 'I
' then
1306 Add_Source_Dir (Argv (3 .. Argv'Last));
1307 Add_Lib_Dir (Argv (3 .. Argv'Last));
1309 -- Processing for -aIdir (to gcc this is like a -I switch)
1311 elsif Argv'Length >= 3 and then Argv (2 .. 3) = "aI" then
1312 Add_Source_Dir (Argv (4 .. Argv'Last));
1314 -- Processing for -aOdir
1316 elsif Argv'Length >= 3 and then Argv (2 .. 3) = "aO" then
1317 Add_Lib_Dir (Argv (4 .. Argv'Last));
1319 -- Processing for -aLdir (to gnatbind this is like a -aO switch)
1321 elsif Argv'Length >= 3 and then Argv (2 .. 3) = "aL" then
1322 Add_Lib_Dir (Argv (4 .. Argv'Last));
1324 -- Processing for -aP<dir>
1326 elsif Argv'Length > 3 and then Argv (1 .. 3) = "-aP" then
1327 Add_Directories (Prj_Path, Argv (4 .. Argv'Last));
1329 -- Processing for -nostdinc
1331 elsif Argv (2 .. Argv'Last) = "nostdinc" then
1332 Opt.No_Stdinc := True;
1334 -- Processing for one character switches
1336 elsif Argv'Length = 2 then
1338 when 'a
' => Also_Predef := True;
1339 when 'h
' => Print_Usage := True;
1340 when 'u
' => Reset_Print; Print_Unit := True;
1341 when 's
' => Reset_Print; Print_Source := True;
1342 when 'o
' => Reset_Print; Print_Object := True;
1343 when 'v
' => Verbose_Mode := True;
1344 when 'd
' => Dependable := True;
1345 when 'l
' => License := True;
1346 when 'V
' => Very_Verbose_Mode := True;
1348 when others => OK := False;
1351 -- Processing for -files=file
1353 elsif Argv'Length > 7 and then Argv (1 .. 7) = "-files=" then
1354 FD := Open_Read (Argv (8 .. Argv'Last), GNAT.OS_Lib.Text);
1356 if FD = Invalid_FD then
1357 Osint.Fail ("could not find text file """ &
1358 Argv (8 .. Argv'Last) & '"');
1361 Len := Integer (File_Length (FD));
1364 Buffer : String (1 .. Len + 1);
1365 Index : Positive := 1;
1371 Len := Read (FD, Buffer (1)'Address, Len);
1372 Buffer (Buffer'Last) := ASCII.NUL;
1375 -- Scan the file line by line
1377 while Index < Buffer'Last loop
1379 -- Find the end of line
1382 while Last <= Buffer'Last
1383 and then Buffer (Last) /= ASCII.LF
1384 and then Buffer (Last) /= ASCII.CR
1389 -- Ignore empty lines
1391 if Last > Index then
1392 Add_File (Buffer (Index .. Last - 1));
1395 -- Find the beginning of the next line
1398 while Buffer (Index) = ASCII.CR or else
1399 Buffer (Index) = ASCII.LF
1406 -- Processing for --RTS=path
1408 elsif Argv'Length >= 5 and then Argv (1 .. 5) = "--RTS" then
1409 if Argv
'Length <= 6 or else Argv
(6) /= '='then
1410 Osint
.Fail
("missing path for --RTS");
1413 -- Check that it is the first time we see this switch or, if
1414 -- it is not the first time, the same path is specified.
1416 if RTS_Specified
= null then
1417 RTS_Specified
:= new String'(Argv (7 .. Argv'Last));
1419 elsif RTS_Specified.all /= Argv (7 .. Argv'Last) then
1420 Osint.Fail ("--RTS cannot be specified multiple times");
1423 -- Valid --RTS switch
1425 Opt.No_Stdinc := True;
1426 Opt.RTS_Switch := True;
1433 -- If not a switch, it must be a file name
1440 Write_Str ("warning: unknown switch """);
1455 Write_Str ("Usage: ");
1456 Osint.Write_Program_Name;
1457 Write_Str (" switches [list of object files]");
1463 Write_Str ("switches:");
1466 Display_Usage_Version_And_Help;
1470 Write_Str (" -a also output relevant predefined units");
1475 Write_Str (" -u output only relevant unit names");
1480 Write_Str (" -h output this help message");
1485 Write_Str (" -s output only relevant source names");
1490 Write_Str (" -o output only relevant object names");
1495 Write_Str (" -d output sources on which specified units " &
1501 Write_Str (" -l output license information");
1506 Write_Str (" -v verbose output, full path and unit " &
1513 Write_Str (" -files=fil files are listed in text file 'fil
'");
1516 -- Line for -aI switch
1518 Write_Str (" -aIdir specify source files search path");
1521 -- Line for -aO switch
1523 Write_Str (" -aOdir specify object files search path");
1526 -- Line for -aP switch
1528 Write_Str (" -aPdir specify project search path");
1531 -- Line for -I switch
1533 Write_Str (" -Idir like -aIdir -aOdir");
1536 -- Line for -I- switch
1538 Write_Str (" -I- do not look for sources & object files");
1539 Write_Str (" in the default directory");
1542 -- Line for -nostdinc
1544 Write_Str (" -nostdinc do not look for source files");
1545 Write_Str (" in the system default directory");
1550 Write_Str (" --RTS=dir specify the default source and object search"
1554 -- File Status explanation
1557 Write_Str (" file status can be:");
1560 for ST in File_Status loop
1562 Output_Status (ST, Verbose => False);
1563 Write_Str (" ==> ");
1564 Output_Status (ST, Verbose => True);
1569 procedure Check_Version_And_Help is new Check_Version_And_Help_G (Usage);
1571 -- Start of processing for Gnatls
1574 -- Initialize standard packages
1580 -- First check for --version or --help
1582 Check_Version_And_Help ("GNATLS", "1992");
1584 -- Loop to scan out arguments
1587 Scan_Args : while Next_Arg < Arg_Count loop
1589 Next_Argv : String (1 .. Len_Arg (Next_Arg));
1591 Fill_Arg (Next_Argv'Address, Next_Arg);
1592 Scan_Ls_Arg (Next_Argv);
1595 Next_Arg := Next_Arg + 1;
1598 -- If -l (output license information) is given, it must be the only switch
1601 if Arg_Count = 2 then
1602 Output_License_Information;
1603 Exit_Program (E_Success);
1607 Write_Str ("Can't use -l with another switch");
1610 Exit_Program (E_Fatal);
1614 -- Handle --RTS switch
1616 if RTS_Specified /= null then
1617 Search_RTS (RTS_Specified.all);
1620 -- Add the source and object directories specified on the command line, if
1621 -- any, to the searched directories.
1623 while First_Source_Dir /= null loop
1624 Add_Src_Search_Dir (First_Source_Dir.Value.all);
1625 First_Source_Dir := First_Source_Dir.Next;
1628 while First_Lib_Dir /= null loop
1629 Add_Lib_Search_Dir (First_Lib_Dir.Value.all);
1630 First_Lib_Dir := First_Lib_Dir.Next;
1633 -- Finally, add the default directories
1635 Osint.Add_Default_Search_Dirs;
1637 -- If --RTS= is not specified, check if there is a default runtime
1639 if RTS_Specified = null then
1641 Text : Source_Buffer_Ptr;
1645 Name_Buffer (1 .. 10) := "system.ads";
1648 Read_Source_File (Name_Find, Lo => 0, Hi => Hi, Src => Text);
1656 if Verbose_Mode then
1658 Display_Version ("GNATLS", "1997");
1663 ("Default runtime not available. Use --RTS= with a valid runtime");
1666 Exit_Status := E_Warnings;
1669 Write_Str ("Source Search Path:");
1672 for J in 1 .. Nb_Dir_In_Src_Search_Path loop
1675 if Dir_In_Src_Search_Path (J)'Length = 0 then
1676 Write_Str ("<Current_Directory>");
1679 elsif not No_Runtime then
1683 (Dir_In_Src_Search_Path (J).all, True).all));
1690 Write_Str ("Object Search Path:");
1693 for J in 1 .. Nb_Dir_In_Obj_Search_Path loop
1696 if Dir_In_Obj_Search_Path (J)'Length = 0 then
1697 Write_Str ("<Current_Directory>");
1700 elsif not No_Runtime then
1704 (Dir_In_Obj_Search_Path (J).all, True).all));
1711 Write_Str (Project_Search_Path);
1713 Write_Str (" <Current_Directory>");
1716 Initialize_Default_Project_Path
1717 (Prj_Path, Target_Name => Sdefault.Target_Name.all);
1720 Project_Path : String_Access;
1725 Get_Path (Prj_Path, Project_Path);
1727 if Project_Path.all /= "" then
1728 First := Project_Path'First;
1730 while First <= Project_Path'Last
1731 and then (Project_Path (First) = Path_Separator)
1736 exit when First > Project_Path'Last;
1739 while Last < Project_Path'Last
1740 and then Project_Path (Last + 1) /= Path_Separator
1745 if First /= Last or else Project_Path (First) /= '.' then
1747 -- If the directory is ".", skip it as it is the current
1748 -- directory and it is already the first directory in the
1755 (Project_Path (First .. Last), True).all));
1767 -- Output usage information when requested
1773 if not More_Lib_Files then
1774 if not Print_Usage and then not Verbose_Mode then
1775 if Argument_Count = 0 then
1779 Exit_Status := E_Fatal;
1783 Exit_Program (Exit_Status);
1787 Initialize_ALI_Source;
1789 -- Print out all libraries for which no ALI files can be located
1791 while More_Lib_Files loop
1792 Main_File := Next_Main_Lib_File;
1793 Ali_File := Full_Lib_File_Name (Lib_File_Name (Main_File));
1795 if Ali_File = No_File then
1796 if Very_Verbose_Mode then
1797 GNATDIST.Output_No_ALI (Lib_File_Name (Main_File));
1801 Write_Str ("Can't find library info for ");
1802 Get_Name_String (Main_File);
1803 Write_Char ('"'); -- "
1804 Write_Str
(Name_Buffer
(1 .. Name_Len
));
1805 Write_Char
('"'); -- "
1807 Exit_Status
:= E_Fatal
;
1811 Ali_File
:= Strip_Directory
(Ali_File
);
1813 if Get_Name_Table_Info
(Ali_File
) = 0 then
1814 Text
:= Read_Library_Info
(Ali_File
, True);
1825 Ignore_Errors
=> True);
1833 -- Reset default output file descriptor, if needed
1835 Set_Standard_Output
;
1837 if Very_Verbose_Mode
then
1838 for A
in ALIs
.First
.. ALIs
.Last
loop
1839 GNATDIST
.Output_ALI
(A
);
1845 Find_General_Layout
;
1847 for Id
in ALIs
.First
.. ALIs
.Last
loop
1852 Get_Name_String
(Units
.Table
(ALIs
.Table
(Id
).First_Unit
).Uname
);
1854 if Also_Predef
or else not Is_Internal_Unit
then
1855 if ALIs
.Table
(Id
).No_Object
then
1856 Output_Object
(No_File
);
1858 Output_Object
(ALIs
.Table
(Id
).Ofile_Full_Name
);
1861 -- In verbose mode print all main units in the ALI file, otherwise
1862 -- just print the first one to ease columnwise printout
1864 if Verbose_Mode
then
1865 Last_U
:= ALIs
.Table
(Id
).Last_Unit
;
1867 Last_U
:= ALIs
.Table
(Id
).First_Unit
;
1870 for U
in ALIs
.Table
(Id
).First_Unit
.. Last_U
loop
1871 if U
/= ALIs
.Table
(Id
).First_Unit
1872 and then Selective_Output
1878 Output_Unit
(Id
, U
);
1880 -- Output source now, unless if it will be done as part of
1881 -- outputing dependencies.
1883 if not (Dependable
and then Print_Source
) then
1884 Output_Source
(Corresponding_Sdep_Entry
(Id
, U
));
1888 -- Print out list of units on which this unit depends (D lines)
1890 if Dependable
and then Print_Source
then
1891 if Verbose_Mode
then
1892 Write_Str
("depends upon");
1900 ALIs
.Table
(Id
).First_Sdep
.. ALIs
.Table
(Id
).Last_Sdep
1903 or else not Is_Internal_File_Name
(Sdep
.Table
(D
).Sfile
)
1905 if Verbose_Mode
then
1915 Write_Str
(Spaces
(1 .. Source_Start
- 2));
1928 -- All done. Set proper exit status
1931 Exit_Program
(Exit_Status
);