]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/ada/xnmake.adb
2003-10-21 Arnaud Charlet <charlet@act-europe.fr>
[thirdparty/gcc.git] / gcc / ada / xnmake.adb
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-2002 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 2, 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 COPYING. If not, write --
19 -- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, --
20 -- MA 02111-1307, USA. --
21 -- --
22 -- GNAT was originally developed by the GNAT team at New York University. --
23 -- Extensive contributions were provided by Ada Core Technologies Inc. --
24 -- --
25 ------------------------------------------------------------------------------
26
27 -- Program to construct the spec and body of the Nmake package
28
29 -- Input files:
30
31 -- sinfo.ads Spec of Sinfo package
32 -- nmake.adt Template for Nmake package
33
34 -- Output files:
35
36 -- nmake.ads Spec of Nmake package
37 -- nmake.adb Body of Nmake package
38
39 -- Note: this program assumes that sinfo.ads has passed the error checks that
40 -- are carried out by the csinfo utility, so it does not duplicate these
41 -- checks and assumes that sinfo.ads has the correct form.
42
43 -- In the absence of any switches, both the ads and adb files are output.
44 -- The switch -s or /s indicates that only the ads file is to be output.
45 -- The switch -b or /b indicates that only the adb file is to be output.
46
47 -- If a file name argument is given, then the output is written to this file
48 -- rather than to nmake.ads or nmake.adb. A file name can only be given if
49 -- exactly one of the -s or -b options is present.
50
51 with Ada.Command_Line; use Ada.Command_Line;
52 with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
53 with Ada.Strings.Unbounded.Text_IO; use Ada.Strings.Unbounded.Text_IO;
54 with Ada.Strings.Maps; use Ada.Strings.Maps;
55 with Ada.Strings.Maps.Constants; use Ada.Strings.Maps.Constants;
56 with Ada.Text_IO; use Ada.Text_IO;
57
58 with GNAT.Spitbol; use GNAT.Spitbol;
59 with GNAT.Spitbol.Patterns; use GNAT.Spitbol.Patterns;
60
61 procedure XNmake is
62
63 Err : exception;
64 -- Raised to terminate execution
65
66 A : VString := Nul;
67 Arg : VString := Nul;
68 Arg_List : VString := Nul;
69 Comment : VString := Nul;
70 Default : VString := Nul;
71 Field : VString := Nul;
72 Line : VString := Nul;
73 Node : VString := Nul;
74 Op_Name : VString := Nul;
75 Prevl : VString := Nul;
76 Synonym : VString := Nul;
77 X : VString := Nul;
78
79 Lineno : Natural;
80 NWidth : Natural;
81
82 FileS : VString := V ("nmake.ads");
83 FileB : VString := V ("nmake.adb");
84 -- Set to null if corresponding file not to be generated
85
86 Given_File : VString := Nul;
87 -- File name given by command line argument
88
89 InS, InT : File_Type;
90 OutS, OutB : File_Type;
91
92 wsp : Pattern := Span (' ' & ASCII.HT);
93
94 Body_Only : Pattern := BreakX (' ') * X & Span (' ') & "-- body only";
95 Spec_Only : Pattern := BreakX (' ') * X & Span (' ') & "-- spec only";
96
97 Node_Hdr : Pattern := wsp & "-- N_" & Rest * Node;
98 Punc : Pattern := BreakX (" .,");
99
100 Binop : Pattern := wsp & "-- plus fields for binary operator";
101 Unop : Pattern := wsp & "-- plus fields for unary operator";
102 Syn : Pattern := wsp & "-- " & Break (' ') * Synonym
103 & " (" & Break (')') * Field & Rest * Comment;
104
105 Templ : Pattern := BreakX ('T') * A & "T e m p l a t e";
106 Spec : Pattern := BreakX ('S') * A & "S p e c";
107
108 Sem_Field : Pattern := BreakX ('-') & "-Sem";
109 Lib_Field : Pattern := BreakX ('-') & "-Lib";
110
111 Get_Field : Pattern := BreakX (Decimal_Digit_Set) * Field;
112
113 Get_Dflt : Pattern := BreakX ('(') & "(set to "
114 & Break (" ") * Default & " if";
115
116 Next_Arg : Pattern := Break (',') * Arg & ',';
117
118 Op_Node : Pattern := "Op_" & Rest * Op_Name;
119
120 Shft_Rot : Pattern := "Shift_" or "Rotate_";
121
122 No_Ent : Pattern := "Or_Else" or "And_Then" or "In" or "Not_In";
123
124 M : Match_Result;
125
126 V_String_Id : constant VString := V ("String_Id");
127 V_Node_Id : constant VString := V ("Node_Id");
128 V_Name_Id : constant VString := V ("Name_Id");
129 V_List_Id : constant VString := V ("List_Id");
130 V_Elist_Id : constant VString := V ("Elist_Id");
131 V_Boolean : constant VString := V ("Boolean");
132
133 procedure WriteS (S : String);
134 procedure WriteB (S : String);
135 procedure WriteBS (S : String);
136 procedure WriteS (S : VString);
137 procedure WriteB (S : VString);
138 procedure WriteBS (S : VString);
139 -- Write given line to spec or body file or both if active
140
141 procedure WriteB (S : String) is
142 begin
143 if FileB /= Nul then
144 Put_Line (OutB, S);
145 end if;
146 end WriteB;
147
148 procedure WriteB (S : VString) is
149 begin
150 if FileB /= Nul then
151 Put_Line (OutB, S);
152 end if;
153 end WriteB;
154
155 procedure WriteBS (S : String) is
156 begin
157 if FileB /= Nul then
158 Put_Line (OutB, S);
159 end if;
160
161 if FileS /= Nul then
162 Put_Line (OutS, S);
163 end if;
164 end WriteBS;
165
166 procedure WriteBS (S : VString) is
167 begin
168 if FileB /= Nul then
169 Put_Line (OutB, S);
170 end if;
171
172 if FileS /= Nul then
173 Put_Line (OutS, S);
174 end if;
175 end WriteBS;
176
177 procedure WriteS (S : String) is
178 begin
179 if FileS /= Nul then
180 Put_Line (OutS, S);
181 end if;
182 end WriteS;
183
184 procedure WriteS (S : VString) is
185 begin
186 if FileS /= Nul then
187 Put_Line (OutS, S);
188 end if;
189 end WriteS;
190
191 -- Start of processing for XNmake
192
193 begin
194 Lineno := 0;
195 NWidth := 28;
196 Anchored_Mode := True;
197
198 for ArgN in 1 .. Argument_Count loop
199 declare
200 Arg : constant String := Argument (ArgN);
201
202 begin
203 if Arg (1) = '-' then
204 if Arg'Length = 2
205 and then (Arg (2) = 'b' or else Arg (2) = 'B')
206 then
207 FileS := Nul;
208
209 elsif Arg'Length = 2
210 and then (Arg (2) = 's' or else Arg (2) = 'S')
211 then
212 FileB := Nul;
213
214 else
215 raise Err;
216 end if;
217
218 else
219 if Given_File /= Nul then
220 raise Err;
221 else
222 Given_File := V (Arg);
223 end if;
224 end if;
225 end;
226 end loop;
227
228 if FileS = Nul and then FileB = Nul then
229 raise Err;
230
231 elsif Given_File /= Nul then
232 if FileB = Nul then
233 FileS := Given_File;
234
235 elsif FileS = Nul then
236 FileB := Given_File;
237
238 else
239 raise Err;
240 end if;
241 end if;
242
243 Open (InS, In_File, "sinfo.ads");
244 Open (InT, In_File, "nmake.adt");
245
246 if FileS /= Nul then
247 Create (OutS, Out_File, S (FileS));
248 end if;
249
250 if FileB /= Nul then
251 Create (OutB, Out_File, S (FileB));
252 end if;
253
254 Anchored_Mode := True;
255
256 -- Copy initial part of template to spec and body
257
258 loop
259 Line := Get_Line (InT);
260
261 -- Skip lines describing the template
262
263 if Match (Line, "-- This file is a template") then
264 loop
265 Line := Get_Line (InT);
266 exit when Line = "";
267 end loop;
268 end if;
269
270 exit when Match (Line, "package");
271
272 if Match (Line, Body_Only, M) then
273 Replace (M, X);
274 WriteB (Line);
275
276 elsif Match (Line, Spec_Only, M) then
277 Replace (M, X);
278 WriteS (Line);
279
280 else
281 if Match (Line, Templ, M) then
282 Replace (M, A & " S p e c ");
283 end if;
284
285 WriteS (Line);
286
287 if Match (Line, Spec, M) then
288 Replace (M, A & "B o d y");
289 end if;
290
291 WriteB (Line);
292 end if;
293 end loop;
294
295 -- Package line reached
296
297 WriteS ("package Nmake is");
298 WriteB ("package body Nmake is");
299 WriteB ("");
300
301 -- Copy rest of lines up to template insert point to spec only
302
303 loop
304 Line := Get_Line (InT);
305 exit when Match (Line, "!!TEMPLATE INSERTION POINT");
306 WriteS (Line);
307 end loop;
308
309 -- Here we are doing the actual insertions, loop through node types
310
311 loop
312 Line := Get_Line (InS);
313
314 if Match (Line, Node_Hdr)
315 and then not Match (Node, Punc)
316 and then Node /= "Unused"
317 then
318 exit when Node = "Empty";
319 Prevl := " function Make_" & Node & " (Sloc : Source_Ptr";
320 Arg_List := Nul;
321
322 -- Loop through fields of one node
323
324 loop
325 Line := Get_Line (InS);
326 exit when Line = "";
327
328 if Match (Line, Binop) then
329 WriteBS (Prevl & ';');
330 Append (Arg_List, "Left_Opnd,Right_Opnd,");
331 WriteBS (
332 " " & Rpad ("Left_Opnd", NWidth) & " : Node_Id;");
333 Prevl :=
334 " " & Rpad ("Right_Opnd", NWidth) & " : Node_Id";
335
336 elsif Match (Line, Unop) then
337 WriteBS (Prevl & ';');
338 Append (Arg_List, "Right_Opnd,");
339 Prevl := " " & Rpad ("Right_Opnd", NWidth) & " : Node_Id";
340
341 elsif Match (Line, Syn) then
342 if Synonym /= "Prev_Ids"
343 and then Synonym /= "More_Ids"
344 and then Synonym /= "Comes_From_Source"
345 and then Synonym /= "Paren_Count"
346 and then not Match (Field, Sem_Field)
347 and then not Match (Field, Lib_Field)
348 then
349 Match (Field, Get_Field);
350
351 if Field = "Str" then Field := V_String_Id;
352 elsif Field = "Node" then Field := V_Node_Id;
353 elsif Field = "Name" then Field := V_Name_Id;
354 elsif Field = "List" then Field := V_List_Id;
355 elsif Field = "Elist" then Field := V_Elist_Id;
356 elsif Field = "Flag" then Field := V_Boolean;
357 end if;
358
359 if Field = "Boolean" then
360 Default := V ("False");
361 else
362 Default := Nul;
363 end if;
364
365 Match (Comment, Get_Dflt);
366
367 WriteBS (Prevl & ';');
368 Append (Arg_List, Synonym & ',');
369 Rpad (Synonym, NWidth);
370
371 if Default = "" then
372 Prevl := " " & Synonym & " : " & Field;
373 else
374 Prevl :=
375 " " & Synonym & " : " & Field & " := " & Default;
376 end if;
377 end if;
378 end if;
379 end loop;
380
381 WriteBS (Prevl & ')');
382 WriteS (" return Node_Id;");
383 WriteS (" pragma Inline (Make_" & Node & ");");
384 WriteB (" return Node_Id");
385 WriteB (" is");
386 WriteB (" N : constant Node_Id :=");
387
388 if Match (Node, "Defining_Identifier") or else
389 Match (Node, "Defining_Character") or else
390 Match (Node, "Defining_Operator")
391 then
392 WriteB (" New_Entity (N_" & Node & ", Sloc);");
393 else
394 WriteB (" New_Node (N_" & Node & ", Sloc);");
395 end if;
396
397 WriteB (" begin");
398
399 while Match (Arg_List, Next_Arg, "") loop
400 if Length (Arg) < NWidth then
401 WriteB (" Set_" & Arg & " (N, " & Arg & ");");
402 else
403 WriteB (" Set_" & Arg);
404 WriteB (" (N, " & Arg & ");");
405 end if;
406 end loop;
407
408 if Match (Node, Op_Node) then
409 if Node = "Op_Plus" then
410 WriteB (" Set_Chars (N, Name_Op_Add);");
411
412 elsif Node = "Op_Minus" then
413 WriteB (" Set_Chars (N, Name_Op_Subtract);");
414
415 elsif Match (Op_Name, Shft_Rot) then
416 WriteB (" Set_Chars (N, Name_" & Op_Name & ");");
417
418 else
419 WriteB (" Set_Chars (N, Name_" & Node & ");");
420 end if;
421
422 if not Match (Op_Name, No_Ent) then
423 WriteB (" Set_Entity (N, Standard_" & Node & ");");
424 end if;
425 end if;
426
427 WriteB (" return N;");
428 WriteB (" end Make_" & Node & ';');
429 WriteBS ("");
430 end if;
431 end loop;
432
433 WriteBS ("end Nmake;");
434
435 exception
436
437 when Err =>
438 Put_Line (Standard_Error, "usage: xnmake [-b] [-s] [filename]");
439 Set_Exit_Status (1);
440
441 end XNmake;