home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Geek Gadgets 1
/
ADE-1.bin
/
ade-dist
/
gnat-2.06-src.tgz
/
tar.out
/
fsf
/
gnat
/
ada
/
table.adb
< prev
next >
Wrap
Text File
|
1996-09-28
|
8KB
|
282 lines
------------------------------------------------------------------------------
-- --
-- GNAT COMPILER COMPONENTS --
-- --
-- T A B L E --
-- --
-- B o d y --
-- --
-- $Revision: 1.19 $ --
-- --
-- Copyright (c) 1992,1993,1994,1995 NYU, All Rights Reserved --
-- --
-- The GNAT library is free software; you can redistribute it and/or modify --
-- it under terms of the GNU Library General Public License as published by --
-- the Free Software Foundation; either version 2, or (at your option) any --
-- later version. The GNAT library is distributed in the hope that it will --
-- be useful, but WITHOUT ANY WARRANTY; without even the implied warranty --
-- of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU --
-- Library General Public License for more details. You should have --
-- received a copy of the GNU Library General Public License along with --
-- the GNAT library; see the file COPYING.LIB. If not, write to the Free --
-- Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. --
-- --
------------------------------------------------------------------------------
with Debug; use Debug;
with Output; use Output;
with System; use System;
with Tree_IO; use Tree_IO;
with Unchecked_Conversion;
with Unchecked_Deallocation;
package body Table is
Last_Val : Int;
-- Current value of Last. Note that we declare this in the body because
-- we don't want the client to modify Last except through one of the
-- official interfaces (since a modification to Last may require a
-- reallocation of the table).
Min : Int;
-- Subscript of the minimum entry in the currently allocated table
Max : Int;
-- Subscript of the maximum entry in the currently allocated table
Length : Int := 0;
-- Number of entries in currently allocated table. The value of zero
-- ensures that we initially allocate the table.
-----------------------
-- Local Subprograms --
-----------------------
procedure Reallocate;
-- Reallocate and extend the existing table
--------------
-- Allocate --
--------------
function Allocate (Num : Int := 1) return Table_Index_Type is
Old_Last : constant Int := Last_Val;
begin
Last_Val := Last_Val + Num;
if Last_Val > Max then
Reallocate;
end if;
return Table_Index_Type (Old_Last + 1);
end Allocate;
----------
-- Copy --
----------
function Copy return Table_Ptr is
subtype Local_Table is Table_Type (Table_Low_Bound .. Last);
type Local_Table_Ptr is access all Local_Table;
Tmp : Local_Table_Ptr;
function To_Table_Ptr is
new Unchecked_Conversion (Local_Table_Ptr, Table_Ptr);
begin
Tmp := new Local_Table;
return To_Table_Ptr (Tmp);
end Copy;
--------------------
-- Decrement_Last --
--------------------
procedure Decrement_Last is
begin
Last_Val := Last_Val - 1;
end Decrement_Last;
--------------------
-- Increment_Last --
--------------------
procedure Increment_Last is
begin
Last_Val := Last_Val + 1;
if Last_Val > Max then
Reallocate;
end if;
end Increment_Last;
----------
-- Free --
----------
procedure Free (T : in out Table_Ptr) is
procedure UD is new Unchecked_Deallocation (Big_Table_Type, Table_Ptr);
begin
UD (T);
end Free;
----------
-- Init --
----------
procedure Init is
Old_Length : Int := Length;
begin
Min := Int (Table_Low_Bound);
Last_Val := Min - 1;
Max := Min + Table_Initial - 1;
Length := Max - Min + 1;
-- If table is same size as before (happens when table is never
-- expanded which is a common case), then simply reuse it, else free
-- the old table and allocate a new one of the proper size.
if Old_Length /= Length then
Free (Table);
declare
subtype Local_Table is
Table_Type (Table_Index_Type (Min) .. Table_Index_Type (Max));
type Local_Table_Ptr is access all Local_Table;
Tmp : Local_Table_Ptr;
function To_Table_Ptr is
new Unchecked_Conversion (Local_Table_Ptr, Table_Ptr);
begin
Tmp := new Local_Table;
Table := To_Table_Ptr (Tmp);
end;
end if;
end Init;
----------
-- Last --
----------
function Last return Table_Index_Type is
begin
return Table_Index_Type (Last_Val);
end Last;
----------------
-- Reallocate --
----------------
procedure Reallocate is
Old_Table : Table_Ptr := Table;
Old_Max : Int := Max;
begin
if Table_Increment = 0 then
Write_Str ("Fatal error, table ");
Write_Str (Table_Name);
Write_Str (" capacity exceeded");
Write_Eol;
raise Unrecoverable_Error;
end if;
while Max < Last_Val loop
Length := Length * (100 + Table_Increment) / 100;
Max := Min + Length - 1;
end loop;
declare
subtype Local_Table is
Table_Type (Table_Index_Type (Min) .. Table_Index_Type (Max));
type Local_Table_Ptr is access all Local_Table;
Tmp : Local_Table_Ptr;
-- We allocate an array of the bounds we want (Local_Table) and
-- then use unchecked conversion to convert this to the fake
-- pointer to giant array type that we use for access. This is
-- done to allow efficient thin pointer access to the table with
-- a fixed and known lower bound.
function To_Table_Ptr is
new Unchecked_Conversion (Local_Table_Ptr, Table_Ptr);
begin
Tmp := new Local_Table;
Table := To_Table_Ptr (Tmp);
end;
if Debug_Flag_D then
Write_Str ("--> Allocating new ");
Write_Str (Table_Name);
Write_Str (" table, size = ");
Write_Int (Max - Min + 1);
Write_Eol;
end if;
for J in Min .. Old_Max loop
Table (Table_Index_Type (J)) := Old_Table (Table_Index_Type (J));
end loop;
Free (Old_Table);
end Reallocate;
--------------
-- Set_Last --
--------------
procedure Set_Last (New_Val : Table_Index_Type) is
Old_Last : Int;
begin
if Int (New_Val) < Last_Val then
Last_Val := Int (New_Val);
else
Old_Last := Last_Val;
Last_Val := Int (New_Val);
if Last_Val > Max then
Reallocate;
end if;
end if;
end Set_Last;
---------------
-- Tree_Read --
---------------
procedure Tree_Read is
N : Int;
begin
Tree_Read_Int (N);
Set_Last (Table_Index_Type (N));
Tree_Read_Data
(Table (First)'Address,
(Last_Val - Int (First) + 1) *
Table_Component_Type'Size / Storage_Unit);
end Tree_Read;
----------------
-- Tree_Write --
----------------
procedure Tree_Write is
begin
Tree_Write_Int (Int (Last));
Tree_Write_Data
(Table (First)'Address,
(Last_Val - Int (First) + 1) *
Table_Component_Type'Size / Storage_Unit);
end Tree_Write;
begin
Init;
end Table;