1 ------------------------------------------------------------------------------
3 -- GNAT SYSTEM UTILITIES --
11 -- Copyright (C) 1992-2001 Free Software Foundation, Inc. --
13 -- GNAT is free software; you can redistribute it and/or modify it under --
14 -- terms of the GNU General Public License as published by the Free Soft- --
15 -- ware Foundation; either version 2, or (at your option) any later ver- --
16 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
17 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
18 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
19 -- for more details. You should have received a copy of the GNU General --
20 -- Public License distributed with GNAT; see file COPYING. If not, write --
21 -- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, --
22 -- MA 02111-1307, USA. --
24 -- GNAT was originally developed by the GNAT team at New York University. --
25 -- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
27 ------------------------------------------------------------------------------
29 -- Program to construct the spec and body of the Nmake package
33 -- sinfo.ads Spec of Sinfo package
34 -- nmake.adt Template for Nmake package
38 -- nmake.ads Spec of Nmake package
39 -- nmake.adb Body of Nmake package
41 -- Note: this program assumes that sinfo.ads has passed the error checks that
42 -- are carried out by the csinfo utility, so it does not duplicate these
43 -- checks and assumes that sinfo.ads has the correct form.
45 -- In the absence of any switches, both the ads and adb files are output.
46 -- The switch -s or /s indicates that only the ads file is to be output.
47 -- The switch -b or /b indicates that only the adb file is to be output.
49 -- If a file name argument is given, then the output is written to this file
50 -- rather than to nmake.ads or nmake.adb. A file name can only be given if
51 -- exactly one of the -s or -b options is present.
53 with Ada.Command_Line; use Ada.Command_Line;
54 with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
55 with Ada.Strings.Unbounded.Text_IO; use Ada.Strings.Unbounded.Text_IO;
56 with Ada.Strings.Maps; use Ada.Strings.Maps;
57 with Ada.Strings.Maps.Constants; use Ada.Strings.Maps.Constants;
58 with Ada.Text_IO; use Ada.Text_IO;
60 with GNAT.Spitbol; use GNAT.Spitbol;
61 with GNAT.Spitbol.Patterns; use GNAT.Spitbol.Patterns;
66 -- Raised to terminate execution
70 Arg_List : VString := Nul;
71 Comment : VString := Nul;
72 Default : VString := Nul;
73 Field : VString := Nul;
74 Line : VString := Nul;
75 Node : VString := Nul;
76 Op_Name : VString := Nul;
77 Prevl : VString := Nul;
78 Sinfo_Rev : VString := Nul;
79 Synonym : VString := Nul;
80 Temp_Rev : VString := Nul;
82 XNmake_Rev : VString := Nul;
87 FileS : VString := V ("nmake.ads");
88 FileB : VString := V ("nmake.adb");
89 -- Set to null if corresponding file not to be generated
91 Given_File : VString := Nul;
92 -- File name given by command line argument
95 OutS, OutB : File_Type;
97 wsp : Pattern := Span (' ' & ASCII.HT);
99 -- Note: in following patterns, we break up the word revision to
100 -- avoid RCS getting enthusiastic about updating the reference!
102 Get_SRev : Pattern := BreakX ('$') & "$Rev" & "ision: " &
103 Break (' ') * Sinfo_Rev;
105 GetT_Rev : Pattern := BreakX ('$') & "$Rev" & "ision: " &
106 Break (' ') * Temp_Rev;
108 Body_Only : Pattern := BreakX (' ') * X & Span (' ') & "-- body only";
109 Spec_Only : Pattern := BreakX (' ') * X & Span (' ') & "-- spec only";
111 Node_Hdr : Pattern := wsp & "-- N_" & Rest * Node;
112 Punc : Pattern := BreakX (" .,");
114 Binop : Pattern := wsp & "-- plus fields for binary operator";
115 Unop : Pattern := wsp & "-- plus fields for unary operator";
116 Syn : Pattern := wsp & "-- " & Break (' ') * Synonym
117 & " (" & Break (')') * Field & Rest * Comment;
119 Templ : Pattern := BreakX ('T') * A & "T e m p l a t e";
120 Spec : Pattern := BreakX ('S') * A & "S p e c";
122 Sem_Field : Pattern := BreakX ('-') & "-Sem";
123 Lib_Field : Pattern := BreakX ('-') & "-Lib";
125 Get_Field : Pattern := BreakX (Decimal_Digit_Set) * Field;
127 Get_Dflt : Pattern := BreakX ('(') & "(set to "
128 & Break (" ") * Default & " if";
130 Next_Arg : Pattern := Break (',') * Arg & ',';
132 Op_Node : Pattern := "Op_" & Rest * Op_Name;
134 Shft_Rot : Pattern := "Shift_" or "Rotate_";
136 No_Ent : Pattern := "Or_Else" or "And_Then" or "In" or "Not_In";
140 V_String_Id : constant VString := V ("String_Id");
141 V_Node_Id : constant VString := V ("Node_Id");
142 V_Name_Id : constant VString := V ("Name_Id");
143 V_List_Id : constant VString := V ("List_Id");
144 V_Elist_Id : constant VString := V ("Elist_Id");
145 V_Boolean : constant VString := V ("Boolean");
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
162 procedure WriteB (S : VString) is
169 procedure WriteBS (S : String) is
180 procedure WriteBS (S : VString) is
191 procedure WriteS (S : String) is
198 procedure WriteS (S : VString) is
205 -- Start of processing for XNmake
208 -- Capture our revision (following line updated by RCS)
210 Match ("$Revision$", "$Rev" & "ision: " & Break (' ') * XNmake_Rev);
214 Anchored_Mode := True;
216 for ArgN in 1 .. Argument_Count loop
218 Arg : constant String := Argument (ArgN);
221 if Arg (1) = '-' then
223 and then (Arg (2) = 'b' or else Arg (2) = 'B')
228 and then (Arg (2) = 's' or else Arg (2) = 'S')
237 if Given_File /= Nul then
240 Given_File := V (Arg);
246 if FileS = Nul and then FileB = Nul then
249 elsif Given_File /= Nul then
253 elsif FileS = Nul then
261 Open (InS, In_File, "sinfo.ads");
262 Open (InT, In_File, "nmake.adt");
265 Create (OutS, Out_File, S (FileS));
269 Create (OutB, Out_File, S (FileB));
272 Anchored_Mode := True;
274 -- Get Sinfo revision number
277 Line := Get_Line (InS);
278 exit when Match (Line, Get_SRev);
281 -- Copy initial part of template to spec and body
284 Line := Get_Line (InT);
286 if Match (Line, GetT_Rev) then
288 ("-- Generated by xnmake revision " &
289 XNmake_Rev & " using" &
293 ("-- sinfo.ads revision " &
298 ("-- nmake.adt revision " &
303 -- Skip lines describing the template
305 if Match (Line, "-- This file is a template") then
307 Line := Get_Line (InT);
312 exit when Match (Line, "package");
314 if Match (Line, Body_Only, M) then
318 elsif Match (Line, Spec_Only, M) then
323 if Match (Line, Templ, M) then
324 Replace (M, A & " S p e c ");
329 if Match (Line, Spec, M) then
330 Replace (M, A & "B o d y");
338 -- Package line reached
340 WriteS ("package Nmake is");
341 WriteB ("package body Nmake is");
344 -- Copy rest of lines up to template insert point to spec only
347 Line := Get_Line (InT);
348 exit when Match (Line, "!!TEMPLATE INSERTION POINT");
352 -- Here we are doing the actual insertions, loop through node types
355 Line := Get_Line (InS);
357 if Match (Line, Node_Hdr)
358 and then not Match (Node, Punc)
359 and then Node /= "Unused"
361 exit when Node = "Empty";
362 Prevl := " function Make_" & Node & " (Sloc : Source_Ptr";
365 -- Loop through fields of one node
368 Line := Get_Line (InS);
371 if Match (Line, Binop) then
372 WriteBS (Prevl & ';');
373 Append (Arg_List, "Left_Opnd,Right_Opnd,");
375 " " & Rpad ("Left_Opnd", NWidth) & " : Node_Id;");
377 " " & Rpad ("Right_Opnd", NWidth) & " : Node_Id";
379 elsif Match (Line, Unop) then
380 WriteBS (Prevl & ';');
381 Append (Arg_List, "Right_Opnd,");
382 Prevl := " " & Rpad ("Right_Opnd", NWidth) & " : Node_Id";
384 elsif Match (Line, Syn) then
385 if Synonym /= "Prev_Ids"
386 and then Synonym /= "More_Ids"
387 and then Synonym /= "Comes_From_Source"
388 and then Synonym /= "Paren_Count"
389 and then not Match (Field, Sem_Field)
390 and then not Match (Field, Lib_Field)
392 Match (Field, Get_Field);
394 if Field = "Str" then Field := V_String_Id;
395 elsif Field = "Node" then Field := V_Node_Id;
396 elsif Field = "Name" then Field := V_Name_Id;
397 elsif Field = "List" then Field := V_List_Id;
398 elsif Field = "Elist" then Field := V_Elist_Id;
399 elsif Field = "Flag" then Field := V_Boolean;
402 if Field = "Boolean" then
403 Default := V ("False");
408 Match (Comment, Get_Dflt);
410 WriteBS (Prevl & ';');
411 Append (Arg_List, Synonym & ',');
412 Rpad (Synonym, NWidth);
415 Prevl := " " & Synonym & " : " & Field;
418 " " & Synonym & " : " & Field & " := " & Default;
424 WriteBS (Prevl & ')');
425 WriteS (" return Node_Id;");
426 WriteS (" pragma Inline (Make_" & Node & ");");
427 WriteB (" return Node_Id");
429 WriteB (" N : constant Node_Id :=");
431 if Match (Node, "Defining_Identifier") or else
432 Match (Node, "Defining_Character") or else
433 Match (Node, "Defining_Operator")
435 WriteB (" New_Entity (N_" & Node & ", Sloc);");
437 WriteB (" New_Node (N_" & Node & ", Sloc);");
442 while Match (Arg_List, Next_Arg, "") loop
443 if Length (Arg) < NWidth then
444 WriteB (" Set_" & Arg & " (N, " & Arg & ");");
446 WriteB (" Set_" & Arg);
447 WriteB (" (N, " & Arg & ");");
451 if Match (Node, Op_Node) then
452 if Node = "Op_Plus" then
453 WriteB (" Set_Chars (N, Name_Op_Add);");
455 elsif Node = "Op_Minus" then
456 WriteB (" Set_Chars (N, Name_Op_Subtract);");
458 elsif Match (Op_Name, Shft_Rot) then
459 WriteB (" Set_Chars (N, Name_" & Op_Name & ");");
462 WriteB (" Set_Chars (N, Name_" & Node & ");");
465 if not Match (Op_Name, No_Ent) then
466 WriteB (" Set_Entity (N, Standard_" & Node & ");");
470 WriteB (" return N;");
471 WriteB (" end Make_" & Node & ';');
476 WriteBS ("end Nmake;");
481 Put_Line (Standard_Error, "usage: xnmake [-b] [-s] [filename]");