1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 2002-2003 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 ------------------------------------------------------------------------------
29 with Ada
.Unchecked_Deallocation
;
31 with GNAT
.OS_Lib
; use GNAT
.OS_Lib
;
34 package body Bld
.IO
is
38 Initial_Number_Of_Lines
: constant := 100;
39 Initial_Length_Of_Line
: constant := 50;
42 Length
: Natural := 0;
43 Value
: String_Access
;
44 Suppressed
: Boolean := False;
46 -- One line of a Makefile.
47 -- Length is the position of the last column in the line.
48 -- Suppressed is set to True by procedure Suppress.
50 type Line_Array
is array (Positive range <>) of Line
;
52 type Buffer
is access Line_Array
;
54 procedure Free
is new Ada
.Unchecked_Deallocation
(Line_Array
, Buffer
);
56 Lines
: Buffer
:= new Line_Array
(1 .. Initial_Number_Of_Lines
);
57 -- The lines of a Makefile
59 Current
: Positive := 1;
60 -- Position of the last line in the Makefile
62 File
: Text_IO
.File_Type
;
63 -- The current Makefile
66 type File_Name_Ref
is access File_Name_Data
;
68 type File_Name_Data
is record
69 Value
: String_Access
;
72 -- Used to record the names of all Makefiles created, so that we may delete
75 File_Names
: File_Name_Ref
;
76 -- List of all the Makefiles created so far.
89 Text_IO
.Put_Line
(Exceptions
.Exception_Message
(X
));
90 Osint
.Fail
("cannot close a Makefile");
97 procedure Create
(File_Name
: String) is
99 Text_IO
.Create
(File
, Text_IO
.Out_File
, File_Name
);
101 Lines
(1).Length
:= 0;
102 Lines
(1).Suppressed
:= False;
104 new File_Name_Data
'(Value => new String'(File_Name
),
108 Text_IO
.Put_Line
(Exceptions
.Exception_Message
(X
));
109 Osint
.Fail
("cannot create """ & File_Name
& '"');
116 procedure Delete_All
is
119 if Text_IO
.Is_Open
(File
) then
120 Text_IO
.Delete
(File
);
121 File_Names
:= File_Names
.Next
;
124 while File_Names
/= null loop
125 Delete_File
(File_Names
.Value
.all, Success
);
126 File_Names
:= File_Names
.Next
;
137 if Lines
(Current
).Length
/= 0 then
138 Osint
.Fail
("INTERNAL ERROR: flushing before end of line: """ &
139 Lines
(Current
).Value
140 (1 .. Lines
(Current
).Length
));
143 for J
in 1 .. Current
- 1 loop
144 if not Lines
(J
).Suppressed
then
145 Last
:= Lines
(J
).Length
;
147 -- The last character of a line cannot be a back slash ('\'),
148 -- otherwise make has a problem. The only real place were it
149 -- should happen is for directory names on Windows, and then
150 -- this terminal back slash is not needed.
152 if Last
> 0 and then Lines
(J
).Value
(Last
) = '\' then
156 Text_IO
.Put_Line
(File
, Lines
(J
).Value
(1 .. Last
));
161 Lines
(1).Length
:= 0;
162 Lines
(1).Suppressed
:= False;
169 procedure Mark
(Pos
: out Position
) is
171 if Lines
(Current
).Length
/= 0 then
172 Osint
.Fail
("INTERNAL ERROR: marking before end of line: """ &
173 Lines
(Current
).Value
174 (1 .. Lines
(Current
).Length
));
177 Pos
:= (Value
=> Current
);
184 function Name_Of_File
return String is
186 return Text_IO
.Name
(File
);
193 procedure New_Line
is
195 Current
:= Current
+ 1;
197 if Current
> Lines
'Last then
199 New_Lines
: constant Buffer
:=
200 new Line_Array
(1 .. 2 * Lines
'Last);
203 New_Lines
(1 .. Lines
'Last) := Lines
.all;
209 Lines
(Current
).Length
:= 0;
210 Lines
(Current
).Suppressed
:= False;
212 -- Allocate a new line, if necessary
214 if Lines
(Current
).Value
= null then
215 Lines
(Current
).Value
:= new String (1 .. Initial_Length_Of_Line
);
223 procedure Put
(S
: String) is
224 Length
: constant Natural := Lines
(Current
).Length
;
227 if Length
+ S
'Length > Lines
(Current
).Value
'Length then
229 New_Line
: String_Access
;
230 New_Length
: Positive := 2 * Lines
(Current
).Value
'Length;
232 while Length
+ S
'Length > New_Length
loop
233 New_Length
:= 2 * New_Length
;
236 New_Line
:= new String (1 .. New_Length
);
237 New_Line
(1 .. Length
) := Lines
(Current
).Value
(1 .. Length
);
238 Free
(Lines
(Current
).Value
);
239 Lines
(Current
).Value
:= New_Line
;
243 Lines
(Current
).Value
(Length
+ 1 .. Length
+ S
'Length) := S
;
244 Lines
(Current
).Length
:= Length
+ S
'Length;
251 procedure Release
(Pos
: Position
) is
253 if Lines
(Current
).Length
/= 0 then
254 Osint
.Fail
("INTERNAL ERROR: releasing before end of line: """ &
255 Lines
(Current
).Value
256 (1 .. Lines
(Current
).Length
));
259 if Pos
.Value
> Current
then
260 Osint
.Fail
("INTERNAL ERROR: releasing ahead of current position");
263 Current
:= Pos
.Value
;
264 Lines
(Current
).Length
:= 0;
271 procedure Suppress
(Pos
: Position
) is
273 if Pos
.Value
>= Current
then
274 Osint
.Fail
("INTERNAL ERROR: suppressing ahead of current position");
277 Lines
(Pos
.Value
).Suppressed
:= True;
281 -- Allocate the first line.
282 -- The other ones are allocated by New_Line.
284 Lines
(1).Value
:= new String (1 .. Initial_Length_Of_Line
);