1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
10 -- Copyright (C) 2001-2002 Free Software Foundation, Inc. --
12 -- GNAT is free software; you can redistribute it and/or modify it under --
13 -- terms of the GNU General Public License as published by the Free Soft- --
14 -- ware Foundation; either version 2, or (at your option) any later ver- --
15 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
16 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
17 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
18 -- for more details. You should have received a copy of the GNU General --
19 -- Public License distributed with GNAT; see file COPYING. If not, write --
20 -- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, --
21 -- MA 02111-1307, USA. --
23 -- GNAT was originally developed by the GNAT team at New York University. --
24 -- Extensive contributions were provided by Ada Core Technologies Inc. --
26 ------------------------------------------------------------------------------
29 with Namet
; use Namet
;
32 with Osint
; use Osint
;
36 with Prj
.Tree
; use Prj
.Tree
;
37 with Snames
; use Snames
;
38 with Stringt
; use Stringt
;
39 with Table
; use Table
;
41 with Ada
.Characters
.Handling
; use Ada
.Characters
.Handling
;
42 with GNAT
.Directory_Operations
; use GNAT
.Directory_Operations
;
43 with GNAT
.Expect
; use GNAT
.Expect
;
44 with GNAT
.OS_Lib
; use GNAT
.OS_Lib
;
45 with GNAT
.Regexp
; use GNAT
.Regexp
;
46 with GNAT
.Regpat
; use GNAT
.Regpat
;
48 package body Prj
.Makr
is
50 type Matched_Type
is (True, False, Excluded
);
52 Naming_File_Suffix
: constant String := "_naming";
53 Source_List_File_Suffix
: constant String := "_source_list.txt";
55 Output_FD
: File_Descriptor
;
56 -- To save the project file and its naming project file.
59 -- Output an empty line.
61 procedure Write_A_Char
(C
: Character);
62 -- Write one character to Output_FD
64 procedure Write_A_String
(S
: String);
65 -- Write a String to Output_FD
73 Project_File
: Boolean;
74 Directories
: Argument_List
;
75 Name_Patterns
: Argument_List
;
76 Excluded_Patterns
: Argument_List
;
77 Very_Verbose
: Boolean)
79 Path_Name
: String (1 .. File_Path
'Length +
80 Project_File_Extension
'Length);
81 Path_Last
: Natural := File_Path
'Length;
83 Directory_Last
: Natural := 0;
85 Output_Name
: String (Path_Name
'Range);
86 Output_Name_Last
: Natural;
87 Output_Name_Id
: Name_Id
;
89 Project_Node
: Project_Node_Id
:= Empty_Node
;
90 Project_Declaration
: Project_Node_Id
:= Empty_Node
;
91 Source_Dirs_List
: Project_Node_Id
:= Empty_Node
;
92 Current_Source_Dir
: Project_Node_Id
:= Empty_Node
;
94 Project_Naming_Node
: Project_Node_Id
:= Empty_Node
;
95 Project_Naming_Decl
: Project_Node_Id
:= Empty_Node
;
96 Naming_Package
: Project_Node_Id
:= Empty_Node
;
98 Project_Naming_File_Name
: String (1 .. Output_Name
'Length +
99 Naming_File_Suffix
'Length);
101 Project_Naming_Last
: Natural;
102 Project_Naming_Id
: Name_Id
:= No_Name
;
104 Excluded_Expressions
: array (Excluded_Patterns
'Range) of Regexp
;
105 Regular_Expressions
: array (Name_Patterns
'Range) of Regexp
;
107 Source_List_Path
: String (1 .. Output_Name
'Length +
108 Source_List_File_Suffix
'Length);
109 Source_List_Last
: Natural;
111 Source_List_FD
: File_Descriptor
;
113 Str
: String (1 .. 2_000
);
117 PD
: Process_Descriptor
;
118 Result
: Expect_Match
;
119 Matcher
: constant Pattern_Matcher
:=
120 Compile
(Expression
=> "expected|Unit.*\)|No such");
122 Args
: Argument_List
:=
123 (1 => new String'("-c"),
124 2 => new String'("-gnats"),
125 3 => new String'("-gnatu"),
126 4 => new String'("-x"),
127 5 => new String'("ada"),
130 type SFN_Pragma is record
131 Unit : String_Access;
132 File : String_Access;
136 package SFN_Pragmas is new Table.Table
137 (Table_Component_Type => SFN_Pragma,
138 Table_Index_Type => Natural,
139 Table_Low_Bound => 0,
141 Table_Increment => 50,
142 Table_Name => "Prj.Makr.SFN_Pragmas");
145 -- Do some needed initializations
152 SFN_Pragmas.Set_Last (0);
154 -- Get the path and file names
156 if File_Names_Case_Sensitive then
157 Path_Name (1 .. Path_Last) := File_Path;
159 Path_Name (1 .. Path_Last) := To_Lower (File_Path);
162 Path_Name (Path_Last + 1 .. Path_Name'Last) :=
163 Project_File_Extension;
165 -- Get the end of directory information, if any
167 for Index in reverse 1 .. Path_Last loop
168 if Path_Name (Index) = Directory_Separator then
169 Directory_Last := Index;
175 if Path_Last < Project_File_Extension'Length + 1
177 (Path_Last - Project_File_Extension'Length + 1 .. Path_Last)
178 /= Project_File_Extension
180 Path_Last := Path_Name'Last;
183 Output_Name (1 .. Path_Last) := To_Lower (Path_Name (1 .. Path_Last));
184 Output_Name_Last := Path_Last - Project_File_Extension'Length;
186 if Directory_Last /= 0 then
187 Output_Name (1 .. Output_Name_Last - Directory_Last) :=
188 Output_Name (Directory_Last + 1 .. Output_Name_Last);
189 Output_Name_Last := Output_Name_Last - Directory_Last;
192 -- Get the project name id
194 Name_Len := Output_Name_Last;
195 Name_Buffer (1 .. Name_Len) := Output_Name (1 .. Name_Len);
196 Output_Name_Id := Name_Find;
198 -- Create the project naming file name
200 Project_Naming_Last := Output_Name_Last;
201 Project_Naming_File_Name (1 .. Project_Naming_Last) :=
202 Output_Name (1 .. Project_Naming_Last);
203 Project_Naming_File_Name
204 (Project_Naming_Last + 1 ..
205 Project_Naming_Last + Naming_File_Suffix'Length) :=
207 Project_Naming_Last :=
208 Project_Naming_Last + Naming_File_Suffix'Length;
210 -- Get the project naming id
212 Name_Len := Project_Naming_Last;
213 Name_Buffer (1 .. Name_Len) :=
214 Project_Naming_File_Name (1 .. Name_Len);
215 Project_Naming_Id := Name_Find;
217 Project_Naming_File_Name
218 (Project_Naming_Last + 1 ..
219 Project_Naming_Last + Project_File_Extension'Length) :=
220 Project_File_Extension;
221 Project_Naming_Last :=
222 Project_Naming_Last + Project_File_Extension'Length;
224 -- Create the source list file name
226 Source_List_Last := Output_Name_Last;
227 Source_List_Path (1 .. Source_List_Last) :=
228 Output_Name (1 .. Source_List_Last);
230 (Source_List_Last + 1 ..
231 Source_List_Last + Source_List_File_Suffix'Length) :=
232 Source_List_File_Suffix;
233 Source_List_Last := Source_List_Last + Source_List_File_Suffix'Length;
235 -- Add the project file extension to the project name
238 (Output_Name_Last + 1 ..
239 Output_Name_Last + Project_File_Extension'Length) :=
240 Project_File_Extension;
241 Output_Name_Last := Output_Name_Last + Project_File_Extension'Length;
244 -- Change the current directory to the directory of the project file,
245 -- if any directory information is specified.
247 if Directory_Last /= 0 then
249 Change_Dir (Path_Name (1 .. Directory_Last));
251 when Directory_Error =>
252 Fail ("unknown directory """ &
253 Path_Name (1 .. Directory_Last) & '"');
259 -- Delete the source list file, if it already exists
266 (Source_List_Path (1 .. Source_List_Last),
270 -- And create a new source list file.
271 -- Fail if file cannot be created.
273 Source_List_FD := Create_New_File
274 (Name => Source_List_Path (1 .. Source_List_Last),
277 if Source_List_FD = Invalid_FD then
278 Fail ("cannot create file
""" &
279 Source_List_Path (1 .. Source_List_Last) & '"');
283 -- Compile the regular expressions. Fails immediately if any of
284 -- the specified strings is in error.
286 for Index in Excluded_Expressions'Range loop
288 Excluded_Expressions (Index) :=
289 Compile (Pattern => Excluded_Patterns (Index).all, Glob => True);
292 when Error_In_Regexp =>
293 Fail ("invalid regular expression """ &
294 Excluded_Patterns (Index).all & '"');
298 for Index in Regular_Expressions'Range loop
300 Regular_Expressions (Index) :=
301 Compile (Pattern => Name_Patterns (Index).all, Glob => True);
304 when Error_In_Regexp =>
305 Fail ("invalid regular expression
""" &
306 Name_Patterns (Index).all & '"');
311 if Opt.Verbose_Mode then
312 Output.Write_Str ("Naming project file name is """);
314 (Project_Naming_File_Name (1 .. Project_Naming_Last));
315 Output.Write_Line ("""");
318 -- If there is already a project file with the specified name,
319 -- parse it to get the components that are not automatically
322 if Is_Regular_File (Output_Name (1 .. Output_Name_Last)) then
323 if Opt.Verbose_Mode then
324 Output.Write_Str ("Parsing already existing project file """);
325 Output.Write_Str (Output_Name (1 .. Output_Name_Last));
326 Output.Write_Line ("""");
330 (Project => Project_Node,
331 Project_File_Name => Output_Name (1 .. Output_Name_Last),
332 Always_Errout_Finalize => False);
334 -- If parsing was successful, remove the components that are
335 -- automatically generated, if any, so that they will be
336 -- unconditionally added later.
338 if Project_Node /= Empty_Node then
340 -- Remove the with clause for the naming project file
343 With_Clause : Project_Node_Id :=
344 First_With_Clause_Of (Project_Node);
345 Previous : Project_Node_Id := Empty_Node;
348 while With_Clause /= Empty_Node loop
349 if Tree.Name_Of (With_Clause) = Project_Naming_Id then
350 if Previous = Empty_Node then
351 Set_First_With_Clause_Of
353 To => Next_With_Clause_Of (With_Clause));
355 Set_Next_With_Clause_Of
357 To => Next_With_Clause_Of (With_Clause));
363 Previous := With_Clause;
364 With_Clause := Next_With_Clause_Of (With_Clause);
368 -- Remove attribute declarations of Source_Files,
369 -- Source_List_File, Source_Dirs, and the declaration of
370 -- package Naming, if they exist.
373 Declaration : Project_Node_Id :=
374 First_Declarative_Item_Of
375 (Project_Declaration_Of (Project_Node));
376 Previous : Project_Node_Id := Empty_Node;
377 Current_Node : Project_Node_Id := Empty_Node;
380 while Declaration /= Empty_Node loop
381 Current_Node := Current_Item_Node (Declaration);
383 if (Kind_Of (Current_Node) = N_Attribute_Declaration
385 (Tree.Name_Of (Current_Node) = Name_Source_Files
386 or else Tree.Name_Of (Current_Node) =
387 Name_Source_List_File
388 or else Tree.Name_Of (Current_Node) =
391 (Kind_Of (Current_Node) = N_Package_Declaration
392 and then Tree.Name_Of (Current_Node) = Name_Naming)
394 if Previous = Empty_Node then
395 Set_First_Declarative_Item_Of
396 (Project_Declaration_Of (Project_Node),
397 To => Next_Declarative_Item (Declaration));
400 Set_Next_Declarative_Item
402 To => Next_Declarative_Item (Declaration));
406 Previous := Declaration;
409 Declaration := Next_Declarative_Item (Declaration);
415 -- If there were no already existing project file, or if the parsing
416 -- was unsuccessful, create an empty project node with the correct
417 -- name and its project declaration node.
419 if Project_Node = Empty_Node then
420 Project_Node := Default_Project_Node (Of_Kind => N_Project);
421 Set_Name_Of (Project_Node, To => Output_Name_Id);
422 Set_Project_Declaration_Of
424 To => Default_Project_Node (Of_Kind => N_Project_Declaration));
428 -- Create the naming project node, and add an attribute declaration
429 -- for Source_Files as an empty list, to indicate there are no
430 -- sources in the naming project.
432 Project_Naming_Node := Default_Project_Node (Of_Kind => N_Project);
433 Set_Name_Of (Project_Naming_Node, To => Project_Naming_Id);
434 Project_Naming_Decl :=
435 Default_Project_Node (Of_Kind => N_Project_Declaration);
436 Set_Project_Declaration_Of (Project_Naming_Node, Project_Naming_Decl);
438 Default_Project_Node (Of_Kind => N_Package_Declaration);
439 Set_Name_Of (Naming_Package, To => Name_Naming);
442 Decl_Item : constant Project_Node_Id :=
443 Default_Project_Node (Of_Kind => N_Declarative_Item);
445 Attribute : constant Project_Node_Id :=
447 (Of_Kind => N_Attribute_Declaration,
448 And_Expr_Kind => List);
450 Expression : constant Project_Node_Id :=
452 (Of_Kind => N_Expression,
453 And_Expr_Kind => List);
455 Term : constant Project_Node_Id :=
458 And_Expr_Kind => List);
460 Empty_List : constant Project_Node_Id :=
462 (Of_Kind => N_Literal_String_List);
465 Set_First_Declarative_Item_Of
466 (Project_Naming_Decl, To => Decl_Item);
467 Set_Next_Declarative_Item (Decl_Item, Naming_Package);
468 Set_Current_Item_Node (Decl_Item, To => Attribute);
469 Set_Name_Of (Attribute, To => Name_Source_Files);
470 Set_Expression_Of (Attribute, To => Expression);
471 Set_First_Term (Expression, To => Term);
472 Set_Current_Term (Term, To => Empty_List);
475 -- Add a with clause on the naming project in the main project
478 With_Clause : constant Project_Node_Id :=
479 Default_Project_Node (Of_Kind => N_With_Clause);
482 Set_Next_With_Clause_Of
483 (With_Clause, To => First_With_Clause_Of (Project_Node));
484 Set_First_With_Clause_Of (Project_Node, To => With_Clause);
485 Set_Name_Of (With_Clause, To => Project_Naming_Id);
488 (Project_Naming_File_Name (1 .. Project_Naming_Last));
489 Set_String_Value_Of (With_Clause, To => End_String);
492 Project_Declaration := Project_Declaration_Of (Project_Node);
494 -- Add a renaming declaration for package Naming in the main project
497 Decl_Item : constant Project_Node_Id :=
498 Default_Project_Node (Of_Kind => N_Declarative_Item);
500 Naming : constant Project_Node_Id :=
501 Default_Project_Node (Of_Kind => N_Package_Declaration);
503 Set_Next_Declarative_Item
505 To => First_Declarative_Item_Of (Project_Declaration));
506 Set_First_Declarative_Item_Of
507 (Project_Declaration, To => Decl_Item);
508 Set_Current_Item_Node (Decl_Item, To => Naming);
509 Set_Name_Of (Naming, To => Name_Naming);
510 Set_Project_Of_Renamed_Package_Of
511 (Naming, To => Project_Naming_Node);
514 -- Add an attribute declaration for Source_Dirs, initialized as an
515 -- empty list. Directories will be added as they are read from the
516 -- directory list file.
519 Decl_Item : constant Project_Node_Id :=
520 Default_Project_Node (Of_Kind => N_Declarative_Item);
522 Attribute : constant Project_Node_Id :=
524 (Of_Kind => N_Attribute_Declaration,
525 And_Expr_Kind => List);
527 Expression : constant Project_Node_Id :=
529 (Of_Kind => N_Expression,
530 And_Expr_Kind => List);
532 Term : constant Project_Node_Id :=
534 (Of_Kind => N_Term, And_Expr_Kind => List);
537 Set_Next_Declarative_Item
539 To => First_Declarative_Item_Of (Project_Declaration));
540 Set_First_Declarative_Item_Of
541 (Project_Declaration, To => Decl_Item);
542 Set_Current_Item_Node (Decl_Item, To => Attribute);
543 Set_Name_Of (Attribute, To => Name_Source_Dirs);
544 Set_Expression_Of (Attribute, To => Expression);
545 Set_First_Term (Expression, To => Term);
547 Default_Project_Node (Of_Kind => N_Literal_String_List,
548 And_Expr_Kind => List);
549 Set_Current_Term (Term, To => Source_Dirs_List);
552 -- Add an attribute declaration for Source_List_File with the
553 -- source list file name that will be created.
556 Decl_Item : constant Project_Node_Id :=
557 Default_Project_Node (Of_Kind => N_Declarative_Item);
559 Attribute : constant Project_Node_Id :=
561 (Of_Kind => N_Attribute_Declaration,
562 And_Expr_Kind => Single);
564 Expression : constant Project_Node_Id :=
566 (Of_Kind => N_Expression,
567 And_Expr_Kind => Single);
569 Term : constant Project_Node_Id :=
572 And_Expr_Kind => Single);
574 Value : constant Project_Node_Id :=
576 (Of_Kind => N_Literal_String,
577 And_Expr_Kind => Single);
580 Set_Next_Declarative_Item
582 To => First_Declarative_Item_Of (Project_Declaration));
583 Set_First_Declarative_Item_Of
584 (Project_Declaration, To => Decl_Item);
585 Set_Current_Item_Node (Decl_Item, To => Attribute);
586 Set_Name_Of (Attribute, To => Name_Source_List_File);
587 Set_Expression_Of (Attribute, To => Expression);
588 Set_First_Term (Expression, To => Term);
589 Set_Current_Term (Term, To => Value);
591 Store_String_Chars (Source_List_Path (1 .. Source_List_Last));
592 Set_String_Value_Of (Value, To => End_String);
596 -- Process each directory
598 for Index in Directories'Range loop
601 Dir_Name : constant String := Directories (Index).all;
602 Matched : Matched_Type := False;
605 if Opt.Verbose_Mode then
606 Output.Write_Str ("Processing directory """);
607 Output.Write_Str (Dir_Name);
608 Output.Write_Line ("""");
613 -- Add the directory in the list for attribute Source_Dirs
616 Expression : constant Project_Node_Id :=
618 (Of_Kind => N_Expression,
619 And_Expr_Kind => Single);
621 Term : constant Project_Node_Id :=
624 And_Expr_Kind => Single);
626 Value : constant Project_Node_Id :=
628 (Of_Kind => N_Literal_String,
629 And_Expr_Kind => Single);
632 if Current_Source_Dir = Empty_Node then
633 Set_First_Expression_In_List
634 (Source_Dirs_List, To => Expression);
636 Set_Next_Expression_In_List
637 (Current_Source_Dir, To => Expression);
640 Current_Source_Dir := Expression;
641 Set_First_Term (Expression, To => Term);
642 Set_Current_Term (Term, To => Value);
644 Store_String_Chars (S => Dir_Name);
645 Set_String_Value_Of (Value, To => End_String);
649 -- Get the source file names from the directory.
650 -- Fails if the directory does not exist.
653 Open (Dir, Dir_Name);
656 when Directory_Error =>
657 Fail ("cannot open directory """ & Dir_Name & '"');
660 -- Process each regular file in the directory
663 Read (Dir, Str, Last);
667 (Dir_Name & Directory_Separator & Str (1 .. Last))
671 -- First, check if the file name matches at least one of
672 -- the excluded expressions;
674 for Index in Excluded_Expressions'Range loop
676 Match (Str (1 .. Last), Excluded_Expressions (Index))
683 -- If it does not match any of the excluded expressions,
684 -- check if the file name matches at least one of the
685 -- regular expressions.
687 if Matched = True then
689 for Index in Regular_Expressions'Range loop
691 Match (Str (1 .. Last), Regular_Expressions (Index))
700 or else (Matched = True and then Opt.Verbose_Mode)
702 Output.Write_Str (" Checking
""");
703 Output.Write_Str (Str (1 .. Last));
704 Output.Write_Str (""": ");
707 -- If the file name matches one of the regular expressions,
708 -- parse it to get its unit name.
710 if Matched = True then
711 Args (6) := new String'
713 Directory_Separator &
718 (PD, "gcc
", Args, Err_To_Out => True);
719 Expect (PD, Result, Matcher);
723 if Opt.Verbose_Mode then
724 Output.Write_Str ("(process died
) ");
727 Result := Expect_Timeout;
730 if Result /= Expect_Timeout then
732 -- If we got a unit name, this is a valid source file
735 S : constant String := Expect_Out_Match (PD);
739 and then S (S'First .. S'First + 3) = "Unit
"
741 if Opt.Verbose_Mode then
743 (S (S'Last - 4 .. S'Last - 1));
744 Output.Write_Str (" of ");
746 (S (S'First + 5 .. S'Last - 7));
751 -- Add the corresponding attribute in the
752 -- Naming package of the naming project.
755 Decl_Item : constant Project_Node_Id :=
760 Attribute : constant Project_Node_Id :=
763 N_Attribute_Declaration);
765 Expression : constant Project_Node_Id :=
767 (Of_Kind => N_Expression,
768 And_Expr_Kind => Single);
770 Term : constant Project_Node_Id :=
773 And_Expr_Kind => Single);
775 Value : constant Project_Node_Id :=
777 (Of_Kind => N_Literal_String,
778 And_Expr_Kind => Single);
781 Set_Next_Declarative_Item
783 To => First_Declarative_Item_Of
785 Set_First_Declarative_Item_Of
786 (Naming_Package, To => Decl_Item);
787 Set_Current_Item_Node
788 (Decl_Item, To => Attribute);
790 if S (S'Last - 5 .. S'Last) = "(spec
)" then
792 (Attribute, To => Name_Specification);
796 To => Name_Implementation);
802 (S (S'First + 5 .. S'Last - 7)));
803 Set_Associative_Array_Index_Of
804 (Attribute, To => End_String);
807 (Attribute, To => Expression);
808 Set_First_Term (Expression, To => Term);
809 Set_Current_Term (Term, To => Value);
812 Store_String_Chars (Str (1 .. Last));
814 (Value, To => End_String);
817 -- Add source file name to source list file
820 Str (Last) := ASCII.LF;
822 if Write (Source_List_FD,
829 -- Add an entry in the SFN_Pragmas table
831 SFN_Pragmas.Increment_Last;
832 SFN_Pragmas.Table (SFN_Pragmas.Last) :=
834 (S (S'First + 5 .. S'Last - 7)),
835 File => new String'(Str (1 .. Last)),
836 Spec => S (S'Last - 5 .. S'Last)
841 if Opt.Verbose_Mode then
842 Output.Write_Line ("not a unit
");
848 if Opt.Verbose_Mode then
849 Output.Write_Line ("not a unit
");
857 if Matched = False then
858 Output.Write_Line ("no match
");
861 Output.Write_Line ("excluded
");
873 Close (Source_List_FD);
880 -- Delete the file if it already exists
883 (Path_Name (Directory_Last + 1 .. Path_Last),
888 if Opt.Verbose_Mode then
889 Output.Write_Str ("Creating
new file
""");
890 Output.Write_Str (Path_Name (Directory_Last + 1 .. Path_Last));
891 Output.Write_Line ("""");
894 Output_FD := Create_New_File
895 (Path_Name (Directory_Last + 1 .. Path_Last),
898 -- Fails if project file cannot be created
900 if Output_FD = Invalid_FD then
901 Fail ("cannot create
new """ & Path_Name (1 .. Path_Last) & '"');
906 -- Output the project file
910 W_Char => Write_A_Char'Access,
911 W_Eol => Write_Eol'Access,
912 W_Str => Write_A_String'Access);
915 -- Delete the naming project file if it already exists
918 (Project_Naming_File_Name (1 .. Project_Naming_Last),
923 if Opt.Verbose_Mode then
924 Output.Write_Str ("Creating new naming project file """);
925 Output.Write_Str (Project_Naming_File_Name
926 (1 .. Project_Naming_Last));
927 Output.Write_Line ("""");
930 Output_FD := Create_New_File
931 (Project_Naming_File_Name (1 .. Project_Naming_Last),
934 -- Fails if naming project file cannot be created
936 if Output_FD = Invalid_FD then
937 Fail ("cannot create new """ &
938 Project_Naming_File_Name (1 .. Project_Naming_Last) &
942 -- Output the naming project file
945 (Project_Naming_Node,
946 W_Char => Write_A_Char'Access,
947 W_Eol => Write_Eol'Access,
948 W_Str => Write_A_String'Access);
952 -- Write to the output file each entry in the SFN_Pragmas table
953 -- as an pragma Source_File_Name.
955 for Index in 1 .. SFN_Pragmas.Last loop
956 Write_A_String ("pragma Source_File_Name
");
958 Write_A_String (" (");
959 Write_A_String (SFN_Pragmas.Table (Index).Unit.all);
960 Write_A_String (",");
963 if SFN_Pragmas.Table (Index).Spec then
964 Write_A_String (" Spec_File_Name
=> """);
967 Write_A_String (" Body_File_Name
=> """);
970 Write_A_String (SFN_Pragmas.Table (Index).File.all);
971 Write_A_String (""");");
984 procedure Write_A_Char (C : Character) is
986 Write_A_String ((1 => C));
993 procedure Write_Eol is
995 Write_A_String ((1 => ASCII.LF));
1000 --------------------
1002 procedure Write_A_String (S : String) is
1003 Str : String (1 .. S'Length);
1006 if S'Length > 0 then
1009 if Write (Output_FD, Str (1)'Address, Str'Length) /= Str'Length then