1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 2001-2002 Free Software Foundation, Inc. --
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 2, 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 COPYING. If not, write --
19 -- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, --
20 -- MA 02111-1307, USA. --
22 -- GNAT was originally developed by the GNAT team at New York University. --
23 -- Extensive contributions were provided by Ada Core Technologies Inc. --
25 ------------------------------------------------------------------------------
28 with Namet
; use Namet
;
31 with Osint
; use Osint
;
35 with Prj
.Tree
; use Prj
.Tree
;
36 with Snames
; use Snames
;
37 with Stringt
; use Stringt
;
38 with Table
; use Table
;
40 with Ada
.Characters
.Handling
; use Ada
.Characters
.Handling
;
41 with GNAT
.Directory_Operations
; use GNAT
.Directory_Operations
;
42 with GNAT
.Expect
; use GNAT
.Expect
;
43 with GNAT
.OS_Lib
; use GNAT
.OS_Lib
;
44 with GNAT
.Regexp
; use GNAT
.Regexp
;
45 with GNAT
.Regpat
; use GNAT
.Regpat
;
47 package body Prj
.Makr
is
49 type Matched_Type
is (True, False, Excluded
);
51 Naming_File_Suffix
: constant String := "_naming";
52 Source_List_File_Suffix
: constant String := "_source_list.txt";
54 Output_FD
: File_Descriptor
;
55 -- To save the project file and its naming project file.
58 -- Output an empty line.
60 procedure Write_A_Char
(C
: Character);
61 -- Write one character to Output_FD
63 procedure Write_A_String
(S
: String);
64 -- Write a String to Output_FD
72 Project_File
: Boolean;
73 Directories
: Argument_List
;
74 Name_Patterns
: Argument_List
;
75 Excluded_Patterns
: Argument_List
;
76 Very_Verbose
: Boolean)
78 Path_Name
: String (1 .. File_Path
'Length +
79 Project_File_Extension
'Length);
80 Path_Last
: Natural := File_Path
'Length;
82 Directory_Last
: Natural := 0;
84 Output_Name
: String (Path_Name
'Range);
85 Output_Name_Last
: Natural;
86 Output_Name_Id
: Name_Id
;
88 Project_Node
: Project_Node_Id
:= Empty_Node
;
89 Project_Declaration
: Project_Node_Id
:= Empty_Node
;
90 Source_Dirs_List
: Project_Node_Id
:= Empty_Node
;
91 Current_Source_Dir
: Project_Node_Id
:= Empty_Node
;
93 Project_Naming_Node
: Project_Node_Id
:= Empty_Node
;
94 Project_Naming_Decl
: Project_Node_Id
:= Empty_Node
;
95 Naming_Package
: Project_Node_Id
:= Empty_Node
;
97 Project_Naming_File_Name
: String (1 .. Output_Name
'Length +
98 Naming_File_Suffix
'Length);
100 Project_Naming_Last
: Natural;
101 Project_Naming_Id
: Name_Id
:= No_Name
;
103 Excluded_Expressions
: array (Excluded_Patterns
'Range) of Regexp
;
104 Regular_Expressions
: array (Name_Patterns
'Range) of Regexp
;
106 Source_List_Path
: String (1 .. Output_Name
'Length +
107 Source_List_File_Suffix
'Length);
108 Source_List_Last
: Natural;
110 Source_List_FD
: File_Descriptor
;
112 Str
: String (1 .. 2_000
);
116 PD
: Process_Descriptor
;
117 Result
: Expect_Match
;
118 Matcher
: constant Pattern_Matcher
:=
119 Compile
(Expression
=> "expected|Unit.*\)|No such");
121 Args
: Argument_List
:=
122 (1 => new String'("-c"),
123 2 => new String'("-gnats"),
124 3 => new String'("-gnatu"),
125 4 => new String'("-x"),
126 5 => new String'("ada"),
129 type SFN_Pragma is record
130 Unit : String_Access;
131 File : String_Access;
135 package SFN_Pragmas is new Table.Table
136 (Table_Component_Type => SFN_Pragma,
137 Table_Index_Type => Natural,
138 Table_Low_Bound => 0,
140 Table_Increment => 50,
141 Table_Name => "Prj.Makr.SFN_Pragmas");
144 -- Do some needed initializations
151 SFN_Pragmas.Set_Last (0);
153 -- Get the path and file names
155 if File_Names_Case_Sensitive then
156 Path_Name (1 .. Path_Last) := File_Path;
158 Path_Name (1 .. Path_Last) := To_Lower (File_Path);
161 Path_Name (Path_Last + 1 .. Path_Name'Last) :=
162 Project_File_Extension;
164 -- Get the end of directory information, if any
166 for Index in reverse 1 .. Path_Last loop
167 if Path_Name (Index) = Directory_Separator then
168 Directory_Last := Index;
174 if Path_Last < Project_File_Extension'Length + 1
176 (Path_Last - Project_File_Extension'Length + 1 .. Path_Last)
177 /= Project_File_Extension
179 Path_Last := Path_Name'Last;
182 Output_Name (1 .. Path_Last) := To_Lower (Path_Name (1 .. Path_Last));
183 Output_Name_Last := Path_Last - Project_File_Extension'Length;
185 if Directory_Last /= 0 then
186 Output_Name (1 .. Output_Name_Last - Directory_Last) :=
187 Output_Name (Directory_Last + 1 .. Output_Name_Last);
188 Output_Name_Last := Output_Name_Last - Directory_Last;
191 -- Get the project name id
193 Name_Len := Output_Name_Last;
194 Name_Buffer (1 .. Name_Len) := Output_Name (1 .. Name_Len);
195 Output_Name_Id := Name_Find;
197 -- Create the project naming file name
199 Project_Naming_Last := Output_Name_Last;
200 Project_Naming_File_Name (1 .. Project_Naming_Last) :=
201 Output_Name (1 .. Project_Naming_Last);
202 Project_Naming_File_Name
203 (Project_Naming_Last + 1 ..
204 Project_Naming_Last + Naming_File_Suffix'Length) :=
206 Project_Naming_Last :=
207 Project_Naming_Last + Naming_File_Suffix'Length;
209 -- Get the project naming id
211 Name_Len := Project_Naming_Last;
212 Name_Buffer (1 .. Name_Len) :=
213 Project_Naming_File_Name (1 .. Name_Len);
214 Project_Naming_Id := Name_Find;
216 Project_Naming_File_Name
217 (Project_Naming_Last + 1 ..
218 Project_Naming_Last + Project_File_Extension'Length) :=
219 Project_File_Extension;
220 Project_Naming_Last :=
221 Project_Naming_Last + Project_File_Extension'Length;
223 -- Create the source list file name
225 Source_List_Last := Output_Name_Last;
226 Source_List_Path (1 .. Source_List_Last) :=
227 Output_Name (1 .. Source_List_Last);
229 (Source_List_Last + 1 ..
230 Source_List_Last + Source_List_File_Suffix'Length) :=
231 Source_List_File_Suffix;
232 Source_List_Last := Source_List_Last + Source_List_File_Suffix'Length;
234 -- Add the project file extension to the project name
237 (Output_Name_Last + 1 ..
238 Output_Name_Last + Project_File_Extension'Length) :=
239 Project_File_Extension;
240 Output_Name_Last := Output_Name_Last + Project_File_Extension'Length;
243 -- Change the current directory to the directory of the project file,
244 -- if any directory information is specified.
246 if Directory_Last /= 0 then
248 Change_Dir (Path_Name (1 .. Directory_Last));
250 when Directory_Error =>
251 Fail ("unknown directory """ &
252 Path_Name (1 .. Directory_Last) & '"');
258 -- Delete the source list file, if it already exists
265 (Source_List_Path (1 .. Source_List_Last),
269 -- And create a new source list file.
270 -- Fail if file cannot be created.
272 Source_List_FD := Create_New_File
273 (Name => Source_List_Path (1 .. Source_List_Last),
276 if Source_List_FD = Invalid_FD then
277 Fail ("cannot create file
""" &
278 Source_List_Path (1 .. Source_List_Last) & '"');
282 -- Compile the regular expressions. Fails immediately if any of
283 -- the specified strings is in error.
285 for Index in Excluded_Expressions'Range loop
287 Excluded_Expressions (Index) :=
288 Compile (Pattern => Excluded_Patterns (Index).all, Glob => True);
291 when Error_In_Regexp =>
292 Fail ("invalid regular expression """ &
293 Excluded_Patterns (Index).all & '"');
297 for Index in Regular_Expressions'Range loop
299 Regular_Expressions (Index) :=
300 Compile (Pattern => Name_Patterns (Index).all, Glob => True);
303 when Error_In_Regexp =>
304 Fail ("invalid regular expression
""" &
305 Name_Patterns (Index).all & '"');
310 if Opt.Verbose_Mode then
311 Output.Write_Str ("Naming project file name is """);
313 (Project_Naming_File_Name (1 .. Project_Naming_Last));
314 Output.Write_Line ("""");
317 -- If there is already a project file with the specified name,
318 -- parse it to get the components that are not automatically
321 if Is_Regular_File (Output_Name (1 .. Output_Name_Last)) then
322 if Opt.Verbose_Mode then
323 Output.Write_Str ("Parsing already existing project file """);
324 Output.Write_Str (Output_Name (1 .. Output_Name_Last));
325 Output.Write_Line ("""");
329 (Project => Project_Node,
330 Project_File_Name => Output_Name (1 .. Output_Name_Last),
331 Always_Errout_Finalize => False);
333 -- If parsing was successful, remove the components that are
334 -- automatically generated, if any, so that they will be
335 -- unconditionally added later.
337 if Project_Node /= Empty_Node then
339 -- Remove the with clause for the naming project file
342 With_Clause : Project_Node_Id :=
343 First_With_Clause_Of (Project_Node);
344 Previous : Project_Node_Id := Empty_Node;
347 while With_Clause /= Empty_Node loop
348 if Tree.Name_Of (With_Clause) = Project_Naming_Id then
349 if Previous = Empty_Node then
350 Set_First_With_Clause_Of
352 To => Next_With_Clause_Of (With_Clause));
354 Set_Next_With_Clause_Of
356 To => Next_With_Clause_Of (With_Clause));
362 Previous := With_Clause;
363 With_Clause := Next_With_Clause_Of (With_Clause);
367 -- Remove attribute declarations of Source_Files,
368 -- Source_List_File, Source_Dirs, and the declaration of
369 -- package Naming, if they exist.
372 Declaration : Project_Node_Id :=
373 First_Declarative_Item_Of
374 (Project_Declaration_Of (Project_Node));
375 Previous : Project_Node_Id := Empty_Node;
376 Current_Node : Project_Node_Id := Empty_Node;
379 while Declaration /= Empty_Node loop
380 Current_Node := Current_Item_Node (Declaration);
382 if (Kind_Of (Current_Node) = N_Attribute_Declaration
384 (Tree.Name_Of (Current_Node) = Name_Source_Files
385 or else Tree.Name_Of (Current_Node) =
386 Name_Source_List_File
387 or else Tree.Name_Of (Current_Node) =
390 (Kind_Of (Current_Node) = N_Package_Declaration
391 and then Tree.Name_Of (Current_Node) = Name_Naming)
393 if Previous = Empty_Node then
394 Set_First_Declarative_Item_Of
395 (Project_Declaration_Of (Project_Node),
396 To => Next_Declarative_Item (Declaration));
399 Set_Next_Declarative_Item
401 To => Next_Declarative_Item (Declaration));
405 Previous := Declaration;
408 Declaration := Next_Declarative_Item (Declaration);
414 -- If there were no already existing project file, or if the parsing
415 -- was unsuccessful, create an empty project node with the correct
416 -- name and its project declaration node.
418 if Project_Node = Empty_Node then
419 Project_Node := Default_Project_Node (Of_Kind => N_Project);
420 Set_Name_Of (Project_Node, To => Output_Name_Id);
421 Set_Project_Declaration_Of
423 To => Default_Project_Node (Of_Kind => N_Project_Declaration));
427 -- Create the naming project node, and add an attribute declaration
428 -- for Source_Files as an empty list, to indicate there are no
429 -- sources in the naming project.
431 Project_Naming_Node := Default_Project_Node (Of_Kind => N_Project);
432 Set_Name_Of (Project_Naming_Node, To => Project_Naming_Id);
433 Project_Naming_Decl :=
434 Default_Project_Node (Of_Kind => N_Project_Declaration);
435 Set_Project_Declaration_Of (Project_Naming_Node, Project_Naming_Decl);
437 Default_Project_Node (Of_Kind => N_Package_Declaration);
438 Set_Name_Of (Naming_Package, To => Name_Naming);
441 Decl_Item : constant Project_Node_Id :=
442 Default_Project_Node (Of_Kind => N_Declarative_Item);
444 Attribute : constant Project_Node_Id :=
446 (Of_Kind => N_Attribute_Declaration,
447 And_Expr_Kind => List);
449 Expression : constant Project_Node_Id :=
451 (Of_Kind => N_Expression,
452 And_Expr_Kind => List);
454 Term : constant Project_Node_Id :=
457 And_Expr_Kind => List);
459 Empty_List : constant Project_Node_Id :=
461 (Of_Kind => N_Literal_String_List);
464 Set_First_Declarative_Item_Of
465 (Project_Naming_Decl, To => Decl_Item);
466 Set_Next_Declarative_Item (Decl_Item, Naming_Package);
467 Set_Current_Item_Node (Decl_Item, To => Attribute);
468 Set_Name_Of (Attribute, To => Name_Source_Files);
469 Set_Expression_Of (Attribute, To => Expression);
470 Set_First_Term (Expression, To => Term);
471 Set_Current_Term (Term, To => Empty_List);
474 -- Add a with clause on the naming project in the main project
477 With_Clause : constant Project_Node_Id :=
478 Default_Project_Node (Of_Kind => N_With_Clause);
481 Set_Next_With_Clause_Of
482 (With_Clause, To => First_With_Clause_Of (Project_Node));
483 Set_First_With_Clause_Of (Project_Node, To => With_Clause);
484 Set_Name_Of (With_Clause, To => Project_Naming_Id);
487 (Project_Naming_File_Name (1 .. Project_Naming_Last));
488 Set_String_Value_Of (With_Clause, To => End_String);
491 Project_Declaration := Project_Declaration_Of (Project_Node);
493 -- Add a renaming declaration for package Naming in the main project
496 Decl_Item : constant Project_Node_Id :=
497 Default_Project_Node (Of_Kind => N_Declarative_Item);
499 Naming : constant Project_Node_Id :=
500 Default_Project_Node (Of_Kind => N_Package_Declaration);
502 Set_Next_Declarative_Item
504 To => First_Declarative_Item_Of (Project_Declaration));
505 Set_First_Declarative_Item_Of
506 (Project_Declaration, To => Decl_Item);
507 Set_Current_Item_Node (Decl_Item, To => Naming);
508 Set_Name_Of (Naming, To => Name_Naming);
509 Set_Project_Of_Renamed_Package_Of
510 (Naming, To => Project_Naming_Node);
513 -- Add an attribute declaration for Source_Dirs, initialized as an
514 -- empty list. Directories will be added as they are read from the
515 -- directory list file.
518 Decl_Item : constant Project_Node_Id :=
519 Default_Project_Node (Of_Kind => N_Declarative_Item);
521 Attribute : constant Project_Node_Id :=
523 (Of_Kind => N_Attribute_Declaration,
524 And_Expr_Kind => List);
526 Expression : constant Project_Node_Id :=
528 (Of_Kind => N_Expression,
529 And_Expr_Kind => List);
531 Term : constant Project_Node_Id :=
533 (Of_Kind => N_Term, And_Expr_Kind => List);
536 Set_Next_Declarative_Item
538 To => First_Declarative_Item_Of (Project_Declaration));
539 Set_First_Declarative_Item_Of
540 (Project_Declaration, To => Decl_Item);
541 Set_Current_Item_Node (Decl_Item, To => Attribute);
542 Set_Name_Of (Attribute, To => Name_Source_Dirs);
543 Set_Expression_Of (Attribute, To => Expression);
544 Set_First_Term (Expression, To => Term);
546 Default_Project_Node (Of_Kind => N_Literal_String_List,
547 And_Expr_Kind => List);
548 Set_Current_Term (Term, To => Source_Dirs_List);
551 -- Add an attribute declaration for Source_List_File with the
552 -- source list file name that will be created.
555 Decl_Item : constant Project_Node_Id :=
556 Default_Project_Node (Of_Kind => N_Declarative_Item);
558 Attribute : constant Project_Node_Id :=
560 (Of_Kind => N_Attribute_Declaration,
561 And_Expr_Kind => Single);
563 Expression : constant Project_Node_Id :=
565 (Of_Kind => N_Expression,
566 And_Expr_Kind => Single);
568 Term : constant Project_Node_Id :=
571 And_Expr_Kind => Single);
573 Value : constant Project_Node_Id :=
575 (Of_Kind => N_Literal_String,
576 And_Expr_Kind => Single);
579 Set_Next_Declarative_Item
581 To => First_Declarative_Item_Of (Project_Declaration));
582 Set_First_Declarative_Item_Of
583 (Project_Declaration, To => Decl_Item);
584 Set_Current_Item_Node (Decl_Item, To => Attribute);
585 Set_Name_Of (Attribute, To => Name_Source_List_File);
586 Set_Expression_Of (Attribute, To => Expression);
587 Set_First_Term (Expression, To => Term);
588 Set_Current_Term (Term, To => Value);
590 Store_String_Chars (Source_List_Path (1 .. Source_List_Last));
591 Set_String_Value_Of (Value, To => End_String);
595 -- Process each directory
597 for Index in Directories'Range loop
600 Dir_Name : constant String := Directories (Index).all;
601 Matched : Matched_Type := False;
604 if Opt.Verbose_Mode then
605 Output.Write_Str ("Processing directory """);
606 Output.Write_Str (Dir_Name);
607 Output.Write_Line ("""");
612 -- Add the directory in the list for attribute Source_Dirs
615 Expression : constant Project_Node_Id :=
617 (Of_Kind => N_Expression,
618 And_Expr_Kind => Single);
620 Term : constant Project_Node_Id :=
623 And_Expr_Kind => Single);
625 Value : constant Project_Node_Id :=
627 (Of_Kind => N_Literal_String,
628 And_Expr_Kind => Single);
631 if Current_Source_Dir = Empty_Node then
632 Set_First_Expression_In_List
633 (Source_Dirs_List, To => Expression);
635 Set_Next_Expression_In_List
636 (Current_Source_Dir, To => Expression);
639 Current_Source_Dir := Expression;
640 Set_First_Term (Expression, To => Term);
641 Set_Current_Term (Term, To => Value);
643 Store_String_Chars (S => Dir_Name);
644 Set_String_Value_Of (Value, To => End_String);
648 -- Get the source file names from the directory.
649 -- Fails if the directory does not exist.
652 Open (Dir, Dir_Name);
655 when Directory_Error =>
656 Fail ("cannot open directory """ & Dir_Name & '"');
659 -- Process each regular file in the directory
662 Read (Dir, Str, Last);
666 (Dir_Name & Directory_Separator & Str (1 .. Last))
670 -- First, check if the file name matches at least one of
671 -- the excluded expressions;
673 for Index in Excluded_Expressions'Range loop
675 Match (Str (1 .. Last), Excluded_Expressions (Index))
682 -- If it does not match any of the excluded expressions,
683 -- check if the file name matches at least one of the
684 -- regular expressions.
686 if Matched = True then
688 for Index in Regular_Expressions'Range loop
690 Match (Str (1 .. Last), Regular_Expressions (Index))
699 or else (Matched = True and then Opt.Verbose_Mode)
701 Output.Write_Str (" Checking
""");
702 Output.Write_Str (Str (1 .. Last));
703 Output.Write_Str (""": ");
706 -- If the file name matches one of the regular expressions,
707 -- parse it to get its unit name.
709 if Matched = True then
710 Args (6) := new String'
712 Directory_Separator &
717 (PD, "gcc
", Args, Err_To_Out => True);
718 Expect (PD, Result, Matcher);
722 if Opt.Verbose_Mode then
723 Output.Write_Str ("(process died
) ");
726 Result := Expect_Timeout;
729 if Result /= Expect_Timeout then
731 -- If we got a unit name, this is a valid source file
734 S : constant String := Expect_Out_Match (PD);
738 and then S (S'First .. S'First + 3) = "Unit
"
740 if Opt.Verbose_Mode then
742 (S (S'Last - 4 .. S'Last - 1));
743 Output.Write_Str (" of ");
745 (S (S'First + 5 .. S'Last - 7));
750 -- Add the corresponding attribute in the
751 -- Naming package of the naming project.
754 Decl_Item : constant Project_Node_Id :=
759 Attribute : constant Project_Node_Id :=
762 N_Attribute_Declaration);
764 Expression : constant Project_Node_Id :=
766 (Of_Kind => N_Expression,
767 And_Expr_Kind => Single);
769 Term : constant Project_Node_Id :=
772 And_Expr_Kind => Single);
774 Value : constant Project_Node_Id :=
776 (Of_Kind => N_Literal_String,
777 And_Expr_Kind => Single);
780 Set_Next_Declarative_Item
782 To => First_Declarative_Item_Of
784 Set_First_Declarative_Item_Of
785 (Naming_Package, To => Decl_Item);
786 Set_Current_Item_Node
787 (Decl_Item, To => Attribute);
789 if S (S'Last - 5 .. S'Last) = "(spec
)" then
791 (Attribute, To => Name_Specification);
795 To => Name_Implementation);
801 (S (S'First + 5 .. S'Last - 7)));
802 Set_Associative_Array_Index_Of
803 (Attribute, To => End_String);
806 (Attribute, To => Expression);
807 Set_First_Term (Expression, To => Term);
808 Set_Current_Term (Term, To => Value);
811 Store_String_Chars (Str (1 .. Last));
813 (Value, To => End_String);
816 -- Add source file name to source list file
819 Str (Last) := ASCII.LF;
821 if Write (Source_List_FD,
828 -- Add an entry in the SFN_Pragmas table
830 SFN_Pragmas.Increment_Last;
831 SFN_Pragmas.Table (SFN_Pragmas.Last) :=
833 (S (S'First + 5 .. S'Last - 7)),
834 File => new String'(Str (1 .. Last)),
835 Spec => S (S'Last - 5 .. S'Last)
840 if Opt.Verbose_Mode then
841 Output.Write_Line ("not a unit
");
847 if Opt.Verbose_Mode then
848 Output.Write_Line ("not a unit
");
856 if Matched = False then
857 Output.Write_Line ("no match
");
860 Output.Write_Line ("excluded
");
872 Close (Source_List_FD);
879 -- Delete the file if it already exists
882 (Path_Name (Directory_Last + 1 .. Path_Last),
887 if Opt.Verbose_Mode then
888 Output.Write_Str ("Creating
new file
""");
889 Output.Write_Str (Path_Name (Directory_Last + 1 .. Path_Last));
890 Output.Write_Line ("""");
893 Output_FD := Create_New_File
894 (Path_Name (Directory_Last + 1 .. Path_Last),
897 -- Fails if project file cannot be created
899 if Output_FD = Invalid_FD then
900 Fail ("cannot create
new """ & Path_Name (1 .. Path_Last) & '"');
905 -- Output the project file
909 W_Char => Write_A_Char'Access,
910 W_Eol => Write_Eol'Access,
911 W_Str => Write_A_String'Access);
914 -- Delete the naming project file if it already exists
917 (Project_Naming_File_Name (1 .. Project_Naming_Last),
922 if Opt.Verbose_Mode then
923 Output.Write_Str ("Creating new naming project file """);
924 Output.Write_Str (Project_Naming_File_Name
925 (1 .. Project_Naming_Last));
926 Output.Write_Line ("""");
929 Output_FD := Create_New_File
930 (Project_Naming_File_Name (1 .. Project_Naming_Last),
933 -- Fails if naming project file cannot be created
935 if Output_FD = Invalid_FD then
936 Fail ("cannot create new """ &
937 Project_Naming_File_Name (1 .. Project_Naming_Last) &
941 -- Output the naming project file
944 (Project_Naming_Node,
945 W_Char => Write_A_Char'Access,
946 W_Eol => Write_Eol'Access,
947 W_Str => Write_A_String'Access);
951 -- Write to the output file each entry in the SFN_Pragmas table
952 -- as an pragma Source_File_Name.
954 for Index in 1 .. SFN_Pragmas.Last loop
955 Write_A_String ("pragma Source_File_Name
");
957 Write_A_String (" (");
958 Write_A_String (SFN_Pragmas.Table (Index).Unit.all);
959 Write_A_String (",");
962 if SFN_Pragmas.Table (Index).Spec then
963 Write_A_String (" Spec_File_Name
=> """);
966 Write_A_String (" Body_File_Name
=> """);
969 Write_A_String (SFN_Pragmas.Table (Index).File.all);
970 Write_A_String (""");");
983 procedure Write_A_Char (C : Character) is
985 Write_A_String ((1 => C));
992 procedure Write_Eol is
994 Write_A_String ((1 => ASCII.LF));
1001 procedure Write_A_String (S : String) is
1002 Str : String (1 .. S'Length);
1005 if S'Length > 0 then
1008 if Write (Output_FD, Str (1)'Address, Str'Length) /= Str'Length then