PR ada/18819
[official-gcc.git] / gcc / ada / g-spitbo.adb
blob7d2ce5bc14c7d59f250c29522f4343c70129ad13
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT LIBRARY COMPONENTS --
4 -- --
5 -- G N A T . S P I T B O L --
6 -- --
7 -- B o d y --
8 -- --
9 -- Copyright (C) 1998-2006, AdaCore --
10 -- --
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, 51 Franklin Street, Fifth Floor, --
20 -- Boston, MA 02110-1301, USA. --
21 -- --
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. --
28 -- --
29 -- GNAT was originally developed by the GNAT team at New York University. --
30 -- Extensive contributions were provided by Ada Core Technologies Inc. --
31 -- --
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
44 ---------
45 -- "&" --
46 ---------
48 function "&" (Num : Integer; Str : String) return String is
49 begin
50 return S (Num) & Str;
51 end "&";
53 function "&" (Str : String; Num : Integer) return String is
54 begin
55 return Str & S (Num);
56 end "&";
58 function "&" (Num : Integer; Str : VString) return VString is
59 begin
60 return S (Num) & Str;
61 end "&";
63 function "&" (Str : VString; Num : Integer) return VString is
64 begin
65 return Str & S (Num);
66 end "&";
68 ----------
69 -- Char --
70 ----------
72 function Char (Num : Natural) return Character is
73 begin
74 return Character'Val (Num);
75 end Char;
77 ----------
78 -- Lpad --
79 ----------
81 function Lpad
82 (Str : VString;
83 Len : Natural;
84 Pad : Character := ' ') return VString
86 begin
87 if Length (Str) >= Len then
88 return Str;
89 else
90 return Tail (Str, Len, Pad);
91 end if;
92 end Lpad;
94 function Lpad
95 (Str : String;
96 Len : Natural;
97 Pad : Character := ' ') return VString
99 begin
100 if Str'Length >= Len then
101 return V (Str);
103 else
104 declare
105 R : String (1 .. Len);
107 begin
108 for J in 1 .. Len - Str'Length loop
109 R (J) := Pad;
110 end loop;
112 R (Len - Str'Length + 1 .. Len) := Str;
113 return V (R);
114 end;
115 end if;
116 end Lpad;
118 procedure Lpad
119 (Str : in out VString;
120 Len : Natural;
121 Pad : Character := ' ')
123 begin
124 if Length (Str) >= Len then
125 return;
126 else
127 Tail (Str, Len, Pad);
128 end if;
129 end Lpad;
131 -------
132 -- N --
133 -------
135 function N (Str : VString) return Integer is
136 S : String_Access;
137 L : Natural;
138 begin
139 Get_String (Str, S, L);
140 return Integer'Value (S (1 .. L));
141 end N;
143 --------------------
144 -- Reverse_String --
145 --------------------
147 function Reverse_String (Str : VString) return VString is
148 S : String_Access;
149 L : Natural;
151 begin
152 Get_String (Str, S, L);
154 declare
155 Result : String (1 .. L);
157 begin
158 for J in 1 .. L loop
159 Result (J) := S (L + 1 - J);
160 end loop;
162 return V (Result);
163 end;
164 end Reverse_String;
166 function Reverse_String (Str : String) return VString is
167 Result : String (1 .. Str'Length);
169 begin
170 for J in 1 .. Str'Length loop
171 Result (J) := Str (Str'Last + 1 - J);
172 end loop;
174 return V (Result);
175 end Reverse_String;
177 procedure Reverse_String (Str : in out VString) is
178 S : String_Access;
179 L : Natural;
181 begin
182 Get_String (Str, S, L);
184 declare
185 Result : String (1 .. L);
187 begin
188 for J in 1 .. L loop
189 Result (J) := S (L + 1 - J);
190 end loop;
192 Set_String (Str, Result);
193 end;
194 end Reverse_String;
196 ----------
197 -- Rpad --
198 ----------
200 function Rpad
201 (Str : VString;
202 Len : Natural;
203 Pad : Character := ' ') return VString
205 begin
206 if Length (Str) >= Len then
207 return Str;
208 else
209 return Head (Str, Len, Pad);
210 end if;
211 end Rpad;
213 function Rpad
214 (Str : String;
215 Len : Natural;
216 Pad : Character := ' ') return VString
218 begin
219 if Str'Length >= Len then
220 return V (Str);
222 else
223 declare
224 R : String (1 .. Len);
226 begin
227 for J in Str'Length + 1 .. Len loop
228 R (J) := Pad;
229 end loop;
231 R (1 .. Str'Length) := Str;
232 return V (R);
233 end;
234 end if;
235 end Rpad;
237 procedure Rpad
238 (Str : in out VString;
239 Len : Natural;
240 Pad : Character := ' ')
242 begin
243 if Length (Str) >= Len then
244 return;
246 else
247 Head (Str, Len, Pad);
248 end if;
249 end Rpad;
251 -------
252 -- S --
253 -------
255 function S (Num : Integer) return String is
256 Buf : String (1 .. 30);
257 Ptr : Natural := Buf'Last + 1;
258 Val : Natural := abs (Num);
260 begin
261 loop
262 Ptr := Ptr - 1;
263 Buf (Ptr) := Character'Val (Val mod 10 + Character'Pos ('0'));
264 Val := Val / 10;
265 exit when Val = 0;
266 end loop;
268 if Num < 0 then
269 Ptr := Ptr - 1;
270 Buf (Ptr) := '-';
271 end if;
273 return Buf (Ptr .. Buf'Last);
274 end S;
276 ------------
277 -- Substr --
278 ------------
280 function Substr
281 (Str : VString;
282 Start : Positive;
283 Len : Natural) return VString
285 S : String_Access;
286 L : Natural;
288 begin
289 Get_String (Str, S, L);
291 if Start > L then
292 raise Index_Error;
293 elsif Start + Len - 1 > L then
294 raise Length_Error;
295 else
296 return V (S (Start .. Start + Len - 1));
297 end if;
298 end Substr;
300 function Substr
301 (Str : String;
302 Start : Positive;
303 Len : Natural) return VString
305 begin
306 if Start > Str'Length then
307 raise Index_Error;
308 elsif Start + Len > Str'Length then
309 raise Length_Error;
310 else
311 return
312 V (Str (Str'First + Start - 1 .. Str'First + Start + Len - 2));
313 end if;
314 end Substr;
316 -----------
317 -- Table --
318 -----------
320 package body Table is
322 procedure Free is new
323 Unchecked_Deallocation (Hash_Element, Hash_Element_Ptr);
325 -----------------------
326 -- Local Subprograms --
327 -----------------------
329 function Hash (Str : String) return Unsigned_32;
330 -- Compute hash function for given String
332 ------------
333 -- Adjust --
334 ------------
336 procedure Adjust (Object : in out Table) is
337 Ptr1 : Hash_Element_Ptr;
338 Ptr2 : Hash_Element_Ptr;
340 begin
341 for J in Object.Elmts'Range loop
342 Ptr1 := Object.Elmts (J)'Unrestricted_Access;
344 if Ptr1.Name /= null then
345 loop
346 Ptr1.Name := new String'(Ptr1.Name.all);
347 exit when Ptr1.Next = null;
348 Ptr2 := Ptr1.Next;
349 Ptr1.Next := new Hash_Element'(Ptr2.all);
350 Ptr1 := Ptr1.Next;
351 end loop;
352 end if;
353 end loop;
354 end Adjust;
356 -----------
357 -- Clear --
358 -----------
360 procedure Clear (T : in out Table) is
361 Ptr1 : Hash_Element_Ptr;
362 Ptr2 : Hash_Element_Ptr;
364 begin
365 for J in T.Elmts'Range loop
366 if T.Elmts (J).Name /= null then
367 Free (T.Elmts (J).Name);
368 T.Elmts (J).Value := Null_Value;
370 Ptr1 := T.Elmts (J).Next;
371 T.Elmts (J).Next := null;
373 while Ptr1 /= null loop
374 Ptr2 := Ptr1.Next;
375 Free (Ptr1.Name);
376 Free (Ptr1);
377 Ptr1 := Ptr2;
378 end loop;
379 end if;
380 end loop;
381 end Clear;
383 ----------------------
384 -- Convert_To_Array --
385 ----------------------
387 function Convert_To_Array (T : Table) return Table_Array is
388 Num_Elmts : Natural := 0;
389 Elmt : Hash_Element_Ptr;
391 begin
392 for J in T.Elmts'Range loop
393 Elmt := T.Elmts (J)'Unrestricted_Access;
395 if Elmt.Name /= null then
396 loop
397 Num_Elmts := Num_Elmts + 1;
398 Elmt := Elmt.Next;
399 exit when Elmt = null;
400 end loop;
401 end if;
402 end loop;
404 declare
405 TA : Table_Array (1 .. Num_Elmts);
406 P : Natural := 1;
408 begin
409 for J in T.Elmts'Range loop
410 Elmt := T.Elmts (J)'Unrestricted_Access;
412 if Elmt.Name /= null then
413 loop
414 Set_String (TA (P).Name, Elmt.Name.all);
415 TA (P).Value := Elmt.Value;
416 P := P + 1;
417 Elmt := Elmt.Next;
418 exit when Elmt = null;
419 end loop;
420 end if;
421 end loop;
423 return TA;
424 end;
425 end Convert_To_Array;
427 ----------
428 -- Copy --
429 ----------
431 procedure Copy (From : Table; To : in out Table) is
432 Elmt : Hash_Element_Ptr;
434 begin
435 Clear (To);
437 for J in From.Elmts'Range loop
438 Elmt := From.Elmts (J)'Unrestricted_Access;
439 if Elmt.Name /= null then
440 loop
441 Set (To, Elmt.Name.all, Elmt.Value);
442 Elmt := Elmt.Next;
443 exit when Elmt = null;
444 end loop;
445 end if;
446 end loop;
447 end Copy;
449 ------------
450 -- Delete --
451 ------------
453 procedure Delete (T : in out Table; Name : Character) is
454 begin
455 Delete (T, String'(1 => Name));
456 end Delete;
458 procedure Delete (T : in out Table; Name : VString) is
459 S : String_Access;
460 L : Natural;
461 begin
462 Get_String (Name, S, L);
463 Delete (T, S (1 .. L));
464 end Delete;
466 procedure Delete (T : in out Table; Name : String) is
467 Slot : constant Unsigned_32 := Hash (Name) mod T.N + 1;
468 Elmt : Hash_Element_Ptr := T.Elmts (Slot)'Unrestricted_Access;
469 Next : Hash_Element_Ptr;
471 begin
472 if Elmt.Name = null then
473 null;
475 elsif Elmt.Name.all = Name then
476 Free (Elmt.Name);
478 if Elmt.Next = null then
479 Elmt.Value := Null_Value;
480 return;
482 else
483 Next := Elmt.Next;
484 Elmt.Name := Next.Name;
485 Elmt.Value := Next.Value;
486 Elmt.Next := Next.Next;
487 Free (Next);
488 return;
489 end if;
491 else
492 loop
493 Next := Elmt.Next;
495 if Next = null then
496 return;
498 elsif Next.Name.all = Name then
499 Free (Next.Name);
500 Elmt.Next := Next.Next;
501 Free (Next);
502 return;
504 else
505 Elmt := Next;
506 end if;
507 end loop;
508 end if;
509 end Delete;
511 ----------
512 -- Dump --
513 ----------
515 procedure Dump (T : Table; Str : String := "Table") is
516 Num_Elmts : Natural := 0;
517 Elmt : Hash_Element_Ptr;
519 begin
520 for J in T.Elmts'Range loop
521 Elmt := T.Elmts (J)'Unrestricted_Access;
523 if Elmt.Name /= null then
524 loop
525 Num_Elmts := Num_Elmts + 1;
526 Put_Line
527 (Str & '<' & Image (Elmt.Name.all) & "> = " &
528 Img (Elmt.Value));
529 Elmt := Elmt.Next;
530 exit when Elmt = null;
531 end loop;
532 end if;
533 end loop;
535 if Num_Elmts = 0 then
536 Put_Line (Str & " is empty");
537 end if;
538 end Dump;
540 procedure Dump (T : Table_Array; Str : String := "Table_Array") is
541 begin
542 if T'Length = 0 then
543 Put_Line (Str & " is empty");
545 else
546 for J in T'Range loop
547 Put_Line
548 (Str & '(' & Image (To_String (T (J).Name)) & ") = " &
549 Img (T (J).Value));
550 end loop;
551 end if;
552 end Dump;
554 --------------
555 -- Finalize --
556 --------------
558 procedure Finalize (Object : in out Table) is
559 Ptr1 : Hash_Element_Ptr;
560 Ptr2 : Hash_Element_Ptr;
562 begin
563 for J in Object.Elmts'Range loop
564 Ptr1 := Object.Elmts (J).Next;
565 Free (Object.Elmts (J).Name);
566 while Ptr1 /= null loop
567 Ptr2 := Ptr1.Next;
568 Free (Ptr1.Name);
569 Free (Ptr1);
570 Ptr1 := Ptr2;
571 end loop;
572 end loop;
573 end Finalize;
575 ---------
576 -- Get --
577 ---------
579 function Get (T : Table; Name : Character) return Value_Type is
580 begin
581 return Get (T, String'(1 => Name));
582 end Get;
584 function Get (T : Table; Name : VString) return Value_Type is
585 S : String_Access;
586 L : Natural;
587 begin
588 Get_String (Name, S, L);
589 return Get (T, S (1 .. L));
590 end Get;
592 function Get (T : Table; Name : String) return Value_Type is
593 Slot : constant Unsigned_32 := Hash (Name) mod T.N + 1;
594 Elmt : Hash_Element_Ptr := T.Elmts (Slot)'Unrestricted_Access;
596 begin
597 if Elmt.Name = null then
598 return Null_Value;
600 else
601 loop
602 if Name = Elmt.Name.all then
603 return Elmt.Value;
605 else
606 Elmt := Elmt.Next;
608 if Elmt = null then
609 return Null_Value;
610 end if;
611 end if;
612 end loop;
613 end if;
614 end Get;
616 ----------
617 -- Hash --
618 ----------
620 function Hash (Str : String) return Unsigned_32 is
621 Result : Unsigned_32 := Str'Length;
623 begin
624 for J in Str'Range loop
625 Result := Rotate_Left (Result, 3) +
626 Unsigned_32 (Character'Pos (Str (J)));
627 end loop;
629 return Result;
630 end Hash;
632 -------------
633 -- Present --
634 -------------
636 function Present (T : Table; Name : Character) return Boolean is
637 begin
638 return Present (T, String'(1 => Name));
639 end Present;
641 function Present (T : Table; Name : VString) return Boolean is
642 S : String_Access;
643 L : Natural;
644 begin
645 Get_String (Name, S, L);
646 return Present (T, S (1 .. L));
647 end Present;
649 function Present (T : Table; Name : String) return Boolean is
650 Slot : constant Unsigned_32 := Hash (Name) mod T.N + 1;
651 Elmt : Hash_Element_Ptr := T.Elmts (Slot)'Unrestricted_Access;
653 begin
654 if Elmt.Name = null then
655 return False;
657 else
658 loop
659 if Name = Elmt.Name.all then
660 return True;
662 else
663 Elmt := Elmt.Next;
665 if Elmt = null then
666 return False;
667 end if;
668 end if;
669 end loop;
670 end if;
671 end Present;
673 ---------
674 -- Set --
675 ---------
677 procedure Set (T : in out Table; Name : VString; Value : Value_Type) is
678 S : String_Access;
679 L : Natural;
680 begin
681 Get_String (Name, S, L);
682 Set (T, S (1 .. L), Value);
683 end Set;
685 procedure Set (T : in out Table; Name : Character; Value : Value_Type) is
686 begin
687 Set (T, String'(1 => Name), Value);
688 end Set;
690 procedure Set
691 (T : in out Table;
692 Name : String;
693 Value : Value_Type)
695 begin
696 if Value = Null_Value then
697 Delete (T, Name);
699 else
700 declare
701 Slot : constant Unsigned_32 := Hash (Name) mod T.N + 1;
702 Elmt : Hash_Element_Ptr := T.Elmts (Slot)'Unrestricted_Access;
704 subtype String1 is String (1 .. Name'Length);
706 begin
707 if Elmt.Name = null then
708 Elmt.Name := new String'(String1 (Name));
709 Elmt.Value := Value;
710 return;
712 else
713 loop
714 if Name = Elmt.Name.all then
715 Elmt.Value := Value;
716 return;
718 elsif Elmt.Next = null then
719 Elmt.Next := new Hash_Element'(
720 Name => new String'(String1 (Name)),
721 Value => Value,
722 Next => null);
723 return;
725 else
726 Elmt := Elmt.Next;
727 end if;
728 end loop;
729 end if;
730 end;
731 end if;
732 end Set;
733 end Table;
735 ----------
736 -- Trim --
737 ----------
739 function Trim (Str : VString) return VString is
740 begin
741 return Trim (Str, Right);
742 end Trim;
744 function Trim (Str : String) return VString is
745 begin
746 for J in reverse Str'Range loop
747 if Str (J) /= ' ' then
748 return V (Str (Str'First .. J));
749 end if;
750 end loop;
752 return Nul;
753 end Trim;
755 procedure Trim (Str : in out VString) is
756 begin
757 Trim (Str, Right);
758 end Trim;
760 -------
761 -- V --
762 -------
764 function V (Num : Integer) return VString is
765 Buf : String (1 .. 30);
766 Ptr : Natural := Buf'Last + 1;
767 Val : Natural := abs (Num);
769 begin
770 loop
771 Ptr := Ptr - 1;
772 Buf (Ptr) := Character'Val (Val mod 10 + Character'Pos ('0'));
773 Val := Val / 10;
774 exit when Val = 0;
775 end loop;
777 if Num < 0 then
778 Ptr := Ptr - 1;
779 Buf (Ptr) := '-';
780 end if;
782 return V (Buf (Ptr .. Buf'Last));
783 end V;
785 end GNAT.Spitbol;