Fortran: Suppress wrong End Of File error with user defined IO.
[official-gcc.git] / gcc / ada / lib.adb
blobc465828c562acf67358edfc5cbb5cd74998a13af
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT COMPILER COMPONENTS --
4 -- --
5 -- L I B --
6 -- --
7 -- B o d y --
8 -- --
9 -- Copyright (C) 1992-2024, 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. 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 COPYING3. If not, go to --
19 -- http://www.gnu.org/licenses for a complete copy of the license. --
20 -- --
21 -- GNAT was originally developed by the GNAT team at New York University. --
22 -- Extensive contributions were provided by Ada Core Technologies Inc. --
23 -- --
24 ------------------------------------------------------------------------------
26 pragma Style_Checks (All_Checks);
27 -- Subprogram ordering not enforced in this unit
28 -- (because of some logical groupings).
30 with Atree; use Atree;
31 with Csets; use Csets;
32 with Einfo; use Einfo;
33 with Einfo.Entities; use Einfo.Entities;
34 with Nlists; use Nlists;
35 with Opt; use Opt;
36 with Output; use Output;
37 with Sinfo; use Sinfo;
38 with Sinfo.Nodes; use Sinfo.Nodes;
39 with Sinput; use Sinput;
40 with Stand; use Stand;
41 with Stringt; use Stringt;
42 with Uname; use Uname;
43 with Widechar; use Widechar;
45 package body Lib is
47 Switch_Storing_Enabled : Boolean := True;
48 -- Controlled by Enable_Switch_Storing/Disable_Switch_Storing
50 -----------------------
51 -- Local Subprograms --
52 -----------------------
54 type SEU_Result is (
55 Yes_Before, -- S1 is in same extended unit as S2 and appears before it
56 Yes_Same, -- S1 is in same extended unit as S2, Slocs are the same
57 Yes_After, -- S1 is in same extended unit as S2, and appears after it
58 No); -- S2 is not in same extended unit as S2
60 function Check_Same_Extended_Unit
61 (S1 : Source_Ptr;
62 S2 : Source_Ptr) return SEU_Result;
63 -- Used by In_Same_Extended_Unit and Earlier_In_Extended_Unit. Returns
64 -- value as described above.
66 function Get_Code_Or_Source_Unit
67 (S : Source_Ptr;
68 Unwind_Instances : Boolean;
69 Unwind_Subunits : Boolean) return Unit_Number_Type;
70 -- Common processing for routines Get_Code_Unit, Get_Source_Unit, and
71 -- Get_Top_Level_Code_Unit. Unwind_Instances is True when the unit for the
72 -- top-level instantiation should be returned instead of the unit for the
73 -- template, in the case of an instantiation. Unwind_Subunits is True when
74 -- the corresponding top-level unit should be returned instead of a
75 -- subunit, in the case of a subunit.
77 --------------------------------------------
78 -- Access Functions for Unit Table Fields --
79 --------------------------------------------
81 function Cunit (U : Unit_Number_Type) return Node_Id is
82 begin
83 return Units.Table (U).Cunit;
84 end Cunit;
86 function Cunit_Entity (U : Unit_Number_Type) return Entity_Id is
87 begin
88 return Units.Table (U).Cunit_Entity;
89 end Cunit_Entity;
91 function Dependency_Num (U : Unit_Number_Type) return Nat is
92 begin
93 return Units.Table (U).Dependency_Num;
94 end Dependency_Num;
96 function Dynamic_Elab (U : Unit_Number_Type) return Boolean is
97 begin
98 return Units.Table (U).Dynamic_Elab;
99 end Dynamic_Elab;
101 function Error_Location (U : Unit_Number_Type) return Source_Ptr is
102 begin
103 return Units.Table (U).Error_Location;
104 end Error_Location;
106 function Expected_Unit (U : Unit_Number_Type) return Unit_Name_Type is
107 begin
108 return Units.Table (U).Expected_Unit;
109 end Expected_Unit;
111 function Fatal_Error (U : Unit_Number_Type) return Fatal_Type is
112 begin
113 return Units.Table (U).Fatal_Error;
114 end Fatal_Error;
116 function Generate_Code (U : Unit_Number_Type) return Boolean is
117 begin
118 return Units.Table (U).Generate_Code;
119 end Generate_Code;
121 function Has_RACW (U : Unit_Number_Type) return Boolean is
122 begin
123 return Units.Table (U).Has_RACW;
124 end Has_RACW;
126 function Is_Predefined_Renaming (U : Unit_Number_Type) return Boolean is
127 begin
128 return Units.Table (U).Is_Predefined_Renaming;
129 end Is_Predefined_Renaming;
131 function Is_Internal_Unit (U : Unit_Number_Type) return Boolean is
132 begin
133 return Units.Table (U).Is_Internal_Unit;
134 end Is_Internal_Unit;
136 function Is_Predefined_Unit (U : Unit_Number_Type) return Boolean is
137 begin
138 return Units.Table (U).Is_Predefined_Unit;
139 end Is_Predefined_Unit;
141 function Ident_String (U : Unit_Number_Type) return Node_Id is
142 begin
143 return Units.Table (U).Ident_String;
144 end Ident_String;
146 function Loading (U : Unit_Number_Type) return Boolean is
147 begin
148 return Units.Table (U).Loading;
149 end Loading;
151 function Main_CPU (U : Unit_Number_Type) return Int is
152 begin
153 return Units.Table (U).Main_CPU;
154 end Main_CPU;
156 function Main_Priority (U : Unit_Number_Type) return Int is
157 begin
158 return Units.Table (U).Main_Priority;
159 end Main_Priority;
161 function Munit_Index (U : Unit_Number_Type) return Nat is
162 begin
163 return Units.Table (U).Munit_Index;
164 end Munit_Index;
166 function No_Elab_Code_All (U : Unit_Number_Type) return Boolean is
167 begin
168 return Units.Table (U).No_Elab_Code_All;
169 end No_Elab_Code_All;
171 function OA_Setting (U : Unit_Number_Type) return Character is
172 begin
173 return Units.Table (U).OA_Setting;
174 end OA_Setting;
176 function Primary_Stack_Count (U : Unit_Number_Type) return Nat is
177 begin
178 return Units.Table (U).Primary_Stack_Count;
179 end Primary_Stack_Count;
181 function Sec_Stack_Count (U : Unit_Number_Type) return Nat is
182 begin
183 return Units.Table (U).Sec_Stack_Count;
184 end Sec_Stack_Count;
186 function Source_Index (U : Unit_Number_Type) return Source_File_Index is
187 begin
188 return Units.Table (U).Source_Index;
189 end Source_Index;
191 function Unit_File_Name (U : Unit_Number_Type) return File_Name_Type is
192 begin
193 return Units.Table (U).Unit_File_Name;
194 end Unit_File_Name;
196 function Unit_Name (U : Unit_Number_Type) return Unit_Name_Type is
197 begin
198 return Units.Table (U).Unit_Name;
199 end Unit_Name;
201 ------------------------------------------
202 -- Subprograms to Set Unit Table Fields --
203 ------------------------------------------
205 procedure Set_Cunit (U : Unit_Number_Type; N : Node_Id) is
206 begin
207 Units.Table (U).Cunit := N;
208 end Set_Cunit;
210 procedure Set_Cunit_Entity (U : Unit_Number_Type; E : Entity_Id) is
211 begin
212 Units.Table (U).Cunit_Entity := E;
213 Set_Is_Compilation_Unit (E);
214 end Set_Cunit_Entity;
216 procedure Set_Dynamic_Elab (U : Unit_Number_Type; B : Boolean := True) is
217 begin
218 Units.Table (U).Dynamic_Elab := B;
219 end Set_Dynamic_Elab;
221 procedure Set_Error_Location (U : Unit_Number_Type; W : Source_Ptr) is
222 begin
223 Units.Table (U).Error_Location := W;
224 end Set_Error_Location;
226 procedure Set_Fatal_Error (U : Unit_Number_Type; V : Fatal_Type) is
227 begin
228 Units.Table (U).Fatal_Error := V;
229 end Set_Fatal_Error;
231 procedure Set_Generate_Code (U : Unit_Number_Type; B : Boolean := True) is
232 begin
233 Units.Table (U).Generate_Code := B;
234 end Set_Generate_Code;
236 procedure Set_Has_RACW (U : Unit_Number_Type; B : Boolean := True) is
237 begin
238 Units.Table (U).Has_RACW := B;
239 end Set_Has_RACW;
241 procedure Set_Ident_String (U : Unit_Number_Type; N : Node_Id) is
242 begin
243 Units.Table (U).Ident_String := N;
244 end Set_Ident_String;
246 procedure Set_Loading (U : Unit_Number_Type; B : Boolean := True) is
247 begin
248 Units.Table (U).Loading := B;
249 end Set_Loading;
251 procedure Set_Main_CPU (U : Unit_Number_Type; P : Int) is
252 begin
253 Units.Table (U).Main_CPU := P;
254 end Set_Main_CPU;
256 procedure Set_Main_Priority (U : Unit_Number_Type; P : Int) is
257 begin
258 Units.Table (U).Main_Priority := P;
259 end Set_Main_Priority;
261 procedure Set_No_Elab_Code_All
262 (U : Unit_Number_Type;
263 B : Boolean := True)
265 begin
266 Units.Table (U).No_Elab_Code_All := B;
267 end Set_No_Elab_Code_All;
269 procedure Set_OA_Setting (U : Unit_Number_Type; C : Character) is
270 begin
271 Units.Table (U).OA_Setting := C;
272 end Set_OA_Setting;
274 procedure Set_Unit_Name (U : Unit_Number_Type; N : Unit_Name_Type) is
275 Old_N : constant Unit_Name_Type := Units.Table (U).Unit_Name;
277 begin
278 -- First unregister the old name, if any
280 if Present (Old_N) and then Unit_Names.Get (Old_N) = U then
281 Unit_Names.Set (Old_N, No_Unit);
282 end if;
284 -- Then set the new name
286 Units.Table (U).Unit_Name := N;
288 -- Finally register the new name
290 if Unit_Names.Get (N) = No_Unit then
291 Unit_Names.Set (N, U);
292 end if;
293 end Set_Unit_Name;
295 ------------------------------
296 -- Check_Same_Extended_Unit --
297 ------------------------------
299 function Check_Same_Extended_Unit
300 (S1 : Source_Ptr;
301 S2 : Source_Ptr) return SEU_Result
303 Max_Iterations : constant Nat := Maximum_Instantiations * 2;
304 -- Limit to prevent a potential infinite loop
306 Counter : Nat := 0;
307 Depth1 : Nat;
308 Depth2 : Nat;
309 Inst1 : Source_Ptr;
310 Inst2 : Source_Ptr;
311 Sind1 : Source_File_Index;
312 Sind2 : Source_File_Index;
313 Sloc1 : Source_Ptr;
314 Sloc2 : Source_Ptr;
315 Unit1 : Node_Id;
316 Unit2 : Node_Id;
317 Unum1 : Unit_Number_Type;
318 Unum2 : Unit_Number_Type;
320 begin
321 if S1 = No_Location or else S2 = No_Location then
322 return No;
323 end if;
325 if S1 = S2 then
326 return Yes_Same;
327 end if;
329 if S1 = Standard_Location or else S2 = Standard_Location then
330 return No;
331 end if;
333 Sloc1 := S1;
334 Sloc2 := S2;
336 Unum1 := Get_Source_Unit (Sloc1);
337 Unum2 := Get_Source_Unit (Sloc2);
339 loop
340 -- Step 1: Check whether the two locations are in the same source
341 -- file.
343 Sind1 := Get_Source_File_Index (Sloc1);
344 Sind2 := Get_Source_File_Index (Sloc2);
346 if Sind1 = Sind2 then
347 if Sloc1 < Sloc2 then
348 return Yes_Before;
349 elsif Sloc1 > Sloc2 then
350 return Yes_After;
351 else
352 return Yes_Same;
353 end if;
354 end if;
356 -- Step 2: Check subunits. If a subunit is instantiated, follow the
357 -- instantiation chain rather than the stub chain.
359 -- Note that we must handle the case where the subunit exists in the
360 -- same body as the main unit (which may happen when Naming gets
361 -- manually specified within a project file or through tools like
362 -- gprname). Otherwise, we will have an infinite loop jumping around
363 -- the same file.
365 Unit1 := Unit (Cunit (Unum1));
366 Unit2 := Unit (Cunit (Unum2));
367 Inst1 := Instantiation (Sind1);
368 Inst2 := Instantiation (Sind2);
370 if Nkind (Unit1) = N_Subunit
371 and then Present (Corresponding_Stub (Unit1))
372 and then Inst1 = No_Location
373 then
374 if Nkind (Unit2) = N_Subunit
375 and then Present (Corresponding_Stub (Unit2))
376 and then Inst2 = No_Location
377 then
378 -- Both locations refer to subunits which may have a common
379 -- ancestor. If they do, the deeper subunit must have a longer
380 -- unit name. Replace the deeper one with its corresponding
381 -- stub in order to find the nearest ancestor.
383 if Length_Of_Name (Unit_Name (Unum1)) <
384 Length_Of_Name (Unit_Name (Unum2))
385 then
386 Sloc2 := Sloc (Corresponding_Stub (Unit2));
388 if Unum2 /= Get_Source_Unit (Sloc2) then
389 Unum2 := Get_Source_Unit (Sloc2);
390 goto Continue;
391 else
392 null; -- Unum2 already designates the correct unit
393 end if;
394 else
395 Sloc1 := Sloc (Corresponding_Stub (Unit1));
397 if Unum1 /= Get_Source_Unit (Sloc1) then
398 Unum1 := Get_Source_Unit (Sloc1);
399 goto Continue;
400 else
401 null; -- Unum1 already designates the correct unit
402 end if;
403 end if;
405 -- Sloc1 in subunit, Sloc2 not
407 else
408 Sloc1 := Sloc (Corresponding_Stub (Unit1));
410 if Unum1 /= Get_Source_Unit (Sloc1) then
411 Unum1 := Get_Source_Unit (Sloc1);
412 goto Continue;
413 else
414 null; -- Unum1 already designates the correct unit
415 end if;
416 end if;
418 -- Sloc2 in subunit, Sloc1 not
420 elsif Nkind (Unit2) = N_Subunit
421 and then Present (Corresponding_Stub (Unit2))
422 and then Inst2 = No_Location
423 then
424 Sloc2 := Sloc (Corresponding_Stub (Unit2));
426 if Unum2 /= Get_Source_Unit (Sloc2) then
427 Unum2 := Get_Source_Unit (Sloc2);
428 goto Continue;
429 else
430 null; -- Unum2 already designates the correct unit
431 end if;
432 end if;
434 -- Step 3: Check instances. The two locations may yield a common
435 -- ancestor.
437 if Inst1 /= No_Location then
438 if Inst2 /= No_Location then
440 -- Both locations denote instantiations
442 Depth1 := Instantiation_Depth (Sloc1);
443 Depth2 := Instantiation_Depth (Sloc2);
445 if Depth1 < Depth2 then
446 Sloc2 := Inst2;
447 Unum2 := Get_Source_Unit (Sloc2);
448 goto Continue;
450 elsif Depth1 > Depth2 then
451 Sloc1 := Inst1;
452 Unum1 := Get_Source_Unit (Sloc1);
453 goto Continue;
455 else
456 Sloc1 := Inst1;
457 Sloc2 := Inst2;
458 Unum1 := Get_Source_Unit (Sloc1);
459 Unum2 := Get_Source_Unit (Sloc2);
460 goto Continue;
461 end if;
463 -- Sloc1 is an instantiation
465 else
466 Sloc1 := Inst1;
467 Unum1 := Get_Source_Unit (Sloc1);
468 goto Continue;
469 end if;
471 -- Sloc2 is an instantiation
473 elsif Inst2 /= No_Location then
474 Sloc2 := Inst2;
475 Unum2 := Get_Source_Unit (Sloc2);
476 goto Continue;
477 end if;
479 -- Step 4: One location in the spec, the other in the corresponding
480 -- body of the same unit. The location in the spec is considered
481 -- earlier.
483 if Nkind (Unit1) in N_Subprogram_Body | N_Package_Body then
484 if Library_Unit (Cunit (Unum1)) = Cunit (Unum2) then
485 return Yes_After;
486 end if;
488 elsif Nkind (Unit2) in N_Subprogram_Body | N_Package_Body then
489 if Library_Unit (Cunit (Unum2)) = Cunit (Unum1) then
490 return Yes_Before;
491 end if;
492 end if;
494 -- At this point it is certain that the two locations denote two
495 -- entirely separate units.
497 return No;
499 <<Continue>>
500 Counter := Counter + 1;
502 -- Prevent looping forever
504 if Counter > Max_Iterations then
506 -- In CodePeer_Mode, return a value to be able to generate SCIL
507 -- files and hope for the best.
509 if CodePeer_Mode then
510 return No;
511 else
512 raise Program_Error;
513 end if;
514 end if;
515 end loop;
516 end Check_Same_Extended_Unit;
518 -------------------------------
519 -- Compilation_Switches_Last --
520 -------------------------------
522 function Compilation_Switches_Last return Nat is
523 begin
524 return Compilation_Switches.Last;
525 end Compilation_Switches_Last;
527 ---------------------------
528 -- Enable_Switch_Storing --
529 ---------------------------
531 procedure Enable_Switch_Storing is
532 begin
533 Switch_Storing_Enabled := True;
534 end Enable_Switch_Storing;
536 ----------------------------
537 -- Disable_Switch_Storing --
538 ----------------------------
540 procedure Disable_Switch_Storing is
541 begin
542 Switch_Storing_Enabled := False;
543 end Disable_Switch_Storing;
545 ------------------------------
546 -- Earlier_In_Extended_Unit --
547 ------------------------------
549 function Earlier_In_Extended_Unit
550 (S1 : Source_Ptr;
551 S2 : Source_Ptr) return Boolean
553 begin
554 return Check_Same_Extended_Unit (S1, S2) = Yes_Before;
555 end Earlier_In_Extended_Unit;
557 function Earlier_In_Extended_Unit
558 (N1 : Node_Or_Entity_Id;
559 N2 : Node_Or_Entity_Id) return Boolean
561 begin
562 return Earlier_In_Extended_Unit (Sloc (N1), Sloc (N2));
563 end Earlier_In_Extended_Unit;
565 -----------------------
566 -- Exact_Source_Name --
567 -----------------------
569 function Exact_Source_Name (Loc : Source_Ptr) return String is
570 U : constant Unit_Number_Type := Get_Source_Unit (Loc);
571 Buf : constant Source_Buffer_Ptr := Source_Text (Source_Index (U));
572 Orig : constant Source_Ptr := Original_Location (Loc);
573 P : Source_Ptr;
575 WC : Char_Code;
576 Err : Boolean;
577 pragma Warnings (Off, WC);
578 pragma Warnings (Off, Err);
580 begin
581 -- Entity is character literal
583 if Buf (Orig) = ''' then
584 return String (Buf (Orig .. Orig + 2));
586 -- Entity is operator symbol
588 elsif Buf (Orig) = '"' or else Buf (Orig) = '%' then
589 P := Orig;
591 loop
592 P := P + 1;
593 exit when Buf (P) = Buf (Orig);
594 end loop;
596 return String (Buf (Orig .. P));
598 -- Entity is identifier
600 else
601 P := Orig;
603 loop
604 if Is_Start_Of_Wide_Char (Buf, P) then
605 Scan_Wide (Buf, P, WC, Err);
606 elsif not Identifier_Char (Buf (P)) then
607 exit;
608 else
609 P := P + 1;
610 end if;
611 end loop;
613 -- Write out the identifier by copying the exact source characters
614 -- used in its declaration. Note that this means wide characters will
615 -- be in their original encoded form.
617 return String (Buf (Orig .. P - 1));
618 end if;
619 end Exact_Source_Name;
621 ----------------------------
622 -- Entity_Is_In_Main_Unit --
623 ----------------------------
625 function Entity_Is_In_Main_Unit (E : Entity_Id) return Boolean is
626 S : Entity_Id;
628 begin
629 S := Scope (E);
631 while S /= Standard_Standard loop
632 if S = Main_Unit_Entity then
633 return True;
634 elsif Ekind (S) = E_Package and then Is_Child_Unit (S) then
635 return False;
636 else
637 S := Scope (S);
638 end if;
639 end loop;
641 return False;
642 end Entity_Is_In_Main_Unit;
644 --------------------------
645 -- Generic_May_Lack_ALI --
646 --------------------------
648 function Generic_May_Lack_ALI (Unum : Unit_Number_Type) return Boolean is
649 begin
650 -- We allow internal generic units to be used without having a
651 -- corresponding ALI files to help bootstrapping with older compilers
652 -- that did not support generating ALIs for such generics. It is safe
653 -- to do so because the only thing the generated code would contain
654 -- is the elaboration boolean, and we are careful to elaborate all
655 -- predefined units first anyway.
657 return Is_Internal_Unit (Unum);
658 end Generic_May_Lack_ALI;
660 -----------------------------
661 -- Get_Code_Or_Source_Unit --
662 -----------------------------
664 function Get_Code_Or_Source_Unit
665 (S : Source_Ptr;
666 Unwind_Instances : Boolean;
667 Unwind_Subunits : Boolean) return Unit_Number_Type
669 begin
670 -- Search table unless we have No_Location, which can happen if the
671 -- relevant location has not been set yet. Happens for example when
672 -- we obtain Sloc (Cunit (Main_Unit)) before it is set.
674 if S /= No_Location then
675 declare
676 Source_File : Source_File_Index;
677 Source_Unit : Unit_Number_Type;
678 Unit_Node : Node_Id;
680 begin
681 Source_File := Get_Source_File_Index (S);
683 if Unwind_Instances then
684 while Template (Source_File) > No_Source_File loop
685 Source_File := Template (Source_File);
686 end loop;
687 end if;
689 Source_Unit := Unit (Source_File);
691 if Unwind_Subunits then
692 Unit_Node := Unit (Cunit (Source_Unit));
694 while Nkind (Unit_Node) = N_Subunit
695 and then Present (Corresponding_Stub (Unit_Node))
696 loop
697 Source_Unit :=
698 Get_Code_Or_Source_Unit
699 (Sloc (Corresponding_Stub (Unit_Node)),
700 Unwind_Instances => Unwind_Instances,
701 Unwind_Subunits => Unwind_Subunits);
702 Unit_Node := Unit (Cunit (Source_Unit));
703 end loop;
704 end if;
706 if Source_Unit /= No_Unit then
707 return Source_Unit;
708 end if;
709 end;
710 end if;
712 -- If S was No_Location, or was not in the table, we must be in the main
713 -- source unit (and the value has not been placed in the table yet),
714 -- or in one of the configuration pragma files.
716 return Main_Unit;
717 end Get_Code_Or_Source_Unit;
719 -------------------
720 -- Get_Code_Unit --
721 -------------------
723 function Get_Code_Unit (S : Source_Ptr) return Unit_Number_Type is
724 begin
725 return
726 Get_Code_Or_Source_Unit
727 (Top_Level_Location (S),
728 Unwind_Instances => False,
729 Unwind_Subunits => False);
730 end Get_Code_Unit;
732 function Get_Code_Unit (N : Node_Or_Entity_Id) return Unit_Number_Type is
733 begin
734 return Get_Code_Unit (Sloc (N));
735 end Get_Code_Unit;
737 ----------------------------
738 -- Get_Compilation_Switch --
739 ----------------------------
741 function Get_Compilation_Switch (N : Pos) return String_Ptr is
742 begin
743 if N <= Compilation_Switches.Last then
744 return Compilation_Switches.Table (N);
745 else
746 return null;
747 end if;
748 end Get_Compilation_Switch;
750 ----------------------------------
751 -- Get_Cunit_Entity_Unit_Number --
752 ----------------------------------
754 function Get_Cunit_Entity_Unit_Number
755 (E : Entity_Id) return Unit_Number_Type
757 begin
758 for U in Units.First .. Units.Last loop
759 if Cunit_Entity (U) = E then
760 return U;
761 end if;
762 end loop;
764 -- If not in the table, must be the main source unit, and we just
765 -- have not got it put into the table yet.
767 return Main_Unit;
768 end Get_Cunit_Entity_Unit_Number;
770 ---------------------------
771 -- Get_Cunit_Unit_Number --
772 ---------------------------
774 function Get_Cunit_Unit_Number (N : Node_Id) return Unit_Number_Type is
775 begin
776 for U in Units.First .. Units.Last loop
777 if Cunit (U) = N then
778 return U;
779 end if;
780 end loop;
782 -- If not in the table, must be a spec created for a main unit that is a
783 -- child subprogram body which we have not inserted into the table yet.
785 if N = Library_Unit (Cunit (Main_Unit)) then
786 return Main_Unit;
788 -- If it is anything else, something is seriously wrong, and we really
789 -- don't want to proceed, even if assertions are off, so we explicitly
790 -- raise an exception in this case to terminate compilation.
792 else
793 raise Program_Error;
794 end if;
795 end Get_Cunit_Unit_Number;
797 ---------------------
798 -- Get_Source_Unit --
799 ---------------------
801 function Get_Source_Unit (S : Source_Ptr) return Unit_Number_Type is
802 begin
803 return
804 Get_Code_Or_Source_Unit
805 (S => S,
806 Unwind_Instances => True,
807 Unwind_Subunits => False);
808 end Get_Source_Unit;
810 function Get_Source_Unit (N : Node_Or_Entity_Id) return Unit_Number_Type is
811 begin
812 return Get_Source_Unit (Sloc (N));
813 end Get_Source_Unit;
815 -----------------------------
816 -- Get_Top_Level_Code_Unit --
817 -----------------------------
819 function Get_Top_Level_Code_Unit (S : Source_Ptr) return Unit_Number_Type is
820 begin
821 return
822 Get_Code_Or_Source_Unit
823 (Top_Level_Location (S),
824 Unwind_Instances => False,
825 Unwind_Subunits => True);
826 end Get_Top_Level_Code_Unit;
828 function Get_Top_Level_Code_Unit
829 (N : Node_Or_Entity_Id) return Unit_Number_Type is
830 begin
831 return Get_Top_Level_Code_Unit (Sloc (N));
832 end Get_Top_Level_Code_Unit;
834 --------------------------------
835 -- In_Extended_Main_Code_Unit --
836 --------------------------------
838 function In_Extended_Main_Code_Unit
839 (N : Node_Or_Entity_Id) return Boolean
841 begin
842 -- Special case Itypes to test the Sloc of the associated node. The
843 -- reason we do this is for possible calls from gigi after -gnatD
844 -- processing is complete in sprint. This processing updates the
845 -- sloc fields of all nodes in the tree, but itypes are not in the
846 -- tree so their slocs do not get updated.
848 if Nkind (N) = N_Defining_Identifier and then Is_Itype (N) then
849 return In_Extended_Main_Code_Unit (Associated_Node_For_Itype (N));
850 end if;
852 return In_Extended_Main_Code_Unit (Sloc (N));
853 end In_Extended_Main_Code_Unit;
855 function In_Extended_Main_Code_Unit (Loc : Source_Ptr) return Boolean is
856 begin
857 -- Special value cases
859 if Loc in No_Location | Standard_Location then
860 return False;
861 end if;
863 -- Otherwise see if we are in the main unit
865 if Get_Code_Unit (Loc) = Get_Code_Unit (Cunit (Main_Unit)) then
866 return True;
867 end if;
869 -- Location may be in spec (or subunit etc) of main unit
871 return In_Same_Extended_Unit (Loc, Sloc (Cunit (Main_Unit)));
872 end In_Extended_Main_Code_Unit;
874 ----------------------------------
875 -- In_Extended_Main_Source_Unit --
876 ----------------------------------
878 function In_Extended_Main_Source_Unit
879 (N : Node_Or_Entity_Id) return Boolean
881 begin
882 -- Special case Itypes to test the Sloc of the associated node. The
883 -- reason we do this is for possible calls from gigi after -gnatD
884 -- processing is complete in sprint. This processing updates the
885 -- sloc fields of all nodes in the tree, but itypes are not in the
886 -- tree so their slocs do not get updated.
888 if Nkind (N) = N_Defining_Identifier and then Is_Itype (N) then
889 pragma Assert (Compiler_State /= Parsing);
890 return In_Extended_Main_Source_Unit (Associated_Node_For_Itype (N));
891 end if;
893 return In_Extended_Main_Source_Unit (Sloc (N));
894 end In_Extended_Main_Source_Unit;
896 function In_Extended_Main_Source_Unit
897 (Loc : Source_Ptr) return Boolean
899 begin
900 -- If parsing, then use the global flag to indicate result
902 if Compiler_State = Parsing then
903 return Parsing_Main_Extended_Source;
904 end if;
906 -- Special value cases
908 if Loc in No_Location | Standard_Location then
909 return False;
910 end if;
912 -- Otherwise compare original locations
914 return In_Same_Extended_Unit
915 (Original_Location (Loc),
916 Original_Location (Sloc (Cunit (Main_Unit))));
917 end In_Extended_Main_Source_Unit;
919 ----------------------
920 -- In_Internal_Unit --
921 ----------------------
923 function In_Internal_Unit (N : Node_Or_Entity_Id) return Boolean is
924 begin
925 return In_Internal_Unit (Sloc (N));
926 end In_Internal_Unit;
928 function In_Internal_Unit (S : Source_Ptr) return Boolean is
929 Unit : constant Unit_Number_Type := Get_Source_Unit (S);
930 begin
931 return Is_Internal_Unit (Unit);
932 end In_Internal_Unit;
934 ----------------------------
935 -- In_Predefined_Renaming --
936 ----------------------------
938 function In_Predefined_Renaming (N : Node_Or_Entity_Id) return Boolean is
939 begin
940 return In_Predefined_Renaming (Sloc (N));
941 end In_Predefined_Renaming;
943 function In_Predefined_Renaming (S : Source_Ptr) return Boolean is
944 Unit : constant Unit_Number_Type := Get_Source_Unit (S);
945 begin
946 return Is_Predefined_Renaming (Unit);
947 end In_Predefined_Renaming;
949 ---------
950 -- ipu --
951 ---------
953 function ipu (N : Node_Or_Entity_Id) return Boolean is
954 begin
955 return In_Predefined_Unit (N);
956 end ipu;
958 ------------------------
959 -- In_Predefined_Unit --
960 ------------------------
962 function In_Predefined_Unit (N : Node_Or_Entity_Id) return Boolean is
963 begin
964 return In_Predefined_Unit (Sloc (N));
965 end In_Predefined_Unit;
967 function In_Predefined_Unit (S : Source_Ptr) return Boolean is
968 Unit : constant Unit_Number_Type := Get_Source_Unit (S);
969 begin
970 return Is_Predefined_Unit (Unit);
971 end In_Predefined_Unit;
973 -----------------------
974 -- In_Same_Code_Unit --
975 -----------------------
977 function In_Same_Code_Unit (N1, N2 : Node_Or_Entity_Id) return Boolean is
978 S1 : constant Source_Ptr := Sloc (N1);
979 S2 : constant Source_Ptr := Sloc (N2);
981 begin
982 if S1 = No_Location or else S2 = No_Location then
983 return False;
985 elsif S1 = Standard_Location then
986 return S2 = Standard_Location;
988 elsif S2 = Standard_Location then
989 return False;
990 end if;
992 return Get_Code_Unit (N1) = Get_Code_Unit (N2);
993 end In_Same_Code_Unit;
995 ---------------------------
996 -- In_Same_Extended_Unit --
997 ---------------------------
999 function In_Same_Extended_Unit
1000 (N1, N2 : Node_Or_Entity_Id) return Boolean
1002 begin
1003 return Check_Same_Extended_Unit (Sloc (N1), Sloc (N2)) /= No;
1004 end In_Same_Extended_Unit;
1006 function In_Same_Extended_Unit (S1, S2 : Source_Ptr) return Boolean is
1007 begin
1008 return Check_Same_Extended_Unit (S1, S2) /= No;
1009 end In_Same_Extended_Unit;
1011 -------------------------
1012 -- In_Same_Source_Unit --
1013 -------------------------
1015 function In_Same_Source_Unit (N1, N2 : Node_Or_Entity_Id) return Boolean is
1016 S1 : constant Source_Ptr := Sloc (N1);
1017 S2 : constant Source_Ptr := Sloc (N2);
1019 begin
1020 if S1 = No_Location or else S2 = No_Location then
1021 return False;
1023 elsif S1 = Standard_Location then
1024 return S2 = Standard_Location;
1026 elsif S2 = Standard_Location then
1027 return False;
1028 end if;
1030 return Get_Source_Unit (N1) = Get_Source_Unit (N2);
1031 end In_Same_Source_Unit;
1033 -----------------------------------
1034 -- Increment_Primary_Stack_Count --
1035 -----------------------------------
1037 procedure Increment_Primary_Stack_Count (Increment : Nat) is
1038 PSC : Nat renames Units.Table (Current_Sem_Unit).Primary_Stack_Count;
1039 begin
1040 PSC := PSC + Increment;
1041 end Increment_Primary_Stack_Count;
1043 -------------------------------
1044 -- Increment_Sec_Stack_Count --
1045 -------------------------------
1047 procedure Increment_Sec_Stack_Count (Increment : Nat) is
1048 SSC : Nat renames Units.Table (Current_Sem_Unit).Sec_Stack_Count;
1049 begin
1050 SSC := SSC + Increment;
1051 end Increment_Sec_Stack_Count;
1053 -----------------------------
1054 -- Increment_Serial_Number --
1055 -----------------------------
1057 function Increment_Serial_Number return Nat is
1058 TSN : Int renames Units.Table (Current_Sem_Unit).Serial_Number;
1059 begin
1060 TSN := TSN + 1;
1061 return TSN;
1062 end Increment_Serial_Number;
1064 ----------------------
1065 -- Init_Unit_Name --
1066 ----------------------
1068 procedure Init_Unit_Name (U : Unit_Number_Type; N : Unit_Name_Type) is
1069 begin
1070 Units.Table (U).Unit_Name := N;
1071 Unit_Names.Set (N, U);
1072 end Init_Unit_Name;
1074 ----------------
1075 -- Initialize --
1076 ----------------
1078 procedure Initialize is
1079 begin
1080 Linker_Option_Lines.Init;
1081 Notes.Init;
1082 Load_Stack.Init;
1083 Units.Init;
1084 Compilation_Switches.Init;
1085 end Initialize;
1087 ---------------
1088 -- Is_Loaded --
1089 ---------------
1091 function Is_Loaded (Uname : Unit_Name_Type) return Boolean is
1092 begin
1093 return Unit_Names.Get (Uname) /= No_Unit;
1094 end Is_Loaded;
1096 ---------------
1097 -- Last_Unit --
1098 ---------------
1100 function Last_Unit return Unit_Number_Type is
1101 begin
1102 return Units.Last;
1103 end Last_Unit;
1105 ----------
1106 -- List --
1107 ----------
1109 procedure List (File_Names_Only : Boolean := False) is separate;
1111 ----------
1112 -- Lock --
1113 ----------
1115 procedure Lock is
1116 begin
1117 Linker_Option_Lines.Release;
1118 Linker_Option_Lines.Locked := True;
1119 Load_Stack.Release;
1120 Load_Stack.Locked := True;
1121 Units.Release;
1122 Units.Locked := True;
1123 end Lock;
1125 ---------------
1126 -- Num_Units --
1127 ---------------
1129 function Num_Units return Nat is
1130 begin
1131 return Int (Units.Last) - Int (Main_Unit) + 1;
1132 end Num_Units;
1134 -----------------
1135 -- Remove_Unit --
1136 -----------------
1138 procedure Remove_Unit (U : Unit_Number_Type) is
1139 begin
1140 pragma Assert (U = Units.Last);
1141 Unit_Names.Set (Unit_Name (U), No_Unit);
1142 Units.Decrement_Last;
1143 end Remove_Unit;
1145 ----------------------------------
1146 -- Replace_Linker_Option_String --
1147 ----------------------------------
1149 procedure Replace_Linker_Option_String
1150 (S : String_Id; Match_String : String)
1152 begin
1153 if Match_String'Length > 0 then
1154 for J in 1 .. Linker_Option_Lines.Last loop
1155 String_To_Name_Buffer (Linker_Option_Lines.Table (J).Option);
1157 if Match_String = Name_Buffer (1 .. Match_String'Length) then
1158 Linker_Option_Lines.Table (J).Option := S;
1159 return;
1160 end if;
1161 end loop;
1162 end if;
1164 Store_Linker_Option_String (S);
1165 end Replace_Linker_Option_String;
1167 ----------
1168 -- Sort --
1169 ----------
1171 procedure Sort (Tbl : in out Unit_Ref_Table) is separate;
1173 ------------------------------
1174 -- Store_Compilation_Switch --
1175 ------------------------------
1177 procedure Store_Compilation_Switch (Switch : String) is
1178 begin
1179 if Switch_Storing_Enabled then
1180 Compilation_Switches.Increment_Last;
1181 Compilation_Switches.Table (Compilation_Switches.Last) :=
1182 new String'(Switch);
1184 -- Fix up --RTS flag which has been transformed by the gcc driver
1185 -- into -fRTS
1187 if Switch'Last >= Switch'First + 4
1188 and then Switch (Switch'First .. Switch'First + 4) = "-fRTS"
1189 then
1190 Compilation_Switches.Table
1191 (Compilation_Switches.Last) (Switch'First + 1) := '-';
1192 end if;
1193 end if;
1194 end Store_Compilation_Switch;
1196 --------------------------------
1197 -- Store_Linker_Option_String --
1198 --------------------------------
1200 procedure Store_Linker_Option_String (S : String_Id) is
1201 begin
1202 Linker_Option_Lines.Append ((Option => S, Unit => Current_Sem_Unit));
1203 end Store_Linker_Option_String;
1205 ----------------
1206 -- Store_Note --
1207 ----------------
1209 procedure Store_Note (N : Node_Id) is
1210 Sfile : constant Source_File_Index := Get_Source_File_Index (Sloc (N));
1212 begin
1213 -- Notes for a generic are emitted when processing the template, never
1214 -- in instances.
1216 if In_Extended_Main_Code_Unit (N)
1217 and then Instance (Sfile) = No_Instance_Id
1218 then
1219 Notes.Append (N);
1220 end if;
1221 end Store_Note;
1223 -------------------------------
1224 -- Synchronize_Serial_Number --
1225 -------------------------------
1227 procedure Synchronize_Serial_Number (SN : Nat) is
1228 TSN : Int renames Units.Table (Current_Sem_Unit).Serial_Number;
1229 begin
1230 -- We should not be trying to synchronize downward
1232 pragma Assert (TSN <= SN);
1234 if TSN < SN then
1235 TSN := SN;
1236 end if;
1237 end Synchronize_Serial_Number;
1239 --------------------
1240 -- Unit_Name_Hash --
1241 --------------------
1243 function Unit_Name_Hash (Id : Unit_Name_Type) return Unit_Name_Header_Num is
1244 begin
1245 return Unit_Name_Header_Num (Id mod Unit_Name_Table_Size);
1246 end Unit_Name_Hash;
1248 ------------
1249 -- Unlock --
1250 ------------
1252 procedure Unlock is
1253 begin
1254 Linker_Option_Lines.Locked := False;
1255 Load_Stack.Locked := False;
1256 Units.Locked := False;
1257 end Unlock;
1259 -----------------
1260 -- Version_Get --
1261 -----------------
1263 function Version_Get (U : Unit_Number_Type) return Word_Hex_String is
1264 begin
1265 return Get_Hex_String (Units.Table (U).Version);
1266 end Version_Get;
1268 ------------------------
1269 -- Version_Referenced --
1270 ------------------------
1272 procedure Version_Referenced (S : String_Id) is
1273 begin
1274 Version_Ref.Append (S);
1275 end Version_Referenced;
1277 ---------------------
1278 -- Write_Unit_Info --
1279 ---------------------
1281 procedure Write_Unit_Info
1282 (Unit_Num : Unit_Number_Type;
1283 Item : Node_Id;
1284 Prefix : String := "";
1285 Withs : Boolean := False)
1287 begin
1288 Write_Str (Prefix);
1289 Write_Unit_Name (Unit_Name (Unit_Num));
1290 Write_Str (", unit ");
1291 Write_Int (Int (Unit_Num));
1292 Write_Str (", ");
1293 Write_Int (Int (Item));
1294 Write_Str ("=");
1295 Write_Str (Node_Kind'Image (Nkind (Item)));
1297 if Is_Rewrite_Substitution (Item) then
1298 Write_Str (", orig = ");
1299 Write_Int (Int (Original_Node (Item)));
1300 Write_Str ("=");
1301 Write_Str (Node_Kind'Image (Nkind (Original_Node (Item))));
1302 end if;
1304 Write_Eol;
1306 -- Skip the rest if we're not supposed to print the withs
1308 if not Withs then
1309 return;
1310 end if;
1312 declare
1313 Context_Item : Node_Id;
1315 begin
1316 Context_Item := First (Context_Items (Cunit (Unit_Num)));
1317 while Present (Context_Item)
1318 and then (Nkind (Context_Item) /= N_With_Clause
1319 or else Limited_Present (Context_Item))
1320 loop
1321 Next (Context_Item);
1322 end loop;
1324 if Present (Context_Item) then
1325 Indent;
1326 Write_Line ("withs:");
1327 Indent;
1329 while Present (Context_Item) loop
1330 if Nkind (Context_Item) = N_With_Clause
1331 and then not Limited_Present (Context_Item)
1332 then
1333 pragma Assert (Present (Library_Unit (Context_Item)));
1334 Write_Unit_Name
1335 (Unit_Name
1336 (Get_Cunit_Unit_Number (Library_Unit (Context_Item))));
1338 if Implicit_With (Context_Item) then
1339 Write_Str (" -- implicit");
1340 end if;
1342 Write_Eol;
1343 end if;
1345 Next (Context_Item);
1346 end loop;
1348 Outdent;
1349 Write_Line ("end withs");
1350 Outdent;
1351 end if;
1352 end;
1353 end Write_Unit_Info;
1355 end Lib;