i386-protos.h (x86_emit_floatuns): Declare.
[official-gcc.git] / gcc / ada / osint.adb
blob8980fa9b5b20d22268b39100ade4ea63c3a3a7ce
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT COMPILER COMPONENTS --
4 -- --
5 -- O S I N T --
6 -- --
7 -- B o d y --
8 -- --
9 -- --
10 -- Copyright (C) 1992-2001 Free Software Foundation, Inc. --
11 -- --
12 -- GNAT is free software; you can redistribute it and/or modify it under --
13 -- terms of the GNU General Public License as published by the Free Soft- --
14 -- ware Foundation; either version 2, or (at your option) any later ver- --
15 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
16 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
17 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
18 -- for more details. You should have received a copy of the GNU General --
19 -- Public License distributed with GNAT; see file COPYING. If not, write --
20 -- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, --
21 -- MA 02111-1307, USA. --
22 -- --
23 -- GNAT was originally developed by the GNAT team at New York University. --
24 -- Extensive contributions were provided by Ada Core Technologies Inc. --
25 -- --
26 ------------------------------------------------------------------------------
28 with Fmap; use Fmap;
29 with Hostparm;
30 with Namet; use Namet;
31 with Opt; use Opt;
32 with Output; use Output;
33 with Sdefault; use Sdefault;
34 with Table;
36 with Unchecked_Conversion;
38 with GNAT.OS_Lib; use GNAT.OS_Lib;
39 with GNAT.HTable;
41 package body Osint is
43 Running_Program : Program_Type := Unspecified;
44 Program_Set : Boolean := False;
46 -------------------------------------
47 -- Use of Name_Find and Name_Enter --
48 -------------------------------------
50 -- This package creates a number of source, ALI and object file names
51 -- that are used to locate the actual file and for the purpose of
52 -- message construction. These names need not be accessible by Name_Find,
53 -- and can be therefore created by using routine Name_Enter. The files in
54 -- question are file names with a prefix directory (ie the files not
55 -- in the current directory). File names without a prefix directory are
56 -- entered with Name_Find because special values might be attached to
57 -- the various Info fields of the corresponding name table entry.
59 -----------------------
60 -- Local Subprograms --
61 -----------------------
63 function Append_Suffix_To_File_Name
64 (Name : Name_Id;
65 Suffix : String)
66 return Name_Id;
67 -- Appends Suffix to Name and returns the new name.
69 function OS_Time_To_GNAT_Time (T : OS_Time) return Time_Stamp_Type;
70 -- Convert OS format time to GNAT format time stamp
72 function Concat (String_One : String; String_Two : String) return String;
73 -- Concatenates 2 strings and returns the result of the concatenation
75 function Update_Path (Path : String_Ptr) return String_Ptr;
76 -- Update the specified path to replace the prefix with the location
77 -- where GNAT is installed. See the file prefix.c in GCC for details.
79 procedure Write_With_Check (A : Address; N : Integer);
80 -- Writes N bytes from buffer starting at address A to file whose FD is
81 -- stored in Output_FD, and whose file name is stored as a File_Name_Type
82 -- in Output_File_Name. A check is made for disk full, and if this is
83 -- detected, the file being written is deleted, and a fatal error is
84 -- signalled.
86 function Locate_File
87 (N : File_Name_Type;
88 T : File_Type;
89 Dir : Natural;
90 Name : String)
91 return File_Name_Type;
92 -- See if the file N whose name is Name exists in directory Dir. Dir is
93 -- an index into the Lib_Search_Directories table if T = Library.
94 -- Otherwise if T = Source, Dir is an index into the
95 -- Src_Search_Directories table. Returns the File_Name_Type of the
96 -- full file name if file found, or No_File if not found.
98 function C_String_Length (S : Address) return Integer;
99 -- Returns length of a C string. Returns zero for a null address.
101 function To_Path_String_Access
102 (Path_Addr : Address;
103 Path_Len : Integer)
104 return String_Access;
105 -- Converts a C String to an Ada String. Are we doing this to avoid
106 -- withing Interfaces.C.Strings ???
108 ------------------------------
109 -- Other Local Declarations --
110 ------------------------------
112 EOL : constant Character := ASCII.LF;
113 -- End of line character
115 Number_File_Names : Int := 0;
116 -- The total number of file names found on command line and placed in
117 -- File_Names.
119 Look_In_Primary_Directory_For_Current_Main : Boolean := False;
120 -- When this variable is True, Find_File will only look in
121 -- the Primary_Directory for the Current_Main file.
122 -- This variable is always True for the compiler.
123 -- It is also True for gnatmake, when the soucr name given
124 -- on the command line has directory information.
126 Current_Full_Source_Name : File_Name_Type := No_File;
127 Current_Full_Source_Stamp : Time_Stamp_Type := Empty_Time_Stamp;
128 Current_Full_Lib_Name : File_Name_Type := No_File;
129 Current_Full_Lib_Stamp : Time_Stamp_Type := Empty_Time_Stamp;
130 Current_Full_Obj_Name : File_Name_Type := No_File;
131 Current_Full_Obj_Stamp : Time_Stamp_Type := Empty_Time_Stamp;
132 -- Respectively full name (with directory info) and time stamp of
133 -- the latest source, library and object files opened by Read_Source_File
134 -- and Read_Library_Info.
136 ------------------
137 -- Search Paths --
138 ------------------
140 Primary_Directory : constant := 0;
141 -- This is index in the tables created below for the first directory to
142 -- search in for source or library information files. This is the
143 -- directory containing the latest main input file (a source file for
144 -- the compiler or a library file for the binder).
146 package Src_Search_Directories is new Table.Table (
147 Table_Component_Type => String_Ptr,
148 Table_Index_Type => Natural,
149 Table_Low_Bound => Primary_Directory,
150 Table_Initial => 10,
151 Table_Increment => 100,
152 Table_Name => "Osint.Src_Search_Directories");
153 -- Table of names of directories in which to search for source (Compiler)
154 -- files. This table is filled in the order in which the directories are
155 -- to be searched, and then used in that order.
157 package Lib_Search_Directories is new Table.Table (
158 Table_Component_Type => String_Ptr,
159 Table_Index_Type => Natural,
160 Table_Low_Bound => Primary_Directory,
161 Table_Initial => 10,
162 Table_Increment => 100,
163 Table_Name => "Osint.Lib_Search_Directories");
164 -- Table of names of directories in which to search for library (Binder)
165 -- files. This table is filled in the order in which the directories are
166 -- to be searched and then used in that order. The reason for having two
167 -- distinct tables is that we need them both in gnatmake.
169 ---------------------
170 -- File Hash Table --
171 ---------------------
173 -- The file hash table is provided to free the programmer from any
174 -- efficiency concern when retrieving full file names or time stamps of
175 -- source files. If the programmer calls Source_File_Data (Cache => True)
176 -- he is guaranteed that the price to retrieve the full name (ie with
177 -- directory info) or time stamp of the file will be payed only once,
178 -- the first time the full name is actually searched (or the first time
179 -- the time stamp is actually retrieved). This is achieved by employing
180 -- a hash table that stores as a key the File_Name_Type of the file and
181 -- associates to that File_Name_Type the full file name of the file and its
182 -- time stamp.
184 File_Cache_Enabled : Boolean := False;
185 -- Set to true if you want the enable the file data caching mechanism.
187 type File_Hash_Num is range 0 .. 1020;
189 function File_Hash (F : File_Name_Type) return File_Hash_Num;
190 -- Compute hash index for use by Simple_HTable
192 package File_Name_Hash_Table is new GNAT.HTable.Simple_HTable (
193 Header_Num => File_Hash_Num,
194 Element => File_Name_Type,
195 No_Element => No_File,
196 Key => File_Name_Type,
197 Hash => File_Hash,
198 Equal => "=");
200 package File_Stamp_Hash_Table is new GNAT.HTable.Simple_HTable (
201 Header_Num => File_Hash_Num,
202 Element => Time_Stamp_Type,
203 No_Element => Empty_Time_Stamp,
204 Key => File_Name_Type,
205 Hash => File_Hash,
206 Equal => "=");
208 function Smart_Find_File
209 (N : File_Name_Type;
210 T : File_Type)
211 return File_Name_Type;
212 -- Exactly like Find_File except that if File_Cache_Enabled is True this
213 -- routine looks first in the hash table to see if the full name of the
214 -- file is already available.
216 function Smart_File_Stamp
217 (N : File_Name_Type;
218 T : File_Type)
219 return Time_Stamp_Type;
220 -- Takes the same parameter as the routine above (N is a file name
221 -- without any prefix directory information) and behaves like File_Stamp
222 -- except that if File_Cache_Enabled is True this routine looks first in
223 -- the hash table to see if the file stamp of the file is already
224 -- available.
226 -----------------------------
227 -- Add_Default_Search_Dirs --
228 -----------------------------
230 procedure Add_Default_Search_Dirs is
231 Search_Dir : String_Access;
232 Search_Path : String_Access;
234 procedure Add_Search_Dir
235 (Search_Dir : String_Access;
236 Additional_Source_Dir : Boolean);
237 -- Add a source search dir or a library search dir, depending on the
238 -- value of Additional_Source_Dir.
240 function Get_Libraries_From_Registry return String_Ptr;
241 -- On Windows systems, get the list of installed standard libraries
242 -- from the registry key:
243 -- HKEY_LOCAL_MACHINE\SOFTWARE\Ada Core Technologies\
244 -- GNAT\Standard Libraries
245 -- Return an empty string on other systems
247 --------------------
248 -- Add_Search_Dir --
249 --------------------
251 procedure Add_Search_Dir
252 (Search_Dir : String_Access;
253 Additional_Source_Dir : Boolean)
255 begin
256 if Additional_Source_Dir then
257 Add_Src_Search_Dir (Search_Dir.all);
258 else
259 Add_Lib_Search_Dir (Search_Dir.all);
260 end if;
261 end Add_Search_Dir;
263 ---------------------------------
264 -- Get_Libraries_From_Registry --
265 ---------------------------------
267 function Get_Libraries_From_Registry return String_Ptr is
268 function C_Get_Libraries_From_Registry return Address;
269 pragma Import (C, C_Get_Libraries_From_Registry,
270 "__gnat_get_libraries_from_registry");
271 function Strlen (Str : Address) return Integer;
272 pragma Import (C, Strlen, "strlen");
273 procedure Strncpy (X : Address; Y : Address; Length : Integer);
274 pragma Import (C, Strncpy, "strncpy");
275 Result_Ptr : Address;
276 Result_Length : Integer;
277 Out_String : String_Ptr;
279 begin
280 Result_Ptr := C_Get_Libraries_From_Registry;
281 Result_Length := Strlen (Result_Ptr);
283 Out_String := new String (1 .. Result_Length);
284 Strncpy (Out_String.all'Address, Result_Ptr, Result_Length);
285 return Out_String;
286 end Get_Libraries_From_Registry;
288 -- Start of processing for Add_Default_Search_Dirs
290 begin
291 -- After the locations specified on the command line, the next places
292 -- to look for files are the directories specified by the appropriate
293 -- environment variable. Get this value, extract the directory names
294 -- and store in the tables.
296 -- On VMS, don't expand the logical name (e.g. environment variable),
297 -- just put it into Unix (e.g. canonical) format. System services
298 -- will handle the expansion as part of the file processing.
300 for Additional_Source_Dir in False .. True loop
302 if Additional_Source_Dir then
303 Search_Path := Getenv ("ADA_INCLUDE_PATH");
304 if Search_Path'Length > 0 then
305 if Hostparm.OpenVMS then
306 Search_Path := To_Canonical_Path_Spec ("ADA_INCLUDE_PATH:");
307 else
308 Search_Path := To_Canonical_Path_Spec (Search_Path.all);
309 end if;
310 end if;
311 else
312 Search_Path := Getenv ("ADA_OBJECTS_PATH");
313 if Search_Path'Length > 0 then
314 if Hostparm.OpenVMS then
315 Search_Path := To_Canonical_Path_Spec ("ADA_OBJECTS_PATH:");
316 else
317 Search_Path := To_Canonical_Path_Spec (Search_Path.all);
318 end if;
319 end if;
320 end if;
322 Get_Next_Dir_In_Path_Init (Search_Path);
323 loop
324 Search_Dir := Get_Next_Dir_In_Path (Search_Path);
325 exit when Search_Dir = null;
326 Add_Search_Dir (Search_Dir, Additional_Source_Dir);
327 end loop;
328 end loop;
330 if not Opt.No_Stdinc then
331 -- For WIN32 systems, look for any system libraries defined in
332 -- the registry. These are added to both source and object
333 -- directories.
335 Search_Path := String_Access (Get_Libraries_From_Registry);
336 Get_Next_Dir_In_Path_Init (Search_Path);
337 loop
338 Search_Dir := Get_Next_Dir_In_Path (Search_Path);
339 exit when Search_Dir = null;
340 Add_Search_Dir (Search_Dir, False);
341 Add_Search_Dir (Search_Dir, True);
342 end loop;
344 -- The last place to look are the defaults
346 Search_Path := Read_Default_Search_Dirs
347 (String_Access (Update_Path (Search_Dir_Prefix)),
348 Include_Search_File,
349 String_Access (Update_Path (Include_Dir_Default_Name)));
351 Get_Next_Dir_In_Path_Init (Search_Path);
352 loop
353 Search_Dir := Get_Next_Dir_In_Path (Search_Path);
354 exit when Search_Dir = null;
355 Add_Search_Dir (Search_Dir, True);
356 end loop;
357 end if;
359 if not Opt.No_Stdlib and not Opt.RTS_Switch then
360 Search_Path := Read_Default_Search_Dirs
361 (String_Access (Update_Path (Search_Dir_Prefix)),
362 Objects_Search_File,
363 String_Access (Update_Path (Object_Dir_Default_Name)));
365 Get_Next_Dir_In_Path_Init (Search_Path);
366 loop
367 Search_Dir := Get_Next_Dir_In_Path (Search_Path);
368 exit when Search_Dir = null;
369 Add_Search_Dir (Search_Dir, False);
370 end loop;
371 end if;
373 end Add_Default_Search_Dirs;
375 --------------
376 -- Add_File --
377 --------------
379 procedure Add_File (File_Name : String) is
380 begin
381 Number_File_Names := Number_File_Names + 1;
383 -- As Add_File may be called for mains specified inside
384 -- a project file, File_Names may be too short and needs
385 -- to be extended.
387 if Number_File_Names > File_Names'Last then
388 File_Names := new File_Name_Array'(File_Names.all & File_Names.all);
389 end if;
391 File_Names (Number_File_Names) := new String'(File_Name);
392 end Add_File;
394 ------------------------
395 -- Add_Lib_Search_Dir --
396 ------------------------
398 procedure Add_Lib_Search_Dir (Dir : String) is
399 begin
400 if Dir'Length = 0 then
401 Fail ("missing library directory name");
402 end if;
404 Lib_Search_Directories.Increment_Last;
405 Lib_Search_Directories.Table (Lib_Search_Directories.Last) :=
406 Normalize_Directory_Name (Dir);
407 end Add_Lib_Search_Dir;
409 ---------------------
410 -- Add_Search_Dirs --
411 ---------------------
413 procedure Add_Search_Dirs
414 (Search_Path : String_Ptr;
415 Path_Type : Search_File_Type)
417 Current_Search_Path : String_Access;
419 begin
420 Get_Next_Dir_In_Path_Init (String_Access (Search_Path));
421 loop
422 Current_Search_Path :=
423 Get_Next_Dir_In_Path (String_Access (Search_Path));
424 exit when Current_Search_Path = null;
426 if Path_Type = Include then
427 Add_Src_Search_Dir (Current_Search_Path.all);
428 else
429 Add_Lib_Search_Dir (Current_Search_Path.all);
430 end if;
431 end loop;
432 end Add_Search_Dirs;
434 ------------------------
435 -- Add_Src_Search_Dir --
436 ------------------------
438 procedure Add_Src_Search_Dir (Dir : String) is
439 begin
440 if Dir'Length = 0 then
441 Fail ("missing source directory name");
442 end if;
444 Src_Search_Directories.Increment_Last;
445 Src_Search_Directories.Table (Src_Search_Directories.Last) :=
446 Normalize_Directory_Name (Dir);
447 end Add_Src_Search_Dir;
449 --------------------------------
450 -- Append_Suffix_To_File_Name --
451 --------------------------------
453 function Append_Suffix_To_File_Name
454 (Name : Name_Id;
455 Suffix : String)
456 return Name_Id
458 begin
459 Get_Name_String (Name);
460 Name_Buffer (Name_Len + 1 .. Name_Len + Suffix'Length) := Suffix;
461 Name_Len := Name_Len + Suffix'Length;
462 return Name_Find;
463 end Append_Suffix_To_File_Name;
465 ---------------------
466 -- C_String_Length --
467 ---------------------
469 function C_String_Length (S : Address) return Integer is
470 function Strlen (S : Address) return Integer;
471 pragma Import (C, Strlen, "strlen");
473 begin
474 if S = Null_Address then
475 return 0;
476 else
477 return Strlen (S);
478 end if;
479 end C_String_Length;
481 ------------------------------
482 -- Canonical_Case_File_Name --
483 ------------------------------
485 -- For now, we only deal with the case of a-z. Eventually we should
486 -- worry about other Latin-1 letters on systems that support this ???
488 procedure Canonical_Case_File_Name (S : in out String) is
489 begin
490 if not File_Names_Case_Sensitive then
491 for J in S'Range loop
492 if S (J) in 'A' .. 'Z' then
493 S (J) := Character'Val (
494 Character'Pos (S (J)) +
495 Character'Pos ('a') -
496 Character'Pos ('A'));
497 end if;
498 end loop;
499 end if;
500 end Canonical_Case_File_Name;
502 ------------
503 -- Concat --
504 ------------
506 function Concat (String_One : String; String_Two : String) return String is
507 Buffer : String (1 .. String_One'Length + String_Two'Length);
509 begin
510 Buffer (1 .. String_One'Length) := String_One;
511 Buffer (String_One'Length + 1 .. Buffer'Last) := String_Two;
512 return Buffer;
513 end Concat;
515 ---------------------------
516 -- Create_File_And_Check --
517 ---------------------------
519 procedure Create_File_And_Check
520 (Fdesc : out File_Descriptor;
521 Fmode : Mode)
523 begin
524 Output_File_Name := Name_Enter;
525 Fdesc := Create_File (Name_Buffer'Address, Fmode);
527 if Fdesc = Invalid_FD then
528 Fail ("Cannot create: ", Name_Buffer (1 .. Name_Len));
529 end if;
530 end Create_File_And_Check;
532 --------------------------------
533 -- Current_Library_File_Stamp --
534 --------------------------------
536 function Current_Library_File_Stamp return Time_Stamp_Type is
537 begin
538 return Current_Full_Lib_Stamp;
539 end Current_Library_File_Stamp;
541 -------------------------------
542 -- Current_Object_File_Stamp --
543 -------------------------------
545 function Current_Object_File_Stamp return Time_Stamp_Type is
546 begin
547 return Current_Full_Obj_Stamp;
548 end Current_Object_File_Stamp;
550 -------------------------------
551 -- Current_Source_File_Stamp --
552 -------------------------------
554 function Current_Source_File_Stamp return Time_Stamp_Type is
555 begin
556 return Current_Full_Source_Stamp;
557 end Current_Source_File_Stamp;
559 ----------------------------
560 -- Dir_In_Obj_Search_Path --
561 ----------------------------
563 function Dir_In_Obj_Search_Path (Position : Natural) return String_Ptr is
564 begin
565 if Opt.Look_In_Primary_Dir then
566 return
567 Lib_Search_Directories.Table (Primary_Directory + Position - 1);
568 else
569 return Lib_Search_Directories.Table (Primary_Directory + Position);
570 end if;
571 end Dir_In_Obj_Search_Path;
573 ----------------------------
574 -- Dir_In_Src_Search_Path --
575 ----------------------------
577 function Dir_In_Src_Search_Path (Position : Natural) return String_Ptr is
578 begin
579 if Opt.Look_In_Primary_Dir then
580 return
581 Src_Search_Directories.Table (Primary_Directory + Position - 1);
582 else
583 return Src_Search_Directories.Table (Primary_Directory + Position);
584 end if;
585 end Dir_In_Src_Search_Path;
587 ---------------------
588 -- Executable_Name --
589 ---------------------
591 function Executable_Name (Name : File_Name_Type) return File_Name_Type is
592 Exec_Suffix : String_Access;
594 begin
595 if Name = No_File then
596 return No_File;
597 end if;
599 Get_Name_String (Name);
600 Exec_Suffix := Get_Executable_Suffix;
602 for J in Exec_Suffix.all'Range loop
603 Name_Len := Name_Len + 1;
604 Name_Buffer (Name_Len) := Exec_Suffix.all (J);
605 end loop;
607 return Name_Enter;
608 end Executable_Name;
610 ------------------
611 -- Exit_Program --
612 ------------------
614 procedure Exit_Program (Exit_Code : Exit_Code_Type) is
615 begin
616 -- The program will exit with the following status:
617 -- 0 if the object file has been generated (with or without warnings)
618 -- 1 if recompilation was not needed (smart recompilation)
619 -- 2 if gnat1 has been killed by a signal (detected by GCC)
620 -- 3 if no code has been generated (spec)
621 -- 4 for a fatal error
622 -- 5 if there were errors
624 case Exit_Code is
625 when E_Success => OS_Exit (0);
626 when E_Warnings => OS_Exit (0);
627 when E_No_Compile => OS_Exit (1);
628 when E_No_Code => OS_Exit (3);
629 when E_Fatal => OS_Exit (4);
630 when E_Errors => OS_Exit (5);
631 when E_Abort => OS_Abort;
632 end case;
633 end Exit_Program;
635 ----------
636 -- Fail --
637 ----------
639 procedure Fail (S1 : String; S2 : String := ""; S3 : String := "") is
641 begin
642 -- We use Output in case there is a special output set up.
643 -- In this case Set_Standard_Error will have no immediate effect.
645 Set_Standard_Error;
646 Osint.Write_Program_Name;
647 Write_Str (": ");
648 Write_Str (S1);
649 Write_Str (S2);
650 Write_Str (S3);
651 Write_Eol;
653 Exit_Program (E_Fatal);
654 end Fail;
656 ---------------
657 -- File_Hash --
658 ---------------
660 function File_Hash (F : File_Name_Type) return File_Hash_Num is
661 begin
662 return File_Hash_Num (Int (F) rem File_Hash_Num'Range_Length);
663 end File_Hash;
665 ----------------
666 -- File_Stamp --
667 ----------------
669 function File_Stamp (Name : File_Name_Type) return Time_Stamp_Type is
670 begin
671 if Name = No_File then
672 return Empty_Time_Stamp;
673 end if;
675 Get_Name_String (Name);
677 if not Is_Regular_File (Name_Buffer (1 .. Name_Len)) then
678 return Empty_Time_Stamp;
679 else
680 Name_Buffer (Name_Len + 1) := ASCII.NUL;
681 return OS_Time_To_GNAT_Time (File_Time_Stamp (Name_Buffer));
682 end if;
683 end File_Stamp;
685 ---------------
686 -- Find_File --
687 ---------------
689 function Find_File
690 (N : File_Name_Type;
691 T : File_Type)
692 return File_Name_Type
694 begin
695 Get_Name_String (N);
697 declare
698 File_Name : String renames Name_Buffer (1 .. Name_Len);
699 File : File_Name_Type := No_File;
700 Last_Dir : Natural;
702 begin
703 -- If we are looking for a config file, look only in the current
704 -- directory, i.e. return input argument unchanged. Also look
705 -- only in the current directory if we are looking for a .dg
706 -- file (happens in -gnatD mode)
708 if T = Config
709 or else (Debug_Generated_Code
710 and then Name_Len > 3
711 and then
712 (Name_Buffer (Name_Len - 2 .. Name_Len) = ".dg"
713 or else
714 (Hostparm.OpenVMS and then
715 Name_Buffer (Name_Len - 2 .. Name_Len) = "_dg")))
716 then
717 return N;
719 -- If we are trying to find the current main file just look in the
720 -- directory where the user said it was.
722 elsif Look_In_Primary_Directory_For_Current_Main
723 and then Current_Main = N
724 then
725 return Locate_File (N, T, Primary_Directory, File_Name);
727 -- Otherwise do standard search for source file
729 else
730 -- Check the mapping of this file name
732 File := Mapped_Path_Name (N);
734 -- If the file name is mapped to a path name, return the
735 -- corresponding path name
737 if File /= No_File then
738 return File;
739 end if;
741 -- First place to look is in the primary directory (i.e. the same
742 -- directory as the source) unless this has been disabled with -I-
744 if Opt.Look_In_Primary_Dir then
745 File := Locate_File (N, T, Primary_Directory, File_Name);
747 if File /= No_File then
748 return File;
749 end if;
750 end if;
752 -- Finally look in directories specified with switches -I/-aI/-aO
754 if T = Library then
755 Last_Dir := Lib_Search_Directories.Last;
756 else
757 Last_Dir := Src_Search_Directories.Last;
758 end if;
760 for D in Primary_Directory + 1 .. Last_Dir loop
761 File := Locate_File (N, T, D, File_Name);
763 if File /= No_File then
764 return File;
765 end if;
766 end loop;
768 return No_File;
769 end if;
770 end;
771 end Find_File;
773 -----------------------
774 -- Find_Program_Name --
775 -----------------------
777 procedure Find_Program_Name is
778 Command_Name : String (1 .. Len_Arg (0));
779 Cindex1 : Integer := Command_Name'First;
780 Cindex2 : Integer := Command_Name'Last;
782 begin
783 Fill_Arg (Command_Name'Address, 0);
785 -- The program name might be specified by a full path name. However,
786 -- we don't want to print that all out in an error message, so the
787 -- path might need to be stripped away.
789 for J in reverse Cindex1 .. Cindex2 loop
790 if Is_Directory_Separator (Command_Name (J)) then
791 Cindex1 := J + 1;
792 exit;
793 end if;
794 end loop;
796 for J in reverse Cindex1 .. Cindex2 loop
797 if Command_Name (J) = '.' then
798 Cindex2 := J - 1;
799 exit;
800 end if;
801 end loop;
803 Name_Len := Cindex2 - Cindex1 + 1;
804 Name_Buffer (1 .. Name_Len) := Command_Name (Cindex1 .. Cindex2);
805 end Find_Program_Name;
807 ------------------------
808 -- Full_Lib_File_Name --
809 ------------------------
811 function Full_Lib_File_Name (N : File_Name_Type) return File_Name_Type is
812 begin
813 return Find_File (N, Library);
814 end Full_Lib_File_Name;
816 ----------------------------
817 -- Full_Library_Info_Name --
818 ----------------------------
820 function Full_Library_Info_Name return File_Name_Type is
821 begin
822 return Current_Full_Lib_Name;
823 end Full_Library_Info_Name;
825 ---------------------------
826 -- Full_Object_File_Name --
827 ---------------------------
829 function Full_Object_File_Name return File_Name_Type is
830 begin
831 return Current_Full_Obj_Name;
832 end Full_Object_File_Name;
834 ----------------------
835 -- Full_Source_Name --
836 ----------------------
838 function Full_Source_Name return File_Name_Type is
839 begin
840 return Current_Full_Source_Name;
841 end Full_Source_Name;
843 ----------------------
844 -- Full_Source_Name --
845 ----------------------
847 function Full_Source_Name (N : File_Name_Type) return File_Name_Type is
848 begin
849 return Smart_Find_File (N, Source);
850 end Full_Source_Name;
852 -------------------
853 -- Get_Directory --
854 -------------------
856 function Get_Directory (Name : File_Name_Type) return File_Name_Type is
857 begin
858 Get_Name_String (Name);
860 for J in reverse 1 .. Name_Len loop
861 if Is_Directory_Separator (Name_Buffer (J)) then
862 Name_Len := J;
863 return Name_Find;
864 end if;
865 end loop;
867 Name_Len := Hostparm.Normalized_CWD'Length;
868 Name_Buffer (1 .. Name_Len) := Hostparm.Normalized_CWD;
869 return Name_Find;
870 end Get_Directory;
872 --------------------------
873 -- Get_Next_Dir_In_Path --
874 --------------------------
876 Search_Path_Pos : Integer;
877 -- Keeps track of current position in search path. Initialized by the
878 -- call to Get_Next_Dir_In_Path_Init, updated by Get_Next_Dir_In_Path.
880 function Get_Next_Dir_In_Path
881 (Search_Path : String_Access)
882 return String_Access
884 Lower_Bound : Positive := Search_Path_Pos;
885 Upper_Bound : Positive;
887 begin
888 loop
889 while Lower_Bound <= Search_Path'Last
890 and then Search_Path.all (Lower_Bound) = Path_Separator
891 loop
892 Lower_Bound := Lower_Bound + 1;
893 end loop;
895 exit when Lower_Bound > Search_Path'Last;
897 Upper_Bound := Lower_Bound;
898 while Upper_Bound <= Search_Path'Last
899 and then Search_Path.all (Upper_Bound) /= Path_Separator
900 loop
901 Upper_Bound := Upper_Bound + 1;
902 end loop;
904 Search_Path_Pos := Upper_Bound;
905 return new String'(Search_Path.all (Lower_Bound .. Upper_Bound - 1));
906 end loop;
908 return null;
909 end Get_Next_Dir_In_Path;
911 -------------------------------
912 -- Get_Next_Dir_In_Path_Init --
913 -------------------------------
915 procedure Get_Next_Dir_In_Path_Init (Search_Path : String_Access) is
916 begin
917 Search_Path_Pos := Search_Path'First;
918 end Get_Next_Dir_In_Path_Init;
920 --------------------------------------
921 -- Get_Primary_Src_Search_Directory --
922 --------------------------------------
924 function Get_Primary_Src_Search_Directory return String_Ptr is
925 begin
926 return Src_Search_Directories.Table (Primary_Directory);
927 end Get_Primary_Src_Search_Directory;
929 -------------------------
930 -- Get_RTS_Search_Dir --
931 -------------------------
933 function Get_RTS_Search_Dir
934 (Search_Dir : String;
935 File_Type : Search_File_Type)
936 return String_Ptr
938 procedure Get_Current_Dir
939 (Dir : System.Address;
940 Length : System.Address);
941 pragma Import (C, Get_Current_Dir, "__gnat_get_current_dir");
943 Max_Path : Integer;
944 pragma Import (C, Max_Path, "__gnat_max_path_len");
945 -- Maximum length of a path name
947 Current_Dir : String_Ptr;
948 Default_Search_Dir : String_Access;
949 Default_Suffix_Dir : String_Access;
950 Local_Search_Dir : String_Access;
951 Norm_Search_Dir : String_Access;
952 Result_Search_Dir : String_Access;
953 Search_File : String_Access;
954 Temp_String : String_Ptr;
956 begin
957 -- Add a directory separator at the end of the directory if necessary
958 -- so that we can directly append a file to the directory
960 if Search_Dir (Search_Dir'Last) /= Directory_Separator then
961 Local_Search_Dir := new String'
962 (Concat (Search_Dir, String' (1 => Directory_Separator)));
963 else
964 Local_Search_Dir := new String' (Search_Dir);
965 end if;
967 if File_Type = Include then
968 Search_File := Include_Search_File;
969 Default_Suffix_Dir := new String'("adainclude");
970 else
971 Search_File := Objects_Search_File;
972 Default_Suffix_Dir := new String' ("adalib");
973 end if;
975 Norm_Search_Dir := To_Canonical_Path_Spec (Local_Search_Dir.all);
977 if Is_Absolute_Path (Norm_Search_Dir.all) then
979 -- We first verify if there is a directory Include_Search_Dir
980 -- containing default search directories
982 Result_Search_Dir
983 := Read_Default_Search_Dirs (Norm_Search_Dir,
984 Search_File,
985 null);
986 Default_Search_Dir := new String'
987 (Concat (Norm_Search_Dir.all, Default_Suffix_Dir.all));
988 Free (Norm_Search_Dir);
990 if Result_Search_Dir /= null then
991 return String_Ptr (Result_Search_Dir);
992 elsif Is_Directory (Default_Search_Dir.all) then
993 return String_Ptr (Default_Search_Dir);
994 else
995 return null;
996 end if;
998 else
999 -- Search in the current directory
1001 -- Get the current directory
1003 declare
1004 Buffer : String (1 .. Max_Path + 2);
1005 Path_Len : Natural := Max_Path;
1007 begin
1008 Get_Current_Dir (Buffer'Address, Path_Len'Address);
1010 if Buffer (Path_Len) /= Directory_Separator then
1011 Path_Len := Path_Len + 1;
1012 Buffer (Path_Len) := Directory_Separator;
1013 end if;
1015 Current_Dir := new String'(Buffer (1 .. Path_Len));
1016 end;
1018 Norm_Search_Dir :=
1019 new String'
1020 (Concat (Current_Dir.all, Local_Search_Dir.all));
1022 Result_Search_Dir :=
1023 Read_Default_Search_Dirs
1024 (String_Access (Update_Path (String_Ptr (Norm_Search_Dir))),
1025 Search_File,
1026 null);
1028 Default_Search_Dir :=
1029 new String'
1030 (Concat (Norm_Search_Dir.all, Default_Suffix_Dir.all));
1032 Free (Norm_Search_Dir);
1034 if Result_Search_Dir /= null then
1035 return String_Ptr (Result_Search_Dir);
1037 elsif Is_Directory (Default_Search_Dir.all) then
1038 return String_Ptr (Default_Search_Dir);
1040 else
1041 -- Search in Search_Dir_Prefix/Search_Dir
1043 Norm_Search_Dir :=
1044 new String'
1045 (Concat (Search_Dir_Prefix.all, Local_Search_Dir.all));
1047 Result_Search_Dir :=
1048 Read_Default_Search_Dirs
1049 (String_Access (Update_Path (String_Ptr (Norm_Search_Dir))),
1050 Search_File,
1051 null);
1053 Default_Search_Dir :=
1054 new String'
1055 (Concat (Norm_Search_Dir.all, Default_Suffix_Dir.all));
1057 Free (Norm_Search_Dir);
1059 if Result_Search_Dir /= null then
1060 return String_Ptr (Result_Search_Dir);
1062 elsif Is_Directory (Default_Search_Dir.all) then
1063 return String_Ptr (Default_Search_Dir);
1065 else
1066 -- We finally search in Search_Dir_Prefix/rts-Search_Dir
1068 Temp_String :=
1069 new String'(Concat (Search_Dir_Prefix.all, "rts-"));
1071 Norm_Search_Dir :=
1072 new String' (Concat (Temp_String.all, Local_Search_Dir.all));
1074 Result_Search_Dir :=
1075 Read_Default_Search_Dirs
1076 (String_Access (Update_Path (String_Ptr (Norm_Search_Dir))),
1077 Search_File,
1078 null);
1080 Default_Search_Dir :=
1081 new String'
1082 (Concat (Norm_Search_Dir.all, Default_Suffix_Dir.all));
1083 Free (Norm_Search_Dir);
1085 if Result_Search_Dir /= null then
1086 return String_Ptr (Result_Search_Dir);
1088 elsif Is_Directory (Default_Search_Dir.all) then
1089 return String_Ptr (Default_Search_Dir);
1091 else
1092 return null;
1093 end if;
1094 end if;
1095 end if;
1096 end if;
1097 end Get_RTS_Search_Dir;
1099 ----------------------------
1100 -- Is_Directory_Separator --
1101 ----------------------------
1103 function Is_Directory_Separator (C : Character) return Boolean is
1104 begin
1105 -- In addition to the default directory_separator allow the '/' to
1106 -- act as separator since this is allowed in MS-DOS, Windows 95/NT,
1107 -- and OS2 ports. On VMS, the situation is more complicated because
1108 -- there are two characters to check for.
1110 return
1111 C = Directory_Separator
1112 or else C = '/'
1113 or else (Hostparm.OpenVMS
1114 and then (C = ']' or else C = ':'));
1115 end Is_Directory_Separator;
1117 -------------------------
1118 -- Is_Readonly_Library --
1119 -------------------------
1121 function Is_Readonly_Library (File : in File_Name_Type) return Boolean is
1122 begin
1123 Get_Name_String (File);
1125 pragma Assert (Name_Buffer (Name_Len - 3 .. Name_Len) = ".ali");
1127 return not Is_Writable_File (Name_Buffer (1 .. Name_Len));
1128 end Is_Readonly_Library;
1130 -------------------
1131 -- Lib_File_Name --
1132 -------------------
1134 function Lib_File_Name
1135 (Source_File : File_Name_Type)
1136 return File_Name_Type
1138 Fptr : Natural;
1139 -- Pointer to location to set extension in place
1141 begin
1142 Get_Name_String (Source_File);
1143 Fptr := Name_Len + 1;
1145 for J in reverse 2 .. Name_Len loop
1146 if Name_Buffer (J) = '.' then
1147 Fptr := J;
1148 exit;
1149 end if;
1150 end loop;
1152 Name_Buffer (Fptr) := '.';
1153 Name_Buffer (Fptr + 1 .. Fptr + ALI_Suffix'Length) := ALI_Suffix.all;
1154 Name_Buffer (Fptr + ALI_Suffix'Length + 1) := ASCII.NUL;
1155 Name_Len := Fptr + ALI_Suffix'Length;
1156 return Name_Find;
1157 end Lib_File_Name;
1159 ------------------------
1160 -- Library_File_Stamp --
1161 ------------------------
1163 function Library_File_Stamp (N : File_Name_Type) return Time_Stamp_Type is
1164 begin
1165 return File_Stamp (Find_File (N, Library));
1166 end Library_File_Stamp;
1168 -----------------
1169 -- Locate_File --
1170 -----------------
1172 function Locate_File
1173 (N : File_Name_Type;
1174 T : File_Type;
1175 Dir : Natural;
1176 Name : String)
1177 return File_Name_Type
1179 Dir_Name : String_Ptr;
1181 begin
1182 if T = Library then
1183 Dir_Name := Lib_Search_Directories.Table (Dir);
1185 else pragma Assert (T = Source);
1186 Dir_Name := Src_Search_Directories.Table (Dir);
1187 end if;
1189 declare
1190 Full_Name : String (1 .. Dir_Name'Length + Name'Length);
1192 begin
1193 Full_Name (1 .. Dir_Name'Length) := Dir_Name.all;
1194 Full_Name (Dir_Name'Length + 1 .. Full_Name'Length) := Name;
1196 if not Is_Regular_File (Full_Name) then
1197 return No_File;
1199 else
1200 -- If the file is in the current directory then return N itself
1202 if Dir_Name'Length = 0 then
1203 return N;
1204 else
1205 Name_Len := Full_Name'Length;
1206 Name_Buffer (1 .. Name_Len) := Full_Name;
1207 return Name_Enter;
1208 end if;
1209 end if;
1210 end;
1211 end Locate_File;
1213 -------------------------------
1214 -- Matching_Full_Source_Name --
1215 -------------------------------
1217 function Matching_Full_Source_Name
1218 (N : File_Name_Type;
1219 T : Time_Stamp_Type)
1220 return File_Name_Type
1222 begin
1223 Get_Name_String (N);
1225 declare
1226 File_Name : constant String := Name_Buffer (1 .. Name_Len);
1227 File : File_Name_Type := No_File;
1228 Last_Dir : Natural;
1230 begin
1231 if Opt.Look_In_Primary_Dir then
1232 File := Locate_File (N, Source, Primary_Directory, File_Name);
1234 if File /= No_File and then T = File_Stamp (N) then
1235 return File;
1236 end if;
1237 end if;
1239 Last_Dir := Src_Search_Directories.Last;
1241 for D in Primary_Directory + 1 .. Last_Dir loop
1242 File := Locate_File (N, Source, D, File_Name);
1244 if File /= No_File and then T = File_Stamp (File) then
1245 return File;
1246 end if;
1247 end loop;
1249 return No_File;
1250 end;
1251 end Matching_Full_Source_Name;
1253 ----------------
1254 -- More_Files --
1255 ----------------
1257 function More_Files return Boolean is
1258 begin
1259 return (Current_File_Name_Index < Number_File_Names);
1260 end More_Files;
1262 -------------------------------
1263 -- Nb_Dir_In_Obj_Search_Path --
1264 -------------------------------
1266 function Nb_Dir_In_Obj_Search_Path return Natural is
1267 begin
1268 if Opt.Look_In_Primary_Dir then
1269 return Lib_Search_Directories.Last - Primary_Directory + 1;
1270 else
1271 return Lib_Search_Directories.Last - Primary_Directory;
1272 end if;
1273 end Nb_Dir_In_Obj_Search_Path;
1275 -------------------------------
1276 -- Nb_Dir_In_Src_Search_Path --
1277 -------------------------------
1279 function Nb_Dir_In_Src_Search_Path return Natural is
1280 begin
1281 if Opt.Look_In_Primary_Dir then
1282 return Src_Search_Directories.Last - Primary_Directory + 1;
1283 else
1284 return Src_Search_Directories.Last - Primary_Directory;
1285 end if;
1286 end Nb_Dir_In_Src_Search_Path;
1288 --------------------
1289 -- Next_Main_File --
1290 --------------------
1292 function Next_Main_File return File_Name_Type is
1293 File_Name : String_Ptr;
1294 Dir_Name : String_Ptr;
1295 Fptr : Natural;
1297 begin
1298 pragma Assert (More_Files);
1300 Current_File_Name_Index := Current_File_Name_Index + 1;
1302 -- Get the file and directory name
1304 File_Name := File_Names (Current_File_Name_Index);
1305 Fptr := File_Name'First;
1307 for J in reverse File_Name'Range loop
1308 if File_Name (J) = Directory_Separator
1309 or else File_Name (J) = '/'
1310 then
1311 if J = File_Name'Last then
1312 Fail ("File name missing");
1313 end if;
1315 Fptr := J + 1;
1316 exit;
1317 end if;
1318 end loop;
1320 -- Save name of directory in which main unit resides for use in
1321 -- locating other units
1323 Dir_Name := new String'(File_Name (File_Name'First .. Fptr - 1));
1325 case Running_Program is
1327 when Compiler =>
1328 Src_Search_Directories.Table (Primary_Directory) := Dir_Name;
1329 Look_In_Primary_Directory_For_Current_Main := True;
1331 when Make =>
1332 Src_Search_Directories.Table (Primary_Directory) := Dir_Name;
1334 if Fptr > File_Name'First then
1335 Look_In_Primary_Directory_For_Current_Main := True;
1336 end if;
1338 when Binder | Gnatls =>
1339 Dir_Name := Normalize_Directory_Name (Dir_Name.all);
1340 Lib_Search_Directories.Table (Primary_Directory) := Dir_Name;
1342 when Unspecified =>
1343 null;
1344 end case;
1346 Name_Len := File_Name'Last - Fptr + 1;
1347 Name_Buffer (1 .. Name_Len) := File_Name (Fptr .. File_Name'Last);
1348 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
1349 Current_Main := File_Name_Type (Name_Find);
1351 -- In the gnatmake case, the main file may have not have the
1352 -- extension. Try ".adb" first then ".ads"
1354 if Running_Program = Make then
1355 declare
1356 Orig_Main : File_Name_Type := Current_Main;
1358 begin
1359 if Strip_Suffix (Orig_Main) = Orig_Main then
1360 Current_Main := Append_Suffix_To_File_Name (Orig_Main, ".adb");
1362 if Full_Source_Name (Current_Main) = No_File then
1363 Current_Main :=
1364 Append_Suffix_To_File_Name (Orig_Main, ".ads");
1366 if Full_Source_Name (Current_Main) = No_File then
1367 Current_Main := Orig_Main;
1368 end if;
1369 end if;
1370 end if;
1371 end;
1372 end if;
1374 return Current_Main;
1375 end Next_Main_File;
1377 ------------------------------
1378 -- Normalize_Directory_Name --
1379 ------------------------------
1381 function Normalize_Directory_Name (Directory : String) return String_Ptr is
1382 Result : String_Ptr;
1384 begin
1385 if Directory'Length = 0 then
1386 Result := new String'(Hostparm.Normalized_CWD);
1388 elsif Is_Directory_Separator (Directory (Directory'Last)) then
1389 Result := new String'(Directory);
1390 else
1391 Result := new String (1 .. Directory'Length + 1);
1392 Result (1 .. Directory'Length) := Directory;
1393 Result (Directory'Length + 1) := Directory_Separator;
1394 end if;
1396 return Result;
1397 end Normalize_Directory_Name;
1399 ---------------------
1400 -- Number_Of_Files --
1401 ---------------------
1403 function Number_Of_Files return Int is
1404 begin
1405 return Number_File_Names;
1406 end Number_Of_Files;
1408 ----------------------
1409 -- Object_File_Name --
1410 ----------------------
1412 function Object_File_Name (N : File_Name_Type) return File_Name_Type is
1413 begin
1414 if N = No_File then
1415 return No_File;
1416 end if;
1418 Get_Name_String (N);
1419 Name_Len := Name_Len - ALI_Suffix'Length - 1;
1421 for J in Object_Suffix'Range loop
1422 Name_Len := Name_Len + 1;
1423 Name_Buffer (Name_Len) := Object_Suffix (J);
1424 end loop;
1426 return Name_Enter;
1427 end Object_File_Name;
1429 --------------------------
1430 -- OS_Time_To_GNAT_Time --
1431 --------------------------
1433 function OS_Time_To_GNAT_Time (T : OS_Time) return Time_Stamp_Type is
1434 GNAT_Time : Time_Stamp_Type;
1436 Y : Year_Type;
1437 Mo : Month_Type;
1438 D : Day_Type;
1439 H : Hour_Type;
1440 Mn : Minute_Type;
1441 S : Second_Type;
1443 begin
1444 GM_Split (T, Y, Mo, D, H, Mn, S);
1445 Make_Time_Stamp
1446 (Year => Nat (Y),
1447 Month => Nat (Mo),
1448 Day => Nat (D),
1449 Hour => Nat (H),
1450 Minutes => Nat (Mn),
1451 Seconds => Nat (S),
1452 TS => GNAT_Time);
1454 return GNAT_Time;
1455 end OS_Time_To_GNAT_Time;
1457 ------------------
1458 -- Program_Name --
1459 ------------------
1461 function Program_Name (Nam : String) return String_Access is
1462 Res : String_Access;
1464 begin
1465 -- Get the name of the current program being executed
1467 Find_Program_Name;
1469 -- Find the target prefix if any, for the cross compilation case
1470 -- for instance in "alpha-dec-vxworks-gcc" the target prefix is
1471 -- "alpha-dec-vxworks-"
1473 while Name_Len > 0 loop
1474 if Name_Buffer (Name_Len) = '-' then
1475 exit;
1476 end if;
1478 Name_Len := Name_Len - 1;
1479 end loop;
1481 -- Create the new program name
1483 Res := new String (1 .. Name_Len + Nam'Length);
1484 Res.all (1 .. Name_Len) := Name_Buffer (1 .. Name_Len);
1485 Res.all (Name_Len + 1 .. Name_Len + Nam'Length) := Nam;
1486 return Res;
1487 end Program_Name;
1489 ------------------------------
1490 -- Read_Default_Search_Dirs --
1491 ------------------------------
1493 function Read_Default_Search_Dirs
1494 (Search_Dir_Prefix : String_Access;
1495 Search_File : String_Access;
1496 Search_Dir_Default_Name : String_Access)
1497 return String_Access
1499 Prefix_Len : constant Integer := Search_Dir_Prefix.all'Length;
1500 Buffer : String (1 .. Prefix_Len + Search_File.all'Length + 1);
1501 File_FD : File_Descriptor;
1502 S, S1 : String_Access;
1503 Len : Integer;
1504 Curr : Integer;
1505 Actual_Len : Integer;
1506 J1 : Integer;
1508 Prev_Was_Separator : Boolean;
1509 Nb_Relative_Dir : Integer;
1511 function Is_Relative (S : String; K : Positive) return Boolean;
1512 pragma Inline (Is_Relative);
1513 -- Returns True if a relative directory specification is found
1514 -- in S at position K, False otherwise.
1516 -----------------
1517 -- Is_Relative --
1518 -----------------
1520 function Is_Relative (S : String; K : Positive) return Boolean is
1521 begin
1522 return not Is_Absolute_Path (S (K .. S'Last));
1523 end Is_Relative;
1525 -- Start of processing for Read_Default_Search_Dirs
1527 begin
1528 -- Construct a C compatible character string buffer.
1530 Buffer (1 .. Search_Dir_Prefix.all'Length)
1531 := Search_Dir_Prefix.all;
1532 Buffer (Search_Dir_Prefix.all'Length + 1 .. Buffer'Last - 1)
1533 := Search_File.all;
1534 Buffer (Buffer'Last) := ASCII.NUL;
1536 File_FD := Open_Read (Buffer'Address, Binary);
1537 if File_FD = Invalid_FD then
1538 return Search_Dir_Default_Name;
1539 end if;
1541 Len := Integer (File_Length (File_FD));
1543 -- An extra character for a trailing Path_Separator is allocated
1545 S := new String (1 .. Len + 1);
1546 S (Len + 1) := Path_Separator;
1548 -- Read the file. Note that the loop is not necessary since the
1549 -- whole file is read at once except on VMS.
1551 Curr := 1;
1552 Actual_Len := Len;
1553 while Actual_Len /= 0 loop
1554 Actual_Len := Read (File_FD, S (Curr)'Address, Len);
1555 Curr := Curr + Actual_Len;
1556 end loop;
1558 -- Process the file, translating line and file ending
1559 -- control characters to a path separator character.
1561 Prev_Was_Separator := True;
1562 Nb_Relative_Dir := 0;
1563 for J in 1 .. Len loop
1564 if S (J) in ASCII.NUL .. ASCII.US
1565 or else S (J) = ' '
1566 then
1567 S (J) := Path_Separator;
1568 end if;
1570 if S (J) = Path_Separator then
1571 Prev_Was_Separator := True;
1572 else
1573 if Prev_Was_Separator and then Is_Relative (S.all, J) then
1574 Nb_Relative_Dir := Nb_Relative_Dir + 1;
1575 end if;
1577 Prev_Was_Separator := False;
1578 end if;
1579 end loop;
1581 if Nb_Relative_Dir = 0 then
1582 return S;
1583 end if;
1585 -- Add the Search_Dir_Prefix to all relative paths
1587 S1 := new String (1 .. S'Length + Nb_Relative_Dir * Prefix_Len);
1588 J1 := 1;
1589 Prev_Was_Separator := True;
1590 for J in 1 .. Len + 1 loop
1591 if S (J) = Path_Separator then
1592 Prev_Was_Separator := True;
1594 else
1595 if Prev_Was_Separator and then Is_Relative (S.all, J) then
1596 S1 (J1 .. J1 + Prefix_Len) := Search_Dir_Prefix.all;
1597 J1 := J1 + Prefix_Len;
1598 end if;
1600 Prev_Was_Separator := False;
1601 end if;
1602 S1 (J1) := S (J);
1603 J1 := J1 + 1;
1604 end loop;
1606 Free (S);
1607 return S1;
1608 end Read_Default_Search_Dirs;
1610 -----------------------
1611 -- Read_Library_Info --
1612 -----------------------
1614 function Read_Library_Info
1615 (Lib_File : File_Name_Type;
1616 Fatal_Err : Boolean := False)
1617 return Text_Buffer_Ptr
1619 Lib_FD : File_Descriptor;
1620 -- The file descriptor for the current library file. A negative value
1621 -- indicates failure to open the specified source file.
1623 Text : Text_Buffer_Ptr;
1624 -- Allocated text buffer.
1626 begin
1627 Current_Full_Lib_Name := Find_File (Lib_File, Library);
1628 Current_Full_Obj_Name := Object_File_Name (Current_Full_Lib_Name);
1630 if Current_Full_Lib_Name = No_File then
1631 if Fatal_Err then
1632 Fail ("Cannot find: ", Name_Buffer (1 .. Name_Len));
1633 else
1634 Current_Full_Obj_Stamp := Empty_Time_Stamp;
1635 return null;
1636 end if;
1637 end if;
1639 Get_Name_String (Current_Full_Lib_Name);
1640 Name_Buffer (Name_Len + 1) := ASCII.NUL;
1642 -- Open the library FD, note that we open in binary mode, because as
1643 -- documented in the spec, the caller is expected to handle either
1644 -- DOS or Unix mode files, and there is no point in wasting time on
1645 -- text translation when it is not required.
1647 Lib_FD := Open_Read (Name_Buffer'Address, Binary);
1649 if Lib_FD = Invalid_FD then
1650 if Fatal_Err then
1651 Fail ("Cannot open: ", Name_Buffer (1 .. Name_Len));
1652 else
1653 Current_Full_Obj_Stamp := Empty_Time_Stamp;
1654 return null;
1655 end if;
1656 end if;
1658 -- Check for object file consistency if requested
1660 if Opt.Check_Object_Consistency then
1661 Current_Full_Lib_Stamp := File_Stamp (Current_Full_Lib_Name);
1662 Current_Full_Obj_Stamp := File_Stamp (Current_Full_Obj_Name);
1664 if Current_Full_Obj_Stamp (1) = ' ' then
1666 -- When the library is readonly, always assume that
1667 -- the object is consistent.
1669 if Is_Readonly_Library (Current_Full_Lib_Name) then
1670 Current_Full_Obj_Stamp := Current_Full_Lib_Stamp;
1672 elsif Fatal_Err then
1673 Get_Name_String (Current_Full_Obj_Name);
1674 Close (Lib_FD);
1675 Fail ("Cannot find: ", Name_Buffer (1 .. Name_Len));
1677 else
1678 Current_Full_Obj_Stamp := Empty_Time_Stamp;
1679 Close (Lib_FD);
1680 return null;
1681 end if;
1682 end if;
1684 -- Object file exists, compare object and ALI time stamps
1686 if Current_Full_Lib_Stamp > Current_Full_Obj_Stamp then
1687 if Fatal_Err then
1688 Get_Name_String (Current_Full_Obj_Name);
1689 Close (Lib_FD);
1690 Fail ("Bad time stamp: ", Name_Buffer (1 .. Name_Len));
1691 else
1692 Current_Full_Obj_Stamp := Empty_Time_Stamp;
1693 Close (Lib_FD);
1694 return null;
1695 end if;
1696 end if;
1697 end if;
1699 -- Read data from the file
1701 declare
1702 Len : Integer := Integer (File_Length (Lib_FD));
1703 -- Length of source file text. If it doesn't fit in an integer
1704 -- we're probably stuck anyway (>2 gigs of source seems a lot!)
1706 Actual_Len : Integer := 0;
1708 Lo : Text_Ptr := 0;
1709 -- Low bound for allocated text buffer
1711 Hi : Text_Ptr := Text_Ptr (Len);
1712 -- High bound for allocated text buffer. Note length is Len + 1
1713 -- which allows for extra EOF character at the end of the buffer.
1715 begin
1716 -- Allocate text buffer. Note extra character at end for EOF
1718 Text := new Text_Buffer (Lo .. Hi);
1720 -- Some systems (e.g. VMS) have file types that require one
1721 -- read per line, so read until we get the Len bytes or until
1722 -- there are no more characters.
1724 Hi := Lo;
1725 loop
1726 Actual_Len := Read (Lib_FD, Text (Hi)'Address, Len);
1727 Hi := Hi + Text_Ptr (Actual_Len);
1728 exit when Actual_Len = Len or Actual_Len <= 0;
1729 end loop;
1731 Text (Hi) := EOF;
1732 end;
1734 -- Read is complete, close file and we are done
1736 Close (Lib_FD);
1737 return Text;
1739 end Read_Library_Info;
1741 ----------------------
1742 -- Read_Source_File --
1743 ----------------------
1745 procedure Read_Source_File
1746 (N : File_Name_Type;
1747 Lo : Source_Ptr;
1748 Hi : out Source_Ptr;
1749 Src : out Source_Buffer_Ptr;
1750 T : File_Type := Source)
1752 Source_File_FD : File_Descriptor;
1753 -- The file descriptor for the current source file. A negative value
1754 -- indicates failure to open the specified source file.
1756 Len : Integer;
1757 -- Length of file. Assume no more than 2 gigabytes of source!
1759 Actual_Len : Integer;
1761 begin
1762 Current_Full_Source_Name := Find_File (N, T);
1763 Current_Full_Source_Stamp := File_Stamp (Current_Full_Source_Name);
1765 if Current_Full_Source_Name = No_File then
1767 -- If we were trying to access the main file and we could not
1768 -- find it we have an error.
1770 if N = Current_Main then
1771 Get_Name_String (N);
1772 Fail ("Cannot find: ", Name_Buffer (1 .. Name_Len));
1773 end if;
1775 Src := null;
1776 Hi := No_Location;
1777 return;
1778 end if;
1780 Get_Name_String (Current_Full_Source_Name);
1781 Name_Buffer (Name_Len + 1) := ASCII.NUL;
1783 -- Open the source FD, note that we open in binary mode, because as
1784 -- documented in the spec, the caller is expected to handle either
1785 -- DOS or Unix mode files, and there is no point in wasting time on
1786 -- text translation when it is not required.
1788 Source_File_FD := Open_Read (Name_Buffer'Address, Binary);
1790 if Source_File_FD = Invalid_FD then
1791 Src := null;
1792 Hi := No_Location;
1793 return;
1794 end if;
1796 -- Prepare to read data from the file
1798 Len := Integer (File_Length (Source_File_FD));
1800 -- Set Hi so that length is one more than the physical length,
1801 -- allowing for the extra EOF character at the end of the buffer
1803 Hi := Lo + Source_Ptr (Len);
1805 -- Do the actual read operation
1807 declare
1808 subtype Actual_Source_Buffer is Source_Buffer (Lo .. Hi);
1809 -- Physical buffer allocated
1811 type Actual_Source_Ptr is access Actual_Source_Buffer;
1812 -- This is the pointer type for the physical buffer allocated
1814 Actual_Ptr : Actual_Source_Ptr := new Actual_Source_Buffer;
1815 -- And this is the actual physical buffer
1817 begin
1818 -- Allocate source buffer, allowing extra character at end for EOF
1820 -- Some systems (e.g. VMS) have file types that require one
1821 -- read per line, so read until we get the Len bytes or until
1822 -- there are no more characters.
1824 Hi := Lo;
1825 loop
1826 Actual_Len := Read (Source_File_FD, Actual_Ptr (Hi)'Address, Len);
1827 Hi := Hi + Source_Ptr (Actual_Len);
1828 exit when Actual_Len = Len or Actual_Len <= 0;
1829 end loop;
1831 Actual_Ptr (Hi) := EOF;
1833 -- Now we need to work out the proper virtual origin pointer to
1834 -- return. This is exactly Actual_Ptr (0)'Address, but we have
1835 -- to be careful to suppress checks to compute this address.
1837 declare
1838 pragma Suppress (All_Checks);
1840 function To_Source_Buffer_Ptr is new
1841 Unchecked_Conversion (Address, Source_Buffer_Ptr);
1843 begin
1844 Src := To_Source_Buffer_Ptr (Actual_Ptr (0)'Address);
1845 end;
1846 end;
1848 -- Read is complete, get time stamp and close file and we are done
1850 Close (Source_File_FD);
1852 end Read_Source_File;
1854 -----------------
1855 -- Set_Program --
1856 -----------------
1858 procedure Set_Program (P : Program_Type) is
1859 begin
1860 if Program_Set then
1861 Fail ("Set_Program called twice");
1862 end if;
1864 Program_Set := True;
1865 Running_Program := P;
1866 end Set_Program;
1868 ----------------------
1869 -- Smart_File_Stamp --
1870 ----------------------
1872 function Smart_File_Stamp
1873 (N : File_Name_Type;
1874 T : File_Type)
1875 return Time_Stamp_Type
1877 Time_Stamp : Time_Stamp_Type;
1879 begin
1880 if not File_Cache_Enabled then
1881 return File_Stamp (Find_File (N, T));
1882 end if;
1884 Time_Stamp := File_Stamp_Hash_Table.Get (N);
1886 if Time_Stamp (1) = ' ' then
1887 Time_Stamp := File_Stamp (Smart_Find_File (N, T));
1888 File_Stamp_Hash_Table.Set (N, Time_Stamp);
1889 end if;
1891 return Time_Stamp;
1892 end Smart_File_Stamp;
1894 ---------------------
1895 -- Smart_Find_File --
1896 ---------------------
1898 function Smart_Find_File
1899 (N : File_Name_Type;
1900 T : File_Type)
1901 return File_Name_Type
1903 Full_File_Name : File_Name_Type;
1905 begin
1906 if not File_Cache_Enabled then
1907 return Find_File (N, T);
1908 end if;
1910 Full_File_Name := File_Name_Hash_Table.Get (N);
1912 if Full_File_Name = No_File then
1913 Full_File_Name := Find_File (N, T);
1914 File_Name_Hash_Table.Set (N, Full_File_Name);
1915 end if;
1917 return Full_File_Name;
1918 end Smart_Find_File;
1920 ----------------------
1921 -- Source_File_Data --
1922 ----------------------
1924 procedure Source_File_Data (Cache : Boolean) is
1925 begin
1926 File_Cache_Enabled := Cache;
1927 end Source_File_Data;
1929 -----------------------
1930 -- Source_File_Stamp --
1931 -----------------------
1933 function Source_File_Stamp (N : File_Name_Type) return Time_Stamp_Type is
1934 begin
1935 return Smart_File_Stamp (N, Source);
1936 end Source_File_Stamp;
1938 ---------------------
1939 -- Strip_Directory --
1940 ---------------------
1942 function Strip_Directory (Name : File_Name_Type) return File_Name_Type is
1943 begin
1944 Get_Name_String (Name);
1946 for J in reverse 1 .. Name_Len - 1 loop
1947 -- If we find the last directory separator
1949 if Is_Directory_Separator (Name_Buffer (J)) then
1950 -- Return the part of Name that follows this last directory
1951 -- separator.
1953 Name_Buffer (1 .. Name_Len - J) := Name_Buffer (J + 1 .. Name_Len);
1954 Name_Len := Name_Len - J;
1955 return Name_Find;
1956 end if;
1957 end loop;
1959 -- There were no directory separator, just return Name
1961 return Name;
1962 end Strip_Directory;
1964 ------------------
1965 -- Strip_Suffix --
1966 ------------------
1968 function Strip_Suffix (Name : File_Name_Type) return File_Name_Type is
1969 begin
1970 Get_Name_String (Name);
1972 for J in reverse 2 .. Name_Len loop
1974 -- If we found the last '.', return the part of Name that precedes
1975 -- this '.'.
1977 if Name_Buffer (J) = '.' then
1978 Name_Len := J - 1;
1979 return Name_Enter;
1980 end if;
1981 end loop;
1983 return Name;
1984 end Strip_Suffix;
1986 ---------------------------
1987 -- To_Canonical_Dir_Spec --
1988 ---------------------------
1990 function To_Canonical_Dir_Spec
1991 (Host_Dir : String;
1992 Prefix_Style : Boolean)
1993 return String_Access
1995 function To_Canonical_Dir_Spec
1996 (Host_Dir : Address;
1997 Prefix_Flag : Integer)
1998 return Address;
1999 pragma Import (C, To_Canonical_Dir_Spec, "__gnat_to_canonical_dir_spec");
2001 C_Host_Dir : String (1 .. Host_Dir'Length + 1);
2002 Canonical_Dir_Addr : Address;
2003 Canonical_Dir_Len : Integer;
2005 begin
2006 C_Host_Dir (1 .. Host_Dir'Length) := Host_Dir;
2007 C_Host_Dir (C_Host_Dir'Last) := ASCII.NUL;
2009 if Prefix_Style then
2010 Canonical_Dir_Addr := To_Canonical_Dir_Spec (C_Host_Dir'Address, 1);
2011 else
2012 Canonical_Dir_Addr := To_Canonical_Dir_Spec (C_Host_Dir'Address, 0);
2013 end if;
2014 Canonical_Dir_Len := C_String_Length (Canonical_Dir_Addr);
2016 if Canonical_Dir_Len = 0 then
2017 return null;
2018 else
2019 return To_Path_String_Access (Canonical_Dir_Addr, Canonical_Dir_Len);
2020 end if;
2022 exception
2023 when others =>
2024 Fail ("erroneous directory spec: ", Host_Dir);
2025 return null;
2026 end To_Canonical_Dir_Spec;
2028 ---------------------------
2029 -- To_Canonical_File_List --
2030 ---------------------------
2032 function To_Canonical_File_List
2033 (Wildcard_Host_File : String;
2034 Only_Dirs : Boolean)
2035 return String_Access_List_Access
2037 function To_Canonical_File_List_Init
2038 (Host_File : Address;
2039 Only_Dirs : Integer)
2040 return Integer;
2041 pragma Import (C, To_Canonical_File_List_Init,
2042 "__gnat_to_canonical_file_list_init");
2044 function To_Canonical_File_List_Next return Address;
2045 pragma Import (C, To_Canonical_File_List_Next,
2046 "__gnat_to_canonical_file_list_next");
2048 procedure To_Canonical_File_List_Free;
2049 pragma Import (C, To_Canonical_File_List_Free,
2050 "__gnat_to_canonical_file_list_free");
2052 Num_Files : Integer;
2053 C_Wildcard_Host_File : String (1 .. Wildcard_Host_File'Length + 1);
2055 begin
2056 C_Wildcard_Host_File (1 .. Wildcard_Host_File'Length) :=
2057 Wildcard_Host_File;
2058 C_Wildcard_Host_File (C_Wildcard_Host_File'Last) := ASCII.NUL;
2060 -- Do the expansion and say how many there are
2062 Num_Files := To_Canonical_File_List_Init
2063 (C_Wildcard_Host_File'Address, Boolean'Pos (Only_Dirs));
2065 declare
2066 Canonical_File_List : String_Access_List (1 .. Num_Files);
2067 Canonical_File_Addr : Address;
2068 Canonical_File_Len : Integer;
2070 begin
2071 -- Retrieve the expanded directoy names and build the list
2073 for J in 1 .. Num_Files loop
2074 Canonical_File_Addr := To_Canonical_File_List_Next;
2075 Canonical_File_Len := C_String_Length (Canonical_File_Addr);
2076 Canonical_File_List (J) := To_Path_String_Access
2077 (Canonical_File_Addr, Canonical_File_Len);
2078 end loop;
2080 -- Free up the storage
2082 To_Canonical_File_List_Free;
2084 return new String_Access_List'(Canonical_File_List);
2085 end;
2086 end To_Canonical_File_List;
2088 ----------------------------
2089 -- To_Canonical_File_Spec --
2090 ----------------------------
2092 function To_Canonical_File_Spec
2093 (Host_File : String)
2094 return String_Access
2096 function To_Canonical_File_Spec (Host_File : Address) return Address;
2097 pragma Import
2098 (C, To_Canonical_File_Spec, "__gnat_to_canonical_file_spec");
2100 C_Host_File : String (1 .. Host_File'Length + 1);
2101 Canonical_File_Addr : Address;
2102 Canonical_File_Len : Integer;
2104 begin
2105 C_Host_File (1 .. Host_File'Length) := Host_File;
2106 C_Host_File (C_Host_File'Last) := ASCII.NUL;
2108 Canonical_File_Addr := To_Canonical_File_Spec (C_Host_File'Address);
2109 Canonical_File_Len := C_String_Length (Canonical_File_Addr);
2111 if Canonical_File_Len = 0 then
2112 return null;
2113 else
2114 return To_Path_String_Access
2115 (Canonical_File_Addr, Canonical_File_Len);
2116 end if;
2118 exception
2119 when others =>
2120 Fail ("erroneous file spec: ", Host_File);
2121 return null;
2122 end To_Canonical_File_Spec;
2124 ----------------------------
2125 -- To_Canonical_Path_Spec --
2126 ----------------------------
2128 function To_Canonical_Path_Spec
2129 (Host_Path : String)
2130 return String_Access
2132 function To_Canonical_Path_Spec (Host_Path : Address) return Address;
2133 pragma Import
2134 (C, To_Canonical_Path_Spec, "__gnat_to_canonical_path_spec");
2136 C_Host_Path : String (1 .. Host_Path'Length + 1);
2137 Canonical_Path_Addr : Address;
2138 Canonical_Path_Len : Integer;
2140 begin
2141 C_Host_Path (1 .. Host_Path'Length) := Host_Path;
2142 C_Host_Path (C_Host_Path'Last) := ASCII.NUL;
2144 Canonical_Path_Addr := To_Canonical_Path_Spec (C_Host_Path'Address);
2145 Canonical_Path_Len := C_String_Length (Canonical_Path_Addr);
2147 -- Return a null string (vice a null) for zero length paths, for
2148 -- compatibility with getenv().
2150 return To_Path_String_Access (Canonical_Path_Addr, Canonical_Path_Len);
2152 exception
2153 when others =>
2154 Fail ("erroneous path spec: ", Host_Path);
2155 return null;
2156 end To_Canonical_Path_Spec;
2158 ---------------------------
2159 -- To_Host_Dir_Spec --
2160 ---------------------------
2162 function To_Host_Dir_Spec
2163 (Canonical_Dir : String;
2164 Prefix_Style : Boolean)
2165 return String_Access
2167 function To_Host_Dir_Spec
2168 (Canonical_Dir : Address;
2169 Prefix_Flag : Integer)
2170 return Address;
2171 pragma Import (C, To_Host_Dir_Spec, "__gnat_to_host_dir_spec");
2173 C_Canonical_Dir : String (1 .. Canonical_Dir'Length + 1);
2174 Host_Dir_Addr : Address;
2175 Host_Dir_Len : Integer;
2177 begin
2178 C_Canonical_Dir (1 .. Canonical_Dir'Length) := Canonical_Dir;
2179 C_Canonical_Dir (C_Canonical_Dir'Last) := ASCII.NUL;
2181 if Prefix_Style then
2182 Host_Dir_Addr := To_Host_Dir_Spec (C_Canonical_Dir'Address, 1);
2183 else
2184 Host_Dir_Addr := To_Host_Dir_Spec (C_Canonical_Dir'Address, 0);
2185 end if;
2186 Host_Dir_Len := C_String_Length (Host_Dir_Addr);
2188 if Host_Dir_Len = 0 then
2189 return null;
2190 else
2191 return To_Path_String_Access (Host_Dir_Addr, Host_Dir_Len);
2192 end if;
2193 end To_Host_Dir_Spec;
2195 ----------------------------
2196 -- To_Host_File_Spec --
2197 ----------------------------
2199 function To_Host_File_Spec
2200 (Canonical_File : String)
2201 return String_Access
2203 function To_Host_File_Spec (Canonical_File : Address) return Address;
2204 pragma Import (C, To_Host_File_Spec, "__gnat_to_host_file_spec");
2206 C_Canonical_File : String (1 .. Canonical_File'Length + 1);
2207 Host_File_Addr : Address;
2208 Host_File_Len : Integer;
2210 begin
2211 C_Canonical_File (1 .. Canonical_File'Length) := Canonical_File;
2212 C_Canonical_File (C_Canonical_File'Last) := ASCII.NUL;
2214 Host_File_Addr := To_Host_File_Spec (C_Canonical_File'Address);
2215 Host_File_Len := C_String_Length (Host_File_Addr);
2217 if Host_File_Len = 0 then
2218 return null;
2219 else
2220 return To_Path_String_Access
2221 (Host_File_Addr, Host_File_Len);
2222 end if;
2223 end To_Host_File_Spec;
2225 ---------------------------
2226 -- To_Path_String_Access --
2227 ---------------------------
2229 function To_Path_String_Access
2230 (Path_Addr : Address;
2231 Path_Len : Integer)
2232 return String_Access
2234 subtype Path_String is String (1 .. Path_Len);
2235 type Path_String_Access is access Path_String;
2237 function Address_To_Access is new
2238 Unchecked_Conversion (Source => Address,
2239 Target => Path_String_Access);
2241 Path_Access : Path_String_Access := Address_To_Access (Path_Addr);
2243 Return_Val : String_Access;
2245 begin
2246 Return_Val := new String (1 .. Path_Len);
2248 for J in 1 .. Path_Len loop
2249 Return_Val (J) := Path_Access (J);
2250 end loop;
2252 return Return_Val;
2253 end To_Path_String_Access;
2255 -----------------
2256 -- Update_Path --
2257 -----------------
2259 function Update_Path (Path : String_Ptr) return String_Ptr is
2261 function C_Update_Path (Path, Component : Address) return Address;
2262 pragma Import (C, C_Update_Path, "update_path");
2264 function Strlen (Str : Address) return Integer;
2265 pragma Import (C, Strlen, "strlen");
2267 procedure Strncpy (X : Address; Y : Address; Length : Integer);
2268 pragma Import (C, Strncpy, "strncpy");
2270 In_Length : constant Integer := Path'Length;
2271 In_String : String (1 .. In_Length + 1);
2272 Component_Name : aliased String := "GNAT" & ASCII.NUL;
2273 Result_Ptr : Address;
2274 Result_Length : Integer;
2275 Out_String : String_Ptr;
2277 begin
2278 In_String (1 .. In_Length) := Path.all;
2279 In_String (In_Length + 1) := ASCII.NUL;
2280 Result_Ptr := C_Update_Path (In_String'Address,
2281 Component_Name'Address);
2282 Result_Length := Strlen (Result_Ptr);
2284 Out_String := new String (1 .. Result_Length);
2285 Strncpy (Out_String.all'Address, Result_Ptr, Result_Length);
2286 return Out_String;
2287 end Update_Path;
2289 ----------------
2290 -- Write_Info --
2291 ----------------
2293 procedure Write_Info (Info : String) is
2294 begin
2295 Write_With_Check (Info'Address, Info'Length);
2296 Write_With_Check (EOL'Address, 1);
2297 end Write_Info;
2299 ------------------------
2300 -- Write_Program_Name --
2301 ------------------------
2303 procedure Write_Program_Name is
2304 Save_Buffer : String (1 .. Name_Len) := Name_Buffer (1 .. Name_Len);
2306 begin
2308 Find_Program_Name;
2310 -- Convert the name to lower case so error messages are the same on
2311 -- all systems.
2313 for J in 1 .. Name_Len loop
2314 if Name_Buffer (J) in 'A' .. 'Z' then
2315 Name_Buffer (J) :=
2316 Character'Val (Character'Pos (Name_Buffer (J)) + 32);
2317 end if;
2318 end loop;
2320 Write_Str (Name_Buffer (1 .. Name_Len));
2322 -- Restore Name_Buffer which was clobbered by the call to
2323 -- Find_Program_Name
2325 Name_Len := Save_Buffer'Last;
2326 Name_Buffer (1 .. Name_Len) := Save_Buffer;
2327 end Write_Program_Name;
2329 ----------------------
2330 -- Write_With_Check --
2331 ----------------------
2333 procedure Write_With_Check (A : Address; N : Integer) is
2334 Ignore : Boolean;
2336 begin
2337 if N = Write (Output_FD, A, N) then
2338 return;
2340 else
2341 Write_Str ("error: disk full writing ");
2342 Write_Name_Decoded (Output_File_Name);
2343 Write_Eol;
2344 Name_Len := Name_Len + 1;
2345 Name_Buffer (Name_Len) := ASCII.NUL;
2346 Delete_File (Name_Buffer'Address, Ignore);
2347 Exit_Program (E_Fatal);
2348 end if;
2349 end Write_With_Check;
2351 ----------------------------
2352 -- Package Initialization --
2353 ----------------------------
2355 begin
2356 Initialization : declare
2358 function Get_Default_Identifier_Character_Set return Character;
2359 pragma Import (C, Get_Default_Identifier_Character_Set,
2360 "__gnat_get_default_identifier_character_set");
2361 -- Function to determine the default identifier character set,
2362 -- which is system dependent. See Opt package spec for a list of
2363 -- the possible character codes and their interpretations.
2365 function Get_Maximum_File_Name_Length return Int;
2366 pragma Import (C, Get_Maximum_File_Name_Length,
2367 "__gnat_get_maximum_file_name_length");
2368 -- Function to get maximum file name length for system
2370 begin
2371 Src_Search_Directories.Init;
2372 Lib_Search_Directories.Init;
2374 Identifier_Character_Set := Get_Default_Identifier_Character_Set;
2375 Maximum_File_Name_Length := Get_Maximum_File_Name_Length;
2377 -- Following should be removed by having above function return
2378 -- Integer'Last as indication of no maximum instead of -1 ???
2380 if Maximum_File_Name_Length = -1 then
2381 Maximum_File_Name_Length := Int'Last;
2382 end if;
2384 -- Start off by setting all suppress options to False, these will
2385 -- be reset later (turning some on if -gnato is not specified, and
2386 -- turning all of them on if -gnatp is specified).
2388 Suppress_Options := (others => False);
2390 -- Reserve the first slot in the search paths table. This is the
2391 -- directory of the main source file or main library file and is
2392 -- filled in by each call to Next_Main_Source/Next_Main_Lib_File with
2393 -- the directory specified for this main source or library file. This
2394 -- is the directory which is searched first by default. This default
2395 -- search is inhibited by the option -I- for both source and library
2396 -- files.
2398 Src_Search_Directories.Set_Last (Primary_Directory);
2399 Src_Search_Directories.Table (Primary_Directory) := new String'("");
2401 Lib_Search_Directories.Set_Last (Primary_Directory);
2402 Lib_Search_Directories.Table (Primary_Directory) := new String'("");
2403 end Initialization;
2405 end Osint;