1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 1992-2009, 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 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. --
18 -- As a special exception under Section 7 of GPL version 3, you are granted --
19 -- additional permissions described in the GCC Runtime Library Exception, --
20 -- version 3.1, as published by the Free Software Foundation. --
22 -- You should have received a copy of the GNU General Public License and --
23 -- a copy of the GCC Runtime Library Exception along with this program; --
24 -- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
25 -- <http://www.gnu.org/licenses/>. --
27 -- GNAT was originally developed by the GNAT team at New York University. --
28 -- Extensive contributions were provided by Ada Core Technologies Inc. --
30 ------------------------------------------------------------------------------
32 with System.OS_Lib; use System.OS_Lib;
34 package body Output is
36 Current_FD : File_Descriptor := Standout;
37 -- File descriptor for current output
39 Special_Output_Proc : Output_Proc := null;
40 -- Record argument to last call to Set_Special_Output. If this is
41 -- non-null, then we are in special output mode.
43 Indentation_Amount : constant Positive := 3;
44 -- Number of spaces to output for each indentation level
46 Indentation_Limit : constant Positive := 40;
47 -- Indentation beyond this number of spaces wraps around
49 pragma Assert (Indentation_Limit < Buffer_Max / 2);
50 -- Make sure this is substantially shorter than the line length
52 Cur_Indentation : Natural := 0;
53 -- Number of spaces to indent each line
55 -----------------------
56 -- Local_Subprograms --
57 -----------------------
59 procedure Flush_Buffer;
60 -- Flush buffer if non-empty and reset column counter
62 ---------------------------
63 -- Cancel_Special_Output --
64 ---------------------------
66 procedure Cancel_Special_Output is
68 Special_Output_Proc := null;
69 end Cancel_Special_Output;
75 function Column return Pos is
77 return Pos (Next_Col);
84 procedure Flush_Buffer is
85 Write_Error : exception;
86 -- Raised if Write fails
92 procedure Write_Buffer (Buf : String);
93 -- Write out Buf, either using Special_Output_Proc, or the normal way
94 -- using Write. Raise Write_Error if Write fails (presumably due to disk
95 -- full). Write_Error is not used in the case of Special_Output_Proc.
97 procedure Write_Buffer (Buf : String) is
99 -- If Special_Output_Proc has been set, then use it
101 if Special_Output_Proc /= null then
102 Special_Output_Proc.all (Buf);
104 -- If output is not set, then output to either standard output
105 -- or standard error.
107 elsif Write (Current_FD, Buf'Address, Buf'Length) /= Buf'Length then
113 Len : constant Natural := Next_Col - 1;
118 -- If there's no indentation, or if the line is too long with
119 -- indentation, just write the buffer.
121 if Cur_Indentation = 0
122 or else Cur_Indentation + Len > Buffer_Max
124 Write_Buffer (Buffer (1 .. Len));
126 -- Otherwise, construct a new buffer with preceding spaces, and
131 Indented_Buffer : constant String
132 := (1 .. Cur_Indentation => ' ') & Buffer (1 .. Len);
134 Write_Buffer (Indented_Buffer);
140 -- If there are errors with standard error, just quit.
141 -- Otherwise, set the output to standard error before reporting
142 -- a failure and quitting.
144 if Current_FD /= Standerr then
145 Current_FD := Standerr;
147 Write_Line ("fatal error: disk full");
153 -- Buffer is now empty
165 -- The "mod" in the following assignment is to cause a wrap around in
166 -- the case where there is too much indentation.
169 (Cur_Indentation + Indentation_Amount) mod Indentation_Limit;
178 -- The "mod" here undoes the wrap around from Indent above
181 (Cur_Indentation - Indentation_Amount) mod Indentation_Limit;
184 ---------------------------
185 -- Restore_Output_Buffer --
186 ---------------------------
188 procedure Restore_Output_Buffer (S : Saved_Output_Buffer) is
190 Next_Col := S.Next_Col;
191 Cur_Indentation := S.Cur_Indentation;
192 Buffer (1 .. Next_Col - 1) := S.Buffer (1 .. Next_Col - 1);
193 end Restore_Output_Buffer;
195 ------------------------
196 -- Save_Output_Buffer --
197 ------------------------
199 function Save_Output_Buffer return Saved_Output_Buffer is
200 S : Saved_Output_Buffer;
202 S.Buffer (1 .. Next_Col - 1) := Buffer (1 .. Next_Col - 1);
203 S.Next_Col := Next_Col;
204 S.Cur_Indentation := Cur_Indentation;
206 Cur_Indentation := 0;
208 end Save_Output_Buffer;
210 ------------------------
211 -- Set_Special_Output --
212 ------------------------
214 procedure Set_Special_Output (P : Output_Proc) is
216 Special_Output_Proc := P;
217 end Set_Special_Output;
219 ------------------------
220 -- Set_Standard_Error --
221 ------------------------
223 procedure Set_Standard_Error is
225 if Special_Output_Proc = null then
229 Current_FD := Standerr;
230 end Set_Standard_Error;
232 -------------------------
233 -- Set_Standard_Output --
234 -------------------------
236 procedure Set_Standard_Output is
238 if Special_Output_Proc = null then
242 Current_FD := Standout;
243 end Set_Standard_Output;
249 procedure w (C : Character) is
257 procedure w (S : String) is
263 procedure w (V : Int) is
269 procedure w (B : Boolean) is
278 procedure w (L : String; C : Character) is
285 procedure w (L : String; S : String) is
292 procedure w (L : String; V : Int) is
299 procedure w (L : String; B : Boolean) is
310 procedure Write_Char (C : Character) is
312 if Next_Col = Buffer'Length then
319 Buffer (Next_Col) := C;
320 Next_Col := Next_Col + 1;
328 procedure Write_Eol is
330 -- Remove any trailing space
332 while Next_Col > 1 and then Buffer (Next_Col - 1) = ' ' loop
333 Next_Col := Next_Col - 1;
336 Buffer (Next_Col) := ASCII.LF;
337 Next_Col := Next_Col + 1;
341 ---------------------------
342 -- Write_Eol_Keep_Blanks --
343 ---------------------------
345 procedure Write_Eol_Keep_Blanks is
347 Buffer (Next_Col) := ASCII.LF;
348 Next_Col := Next_Col + 1;
350 end Write_Eol_Keep_Blanks;
352 ----------------------
353 -- Write_Erase_Char --
354 ----------------------
356 procedure Write_Erase_Char (C : Character) is
358 if Next_Col /= 1 and then Buffer (Next_Col - 1) = C then
359 Next_Col := Next_Col - 1;
361 end Write_Erase_Char;
367 procedure Write_Int (Val : Int) is
375 Write_Int (Val / 10);
378 Write_Char (Character'Val ((Val mod 10) + Character'Pos ('0')));
386 procedure Write_Line (S : String) is
396 procedure Write_Spaces (N : Nat) is
407 procedure Write_Str (S : String) is
409 for J in S'Range loop