diff options
author | Tristan Gingold | 2014-11-04 20:14:19 +0100 |
---|---|---|
committer | Tristan Gingold | 2014-11-04 20:14:19 +0100 |
commit | 9c195bf5d86d67ea5eb419ccf6e48dc153e57c68 (patch) | |
tree | 575346e529b99e26382b4a06f6ff2caa0b391ab2 /src/lists.adb | |
parent | 184a123f91e07c927292d67462561dc84f3a920d (diff) | |
download | ghdl-9c195bf5d86d67ea5eb419ccf6e48dc153e57c68.tar.gz ghdl-9c195bf5d86d67ea5eb419ccf6e48dc153e57c68.tar.bz2 ghdl-9c195bf5d86d67ea5eb419ccf6e48dc153e57c68.zip |
Move sources to src/ subdirectory.
Diffstat (limited to 'src/lists.adb')
-rw-r--r-- | src/lists.adb | 257 |
1 files changed, 257 insertions, 0 deletions
diff --git a/src/lists.adb b/src/lists.adb new file mode 100644 index 0000000..38afea5 --- /dev/null +++ b/src/lists.adb @@ -0,0 +1,257 @@ +-- Lists data type. +-- Copyright (C) 2002, 2003, 2004, 2005 Tristan Gingold +-- +-- GHDL is free software; you can redistribute it and/or modify it under +-- the terms of the GNU General Public License as published by the Free +-- Software Foundation; either version 2, or (at your option) any later +-- version. +-- +-- GHDL 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 General Public License +-- for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with GHDL; see the file COPYING. If not, write to the Free +-- Software Foundation, 59 Temple Place - Suite 330, Boston, MA +-- 02111-1307, USA. +with System; +with GNAT.Table; + +package body Lists is + type Node_Array_Fat is array (Natural) of Node_Type; + type Node_Array_Fat_Acc is access Node_Array_Fat; + + type List_Record is record + Max : Natural; + Nbr : Natural; + Next : List_Type; + Els : Node_Array_Fat_Acc; + end record; + + package Listt is new GNAT.Table + (Table_Component_Type => List_Record, + Table_Index_Type => List_Type, + Table_Low_Bound => 4, + Table_Initial => 128, + Table_Increment => 100); + + --function Get_Max_Nbr_Elements (List : List_Type) return Natural; + --pragma Inline (Get_Max_Nbr_Elements); + + --procedure Set_Max_Nbr_Elements (List : List_Type; Max : Natural); + --pragma Inline (Set_Max_Nbr_Elements); + + procedure List_Set_Nbr_Elements (List : List_Type; Nbr : Natural); + pragma Inline (List_Set_Nbr_Elements); + + function Get_Nbr_Elements (List: List_Type) return Natural is + begin + return Listt.Table (List).Nbr; + end Get_Nbr_Elements; + + procedure List_Set_Nbr_Elements (List : List_Type; Nbr : Natural) is + begin + Listt.Table (List).Nbr := Nbr; + end List_Set_Nbr_Elements; + + --function Get_Max_Nbr_Elements (List : List_Type) return Natural is + --begin + -- return Listt.Table (List).Max; + --end Get_Max_Nbr_Elements; + + --procedure Set_Max_Nbr_Elements (List : List_Type; Max : Natural) is + --begin + -- Listt.Table (List).Max := Max; + --end Set_Max_Nbr_Elements; + + function Get_Nth_Element (List: List_Type; N: Natural) + return Node_Type + is + begin + if N >= Listt.Table (List).Nbr then + return Null_Node; + end if; + return Listt.Table (List).Els (N); + end Get_Nth_Element; + + -- Replace an element selected by position. + procedure Replace_Nth_Element (List: List_Type; N: Natural; El: Node_Type) + is + begin + if N >= Listt.Table (List).Nbr then + raise Program_Error; + end if; + Listt.Table (List).Els (N) := El; + end Replace_Nth_Element; + + -- Be sure an element can be added to LIST. + -- It doesn't change the number of elements. + procedure List_Grow (List: List_Type) + is + L : List_Record renames Listt.Table (List); + + -- Be careful: size in bytes. + function Alloc (Size : Natural) return Node_Array_Fat_Acc; + pragma Import (C, Alloc, "malloc"); + + function Realloc (Ptr : Node_Array_Fat_Acc; Size : Natural) + return Node_Array_Fat_Acc; + pragma Import (C, Realloc, "realloc"); + + Tmp : Node_Array_Fat_Acc; + N : Natural; + begin + if L.Nbr < L.Max then + return; + end if; + if L.Max = 0 then + N := 8; + Tmp := Alloc (N * Node_Type'Size / System.Storage_Unit); + else + N := L.Max * 2; + Tmp := Realloc (L.Els, N * Node_Type'Size / System.Storage_Unit); + end if; + L.Els := Tmp; + L.Max := N; + end List_Grow; + + procedure Append_Element (List: List_Type; Element: Node_Type) + is + L : List_Record renames Listt.Table (List); + begin + if L.Nbr >= L.Max then + List_Grow (List); + end if; + L.Els (L.Nbr) := Element; + L.Nbr := L.Nbr + 1; + end Append_Element; + + -- Return the last element of the list, or null. + function Get_Last_Element (List: List_Type) return Node_Type + is + L : List_Record renames Listt.Table (List); + begin + if L.Nbr = 0 then + return Null_Node; + else + return L.Els (L.Nbr - 1); + end if; + end Get_Last_Element; + + -- Return the first element of the list, or null. + function Get_First_Element (List: List_Type) return Node_Type is + begin + if Listt.Table (List).Nbr = 0 then + return Null_Node; + else + return Listt.Table (List).Els (0); + end if; + end Get_First_Element; + + -- Add (append) an element only if it was not already present in the list. + procedure Add_Element (List: List_Type; El: Node_Type) + is + Nbr : constant Natural := Get_Nbr_Elements (List); + begin + for I in 0 .. Nbr - 1 loop + if Listt.Table (List).Els (I) = El then + return; + end if; + end loop; + + Append_Element (List, El); + end Add_Element; + + procedure Remove_Nth_Element (List: List_Type; N: Natural) + is + Nbr : constant Natural := Get_Nbr_Elements (List); + begin + if N >= Nbr then + raise Program_Error; + end if; + for I in N .. Nbr - 2 loop + Listt.Table (List).Els (I) := Listt.Table (List).Els (I + 1); + end loop; + Listt.Table (List).Nbr := Nbr - 1; + end Remove_Nth_Element; + + procedure Set_Nbr_Elements (List: List_Type; N: Natural) is + begin + if N > Get_Nbr_Elements (List) then + raise Program_Error; + end if; + List_Set_Nbr_Elements (List, N); + end Set_Nbr_Elements; + + -- Return the position of the last element. + -- Return -1 if the list is empty. + function Get_Last_Element_Position (List: List_Type) return Integer is + begin + return Get_Nbr_Elements (List) - 1; + end Get_Last_Element_Position; + + function Get_Nbr_Elements_Safe (List: List_Type) return Natural is + begin + if List = Null_List then + return 0; + else + return Get_Nbr_Elements (List); + end if; + end Get_Nbr_Elements_Safe; + + -- Empty the list + procedure Empty_List (List: List_Type) is + begin + Set_Nbr_Elements (List, 0); + end Empty_List; + + -- Chain of unused lists. + Free_Chain : List_Type := Null_List; + + function Create_List return List_Type + is + Res : List_Type; + begin + if Free_Chain = Null_List then + Listt.Increment_Last; + Res := Listt.Last; + else + Res := Free_Chain; + Free_Chain := Listt.Table (Res).Next; + end if; + Listt.Table (Res) := List_Record'(Max => 0, Nbr => 0, + Next => Null_List, Els => null); + return Res; + end Create_List; + + procedure Free (Ptr : Node_Array_Fat_Acc); + pragma Import (C, Free, "free"); + + procedure Destroy_List (List : in out List_Type) + is + begin + if List = Null_List then + return; + end if; + if Listt.Table (List).Max > 0 then + Free (Listt.Table (List).Els); + Listt.Table (List).Els := null; + end if; + Listt.Table (List).Next := Free_Chain; + Free_Chain := List; + List := Null_List; + end Destroy_List; + + procedure Initialize is + begin + for I in Listt.First .. Listt.Last loop + if Listt.Table (I).Els /= null then + Free (Listt.Table (I).Els); + end if; + end loop; + Listt.Free; + Listt.Init; + end Initialize; + +end Lists; |