1------------------------------------------------------------------------------ 2-- -- 3-- GNAT COMPILER COMPONENTS -- 4-- -- 5-- U N A M E -- 6-- -- 7-- B o d y -- 8-- -- 9-- Copyright (C) 1992-2013, 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------------------------------------------------------------------------------ 31 32with Atree; use Atree; 33with Casing; use Casing; 34with Einfo; use Einfo; 35with Hostparm; 36with Lib; use Lib; 37with Nlists; use Nlists; 38with Output; use Output; 39with Sinfo; use Sinfo; 40with Sinput; use Sinput; 41 42package body Uname is 43 44 ------------------- 45 -- Get_Body_Name -- 46 ------------------- 47 48 function Get_Body_Name (N : Unit_Name_Type) return Unit_Name_Type is 49 begin 50 Get_Name_String (N); 51 52 pragma Assert (Name_Len > 2 53 and then Name_Buffer (Name_Len - 1) = '%' 54 and then Name_Buffer (Name_Len) = 's'); 55 56 Name_Buffer (Name_Len) := 'b'; 57 return Name_Find; 58 end Get_Body_Name; 59 60 ----------------------------------- 61 -- Get_External_Unit_Name_String -- 62 ----------------------------------- 63 64 procedure Get_External_Unit_Name_String (N : Unit_Name_Type) is 65 Pcount : Natural; 66 Newlen : Natural; 67 68 begin 69 -- Get unit name and eliminate trailing %s or %b 70 71 Get_Name_String (N); 72 Name_Len := Name_Len - 2; 73 74 -- Find number of components 75 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; 82 83 -- If simple name, nothing to do 84 85 if Pcount = 0 then 86 return; 87 end if; 88 89 -- If name has multiple components, replace dots by double underscore 90 91 Newlen := Name_Len + Pcount; 92 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; 98 99 else 100 Name_Buffer (Newlen) := Name_Buffer (J); 101 Newlen := Newlen - 1; 102 end if; 103 end loop; 104 105 Name_Len := Name_Len + Pcount; 106 end Get_External_Unit_Name_String; 107 108 -------------------------- 109 -- Get_Parent_Body_Name -- 110 -------------------------- 111 112 function Get_Parent_Body_Name (N : Unit_Name_Type) return Unit_Name_Type is 113 begin 114 Get_Name_String (N); 115 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; 120 121 Name_Buffer (Name_Len) := '%'; 122 Name_Len := Name_Len + 1; 123 Name_Buffer (Name_Len) := 'b'; 124 return Name_Find; 125 126 end Get_Parent_Body_Name; 127 128 -------------------------- 129 -- Get_Parent_Spec_Name -- 130 -------------------------- 131 132 function Get_Parent_Spec_Name (N : Unit_Name_Type) return Unit_Name_Type is 133 begin 134 Get_Name_String (N); 135 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; 143 144 Name_Buffer (Name_Len) := '%'; 145 Name_Len := Name_Len + 1; 146 Name_Buffer (Name_Len) := 's'; 147 return Name_Find; 148 149 end Get_Parent_Spec_Name; 150 151 ------------------- 152 -- Get_Spec_Name -- 153 ------------------- 154 155 function Get_Spec_Name (N : Unit_Name_Type) return Unit_Name_Type is 156 begin 157 Get_Name_String (N); 158 159 pragma Assert (Name_Len > 2 160 and then Name_Buffer (Name_Len - 1) = '%' 161 and then Name_Buffer (Name_Len) = 'b'); 162 163 Name_Buffer (Name_Len) := 's'; 164 return Name_Find; 165 end Get_Spec_Name; 166 167 ------------------- 168 -- Get_Unit_Name -- 169 ------------------- 170 171 function Get_Unit_Name (N : Node_Id) return Unit_Name_Type is 172 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. 177 178 Unit_Name_Length : Natural := 0; 179 -- Length of name stored in Unit_Name_Buffer 180 181 Node : Node_Id; 182 -- Program unit node 183 184 procedure Add_Char (C : Character); 185 -- Add a single character to stored unit name 186 187 procedure Add_Name (Name : Name_Id); 188 -- Add the characters of a names table entry to stored unit name 189 190 procedure Add_Node_Name (Node : Node_Id); 191 -- Recursive procedure adds characters associated with Node 192 193 function Get_Parent (Node : Node_Id) return Node_Id; 194 -- Get parent compilation unit of a stub 195 196 -------------- 197 -- Add_Char -- 198 -------------- 199 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; 206 207 -------------- 208 -- Add_Name -- 209 -------------- 210 211 procedure Add_Name (Name : Name_Id) is 212 begin 213 Get_Name_String (Name); 214 215 for J in 1 .. Name_Len loop 216 Add_Char (Name_Buffer (J)); 217 end loop; 218 end Add_Name; 219 220 ------------------- 221 -- Add_Node_Name -- 222 ------------------- 223 224 procedure Add_Node_Name (Node : Node_Id) is 225 Kind : constant Node_Kind := Nkind (Node); 226 227 begin 228 -- Just ignore an error node (someone else will give a message) 229 230 if Node = Error then 231 return; 232 233 -- Otherwise see what kind of node we have 234 235 else 236 case Kind is 237 238 when N_Identifier | 239 N_Defining_Identifier | 240 N_Defining_Operator_Symbol => 241 242 -- Note: it is of course an error to have a defining 243 -- operator symbol at this point, but this is not where 244 -- the error is signalled, so we handle it nicely here. 245 246 Add_Name (Chars (Node)); 247 248 when N_Defining_Program_Unit_Name => 249 Add_Node_Name (Name (Node)); 250 Add_Char ('.'); 251 Add_Node_Name (Defining_Identifier (Node)); 252 253 when N_Selected_Component | 254 N_Expanded_Name => 255 Add_Node_Name (Prefix (Node)); 256 Add_Char ('.'); 257 Add_Node_Name (Selector_Name (Node)); 258 259 when N_Subprogram_Specification | 260 N_Package_Specification => 261 Add_Node_Name (Defining_Unit_Name (Node)); 262 263 when N_Subprogram_Body | 264 N_Subprogram_Declaration | 265 N_Package_Declaration | 266 N_Generic_Declaration => 267 Add_Node_Name (Specification (Node)); 268 269 when N_Generic_Instantiation => 270 Add_Node_Name (Defining_Unit_Name (Node)); 271 272 when N_Package_Body => 273 Add_Node_Name (Defining_Unit_Name (Node)); 274 275 when N_Task_Body | 276 N_Protected_Body => 277 Add_Node_Name (Defining_Identifier (Node)); 278 279 when N_Package_Renaming_Declaration => 280 Add_Node_Name (Defining_Unit_Name (Node)); 281 282 when N_Subprogram_Renaming_Declaration => 283 Add_Node_Name (Specification (Node)); 284 285 when N_Generic_Renaming_Declaration => 286 Add_Node_Name (Defining_Unit_Name (Node)); 287 288 when N_Subprogram_Body_Stub => 289 Add_Node_Name (Get_Parent (Node)); 290 Add_Char ('.'); 291 Add_Node_Name (Specification (Node)); 292 293 when N_Compilation_Unit => 294 Add_Node_Name (Unit (Node)); 295 296 when N_Package_Body_Stub => 297 Add_Node_Name (Get_Parent (Node)); 298 Add_Char ('.'); 299 Add_Node_Name (Defining_Identifier (Node)); 300 301 when N_Task_Body_Stub | 302 N_Protected_Body_Stub => 303 Add_Node_Name (Get_Parent (Node)); 304 Add_Char ('.'); 305 Add_Node_Name (Defining_Identifier (Node)); 306 307 when N_Subunit => 308 Add_Node_Name (Name (Node)); 309 Add_Char ('.'); 310 Add_Node_Name (Proper_Body (Node)); 311 312 when N_With_Clause => 313 Add_Node_Name (Name (Node)); 314 315 when N_Pragma => 316 Add_Node_Name (Expression (First 317 (Pragma_Argument_Associations (Node)))); 318 319 -- Tasks and protected stuff appear only in an error context, 320 -- but the error has been posted elsewhere, so we deal nicely 321 -- with these error situations here, and produce a reasonable 322 -- unit name using the defining identifier. 323 324 when N_Task_Type_Declaration | 325 N_Single_Task_Declaration | 326 N_Protected_Type_Declaration | 327 N_Single_Protected_Declaration => 328 Add_Node_Name (Defining_Identifier (Node)); 329 330 when others => 331 raise Program_Error; 332 333 end case; 334 end if; 335 end Add_Node_Name; 336 337 ---------------- 338 -- Get_Parent -- 339 ---------------- 340 341 function Get_Parent (Node : Node_Id) return Node_Id is 342 N : Node_Id := Node; 343 344 begin 345 while Nkind (N) /= N_Compilation_Unit loop 346 N := Parent (N); 347 end loop; 348 349 return N; 350 end Get_Parent; 351 352 -- Start of processing for Get_Unit_Name 353 354 begin 355 Node := N; 356 357 -- If we have Defining_Identifier, find the associated unit node 358 359 if Nkind (Node) = N_Defining_Identifier then 360 Node := Declaration_Node (Node); 361 362 -- If an expanded name, it is an already analyzed child unit, find 363 -- unit node. 364 365 elsif Nkind (Node) = N_Expanded_Name then 366 Node := Declaration_Node (Entity (Node)); 367 end if; 368 369 if Nkind (Node) = N_Package_Specification 370 or else Nkind (Node) in N_Subprogram_Specification 371 then 372 Node := Parent (Node); 373 end if; 374 375 -- Node points to the unit, so get its name and add proper suffix 376 377 Add_Node_Name (Node); 378 Add_Char ('%'); 379 380 case Nkind (Node) is 381 when N_Generic_Declaration | 382 N_Subprogram_Declaration | 383 N_Package_Declaration | 384 N_With_Clause | 385 N_Pragma | 386 N_Generic_Instantiation | 387 N_Package_Renaming_Declaration | 388 N_Subprogram_Renaming_Declaration | 389 N_Generic_Renaming_Declaration | 390 N_Single_Task_Declaration | 391 N_Single_Protected_Declaration | 392 N_Task_Type_Declaration | 393 N_Protected_Type_Declaration => 394 395 Add_Char ('s'); 396 397 when N_Subprogram_Body | 398 N_Package_Body | 399 N_Subunit | 400 N_Body_Stub | 401 N_Task_Body | 402 N_Protected_Body | 403 N_Identifier | 404 N_Selected_Component => 405 406 Add_Char ('b'); 407 408 when others => 409 raise Program_Error; 410 end case; 411 412 Name_Buffer (1 .. Unit_Name_Length) := 413 Unit_Name_Buffer (1 .. Unit_Name_Length); 414 Name_Len := Unit_Name_Length; 415 return Name_Find; 416 417 end Get_Unit_Name; 418 419 -------------------------- 420 -- Get_Unit_Name_String -- 421 -------------------------- 422 423 procedure Get_Unit_Name_String 424 (N : Unit_Name_Type; 425 Suffix : Boolean := True) 426 is 427 Unit_Is_Body : Boolean; 428 429 begin 430 Get_Decoded_Name_String (N); 431 Unit_Is_Body := Name_Buffer (Name_Len) = 'b'; 432 Set_Casing (Identifier_Casing (Source_Index (Main_Unit)), Mixed_Case); 433 434 -- A special fudge, normally we don't have operator symbols present, 435 -- since it is always an error to do so. However, if we do, at this 436 -- stage it has the form: 437 438 -- "and" 439 440 -- and the %s or %b has already been eliminated so put 2 chars back 441 442 if Name_Buffer (1) = '"' then 443 Name_Len := Name_Len + 2; 444 end if; 445 446 -- Now adjust the %s or %b to (spec) or (body) 447 448 if Suffix then 449 if Unit_Is_Body then 450 Name_Buffer (Name_Len - 1 .. Name_Len + 5) := " (body)"; 451 else 452 Name_Buffer (Name_Len - 1 .. Name_Len + 5) := " (spec)"; 453 end if; 454 end if; 455 456 for J in 1 .. Name_Len loop 457 if Name_Buffer (J) = '-' then 458 Name_Buffer (J) := '.'; 459 end if; 460 end loop; 461 462 -- Adjust Name_Len 463 464 if Suffix then 465 Name_Len := Name_Len + (7 - 2); 466 else 467 Name_Len := Name_Len - 2; 468 end if; 469 end Get_Unit_Name_String; 470 471 ------------------ 472 -- Is_Body_Name -- 473 ------------------ 474 475 function Is_Body_Name (N : Unit_Name_Type) return Boolean is 476 begin 477 Get_Name_String (N); 478 return Name_Len > 2 479 and then Name_Buffer (Name_Len - 1) = '%' 480 and then Name_Buffer (Name_Len) = 'b'; 481 end Is_Body_Name; 482 483 ------------------- 484 -- Is_Child_Name -- 485 ------------------- 486 487 function Is_Child_Name (N : Unit_Name_Type) return Boolean is 488 J : Natural; 489 490 begin 491 Get_Name_String (N); 492 J := Name_Len; 493 494 while Name_Buffer (J) /= '.' loop 495 if J = 1 then 496 return False; -- not a child or subunit name 497 else 498 J := J - 1; 499 end if; 500 end loop; 501 502 return True; 503 end Is_Child_Name; 504 505 ------------------ 506 -- Is_Spec_Name -- 507 ------------------ 508 509 function Is_Spec_Name (N : Unit_Name_Type) return Boolean is 510 begin 511 Get_Name_String (N); 512 return Name_Len > 2 513 and then Name_Buffer (Name_Len - 1) = '%' 514 and then Name_Buffer (Name_Len) = 's'; 515 end Is_Spec_Name; 516 517 ----------------------- 518 -- Name_To_Unit_Name -- 519 ----------------------- 520 521 function Name_To_Unit_Name (N : Name_Id) return Unit_Name_Type is 522 begin 523 Get_Name_String (N); 524 Name_Buffer (Name_Len + 1) := '%'; 525 Name_Buffer (Name_Len + 2) := 's'; 526 Name_Len := Name_Len + 2; 527 return Name_Find; 528 end Name_To_Unit_Name; 529 530 --------------- 531 -- New_Child -- 532 --------------- 533 534 function New_Child 535 (Old : Unit_Name_Type; 536 Newp : Unit_Name_Type) return Unit_Name_Type 537 is 538 P : Natural; 539 540 begin 541 Get_Name_String (Old); 542 543 declare 544 Child : constant String := Name_Buffer (1 .. Name_Len); 545 546 begin 547 Get_Name_String (Newp); 548 Name_Len := Name_Len - 2; 549 550 P := Child'Last; 551 while Child (P) /= '.' loop 552 P := P - 1; 553 end loop; 554 555 while P <= Child'Last loop 556 Name_Len := Name_Len + 1; 557 Name_Buffer (Name_Len) := Child (P); 558 P := P + 1; 559 end loop; 560 561 return Name_Find; 562 end; 563 end New_Child; 564 565 -------------- 566 -- Uname_Ge -- 567 -------------- 568 569 function Uname_Ge (Left, Right : Unit_Name_Type) return Boolean is 570 begin 571 return Left = Right or else Uname_Gt (Left, Right); 572 end Uname_Ge; 573 574 -------------- 575 -- Uname_Gt -- 576 -------------- 577 578 function Uname_Gt (Left, Right : Unit_Name_Type) return Boolean is 579 begin 580 return Left /= Right and then not Uname_Lt (Left, Right); 581 end Uname_Gt; 582 583 -------------- 584 -- Uname_Le -- 585 -------------- 586 587 function Uname_Le (Left, Right : Unit_Name_Type) return Boolean is 588 begin 589 return Left = Right or else Uname_Lt (Left, Right); 590 end Uname_Le; 591 592 -------------- 593 -- Uname_Lt -- 594 -------------- 595 596 function Uname_Lt (Left, Right : Unit_Name_Type) return Boolean is 597 Left_Name : String (1 .. Hostparm.Max_Name_Length); 598 Left_Length : Natural; 599 Right_Name : String renames Name_Buffer; 600 Right_Length : Natural renames Name_Len; 601 J : Natural; 602 603 begin 604 pragma Warnings (Off, Right_Length); 605 -- Suppress warnings on Right_Length, used in pragma Assert 606 607 if Left = Right then 608 return False; 609 end if; 610 611 Get_Name_String (Left); 612 Left_Name (1 .. Name_Len + 1) := Name_Buffer (1 .. Name_Len + 1); 613 Left_Length := Name_Len; 614 Get_Name_String (Right); 615 J := 1; 616 617 loop 618 exit when Left_Name (J) = '%'; 619 620 if Right_Name (J) = '%' then 621 return False; -- left name is longer 622 end if; 623 624 pragma Assert (J <= Left_Length and then J <= Right_Length); 625 626 if Left_Name (J) /= Right_Name (J) then 627 return Left_Name (J) < Right_Name (J); -- parent names different 628 end if; 629 630 J := J + 1; 631 end loop; 632 633 -- Come here pointing to % in left name 634 635 if Right_Name (J) /= '%' then 636 return True; -- right name is longer 637 end if; 638 639 -- Here the parent names are the same and specs sort low. If neither is 640 -- a spec, then we are comparing the same name and we want a result of 641 -- False in any case. 642 643 return Left_Name (J + 1) = 's'; 644 end Uname_Lt; 645 646 --------------------- 647 -- Write_Unit_Name -- 648 --------------------- 649 650 procedure Write_Unit_Name (N : Unit_Name_Type) is 651 begin 652 Get_Unit_Name_String (N); 653 Write_Str (Name_Buffer (1 .. Name_Len)); 654 end Write_Unit_Name; 655 656end Uname; 657