1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 1992-2003 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;
232 Path_File_Name : String_Access;
234 procedure Add_Search_Dir
235 (Search_Dir : String;
236 Additional_Source_Dir : Boolean);
237 procedure Add_Search_Dir
238 (Search_Dir : String_Access;
239 Additional_Source_Dir : Boolean);
240 -- Add a source search dir or a library search dir, depending on the
241 -- value of Additional_Source_Dir.
243 procedure Get_Dirs_From_File (Additional_Source_Dir : Boolean);
244 -- Open a path file and read the directory to search, one per line
246 function Get_Libraries_From_Registry return String_Ptr;
247 -- On Windows systems, get the list of installed standard libraries
248 -- from the registry key:
249 -- HKEY_LOCAL_MACHINE\SOFTWARE\Ada Core Technologies\
250 -- GNAT\Standard Libraries
251 -- Return an empty string on other systems
257 procedure Add_Search_Dir
258 (Search_Dir : String;
259 Additional_Source_Dir : Boolean)
262 if Additional_Source_Dir then
263 Add_Src_Search_Dir (Search_Dir);
265 Add_Lib_Search_Dir (Search_Dir);
269 procedure Add_Search_Dir
270 (Search_Dir : String_Access;
271 Additional_Source_Dir : Boolean)
274 if Additional_Source_Dir then
275 Add_Src_Search_Dir (Search_Dir.all);
277 Add_Lib_Search_Dir (Search_Dir.all);
281 ------------------------
282 -- Get_Dirs_From_File --
283 ------------------------
285 procedure Get_Dirs_From_File (Additional_Source_Dir : Boolean) is
286 File_FD : File_Descriptor;
287 Buffer : String (1 .. Path_File_Name'Length + 1);
289 Actual_Len : Natural;
296 -- For the call to Close
299 -- Construct a C compatible character string buffer.
301 Buffer (1 .. Buffer'Last - 1) := Path_File_Name.all;
302 Buffer (Buffer'Last) := ASCII.NUL;
304 File_FD := Open_Read (Buffer'Address, Binary);
306 -- If we cannot open the file, we ignore it, we don't fail
308 if File_FD = Invalid_FD then
312 Len := Integer (File_Length (File_FD));
314 S := new String (1 .. Len);
316 -- Read the file. Note that the loop is not necessary since the
317 -- whole file is read at once except on VMS.
321 while Curr <= Len and then Actual_Len /= 0 loop
322 Actual_Len := Read (File_FD, S (Curr)'Address, Len);
323 Curr := Curr + Actual_Len;
326 -- We are done with the file, so we close it
328 Close (File_FD, Status);
329 -- We ignore any error here, because we have successfully read the
332 -- Now, we read line by line
337 while Curr < Len loop
340 if Ch = ASCII.CR or else Ch = ASCII.LF
341 or else Ch = ASCII.FF or else Ch = ASCII.VT
343 if First <= Curr then
344 Add_Search_Dir (S (First .. Curr), Additional_Source_Dir);
353 -- Last line is a special case, if the file does not end with
354 -- an end of line mark.
356 if First <= S'Last then
357 Add_Search_Dir (S (First .. S'Last), Additional_Source_Dir);
359 end Get_Dirs_From_File;
361 ---------------------------------
362 -- Get_Libraries_From_Registry --
363 ---------------------------------
365 function Get_Libraries_From_Registry return String_Ptr is
366 function C_Get_Libraries_From_Registry return Address;
367 pragma Import (C, C_Get_Libraries_From_Registry,
368 "__gnat_get_libraries_from_registry");
369 function Strlen (Str : Address) return Integer;
370 pragma Import (C, Strlen, "strlen");
371 procedure Strncpy (X : Address; Y : Address; Length : Integer);
372 pragma Import (C, Strncpy, "strncpy");
373 Result_Ptr : Address;
374 Result_Length : Integer;
375 Out_String : String_Ptr;
378 Result_Ptr := C_Get_Libraries_From_Registry;
379 Result_Length := Strlen (Result_Ptr);
381 Out_String := new String (1 .. Result_Length);
382 Strncpy (Out_String.all'Address, Result_Ptr, Result_Length);
384 end Get_Libraries_From_Registry;
386 -- Start of processing for Add_Default_Search_Dirs
389 -- After the locations specified on the command line, the next places
390 -- to look for files are the directories specified by the appropriate
391 -- environment variable. Get this value, extract the directory names
392 -- and store in the tables.
394 -- On VMS, don't expand the logical name (e.g. environment variable),
395 -- just put it into Unix (e.g. canonical) format. System services
396 -- will handle the expansion as part of the file processing.
398 for Additional_Source_Dir in False .. True loop
400 if Additional_Source_Dir then
401 Search_Path := Getenv (Ada_Include_Path);
402 if Search_Path'Length > 0 then
403 if Hostparm.OpenVMS then
404 Search_Path := To_Canonical_Path_Spec ("ADA_INCLUDE_PATH:");
406 Search_Path := To_Canonical_Path_Spec (Search_Path.all);
410 Search_Path := Getenv (Ada_Objects_Path);
411 if Search_Path'Length > 0 then
412 if Hostparm.OpenVMS then
413 Search_Path := To_Canonical_Path_Spec ("ADA_OBJECTS_PATH:");
415 Search_Path := To_Canonical_Path_Spec (Search_Path.all);
420 Get_Next_Dir_In_Path_Init (Search_Path);
422 Search_Dir := Get_Next_Dir_In_Path (Search_Path);
423 exit when Search_Dir = null;
424 Add_Search_Dir (Search_Dir, Additional_Source_Dir);
428 -- Check for eventual project path file env vars
430 Path_File_Name := Getenv (Project_Include_Path_File);
432 if Path_File_Name'Length > 0 then
433 Get_Dirs_From_File (Additional_Source_Dir => True);
436 Path_File_Name := Getenv (Project_Objects_Path_File);
438 if Path_File_Name'Length > 0 then
439 Get_Dirs_From_File (Additional_Source_Dir => False);
442 -- For the compiler, if --RTS= was apecified, add the runtime
445 if RTS_Src_Path_Name /= null and then
446 RTS_Lib_Path_Name /= null
448 Add_Search_Dirs (RTS_Src_Path_Name, Include);
449 Add_Search_Dirs (RTS_Lib_Path_Name, Objects);
452 if not Opt.No_Stdinc then
454 -- For WIN32 systems, look for any system libraries defined in
455 -- the registry. These are added to both source and object
458 Search_Path := String_Access (Get_Libraries_From_Registry);
460 Get_Next_Dir_In_Path_Init (Search_Path);
462 Search_Dir := Get_Next_Dir_In_Path (Search_Path);
463 exit when Search_Dir = null;
464 Add_Search_Dir (Search_Dir, False);
465 Add_Search_Dir (Search_Dir, True);
468 -- The last place to look are the defaults
471 Read_Default_Search_Dirs
472 (String_Access (Update_Path (Search_Dir_Prefix)),
474 String_Access (Update_Path (Include_Dir_Default_Name)));
476 Get_Next_Dir_In_Path_Init (Search_Path);
478 Search_Dir := Get_Next_Dir_In_Path (Search_Path);
479 exit when Search_Dir = null;
480 Add_Search_Dir (Search_Dir, True);
484 if not Opt.No_Stdlib and not Opt.RTS_Switch then
486 Read_Default_Search_Dirs
487 (String_Access (Update_Path (Search_Dir_Prefix)),
489 String_Access (Update_Path (Object_Dir_Default_Name)));
491 Get_Next_Dir_In_Path_Init (Search_Path);
493 Search_Dir := Get_Next_Dir_In_Path (Search_Path);
494 exit when Search_Dir = null;
495 Add_Search_Dir (Search_Dir, False);
499 end Add_Default_Search_Dirs;
505 procedure Add_File (File_Name : String) is
507 Number_File_Names := Number_File_Names + 1;
509 -- As Add_File may be called for mains specified inside
510 -- a project file, File_Names may be too short and needs
513 if Number_File_Names > File_Names'Last then
514 File_Names := new File_Name_Array'(File_Names.all & File_Names.all);
517 File_Names (Number_File_Names) := new String'(File_Name);
520 ------------------------
521 -- Add_Lib_Search_Dir --
522 ------------------------
524 procedure Add_Lib_Search_Dir (Dir : String) is
526 if Dir'Length = 0 then
527 Fail ("missing library directory name");
530 Lib_Search_Directories.Increment_Last;
531 Lib_Search_Directories.Table (Lib_Search_Directories.Last) :=
532 Normalize_Directory_Name (Dir);
533 end Add_Lib_Search_Dir;
535 ---------------------
536 -- Add_Search_Dirs --
537 ---------------------
539 procedure Add_Search_Dirs
540 (Search_Path : String_Ptr;
541 Path_Type : Search_File_Type)
543 Current_Search_Path : String_Access;
546 Get_Next_Dir_In_Path_Init (String_Access (Search_Path));
548 Current_Search_Path :=
549 Get_Next_Dir_In_Path (String_Access (Search_Path));
550 exit when Current_Search_Path = null;
552 if Path_Type = Include then
553 Add_Src_Search_Dir (Current_Search_Path.all);
555 Add_Lib_Search_Dir (Current_Search_Path.all);
560 ------------------------
561 -- Add_Src_Search_Dir --
562 ------------------------
564 procedure Add_Src_Search_Dir (Dir : String) is
566 if Dir'Length = 0 then
567 Fail ("missing source directory name");
570 Src_Search_Directories.Increment_Last;
571 Src_Search_Directories.Table (Src_Search_Directories.Last) :=
572 Normalize_Directory_Name (Dir);
573 end Add_Src_Search_Dir;
575 --------------------------------
576 -- Append_Suffix_To_File_Name --
577 --------------------------------
579 function Append_Suffix_To_File_Name
585 Get_Name_String (Name);
586 Name_Buffer (Name_Len + 1 .. Name_Len + Suffix'Length) := Suffix;
587 Name_Len := Name_Len + Suffix'Length;
589 end Append_Suffix_To_File_Name;
591 ---------------------
592 -- C_String_Length --
593 ---------------------
595 function C_String_Length (S : Address) return Integer is
596 function Strlen (S : Address) return Integer;
597 pragma Import (C, Strlen, "strlen");
600 if S = Null_Address then
607 ------------------------------
608 -- Canonical_Case_File_Name --
609 ------------------------------
611 -- For now, we only deal with the case of a-z. Eventually we should
612 -- worry about other Latin-1 letters on systems that support this ???
614 procedure Canonical_Case_File_Name (S : in out String) is
616 if not File_Names_Case_Sensitive then
617 for J in S'Range loop
618 if S (J) in 'A' .. 'Z' then
619 S (J) := Character'Val (
620 Character'Pos (S (J)) +
621 Character'Pos ('a') -
622 Character'Pos ('A'));
626 end Canonical_Case_File_Name;
632 function Concat (String_One : String; String_Two : String) return String is
633 Buffer : String (1 .. String_One'Length + String_Two'Length);
636 Buffer (1 .. String_One'Length) := String_One;
637 Buffer (String_One'Length + 1 .. Buffer'Last) := String_Two;
641 ---------------------------
642 -- Create_File_And_Check --
643 ---------------------------
645 procedure Create_File_And_Check
646 (Fdesc : out File_Descriptor;
650 Output_File_Name := Name_Enter;
651 Fdesc := Create_File (Name_Buffer'Address, Fmode);
653 if Fdesc = Invalid_FD then
654 Fail ("Cannot create: ", Name_Buffer (1 .. Name_Len));
656 end Create_File_And_Check;
658 --------------------------------
659 -- Current_Library_File_Stamp --
660 --------------------------------
662 function Current_Library_File_Stamp return Time_Stamp_Type is
664 return Current_Full_Lib_Stamp;
665 end Current_Library_File_Stamp;
667 -------------------------------
668 -- Current_Object_File_Stamp --
669 -------------------------------
671 function Current_Object_File_Stamp return Time_Stamp_Type is
673 return Current_Full_Obj_Stamp;
674 end Current_Object_File_Stamp;
676 -------------------------------
677 -- Current_Source_File_Stamp --
678 -------------------------------
680 function Current_Source_File_Stamp return Time_Stamp_Type is
682 return Current_Full_Source_Stamp;
683 end Current_Source_File_Stamp;
685 ----------------------------
686 -- Dir_In_Obj_Search_Path --
687 ----------------------------
689 function Dir_In_Obj_Search_Path (Position : Natural) return String_Ptr is
691 if Opt.Look_In_Primary_Dir then
693 Lib_Search_Directories.Table (Primary_Directory + Position - 1);
695 return Lib_Search_Directories.Table (Primary_Directory + Position);
697 end Dir_In_Obj_Search_Path;
699 ----------------------------
700 -- Dir_In_Src_Search_Path --
701 ----------------------------
703 function Dir_In_Src_Search_Path (Position : Natural) return String_Ptr is
705 if Opt.Look_In_Primary_Dir then
707 Src_Search_Directories.Table (Primary_Directory + Position - 1);
709 return Src_Search_Directories.Table (Primary_Directory + Position);
711 end Dir_In_Src_Search_Path;
713 ---------------------
714 -- Executable_Name --
715 ---------------------
717 function Executable_Name (Name : File_Name_Type) return File_Name_Type is
718 Exec_Suffix : String_Access;
721 if Name = No_File then
725 Get_Name_String (Name);
726 Exec_Suffix := Get_Executable_Suffix;
728 for J in Exec_Suffix'Range loop
729 Name_Len := Name_Len + 1;
730 Name_Buffer (Name_Len) := Exec_Suffix (J);
742 procedure Exit_Program (Exit_Code : Exit_Code_Type) is
744 -- The program will exit with the following status:
745 -- 0 if the object file has been generated (with or without warnings)
746 -- 1 if recompilation was not needed (smart recompilation)
747 -- 2 if gnat1 has been killed by a signal (detected by GCC)
748 -- 4 for a fatal error
749 -- 5 if there were errors
750 -- 6 if no code has been generated (spec)
752 -- Note that exit code 3 is not used and must not be used as this is
753 -- the code returned by a program aborted via C abort() routine on
754 -- Windows. GCC checks for that case and thinks that the child process
755 -- has been aborted. This code (exit code 3) used to be the code used
756 -- for E_No_Code, but E_No_Code was changed to 6 for this reason.
759 when E_Success => OS_Exit (0);
760 when E_Warnings => OS_Exit (0);
761 when E_No_Compile => OS_Exit (1);
762 when E_Fatal => OS_Exit (4);
763 when E_Errors => OS_Exit (5);
764 when E_No_Code => OS_Exit (6);
765 when E_Abort => OS_Abort;
773 procedure Fail (S1 : String; S2 : String := ""; S3 : String := "") is
775 -- We use Output in case there is a special output set up.
776 -- In this case Set_Standard_Error will have no immediate effect.
779 Osint.Write_Program_Name;
786 Exit_Program (E_Fatal);
793 function File_Hash (F : File_Name_Type) return File_Hash_Num is
795 return File_Hash_Num (Int (F) rem File_Hash_Num'Range_Length);
802 function File_Stamp (Name : File_Name_Type) return Time_Stamp_Type is
804 if Name = No_File then
805 return Empty_Time_Stamp;
808 Get_Name_String (Name);
810 if not Is_Regular_File (Name_Buffer (1 .. Name_Len)) then
811 return Empty_Time_Stamp;
813 Name_Buffer (Name_Len + 1) := ASCII.NUL;
814 return OS_Time_To_GNAT_Time (File_Time_Stamp (Name_Buffer));
825 return File_Name_Type
831 File_Name : String renames Name_Buffer (1 .. Name_Len);
832 File : File_Name_Type := No_File;
836 -- If we are looking for a config file, look only in the current
837 -- directory, i.e. return input argument unchanged. Also look
838 -- only in the current directory if we are looking for a .dg
839 -- file (happens in -gnatD mode)
842 or else (Debug_Generated_Code
843 and then Name_Len > 3
845 (Name_Buffer (Name_Len - 2 .. Name_Len) = ".dg"
847 (Hostparm.OpenVMS and then
848 Name_Buffer (Name_Len - 2 .. Name_Len) = "_dg")))
852 -- If we are trying to find the current main file just look in the
853 -- directory where the user said it was.
855 elsif Look_In_Primary_Directory_For_Current_Main
856 and then Current_Main = N
858 return Locate_File (N, T, Primary_Directory, File_Name);
860 -- Otherwise do standard search for source file
863 -- Check the mapping of this file name
865 File := Mapped_Path_Name (N);
867 -- If the file name is mapped to a path name, return the
868 -- corresponding path name
870 if File /= No_File then
871 -- For locally removed file, Error_Name is returned; then
872 -- return No_File, indicating the file is not a source.
874 if File = Error_Name then
882 -- First place to look is in the primary directory (i.e. the same
883 -- directory as the source) unless this has been disabled with -I-
885 if Opt.Look_In_Primary_Dir then
886 File := Locate_File (N, T, Primary_Directory, File_Name);
888 if File /= No_File then
893 -- Finally look in directories specified with switches -I/-aI/-aO
896 Last_Dir := Lib_Search_Directories.Last;
898 Last_Dir := Src_Search_Directories.Last;
901 for D in Primary_Directory + 1 .. Last_Dir loop
902 File := Locate_File (N, T, D, File_Name);
904 if File /= No_File then
914 -----------------------
915 -- Find_Program_Name --
916 -----------------------
918 procedure Find_Program_Name is
919 Command_Name : String (1 .. Len_Arg (0));
920 Cindex1 : Integer := Command_Name'First;
921 Cindex2 : Integer := Command_Name'Last;
924 Fill_Arg (Command_Name'Address, 0);
926 -- The program name might be specified by a full path name. However,
927 -- we don't want to print that all out in an error message, so the
928 -- path might need to be stripped away.
930 for J in reverse Cindex1 .. Cindex2 loop
931 if Is_Directory_Separator (Command_Name (J)) then
937 for J in reverse Cindex1 .. Cindex2 loop
938 if Command_Name (J) = '.' then
944 Name_Len := Cindex2 - Cindex1 + 1;
945 Name_Buffer (1 .. Name_Len) := Command_Name (Cindex1 .. Cindex2);
946 end Find_Program_Name;
948 ------------------------
949 -- Full_Lib_File_Name --
950 ------------------------
952 function Full_Lib_File_Name (N : File_Name_Type) return File_Name_Type is
954 return Find_File (N, Library);
955 end Full_Lib_File_Name;
957 ----------------------------
958 -- Full_Library_Info_Name --
959 ----------------------------
961 function Full_Library_Info_Name return File_Name_Type is
963 return Current_Full_Lib_Name;
964 end Full_Library_Info_Name;
966 ---------------------------
967 -- Full_Object_File_Name --
968 ---------------------------
970 function Full_Object_File_Name return File_Name_Type is
972 return Current_Full_Obj_Name;
973 end Full_Object_File_Name;
975 ----------------------
976 -- Full_Source_Name --
977 ----------------------
979 function Full_Source_Name return File_Name_Type is
981 return Current_Full_Source_Name;
982 end Full_Source_Name;
984 ----------------------
985 -- Full_Source_Name --
986 ----------------------
988 function Full_Source_Name (N : File_Name_Type) return File_Name_Type is
990 return Smart_Find_File (N, Source);
991 end Full_Source_Name;
997 function Get_Directory (Name : File_Name_Type) return File_Name_Type is
999 Get_Name_String (Name);
1001 for J in reverse 1 .. Name_Len loop
1002 if Is_Directory_Separator (Name_Buffer (J)) then
1008 Name_Len := Hostparm.Normalized_CWD'Length;
1009 Name_Buffer (1 .. Name_Len) := Hostparm.Normalized_CWD;
1013 --------------------------
1014 -- Get_Next_Dir_In_Path --
1015 --------------------------
1017 Search_Path_Pos : Integer;
1018 -- Keeps track of current position in search path. Initialized by the
1019 -- call to Get_Next_Dir_In_Path_Init, updated by Get_Next_Dir_In_Path.
1021 function Get_Next_Dir_In_Path
1022 (Search_Path : String_Access)
1023 return String_Access
1025 Lower_Bound : Positive := Search_Path_Pos;
1026 Upper_Bound : Positive;
1030 while Lower_Bound <= Search_Path'Last
1031 and then Search_Path.all (Lower_Bound) = Path_Separator
1033 Lower_Bound := Lower_Bound + 1;
1036 exit when Lower_Bound > Search_Path'Last;
1038 Upper_Bound := Lower_Bound;
1039 while Upper_Bound <= Search_Path'Last
1040 and then Search_Path.all (Upper_Bound) /= Path_Separator
1042 Upper_Bound := Upper_Bound + 1;
1045 Search_Path_Pos := Upper_Bound;
1046 return new String'(Search_Path.all (Lower_Bound .. Upper_Bound - 1));
1050 end Get_Next_Dir_In_Path;
1052 -------------------------------
1053 -- Get_Next_Dir_In_Path_Init --
1054 -------------------------------
1056 procedure Get_Next_Dir_In_Path_Init (Search_Path : String_Access) is
1058 Search_Path_Pos := Search_Path'First;
1059 end Get_Next_Dir_In_Path_Init;
1061 --------------------------------------
1062 -- Get_Primary_Src_Search_Directory --
1063 --------------------------------------
1065 function Get_Primary_Src_Search_Directory return String_Ptr is
1067 return Src_Search_Directories.Table (Primary_Directory);
1068 end Get_Primary_Src_Search_Directory;
1070 -------------------------
1071 -- Get_RTS_Search_Dir --
1072 -------------------------
1074 function Get_RTS_Search_Dir
1075 (Search_Dir : String;
1076 File_Type : Search_File_Type)
1079 procedure Get_Current_Dir
1080 (Dir : System.Address;
1081 Length : System.Address);
1082 pragma Import (C, Get_Current_Dir, "__gnat_get_current_dir");
1085 pragma Import (C, Max_Path, "__gnat_max_path_len");
1086 -- Maximum length of a path name
1088 Current_Dir : String_Ptr;
1089 Default_Search_Dir : String_Access;
1090 Default_Suffix_Dir : String_Access;
1091 Local_Search_Dir : String_Access;
1092 Norm_Search_Dir : String_Access;
1093 Result_Search_Dir : String_Access;
1094 Search_File : String_Access;
1095 Temp_String : String_Ptr;
1098 -- Add a directory separator at the end of the directory if necessary
1099 -- so that we can directly append a file to the directory
1101 if Search_Dir (Search_Dir'Last) /= Directory_Separator then
1102 Local_Search_Dir := new String'
1103 (Concat (Search_Dir, String'(1 => Directory_Separator)));
1105 Local_Search_Dir := new String'(Search_Dir);
1108 if File_Type = Include then
1109 Search_File := Include_Search_File;
1110 Default_Suffix_Dir := new String'("adainclude");
1112 Search_File := Objects_Search_File;
1113 Default_Suffix_Dir := new String'("adalib");
1116 Norm_Search_Dir := To_Canonical_Path_Spec (Local_Search_Dir.all);
1118 if Is_Absolute_Path (Norm_Search_Dir.all) then
1120 -- We first verify if there is a directory Include_Search_Dir
1121 -- containing default search directories
1124 := Read_Default_Search_Dirs (Norm_Search_Dir,
1127 Default_Search_Dir := new String'
1128 (Concat (Norm_Search_Dir.all, Default_Suffix_Dir.all));
1129 Free (Norm_Search_Dir);
1131 if Result_Search_Dir /= null then
1132 return String_Ptr (Result_Search_Dir);
1133 elsif Is_Directory (Default_Search_Dir.all) then
1134 return String_Ptr (Default_Search_Dir);
1140 -- Search in the current directory
1142 -- Get the current directory
1145 Buffer : String (1 .. Max_Path + 2);
1146 Path_Len : Natural := Max_Path;
1149 Get_Current_Dir (Buffer'Address, Path_Len'Address);
1151 if Buffer (Path_Len) /= Directory_Separator then
1152 Path_Len := Path_Len + 1;
1153 Buffer (Path_Len) := Directory_Separator;
1156 Current_Dir := new String'(Buffer (1 .. Path_Len));
1160 new String'(Concat (Current_Dir.all, Local_Search_Dir.all));
1162 Result_Search_Dir :=
1163 Read_Default_Search_Dirs (Norm_Search_Dir, Search_File, null);
1165 Default_Search_Dir :=
1167 (Concat (Norm_Search_Dir.all, Default_Suffix_Dir.all));
1169 Free (Norm_Search_Dir);
1171 if Result_Search_Dir /= null then
1172 return String_Ptr (Result_Search_Dir);
1174 elsif Is_Directory (Default_Search_Dir.all) then
1175 return String_Ptr (Default_Search_Dir);
1178 -- Search in Search_Dir_Prefix/Search_Dir
1182 (Concat (Update_Path (Search_Dir_Prefix).all,
1183 Local_Search_Dir.all));
1185 Result_Search_Dir :=
1186 Read_Default_Search_Dirs (Norm_Search_Dir, Search_File, null);
1188 Default_Search_Dir :=
1190 (Concat (Norm_Search_Dir.all, Default_Suffix_Dir.all));
1192 Free (Norm_Search_Dir);
1194 if Result_Search_Dir /= null then
1195 return String_Ptr (Result_Search_Dir);
1197 elsif Is_Directory (Default_Search_Dir.all) then
1198 return String_Ptr (Default_Search_Dir);
1201 -- We finally search in Search_Dir_Prefix/rts-Search_Dir
1205 (Concat (Update_Path (Search_Dir_Prefix).all, "rts-"));
1208 new String'(Concat (Temp_String.all, Local_Search_Dir.all));
1210 Result_Search_Dir :=
1211 Read_Default_Search_Dirs (Norm_Search_Dir, Search_File, null);
1213 Default_Search_Dir :=
1215 (Concat (Norm_Search_Dir.all, Default_Suffix_Dir.all));
1216 Free (Norm_Search_Dir);
1218 if Result_Search_Dir /= null then
1219 return String_Ptr (Result_Search_Dir);
1221 elsif Is_Directory (Default_Search_Dir.all) then
1222 return String_Ptr (Default_Search_Dir);
1230 end Get_RTS_Search_Dir;
1236 procedure Initialize is
1238 Number_File_Names := 0;
1239 Current_File_Name_Index := 0;
1241 Src_Search_Directories.Init;
1242 Lib_Search_Directories.Init;
1244 -- Start off by setting all suppress options to False, these will
1245 -- be reset later (turning some on if -gnato is not specified, and
1246 -- turning all of them on if -gnatp is specified).
1248 Suppress_Options := (others => False);
1250 -- Reserve the first slot in the search paths table. This is the
1251 -- directory of the main source file or main library file and is
1252 -- filled in by each call to Next_Main_Source/Next_Main_Lib_File with
1253 -- the directory specified for this main source or library file. This
1254 -- is the directory which is searched first by default. This default
1255 -- search is inhibited by the option -I- for both source and library
1258 Src_Search_Directories.Set_Last (Primary_Directory);
1259 Src_Search_Directories.Table (Primary_Directory) := new String'("");
1261 Lib_Search_Directories.Set_Last (Primary_Directory);
1262 Lib_Search_Directories.Table (Primary_Directory) := new String'("");
1265 ----------------------------
1266 -- Is_Directory_Separator --
1267 ----------------------------
1269 function Is_Directory_Separator (C : Character) return Boolean is
1271 -- In addition to the default directory_separator allow the '/' to
1272 -- act as separator since this is allowed in MS-DOS, Windows 95/NT,
1273 -- and OS2 ports. On VMS, the situation is more complicated because
1274 -- there are two characters to check for.
1277 C = Directory_Separator
1279 or else (Hostparm.OpenVMS
1280 and then (C = ']' or else C = ':'));
1281 end Is_Directory_Separator;
1283 -------------------------
1284 -- Is_Readonly_Library --
1285 -------------------------
1287 function Is_Readonly_Library (File : in File_Name_Type) return Boolean is
1289 Get_Name_String (File);
1291 pragma Assert (Name_Buffer (Name_Len - 3 .. Name_Len) = ".ali");
1293 return not Is_Writable_File (Name_Buffer (1 .. Name_Len));
1294 end Is_Readonly_Library;
1300 function Lib_File_Name
1301 (Source_File : File_Name_Type)
1302 return File_Name_Type
1305 -- Pointer to location to set extension in place
1308 Get_Name_String (Source_File);
1309 Fptr := Name_Len + 1;
1311 for J in reverse 2 .. Name_Len loop
1312 if Name_Buffer (J) = '.' then
1318 Name_Buffer (Fptr) := '.';
1319 Name_Buffer (Fptr + 1 .. Fptr + ALI_Suffix'Length) := ALI_Suffix.all;
1320 Name_Buffer (Fptr + ALI_Suffix'Length + 1) := ASCII.NUL;
1321 Name_Len := Fptr + ALI_Suffix'Length;
1325 ------------------------
1326 -- Library_File_Stamp --
1327 ------------------------
1329 function Library_File_Stamp (N : File_Name_Type) return Time_Stamp_Type is
1331 return File_Stamp (Find_File (N, Library));
1332 end Library_File_Stamp;
1338 function Locate_File
1339 (N : File_Name_Type;
1343 return File_Name_Type
1345 Dir_Name : String_Ptr;
1349 Dir_Name := Lib_Search_Directories.Table (Dir);
1351 else pragma Assert (T /= Config);
1352 Dir_Name := Src_Search_Directories.Table (Dir);
1356 Full_Name : String (1 .. Dir_Name'Length + Name'Length);
1359 Full_Name (1 .. Dir_Name'Length) := Dir_Name.all;
1360 Full_Name (Dir_Name'Length + 1 .. Full_Name'Length) := Name;
1362 if not Is_Regular_File (Full_Name) then
1366 -- If the file is in the current directory then return N itself
1368 if Dir_Name'Length = 0 then
1371 Name_Len := Full_Name'Length;
1372 Name_Buffer (1 .. Name_Len) := Full_Name;
1379 -------------------------------
1380 -- Matching_Full_Source_Name --
1381 -------------------------------
1383 function Matching_Full_Source_Name
1384 (N : File_Name_Type;
1385 T : Time_Stamp_Type)
1386 return File_Name_Type
1389 Get_Name_String (N);
1392 File_Name : constant String := Name_Buffer (1 .. Name_Len);
1393 File : File_Name_Type := No_File;
1397 if Opt.Look_In_Primary_Dir then
1398 File := Locate_File (N, Source, Primary_Directory, File_Name);
1400 if File /= No_File and then T = File_Stamp (N) then
1405 Last_Dir := Src_Search_Directories.Last;
1407 for D in Primary_Directory + 1 .. Last_Dir loop
1408 File := Locate_File (N, Source, D, File_Name);
1410 if File /= No_File and then T = File_Stamp (File) then
1417 end Matching_Full_Source_Name;
1423 function More_Files return Boolean is
1425 return (Current_File_Name_Index < Number_File_Names);
1428 -------------------------------
1429 -- Nb_Dir_In_Obj_Search_Path --
1430 -------------------------------
1432 function Nb_Dir_In_Obj_Search_Path return Natural is
1434 if Opt.Look_In_Primary_Dir then
1435 return Lib_Search_Directories.Last - Primary_Directory + 1;
1437 return Lib_Search_Directories.Last - Primary_Directory;
1439 end Nb_Dir_In_Obj_Search_Path;
1441 -------------------------------
1442 -- Nb_Dir_In_Src_Search_Path --
1443 -------------------------------
1445 function Nb_Dir_In_Src_Search_Path return Natural is
1447 if Opt.Look_In_Primary_Dir then
1448 return Src_Search_Directories.Last - Primary_Directory + 1;
1450 return Src_Search_Directories.Last - Primary_Directory;
1452 end Nb_Dir_In_Src_Search_Path;
1454 --------------------
1455 -- Next_Main_File --
1456 --------------------
1458 function Next_Main_File return File_Name_Type is
1459 File_Name : String_Ptr;
1460 Dir_Name : String_Ptr;
1464 pragma Assert (More_Files);
1466 Current_File_Name_Index := Current_File_Name_Index + 1;
1468 -- Get the file and directory name
1470 File_Name := File_Names (Current_File_Name_Index);
1471 Fptr := File_Name'First;
1473 for J in reverse File_Name'Range loop
1474 if File_Name (J) = Directory_Separator
1475 or else File_Name (J) = '/'
1477 if J = File_Name'Last then
1478 Fail ("File name missing");
1486 -- Save name of directory in which main unit resides for use in
1487 -- locating other units
1489 Dir_Name := new String'(File_Name (File_Name'First .. Fptr - 1));
1491 case Running_Program is
1494 Src_Search_Directories.Table (Primary_Directory) := Dir_Name;
1495 Look_In_Primary_Directory_For_Current_Main := True;
1498 Src_Search_Directories.Table (Primary_Directory) := Dir_Name;
1500 if Fptr > File_Name'First then
1501 Look_In_Primary_Directory_For_Current_Main := True;
1504 when Binder | Gnatls =>
1505 Dir_Name := Normalize_Directory_Name (Dir_Name.all);
1506 Lib_Search_Directories.Table (Primary_Directory) := Dir_Name;
1512 Name_Len := File_Name'Last - Fptr + 1;
1513 Name_Buffer (1 .. Name_Len) := File_Name (Fptr .. File_Name'Last);
1514 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
1515 Current_Main := File_Name_Type (Name_Find);
1517 -- In the gnatmake case, the main file may have not have the
1518 -- extension. Try ".adb" first then ".ads"
1520 if Running_Program = Make then
1522 Orig_Main : constant File_Name_Type := Current_Main;
1525 if Strip_Suffix (Orig_Main) = Orig_Main then
1526 Current_Main := Append_Suffix_To_File_Name (Orig_Main, ".adb");
1528 if Full_Source_Name (Current_Main) = No_File then
1530 Append_Suffix_To_File_Name (Orig_Main, ".ads");
1532 if Full_Source_Name (Current_Main) = No_File then
1533 Current_Main := Orig_Main;
1540 return Current_Main;
1543 ------------------------------
1544 -- Normalize_Directory_Name --
1545 ------------------------------
1547 function Normalize_Directory_Name (Directory : String) return String_Ptr is
1549 function Is_Quoted (Path : String) return Boolean;
1550 pragma Inline (Is_Quoted);
1551 -- Returns true if Path is quoted (either double or single quotes)
1557 function Is_Quoted (Path : String) return Boolean is
1558 First : constant Character := Path (Path'First);
1559 Last : constant Character := Path (Path'Last);
1562 if (First = ''' and then Last = ''')
1564 (First = '"' and then Last = '"')
1572 Result : String_Ptr;
1574 -- Start of processing for Normalize_Directory_Name
1577 if Directory'Length = 0 then
1578 Result := new String'(Hostparm.Normalized_CWD);
1580 elsif Is_Directory_Separator (Directory (Directory'Last)) then
1581 Result := new String'(Directory);
1583 elsif Is_Quoted (Directory) then
1585 -- This is a quoted string, it certainly means that the directory
1586 -- contains some spaces for example. We can safely remove the quotes
1587 -- here as the OS_Lib.Normalize_Arguments will be called before any
1588 -- spawn routines. This ensure that quotes will be added when needed.
1590 Result := new String (1 .. Directory'Length - 1);
1591 Result (1 .. Directory'Length - 1) :=
1592 Directory (Directory'First + 1 .. Directory'Last - 1);
1593 Result (Result'Last) := Directory_Separator;
1596 Result := new String (1 .. Directory'Length + 1);
1597 Result (1 .. Directory'Length) := Directory;
1598 Result (Directory'Length + 1) := Directory_Separator;
1602 end Normalize_Directory_Name;
1604 ---------------------
1605 -- Number_Of_Files --
1606 ---------------------
1608 function Number_Of_Files return Int is
1610 return Number_File_Names;
1611 end Number_Of_Files;
1613 ----------------------
1614 -- Object_File_Name --
1615 ----------------------
1617 function Object_File_Name (N : File_Name_Type) return File_Name_Type is
1623 Get_Name_String (N);
1624 Name_Len := Name_Len - ALI_Suffix'Length - 1;
1626 for J in Object_Suffix'Range loop
1627 Name_Len := Name_Len + 1;
1628 Name_Buffer (Name_Len) := Object_Suffix (J);
1632 end Object_File_Name;
1634 --------------------------
1635 -- OS_Time_To_GNAT_Time --
1636 --------------------------
1638 function OS_Time_To_GNAT_Time (T : OS_Time) return Time_Stamp_Type is
1639 GNAT_Time : Time_Stamp_Type;
1649 GM_Split (T, Y, Mo, D, H, Mn, S);
1655 Minutes => Nat (Mn),
1660 end OS_Time_To_GNAT_Time;
1666 function Program_Name (Nam : String) return String_Access is
1667 Res : String_Access;
1670 -- Get the name of the current program being executed
1674 -- Find the target prefix if any, for the cross compilation case
1675 -- for instance in "alpha-dec-vxworks-gcc" the target prefix is
1676 -- "alpha-dec-vxworks-"
1678 while Name_Len > 0 loop
1679 if Name_Buffer (Name_Len) = '-' then
1683 Name_Len := Name_Len - 1;
1686 -- Create the new program name
1688 Res := new String (1 .. Name_Len + Nam'Length);
1689 Res.all (1 .. Name_Len) := Name_Buffer (1 .. Name_Len);
1690 Res.all (Name_Len + 1 .. Name_Len + Nam'Length) := Nam;
1694 ------------------------------
1695 -- Read_Default_Search_Dirs --
1696 ------------------------------
1698 function Read_Default_Search_Dirs
1699 (Search_Dir_Prefix : String_Access;
1700 Search_File : String_Access;
1701 Search_Dir_Default_Name : String_Access)
1702 return String_Access
1704 Prefix_Len : constant Integer := Search_Dir_Prefix.all'Length;
1705 Buffer : String (1 .. Prefix_Len + Search_File.all'Length + 1);
1706 File_FD : File_Descriptor;
1707 S, S1 : String_Access;
1710 Actual_Len : Integer;
1713 Prev_Was_Separator : Boolean;
1714 Nb_Relative_Dir : Integer;
1716 function Is_Relative (S : String; K : Positive) return Boolean;
1717 pragma Inline (Is_Relative);
1718 -- Returns True if a relative directory specification is found
1719 -- in S at position K, False otherwise.
1725 function Is_Relative (S : String; K : Positive) return Boolean is
1727 return not Is_Absolute_Path (S (K .. S'Last));
1730 -- Start of processing for Read_Default_Search_Dirs
1733 -- Construct a C compatible character string buffer.
1735 Buffer (1 .. Search_Dir_Prefix.all'Length)
1736 := Search_Dir_Prefix.all;
1737 Buffer (Search_Dir_Prefix.all'Length + 1 .. Buffer'Last - 1)
1739 Buffer (Buffer'Last) := ASCII.NUL;
1741 File_FD := Open_Read (Buffer'Address, Binary);
1742 if File_FD = Invalid_FD then
1743 return Search_Dir_Default_Name;
1746 Len := Integer (File_Length (File_FD));
1748 -- An extra character for a trailing Path_Separator is allocated
1750 S := new String (1 .. Len + 1);
1751 S (Len + 1) := Path_Separator;
1753 -- Read the file. Note that the loop is not necessary since the
1754 -- whole file is read at once except on VMS.
1758 while Actual_Len /= 0 loop
1759 Actual_Len := Read (File_FD, S (Curr)'Address, Len);
1760 Curr := Curr + Actual_Len;
1763 -- Process the file, translating line and file ending
1764 -- control characters to a path separator character.
1766 Prev_Was_Separator := True;
1767 Nb_Relative_Dir := 0;
1768 for J in 1 .. Len loop
1769 if S (J) in ASCII.NUL .. ASCII.US
1772 S (J) := Path_Separator;
1775 if S (J) = Path_Separator then
1776 Prev_Was_Separator := True;
1778 if Prev_Was_Separator and then Is_Relative (S.all, J) then
1779 Nb_Relative_Dir := Nb_Relative_Dir + 1;
1782 Prev_Was_Separator := False;
1786 if Nb_Relative_Dir = 0 then
1790 -- Add the Search_Dir_Prefix to all relative paths
1792 S1 := new String (1 .. S'Length + Nb_Relative_Dir * Prefix_Len);
1794 Prev_Was_Separator := True;
1795 for J in 1 .. Len + 1 loop
1796 if S (J) = Path_Separator then
1797 Prev_Was_Separator := True;
1800 if Prev_Was_Separator and then Is_Relative (S.all, J) then
1801 S1 (J1 .. J1 + Prefix_Len - 1) := Search_Dir_Prefix.all;
1802 J1 := J1 + Prefix_Len;
1805 Prev_Was_Separator := False;
1813 end Read_Default_Search_Dirs;
1815 -----------------------
1816 -- Read_Library_Info --
1817 -----------------------
1819 function Read_Library_Info
1820 (Lib_File : File_Name_Type;
1821 Fatal_Err : Boolean := False)
1822 return Text_Buffer_Ptr
1824 Lib_FD : File_Descriptor;
1825 -- The file descriptor for the current library file. A negative value
1826 -- indicates failure to open the specified source file.
1828 Text : Text_Buffer_Ptr;
1829 -- Allocated text buffer.
1832 -- For the calls to Close
1835 Current_Full_Lib_Name := Find_File (Lib_File, Library);
1836 Current_Full_Obj_Name := Object_File_Name (Current_Full_Lib_Name);
1838 if Current_Full_Lib_Name = No_File then
1840 Fail ("Cannot find: ", Name_Buffer (1 .. Name_Len));
1842 Current_Full_Obj_Stamp := Empty_Time_Stamp;
1847 Get_Name_String (Current_Full_Lib_Name);
1848 Name_Buffer (Name_Len + 1) := ASCII.NUL;
1850 -- Open the library FD, note that we open in binary mode, because as
1851 -- documented in the spec, the caller is expected to handle either
1852 -- DOS or Unix mode files, and there is no point in wasting time on
1853 -- text translation when it is not required.
1855 Lib_FD := Open_Read (Name_Buffer'Address, Binary);
1857 if Lib_FD = Invalid_FD then
1859 Fail ("Cannot open: ", Name_Buffer (1 .. Name_Len));
1861 Current_Full_Obj_Stamp := Empty_Time_Stamp;
1866 -- Check for object file consistency if requested
1868 if Opt.Check_Object_Consistency then
1869 Current_Full_Lib_Stamp := File_Stamp (Current_Full_Lib_Name);
1870 Current_Full_Obj_Stamp := File_Stamp (Current_Full_Obj_Name);
1872 if Current_Full_Obj_Stamp (1) = ' ' then
1874 -- When the library is readonly, always assume that
1875 -- the object is consistent.
1877 if Is_Readonly_Library (Current_Full_Lib_Name) then
1878 Current_Full_Obj_Stamp := Current_Full_Lib_Stamp;
1880 elsif Fatal_Err then
1881 Get_Name_String (Current_Full_Obj_Name);
1882 Close (Lib_FD, Status);
1883 -- No need to check the status, we fail anyway
1885 Fail ("Cannot find: ", Name_Buffer (1 .. Name_Len));
1888 Current_Full_Obj_Stamp := Empty_Time_Stamp;
1889 Close (Lib_FD, Status);
1890 -- No need to check the status, we return null anyway
1896 -- Object file exists, compare object and ALI time stamps
1898 if Current_Full_Lib_Stamp > Current_Full_Obj_Stamp then
1900 Get_Name_String (Current_Full_Obj_Name);
1901 Close (Lib_FD, Status);
1902 -- No need to check the status, we fail anyway
1903 Fail ("Bad time stamp: ", Name_Buffer (1 .. Name_Len));
1905 Current_Full_Obj_Stamp := Empty_Time_Stamp;
1906 Close (Lib_FD, Status);
1907 -- No need to check the status, we return null anyway
1914 -- Read data from the file
1917 Len : constant Integer := Integer (File_Length (Lib_FD));
1918 -- Length of source file text. If it doesn't fit in an integer
1919 -- we're probably stuck anyway (>2 gigs of source seems a lot!)
1921 Actual_Len : Integer := 0;
1923 Lo : constant Text_Ptr := 0;
1924 -- Low bound for allocated text buffer
1926 Hi : Text_Ptr := Text_Ptr (Len);
1927 -- High bound for allocated text buffer. Note length is Len + 1
1928 -- which allows for extra EOF character at the end of the buffer.
1931 -- Allocate text buffer. Note extra character at end for EOF
1933 Text := new Text_Buffer (Lo .. Hi);
1935 -- Some systems (e.g. VMS) have file types that require one
1936 -- read per line, so read until we get the Len bytes or until
1937 -- there are no more characters.
1941 Actual_Len := Read (Lib_FD, Text (Hi)'Address, Len);
1942 Hi := Hi + Text_Ptr (Actual_Len);
1943 exit when Actual_Len = Len or Actual_Len <= 0;
1949 -- Read is complete, close file and we are done
1951 Close (Lib_FD, Status);
1952 -- The status should never be False. But, if it is, what can we do?
1953 -- So, we don't test it.
1957 end Read_Library_Info;
1959 ----------------------
1960 -- Read_Source_File --
1961 ----------------------
1963 procedure Read_Source_File
1964 (N : File_Name_Type;
1966 Hi : out Source_Ptr;
1967 Src : out Source_Buffer_Ptr;
1968 T : File_Type := Source)
1970 Source_File_FD : File_Descriptor;
1971 -- The file descriptor for the current source file. A negative value
1972 -- indicates failure to open the specified source file.
1975 -- Length of file. Assume no more than 2 gigabytes of source!
1977 Actual_Len : Integer;
1980 -- For the call to Close
1983 Current_Full_Source_Name := Find_File (N, T);
1984 Current_Full_Source_Stamp := File_Stamp (Current_Full_Source_Name);
1986 if Current_Full_Source_Name = No_File then
1988 -- If we were trying to access the main file and we could not
1989 -- find it we have an error.
1991 if N = Current_Main then
1992 Get_Name_String (N);
1993 Fail ("Cannot find: ", Name_Buffer (1 .. Name_Len));
2001 Get_Name_String (Current_Full_Source_Name);
2002 Name_Buffer (Name_Len + 1) := ASCII.NUL;
2004 -- Open the source FD, note that we open in binary mode, because as
2005 -- documented in the spec, the caller is expected to handle either
2006 -- DOS or Unix mode files, and there is no point in wasting time on
2007 -- text translation when it is not required.
2009 Source_File_FD := Open_Read (Name_Buffer'Address, Binary);
2011 if Source_File_FD = Invalid_FD then
2017 -- Prepare to read data from the file
2019 Len := Integer (File_Length (Source_File_FD));
2021 -- Set Hi so that length is one more than the physical length,
2022 -- allowing for the extra EOF character at the end of the buffer
2024 Hi := Lo + Source_Ptr (Len);
2026 -- Do the actual read operation
2029 subtype Actual_Source_Buffer is Source_Buffer (Lo .. Hi);
2030 -- Physical buffer allocated
2032 type Actual_Source_Ptr is access Actual_Source_Buffer;
2033 -- This is the pointer type for the physical buffer allocated
2035 Actual_Ptr : Actual_Source_Ptr := new Actual_Source_Buffer;
2036 -- And this is the actual physical buffer
2039 -- Allocate source buffer, allowing extra character at end for EOF
2041 -- Some systems (e.g. VMS) have file types that require one
2042 -- read per line, so read until we get the Len bytes or until
2043 -- there are no more characters.
2047 Actual_Len := Read (Source_File_FD, Actual_Ptr (Hi)'Address, Len);
2048 Hi := Hi + Source_Ptr (Actual_Len);
2049 exit when Actual_Len = Len or Actual_Len <= 0;
2052 Actual_Ptr (Hi) := EOF;
2054 -- Now we need to work out the proper virtual origin pointer to
2055 -- return. This is exactly Actual_Ptr (0)'Address, but we have
2056 -- to be careful to suppress checks to compute this address.
2059 pragma Suppress (All_Checks);
2061 function To_Source_Buffer_Ptr is new
2062 Unchecked_Conversion (Address, Source_Buffer_Ptr);
2065 Src := To_Source_Buffer_Ptr (Actual_Ptr (0)'Address);
2069 -- Read is complete, get time stamp and close file and we are done
2071 Close (Source_File_FD, Status);
2072 -- The status should never be False. But, if it is, what can we do?
2073 -- So, we don't test it.
2075 end Read_Source_File;
2081 procedure Set_Program (P : Program_Type) is
2084 Fail ("Set_Program called twice");
2087 Program_Set := True;
2088 Running_Program := P;
2091 ----------------------
2092 -- Smart_File_Stamp --
2093 ----------------------
2095 function Smart_File_Stamp
2096 (N : File_Name_Type;
2098 return Time_Stamp_Type
2100 Time_Stamp : Time_Stamp_Type;
2103 if not File_Cache_Enabled then
2104 return File_Stamp (Find_File (N, T));
2107 Time_Stamp := File_Stamp_Hash_Table.Get (N);
2109 if Time_Stamp (1) = ' ' then
2110 Time_Stamp := File_Stamp (Smart_Find_File (N, T));
2111 File_Stamp_Hash_Table.Set (N, Time_Stamp);
2115 end Smart_File_Stamp;
2117 ---------------------
2118 -- Smart_Find_File --
2119 ---------------------
2121 function Smart_Find_File
2122 (N : File_Name_Type;
2124 return File_Name_Type
2126 Full_File_Name : File_Name_Type;
2129 if not File_Cache_Enabled then
2130 return Find_File (N, T);
2133 Full_File_Name := File_Name_Hash_Table.Get (N);
2135 if Full_File_Name = No_File then
2136 Full_File_Name := Find_File (N, T);
2137 File_Name_Hash_Table.Set (N, Full_File_Name);
2140 return Full_File_Name;
2141 end Smart_Find_File;
2143 ----------------------
2144 -- Source_File_Data --
2145 ----------------------
2147 procedure Source_File_Data (Cache : Boolean) is
2149 File_Cache_Enabled := Cache;
2150 end Source_File_Data;
2152 -----------------------
2153 -- Source_File_Stamp --
2154 -----------------------
2156 function Source_File_Stamp (N : File_Name_Type) return Time_Stamp_Type is
2158 return Smart_File_Stamp (N, Source);
2159 end Source_File_Stamp;
2161 ---------------------
2162 -- Strip_Directory --
2163 ---------------------
2165 function Strip_Directory (Name : File_Name_Type) return File_Name_Type is
2167 Get_Name_String (Name);
2169 for J in reverse 1 .. Name_Len - 1 loop
2170 -- If we find the last directory separator
2172 if Is_Directory_Separator (Name_Buffer (J)) then
2173 -- Return the part of Name that follows this last directory
2176 Name_Buffer (1 .. Name_Len - J) := Name_Buffer (J + 1 .. Name_Len);
2177 Name_Len := Name_Len - J;
2182 -- There were no directory separator, just return Name
2185 end Strip_Directory;
2191 function Strip_Suffix (Name : File_Name_Type) return File_Name_Type is
2193 Get_Name_String (Name);
2195 for J in reverse 2 .. Name_Len loop
2197 -- If we found the last '.', return the part of Name that precedes
2200 if Name_Buffer (J) = '.' then
2209 ---------------------------
2210 -- To_Canonical_Dir_Spec --
2211 ---------------------------
2213 function To_Canonical_Dir_Spec
2215 Prefix_Style : Boolean)
2216 return String_Access
2218 function To_Canonical_Dir_Spec
2219 (Host_Dir : Address;
2220 Prefix_Flag : Integer)
2222 pragma Import (C, To_Canonical_Dir_Spec, "__gnat_to_canonical_dir_spec");
2224 C_Host_Dir : String (1 .. Host_Dir'Length + 1);
2225 Canonical_Dir_Addr : Address;
2226 Canonical_Dir_Len : Integer;
2229 C_Host_Dir (1 .. Host_Dir'Length) := Host_Dir;
2230 C_Host_Dir (C_Host_Dir'Last) := ASCII.NUL;
2232 if Prefix_Style then
2233 Canonical_Dir_Addr := To_Canonical_Dir_Spec (C_Host_Dir'Address, 1);
2235 Canonical_Dir_Addr := To_Canonical_Dir_Spec (C_Host_Dir'Address, 0);
2237 Canonical_Dir_Len := C_String_Length (Canonical_Dir_Addr);
2239 if Canonical_Dir_Len = 0 then
2242 return To_Path_String_Access (Canonical_Dir_Addr, Canonical_Dir_Len);
2247 Fail ("erroneous directory spec: ", Host_Dir);
2249 end To_Canonical_Dir_Spec;
2251 ---------------------------
2252 -- To_Canonical_File_List --
2253 ---------------------------
2255 function To_Canonical_File_List
2256 (Wildcard_Host_File : String;
2257 Only_Dirs : Boolean)
2258 return String_Access_List_Access
2260 function To_Canonical_File_List_Init
2261 (Host_File : Address;
2262 Only_Dirs : Integer)
2264 pragma Import (C, To_Canonical_File_List_Init,
2265 "__gnat_to_canonical_file_list_init");
2267 function To_Canonical_File_List_Next return Address;
2268 pragma Import (C, To_Canonical_File_List_Next,
2269 "__gnat_to_canonical_file_list_next");
2271 procedure To_Canonical_File_List_Free;
2272 pragma Import (C, To_Canonical_File_List_Free,
2273 "__gnat_to_canonical_file_list_free");
2275 Num_Files : Integer;
2276 C_Wildcard_Host_File : String (1 .. Wildcard_Host_File'Length + 1);
2279 C_Wildcard_Host_File (1 .. Wildcard_Host_File'Length) :=
2281 C_Wildcard_Host_File (C_Wildcard_Host_File'Last) := ASCII.NUL;
2283 -- Do the expansion and say how many there are
2285 Num_Files := To_Canonical_File_List_Init
2286 (C_Wildcard_Host_File'Address, Boolean'Pos (Only_Dirs));
2289 Canonical_File_List : String_Access_List (1 .. Num_Files);
2290 Canonical_File_Addr : Address;
2291 Canonical_File_Len : Integer;
2294 -- Retrieve the expanded directoy names and build the list
2296 for J in 1 .. Num_Files loop
2297 Canonical_File_Addr := To_Canonical_File_List_Next;
2298 Canonical_File_Len := C_String_Length (Canonical_File_Addr);
2299 Canonical_File_List (J) := To_Path_String_Access
2300 (Canonical_File_Addr, Canonical_File_Len);
2303 -- Free up the storage
2305 To_Canonical_File_List_Free;
2307 return new String_Access_List'(Canonical_File_List);
2309 end To_Canonical_File_List;
2311 ----------------------------
2312 -- To_Canonical_File_Spec --
2313 ----------------------------
2315 function To_Canonical_File_Spec
2316 (Host_File : String)
2317 return String_Access
2319 function To_Canonical_File_Spec (Host_File : Address) return Address;
2321 (C, To_Canonical_File_Spec, "__gnat_to_canonical_file_spec");
2323 C_Host_File : String (1 .. Host_File'Length + 1);
2324 Canonical_File_Addr : Address;
2325 Canonical_File_Len : Integer;
2328 C_Host_File (1 .. Host_File'Length) := Host_File;
2329 C_Host_File (C_Host_File'Last) := ASCII.NUL;
2331 Canonical_File_Addr := To_Canonical_File_Spec (C_Host_File'Address);
2332 Canonical_File_Len := C_String_Length (Canonical_File_Addr);
2334 if Canonical_File_Len = 0 then
2337 return To_Path_String_Access
2338 (Canonical_File_Addr, Canonical_File_Len);
2343 Fail ("erroneous file spec: ", Host_File);
2345 end To_Canonical_File_Spec;
2347 ----------------------------
2348 -- To_Canonical_Path_Spec --
2349 ----------------------------
2351 function To_Canonical_Path_Spec
2352 (Host_Path : String)
2353 return String_Access
2355 function To_Canonical_Path_Spec (Host_Path : Address) return Address;
2357 (C, To_Canonical_Path_Spec, "__gnat_to_canonical_path_spec");
2359 C_Host_Path : String (1 .. Host_Path'Length + 1);
2360 Canonical_Path_Addr : Address;
2361 Canonical_Path_Len : Integer;
2364 C_Host_Path (1 .. Host_Path'Length) := Host_Path;
2365 C_Host_Path (C_Host_Path'Last) := ASCII.NUL;
2367 Canonical_Path_Addr := To_Canonical_Path_Spec (C_Host_Path'Address);
2368 Canonical_Path_Len := C_String_Length (Canonical_Path_Addr);
2370 -- Return a null string (vice a null) for zero length paths, for
2371 -- compatibility with getenv().
2373 return To_Path_String_Access (Canonical_Path_Addr, Canonical_Path_Len);
2377 Fail ("erroneous path spec: ", Host_Path);
2379 end To_Canonical_Path_Spec;
2381 ---------------------------
2382 -- To_Host_Dir_Spec --
2383 ---------------------------
2385 function To_Host_Dir_Spec
2386 (Canonical_Dir : String;
2387 Prefix_Style : Boolean)
2388 return String_Access
2390 function To_Host_Dir_Spec
2391 (Canonical_Dir : Address;
2392 Prefix_Flag : Integer)
2394 pragma Import (C, To_Host_Dir_Spec, "__gnat_to_host_dir_spec");
2396 C_Canonical_Dir : String (1 .. Canonical_Dir'Length + 1);
2397 Host_Dir_Addr : Address;
2398 Host_Dir_Len : Integer;
2401 C_Canonical_Dir (1 .. Canonical_Dir'Length) := Canonical_Dir;
2402 C_Canonical_Dir (C_Canonical_Dir'Last) := ASCII.NUL;
2404 if Prefix_Style then
2405 Host_Dir_Addr := To_Host_Dir_Spec (C_Canonical_Dir'Address, 1);
2407 Host_Dir_Addr := To_Host_Dir_Spec (C_Canonical_Dir'Address, 0);
2409 Host_Dir_Len := C_String_Length (Host_Dir_Addr);
2411 if Host_Dir_Len = 0 then
2414 return To_Path_String_Access (Host_Dir_Addr, Host_Dir_Len);
2416 end To_Host_Dir_Spec;
2418 ----------------------------
2419 -- To_Host_File_Spec --
2420 ----------------------------
2422 function To_Host_File_Spec
2423 (Canonical_File : String)
2424 return String_Access
2426 function To_Host_File_Spec (Canonical_File : Address) return Address;
2427 pragma Import (C, To_Host_File_Spec, "__gnat_to_host_file_spec");
2429 C_Canonical_File : String (1 .. Canonical_File'Length + 1);
2430 Host_File_Addr : Address;
2431 Host_File_Len : Integer;
2434 C_Canonical_File (1 .. Canonical_File'Length) := Canonical_File;
2435 C_Canonical_File (C_Canonical_File'Last) := ASCII.NUL;
2437 Host_File_Addr := To_Host_File_Spec (C_Canonical_File'Address);
2438 Host_File_Len := C_String_Length (Host_File_Addr);
2440 if Host_File_Len = 0 then
2443 return To_Path_String_Access
2444 (Host_File_Addr, Host_File_Len);
2446 end To_Host_File_Spec;
2448 ---------------------------
2449 -- To_Path_String_Access --
2450 ---------------------------
2452 function To_Path_String_Access
2453 (Path_Addr : Address;
2455 return String_Access
2457 subtype Path_String is String (1 .. Path_Len);
2458 type Path_String_Access is access Path_String;
2460 function Address_To_Access is new
2461 Unchecked_Conversion (Source => Address,
2462 Target => Path_String_Access);
2464 Path_Access : constant Path_String_Access :=
2465 Address_To_Access (Path_Addr);
2467 Return_Val : String_Access;
2470 Return_Val := new String (1 .. Path_Len);
2472 for J in 1 .. Path_Len loop
2473 Return_Val (J) := Path_Access (J);
2477 end To_Path_String_Access;
2483 function Update_Path (Path : String_Ptr) return String_Ptr is
2485 function C_Update_Path (Path, Component : Address) return Address;
2486 pragma Import (C, C_Update_Path, "update_path");
2488 function Strlen (Str : Address) return Integer;
2489 pragma Import (C, Strlen, "strlen");
2491 procedure Strncpy (X : Address; Y : Address; Length : Integer);
2492 pragma Import (C, Strncpy, "strncpy");
2494 In_Length : constant Integer := Path'Length;
2495 In_String : String (1 .. In_Length + 1);
2496 Component_Name : aliased String := "GNAT" & ASCII.NUL;
2497 Result_Ptr : Address;
2498 Result_Length : Integer;
2499 Out_String : String_Ptr;
2502 In_String (1 .. In_Length) := Path.all;
2503 In_String (In_Length + 1) := ASCII.NUL;
2504 Result_Ptr := C_Update_Path (In_String'Address,
2505 Component_Name'Address);
2506 Result_Length := Strlen (Result_Ptr);
2508 Out_String := new String (1 .. Result_Length);
2509 Strncpy (Out_String.all'Address, Result_Ptr, Result_Length);
2517 procedure Write_Info (Info : String) is
2519 Write_With_Check (Info'Address, Info'Length);
2520 Write_With_Check (EOL'Address, 1);
2523 ------------------------
2524 -- Write_Program_Name --
2525 ------------------------
2527 procedure Write_Program_Name is
2528 Save_Buffer : constant String (1 .. Name_Len) :=
2529 Name_Buffer (1 .. Name_Len);
2535 -- Convert the name to lower case so error messages are the same on
2538 for J in 1 .. Name_Len loop
2539 if Name_Buffer (J) in 'A' .. 'Z' then
2541 Character'Val (Character'Pos (Name_Buffer (J)) + 32);
2545 Write_Str (Name_Buffer (1 .. Name_Len));
2547 -- Restore Name_Buffer which was clobbered by the call to
2548 -- Find_Program_Name
2550 Name_Len := Save_Buffer'Last;
2551 Name_Buffer (1 .. Name_Len) := Save_Buffer;
2552 end Write_Program_Name;
2554 ----------------------
2555 -- Write_With_Check --
2556 ----------------------
2558 procedure Write_With_Check (A : Address; N : Integer) is
2562 if N = Write (Output_FD, A, N) then
2566 Write_Str ("error: disk full writing ");
2567 Write_Name_Decoded (Output_File_Name);
2569 Name_Len := Name_Len + 1;
2570 Name_Buffer (Name_Len) := ASCII.NUL;
2571 Delete_File (Name_Buffer'Address, Ignore);
2572 Exit_Program (E_Fatal);
2574 end Write_With_Check;
2576 ----------------------------
2577 -- Package Initialization --
2578 ----------------------------
2581 Initialization : declare
2583 function Get_Default_Identifier_Character_Set return Character;
2584 pragma Import (C, Get_Default_Identifier_Character_Set,
2585 "__gnat_get_default_identifier_character_set");
2586 -- Function to determine the default identifier character set,
2587 -- which is system dependent. See Opt package spec for a list of
2588 -- the possible character codes and their interpretations.
2590 function Get_Maximum_File_Name_Length return Int;
2591 pragma Import (C, Get_Maximum_File_Name_Length,
2592 "__gnat_get_maximum_file_name_length");
2593 -- Function to get maximum file name length for system
2596 Identifier_Character_Set := Get_Default_Identifier_Character_Set;
2597 Maximum_File_Name_Length := Get_Maximum_File_Name_Length;
2599 -- Following should be removed by having above function return
2600 -- Integer'Last as indication of no maximum instead of -1 ???
2602 if Maximum_File_Name_Length = -1 then
2603 Maximum_File_Name_Length := Int'Last;
2606 Src_Search_Directories.Set_Last (Primary_Directory);
2607 Src_Search_Directories.Table (Primary_Directory) := new String'("");
2609 Lib_Search_Directories.Set_Last (Primary_Directory);
2610 Lib_Search_Directories.Table (Primary_Directory) := new String'("");