OSDN Git Service

gcc/ChangeLog:
[pf3gnuchains/gcc-fork.git] / gcc / ada / xeinfo.adb
1 ------------------------------------------------------------------------------
2 --                                                                          --
3 --                          GNAT SYSTEM UTILITIES                           --
4 --                                                                          --
5 --                               X E I N F O                                --
6 --                                                                          --
7 --                                 B o d y                                  --
8 --                                                                          --
9 --          Copyright (C) 1992-2008, 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 --  Program to construct C header file a-einfo.h (C version of einfo.ads spec)
27 --  for use by Gigi. This header file contains all definitions and access
28 --  functions, but does not contain set procedures, since Gigi is not allowed
29 --  to modify the GNAT tree)
30
31 --    Input files:
32
33 --       einfo.ads     spec of Einfo package
34 --       einfo.adb     body of Einfo package
35
36 --    Output files:
37
38 --       a-einfo.h     Corresponding c header file
39
40 --  Note: It is assumed that the input files have been compiled without errors
41
42 --  An optional argument allows the specification of an output file name to
43 --  override the default a-einfo.h file name for the generated output file.
44
45 --  Most, but not all of the functions in Einfo can be inlined in the C header.
46 --  They are the functions identified by pragma Inline in the spec. Functions
47 --  that cannot be inlined are simply defined in the header.
48
49 with Ada.Command_Line;              use Ada.Command_Line;
50 with Ada.Strings.Unbounded;         use Ada.Strings.Unbounded;
51 with Ada.Strings.Unbounded.Text_IO; use Ada.Strings.Unbounded.Text_IO;
52 with Ada.Strings.Maps;              use Ada.Strings.Maps;
53 with Ada.Strings.Maps.Constants;    use Ada.Strings.Maps.Constants;
54 with Ada.Text_IO;                   use Ada.Text_IO;
55
56 with GNAT.Spitbol;                  use GNAT.Spitbol;
57 with GNAT.Spitbol.Patterns;         use GNAT.Spitbol.Patterns;
58 with GNAT.Spitbol.Table_Boolean;    use GNAT.Spitbol.Table_Boolean;
59
60 procedure XEinfo is
61
62    package TB renames GNAT.Spitbol.Table_Boolean;
63
64    Err : exception;
65
66    A         : VString := Nul;
67    B         : VString := Nul;
68    C         : VString := Nul;
69    Expr      : VString := Nul;
70    Filler    : VString := Nul;
71    Fline     : VString := Nul;
72    Formal    : VString := Nul;
73    Formaltyp : VString := Nul;
74    FN        : VString := Nul;
75    Line      : VString := Nul;
76    N         : VString := Nul;
77    N1        : VString := Nul;
78    N2        : VString := Nul;
79    N3        : VString := Nul;
80    Nam       : VString := Nul;
81    Name      : VString := Nul;
82    NewS      : VString := Nul;
83    Nextlin   : VString := Nul;
84    OldS      : VString := Nul;
85    Rtn       : VString := Nul;
86    Term      : VString := Nul;
87
88    InB : File_Type;
89    --  Used to read initial header from body
90
91    InF   : File_Type;
92    --  Used to read full text of both spec and body
93
94    Ofile : File_Type;
95    --  Used to write output file
96
97    wsp      : constant Pattern := NSpan (' ' & ASCII.HT);
98    Comment  : constant Pattern := wsp & "--";
99    For_Rep  : constant Pattern := wsp & "for";
100    Get_Func : constant Pattern := wsp * A & "function" & wsp
101                                   & Break (' ') * Name;
102    Inline   : constant Pattern := wsp & "pragma Inline (" & Break (')') * Name;
103    Get_Pack : constant Pattern := wsp & "package ";
104    Get_Enam : constant Pattern := wsp & Break (',') * N & ',';
105    Find_Fun : constant Pattern := wsp & "function";
106    F_Subtyp : constant Pattern := wsp * A & "subtype " & Break (' ') * N;
107    G_Subtyp : constant Pattern := wsp & "subtype" & wsp & Break (' ') * NewS
108                                   & wsp & "is" & wsp & Break (" ;") * OldS
109                                   & wsp & ';' & wsp & Rtab (0);
110    F_Typ    : constant Pattern := wsp * A & "type " & Break (' ') * N &
111                                   " is (";
112    Get_Nam  : constant Pattern := wsp * A & Break (",)") * Nam
113                                   & Len (1) * Term;
114    Get_Styp : constant Pattern := wsp * A & "subtype " & Break (' ') * N;
115    Get_N1   : constant Pattern := wsp & Break (' ') * N1;
116    Get_N2   : constant Pattern := wsp & "-- " & Rest * N2;
117    Get_N3   : constant Pattern := wsp & Break (';') * N3;
118    Get_FN   : constant Pattern := wsp * C & "function" & wsp
119                                   & Break (" (") * FN;
120    Is_Rturn : constant Pattern := BreakX ('r') & "return";
121    Is_Begin : constant Pattern := wsp & "begin";
122    Get_Asrt : constant Pattern := wsp & "pragma Assert";
123    Semicoln : constant Pattern := BreakX (';');
124    Get_Cmnt : constant Pattern := BreakX ('-') * A & "--";
125    Get_Expr : constant Pattern := wsp & "return " & Break (';') * Expr;
126    Chek_End : constant Pattern := wsp & "end" & BreakX (';') & ';';
127    Get_B1   : constant Pattern := BreakX (' ') * A & " in " & Rest * B;
128    Get_B2   : constant Pattern := BreakX (' ') * A & " = " & Rest * B;
129    Get_B3   : constant Pattern := BreakX (' ') * A & " /= " & Rest * B;
130    To_Paren : constant Pattern := wsp * Filler & '(';
131    Get_Fml  : constant Pattern := Break (" :") * Formal & wsp & ':' & wsp
132                                   & BreakX (" );") * Formaltyp;
133    Nxt_Fml  : constant Pattern := wsp & "; ";
134    Get_Rtn  : constant Pattern := wsp & "return" & wsp & BreakX (" ;") * Rtn;
135    Rem_Prn  : constant Pattern := wsp & ')';
136
137    M : Match_Result;
138
139    Lineno : Natural := 0;
140    --  Line number in spec
141
142    V   : Natural;
143    Ctr : Natural;
144
145    Inlined : TB.Table (200);
146    --  Inlined<N> = True for inlined function, False otherwise
147
148    Lastinlined : Boolean;
149
150    procedure Badfunc;
151    --  Signal bad function in body
152
153    function Getlin return VString;
154    --  Get non-comment line (comment lines skipped, also skips FOR rep clauses)
155    --  Fatal error (raises End_Error exception) if end of file encountered
156
157    procedure Must (B : Boolean);
158    --  Raises Err if the argument (a Match) call, returns False
159
160    procedure Sethead (Line : in out VString; Term : String);
161    --  Process function header into C
162
163    -------------
164    -- Badfunc --
165    -------------
166
167    procedure Badfunc is
168    begin
169       Put_Line
170         (Standard_Error,
171          "Body for function " & FN & " does not meet requirements");
172       raise Err;
173    end Badfunc;
174
175    -------------
176    -- Getlin --
177    -------------
178
179    function Getlin return VString is
180       Lin : VString;
181
182    begin
183       loop
184          Lin := Get_Line (InF);
185          Lineno := Lineno + 1;
186
187          if Lin /= ""
188            and then not Match (Lin, Comment)
189            and then not Match (Lin, For_Rep)
190          then
191             return Lin;
192          end if;
193       end loop;
194    end Getlin;
195
196    ----------
197    -- Must --
198    ----------
199
200    procedure Must (B : Boolean) is
201    begin
202       if not B then
203          raise Err;
204       end if;
205    end Must;
206
207    -------------
208    -- Sethead --
209    -------------
210
211    procedure Sethead (Line : in out VString; Term : String) is
212       Args : VString;
213
214    begin
215       Must (Match (Line, Get_Func, ""));
216       Args := Nul;
217
218       if Match (Line, To_Paren, "") then
219          Args := Filler & '(';
220
221          loop
222             Must (Match (Line, Get_Fml, ""));
223             Append (Args, Formaltyp & ' ' & Formal);
224             exit when not Match (Line, Nxt_Fml);
225             Append (Args, ",");
226          end loop;
227
228          Match (Line, Rem_Prn, "");
229          Append (Args, ')');
230       end if;
231
232       Must (Match (Line, Get_Rtn));
233
234       if Present (Inlined, Name) then
235          Put_Line (Ofile, A & "INLINE " & Rtn & ' ' & Name & Args & Term);
236       else
237          Put_Line (Ofile, A &  Rtn & ' ' & Name & Args & Term);
238       end if;
239    end Sethead;
240
241 --  Start of processing for XEinfo
242
243 begin
244    Anchored_Mode := True;
245
246    if Argument_Count > 0 then
247       Create (Ofile, Out_File, Argument (1));
248    else
249       Create (Ofile, Out_File, "a-einfo.h");
250    end if;
251
252    Open (InB, In_File, "einfo.adb");
253    Open (InF, In_File, "einfo.ads");
254
255    Lineno := 0;
256    loop
257       Line := Get_Line (InF);
258       Lineno := Lineno + 1;
259       exit when Line = "";
260
261       Match (Line,
262              "--                                 S p e c       ",
263              "--                              C Header File    ");
264       Match (Line, "--", "/*");
265       Match (Line, Rtab (2) * A & "--", M);
266       Replace (M, A & "*/");
267       Put_Line (Ofile, Line);
268    end loop;
269
270    Put_Line (Ofile, "");
271
272    --  Find and record pragma Inlines
273
274    loop
275       Line := Get_Line (InF);
276       exit when Match (Line, "   --  END XEINFO INLINES");
277
278       if Match (Line, Inline) then
279          Set (Inlined, Name, True);
280       end if;
281    end loop;
282
283    --  Skip to package line
284
285    Reset (InF, In_File);
286    Lineno := 0;
287
288    loop
289       Line := Getlin;
290       exit when Match (Line, Get_Pack);
291    end loop;
292
293    V := 0;
294    Line := Getlin;
295    Must (Match (Line, wsp & "type Entity_Kind"));
296
297    --  Process entity kind code definitions
298
299    loop
300       Line := Getlin;
301       exit when not Match (Line, Get_Enam);
302       Put_Line (Ofile, "   #define " & Rpad (N, 32) & " " & V);
303       V := V + 1;
304    end loop;
305
306    Must (Match (Line, wsp & Rest * N));
307    Put_Line (Ofile, "   #define " & Rpad (N, 32) & ' ' & V);
308    Line := Getlin;
309
310    Must (Match (Line, wsp & ");"));
311    Put_Line (Ofile, "");
312
313    --  Loop through subtype and type declarations
314
315    loop
316       Line := Getlin;
317       exit when Match (Line, Find_Fun);
318
319       --  Case of a subtype declaration
320
321       if Match (Line, F_Subtyp) then
322
323          --  Case of a subtype declaration that is an abbreviation of the
324          --  form subtype x is y, and if so generate the appropriate typedef
325
326          if Match (Line, G_Subtyp) then
327             Put_Line (Ofile, A & "typedef " & OldS & ' ' & NewS & ';');
328
329          --  Otherwise the subtype must be declaring a subrange of Entity_Id
330
331          else
332             Must (Match (Line, Get_Styp));
333             Line := Getlin;
334             Must (Match (Line, Get_N1));
335
336             loop
337                Line := Get_Line (InF);
338                Lineno := Lineno + 1;
339                exit when not Match (Line, Get_N2);
340             end loop;
341
342             Must (Match (Line, Get_N3));
343             Put_Line (Ofile, A & "SUBTYPE (" & N & ", Entity_Kind, ");
344             Put_Line (Ofile, A & "   " & N1 & ", " & N3 & ')');
345             Put_Line (Ofile, "");
346          end if;
347
348       --  Case of type declaration
349
350       elsif Match (Line, F_Typ) then
351          --  Process type declaration (must be enumeration type)
352
353          Ctr := 0;
354          Put_Line (Ofile, A & "typedef char " & N & ';');
355
356          loop
357             Line := Getlin;
358             Must (Match (Line, Get_Nam));
359             Put_Line (Ofile, A & "#define " & Rpad (Nam, 25) & Ctr);
360             Ctr := Ctr + 1;
361             exit when Term /= ",";
362          end loop;
363
364          Put_Line (Ofile, "");
365
366       --  Neither subtype nor type declaration
367
368       else
369          raise Err;
370       end if;
371    end loop;
372
373    --  Process function declarations
374    --  Note: Lastinlined used to control blank lines
375
376    Put_Line (Ofile, "");
377    Lastinlined := True;
378
379    --  Loop through function declarations
380
381    while Match (Line, Get_FN) loop
382
383       --  Non-inlined function
384
385       if not Present (Inlined, FN) then
386          Put_Line (Ofile, "");
387          Put_Line
388            (Ofile,
389             "   #define " & FN & " einfo__" & Translate (FN, Lower_Case_Map));
390
391       --  Inlined function
392
393       else
394          if not Lastinlined then
395             Put_Line (Ofile, "");
396          end if;
397       end if;
398
399       --  Merge here to output spec
400
401       Sethead (Line, ";");
402       Lastinlined := Get (Inlined, FN);
403       Line := Getlin;
404    end loop;
405
406    Put_Line (Ofile, "");
407
408    --  Read body to find inlined functions
409
410    Close (InB);
411    Close (InF);
412    Open (InF, In_File, "einfo.adb");
413    Lineno := 0;
414
415    --  Loop through input lines to find bodies of inlined functions
416
417    while not End_Of_File (InF) loop
418       Fline := Get_Line (InF);
419
420       if Match (Fline, Get_FN)
421         and then Get (Inlined, FN)
422       then
423          --  Here we have an inlined function
424
425          if not Match (Fline, Is_Rturn) then
426             Line := Fline;
427             Badfunc;
428          end if;
429
430          Line := Getlin;
431
432          if not Match (Line, Is_Begin) then
433             Badfunc;
434          end if;
435
436          --  Skip past pragma Asserts
437
438          loop
439             Line := Getlin;
440             exit when not Match (Line, Get_Asrt);
441
442             --  Pragma assert found, get its continuation lines
443
444             loop
445                exit when Match (Line, Semicoln);
446                Line := Getlin;
447             end loop;
448          end loop;
449
450          --  Process return statement
451
452          Match (Line, Get_Cmnt, M);
453          Replace (M, A);
454
455          --  Get continuations of return statement
456
457          while not Match (Line, Semicoln) loop
458             Nextlin := Getlin;
459             Match (Nextlin, wsp, " ");
460             Append (Line, Nextlin);
461          end loop;
462
463          if not Match (Line, Get_Expr) then
464             Badfunc;
465          end if;
466
467          Line := Getlin;
468
469          if not Match (Line, Chek_End) then
470             Badfunc;
471          end if;
472
473          Match (Expr, Get_B1, M);
474          Replace (M, "IN (" & A & ", " & B & ')');
475          Match (Expr, Get_B2, M);
476          Replace (M, A & " == " & B);
477          Match (Expr, Get_B3, M);
478          Replace (M, A & " != " & B);
479          Put_Line (Ofile, "");
480          Sethead (Fline, "");
481          Put_Line (Ofile, C & "   { return " & Expr & "; }");
482       end if;
483    end loop;
484
485    Put_Line (Ofile, "");
486    Put_Line
487      (Ofile,
488       "/* End of einfo.h (C version of Einfo package specification) */");
489
490 exception
491    when Err =>
492       Put_Line (Standard_Error, Lineno & ".  " & Line);
493       Put_Line (Standard_Error, "**** fatal error ****");
494       Set_Exit_Status (1);
495
496    when End_Error =>
497       Put_Line (Standard_Error, "unexpected end of file");
498       Put_Line (Standard_Error, "**** fatal error ****");
499
500 end XEinfo;