OSDN Git Service

* env.c [__alpha__ && __osf__] (AES_SOURCE): Define.
[pf3gnuchains/gcc-fork.git] / gcc / ada / xoscons.adb
1 ------------------------------------------------------------------------------
2 --                                                                          --
3 --                          GNAT SYSTEM UTILITIES                           --
4 --                                                                          --
5 --                              X O S C O N S                               --
6 --                                                                          --
7 --                                 B o d y                                  --
8 --                                                                          --
9 --          Copyright (C) 2008-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.  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 COPYING3.  If not, go to --
19 -- http://www.gnu.org/licenses for a complete copy of the license.          --
20 --                                                                          --
21 -- GNAT was originally developed  by the GNAT team at  New York University. --
22 -- Extensive contributions were provided by Ada Core Technologies Inc.      --
23 --                                                                          --
24 ------------------------------------------------------------------------------
25
26 --  This program generates the spec of System.OS_Constants (s-oscons.ads)
27
28 --  It works in conjunction with a C template file which must be pre-processed
29 --  and compiled using the cross compiler. Two input files are used:
30 --    - the preprocessed C file: s-oscons-tmplt.i
31 --    - the generated assembly file: s-oscons-tmplt.s
32
33 --  The contents of s-oscons.ads is written on standard output
34
35 with Ada.Characters.Handling; use Ada.Characters.Handling;
36 with Ada.Exceptions;          use Ada.Exceptions;
37 with Ada.Strings.Fixed;       use Ada.Strings.Fixed;
38 with Ada.Text_IO;             use Ada.Text_IO;
39 with Ada.Streams.Stream_IO;   use Ada.Streams.Stream_IO;
40
41 pragma Warnings (Off);
42 --  System.Unsigned_Types is an internal GNAT unit
43 with System.Unsigned_Types;   use System.Unsigned_Types;
44 pragma Warnings (On);
45
46 with GNAT.Table;
47
48 with XUtil;                   use XUtil;
49
50 procedure XOSCons is
51
52    use ASCII;
53    use Ada.Strings;
54
55    Unit_Name : constant String := "s-oscons";
56    Tmpl_Name : constant String := Unit_Name & "-tmplt";
57
58    -------------------------------------------------
59    -- Information retrieved from assembly listing --
60    -------------------------------------------------
61
62    type String_Access is access all String;
63    --  Note: we can't use GNAT.Strings for this definition, since that unit
64    --  is not available in older base compilers.
65
66    --  We need to deal with integer values that can be signed or unsigned, so
67    --  we need to accomodate the maximum range of both cases.
68
69    type Int_Value_Type is record
70       Positive  : Boolean;
71       Abs_Value : Long_Unsigned := 0;
72    end record;
73
74    type Asm_Info_Kind is
75      (CND,     --  Constant (decimal)
76       CNS,     --  Constant (freeform string)
77       TXT);    --  Literal text
78    --  Recognized markers found in assembly file. These markers are produced by
79    --  the same-named macros from the C template.
80
81    type Asm_Info (Kind : Asm_Info_Kind := TXT) is record
82       Line_Number   : Integer;
83       --  Line number in C source file
84
85       Constant_Name : String_Access;
86       --  Name of constant to be defined
87
88       Value_Len     : Natural := 0;
89       --  Length of text representation of constant's value
90
91       Text_Value    : String_Access;
92       --  Value for CNS constant
93
94       Int_Value     : Int_Value_Type;
95       --  Value for CND constant
96
97       Comment       : String_Access;
98       --  Additional descriptive comment for constant, or free-form text (TXT)
99    end record;
100
101    package Asm_Infos is new GNAT.Table
102      (Table_Component_Type => Asm_Info,
103       Table_Index_Type     => Integer,
104       Table_Low_Bound      => 1,
105       Table_Initial        => 100,
106       Table_Increment      => 10);
107
108    Max_Const_Name_Len     : Natural := 0;
109    Max_Constant_Value_Len : Natural := 0;
110    --  Lengths of longest name and longest value
111
112    type Language is (Lang_Ada, Lang_C);
113
114    procedure Output_Info
115      (Lang       : Language;
116       OFile      : Sfile;
117       Info_Index : Integer);
118    --  Output information from the indicated asm info line
119
120    procedure Parse_Asm_Line (Line : String);
121    --  Parse one information line from the assembly source
122
123    function Contains_Template_Name (S : String) return Boolean;
124    --  True if S contains Tmpl_Name, possibly with different casing
125
126    function Spaces (Count : Integer) return String;
127    --  If Count is positive, return a string of Count spaces, else return an
128    --  empty string.
129
130    ----------------------------
131    -- Contains_Template_Name --
132    ----------------------------
133
134    function Contains_Template_Name (S : String) return Boolean is
135    begin
136       if Index (Source => To_Lower (S), Pattern => Tmpl_Name) > 0 then
137          return True;
138       else
139          return False;
140       end if;
141    end Contains_Template_Name;
142
143    -----------------
144    -- Output_Info --
145    -----------------
146
147    procedure Output_Info
148      (Lang       : Language;
149       OFile      : Sfile;
150       Info_Index : Integer)
151    is
152       Info : Asm_Info renames Asm_Infos.Table (Info_Index);
153
154       procedure Put (S : String);
155       --  Write S to OFile
156
157       ---------
158       -- Put --
159       ---------
160
161       procedure Put (S : String) is
162       begin
163          Put (OFile, S);
164       end Put;
165
166    begin
167       if Info.Kind /= TXT then
168          --  TXT case is handled by the common code below
169
170          case Lang is
171             when Lang_Ada =>
172                Put ("   " & Info.Constant_Name.all);
173                Put (Spaces (Max_Const_Name_Len - Info.Constant_Name'Length));
174
175                Put (" : constant := ");
176
177             when Lang_C =>
178                Put ("#define " & Info.Constant_Name.all & " ");
179                Put (Spaces (Max_Const_Name_Len - Info.Constant_Name'Length));
180          end case;
181
182          if Info.Kind = CND then
183             if not Info.Int_Value.Positive then
184                Put ("-");
185             end if;
186             Put (Trim (Info.Int_Value.Abs_Value'Img, Side => Left));
187          else
188             Put (Info.Text_Value.all);
189          end if;
190
191          if Lang = Lang_Ada then
192             Put (";");
193
194             if Info.Comment'Length > 0 then
195                Put (Spaces (Max_Constant_Value_Len - Info.Value_Len));
196                Put (" --  ");
197             end if;
198          end if;
199       end if;
200
201       if Lang = Lang_Ada then
202          Put (Info.Comment.all);
203       end if;
204
205       New_Line (OFile);
206    end Output_Info;
207
208    --------------------
209    -- Parse_Asm_Line --
210    --------------------
211
212    procedure Parse_Asm_Line (Line : String) is
213       Index1, Index2 : Integer := Line'First;
214
215       function Field_Alloc return String_Access;
216       --  Allocate and return a copy of Line (Index1 .. Index2 - 1)
217
218       procedure Find_Colon (Index : in out Integer);
219       --  Increment Index until the next colon in Line
220
221       function Parse_Int (S : String) return Int_Value_Type;
222       --  Parse a decimal number, preceded by an optional '$' or '#' character,
223       --  and return its value.
224
225       -----------------
226       -- Field_Alloc --
227       -----------------
228
229       function Field_Alloc return String_Access is
230       begin
231          return new String'(Line (Index1 .. Index2 - 1));
232       end Field_Alloc;
233
234       ----------------
235       -- Find_Colon --
236       ----------------
237
238       procedure Find_Colon (Index : in out Integer) is
239       begin
240          loop
241             Index := Index + 1;
242             exit when Index > Line'Last or else Line (Index) = ':';
243          end loop;
244       end Find_Colon;
245
246       ---------------
247       -- Parse_Int --
248       ---------------
249
250       function Parse_Int (S : String) return Int_Value_Type is
251          First    : Integer := S'First;
252          Positive : Boolean;
253       begin
254          --  On some platforms, immediate integer values are prefixed with
255          --  a $ or # character in assembly output.
256
257          if S (First) = '$' or else S (First) = '#' then
258             First := First + 1;
259          end if;
260
261          if S (First) = '-' then
262             Positive := False;
263             First    := First + 1;
264          else
265             Positive := True;
266          end if;
267
268          return (Positive  => Positive,
269                  Abs_Value => Long_Unsigned'Value (S (First .. S'Last)));
270
271       exception
272          when E : others =>
273             Put_Line (Standard_Error, "can't parse decimal value: " & S);
274             raise;
275       end Parse_Int;
276
277    --  Start of processing for Parse_Asm_Line
278
279    begin
280       Find_Colon (Index2);
281
282       declare
283          Info : Asm_Info (Kind => Asm_Info_Kind'Value
284                                     (Line (Line'First .. Index2 - 1)));
285       begin
286          Index1 := Index2 + 1;
287          Find_Colon (Index2);
288
289          Info.Line_Number :=
290            Integer (Parse_Int (Line (Index1 .. Index2 - 1)).Abs_Value);
291
292          case Info.Kind is
293             when CND | CNS =>
294                Index1 := Index2 + 1;
295                Find_Colon (Index2);
296
297                Info.Constant_Name := Field_Alloc;
298                if Info.Constant_Name'Length > Max_Const_Name_Len then
299                   Max_Const_Name_Len := Info.Constant_Name'Length;
300                end if;
301
302                Index1 := Index2 + 1;
303                Find_Colon (Index2);
304
305                if Info.Kind = CND then
306                   Info.Int_Value := Parse_Int (Line (Index1 .. Index2 - 1));
307                   Info.Value_Len := Index2 - Index1 - 1;
308
309                else
310                   Info.Text_Value := Field_Alloc;
311                   Info.Value_Len  := Info.Text_Value'Length;
312                end if;
313
314             when others =>
315                null;
316          end case;
317
318          Index1 := Index2 + 1;
319          Index2 := Line'Last + 1;
320          Info.Comment := Field_Alloc;
321
322          if Info.Kind = TXT then
323             Info.Text_Value := Info.Comment;
324
325          --  Update Max_Constant_Value_Len, but only if this constant has a
326          --  comment (else the value is allowed to be longer).
327
328          elsif Info.Comment'Length > 0 then
329             if Info.Value_Len > Max_Constant_Value_Len then
330                Max_Constant_Value_Len := Info.Value_Len;
331             end if;
332          end if;
333
334          Asm_Infos.Append (Info);
335       end;
336    exception
337       when E : others =>
338          Put_Line (Standard_Error,
339            "can't parse " & Line);
340          Put_Line (Standard_Error,
341            "exception raised: " & Exception_Information (E));
342    end Parse_Asm_Line;
343
344    ------------
345    -- Spaces --
346    ------------
347
348    function Spaces (Count : Integer) return String is
349    begin
350       if Count <= 0 then
351          return "";
352       else
353          return (1 .. Count => ' ');
354       end if;
355    end Spaces;
356
357    --  Local declarations
358
359    --  Input files
360
361    Tmpl_File_Name : constant String := Tmpl_Name & ".i";
362    Asm_File_Name  : constant String := Tmpl_Name & ".s";
363
364    --  Output files
365
366    Ada_File_Name  : constant String := Unit_Name & ".ads";
367    C_File_Name    : constant String := Unit_Name & ".h";
368
369    Asm_File  : Ada.Text_IO.File_Type;
370    Tmpl_File : Ada.Text_IO.File_Type;
371    Ada_OFile : Sfile;
372    C_OFile   : Sfile;
373
374    Line : String (1 .. 256);
375    Last : Integer;
376    --  Line being processed
377
378    Current_Line : Integer;
379    Current_Info : Integer;
380    In_Comment   : Boolean;
381    In_Template  : Boolean;
382
383 --  Start of processing for XOSCons
384
385 begin
386    --  Load values from assembly file
387
388    Open (Asm_File, In_File, Asm_File_Name);
389
390    while not End_Of_File (Asm_File) loop
391       Get_Line (Asm_File, Line, Last);
392       if Last > 2 and then Line (1 .. 2) = "->" then
393          Parse_Asm_Line (Line (3 .. Last));
394       end if;
395    end loop;
396
397    Close (Asm_File);
398
399    --  Load C template and output definitions
400
401    Open   (Tmpl_File, In_File,  Tmpl_File_Name);
402    Create (Ada_OFile, Out_File, Ada_File_Name);
403    Create (C_OFile,   Out_File, C_File_Name);
404
405    Current_Line := 0;
406    Current_Info := Asm_Infos.First;
407    In_Comment   := False;
408
409    while not End_Of_File (Tmpl_File) loop
410       <<Get_One_Line>>
411       Get_Line (Tmpl_File, Line, Last);
412
413       if Last >= 2 and then Line (1 .. 2) = "# " then
414          declare
415             Index : Integer := 3;
416          begin
417             while Index <= Last and then Line (Index) in '0' .. '9' loop
418                Index := Index + 1;
419             end loop;
420
421             if Contains_Template_Name (Line (Index + 1 .. Last)) then
422                Current_Line := Integer'Value (Line (3 .. Index - 1));
423                In_Template  := True;
424                goto Get_One_Line;
425             else
426                In_Template := False;
427             end if;
428          end;
429
430       elsif In_Template then
431          if In_Comment then
432             if Line (1 .. Last) = "*/" then
433                Put_Line (C_OFile, Line (1 .. Last));
434                In_Comment := False;
435             else
436                Put_Line (Ada_OFile, Line (1 .. Last));
437                Put_Line (C_OFile, Line (1 .. Last));
438             end if;
439
440          elsif Line (1 .. Last) = "/*" then
441             Put_Line (C_OFile, Line (1 .. Last));
442             In_Comment := True;
443
444          elsif Asm_Infos.Table (Current_Info).Line_Number = Current_Line then
445             Output_Info (Lang_Ada, Ada_OFile, Current_Info);
446             Output_Info (Lang_C,   C_OFile,   Current_Info);
447             Current_Info := Current_Info + 1;
448          end if;
449
450          Current_Line := Current_Line + 1;
451       end if;
452    end loop;
453
454    Close (Tmpl_File);
455
456 end XOSCons;