OSDN Git Service

2009-07-13 Thomas Quinot <quinot@adacore.com>
[pf3gnuchains/gcc-fork.git] / gcc / ada / output.adb
1 ------------------------------------------------------------------------------
2 --                                                                          --
3 --                         GNAT COMPILER COMPONENTS                         --
4 --                                                                          --
5 --                               O U T P U T                                --
6 --                                                                          --
7 --                                 B o d y                                  --
8 --                                                                          --
9 --          Copyright (C) 1992-2009, 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.                                     --
17 --                                                                          --
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.               --
21 --                                                                          --
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/>.                                          --
26 --                                                                          --
27 -- GNAT was originally developed  by the GNAT team at  New York University. --
28 -- Extensive contributions were provided by Ada Core Technologies Inc.      --
29 --                                                                          --
30 ------------------------------------------------------------------------------
31
32 pragma Warnings (Off);
33 with System.OS_Lib; use System.OS_Lib;
34 pragma Warnings (On);
35
36 package body Output is
37
38    Current_FD : File_Descriptor := Standout;
39    --  File descriptor for current output
40
41    Special_Output_Proc : Output_Proc := null;
42    --  Record argument to last call to Set_Special_Output. If this is
43    --  non-null, then we are in special output mode.
44
45    Indentation_Amount : constant Positive := 3;
46    --  Number of spaces to output for each indentation level
47
48    Indentation_Limit : constant Positive := 40;
49    --  Indentation beyond this number of spaces wraps around
50
51    pragma Assert (Indentation_Limit < Buffer_Max / 2);
52    --  Make sure this is substantially shorter than the line length
53
54    Cur_Indentation : Natural := 0;
55    --  Number of spaces to indent each line
56
57    -----------------------
58    -- Local_Subprograms --
59    -----------------------
60
61    procedure Flush_Buffer;
62    --  Flush buffer if non-empty and reset column counter
63
64    ---------------------------
65    -- Cancel_Special_Output --
66    ---------------------------
67
68    procedure Cancel_Special_Output is
69    begin
70       Special_Output_Proc := null;
71    end Cancel_Special_Output;
72
73    ------------
74    -- Column --
75    ------------
76
77    function Column return Pos is
78    begin
79       return Pos (Next_Col);
80    end Column;
81
82    ------------------
83    -- Flush_Buffer --
84    ------------------
85
86    procedure Flush_Buffer is
87       Write_Error : exception;
88       --  Raised if Write fails
89
90       ------------------
91       -- Write_Buffer --
92       ------------------
93
94       procedure Write_Buffer (Buf : String);
95       --  Write out Buf, either using Special_Output_Proc, or the normal way
96       --  using Write. Raise Write_Error if Write fails (presumably due to disk
97       --  full). Write_Error is not used in the case of Special_Output_Proc.
98
99       procedure Write_Buffer (Buf : String) is
100       begin
101          --  If Special_Output_Proc has been set, then use it
102
103          if Special_Output_Proc /= null then
104             Special_Output_Proc.all (Buf);
105
106          --  If output is not set, then output to either standard output
107          --  or standard error.
108
109          elsif Write (Current_FD, Buf'Address, Buf'Length) /= Buf'Length then
110             raise Write_Error;
111
112          end if;
113       end Write_Buffer;
114
115       Len : constant Natural := Next_Col - 1;
116
117    --  Start of processing for Flush_Buffer
118
119    begin
120       if Len /= 0 then
121          begin
122             --  If there's no indentation, or if the line is too long with
123             --  indentation, or if it's a blank line, just write the buffer.
124
125             if Cur_Indentation = 0
126               or else Cur_Indentation + Len > Buffer_Max
127               or else Buffer (1 .. Len) = (1 => ASCII.LF)
128             then
129                Write_Buffer (Buffer (1 .. Len));
130
131             --  Otherwise, construct a new buffer with preceding spaces, and
132             --  write that.
133
134             else
135                declare
136                   Indented_Buffer : constant String
137                     := (1 .. Cur_Indentation => ' ') & Buffer (1 .. Len);
138                begin
139                   Write_Buffer (Indented_Buffer);
140                end;
141             end if;
142
143          exception
144             when Write_Error =>
145                --  If there are errors with standard error, just quit.
146                --  Otherwise, set the output to standard error before reporting
147                --  a failure and quitting.
148
149                if Current_FD /= Standerr then
150                   Current_FD := Standerr;
151                   Next_Col := 1;
152                   Write_Line ("fatal error: disk full");
153                end if;
154
155                OS_Exit (2);
156          end;
157
158          --  Buffer is now empty
159
160          Next_Col := 1;
161       end if;
162    end Flush_Buffer;
163
164    -------------------
165    -- Ignore_Output --
166    -------------------
167
168    procedure Ignore_Output (S : String) is
169    begin
170       null;
171    end Ignore_Output;
172
173    ------------
174    -- Indent --
175    ------------
176
177    procedure Indent is
178    begin
179       --  The "mod" in the following assignment is to cause a wrap around in
180       --  the case where there is too much indentation.
181
182       Cur_Indentation :=
183         (Cur_Indentation + Indentation_Amount) mod Indentation_Limit;
184    end Indent;
185
186    -------------
187    -- Outdent --
188    -------------
189
190    procedure Outdent is
191    begin
192       --  The "mod" here undoes the wrap around from Indent above
193
194       Cur_Indentation :=
195         (Cur_Indentation - Indentation_Amount) mod Indentation_Limit;
196    end Outdent;
197
198    ---------------------------
199    -- Restore_Output_Buffer --
200    ---------------------------
201
202    procedure Restore_Output_Buffer (S : Saved_Output_Buffer) is
203    begin
204       Next_Col := S.Next_Col;
205       Cur_Indentation := S.Cur_Indentation;
206       Buffer (1 .. Next_Col - 1) := S.Buffer (1 .. Next_Col - 1);
207    end Restore_Output_Buffer;
208
209    ------------------------
210    -- Save_Output_Buffer --
211    ------------------------
212
213    function Save_Output_Buffer return Saved_Output_Buffer is
214       S : Saved_Output_Buffer;
215    begin
216       S.Buffer (1 .. Next_Col - 1) := Buffer (1 .. Next_Col - 1);
217       S.Next_Col := Next_Col;
218       S.Cur_Indentation := Cur_Indentation;
219       Next_Col := 1;
220       Cur_Indentation := 0;
221       return S;
222    end Save_Output_Buffer;
223
224    ------------------------
225    -- Set_Special_Output --
226    ------------------------
227
228    procedure Set_Special_Output (P : Output_Proc) is
229    begin
230       Special_Output_Proc := P;
231    end Set_Special_Output;
232
233    ------------------------
234    -- Set_Standard_Error --
235    ------------------------
236
237    procedure Set_Standard_Error is
238    begin
239       if Special_Output_Proc = null then
240          Flush_Buffer;
241       end if;
242
243       Current_FD := Standerr;
244    end Set_Standard_Error;
245
246    -------------------------
247    -- Set_Standard_Output --
248    -------------------------
249
250    procedure Set_Standard_Output is
251    begin
252       if Special_Output_Proc = null then
253          Flush_Buffer;
254       end if;
255
256       Current_FD := Standout;
257    end Set_Standard_Output;
258
259    -------
260    -- w --
261    -------
262
263    procedure w (C : Character) is
264    begin
265       Write_Char (''');
266       Write_Char (C);
267       Write_Char (''');
268       Write_Eol;
269    end w;
270
271    procedure w (S : String) is
272    begin
273       Write_Str (S);
274       Write_Eol;
275    end w;
276
277    procedure w (V : Int) is
278    begin
279       Write_Int (V);
280       Write_Eol;
281    end w;
282
283    procedure w (B : Boolean) is
284    begin
285       if B then
286          w ("True");
287       else
288          w ("False");
289       end if;
290    end w;
291
292    procedure w (L : String; C : Character) is
293    begin
294       Write_Str (L);
295       Write_Char (' ');
296       w (C);
297    end w;
298
299    procedure w (L : String; S : String) is
300    begin
301       Write_Str (L);
302       Write_Char (' ');
303       w (S);
304    end w;
305
306    procedure w (L : String; V : Int) is
307    begin
308       Write_Str (L);
309       Write_Char (' ');
310       w (V);
311    end w;
312
313    procedure w (L : String; B : Boolean) is
314    begin
315       Write_Str (L);
316       Write_Char (' ');
317       w (B);
318    end w;
319
320    ----------------
321    -- Write_Char --
322    ----------------
323
324    procedure Write_Char (C : Character) is
325    begin
326       if Next_Col = Buffer'Length then
327          Write_Eol;
328       end if;
329
330       if C = ASCII.LF then
331          Write_Eol;
332       else
333          Buffer (Next_Col) := C;
334          Next_Col := Next_Col + 1;
335       end if;
336    end Write_Char;
337
338    ---------------
339    -- Write_Eol --
340    ---------------
341
342    procedure Write_Eol is
343    begin
344       --  Remove any trailing space
345
346       while Next_Col > 1 and then Buffer (Next_Col - 1) = ' ' loop
347          Next_Col := Next_Col - 1;
348       end loop;
349
350       Buffer (Next_Col) := ASCII.LF;
351       Next_Col := Next_Col + 1;
352       Flush_Buffer;
353    end Write_Eol;
354
355    ---------------------------
356    -- Write_Eol_Keep_Blanks --
357    ---------------------------
358
359    procedure Write_Eol_Keep_Blanks is
360    begin
361       Buffer (Next_Col) := ASCII.LF;
362       Next_Col := Next_Col + 1;
363       Flush_Buffer;
364    end Write_Eol_Keep_Blanks;
365
366    ----------------------
367    -- Write_Erase_Char --
368    ----------------------
369
370    procedure Write_Erase_Char (C : Character) is
371    begin
372       if Next_Col /= 1 and then Buffer (Next_Col - 1) = C then
373          Next_Col := Next_Col - 1;
374       end if;
375    end Write_Erase_Char;
376
377    ---------------
378    -- Write_Int --
379    ---------------
380
381    procedure Write_Int (Val : Int) is
382    begin
383       if Val < 0 then
384          Write_Char ('-');
385          Write_Int (-Val);
386
387       else
388          if Val > 9 then
389             Write_Int (Val / 10);
390          end if;
391
392          Write_Char (Character'Val ((Val mod 10) + Character'Pos ('0')));
393       end if;
394    end Write_Int;
395
396    ----------------
397    -- Write_Line --
398    ----------------
399
400    procedure Write_Line (S : String) is
401    begin
402       Write_Str (S);
403       Write_Eol;
404    end Write_Line;
405
406    ------------------
407    -- Write_Spaces --
408    ------------------
409
410    procedure Write_Spaces (N : Nat) is
411    begin
412       for J in 1 .. N loop
413          Write_Char (' ');
414       end loop;
415    end Write_Spaces;
416
417    ---------------
418    -- Write_Str --
419    ---------------
420
421    procedure Write_Str (S : String) is
422    begin
423       for J in S'Range loop
424          Write_Char (S (J));
425       end loop;
426    end Write_Str;
427
428 end Output;