PR c++/79377
[official-gcc.git] / gcc / ada / uname.adb
blobc879cbbdee200174862b38bed225d9ece66e6a38
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT COMPILER COMPONENTS --
4 -- --
5 -- U N A M E --
6 -- --
7 -- B o d y --
8 -- --
9 -- Copyright (C) 1992-2016, Free Software Foundation, Inc. --
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 3, 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. --
17 -- --
18 -- As a special exception under Section 7 of GPL version 3, you are granted --
19 -- additional permissions described in the GCC Runtime Library Exception, --
20 -- version 3.1, as published by the Free Software Foundation. --
21 -- --
22 -- You should have received a copy of the GNU General Public License and --
23 -- a copy of the GCC Runtime Library Exception along with this program; --
24 -- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
25 -- <http://www.gnu.org/licenses/>. --
26 -- --
27 -- GNAT was originally developed by the GNAT team at New York University. --
28 -- Extensive contributions were provided by Ada Core Technologies Inc. --
29 -- --
30 ------------------------------------------------------------------------------
32 with Atree; use Atree;
33 with Casing; use Casing;
34 with Einfo; use Einfo;
35 with Hostparm;
36 with Lib; use Lib;
37 with Nlists; use Nlists;
38 with Output; use Output;
39 with Sinfo; use Sinfo;
40 with Sinput; use Sinput;
42 package body Uname is
44 -------------------
45 -- Get_Body_Name --
46 -------------------
48 function Get_Body_Name (N : Unit_Name_Type) return Unit_Name_Type is
49 begin
50 Get_Name_String (N);
52 pragma Assert (Name_Len > 2
53 and then Name_Buffer (Name_Len - 1) = '%'
54 and then Name_Buffer (Name_Len) = 's');
56 Name_Buffer (Name_Len) := 'b';
57 return Name_Find;
58 end Get_Body_Name;
60 -----------------------------------
61 -- Get_External_Unit_Name_String --
62 -----------------------------------
64 procedure Get_External_Unit_Name_String (N : Unit_Name_Type) is
65 Pcount : Natural;
66 Newlen : Natural;
68 begin
69 -- Get unit name and eliminate trailing %s or %b
71 Get_Name_String (N);
72 Name_Len := Name_Len - 2;
74 -- Find number of components
76 Pcount := 0;
77 for J in 1 .. Name_Len loop
78 if Name_Buffer (J) = '.' then
79 Pcount := Pcount + 1;
80 end if;
81 end loop;
83 -- If simple name, nothing to do
85 if Pcount = 0 then
86 return;
87 end if;
89 -- If name has multiple components, replace dots by double underscore
91 Newlen := Name_Len + Pcount;
93 for J in reverse 1 .. Name_Len loop
94 if Name_Buffer (J) = '.' then
95 Name_Buffer (Newlen) := '_';
96 Name_Buffer (Newlen - 1) := '_';
97 Newlen := Newlen - 2;
99 else
100 Name_Buffer (Newlen) := Name_Buffer (J);
101 Newlen := Newlen - 1;
102 end if;
103 end loop;
105 Name_Len := Name_Len + Pcount;
106 end Get_External_Unit_Name_String;
108 --------------------------
109 -- Get_Parent_Body_Name --
110 --------------------------
112 function Get_Parent_Body_Name (N : Unit_Name_Type) return Unit_Name_Type is
113 begin
114 Get_Name_String (N);
116 while Name_Buffer (Name_Len) /= '.' loop
117 pragma Assert (Name_Len > 1); -- not a child or subunit name
118 Name_Len := Name_Len - 1;
119 end loop;
121 Name_Buffer (Name_Len) := '%';
122 Name_Len := Name_Len + 1;
123 Name_Buffer (Name_Len) := 'b';
124 return Name_Find;
126 end Get_Parent_Body_Name;
128 --------------------------
129 -- Get_Parent_Spec_Name --
130 --------------------------
132 function Get_Parent_Spec_Name (N : Unit_Name_Type) return Unit_Name_Type is
133 begin
134 Get_Name_String (N);
136 while Name_Buffer (Name_Len) /= '.' loop
137 if Name_Len = 1 then
138 return No_Unit_Name;
139 else
140 Name_Len := Name_Len - 1;
141 end if;
142 end loop;
144 Name_Buffer (Name_Len) := '%';
145 Name_Len := Name_Len + 1;
146 Name_Buffer (Name_Len) := 's';
147 return Name_Find;
149 end Get_Parent_Spec_Name;
151 -------------------
152 -- Get_Spec_Name --
153 -------------------
155 function Get_Spec_Name (N : Unit_Name_Type) return Unit_Name_Type is
156 begin
157 Get_Name_String (N);
159 pragma Assert (Name_Len > 2
160 and then Name_Buffer (Name_Len - 1) = '%'
161 and then Name_Buffer (Name_Len) = 'b');
163 Name_Buffer (Name_Len) := 's';
164 return Name_Find;
165 end Get_Spec_Name;
167 -------------------
168 -- Get_Unit_Name --
169 -------------------
171 function Get_Unit_Name (N : Node_Id) return Unit_Name_Type is
173 Unit_Name_Buffer : String (1 .. Hostparm.Max_Name_Length);
174 -- Buffer used to build name of unit. Note that we cannot use the
175 -- Name_Buffer in package Name_Table because we use it to read
176 -- component names.
178 Unit_Name_Length : Natural := 0;
179 -- Length of name stored in Unit_Name_Buffer
181 Node : Node_Id;
182 -- Program unit node
184 procedure Add_Char (C : Character);
185 -- Add a single character to stored unit name
187 procedure Add_Name (Name : Name_Id);
188 -- Add the characters of a names table entry to stored unit name
190 procedure Add_Node_Name (Node : Node_Id);
191 -- Recursive procedure adds characters associated with Node
193 function Get_Parent (Node : Node_Id) return Node_Id;
194 -- Get parent compilation unit of a stub
196 --------------
197 -- Add_Char --
198 --------------
200 procedure Add_Char (C : Character) is
201 begin
202 -- Should really check for max length exceeded here???
203 Unit_Name_Length := Unit_Name_Length + 1;
204 Unit_Name_Buffer (Unit_Name_Length) := C;
205 end Add_Char;
207 --------------
208 -- Add_Name --
209 --------------
211 procedure Add_Name (Name : Name_Id) is
212 begin
213 Get_Name_String (Name);
215 for J in 1 .. Name_Len loop
216 Add_Char (Name_Buffer (J));
217 end loop;
218 end Add_Name;
220 -------------------
221 -- Add_Node_Name --
222 -------------------
224 procedure Add_Node_Name (Node : Node_Id) is
225 Kind : constant Node_Kind := Nkind (Node);
227 begin
228 -- Just ignore an error node (someone else will give a message)
230 if Node = Error then
231 return;
233 -- Otherwise see what kind of node we have
235 else
236 case Kind is
237 when N_Defining_Identifier
238 | N_Defining_Operator_Symbol
239 | N_Identifier
241 -- Note: it is of course an error to have a defining
242 -- operator symbol at this point, but this is not where
243 -- the error is signalled, so we handle it nicely here.
245 Add_Name (Chars (Node));
247 when N_Defining_Program_Unit_Name =>
248 Add_Node_Name (Name (Node));
249 Add_Char ('.');
250 Add_Node_Name (Defining_Identifier (Node));
252 when N_Expanded_Name
253 | N_Selected_Component
255 Add_Node_Name (Prefix (Node));
256 Add_Char ('.');
257 Add_Node_Name (Selector_Name (Node));
259 when N_Package_Specification
260 | N_Subprogram_Specification
262 Add_Node_Name (Defining_Unit_Name (Node));
264 when N_Generic_Declaration
265 | N_Package_Declaration
266 | N_Subprogram_Body
267 | N_Subprogram_Declaration
269 Add_Node_Name (Specification (Node));
271 when N_Generic_Instantiation =>
272 Add_Node_Name (Defining_Unit_Name (Node));
274 when N_Package_Body =>
275 Add_Node_Name (Defining_Unit_Name (Node));
277 when N_Protected_Body
278 | N_Task_Body
280 Add_Node_Name (Defining_Identifier (Node));
282 when N_Package_Renaming_Declaration =>
283 Add_Node_Name (Defining_Unit_Name (Node));
285 when N_Subprogram_Renaming_Declaration =>
286 Add_Node_Name (Specification (Node));
288 when N_Generic_Renaming_Declaration =>
289 Add_Node_Name (Defining_Unit_Name (Node));
291 when N_Subprogram_Body_Stub =>
292 Add_Node_Name (Get_Parent (Node));
293 Add_Char ('.');
294 Add_Node_Name (Specification (Node));
296 when N_Compilation_Unit =>
297 Add_Node_Name (Unit (Node));
299 when N_Package_Body_Stub =>
300 Add_Node_Name (Get_Parent (Node));
301 Add_Char ('.');
302 Add_Node_Name (Defining_Identifier (Node));
304 when N_Protected_Body_Stub
305 | N_Task_Body_Stub
307 Add_Node_Name (Get_Parent (Node));
308 Add_Char ('.');
309 Add_Node_Name (Defining_Identifier (Node));
311 when N_Subunit =>
312 Add_Node_Name (Name (Node));
313 Add_Char ('.');
314 Add_Node_Name (Proper_Body (Node));
316 when N_With_Clause =>
317 Add_Node_Name (Name (Node));
319 when N_Pragma =>
320 Add_Node_Name (Expression (First
321 (Pragma_Argument_Associations (Node))));
323 -- Tasks and protected stuff appear only in an error context,
324 -- but the error has been posted elsewhere, so we deal nicely
325 -- with these error situations here, and produce a reasonable
326 -- unit name using the defining identifier.
328 when N_Protected_Type_Declaration
329 | N_Single_Protected_Declaration
330 | N_Single_Task_Declaration
331 | N_Task_Type_Declaration
333 Add_Node_Name (Defining_Identifier (Node));
335 when others =>
336 raise Program_Error;
337 end case;
338 end if;
339 end Add_Node_Name;
341 ----------------
342 -- Get_Parent --
343 ----------------
345 function Get_Parent (Node : Node_Id) return Node_Id is
346 N : Node_Id := Node;
348 begin
349 while Nkind (N) /= N_Compilation_Unit loop
350 N := Parent (N);
351 end loop;
353 return N;
354 end Get_Parent;
356 -- Start of processing for Get_Unit_Name
358 begin
359 Node := N;
361 -- If we have Defining_Identifier, find the associated unit node
363 if Nkind (Node) = N_Defining_Identifier then
364 Node := Declaration_Node (Node);
366 -- If an expanded name, it is an already analyzed child unit, find
367 -- unit node.
369 elsif Nkind (Node) = N_Expanded_Name then
370 Node := Declaration_Node (Entity (Node));
371 end if;
373 if Nkind (Node) = N_Package_Specification
374 or else Nkind (Node) in N_Subprogram_Specification
375 then
376 Node := Parent (Node);
377 end if;
379 -- Node points to the unit, so get its name and add proper suffix
381 Add_Node_Name (Node);
382 Add_Char ('%');
384 case Nkind (Node) is
385 when N_Generic_Declaration
386 | N_Generic_Instantiation
387 | N_Generic_Renaming_Declaration
388 | N_Package_Declaration
389 | N_Package_Renaming_Declaration
390 | N_Pragma
391 | N_Protected_Type_Declaration
392 | N_Single_Protected_Declaration
393 | N_Single_Task_Declaration
394 | N_Subprogram_Declaration
395 | N_Subprogram_Renaming_Declaration
396 | N_Task_Type_Declaration
397 | N_With_Clause
399 Add_Char ('s');
401 when N_Body_Stub
402 | N_Identifier
403 | N_Package_Body
404 | N_Protected_Body
405 | N_Selected_Component
406 | N_Subprogram_Body
407 | N_Subunit
408 | N_Task_Body
410 Add_Char ('b');
412 when others =>
413 raise Program_Error;
414 end case;
416 Name_Buffer (1 .. Unit_Name_Length) :=
417 Unit_Name_Buffer (1 .. Unit_Name_Length);
418 Name_Len := Unit_Name_Length;
419 return Name_Find;
421 end Get_Unit_Name;
423 --------------------------
424 -- Get_Unit_Name_String --
425 --------------------------
427 procedure Get_Unit_Name_String
428 (N : Unit_Name_Type;
429 Suffix : Boolean := True)
431 Unit_Is_Body : Boolean;
433 begin
434 Get_Decoded_Name_String (N);
435 Unit_Is_Body := Name_Buffer (Name_Len) = 'b';
436 Set_Casing (Identifier_Casing (Source_Index (Main_Unit)));
438 -- A special fudge, normally we don't have operator symbols present,
439 -- since it is always an error to do so. However, if we do, at this
440 -- stage it has the form:
442 -- "and"
444 -- and the %s or %b has already been eliminated so put 2 chars back
446 if Name_Buffer (1) = '"' then
447 Name_Len := Name_Len + 2;
448 end if;
450 -- Now adjust the %s or %b to (spec) or (body)
452 if Suffix then
453 if Unit_Is_Body then
454 Name_Buffer (Name_Len - 1 .. Name_Len + 5) := " (body)";
455 else
456 Name_Buffer (Name_Len - 1 .. Name_Len + 5) := " (spec)";
457 end if;
458 end if;
460 for J in 1 .. Name_Len loop
461 if Name_Buffer (J) = '-' then
462 Name_Buffer (J) := '.';
463 end if;
464 end loop;
466 -- Adjust Name_Len
468 if Suffix then
469 Name_Len := Name_Len + (7 - 2);
470 else
471 Name_Len := Name_Len - 2;
472 end if;
473 end Get_Unit_Name_String;
475 ------------------
476 -- Is_Body_Name --
477 ------------------
479 function Is_Body_Name (N : Unit_Name_Type) return Boolean is
480 begin
481 Get_Name_String (N);
482 return Name_Len > 2
483 and then Name_Buffer (Name_Len - 1) = '%'
484 and then Name_Buffer (Name_Len) = 'b';
485 end Is_Body_Name;
487 -------------------
488 -- Is_Child_Name --
489 -------------------
491 function Is_Child_Name (N : Unit_Name_Type) return Boolean is
492 J : Natural;
494 begin
495 Get_Name_String (N);
496 J := Name_Len;
498 while Name_Buffer (J) /= '.' loop
499 if J = 1 then
500 return False; -- not a child or subunit name
501 else
502 J := J - 1;
503 end if;
504 end loop;
506 return True;
507 end Is_Child_Name;
509 ------------------
510 -- Is_Spec_Name --
511 ------------------
513 function Is_Spec_Name (N : Unit_Name_Type) return Boolean is
514 begin
515 Get_Name_String (N);
516 return Name_Len > 2
517 and then Name_Buffer (Name_Len - 1) = '%'
518 and then Name_Buffer (Name_Len) = 's';
519 end Is_Spec_Name;
521 -----------------------
522 -- Name_To_Unit_Name --
523 -----------------------
525 function Name_To_Unit_Name (N : Name_Id) return Unit_Name_Type is
526 begin
527 Get_Name_String (N);
528 Name_Buffer (Name_Len + 1) := '%';
529 Name_Buffer (Name_Len + 2) := 's';
530 Name_Len := Name_Len + 2;
531 return Name_Find;
532 end Name_To_Unit_Name;
534 ---------------
535 -- New_Child --
536 ---------------
538 function New_Child
539 (Old : Unit_Name_Type;
540 Newp : Unit_Name_Type) return Unit_Name_Type
542 P : Natural;
544 begin
545 Get_Name_String (Old);
547 declare
548 Child : constant String := Name_Buffer (1 .. Name_Len);
550 begin
551 Get_Name_String (Newp);
552 Name_Len := Name_Len - 2;
554 P := Child'Last;
555 while Child (P) /= '.' loop
556 P := P - 1;
557 end loop;
559 while P <= Child'Last loop
560 Name_Len := Name_Len + 1;
561 Name_Buffer (Name_Len) := Child (P);
562 P := P + 1;
563 end loop;
565 return Name_Find;
566 end;
567 end New_Child;
569 --------------
570 -- Uname_Ge --
571 --------------
573 function Uname_Ge (Left, Right : Unit_Name_Type) return Boolean is
574 begin
575 return Left = Right or else Uname_Gt (Left, Right);
576 end Uname_Ge;
578 --------------
579 -- Uname_Gt --
580 --------------
582 function Uname_Gt (Left, Right : Unit_Name_Type) return Boolean is
583 begin
584 return Left /= Right and then not Uname_Lt (Left, Right);
585 end Uname_Gt;
587 --------------
588 -- Uname_Le --
589 --------------
591 function Uname_Le (Left, Right : Unit_Name_Type) return Boolean is
592 begin
593 return Left = Right or else Uname_Lt (Left, Right);
594 end Uname_Le;
596 --------------
597 -- Uname_Lt --
598 --------------
600 function Uname_Lt (Left, Right : Unit_Name_Type) return Boolean is
601 Left_Name : String (1 .. Hostparm.Max_Name_Length);
602 Left_Length : Natural;
603 Right_Name : String renames Name_Buffer;
604 Right_Length : Natural renames Name_Len;
605 J : Natural;
607 begin
608 pragma Warnings (Off, Right_Length);
609 -- Suppress warnings on Right_Length, used in pragma Assert
611 if Left = Right then
612 return False;
613 end if;
615 Get_Name_String (Left);
616 Left_Name (1 .. Name_Len + 1) := Name_Buffer (1 .. Name_Len + 1);
617 Left_Length := Name_Len;
618 Get_Name_String (Right);
619 J := 1;
621 loop
622 exit when Left_Name (J) = '%';
624 if Right_Name (J) = '%' then
625 return False; -- left name is longer
626 end if;
628 pragma Assert (J <= Left_Length and then J <= Right_Length);
630 if Left_Name (J) /= Right_Name (J) then
631 return Left_Name (J) < Right_Name (J); -- parent names different
632 end if;
634 J := J + 1;
635 end loop;
637 -- Come here pointing to % in left name
639 if Right_Name (J) /= '%' then
640 return True; -- right name is longer
641 end if;
643 -- Here the parent names are the same and specs sort low. If neither is
644 -- a spec, then we are comparing the same name and we want a result of
645 -- False in any case.
647 return Left_Name (J + 1) = 's';
648 end Uname_Lt;
650 ---------------------
651 -- Write_Unit_Name --
652 ---------------------
654 procedure Write_Unit_Name (N : Unit_Name_Type) is
655 begin
656 Get_Unit_Name_String (N);
657 Write_Str (Name_Buffer (1 .. Name_Len));
658 end Write_Unit_Name;
660 end Uname;