1 ------------------------------------------------------------------------------
3 -- GNAT LIBRARY COMPONENTS --
5 -- G N A T . S P I T B O L --
9 -- Copyright (C) 1998-2002 Ada Core Technologies, Inc. --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 2, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING. If not, write --
19 -- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, --
20 -- MA 02111-1307, USA. --
22 -- As a special exception, if other files instantiate generics from this --
23 -- unit, or you link this unit with other files to produce an executable, --
24 -- this unit does not by itself cause the resulting executable to be --
25 -- covered by the GNU General Public License. This exception does not --
26 -- however invalidate any other reasons why the executable file might be --
27 -- covered by the GNU Public License. --
29 -- GNAT was originally developed by the GNAT team at New York University. --
30 -- Extensive contributions were provided by Ada Core Technologies Inc. --
32 ------------------------------------------------------------------------------
34 with Ada.Strings; use Ada.Strings;
35 with Ada.Strings.Unbounded.Aux; use Ada.Strings.Unbounded.Aux;
37 with GNAT.Debug_Utilities; use GNAT.Debug_Utilities;
38 with GNAT.IO; use GNAT.IO;
40 with Unchecked_Deallocation;
42 package body GNAT.Spitbol is
48 function "&" (Num : Integer; Str : String) return String is
53 function "&" (Str : String; Num : Integer) return String is
58 function "&" (Num : Integer; Str : VString) return VString is
63 function "&" (Str : VString; Num : Integer) return VString is
72 function Char (Num : Natural) return Character is
74 return Character'Val (Num);
84 Pad : Character := ' ')
88 if Length (Str) >= Len then
91 return Tail (Str, Len, Pad);
98 Pad : Character := ' ')
102 if Str'Length >= Len then
107 R : String (1 .. Len);
110 for J in 1 .. Len - Str'Length loop
114 R (Len - Str'Length + 1 .. Len) := Str;
121 (Str : in out VString;
123 Pad : Character := ' ')
126 if Length (Str) >= Len then
129 Tail (Str, Len, Pad);
137 function N (Str : VString) return Integer is
139 return Integer'Value (Get_String (Str).all);
146 function Reverse_String (Str : VString) return VString is
147 Len : constant Natural := Length (Str);
148 Chars : constant String_Access := Get_String (Str);
149 Result : String (1 .. Len);
152 for J in 1 .. Len loop
153 Result (J) := Chars (Len + 1 - J);
159 function Reverse_String (Str : String) return VString is
160 Result : String (1 .. Str'Length);
163 for J in 1 .. Str'Length loop
164 Result (J) := Str (Str'Last + 1 - J);
170 procedure Reverse_String (Str : in out VString) is
171 Len : constant Natural := Length (Str);
172 Chars : constant String_Access := Get_String (Str);
176 for J in 1 .. Len / 2 loop
178 Chars (J) := Chars (Len + 1 - J);
179 Chars (Len + 1 - J) := Temp;
190 Pad : Character := ' ')
194 if Length (Str) >= Len then
197 return Head (Str, Len, Pad);
204 Pad : Character := ' ')
208 if Str'Length >= Len then
213 R : String (1 .. Len);
216 for J in Str'Length + 1 .. Len loop
220 R (1 .. Str'Length) := Str;
227 (Str : in out VString;
229 Pad : Character := ' ')
232 if Length (Str) >= Len then
236 Head (Str, Len, Pad);
244 function S (Num : Integer) return String is
245 Buf : String (1 .. 30);
246 Ptr : Natural := Buf'Last + 1;
247 Val : Natural := abs (Num);
252 Buf (Ptr) := Character'Val (Val mod 10 + Character'Pos ('0'));
262 return Buf (Ptr .. Buf'Last);
276 if Start > Length (Str) then
279 elsif Start + Len - 1 > Length (Str) then
283 return V (Get_String (Str).all (Start .. Start + Len - 1));
294 if Start > Str'Length then
297 elsif Start + Len > Str'Length then
302 V (Str (Str'First + Start - 1 .. Str'First + Start + Len - 2));
310 package body Table is
312 procedure Free is new
313 Unchecked_Deallocation (Hash_Element, Hash_Element_Ptr);
315 -----------------------
316 -- Local Subprograms --
317 -----------------------
319 function Hash (Str : String) return Unsigned_32;
320 -- Compute hash function for given String
326 procedure Adjust (Object : in out Table) is
327 Ptr1 : Hash_Element_Ptr;
328 Ptr2 : Hash_Element_Ptr;
331 for J in Object.Elmts'Range loop
332 Ptr1 := Object.Elmts (J)'Unrestricted_Access;
334 if Ptr1.Name /= null then
336 Ptr1.Name := new String'(Ptr1.Name.all);
337 exit when Ptr1.Next = null;
339 Ptr1.Next := new Hash_Element'(Ptr2.all);
350 procedure Clear (T : in out Table) is
351 Ptr1 : Hash_Element_Ptr;
352 Ptr2 : Hash_Element_Ptr;
355 for J in T.Elmts'Range loop
356 if T.Elmts (J).Name /= null then
357 Free (T.Elmts (J).Name);
358 T.Elmts (J).Value := Null_Value;
360 Ptr1 := T.Elmts (J).Next;
361 T.Elmts (J).Next := null;
363 while Ptr1 /= null loop
373 ----------------------
374 -- Convert_To_Array --
375 ----------------------
377 function Convert_To_Array (T : Table) return Table_Array is
378 Num_Elmts : Natural := 0;
379 Elmt : Hash_Element_Ptr;
382 for J in T.Elmts'Range loop
383 Elmt := T.Elmts (J)'Unrestricted_Access;
385 if Elmt.Name /= null then
387 Num_Elmts := Num_Elmts + 1;
389 exit when Elmt = null;
395 TA : Table_Array (1 .. Num_Elmts);
399 for J in T.Elmts'Range loop
400 Elmt := T.Elmts (J)'Unrestricted_Access;
402 if Elmt.Name /= null then
404 Set_String (TA (P).Name, Elmt.Name.all);
405 TA (P).Value := Elmt.Value;
408 exit when Elmt = null;
415 end Convert_To_Array;
421 procedure Copy (From : in Table; To : in out Table) is
422 Elmt : Hash_Element_Ptr;
427 for J in From.Elmts'Range loop
428 Elmt := From.Elmts (J)'Unrestricted_Access;
429 if Elmt.Name /= null then
431 Set (To, Elmt.Name.all, Elmt.Value);
433 exit when Elmt = null;
443 procedure Delete (T : in out Table; Name : Character) is
445 Delete (T, String'(1 => Name));
448 procedure Delete (T : in out Table; Name : VString) is
450 Delete (T, Get_String (Name).all);
453 procedure Delete (T : in out Table; Name : String) is
454 Slot : constant Unsigned_32 := Hash (Name) mod T.N + 1;
455 Elmt : Hash_Element_Ptr := T.Elmts (Slot)'Unrestricted_Access;
456 Next : Hash_Element_Ptr;
459 if Elmt.Name = null then
462 elsif Elmt.Name.all = Name then
465 if Elmt.Next = null then
466 Elmt.Value := Null_Value;
471 Elmt.Name := Next.Name;
472 Elmt.Value := Next.Value;
473 Elmt.Next := Next.Next;
485 elsif Next.Name.all = Name then
487 Elmt.Next := Next.Next;
502 procedure Dump (T : Table; Str : String := "Table") is
503 Num_Elmts : Natural := 0;
504 Elmt : Hash_Element_Ptr;
507 for J in T.Elmts'Range loop
508 Elmt := T.Elmts (J)'Unrestricted_Access;
510 if Elmt.Name /= null then
512 Num_Elmts := Num_Elmts + 1;
514 (Str & '<' & Image (Elmt.Name.all) & "> = " &
517 exit when Elmt = null;
522 if Num_Elmts = 0 then
523 Put_Line (Str & " is empty");
527 procedure Dump (T : Table_Array; Str : String := "Table_Array") is
530 Put_Line (Str & " is empty");
533 for J in T'Range loop
535 (Str & '(' & Image (To_String (T (J).Name)) & ") = " &
545 procedure Finalize (Object : in out Table) is
546 Ptr1 : Hash_Element_Ptr;
547 Ptr2 : Hash_Element_Ptr;
550 for J in Object.Elmts'Range loop
551 Ptr1 := Object.Elmts (J).Next;
552 Free (Object.Elmts (J).Name);
553 while Ptr1 /= null loop
566 function Get (T : Table; Name : Character) return Value_Type is
568 return Get (T, String'(1 => Name));
571 function Get (T : Table; Name : VString) return Value_Type is
573 return Get (T, Get_String (Name).all);
576 function Get (T : Table; Name : String) return Value_Type is
577 Slot : constant Unsigned_32 := Hash (Name) mod T.N + 1;
578 Elmt : Hash_Element_Ptr := T.Elmts (Slot)'Unrestricted_Access;
581 if Elmt.Name = null then
586 if Name = Elmt.Name.all then
604 function Hash (Str : String) return Unsigned_32 is
605 Result : Unsigned_32 := Str'Length;
608 for J in Str'Range loop
609 Result := Rotate_Left (Result, 1) +
610 Unsigned_32 (Character'Pos (Str (J)));
620 function Present (T : Table; Name : Character) return Boolean is
622 return Present (T, String'(1 => Name));
625 function Present (T : Table; Name : VString) return Boolean is
627 return Present (T, Get_String (Name).all);
630 function Present (T : Table; Name : String) return Boolean is
631 Slot : constant Unsigned_32 := Hash (Name) mod T.N + 1;
632 Elmt : Hash_Element_Ptr := T.Elmts (Slot)'Unrestricted_Access;
635 if Elmt.Name = null then
640 if Name = Elmt.Name.all then
658 procedure Set (T : in out Table; Name : VString; Value : Value_Type) is
660 Set (T, Get_String (Name).all, Value);
663 procedure Set (T : in out Table; Name : Character; Value : Value_Type) is
665 Set (T, String'(1 => Name), Value);
674 if Value = Null_Value then
679 Slot : constant Unsigned_32 := Hash (Name) mod T.N + 1;
680 Elmt : Hash_Element_Ptr := T.Elmts (Slot)'Unrestricted_Access;
682 subtype String1 is String (1 .. Name'Length);
685 if Elmt.Name = null then
686 Elmt.Name := new String'(String1 (Name));
692 if Name = Elmt.Name.all then
696 elsif Elmt.Next = null then
697 Elmt.Next := new Hash_Element'(
698 Name => new String'(String1 (Name)),
717 function Trim (Str : VString) return VString is
719 return Trim (Str, Right);
722 function Trim (Str : String) return VString is
724 for J in reverse Str'Range loop
725 if Str (J) /= ' ' then
726 return V (Str (Str'First .. J));
733 procedure Trim (Str : in out VString) is
742 function V (Num : Integer) return VString is
743 Buf : String (1 .. 30);
744 Ptr : Natural := Buf'Last + 1;
745 Val : Natural := abs (Num);
750 Buf (Ptr) := Character'Val (Val mod 10 + Character'Pos ('0'));
760 return V (Buf (Ptr .. Buf'Last));