]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/ada/makeutl.adb
Fix for PR40616: missing java.io.PrintStream constructors.
[thirdparty/gcc.git] / gcc / ada / makeutl.adb
CommitLineData
8f9df7d8
VC
1------------------------------------------------------------------------------
2-- --
3-- GNAT COMPILER COMPONENTS --
4-- --
5-- M A K E U T L --
6-- --
7-- B o d y --
8-- --
74744c7b 9-- Copyright (C) 2004-2009, Free Software Foundation, Inc. --
8f9df7d8
VC
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- --
b5c84c3c 13-- ware Foundation; either version 3, or (at your option) any later ver- --
8f9df7d8
VC
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 --
b5c84c3c
RD
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. --
8f9df7d8
VC
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
38990220 26with ALI; use ALI;
7d903840 27with Debug;
5950a3ac 28with Osint; use Osint;
2cd44f5a 29with Output; use Output;
f7e71125 30with Opt; use Opt;
8f9df7d8
VC
31with Prj.Ext;
32with Prj.Util;
5950a3ac 33with Snames; use Snames;
8f9df7d8 34with Table;
8f9df7d8 35
7d903840
AC
36with Ada.Command_Line; use Ada.Command_Line;
37
38with GNAT.Directory_Operations; use GNAT.Directory_Operations;
39
958a816e 40with System.Case_Util; use System.Case_Util;
aa720a54
AC
41with System.HTable;
42
8f9df7d8
VC
43package body Makeutl is
44
aa720a54
AC
45 type Mark_Key is record
46 File : File_Name_Type;
47 Index : Int;
48 end record;
49 -- Identify either a mono-unit source (when Index = 0) or a specific unit
7d903840 50 -- (index = 1's origin index of unit) in a multi-unit source.
aa720a54 51
5950a3ac
AC
52 -- There follow many global undocumented declarations, comments needed ???
53
aa720a54
AC
54 Max_Mask_Num : constant := 2048;
55
56 subtype Mark_Num is Union_Id range 0 .. Max_Mask_Num - 1;
57
58 function Hash (Key : Mark_Key) return Mark_Num;
59
60 package Marks is new System.HTable.Simple_HTable
61 (Header_Num => Mark_Num,
62 Element => Boolean,
63 No_Element => False,
64 Key => Mark_Key,
65 Hash => Hash,
66 Equal => "=");
9de61fcb 67 -- A hash table to keep tracks of the marked units
aa720a54 68
8f9df7d8
VC
69 type Linker_Options_Data is record
70 Project : Project_Id;
71 Options : String_List_Id;
72 end record;
73
74 Linker_Option_Initial_Count : constant := 20;
75
76 Linker_Options_Buffer : String_List_Access :=
77 new String_List (1 .. Linker_Option_Initial_Count);
78
79 Last_Linker_Option : Natural := 0;
80
81 package Linker_Opts is new Table.Table (
82 Table_Component_Type => Linker_Options_Data,
83 Table_Index_Type => Integer,
84 Table_Low_Bound => 1,
85 Table_Initial => 10,
86 Table_Increment => 100,
87 Table_Name => "Make.Linker_Opts");
88
89 procedure Add_Linker_Option (Option : String);
90
2cd44f5a
VC
91 ---------
92 -- Add --
93 ---------
94
95 procedure Add
96 (Option : String_Access;
97 To : in out String_List_Access;
98 Last : in out Natural)
99 is
100 begin
101 if Last = To'Last then
102 declare
103 New_Options : constant String_List_Access :=
104 new String_List (1 .. To'Last * 2);
74744c7b 105
2cd44f5a
VC
106 begin
107 New_Options (To'Range) := To.all;
108
109 -- Set all elements of the original options to null to avoid
110 -- deallocation of copies.
111
112 To.all := (others => null);
113
114 Free (To);
115 To := New_Options;
116 end;
117 end if;
118
119 Last := Last + 1;
120 To (Last) := Option;
121 end Add;
122
123 procedure Add
124 (Option : String;
125 To : in out String_List_Access;
126 Last : in out Natural)
127 is
128 begin
129 Add (Option => new String'(Option), To => To, Last => Last);
130 end Add;
131
8f9df7d8
VC
132 -----------------------
133 -- Add_Linker_Option --
134 -----------------------
135
136 procedure Add_Linker_Option (Option : String) is
137 begin
138 if Option'Length > 0 then
139 if Last_Linker_Option = Linker_Options_Buffer'Last then
140 declare
141 New_Buffer : constant String_List_Access :=
5950a3ac
AC
142 new String_List
143 (1 .. Linker_Options_Buffer'Last +
144 Linker_Option_Initial_Count);
8f9df7d8
VC
145 begin
146 New_Buffer (Linker_Options_Buffer'Range) :=
147 Linker_Options_Buffer.all;
148 Linker_Options_Buffer.all := (others => null);
149 Free (Linker_Options_Buffer);
150 Linker_Options_Buffer := New_Buffer;
151 end;
152 end if;
153
154 Last_Linker_Option := Last_Linker_Option + 1;
155 Linker_Options_Buffer (Last_Linker_Option) := new String'(Option);
156 end if;
157 end Add_Linker_Option;
158
38990220
EB
159 ------------------------------
160 -- Check_Source_Info_In_ALI --
161 ------------------------------
162
163 function Check_Source_Info_In_ALI (The_ALI : ALI_Id) return Boolean is
164 Unit_Name : Name_Id;
165 begin
166 U_Chk :
167 for U in ALIs.Table (The_ALI).First_Unit
168 .. ALIs.Table (The_ALI).Last_Unit
169 loop
170 -- Check if the file name is one of the source of the unit.
171
172 Get_Name_String (Units.Table (U).Uname);
173 Name_Len := Name_Len - 2;
174 Unit_Name := Name_Find;
175
176 if File_Not_A_Source_Of (Unit_Name, Units.Table (U).Sfile) then
177 return False;
178 end if;
179
180 -- Do the same check for each of the withed units
181
182 W_Check :
183 for W in Units.Table (U).First_With .. Units.Table (U).Last_With loop
184 declare
185 WR : ALI.With_Record renames Withs.Table (W);
186 begin
187 if WR.Sfile /= No_File then
188 Get_Name_String (WR.Uname);
189 Name_Len := Name_Len - 2;
190 Unit_Name := Name_Find;
191
192 if File_Not_A_Source_Of (Unit_Name, WR.Sfile) then
193 return False;
194 end if;
195 end if;
196 end;
197 end loop W_Check;
198 end loop U_Chk;
199
200 -- Check also the subunits
201
202 D_Check :
203 for D in ALIs.Table (The_ALI).First_Sdep
204 .. ALIs.Table (The_ALI).Last_Sdep
205 loop
206 declare
207 SD : Sdep_Record renames Sdep.Table (D);
208 begin
209 Unit_Name := SD.Subunit_Name;
210
211 if Unit_Name /= No_Name then
212 -- For separates, the file is no longer associated with the
213 -- unit ("proc-sep.adb" is not associated with unit "proc.sep".
214 -- So we need to check whether the source file still exists in
215 -- the source tree: it will if it matches the naming scheme
216 -- (and then will be for the same unit).
217
218 if Find_Source
219 (In_Tree => Project_Tree,
220 Project => No_Project,
221 Base_Name => SD.Sfile) = No_Source
222 then
223 -- If this is not a runtime file (when using -a) ? Otherwise
224 -- we get complaints about a-except.adb, which uses
225 -- separates.
226
227 if not Check_Readonly_Files
228 or else Find_File (SD.Sfile, Osint.Source) = No_File
229 then
230 if Verbose_Mode then
231 Write_Line
232 ("While parsing ALI file: Sdep associates "
233 & Get_Name_String (SD.Sfile)
234 & " with unit " & Get_Name_String (Unit_Name)
235 & " but this does not match what was found while"
236 & " parsing the project. Will recompile");
237 end if;
238 return False;
239 end if;
240 end if;
241 end if;
242 end;
243 end loop D_Check;
244
245 return True;
246 end Check_Source_Info_In_ALI;
247
2cd44f5a
VC
248 -----------------
249 -- Create_Name --
250 -----------------
251
252 function Create_Name (Name : String) return File_Name_Type is
253 begin
254 Name_Len := 0;
255 Add_Str_To_Name_Buffer (Name);
256 return Name_Find;
257 end Create_Name;
258
259 function Create_Name (Name : String) return Name_Id is
260 begin
261 Name_Len := 0;
262 Add_Str_To_Name_Buffer (Name);
263 return Name_Find;
264 end Create_Name;
265
266 function Create_Name (Name : String) return Path_Name_Type is
267 begin
268 Name_Len := 0;
269 Add_Str_To_Name_Buffer (Name);
270 return Name_Find;
271 end Create_Name;
272
aa720a54
AC
273 ----------------------
274 -- Delete_All_Marks --
275 ----------------------
276
277 procedure Delete_All_Marks is
278 begin
279 Marks.Reset;
280 end Delete_All_Marks;
281
958a816e
VC
282 ----------------------------
283 -- Executable_Prefix_Path --
284 ----------------------------
285
286 function Executable_Prefix_Path return String is
287 Exec_Name : constant String := Command_Name;
288
289 function Get_Install_Dir (S : String) return String;
74744c7b
AC
290 -- S is the executable name preceded by the absolute or relative path,
291 -- e.g. "c:\usr\bin\gcc.exe". Returns the absolute directory where "bin"
292 -- lies (in the example "C:\usr"). If the executable is not in a "bin"
293 -- directory, return "".
958a816e
VC
294
295 ---------------------
296 -- Get_Install_Dir --
297 ---------------------
298
299 function Get_Install_Dir (S : String) return String is
300 Exec : String := S;
301 Path_Last : Integer := 0;
302
303 begin
304 for J in reverse Exec'Range loop
305 if Exec (J) = Directory_Separator then
306 Path_Last := J - 1;
307 exit;
308 end if;
309 end loop;
310
311 if Path_Last >= Exec'First + 2 then
312 To_Lower (Exec (Path_Last - 2 .. Path_Last));
313 end if;
314
315 if Path_Last < Exec'First + 2
316 or else Exec (Path_Last - 2 .. Path_Last) /= "bin"
317 or else (Path_Last - 3 >= Exec'First
318 and then Exec (Path_Last - 3) /= Directory_Separator)
319 then
320 return "";
321 end if;
322
659819b9
AC
323 return Normalize_Pathname (Exec (Exec'First .. Path_Last - 4))
324 & Directory_Separator;
958a816e
VC
325 end Get_Install_Dir;
326
327 -- Beginning of Executable_Prefix_Path
328
329 begin
330 -- First determine if a path prefix was placed in front of the
331 -- executable name.
332
333 for J in reverse Exec_Name'Range loop
334 if Exec_Name (J) = Directory_Separator then
335 return Get_Install_Dir (Exec_Name);
336 end if;
337 end loop;
338
339 -- If we get here, the user has typed the executable name with no
340 -- directory prefix.
341
67d7b0ab 342 declare
659819b9 343 Path : String_Access := Locate_Exec_On_Path (Exec_Name);
67d7b0ab
VC
344 begin
345 if Path = null then
346 return "";
67d7b0ab 347 else
659819b9
AC
348 declare
349 Dir : constant String := Get_Install_Dir (Path.all);
350 begin
351 Free (Path);
352 return Dir;
353 end;
67d7b0ab
VC
354 end if;
355 end;
958a816e
VC
356 end Executable_Prefix_Path;
357
f7e71125
AC
358 --------------------------
359 -- File_Not_A_Source_Of --
360 --------------------------
361
362 function File_Not_A_Source_Of
363 (Uname : Name_Id;
364 Sfile : File_Name_Type) return Boolean
365 is
366 Unit : constant Unit_Index :=
367 Units_Htable.Get (Project_Tree.Units_HT, Uname);
368
369 At_Least_One_File : Boolean := False;
370
371 begin
372 if Unit /= No_Unit_Index then
373 for F in Unit.File_Names'Range loop
374 if Unit.File_Names (F) /= null then
375 At_Least_One_File := True;
376 if Unit.File_Names (F).File = Sfile then
377 return False;
378 end if;
379 end if;
380 end loop;
381
382 if not At_Least_One_File then
383
384 -- The unit was probably created initially for a separate unit
385 -- (which are initially created as IMPL when both suffixes are the
386 -- same). Later on, Override_Kind changed the type of the file,
387 -- and the unit is no longer valid in fact.
388
389 return False;
390 end if;
391
392 Verbose_Msg (Uname, "sources do not include ", Name_Id (Sfile));
393 return True;
394 end if;
395
396 return False;
397 end File_Not_A_Source_Of;
398
aa720a54
AC
399 ----------
400 -- Hash --
401 ----------
402
403 function Hash (Key : Mark_Key) return Mark_Num is
404 begin
405 return Union_Id (Key.File) mod Max_Mask_Num;
406 end Hash;
407
2cd44f5a
VC
408 ------------
409 -- Inform --
410 ------------
411
412 procedure Inform (N : File_Name_Type; Msg : String) is
413 begin
414 Inform (Name_Id (N), Msg);
415 end Inform;
416
417 procedure Inform (N : Name_Id := No_Name; Msg : String) is
418 begin
419 Osint.Write_Program_Name;
420
421 Write_Str (": ");
422
423 if N /= No_Name then
424 Write_Str ("""");
7d903840
AC
425
426 declare
427 Name : constant String := Get_Name_String (N);
428 begin
429 if Debug.Debug_Flag_F and then Is_Absolute_Path (Name) then
430 Write_Str (File_Name (Name));
431 else
432 Write_Str (Name);
433 end if;
434 end;
435
2cd44f5a
VC
436 Write_Str (""" ");
437 end if;
438
439 Write_Str (Msg);
440 Write_Eol;
441 end Inform;
442
8f9df7d8
VC
443 ----------------------------
444 -- Is_External_Assignment --
445 ----------------------------
446
447 function Is_External_Assignment (Argv : String) return Boolean is
448 Start : Positive := 3;
449 Finish : Natural := Argv'Last;
450 Equal_Pos : Natural;
451
bfc8aa81
RD
452 pragma Assert (Argv'First = 1);
453 pragma Assert (Argv (1 .. 2) = "-X");
454
8f9df7d8
VC
455 begin
456 if Argv'Last < 5 then
457 return False;
458
459 elsif Argv (3) = '"' then
460 if Argv (Argv'Last) /= '"' or else Argv'Last < 7 then
461 return False;
462 else
463 Start := 4;
464 Finish := Argv'Last - 1;
465 end if;
466 end if;
467
468 Equal_Pos := Start;
469
470 while Equal_Pos <= Finish and then Argv (Equal_Pos) /= '=' loop
471 Equal_Pos := Equal_Pos + 1;
472 end loop;
473
74744c7b 474 if Equal_Pos = Start or else Equal_Pos > Finish then
8f9df7d8 475 return False;
8f9df7d8
VC
476 else
477 Prj.Ext.Add
478 (External_Name => Argv (Start .. Equal_Pos - 1),
479 Value => Argv (Equal_Pos + 1 .. Finish));
480 return True;
481 end if;
482 end Is_External_Assignment;
483
aa720a54
AC
484 ---------------
485 -- Is_Marked --
486 ---------------
487
488 function Is_Marked
489 (Source_File : File_Name_Type;
5950a3ac 490 Index : Int := 0) return Boolean
aa720a54
AC
491 is
492 begin
493 return Marks.Get (K => (File => Source_File, Index => Index));
494 end Is_Marked;
495
8f9df7d8
VC
496 -----------------------------
497 -- Linker_Options_Switches --
498 -----------------------------
499
500 function Linker_Options_Switches
7e98a4c6
VC
501 (Project : Project_Id;
502 In_Tree : Project_Tree_Ref) return String_List
8f9df7d8 503 is
8b9890fa 504 procedure Recursive_Add (Proj : Project_Id; Dummy : in out Boolean);
5950a3ac 505 -- The recursive routine used to add linker options
8f9df7d8 506
8b9890fa
EB
507 -------------------
508 -- Recursive_Add --
509 -------------------
8f9df7d8 510
8b9890fa
EB
511 procedure Recursive_Add (Proj : Project_Id; Dummy : in out Boolean) is
512 pragma Unreferenced (Dummy);
74744c7b 513
8f9df7d8 514 Linker_Package : Package_Id;
5950a3ac 515 Options : Variable_Value;
5950a3ac 516
8f9df7d8 517 begin
8b9890fa
EB
518 Linker_Package :=
519 Prj.Util.Value_Of
520 (Name => Name_Linker,
66713d62 521 In_Packages => Proj.Decl.Packages,
8b9890fa 522 In_Tree => In_Tree);
74744c7b 523
8b9890fa
EB
524 Options :=
525 Prj.Util.Value_Of
526 (Name => Name_Ada,
527 Index => 0,
528 Attribute_Or_Array_Name => Name_Linker_Options,
529 In_Package => Linker_Package,
530 In_Tree => In_Tree);
531
532 -- If attribute is present, add the project with
533 -- the attribute to table Linker_Opts.
534
535 if Options /= Nil_Variable_Value then
536 Linker_Opts.Increment_Last;
537 Linker_Opts.Table (Linker_Opts.Last) :=
538 (Project => Proj, Options => Options.Values);
8f9df7d8 539 end if;
8b9890fa
EB
540 end Recursive_Add;
541
542 procedure For_All_Projects is
543 new For_Every_Project_Imported (Boolean, Recursive_Add);
74744c7b 544
8b9890fa 545 Dummy : Boolean := False;
8f9df7d8 546
5950a3ac
AC
547 -- Start of processing for Linker_Options_Switches
548
8f9df7d8
VC
549 begin
550 Linker_Opts.Init;
551
66713d62 552 For_All_Projects (Project, Dummy, Imported_First => True);
8f9df7d8
VC
553
554 Last_Linker_Option := 0;
555
556 for Index in reverse 1 .. Linker_Opts.Last loop
557 declare
66713d62 558 Options : String_List_Id;
8f9df7d8 559 Proj : constant Project_Id :=
74744c7b 560 Linker_Opts.Table (Index).Project;
8f9df7d8 561 Option : Name_Id;
2324b3fd 562 Dir_Path : constant String :=
66713d62 563 Get_Name_String (Proj.Directory.Name);
8f9df7d8
VC
564
565 begin
66713d62 566 Options := Linker_Opts.Table (Index).Options;
8f9df7d8 567 while Options /= Nil_String loop
74744c7b 568 Option := In_Tree.String_Elements.Table (Options).Value;
f2c573b1
VC
569 Get_Name_String (Option);
570
571 -- Do not consider empty linker options
572
573 if Name_Len /= 0 then
574 Add_Linker_Option (Name_Buffer (1 .. Name_Len));
575
576 -- Object files and -L switches specified with relative
577 -- paths must be converted to absolute paths.
578
579 Test_If_Relative_Path
74744c7b 580 (Switch => Linker_Options_Buffer (Last_Linker_Option),
2324b3fd 581 Parent => Dir_Path,
f2c573b1
VC
582 Including_L_Switch => True);
583 end if;
584
66713d62 585 Options := In_Tree.String_Elements.Table (Options).Next;
8f9df7d8
VC
586 end loop;
587 end;
588 end loop;
589
590 return Linker_Options_Buffer (1 .. Last_Linker_Option);
591 end Linker_Options_Switches;
592
593 -----------
594 -- Mains --
595 -----------
596
597 package body Mains is
598
1e887886
VC
599 type File_And_Loc is record
600 File_Name : File_Name_Type;
601 Location : Source_Ptr := No_Location;
602 end record;
603
8f9df7d8 604 package Names is new Table.Table
1e887886 605 (Table_Component_Type => File_And_Loc,
8f9df7d8
VC
606 Table_Index_Type => Integer,
607 Table_Low_Bound => 1,
608 Table_Initial => 10,
609 Table_Increment => 100,
610 Table_Name => "Makeutl.Mains.Names");
611 -- The table that stores the mains
612
613 Current : Natural := 0;
614 -- The index of the last main retrieved from the table
615
616 --------------
617 -- Add_Main --
618 --------------
619
620 procedure Add_Main (Name : String) is
621 begin
622 Name_Len := 0;
623 Add_Str_To_Name_Buffer (Name);
624 Names.Increment_Last;
1e887886 625 Names.Table (Names.Last) := (Name_Find, No_Location);
8f9df7d8
VC
626 end Add_Main;
627
628 ------------
629 -- Delete --
630 ------------
631
632 procedure Delete is
633 begin
634 Names.Set_Last (0);
7e98a4c6 635 Mains.Reset;
8f9df7d8
VC
636 end Delete;
637
1e887886
VC
638 ------------------
639 -- Get_Location --
640 ------------------
641
642 function Get_Location return Source_Ptr is
643 begin
a573518c
TQ
644 if Current in Names.First .. Names.Last then
645 return Names.Table (Current).Location;
1e887886 646 else
a573518c 647 return No_Location;
1e887886
VC
648 end if;
649 end Get_Location;
650
8f9df7d8
VC
651 ---------------
652 -- Next_Main --
653 ---------------
654
655 function Next_Main return String is
656 begin
657 if Current >= Names.Last then
658 return "";
8f9df7d8
VC
659 else
660 Current := Current + 1;
1e887886 661 return Get_Name_String (Names.Table (Current).File_Name);
8f9df7d8
VC
662 end if;
663 end Next_Main;
664
665 ---------------------
666 -- Number_Of_Mains --
667 ---------------------
668
669 function Number_Of_Mains return Natural is
670 begin
671 return Names.Last;
672 end Number_Of_Mains;
673
674 -----------
675 -- Reset --
676 -----------
677
678 procedure Reset is
679 begin
680 Current := 0;
681 end Reset;
682
1e887886
VC
683 ------------------
684 -- Set_Location --
685 ------------------
686
687 procedure Set_Location (Location : Source_Ptr) is
688 begin
689 if Names.Last > 0 then
690 Names.Table (Names.Last).Location := Location;
691 end if;
692 end Set_Location;
693
694 -----------------
695 -- Update_Main --
696 -----------------
697
698 procedure Update_Main (Name : String) is
699 begin
a573518c 700 if Current in Names.First .. Names.Last then
1e887886
VC
701 Name_Len := 0;
702 Add_Str_To_Name_Buffer (Name);
703 Names.Table (Current).File_Name := Name_Find;
704 end if;
705 end Update_Main;
8f9df7d8
VC
706 end Mains;
707
aa720a54
AC
708 ----------
709 -- Mark --
710 ----------
711
712 procedure Mark (Source_File : File_Name_Type; Index : Int := 0) is
713 begin
714 Marks.Set (K => (File => Source_File, Index => Index), E => True);
715 end Mark;
716
7d903840
AC
717 -----------------------
718 -- Path_Or_File_Name --
719 -----------------------
720
721 function Path_Or_File_Name (Path : Path_Name_Type) return String is
722 Path_Name : constant String := Get_Name_String (Path);
723 begin
724 if Debug.Debug_Flag_F then
725 return File_Name (Path_Name);
726 else
727 return Path_Name;
728 end if;
729 end Path_Or_File_Name;
730
8f9df7d8
VC
731 ---------------------------
732 -- Test_If_Relative_Path --
733 ---------------------------
734
735 procedure Test_If_Relative_Path
1086c39b 736 (Switch : in out String_Access;
2324b3fd 737 Parent : String;
1086c39b 738 Including_L_Switch : Boolean := True;
35debead
EB
739 Including_Non_Switch : Boolean := True;
740 Including_RTS : Boolean := False)
8f9df7d8
VC
741 is
742 begin
743 if Switch /= null then
8f9df7d8 744 declare
74744c7b 745 Sw : String (1 .. Switch'Length);
8f9df7d8
VC
746 Start : Positive;
747
748 begin
749 Sw := Switch.all;
750
751 if Sw (1) = '-' then
752 if Sw'Length >= 3
753 and then (Sw (2) = 'A'
74744c7b
AC
754 or else Sw (2) = 'I'
755 or else (Including_L_Switch and then Sw (2) = 'L'))
8f9df7d8
VC
756 then
757 Start := 3;
758
759 if Sw = "-I-" then
760 return;
761 end if;
762
763 elsif Sw'Length >= 4
764 and then (Sw (2 .. 3) = "aL"
74744c7b
AC
765 or else Sw (2 .. 3) = "aO"
766 or else Sw (2 .. 3) = "aI")
8f9df7d8
VC
767 then
768 Start := 4;
769
35debead
EB
770 elsif Including_RTS
771 and then Sw'Length >= 7
772 and then Sw (2 .. 6) = "-RTS="
773 then
774 Start := 7;
775
8f9df7d8
VC
776 else
777 return;
778 end if;
779
780 -- Because relative path arguments to --RTS= may be relative
781 -- to the search directory prefix, those relative path
35debead
EB
782 -- arguments are converted only when they include directory
783 -- information.
8f9df7d8
VC
784
785 if not Is_Absolute_Path (Sw (Start .. Sw'Last)) then
2324b3fd 786 if Parent'Length = 0 then
8f9df7d8 787 Do_Fail
3dd9959c
AC
788 ("relative search path switches ("""
789 & Sw
790 & """) are not allowed");
8f9df7d8 791
35debead
EB
792 elsif Including_RTS then
793 for J in Start .. Sw'Last loop
794 if Sw (J) = Directory_Separator then
795 Switch :=
796 new String'
797 (Sw (1 .. Start - 1) &
798 Parent &
799 Directory_Separator &
800 Sw (Start .. Sw'Last));
801 return;
802 end if;
803 end loop;
804
8f9df7d8
VC
805 else
806 Switch :=
807 new String'
808 (Sw (1 .. Start - 1) &
2324b3fd 809 Parent &
8f9df7d8
VC
810 Directory_Separator &
811 Sw (Start .. Sw'Last));
812 end if;
813 end if;
814
1086c39b 815 elsif Including_Non_Switch then
8f9df7d8 816 if not Is_Absolute_Path (Sw) then
2324b3fd 817 if Parent'Length = 0 then
8f9df7d8 818 Do_Fail
3dd9959c 819 ("relative paths (""" & Sw & """) are not allowed");
8f9df7d8 820 else
2324b3fd 821 Switch := new String'(Parent & Directory_Separator & Sw);
8f9df7d8
VC
822 end if;
823 end if;
824 end if;
825 end;
826 end if;
827 end Test_If_Relative_Path;
828
aa720a54
AC
829 -------------------
830 -- Unit_Index_Of --
831 -------------------
832
833 function Unit_Index_Of (ALI_File : File_Name_Type) return Int is
834 Start : Natural;
835 Finish : Natural;
836 Result : Int := 0;
5950a3ac 837
aa720a54
AC
838 begin
839 Get_Name_String (ALI_File);
840
841 -- First, find the last dot
842
843 Finish := Name_Len;
844
845 while Finish >= 1 and then Name_Buffer (Finish) /= '.' loop
846 Finish := Finish - 1;
847 end loop;
848
849 if Finish = 1 then
850 return 0;
851 end if;
852
853 -- Now check that the dot is preceded by digits
854
855 Start := Finish;
856 Finish := Finish - 1;
857
858 while Start >= 1 and then Name_Buffer (Start - 1) in '0' .. '9' loop
859 Start := Start - 1;
860 end loop;
861
74744c7b
AC
862 -- If there are no digits, or if the digits are not preceded by the
863 -- character that precedes a unit index, this is not the ALI file of
864 -- a unit in a multi-unit source.
aa720a54 865
5950a3ac
AC
866 if Start > Finish
867 or else Start = 1
868 or else Name_Buffer (Start - 1) /= Multi_Unit_Index_Character
aa720a54
AC
869 then
870 return 0;
871 end if;
872
873 -- Build the index from the digit(s)
874
875 while Start <= Finish loop
5950a3ac
AC
876 Result := Result * 10 +
877 Character'Pos (Name_Buffer (Start)) - Character'Pos ('0');
aa720a54
AC
878 Start := Start + 1;
879 end loop;
880
881 return Result;
882 end Unit_Index_Of;
883
f7e71125
AC
884 -----------------
885 -- Verbose_Msg --
886 -----------------
887
888 procedure Verbose_Msg
889 (N1 : Name_Id;
890 S1 : String;
891 N2 : Name_Id := No_Name;
892 S2 : String := "";
893 Prefix : String := " -> ";
894 Minimum_Verbosity : Opt.Verbosity_Level_Type := Opt.Low)
895 is
896 begin
897 if not Opt.Verbose_Mode
898 or else Minimum_Verbosity > Opt.Verbosity_Level
899 then
900 return;
901 end if;
902
903 Write_Str (Prefix);
904 Write_Str ("""");
905 Write_Name (N1);
906 Write_Str (""" ");
907 Write_Str (S1);
908
909 if N2 /= No_Name then
910 Write_Str (" """);
911 Write_Name (N2);
912 Write_Str (""" ");
913 end if;
914
915 Write_Str (S2);
916 Write_Eol;
917 end Verbose_Msg;
918
919 procedure Verbose_Msg
920 (N1 : File_Name_Type;
921 S1 : String;
922 N2 : File_Name_Type := No_File;
923 S2 : String := "";
924 Prefix : String := " -> ";
925 Minimum_Verbosity : Opt.Verbosity_Level_Type := Opt.Low)
926 is
927 begin
928 Verbose_Msg
929 (Name_Id (N1), S1, Name_Id (N2), S2, Prefix, Minimum_Verbosity);
930 end Verbose_Msg;
931
8f9df7d8 932end Makeutl;