OSDN Git Service

* gcc-interface/decl.c (make_type_from_size) <INTEGER_TYPE>: Just copy
[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,     --  Named number (decimal)
76       CNS,     --  Named number (freeform text)
77       C,       --  Constant object
78       TXT);    --  Literal text
79    --  Recognized markers found in assembly file. These markers are produced by
80    --  the same-named macros from the C template.
81
82    subtype Named_Number is Asm_Info_Kind range CND .. CNS;
83
84    type Asm_Info (Kind : Asm_Info_Kind := TXT) is record
85       Line_Number   : Integer;
86       --  Line number in C source file
87
88       Constant_Name : String_Access;
89       --  Name of constant to be defined
90
91       Constant_Type : String_Access;
92       --  Type of constant (case of Kind = C)
93
94       Value_Len     : Natural := 0;
95       --  Length of text representation of constant's value
96
97       Text_Value    : String_Access;
98       --  Value for CNS / C constant
99
100       Int_Value     : Int_Value_Type;
101       --  Value for CND constant
102
103       Comment       : String_Access;
104       --  Additional descriptive comment for constant, or free-form text (TXT)
105    end record;
106
107    package Asm_Infos is new GNAT.Table
108      (Table_Component_Type => Asm_Info,
109       Table_Index_Type     => Integer,
110       Table_Low_Bound      => 1,
111       Table_Initial        => 100,
112       Table_Increment      => 10);
113
114    Max_Constant_Name_Len  : Natural := 0;
115    Max_Constant_Value_Len : Natural := 0;
116    Max_Constant_Type_Len  : Natural := 0;
117    --  Lengths of longest name and longest value
118
119    type Language is (Lang_Ada, Lang_C);
120
121    procedure Output_Info
122      (Lang       : Language;
123       OFile      : Sfile;
124       Info_Index : Integer);
125    --  Output information from the indicated asm info line
126
127    procedure Parse_Asm_Line (Line : String);
128    --  Parse one information line from the assembly source
129
130    function Contains_Template_Name (S : String) return Boolean;
131    --  True if S contains Tmpl_Name, possibly with different casing
132
133    function Spaces (Count : Integer) return String;
134    --  If Count is positive, return a string of Count spaces, else return an
135    --  empty string.
136
137    ----------------------------
138    -- Contains_Template_Name --
139    ----------------------------
140
141    function Contains_Template_Name (S : String) return Boolean is
142    begin
143       if Index (Source => To_Lower (S), Pattern => Tmpl_Name) > 0 then
144          return True;
145       else
146          return False;
147       end if;
148    end Contains_Template_Name;
149
150    -----------------
151    -- Output_Info --
152    -----------------
153
154    procedure Output_Info
155      (Lang       : Language;
156       OFile      : Sfile;
157       Info_Index : Integer)
158    is
159       Info : Asm_Info renames Asm_Infos.Table (Info_Index);
160
161       procedure Put (S : String);
162       --  Write S to OFile
163
164       ---------
165       -- Put --
166       ---------
167
168       procedure Put (S : String) is
169       begin
170          Put (OFile, S);
171       end Put;
172
173    begin
174       if Info.Kind /= TXT then
175          --  TXT case is handled by the common code below
176
177          case Lang is
178             when Lang_Ada =>
179                Put ("   " & Info.Constant_Name.all);
180                Put (Spaces (Max_Constant_Name_Len
181                               - Info.Constant_Name'Length));
182
183                if Info.Kind in Named_Number then
184                   Put (" : constant := ");
185                else
186                   Put (" : constant " & Info.Constant_Type.all);
187                   Put (Spaces (Max_Constant_Type_Len
188                                  - Info.Constant_Type'Length));
189                   Put (" := ");
190                end if;
191
192             when Lang_C =>
193                Put ("#define " & Info.Constant_Name.all & " ");
194                Put (Spaces (Max_Constant_Name_Len
195                               - Info.Constant_Name'Length));
196          end case;
197
198          if Info.Kind = CND then
199             if not Info.Int_Value.Positive then
200                Put ("-");
201             end if;
202             Put (Trim (Info.Int_Value.Abs_Value'Img, Side => Left));
203          else
204             declare
205                Is_String : constant Boolean :=
206                              Info.Kind = C
207                                and then Info.Constant_Type.all = "String";
208             begin
209                if Is_String then
210                   Put ("""");
211                end if;
212                Put (Info.Text_Value.all);
213                if Is_String then
214                   Put ("""");
215                end if;
216             end;
217          end if;
218
219          if Lang = Lang_Ada then
220             Put (";");
221
222             if Info.Comment'Length > 0 then
223                Put (Spaces (Max_Constant_Value_Len - Info.Value_Len));
224                Put (" --  ");
225             end if;
226          end if;
227       end if;
228
229       if Lang = Lang_Ada then
230          Put (Info.Comment.all);
231       end if;
232
233       New_Line (OFile);
234    end Output_Info;
235
236    --------------------
237    -- Parse_Asm_Line --
238    --------------------
239
240    procedure Parse_Asm_Line (Line : String) is
241       Index1, Index2 : Integer := Line'First;
242
243       function Field_Alloc return String_Access;
244       --  Allocate and return a copy of Line (Index1 .. Index2 - 1)
245
246       procedure Find_Colon (Index : in out Integer);
247       --  Increment Index until the next colon in Line
248
249       function Parse_Int (S : String) return Int_Value_Type;
250       --  Parse a decimal number, preceded by an optional '$' or '#' character,
251       --  and return its value.
252
253       -----------------
254       -- Field_Alloc --
255       -----------------
256
257       function Field_Alloc return String_Access is
258       begin
259          return new String'(Line (Index1 .. Index2 - 1));
260       end Field_Alloc;
261
262       ----------------
263       -- Find_Colon --
264       ----------------
265
266       procedure Find_Colon (Index : in out Integer) is
267       begin
268          loop
269             Index := Index + 1;
270             exit when Index > Line'Last or else Line (Index) = ':';
271          end loop;
272       end Find_Colon;
273
274       ---------------
275       -- Parse_Int --
276       ---------------
277
278       function Parse_Int (S : String) return Int_Value_Type is
279          First    : Integer := S'First;
280          Positive : Boolean;
281       begin
282          --  On some platforms, immediate integer values are prefixed with
283          --  a $ or # character in assembly output.
284
285          if S (First) = '$' or else S (First) = '#' then
286             First := First + 1;
287          end if;
288
289          if S (First) = '-' then
290             Positive := False;
291             First    := First + 1;
292          else
293             Positive := True;
294          end if;
295
296          return (Positive  => Positive,
297                  Abs_Value => Long_Unsigned'Value (S (First .. S'Last)));
298
299       exception
300          when E : others =>
301             Put_Line (Standard_Error, "can't parse decimal value: " & S);
302             raise;
303       end Parse_Int;
304
305    --  Start of processing for Parse_Asm_Line
306
307    begin
308       Find_Colon (Index2);
309
310       declare
311          Info : Asm_Info (Kind => Asm_Info_Kind'Value
312                                     (Line (Line'First .. Index2 - 1)));
313       begin
314          Index1 := Index2 + 1;
315          Find_Colon (Index2);
316
317          Info.Line_Number :=
318            Integer (Parse_Int (Line (Index1 .. Index2 - 1)).Abs_Value);
319
320          case Info.Kind is
321             when CND | CNS | C =>
322                Index1 := Index2 + 1;
323                Find_Colon (Index2);
324
325                Info.Constant_Name := Field_Alloc;
326                if Info.Constant_Name'Length > Max_Constant_Name_Len then
327                   Max_Constant_Name_Len := Info.Constant_Name'Length;
328                end if;
329
330                Index1 := Index2 + 1;
331                Find_Colon (Index2);
332
333                if Info.Kind = C then
334                   Info.Constant_Type := Field_Alloc;
335                   if Info.Constant_Type'Length > Max_Constant_Type_Len then
336                      Max_Constant_Type_Len := Info.Constant_Type'Length;
337                   end if;
338
339                   Index1 := Index2 + 1;
340                   Find_Colon (Index2);
341                end if;
342
343                if Info.Kind = CND then
344                   Info.Int_Value := Parse_Int (Line (Index1 .. Index2 - 1));
345                   Info.Value_Len := Index2 - Index1 - 1;
346
347                else
348                   Info.Text_Value := Field_Alloc;
349                   Info.Value_Len  := Info.Text_Value'Length;
350                end if;
351
352             when others =>
353                null;
354          end case;
355
356          Index1 := Index2 + 1;
357          Index2 := Line'Last + 1;
358          Info.Comment := Field_Alloc;
359
360          if Info.Kind = TXT then
361             Info.Text_Value := Info.Comment;
362
363          --  Update Max_Constant_Value_Len, but only if this constant has a
364          --  comment (else the value is allowed to be longer).
365
366          elsif Info.Comment'Length > 0 then
367             if Info.Value_Len > Max_Constant_Value_Len then
368                Max_Constant_Value_Len := Info.Value_Len;
369             end if;
370          end if;
371
372          Asm_Infos.Append (Info);
373       end;
374    exception
375       when E : others =>
376          Put_Line (Standard_Error,
377            "can't parse " & Line);
378          Put_Line (Standard_Error,
379            "exception raised: " & Exception_Information (E));
380    end Parse_Asm_Line;
381
382    ------------
383    -- Spaces --
384    ------------
385
386    function Spaces (Count : Integer) return String is
387    begin
388       if Count <= 0 then
389          return "";
390       else
391          return (1 .. Count => ' ');
392       end if;
393    end Spaces;
394
395    --  Local declarations
396
397    --  Input files
398
399    Tmpl_File_Name : constant String := Tmpl_Name & ".i";
400    Asm_File_Name  : constant String := Tmpl_Name & ".s";
401
402    --  Output files
403
404    Ada_File_Name  : constant String := Unit_Name & ".ads";
405    C_File_Name    : constant String := Unit_Name & ".h";
406
407    Asm_File  : Ada.Text_IO.File_Type;
408    Tmpl_File : Ada.Text_IO.File_Type;
409    Ada_OFile : Sfile;
410    C_OFile   : Sfile;
411
412    Line : String (1 .. 256);
413    Last : Integer;
414    --  Line being processed
415
416    Current_Line : Integer;
417    Current_Info : Integer;
418    In_Comment   : Boolean;
419    In_Template  : Boolean;
420
421 --  Start of processing for XOSCons
422
423 begin
424    --  Load values from assembly file
425
426    Open (Asm_File, In_File, Asm_File_Name);
427
428    while not End_Of_File (Asm_File) loop
429       Get_Line (Asm_File, Line, Last);
430       if Last > 2 and then Line (1 .. 2) = "->" then
431          Parse_Asm_Line (Line (3 .. Last));
432       end if;
433    end loop;
434
435    Close (Asm_File);
436
437    --  Load C template and output definitions
438
439    Open   (Tmpl_File, In_File,  Tmpl_File_Name);
440    Create (Ada_OFile, Out_File, Ada_File_Name);
441    Create (C_OFile,   Out_File, C_File_Name);
442
443    Current_Line := 0;
444    Current_Info := Asm_Infos.First;
445    In_Comment   := False;
446
447    while not End_Of_File (Tmpl_File) loop
448       <<Get_One_Line>>
449       Get_Line (Tmpl_File, Line, Last);
450
451       if Last >= 2 and then Line (1 .. 2) = "# " then
452          declare
453             Index : Integer := 3;
454          begin
455             while Index <= Last and then Line (Index) in '0' .. '9' loop
456                Index := Index + 1;
457             end loop;
458
459             if Contains_Template_Name (Line (Index + 1 .. Last)) then
460                Current_Line := Integer'Value (Line (3 .. Index - 1));
461                In_Template  := True;
462                goto Get_One_Line;
463             else
464                In_Template := False;
465             end if;
466          end;
467
468       elsif In_Template then
469          if In_Comment then
470             if Line (1 .. Last) = "*/" then
471                Put_Line (C_OFile, Line (1 .. Last));
472                In_Comment := False;
473             else
474                Put_Line (Ada_OFile, Line (1 .. Last));
475                Put_Line (C_OFile, Line (1 .. Last));
476             end if;
477
478          elsif Line (1 .. Last) = "/*" then
479             Put_Line (C_OFile, Line (1 .. Last));
480             In_Comment := True;
481
482          elsif Asm_Infos.Table (Current_Info).Line_Number = Current_Line then
483             Output_Info (Lang_Ada, Ada_OFile, Current_Info);
484             Output_Info (Lang_C,   C_OFile,   Current_Info);
485             Current_Info := Current_Info + 1;
486          end if;
487
488          Current_Line := Current_Line + 1;
489       end if;
490    end loop;
491
492    Close (Tmpl_File);
493
494 end XOSCons;