1 |
706 |
jeremybenn |
------------------------------------------------------------------------------
|
2 |
|
|
-- --
|
3 |
|
|
-- GNAT COMPILER COMPONENTS --
|
4 |
|
|
-- --
|
5 |
|
|
-- R T S F I N D --
|
6 |
|
|
-- --
|
7 |
|
|
-- B o d y --
|
8 |
|
|
-- --
|
9 |
|
|
-- Copyright (C) 1992-2012, 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 |
|
|
------------------------------------------------------------------------------
|
25 |
|
|
|
26 |
|
|
with Atree; use Atree;
|
27 |
|
|
with Casing; use Casing;
|
28 |
|
|
with Csets; use Csets;
|
29 |
|
|
with Debug; use Debug;
|
30 |
|
|
with Einfo; use Einfo;
|
31 |
|
|
with Elists; use Elists;
|
32 |
|
|
with Errout; use Errout;
|
33 |
|
|
with Exp_Dist; use Exp_Dist;
|
34 |
|
|
with Fname; use Fname;
|
35 |
|
|
with Fname.UF; use Fname.UF;
|
36 |
|
|
with Lib; use Lib;
|
37 |
|
|
with Lib.Load; use Lib.Load;
|
38 |
|
|
with Namet; use Namet;
|
39 |
|
|
with Nlists; use Nlists;
|
40 |
|
|
with Nmake; use Nmake;
|
41 |
|
|
with Output; use Output;
|
42 |
|
|
with Opt; use Opt;
|
43 |
|
|
with Restrict; use Restrict;
|
44 |
|
|
with Sem; use Sem;
|
45 |
|
|
with Sem_Aux; use Sem_Aux;
|
46 |
|
|
with Sem_Ch7; use Sem_Ch7;
|
47 |
|
|
with Sem_Dist; use Sem_Dist;
|
48 |
|
|
with Sem_Util; use Sem_Util;
|
49 |
|
|
with Sinfo; use Sinfo;
|
50 |
|
|
with Stand; use Stand;
|
51 |
|
|
with Snames; use Snames;
|
52 |
|
|
with Tbuild; use Tbuild;
|
53 |
|
|
with Uname; use Uname;
|
54 |
|
|
|
55 |
|
|
package body Rtsfind is
|
56 |
|
|
|
57 |
|
|
RTE_Available_Call : Boolean := False;
|
58 |
|
|
-- Set True during call to RTE from RTE_Available (or from call to
|
59 |
|
|
-- RTE_Record_Component from RTE_Record_Component_Available). Tells
|
60 |
|
|
-- the called subprogram to set RTE_Is_Available to False rather than
|
61 |
|
|
-- generating an error message.
|
62 |
|
|
|
63 |
|
|
RTE_Is_Available : Boolean;
|
64 |
|
|
-- Set True by RTE_Available on entry. When RTE_Available_Call is set
|
65 |
|
|
-- True, set False if RTE would otherwise generate an error message.
|
66 |
|
|
|
67 |
|
|
----------------
|
68 |
|
|
-- Unit table --
|
69 |
|
|
----------------
|
70 |
|
|
|
71 |
|
|
-- The unit table has one entry for each unit included in the definition
|
72 |
|
|
-- of the type RTU_Id in the spec. The table entries are initialized in
|
73 |
|
|
-- Initialize to set the Entity field to Empty, indicating that the
|
74 |
|
|
-- corresponding unit has not yet been loaded. The fields are set when
|
75 |
|
|
-- a unit is loaded to contain the defining entity for the unit, the
|
76 |
|
|
-- unit name, and the unit number.
|
77 |
|
|
|
78 |
|
|
-- Note that a unit can be loaded either by a call to find an entity
|
79 |
|
|
-- within the unit (e.g. RTE), or by an explicit with of the unit. In
|
80 |
|
|
-- the latter case it is critical to make a call to Set_RTU_Loaded to
|
81 |
|
|
-- ensure that the entry in this table reflects the load.
|
82 |
|
|
|
83 |
|
|
-- A unit retrieved through rtsfind may end up in the context of several
|
84 |
|
|
-- other units, in addition to the main unit. These additional with_clauses
|
85 |
|
|
-- are needed to generate a proper traversal order for Inspector. To
|
86 |
|
|
-- minimize somewhat the redundancy created by numerous calls to rtsfind
|
87 |
|
|
-- from different units, we keep track of the list of implicit with_clauses
|
88 |
|
|
-- already created for the current loaded unit.
|
89 |
|
|
|
90 |
|
|
type RT_Unit_Table_Record is record
|
91 |
|
|
Entity : Entity_Id;
|
92 |
|
|
Uname : Unit_Name_Type;
|
93 |
|
|
First_Implicit_With : Node_Id;
|
94 |
|
|
Unum : Unit_Number_Type;
|
95 |
|
|
end record;
|
96 |
|
|
|
97 |
|
|
RT_Unit_Table : array (RTU_Id) of RT_Unit_Table_Record;
|
98 |
|
|
|
99 |
|
|
--------------------------
|
100 |
|
|
-- Runtime Entity Table --
|
101 |
|
|
--------------------------
|
102 |
|
|
|
103 |
|
|
-- There is one entry in the runtime entity table for each entity that is
|
104 |
|
|
-- included in the definition of the RE_Id type in the spec. The entries
|
105 |
|
|
-- are set by Initialize_Rtsfind to contain Empty, indicating that the
|
106 |
|
|
-- entity has not yet been located. Once the entity is located for the
|
107 |
|
|
-- first time, its ID is stored in this array, so that subsequent calls
|
108 |
|
|
-- for the same entity can be satisfied immediately.
|
109 |
|
|
|
110 |
|
|
-- NOTE: In order to avoid conflicts between record components and subprgs
|
111 |
|
|
-- that have the same name (i.e. subprogram External_Tag and
|
112 |
|
|
-- component External_Tag of package Ada.Tags) this table is not used
|
113 |
|
|
-- with Record_Components.
|
114 |
|
|
|
115 |
|
|
RE_Table : array (RE_Id) of Entity_Id;
|
116 |
|
|
|
117 |
|
|
--------------------------------
|
118 |
|
|
-- Generation of with_clauses --
|
119 |
|
|
--------------------------------
|
120 |
|
|
|
121 |
|
|
-- When a unit is implicitly loaded as a result of a call to RTE, it is
|
122 |
|
|
-- necessary to create one or two implicit with_clauses. We add such
|
123 |
|
|
-- with_clauses to the extended main unit if needed, and also to whatever
|
124 |
|
|
-- unit needs them, which is not necessarily the main unit. The former
|
125 |
|
|
-- ensures that the object is correctly loaded by the binder. The latter
|
126 |
|
|
-- is necessary for SofCheck Inspector.
|
127 |
|
|
|
128 |
|
|
-- The field First_Implicit_With in the unit table record are used to
|
129 |
|
|
-- avoid creating duplicate with_clauses.
|
130 |
|
|
|
131 |
|
|
-----------------------
|
132 |
|
|
-- Local Subprograms --
|
133 |
|
|
-----------------------
|
134 |
|
|
|
135 |
|
|
function Check_CRT (E : RE_Id; Eid : Entity_Id) return Entity_Id;
|
136 |
|
|
-- Check entity Eid to ensure that configurable run-time restrictions are
|
137 |
|
|
-- met. May generate an error message (if RTE_Available_Call is false) and
|
138 |
|
|
-- raise RE_Not_Available if entity E does not exist (e.g. Eid is Empty).
|
139 |
|
|
-- Also check that entity is not overloaded.
|
140 |
|
|
|
141 |
|
|
procedure Entity_Not_Defined (Id : RE_Id);
|
142 |
|
|
-- Outputs error messages for an entity that is not defined in the run-time
|
143 |
|
|
-- library (the form of the error message is tailored for no run time or
|
144 |
|
|
-- configurable run time mode as required).
|
145 |
|
|
|
146 |
|
|
function Get_Unit_Name (U_Id : RTU_Id) return Unit_Name_Type;
|
147 |
|
|
-- Retrieves the Unit Name given a unit id represented by its enumeration
|
148 |
|
|
-- value in RTU_Id.
|
149 |
|
|
|
150 |
|
|
procedure Load_Fail (S : String; U_Id : RTU_Id; Id : RE_Id);
|
151 |
|
|
-- Internal procedure called if we can't successfully locate or process a
|
152 |
|
|
-- run-time unit. The parameters give information about the error message
|
153 |
|
|
-- to be given. S is a reason for failing to compile the file and U_Id is
|
154 |
|
|
-- the unit id. RE_Id is the RE_Id originally passed to RTE. The message in
|
155 |
|
|
-- S is one of the following:
|
156 |
|
|
--
|
157 |
|
|
-- "not found"
|
158 |
|
|
-- "had parser errors"
|
159 |
|
|
-- "had semantic errors"
|
160 |
|
|
--
|
161 |
|
|
-- The "not found" case is treated specially in that it is considered
|
162 |
|
|
-- a normal situation in configurable run-time mode, and generates
|
163 |
|
|
-- a warning, but is otherwise ignored.
|
164 |
|
|
|
165 |
|
|
procedure Load_RTU
|
166 |
|
|
(U_Id : RTU_Id;
|
167 |
|
|
Id : RE_Id := RE_Null;
|
168 |
|
|
Use_Setting : Boolean := False);
|
169 |
|
|
-- Load the unit whose Id is given if not already loaded. The unit is
|
170 |
|
|
-- loaded and analyzed, and the entry in RT_Unit_Table is updated to
|
171 |
|
|
-- reflect the load. Use_Setting is used to indicate the initial setting
|
172 |
|
|
-- for the Is_Potentially_Use_Visible flag of the entity for the loaded
|
173 |
|
|
-- unit (if it is indeed loaded). A value of False means nothing special
|
174 |
|
|
-- need be done. A value of True indicates that this flag must be set to
|
175 |
|
|
-- True. It is needed only in the Text_IO_Kludge procedure, which may
|
176 |
|
|
-- materialize an entity of Text_IO (or [Wide_]Wide_Text_IO) that was
|
177 |
|
|
-- previously unknown. Id is the RE_Id value of the entity which was
|
178 |
|
|
-- originally requested. Id is used only for error message detail, and if
|
179 |
|
|
-- it is RE_Null, then the attempt to output the entity name is ignored.
|
180 |
|
|
|
181 |
|
|
function Make_Unit_Name
|
182 |
|
|
(U : RT_Unit_Table_Record;
|
183 |
|
|
N : Node_Id) return Node_Id;
|
184 |
|
|
-- If the unit is a child unit, build fully qualified name for use in
|
185 |
|
|
-- With_Clause.
|
186 |
|
|
|
187 |
|
|
procedure Maybe_Add_With (U : in out RT_Unit_Table_Record);
|
188 |
|
|
-- If necessary, add an implicit with_clause from the current unit to the
|
189 |
|
|
-- one represented by U.
|
190 |
|
|
|
191 |
|
|
procedure Output_Entity_Name (Id : RE_Id; Msg : String);
|
192 |
|
|
-- Output continuation error message giving qualified name of entity
|
193 |
|
|
-- corresponding to Id, appending the string given by Msg. This call
|
194 |
|
|
-- is only effective in All_Errors mode.
|
195 |
|
|
|
196 |
|
|
function RE_Chars (E : RE_Id) return Name_Id;
|
197 |
|
|
-- Given a RE_Id value returns the Chars of the corresponding entity
|
198 |
|
|
|
199 |
|
|
procedure RTE_Error_Msg (Msg : String);
|
200 |
|
|
-- Generates a message by calling Error_Msg_N specifying Current_Error_Node
|
201 |
|
|
-- as the node location using the given Msg text. Special processing in the
|
202 |
|
|
-- case where RTE_Available_Call is set. In this case, no message is output
|
203 |
|
|
-- and instead RTE_Is_Available is set to False. Note that this can only be
|
204 |
|
|
-- used if you are sure that the message comes directly or indirectly from
|
205 |
|
|
-- a call to the RTE function.
|
206 |
|
|
|
207 |
|
|
---------------
|
208 |
|
|
-- Check_CRT --
|
209 |
|
|
---------------
|
210 |
|
|
|
211 |
|
|
function Check_CRT (E : RE_Id; Eid : Entity_Id) return Entity_Id is
|
212 |
|
|
U_Id : constant RTU_Id := RE_Unit_Table (E);
|
213 |
|
|
|
214 |
|
|
begin
|
215 |
|
|
if No (Eid) then
|
216 |
|
|
if RTE_Available_Call then
|
217 |
|
|
RTE_Is_Available := False;
|
218 |
|
|
else
|
219 |
|
|
Entity_Not_Defined (E);
|
220 |
|
|
end if;
|
221 |
|
|
|
222 |
|
|
raise RE_Not_Available;
|
223 |
|
|
|
224 |
|
|
-- Entity is available
|
225 |
|
|
|
226 |
|
|
else
|
227 |
|
|
-- If in No_Run_Time mode and entity is not in one of the
|
228 |
|
|
-- specially permitted units, raise the exception.
|
229 |
|
|
|
230 |
|
|
if No_Run_Time_Mode
|
231 |
|
|
and then not OK_No_Run_Time_Unit (U_Id)
|
232 |
|
|
then
|
233 |
|
|
Entity_Not_Defined (E);
|
234 |
|
|
raise RE_Not_Available;
|
235 |
|
|
end if;
|
236 |
|
|
|
237 |
|
|
-- Check entity is not overloaded, checking for special exceptions
|
238 |
|
|
|
239 |
|
|
if Has_Homonym (Eid)
|
240 |
|
|
and then E /= RE_Save_Occurrence
|
241 |
|
|
then
|
242 |
|
|
Set_Standard_Error;
|
243 |
|
|
Write_Str ("Run-time configuration error (");
|
244 |
|
|
Write_Str ("rtsfind entity """);
|
245 |
|
|
Get_Decoded_Name_String (Chars (Eid));
|
246 |
|
|
Set_Casing (Mixed_Case);
|
247 |
|
|
Write_Str (Name_Buffer (1 .. Name_Len));
|
248 |
|
|
Write_Str (""" is overloaded)");
|
249 |
|
|
Write_Eol;
|
250 |
|
|
raise Unrecoverable_Error;
|
251 |
|
|
end if;
|
252 |
|
|
|
253 |
|
|
-- Otherwise entity is accessible
|
254 |
|
|
|
255 |
|
|
return Eid;
|
256 |
|
|
end if;
|
257 |
|
|
end Check_CRT;
|
258 |
|
|
|
259 |
|
|
------------------------
|
260 |
|
|
-- Entity_Not_Defined --
|
261 |
|
|
------------------------
|
262 |
|
|
|
263 |
|
|
procedure Entity_Not_Defined (Id : RE_Id) is
|
264 |
|
|
begin
|
265 |
|
|
if No_Run_Time_Mode then
|
266 |
|
|
|
267 |
|
|
-- If the error occurs when compiling the body of a predefined
|
268 |
|
|
-- unit for inlining purposes, the body must be illegal in this
|
269 |
|
|
-- mode, and there is no point in continuing.
|
270 |
|
|
|
271 |
|
|
if Is_Predefined_File_Name
|
272 |
|
|
(Unit_File_Name (Get_Source_Unit (Sloc (Current_Error_Node))))
|
273 |
|
|
then
|
274 |
|
|
Error_Msg_N
|
275 |
|
|
("construct not allowed in no run time mode!",
|
276 |
|
|
Current_Error_Node);
|
277 |
|
|
raise Unrecoverable_Error;
|
278 |
|
|
|
279 |
|
|
else
|
280 |
|
|
RTE_Error_Msg ("|construct not allowed in no run time mode");
|
281 |
|
|
end if;
|
282 |
|
|
|
283 |
|
|
elsif Configurable_Run_Time_Mode then
|
284 |
|
|
RTE_Error_Msg ("|construct not allowed in this configuration>");
|
285 |
|
|
else
|
286 |
|
|
RTE_Error_Msg ("run-time configuration error");
|
287 |
|
|
end if;
|
288 |
|
|
|
289 |
|
|
Output_Entity_Name (Id, "not defined");
|
290 |
|
|
end Entity_Not_Defined;
|
291 |
|
|
|
292 |
|
|
-------------------
|
293 |
|
|
-- Get_Unit_Name --
|
294 |
|
|
-------------------
|
295 |
|
|
|
296 |
|
|
function Get_Unit_Name (U_Id : RTU_Id) return Unit_Name_Type is
|
297 |
|
|
Uname_Chars : constant String := RTU_Id'Image (U_Id);
|
298 |
|
|
|
299 |
|
|
begin
|
300 |
|
|
Name_Len := Uname_Chars'Length;
|
301 |
|
|
Name_Buffer (1 .. Name_Len) := Uname_Chars;
|
302 |
|
|
Set_Casing (All_Lower_Case);
|
303 |
|
|
|
304 |
|
|
if U_Id in Ada_Child then
|
305 |
|
|
Name_Buffer (4) := '.';
|
306 |
|
|
|
307 |
|
|
if U_Id in Ada_Calendar_Child then
|
308 |
|
|
Name_Buffer (13) := '.';
|
309 |
|
|
|
310 |
|
|
elsif U_Id in Ada_Dispatching_Child then
|
311 |
|
|
Name_Buffer (16) := '.';
|
312 |
|
|
|
313 |
|
|
elsif U_Id in Ada_Interrupts_Child then
|
314 |
|
|
Name_Buffer (15) := '.';
|
315 |
|
|
|
316 |
|
|
elsif U_Id in Ada_Numerics_Child then
|
317 |
|
|
Name_Buffer (13) := '.';
|
318 |
|
|
|
319 |
|
|
elsif U_Id in Ada_Real_Time_Child then
|
320 |
|
|
Name_Buffer (14) := '.';
|
321 |
|
|
|
322 |
|
|
elsif U_Id in Ada_Streams_Child then
|
323 |
|
|
Name_Buffer (12) := '.';
|
324 |
|
|
|
325 |
|
|
elsif U_Id in Ada_Strings_Child then
|
326 |
|
|
Name_Buffer (12) := '.';
|
327 |
|
|
|
328 |
|
|
elsif U_Id in Ada_Text_IO_Child then
|
329 |
|
|
Name_Buffer (12) := '.';
|
330 |
|
|
|
331 |
|
|
elsif U_Id in Ada_Wide_Text_IO_Child then
|
332 |
|
|
Name_Buffer (17) := '.';
|
333 |
|
|
|
334 |
|
|
elsif U_Id in Ada_Wide_Wide_Text_IO_Child then
|
335 |
|
|
Name_Buffer (22) := '.';
|
336 |
|
|
end if;
|
337 |
|
|
|
338 |
|
|
elsif U_Id in Interfaces_Child then
|
339 |
|
|
Name_Buffer (11) := '.';
|
340 |
|
|
|
341 |
|
|
elsif U_Id in System_Child then
|
342 |
|
|
Name_Buffer (7) := '.';
|
343 |
|
|
|
344 |
|
|
if U_Id in System_Dim_Child then
|
345 |
|
|
Name_Buffer (11) := '.';
|
346 |
|
|
end if;
|
347 |
|
|
|
348 |
|
|
if U_Id in System_Multiprocessors_Child then
|
349 |
|
|
Name_Buffer (23) := '.';
|
350 |
|
|
end if;
|
351 |
|
|
|
352 |
|
|
if U_Id in System_Storage_Pools_Child then
|
353 |
|
|
Name_Buffer (21) := '.';
|
354 |
|
|
end if;
|
355 |
|
|
|
356 |
|
|
if U_Id in System_Strings_Child then
|
357 |
|
|
Name_Buffer (15) := '.';
|
358 |
|
|
end if;
|
359 |
|
|
|
360 |
|
|
if U_Id in System_Tasking_Child then
|
361 |
|
|
Name_Buffer (15) := '.';
|
362 |
|
|
end if;
|
363 |
|
|
|
364 |
|
|
if U_Id in System_Tasking_Restricted_Child then
|
365 |
|
|
Name_Buffer (26) := '.';
|
366 |
|
|
end if;
|
367 |
|
|
|
368 |
|
|
if U_Id in System_Tasking_Protected_Objects_Child then
|
369 |
|
|
Name_Buffer (33) := '.';
|
370 |
|
|
end if;
|
371 |
|
|
|
372 |
|
|
if U_Id in System_Tasking_Async_Delays_Child then
|
373 |
|
|
Name_Buffer (28) := '.';
|
374 |
|
|
end if;
|
375 |
|
|
end if;
|
376 |
|
|
|
377 |
|
|
-- Add %s at end for spec
|
378 |
|
|
|
379 |
|
|
Name_Buffer (Name_Len + 1) := '%';
|
380 |
|
|
Name_Buffer (Name_Len + 2) := 's';
|
381 |
|
|
Name_Len := Name_Len + 2;
|
382 |
|
|
|
383 |
|
|
return Name_Find;
|
384 |
|
|
end Get_Unit_Name;
|
385 |
|
|
|
386 |
|
|
----------------
|
387 |
|
|
-- Initialize --
|
388 |
|
|
----------------
|
389 |
|
|
|
390 |
|
|
procedure Initialize is
|
391 |
|
|
begin
|
392 |
|
|
-- Initialize the unit table
|
393 |
|
|
|
394 |
|
|
for J in RTU_Id loop
|
395 |
|
|
RT_Unit_Table (J).Entity := Empty;
|
396 |
|
|
end loop;
|
397 |
|
|
|
398 |
|
|
for J in RE_Id loop
|
399 |
|
|
RE_Table (J) := Empty;
|
400 |
|
|
end loop;
|
401 |
|
|
|
402 |
|
|
RTE_Is_Available := False;
|
403 |
|
|
end Initialize;
|
404 |
|
|
|
405 |
|
|
------------
|
406 |
|
|
-- Is_RTE --
|
407 |
|
|
------------
|
408 |
|
|
|
409 |
|
|
function Is_RTE (Ent : Entity_Id; E : RE_Id) return Boolean is
|
410 |
|
|
E_Unit_Name : Unit_Name_Type;
|
411 |
|
|
Ent_Unit_Name : Unit_Name_Type;
|
412 |
|
|
|
413 |
|
|
S : Entity_Id;
|
414 |
|
|
E1 : Entity_Id;
|
415 |
|
|
E2 : Entity_Id;
|
416 |
|
|
|
417 |
|
|
begin
|
418 |
|
|
if No (Ent) then
|
419 |
|
|
return False;
|
420 |
|
|
|
421 |
|
|
-- If E has already a corresponding entity, check it directly,
|
422 |
|
|
-- going to full views if they exist to deal with the incomplete
|
423 |
|
|
-- and private type cases properly.
|
424 |
|
|
|
425 |
|
|
elsif Present (RE_Table (E)) then
|
426 |
|
|
E1 := Ent;
|
427 |
|
|
|
428 |
|
|
if Is_Type (E1) and then Present (Full_View (E1)) then
|
429 |
|
|
E1 := Full_View (E1);
|
430 |
|
|
end if;
|
431 |
|
|
|
432 |
|
|
E2 := RE_Table (E);
|
433 |
|
|
|
434 |
|
|
if Is_Type (E2) and then Present (Full_View (E2)) then
|
435 |
|
|
E2 := Full_View (E2);
|
436 |
|
|
end if;
|
437 |
|
|
|
438 |
|
|
return E1 = E2;
|
439 |
|
|
end if;
|
440 |
|
|
|
441 |
|
|
-- If the unit containing E is not loaded, we already know that the
|
442 |
|
|
-- entity we have cannot have come from this unit.
|
443 |
|
|
|
444 |
|
|
E_Unit_Name := Get_Unit_Name (RE_Unit_Table (E));
|
445 |
|
|
|
446 |
|
|
if not Is_Loaded (E_Unit_Name) then
|
447 |
|
|
return False;
|
448 |
|
|
end if;
|
449 |
|
|
|
450 |
|
|
-- Here the unit containing the entity is loaded. We have not made
|
451 |
|
|
-- an explicit call to RTE to get the entity in question, but we may
|
452 |
|
|
-- have obtained a reference to it indirectly from some other entity
|
453 |
|
|
-- in the same unit, or some other unit that references it.
|
454 |
|
|
|
455 |
|
|
-- Get the defining unit of the entity
|
456 |
|
|
|
457 |
|
|
S := Scope (Ent);
|
458 |
|
|
|
459 |
|
|
if Ekind (S) /= E_Package then
|
460 |
|
|
return False;
|
461 |
|
|
end if;
|
462 |
|
|
|
463 |
|
|
Ent_Unit_Name := Get_Unit_Name (Unit_Declaration_Node (S));
|
464 |
|
|
|
465 |
|
|
-- If the defining unit of the entity we are testing is not the
|
466 |
|
|
-- unit containing E, then they cannot possibly match.
|
467 |
|
|
|
468 |
|
|
if Ent_Unit_Name /= E_Unit_Name then
|
469 |
|
|
return False;
|
470 |
|
|
end if;
|
471 |
|
|
|
472 |
|
|
-- If the units match, then compare the names (remember that no
|
473 |
|
|
-- overloading is permitted in entities fetched using Rtsfind).
|
474 |
|
|
|
475 |
|
|
if RE_Chars (E) = Chars (Ent) then
|
476 |
|
|
RE_Table (E) := Ent;
|
477 |
|
|
|
478 |
|
|
-- If front-end inlining is enabled, we may be within a body that
|
479 |
|
|
-- contains inlined functions, which has not been retrieved through
|
480 |
|
|
-- rtsfind, and therefore is not yet recorded in the RT_Unit_Table.
|
481 |
|
|
-- Add the unit information now, it must be fully available.
|
482 |
|
|
|
483 |
|
|
declare
|
484 |
|
|
U : RT_Unit_Table_Record
|
485 |
|
|
renames RT_Unit_Table (RE_Unit_Table (E));
|
486 |
|
|
begin
|
487 |
|
|
if No (U.Entity) then
|
488 |
|
|
U.Entity := S;
|
489 |
|
|
U.Uname := E_Unit_Name;
|
490 |
|
|
U.Unum := Get_Source_Unit (S);
|
491 |
|
|
end if;
|
492 |
|
|
end;
|
493 |
|
|
|
494 |
|
|
return True;
|
495 |
|
|
else
|
496 |
|
|
return False;
|
497 |
|
|
end if;
|
498 |
|
|
end Is_RTE;
|
499 |
|
|
|
500 |
|
|
------------
|
501 |
|
|
-- Is_RTU --
|
502 |
|
|
------------
|
503 |
|
|
|
504 |
|
|
function Is_RTU (Ent : Entity_Id; U : RTU_Id) return Boolean is
|
505 |
|
|
E : constant Entity_Id := RT_Unit_Table (U).Entity;
|
506 |
|
|
begin
|
507 |
|
|
return Present (E) and then E = Ent;
|
508 |
|
|
end Is_RTU;
|
509 |
|
|
|
510 |
|
|
----------------------------
|
511 |
|
|
-- Is_Text_IO_Kludge_Unit --
|
512 |
|
|
----------------------------
|
513 |
|
|
|
514 |
|
|
function Is_Text_IO_Kludge_Unit (Nam : Node_Id) return Boolean is
|
515 |
|
|
Prf : Node_Id;
|
516 |
|
|
Sel : Node_Id;
|
517 |
|
|
|
518 |
|
|
begin
|
519 |
|
|
if Nkind (Nam) /= N_Expanded_Name then
|
520 |
|
|
return False;
|
521 |
|
|
end if;
|
522 |
|
|
|
523 |
|
|
Prf := Prefix (Nam);
|
524 |
|
|
Sel := Selector_Name (Nam);
|
525 |
|
|
|
526 |
|
|
if Nkind (Sel) /= N_Expanded_Name
|
527 |
|
|
or else Nkind (Prf) /= N_Identifier
|
528 |
|
|
or else Chars (Prf) /= Name_Ada
|
529 |
|
|
then
|
530 |
|
|
return False;
|
531 |
|
|
end if;
|
532 |
|
|
|
533 |
|
|
Prf := Prefix (Sel);
|
534 |
|
|
Sel := Selector_Name (Sel);
|
535 |
|
|
|
536 |
|
|
return
|
537 |
|
|
Nkind (Prf) = N_Identifier
|
538 |
|
|
and then
|
539 |
|
|
(Chars (Prf) = Name_Text_IO
|
540 |
|
|
or else
|
541 |
|
|
Chars (Prf) = Name_Wide_Text_IO
|
542 |
|
|
or else
|
543 |
|
|
Chars (Prf) = Name_Wide_Wide_Text_IO)
|
544 |
|
|
and then
|
545 |
|
|
Nkind (Sel) = N_Identifier
|
546 |
|
|
and then
|
547 |
|
|
Chars (Sel) in Text_IO_Package_Name;
|
548 |
|
|
end Is_Text_IO_Kludge_Unit;
|
549 |
|
|
|
550 |
|
|
---------------
|
551 |
|
|
-- Load_Fail --
|
552 |
|
|
---------------
|
553 |
|
|
|
554 |
|
|
procedure Load_Fail (S : String; U_Id : RTU_Id; Id : RE_Id) is
|
555 |
|
|
M : String (1 .. 100);
|
556 |
|
|
P : Natural := 0;
|
557 |
|
|
|
558 |
|
|
begin
|
559 |
|
|
-- Output header message
|
560 |
|
|
|
561 |
|
|
if Configurable_Run_Time_Mode then
|
562 |
|
|
RTE_Error_Msg ("construct not allowed in configurable run-time mode");
|
563 |
|
|
else
|
564 |
|
|
RTE_Error_Msg ("run-time library configuration error");
|
565 |
|
|
end if;
|
566 |
|
|
|
567 |
|
|
-- Output file name and reason string
|
568 |
|
|
|
569 |
|
|
M (1 .. 6) := "\file ";
|
570 |
|
|
P := 6;
|
571 |
|
|
|
572 |
|
|
Get_Name_String
|
573 |
|
|
(Get_File_Name (RT_Unit_Table (U_Id).Uname, Subunit => False));
|
574 |
|
|
M (P + 1 .. P + Name_Len) := Name_Buffer (1 .. Name_Len);
|
575 |
|
|
P := P + Name_Len;
|
576 |
|
|
|
577 |
|
|
M (P + 1) := ' ';
|
578 |
|
|
P := P + 1;
|
579 |
|
|
|
580 |
|
|
M (P + 1 .. P + S'Length) := S;
|
581 |
|
|
P := P + S'Length;
|
582 |
|
|
|
583 |
|
|
RTE_Error_Msg (M (1 .. P));
|
584 |
|
|
|
585 |
|
|
-- Output entity name
|
586 |
|
|
|
587 |
|
|
Output_Entity_Name (Id, "not available");
|
588 |
|
|
|
589 |
|
|
-- In configurable run time mode, we raise RE_Not_Available, and the
|
590 |
|
|
-- caller is expected to deal gracefully with this. In the case of a
|
591 |
|
|
-- call to RTE_Available, this exception will be caught in Rtsfind,
|
592 |
|
|
-- and result in a returned value of False for the call.
|
593 |
|
|
|
594 |
|
|
if Configurable_Run_Time_Mode then
|
595 |
|
|
raise RE_Not_Available;
|
596 |
|
|
|
597 |
|
|
-- Here we have a load failure in normal full run time mode. See if we
|
598 |
|
|
-- are in the context of an RTE_Available call. If so, we just raise
|
599 |
|
|
-- RE_Not_Available. This can happen if a unit is unavailable, which
|
600 |
|
|
-- happens for example in the VM case, where the run-time is not
|
601 |
|
|
-- complete, but we do not regard it as a configurable run-time.
|
602 |
|
|
-- If the caller has done an explicit call to RTE_Available, then
|
603 |
|
|
-- clearly the caller is prepared to deal with a result of False.
|
604 |
|
|
|
605 |
|
|
elsif RTE_Available_Call then
|
606 |
|
|
RTE_Is_Available := False;
|
607 |
|
|
raise RE_Not_Available;
|
608 |
|
|
|
609 |
|
|
-- If we are not in the context of an RTE_Available call, we are really
|
610 |
|
|
-- trying to load an entity that is not there, and that should never
|
611 |
|
|
-- happen, so in this case we signal a fatal error.
|
612 |
|
|
|
613 |
|
|
else
|
614 |
|
|
raise Unrecoverable_Error;
|
615 |
|
|
end if;
|
616 |
|
|
end Load_Fail;
|
617 |
|
|
|
618 |
|
|
--------------
|
619 |
|
|
-- Load_RTU --
|
620 |
|
|
--------------
|
621 |
|
|
|
622 |
|
|
procedure Load_RTU
|
623 |
|
|
(U_Id : RTU_Id;
|
624 |
|
|
Id : RE_Id := RE_Null;
|
625 |
|
|
Use_Setting : Boolean := False)
|
626 |
|
|
is
|
627 |
|
|
U : RT_Unit_Table_Record renames RT_Unit_Table (U_Id);
|
628 |
|
|
Priv_Par : constant Elist_Id := New_Elmt_List;
|
629 |
|
|
Lib_Unit : Node_Id;
|
630 |
|
|
|
631 |
|
|
procedure Save_Private_Visibility;
|
632 |
|
|
-- If the current unit is the body of child unit or the spec of a
|
633 |
|
|
-- private child unit, the private declarations of the parent(s) are
|
634 |
|
|
-- visible. If the unit to be loaded is another public sibling, its
|
635 |
|
|
-- compilation will affect the visibility of the common ancestors.
|
636 |
|
|
-- Indicate those that must be restored.
|
637 |
|
|
|
638 |
|
|
procedure Restore_Private_Visibility;
|
639 |
|
|
-- Restore the visibility of ancestors after compiling RTU
|
640 |
|
|
|
641 |
|
|
--------------------------------
|
642 |
|
|
-- Restore_Private_Visibility --
|
643 |
|
|
--------------------------------
|
644 |
|
|
|
645 |
|
|
procedure Restore_Private_Visibility is
|
646 |
|
|
E_Par : Elmt_Id;
|
647 |
|
|
|
648 |
|
|
begin
|
649 |
|
|
E_Par := First_Elmt (Priv_Par);
|
650 |
|
|
while Present (E_Par) loop
|
651 |
|
|
if not In_Private_Part (Node (E_Par)) then
|
652 |
|
|
Install_Private_Declarations (Node (E_Par));
|
653 |
|
|
end if;
|
654 |
|
|
|
655 |
|
|
Next_Elmt (E_Par);
|
656 |
|
|
end loop;
|
657 |
|
|
end Restore_Private_Visibility;
|
658 |
|
|
|
659 |
|
|
-----------------------------
|
660 |
|
|
-- Save_Private_Visibility --
|
661 |
|
|
-----------------------------
|
662 |
|
|
|
663 |
|
|
procedure Save_Private_Visibility is
|
664 |
|
|
Par : Entity_Id;
|
665 |
|
|
|
666 |
|
|
begin
|
667 |
|
|
Par := Scope (Current_Scope);
|
668 |
|
|
while Present (Par)
|
669 |
|
|
and then Par /= Standard_Standard
|
670 |
|
|
loop
|
671 |
|
|
if Ekind (Par) = E_Package
|
672 |
|
|
and then Is_Compilation_Unit (Par)
|
673 |
|
|
and then In_Private_Part (Par)
|
674 |
|
|
then
|
675 |
|
|
Append_Elmt (Par, Priv_Par);
|
676 |
|
|
end if;
|
677 |
|
|
|
678 |
|
|
Par := Scope (Par);
|
679 |
|
|
end loop;
|
680 |
|
|
end Save_Private_Visibility;
|
681 |
|
|
|
682 |
|
|
-- Start of processing for Load_RTU
|
683 |
|
|
|
684 |
|
|
begin
|
685 |
|
|
-- Nothing to do if unit is already loaded
|
686 |
|
|
|
687 |
|
|
if Present (U.Entity) then
|
688 |
|
|
return;
|
689 |
|
|
end if;
|
690 |
|
|
|
691 |
|
|
-- Note if secondary stack is used
|
692 |
|
|
|
693 |
|
|
if U_Id = System_Secondary_Stack then
|
694 |
|
|
Opt.Sec_Stack_Used := True;
|
695 |
|
|
end if;
|
696 |
|
|
|
697 |
|
|
-- Otherwise we need to load the unit, First build unit name
|
698 |
|
|
-- from the enumeration literal name in type RTU_Id.
|
699 |
|
|
|
700 |
|
|
U.Uname := Get_Unit_Name (U_Id);
|
701 |
|
|
U. First_Implicit_With := Empty;
|
702 |
|
|
|
703 |
|
|
-- Now do the load call, note that setting Error_Node to Empty is
|
704 |
|
|
-- a signal to Load_Unit that we will regard a failure to find the
|
705 |
|
|
-- file as a fatal error, and that it should not output any kind
|
706 |
|
|
-- of diagnostics, since we will take care of it here.
|
707 |
|
|
|
708 |
|
|
-- We save style checking switches and turn off style checking for
|
709 |
|
|
-- loading the unit, since we don't want any style checking!
|
710 |
|
|
|
711 |
|
|
declare
|
712 |
|
|
Save_Style_Check : constant Boolean := Style_Check;
|
713 |
|
|
begin
|
714 |
|
|
Style_Check := False;
|
715 |
|
|
U.Unum :=
|
716 |
|
|
Load_Unit
|
717 |
|
|
(Load_Name => U.Uname,
|
718 |
|
|
Required => False,
|
719 |
|
|
Subunit => False,
|
720 |
|
|
Error_Node => Empty);
|
721 |
|
|
Style_Check := Save_Style_Check;
|
722 |
|
|
end;
|
723 |
|
|
|
724 |
|
|
-- Check for bad unit load
|
725 |
|
|
|
726 |
|
|
if U.Unum = No_Unit then
|
727 |
|
|
Load_Fail ("not found", U_Id, Id);
|
728 |
|
|
elsif Fatal_Error (U.Unum) then
|
729 |
|
|
Load_Fail ("had parser errors", U_Id, Id);
|
730 |
|
|
end if;
|
731 |
|
|
|
732 |
|
|
-- Make sure that the unit is analyzed
|
733 |
|
|
|
734 |
|
|
declare
|
735 |
|
|
Was_Analyzed : constant Boolean :=
|
736 |
|
|
Analyzed (Cunit (Current_Sem_Unit));
|
737 |
|
|
|
738 |
|
|
begin
|
739 |
|
|
-- Pretend that the current unit is analyzed, in case it is System
|
740 |
|
|
-- or some such. This allows us to put some declarations, such as
|
741 |
|
|
-- exceptions and packed arrays of Boolean, into System even though
|
742 |
|
|
-- expanding them requires System...
|
743 |
|
|
|
744 |
|
|
-- This is a bit odd but works fine. If the RTS unit does not depend
|
745 |
|
|
-- in any way on the current unit, then it never gets back into the
|
746 |
|
|
-- current unit's tree, and the change we make to the current unit
|
747 |
|
|
-- tree is never noticed by anyone (it is undone in a moment). That
|
748 |
|
|
-- is the normal situation.
|
749 |
|
|
|
750 |
|
|
-- If the RTS Unit *does* depend on the current unit, for instance,
|
751 |
|
|
-- when you are compiling System, then you had better have finished
|
752 |
|
|
-- analyzing the part of System that is depended on before you try to
|
753 |
|
|
-- load the RTS Unit. This means having the code in System ordered in
|
754 |
|
|
-- an appropriate manner.
|
755 |
|
|
|
756 |
|
|
Set_Analyzed (Cunit (Current_Sem_Unit), True);
|
757 |
|
|
|
758 |
|
|
if not Analyzed (Cunit (U.Unum)) then
|
759 |
|
|
|
760 |
|
|
-- If the unit is already loaded through a limited_with_clause,
|
761 |
|
|
-- the relevant entities must already be available. We do not
|
762 |
|
|
-- want to load and analyze the unit because this would create
|
763 |
|
|
-- a real semantic dependence when the purpose of the limited_with
|
764 |
|
|
-- is precisely to avoid such.
|
765 |
|
|
|
766 |
|
|
if From_With_Type (Cunit_Entity (U.Unum)) then
|
767 |
|
|
null;
|
768 |
|
|
|
769 |
|
|
else
|
770 |
|
|
Save_Private_Visibility;
|
771 |
|
|
Semantics (Cunit (U.Unum));
|
772 |
|
|
Restore_Private_Visibility;
|
773 |
|
|
|
774 |
|
|
if Fatal_Error (U.Unum) then
|
775 |
|
|
Load_Fail ("had semantic errors", U_Id, Id);
|
776 |
|
|
end if;
|
777 |
|
|
end if;
|
778 |
|
|
end if;
|
779 |
|
|
|
780 |
|
|
-- Undo the pretence
|
781 |
|
|
|
782 |
|
|
Set_Analyzed (Cunit (Current_Sem_Unit), Was_Analyzed);
|
783 |
|
|
end;
|
784 |
|
|
|
785 |
|
|
Lib_Unit := Unit (Cunit (U.Unum));
|
786 |
|
|
U.Entity := Defining_Entity (Lib_Unit);
|
787 |
|
|
|
788 |
|
|
if Use_Setting then
|
789 |
|
|
Set_Is_Potentially_Use_Visible (U.Entity, True);
|
790 |
|
|
end if;
|
791 |
|
|
end Load_RTU;
|
792 |
|
|
|
793 |
|
|
--------------------
|
794 |
|
|
-- Make_Unit_Name --
|
795 |
|
|
--------------------
|
796 |
|
|
|
797 |
|
|
function Make_Unit_Name
|
798 |
|
|
(U : RT_Unit_Table_Record;
|
799 |
|
|
N : Node_Id) return Node_Id is
|
800 |
|
|
|
801 |
|
|
Nam : Node_Id;
|
802 |
|
|
Scop : Entity_Id;
|
803 |
|
|
|
804 |
|
|
begin
|
805 |
|
|
Nam := New_Reference_To (U.Entity, Standard_Location);
|
806 |
|
|
Scop := Scope (U.Entity);
|
807 |
|
|
|
808 |
|
|
if Nkind (N) = N_Defining_Program_Unit_Name then
|
809 |
|
|
while Scop /= Standard_Standard loop
|
810 |
|
|
Nam :=
|
811 |
|
|
Make_Expanded_Name (Standard_Location,
|
812 |
|
|
Chars => Chars (U.Entity),
|
813 |
|
|
Prefix => New_Reference_To (Scop, Standard_Location),
|
814 |
|
|
Selector_Name => Nam);
|
815 |
|
|
Set_Entity (Nam, U.Entity);
|
816 |
|
|
|
817 |
|
|
Scop := Scope (Scop);
|
818 |
|
|
end loop;
|
819 |
|
|
end if;
|
820 |
|
|
|
821 |
|
|
return Nam;
|
822 |
|
|
end Make_Unit_Name;
|
823 |
|
|
|
824 |
|
|
--------------------
|
825 |
|
|
-- Maybe_Add_With --
|
826 |
|
|
--------------------
|
827 |
|
|
|
828 |
|
|
procedure Maybe_Add_With (U : in out RT_Unit_Table_Record) is
|
829 |
|
|
begin
|
830 |
|
|
-- We do not need to generate a with_clause for a call issued from
|
831 |
|
|
-- RTE_Component_Available. However, for CodePeer, we need these
|
832 |
|
|
-- additional with's, because for a sequence like "if RTE_Available (X)
|
833 |
|
|
-- then ... RTE (X)" the RTE call fails to create some necessary
|
834 |
|
|
-- with's.
|
835 |
|
|
|
836 |
|
|
if RTE_Available_Call and then not Generate_SCIL then
|
837 |
|
|
return;
|
838 |
|
|
end if;
|
839 |
|
|
|
840 |
|
|
-- Avoid creating directly self-referential with clauses
|
841 |
|
|
|
842 |
|
|
if Current_Sem_Unit = U.Unum then
|
843 |
|
|
return;
|
844 |
|
|
end if;
|
845 |
|
|
|
846 |
|
|
-- Add the with_clause, if not already in the context of the
|
847 |
|
|
-- current compilation unit.
|
848 |
|
|
|
849 |
|
|
declare
|
850 |
|
|
LibUnit : constant Node_Id := Unit (Cunit (U.Unum));
|
851 |
|
|
Clause : Node_Id;
|
852 |
|
|
Withn : Node_Id;
|
853 |
|
|
|
854 |
|
|
begin
|
855 |
|
|
Clause := U.First_Implicit_With;
|
856 |
|
|
while Present (Clause) loop
|
857 |
|
|
if Parent (Clause) = Cunit (Current_Sem_Unit) then
|
858 |
|
|
return;
|
859 |
|
|
end if;
|
860 |
|
|
|
861 |
|
|
Clause := Next_Implicit_With (Clause);
|
862 |
|
|
end loop;
|
863 |
|
|
|
864 |
|
|
Withn :=
|
865 |
|
|
Make_With_Clause (Standard_Location,
|
866 |
|
|
Name =>
|
867 |
|
|
Make_Unit_Name
|
868 |
|
|
(U, Defining_Unit_Name (Specification (LibUnit))));
|
869 |
|
|
|
870 |
|
|
Set_Library_Unit (Withn, Cunit (U.Unum));
|
871 |
|
|
Set_Corresponding_Spec (Withn, U.Entity);
|
872 |
|
|
Set_First_Name (Withn, True);
|
873 |
|
|
Set_Implicit_With (Withn, True);
|
874 |
|
|
Set_Next_Implicit_With (Withn, U.First_Implicit_With);
|
875 |
|
|
|
876 |
|
|
U.First_Implicit_With := Withn;
|
877 |
|
|
|
878 |
|
|
Mark_Rewrite_Insertion (Withn);
|
879 |
|
|
Append (Withn, Context_Items (Cunit (Current_Sem_Unit)));
|
880 |
|
|
Check_Restriction_No_Dependence (Name (Withn), Current_Error_Node);
|
881 |
|
|
end;
|
882 |
|
|
end Maybe_Add_With;
|
883 |
|
|
|
884 |
|
|
------------------------
|
885 |
|
|
-- Output_Entity_Name --
|
886 |
|
|
------------------------
|
887 |
|
|
|
888 |
|
|
procedure Output_Entity_Name (Id : RE_Id; Msg : String) is
|
889 |
|
|
M : String (1 .. 2048);
|
890 |
|
|
P : Natural := 0;
|
891 |
|
|
-- M (1 .. P) is current message to be output
|
892 |
|
|
|
893 |
|
|
RE_Image : constant String := RE_Id'Image (Id);
|
894 |
|
|
|
895 |
|
|
begin
|
896 |
|
|
if Id = RE_Null then
|
897 |
|
|
return;
|
898 |
|
|
end if;
|
899 |
|
|
|
900 |
|
|
M (1 .. 9) := "\entity """;
|
901 |
|
|
P := 9;
|
902 |
|
|
|
903 |
|
|
-- Add unit name to message, excluding %s or %b at end
|
904 |
|
|
|
905 |
|
|
Get_Name_String (Get_Unit_Name (RE_Unit_Table (Id)));
|
906 |
|
|
Name_Len := Name_Len - 2;
|
907 |
|
|
Set_Casing (Mixed_Case);
|
908 |
|
|
M (P + 1 .. P + Name_Len) := Name_Buffer (1 .. Name_Len);
|
909 |
|
|
P := P + Name_Len;
|
910 |
|
|
|
911 |
|
|
-- Add a qualifying period
|
912 |
|
|
|
913 |
|
|
M (P + 1) := '.';
|
914 |
|
|
P := P + 1;
|
915 |
|
|
|
916 |
|
|
-- Add entity name and closing quote to message
|
917 |
|
|
|
918 |
|
|
Name_Len := RE_Image'Length - 3;
|
919 |
|
|
Name_Buffer (1 .. Name_Len) := RE_Image (4 .. RE_Image'Length);
|
920 |
|
|
Set_Casing (Mixed_Case);
|
921 |
|
|
M (P + 1 .. P + Name_Len) := Name_Buffer (1 .. Name_Len);
|
922 |
|
|
P := P + Name_Len;
|
923 |
|
|
M (P + 1) := '"';
|
924 |
|
|
P := P + 1;
|
925 |
|
|
|
926 |
|
|
-- Add message
|
927 |
|
|
|
928 |
|
|
M (P + 1) := ' ';
|
929 |
|
|
P := P + 1;
|
930 |
|
|
M (P + 1 .. P + Msg'Length) := Msg;
|
931 |
|
|
P := P + Msg'Length;
|
932 |
|
|
|
933 |
|
|
-- Output message at current error node location
|
934 |
|
|
|
935 |
|
|
RTE_Error_Msg (M (1 .. P));
|
936 |
|
|
end Output_Entity_Name;
|
937 |
|
|
|
938 |
|
|
--------------
|
939 |
|
|
-- RE_Chars --
|
940 |
|
|
--------------
|
941 |
|
|
|
942 |
|
|
function RE_Chars (E : RE_Id) return Name_Id is
|
943 |
|
|
RE_Name_Chars : constant String := RE_Id'Image (E);
|
944 |
|
|
|
945 |
|
|
begin
|
946 |
|
|
-- Copy name skipping initial RE_ or RO_XX characters
|
947 |
|
|
|
948 |
|
|
if RE_Name_Chars (1 .. 2) = "RE" then
|
949 |
|
|
for J in 4 .. RE_Name_Chars'Last loop
|
950 |
|
|
Name_Buffer (J - 3) := Fold_Lower (RE_Name_Chars (J));
|
951 |
|
|
end loop;
|
952 |
|
|
|
953 |
|
|
Name_Len := RE_Name_Chars'Length - 3;
|
954 |
|
|
|
955 |
|
|
else
|
956 |
|
|
for J in 7 .. RE_Name_Chars'Last loop
|
957 |
|
|
Name_Buffer (J - 6) := Fold_Lower (RE_Name_Chars (J));
|
958 |
|
|
end loop;
|
959 |
|
|
|
960 |
|
|
Name_Len := RE_Name_Chars'Length - 6;
|
961 |
|
|
end if;
|
962 |
|
|
|
963 |
|
|
return Name_Find;
|
964 |
|
|
end RE_Chars;
|
965 |
|
|
|
966 |
|
|
---------
|
967 |
|
|
-- RTE --
|
968 |
|
|
---------
|
969 |
|
|
|
970 |
|
|
function RTE (E : RE_Id) return Entity_Id is
|
971 |
|
|
U_Id : constant RTU_Id := RE_Unit_Table (E);
|
972 |
|
|
U : RT_Unit_Table_Record renames RT_Unit_Table (U_Id);
|
973 |
|
|
|
974 |
|
|
Lib_Unit : Node_Id;
|
975 |
|
|
Pkg_Ent : Entity_Id;
|
976 |
|
|
Ename : Name_Id;
|
977 |
|
|
|
978 |
|
|
-- The following flag is used to disable front-end inlining when RTE
|
979 |
|
|
-- is invoked. This prevents the analysis of other runtime bodies when
|
980 |
|
|
-- a particular spec is loaded through Rtsfind. This is both efficient,
|
981 |
|
|
-- and it prevents spurious visibility conflicts between use-visible
|
982 |
|
|
-- user entities, and entities in run-time packages.
|
983 |
|
|
|
984 |
|
|
Save_Front_End_Inlining : Boolean;
|
985 |
|
|
|
986 |
|
|
procedure Check_RPC;
|
987 |
|
|
-- Reject programs that make use of distribution features not supported
|
988 |
|
|
-- on the current target. Also check that the PCS is compatible with
|
989 |
|
|
-- the code generator version. On such targets (VMS, Vxworks, others?)
|
990 |
|
|
-- we provide a minimal body for System.Rpc that only supplies an
|
991 |
|
|
-- implementation of Partition_Id.
|
992 |
|
|
|
993 |
|
|
function Find_Local_Entity (E : RE_Id) return Entity_Id;
|
994 |
|
|
-- This function is used when entity E is in this compilation's main
|
995 |
|
|
-- unit. It gets the value from the already compiled declaration.
|
996 |
|
|
|
997 |
|
|
---------------
|
998 |
|
|
-- Check_RPC --
|
999 |
|
|
---------------
|
1000 |
|
|
|
1001 |
|
|
procedure Check_RPC is
|
1002 |
|
|
begin
|
1003 |
|
|
-- Bypass this check if debug flag -gnatdR set
|
1004 |
|
|
|
1005 |
|
|
if Debug_Flag_RR then
|
1006 |
|
|
return;
|
1007 |
|
|
end if;
|
1008 |
|
|
|
1009 |
|
|
-- Otherwise we need the check if we are going after one of the
|
1010 |
|
|
-- critical entities in System.RPC / System.Partition_Interface.
|
1011 |
|
|
|
1012 |
|
|
if E = RE_Do_Rpc
|
1013 |
|
|
or else
|
1014 |
|
|
E = RE_Do_Apc
|
1015 |
|
|
or else
|
1016 |
|
|
E = RE_Params_Stream_Type
|
1017 |
|
|
or else
|
1018 |
|
|
E = RE_Request_Access
|
1019 |
|
|
then
|
1020 |
|
|
-- If generating RCI stubs, check that we have a real PCS
|
1021 |
|
|
|
1022 |
|
|
if (Distribution_Stub_Mode = Generate_Receiver_Stub_Body
|
1023 |
|
|
or else
|
1024 |
|
|
Distribution_Stub_Mode = Generate_Caller_Stub_Body)
|
1025 |
|
|
and then Get_PCS_Name = Name_No_DSA
|
1026 |
|
|
then
|
1027 |
|
|
Set_Standard_Error;
|
1028 |
|
|
Write_Str ("distribution feature not supported");
|
1029 |
|
|
Write_Eol;
|
1030 |
|
|
raise Unrecoverable_Error;
|
1031 |
|
|
|
1032 |
|
|
-- In all cases, check Exp_Dist and System.Partition_Interface
|
1033 |
|
|
-- consistency.
|
1034 |
|
|
|
1035 |
|
|
elsif Get_PCS_Version /=
|
1036 |
|
|
Exp_Dist.PCS_Version_Number (Get_PCS_Name)
|
1037 |
|
|
then
|
1038 |
|
|
Set_Standard_Error;
|
1039 |
|
|
Write_Str ("PCS version mismatch: expander ");
|
1040 |
|
|
Write_Int (Exp_Dist.PCS_Version_Number (Get_PCS_Name));
|
1041 |
|
|
Write_Str (", PCS (");
|
1042 |
|
|
Write_Name (Get_PCS_Name);
|
1043 |
|
|
Write_Str (") ");
|
1044 |
|
|
Write_Int (Get_PCS_Version);
|
1045 |
|
|
Write_Eol;
|
1046 |
|
|
raise Unrecoverable_Error;
|
1047 |
|
|
end if;
|
1048 |
|
|
end if;
|
1049 |
|
|
end Check_RPC;
|
1050 |
|
|
|
1051 |
|
|
-----------------------
|
1052 |
|
|
-- Find_Local_Entity --
|
1053 |
|
|
-----------------------
|
1054 |
|
|
|
1055 |
|
|
function Find_Local_Entity (E : RE_Id) return Entity_Id is
|
1056 |
|
|
RE_Str : constant String := RE_Id'Image (E);
|
1057 |
|
|
Nam : Name_Id;
|
1058 |
|
|
Ent : Entity_Id;
|
1059 |
|
|
|
1060 |
|
|
Save_Nam : constant String := Name_Buffer (1 .. Name_Len);
|
1061 |
|
|
-- Save name buffer and length over call
|
1062 |
|
|
|
1063 |
|
|
begin
|
1064 |
|
|
Name_Len := Natural'Max (0, RE_Str'Length - 3);
|
1065 |
|
|
Name_Buffer (1 .. Name_Len) :=
|
1066 |
|
|
RE_Str (RE_Str'First + 3 .. RE_Str'Last);
|
1067 |
|
|
|
1068 |
|
|
Nam := Name_Find;
|
1069 |
|
|
Ent := Entity_Id (Get_Name_Table_Info (Nam));
|
1070 |
|
|
|
1071 |
|
|
Name_Len := Save_Nam'Length;
|
1072 |
|
|
Name_Buffer (1 .. Name_Len) := Save_Nam;
|
1073 |
|
|
|
1074 |
|
|
return Ent;
|
1075 |
|
|
end Find_Local_Entity;
|
1076 |
|
|
|
1077 |
|
|
-- Start of processing for RTE
|
1078 |
|
|
|
1079 |
|
|
begin
|
1080 |
|
|
-- Doing a rtsfind in system.ads is special, as we cannot do this
|
1081 |
|
|
-- when compiling System itself. So if we are compiling system then
|
1082 |
|
|
-- we should already have acquired and processed the declaration
|
1083 |
|
|
-- of the entity. The test is to see if this compilation's main unit
|
1084 |
|
|
-- is System. If so, return the value from the already compiled
|
1085 |
|
|
-- declaration and otherwise do a regular find.
|
1086 |
|
|
|
1087 |
|
|
-- Not pleasant, but these kinds of annoying recursion when
|
1088 |
|
|
-- writing an Ada compiler in Ada have to be broken somewhere!
|
1089 |
|
|
|
1090 |
|
|
if Present (Main_Unit_Entity)
|
1091 |
|
|
and then Chars (Main_Unit_Entity) = Name_System
|
1092 |
|
|
and then Analyzed (Main_Unit_Entity)
|
1093 |
|
|
and then not Is_Child_Unit (Main_Unit_Entity)
|
1094 |
|
|
then
|
1095 |
|
|
return Check_CRT (E, Find_Local_Entity (E));
|
1096 |
|
|
end if;
|
1097 |
|
|
|
1098 |
|
|
Save_Front_End_Inlining := Front_End_Inlining;
|
1099 |
|
|
Front_End_Inlining := False;
|
1100 |
|
|
|
1101 |
|
|
-- Load unit if unit not previously loaded
|
1102 |
|
|
|
1103 |
|
|
if No (RE_Table (E)) then
|
1104 |
|
|
Load_RTU (U_Id, Id => E);
|
1105 |
|
|
Lib_Unit := Unit (Cunit (U.Unum));
|
1106 |
|
|
|
1107 |
|
|
-- In the subprogram case, we are all done, the entity we want
|
1108 |
|
|
-- is the entity for the subprogram itself. Note that we do not
|
1109 |
|
|
-- bother to check that it is the entity that was requested.
|
1110 |
|
|
-- the only way that could fail to be the case is if runtime is
|
1111 |
|
|
-- hopelessly misconfigured, and it isn't worth testing for this.
|
1112 |
|
|
|
1113 |
|
|
if Nkind (Lib_Unit) = N_Subprogram_Declaration then
|
1114 |
|
|
RE_Table (E) := U.Entity;
|
1115 |
|
|
|
1116 |
|
|
-- Otherwise we must have the package case. First check package
|
1117 |
|
|
-- entity itself (e.g. RTE_Name for System.Interrupts.Name)
|
1118 |
|
|
|
1119 |
|
|
else
|
1120 |
|
|
pragma Assert (Nkind (Lib_Unit) = N_Package_Declaration);
|
1121 |
|
|
Ename := RE_Chars (E);
|
1122 |
|
|
|
1123 |
|
|
-- First we search the package entity chain. If the package
|
1124 |
|
|
-- only has a limited view, scan the corresponding list of
|
1125 |
|
|
-- incomplete types.
|
1126 |
|
|
|
1127 |
|
|
if From_With_Type (U.Entity) then
|
1128 |
|
|
Pkg_Ent := First_Entity (Limited_View (U.Entity));
|
1129 |
|
|
else
|
1130 |
|
|
Pkg_Ent := First_Entity (U.Entity);
|
1131 |
|
|
end if;
|
1132 |
|
|
|
1133 |
|
|
while Present (Pkg_Ent) loop
|
1134 |
|
|
if Ename = Chars (Pkg_Ent) then
|
1135 |
|
|
RE_Table (E) := Pkg_Ent;
|
1136 |
|
|
Check_RPC;
|
1137 |
|
|
goto Found;
|
1138 |
|
|
end if;
|
1139 |
|
|
|
1140 |
|
|
Next_Entity (Pkg_Ent);
|
1141 |
|
|
end loop;
|
1142 |
|
|
|
1143 |
|
|
-- If we did not find the entity in the package entity chain,
|
1144 |
|
|
-- then check if the package entity itself matches. Note that
|
1145 |
|
|
-- we do this check after searching the entity chain, since
|
1146 |
|
|
-- the rule is that in case of ambiguity, we prefer the entity
|
1147 |
|
|
-- defined within the package, rather than the package itself.
|
1148 |
|
|
|
1149 |
|
|
if Ename = Chars (U.Entity) then
|
1150 |
|
|
RE_Table (E) := U.Entity;
|
1151 |
|
|
end if;
|
1152 |
|
|
|
1153 |
|
|
-- If we didn't find the entity we want, something is wrong.
|
1154 |
|
|
-- We just leave RE_Table (E) set to Empty and the appropriate
|
1155 |
|
|
-- action will be taken by Check_CRT when we exit.
|
1156 |
|
|
|
1157 |
|
|
end if;
|
1158 |
|
|
end if;
|
1159 |
|
|
|
1160 |
|
|
<<Found>>
|
1161 |
|
|
Maybe_Add_With (U);
|
1162 |
|
|
|
1163 |
|
|
Front_End_Inlining := Save_Front_End_Inlining;
|
1164 |
|
|
return Check_CRT (E, RE_Table (E));
|
1165 |
|
|
end RTE;
|
1166 |
|
|
|
1167 |
|
|
-------------------
|
1168 |
|
|
-- RTE_Available --
|
1169 |
|
|
-------------------
|
1170 |
|
|
|
1171 |
|
|
function RTE_Available (E : RE_Id) return Boolean is
|
1172 |
|
|
Dummy : Entity_Id;
|
1173 |
|
|
pragma Warnings (Off, Dummy);
|
1174 |
|
|
|
1175 |
|
|
Result : Boolean;
|
1176 |
|
|
|
1177 |
|
|
Save_RTE_Available_Call : constant Boolean := RTE_Available_Call;
|
1178 |
|
|
Save_RTE_Is_Available : constant Boolean := RTE_Is_Available;
|
1179 |
|
|
-- These are saved recursively because the call to load a unit
|
1180 |
|
|
-- caused by an upper level call may perform a recursive call
|
1181 |
|
|
-- to this routine during analysis of the corresponding unit.
|
1182 |
|
|
|
1183 |
|
|
begin
|
1184 |
|
|
RTE_Available_Call := True;
|
1185 |
|
|
RTE_Is_Available := True;
|
1186 |
|
|
Dummy := RTE (E);
|
1187 |
|
|
Result := RTE_Is_Available;
|
1188 |
|
|
RTE_Available_Call := Save_RTE_Available_Call;
|
1189 |
|
|
RTE_Is_Available := Save_RTE_Is_Available;
|
1190 |
|
|
return Result;
|
1191 |
|
|
|
1192 |
|
|
exception
|
1193 |
|
|
when RE_Not_Available =>
|
1194 |
|
|
RTE_Available_Call := Save_RTE_Available_Call;
|
1195 |
|
|
RTE_Is_Available := Save_RTE_Is_Available;
|
1196 |
|
|
return False;
|
1197 |
|
|
end RTE_Available;
|
1198 |
|
|
|
1199 |
|
|
--------------------------
|
1200 |
|
|
-- RTE_Record_Component --
|
1201 |
|
|
--------------------------
|
1202 |
|
|
|
1203 |
|
|
function RTE_Record_Component (E : RE_Id) return Entity_Id is
|
1204 |
|
|
U_Id : constant RTU_Id := RE_Unit_Table (E);
|
1205 |
|
|
U : RT_Unit_Table_Record renames RT_Unit_Table (U_Id);
|
1206 |
|
|
E1 : Entity_Id;
|
1207 |
|
|
Ename : Name_Id;
|
1208 |
|
|
Found_E : Entity_Id;
|
1209 |
|
|
Lib_Unit : Node_Id;
|
1210 |
|
|
Pkg_Ent : Entity_Id;
|
1211 |
|
|
|
1212 |
|
|
-- The following flag is used to disable front-end inlining when
|
1213 |
|
|
-- RTE_Record_Component is invoked. This prevents the analysis of other
|
1214 |
|
|
-- runtime bodies when a particular spec is loaded through Rtsfind. This
|
1215 |
|
|
-- is both efficient, and it prevents spurious visibility conflicts
|
1216 |
|
|
-- between use-visible user entities, and entities in run-time packages.
|
1217 |
|
|
|
1218 |
|
|
Save_Front_End_Inlining : Boolean;
|
1219 |
|
|
|
1220 |
|
|
begin
|
1221 |
|
|
-- Note: Contrary to subprogram RTE, there is no need to do any special
|
1222 |
|
|
-- management with package system.ads because it has no record type
|
1223 |
|
|
-- declarations.
|
1224 |
|
|
|
1225 |
|
|
Save_Front_End_Inlining := Front_End_Inlining;
|
1226 |
|
|
Front_End_Inlining := False;
|
1227 |
|
|
|
1228 |
|
|
-- Load unit if unit not previously loaded
|
1229 |
|
|
|
1230 |
|
|
if not Present (U.Entity) then
|
1231 |
|
|
Load_RTU (U_Id, Id => E);
|
1232 |
|
|
end if;
|
1233 |
|
|
|
1234 |
|
|
Lib_Unit := Unit (Cunit (U.Unum));
|
1235 |
|
|
|
1236 |
|
|
pragma Assert (Nkind (Lib_Unit) = N_Package_Declaration);
|
1237 |
|
|
Ename := RE_Chars (E);
|
1238 |
|
|
|
1239 |
|
|
-- Search the entity in the components of record type declarations
|
1240 |
|
|
-- found in the package entity chain.
|
1241 |
|
|
|
1242 |
|
|
Found_E := Empty;
|
1243 |
|
|
Pkg_Ent := First_Entity (U.Entity);
|
1244 |
|
|
Search : while Present (Pkg_Ent) loop
|
1245 |
|
|
if Is_Record_Type (Pkg_Ent) then
|
1246 |
|
|
E1 := First_Entity (Pkg_Ent);
|
1247 |
|
|
while Present (E1) loop
|
1248 |
|
|
if Ename = Chars (E1) then
|
1249 |
|
|
pragma Assert (not Present (Found_E));
|
1250 |
|
|
Found_E := E1;
|
1251 |
|
|
end if;
|
1252 |
|
|
|
1253 |
|
|
Next_Entity (E1);
|
1254 |
|
|
end loop;
|
1255 |
|
|
end if;
|
1256 |
|
|
|
1257 |
|
|
Next_Entity (Pkg_Ent);
|
1258 |
|
|
end loop Search;
|
1259 |
|
|
|
1260 |
|
|
-- If we didn't find the entity we want, something is wrong. The
|
1261 |
|
|
-- appropriate action will be taken by Check_CRT when we exit.
|
1262 |
|
|
|
1263 |
|
|
Maybe_Add_With (U);
|
1264 |
|
|
|
1265 |
|
|
Front_End_Inlining := Save_Front_End_Inlining;
|
1266 |
|
|
return Check_CRT (E, Found_E);
|
1267 |
|
|
end RTE_Record_Component;
|
1268 |
|
|
|
1269 |
|
|
------------------------------------
|
1270 |
|
|
-- RTE_Record_Component_Available --
|
1271 |
|
|
------------------------------------
|
1272 |
|
|
|
1273 |
|
|
function RTE_Record_Component_Available (E : RE_Id) return Boolean is
|
1274 |
|
|
Dummy : Entity_Id;
|
1275 |
|
|
pragma Warnings (Off, Dummy);
|
1276 |
|
|
|
1277 |
|
|
Result : Boolean;
|
1278 |
|
|
|
1279 |
|
|
Save_RTE_Available_Call : constant Boolean := RTE_Available_Call;
|
1280 |
|
|
Save_RTE_Is_Available : constant Boolean := RTE_Is_Available;
|
1281 |
|
|
-- These are saved recursively because the call to load a unit
|
1282 |
|
|
-- caused by an upper level call may perform a recursive call
|
1283 |
|
|
-- to this routine during analysis of the corresponding unit.
|
1284 |
|
|
|
1285 |
|
|
begin
|
1286 |
|
|
RTE_Available_Call := True;
|
1287 |
|
|
RTE_Is_Available := True;
|
1288 |
|
|
Dummy := RTE_Record_Component (E);
|
1289 |
|
|
Result := RTE_Is_Available;
|
1290 |
|
|
RTE_Available_Call := Save_RTE_Available_Call;
|
1291 |
|
|
RTE_Is_Available := Save_RTE_Is_Available;
|
1292 |
|
|
return Result;
|
1293 |
|
|
|
1294 |
|
|
exception
|
1295 |
|
|
when RE_Not_Available =>
|
1296 |
|
|
RTE_Available_Call := Save_RTE_Available_Call;
|
1297 |
|
|
RTE_Is_Available := Save_RTE_Is_Available;
|
1298 |
|
|
return False;
|
1299 |
|
|
end RTE_Record_Component_Available;
|
1300 |
|
|
|
1301 |
|
|
-------------------
|
1302 |
|
|
-- RTE_Error_Msg --
|
1303 |
|
|
-------------------
|
1304 |
|
|
|
1305 |
|
|
procedure RTE_Error_Msg (Msg : String) is
|
1306 |
|
|
begin
|
1307 |
|
|
if RTE_Available_Call then
|
1308 |
|
|
RTE_Is_Available := False;
|
1309 |
|
|
else
|
1310 |
|
|
Error_Msg_N (Msg, Current_Error_Node);
|
1311 |
|
|
|
1312 |
|
|
-- Bump count of violations if we are in configurable run-time
|
1313 |
|
|
-- mode and this is not a continuation message.
|
1314 |
|
|
|
1315 |
|
|
if Configurable_Run_Time_Mode and then Msg (Msg'First) /= '\' then
|
1316 |
|
|
Configurable_Run_Time_Violations :=
|
1317 |
|
|
Configurable_Run_Time_Violations + 1;
|
1318 |
|
|
end if;
|
1319 |
|
|
end if;
|
1320 |
|
|
end RTE_Error_Msg;
|
1321 |
|
|
|
1322 |
|
|
----------------
|
1323 |
|
|
-- RTU_Entity --
|
1324 |
|
|
----------------
|
1325 |
|
|
|
1326 |
|
|
function RTU_Entity (U : RTU_Id) return Entity_Id is
|
1327 |
|
|
begin
|
1328 |
|
|
return RT_Unit_Table (U).Entity;
|
1329 |
|
|
end RTU_Entity;
|
1330 |
|
|
|
1331 |
|
|
----------------
|
1332 |
|
|
-- RTU_Loaded --
|
1333 |
|
|
----------------
|
1334 |
|
|
|
1335 |
|
|
function RTU_Loaded (U : RTU_Id) return Boolean is
|
1336 |
|
|
begin
|
1337 |
|
|
return Present (RT_Unit_Table (U).Entity);
|
1338 |
|
|
end RTU_Loaded;
|
1339 |
|
|
|
1340 |
|
|
--------------------
|
1341 |
|
|
-- Set_RTU_Loaded --
|
1342 |
|
|
--------------------
|
1343 |
|
|
|
1344 |
|
|
procedure Set_RTU_Loaded (N : Node_Id) is
|
1345 |
|
|
Loc : constant Source_Ptr := Sloc (N);
|
1346 |
|
|
Unum : constant Unit_Number_Type := Get_Source_Unit (Loc);
|
1347 |
|
|
Uname : constant Unit_Name_Type := Unit_Name (Unum);
|
1348 |
|
|
E : constant Entity_Id :=
|
1349 |
|
|
Defining_Entity (Unit (Cunit (Unum)));
|
1350 |
|
|
begin
|
1351 |
|
|
pragma Assert (Is_Predefined_File_Name (Unit_File_Name (Unum)));
|
1352 |
|
|
|
1353 |
|
|
-- Loop through entries in RTU table looking for matching entry
|
1354 |
|
|
|
1355 |
|
|
for U_Id in RTU_Id'Range loop
|
1356 |
|
|
|
1357 |
|
|
-- Here we have a match
|
1358 |
|
|
|
1359 |
|
|
if Get_Unit_Name (U_Id) = Uname then
|
1360 |
|
|
declare
|
1361 |
|
|
U : RT_Unit_Table_Record renames RT_Unit_Table (U_Id);
|
1362 |
|
|
-- The RT_Unit_Table entry that may need updating
|
1363 |
|
|
|
1364 |
|
|
begin
|
1365 |
|
|
-- If entry is not set, set it now, and indicate that it was
|
1366 |
|
|
-- loaded through an explicit context clause.
|
1367 |
|
|
|
1368 |
|
|
if No (U.Entity) then
|
1369 |
|
|
U := (Entity => E,
|
1370 |
|
|
Uname => Get_Unit_Name (U_Id),
|
1371 |
|
|
Unum => Unum,
|
1372 |
|
|
First_Implicit_With => Empty);
|
1373 |
|
|
end if;
|
1374 |
|
|
|
1375 |
|
|
return;
|
1376 |
|
|
end;
|
1377 |
|
|
end if;
|
1378 |
|
|
end loop;
|
1379 |
|
|
end Set_RTU_Loaded;
|
1380 |
|
|
|
1381 |
|
|
--------------------
|
1382 |
|
|
-- Text_IO_Kludge --
|
1383 |
|
|
--------------------
|
1384 |
|
|
|
1385 |
|
|
procedure Text_IO_Kludge (Nam : Node_Id) is
|
1386 |
|
|
Chrs : Name_Id;
|
1387 |
|
|
|
1388 |
|
|
type Name_Map_Type is array (Text_IO_Package_Name) of RTU_Id;
|
1389 |
|
|
|
1390 |
|
|
Name_Map : constant Name_Map_Type := Name_Map_Type'(
|
1391 |
|
|
Name_Decimal_IO => Ada_Text_IO_Decimal_IO,
|
1392 |
|
|
Name_Enumeration_IO => Ada_Text_IO_Enumeration_IO,
|
1393 |
|
|
Name_Fixed_IO => Ada_Text_IO_Fixed_IO,
|
1394 |
|
|
Name_Float_IO => Ada_Text_IO_Float_IO,
|
1395 |
|
|
Name_Integer_IO => Ada_Text_IO_Integer_IO,
|
1396 |
|
|
Name_Modular_IO => Ada_Text_IO_Modular_IO);
|
1397 |
|
|
|
1398 |
|
|
Wide_Name_Map : constant Name_Map_Type := Name_Map_Type'(
|
1399 |
|
|
Name_Decimal_IO => Ada_Wide_Text_IO_Decimal_IO,
|
1400 |
|
|
Name_Enumeration_IO => Ada_Wide_Text_IO_Enumeration_IO,
|
1401 |
|
|
Name_Fixed_IO => Ada_Wide_Text_IO_Fixed_IO,
|
1402 |
|
|
Name_Float_IO => Ada_Wide_Text_IO_Float_IO,
|
1403 |
|
|
Name_Integer_IO => Ada_Wide_Text_IO_Integer_IO,
|
1404 |
|
|
Name_Modular_IO => Ada_Wide_Text_IO_Modular_IO);
|
1405 |
|
|
|
1406 |
|
|
Wide_Wide_Name_Map : constant Name_Map_Type := Name_Map_Type'(
|
1407 |
|
|
Name_Decimal_IO => Ada_Wide_Wide_Text_IO_Decimal_IO,
|
1408 |
|
|
Name_Enumeration_IO => Ada_Wide_Wide_Text_IO_Enumeration_IO,
|
1409 |
|
|
Name_Fixed_IO => Ada_Wide_Wide_Text_IO_Fixed_IO,
|
1410 |
|
|
Name_Float_IO => Ada_Wide_Wide_Text_IO_Float_IO,
|
1411 |
|
|
Name_Integer_IO => Ada_Wide_Wide_Text_IO_Integer_IO,
|
1412 |
|
|
Name_Modular_IO => Ada_Wide_Wide_Text_IO_Modular_IO);
|
1413 |
|
|
|
1414 |
|
|
To_Load : RTU_Id;
|
1415 |
|
|
-- Unit to be loaded, from one of the above maps
|
1416 |
|
|
|
1417 |
|
|
begin
|
1418 |
|
|
-- Nothing to do if name is not an identifier or a selected component
|
1419 |
|
|
-- whose selector_name is an identifier.
|
1420 |
|
|
|
1421 |
|
|
if Nkind (Nam) = N_Identifier then
|
1422 |
|
|
Chrs := Chars (Nam);
|
1423 |
|
|
|
1424 |
|
|
elsif Nkind (Nam) = N_Selected_Component
|
1425 |
|
|
and then Nkind (Selector_Name (Nam)) = N_Identifier
|
1426 |
|
|
then
|
1427 |
|
|
Chrs := Chars (Selector_Name (Nam));
|
1428 |
|
|
|
1429 |
|
|
else
|
1430 |
|
|
return;
|
1431 |
|
|
end if;
|
1432 |
|
|
|
1433 |
|
|
-- Nothing to do if name is not one of the Text_IO subpackages
|
1434 |
|
|
-- Otherwise look through loaded units, and if we find Text_IO
|
1435 |
|
|
-- or [Wide_]Wide_Text_IO already loaded, then load the proper child.
|
1436 |
|
|
|
1437 |
|
|
if Chrs in Text_IO_Package_Name then
|
1438 |
|
|
for U in Main_Unit .. Last_Unit loop
|
1439 |
|
|
Get_Name_String (Unit_File_Name (U));
|
1440 |
|
|
|
1441 |
|
|
if Name_Len = 12 then
|
1442 |
|
|
|
1443 |
|
|
-- Here is where we do the loads if we find one of the units
|
1444 |
|
|
-- Ada.Text_IO or Ada.[Wide_]Wide_Text_IO. An interesting
|
1445 |
|
|
-- detail is that these units may already be used (i.e. their
|
1446 |
|
|
-- In_Use flags may be set). Normally when the In_Use flag is
|
1447 |
|
|
-- set, the Is_Potentially_Use_Visible flag of all entities in
|
1448 |
|
|
-- the package is set, but the new entity we are mysteriously
|
1449 |
|
|
-- adding was not there to have its flag set at the time. So
|
1450 |
|
|
-- that's why we pass the extra parameter to RTU_Find, to make
|
1451 |
|
|
-- sure the flag does get set now. Given that those generic
|
1452 |
|
|
-- packages are in fact child units, we must indicate that
|
1453 |
|
|
-- they are visible.
|
1454 |
|
|
|
1455 |
|
|
if Name_Buffer (1 .. 12) = "a-textio.ads" then
|
1456 |
|
|
To_Load := Name_Map (Chrs);
|
1457 |
|
|
|
1458 |
|
|
elsif Name_Buffer (1 .. 12) = "a-witeio.ads" then
|
1459 |
|
|
To_Load := Wide_Name_Map (Chrs);
|
1460 |
|
|
|
1461 |
|
|
elsif Name_Buffer (1 .. 12) = "a-ztexio.ads" then
|
1462 |
|
|
To_Load := Wide_Wide_Name_Map (Chrs);
|
1463 |
|
|
|
1464 |
|
|
else
|
1465 |
|
|
goto Continue;
|
1466 |
|
|
end if;
|
1467 |
|
|
|
1468 |
|
|
Load_RTU (To_Load, Use_Setting => In_Use (Cunit_Entity (U)));
|
1469 |
|
|
Set_Is_Visible_Child_Unit (RT_Unit_Table (To_Load).Entity);
|
1470 |
|
|
|
1471 |
|
|
-- Prevent creation of an implicit 'with' from (for example)
|
1472 |
|
|
-- Ada.Wide_Text_IO.Integer_IO to Ada.Text_IO.Integer_IO,
|
1473 |
|
|
-- because these could create cycles. First check whether the
|
1474 |
|
|
-- simple names match ("integer_io" = "integer_io"), and then
|
1475 |
|
|
-- check whether the parent is indeed one of the
|
1476 |
|
|
-- [[Wide_]Wide_]Text_IO packages.
|
1477 |
|
|
|
1478 |
|
|
if Chrs = Chars (Cunit_Entity (Current_Sem_Unit)) then
|
1479 |
|
|
declare
|
1480 |
|
|
Parent_Name : constant Unit_Name_Type :=
|
1481 |
|
|
Get_Parent_Spec_Name
|
1482 |
|
|
(Unit_Name (Current_Sem_Unit));
|
1483 |
|
|
|
1484 |
|
|
begin
|
1485 |
|
|
if Parent_Name /= No_Unit_Name then
|
1486 |
|
|
Get_Name_String (Parent_Name);
|
1487 |
|
|
|
1488 |
|
|
declare
|
1489 |
|
|
P : String renames Name_Buffer (1 .. Name_Len);
|
1490 |
|
|
begin
|
1491 |
|
|
if P = "ada.text_io%s" or else
|
1492 |
|
|
P = "ada.wide_text_io%s" or else
|
1493 |
|
|
P = "ada.wide_wide_text_io%s"
|
1494 |
|
|
then
|
1495 |
|
|
goto Continue;
|
1496 |
|
|
end if;
|
1497 |
|
|
end;
|
1498 |
|
|
end if;
|
1499 |
|
|
end;
|
1500 |
|
|
end if;
|
1501 |
|
|
|
1502 |
|
|
-- Add an implicit with clause from the current unit to the
|
1503 |
|
|
-- [[Wide_]Wide_]Text_IO child (if necessary).
|
1504 |
|
|
|
1505 |
|
|
Maybe_Add_With (RT_Unit_Table (To_Load));
|
1506 |
|
|
end if;
|
1507 |
|
|
|
1508 |
|
|
<<Continue>> null;
|
1509 |
|
|
end loop;
|
1510 |
|
|
end if;
|
1511 |
|
|
|
1512 |
|
|
exception
|
1513 |
|
|
-- Generate error message if run-time unit not available
|
1514 |
|
|
|
1515 |
|
|
when RE_Not_Available =>
|
1516 |
|
|
Error_Msg_N ("& not available", Nam);
|
1517 |
|
|
end Text_IO_Kludge;
|
1518 |
|
|
|
1519 |
|
|
end Rtsfind;
|