1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
11 -- Copyright (C) 1992-2001 Free Software Foundation, Inc. --
13 -- GNAT is free software; you can redistribute it and/or modify it under --
14 -- terms of the GNU General Public License as published by the Free Soft- --
15 -- ware Foundation; either version 2, or (at your option) any later ver- --
16 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
17 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
18 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
19 -- for more details. You should have received a copy of the GNU General --
20 -- Public License distributed with GNAT; see file COPYING. If not, write --
21 -- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, --
22 -- MA 02111-1307, USA. --
24 -- GNAT was originally developed by the GNAT team at New York University. --
25 -- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
27 ------------------------------------------------------------------------------
30 with Atree
; use Atree
;
31 with Debug
; use Debug
;
32 with Einfo
; use Einfo
;
33 with Namet
; use Namet
;
35 with Osint
; use Osint
;
36 with Output
; use Output
;
37 with Scans
; use Scans
;
39 with Sinfo
; use Sinfo
;
40 with System
; use System
;
42 with Unchecked_Conversion
;
44 package body Sinput
.L
is
46 Dfile
: Source_File_Index
;
47 -- Index of currently active debug source file
53 procedure Trim_Lines_Table
(S
: Source_File_Index
);
54 -- Set lines table size for entry S in the source file table to
55 -- correspond to the current value of Num_Source_Lines, releasing
56 -- any unused storage.
61 return Source_File_Index
;
62 -- Load a source file or a configuration pragma file.
64 -------------------------------
65 -- Adjust_Instantiation_Sloc --
66 -------------------------------
68 procedure Adjust_Instantiation_Sloc
(N
: Node_Id
; A
: Sloc_Adjustment
) is
69 Loc
: constant Source_Ptr
:= Sloc
(N
);
72 -- We only do the adjustment if the value is between the appropriate
73 -- low and high values. It is not clear that this should ever not be
74 -- the case, but in practice there seem to be some nodes that get
75 -- copied twice, and this is a defence against that happening.
77 if A
.Lo
<= Loc
and then Loc
<= A
.Hi
then
78 Set_Sloc
(N
, Loc
+ A
.Adjust
);
80 end Adjust_Instantiation_Sloc
;
82 ------------------------
83 -- Close_Debug_Source --
84 ------------------------
86 procedure Close_Debug_Source
is
87 S
: Source_File_Record
renames Source_File
.Table
(Dfile
);
88 Src
: Source_Buffer_Ptr
;
91 Trim_Lines_Table
(Dfile
);
94 -- Now we need to read the file that we wrote and store it
95 -- in memory for subsequent access.
98 (S
.Debug_Source_Name
, S
.Source_First
, S
.Source_Last
, Src
);
100 end Close_Debug_Source
;
102 --------------------------------
103 -- Complete_Source_File_Entry --
104 --------------------------------
106 procedure Complete_Source_File_Entry
is
107 CSF
: constant Source_File_Index
:= Current_Source_File
;
110 Trim_Lines_Table
(CSF
);
111 Source_File
.Table
(CSF
).Source_Checksum
:= Checksum
;
112 end Complete_Source_File_Entry
;
114 -------------------------
115 -- Create_Debug_Source --
116 -------------------------
118 procedure Create_Debug_Source
119 (Source
: Source_File_Index
;
120 Loc
: out Source_Ptr
)
123 Loc
:= Source_File
.Table
(Source_File
.Last
).Source_Last
+ 1;
124 Source_File
.Increment_Last
;
125 Dfile
:= Source_File
.Last
;
128 S
: Source_File_Record
renames Source_File
.Table
(Dfile
);
131 S
:= Source_File
.Table
(Source
);
132 S
.Debug_Source_Name
:= Create_Debug_File
(S
.File_Name
);
133 S
.Source_First
:= Loc
;
134 S
.Source_Last
:= Loc
;
135 S
.Lines_Table
:= null;
136 S
.Last_Source_Line
:= 1;
138 -- Allocate lines table, guess that it needs to be three times
139 -- bigger than the original source (in number of lines).
142 (S
, Int
(Source_File
.Table
(Source
).Last_Source_Line
* 3));
143 S
.Lines_Table
(1) := Loc
;
146 if Debug_Flag_GG
then
147 Write_Str
("---> Create_Debug_Source (Source => ");
148 Write_Int
(Int
(Source
));
149 Write_Str
(", Loc => ");
150 Write_Int
(Int
(Loc
));
155 end Create_Debug_Source
;
157 ---------------------------------
158 -- Create_Instantiation_Source --
159 ---------------------------------
161 procedure Create_Instantiation_Source
162 (Inst_Node
: Entity_Id
;
163 Template_Id
: Entity_Id
;
164 A
: out Sloc_Adjustment
)
166 Dnod
: constant Node_Id
:= Declaration_Node
(Template_Id
);
167 Xold
: Source_File_Index
;
168 Xnew
: Source_File_Index
;
171 Xold
:= Get_Source_File_Index
(Sloc
(Template_Id
));
172 A
.Lo
:= Source_File
.Table
(Xold
).Source_First
;
173 A
.Hi
:= Source_File
.Table
(Xold
).Source_Last
;
175 Source_File
.Increment_Last
;
176 Xnew
:= Source_File
.Last
;
178 Source_File
.Table
(Xnew
) := Source_File
.Table
(Xold
);
179 Source_File
.Table
(Xnew
).Instantiation
:= Sloc
(Inst_Node
);
180 Source_File
.Table
(Xnew
).Template
:= Xold
;
182 -- Now we need to compute the new values of Source_First, Source_Last
183 -- and adjust the source file pointer to have the correct virtual
184 -- origin for the new range of values.
186 Source_File
.Table
(Xnew
).Source_First
:=
187 Source_File
.Table
(Xnew
- 1).Source_Last
+ 1;
189 A
.Adjust
:= Source_File
.Table
(Xnew
).Source_First
- A
.Lo
;
190 Source_File
.Table
(Xnew
).Source_Last
:= A
.Hi
+ A
.Adjust
;
192 Source_File
.Table
(Xnew
).Sloc_Adjust
:=
193 Source_File
.Table
(Xold
).Sloc_Adjust
- A
.Adjust
;
197 Write_Str
("*** Create instantiation source for ");
199 if Nkind
(Dnod
) in N_Proper_Body
200 and then Was_Originally_Stub
(Dnod
)
202 Write_Str
("subunit ");
204 elsif Ekind
(Template_Id
) = E_Generic_Package
then
205 if Nkind
(Dnod
) = N_Package_Body
then
206 Write_Str
("body of package ");
208 Write_Str
("spec of package ");
211 elsif Ekind
(Template_Id
) = E_Function
then
212 Write_Str
("body of function ");
214 elsif Ekind
(Template_Id
) = E_Procedure
then
215 Write_Str
("body of procedure ");
217 elsif Ekind
(Template_Id
) = E_Generic_Function
then
218 Write_Str
("spec of function ");
220 elsif Ekind
(Template_Id
) = E_Generic_Procedure
then
221 Write_Str
("spec of procedure ");
223 elsif Ekind
(Template_Id
) = E_Package_Body
then
224 Write_Str
("body of package ");
226 else pragma Assert
(Ekind
(Template_Id
) = E_Subprogram_Body
);
228 if Nkind
(Dnod
) = N_Procedure_Specification
then
229 Write_Str
("body of procedure ");
231 Write_Str
("body of function ");
235 Write_Name
(Chars
(Template_Id
));
238 Write_Str
(" new source index = ");
239 Write_Int
(Int
(Xnew
));
242 Write_Str
(" copying from file name = ");
243 Write_Name
(File_Name
(Xold
));
246 Write_Str
(" old source index = ");
247 Write_Int
(Int
(Xold
));
250 Write_Str
(" old lo = ");
251 Write_Int
(Int
(A
.Lo
));
254 Write_Str
(" old hi = ");
255 Write_Int
(Int
(A
.Hi
));
258 Write_Str
(" new lo = ");
259 Write_Int
(Int
(Source_File
.Table
(Xnew
).Source_First
));
262 Write_Str
(" new hi = ");
263 Write_Int
(Int
(Source_File
.Table
(Xnew
).Source_Last
));
266 Write_Str
(" adjustment factor = ");
267 Write_Int
(Int
(A
.Adjust
));
270 Write_Str
(" instantiation location: ");
271 Write_Location
(Sloc
(Inst_Node
));
275 -- For a given character in the source, a higher subscript will be
276 -- used to access the instantiation, which means that the virtual
277 -- origin must have a corresponding lower value. We compute this
278 -- new origin by taking the address of the appropriate adjusted
279 -- element in the old array. Since this adjusted element will be
280 -- at a negative subscript, we must suppress checks.
283 pragma Suppress
(All_Checks
);
285 function To_Source_Buffer_Ptr
is new
286 Unchecked_Conversion
(Address
, Source_Buffer_Ptr
);
289 Source_File
.Table
(Xnew
).Source_Text
:=
291 (Source_File
.Table
(Xold
).Source_Text
(-A
.Adjust
)'Address);
294 end Create_Instantiation_Source
;
296 ----------------------
297 -- Load_Config_File --
298 ----------------------
300 function Load_Config_File
302 return Source_File_Index
305 return Load_File
(N
, Osint
.Config
);
306 end Load_Config_File
;
315 return Source_File_Index
317 Src
: Source_Buffer_Ptr
;
318 X
: Source_File_Index
;
323 for J
in 1 .. Source_File
.Last
loop
324 if Source_File
.Table
(J
).File_Name
= N
then
329 -- Here we must build a new entry in the file table
331 Source_File
.Increment_Last
;
332 X
:= Source_File
.Last
;
334 if X
= Source_File
.First
then
335 Lo
:= First_Source_Ptr
;
337 Lo
:= Source_File
.Table
(X
- 1).Source_Last
+ 1;
340 Read_Source_File
(N
, Lo
, Hi
, Src
, T
);
343 Source_File
.Decrement_Last
;
344 return No_Source_File
;
349 Write_Str
("*** Build source file table entry, Index = ");
351 Write_Str
(", file name = ");
354 Write_Str
(" lo = ");
355 Write_Int
(Int
(Lo
));
357 Write_Str
(" hi = ");
358 Write_Int
(Int
(Hi
));
361 Write_Str
(" first 10 chars -->");
364 procedure Wchar
(C
: Character);
365 -- Writes character or ? for control character
367 procedure Wchar
(C
: Character) is
369 if C
< ' ' or C
in ASCII
.DEL
.. Character'Val (16#
9F#
) then
377 for J
in Lo
.. Lo
+ 9 loop
384 Write_Str
(" last 10 chars -->");
386 for J
in Hi
- 10 .. Hi
- 1 loop
393 if Src
(Hi
) /= EOF
then
394 Write_Str
(" error: no EOF at end");
401 S
: Source_File_Record
renames Source_File
.Table
(X
);
404 S
:= (Debug_Source_Name
=> Full_Source_Name
,
406 First_Mapped_Line
=> No_Line_Number
,
407 Full_File_Name
=> Full_Source_Name
,
408 Full_Ref_Name
=> Full_Source_Name
,
409 Identifier_Casing
=> Unknown
,
410 Instantiation
=> No_Location
,
411 Keyword_Casing
=> Unknown
,
412 Last_Source_Line
=> 1,
415 Lines_Table_Max
=> 1,
416 Logical_Lines_Table
=> null,
417 Num_SRef_Pragmas
=> 0,
420 Source_Checksum
=> 0,
424 Template
=> No_Source_File
,
425 Time_Stamp
=> Current_Source_File_Stamp
);
427 Alloc_Line_Tables
(S
, Opt
.Table_Factor
* Alloc
.Lines_Initial
);
428 S
.Lines_Table
(1) := Lo
;
435 ----------------------
436 -- Load_Source_File --
437 ----------------------
439 function Load_Source_File
441 return Source_File_Index
444 return Load_File
(N
, Osint
.Source
);
445 end Load_Source_File
;
447 ----------------------------
448 -- Source_File_Is_Subunit --
449 ----------------------------
451 function Source_File_Is_Subunit
(X
: Source_File_Index
) return Boolean is
453 Initialize_Scanner
(No_Unit
, X
);
455 -- We scan past junk to the first interesting compilation unit
456 -- token, to see if it is SEPARATE. We ignore WITH keywords during
457 -- this and also PRIVATE. The reason for ignoring PRIVATE is that
458 -- it handles some error situations, and also it is possible that
459 -- a PRIVATE WITH feature might be approved some time in the future.
461 while Token
= Tok_With
462 or else Token
= Tok_Private
463 or else (Token
not in Token_Class_Cunit
and then Token
/= Tok_EOF
)
468 return Token
= Tok_Separate
;
469 end Source_File_Is_Subunit
;
471 ----------------------
472 -- Trim_Lines_Table --
473 ----------------------
475 procedure Trim_Lines_Table
(S
: Source_File_Index
) is
478 (P
: Lines_Table_Ptr
;
480 return Lines_Table_Ptr
;
481 pragma Import
(C
, realloc
);
483 Max
: constant Nat
:= Nat
(Source_File
.Table
(S
).Last_Source_Line
);
486 -- Release allocated storage that is no longer needed
488 Source_File
.Table
(S
).Lines_Table
:=
490 (Source_File
.Table
(S
).Lines_Table
,
491 Max
* (Lines_Table_Type
'Component_Size / System
.Storage_Unit
));
492 Source_File
.Table
(S
).Lines_Table_Max
:= Physical_Line_Number
(Max
);
493 end Trim_Lines_Table
;
495 ----------------------
496 -- Write_Debug_Line --
497 ----------------------
499 procedure Write_Debug_Line
(Str
: String; Loc
: in out Source_Ptr
) is
500 S
: Source_File_Record
renames Source_File
.Table
(Dfile
);
503 -- Ignore write request if null line at start of file
505 if Str
'Length = 0 and then Loc
= S
.Source_First
then
508 -- Here we write the line, and update the source record entry
511 Write_Debug_Info
(Str
);
512 Add_Line_Tables_Entry
(S
, Loc
);
513 Loc
:= Loc
+ Source_Ptr
(Str
'Length + Debug_File_Eol_Length
);
514 S
.Source_Last
:= Loc
;
516 if Debug_Flag_GG
then
518 Lin
: constant String := Str
;
522 Write_Str
("---> Write_Debug_Line (Str => """);
524 Write_Str
(""", Loc => ");
525 Write_Int
(Int
(Loc
));
531 end Write_Debug_Line
;