comparison gcc/ada/make_util.adb @ 111:04ced10e8804

gcc 7
author kono
date Fri, 27 Oct 2017 22:46:09 +0900
parents
children 84e7813d76e9
comparison
equal deleted inserted replaced
68:561a7518be6b 111:04ced10e8804
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT COMPILER COMPONENTS --
4 -- --
5 -- M A K E _ U T I L --
6 -- --
7 -- B o d y --
8 -- --
9 -- Copyright (C) 2004-2017, 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 Atree; use Atree;
27 with Debug;
28 with Errutil;
29 with Osint; use Osint;
30 with Output; use Output;
31 with Opt; use Opt;
32 with Table;
33
34 with Ada.Command_Line; use Ada.Command_Line;
35
36 with GNAT.Case_Util; use GNAT.Case_Util;
37 with GNAT.Directory_Operations; use GNAT.Directory_Operations;
38 with GNAT.HTable;
39
40 package body Make_Util is
41
42 ---------
43 -- Add --
44 ---------
45
46 procedure Add
47 (Option : String_Access;
48 To : in out String_List_Access;
49 Last : in out Natural)
50 is
51 begin
52 if Last = To'Last then
53 declare
54 New_Options : constant String_List_Access :=
55 new String_List (1 .. To'Last * 2);
56
57 begin
58 New_Options (To'Range) := To.all;
59
60 -- Set all elements of the original options to null to avoid
61 -- deallocation of copies.
62
63 To.all := (others => null);
64
65 Free (To);
66 To := New_Options;
67 end;
68 end if;
69
70 Last := Last + 1;
71 To (Last) := Option;
72 end Add;
73
74 procedure Add
75 (Option : String;
76 To : in out String_List_Access;
77 Last : in out Natural)
78 is
79 begin
80 Add (Option => new String'(Option), To => To, Last => Last);
81 end Add;
82
83 -------------------------
84 -- Base_Name_Index_For --
85 -------------------------
86
87 function Base_Name_Index_For
88 (Main : String;
89 Main_Index : Int;
90 Index_Separator : Character) return File_Name_Type
91 is
92 Result : File_Name_Type;
93
94 begin
95 Name_Len := 0;
96 Add_Str_To_Name_Buffer (Base_Name (Main));
97
98 -- Remove the extension, if any, that is the last part of the base name
99 -- starting with a dot and following some characters.
100
101 for J in reverse 2 .. Name_Len loop
102 if Name_Buffer (J) = '.' then
103 Name_Len := J - 1;
104 exit;
105 end if;
106 end loop;
107
108 -- Add the index info, if index is different from 0
109
110 if Main_Index > 0 then
111 Add_Char_To_Name_Buffer (Index_Separator);
112
113 declare
114 Img : constant String := Main_Index'Img;
115 begin
116 Add_Str_To_Name_Buffer (Img (2 .. Img'Last));
117 end;
118 end if;
119
120 Result := Name_Find;
121 return Result;
122 end Base_Name_Index_For;
123
124 -----------------
125 -- Create_Name --
126 -----------------
127
128 function Create_Name (Name : String) return File_Name_Type is
129 begin
130 Name_Len := 0;
131 Add_Str_To_Name_Buffer (Name);
132 return Name_Find;
133 end Create_Name;
134
135 function Create_Name (Name : String) return Name_Id is
136 begin
137 Name_Len := 0;
138 Add_Str_To_Name_Buffer (Name);
139 return Name_Find;
140 end Create_Name;
141
142 function Create_Name (Name : String) return Path_Name_Type is
143 begin
144 Name_Len := 0;
145 Add_Str_To_Name_Buffer (Name);
146 return Name_Find;
147 end Create_Name;
148
149 ---------------------------
150 -- Ensure_Absolute_Path --
151 ---------------------------
152
153 procedure Ensure_Absolute_Path
154 (Switch : in out String_Access;
155 Parent : String;
156 Do_Fail : Fail_Proc;
157 For_Gnatbind : Boolean := False;
158 Including_Non_Switch : Boolean := True;
159 Including_RTS : Boolean := False)
160 is
161 begin
162 if Switch /= null then
163 declare
164 Sw : String (1 .. Switch'Length);
165 Start : Positive;
166
167 begin
168 Sw := Switch.all;
169
170 if Sw (1) = '-' then
171 if Sw'Length >= 3
172 and then (Sw (2) = 'I'
173 or else (not For_Gnatbind
174 and then (Sw (2) = 'L'
175 or else
176 Sw (2) = 'A')))
177 then
178 Start := 3;
179
180 if Sw = "-I-" then
181 return;
182 end if;
183
184 elsif Sw'Length >= 4
185 and then
186 (Sw (2 .. 3) = "aL" or else
187 Sw (2 .. 3) = "aO" or else
188 Sw (2 .. 3) = "aI"
189 or else (For_Gnatbind and then Sw (2 .. 3) = "A="))
190 then
191 Start := 4;
192
193 elsif Including_RTS
194 and then Sw'Length >= 7
195 and then Sw (2 .. 6) = "-RTS="
196 then
197 Start := 7;
198
199 else
200 return;
201 end if;
202
203 -- Because relative path arguments to --RTS= may be relative to
204 -- the search directory prefix, those relative path arguments
205 -- are converted only when they include directory information.
206
207 if not Is_Absolute_Path (Sw (Start .. Sw'Last)) then
208 if Parent'Length = 0 then
209 Do_Fail
210 ("relative search path switches ("""
211 & Sw
212 & """) are not allowed");
213
214 elsif Including_RTS then
215 for J in Start .. Sw'Last loop
216 if Sw (J) = Directory_Separator then
217 Switch :=
218 new String'
219 (Sw (1 .. Start - 1)
220 & Parent
221 & Directory_Separator
222 & Sw (Start .. Sw'Last));
223 return;
224 end if;
225 end loop;
226
227 else
228 Switch :=
229 new String'
230 (Sw (1 .. Start - 1)
231 & Parent
232 & Directory_Separator
233 & Sw (Start .. Sw'Last));
234 end if;
235 end if;
236
237 elsif Including_Non_Switch then
238 if not Is_Absolute_Path (Sw) then
239 if Parent'Length = 0 then
240 Do_Fail
241 ("relative paths (""" & Sw & """) are not allowed");
242 else
243 Switch := new String'(Parent & Directory_Separator & Sw);
244 end if;
245 end if;
246 end if;
247 end;
248 end if;
249 end Ensure_Absolute_Path;
250
251 ----------------------------
252 -- Executable_Prefix_Path --
253 ----------------------------
254
255 function Executable_Prefix_Path return String is
256 Exec_Name : constant String := Command_Name;
257
258 function Get_Install_Dir (S : String) return String;
259 -- S is the executable name preceded by the absolute or relative path,
260 -- e.g. "c:\usr\bin\gcc.exe". Returns the absolute directory where "bin"
261 -- lies (in the example "C:\usr"). If the executable is not in a "bin"
262 -- directory, return "".
263
264 ---------------------
265 -- Get_Install_Dir --
266 ---------------------
267
268 function Get_Install_Dir (S : String) return String is
269 Exec : String := S;
270 Path_Last : Integer := 0;
271
272 begin
273 for J in reverse Exec'Range loop
274 if Exec (J) = Directory_Separator then
275 Path_Last := J - 1;
276 exit;
277 end if;
278 end loop;
279
280 if Path_Last >= Exec'First + 2 then
281 To_Lower (Exec (Path_Last - 2 .. Path_Last));
282 end if;
283
284 if Path_Last < Exec'First + 2
285 or else Exec (Path_Last - 2 .. Path_Last) /= "bin"
286 or else (Path_Last - 3 >= Exec'First
287 and then Exec (Path_Last - 3) /= Directory_Separator)
288 then
289 return "";
290 end if;
291
292 return Normalize_Pathname
293 (Exec (Exec'First .. Path_Last - 4),
294 Resolve_Links => Opt.Follow_Links_For_Dirs)
295 & Directory_Separator;
296 end Get_Install_Dir;
297
298 -- Beginning of Executable_Prefix_Path
299
300 begin
301 -- First determine if a path prefix was placed in front of the
302 -- executable name.
303
304 for J in reverse Exec_Name'Range loop
305 if Exec_Name (J) = Directory_Separator then
306 return Get_Install_Dir (Exec_Name);
307 end if;
308 end loop;
309
310 -- If we get here, the user has typed the executable name with no
311 -- directory prefix.
312
313 declare
314 Path : String_Access := Locate_Exec_On_Path (Exec_Name);
315 begin
316 if Path = null then
317 return "";
318 else
319 declare
320 Dir : constant String := Get_Install_Dir (Path.all);
321 begin
322 Free (Path);
323 return Dir;
324 end;
325 end if;
326 end;
327 end Executable_Prefix_Path;
328
329 ------------------
330 -- Fail_Program --
331 ------------------
332
333 procedure Fail_Program
334 (S : String;
335 Flush_Messages : Boolean := True)
336 is
337 begin
338 if Flush_Messages and not No_Exit_Message then
339 if Total_Errors_Detected /= 0 or else Warnings_Detected /= 0 then
340 Errutil.Finalize;
341 end if;
342 end if;
343
344 Finish_Program (E_Fatal, S => S);
345 end Fail_Program;
346
347 --------------------
348 -- Finish_Program --
349 --------------------
350
351 procedure Finish_Program
352 (Exit_Code : Osint.Exit_Code_Type := Osint.E_Success;
353 S : String := "")
354 is
355 begin
356 if S'Length > 0 then
357 if Exit_Code /= E_Success then
358 if No_Exit_Message then
359 Osint.Exit_Program (E_Fatal);
360 else
361 Osint.Fail (S);
362 end if;
363
364 elsif not No_Exit_Message then
365 Write_Str (S);
366 end if;
367 end if;
368
369 -- Output Namet statistics
370
371 Namet.Finalize;
372
373 Exit_Program (Exit_Code);
374 end Finish_Program;
375
376 ----------
377 -- Hash --
378 ----------
379
380 function Hash is new GNAT.HTable.Hash (Header_Num => Header_Num);
381 -- Used in implementation of other functions Hash below
382
383 ----------
384 -- Hash --
385 ----------
386
387 function Hash (Name : File_Name_Type) return Header_Num is
388 begin
389 return Hash (Get_Name_String (Name));
390 end Hash;
391
392 function Hash (Name : Name_Id) return Header_Num is
393 begin
394 return Hash (Get_Name_String (Name));
395 end Hash;
396
397 function Hash (Name : Path_Name_Type) return Header_Num is
398 begin
399 return Hash (Get_Name_String (Name));
400 end Hash;
401
402 ------------
403 -- Inform --
404 ------------
405
406 procedure Inform (N : File_Name_Type; Msg : String) is
407 begin
408 Inform (Name_Id (N), Msg);
409 end Inform;
410
411 procedure Inform (N : Name_Id := No_Name; Msg : String) is
412 begin
413 Osint.Write_Program_Name;
414
415 Write_Str (": ");
416
417 if N /= No_Name then
418 Write_Str ("""");
419
420 declare
421 Name : constant String := Get_Name_String (N);
422 begin
423 if Debug.Debug_Flag_F and then Is_Absolute_Path (Name) then
424 Write_Str (File_Name (Name));
425 else
426 Write_Str (Name);
427 end if;
428 end;
429
430 Write_Str (""" ");
431 end if;
432
433 Write_Str (Msg);
434 Write_Eol;
435 end Inform;
436
437 -----------
438 -- Mains --
439 -----------
440
441 package body Mains is
442
443 package Names is new Table.Table
444 (Table_Component_Type => Main_Info,
445 Table_Index_Type => Integer,
446 Table_Low_Bound => 1,
447 Table_Initial => 10,
448 Table_Increment => 100,
449 Table_Name => "Makeutl.Mains.Names");
450 -- The table that stores the mains
451
452 Current : Natural := 0;
453 -- The index of the last main retrieved from the table
454
455 Count_Of_Mains_With_No_Tree : Natural := 0;
456 -- Number of main units for which we do not know the project tree
457
458 --------------
459 -- Add_Main --
460 --------------
461
462 procedure Add_Main (Name : String; Index : Int := 0) is
463 begin
464 Name_Len := 0;
465 Add_Str_To_Name_Buffer (Name);
466 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
467
468 Names.Increment_Last;
469 Names.Table (Names.Last) := (Name_Find, Index);
470
471 Mains.Count_Of_Mains_With_No_Tree :=
472 Mains.Count_Of_Mains_With_No_Tree + 1;
473 end Add_Main;
474
475 ------------
476 -- Delete --
477 ------------
478
479 procedure Delete is
480 begin
481 Names.Set_Last (0);
482 Mains.Reset;
483 end Delete;
484
485 ---------------
486 -- Next_Main --
487 ---------------
488
489 function Next_Main return String is
490 Info : constant Main_Info := Next_Main;
491 begin
492 if Info = No_Main_Info then
493 return "";
494 else
495 return Get_Name_String (Info.File);
496 end if;
497 end Next_Main;
498
499 function Next_Main return Main_Info is
500 begin
501 if Current >= Names.Last then
502 return No_Main_Info;
503 else
504 Current := Current + 1;
505
506 declare
507 Orig_Main : constant File_Name_Type :=
508 Names.Table (Current).File;
509 Current_Main : File_Name_Type;
510
511 begin
512 if Strip_Suffix (Orig_Main) = Orig_Main then
513 Get_Name_String (Orig_Main);
514 Add_Str_To_Name_Buffer (".adb");
515 Current_Main := Name_Find;
516
517 if Full_Source_Name (Current_Main) = No_File then
518 Get_Name_String (Orig_Main);
519 Add_Str_To_Name_Buffer (".ads");
520 Current_Main := Name_Find;
521
522 if Full_Source_Name (Current_Main) /= No_File then
523 Names.Table (Current).File := Current_Main;
524 end if;
525
526 else
527 Names.Table (Current).File := Current_Main;
528 end if;
529 end if;
530 end;
531
532 return Names.Table (Current);
533 end if;
534 end Next_Main;
535
536 ---------------------
537 -- Number_Of_Mains --
538 ---------------------
539
540 function Number_Of_Mains return Natural is
541 begin
542 return Names.Last;
543 end Number_Of_Mains;
544
545 -----------
546 -- Reset --
547 -----------
548
549 procedure Reset is
550 begin
551 Current := 0;
552 end Reset;
553
554 --------------------------
555 -- Set_Multi_Unit_Index --
556 --------------------------
557
558 procedure Set_Multi_Unit_Index
559 (Index : Int := 0)
560 is
561 begin
562 if Index /= 0 then
563 if Names.Last = 0 then
564 Fail_Program
565 ("cannot specify a multi-unit index but no main "
566 & "on the command line");
567
568 elsif Names.Last > 1 then
569 Fail_Program
570 ("cannot specify several mains with a multi-unit index");
571
572 else
573 Names.Table (Names.Last).Index := Index;
574 end if;
575 end if;
576 end Set_Multi_Unit_Index;
577
578 end Mains;
579
580 -----------------------
581 -- Path_Or_File_Name --
582 -----------------------
583
584 function Path_Or_File_Name (Path : Path_Name_Type) return String is
585 Path_Name : constant String := Get_Name_String (Path);
586 begin
587 if Debug.Debug_Flag_F then
588 return File_Name (Path_Name);
589 else
590 return Path_Name;
591 end if;
592 end Path_Or_File_Name;
593
594 -------------------
595 -- Unit_Index_Of --
596 -------------------
597
598 function Unit_Index_Of (ALI_File : File_Name_Type) return Int is
599 Start : Natural;
600 Finish : Natural;
601 Result : Int := 0;
602
603 begin
604 Get_Name_String (ALI_File);
605
606 -- First, find the last dot
607
608 Finish := Name_Len;
609
610 while Finish >= 1 and then Name_Buffer (Finish) /= '.' loop
611 Finish := Finish - 1;
612 end loop;
613
614 if Finish = 1 then
615 return 0;
616 end if;
617
618 -- Now check that the dot is preceded by digits
619
620 Start := Finish;
621 Finish := Finish - 1;
622 while Start >= 1 and then Name_Buffer (Start - 1) in '0' .. '9' loop
623 Start := Start - 1;
624 end loop;
625
626 -- If there are no digits, or if the digits are not preceded by the
627 -- character that precedes a unit index, this is not the ALI file of
628 -- a unit in a multi-unit source.
629
630 if Start > Finish
631 or else Start = 1
632 or else Name_Buffer (Start - 1) /= Multi_Unit_Index_Character
633 then
634 return 0;
635 end if;
636
637 -- Build the index from the digit(s)
638
639 while Start <= Finish loop
640 Result := Result * 10 +
641 Character'Pos (Name_Buffer (Start)) - Character'Pos ('0');
642 Start := Start + 1;
643 end loop;
644
645 return Result;
646 end Unit_Index_Of;
647
648 -----------------
649 -- Verbose_Msg --
650 -----------------
651
652 procedure Verbose_Msg
653 (N1 : Name_Id;
654 S1 : String;
655 N2 : Name_Id := No_Name;
656 S2 : String := "";
657 Prefix : String := " -> ";
658 Minimum_Verbosity : Opt.Verbosity_Level_Type := Opt.Low)
659 is
660 begin
661 if not Opt.Verbose_Mode
662 or else Minimum_Verbosity > Opt.Verbosity_Level
663 then
664 return;
665 end if;
666
667 Write_Str (Prefix);
668 Write_Str ("""");
669 Write_Name (N1);
670 Write_Str (""" ");
671 Write_Str (S1);
672
673 if N2 /= No_Name then
674 Write_Str (" """);
675 Write_Name (N2);
676 Write_Str (""" ");
677 end if;
678
679 Write_Str (S2);
680 Write_Eol;
681 end Verbose_Msg;
682
683 procedure Verbose_Msg
684 (N1 : File_Name_Type;
685 S1 : String;
686 N2 : File_Name_Type := No_File;
687 S2 : String := "";
688 Prefix : String := " -> ";
689 Minimum_Verbosity : Opt.Verbosity_Level_Type := Opt.Low)
690 is
691 begin
692 Verbose_Msg
693 (Name_Id (N1), S1, Name_Id (N2), S2, Prefix, Minimum_Verbosity);
694 end Verbose_Msg;
695
696 -----------
697 -- Queue --
698 -----------
699
700 package body Queue is
701
702 type Q_Record is record
703 Info : Source_Info;
704 Processed : Boolean;
705 end record;
706
707 package Q is new Table.Table
708 (Table_Component_Type => Q_Record,
709 Table_Index_Type => Natural,
710 Table_Low_Bound => 1,
711 Table_Initial => 1000,
712 Table_Increment => 100,
713 Table_Name => "Makeutl.Queue.Q");
714 -- This is the actual Queue
715
716 type Mark_Key is record
717 File : File_Name_Type;
718 Index : Int;
719 end record;
720 -- Identify either a mono-unit source (when Index = 0) or a specific
721 -- unit (index = 1's origin index of unit) in a multi-unit source.
722
723 Max_Mask_Num : constant := 2048;
724 subtype Mark_Num is Union_Id range 0 .. Max_Mask_Num - 1;
725
726 function Hash (Key : Mark_Key) return Mark_Num;
727
728 package Marks is new GNAT.HTable.Simple_HTable
729 (Header_Num => Mark_Num,
730 Element => Boolean,
731 No_Element => False,
732 Key => Mark_Key,
733 Hash => Hash,
734 Equal => "=");
735 -- A hash table to keep tracks of the marked units.
736 -- These are the units that have already been processed, when using the
737 -- gnatmake format. When using the gprbuild format, we can directly
738 -- store in the source_id whether the file has already been processed.
739
740 procedure Mark (Source_File : File_Name_Type; Index : Int := 0);
741 -- Mark a unit, identified by its source file and, when Index is not 0,
742 -- the index of the unit in the source file. Marking is used to signal
743 -- that the unit has already been inserted in the Q.
744
745 function Is_Marked
746 (Source_File : File_Name_Type;
747 Index : Int := 0) return Boolean;
748 -- Returns True if the unit was previously marked
749
750 Q_Processed : Natural := 0;
751 Q_Initialized : Boolean := False;
752
753 Q_First : Natural := 1;
754 -- Points to the first valid element in the queue
755
756 procedure Debug_Display (S : Source_Info);
757 -- A debug display for S
758
759 function Was_Processed (S : Source_Info) return Boolean;
760 -- Whether S has already been processed. This marks the source as
761 -- processed, if it hasn't already been processed.
762
763 -------------------
764 -- Was_Processed --
765 -------------------
766
767 function Was_Processed (S : Source_Info) return Boolean is
768 begin
769 if Is_Marked (S.File, S.Index) then
770 return True;
771 end if;
772
773 Mark (S.File, Index => S.Index);
774
775 return False;
776 end Was_Processed;
777
778 -------------------
779 -- Debug_Display --
780 -------------------
781
782 procedure Debug_Display (S : Source_Info) is
783 begin
784 Write_Name (S.File);
785
786 if S.Index /= 0 then
787 Write_Str (", ");
788 Write_Int (S.Index);
789 end if;
790 end Debug_Display;
791
792 ----------
793 -- Hash --
794 ----------
795
796 function Hash (Key : Mark_Key) return Mark_Num is
797 begin
798 return Union_Id (Key.File) mod Max_Mask_Num;
799 end Hash;
800
801 ---------------
802 -- Is_Marked --
803 ---------------
804
805 function Is_Marked
806 (Source_File : File_Name_Type;
807 Index : Int := 0) return Boolean
808 is
809 begin
810 return Marks.Get (K => (File => Source_File, Index => Index));
811 end Is_Marked;
812
813 ----------
814 -- Mark --
815 ----------
816
817 procedure Mark (Source_File : File_Name_Type; Index : Int := 0) is
818 begin
819 Marks.Set (K => (File => Source_File, Index => Index), E => True);
820 end Mark;
821
822 -------------
823 -- Extract --
824 -------------
825
826 procedure Extract
827 (Found : out Boolean;
828 Source : out Source_Info)
829 is
830 begin
831 Found := False;
832
833 if Q_First <= Q.Last then
834 Source := Q.Table (Q_First).Info;
835 Q.Table (Q_First).Processed := True;
836 Q_First := Q_First + 1;
837 Found := True;
838 end if;
839
840 if Found then
841 Q_Processed := Q_Processed + 1;
842 end if;
843
844 if Found and then Debug.Debug_Flag_Q then
845 Write_Str (" Q := Q - [ ");
846 Debug_Display (Source);
847 Write_Str (" ]");
848 Write_Eol;
849
850 Write_Str (" Q_First =");
851 Write_Int (Int (Q_First));
852 Write_Eol;
853
854 Write_Str (" Q.Last =");
855 Write_Int (Int (Q.Last));
856 Write_Eol;
857 end if;
858 end Extract;
859
860 ---------------
861 -- Processed --
862 ---------------
863
864 function Processed return Natural is
865 begin
866 return Q_Processed;
867 end Processed;
868
869 ----------------
870 -- Initialize --
871 ----------------
872
873 procedure Initialize (Force : Boolean := False) is
874 begin
875 if Force or else not Q_Initialized then
876 Q_Initialized := True;
877 Q.Init;
878 Q_Processed := 0;
879 Q_First := 1;
880 end if;
881 end Initialize;
882
883 ------------
884 -- Insert --
885 ------------
886
887 function Insert (Source : Source_Info) return Boolean is
888 begin
889 -- Only insert in the Q if it is not already done, to avoid
890 -- simultaneous compilations if -jnnn is used.
891
892 if Was_Processed (Source) then
893 return False;
894 end if;
895
896 Q.Append (New_Val => (Info => Source, Processed => False));
897
898 if Debug.Debug_Flag_Q then
899 Write_Str (" Q := Q + [ ");
900 Debug_Display (Source);
901 Write_Str (" ] ");
902 Write_Eol;
903
904 Write_Str (" Q_First =");
905 Write_Int (Int (Q_First));
906 Write_Eol;
907
908 Write_Str (" Q.Last =");
909 Write_Int (Int (Q.Last));
910 Write_Eol;
911 end if;
912
913 return True;
914 end Insert;
915
916 procedure Insert (Source : Source_Info) is
917 Discard : Boolean;
918 begin
919 Discard := Insert (Source);
920 end Insert;
921
922 --------------
923 -- Is_Empty --
924 --------------
925
926 function Is_Empty return Boolean is
927 begin
928 return Q_Processed >= Q.Last;
929 end Is_Empty;
930
931 ----------
932 -- Size --
933 ----------
934
935 function Size return Natural is
936 begin
937 return Q.Last;
938 end Size;
939
940 -------------
941 -- Element --
942 -------------
943
944 function Element (Rank : Positive) return File_Name_Type is
945 begin
946 if Rank <= Q.Last then
947 return Q.Table (Rank).Info.File;
948 else
949 return No_File;
950 end if;
951 end Element;
952
953 ------------------
954 -- Remove_Marks --
955 ------------------
956
957 procedure Remove_Marks is
958 begin
959 Marks.Reset;
960 end Remove_Marks;
961
962 end Queue;
963
964 end Make_Util;