Merge -r 127928:132243 from trunk
[official-gcc.git] / gcc / ada / xnmake.adb
blob3b3ed830b3a0b2e499699674d57dbbe2406dad08
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT SYSTEM UTILITIES --
4 -- --
5 -- X N M A K E --
6 -- --
7 -- B o d y --
8 -- --
9 -- Copyright (C) 1992-2007, 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 ------------------------------------------------------------------------------
26 -- Program to construct the spec and body of the Nmake package
28 -- Input files:
30 -- sinfo.ads Spec of Sinfo package
31 -- nmake.adt Template for Nmake package
33 -- Output files:
35 -- nmake.ads Spec of Nmake package
36 -- nmake.adb Body of Nmake package
38 -- Note: this program assumes that sinfo.ads has passed the error checks that
39 -- are carried out by the csinfo utility, so it does not duplicate these
40 -- checks and assumes that sinfo.ads has the correct form.
42 -- In the absence of any switches, both the ads and adb files are output.
43 -- The switch -s or /s indicates that only the ads file is to be output.
44 -- The switch -b or /b indicates that only the adb file is to be output.
46 -- If a file name argument is given, then the output is written to this file
47 -- rather than to nmake.ads or nmake.adb. A file name can only be given if
48 -- exactly one of the -s or -b options is present.
50 with Ada.Command_Line; use Ada.Command_Line;
51 with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
52 with Ada.Strings.Unbounded.Text_IO; use Ada.Strings.Unbounded.Text_IO;
53 with Ada.Strings.Maps; use Ada.Strings.Maps;
54 with Ada.Strings.Maps.Constants; use Ada.Strings.Maps.Constants;
55 with Ada.Streams.Stream_IO; use Ada.Streams.Stream_IO;
56 with Ada.Text_IO; use Ada.Text_IO;
58 with GNAT.Spitbol; use GNAT.Spitbol;
59 with GNAT.Spitbol.Patterns; use GNAT.Spitbol.Patterns;
61 procedure XNmake is
63 Err : exception;
64 -- Raised to terminate execution
66 pragma Warnings (Off);
67 -- The following are modified by * operator
69 A : VString := Nul;
70 Arg : VString := Nul;
71 Arg_List : VString := Nul;
72 Comment : VString := Nul;
73 Default : VString := Nul;
74 Field : VString := Nul;
75 Line : VString := Nul;
76 Node : VString := Nul;
77 Op_Name : VString := Nul;
78 Prevl : VString := Nul;
79 Synonym : VString := Nul;
80 X : VString := Nul;
82 NWidth : Natural;
84 FileS : VString := V ("nmake.ads");
85 FileB : VString := V ("nmake.adb");
86 -- Set to null if corresponding file not to be generated
88 Given_File : VString := Nul;
89 -- File name given by command line argument
91 subtype Sfile is Ada.Streams.Stream_IO.File_Type;
93 InS, InT : Ada.Text_IO.File_Type;
94 OutS, OutB : Sfile;
96 wsp : constant Pattern := Span (' ' & ASCII.HT);
98 Body_Only : constant Pattern := BreakX (' ') * X
99 & Span (' ') & "-- body only";
100 Spec_Only : constant Pattern := BreakX (' ') * X
101 & Span (' ') & "-- spec only";
103 Node_Hdr : constant Pattern := wsp & "-- N_" & Rest * Node;
104 Punc : constant Pattern := BreakX (" .,");
106 Binop : constant Pattern := wsp
107 & "-- plus fields for binary operator";
108 Unop : constant Pattern := wsp
109 & "-- plus fields for unary operator";
110 Syn : constant Pattern := wsp & "-- " & Break (' ') * Synonym
111 & " (" & Break (')') * Field
112 & Rest * Comment;
114 Templ : constant Pattern := BreakX ('T') * A & "T e m p l a t e";
115 Spec : constant Pattern := BreakX ('S') * A & "S p e c";
117 Sem_Field : constant Pattern := BreakX ('-') & "-Sem";
118 Lib_Field : constant Pattern := BreakX ('-') & "-Lib";
120 Get_Field : constant Pattern := BreakX (Decimal_Digit_Set) * Field;
122 Get_Dflt : constant Pattern := BreakX ('(') & "(set to "
123 & Break (" ") * Default & " if";
125 Next_Arg : constant Pattern := Break (',') * Arg & ',';
127 Op_Node : constant Pattern := "Op_" & Rest * Op_Name;
129 Shft_Rot : constant Pattern := "Shift_" or "Rotate_";
131 No_Ent : constant Pattern := "Or_Else" or "And_Then"
132 or "In" or "Not_In";
134 M : Match_Result;
136 V_String_Id : constant VString := V ("String_Id");
137 V_Node_Id : constant VString := V ("Node_Id");
138 V_Name_Id : constant VString := V ("Name_Id");
139 V_List_Id : constant VString := V ("List_Id");
140 V_Elist_Id : constant VString := V ("Elist_Id");
141 V_Boolean : constant VString := V ("Boolean");
143 procedure Put_Line (F : Sfile; S : String);
144 procedure Put_Line (F : Sfile; S : VString);
145 -- Local version of Put_Line ensures Unix style line endings
147 procedure WriteS (S : String);
148 procedure WriteB (S : String);
149 procedure WriteBS (S : String);
150 procedure WriteS (S : VString);
151 procedure WriteB (S : VString);
152 procedure WriteBS (S : VString);
153 -- Write given line to spec or body file or both if active
155 procedure WriteB (S : String) is
156 begin
157 if FileB /= Nul then
158 Put_Line (OutB, S);
159 end if;
160 end WriteB;
162 procedure WriteB (S : VString) is
163 begin
164 if FileB /= Nul then
165 Put_Line (OutB, S);
166 end if;
167 end WriteB;
169 procedure WriteBS (S : String) is
170 begin
171 if FileB /= Nul then
172 Put_Line (OutB, S);
173 end if;
175 if FileS /= Nul then
176 Put_Line (OutS, S);
177 end if;
178 end WriteBS;
180 procedure WriteBS (S : VString) is
181 begin
182 if FileB /= Nul then
183 Put_Line (OutB, S);
184 end if;
186 if FileS /= Nul then
187 Put_Line (OutS, S);
188 end if;
189 end WriteBS;
191 procedure WriteS (S : String) is
192 begin
193 if FileS /= Nul then
194 Put_Line (OutS, S);
195 end if;
196 end WriteS;
198 procedure WriteS (S : VString) is
199 begin
200 if FileS /= Nul then
201 Put_Line (OutS, S);
202 end if;
203 end WriteS;
205 procedure Put_Line (F : Sfile; S : String) is
206 begin
207 String'Write (Stream (F), S);
208 Character'Write (Stream (F), ASCII.LF);
209 end Put_Line;
211 procedure Put_Line (F : Sfile; S : VString) is
212 begin
213 Put_Line (F, To_String (S));
214 end Put_Line;
216 -- Start of processing for XNmake
218 begin
219 NWidth := 28;
220 Anchored_Mode := True;
222 for ArgN in 1 .. Argument_Count loop
223 declare
224 Arg : constant String := Argument (ArgN);
226 begin
227 if Arg (1) = '-' then
228 if Arg'Length = 2
229 and then (Arg (2) = 'b' or else Arg (2) = 'B')
230 then
231 FileS := Nul;
233 elsif Arg'Length = 2
234 and then (Arg (2) = 's' or else Arg (2) = 'S')
235 then
236 FileB := Nul;
238 else
239 raise Err;
240 end if;
242 else
243 if Given_File /= Nul then
244 raise Err;
245 else
246 Given_File := V (Arg);
247 end if;
248 end if;
249 end;
250 end loop;
252 if FileS = Nul and then FileB = Nul then
253 raise Err;
255 elsif Given_File /= Nul then
256 if FileB = Nul then
257 FileS := Given_File;
259 elsif FileS = Nul then
260 FileB := Given_File;
262 else
263 raise Err;
264 end if;
265 end if;
267 Open (InS, In_File, "sinfo.ads");
268 Open (InT, In_File, "nmake.adt");
270 if FileS /= Nul then
271 Create (OutS, Out_File, S (FileS));
272 end if;
274 if FileB /= Nul then
275 Create (OutB, Out_File, S (FileB));
276 end if;
278 Anchored_Mode := True;
280 -- Copy initial part of template to spec and body
282 loop
283 Line := Get_Line (InT);
285 -- Skip lines describing the template
287 if Match (Line, "-- This file is a template") then
288 loop
289 Line := Get_Line (InT);
290 exit when Line = "";
291 end loop;
292 end if;
294 -- Loop keeps going until "package" keyword written
296 exit when Match (Line, "package");
298 -- Deal with WITH lines, writing to body or spec as appropriate
300 if Match (Line, Body_Only, M) then
301 Replace (M, X);
302 WriteB (Line);
304 elsif Match (Line, Spec_Only, M) then
305 Replace (M, X);
306 WriteS (Line);
308 -- Change header from Template to Spec and write to spec file
310 else
311 if Match (Line, Templ, M) then
312 Replace (M, A & " S p e c ");
313 end if;
315 WriteS (Line);
317 -- Write header line to body file
319 if Match (Line, Spec, M) then
320 Replace (M, A & "B o d y");
321 end if;
323 WriteB (Line);
324 end if;
325 end loop;
327 -- Package line reached
329 WriteS ("package Nmake is");
330 WriteB ("package body Nmake is");
331 WriteB ("");
333 -- Copy rest of lines up to template insert point to spec only
335 loop
336 Line := Get_Line (InT);
337 exit when Match (Line, "!!TEMPLATE INSERTION POINT");
338 WriteS (Line);
339 end loop;
341 -- Here we are doing the actual insertions, loop through node types
343 loop
344 Line := Get_Line (InS);
346 if Match (Line, Node_Hdr)
347 and then not Match (Node, Punc)
348 and then Node /= "Unused"
349 then
350 exit when Node = "Empty";
351 Prevl := " function Make_" & Node & " (Sloc : Source_Ptr";
352 Arg_List := Nul;
354 -- Loop through fields of one node
356 loop
357 Line := Get_Line (InS);
358 exit when Line = "";
360 if Match (Line, Binop) then
361 WriteBS (Prevl & ';');
362 Append (Arg_List, "Left_Opnd,Right_Opnd,");
363 WriteBS (
364 " " & Rpad ("Left_Opnd", NWidth) & " : Node_Id;");
365 Prevl :=
366 " " & Rpad ("Right_Opnd", NWidth) & " : Node_Id";
368 elsif Match (Line, Unop) then
369 WriteBS (Prevl & ';');
370 Append (Arg_List, "Right_Opnd,");
371 Prevl := " " & Rpad ("Right_Opnd", NWidth) & " : Node_Id";
373 elsif Match (Line, Syn) then
374 if Synonym /= "Prev_Ids"
375 and then Synonym /= "More_Ids"
376 and then Synonym /= "Comes_From_Source"
377 and then Synonym /= "Paren_Count"
378 and then not Match (Field, Sem_Field)
379 and then not Match (Field, Lib_Field)
380 then
381 Match (Field, Get_Field);
383 if Field = "Str" then
384 Field := V_String_Id;
385 elsif Field = "Node" then
386 Field := V_Node_Id;
387 elsif Field = "Name" then
388 Field := V_Name_Id;
389 elsif Field = "List" then
390 Field := V_List_Id;
391 elsif Field = "Elist" then
392 Field := V_Elist_Id;
393 elsif Field = "Flag" then
394 Field := V_Boolean;
395 end if;
397 if Field = "Boolean" then
398 Default := V ("False");
399 else
400 Default := Nul;
401 end if;
403 Match (Comment, Get_Dflt);
405 WriteBS (Prevl & ';');
406 Append (Arg_List, Synonym & ',');
407 Rpad (Synonym, NWidth);
409 if Default = "" then
410 Prevl := " " & Synonym & " : " & Field;
411 else
412 Prevl :=
413 " " & Synonym & " : " & Field & " := " & Default;
414 end if;
415 end if;
416 end if;
417 end loop;
419 WriteBS (Prevl & ')');
420 WriteS (" return Node_Id;");
421 WriteS (" pragma Inline (Make_" & Node & ");");
422 WriteB (" return Node_Id");
423 WriteB (" is");
424 WriteB (" N : constant Node_Id :=");
426 if Match (Node, "Defining_Identifier") or else
427 Match (Node, "Defining_Character") or else
428 Match (Node, "Defining_Operator")
429 then
430 WriteB (" New_Entity (N_" & Node & ", Sloc);");
431 else
432 WriteB (" New_Node (N_" & Node & ", Sloc);");
433 end if;
435 WriteB (" begin");
437 while Match (Arg_List, Next_Arg, "") loop
438 if Length (Arg) < NWidth then
439 WriteB (" Set_" & Arg & " (N, " & Arg & ");");
440 else
441 WriteB (" Set_" & Arg);
442 WriteB (" (N, " & Arg & ");");
443 end if;
444 end loop;
446 if Match (Node, Op_Node) then
447 if Node = "Op_Plus" then
448 WriteB (" Set_Chars (N, Name_Op_Add);");
450 elsif Node = "Op_Minus" then
451 WriteB (" Set_Chars (N, Name_Op_Subtract);");
453 elsif Match (Op_Name, Shft_Rot) then
454 WriteB (" Set_Chars (N, Name_" & Op_Name & ");");
456 else
457 WriteB (" Set_Chars (N, Name_" & Node & ");");
458 end if;
460 if not Match (Op_Name, No_Ent) then
461 WriteB (" Set_Entity (N, Standard_" & Node & ");");
462 end if;
463 end if;
465 WriteB (" return N;");
466 WriteB (" end Make_" & Node & ';');
467 WriteBS ("");
468 end if;
469 end loop;
471 WriteBS ("end Nmake;");
473 exception
475 when Err =>
476 Put_Line (Standard_Error, "usage: xnmake [-b] [-s] [filename]");
477 Set_Exit_Status (1);
479 end XNmake;