Daily bump.
[official-gcc.git] / gcc / ada / table.adb
blobf8084691e35a80fc21ed0491c1899b5792017fb8
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT COMPILER COMPONENTS --
4 -- --
5 -- T A B L E --
6 -- --
7 -- B o d y --
8 -- --
9 -- $Revision: 1.1 $
10 -- --
11 -- Copyright (C) 1992-2001 Free Software Foundation, Inc. --
12 -- --
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. --
23 -- --
24 -- As a special exception, if other files instantiate generics from this --
25 -- unit, or you link this unit with other files to produce an executable, --
26 -- this unit does not by itself cause the resulting executable to be --
27 -- covered by the GNU General Public License. This exception does not --
28 -- however invalidate any other reasons why the executable file might be --
29 -- covered by the GNU Public License. --
30 -- --
31 -- GNAT was originally developed by the GNAT team at New York University. --
32 -- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
33 -- --
34 ------------------------------------------------------------------------------
36 with Debug; use Debug;
37 with Opt;
38 with Output; use Output;
39 with System; use System;
40 with Tree_IO; use Tree_IO;
42 package body Table is
43 package body Table is
45 Min : constant Int := Int (Table_Low_Bound);
46 -- Subscript of the minimum entry in the currently allocated table
48 Length : Int := 0;
49 -- Number of entries in currently allocated table. The value of zero
50 -- ensures that we initially allocate the table.
52 procedure free (T : Table_Ptr);
53 pragma Import (C, free);
55 -----------------------
56 -- Local Subprograms --
57 -----------------------
59 procedure Reallocate;
60 -- Reallocate the existing table according to the current value stored
61 -- in Max. Works correctly to do an initial allocation if the table
62 -- is currently null.
64 function Tree_Get_Table_Address return Address;
65 -- Return Null_Address if the table length is zero,
66 -- Table (First)'Address if not.
68 ------------
69 -- Append --
70 ------------
72 procedure Append (New_Val : Table_Component_Type) is
73 begin
74 Increment_Last;
75 Table (Table_Index_Type (Last_Val)) := New_Val;
76 end Append;
78 --------------------
79 -- Decrement_Last --
80 --------------------
82 procedure Decrement_Last is
83 begin
84 Last_Val := Last_Val - 1;
85 end Decrement_Last;
87 ----------
88 -- Free --
89 ----------
91 procedure Free is
92 begin
93 free (Table);
94 Table := null;
95 Length := 0;
96 end Free;
98 --------------------
99 -- Increment_Last --
100 --------------------
102 procedure Increment_Last is
103 begin
104 Last_Val := Last_Val + 1;
106 if Last_Val > Max then
107 Reallocate;
108 end if;
109 end Increment_Last;
111 ----------
112 -- Init --
113 ----------
115 procedure Init is
116 Old_Length : Int := Length;
118 begin
119 Last_Val := Min - 1;
120 Max := Min + (Table_Initial * Opt.Table_Factor) - 1;
121 Length := Max - Min + 1;
123 -- If table is same size as before (happens when table is never
124 -- expanded which is a common case), then simply reuse it. Note
125 -- that this also means that an explicit Init call right after
126 -- the implicit one in the package body is harmless.
128 if Old_Length = Length then
129 return;
131 -- Otherwise we can use Reallocate to get a table of the right size.
132 -- Note that Reallocate works fine to allocate a table of the right
133 -- initial size when it is first allocated.
135 else
136 Reallocate;
137 end if;
138 end Init;
140 ----------
141 -- Last --
142 ----------
144 function Last return Table_Index_Type is
145 begin
146 return Table_Index_Type (Last_Val);
147 end Last;
149 ----------------
150 -- Reallocate --
151 ----------------
153 procedure Reallocate is
155 function realloc
156 (memblock : Table_Ptr;
157 size : size_t)
158 return Table_Ptr;
159 pragma Import (C, realloc);
161 function malloc
162 (size : size_t)
163 return Table_Ptr;
164 pragma Import (C, malloc);
166 New_Size : size_t;
168 begin
169 if Max < Last_Val then
170 pragma Assert (not Locked);
172 -- Make sure that we have at least the initial allocation. This
173 -- is needed in cases where a zero length table is written out.
175 Length := Int'Max (Length, Table_Initial);
177 -- Now increment table length until it is sufficiently large
179 while Max < Last_Val loop
180 Length := Length * (100 + Table_Increment) / 100;
181 Max := Min + Length - 1;
182 end loop;
184 if Debug_Flag_D then
185 Write_Str ("--> Allocating new ");
186 Write_Str (Table_Name);
187 Write_Str (" table, size = ");
188 Write_Int (Max - Min + 1);
189 Write_Eol;
190 end if;
191 end if;
193 New_Size :=
194 size_t ((Max - Min + 1) *
195 (Table_Type'Component_Size / Storage_Unit));
197 if Table = null then
198 Table := malloc (New_Size);
200 elsif New_Size > 0 then
201 Table :=
202 realloc
203 (memblock => Table,
204 size => New_Size);
205 end if;
207 if Length /= 0 and then Table = null then
208 Set_Standard_Error;
209 Write_Str ("available memory exhausted");
210 Write_Eol;
211 Set_Standard_Output;
212 raise Unrecoverable_Error;
213 end if;
215 end Reallocate;
217 -------------
218 -- Release --
219 -------------
221 procedure Release is
222 begin
223 Length := Last_Val - Int (Table_Low_Bound) + 1;
224 Max := Last_Val;
225 Reallocate;
226 end Release;
228 -------------
229 -- Restore --
230 -------------
232 procedure Restore (T : Saved_Table) is
233 begin
234 free (Table);
235 Last_Val := T.Last_Val;
236 Max := T.Max;
237 Table := T.Table;
238 Length := Max - Min + 1;
239 end Restore;
241 ----------
242 -- Save --
243 ----------
245 function Save return Saved_Table is
246 Res : Saved_Table;
248 begin
249 Res.Last_Val := Last_Val;
250 Res.Max := Max;
251 Res.Table := Table;
253 Table := null;
254 Length := 0;
255 Init;
256 return Res;
257 end Save;
259 --------------
260 -- Set_Item --
261 --------------
263 procedure Set_Item
264 (Index : Table_Index_Type;
265 Item : Table_Component_Type)
267 begin
268 if Int (Index) > Max then
269 Set_Last (Index);
270 end if;
272 Table (Index) := Item;
273 end Set_Item;
275 --------------
276 -- Set_Last --
277 --------------
279 procedure Set_Last (New_Val : Table_Index_Type) is
280 begin
281 if Int (New_Val) < Last_Val then
282 Last_Val := Int (New_Val);
283 else
284 Last_Val := Int (New_Val);
286 if Last_Val > Max then
287 Reallocate;
288 end if;
289 end if;
290 end Set_Last;
292 ----------------------------
293 -- Tree_Get_Table_Address --
294 ----------------------------
296 function Tree_Get_Table_Address return Address is
297 begin
298 if Length = 0 then
299 return Null_Address;
300 else
301 return Table (First)'Address;
302 end if;
303 end Tree_Get_Table_Address;
305 ---------------
306 -- Tree_Read --
307 ---------------
309 -- Note: we allocate only the space required to accommodate the data
310 -- actually written, which means that a Tree_Write/Tree_Read sequence
311 -- does an implicit Release.
313 procedure Tree_Read is
314 begin
315 Tree_Read_Int (Max);
316 Last_Val := Max;
317 Length := Max - Min + 1;
318 Reallocate;
320 Tree_Read_Data
321 (Tree_Get_Table_Address,
322 (Last_Val - Int (First) + 1) *
323 Table_Type'Component_Size / Storage_Unit);
324 end Tree_Read;
326 ----------------
327 -- Tree_Write --
328 ----------------
330 -- Note: we write out only the currently valid data, not the entire
331 -- contents of the allocated array. See note above on Tree_Read.
333 procedure Tree_Write is
334 begin
335 Tree_Write_Int (Int (Last));
336 Tree_Write_Data
337 (Tree_Get_Table_Address,
338 (Last_Val - Int (First) + 1) *
339 Table_Type'Component_Size / Storage_Unit);
340 end Tree_Write;
342 begin
343 Init;
344 end Table;
345 end Table;