OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gcc-4.5.1/] [gcc/] [ada/] [osint.adb] - Blame information for rev 310

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 281 jeremybenn
------------------------------------------------------------------------------
2
--                                                                          --
3
--                         GNAT COMPILER COMPONENTS                         --
4
--                                                                          --
5
--                                O S I N T                                 --
6
--                                                                          --
7
--                                 B o d y                                  --
8
--                                                                          --
9
--          Copyright (C) 1992-2009, Free Software Foundation, Inc.         --
10
--                                                                          --
11
-- GNAT is free software;  you can  redistribute it  and/or modify it under --
12
-- terms of the  GNU General Public License as published  by the Free Soft- --
13
-- ware  Foundation;  either version 3,  or (at your option) any later ver- --
14
-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
15
-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
16
-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
17
-- for  more details.  You should have  received  a copy of the GNU General --
18
-- Public License  distributed with GNAT; see file COPYING3.  If not, go to --
19
-- http://www.gnu.org/licenses for a complete copy of the license.          --
20
--                                                                          --
21
-- GNAT was originally developed  by the GNAT team at  New York University. --
22
-- Extensive contributions were provided by Ada Core Technologies Inc.      --
23
--                                                                          --
24
------------------------------------------------------------------------------
25
 
26
with Unchecked_Conversion;
27
 
28
with System.Case_Util; use System.Case_Util;
29
 
30
with GNAT.HTable;
31
 
32
with Alloc;
33
with Debug;
34
with Fmap;             use Fmap;
35
with Gnatvsn;          use Gnatvsn;
36
with Hostparm;
37
with Opt;              use Opt;
38
with Output;           use Output;
39
with Sdefault;         use Sdefault;
40
with Table;
41
with Targparm;         use Targparm;
42
 
43
package body Osint is
44
 
45
   Running_Program : Program_Type := Unspecified;
46
   --  comment required here ???
47
 
48
   Program_Set : Boolean := False;
49
   --  comment required here ???
50
 
51
   Std_Prefix : String_Ptr;
52
   --  Standard prefix, computed dynamically the first time Relocate_Path
53
   --  is called, and cached for subsequent calls.
54
 
55
   Empty  : aliased String := "";
56
   No_Dir : constant String_Ptr := Empty'Access;
57
   --  Used in Locate_File as a fake directory when Name is already an
58
   --  absolute path.
59
 
60
   -------------------------------------
61
   -- Use of Name_Find and Name_Enter --
62
   -------------------------------------
63
 
64
   --  This package creates a number of source, ALI and object file names
65
   --  that are used to locate the actual file and for the purpose of message
66
   --  construction. These names need not be accessible by Name_Find, and can
67
   --  be therefore created by using routine Name_Enter. The files in question
68
   --  are file names with a prefix directory (i.e., the files not in the
69
   --  current directory). File names without a prefix directory are entered
70
   --  with Name_Find because special values might be attached to the various
71
   --  Info fields of the corresponding name table entry.
72
 
73
   -----------------------
74
   -- Local Subprograms --
75
   -----------------------
76
 
77
   function Append_Suffix_To_File_Name
78
     (Name   : File_Name_Type;
79
      Suffix : String) return File_Name_Type;
80
   --  Appends Suffix to Name and returns the new name
81
 
82
   function OS_Time_To_GNAT_Time (T : OS_Time) return Time_Stamp_Type;
83
   --  Convert OS format time to GNAT format time stamp. If T is Invalid_Time,
84
   --  then returns Empty_Time_Stamp.
85
 
86
   function Executable_Prefix return String_Ptr;
87
   --  Returns the name of the root directory where the executable is stored.
88
   --  The executable must be located in a directory called "bin", or under
89
   --  root/lib/gcc-lib/..., or under root/libexec/gcc/... For example, if
90
   --  executable is stored in directory "/foo/bar/bin", this routine returns
91
   --  "/foo/bar/". Return "" if location is not recognized as described above.
92
 
93
   function Update_Path (Path : String_Ptr) return String_Ptr;
94
   --  Update the specified path to replace the prefix with the location where
95
   --  GNAT is installed. See the file prefix.c in GCC for details.
96
 
97
   procedure Locate_File
98
     (N     : File_Name_Type;
99
      T     : File_Type;
100
      Dir   : Natural;
101
      Name  : String;
102
      Found : out File_Name_Type;
103
      Attr  : access File_Attributes);
104
   --  See if the file N whose name is Name exists in directory Dir. Dir is an
105
   --  index into the Lib_Search_Directories table if T = Library. Otherwise
106
   --  if T = Source, Dir is an index into the Src_Search_Directories table.
107
   --  Returns the File_Name_Type of the full file name if file found, or
108
   --  No_File if not found.
109
   --
110
   --  On exit, Found is set to the file that was found, and Attr to a cache of
111
   --  its attributes (at least those that have been computed so far). Reusing
112
   --  the cache will save some system calls.
113
   --
114
   --  Attr is always reset in this call to Unknown_Attributes, even in case of
115
   --  failure
116
 
117
   procedure Find_File
118
     (N     : File_Name_Type;
119
      T     : File_Type;
120
      Found : out File_Name_Type;
121
      Attr  : access File_Attributes);
122
   --  A version of Find_File that also returns a cache of the file attributes
123
   --  for later reuse
124
 
125
   procedure Smart_Find_File
126
     (N     : File_Name_Type;
127
      T     : File_Type;
128
      Found : out File_Name_Type;
129
      Attr  : out File_Attributes);
130
   --  A version of Smart_Find_File that also returns a cache of the file
131
   --  attributes for later reuse
132
 
133
   function C_String_Length (S : Address) return Integer;
134
   --  Returns length of a C string (zero for a null address)
135
 
136
   function To_Path_String_Access
137
     (Path_Addr : Address;
138
      Path_Len  : Integer) return String_Access;
139
   --  Converts a C String to an Ada String. Are we doing this to avoid withing
140
   --  Interfaces.C.Strings ???
141
   --  Caller must free result.
142
 
143
   function Include_Dir_Default_Prefix return String_Access;
144
   --  Same as exported version, except returns a String_Access
145
 
146
   ------------------------------
147
   -- Other Local Declarations --
148
   ------------------------------
149
 
150
   EOL : constant Character := ASCII.LF;
151
   --  End of line character
152
 
153
   Number_File_Names : Int := 0;
154
   --  Number of file names found on command line and placed in File_Names
155
 
156
   Look_In_Primary_Directory_For_Current_Main : Boolean := False;
157
   --  When this variable is True, Find_File only looks in Primary_Directory
158
   --  for the Current_Main file. This variable is always set to True for the
159
   --  compiler. It is also True for gnatmake, when the source name given on
160
   --  the command line has directory information.
161
 
162
   Current_Full_Source_Name  : File_Name_Type  := No_File;
163
   Current_Full_Source_Stamp : Time_Stamp_Type := Empty_Time_Stamp;
164
   Current_Full_Lib_Name     : File_Name_Type  := No_File;
165
   Current_Full_Lib_Stamp    : Time_Stamp_Type := Empty_Time_Stamp;
166
   Current_Full_Obj_Name     : File_Name_Type  := No_File;
167
   Current_Full_Obj_Stamp    : Time_Stamp_Type := Empty_Time_Stamp;
168
   --  Respectively full name (with directory info) and time stamp of the
169
   --  latest source, library and object files opened by Read_Source_File and
170
   --  Read_Library_Info.
171
 
172
   package File_Name_Chars is new Table.Table (
173
     Table_Component_Type => Character,
174
     Table_Index_Type     => Int,
175
     Table_Low_Bound      => 1,
176
     Table_Initial        => Alloc.File_Name_Chars_Initial,
177
     Table_Increment      => Alloc.File_Name_Chars_Increment,
178
     Table_Name           => "File_Name_Chars");
179
   --  Table to store text to be printed by Dump_Source_File_Names
180
 
181
   The_Include_Dir_Default_Prefix : String_Access := null;
182
   --  Value returned by Include_Dir_Default_Prefix. We don't initialize it
183
   --  here, because that causes an elaboration cycle with Sdefault; we
184
   --  initialize it lazily instead.
185
 
186
   ------------------
187
   -- Search Paths --
188
   ------------------
189
 
190
   Primary_Directory : constant := 0;
191
   --  This is index in the tables created below for the first directory to
192
   --  search in for source or library information files. This is the directory
193
   --  containing the latest main input file (a source file for the compiler or
194
   --  a library file for the binder).
195
 
196
   package Src_Search_Directories is new Table.Table (
197
     Table_Component_Type => String_Ptr,
198
     Table_Index_Type     => Integer,
199
     Table_Low_Bound      => Primary_Directory,
200
     Table_Initial        => 10,
201
     Table_Increment      => 100,
202
     Table_Name           => "Osint.Src_Search_Directories");
203
   --  Table of names of directories in which to search for source (Compiler)
204
   --  files. This table is filled in the order in which the directories are
205
   --  to be searched, and then used in that order.
206
 
207
   package Lib_Search_Directories is new Table.Table (
208
     Table_Component_Type => String_Ptr,
209
     Table_Index_Type     => Integer,
210
     Table_Low_Bound      => Primary_Directory,
211
     Table_Initial        => 10,
212
     Table_Increment      => 100,
213
     Table_Name           => "Osint.Lib_Search_Directories");
214
   --  Table of names of directories in which to search for library (Binder)
215
   --  files. This table is filled in the order in which the directories are
216
   --  to be searched and then used in that order. The reason for having two
217
   --  distinct tables is that we need them both in gnatmake.
218
 
219
   ---------------------
220
   -- File Hash Table --
221
   ---------------------
222
 
223
   --  The file hash table is provided to free the programmer from any
224
   --  efficiency concern when retrieving full file names or time stamps of
225
   --  source files. If the programmer calls Source_File_Data (Cache => True)
226
   --  he is guaranteed that the price to retrieve the full name (i.e. with
227
   --  directory info) or time stamp of the file will be payed only once, the
228
   --  first time the full name is actually searched (or the first time the
229
   --  time stamp is actually retrieved). This is achieved by employing a hash
230
   --  table that stores as a key the File_Name_Type of the file and associates
231
   --  to that File_Name_Type the full file name and time stamp of the file.
232
 
233
   File_Cache_Enabled : Boolean := False;
234
   --  Set to true if you want the enable the file data caching mechanism
235
 
236
   type File_Hash_Num is range 0 .. 1020;
237
 
238
   function File_Hash (F : File_Name_Type) return File_Hash_Num;
239
   --  Compute hash index for use by Simple_HTable
240
 
241
   type File_Info_Cache is record
242
      File : File_Name_Type;
243
      Attr : aliased File_Attributes;
244
   end record;
245
 
246
   No_File_Info_Cache : constant File_Info_Cache :=
247
                          (No_File, Unknown_Attributes);
248
 
249
   package File_Name_Hash_Table is new GNAT.HTable.Simple_HTable (
250
     Header_Num => File_Hash_Num,
251
     Element    => File_Info_Cache,
252
     No_Element => No_File_Info_Cache,
253
     Key        => File_Name_Type,
254
     Hash       => File_Hash,
255
     Equal      => "=");
256
 
257
   function Smart_Find_File
258
     (N : File_Name_Type;
259
      T : File_Type) return File_Name_Type;
260
   --  Exactly like Find_File except that if File_Cache_Enabled is True this
261
   --  routine looks first in the hash table to see if the full name of the
262
   --  file is already available.
263
 
264
   function Smart_File_Stamp
265
     (N : File_Name_Type;
266
      T : File_Type) return Time_Stamp_Type;
267
   --  Takes the same parameter as the routine above (N is a file name without
268
   --  any prefix directory information) and behaves like File_Stamp except
269
   --  that if File_Cache_Enabled is True this routine looks first in the hash
270
   --  table to see if the file stamp of the file is already available.
271
 
272
   -----------------------------
273
   -- Add_Default_Search_Dirs --
274
   -----------------------------
275
 
276
   procedure Add_Default_Search_Dirs is
277
      Search_Dir     : String_Access;
278
      Search_Path    : String_Access;
279
      Path_File_Name : String_Access;
280
 
281
      procedure Add_Search_Dir
282
        (Search_Dir            : String;
283
         Additional_Source_Dir : Boolean);
284
      procedure Add_Search_Dir
285
        (Search_Dir            : String_Access;
286
         Additional_Source_Dir : Boolean);
287
      --  Add a source search dir or a library search dir, depending on the
288
      --  value of Additional_Source_Dir.
289
 
290
      procedure Get_Dirs_From_File (Additional_Source_Dir : Boolean);
291
      --  Open a path file and read the directory to search, one per line
292
 
293
      function Get_Libraries_From_Registry return String_Ptr;
294
      --  On Windows systems, get the list of installed standard libraries
295
      --  from the registry key:
296
      --
297
      --  HKEY_LOCAL_MACHINE\SOFTWARE\Ada Core Technologies\
298
      --                             GNAT\Standard Libraries
299
      --  Return an empty string on other systems.
300
      --
301
      --  Note that this is an undocumented legacy feature, and that it
302
      --  works only when using the default runtime library (i.e. no --RTS=
303
      --  command line switch).
304
 
305
      --------------------
306
      -- Add_Search_Dir --
307
      --------------------
308
 
309
      procedure Add_Search_Dir
310
        (Search_Dir            : String;
311
         Additional_Source_Dir : Boolean)
312
      is
313
      begin
314
         if Additional_Source_Dir then
315
            Add_Src_Search_Dir (Search_Dir);
316
         else
317
            Add_Lib_Search_Dir (Search_Dir);
318
         end if;
319
      end Add_Search_Dir;
320
 
321
      procedure Add_Search_Dir
322
        (Search_Dir            : String_Access;
323
         Additional_Source_Dir : Boolean)
324
      is
325
      begin
326
         if Additional_Source_Dir then
327
            Add_Src_Search_Dir (Search_Dir.all);
328
         else
329
            Add_Lib_Search_Dir (Search_Dir.all);
330
         end if;
331
      end Add_Search_Dir;
332
 
333
      ------------------------
334
      -- Get_Dirs_From_File --
335
      ------------------------
336
 
337
      procedure Get_Dirs_From_File (Additional_Source_Dir : Boolean) is
338
         File_FD    : File_Descriptor;
339
         Buffer     : constant String := Path_File_Name.all & ASCII.NUL;
340
         Len        : Natural;
341
         Actual_Len : Natural;
342
         S          : String_Access;
343
         Curr       : Natural;
344
         First      : Natural;
345
         Ch         : Character;
346
 
347
         Status : Boolean;
348
         pragma Warnings (Off, Status);
349
         --  For the call to Close where status is ignored
350
 
351
      begin
352
         File_FD := Open_Read (Buffer'Address, Binary);
353
 
354
         --  If we cannot open the file, we ignore it, we don't fail
355
 
356
         if File_FD = Invalid_FD then
357
            return;
358
         end if;
359
 
360
         Len := Integer (File_Length (File_FD));
361
 
362
         S := new String (1 .. Len);
363
 
364
         --  Read the file. Note that the loop is not necessary since the
365
         --  whole file is read at once except on VMS.
366
 
367
         Curr := 1;
368
         Actual_Len := Len;
369
         while Curr <= Len and then Actual_Len /= 0 loop
370
            Actual_Len := Read (File_FD, S (Curr)'Address, Len);
371
            Curr := Curr + Actual_Len;
372
         end loop;
373
 
374
         --  We are done with the file, so we close it (ignore any error on
375
         --  the close, since we have successfully read the file).
376
 
377
         Close (File_FD, Status);
378
 
379
         --  Now, we read line by line
380
 
381
         First := 1;
382
         Curr := 0;
383
         while Curr < Len loop
384
            Ch := S (Curr + 1);
385
 
386
            if Ch = ASCII.CR or else Ch = ASCII.LF
387
              or else Ch = ASCII.FF or else Ch = ASCII.VT
388
            then
389
               if First <= Curr then
390
                  Add_Search_Dir (S (First .. Curr), Additional_Source_Dir);
391
               end if;
392
 
393
               First := Curr + 2;
394
            end if;
395
 
396
            Curr := Curr + 1;
397
         end loop;
398
 
399
         --  Last line is a special case, if the file does not end with
400
         --  an end of line mark.
401
 
402
         if First <= S'Last then
403
            Add_Search_Dir (S (First .. S'Last), Additional_Source_Dir);
404
         end if;
405
      end Get_Dirs_From_File;
406
 
407
      ---------------------------------
408
      -- Get_Libraries_From_Registry --
409
      ---------------------------------
410
 
411
      function Get_Libraries_From_Registry return String_Ptr is
412
         function C_Get_Libraries_From_Registry return Address;
413
         pragma Import (C, C_Get_Libraries_From_Registry,
414
                        "__gnat_get_libraries_from_registry");
415
 
416
         function Strlen (Str : Address) return Integer;
417
         pragma Import (C, Strlen, "strlen");
418
 
419
         procedure Strncpy (X : Address; Y : Address; Length : Integer);
420
         pragma Import (C, Strncpy, "strncpy");
421
 
422
         procedure C_Free (Str : Address);
423
         pragma Import (C, C_Free, "free");
424
 
425
         Result_Ptr    : Address;
426
         Result_Length : Integer;
427
         Out_String    : String_Ptr;
428
 
429
      begin
430
         Result_Ptr := C_Get_Libraries_From_Registry;
431
         Result_Length := Strlen (Result_Ptr);
432
 
433
         Out_String := new String (1 .. Result_Length);
434
         Strncpy (Out_String.all'Address, Result_Ptr, Result_Length);
435
 
436
         C_Free (Result_Ptr);
437
 
438
         return Out_String;
439
      end Get_Libraries_From_Registry;
440
 
441
   --  Start of processing for Add_Default_Search_Dirs
442
 
443
   begin
444
      --  After the locations specified on the command line, the next places
445
      --  to look for files are the directories specified by the appropriate
446
      --  environment variable. Get this value, extract the directory names
447
      --  and store in the tables.
448
 
449
      --  Check for eventual project path file env vars
450
 
451
      Path_File_Name := Getenv (Project_Include_Path_File);
452
 
453
      if Path_File_Name'Length > 0 then
454
         Get_Dirs_From_File (Additional_Source_Dir => True);
455
      end if;
456
 
457
      Path_File_Name := Getenv (Project_Objects_Path_File);
458
 
459
      if Path_File_Name'Length > 0 then
460
         Get_Dirs_From_File (Additional_Source_Dir => False);
461
      end if;
462
 
463
      --  On VMS, don't expand the logical name (e.g. environment variable),
464
      --  just put it into Unix (e.g. canonical) format. System services
465
      --  will handle the expansion as part of the file processing.
466
 
467
      for Additional_Source_Dir in False .. True loop
468
         if Additional_Source_Dir then
469
            Search_Path := Getenv (Ada_Include_Path);
470
 
471
            if Search_Path'Length > 0 then
472
               if Hostparm.OpenVMS then
473
                  Search_Path := To_Canonical_Path_Spec ("ADA_INCLUDE_PATH:");
474
               else
475
                  Search_Path := To_Canonical_Path_Spec (Search_Path.all);
476
               end if;
477
            end if;
478
 
479
         else
480
            Search_Path := Getenv (Ada_Objects_Path);
481
 
482
            if Search_Path'Length > 0 then
483
               if Hostparm.OpenVMS then
484
                  Search_Path := To_Canonical_Path_Spec ("ADA_OBJECTS_PATH:");
485
               else
486
                  Search_Path := To_Canonical_Path_Spec (Search_Path.all);
487
               end if;
488
            end if;
489
         end if;
490
 
491
         Get_Next_Dir_In_Path_Init (Search_Path);
492
         loop
493
            Search_Dir := Get_Next_Dir_In_Path (Search_Path);
494
            exit when Search_Dir = null;
495
            Add_Search_Dir (Search_Dir, Additional_Source_Dir);
496
         end loop;
497
      end loop;
498
 
499
      --  For the compiler, if --RTS= was specified, add the runtime
500
      --  directories.
501
 
502
      if RTS_Src_Path_Name /= null
503
        and then RTS_Lib_Path_Name /= null
504
      then
505
         Add_Search_Dirs (RTS_Src_Path_Name, Include);
506
         Add_Search_Dirs (RTS_Lib_Path_Name, Objects);
507
 
508
      else
509
         if not Opt.No_Stdinc then
510
 
511
            --  For WIN32 systems, look for any system libraries defined in
512
            --  the registry. These are added to both source and object
513
            --  directories.
514
 
515
            Search_Path := String_Access (Get_Libraries_From_Registry);
516
 
517
            Get_Next_Dir_In_Path_Init (Search_Path);
518
            loop
519
               Search_Dir := Get_Next_Dir_In_Path (Search_Path);
520
               exit when Search_Dir = null;
521
               Add_Search_Dir (Search_Dir, False);
522
               Add_Search_Dir (Search_Dir, True);
523
            end loop;
524
 
525
            --  The last place to look are the defaults
526
 
527
            Search_Path :=
528
              Read_Default_Search_Dirs
529
                (String_Access (Update_Path (Search_Dir_Prefix)),
530
                 Include_Search_File,
531
                 String_Access (Update_Path (Include_Dir_Default_Name)));
532
 
533
            Get_Next_Dir_In_Path_Init (Search_Path);
534
            loop
535
               Search_Dir := Get_Next_Dir_In_Path (Search_Path);
536
               exit when Search_Dir = null;
537
               Add_Search_Dir (Search_Dir, True);
538
            end loop;
539
         end if;
540
 
541
         if not Opt.No_Stdlib and not Opt.RTS_Switch then
542
            Search_Path :=
543
              Read_Default_Search_Dirs
544
                (String_Access (Update_Path (Search_Dir_Prefix)),
545
                 Objects_Search_File,
546
                 String_Access (Update_Path (Object_Dir_Default_Name)));
547
 
548
            Get_Next_Dir_In_Path_Init (Search_Path);
549
            loop
550
               Search_Dir := Get_Next_Dir_In_Path (Search_Path);
551
               exit when Search_Dir = null;
552
               Add_Search_Dir (Search_Dir, False);
553
            end loop;
554
         end if;
555
      end if;
556
   end Add_Default_Search_Dirs;
557
 
558
   --------------
559
   -- Add_File --
560
   --------------
561
 
562
   procedure Add_File (File_Name : String; Index : Int := No_Index) is
563
   begin
564
      Number_File_Names := Number_File_Names + 1;
565
 
566
      --  As Add_File may be called for mains specified inside a project file,
567
      --  File_Names may be too short and needs to be extended.
568
 
569
      if Number_File_Names > File_Names'Last then
570
         File_Names := new File_Name_Array'(File_Names.all & File_Names.all);
571
         File_Indexes :=
572
           new File_Index_Array'(File_Indexes.all & File_Indexes.all);
573
      end if;
574
 
575
      File_Names   (Number_File_Names) := new String'(File_Name);
576
      File_Indexes (Number_File_Names) := Index;
577
   end Add_File;
578
 
579
   ------------------------
580
   -- Add_Lib_Search_Dir --
581
   ------------------------
582
 
583
   procedure Add_Lib_Search_Dir (Dir : String) is
584
   begin
585
      if Dir'Length = 0 then
586
         Fail ("missing library directory name");
587
      end if;
588
 
589
      declare
590
         Norm : String_Ptr := Normalize_Directory_Name (Dir);
591
 
592
      begin
593
         --  Do nothing if the directory is already in the list. This saves
594
         --  system calls and avoid unneeded work
595
 
596
         for D in Lib_Search_Directories.First ..
597
                  Lib_Search_Directories.Last
598
         loop
599
            if Lib_Search_Directories.Table (D).all = Norm.all then
600
               Free (Norm);
601
               return;
602
            end if;
603
         end loop;
604
 
605
         Lib_Search_Directories.Increment_Last;
606
         Lib_Search_Directories.Table (Lib_Search_Directories.Last) := Norm;
607
      end;
608
   end Add_Lib_Search_Dir;
609
 
610
   ---------------------
611
   -- Add_Search_Dirs --
612
   ---------------------
613
 
614
   procedure Add_Search_Dirs
615
     (Search_Path : String_Ptr;
616
      Path_Type   : Search_File_Type)
617
   is
618
      Current_Search_Path : String_Access;
619
 
620
   begin
621
      Get_Next_Dir_In_Path_Init (String_Access (Search_Path));
622
      loop
623
         Current_Search_Path :=
624
           Get_Next_Dir_In_Path (String_Access (Search_Path));
625
         exit when Current_Search_Path = null;
626
 
627
         if Path_Type = Include then
628
            Add_Src_Search_Dir (Current_Search_Path.all);
629
         else
630
            Add_Lib_Search_Dir (Current_Search_Path.all);
631
         end if;
632
      end loop;
633
   end Add_Search_Dirs;
634
 
635
   ------------------------
636
   -- Add_Src_Search_Dir --
637
   ------------------------
638
 
639
   procedure Add_Src_Search_Dir (Dir : String) is
640
   begin
641
      if Dir'Length = 0 then
642
         Fail ("missing source directory name");
643
      end if;
644
 
645
      Src_Search_Directories.Increment_Last;
646
      Src_Search_Directories.Table (Src_Search_Directories.Last) :=
647
        Normalize_Directory_Name (Dir);
648
   end Add_Src_Search_Dir;
649
 
650
   --------------------------------
651
   -- Append_Suffix_To_File_Name --
652
   --------------------------------
653
 
654
   function Append_Suffix_To_File_Name
655
     (Name   : File_Name_Type;
656
      Suffix : String) return File_Name_Type
657
   is
658
   begin
659
      Get_Name_String (Name);
660
      Name_Buffer (Name_Len + 1 .. Name_Len + Suffix'Length) := Suffix;
661
      Name_Len := Name_Len + Suffix'Length;
662
      return Name_Find;
663
   end Append_Suffix_To_File_Name;
664
 
665
   ---------------------
666
   -- C_String_Length --
667
   ---------------------
668
 
669
   function C_String_Length (S : Address) return Integer is
670
      function Strlen (S : Address) return Integer;
671
      pragma Import (C, Strlen, "strlen");
672
   begin
673
      if S = Null_Address then
674
         return 0;
675
      else
676
         return Strlen (S);
677
      end if;
678
   end C_String_Length;
679
 
680
   ------------------------------
681
   -- Canonical_Case_File_Name --
682
   ------------------------------
683
 
684
   --  For now, we only deal with the case of a-z. Eventually we should
685
   --  worry about other Latin-1 letters on systems that support this ???
686
 
687
   procedure Canonical_Case_File_Name (S : in out String) is
688
   begin
689
      if not File_Names_Case_Sensitive then
690
         for J in S'Range loop
691
            if S (J) in 'A' .. 'Z' then
692
               S (J) := Character'Val (
693
                          Character'Pos (S (J)) +
694
                          Character'Pos ('a')   -
695
                          Character'Pos ('A'));
696
            end if;
697
         end loop;
698
      end if;
699
   end Canonical_Case_File_Name;
700
 
701
   ---------------------------
702
   -- Create_File_And_Check --
703
   ---------------------------
704
 
705
   procedure Create_File_And_Check
706
     (Fdesc : out File_Descriptor;
707
      Fmode : Mode)
708
   is
709
   begin
710
      Output_File_Name := Name_Enter;
711
      Fdesc := Create_File (Name_Buffer'Address, Fmode);
712
 
713
      if Fdesc = Invalid_FD then
714
         Fail ("Cannot create: " & Name_Buffer (1 .. Name_Len));
715
      end if;
716
   end Create_File_And_Check;
717
 
718
   ------------------------
719
   -- Current_File_Index --
720
   ------------------------
721
 
722
   function Current_File_Index return Int is
723
   begin
724
      return File_Indexes (Current_File_Name_Index);
725
   end Current_File_Index;
726
 
727
   --------------------------------
728
   -- Current_Library_File_Stamp --
729
   --------------------------------
730
 
731
   function Current_Library_File_Stamp return Time_Stamp_Type is
732
   begin
733
      return Current_Full_Lib_Stamp;
734
   end Current_Library_File_Stamp;
735
 
736
   -------------------------------
737
   -- Current_Object_File_Stamp --
738
   -------------------------------
739
 
740
   function Current_Object_File_Stamp return Time_Stamp_Type is
741
   begin
742
      return Current_Full_Obj_Stamp;
743
   end Current_Object_File_Stamp;
744
 
745
   -------------------------------
746
   -- Current_Source_File_Stamp --
747
   -------------------------------
748
 
749
   function Current_Source_File_Stamp return Time_Stamp_Type is
750
   begin
751
      return Current_Full_Source_Stamp;
752
   end Current_Source_File_Stamp;
753
 
754
   ----------------------------
755
   -- Dir_In_Obj_Search_Path --
756
   ----------------------------
757
 
758
   function Dir_In_Obj_Search_Path (Position : Natural) return String_Ptr is
759
   begin
760
      if Opt.Look_In_Primary_Dir then
761
         return
762
           Lib_Search_Directories.Table (Primary_Directory + Position - 1);
763
      else
764
         return Lib_Search_Directories.Table (Primary_Directory + Position);
765
      end if;
766
   end Dir_In_Obj_Search_Path;
767
 
768
   ----------------------------
769
   -- Dir_In_Src_Search_Path --
770
   ----------------------------
771
 
772
   function Dir_In_Src_Search_Path (Position : Natural) return String_Ptr is
773
   begin
774
      if Opt.Look_In_Primary_Dir then
775
         return
776
           Src_Search_Directories.Table (Primary_Directory + Position - 1);
777
      else
778
         return Src_Search_Directories.Table (Primary_Directory + Position);
779
      end if;
780
   end Dir_In_Src_Search_Path;
781
 
782
   ----------------------------
783
   -- Dump_Source_File_Names --
784
   ----------------------------
785
 
786
   procedure Dump_Source_File_Names is
787
      subtype Rng is Int range File_Name_Chars.First .. File_Name_Chars.Last;
788
   begin
789
      Write_Str (String (File_Name_Chars.Table (Rng)));
790
   end Dump_Source_File_Names;
791
 
792
   ---------------------
793
   -- Executable_Name --
794
   ---------------------
795
 
796
   function Executable_Name
797
     (Name              : File_Name_Type;
798
      Only_If_No_Suffix : Boolean := False) return File_Name_Type
799
   is
800
      Exec_Suffix : String_Access;
801
      Add_Suffix  : Boolean;
802
 
803
   begin
804
      if Name = No_File then
805
         return No_File;
806
      end if;
807
 
808
      if Executable_Extension_On_Target = No_Name then
809
         Exec_Suffix := Get_Target_Executable_Suffix;
810
      else
811
         Get_Name_String (Executable_Extension_On_Target);
812
         Exec_Suffix := new String'(Name_Buffer (1 .. Name_Len));
813
      end if;
814
 
815
      if Exec_Suffix'Length /= 0 then
816
         Get_Name_String (Name);
817
 
818
         Add_Suffix := True;
819
         if Only_If_No_Suffix then
820
            for J in reverse 1 .. Name_Len loop
821
               if Name_Buffer (J) = '.' then
822
                  Add_Suffix := False;
823
                  exit;
824
 
825
               elsif Name_Buffer (J) = '/' or else
826
                     Name_Buffer (J) = Directory_Separator
827
               then
828
                  exit;
829
               end if;
830
            end loop;
831
         end if;
832
 
833
         if Add_Suffix then
834
            declare
835
               Buffer : String := Name_Buffer (1 .. Name_Len);
836
 
837
            begin
838
               --  Get the file name in canonical case to accept as is names
839
               --  ending with ".EXE" on VMS and Windows.
840
 
841
               Canonical_Case_File_Name (Buffer);
842
 
843
               --  If Executable does not end with the executable suffix, add
844
               --  it.
845
 
846
               if Buffer'Length <= Exec_Suffix'Length
847
                 or else
848
                   Buffer (Buffer'Last - Exec_Suffix'Length + 1 .. Buffer'Last)
849
                     /= Exec_Suffix.all
850
               then
851
                  Name_Buffer
852
                    (Name_Len + 1 .. Name_Len + Exec_Suffix'Length) :=
853
                      Exec_Suffix.all;
854
                  Name_Len := Name_Len + Exec_Suffix'Length;
855
                  Free (Exec_Suffix);
856
                  return Name_Find;
857
               end if;
858
            end;
859
         end if;
860
      end if;
861
 
862
      Free (Exec_Suffix);
863
      return Name;
864
   end Executable_Name;
865
 
866
   function Executable_Name
867
     (Name              : String;
868
      Only_If_No_Suffix : Boolean := False) return String
869
   is
870
      Exec_Suffix    : String_Access;
871
      Add_Suffix     : Boolean;
872
      Canonical_Name : String := Name;
873
 
874
   begin
875
      if Executable_Extension_On_Target = No_Name then
876
         Exec_Suffix := Get_Target_Executable_Suffix;
877
      else
878
         Get_Name_String (Executable_Extension_On_Target);
879
         Exec_Suffix := new String'(Name_Buffer (1 .. Name_Len));
880
      end if;
881
 
882
      if Exec_Suffix'Length = 0 then
883
         Free (Exec_Suffix);
884
         return Name;
885
 
886
      else
887
         declare
888
            Suffix : constant String := Exec_Suffix.all;
889
 
890
         begin
891
            Free (Exec_Suffix);
892
            Canonical_Case_File_Name (Canonical_Name);
893
 
894
            Add_Suffix := True;
895
            if Only_If_No_Suffix then
896
               for J in reverse Canonical_Name'Range loop
897
                  if Canonical_Name (J) = '.' then
898
                     Add_Suffix := False;
899
                     exit;
900
 
901
                  elsif Canonical_Name (J) = '/' or else
902
                        Canonical_Name (J) = Directory_Separator
903
                  then
904
                     exit;
905
                  end if;
906
               end loop;
907
            end if;
908
 
909
            if Add_Suffix and then
910
              (Canonical_Name'Length <= Suffix'Length
911
               or else Canonical_Name (Canonical_Name'Last - Suffix'Length + 1
912
                                       .. Canonical_Name'Last) /= Suffix)
913
            then
914
               declare
915
                  Result : String (1 .. Name'Length + Suffix'Length);
916
               begin
917
                  Result (1 .. Name'Length) := Name;
918
                  Result (Name'Length + 1 .. Result'Last) := Suffix;
919
                  return Result;
920
               end;
921
            else
922
               return Name;
923
            end if;
924
         end;
925
      end if;
926
   end Executable_Name;
927
 
928
   -----------------------
929
   -- Executable_Prefix --
930
   -----------------------
931
 
932
   function Executable_Prefix return String_Ptr is
933
 
934
      function Get_Install_Dir (Exec : String) return String_Ptr;
935
      --  S is the executable name preceded by the absolute or relative
936
      --  path, e.g. "c:\usr\bin\gcc.exe" or "..\bin\gcc".
937
 
938
      ---------------------
939
      -- Get_Install_Dir --
940
      ---------------------
941
 
942
      function Get_Install_Dir (Exec : String) return String_Ptr is
943
         Full_Path : constant String := Normalize_Pathname (Exec);
944
         --  Use the full path, so that we find "lib" or "bin", even when
945
         --  the tool has been invoked with a relative path, as in
946
         --  "./gnatls -v" invoked in the GNAT bin directory.
947
 
948
      begin
949
         for J in reverse Full_Path'Range loop
950
            if Is_Directory_Separator (Full_Path (J)) then
951
               if J < Full_Path'Last - 5 then
952
                  if (To_Lower (Full_Path (J + 1)) = 'l'
953
                      and then To_Lower (Full_Path (J + 2)) = 'i'
954
                      and then To_Lower (Full_Path (J + 3)) = 'b')
955
                    or else
956
                      (To_Lower (Full_Path (J + 1)) = 'b'
957
                       and then To_Lower (Full_Path (J + 2)) = 'i'
958
                       and then To_Lower (Full_Path (J + 3)) = 'n')
959
                  then
960
                     return new String'(Full_Path (Full_Path'First .. J));
961
                  end if;
962
               end if;
963
            end if;
964
         end loop;
965
 
966
         return new String'("");
967
      end Get_Install_Dir;
968
 
969
   --  Start of processing for Executable_Prefix
970
 
971
   begin
972
      if Exec_Name = null then
973
         Exec_Name := new String (1 .. Len_Arg (0));
974
         Osint.Fill_Arg (Exec_Name (1)'Address, 0);
975
      end if;
976
 
977
      --  First determine if a path prefix was placed in front of the
978
      --  executable name.
979
 
980
      for J in reverse Exec_Name'Range loop
981
         if Is_Directory_Separator (Exec_Name (J)) then
982
            return Get_Install_Dir (Exec_Name.all);
983
         end if;
984
      end loop;
985
 
986
      --  If we come here, the user has typed the executable name with no
987
      --  directory prefix.
988
 
989
      return Get_Install_Dir (Locate_Exec_On_Path (Exec_Name.all).all);
990
   end Executable_Prefix;
991
 
992
   ------------------
993
   -- Exit_Program --
994
   ------------------
995
 
996
   procedure Exit_Program (Exit_Code : Exit_Code_Type) is
997
   begin
998
      --  The program will exit with the following status:
999
 
1000
      --    0 if the object file has been generated (with or without warnings)
1001
      --    1 if recompilation was not needed (smart recompilation)
1002
      --    2 if gnat1 has been killed by a signal (detected by GCC)
1003
      --    4 for a fatal error
1004
      --    5 if there were errors
1005
      --    6 if no code has been generated (spec)
1006
 
1007
      --  Note that exit code 3 is not used and must not be used as this is
1008
      --  the code returned by a program aborted via C abort() routine on
1009
      --  Windows. GCC checks for that case and thinks that the child process
1010
      --  has been aborted. This code (exit code 3) used to be the code used
1011
      --  for E_No_Code, but E_No_Code was changed to 6 for this reason.
1012
 
1013
      case Exit_Code is
1014
         when E_Success    => OS_Exit (0);
1015
         when E_Warnings   => OS_Exit (0);
1016
         when E_No_Compile => OS_Exit (1);
1017
         when E_Fatal      => OS_Exit (4);
1018
         when E_Errors     => OS_Exit (5);
1019
         when E_No_Code    => OS_Exit (6);
1020
         when E_Abort      => OS_Abort;
1021
      end case;
1022
   end Exit_Program;
1023
 
1024
   ----------
1025
   -- Fail --
1026
   ----------
1027
 
1028
   procedure Fail (S : String) is
1029
   begin
1030
      --  We use Output in case there is a special output set up.
1031
      --  In this case Set_Standard_Error will have no immediate effect.
1032
 
1033
      Set_Standard_Error;
1034
      Osint.Write_Program_Name;
1035
      Write_Str (": ");
1036
      Write_Str (S);
1037
      Write_Eol;
1038
 
1039
      Exit_Program (E_Fatal);
1040
   end Fail;
1041
 
1042
   ---------------
1043
   -- File_Hash --
1044
   ---------------
1045
 
1046
   function File_Hash (F : File_Name_Type) return File_Hash_Num is
1047
   begin
1048
      return File_Hash_Num (Int (F) rem File_Hash_Num'Range_Length);
1049
   end File_Hash;
1050
 
1051
   -----------------
1052
   -- File_Length --
1053
   -----------------
1054
 
1055
   function File_Length
1056
     (Name : C_File_Name;
1057
      Attr : access File_Attributes) return Long_Integer
1058
   is
1059
      function Internal
1060
        (F : Integer;
1061
         N : C_File_Name;
1062
         A : System.Address) return Long_Integer;
1063
      pragma Import (C, Internal, "__gnat_file_length_attr");
1064
   begin
1065
      return Internal (-1, Name, Attr.all'Address);
1066
   end File_Length;
1067
 
1068
   ---------------------
1069
   -- File_Time_Stamp --
1070
   ---------------------
1071
 
1072
   function File_Time_Stamp
1073
     (Name : C_File_Name;
1074
      Attr : access File_Attributes) return OS_Time
1075
   is
1076
      function Internal (N : C_File_Name; A : System.Address) return OS_Time;
1077
      pragma Import (C, Internal, "__gnat_file_time_name_attr");
1078
   begin
1079
      return Internal (Name, Attr.all'Address);
1080
   end File_Time_Stamp;
1081
 
1082
   function File_Time_Stamp
1083
     (Name : Path_Name_Type;
1084
      Attr : access File_Attributes) return Time_Stamp_Type
1085
   is
1086
   begin
1087
      if Name = No_Path then
1088
         return Empty_Time_Stamp;
1089
      end if;
1090
 
1091
      Get_Name_String (Name);
1092
      Name_Buffer (Name_Len + 1) := ASCII.NUL;
1093
      return OS_Time_To_GNAT_Time
1094
               (File_Time_Stamp (Name_Buffer'Address, Attr));
1095
   end File_Time_Stamp;
1096
 
1097
   ----------------
1098
   -- File_Stamp --
1099
   ----------------
1100
 
1101
   function File_Stamp (Name : File_Name_Type) return Time_Stamp_Type is
1102
   begin
1103
      if Name = No_File then
1104
         return Empty_Time_Stamp;
1105
      end if;
1106
 
1107
      Get_Name_String (Name);
1108
 
1109
      --  File_Time_Stamp will always return Invalid_Time if the file does
1110
      --  not exist, and OS_Time_To_GNAT_Time will convert this value to
1111
      --  Empty_Time_Stamp. Therefore we do not need to first test whether
1112
      --  the file actually exists, which saves a system call.
1113
 
1114
      return OS_Time_To_GNAT_Time
1115
               (File_Time_Stamp (Name_Buffer (1 .. Name_Len)));
1116
   end File_Stamp;
1117
 
1118
   function File_Stamp (Name : Path_Name_Type) return Time_Stamp_Type is
1119
   begin
1120
      return File_Stamp (File_Name_Type (Name));
1121
   end File_Stamp;
1122
 
1123
   ---------------
1124
   -- Find_File --
1125
   ---------------
1126
 
1127
   function Find_File
1128
     (N : File_Name_Type;
1129
      T : File_Type) return File_Name_Type
1130
   is
1131
      Attr  : aliased File_Attributes;
1132
      Found : File_Name_Type;
1133
   begin
1134
      Find_File (N, T, Found, Attr'Access);
1135
      return Found;
1136
   end Find_File;
1137
 
1138
   ---------------
1139
   -- Find_File --
1140
   ---------------
1141
 
1142
   procedure Find_File
1143
     (N     : File_Name_Type;
1144
      T     : File_Type;
1145
      Found : out File_Name_Type;
1146
      Attr  : access File_Attributes) is
1147
   begin
1148
      Get_Name_String (N);
1149
 
1150
      declare
1151
         File_Name : String renames Name_Buffer (1 .. Name_Len);
1152
         File      : File_Name_Type := No_File;
1153
         Last_Dir  : Natural;
1154
 
1155
      begin
1156
         --  If we are looking for a config file, look only in the current
1157
         --  directory, i.e. return input argument unchanged. Also look only in
1158
         --  the curren directory if we are looking for a .dg file (happens in
1159
         --  -gnatD mode).
1160
 
1161
         if T = Config
1162
           or else (Debug_Generated_Code
1163
                      and then Name_Len > 3
1164
                      and then
1165
                      (Name_Buffer (Name_Len - 2 .. Name_Len) = ".dg"
1166
                       or else
1167
                       (Hostparm.OpenVMS and then
1168
                        Name_Buffer (Name_Len - 2 .. Name_Len) = "_dg")))
1169
         then
1170
            Found := N;
1171
            Attr.all  := Unknown_Attributes;
1172
            return;
1173
 
1174
         --  If we are trying to find the current main file just look in the
1175
         --  directory where the user said it was.
1176
 
1177
         elsif Look_In_Primary_Directory_For_Current_Main
1178
           and then Current_Main = N
1179
         then
1180
            Locate_File (N, T, Primary_Directory, File_Name, Found, Attr);
1181
            return;
1182
 
1183
         --  Otherwise do standard search for source file
1184
 
1185
         else
1186
            --  Check the mapping of this file name
1187
 
1188
            File := Mapped_Path_Name (N);
1189
 
1190
            --  If the file name is mapped to a path name, return the
1191
            --  corresponding path name
1192
 
1193
            if File /= No_File then
1194
 
1195
               --  For locally removed file, Error_Name is returned; then
1196
               --  return No_File, indicating the file is not a source.
1197
 
1198
               if File = Error_File_Name then
1199
                  Found := No_File;
1200
               else
1201
                  Found := File;
1202
               end if;
1203
 
1204
               Attr.all := Unknown_Attributes;
1205
               return;
1206
            end if;
1207
 
1208
            --  First place to look is in the primary directory (i.e. the same
1209
            --  directory as the source) unless this has been disabled with -I-
1210
 
1211
            if Opt.Look_In_Primary_Dir then
1212
               Locate_File (N, T, Primary_Directory, File_Name, Found, Attr);
1213
 
1214
               if Found /= No_File then
1215
                  return;
1216
               end if;
1217
            end if;
1218
 
1219
            --  Finally look in directories specified with switches -I/-aI/-aO
1220
 
1221
            if T = Library then
1222
               Last_Dir := Lib_Search_Directories.Last;
1223
            else
1224
               Last_Dir := Src_Search_Directories.Last;
1225
            end if;
1226
 
1227
            for D in Primary_Directory + 1 .. Last_Dir loop
1228
               Locate_File (N, T, D, File_Name, Found, Attr);
1229
 
1230
               if Found /= No_File then
1231
                  return;
1232
               end if;
1233
            end loop;
1234
 
1235
            Attr.all := Unknown_Attributes;
1236
            Found := No_File;
1237
         end if;
1238
      end;
1239
   end Find_File;
1240
 
1241
   -----------------------
1242
   -- Find_Program_Name --
1243
   -----------------------
1244
 
1245
   procedure Find_Program_Name is
1246
      Command_Name : String (1 .. Len_Arg (0));
1247
      Cindex1      : Integer := Command_Name'First;
1248
      Cindex2      : Integer := Command_Name'Last;
1249
 
1250
   begin
1251
      Fill_Arg (Command_Name'Address, 0);
1252
 
1253
      if Command_Name = "" then
1254
         Name_Len := 0;
1255
         return;
1256
      end if;
1257
 
1258
      --  The program name might be specified by a full path name. However,
1259
      --  we don't want to print that all out in an error message, so the
1260
      --  path might need to be stripped away.
1261
 
1262
      for J in reverse Cindex1 .. Cindex2 loop
1263
         if Is_Directory_Separator (Command_Name (J)) then
1264
            Cindex1 := J + 1;
1265
            exit;
1266
         end if;
1267
      end loop;
1268
 
1269
      --  Command_Name(Cindex1 .. Cindex2) is now the equivalent of the
1270
      --  POSIX command "basename argv[0]"
1271
 
1272
      --  Strip off any versioning information such as found on VMS.
1273
      --  This would take the form of TOOL.exe followed by a ";" or "."
1274
      --  and a sequence of one or more numbers.
1275
 
1276
      if Command_Name (Cindex2) in '0' .. '9' then
1277
         for J in reverse Cindex1 .. Cindex2 loop
1278
            if Command_Name (J) = '.' or else Command_Name (J) = ';' then
1279
               Cindex2 := J - 1;
1280
               exit;
1281
            end if;
1282
 
1283
            exit when Command_Name (J) not in '0' .. '9';
1284
         end loop;
1285
      end if;
1286
 
1287
      --  Strip off any executable extension (usually nothing or .exe)
1288
      --  but formally reported by autoconf in the variable EXEEXT
1289
 
1290
      if Cindex2 - Cindex1 >= 4 then
1291
         if To_Lower (Command_Name (Cindex2 - 3)) = '.'
1292
            and then To_Lower (Command_Name (Cindex2 - 2)) = 'e'
1293
            and then To_Lower (Command_Name (Cindex2 - 1)) = 'x'
1294
            and then To_Lower (Command_Name (Cindex2)) = 'e'
1295
         then
1296
            Cindex2 := Cindex2 - 4;
1297
         end if;
1298
      end if;
1299
 
1300
      Name_Len := Cindex2 - Cindex1 + 1;
1301
      Name_Buffer (1 .. Name_Len) := Command_Name (Cindex1 .. Cindex2);
1302
   end Find_Program_Name;
1303
 
1304
   ------------------------
1305
   -- Full_Lib_File_Name --
1306
   ------------------------
1307
 
1308
   procedure Full_Lib_File_Name
1309
     (N        : File_Name_Type;
1310
      Lib_File : out File_Name_Type;
1311
      Attr     : out File_Attributes)
1312
   is
1313
      A : aliased File_Attributes;
1314
   begin
1315
      --  ??? seems we could use Smart_Find_File here
1316
      Find_File (N, Library, Lib_File, A'Access);
1317
      Attr := A;
1318
   end Full_Lib_File_Name;
1319
 
1320
   ------------------------
1321
   -- Full_Lib_File_Name --
1322
   ------------------------
1323
 
1324
   function Full_Lib_File_Name (N : File_Name_Type) return File_Name_Type is
1325
      Attr : File_Attributes;
1326
      File : File_Name_Type;
1327
   begin
1328
      Full_Lib_File_Name (N, File, Attr);
1329
      return File;
1330
   end Full_Lib_File_Name;
1331
 
1332
   ----------------------------
1333
   -- Full_Library_Info_Name --
1334
   ----------------------------
1335
 
1336
   function Full_Library_Info_Name return File_Name_Type is
1337
   begin
1338
      return Current_Full_Lib_Name;
1339
   end Full_Library_Info_Name;
1340
 
1341
   ---------------------------
1342
   -- Full_Object_File_Name --
1343
   ---------------------------
1344
 
1345
   function Full_Object_File_Name return File_Name_Type is
1346
   begin
1347
      return Current_Full_Obj_Name;
1348
   end Full_Object_File_Name;
1349
 
1350
   ----------------------
1351
   -- Full_Source_Name --
1352
   ----------------------
1353
 
1354
   function Full_Source_Name return File_Name_Type is
1355
   begin
1356
      return Current_Full_Source_Name;
1357
   end Full_Source_Name;
1358
 
1359
   ----------------------
1360
   -- Full_Source_Name --
1361
   ----------------------
1362
 
1363
   function Full_Source_Name (N : File_Name_Type) return File_Name_Type is
1364
   begin
1365
      return Smart_Find_File (N, Source);
1366
   end Full_Source_Name;
1367
 
1368
   ----------------------
1369
   -- Full_Source_Name --
1370
   ----------------------
1371
 
1372
   procedure Full_Source_Name
1373
     (N         : File_Name_Type;
1374
      Full_File : out File_Name_Type;
1375
      Attr      : access File_Attributes) is
1376
   begin
1377
      Smart_Find_File (N, Source, Full_File, Attr.all);
1378
   end Full_Source_Name;
1379
 
1380
   -------------------
1381
   -- Get_Directory --
1382
   -------------------
1383
 
1384
   function Get_Directory (Name : File_Name_Type) return File_Name_Type is
1385
   begin
1386
      Get_Name_String (Name);
1387
 
1388
      for J in reverse 1 .. Name_Len loop
1389
         if Is_Directory_Separator (Name_Buffer (J)) then
1390
            Name_Len := J;
1391
            return Name_Find;
1392
         end if;
1393
      end loop;
1394
 
1395
      Name_Len := Hostparm.Normalized_CWD'Length;
1396
      Name_Buffer (1 .. Name_Len) := Hostparm.Normalized_CWD;
1397
      return Name_Find;
1398
   end Get_Directory;
1399
 
1400
   --------------------------
1401
   -- Get_Next_Dir_In_Path --
1402
   --------------------------
1403
 
1404
   Search_Path_Pos : Integer;
1405
   --  Keeps track of current position in search path. Initialized by the
1406
   --  call to Get_Next_Dir_In_Path_Init, updated by Get_Next_Dir_In_Path.
1407
 
1408
   function Get_Next_Dir_In_Path
1409
     (Search_Path : String_Access) return String_Access
1410
   is
1411
      Lower_Bound : Positive := Search_Path_Pos;
1412
      Upper_Bound : Positive;
1413
 
1414
   begin
1415
      loop
1416
         while Lower_Bound <= Search_Path'Last
1417
           and then Search_Path.all (Lower_Bound) = Path_Separator
1418
         loop
1419
            Lower_Bound := Lower_Bound + 1;
1420
         end loop;
1421
 
1422
         exit when Lower_Bound > Search_Path'Last;
1423
 
1424
         Upper_Bound := Lower_Bound;
1425
         while Upper_Bound <= Search_Path'Last
1426
           and then Search_Path.all (Upper_Bound) /= Path_Separator
1427
         loop
1428
            Upper_Bound := Upper_Bound + 1;
1429
         end loop;
1430
 
1431
         Search_Path_Pos := Upper_Bound;
1432
         return new String'(Search_Path.all (Lower_Bound .. Upper_Bound - 1));
1433
      end loop;
1434
 
1435
      return null;
1436
   end Get_Next_Dir_In_Path;
1437
 
1438
   -------------------------------
1439
   -- Get_Next_Dir_In_Path_Init --
1440
   -------------------------------
1441
 
1442
   procedure Get_Next_Dir_In_Path_Init (Search_Path : String_Access) is
1443
   begin
1444
      Search_Path_Pos := Search_Path'First;
1445
   end Get_Next_Dir_In_Path_Init;
1446
 
1447
   --------------------------------------
1448
   -- Get_Primary_Src_Search_Directory --
1449
   --------------------------------------
1450
 
1451
   function Get_Primary_Src_Search_Directory return String_Ptr is
1452
   begin
1453
      return Src_Search_Directories.Table (Primary_Directory);
1454
   end Get_Primary_Src_Search_Directory;
1455
 
1456
   ------------------------
1457
   -- Get_RTS_Search_Dir --
1458
   ------------------------
1459
 
1460
   function Get_RTS_Search_Dir
1461
     (Search_Dir : String;
1462
      File_Type  : Search_File_Type) return String_Ptr
1463
   is
1464
      procedure Get_Current_Dir
1465
        (Dir    : System.Address;
1466
         Length : System.Address);
1467
      pragma Import (C, Get_Current_Dir, "__gnat_get_current_dir");
1468
 
1469
      Max_Path : Integer;
1470
      pragma Import (C, Max_Path, "__gnat_max_path_len");
1471
      --  Maximum length of a path name
1472
 
1473
      Current_Dir        : String_Ptr;
1474
      Default_Search_Dir : String_Access;
1475
      Default_Suffix_Dir : String_Access;
1476
      Local_Search_Dir   : String_Access;
1477
      Norm_Search_Dir    : String_Access;
1478
      Result_Search_Dir  : String_Access;
1479
      Search_File        : String_Access;
1480
      Temp_String        : String_Ptr;
1481
 
1482
   begin
1483
      --  Add a directory separator at the end of the directory if necessary
1484
      --  so that we can directly append a file to the directory
1485
 
1486
      if Search_Dir (Search_Dir'Last) /= Directory_Separator then
1487
         Local_Search_Dir :=
1488
           new String'(Search_Dir & String'(1 => Directory_Separator));
1489
      else
1490
         Local_Search_Dir := new String'(Search_Dir);
1491
      end if;
1492
 
1493
      if File_Type = Include then
1494
         Search_File := Include_Search_File;
1495
         Default_Suffix_Dir := new String'("adainclude");
1496
      else
1497
         Search_File := Objects_Search_File;
1498
         Default_Suffix_Dir := new String'("adalib");
1499
      end if;
1500
 
1501
      Norm_Search_Dir := To_Canonical_Path_Spec (Local_Search_Dir.all);
1502
 
1503
      if Is_Absolute_Path (Norm_Search_Dir.all) then
1504
 
1505
         --  We first verify if there is a directory Include_Search_Dir
1506
         --  containing default search directories
1507
 
1508
         Result_Search_Dir :=
1509
           Read_Default_Search_Dirs (Norm_Search_Dir, Search_File, null);
1510
         Default_Search_Dir :=
1511
           new String'(Norm_Search_Dir.all & Default_Suffix_Dir.all);
1512
         Free (Norm_Search_Dir);
1513
 
1514
         if Result_Search_Dir /= null then
1515
            return String_Ptr (Result_Search_Dir);
1516
         elsif Is_Directory (Default_Search_Dir.all) then
1517
            return String_Ptr (Default_Search_Dir);
1518
         else
1519
            return null;
1520
         end if;
1521
 
1522
      --  Search in the current directory
1523
 
1524
      else
1525
         --  Get the current directory
1526
 
1527
         declare
1528
            Buffer   : String (1 .. Max_Path + 2);
1529
            Path_Len : Natural := Max_Path;
1530
 
1531
         begin
1532
            Get_Current_Dir (Buffer'Address, Path_Len'Address);
1533
 
1534
            if Buffer (Path_Len) /= Directory_Separator then
1535
               Path_Len := Path_Len + 1;
1536
               Buffer (Path_Len) := Directory_Separator;
1537
            end if;
1538
 
1539
            Current_Dir := new String'(Buffer (1 .. Path_Len));
1540
         end;
1541
 
1542
         Norm_Search_Dir :=
1543
           new String'(Current_Dir.all & Local_Search_Dir.all);
1544
 
1545
         Result_Search_Dir :=
1546
           Read_Default_Search_Dirs (Norm_Search_Dir, Search_File, null);
1547
 
1548
         Default_Search_Dir :=
1549
           new String'(Norm_Search_Dir.all & Default_Suffix_Dir.all);
1550
 
1551
         Free (Norm_Search_Dir);
1552
 
1553
         if Result_Search_Dir /= null then
1554
            return String_Ptr (Result_Search_Dir);
1555
 
1556
         elsif Is_Directory (Default_Search_Dir.all) then
1557
            return String_Ptr (Default_Search_Dir);
1558
 
1559
         else
1560
            --  Search in Search_Dir_Prefix/Search_Dir
1561
 
1562
            Norm_Search_Dir :=
1563
              new String'
1564
               (Update_Path (Search_Dir_Prefix).all & Local_Search_Dir.all);
1565
 
1566
            Result_Search_Dir :=
1567
              Read_Default_Search_Dirs (Norm_Search_Dir, Search_File, null);
1568
 
1569
            Default_Search_Dir :=
1570
              new String'(Norm_Search_Dir.all & Default_Suffix_Dir.all);
1571
 
1572
            Free (Norm_Search_Dir);
1573
 
1574
            if Result_Search_Dir /= null then
1575
               return String_Ptr (Result_Search_Dir);
1576
 
1577
            elsif Is_Directory (Default_Search_Dir.all) then
1578
               return String_Ptr (Default_Search_Dir);
1579
 
1580
            else
1581
               --  We finally search in Search_Dir_Prefix/rts-Search_Dir
1582
 
1583
               Temp_String :=
1584
                 new String'(Update_Path (Search_Dir_Prefix).all & "rts-");
1585
 
1586
               Norm_Search_Dir :=
1587
                 new String'(Temp_String.all & Local_Search_Dir.all);
1588
 
1589
               Result_Search_Dir :=
1590
                 Read_Default_Search_Dirs (Norm_Search_Dir, Search_File, null);
1591
 
1592
               Default_Search_Dir :=
1593
                 new String'(Norm_Search_Dir.all & Default_Suffix_Dir.all);
1594
               Free (Norm_Search_Dir);
1595
 
1596
               if Result_Search_Dir /= null then
1597
                  return String_Ptr (Result_Search_Dir);
1598
 
1599
               elsif Is_Directory (Default_Search_Dir.all) then
1600
                  return String_Ptr (Default_Search_Dir);
1601
 
1602
               else
1603
                  return null;
1604
               end if;
1605
            end if;
1606
         end if;
1607
      end if;
1608
   end Get_RTS_Search_Dir;
1609
 
1610
   --------------------------------
1611
   -- Include_Dir_Default_Prefix --
1612
   --------------------------------
1613
 
1614
   function Include_Dir_Default_Prefix return String_Access is
1615
   begin
1616
      if The_Include_Dir_Default_Prefix = null then
1617
         The_Include_Dir_Default_Prefix :=
1618
           String_Access (Update_Path (Include_Dir_Default_Name));
1619
      end if;
1620
 
1621
      return The_Include_Dir_Default_Prefix;
1622
   end Include_Dir_Default_Prefix;
1623
 
1624
   function Include_Dir_Default_Prefix return String is
1625
   begin
1626
      return Include_Dir_Default_Prefix.all;
1627
   end Include_Dir_Default_Prefix;
1628
 
1629
   ----------------
1630
   -- Initialize --
1631
   ----------------
1632
 
1633
   procedure Initialize is
1634
   begin
1635
      Number_File_Names       := 0;
1636
      Current_File_Name_Index := 0;
1637
 
1638
      Src_Search_Directories.Init;
1639
      Lib_Search_Directories.Init;
1640
 
1641
      --  Start off by setting all suppress options to False, these will
1642
      --  be reset later (turning some on if -gnato is not specified, and
1643
      --  turning all of them on if -gnatp is specified).
1644
 
1645
      Suppress_Options := (others => False);
1646
 
1647
      --  Reserve the first slot in the search paths table. This is the
1648
      --  directory of the main source file or main library file and is filled
1649
      --  in by each call to Next_Main_Source/Next_Main_Lib_File with the
1650
      --  directory specified for this main source or library file. This is the
1651
      --  directory which is searched first by default. This default search is
1652
      --  inhibited by the option -I- for both source and library files.
1653
 
1654
      Src_Search_Directories.Set_Last (Primary_Directory);
1655
      Src_Search_Directories.Table (Primary_Directory) := new String'("");
1656
 
1657
      Lib_Search_Directories.Set_Last (Primary_Directory);
1658
      Lib_Search_Directories.Table (Primary_Directory) := new String'("");
1659
   end Initialize;
1660
 
1661
   ------------------
1662
   -- Is_Directory --
1663
   ------------------
1664
 
1665
   function Is_Directory
1666
     (Name : C_File_Name; Attr : access File_Attributes) return Boolean
1667
   is
1668
      function Internal (N : C_File_Name; A : System.Address) return Integer;
1669
      pragma Import (C, Internal, "__gnat_is_directory_attr");
1670
   begin
1671
      return Internal (Name, Attr.all'Address) /= 0;
1672
   end Is_Directory;
1673
 
1674
   ----------------------------
1675
   -- Is_Directory_Separator --
1676
   ----------------------------
1677
 
1678
   function Is_Directory_Separator (C : Character) return Boolean is
1679
   begin
1680
      --  In addition to the default directory_separator allow the '/' to
1681
      --  act as separator since this is allowed in MS-DOS, Windows 95/NT,
1682
      --  and OS2 ports. On VMS, the situation is more complicated because
1683
      --  there are two characters to check for.
1684
 
1685
      return
1686
        C = Directory_Separator
1687
          or else C = '/'
1688
          or else (Hostparm.OpenVMS
1689
                    and then (C = ']' or else C = ':'));
1690
   end Is_Directory_Separator;
1691
 
1692
   -------------------------
1693
   -- Is_Readonly_Library --
1694
   -------------------------
1695
 
1696
   function Is_Readonly_Library (File : File_Name_Type) return Boolean is
1697
   begin
1698
      Get_Name_String (File);
1699
 
1700
      pragma Assert (Name_Buffer (Name_Len - 3 .. Name_Len) = ".ali");
1701
 
1702
      return not Is_Writable_File (Name_Buffer (1 .. Name_Len));
1703
   end Is_Readonly_Library;
1704
 
1705
   ------------------------
1706
   -- Is_Executable_File --
1707
   ------------------------
1708
 
1709
   function Is_Executable_File
1710
     (Name : C_File_Name; Attr : access File_Attributes) return Boolean
1711
   is
1712
      function Internal (N : C_File_Name; A : System.Address) return Integer;
1713
      pragma Import (C, Internal, "__gnat_is_executable_file_attr");
1714
   begin
1715
      return Internal (Name, Attr.all'Address) /= 0;
1716
   end Is_Executable_File;
1717
 
1718
   ----------------------
1719
   -- Is_Readable_File --
1720
   ----------------------
1721
 
1722
   function Is_Readable_File
1723
     (Name : C_File_Name; Attr : access File_Attributes) return Boolean
1724
   is
1725
      function Internal (N : C_File_Name; A : System.Address) return Integer;
1726
      pragma Import (C, Internal, "__gnat_is_readable_file_attr");
1727
   begin
1728
      return Internal (Name, Attr.all'Address) /= 0;
1729
   end Is_Readable_File;
1730
 
1731
   ---------------------
1732
   -- Is_Regular_File --
1733
   ---------------------
1734
 
1735
   function Is_Regular_File
1736
     (Name : C_File_Name; Attr : access File_Attributes) return Boolean
1737
   is
1738
      function Internal (N : C_File_Name; A : System.Address) return Integer;
1739
      pragma Import (C, Internal, "__gnat_is_regular_file_attr");
1740
   begin
1741
      return Internal (Name, Attr.all'Address) /= 0;
1742
   end Is_Regular_File;
1743
 
1744
   ----------------------
1745
   -- Is_Symbolic_Link --
1746
   ----------------------
1747
 
1748
   function Is_Symbolic_Link
1749
     (Name : C_File_Name; Attr : access File_Attributes) return Boolean
1750
   is
1751
      function Internal (N : C_File_Name; A : System.Address) return Integer;
1752
      pragma Import (C, Internal, "__gnat_is_symbolic_link_attr");
1753
   begin
1754
      return Internal (Name, Attr.all'Address) /= 0;
1755
   end Is_Symbolic_Link;
1756
 
1757
   ----------------------
1758
   -- Is_Writable_File --
1759
   ----------------------
1760
 
1761
   function Is_Writable_File
1762
     (Name : C_File_Name; Attr : access File_Attributes) return Boolean
1763
   is
1764
      function Internal (N : C_File_Name; A : System.Address) return Integer;
1765
      pragma Import (C, Internal, "__gnat_is_writable_file_attr");
1766
   begin
1767
      return Internal (Name, Attr.all'Address) /= 0;
1768
   end Is_Writable_File;
1769
 
1770
   -------------------
1771
   -- Lib_File_Name --
1772
   -------------------
1773
 
1774
   function Lib_File_Name
1775
     (Source_File : File_Name_Type;
1776
      Munit_Index : Nat := 0) return File_Name_Type
1777
   is
1778
   begin
1779
      Get_Name_String (Source_File);
1780
 
1781
      for J in reverse 2 .. Name_Len loop
1782
         if Name_Buffer (J) = '.' then
1783
            Name_Len := J - 1;
1784
            exit;
1785
         end if;
1786
      end loop;
1787
 
1788
      if Munit_Index /= 0 then
1789
         Add_Char_To_Name_Buffer (Multi_Unit_Index_Character);
1790
         Add_Nat_To_Name_Buffer (Munit_Index);
1791
      end if;
1792
 
1793
      Add_Char_To_Name_Buffer ('.');
1794
      Add_Str_To_Name_Buffer (ALI_Suffix.all);
1795
      return Name_Find;
1796
   end Lib_File_Name;
1797
 
1798
   -----------------
1799
   -- Locate_File --
1800
   -----------------
1801
 
1802
   procedure Locate_File
1803
     (N     : File_Name_Type;
1804
      T     : File_Type;
1805
      Dir   : Natural;
1806
      Name  : String;
1807
      Found : out File_Name_Type;
1808
      Attr  : access File_Attributes)
1809
   is
1810
      Dir_Name : String_Ptr;
1811
 
1812
   begin
1813
      --  If Name is already an absolute path, do not look for a directory
1814
 
1815
      if Is_Absolute_Path (Name) then
1816
         Dir_Name := No_Dir;
1817
 
1818
      elsif T = Library then
1819
         Dir_Name := Lib_Search_Directories.Table (Dir);
1820
 
1821
      else
1822
         pragma Assert (T /= Config);
1823
         Dir_Name := Src_Search_Directories.Table (Dir);
1824
      end if;
1825
 
1826
      declare
1827
         Full_Name : String (1 .. Dir_Name'Length + Name'Length + 1);
1828
 
1829
      begin
1830
         Full_Name (1 .. Dir_Name'Length) := Dir_Name.all;
1831
         Full_Name (Dir_Name'Length + 1 .. Full_Name'Last - 1) := Name;
1832
         Full_Name (Full_Name'Last) := ASCII.NUL;
1833
 
1834
         Attr.all := Unknown_Attributes;
1835
 
1836
         if not Is_Regular_File (Full_Name'Address, Attr) then
1837
            Found := No_File;
1838
 
1839
         else
1840
            --  If the file is in the current directory then return N itself
1841
 
1842
            if Dir_Name'Length = 0 then
1843
               Found := N;
1844
            else
1845
               Name_Len := Full_Name'Length - 1;
1846
               Name_Buffer (1 .. Name_Len) :=
1847
                 Full_Name (1 .. Full_Name'Last - 1);
1848
               Found := Name_Find;  --  ??? Was Name_Enter, no obvious reason
1849
            end if;
1850
         end if;
1851
      end;
1852
   end Locate_File;
1853
 
1854
   -------------------------------
1855
   -- Matching_Full_Source_Name --
1856
   -------------------------------
1857
 
1858
   function Matching_Full_Source_Name
1859
     (N : File_Name_Type;
1860
      T : Time_Stamp_Type) return File_Name_Type
1861
   is
1862
   begin
1863
      Get_Name_String (N);
1864
 
1865
      declare
1866
         File_Name : constant String := Name_Buffer (1 .. Name_Len);
1867
         File      : File_Name_Type := No_File;
1868
         Attr      : aliased File_Attributes;
1869
         Last_Dir  : Natural;
1870
 
1871
      begin
1872
         if Opt.Look_In_Primary_Dir then
1873
            Locate_File
1874
              (N, Source, Primary_Directory, File_Name, File, Attr'Access);
1875
 
1876
            if File /= No_File and then T = File_Stamp (N) then
1877
               return File;
1878
            end if;
1879
         end if;
1880
 
1881
         Last_Dir := Src_Search_Directories.Last;
1882
 
1883
         for D in Primary_Directory + 1 .. Last_Dir loop
1884
            Locate_File (N, Source, D, File_Name, File, Attr'Access);
1885
 
1886
            if File /= No_File and then T = File_Stamp (File) then
1887
               return File;
1888
            end if;
1889
         end loop;
1890
 
1891
         return No_File;
1892
      end;
1893
   end Matching_Full_Source_Name;
1894
 
1895
   ----------------
1896
   -- More_Files --
1897
   ----------------
1898
 
1899
   function More_Files return Boolean is
1900
   begin
1901
      return (Current_File_Name_Index < Number_File_Names);
1902
   end More_Files;
1903
 
1904
   -------------------------------
1905
   -- Nb_Dir_In_Obj_Search_Path --
1906
   -------------------------------
1907
 
1908
   function Nb_Dir_In_Obj_Search_Path return Natural is
1909
   begin
1910
      if Opt.Look_In_Primary_Dir then
1911
         return Lib_Search_Directories.Last -  Primary_Directory + 1;
1912
      else
1913
         return Lib_Search_Directories.Last -  Primary_Directory;
1914
      end if;
1915
   end Nb_Dir_In_Obj_Search_Path;
1916
 
1917
   -------------------------------
1918
   -- Nb_Dir_In_Src_Search_Path --
1919
   -------------------------------
1920
 
1921
   function Nb_Dir_In_Src_Search_Path return Natural is
1922
   begin
1923
      if Opt.Look_In_Primary_Dir then
1924
         return Src_Search_Directories.Last -  Primary_Directory + 1;
1925
      else
1926
         return Src_Search_Directories.Last -  Primary_Directory;
1927
      end if;
1928
   end Nb_Dir_In_Src_Search_Path;
1929
 
1930
   --------------------
1931
   -- Next_Main_File --
1932
   --------------------
1933
 
1934
   function Next_Main_File return File_Name_Type is
1935
      File_Name : String_Ptr;
1936
      Dir_Name  : String_Ptr;
1937
      Fptr      : Natural;
1938
 
1939
   begin
1940
      pragma Assert (More_Files);
1941
 
1942
      Current_File_Name_Index := Current_File_Name_Index + 1;
1943
 
1944
      --  Get the file and directory name
1945
 
1946
      File_Name := File_Names (Current_File_Name_Index);
1947
      Fptr := File_Name'First;
1948
 
1949
      for J in reverse File_Name'Range loop
1950
         if File_Name (J) = Directory_Separator
1951
           or else File_Name (J) = '/'
1952
         then
1953
            if J = File_Name'Last then
1954
               Fail ("File name missing");
1955
            end if;
1956
 
1957
            Fptr := J + 1;
1958
            exit;
1959
         end if;
1960
      end loop;
1961
 
1962
      --  Save name of directory in which main unit resides for use in
1963
      --  locating other units
1964
 
1965
      Dir_Name := new String'(File_Name (File_Name'First .. Fptr - 1));
1966
 
1967
      case Running_Program is
1968
 
1969
         when Compiler =>
1970
            Src_Search_Directories.Table (Primary_Directory) := Dir_Name;
1971
            Look_In_Primary_Directory_For_Current_Main := True;
1972
 
1973
         when Make =>
1974
            Src_Search_Directories.Table (Primary_Directory) := Dir_Name;
1975
 
1976
            if Fptr > File_Name'First then
1977
               Look_In_Primary_Directory_For_Current_Main := True;
1978
            end if;
1979
 
1980
         when Binder | Gnatls =>
1981
            Dir_Name := Normalize_Directory_Name (Dir_Name.all);
1982
            Lib_Search_Directories.Table (Primary_Directory) := Dir_Name;
1983
 
1984
         when Unspecified =>
1985
            null;
1986
      end case;
1987
 
1988
      Name_Len := File_Name'Last - Fptr + 1;
1989
      Name_Buffer (1 .. Name_Len) := File_Name (Fptr .. File_Name'Last);
1990
      Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
1991
      Current_Main := Name_Find;
1992
 
1993
      --  In the gnatmake case, the main file may have not have the
1994
      --  extension. Try ".adb" first then ".ads"
1995
 
1996
      if Running_Program = Make then
1997
         declare
1998
            Orig_Main : constant File_Name_Type := Current_Main;
1999
 
2000
         begin
2001
            if Strip_Suffix (Orig_Main) = Orig_Main then
2002
               Current_Main :=
2003
                 Append_Suffix_To_File_Name (Orig_Main, ".adb");
2004
 
2005
               if Full_Source_Name (Current_Main) = No_File then
2006
                  Current_Main :=
2007
                    Append_Suffix_To_File_Name (Orig_Main, ".ads");
2008
 
2009
                  if Full_Source_Name (Current_Main) = No_File then
2010
                     Current_Main := Orig_Main;
2011
                  end if;
2012
               end if;
2013
            end if;
2014
         end;
2015
      end if;
2016
 
2017
      return Current_Main;
2018
   end Next_Main_File;
2019
 
2020
   ------------------------------
2021
   -- Normalize_Directory_Name --
2022
   ------------------------------
2023
 
2024
   function Normalize_Directory_Name (Directory : String) return String_Ptr is
2025
 
2026
      function Is_Quoted (Path : String) return Boolean;
2027
      pragma Inline (Is_Quoted);
2028
      --  Returns true if Path is quoted (either double or single quotes)
2029
 
2030
      ---------------
2031
      -- Is_Quoted --
2032
      ---------------
2033
 
2034
      function Is_Quoted (Path : String) return Boolean is
2035
         First : constant Character := Path (Path'First);
2036
         Last  : constant Character := Path (Path'Last);
2037
 
2038
      begin
2039
         if (First = ''' and then Last = ''')
2040
               or else
2041
            (First = '"' and then Last = '"')
2042
         then
2043
            return True;
2044
         else
2045
            return False;
2046
         end if;
2047
      end Is_Quoted;
2048
 
2049
      Result : String_Ptr;
2050
 
2051
   --  Start of processing for Normalize_Directory_Name
2052
 
2053
   begin
2054
      if Directory'Length = 0 then
2055
         Result := new String'(Hostparm.Normalized_CWD);
2056
 
2057
      elsif Is_Directory_Separator (Directory (Directory'Last)) then
2058
         Result := new String'(Directory);
2059
 
2060
      elsif Is_Quoted (Directory) then
2061
 
2062
         --  This is a quoted string, it certainly means that the directory
2063
         --  contains some spaces for example. We can safely remove the quotes
2064
         --  here as the OS_Lib.Normalize_Arguments will be called before any
2065
         --  spawn routines. This ensure that quotes will be added when needed.
2066
 
2067
         Result := new String (1 .. Directory'Length - 1);
2068
         Result (1 .. Directory'Length - 2) :=
2069
           Directory (Directory'First + 1 .. Directory'Last - 1);
2070
         Result (Result'Last) := Directory_Separator;
2071
 
2072
      else
2073
         Result := new String (1 .. Directory'Length + 1);
2074
         Result (1 .. Directory'Length) := Directory;
2075
         Result (Directory'Length + 1) := Directory_Separator;
2076
      end if;
2077
 
2078
      return Result;
2079
   end Normalize_Directory_Name;
2080
 
2081
   ---------------------
2082
   -- Number_Of_Files --
2083
   ---------------------
2084
 
2085
   function Number_Of_Files return Int is
2086
   begin
2087
      return Number_File_Names;
2088
   end Number_Of_Files;
2089
 
2090
   -------------------------------
2091
   -- Object_Dir_Default_Prefix --
2092
   -------------------------------
2093
 
2094
   function Object_Dir_Default_Prefix return String is
2095
      Object_Dir : String_Access :=
2096
                     String_Access (Update_Path (Object_Dir_Default_Name));
2097
 
2098
   begin
2099
      if Object_Dir = null then
2100
         return "";
2101
 
2102
      else
2103
         declare
2104
            Result : constant String := Object_Dir.all;
2105
         begin
2106
            Free (Object_Dir);
2107
            return Result;
2108
         end;
2109
      end if;
2110
   end Object_Dir_Default_Prefix;
2111
 
2112
   ----------------------
2113
   -- Object_File_Name --
2114
   ----------------------
2115
 
2116
   function Object_File_Name (N : File_Name_Type) return File_Name_Type is
2117
   begin
2118
      if N = No_File then
2119
         return No_File;
2120
      end if;
2121
 
2122
      Get_Name_String (N);
2123
      Name_Len := Name_Len - ALI_Suffix'Length - 1;
2124
 
2125
      for J in Target_Object_Suffix'Range loop
2126
         Name_Len := Name_Len + 1;
2127
         Name_Buffer (Name_Len) := Target_Object_Suffix (J);
2128
      end loop;
2129
 
2130
      return Name_Enter;
2131
   end Object_File_Name;
2132
 
2133
   -------------------------------
2134
   -- OS_Exit_Through_Exception --
2135
   -------------------------------
2136
 
2137
   procedure OS_Exit_Through_Exception (Status : Integer) is
2138
   begin
2139
      Current_Exit_Status := Status;
2140
      raise Types.Terminate_Program;
2141
   end OS_Exit_Through_Exception;
2142
 
2143
   --------------------------
2144
   -- OS_Time_To_GNAT_Time --
2145
   --------------------------
2146
 
2147
   function OS_Time_To_GNAT_Time (T : OS_Time) return Time_Stamp_Type is
2148
      GNAT_Time : Time_Stamp_Type;
2149
 
2150
      Y  : Year_Type;
2151
      Mo : Month_Type;
2152
      D  : Day_Type;
2153
      H  : Hour_Type;
2154
      Mn : Minute_Type;
2155
      S  : Second_Type;
2156
 
2157
   begin
2158
      if T = Invalid_Time then
2159
         return Empty_Time_Stamp;
2160
      end if;
2161
 
2162
      GM_Split (T, Y, Mo, D, H, Mn, S);
2163
      Make_Time_Stamp
2164
        (Year    => Nat (Y),
2165
         Month   => Nat (Mo),
2166
         Day     => Nat (D),
2167
         Hour    => Nat (H),
2168
         Minutes => Nat (Mn),
2169
         Seconds => Nat (S),
2170
         TS      => GNAT_Time);
2171
 
2172
      return GNAT_Time;
2173
   end OS_Time_To_GNAT_Time;
2174
 
2175
   ------------------
2176
   -- Program_Name --
2177
   ------------------
2178
 
2179
   function Program_Name (Nam : String; Prog : String) return String_Access is
2180
      End_Of_Prefix   : Natural := 0;
2181
      Start_Of_Prefix : Positive := 1;
2182
      Start_Of_Suffix : Positive;
2183
 
2184
   begin
2185
      --  GNAAMP tool names require special treatment
2186
 
2187
      if AAMP_On_Target then
2188
 
2189
         --  The name "gcc" is mapped to "gnaamp" (the compiler driver)
2190
 
2191
         if Nam = "gcc" then
2192
            return new String'("gnaamp");
2193
 
2194
         --  Tool names starting with "gnat" are mapped by substituting the
2195
         --  string "gnaamp" for "gnat" (for example, "gnatpp" => "gnaamppp").
2196
 
2197
         elsif Nam'Length >= 4
2198
           and then Nam (Nam'First .. Nam'First + 3) = "gnat"
2199
         then
2200
            return new String'("gnaamp" & Nam (Nam'First + 4 .. Nam'Last));
2201
 
2202
         --  No other mapping rules, so we continue and handle any other forms
2203
         --  of tool names the same as on other targets.
2204
 
2205
         else
2206
            null;
2207
         end if;
2208
      end if;
2209
 
2210
      --  Get the name of the current program being executed
2211
 
2212
      Find_Program_Name;
2213
 
2214
      Start_Of_Suffix := Name_Len + 1;
2215
 
2216
      --  Find the target prefix if any, for the cross compilation case.
2217
      --  For instance in "powerpc-elf-gcc" the target prefix is
2218
      --  "powerpc-elf-"
2219
      --  Ditto for suffix, e.g. in "gcc-4.1", the suffix is "-4.1"
2220
 
2221
      for J in reverse 1 .. Name_Len loop
2222
         if Name_Buffer (J) = '/'
2223
           or else Name_Buffer (J) = Directory_Separator
2224
           or else Name_Buffer (J) = ':'
2225
         then
2226
            Start_Of_Prefix := J + 1;
2227
            exit;
2228
         end if;
2229
      end loop;
2230
 
2231
      --  Find End_Of_Prefix
2232
 
2233
      for J in Start_Of_Prefix .. Name_Len - Prog'Length + 1 loop
2234
         if Name_Buffer (J .. J + Prog'Length - 1) = Prog then
2235
            End_Of_Prefix := J - 1;
2236
            exit;
2237
         end if;
2238
      end loop;
2239
 
2240
      if End_Of_Prefix > 1 then
2241
         Start_Of_Suffix := End_Of_Prefix + Prog'Length + 1;
2242
      end if;
2243
 
2244
      --  Create the new program name
2245
 
2246
      return new String'
2247
        (Name_Buffer (Start_Of_Prefix .. End_Of_Prefix)
2248
         & Nam
2249
         & Name_Buffer (Start_Of_Suffix .. Name_Len));
2250
   end Program_Name;
2251
 
2252
   ------------------------------
2253
   -- Read_Default_Search_Dirs --
2254
   ------------------------------
2255
 
2256
   function Read_Default_Search_Dirs
2257
     (Search_Dir_Prefix       : String_Access;
2258
      Search_File             : String_Access;
2259
      Search_Dir_Default_Name : String_Access) return String_Access
2260
   is
2261
      Prefix_Len : constant Integer := Search_Dir_Prefix.all'Length;
2262
      Buffer     : String (1 .. Prefix_Len + Search_File.all'Length + 1);
2263
      File_FD    : File_Descriptor;
2264
      S, S1      : String_Access;
2265
      Len        : Integer;
2266
      Curr       : Integer;
2267
      Actual_Len : Integer;
2268
      J1         : Integer;
2269
 
2270
      Prev_Was_Separator : Boolean;
2271
      Nb_Relative_Dir    : Integer;
2272
 
2273
      function Is_Relative (S : String; K : Positive) return Boolean;
2274
      pragma Inline (Is_Relative);
2275
      --  Returns True if a relative directory specification is found
2276
      --  in S at position K, False otherwise.
2277
 
2278
      -----------------
2279
      -- Is_Relative --
2280
      -----------------
2281
 
2282
      function Is_Relative (S : String; K : Positive) return Boolean is
2283
      begin
2284
         return not Is_Absolute_Path (S (K .. S'Last));
2285
      end Is_Relative;
2286
 
2287
   --  Start of processing for Read_Default_Search_Dirs
2288
 
2289
   begin
2290
      --  Construct a C compatible character string buffer
2291
 
2292
      Buffer (1 .. Search_Dir_Prefix.all'Length)
2293
        := Search_Dir_Prefix.all;
2294
      Buffer (Search_Dir_Prefix.all'Length + 1 .. Buffer'Last - 1)
2295
        := Search_File.all;
2296
      Buffer (Buffer'Last) := ASCII.NUL;
2297
 
2298
      File_FD := Open_Read (Buffer'Address, Binary);
2299
      if File_FD = Invalid_FD then
2300
         return Search_Dir_Default_Name;
2301
      end if;
2302
 
2303
      Len := Integer (File_Length (File_FD));
2304
 
2305
      --  An extra character for a trailing Path_Separator is allocated
2306
 
2307
      S := new String (1 .. Len + 1);
2308
      S (Len + 1) := Path_Separator;
2309
 
2310
      --  Read the file. Note that the loop is not necessary since the
2311
      --  whole file is read at once except on VMS.
2312
 
2313
      Curr := 1;
2314
      Actual_Len := Len;
2315
      while Actual_Len /= 0 loop
2316
         Actual_Len := Read (File_FD, S (Curr)'Address, Len);
2317
         Curr := Curr + Actual_Len;
2318
      end loop;
2319
 
2320
      --  Process the file, dealing with path separators
2321
 
2322
      Prev_Was_Separator := True;
2323
      Nb_Relative_Dir := 0;
2324
      for J in 1 .. Len loop
2325
 
2326
         --  Treat any control character as a path separator. Note that we do
2327
         --  not treat space as a path separator (we used to treat space as a
2328
         --  path separator in an earlier version). That way space can appear
2329
         --  as a legitimate character in a path name.
2330
 
2331
         --  Why do we treat all control characters as path separators???
2332
 
2333
         if S (J) in ASCII.NUL .. ASCII.US then
2334
            S (J) := Path_Separator;
2335
         end if;
2336
 
2337
         --  Test for explicit path separator (or control char as above)
2338
 
2339
         if S (J) = Path_Separator then
2340
            Prev_Was_Separator := True;
2341
 
2342
         --  If not path separator, register use of relative directory
2343
 
2344
         else
2345
            if Prev_Was_Separator and then Is_Relative (S.all, J) then
2346
               Nb_Relative_Dir := Nb_Relative_Dir + 1;
2347
            end if;
2348
 
2349
            Prev_Was_Separator := False;
2350
         end if;
2351
      end loop;
2352
 
2353
      if Nb_Relative_Dir = 0 then
2354
         return S;
2355
      end if;
2356
 
2357
      --  Add the Search_Dir_Prefix to all relative paths
2358
 
2359
      S1 := new String (1 .. S'Length + Nb_Relative_Dir * Prefix_Len);
2360
      J1 := 1;
2361
      Prev_Was_Separator := True;
2362
      for J in 1 .. Len + 1 loop
2363
         if S (J) = Path_Separator then
2364
            Prev_Was_Separator := True;
2365
 
2366
         else
2367
            if Prev_Was_Separator and then Is_Relative (S.all, J) then
2368
               S1 (J1 .. J1 + Prefix_Len - 1) := Search_Dir_Prefix.all;
2369
               J1 := J1 + Prefix_Len;
2370
            end if;
2371
 
2372
            Prev_Was_Separator := False;
2373
         end if;
2374
         S1 (J1) := S (J);
2375
         J1 := J1 + 1;
2376
      end loop;
2377
 
2378
      Free (S);
2379
      return S1;
2380
   end Read_Default_Search_Dirs;
2381
 
2382
   -----------------------
2383
   -- Read_Library_Info --
2384
   -----------------------
2385
 
2386
   function Read_Library_Info
2387
     (Lib_File  : File_Name_Type;
2388
      Fatal_Err : Boolean := False) return Text_Buffer_Ptr
2389
   is
2390
      File : File_Name_Type;
2391
      Attr : aliased File_Attributes;
2392
   begin
2393
      Find_File (Lib_File, Library, File, Attr'Access);
2394
      return Read_Library_Info_From_Full
2395
        (Full_Lib_File => File,
2396
         Lib_File_Attr => Attr'Access,
2397
         Fatal_Err     => Fatal_Err);
2398
   end Read_Library_Info;
2399
 
2400
   ---------------------------------
2401
   -- Read_Library_Info_From_Full --
2402
   ---------------------------------
2403
 
2404
   function Read_Library_Info_From_Full
2405
     (Full_Lib_File : File_Name_Type;
2406
      Lib_File_Attr : access File_Attributes;
2407
      Fatal_Err     : Boolean := False) return Text_Buffer_Ptr
2408
   is
2409
      Lib_FD : File_Descriptor;
2410
      --  The file descriptor for the current library file. A negative value
2411
      --  indicates failure to open the specified source file.
2412
 
2413
      Len : Integer;
2414
      --  Length of source file text (ALI). If it doesn't fit in an integer
2415
      --  we're probably stuck anyway (>2 gigs of source seems a lot!)
2416
 
2417
      Text : Text_Buffer_Ptr;
2418
      --  Allocated text buffer
2419
 
2420
      Status : Boolean;
2421
      pragma Warnings (Off, Status);
2422
      --  For the calls to Close
2423
 
2424
   begin
2425
      Current_Full_Lib_Name := Full_Lib_File;
2426
      Current_Full_Obj_Name := Object_File_Name (Current_Full_Lib_Name);
2427
 
2428
      if Current_Full_Lib_Name = No_File then
2429
         if Fatal_Err then
2430
            Fail ("Cannot find: " & Name_Buffer (1 .. Name_Len));
2431
         else
2432
            Current_Full_Obj_Stamp := Empty_Time_Stamp;
2433
            return null;
2434
         end if;
2435
      end if;
2436
 
2437
      Get_Name_String (Current_Full_Lib_Name);
2438
      Name_Buffer (Name_Len + 1) := ASCII.NUL;
2439
 
2440
      --  Open the library FD, note that we open in binary mode, because as
2441
      --  documented in the spec, the caller is expected to handle either
2442
      --  DOS or Unix mode files, and there is no point in wasting time on
2443
      --  text translation when it is not required.
2444
 
2445
      Lib_FD := Open_Read (Name_Buffer'Address, Binary);
2446
 
2447
      if Lib_FD = Invalid_FD then
2448
         if Fatal_Err then
2449
            Fail ("Cannot open: " & Name_Buffer (1 .. Name_Len));
2450
         else
2451
            Current_Full_Obj_Stamp := Empty_Time_Stamp;
2452
            return null;
2453
         end if;
2454
      end if;
2455
 
2456
      --  Compute the length of the file (potentially also preparing other data
2457
      --  like the timestamp and whether the file is read-only, for future use)
2458
 
2459
      Len := Integer (File_Length (Name_Buffer'Address, Lib_File_Attr));
2460
 
2461
      --  Check for object file consistency if requested
2462
 
2463
      if Opt.Check_Object_Consistency then
2464
         --  On most systems, this does not result in an extra system call
2465
 
2466
         Current_Full_Lib_Stamp :=
2467
           OS_Time_To_GNAT_Time
2468
             (File_Time_Stamp (Name_Buffer'Address, Lib_File_Attr));
2469
 
2470
         --  ??? One system call here
2471
 
2472
         Current_Full_Obj_Stamp := File_Stamp (Current_Full_Obj_Name);
2473
 
2474
         if Current_Full_Obj_Stamp (1) = ' ' then
2475
 
2476
            --  When the library is readonly always assume object is consistent
2477
            --  The call to Is_Writable_File only results in a system call on
2478
            --  some systems, but in most cases it has already been computed as
2479
            --  part of the call to File_Length above.
2480
 
2481
            Get_Name_String (Current_Full_Lib_Name);
2482
            Name_Buffer (Name_Len + 1) := ASCII.NUL;
2483
 
2484
            if not Is_Writable_File (Name_Buffer'Address, Lib_File_Attr) then
2485
               Current_Full_Obj_Stamp := Current_Full_Lib_Stamp;
2486
 
2487
            elsif Fatal_Err then
2488
               Get_Name_String (Current_Full_Obj_Name);
2489
               Close (Lib_FD, Status);
2490
 
2491
               --  No need to check the status, we fail anyway
2492
 
2493
               Fail ("Cannot find: " & Name_Buffer (1 .. Name_Len));
2494
 
2495
            else
2496
               Current_Full_Obj_Stamp := Empty_Time_Stamp;
2497
               Close (Lib_FD, Status);
2498
 
2499
               --  No need to check the status, we return null anyway
2500
 
2501
               return null;
2502
            end if;
2503
         end if;
2504
      end if;
2505
 
2506
      --  Read data from the file
2507
 
2508
      declare
2509
         Actual_Len : Integer := 0;
2510
 
2511
         Lo : constant Text_Ptr := 0;
2512
         --  Low bound for allocated text buffer
2513
 
2514
         Hi : Text_Ptr := Text_Ptr (Len);
2515
         --  High bound for allocated text buffer. Note length is Len + 1
2516
         --  which allows for extra EOF character at the end of the buffer.
2517
 
2518
      begin
2519
         --  Allocate text buffer. Note extra character at end for EOF
2520
 
2521
         Text := new Text_Buffer (Lo .. Hi);
2522
 
2523
         --  Some systems (e.g. VMS) have file types that require one
2524
         --  read per line, so read until we get the Len bytes or until
2525
         --  there are no more characters.
2526
 
2527
         Hi := Lo;
2528
         loop
2529
            Actual_Len := Read (Lib_FD, Text (Hi)'Address, Len);
2530
            Hi := Hi + Text_Ptr (Actual_Len);
2531
            exit when Actual_Len = Len or else Actual_Len <= 0;
2532
         end loop;
2533
 
2534
         Text (Hi) := EOF;
2535
      end;
2536
 
2537
      --  Read is complete, close file and we are done
2538
 
2539
      Close (Lib_FD, Status);
2540
      --  The status should never be False. But, if it is, what can we do?
2541
      --  So, we don't test it.
2542
 
2543
      return Text;
2544
 
2545
   end Read_Library_Info_From_Full;
2546
 
2547
   ----------------------
2548
   -- Read_Source_File --
2549
   ----------------------
2550
 
2551
   procedure Read_Source_File
2552
     (N   : File_Name_Type;
2553
      Lo  : Source_Ptr;
2554
      Hi  : out Source_Ptr;
2555
      Src : out Source_Buffer_Ptr;
2556
      T   : File_Type := Source)
2557
   is
2558
      Source_File_FD : File_Descriptor;
2559
      --  The file descriptor for the current source file. A negative value
2560
      --  indicates failure to open the specified source file.
2561
 
2562
      Len : Integer;
2563
      --  Length of file. Assume no more than 2 gigabytes of source!
2564
 
2565
      Actual_Len : Integer;
2566
 
2567
      Status : Boolean;
2568
      pragma Warnings (Off, Status);
2569
      --  For the call to Close
2570
 
2571
   begin
2572
      Current_Full_Source_Name  := Find_File (N, T);
2573
      Current_Full_Source_Stamp := File_Stamp (Current_Full_Source_Name);
2574
 
2575
      if Current_Full_Source_Name = No_File then
2576
 
2577
         --  If we were trying to access the main file and we could not find
2578
         --  it, we have an error.
2579
 
2580
         if N = Current_Main then
2581
            Get_Name_String (N);
2582
            Fail ("Cannot find: " & Name_Buffer (1 .. Name_Len));
2583
         end if;
2584
 
2585
         Src := null;
2586
         Hi  := No_Location;
2587
         return;
2588
      end if;
2589
 
2590
      Get_Name_String (Current_Full_Source_Name);
2591
      Name_Buffer (Name_Len + 1) := ASCII.NUL;
2592
 
2593
      --  Open the source FD, note that we open in binary mode, because as
2594
      --  documented in the spec, the caller is expected to handle either
2595
      --  DOS or Unix mode files, and there is no point in wasting time on
2596
      --  text translation when it is not required.
2597
 
2598
      Source_File_FD := Open_Read (Name_Buffer'Address, Binary);
2599
 
2600
      if Source_File_FD = Invalid_FD then
2601
         Src := null;
2602
         Hi  := No_Location;
2603
         return;
2604
      end if;
2605
 
2606
      --  Print out the file name, if requested, and if it's not part of the
2607
      --  runtimes, store it in File_Name_Chars.
2608
 
2609
      declare
2610
         Name : String renames Name_Buffer (1 .. Name_Len);
2611
         Inc  : String renames Include_Dir_Default_Prefix.all;
2612
 
2613
      begin
2614
         if Debug.Debug_Flag_Dot_N then
2615
            Write_Line (Name);
2616
         end if;
2617
 
2618
         if Inc /= ""
2619
           and then Inc'Length < Name_Len
2620
           and then Name_Buffer (1 .. Inc'Length) = Inc
2621
         then
2622
            --  Part of runtimes, so ignore it
2623
 
2624
            null;
2625
 
2626
         else
2627
            File_Name_Chars.Append_All (File_Name_Chars.Table_Type (Name));
2628
            File_Name_Chars.Append (ASCII.LF);
2629
         end if;
2630
      end;
2631
 
2632
      --  Prepare to read data from the file
2633
 
2634
      Len := Integer (File_Length (Source_File_FD));
2635
 
2636
      --  Set Hi so that length is one more than the physical length,
2637
      --  allowing for the extra EOF character at the end of the buffer
2638
 
2639
      Hi := Lo + Source_Ptr (Len);
2640
 
2641
      --  Do the actual read operation
2642
 
2643
      declare
2644
         subtype Actual_Source_Buffer is Source_Buffer (Lo .. Hi);
2645
         --  Physical buffer allocated
2646
 
2647
         type Actual_Source_Ptr is access Actual_Source_Buffer;
2648
         --  This is the pointer type for the physical buffer allocated
2649
 
2650
         Actual_Ptr : constant Actual_Source_Ptr := new Actual_Source_Buffer;
2651
         --  And this is the actual physical buffer
2652
 
2653
      begin
2654
         --  Allocate source buffer, allowing extra character at end for EOF
2655
 
2656
         --  Some systems (e.g. VMS) have file types that require one read per
2657
         --  line, so read until we get the Len bytes or until there are no
2658
         --  more characters.
2659
 
2660
         Hi := Lo;
2661
         loop
2662
            Actual_Len := Read (Source_File_FD, Actual_Ptr (Hi)'Address, Len);
2663
            Hi := Hi + Source_Ptr (Actual_Len);
2664
            exit when Actual_Len = Len or else Actual_Len <= 0;
2665
         end loop;
2666
 
2667
         Actual_Ptr (Hi) := EOF;
2668
 
2669
         --  Now we need to work out the proper virtual origin pointer to
2670
         --  return. This is exactly Actual_Ptr (0)'Address, but we have to
2671
         --  be careful to suppress checks to compute this address.
2672
 
2673
         declare
2674
            pragma Suppress (All_Checks);
2675
 
2676
            pragma Warnings (Off);
2677
            --  This use of unchecked conversion is aliasing safe
2678
 
2679
            function To_Source_Buffer_Ptr is new
2680
              Unchecked_Conversion (Address, Source_Buffer_Ptr);
2681
 
2682
            pragma Warnings (On);
2683
 
2684
         begin
2685
            Src := To_Source_Buffer_Ptr (Actual_Ptr (0)'Address);
2686
         end;
2687
      end;
2688
 
2689
      --  Read is complete, get time stamp and close file and we are done
2690
 
2691
      Close (Source_File_FD, Status);
2692
 
2693
      --  The status should never be False. But, if it is, what can we do?
2694
      --  So, we don't test it.
2695
 
2696
   end Read_Source_File;
2697
 
2698
   -------------------
2699
   -- Relocate_Path --
2700
   -------------------
2701
 
2702
   function Relocate_Path
2703
     (Prefix : String;
2704
      Path   : String) return String_Ptr
2705
   is
2706
      S : String_Ptr;
2707
 
2708
      procedure set_std_prefix (S : String; Len : Integer);
2709
      pragma Import (C, set_std_prefix);
2710
 
2711
   begin
2712
      if Std_Prefix = null then
2713
         Std_Prefix := Executable_Prefix;
2714
 
2715
         if Std_Prefix.all /= "" then
2716
 
2717
            --  Remove trailing directory separator when calling set_std_prefix
2718
 
2719
            set_std_prefix (Std_Prefix.all, Std_Prefix'Length - 1);
2720
         end if;
2721
      end if;
2722
 
2723
      if Path (Prefix'Range) = Prefix then
2724
         if Std_Prefix.all /= "" then
2725
            S := new String
2726
              (1 .. Std_Prefix'Length + Path'Last - Prefix'Last);
2727
            S (1 .. Std_Prefix'Length) := Std_Prefix.all;
2728
            S (Std_Prefix'Length + 1 .. S'Last) :=
2729
              Path (Prefix'Last + 1 .. Path'Last);
2730
            return S;
2731
         end if;
2732
      end if;
2733
 
2734
      return new String'(Path);
2735
   end Relocate_Path;
2736
 
2737
   -----------------
2738
   -- Set_Program --
2739
   -----------------
2740
 
2741
   procedure Set_Program (P : Program_Type) is
2742
   begin
2743
      if Program_Set then
2744
         Fail ("Set_Program called twice");
2745
      end if;
2746
 
2747
      Program_Set := True;
2748
      Running_Program := P;
2749
   end Set_Program;
2750
 
2751
   ----------------
2752
   -- Shared_Lib --
2753
   ----------------
2754
 
2755
   function Shared_Lib (Name : String) return String is
2756
      Library : String (1 .. Name'Length + Library_Version'Length + 3);
2757
      --  3 = 2 for "-l" + 1 for "-" before lib version
2758
 
2759
   begin
2760
      Library (1 .. 2)                          := "-l";
2761
      Library (3 .. 2 + Name'Length)            := Name;
2762
      Library (3 + Name'Length)                 := '-';
2763
      Library (4 + Name'Length .. Library'Last) := Library_Version;
2764
 
2765
      if OpenVMS_On_Target then
2766
         for K in Library'First + 2 .. Library'Last loop
2767
            if Library (K) = '.' or else Library (K) = '-' then
2768
               Library (K) := '_';
2769
            end if;
2770
         end loop;
2771
      end if;
2772
 
2773
      return Library;
2774
   end Shared_Lib;
2775
 
2776
   ----------------------
2777
   -- Smart_File_Stamp --
2778
   ----------------------
2779
 
2780
   function Smart_File_Stamp
2781
     (N : File_Name_Type;
2782
      T : File_Type) return Time_Stamp_Type
2783
   is
2784
      File : File_Name_Type;
2785
      Attr : aliased File_Attributes;
2786
 
2787
   begin
2788
      if not File_Cache_Enabled then
2789
         Find_File (N, T, File, Attr'Access);
2790
      else
2791
         Smart_Find_File (N, T, File, Attr);
2792
      end if;
2793
 
2794
      if File = No_File then
2795
         return Empty_Time_Stamp;
2796
      else
2797
         Get_Name_String (File);
2798
         Name_Buffer (Name_Len + 1) := ASCII.NUL;
2799
         return
2800
           OS_Time_To_GNAT_Time
2801
             (File_Time_Stamp (Name_Buffer'Address, Attr'Access));
2802
      end if;
2803
   end Smart_File_Stamp;
2804
 
2805
   ---------------------
2806
   -- Smart_Find_File --
2807
   ---------------------
2808
 
2809
   function Smart_Find_File
2810
     (N : File_Name_Type;
2811
      T : File_Type) return File_Name_Type
2812
   is
2813
      File : File_Name_Type;
2814
      Attr : File_Attributes;
2815
   begin
2816
      Smart_Find_File (N, T, File, Attr);
2817
      return File;
2818
   end Smart_Find_File;
2819
 
2820
   ---------------------
2821
   -- Smart_Find_File --
2822
   ---------------------
2823
 
2824
   procedure Smart_Find_File
2825
     (N     : File_Name_Type;
2826
      T     : File_Type;
2827
      Found : out File_Name_Type;
2828
      Attr  : out File_Attributes)
2829
   is
2830
      Info : File_Info_Cache;
2831
 
2832
   begin
2833
      if not File_Cache_Enabled then
2834
         Find_File (N, T, Info.File, Info.Attr'Access);
2835
 
2836
      else
2837
         Info := File_Name_Hash_Table.Get (N);
2838
 
2839
         if Info.File = No_File then
2840
            Find_File (N, T, Info.File, Info.Attr'Access);
2841
            File_Name_Hash_Table.Set (N, Info);
2842
         end if;
2843
      end if;
2844
 
2845
      Found := Info.File;
2846
      Attr  := Info.Attr;
2847
   end Smart_Find_File;
2848
 
2849
   ----------------------
2850
   -- Source_File_Data --
2851
   ----------------------
2852
 
2853
   procedure Source_File_Data (Cache : Boolean) is
2854
   begin
2855
      File_Cache_Enabled := Cache;
2856
   end Source_File_Data;
2857
 
2858
   -----------------------
2859
   -- Source_File_Stamp --
2860
   -----------------------
2861
 
2862
   function Source_File_Stamp (N : File_Name_Type) return Time_Stamp_Type is
2863
   begin
2864
      return Smart_File_Stamp (N, Source);
2865
   end Source_File_Stamp;
2866
 
2867
   ---------------------
2868
   -- Strip_Directory --
2869
   ---------------------
2870
 
2871
   function Strip_Directory (Name : File_Name_Type) return File_Name_Type is
2872
   begin
2873
      Get_Name_String (Name);
2874
 
2875
      for J in reverse 1 .. Name_Len - 1 loop
2876
 
2877
         --  If we find the last directory separator
2878
 
2879
         if Is_Directory_Separator (Name_Buffer (J)) then
2880
 
2881
            --  Return part of Name that follows this last directory separator
2882
 
2883
            Name_Buffer (1 .. Name_Len - J) := Name_Buffer (J + 1 .. Name_Len);
2884
            Name_Len := Name_Len - J;
2885
            return Name_Find;
2886
         end if;
2887
      end loop;
2888
 
2889
      --  There were no directory separator, just return Name
2890
 
2891
      return Name;
2892
   end Strip_Directory;
2893
 
2894
   ------------------
2895
   -- Strip_Suffix --
2896
   ------------------
2897
 
2898
   function Strip_Suffix (Name : File_Name_Type) return File_Name_Type is
2899
   begin
2900
      Get_Name_String (Name);
2901
 
2902
      for J in reverse 2 .. Name_Len loop
2903
 
2904
         --  If we found the last '.', return part of Name that precedes it
2905
 
2906
         if Name_Buffer (J) = '.' then
2907
            Name_Len := J - 1;
2908
            return Name_Enter;
2909
         end if;
2910
      end loop;
2911
 
2912
      return Name;
2913
   end Strip_Suffix;
2914
 
2915
   ---------------------------
2916
   -- To_Canonical_Dir_Spec --
2917
   ---------------------------
2918
 
2919
   function To_Canonical_Dir_Spec
2920
     (Host_Dir     : String;
2921
      Prefix_Style : Boolean) return String_Access
2922
   is
2923
      function To_Canonical_Dir_Spec
2924
        (Host_Dir    : Address;
2925
         Prefix_Flag : Integer) return Address;
2926
      pragma Import (C, To_Canonical_Dir_Spec, "__gnat_to_canonical_dir_spec");
2927
 
2928
      C_Host_Dir         : String (1 .. Host_Dir'Length + 1);
2929
      Canonical_Dir_Addr : Address;
2930
      Canonical_Dir_Len  : Integer;
2931
 
2932
   begin
2933
      C_Host_Dir (1 .. Host_Dir'Length) := Host_Dir;
2934
      C_Host_Dir (C_Host_Dir'Last)      := ASCII.NUL;
2935
 
2936
      if Prefix_Style then
2937
         Canonical_Dir_Addr := To_Canonical_Dir_Spec (C_Host_Dir'Address, 1);
2938
      else
2939
         Canonical_Dir_Addr := To_Canonical_Dir_Spec (C_Host_Dir'Address, 0);
2940
      end if;
2941
 
2942
      Canonical_Dir_Len := C_String_Length (Canonical_Dir_Addr);
2943
 
2944
      if Canonical_Dir_Len = 0 then
2945
         return null;
2946
      else
2947
         return To_Path_String_Access (Canonical_Dir_Addr, Canonical_Dir_Len);
2948
      end if;
2949
 
2950
   exception
2951
      when others =>
2952
         Fail ("erroneous directory spec: " & Host_Dir);
2953
         return null;
2954
   end To_Canonical_Dir_Spec;
2955
 
2956
   ---------------------------
2957
   -- To_Canonical_File_List --
2958
   ---------------------------
2959
 
2960
   function To_Canonical_File_List
2961
     (Wildcard_Host_File : String;
2962
      Only_Dirs          : Boolean) return String_Access_List_Access
2963
   is
2964
      function To_Canonical_File_List_Init
2965
        (Host_File : Address;
2966
         Only_Dirs : Integer) return Integer;
2967
      pragma Import (C, To_Canonical_File_List_Init,
2968
                     "__gnat_to_canonical_file_list_init");
2969
 
2970
      function To_Canonical_File_List_Next return Address;
2971
      pragma Import (C, To_Canonical_File_List_Next,
2972
                     "__gnat_to_canonical_file_list_next");
2973
 
2974
      procedure To_Canonical_File_List_Free;
2975
      pragma Import (C, To_Canonical_File_List_Free,
2976
                     "__gnat_to_canonical_file_list_free");
2977
 
2978
      Num_Files            : Integer;
2979
      C_Wildcard_Host_File : String (1 .. Wildcard_Host_File'Length + 1);
2980
 
2981
   begin
2982
      C_Wildcard_Host_File (1 .. Wildcard_Host_File'Length) :=
2983
        Wildcard_Host_File;
2984
      C_Wildcard_Host_File (C_Wildcard_Host_File'Last) := ASCII.NUL;
2985
 
2986
      --  Do the expansion and say how many there are
2987
 
2988
      Num_Files := To_Canonical_File_List_Init
2989
         (C_Wildcard_Host_File'Address, Boolean'Pos (Only_Dirs));
2990
 
2991
      declare
2992
         Canonical_File_List : String_Access_List (1 .. Num_Files);
2993
         Canonical_File_Addr : Address;
2994
         Canonical_File_Len  : Integer;
2995
 
2996
      begin
2997
         --  Retrieve the expanded directory names and build the list
2998
 
2999
         for J in 1 .. Num_Files loop
3000
            Canonical_File_Addr := To_Canonical_File_List_Next;
3001
            Canonical_File_Len  := C_String_Length (Canonical_File_Addr);
3002
            Canonical_File_List (J) := To_Path_String_Access
3003
                  (Canonical_File_Addr, Canonical_File_Len);
3004
         end loop;
3005
 
3006
         --  Free up the storage
3007
 
3008
         To_Canonical_File_List_Free;
3009
 
3010
         return new String_Access_List'(Canonical_File_List);
3011
      end;
3012
   end To_Canonical_File_List;
3013
 
3014
   ----------------------------
3015
   -- To_Canonical_File_Spec --
3016
   ----------------------------
3017
 
3018
   function To_Canonical_File_Spec
3019
     (Host_File : String) return String_Access
3020
   is
3021
      function To_Canonical_File_Spec (Host_File : Address) return Address;
3022
      pragma Import
3023
        (C, To_Canonical_File_Spec, "__gnat_to_canonical_file_spec");
3024
 
3025
      C_Host_File         : String (1 .. Host_File'Length + 1);
3026
      Canonical_File_Addr : Address;
3027
      Canonical_File_Len  : Integer;
3028
 
3029
   begin
3030
      C_Host_File (1 .. Host_File'Length) := Host_File;
3031
      C_Host_File (C_Host_File'Last)      := ASCII.NUL;
3032
 
3033
      Canonical_File_Addr := To_Canonical_File_Spec (C_Host_File'Address);
3034
      Canonical_File_Len  := C_String_Length (Canonical_File_Addr);
3035
 
3036
      if Canonical_File_Len = 0 then
3037
         return null;
3038
      else
3039
         return To_Path_String_Access
3040
                  (Canonical_File_Addr, Canonical_File_Len);
3041
      end if;
3042
 
3043
   exception
3044
      when others =>
3045
         Fail ("erroneous file spec: " & Host_File);
3046
         return null;
3047
   end To_Canonical_File_Spec;
3048
 
3049
   ----------------------------
3050
   -- To_Canonical_Path_Spec --
3051
   ----------------------------
3052
 
3053
   function To_Canonical_Path_Spec
3054
     (Host_Path : String) return String_Access
3055
   is
3056
      function To_Canonical_Path_Spec (Host_Path : Address) return Address;
3057
      pragma Import
3058
        (C, To_Canonical_Path_Spec, "__gnat_to_canonical_path_spec");
3059
 
3060
      C_Host_Path         : String (1 .. Host_Path'Length + 1);
3061
      Canonical_Path_Addr : Address;
3062
      Canonical_Path_Len  : Integer;
3063
 
3064
   begin
3065
      C_Host_Path (1 .. Host_Path'Length) := Host_Path;
3066
      C_Host_Path (C_Host_Path'Last)      := ASCII.NUL;
3067
 
3068
      Canonical_Path_Addr := To_Canonical_Path_Spec (C_Host_Path'Address);
3069
      Canonical_Path_Len  := C_String_Length (Canonical_Path_Addr);
3070
 
3071
      --  Return a null string (vice a null) for zero length paths, for
3072
      --  compatibility with getenv().
3073
 
3074
      return To_Path_String_Access (Canonical_Path_Addr, Canonical_Path_Len);
3075
 
3076
   exception
3077
      when others =>
3078
         Fail ("erroneous path spec: " & Host_Path);
3079
         return null;
3080
   end To_Canonical_Path_Spec;
3081
 
3082
   ---------------------------
3083
   -- To_Host_Dir_Spec --
3084
   ---------------------------
3085
 
3086
   function To_Host_Dir_Spec
3087
     (Canonical_Dir : String;
3088
      Prefix_Style  : Boolean) return String_Access
3089
   is
3090
      function To_Host_Dir_Spec
3091
        (Canonical_Dir : Address;
3092
         Prefix_Flag   : Integer) return Address;
3093
      pragma Import (C, To_Host_Dir_Spec, "__gnat_to_host_dir_spec");
3094
 
3095
      C_Canonical_Dir : String (1 .. Canonical_Dir'Length + 1);
3096
      Host_Dir_Addr   : Address;
3097
      Host_Dir_Len    : Integer;
3098
 
3099
   begin
3100
      C_Canonical_Dir (1 .. Canonical_Dir'Length) := Canonical_Dir;
3101
      C_Canonical_Dir (C_Canonical_Dir'Last)      := ASCII.NUL;
3102
 
3103
      if Prefix_Style then
3104
         Host_Dir_Addr := To_Host_Dir_Spec (C_Canonical_Dir'Address, 1);
3105
      else
3106
         Host_Dir_Addr := To_Host_Dir_Spec (C_Canonical_Dir'Address, 0);
3107
      end if;
3108
      Host_Dir_Len := C_String_Length (Host_Dir_Addr);
3109
 
3110
      if Host_Dir_Len = 0 then
3111
         return null;
3112
      else
3113
         return To_Path_String_Access (Host_Dir_Addr, Host_Dir_Len);
3114
      end if;
3115
   end To_Host_Dir_Spec;
3116
 
3117
   ----------------------------
3118
   -- To_Host_File_Spec --
3119
   ----------------------------
3120
 
3121
   function To_Host_File_Spec
3122
     (Canonical_File : String) return String_Access
3123
   is
3124
      function To_Host_File_Spec (Canonical_File : Address) return Address;
3125
      pragma Import (C, To_Host_File_Spec, "__gnat_to_host_file_spec");
3126
 
3127
      C_Canonical_File      : String (1 .. Canonical_File'Length + 1);
3128
      Host_File_Addr : Address;
3129
      Host_File_Len  : Integer;
3130
 
3131
   begin
3132
      C_Canonical_File (1 .. Canonical_File'Length) := Canonical_File;
3133
      C_Canonical_File (C_Canonical_File'Last)      := ASCII.NUL;
3134
 
3135
      Host_File_Addr := To_Host_File_Spec (C_Canonical_File'Address);
3136
      Host_File_Len  := C_String_Length (Host_File_Addr);
3137
 
3138
      if Host_File_Len = 0 then
3139
         return null;
3140
      else
3141
         return To_Path_String_Access
3142
                  (Host_File_Addr, Host_File_Len);
3143
      end if;
3144
   end To_Host_File_Spec;
3145
 
3146
   ---------------------------
3147
   -- To_Path_String_Access --
3148
   ---------------------------
3149
 
3150
   function To_Path_String_Access
3151
     (Path_Addr : Address;
3152
      Path_Len  : Integer) return String_Access
3153
   is
3154
      subtype Path_String is String (1 .. Path_Len);
3155
      type Path_String_Access is access Path_String;
3156
 
3157
      function Address_To_Access is new
3158
        Unchecked_Conversion (Source => Address,
3159
                              Target => Path_String_Access);
3160
 
3161
      Path_Access : constant Path_String_Access :=
3162
                      Address_To_Access (Path_Addr);
3163
 
3164
      Return_Val : String_Access;
3165
 
3166
   begin
3167
      Return_Val := new String (1 .. Path_Len);
3168
 
3169
      for J in 1 .. Path_Len loop
3170
         Return_Val (J) := Path_Access (J);
3171
      end loop;
3172
 
3173
      return Return_Val;
3174
   end To_Path_String_Access;
3175
 
3176
   -----------------
3177
   -- Update_Path --
3178
   -----------------
3179
 
3180
   function Update_Path (Path : String_Ptr) return String_Ptr is
3181
 
3182
      function C_Update_Path (Path, Component : Address) return Address;
3183
      pragma Import (C, C_Update_Path, "update_path");
3184
 
3185
      function Strlen (Str : Address) return Integer;
3186
      pragma Import (C, Strlen, "strlen");
3187
 
3188
      procedure Strncpy (X : Address; Y : Address; Length : Integer);
3189
      pragma Import (C, Strncpy, "strncpy");
3190
 
3191
      In_Length      : constant Integer := Path'Length;
3192
      In_String      : String (1 .. In_Length + 1);
3193
      Component_Name : aliased String := "GCC" & ASCII.NUL;
3194
      Result_Ptr     : Address;
3195
      Result_Length  : Integer;
3196
      Out_String     : String_Ptr;
3197
 
3198
   begin
3199
      In_String (1 .. In_Length) := Path.all;
3200
      In_String (In_Length + 1) := ASCII.NUL;
3201
      Result_Ptr := C_Update_Path (In_String'Address, Component_Name'Address);
3202
      Result_Length := Strlen (Result_Ptr);
3203
 
3204
      Out_String := new String (1 .. Result_Length);
3205
      Strncpy (Out_String.all'Address, Result_Ptr, Result_Length);
3206
      return Out_String;
3207
   end Update_Path;
3208
 
3209
   ----------------
3210
   -- Write_Info --
3211
   ----------------
3212
 
3213
   procedure Write_Info (Info : String) is
3214
   begin
3215
      Write_With_Check (Info'Address, Info'Length);
3216
      Write_With_Check (EOL'Address, 1);
3217
   end Write_Info;
3218
 
3219
   ------------------------
3220
   -- Write_Program_Name --
3221
   ------------------------
3222
 
3223
   procedure Write_Program_Name is
3224
      Save_Buffer : constant String (1 .. Name_Len) :=
3225
                      Name_Buffer (1 .. Name_Len);
3226
 
3227
   begin
3228
      Find_Program_Name;
3229
 
3230
      --  Convert the name to lower case so error messages are the same on
3231
      --  all systems.
3232
 
3233
      for J in 1 .. Name_Len loop
3234
         if Name_Buffer (J) in 'A' .. 'Z' then
3235
            Name_Buffer (J) :=
3236
              Character'Val (Character'Pos (Name_Buffer (J)) + 32);
3237
         end if;
3238
      end loop;
3239
 
3240
      Write_Str (Name_Buffer (1 .. Name_Len));
3241
 
3242
      --  Restore Name_Buffer which was clobbered by the call to
3243
      --  Find_Program_Name
3244
 
3245
      Name_Len := Save_Buffer'Last;
3246
      Name_Buffer (1 .. Name_Len) := Save_Buffer;
3247
   end Write_Program_Name;
3248
 
3249
   ----------------------
3250
   -- Write_With_Check --
3251
   ----------------------
3252
 
3253
   procedure Write_With_Check (A  : Address; N  : Integer) is
3254
      Ignore : Boolean;
3255
      pragma Warnings (Off, Ignore);
3256
 
3257
   begin
3258
      if N = Write (Output_FD, A, N) then
3259
         return;
3260
 
3261
      else
3262
         Write_Str ("error: disk full writing ");
3263
         Write_Name_Decoded (Output_File_Name);
3264
         Write_Eol;
3265
         Name_Len := Name_Len + 1;
3266
         Name_Buffer (Name_Len) := ASCII.NUL;
3267
         Delete_File (Name_Buffer'Address, Ignore);
3268
         Exit_Program (E_Fatal);
3269
      end if;
3270
   end Write_With_Check;
3271
 
3272
----------------------------
3273
-- Package Initialization --
3274
----------------------------
3275
 
3276
   procedure Reset_File_Attributes (Attr : System.Address);
3277
   pragma Import (C, Reset_File_Attributes, "__gnat_reset_attributes");
3278
 
3279
begin
3280
   Initialization : declare
3281
 
3282
      function Get_Default_Identifier_Character_Set return Character;
3283
      pragma Import (C, Get_Default_Identifier_Character_Set,
3284
                       "__gnat_get_default_identifier_character_set");
3285
      --  Function to determine the default identifier character set,
3286
      --  which is system dependent. See Opt package spec for a list of
3287
      --  the possible character codes and their interpretations.
3288
 
3289
      function Get_Maximum_File_Name_Length return Int;
3290
      pragma Import (C, Get_Maximum_File_Name_Length,
3291
                    "__gnat_get_maximum_file_name_length");
3292
      --  Function to get maximum file name length for system
3293
 
3294
      Sizeof_File_Attributes : Integer;
3295
      pragma Import (C, Sizeof_File_Attributes,
3296
                     "__gnat_size_of_file_attributes");
3297
 
3298
   begin
3299
      pragma Assert (Sizeof_File_Attributes <= File_Attributes_Size);
3300
 
3301
      Reset_File_Attributes (Unknown_Attributes'Address);
3302
 
3303
      Identifier_Character_Set := Get_Default_Identifier_Character_Set;
3304
      Maximum_File_Name_Length := Get_Maximum_File_Name_Length;
3305
 
3306
      --  Following should be removed by having above function return
3307
      --  Integer'Last as indication of no maximum instead of -1 ???
3308
 
3309
      if Maximum_File_Name_Length = -1 then
3310
         Maximum_File_Name_Length := Int'Last;
3311
      end if;
3312
 
3313
      Src_Search_Directories.Set_Last (Primary_Directory);
3314
      Src_Search_Directories.Table (Primary_Directory) := new String'("");
3315
 
3316
      Lib_Search_Directories.Set_Last (Primary_Directory);
3317
      Lib_Search_Directories.Table (Primary_Directory) := new String'("");
3318
 
3319
      Osint.Initialize;
3320
   end Initialization;
3321
 
3322
end Osint;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.