* config/xtensa/xtensa.h (GO_IF_MODE_DEPENDENT_ADDRESS): Treat
[official-gcc.git] / gcc / ada / namet.adb
blob361190fe9fb3aad0d34e12bb39de8574ec382453
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT COMPILER COMPONENTS --
4 -- --
5 -- N A M E T --
6 -- --
7 -- B o d y --
8 -- --
9 -- --
10 -- Copyright (C) 1992-2001 Free Software Foundation, Inc. --
11 -- --
12 -- GNAT is free software; you can redistribute it and/or modify it under --
13 -- terms of the GNU General Public License as published by the Free Soft- --
14 -- ware Foundation; either version 2, or (at your option) any later ver- --
15 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
16 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
17 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
18 -- for more details. You should have received a copy of the GNU General --
19 -- Public License distributed with GNAT; see file COPYING. If not, write --
20 -- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, --
21 -- MA 02111-1307, USA. --
22 -- --
23 -- As a special exception, if other files instantiate generics from this --
24 -- unit, or you link this unit with other files to produce an executable, --
25 -- this unit does not by itself cause the resulting executable to be --
26 -- covered by the GNU General Public License. This exception does not --
27 -- however invalidate any other reasons why the executable file might be --
28 -- covered by the GNU Public License. --
29 -- --
30 -- GNAT was originally developed by the GNAT team at New York University. --
31 -- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
32 -- --
33 ------------------------------------------------------------------------------
35 -- WARNING: There is a C version of this package. Any changes to this
36 -- source file must be properly reflected in the C header file a-namet.h
37 -- which is created manually from namet.ads and namet.adb.
39 with Debug; use Debug;
40 with Output; use Output;
41 with Tree_IO; use Tree_IO;
42 with Widechar; use Widechar;
44 package body Namet is
46 Name_Chars_Reserve : constant := 5000;
47 Name_Entries_Reserve : constant := 100;
48 -- The names table is locked during gigi processing, since gigi assumes
49 -- that the table does not move. After returning from gigi, the names
50 -- table is unlocked again, since writing library file information needs
51 -- to generate some extra names. To avoid the inefficiency of always
52 -- reallocating during this second unlocked phase, we reserve a bit of
53 -- extra space before doing the release call.
55 Hash_Num : constant Int := 2**12;
56 -- Number of headers in the hash table. Current hash algorithm is closely
57 -- tailored to this choice, so it can only be changed if a corresponding
58 -- change is made to the hash alogorithm.
60 Hash_Max : constant Int := Hash_Num - 1;
61 -- Indexes in the hash header table run from 0 to Hash_Num - 1
63 subtype Hash_Index_Type is Int range 0 .. Hash_Max;
64 -- Range of hash index values
66 Hash_Table : array (Hash_Index_Type) of Name_Id;
67 -- The hash table is used to locate existing entries in the names table.
68 -- The entries point to the first names table entry whose hash value
69 -- matches the hash code. Then subsequent names table entries with the
70 -- same hash code value are linked through the Hash_Link fields.
72 -----------------------
73 -- Local Subprograms --
74 -----------------------
76 function Hash return Hash_Index_Type;
77 pragma Inline (Hash);
78 -- Compute hash code for name stored in Name_Buffer (length in Name_Len)
80 procedure Strip_Qualification_And_Suffixes;
81 -- Given an encoded entity name in Name_Buffer, remove package body
82 -- suffix as described for Strip_Package_Body_Suffix, and also remove
83 -- all qualification, i.e. names followed by two underscores. The
84 -- contents of Name_Buffer is modified by this call, and on return
85 -- Name_Buffer and Name_Len reflect the stripped name.
87 -----------------------------
88 -- Add_Char_To_Name_Buffer --
89 -----------------------------
91 procedure Add_Char_To_Name_Buffer (C : Character) is
92 begin
93 if Name_Len < Name_Buffer'Last then
94 Name_Len := Name_Len + 1;
95 Name_Buffer (Name_Len) := C;
96 end if;
97 end Add_Char_To_Name_Buffer;
99 ----------------------------
100 -- Add_Nat_To_Name_Buffer --
101 ----------------------------
103 procedure Add_Nat_To_Name_Buffer (V : Nat) is
104 begin
105 if V >= 10 then
106 Add_Nat_To_Name_Buffer (V / 10);
107 end if;
109 Add_Char_To_Name_Buffer (Character'Val (Character'Pos ('0') + V rem 10));
110 end Add_Nat_To_Name_Buffer;
112 ----------------------------
113 -- Add_Str_To_Name_Buffer --
114 ----------------------------
116 procedure Add_Str_To_Name_Buffer (S : String) is
117 begin
118 for J in S'Range loop
119 Add_Char_To_Name_Buffer (S (J));
120 end loop;
121 end Add_Str_To_Name_Buffer;
123 --------------
124 -- Finalize --
125 --------------
127 procedure Finalize is
128 Max_Chain_Length : constant := 50;
129 -- Max length of chains for which specific information is output
131 F : array (Int range 0 .. Max_Chain_Length) of Int;
132 -- N'th entry is number of chains of length N
134 Probes : Int := 0;
135 -- Used to compute average number of probes
137 Nsyms : Int := 0;
138 -- Number of symbols in table
140 begin
141 if Debug_Flag_H then
143 for J in F'Range loop
144 F (J) := 0;
145 end loop;
147 for I in Hash_Index_Type loop
148 if Hash_Table (I) = No_Name then
149 F (0) := F (0) + 1;
151 else
152 Write_Str ("Hash_Table (");
153 Write_Int (Int (I));
154 Write_Str (") has ");
156 declare
157 C : Int := 1;
158 N : Name_Id;
159 S : Int;
161 begin
162 C := 0;
163 N := Hash_Table (I);
165 while N /= No_Name loop
166 N := Name_Entries.Table (N).Hash_Link;
167 C := C + 1;
168 end loop;
170 Write_Int (C);
171 Write_Str (" entries");
172 Write_Eol;
174 if C < Max_Chain_Length then
175 F (C) := F (C) + 1;
176 else
177 F (Max_Chain_Length) := F (Max_Chain_Length) + 1;
178 end if;
180 N := Hash_Table (I);
182 while N /= No_Name loop
183 S := Name_Entries.Table (N).Name_Chars_Index;
184 Write_Str (" ");
186 for J in 1 .. Name_Entries.Table (N).Name_Len loop
187 Write_Char (Name_Chars.Table (S + Int (J)));
188 end loop;
190 Write_Eol;
191 N := Name_Entries.Table (N).Hash_Link;
192 end loop;
193 end;
194 end if;
195 end loop;
197 Write_Eol;
199 for I in Int range 0 .. Max_Chain_Length loop
200 if F (I) /= 0 then
201 Write_Str ("Number of hash chains of length ");
203 if I < 10 then
204 Write_Char (' ');
205 end if;
207 Write_Int (I);
209 if I = Max_Chain_Length then
210 Write_Str (" or greater");
211 end if;
213 Write_Str (" = ");
214 Write_Int (F (I));
215 Write_Eol;
217 if I /= 0 then
218 Nsyms := Nsyms + F (I);
219 Probes := Probes + F (I) * (1 + I) * 100;
220 end if;
221 end if;
222 end loop;
224 Write_Eol;
225 Write_Str ("Average number of probes for lookup = ");
226 Probes := Probes / Nsyms;
227 Write_Int (Probes / 200);
228 Write_Char ('.');
229 Probes := (Probes mod 200) / 2;
230 Write_Char (Character'Val (48 + Probes / 10));
231 Write_Char (Character'Val (48 + Probes mod 10));
232 Write_Eol;
233 Write_Eol;
234 end if;
235 end Finalize;
237 -----------------------------
238 -- Get_Decoded_Name_String --
239 -----------------------------
241 procedure Get_Decoded_Name_String (Id : Name_Id) is
242 C : Character;
243 P : Natural;
245 begin
246 Get_Name_String (Id);
248 -- Quick loop to see if there is anything special to do
250 P := 1;
251 loop
252 if P = Name_Len then
253 return;
255 else
256 C := Name_Buffer (P);
258 exit when
259 C = 'U' or else
260 C = 'W' or else
261 C = 'Q' or else
262 C = 'O';
264 P := P + 1;
265 end if;
266 end loop;
268 -- Here we have at least some encoding that we must decode
270 -- Here we have to decode one or more Uhh or Whhhh sequences
272 declare
273 New_Len : Natural;
274 Old : Positive;
275 New_Buf : String (1 .. Name_Buffer'Last);
277 procedure Insert_Character (C : Character);
278 -- Insert a new character into output decoded name
280 procedure Copy_One_Character;
281 -- Copy a character from Name_Buffer to New_Buf. Includes case
282 -- of copying a Uhh or Whhhh sequence and decoding it.
284 function Hex (N : Natural) return Natural;
285 -- Scans past N digits using Old pointer and returns hex value
287 procedure Copy_One_Character is
288 C : Character;
290 begin
291 C := Name_Buffer (Old);
293 if C = 'U' then
294 Old := Old + 1;
295 Insert_Character (Character'Val (Hex (2)));
297 elsif C = 'W' then
298 Old := Old + 1;
299 Widechar.Set_Wide (Char_Code (Hex (4)), New_Buf, New_Len);
301 else
302 Insert_Character (Name_Buffer (Old));
303 Old := Old + 1;
304 end if;
305 end Copy_One_Character;
307 function Hex (N : Natural) return Natural is
308 T : Natural := 0;
309 C : Character;
311 begin
312 for J in 1 .. N loop
313 C := Name_Buffer (Old);
314 Old := Old + 1;
316 pragma Assert (C in '0' .. '9' or else C in 'a' .. 'f');
318 if C <= '9' then
319 T := 16 * T + Character'Pos (C) - Character'Pos ('0');
320 else -- C in 'a' .. 'f'
321 T := 16 * T + Character'Pos (C) - (Character'Pos ('a') - 10);
322 end if;
323 end loop;
325 return T;
326 end Hex;
328 procedure Insert_Character (C : Character) is
329 begin
330 New_Len := New_Len + 1;
331 New_Buf (New_Len) := C;
332 end Insert_Character;
334 -- Actual decoding processing
336 begin
337 New_Len := 0;
338 Old := 1;
340 -- Loop through characters of name
342 while Old <= Name_Len loop
344 -- Case of character literal, put apostrophes around character
346 if Name_Buffer (Old) = 'Q' then
347 Old := Old + 1;
348 Insert_Character (''');
349 Copy_One_Character;
350 Insert_Character (''');
352 -- Case of operator name
354 elsif Name_Buffer (Old) = 'O' then
355 Old := Old + 1;
357 declare
358 -- This table maps the 2nd and 3rd characters of the name
359 -- into the required output. Two blanks means leave the
360 -- name alone
362 Map : constant String :=
363 "ab " & -- Oabs => "abs"
364 "ad+ " & -- Oadd => "+"
365 "an " & -- Oand => "and"
366 "co& " & -- Oconcat => "&"
367 "di/ " & -- Odivide => "/"
368 "eq= " & -- Oeq => "="
369 "ex**" & -- Oexpon => "**"
370 "gt> " & -- Ogt => ">"
371 "ge>=" & -- Oge => ">="
372 "le<=" & -- Ole => "<="
373 "lt< " & -- Olt => "<"
374 "mo " & -- Omod => "mod"
375 "mu* " & -- Omutliply => "*"
376 "ne/=" & -- One => "/="
377 "no " & -- Onot => "not"
378 "or " & -- Oor => "or"
379 "re " & -- Orem => "rem"
380 "su- " & -- Osubtract => "-"
381 "xo "; -- Oxor => "xor"
383 J : Integer;
385 begin
386 Insert_Character ('"');
388 -- Search the map. Note that this loop must terminate, if
389 -- not we have some kind of internal error, and a constraint
390 -- constraint error may be raised.
392 J := Map'First;
393 loop
394 exit when Name_Buffer (Old) = Map (J)
395 and then Name_Buffer (Old + 1) = Map (J + 1);
396 J := J + 4;
397 end loop;
399 -- Special operator name
401 if Map (J + 2) /= ' ' then
402 Insert_Character (Map (J + 2));
404 if Map (J + 3) /= ' ' then
405 Insert_Character (Map (J + 3));
406 end if;
408 Insert_Character ('"');
410 -- Skip past original operator name in input
412 while Old <= Name_Len
413 and then Name_Buffer (Old) in 'a' .. 'z'
414 loop
415 Old := Old + 1;
416 end loop;
418 -- For other operator names, leave them in lower case,
419 -- surrounded by apostrophes
421 else
422 -- Copy original operator name from input to output
424 while Old <= Name_Len
425 and then Name_Buffer (Old) in 'a' .. 'z'
426 loop
427 Copy_One_Character;
428 end loop;
430 Insert_Character ('"');
431 end if;
432 end;
434 -- Else copy one character and keep going
436 else
437 Copy_One_Character;
438 end if;
439 end loop;
441 -- Copy new buffer as result
443 Name_Len := New_Len;
444 Name_Buffer (1 .. New_Len) := New_Buf (1 .. New_Len);
445 end;
447 end Get_Decoded_Name_String;
449 -------------------------------------------
450 -- Get_Decoded_Name_String_With_Brackets --
451 -------------------------------------------
453 procedure Get_Decoded_Name_String_With_Brackets (Id : Name_Id) is
454 P : Natural;
456 begin
457 -- Case of operator name, normal decoding is fine
459 if Name_Buffer (1) = 'O' then
460 Get_Decoded_Name_String (Id);
462 -- For character literals, normal decoding is fine
464 elsif Name_Buffer (1) = 'Q' then
465 Get_Decoded_Name_String (Id);
467 -- Only remaining issue is U/W sequences
469 else
470 Get_Name_String (Id);
472 P := 1;
473 while P < Name_Len loop
474 if Name_Buffer (P) = 'U' then
475 for J in reverse P + 3 .. P + Name_Len loop
476 Name_Buffer (J + 3) := Name_Buffer (J);
477 end loop;
479 Name_Len := Name_Len + 3;
480 Name_Buffer (P + 3) := Name_Buffer (P + 2);
481 Name_Buffer (P + 2) := Name_Buffer (P + 1);
482 Name_Buffer (P) := '[';
483 Name_Buffer (P + 1) := '"';
484 Name_Buffer (P + 4) := '"';
485 Name_Buffer (P + 5) := ']';
486 P := P + 6;
488 elsif Name_Buffer (P) = 'W' then
489 Name_Buffer (P + 8 .. P + Name_Len + 5) :=
490 Name_Buffer (P + 5 .. Name_Len);
491 Name_Buffer (P + 5) := Name_Buffer (P + 4);
492 Name_Buffer (P + 4) := Name_Buffer (P + 3);
493 Name_Buffer (P + 3) := Name_Buffer (P + 2);
494 Name_Buffer (P + 2) := Name_Buffer (P + 1);
495 Name_Buffer (P) := '[';
496 Name_Buffer (P + 1) := '"';
497 Name_Buffer (P + 6) := '"';
498 Name_Buffer (P + 7) := ']';
499 Name_Len := Name_Len + 5;
500 P := P + 8;
502 else
503 P := P + 1;
504 end if;
505 end loop;
506 end if;
507 end Get_Decoded_Name_String_With_Brackets;
509 ---------------------
510 -- Get_Name_String --
511 ---------------------
513 procedure Get_Name_String (Id : Name_Id) is
514 S : Int;
516 begin
517 pragma Assert (Id in Name_Entries.First .. Name_Entries.Last);
519 S := Name_Entries.Table (Id).Name_Chars_Index;
520 Name_Len := Natural (Name_Entries.Table (Id).Name_Len);
522 for J in 1 .. Name_Len loop
523 Name_Buffer (J) := Name_Chars.Table (S + Int (J));
524 end loop;
525 end Get_Name_String;
527 function Get_Name_String (Id : Name_Id) return String is
528 S : Int;
530 begin
531 pragma Assert (Id in Name_Entries.First .. Name_Entries.Last);
532 S := Name_Entries.Table (Id).Name_Chars_Index;
534 declare
535 R : String (1 .. Natural (Name_Entries.Table (Id).Name_Len));
537 begin
538 for J in R'Range loop
539 R (J) := Name_Chars.Table (S + Int (J));
540 end loop;
542 return R;
543 end;
544 end Get_Name_String;
546 --------------------------------
547 -- Get_Name_String_And_Append --
548 --------------------------------
550 procedure Get_Name_String_And_Append (Id : Name_Id) is
551 S : Int;
553 begin
554 pragma Assert (Id in Name_Entries.First .. Name_Entries.Last);
556 S := Name_Entries.Table (Id).Name_Chars_Index;
558 for J in 1 .. Natural (Name_Entries.Table (Id).Name_Len) loop
559 Name_Len := Name_Len + 1;
560 Name_Buffer (Name_Len) := Name_Chars.Table (S + Int (J));
561 end loop;
562 end Get_Name_String_And_Append;
564 -------------------------
565 -- Get_Name_Table_Byte --
566 -------------------------
568 function Get_Name_Table_Byte (Id : Name_Id) return Byte is
569 begin
570 pragma Assert (Id in Name_Entries.First .. Name_Entries.Last);
571 return Name_Entries.Table (Id).Byte_Info;
572 end Get_Name_Table_Byte;
574 -------------------------
575 -- Get_Name_Table_Info --
576 -------------------------
578 function Get_Name_Table_Info (Id : Name_Id) return Int is
579 begin
580 pragma Assert (Id in Name_Entries.First .. Name_Entries.Last);
581 return Name_Entries.Table (Id).Int_Info;
582 end Get_Name_Table_Info;
584 -----------------------------------------
585 -- Get_Unqualified_Decoded_Name_String --
586 -----------------------------------------
588 procedure Get_Unqualified_Decoded_Name_String (Id : Name_Id) is
589 begin
590 Get_Decoded_Name_String (Id);
591 Strip_Qualification_And_Suffixes;
592 end Get_Unqualified_Decoded_Name_String;
594 ---------------------------------
595 -- Get_Unqualified_Name_String --
596 ---------------------------------
598 procedure Get_Unqualified_Name_String (Id : Name_Id) is
599 begin
600 Get_Name_String (Id);
601 Strip_Qualification_And_Suffixes;
602 end Get_Unqualified_Name_String;
604 ----------
605 -- Hash --
606 ----------
608 function Hash return Hash_Index_Type is
609 subtype Int_1_12 is Int range 1 .. 12;
610 -- Used to avoid when others on case jump below
612 Even_Name_Len : Integer;
613 -- Last even numbered position (used for >12 case)
615 begin
617 -- Special test for 12 (rather than counting on a when others for the
618 -- case statement below) avoids some Ada compilers converting the case
619 -- statement into successive jumps.
621 -- The case of a name longer than 12 characters is handled by taking
622 -- the first 6 odd numbered characters and the last 6 even numbered
623 -- characters
625 if Name_Len > 12 then
626 Even_Name_Len := (Name_Len) / 2 * 2;
628 return ((((((((((((
629 Character'Pos (Name_Buffer (01))) * 2 +
630 Character'Pos (Name_Buffer (Even_Name_Len - 10))) * 2 +
631 Character'Pos (Name_Buffer (03))) * 2 +
632 Character'Pos (Name_Buffer (Even_Name_Len - 08))) * 2 +
633 Character'Pos (Name_Buffer (05))) * 2 +
634 Character'Pos (Name_Buffer (Even_Name_Len - 06))) * 2 +
635 Character'Pos (Name_Buffer (07))) * 2 +
636 Character'Pos (Name_Buffer (Even_Name_Len - 04))) * 2 +
637 Character'Pos (Name_Buffer (09))) * 2 +
638 Character'Pos (Name_Buffer (Even_Name_Len - 02))) * 2 +
639 Character'Pos (Name_Buffer (11))) * 2 +
640 Character'Pos (Name_Buffer (Even_Name_Len))) mod Hash_Num;
641 end if;
643 -- For the cases of 1-12 characters, all characters participate in the
644 -- hash. The positioning is randomized, with the bias that characters
645 -- later on participate fully (i.e. are added towards the right side).
647 case Int_1_12 (Name_Len) is
649 when 1 =>
650 return
651 Character'Pos (Name_Buffer (1));
653 when 2 =>
654 return ((
655 Character'Pos (Name_Buffer (1))) * 64 +
656 Character'Pos (Name_Buffer (2))) mod Hash_Num;
658 when 3 =>
659 return (((
660 Character'Pos (Name_Buffer (1))) * 16 +
661 Character'Pos (Name_Buffer (3))) * 16 +
662 Character'Pos (Name_Buffer (2))) mod Hash_Num;
664 when 4 =>
665 return ((((
666 Character'Pos (Name_Buffer (1))) * 8 +
667 Character'Pos (Name_Buffer (2))) * 8 +
668 Character'Pos (Name_Buffer (3))) * 8 +
669 Character'Pos (Name_Buffer (4))) mod Hash_Num;
671 when 5 =>
672 return (((((
673 Character'Pos (Name_Buffer (4))) * 8 +
674 Character'Pos (Name_Buffer (1))) * 4 +
675 Character'Pos (Name_Buffer (3))) * 4 +
676 Character'Pos (Name_Buffer (5))) * 8 +
677 Character'Pos (Name_Buffer (2))) mod Hash_Num;
679 when 6 =>
680 return ((((((
681 Character'Pos (Name_Buffer (5))) * 4 +
682 Character'Pos (Name_Buffer (1))) * 4 +
683 Character'Pos (Name_Buffer (4))) * 4 +
684 Character'Pos (Name_Buffer (2))) * 4 +
685 Character'Pos (Name_Buffer (6))) * 4 +
686 Character'Pos (Name_Buffer (3))) mod Hash_Num;
688 when 7 =>
689 return (((((((
690 Character'Pos (Name_Buffer (4))) * 4 +
691 Character'Pos (Name_Buffer (3))) * 4 +
692 Character'Pos (Name_Buffer (1))) * 4 +
693 Character'Pos (Name_Buffer (2))) * 2 +
694 Character'Pos (Name_Buffer (5))) * 2 +
695 Character'Pos (Name_Buffer (7))) * 2 +
696 Character'Pos (Name_Buffer (6))) mod Hash_Num;
698 when 8 =>
699 return ((((((((
700 Character'Pos (Name_Buffer (2))) * 4 +
701 Character'Pos (Name_Buffer (1))) * 4 +
702 Character'Pos (Name_Buffer (3))) * 2 +
703 Character'Pos (Name_Buffer (5))) * 2 +
704 Character'Pos (Name_Buffer (7))) * 2 +
705 Character'Pos (Name_Buffer (6))) * 2 +
706 Character'Pos (Name_Buffer (4))) * 2 +
707 Character'Pos (Name_Buffer (8))) mod Hash_Num;
709 when 9 =>
710 return (((((((((
711 Character'Pos (Name_Buffer (2))) * 4 +
712 Character'Pos (Name_Buffer (1))) * 4 +
713 Character'Pos (Name_Buffer (3))) * 4 +
714 Character'Pos (Name_Buffer (4))) * 2 +
715 Character'Pos (Name_Buffer (8))) * 2 +
716 Character'Pos (Name_Buffer (7))) * 2 +
717 Character'Pos (Name_Buffer (5))) * 2 +
718 Character'Pos (Name_Buffer (6))) * 2 +
719 Character'Pos (Name_Buffer (9))) mod Hash_Num;
721 when 10 =>
722 return ((((((((((
723 Character'Pos (Name_Buffer (01))) * 2 +
724 Character'Pos (Name_Buffer (02))) * 2 +
725 Character'Pos (Name_Buffer (08))) * 2 +
726 Character'Pos (Name_Buffer (03))) * 2 +
727 Character'Pos (Name_Buffer (04))) * 2 +
728 Character'Pos (Name_Buffer (09))) * 2 +
729 Character'Pos (Name_Buffer (06))) * 2 +
730 Character'Pos (Name_Buffer (05))) * 2 +
731 Character'Pos (Name_Buffer (07))) * 2 +
732 Character'Pos (Name_Buffer (10))) mod Hash_Num;
734 when 11 =>
735 return (((((((((((
736 Character'Pos (Name_Buffer (05))) * 2 +
737 Character'Pos (Name_Buffer (01))) * 2 +
738 Character'Pos (Name_Buffer (06))) * 2 +
739 Character'Pos (Name_Buffer (09))) * 2 +
740 Character'Pos (Name_Buffer (07))) * 2 +
741 Character'Pos (Name_Buffer (03))) * 2 +
742 Character'Pos (Name_Buffer (08))) * 2 +
743 Character'Pos (Name_Buffer (02))) * 2 +
744 Character'Pos (Name_Buffer (10))) * 2 +
745 Character'Pos (Name_Buffer (04))) * 2 +
746 Character'Pos (Name_Buffer (11))) mod Hash_Num;
748 when 12 =>
749 return ((((((((((((
750 Character'Pos (Name_Buffer (03))) * 2 +
751 Character'Pos (Name_Buffer (02))) * 2 +
752 Character'Pos (Name_Buffer (05))) * 2 +
753 Character'Pos (Name_Buffer (01))) * 2 +
754 Character'Pos (Name_Buffer (06))) * 2 +
755 Character'Pos (Name_Buffer (04))) * 2 +
756 Character'Pos (Name_Buffer (08))) * 2 +
757 Character'Pos (Name_Buffer (11))) * 2 +
758 Character'Pos (Name_Buffer (07))) * 2 +
759 Character'Pos (Name_Buffer (09))) * 2 +
760 Character'Pos (Name_Buffer (10))) * 2 +
761 Character'Pos (Name_Buffer (12))) mod Hash_Num;
763 end case;
764 end Hash;
766 ----------------
767 -- Initialize --
768 ----------------
770 procedure Initialize is
772 begin
773 Name_Chars.Init;
774 Name_Entries.Init;
776 -- Initialize entries for one character names
778 for C in Character loop
779 Name_Entries.Increment_Last;
780 Name_Entries.Table (Name_Entries.Last).Name_Chars_Index :=
781 Name_Chars.Last;
782 Name_Entries.Table (Name_Entries.Last).Name_Len := 1;
783 Name_Entries.Table (Name_Entries.Last).Hash_Link := No_Name;
784 Name_Entries.Table (Name_Entries.Last).Int_Info := 0;
785 Name_Entries.Table (Name_Entries.Last).Byte_Info := 0;
786 Name_Chars.Increment_Last;
787 Name_Chars.Table (Name_Chars.Last) := C;
788 Name_Chars.Increment_Last;
789 Name_Chars.Table (Name_Chars.Last) := ASCII.NUL;
790 end loop;
792 -- Clear hash table
794 for J in Hash_Index_Type loop
795 Hash_Table (J) := No_Name;
796 end loop;
797 end Initialize;
799 ----------------------
800 -- Is_Internal_Name --
801 ----------------------
803 function Is_Internal_Name (Id : Name_Id) return Boolean is
804 begin
805 Get_Name_String (Id);
806 return Is_Internal_Name;
807 end Is_Internal_Name;
809 function Is_Internal_Name return Boolean is
810 begin
811 if Name_Buffer (1) = '_'
812 or else Name_Buffer (Name_Len) = '_'
813 then
814 return True;
816 else
817 -- Test backwards, because we only want to test the last entity
818 -- name if the name we have is qualified with other entities.
820 for J in reverse 1 .. Name_Len loop
821 if Is_OK_Internal_Letter (Name_Buffer (J)) then
822 return True;
824 -- Quit if we come to terminating double underscore (note that
825 -- if the current character is an underscore, we know that
826 -- there is a previous character present, since we already
827 -- filtered out the case of Name_Buffer (1) = '_' above.
829 elsif Name_Buffer (J) = '_'
830 and then Name_Buffer (J - 1) = '_'
831 and then Name_Buffer (J - 2) /= '_'
832 then
833 return False;
834 end if;
835 end loop;
836 end if;
838 return False;
839 end Is_Internal_Name;
841 ---------------------------
842 -- Is_OK_Internal_Letter --
843 ---------------------------
845 function Is_OK_Internal_Letter (C : Character) return Boolean is
846 begin
847 return C in 'A' .. 'Z'
848 and then C /= 'O'
849 and then C /= 'Q'
850 and then C /= 'U'
851 and then C /= 'W'
852 and then C /= 'X';
853 end Is_OK_Internal_Letter;
855 --------------------
856 -- Length_Of_Name --
857 --------------------
859 function Length_Of_Name (Id : Name_Id) return Nat is
860 begin
861 return Int (Name_Entries.Table (Id).Name_Len);
862 end Length_Of_Name;
864 ----------
865 -- Lock --
866 ----------
868 procedure Lock is
869 begin
870 Name_Chars.Set_Last (Name_Chars.Last + Name_Chars_Reserve);
871 Name_Entries.Set_Last (Name_Entries.Last + Name_Entries_Reserve);
872 Name_Chars.Locked := True;
873 Name_Entries.Locked := True;
874 Name_Chars.Release;
875 Name_Entries.Release;
876 end Lock;
878 ------------------------
879 -- Name_Chars_Address --
880 ------------------------
882 function Name_Chars_Address return System.Address is
883 begin
884 return Name_Chars.Table (0)'Address;
885 end Name_Chars_Address;
887 ----------------
888 -- Name_Enter --
889 ----------------
891 function Name_Enter return Name_Id is
892 begin
894 Name_Entries.Increment_Last;
895 Name_Entries.Table (Name_Entries.Last).Name_Chars_Index :=
896 Name_Chars.Last;
897 Name_Entries.Table (Name_Entries.Last).Name_Len := Short (Name_Len);
898 Name_Entries.Table (Name_Entries.Last).Hash_Link := No_Name;
899 Name_Entries.Table (Name_Entries.Last).Int_Info := 0;
900 Name_Entries.Table (Name_Entries.Last).Byte_Info := 0;
902 -- Set corresponding string entry in the Name_Chars table
904 for J in 1 .. Name_Len loop
905 Name_Chars.Increment_Last;
906 Name_Chars.Table (Name_Chars.Last) := Name_Buffer (J);
907 end loop;
909 Name_Chars.Increment_Last;
910 Name_Chars.Table (Name_Chars.Last) := ASCII.NUL;
912 return Name_Entries.Last;
913 end Name_Enter;
915 --------------------------
916 -- Name_Entries_Address --
917 --------------------------
919 function Name_Entries_Address return System.Address is
920 begin
921 return Name_Entries.Table (First_Name_Id)'Address;
922 end Name_Entries_Address;
924 ------------------------
925 -- Name_Entries_Count --
926 ------------------------
928 function Name_Entries_Count return Nat is
929 begin
930 return Int (Name_Entries.Last - Name_Entries.First + 1);
931 end Name_Entries_Count;
933 ---------------
934 -- Name_Find --
935 ---------------
937 function Name_Find return Name_Id is
938 New_Id : Name_Id;
939 -- Id of entry in hash search, and value to be returned
941 S : Int;
942 -- Pointer into string table
944 Hash_Index : Hash_Index_Type;
945 -- Computed hash index
947 begin
948 -- Quick handling for one character names
950 if Name_Len = 1 then
951 return Name_Id (First_Name_Id + Character'Pos (Name_Buffer (1)));
953 -- Otherwise search hash table for existing matching entry
955 else
956 Hash_Index := Namet.Hash;
957 New_Id := Hash_Table (Hash_Index);
959 if New_Id = No_Name then
960 Hash_Table (Hash_Index) := Name_Entries.Last + 1;
962 else
963 Search : loop
964 if Name_Len /=
965 Integer (Name_Entries.Table (New_Id).Name_Len)
966 then
967 goto No_Match;
968 end if;
970 S := Name_Entries.Table (New_Id).Name_Chars_Index;
972 for I in 1 .. Name_Len loop
973 if Name_Chars.Table (S + Int (I)) /= Name_Buffer (I) then
974 goto No_Match;
975 end if;
976 end loop;
978 return New_Id;
980 -- Current entry in hash chain does not match
982 <<No_Match>>
983 if Name_Entries.Table (New_Id).Hash_Link /= No_Name then
984 New_Id := Name_Entries.Table (New_Id).Hash_Link;
985 else
986 Name_Entries.Table (New_Id).Hash_Link :=
987 Name_Entries.Last + 1;
988 exit Search;
989 end if;
991 end loop Search;
992 end if;
994 -- We fall through here only if a matching entry was not found in the
995 -- hash table. We now create a new entry in the names table. The hash
996 -- link pointing to the new entry (Name_Entries.Last+1) has been set.
998 Name_Entries.Increment_Last;
999 Name_Entries.Table (Name_Entries.Last).Name_Chars_Index :=
1000 Name_Chars.Last;
1001 Name_Entries.Table (Name_Entries.Last).Name_Len := Short (Name_Len);
1002 Name_Entries.Table (Name_Entries.Last).Hash_Link := No_Name;
1003 Name_Entries.Table (Name_Entries.Last).Int_Info := 0;
1004 Name_Entries.Table (Name_Entries.Last).Byte_Info := 0;
1006 -- Set corresponding string entry in the Name_Chars table
1008 for I in 1 .. Name_Len loop
1009 Name_Chars.Increment_Last;
1010 Name_Chars.Table (Name_Chars.Last) := Name_Buffer (I);
1011 end loop;
1013 Name_Chars.Increment_Last;
1014 Name_Chars.Table (Name_Chars.Last) := ASCII.NUL;
1016 return Name_Entries.Last;
1017 end if;
1018 end Name_Find;
1020 ----------------------
1021 -- Reset_Name_Table --
1022 ----------------------
1024 procedure Reset_Name_Table is
1025 begin
1026 for J in First_Name_Id .. Name_Entries.Last loop
1027 Name_Entries.Table (J).Int_Info := 0;
1028 Name_Entries.Table (J).Byte_Info := 0;
1029 end loop;
1030 end Reset_Name_Table;
1032 --------------------------------
1033 -- Set_Character_Literal_Name --
1034 --------------------------------
1036 procedure Set_Character_Literal_Name (C : Char_Code) is
1037 begin
1038 Name_Buffer (1) := 'Q';
1039 Name_Len := 1;
1040 Store_Encoded_Character (C);
1041 end Set_Character_Literal_Name;
1043 -------------------------
1044 -- Set_Name_Table_Byte --
1045 -------------------------
1047 procedure Set_Name_Table_Byte (Id : Name_Id; Val : Byte) is
1048 begin
1049 pragma Assert (Id in Name_Entries.First .. Name_Entries.Last);
1050 Name_Entries.Table (Id).Byte_Info := Val;
1051 end Set_Name_Table_Byte;
1053 -------------------------
1054 -- Set_Name_Table_Info --
1055 -------------------------
1057 procedure Set_Name_Table_Info (Id : Name_Id; Val : Int) is
1058 begin
1059 pragma Assert (Id in Name_Entries.First .. Name_Entries.Last);
1060 Name_Entries.Table (Id).Int_Info := Val;
1061 end Set_Name_Table_Info;
1063 -----------------------------
1064 -- Store_Encoded_Character --
1065 -----------------------------
1067 procedure Store_Encoded_Character (C : Char_Code) is
1069 procedure Set_Hex_Chars (N : Natural);
1070 -- Stores given value, which is in the range 0 .. 255, as two hex
1071 -- digits (using lower case a-f) in Name_Buffer, incrementing Name_Len
1073 procedure Set_Hex_Chars (N : Natural) is
1074 Hexd : constant String := "0123456789abcdef";
1076 begin
1077 Name_Buffer (Name_Len + 1) := Hexd (N / 16 + 1);
1078 Name_Buffer (Name_Len + 2) := Hexd (N mod 16 + 1);
1079 Name_Len := Name_Len + 2;
1080 end Set_Hex_Chars;
1082 begin
1083 Name_Len := Name_Len + 1;
1085 if In_Character_Range (C) then
1086 declare
1087 CC : constant Character := Get_Character (C);
1089 begin
1090 if CC in 'a' .. 'z' or else CC in '0' .. '9' then
1091 Name_Buffer (Name_Len) := CC;
1093 else
1094 Name_Buffer (Name_Len) := 'U';
1095 Set_Hex_Chars (Natural (C));
1096 end if;
1097 end;
1099 else
1100 Name_Buffer (Name_Len) := 'W';
1101 Set_Hex_Chars (Natural (C) / 256);
1102 Set_Hex_Chars (Natural (C) mod 256);
1103 end if;
1105 end Store_Encoded_Character;
1107 --------------------------------------
1108 -- Strip_Qualification_And_Suffixes --
1109 --------------------------------------
1111 procedure Strip_Qualification_And_Suffixes is
1112 J : Integer;
1114 begin
1115 -- Strip package body qualification string off end
1117 for J in reverse 2 .. Name_Len loop
1118 if Name_Buffer (J) = 'X' then
1119 Name_Len := J - 1;
1120 exit;
1121 end if;
1123 exit when Name_Buffer (J) /= 'b'
1124 and then Name_Buffer (J) /= 'n'
1125 and then Name_Buffer (J) /= 'p';
1126 end loop;
1128 -- Find rightmost __ or $ separator if one exists
1130 J := Name_Len - 1;
1131 while J > 1 loop
1133 -- If $ separator, homonym separator, so strip it and keep looking
1135 if Name_Buffer (J) = '$' then
1136 Name_Len := J - 1;
1137 J := Name_Len - 1;
1139 -- Else check for __ found
1141 elsif Name_Buffer (J) = '_' and then Name_Buffer (J + 1) = '_' then
1143 -- Found __ so see if digit follows, and if so, this is a
1144 -- homonym separator, so strip it and keep looking.
1146 if Name_Buffer (J + 2) in '0' .. '9' then
1147 Name_Len := J - 1;
1148 J := Name_Len - 1;
1150 -- If not a homonym separator, then we simply strip the
1151 -- separator and everything that precedes it, and we are done
1153 else
1154 Name_Buffer (1 .. Name_Len - J - 1) :=
1155 Name_Buffer (J + 2 .. Name_Len);
1156 Name_Len := Name_Len - J - 1;
1157 exit;
1158 end if;
1160 else
1161 J := J - 1;
1162 end if;
1163 end loop;
1164 end Strip_Qualification_And_Suffixes;
1166 ---------------
1167 -- Tree_Read --
1168 ---------------
1170 procedure Tree_Read is
1171 begin
1172 Name_Chars.Tree_Read;
1173 Name_Entries.Tree_Read;
1175 Tree_Read_Data
1176 (Hash_Table'Address,
1177 Hash_Table'Length * (Hash_Table'Component_Size / Storage_Unit));
1178 end Tree_Read;
1180 ----------------
1181 -- Tree_Write --
1182 ----------------
1184 procedure Tree_Write is
1185 begin
1186 Name_Chars.Tree_Write;
1187 Name_Entries.Tree_Write;
1189 Tree_Write_Data
1190 (Hash_Table'Address,
1191 Hash_Table'Length * (Hash_Table'Component_Size / Storage_Unit));
1192 end Tree_Write;
1194 ------------
1195 -- Unlock --
1196 ------------
1198 procedure Unlock is
1199 begin
1200 Name_Chars.Set_Last (Name_Chars.Last - Name_Chars_Reserve);
1201 Name_Entries.Set_Last (Name_Entries.Last - Name_Entries_Reserve);
1202 Name_Chars.Locked := False;
1203 Name_Entries.Locked := False;
1204 Name_Chars.Release;
1205 Name_Entries.Release;
1206 end Unlock;
1208 --------
1209 -- wn --
1210 --------
1212 procedure wn (Id : Name_Id) is
1213 begin
1214 Write_Name (Id);
1215 Write_Eol;
1216 end wn;
1218 ----------------
1219 -- Write_Name --
1220 ----------------
1222 procedure Write_Name (Id : Name_Id) is
1223 begin
1224 if Id >= First_Name_Id then
1225 Get_Name_String (Id);
1226 Write_Str (Name_Buffer (1 .. Name_Len));
1227 end if;
1228 end Write_Name;
1230 ------------------------
1231 -- Write_Name_Decoded --
1232 ------------------------
1234 procedure Write_Name_Decoded (Id : Name_Id) is
1235 begin
1236 if Id >= First_Name_Id then
1237 Get_Decoded_Name_String (Id);
1238 Write_Str (Name_Buffer (1 .. Name_Len));
1239 end if;
1240 end Write_Name_Decoded;
1242 end Namet;