1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 1992-2001 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 2, 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 COPYING. If not, write --
19 -- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, --
20 -- MA 02111-1307, USA. --
22 -- GNAT was originally developed by the GNAT team at New York University. --
23 -- Extensive contributions were provided by Ada Core Technologies Inc. --
25 ------------------------------------------------------------------------------
29 with Namet
; use Namet
;
31 with Output
; use Output
;
32 with Sdefault
; use Sdefault
;
35 with Unchecked_Conversion
;
37 with GNAT
.OS_Lib
; use GNAT
.OS_Lib
;
42 Running_Program
: Program_Type
:= Unspecified
;
43 Program_Set
: Boolean := False;
45 -------------------------------------
46 -- Use of Name_Find and Name_Enter --
47 -------------------------------------
49 -- This package creates a number of source, ALI and object file names
50 -- that are used to locate the actual file and for the purpose of
51 -- message construction. These names need not be accessible by Name_Find,
52 -- and can be therefore created by using routine Name_Enter. The files in
53 -- question are file names with a prefix directory (ie the files not
54 -- in the current directory). File names without a prefix directory are
55 -- entered with Name_Find because special values might be attached to
56 -- the various Info fields of the corresponding name table entry.
58 -----------------------
59 -- Local Subprograms --
60 -----------------------
62 function Append_Suffix_To_File_Name
66 -- Appends Suffix to Name and returns the new name.
68 function OS_Time_To_GNAT_Time
(T
: OS_Time
) return Time_Stamp_Type
;
69 -- Convert OS format time to GNAT format time stamp
71 function Concat
(String_One
: String; String_Two
: String) return String;
72 -- Concatenates 2 strings and returns the result of the concatenation
74 function Update_Path
(Path
: String_Ptr
) return String_Ptr
;
75 -- Update the specified path to replace the prefix with the location
76 -- where GNAT is installed. See the file prefix.c in GCC for details.
78 procedure Write_With_Check
(A
: Address
; N
: Integer);
79 -- Writes N bytes from buffer starting at address A to file whose FD is
80 -- stored in Output_FD, and whose file name is stored as a File_Name_Type
81 -- in Output_File_Name. A check is made for disk full, and if this is
82 -- detected, the file being written is deleted, and a fatal error is
90 return File_Name_Type
;
91 -- See if the file N whose name is Name exists in directory Dir. Dir is
92 -- an index into the Lib_Search_Directories table if T = Library.
93 -- Otherwise if T = Source, Dir is an index into the
94 -- Src_Search_Directories table. Returns the File_Name_Type of the
95 -- full file name if file found, or No_File if not found.
97 function C_String_Length
(S
: Address
) return Integer;
98 -- Returns length of a C string. Returns zero for a null address.
100 function To_Path_String_Access
101 (Path_Addr
: Address
;
103 return String_Access
;
104 -- Converts a C String to an Ada String. Are we doing this to avoid
105 -- withing Interfaces.C.Strings ???
107 ------------------------------
108 -- Other Local Declarations --
109 ------------------------------
111 EOL
: constant Character := ASCII
.LF
;
112 -- End of line character
114 Number_File_Names
: Int
:= 0;
115 -- The total number of file names found on command line and placed in
118 Look_In_Primary_Directory_For_Current_Main
: Boolean := False;
119 -- When this variable is True, Find_File will only look in
120 -- the Primary_Directory for the Current_Main file.
121 -- This variable is always True for the compiler.
122 -- It is also True for gnatmake, when the soucr name given
123 -- on the command line has directory information.
125 Current_Full_Source_Name
: File_Name_Type
:= No_File
;
126 Current_Full_Source_Stamp
: Time_Stamp_Type
:= Empty_Time_Stamp
;
127 Current_Full_Lib_Name
: File_Name_Type
:= No_File
;
128 Current_Full_Lib_Stamp
: Time_Stamp_Type
:= Empty_Time_Stamp
;
129 Current_Full_Obj_Name
: File_Name_Type
:= No_File
;
130 Current_Full_Obj_Stamp
: Time_Stamp_Type
:= Empty_Time_Stamp
;
131 -- Respectively full name (with directory info) and time stamp of
132 -- the latest source, library and object files opened by Read_Source_File
133 -- and Read_Library_Info.
139 Primary_Directory
: constant := 0;
140 -- This is index in the tables created below for the first directory to
141 -- search in for source or library information files. This is the
142 -- directory containing the latest main input file (a source file for
143 -- the compiler or a library file for the binder).
145 package Src_Search_Directories
is new Table
.Table
(
146 Table_Component_Type
=> String_Ptr
,
147 Table_Index_Type
=> Natural,
148 Table_Low_Bound
=> Primary_Directory
,
150 Table_Increment
=> 100,
151 Table_Name
=> "Osint.Src_Search_Directories");
152 -- Table of names of directories in which to search for source (Compiler)
153 -- files. This table is filled in the order in which the directories are
154 -- to be searched, and then used in that order.
156 package Lib_Search_Directories
is new Table
.Table
(
157 Table_Component_Type
=> String_Ptr
,
158 Table_Index_Type
=> Natural,
159 Table_Low_Bound
=> Primary_Directory
,
161 Table_Increment
=> 100,
162 Table_Name
=> "Osint.Lib_Search_Directories");
163 -- Table of names of directories in which to search for library (Binder)
164 -- files. This table is filled in the order in which the directories are
165 -- to be searched and then used in that order. The reason for having two
166 -- distinct tables is that we need them both in gnatmake.
168 ---------------------
169 -- File Hash Table --
170 ---------------------
172 -- The file hash table is provided to free the programmer from any
173 -- efficiency concern when retrieving full file names or time stamps of
174 -- source files. If the programmer calls Source_File_Data (Cache => True)
175 -- he is guaranteed that the price to retrieve the full name (ie with
176 -- directory info) or time stamp of the file will be payed only once,
177 -- the first time the full name is actually searched (or the first time
178 -- the time stamp is actually retrieved). This is achieved by employing
179 -- a hash table that stores as a key the File_Name_Type of the file and
180 -- associates to that File_Name_Type the full file name of the file and its
183 File_Cache_Enabled
: Boolean := False;
184 -- Set to true if you want the enable the file data caching mechanism.
186 type File_Hash_Num
is range 0 .. 1020;
188 function File_Hash
(F
: File_Name_Type
) return File_Hash_Num
;
189 -- Compute hash index for use by Simple_HTable
191 package File_Name_Hash_Table
is new GNAT
.HTable
.Simple_HTable
(
192 Header_Num
=> File_Hash_Num
,
193 Element
=> File_Name_Type
,
194 No_Element
=> No_File
,
195 Key
=> File_Name_Type
,
199 package File_Stamp_Hash_Table
is new GNAT
.HTable
.Simple_HTable
(
200 Header_Num
=> File_Hash_Num
,
201 Element
=> Time_Stamp_Type
,
202 No_Element
=> Empty_Time_Stamp
,
203 Key
=> File_Name_Type
,
207 function Smart_Find_File
210 return File_Name_Type
;
211 -- Exactly like Find_File except that if File_Cache_Enabled is True this
212 -- routine looks first in the hash table to see if the full name of the
213 -- file is already available.
215 function Smart_File_Stamp
218 return Time_Stamp_Type
;
219 -- Takes the same parameter as the routine above (N is a file name
220 -- without any prefix directory information) and behaves like File_Stamp
221 -- except that if File_Cache_Enabled is True this routine looks first in
222 -- the hash table to see if the file stamp of the file is already
225 -----------------------------
226 -- Add_Default_Search_Dirs --
227 -----------------------------
229 procedure Add_Default_Search_Dirs
is
230 Search_Dir
: String_Access
;
231 Search_Path
: String_Access
;
233 procedure Add_Search_Dir
234 (Search_Dir
: String_Access
;
235 Additional_Source_Dir
: Boolean);
236 -- Add a source search dir or a library search dir, depending on the
237 -- value of Additional_Source_Dir.
239 function Get_Libraries_From_Registry
return String_Ptr
;
240 -- On Windows systems, get the list of installed standard libraries
241 -- from the registry key:
242 -- HKEY_LOCAL_MACHINE\SOFTWARE\Ada Core Technologies\
243 -- GNAT\Standard Libraries
244 -- Return an empty string on other systems
250 procedure Add_Search_Dir
251 (Search_Dir
: String_Access
;
252 Additional_Source_Dir
: Boolean)
255 if Additional_Source_Dir
then
256 Add_Src_Search_Dir
(Search_Dir
.all);
258 Add_Lib_Search_Dir
(Search_Dir
.all);
262 ---------------------------------
263 -- Get_Libraries_From_Registry --
264 ---------------------------------
266 function Get_Libraries_From_Registry
return String_Ptr
is
267 function C_Get_Libraries_From_Registry
return Address
;
268 pragma Import
(C
, C_Get_Libraries_From_Registry
,
269 "__gnat_get_libraries_from_registry");
270 function Strlen
(Str
: Address
) return Integer;
271 pragma Import
(C
, Strlen
, "strlen");
272 procedure Strncpy
(X
: Address
; Y
: Address
; Length
: Integer);
273 pragma Import
(C
, Strncpy
, "strncpy");
274 Result_Ptr
: Address
;
275 Result_Length
: Integer;
276 Out_String
: String_Ptr
;
279 Result_Ptr
:= C_Get_Libraries_From_Registry
;
280 Result_Length
:= Strlen
(Result_Ptr
);
282 Out_String
:= new String (1 .. Result_Length
);
283 Strncpy
(Out_String
.all'Address, Result_Ptr
, Result_Length
);
285 end Get_Libraries_From_Registry
;
287 -- Start of processing for Add_Default_Search_Dirs
290 -- After the locations specified on the command line, the next places
291 -- to look for files are the directories specified by the appropriate
292 -- environment variable. Get this value, extract the directory names
293 -- and store in the tables.
295 -- On VMS, don't expand the logical name (e.g. environment variable),
296 -- just put it into Unix (e.g. canonical) format. System services
297 -- will handle the expansion as part of the file processing.
299 for Additional_Source_Dir
in False .. True loop
301 if Additional_Source_Dir
then
302 Search_Path
:= Getenv
("ADA_INCLUDE_PATH");
303 if Search_Path
'Length > 0 then
304 if Hostparm
.OpenVMS
then
305 Search_Path
:= To_Canonical_Path_Spec
("ADA_INCLUDE_PATH:");
307 Search_Path
:= To_Canonical_Path_Spec
(Search_Path
.all);
311 Search_Path
:= Getenv
("ADA_OBJECTS_PATH");
312 if Search_Path
'Length > 0 then
313 if Hostparm
.OpenVMS
then
314 Search_Path
:= To_Canonical_Path_Spec
("ADA_OBJECTS_PATH:");
316 Search_Path
:= To_Canonical_Path_Spec
(Search_Path
.all);
321 Get_Next_Dir_In_Path_Init
(Search_Path
);
323 Search_Dir
:= Get_Next_Dir_In_Path
(Search_Path
);
324 exit when Search_Dir
= null;
325 Add_Search_Dir
(Search_Dir
, Additional_Source_Dir
);
329 if not Opt
.No_Stdinc
then
330 -- For WIN32 systems, look for any system libraries defined in
331 -- the registry. These are added to both source and object
334 Search_Path
:= String_Access
(Get_Libraries_From_Registry
);
335 Get_Next_Dir_In_Path_Init
(Search_Path
);
337 Search_Dir
:= Get_Next_Dir_In_Path
(Search_Path
);
338 exit when Search_Dir
= null;
339 Add_Search_Dir
(Search_Dir
, False);
340 Add_Search_Dir
(Search_Dir
, True);
343 -- The last place to look are the defaults
345 Search_Path
:= Read_Default_Search_Dirs
346 (String_Access
(Update_Path
(Search_Dir_Prefix
)),
348 String_Access
(Update_Path
(Include_Dir_Default_Name
)));
350 Get_Next_Dir_In_Path_Init
(Search_Path
);
352 Search_Dir
:= Get_Next_Dir_In_Path
(Search_Path
);
353 exit when Search_Dir
= null;
354 Add_Search_Dir
(Search_Dir
, True);
358 if not Opt
.No_Stdlib
and not Opt
.RTS_Switch
then
359 Search_Path
:= Read_Default_Search_Dirs
360 (String_Access
(Update_Path
(Search_Dir_Prefix
)),
362 String_Access
(Update_Path
(Object_Dir_Default_Name
)));
364 Get_Next_Dir_In_Path_Init
(Search_Path
);
366 Search_Dir
:= Get_Next_Dir_In_Path
(Search_Path
);
367 exit when Search_Dir
= null;
368 Add_Search_Dir
(Search_Dir
, False);
372 end Add_Default_Search_Dirs
;
378 procedure Add_File
(File_Name
: String) is
380 Number_File_Names
:= Number_File_Names
+ 1;
382 -- As Add_File may be called for mains specified inside
383 -- a project file, File_Names may be too short and needs
386 if Number_File_Names
> File_Names
'Last then
387 File_Names
:= new File_Name_Array
'(File_Names.all & File_Names.all);
390 File_Names (Number_File_Names) := new String'(File_Name
);
393 ------------------------
394 -- Add_Lib_Search_Dir --
395 ------------------------
397 procedure Add_Lib_Search_Dir
(Dir
: String) is
399 if Dir
'Length = 0 then
400 Fail
("missing library directory name");
403 Lib_Search_Directories
.Increment_Last
;
404 Lib_Search_Directories
.Table
(Lib_Search_Directories
.Last
) :=
405 Normalize_Directory_Name
(Dir
);
406 end Add_Lib_Search_Dir
;
408 ---------------------
409 -- Add_Search_Dirs --
410 ---------------------
412 procedure Add_Search_Dirs
413 (Search_Path
: String_Ptr
;
414 Path_Type
: Search_File_Type
)
416 Current_Search_Path
: String_Access
;
419 Get_Next_Dir_In_Path_Init
(String_Access
(Search_Path
));
421 Current_Search_Path
:=
422 Get_Next_Dir_In_Path
(String_Access
(Search_Path
));
423 exit when Current_Search_Path
= null;
425 if Path_Type
= Include
then
426 Add_Src_Search_Dir
(Current_Search_Path
.all);
428 Add_Lib_Search_Dir
(Current_Search_Path
.all);
433 ------------------------
434 -- Add_Src_Search_Dir --
435 ------------------------
437 procedure Add_Src_Search_Dir
(Dir
: String) is
439 if Dir
'Length = 0 then
440 Fail
("missing source directory name");
443 Src_Search_Directories
.Increment_Last
;
444 Src_Search_Directories
.Table
(Src_Search_Directories
.Last
) :=
445 Normalize_Directory_Name
(Dir
);
446 end Add_Src_Search_Dir
;
448 --------------------------------
449 -- Append_Suffix_To_File_Name --
450 --------------------------------
452 function Append_Suffix_To_File_Name
458 Get_Name_String
(Name
);
459 Name_Buffer
(Name_Len
+ 1 .. Name_Len
+ Suffix
'Length) := Suffix
;
460 Name_Len
:= Name_Len
+ Suffix
'Length;
462 end Append_Suffix_To_File_Name
;
464 ---------------------
465 -- C_String_Length --
466 ---------------------
468 function C_String_Length
(S
: Address
) return Integer is
469 function Strlen
(S
: Address
) return Integer;
470 pragma Import
(C
, Strlen
, "strlen");
473 if S
= Null_Address
then
480 ------------------------------
481 -- Canonical_Case_File_Name --
482 ------------------------------
484 -- For now, we only deal with the case of a-z. Eventually we should
485 -- worry about other Latin-1 letters on systems that support this ???
487 procedure Canonical_Case_File_Name
(S
: in out String) is
489 if not File_Names_Case_Sensitive
then
490 for J
in S
'Range loop
491 if S
(J
) in 'A' .. 'Z' then
492 S
(J
) := Character'Val (
493 Character'Pos (S
(J
)) +
494 Character'Pos ('a') -
495 Character'Pos ('A'));
499 end Canonical_Case_File_Name
;
505 function Concat
(String_One
: String; String_Two
: String) return String is
506 Buffer
: String (1 .. String_One
'Length + String_Two
'Length);
509 Buffer
(1 .. String_One
'Length) := String_One
;
510 Buffer
(String_One
'Length + 1 .. Buffer
'Last) := String_Two
;
514 ---------------------------
515 -- Create_File_And_Check --
516 ---------------------------
518 procedure Create_File_And_Check
519 (Fdesc
: out File_Descriptor
;
523 Output_File_Name
:= Name_Enter
;
524 Fdesc
:= Create_File
(Name_Buffer
'Address, Fmode
);
526 if Fdesc
= Invalid_FD
then
527 Fail
("Cannot create: ", Name_Buffer
(1 .. Name_Len
));
529 end Create_File_And_Check
;
531 --------------------------------
532 -- Current_Library_File_Stamp --
533 --------------------------------
535 function Current_Library_File_Stamp
return Time_Stamp_Type
is
537 return Current_Full_Lib_Stamp
;
538 end Current_Library_File_Stamp
;
540 -------------------------------
541 -- Current_Object_File_Stamp --
542 -------------------------------
544 function Current_Object_File_Stamp
return Time_Stamp_Type
is
546 return Current_Full_Obj_Stamp
;
547 end Current_Object_File_Stamp
;
549 -------------------------------
550 -- Current_Source_File_Stamp --
551 -------------------------------
553 function Current_Source_File_Stamp
return Time_Stamp_Type
is
555 return Current_Full_Source_Stamp
;
556 end Current_Source_File_Stamp
;
558 ----------------------------
559 -- Dir_In_Obj_Search_Path --
560 ----------------------------
562 function Dir_In_Obj_Search_Path
(Position
: Natural) return String_Ptr
is
564 if Opt
.Look_In_Primary_Dir
then
566 Lib_Search_Directories
.Table
(Primary_Directory
+ Position
- 1);
568 return Lib_Search_Directories
.Table
(Primary_Directory
+ Position
);
570 end Dir_In_Obj_Search_Path
;
572 ----------------------------
573 -- Dir_In_Src_Search_Path --
574 ----------------------------
576 function Dir_In_Src_Search_Path
(Position
: Natural) return String_Ptr
is
578 if Opt
.Look_In_Primary_Dir
then
580 Src_Search_Directories
.Table
(Primary_Directory
+ Position
- 1);
582 return Src_Search_Directories
.Table
(Primary_Directory
+ Position
);
584 end Dir_In_Src_Search_Path
;
586 ---------------------
587 -- Executable_Name --
588 ---------------------
590 function Executable_Name
(Name
: File_Name_Type
) return File_Name_Type
is
591 Exec_Suffix
: String_Access
;
594 if Name
= No_File
then
598 Get_Name_String
(Name
);
599 Exec_Suffix
:= Get_Executable_Suffix
;
601 for J
in Exec_Suffix
.all'Range loop
602 Name_Len
:= Name_Len
+ 1;
603 Name_Buffer
(Name_Len
) := Exec_Suffix
.all (J
);
613 procedure Exit_Program
(Exit_Code
: Exit_Code_Type
) is
615 -- The program will exit with the following status:
616 -- 0 if the object file has been generated (with or without warnings)
617 -- 1 if recompilation was not needed (smart recompilation)
618 -- 2 if gnat1 has been killed by a signal (detected by GCC)
619 -- 3 if no code has been generated (spec)
620 -- 4 for a fatal error
621 -- 5 if there were errors
624 when E_Success
=> OS_Exit
(0);
625 when E_Warnings
=> OS_Exit
(0);
626 when E_No_Compile
=> OS_Exit
(1);
627 when E_No_Code
=> OS_Exit
(3);
628 when E_Fatal
=> OS_Exit
(4);
629 when E_Errors
=> OS_Exit
(5);
630 when E_Abort
=> OS_Abort
;
638 procedure Fail
(S1
: String; S2
: String := ""; S3
: String := "") is
641 -- We use Output in case there is a special output set up.
642 -- In this case Set_Standard_Error will have no immediate effect.
645 Osint
.Write_Program_Name
;
652 Exit_Program
(E_Fatal
);
659 function File_Hash
(F
: File_Name_Type
) return File_Hash_Num
is
661 return File_Hash_Num
(Int
(F
) rem File_Hash_Num
'Range_Length);
668 function File_Stamp
(Name
: File_Name_Type
) return Time_Stamp_Type
is
670 if Name
= No_File
then
671 return Empty_Time_Stamp
;
674 Get_Name_String
(Name
);
676 if not Is_Regular_File
(Name_Buffer
(1 .. Name_Len
)) then
677 return Empty_Time_Stamp
;
679 Name_Buffer
(Name_Len
+ 1) := ASCII
.NUL
;
680 return OS_Time_To_GNAT_Time
(File_Time_Stamp
(Name_Buffer
));
691 return File_Name_Type
697 File_Name
: String renames Name_Buffer
(1 .. Name_Len
);
698 File
: File_Name_Type
:= No_File
;
702 -- If we are looking for a config file, look only in the current
703 -- directory, i.e. return input argument unchanged. Also look
704 -- only in the current directory if we are looking for a .dg
705 -- file (happens in -gnatD mode)
708 or else (Debug_Generated_Code
709 and then Name_Len
> 3
711 (Name_Buffer
(Name_Len
- 2 .. Name_Len
) = ".dg"
713 (Hostparm
.OpenVMS
and then
714 Name_Buffer
(Name_Len
- 2 .. Name_Len
) = "_dg")))
718 -- If we are trying to find the current main file just look in the
719 -- directory where the user said it was.
721 elsif Look_In_Primary_Directory_For_Current_Main
722 and then Current_Main
= N
724 return Locate_File
(N
, T
, Primary_Directory
, File_Name
);
726 -- Otherwise do standard search for source file
729 -- Check the mapping of this file name
731 File
:= Mapped_Path_Name
(N
);
733 -- If the file name is mapped to a path name, return the
734 -- corresponding path name
736 if File
/= No_File
then
740 -- First place to look is in the primary directory (i.e. the same
741 -- directory as the source) unless this has been disabled with -I-
743 if Opt
.Look_In_Primary_Dir
then
744 File
:= Locate_File
(N
, T
, Primary_Directory
, File_Name
);
746 if File
/= No_File
then
751 -- Finally look in directories specified with switches -I/-aI/-aO
754 Last_Dir
:= Lib_Search_Directories
.Last
;
756 Last_Dir
:= Src_Search_Directories
.Last
;
759 for D
in Primary_Directory
+ 1 .. Last_Dir
loop
760 File
:= Locate_File
(N
, T
, D
, File_Name
);
762 if File
/= No_File
then
772 -----------------------
773 -- Find_Program_Name --
774 -----------------------
776 procedure Find_Program_Name
is
777 Command_Name
: String (1 .. Len_Arg
(0));
778 Cindex1
: Integer := Command_Name
'First;
779 Cindex2
: Integer := Command_Name
'Last;
782 Fill_Arg
(Command_Name
'Address, 0);
784 -- The program name might be specified by a full path name. However,
785 -- we don't want to print that all out in an error message, so the
786 -- path might need to be stripped away.
788 for J
in reverse Cindex1
.. Cindex2
loop
789 if Is_Directory_Separator
(Command_Name
(J
)) then
795 for J
in reverse Cindex1
.. Cindex2
loop
796 if Command_Name
(J
) = '.' then
802 Name_Len
:= Cindex2
- Cindex1
+ 1;
803 Name_Buffer
(1 .. Name_Len
) := Command_Name
(Cindex1
.. Cindex2
);
804 end Find_Program_Name
;
806 ------------------------
807 -- Full_Lib_File_Name --
808 ------------------------
810 function Full_Lib_File_Name
(N
: File_Name_Type
) return File_Name_Type
is
812 return Find_File
(N
, Library
);
813 end Full_Lib_File_Name
;
815 ----------------------------
816 -- Full_Library_Info_Name --
817 ----------------------------
819 function Full_Library_Info_Name
return File_Name_Type
is
821 return Current_Full_Lib_Name
;
822 end Full_Library_Info_Name
;
824 ---------------------------
825 -- Full_Object_File_Name --
826 ---------------------------
828 function Full_Object_File_Name
return File_Name_Type
is
830 return Current_Full_Obj_Name
;
831 end Full_Object_File_Name
;
833 ----------------------
834 -- Full_Source_Name --
835 ----------------------
837 function Full_Source_Name
return File_Name_Type
is
839 return Current_Full_Source_Name
;
840 end Full_Source_Name
;
842 ----------------------
843 -- Full_Source_Name --
844 ----------------------
846 function Full_Source_Name
(N
: File_Name_Type
) return File_Name_Type
is
848 return Smart_Find_File
(N
, Source
);
849 end Full_Source_Name
;
855 function Get_Directory
(Name
: File_Name_Type
) return File_Name_Type
is
857 Get_Name_String
(Name
);
859 for J
in reverse 1 .. Name_Len
loop
860 if Is_Directory_Separator
(Name_Buffer
(J
)) then
866 Name_Len
:= Hostparm
.Normalized_CWD
'Length;
867 Name_Buffer
(1 .. Name_Len
) := Hostparm
.Normalized_CWD
;
871 --------------------------
872 -- Get_Next_Dir_In_Path --
873 --------------------------
875 Search_Path_Pos
: Integer;
876 -- Keeps track of current position in search path. Initialized by the
877 -- call to Get_Next_Dir_In_Path_Init, updated by Get_Next_Dir_In_Path.
879 function Get_Next_Dir_In_Path
880 (Search_Path
: String_Access
)
883 Lower_Bound
: Positive := Search_Path_Pos
;
884 Upper_Bound
: Positive;
888 while Lower_Bound
<= Search_Path
'Last
889 and then Search_Path
.all (Lower_Bound
) = Path_Separator
891 Lower_Bound
:= Lower_Bound
+ 1;
894 exit when Lower_Bound
> Search_Path
'Last;
896 Upper_Bound
:= Lower_Bound
;
897 while Upper_Bound
<= Search_Path
'Last
898 and then Search_Path
.all (Upper_Bound
) /= Path_Separator
900 Upper_Bound
:= Upper_Bound
+ 1;
903 Search_Path_Pos
:= Upper_Bound
;
904 return new String'(Search_Path.all (Lower_Bound .. Upper_Bound - 1));
908 end Get_Next_Dir_In_Path;
910 -------------------------------
911 -- Get_Next_Dir_In_Path_Init --
912 -------------------------------
914 procedure Get_Next_Dir_In_Path_Init (Search_Path : String_Access) is
916 Search_Path_Pos := Search_Path'First;
917 end Get_Next_Dir_In_Path_Init;
919 --------------------------------------
920 -- Get_Primary_Src_Search_Directory --
921 --------------------------------------
923 function Get_Primary_Src_Search_Directory return String_Ptr is
925 return Src_Search_Directories.Table (Primary_Directory);
926 end Get_Primary_Src_Search_Directory;
928 -------------------------
929 -- Get_RTS_Search_Dir --
930 -------------------------
932 function Get_RTS_Search_Dir
933 (Search_Dir : String;
934 File_Type : Search_File_Type)
937 procedure Get_Current_Dir
938 (Dir : System.Address;
939 Length : System.Address);
940 pragma Import (C, Get_Current_Dir, "__gnat_get_current_dir");
943 pragma Import (C, Max_Path, "__gnat_max_path_len");
944 -- Maximum length of a path name
946 Current_Dir : String_Ptr;
947 Default_Search_Dir : String_Access;
948 Default_Suffix_Dir : String_Access;
949 Local_Search_Dir : String_Access;
950 Norm_Search_Dir : String_Access;
951 Result_Search_Dir : String_Access;
952 Search_File : String_Access;
953 Temp_String : String_Ptr;
956 -- Add a directory separator at the end of the directory if necessary
957 -- so that we can directly append a file to the directory
959 if Search_Dir (Search_Dir'Last) /= Directory_Separator then
960 Local_Search_Dir := new String'
961 (Concat
(Search_Dir
, String' (1 => Directory_Separator)));
963 Local_Search_Dir := new String' (Search_Dir
);
966 if File_Type
= Include
then
967 Search_File
:= Include_Search_File
;
968 Default_Suffix_Dir
:= new String'("adainclude");
970 Search_File := Objects_Search_File;
971 Default_Suffix_Dir := new String' ("adalib");
974 Norm_Search_Dir
:= To_Canonical_Path_Spec
(Local_Search_Dir
.all);
976 if Is_Absolute_Path
(Norm_Search_Dir
.all) then
978 -- We first verify if there is a directory Include_Search_Dir
979 -- containing default search directories
982 := Read_Default_Search_Dirs
(Norm_Search_Dir
,
985 Default_Search_Dir
:= new String'
986 (Concat (Norm_Search_Dir.all, Default_Suffix_Dir.all));
987 Free (Norm_Search_Dir);
989 if Result_Search_Dir /= null then
990 return String_Ptr (Result_Search_Dir);
991 elsif Is_Directory (Default_Search_Dir.all) then
992 return String_Ptr (Default_Search_Dir);
998 -- Search in the current directory
1000 -- Get the current directory
1003 Buffer : String (1 .. Max_Path + 2);
1004 Path_Len : Natural := Max_Path;
1007 Get_Current_Dir (Buffer'Address, Path_Len'Address);
1009 if Buffer (Path_Len) /= Directory_Separator then
1010 Path_Len := Path_Len + 1;
1011 Buffer (Path_Len) := Directory_Separator;
1014 Current_Dir := new String'(Buffer
(1 .. Path_Len
));
1019 (Concat (Current_Dir.all, Local_Search_Dir.all));
1021 Result_Search_Dir :=
1022 Read_Default_Search_Dirs
1023 (String_Access (Update_Path (String_Ptr (Norm_Search_Dir))),
1027 Default_Search_Dir :=
1029 (Concat
(Norm_Search_Dir
.all, Default_Suffix_Dir
.all));
1031 Free
(Norm_Search_Dir
);
1033 if Result_Search_Dir
/= null then
1034 return String_Ptr
(Result_Search_Dir
);
1036 elsif Is_Directory
(Default_Search_Dir
.all) then
1037 return String_Ptr
(Default_Search_Dir
);
1040 -- Search in Search_Dir_Prefix/Search_Dir
1044 (Concat (Search_Dir_Prefix.all, Local_Search_Dir.all));
1046 Result_Search_Dir :=
1047 Read_Default_Search_Dirs
1048 (String_Access (Update_Path (String_Ptr (Norm_Search_Dir))),
1052 Default_Search_Dir :=
1054 (Concat
(Norm_Search_Dir
.all, Default_Suffix_Dir
.all));
1056 Free
(Norm_Search_Dir
);
1058 if Result_Search_Dir
/= null then
1059 return String_Ptr
(Result_Search_Dir
);
1061 elsif Is_Directory
(Default_Search_Dir
.all) then
1062 return String_Ptr
(Default_Search_Dir
);
1065 -- We finally search in Search_Dir_Prefix/rts-Search_Dir
1068 new String'(Concat (Search_Dir_Prefix.all, "rts-"));
1071 new String' (Concat
(Temp_String
.all, Local_Search_Dir
.all));
1073 Result_Search_Dir
:=
1074 Read_Default_Search_Dirs
1075 (String_Access
(Update_Path
(String_Ptr
(Norm_Search_Dir
))),
1079 Default_Search_Dir
:=
1081 (Concat (Norm_Search_Dir.all, Default_Suffix_Dir.all));
1082 Free (Norm_Search_Dir);
1084 if Result_Search_Dir /= null then
1085 return String_Ptr (Result_Search_Dir);
1087 elsif Is_Directory (Default_Search_Dir.all) then
1088 return String_Ptr (Default_Search_Dir);
1096 end Get_RTS_Search_Dir;
1098 ----------------------------
1099 -- Is_Directory_Separator --
1100 ----------------------------
1102 function Is_Directory_Separator (C : Character) return Boolean is
1104 -- In addition to the default directory_separator allow the '/' to
1105 -- act as separator since this is allowed in MS-DOS, Windows 95/NT,
1106 -- and OS2 ports. On VMS, the situation is more complicated because
1107 -- there are two characters to check for.
1110 C = Directory_Separator
1112 or else (Hostparm.OpenVMS
1113 and then (C = ']' or else C = ':'));
1114 end Is_Directory_Separator;
1116 -------------------------
1117 -- Is_Readonly_Library --
1118 -------------------------
1120 function Is_Readonly_Library (File : in File_Name_Type) return Boolean is
1122 Get_Name_String (File);
1124 pragma Assert (Name_Buffer (Name_Len - 3 .. Name_Len) = ".ali");
1126 return not Is_Writable_File (Name_Buffer (1 .. Name_Len));
1127 end Is_Readonly_Library;
1133 function Lib_File_Name
1134 (Source_File : File_Name_Type)
1135 return File_Name_Type
1138 -- Pointer to location to set extension in place
1141 Get_Name_String (Source_File);
1142 Fptr := Name_Len + 1;
1144 for J in reverse 2 .. Name_Len loop
1145 if Name_Buffer (J) = '.' then
1151 Name_Buffer (Fptr) := '.';
1152 Name_Buffer (Fptr + 1 .. Fptr + ALI_Suffix'Length) := ALI_Suffix.all;
1153 Name_Buffer (Fptr + ALI_Suffix'Length + 1) := ASCII.NUL;
1154 Name_Len := Fptr + ALI_Suffix'Length;
1158 ------------------------
1159 -- Library_File_Stamp --
1160 ------------------------
1162 function Library_File_Stamp (N : File_Name_Type) return Time_Stamp_Type is
1164 return File_Stamp (Find_File (N, Library));
1165 end Library_File_Stamp;
1171 function Locate_File
1172 (N : File_Name_Type;
1176 return File_Name_Type
1178 Dir_Name : String_Ptr;
1182 Dir_Name := Lib_Search_Directories.Table (Dir);
1184 else pragma Assert (T = Source);
1185 Dir_Name := Src_Search_Directories.Table (Dir);
1189 Full_Name : String (1 .. Dir_Name'Length + Name'Length);
1192 Full_Name (1 .. Dir_Name'Length) := Dir_Name.all;
1193 Full_Name (Dir_Name'Length + 1 .. Full_Name'Length) := Name;
1195 if not Is_Regular_File (Full_Name) then
1199 -- If the file is in the current directory then return N itself
1201 if Dir_Name'Length = 0 then
1204 Name_Len := Full_Name'Length;
1205 Name_Buffer (1 .. Name_Len) := Full_Name;
1212 -------------------------------
1213 -- Matching_Full_Source_Name --
1214 -------------------------------
1216 function Matching_Full_Source_Name
1217 (N : File_Name_Type;
1218 T : Time_Stamp_Type)
1219 return File_Name_Type
1222 Get_Name_String (N);
1225 File_Name : constant String := Name_Buffer (1 .. Name_Len);
1226 File : File_Name_Type := No_File;
1230 if Opt.Look_In_Primary_Dir then
1231 File := Locate_File (N, Source, Primary_Directory, File_Name);
1233 if File /= No_File and then T = File_Stamp (N) then
1238 Last_Dir := Src_Search_Directories.Last;
1240 for D in Primary_Directory + 1 .. Last_Dir loop
1241 File := Locate_File (N, Source, D, File_Name);
1243 if File /= No_File and then T = File_Stamp (File) then
1250 end Matching_Full_Source_Name;
1256 function More_Files return Boolean is
1258 return (Current_File_Name_Index < Number_File_Names);
1261 -------------------------------
1262 -- Nb_Dir_In_Obj_Search_Path --
1263 -------------------------------
1265 function Nb_Dir_In_Obj_Search_Path return Natural is
1267 if Opt.Look_In_Primary_Dir then
1268 return Lib_Search_Directories.Last - Primary_Directory + 1;
1270 return Lib_Search_Directories.Last - Primary_Directory;
1272 end Nb_Dir_In_Obj_Search_Path;
1274 -------------------------------
1275 -- Nb_Dir_In_Src_Search_Path --
1276 -------------------------------
1278 function Nb_Dir_In_Src_Search_Path return Natural is
1280 if Opt.Look_In_Primary_Dir then
1281 return Src_Search_Directories.Last - Primary_Directory + 1;
1283 return Src_Search_Directories.Last - Primary_Directory;
1285 end Nb_Dir_In_Src_Search_Path;
1287 --------------------
1288 -- Next_Main_File --
1289 --------------------
1291 function Next_Main_File return File_Name_Type is
1292 File_Name : String_Ptr;
1293 Dir_Name : String_Ptr;
1297 pragma Assert (More_Files);
1299 Current_File_Name_Index := Current_File_Name_Index + 1;
1301 -- Get the file and directory name
1303 File_Name := File_Names (Current_File_Name_Index);
1304 Fptr := File_Name'First;
1306 for J in reverse File_Name'Range loop
1307 if File_Name (J) = Directory_Separator
1308 or else File_Name (J) = '/'
1310 if J = File_Name'Last then
1311 Fail ("File name missing");
1319 -- Save name of directory in which main unit resides for use in
1320 -- locating other units
1322 Dir_Name := new String'(File_Name
(File_Name
'First .. Fptr
- 1));
1324 case Running_Program
is
1327 Src_Search_Directories
.Table
(Primary_Directory
) := Dir_Name
;
1328 Look_In_Primary_Directory_For_Current_Main
:= True;
1331 Src_Search_Directories
.Table
(Primary_Directory
) := Dir_Name
;
1333 if Fptr
> File_Name
'First then
1334 Look_In_Primary_Directory_For_Current_Main
:= True;
1337 when Binder | Gnatls
=>
1338 Dir_Name
:= Normalize_Directory_Name
(Dir_Name
.all);
1339 Lib_Search_Directories
.Table
(Primary_Directory
) := Dir_Name
;
1345 Name_Len
:= File_Name
'Last - Fptr
+ 1;
1346 Name_Buffer
(1 .. Name_Len
) := File_Name
(Fptr
.. File_Name
'Last);
1347 Canonical_Case_File_Name
(Name_Buffer
(1 .. Name_Len
));
1348 Current_Main
:= File_Name_Type
(Name_Find
);
1350 -- In the gnatmake case, the main file may have not have the
1351 -- extension. Try ".adb" first then ".ads"
1353 if Running_Program
= Make
then
1355 Orig_Main
: File_Name_Type
:= Current_Main
;
1358 if Strip_Suffix
(Orig_Main
) = Orig_Main
then
1359 Current_Main
:= Append_Suffix_To_File_Name
(Orig_Main
, ".adb");
1361 if Full_Source_Name
(Current_Main
) = No_File
then
1363 Append_Suffix_To_File_Name
(Orig_Main
, ".ads");
1365 if Full_Source_Name
(Current_Main
) = No_File
then
1366 Current_Main
:= Orig_Main
;
1373 return Current_Main
;
1376 ------------------------------
1377 -- Normalize_Directory_Name --
1378 ------------------------------
1380 function Normalize_Directory_Name
(Directory
: String) return String_Ptr
is
1381 Result
: String_Ptr
;
1384 if Directory
'Length = 0 then
1385 Result
:= new String'(Hostparm.Normalized_CWD);
1387 elsif Is_Directory_Separator (Directory (Directory'Last)) then
1388 Result := new String'(Directory
);
1390 Result
:= new String (1 .. Directory
'Length + 1);
1391 Result
(1 .. Directory
'Length) := Directory
;
1392 Result
(Directory
'Length + 1) := Directory_Separator
;
1396 end Normalize_Directory_Name
;
1398 ---------------------
1399 -- Number_Of_Files --
1400 ---------------------
1402 function Number_Of_Files
return Int
is
1404 return Number_File_Names
;
1405 end Number_Of_Files
;
1407 ----------------------
1408 -- Object_File_Name --
1409 ----------------------
1411 function Object_File_Name
(N
: File_Name_Type
) return File_Name_Type
is
1417 Get_Name_String
(N
);
1418 Name_Len
:= Name_Len
- ALI_Suffix
'Length - 1;
1420 for J
in Object_Suffix
'Range loop
1421 Name_Len
:= Name_Len
+ 1;
1422 Name_Buffer
(Name_Len
) := Object_Suffix
(J
);
1426 end Object_File_Name
;
1428 --------------------------
1429 -- OS_Time_To_GNAT_Time --
1430 --------------------------
1432 function OS_Time_To_GNAT_Time
(T
: OS_Time
) return Time_Stamp_Type
is
1433 GNAT_Time
: Time_Stamp_Type
;
1443 GM_Split
(T
, Y
, Mo
, D
, H
, Mn
, S
);
1449 Minutes
=> Nat
(Mn
),
1454 end OS_Time_To_GNAT_Time
;
1460 function Program_Name
(Nam
: String) return String_Access
is
1461 Res
: String_Access
;
1464 -- Get the name of the current program being executed
1468 -- Find the target prefix if any, for the cross compilation case
1469 -- for instance in "alpha-dec-vxworks-gcc" the target prefix is
1470 -- "alpha-dec-vxworks-"
1472 while Name_Len
> 0 loop
1473 if Name_Buffer
(Name_Len
) = '-' then
1477 Name_Len
:= Name_Len
- 1;
1480 -- Create the new program name
1482 Res
:= new String (1 .. Name_Len
+ Nam
'Length);
1483 Res
.all (1 .. Name_Len
) := Name_Buffer
(1 .. Name_Len
);
1484 Res
.all (Name_Len
+ 1 .. Name_Len
+ Nam
'Length) := Nam
;
1488 ------------------------------
1489 -- Read_Default_Search_Dirs --
1490 ------------------------------
1492 function Read_Default_Search_Dirs
1493 (Search_Dir_Prefix
: String_Access
;
1494 Search_File
: String_Access
;
1495 Search_Dir_Default_Name
: String_Access
)
1496 return String_Access
1498 Prefix_Len
: constant Integer := Search_Dir_Prefix
.all'Length;
1499 Buffer
: String (1 .. Prefix_Len
+ Search_File
.all'Length + 1);
1500 File_FD
: File_Descriptor
;
1501 S
, S1
: String_Access
;
1504 Actual_Len
: Integer;
1507 Prev_Was_Separator
: Boolean;
1508 Nb_Relative_Dir
: Integer;
1510 function Is_Relative
(S
: String; K
: Positive) return Boolean;
1511 pragma Inline
(Is_Relative
);
1512 -- Returns True if a relative directory specification is found
1513 -- in S at position K, False otherwise.
1519 function Is_Relative
(S
: String; K
: Positive) return Boolean is
1521 return not Is_Absolute_Path
(S
(K
.. S
'Last));
1524 -- Start of processing for Read_Default_Search_Dirs
1527 -- Construct a C compatible character string buffer.
1529 Buffer
(1 .. Search_Dir_Prefix
.all'Length)
1530 := Search_Dir_Prefix
.all;
1531 Buffer
(Search_Dir_Prefix
.all'Length + 1 .. Buffer
'Last - 1)
1533 Buffer
(Buffer
'Last) := ASCII
.NUL
;
1535 File_FD
:= Open_Read
(Buffer
'Address, Binary
);
1536 if File_FD
= Invalid_FD
then
1537 return Search_Dir_Default_Name
;
1540 Len
:= Integer (File_Length
(File_FD
));
1542 -- An extra character for a trailing Path_Separator is allocated
1544 S
:= new String (1 .. Len
+ 1);
1545 S
(Len
+ 1) := Path_Separator
;
1547 -- Read the file. Note that the loop is not necessary since the
1548 -- whole file is read at once except on VMS.
1552 while Actual_Len
/= 0 loop
1553 Actual_Len
:= Read
(File_FD
, S
(Curr
)'Address, Len
);
1554 Curr
:= Curr
+ Actual_Len
;
1557 -- Process the file, translating line and file ending
1558 -- control characters to a path separator character.
1560 Prev_Was_Separator
:= True;
1561 Nb_Relative_Dir
:= 0;
1562 for J
in 1 .. Len
loop
1563 if S
(J
) in ASCII
.NUL
.. ASCII
.US
1566 S
(J
) := Path_Separator
;
1569 if S
(J
) = Path_Separator
then
1570 Prev_Was_Separator
:= True;
1572 if Prev_Was_Separator
and then Is_Relative
(S
.all, J
) then
1573 Nb_Relative_Dir
:= Nb_Relative_Dir
+ 1;
1576 Prev_Was_Separator
:= False;
1580 if Nb_Relative_Dir
= 0 then
1584 -- Add the Search_Dir_Prefix to all relative paths
1586 S1
:= new String (1 .. S
'Length + Nb_Relative_Dir
* Prefix_Len
);
1588 Prev_Was_Separator
:= True;
1589 for J
in 1 .. Len
+ 1 loop
1590 if S
(J
) = Path_Separator
then
1591 Prev_Was_Separator
:= True;
1594 if Prev_Was_Separator
and then Is_Relative
(S
.all, J
) then
1595 S1
(J1
.. J1
+ Prefix_Len
) := Search_Dir_Prefix
.all;
1596 J1
:= J1
+ Prefix_Len
;
1599 Prev_Was_Separator
:= False;
1607 end Read_Default_Search_Dirs
;
1609 -----------------------
1610 -- Read_Library_Info --
1611 -----------------------
1613 function Read_Library_Info
1614 (Lib_File
: File_Name_Type
;
1615 Fatal_Err
: Boolean := False)
1616 return Text_Buffer_Ptr
1618 Lib_FD
: File_Descriptor
;
1619 -- The file descriptor for the current library file. A negative value
1620 -- indicates failure to open the specified source file.
1622 Text
: Text_Buffer_Ptr
;
1623 -- Allocated text buffer.
1626 Current_Full_Lib_Name
:= Find_File
(Lib_File
, Library
);
1627 Current_Full_Obj_Name
:= Object_File_Name
(Current_Full_Lib_Name
);
1629 if Current_Full_Lib_Name
= No_File
then
1631 Fail
("Cannot find: ", Name_Buffer
(1 .. Name_Len
));
1633 Current_Full_Obj_Stamp
:= Empty_Time_Stamp
;
1638 Get_Name_String
(Current_Full_Lib_Name
);
1639 Name_Buffer
(Name_Len
+ 1) := ASCII
.NUL
;
1641 -- Open the library FD, note that we open in binary mode, because as
1642 -- documented in the spec, the caller is expected to handle either
1643 -- DOS or Unix mode files, and there is no point in wasting time on
1644 -- text translation when it is not required.
1646 Lib_FD
:= Open_Read
(Name_Buffer
'Address, Binary
);
1648 if Lib_FD
= Invalid_FD
then
1650 Fail
("Cannot open: ", Name_Buffer
(1 .. Name_Len
));
1652 Current_Full_Obj_Stamp
:= Empty_Time_Stamp
;
1657 -- Check for object file consistency if requested
1659 if Opt
.Check_Object_Consistency
then
1660 Current_Full_Lib_Stamp
:= File_Stamp
(Current_Full_Lib_Name
);
1661 Current_Full_Obj_Stamp
:= File_Stamp
(Current_Full_Obj_Name
);
1663 if Current_Full_Obj_Stamp
(1) = ' ' then
1665 -- When the library is readonly, always assume that
1666 -- the object is consistent.
1668 if Is_Readonly_Library
(Current_Full_Lib_Name
) then
1669 Current_Full_Obj_Stamp
:= Current_Full_Lib_Stamp
;
1671 elsif Fatal_Err
then
1672 Get_Name_String
(Current_Full_Obj_Name
);
1674 Fail
("Cannot find: ", Name_Buffer
(1 .. Name_Len
));
1677 Current_Full_Obj_Stamp
:= Empty_Time_Stamp
;
1683 -- Object file exists, compare object and ALI time stamps
1685 if Current_Full_Lib_Stamp
> Current_Full_Obj_Stamp
then
1687 Get_Name_String
(Current_Full_Obj_Name
);
1689 Fail
("Bad time stamp: ", Name_Buffer
(1 .. Name_Len
));
1691 Current_Full_Obj_Stamp
:= Empty_Time_Stamp
;
1698 -- Read data from the file
1701 Len
: Integer := Integer (File_Length
(Lib_FD
));
1702 -- Length of source file text. If it doesn't fit in an integer
1703 -- we're probably stuck anyway (>2 gigs of source seems a lot!)
1705 Actual_Len
: Integer := 0;
1708 -- Low bound for allocated text buffer
1710 Hi
: Text_Ptr
:= Text_Ptr
(Len
);
1711 -- High bound for allocated text buffer. Note length is Len + 1
1712 -- which allows for extra EOF character at the end of the buffer.
1715 -- Allocate text buffer. Note extra character at end for EOF
1717 Text
:= new Text_Buffer
(Lo
.. Hi
);
1719 -- Some systems (e.g. VMS) have file types that require one
1720 -- read per line, so read until we get the Len bytes or until
1721 -- there are no more characters.
1725 Actual_Len
:= Read
(Lib_FD
, Text
(Hi
)'Address, Len
);
1726 Hi
:= Hi
+ Text_Ptr
(Actual_Len
);
1727 exit when Actual_Len
= Len
or Actual_Len
<= 0;
1733 -- Read is complete, close file and we are done
1738 end Read_Library_Info
;
1740 ----------------------
1741 -- Read_Source_File --
1742 ----------------------
1744 procedure Read_Source_File
1745 (N
: File_Name_Type
;
1747 Hi
: out Source_Ptr
;
1748 Src
: out Source_Buffer_Ptr
;
1749 T
: File_Type
:= Source
)
1751 Source_File_FD
: File_Descriptor
;
1752 -- The file descriptor for the current source file. A negative value
1753 -- indicates failure to open the specified source file.
1756 -- Length of file. Assume no more than 2 gigabytes of source!
1758 Actual_Len
: Integer;
1761 Current_Full_Source_Name
:= Find_File
(N
, T
);
1762 Current_Full_Source_Stamp
:= File_Stamp
(Current_Full_Source_Name
);
1764 if Current_Full_Source_Name
= No_File
then
1766 -- If we were trying to access the main file and we could not
1767 -- find it we have an error.
1769 if N
= Current_Main
then
1770 Get_Name_String
(N
);
1771 Fail
("Cannot find: ", Name_Buffer
(1 .. Name_Len
));
1779 Get_Name_String
(Current_Full_Source_Name
);
1780 Name_Buffer
(Name_Len
+ 1) := ASCII
.NUL
;
1782 -- Open the source FD, note that we open in binary mode, because as
1783 -- documented in the spec, the caller is expected to handle either
1784 -- DOS or Unix mode files, and there is no point in wasting time on
1785 -- text translation when it is not required.
1787 Source_File_FD
:= Open_Read
(Name_Buffer
'Address, Binary
);
1789 if Source_File_FD
= Invalid_FD
then
1795 -- Prepare to read data from the file
1797 Len
:= Integer (File_Length
(Source_File_FD
));
1799 -- Set Hi so that length is one more than the physical length,
1800 -- allowing for the extra EOF character at the end of the buffer
1802 Hi
:= Lo
+ Source_Ptr
(Len
);
1804 -- Do the actual read operation
1807 subtype Actual_Source_Buffer
is Source_Buffer
(Lo
.. Hi
);
1808 -- Physical buffer allocated
1810 type Actual_Source_Ptr
is access Actual_Source_Buffer
;
1811 -- This is the pointer type for the physical buffer allocated
1813 Actual_Ptr
: Actual_Source_Ptr
:= new Actual_Source_Buffer
;
1814 -- And this is the actual physical buffer
1817 -- Allocate source buffer, allowing extra character at end for EOF
1819 -- Some systems (e.g. VMS) have file types that require one
1820 -- read per line, so read until we get the Len bytes or until
1821 -- there are no more characters.
1825 Actual_Len
:= Read
(Source_File_FD
, Actual_Ptr
(Hi
)'Address, Len
);
1826 Hi
:= Hi
+ Source_Ptr
(Actual_Len
);
1827 exit when Actual_Len
= Len
or Actual_Len
<= 0;
1830 Actual_Ptr
(Hi
) := EOF
;
1832 -- Now we need to work out the proper virtual origin pointer to
1833 -- return. This is exactly Actual_Ptr (0)'Address, but we have
1834 -- to be careful to suppress checks to compute this address.
1837 pragma Suppress
(All_Checks
);
1839 function To_Source_Buffer_Ptr
is new
1840 Unchecked_Conversion
(Address
, Source_Buffer_Ptr
);
1843 Src
:= To_Source_Buffer_Ptr
(Actual_Ptr
(0)'Address);
1847 -- Read is complete, get time stamp and close file and we are done
1849 Close
(Source_File_FD
);
1851 end Read_Source_File
;
1857 procedure Set_Program
(P
: Program_Type
) is
1860 Fail
("Set_Program called twice");
1863 Program_Set
:= True;
1864 Running_Program
:= P
;
1867 ----------------------
1868 -- Smart_File_Stamp --
1869 ----------------------
1871 function Smart_File_Stamp
1872 (N
: File_Name_Type
;
1874 return Time_Stamp_Type
1876 Time_Stamp
: Time_Stamp_Type
;
1879 if not File_Cache_Enabled
then
1880 return File_Stamp
(Find_File
(N
, T
));
1883 Time_Stamp
:= File_Stamp_Hash_Table
.Get
(N
);
1885 if Time_Stamp
(1) = ' ' then
1886 Time_Stamp
:= File_Stamp
(Smart_Find_File
(N
, T
));
1887 File_Stamp_Hash_Table
.Set
(N
, Time_Stamp
);
1891 end Smart_File_Stamp
;
1893 ---------------------
1894 -- Smart_Find_File --
1895 ---------------------
1897 function Smart_Find_File
1898 (N
: File_Name_Type
;
1900 return File_Name_Type
1902 Full_File_Name
: File_Name_Type
;
1905 if not File_Cache_Enabled
then
1906 return Find_File
(N
, T
);
1909 Full_File_Name
:= File_Name_Hash_Table
.Get
(N
);
1911 if Full_File_Name
= No_File
then
1912 Full_File_Name
:= Find_File
(N
, T
);
1913 File_Name_Hash_Table
.Set
(N
, Full_File_Name
);
1916 return Full_File_Name
;
1917 end Smart_Find_File
;
1919 ----------------------
1920 -- Source_File_Data --
1921 ----------------------
1923 procedure Source_File_Data
(Cache
: Boolean) is
1925 File_Cache_Enabled
:= Cache
;
1926 end Source_File_Data
;
1928 -----------------------
1929 -- Source_File_Stamp --
1930 -----------------------
1932 function Source_File_Stamp
(N
: File_Name_Type
) return Time_Stamp_Type
is
1934 return Smart_File_Stamp
(N
, Source
);
1935 end Source_File_Stamp
;
1937 ---------------------
1938 -- Strip_Directory --
1939 ---------------------
1941 function Strip_Directory
(Name
: File_Name_Type
) return File_Name_Type
is
1943 Get_Name_String
(Name
);
1945 for J
in reverse 1 .. Name_Len
- 1 loop
1946 -- If we find the last directory separator
1948 if Is_Directory_Separator
(Name_Buffer
(J
)) then
1949 -- Return the part of Name that follows this last directory
1952 Name_Buffer
(1 .. Name_Len
- J
) := Name_Buffer
(J
+ 1 .. Name_Len
);
1953 Name_Len
:= Name_Len
- J
;
1958 -- There were no directory separator, just return Name
1961 end Strip_Directory
;
1967 function Strip_Suffix
(Name
: File_Name_Type
) return File_Name_Type
is
1969 Get_Name_String
(Name
);
1971 for J
in reverse 2 .. Name_Len
loop
1973 -- If we found the last '.', return the part of Name that precedes
1976 if Name_Buffer
(J
) = '.' then
1985 ---------------------------
1986 -- To_Canonical_Dir_Spec --
1987 ---------------------------
1989 function To_Canonical_Dir_Spec
1991 Prefix_Style
: Boolean)
1992 return String_Access
1994 function To_Canonical_Dir_Spec
1995 (Host_Dir
: Address
;
1996 Prefix_Flag
: Integer)
1998 pragma Import
(C
, To_Canonical_Dir_Spec
, "__gnat_to_canonical_dir_spec");
2000 C_Host_Dir
: String (1 .. Host_Dir
'Length + 1);
2001 Canonical_Dir_Addr
: Address
;
2002 Canonical_Dir_Len
: Integer;
2005 C_Host_Dir
(1 .. Host_Dir
'Length) := Host_Dir
;
2006 C_Host_Dir
(C_Host_Dir
'Last) := ASCII
.NUL
;
2008 if Prefix_Style
then
2009 Canonical_Dir_Addr
:= To_Canonical_Dir_Spec
(C_Host_Dir
'Address, 1);
2011 Canonical_Dir_Addr
:= To_Canonical_Dir_Spec
(C_Host_Dir
'Address, 0);
2013 Canonical_Dir_Len
:= C_String_Length
(Canonical_Dir_Addr
);
2015 if Canonical_Dir_Len
= 0 then
2018 return To_Path_String_Access
(Canonical_Dir_Addr
, Canonical_Dir_Len
);
2023 Fail
("erroneous directory spec: ", Host_Dir
);
2025 end To_Canonical_Dir_Spec
;
2027 ---------------------------
2028 -- To_Canonical_File_List --
2029 ---------------------------
2031 function To_Canonical_File_List
2032 (Wildcard_Host_File
: String;
2033 Only_Dirs
: Boolean)
2034 return String_Access_List_Access
2036 function To_Canonical_File_List_Init
2037 (Host_File
: Address
;
2038 Only_Dirs
: Integer)
2040 pragma Import
(C
, To_Canonical_File_List_Init
,
2041 "__gnat_to_canonical_file_list_init");
2043 function To_Canonical_File_List_Next
return Address
;
2044 pragma Import
(C
, To_Canonical_File_List_Next
,
2045 "__gnat_to_canonical_file_list_next");
2047 procedure To_Canonical_File_List_Free
;
2048 pragma Import
(C
, To_Canonical_File_List_Free
,
2049 "__gnat_to_canonical_file_list_free");
2051 Num_Files
: Integer;
2052 C_Wildcard_Host_File
: String (1 .. Wildcard_Host_File
'Length + 1);
2055 C_Wildcard_Host_File
(1 .. Wildcard_Host_File
'Length) :=
2057 C_Wildcard_Host_File
(C_Wildcard_Host_File
'Last) := ASCII
.NUL
;
2059 -- Do the expansion and say how many there are
2061 Num_Files
:= To_Canonical_File_List_Init
2062 (C_Wildcard_Host_File
'Address, Boolean'Pos (Only_Dirs
));
2065 Canonical_File_List
: String_Access_List
(1 .. Num_Files
);
2066 Canonical_File_Addr
: Address
;
2067 Canonical_File_Len
: Integer;
2070 -- Retrieve the expanded directoy names and build the list
2072 for J
in 1 .. Num_Files
loop
2073 Canonical_File_Addr
:= To_Canonical_File_List_Next
;
2074 Canonical_File_Len
:= C_String_Length
(Canonical_File_Addr
);
2075 Canonical_File_List
(J
) := To_Path_String_Access
2076 (Canonical_File_Addr
, Canonical_File_Len
);
2079 -- Free up the storage
2081 To_Canonical_File_List_Free
;
2083 return new String_Access_List
'(Canonical_File_List);
2085 end To_Canonical_File_List;
2087 ----------------------------
2088 -- To_Canonical_File_Spec --
2089 ----------------------------
2091 function To_Canonical_File_Spec
2092 (Host_File : String)
2093 return String_Access
2095 function To_Canonical_File_Spec (Host_File : Address) return Address;
2097 (C, To_Canonical_File_Spec, "__gnat_to_canonical_file_spec");
2099 C_Host_File : String (1 .. Host_File'Length + 1);
2100 Canonical_File_Addr : Address;
2101 Canonical_File_Len : Integer;
2104 C_Host_File (1 .. Host_File'Length) := Host_File;
2105 C_Host_File (C_Host_File'Last) := ASCII.NUL;
2107 Canonical_File_Addr := To_Canonical_File_Spec (C_Host_File'Address);
2108 Canonical_File_Len := C_String_Length (Canonical_File_Addr);
2110 if Canonical_File_Len = 0 then
2113 return To_Path_String_Access
2114 (Canonical_File_Addr, Canonical_File_Len);
2119 Fail ("erroneous file spec: ", Host_File);
2121 end To_Canonical_File_Spec;
2123 ----------------------------
2124 -- To_Canonical_Path_Spec --
2125 ----------------------------
2127 function To_Canonical_Path_Spec
2128 (Host_Path : String)
2129 return String_Access
2131 function To_Canonical_Path_Spec (Host_Path : Address) return Address;
2133 (C, To_Canonical_Path_Spec, "__gnat_to_canonical_path_spec");
2135 C_Host_Path : String (1 .. Host_Path'Length + 1);
2136 Canonical_Path_Addr : Address;
2137 Canonical_Path_Len : Integer;
2140 C_Host_Path (1 .. Host_Path'Length) := Host_Path;
2141 C_Host_Path (C_Host_Path'Last) := ASCII.NUL;
2143 Canonical_Path_Addr := To_Canonical_Path_Spec (C_Host_Path'Address);
2144 Canonical_Path_Len := C_String_Length (Canonical_Path_Addr);
2146 -- Return a null string (vice a null) for zero length paths, for
2147 -- compatibility with getenv().
2149 return To_Path_String_Access (Canonical_Path_Addr, Canonical_Path_Len);
2153 Fail ("erroneous path spec: ", Host_Path);
2155 end To_Canonical_Path_Spec;
2157 ---------------------------
2158 -- To_Host_Dir_Spec --
2159 ---------------------------
2161 function To_Host_Dir_Spec
2162 (Canonical_Dir : String;
2163 Prefix_Style : Boolean)
2164 return String_Access
2166 function To_Host_Dir_Spec
2167 (Canonical_Dir : Address;
2168 Prefix_Flag : Integer)
2170 pragma Import (C, To_Host_Dir_Spec, "__gnat_to_host_dir_spec");
2172 C_Canonical_Dir : String (1 .. Canonical_Dir'Length + 1);
2173 Host_Dir_Addr : Address;
2174 Host_Dir_Len : Integer;
2177 C_Canonical_Dir (1 .. Canonical_Dir'Length) := Canonical_Dir;
2178 C_Canonical_Dir (C_Canonical_Dir'Last) := ASCII.NUL;
2180 if Prefix_Style then
2181 Host_Dir_Addr := To_Host_Dir_Spec (C_Canonical_Dir'Address, 1);
2183 Host_Dir_Addr := To_Host_Dir_Spec (C_Canonical_Dir'Address, 0);
2185 Host_Dir_Len := C_String_Length (Host_Dir_Addr);
2187 if Host_Dir_Len = 0 then
2190 return To_Path_String_Access (Host_Dir_Addr, Host_Dir_Len);
2192 end To_Host_Dir_Spec;
2194 ----------------------------
2195 -- To_Host_File_Spec --
2196 ----------------------------
2198 function To_Host_File_Spec
2199 (Canonical_File : String)
2200 return String_Access
2202 function To_Host_File_Spec (Canonical_File : Address) return Address;
2203 pragma Import (C, To_Host_File_Spec, "__gnat_to_host_file_spec");
2205 C_Canonical_File : String (1 .. Canonical_File'Length + 1);
2206 Host_File_Addr : Address;
2207 Host_File_Len : Integer;
2210 C_Canonical_File (1 .. Canonical_File'Length) := Canonical_File;
2211 C_Canonical_File (C_Canonical_File'Last) := ASCII.NUL;
2213 Host_File_Addr := To_Host_File_Spec (C_Canonical_File'Address);
2214 Host_File_Len := C_String_Length (Host_File_Addr);
2216 if Host_File_Len = 0 then
2219 return To_Path_String_Access
2220 (Host_File_Addr, Host_File_Len);
2222 end To_Host_File_Spec;
2224 ---------------------------
2225 -- To_Path_String_Access --
2226 ---------------------------
2228 function To_Path_String_Access
2229 (Path_Addr : Address;
2231 return String_Access
2233 subtype Path_String is String (1 .. Path_Len);
2234 type Path_String_Access is access Path_String;
2236 function Address_To_Access is new
2237 Unchecked_Conversion (Source => Address,
2238 Target => Path_String_Access);
2240 Path_Access : Path_String_Access := Address_To_Access (Path_Addr);
2242 Return_Val : String_Access;
2245 Return_Val := new String (1 .. Path_Len);
2247 for J in 1 .. Path_Len loop
2248 Return_Val (J) := Path_Access (J);
2252 end To_Path_String_Access;
2258 function Update_Path (Path : String_Ptr) return String_Ptr is
2260 function C_Update_Path (Path, Component : Address) return Address;
2261 pragma Import (C, C_Update_Path, "update_path");
2263 function Strlen (Str : Address) return Integer;
2264 pragma Import (C, Strlen, "strlen");
2266 procedure Strncpy (X : Address; Y : Address; Length : Integer);
2267 pragma Import (C, Strncpy, "strncpy");
2269 In_Length : constant Integer := Path'Length;
2270 In_String : String (1 .. In_Length + 1);
2271 Component_Name : aliased String := "GNAT" & ASCII.NUL;
2272 Result_Ptr : Address;
2273 Result_Length : Integer;
2274 Out_String : String_Ptr;
2277 In_String (1 .. In_Length) := Path.all;
2278 In_String (In_Length + 1) := ASCII.NUL;
2279 Result_Ptr := C_Update_Path (In_String'Address,
2280 Component_Name'Address);
2281 Result_Length := Strlen (Result_Ptr);
2283 Out_String := new String (1 .. Result_Length);
2284 Strncpy (Out_String.all'Address, Result_Ptr, Result_Length);
2292 procedure Write_Info (Info : String) is
2294 Write_With_Check (Info'Address, Info'Length);
2295 Write_With_Check (EOL'Address, 1);
2298 ------------------------
2299 -- Write_Program_Name --
2300 ------------------------
2302 procedure Write_Program_Name is
2303 Save_Buffer : String (1 .. Name_Len) := Name_Buffer (1 .. Name_Len);
2309 -- Convert the name to lower case so error messages are the same on
2312 for J in 1 .. Name_Len loop
2313 if Name_Buffer (J) in 'A
' .. 'Z
' then
2315 Character'Val (Character'Pos (Name_Buffer (J)) + 32);
2319 Write_Str (Name_Buffer (1 .. Name_Len));
2321 -- Restore Name_Buffer which was clobbered by the call to
2322 -- Find_Program_Name
2324 Name_Len := Save_Buffer'Last;
2325 Name_Buffer (1 .. Name_Len) := Save_Buffer;
2326 end Write_Program_Name;
2328 ----------------------
2329 -- Write_With_Check --
2330 ----------------------
2332 procedure Write_With_Check (A : Address; N : Integer) is
2336 if N = Write (Output_FD, A, N) then
2340 Write_Str ("error: disk full writing ");
2341 Write_Name_Decoded (Output_File_Name);
2343 Name_Len := Name_Len + 1;
2344 Name_Buffer (Name_Len) := ASCII.NUL;
2345 Delete_File (Name_Buffer'Address, Ignore);
2346 Exit_Program (E_Fatal);
2348 end Write_With_Check;
2350 ----------------------------
2351 -- Package Initialization --
2352 ----------------------------
2355 Initialization : declare
2357 function Get_Default_Identifier_Character_Set return Character;
2358 pragma Import (C, Get_Default_Identifier_Character_Set,
2359 "__gnat_get_default_identifier_character_set");
2360 -- Function to determine the default identifier character set,
2361 -- which is system dependent. See Opt package spec for a list of
2362 -- the possible character codes and their interpretations.
2364 function Get_Maximum_File_Name_Length return Int;
2365 pragma Import (C, Get_Maximum_File_Name_Length,
2366 "__gnat_get_maximum_file_name_length");
2367 -- Function to get maximum file name length for system
2370 Src_Search_Directories.Init;
2371 Lib_Search_Directories.Init;
2373 Identifier_Character_Set := Get_Default_Identifier_Character_Set;
2374 Maximum_File_Name_Length := Get_Maximum_File_Name_Length;
2376 -- Following should be removed by having above function return
2377 -- Integer'Last as indication of no maximum instead of -1 ???
2379 if Maximum_File_Name_Length = -1 then
2380 Maximum_File_Name_Length := Int'Last;
2383 -- Start off by setting all suppress options to False, these will
2384 -- be reset later (turning some on if -gnato is not specified, and
2385 -- turning all of them on if -gnatp is specified).
2387 Suppress_Options := (others => False);
2389 -- Reserve the first slot in the search paths table. This is the
2390 -- directory of the main source file or main library file and is
2391 -- filled in by each call to Next_Main_Source/Next_Main_Lib_File with
2392 -- the directory specified for this main source or library file. This
2393 -- is the directory which is searched first by default. This default
2394 -- search is inhibited by the option -I- for both source and library
2397 Src_Search_Directories.Set_Last (Primary_Directory);
2398 Src_Search_Directories.Table (Primary_Directory) := new String'("");
2400 Lib_Search_Directories
.Set_Last
(Primary_Directory
);
2401 Lib_Search_Directories
.Table
(Primary_Directory
) := new String'("");