FSF GCC merge 02/23/03
[official-gcc.git] / gcc / ada / prj-util.adb
blob02aa6b4487d9519abb4321b54725b07934f52cd9
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT COMPILER COMPONENTS --
4 -- --
5 -- P R J . U T I L --
6 -- --
7 -- B o d y --
8 -- --
9 -- --
10 -- Copyright (C) 2001 Free Software Foundation, Inc. --
11 -- --
12 -- GNAT is free software; you can redistribute it and/or modify it under --
13 -- terms of the GNU General Public License as published by the Free Soft- --
14 -- ware Foundation; either version 2, or (at your option) any later ver- --
15 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
16 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
17 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
18 -- for more details. You should have received a copy of the GNU General --
19 -- Public License distributed with GNAT; see file COPYING. If not, write --
20 -- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, --
21 -- MA 02111-1307, USA. --
22 -- --
23 -- GNAT was originally developed by the GNAT team at New York University. --
24 -- Extensive contributions were provided by Ada Core Technologies Inc. --
25 -- --
26 ------------------------------------------------------------------------------
28 with Ada.Unchecked_Deallocation;
30 with Namet; use Namet;
31 with Osint;
32 with Output; use Output;
33 with Stringt; use Stringt;
35 package body Prj.Util is
37 procedure Free is new Ada.Unchecked_Deallocation
38 (Text_File_Data, Text_File);
40 -----------
41 -- Close --
42 -----------
44 procedure Close (File : in out Text_File) is
45 begin
46 if File = null then
47 Osint.Fail ("Close attempted on an invalid Text_File");
48 end if;
50 Close (File.FD);
51 Free (File);
52 end Close;
54 -----------------
55 -- End_Of_File --
56 -----------------
58 function End_Of_File (File : Text_File) return Boolean is
59 begin
60 if File = null then
61 Osint.Fail ("End_Of_File attempted on an invalid Text_File");
62 end if;
64 return File.End_Of_File_Reached;
65 end End_Of_File;
67 --------------
68 -- Get_Line --
69 --------------
71 procedure Get_Line
72 (File : Text_File;
73 Line : out String;
74 Last : out Natural)
76 C : Character;
78 procedure Advance;
80 -------------
81 -- Advance --
82 -------------
84 procedure Advance is
85 begin
86 if File.Cursor = File.Buffer_Len then
87 File.Buffer_Len :=
88 Read
89 (FD => File.FD,
90 A => File.Buffer'Address,
91 N => File.Buffer'Length);
93 if File.Buffer_Len = 0 then
94 File.End_Of_File_Reached := True;
95 return;
96 else
97 File.Cursor := 1;
98 end if;
100 else
101 File.Cursor := File.Cursor + 1;
102 end if;
103 end Advance;
105 -- Start of processing for Get_Line
107 begin
108 if File = null then
109 Osint.Fail ("Get_Line attempted on an invalid Text_File");
110 end if;
112 Last := Line'First - 1;
114 if not File.End_Of_File_Reached then
115 loop
116 C := File.Buffer (File.Cursor);
117 exit when C = ASCII.CR or else C = ASCII.LF;
118 Last := Last + 1;
119 Line (Last) := C;
120 Advance;
122 if File.End_Of_File_Reached then
123 return;
124 end if;
126 exit when Last = Line'Last;
127 end loop;
129 if C = ASCII.CR or else C = ASCII.LF then
130 Advance;
132 if File.End_Of_File_Reached then
133 return;
134 end if;
135 end if;
137 if C = ASCII.CR
138 and then File.Buffer (File.Cursor) = ASCII.LF
139 then
140 Advance;
141 end if;
142 end if;
143 end Get_Line;
145 --------------
146 -- Is_Valid --
147 --------------
149 function Is_Valid (File : Text_File) return Boolean is
150 begin
151 return File /= null;
152 end Is_Valid;
154 ----------
155 -- Open --
156 ----------
158 procedure Open (File : out Text_File; Name : in String) is
159 FD : File_Descriptor;
160 File_Name : String (1 .. Name'Length + 1);
162 begin
163 File_Name (1 .. Name'Length) := Name;
164 File_Name (File_Name'Last) := ASCII.NUL;
165 FD := Open_Read (Name => File_Name'Address,
166 Fmode => GNAT.OS_Lib.Text);
167 if FD = Invalid_FD then
168 File := null;
169 else
170 File := new Text_File_Data;
171 File.FD := FD;
172 File.Buffer_Len :=
173 Read (FD => FD,
174 A => File.Buffer'Address,
175 N => File.Buffer'Length);
177 if File.Buffer_Len = 0 then
178 File.End_Of_File_Reached := True;
179 else
180 File.Cursor := 1;
181 end if;
182 end if;
183 end Open;
185 --------------
186 -- Value_Of --
187 --------------
189 function Value_Of
190 (Variable : Variable_Value;
191 Default : String)
192 return String
194 begin
195 if Variable.Kind /= Single
196 or else Variable.Default
197 or else Variable.Value = No_String then
198 return Default;
200 else
201 String_To_Name_Buffer (Variable.Value);
202 return Name_Buffer (1 .. Name_Len);
203 end if;
204 end Value_Of;
206 function Value_Of
207 (Index : Name_Id;
208 In_Array : Array_Element_Id)
209 return Name_Id
211 Current : Array_Element_Id := In_Array;
212 Element : Array_Element;
214 begin
215 while Current /= No_Array_Element loop
216 Element := Array_Elements.Table (Current);
218 if Index = Element.Index then
219 exit when Element.Value.Kind /= Single;
220 exit when String_Length (Element.Value.Value) = 0;
221 String_To_Name_Buffer (Element.Value.Value);
222 return Name_Find;
223 else
224 Current := Element.Next;
225 end if;
226 end loop;
228 return No_Name;
229 end Value_Of;
231 function Value_Of
232 (Index : Name_Id;
233 In_Array : Array_Element_Id)
234 return Variable_Value
236 Current : Array_Element_Id := In_Array;
237 Element : Array_Element;
239 begin
240 while Current /= No_Array_Element loop
241 Element := Array_Elements.Table (Current);
243 if Index = Element.Index then
244 return Element.Value;
245 else
246 Current := Element.Next;
247 end if;
248 end loop;
250 return Nil_Variable_Value;
251 end Value_Of;
253 function Value_Of
254 (Name : Name_Id;
255 Attribute_Or_Array_Name : Name_Id;
256 In_Package : Package_Id)
257 return Variable_Value
259 The_Array : Array_Element_Id;
260 The_Attribute : Variable_Value := Nil_Variable_Value;
262 begin
263 if In_Package /= No_Package then
265 -- First, look if there is an array element that fits
267 The_Array :=
268 Value_Of
269 (Name => Attribute_Or_Array_Name,
270 In_Arrays => Packages.Table (In_Package).Decl.Arrays);
271 The_Attribute :=
272 Value_Of
273 (Index => Name,
274 In_Array => The_Array);
276 -- If there is no array element, look for a variable
278 if The_Attribute = Nil_Variable_Value then
279 The_Attribute :=
280 Value_Of
281 (Variable_Name => Attribute_Or_Array_Name,
282 In_Variables => Packages.Table (In_Package).Decl.Attributes);
283 end if;
284 end if;
286 return The_Attribute;
287 end Value_Of;
289 function Value_Of
290 (Index : Name_Id;
291 In_Array : Name_Id;
292 In_Arrays : Array_Id)
293 return Name_Id
295 Current : Array_Id := In_Arrays;
296 The_Array : Array_Data;
298 begin
299 while Current /= No_Array loop
300 The_Array := Arrays.Table (Current);
301 if The_Array.Name = In_Array then
302 return Value_Of (Index, In_Array => The_Array.Value);
303 else
304 Current := The_Array.Next;
305 end if;
306 end loop;
308 return No_Name;
309 end Value_Of;
311 function Value_Of
312 (Name : Name_Id;
313 In_Arrays : Array_Id)
314 return Array_Element_Id
316 Current : Array_Id := In_Arrays;
317 The_Array : Array_Data;
319 begin
320 while Current /= No_Array loop
321 The_Array := Arrays.Table (Current);
323 if The_Array.Name = Name then
324 return The_Array.Value;
325 else
326 Current := The_Array.Next;
327 end if;
328 end loop;
330 return No_Array_Element;
331 end Value_Of;
333 function Value_Of
334 (Name : Name_Id;
335 In_Packages : Package_Id)
336 return Package_Id
338 Current : Package_Id := In_Packages;
339 The_Package : Package_Element;
341 begin
342 while Current /= No_Package loop
343 The_Package := Packages.Table (Current);
344 exit when The_Package.Name /= No_Name
345 and then The_Package.Name = Name;
346 Current := The_Package.Next;
347 end loop;
349 return Current;
350 end Value_Of;
352 function Value_Of
353 (Variable_Name : Name_Id;
354 In_Variables : Variable_Id)
355 return Variable_Value
357 Current : Variable_Id := In_Variables;
358 The_Variable : Variable;
360 begin
361 while Current /= No_Variable loop
362 The_Variable := Variable_Elements.Table (Current);
364 if Variable_Name = The_Variable.Name then
365 return The_Variable.Value;
366 else
367 Current := The_Variable.Next;
368 end if;
369 end loop;
371 return Nil_Variable_Value;
372 end Value_Of;
374 ---------------
375 -- Write_Str --
376 ---------------
378 procedure Write_Str
379 (S : String;
380 Max_Length : Positive;
381 Separator : Character)
383 First : Positive := S'First;
384 Last : Natural := S'Last;
386 begin
387 -- Nothing to do for empty strings
389 if S'Length > 0 then
391 -- Start on a new line if current line is already longer than
392 -- Max_Length.
394 if Positive (Column) >= Max_Length then
395 Write_Eol;
396 end if;
398 -- If length of remainder is longer than Max_Length, we need to
399 -- cut the remainder in several lines.
401 while Positive (Column) + S'Last - First > Max_Length loop
403 -- Try the maximum length possible
405 Last := First + Max_Length - Positive (Column);
407 -- Look for last Separator in the line
409 while Last >= First and then S (Last) /= Separator loop
410 Last := Last - 1;
411 end loop;
413 -- If we do not find a separator, we output the maximum length
414 -- possible.
416 if Last < First then
417 Last := First + Max_Length - Positive (Column);
418 end if;
420 Write_Line (S (First .. Last));
422 -- Set the beginning of the new remainder
424 First := Last + 1;
425 end loop;
427 -- What is left goes to the buffer, without EOL
429 Write_Str (S (First .. S'Last));
430 end if;
431 end Write_Str;
433 end Prj.Util;