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