1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
5 -- G E T _ S P A R K _ X R E F S --
9 -- Copyright (C) 2011-2013, Free Software Foundation, Inc. --
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. --
21 -- GNAT was originally developed by the GNAT team at New York University. --
22 -- Extensive contributions were provided by Ada Core Technologies Inc. --
24 ------------------------------------------------------------------------------
26 with SPARK_Xrefs
; use SPARK_Xrefs
;
27 with Types
; use Types
;
29 with Ada
.IO_Exceptions
; use Ada
.IO_Exceptions
;
31 procedure Get_SPARK_Xrefs
is
38 -- Dependency number for the current file
41 -- Scope number for the current scope entity
43 Cur_File_Idx
: File_Index
;
44 -- Index in SPARK_File_Table of the current file
46 Cur_Scope_Idx
: Scope_Index
;
47 -- Index in SPARK_Scope_Table of the current scope
49 Name_Str
: String (1 .. 32768);
50 Name_Len
: Natural := 0;
51 -- Local string used to store name of File/entity scanned as
52 -- Name_Str (1 .. Name_Len).
54 File_Name
: String_Ptr
;
55 Unit_File_Name
: String_Ptr
;
57 -----------------------
58 -- Local Subprograms --
59 -----------------------
61 function At_EOL
return Boolean;
62 -- Skips any spaces, then checks if at the end of a line. If so, returns
63 -- True (but does not skip the EOL sequence). If not, then returns False.
65 procedure Check
(C
: Character);
66 -- Checks that file is positioned at given character, and if so skips past
67 -- it, If not, raises Data_Error.
69 function Get_Nat
return Nat
;
70 -- On entry the file is positioned to a digit. On return, the file is
71 -- positioned past the last digit, and the returned result is the decimal
72 -- value read. Data_Error is raised for overflow (value greater than
73 -- Int'Last), or if the initial character is not a digit.
76 -- On entry the file is positioned to a name. On return, the file is
77 -- positioned past the last character, and the name scanned is returned
78 -- in Name_Str (1 .. Name_Len).
81 -- Called with the current character about to be read being LF or CR. Skips
82 -- past CR/LF characters until either a non-CR/LF character is found, or
83 -- the end of file is encountered.
85 procedure Skip_Spaces
;
86 -- Skips zero or more spaces at the current position, leaving the file
87 -- positioned at the first non-blank character (or Types.EOF).
93 function At_EOL
return Boolean is
96 return Nextc
= CR
or else Nextc
= LF
;
103 procedure Check
(C
: Character) is
116 function Get_Nat
return Nat
is
124 if C
not in '0' .. '9' then
128 -- Loop to read digits of integer value
132 pragma Unsuppress
(Overflow_Check
);
134 Val
:= Val
* 10 + (Character'Pos (C
) - Character'Pos ('0'));
140 exit when C
not in '0' .. '9';
146 when Constraint_Error
=>
154 procedure Get_Name
is
159 while Nextc
> ' ' loop
161 Name_Str
(N
) := Getc
;
171 procedure Skip_EOL
is
178 exit when C
/= LF
and then C
/= CR
;
183 exit when C
/= LF
and then C
/= CR
;
192 procedure Skip_Spaces
is
194 while Nextc
= ' ' loop
199 -- Start of processing for Get_SPARK_Xrefs
202 Initialize_SPARK_Tables
;
209 -- Loop through lines of SPARK cross-reference information
211 while Nextc
= 'F' loop
216 -- Make sure first line is a File line
218 if SPARK_File_Table
.Last
= 0 and then C
/= 'D' then
222 -- Otherwise dispatch on type of line
226 -- Header entry for scope section
230 -- Complete previous entry if any
232 if SPARK_File_Table
.Last
/= 0 then
233 SPARK_File_Table
.Table
(SPARK_File_Table
.Last
).To_Scope
:=
234 SPARK_Scope_Table
.Last
;
237 -- Scan out dependency number and file name
244 File_Name
:= new String'(Name_Str (1 .. Name_Len));
247 -- Scan out unit file name when present (for subunits)
254 Unit_File_Name := new String'(Name_Str
(1 .. Name_Len
));
257 Unit_File_Name
:= null;
260 -- Make new File table entry (will fill in To_Scope later)
262 SPARK_File_Table
.Append
(
263 (File_Name
=> File_Name
,
264 Unit_File_Name
=> Unit_File_Name
,
265 File_Num
=> Cur_File
,
266 From_Scope
=> SPARK_Scope_Table
.Last
+ 1,
269 -- Initialize counter for scopes
295 pragma Assert
(Scope
= Cur_Scope
);
296 pragma Assert
(Typ
= 'K'
300 -- Scan out scope entity name
310 Spec_File
:= Get_Nat
;
312 Spec_Scope
:= Get_Nat
;
319 -- Make new scope table entry (will fill in From_Xref and
320 -- To_Xref later). Initial range (From_Xref .. To_Xref) is
321 -- empty for scopes without entities.
323 SPARK_Scope_Table
.Append
(
324 (Scope_Entity
=> Empty
,
325 Scope_Name
=> new String'(Name_Str (1 .. Name_Len)),
326 File_Num => Cur_File,
327 Scope_Num => Cur_Scope,
328 Spec_File_Num => Spec_File,
329 Spec_Scope_Num => Spec_Scope,
337 -- Update counter for scopes
339 Cur_Scope := Cur_Scope + 1;
341 -- Header entry for cross-ref section
345 -- Scan out dependency number and file name (ignored)
352 -- Update component From_Xref of current file if first reference
355 while SPARK_File_Table.Table (Cur_File_Idx).File_Num /= Cur_File
357 Cur_File_Idx := Cur_File_Idx + 1;
360 -- Scan out scope entity number and entity name (ignored)
364 Cur_Scope := Get_Nat;
368 -- Update component To_Xref of previous scope
370 if Cur_Scope_Idx /= 0 then
371 SPARK_Scope_Table.Table (Cur_Scope_Idx).To_Xref :=
372 SPARK_Xref_Table.Last;
375 -- Update component From_Xref of current scope
377 Cur_Scope_Idx := SPARK_File_Table.Table (Cur_File_Idx).From_Scope;
379 while SPARK_Scope_Table.Table (Cur_Scope_Idx).Scope_Num /=
382 Cur_Scope_Idx := Cur_Scope_Idx + 1;
385 SPARK_Scope_Table.Table (Cur_Scope_Idx).From_Xref :=
386 SPARK_Xref_Table.Last + 1;
388 -- Cross reference entry
392 XR_Entity : String_Ptr;
393 XR_Entity_Line : Nat;
395 XR_Entity_Typ : Character;
398 -- Keeps track of the current file (changed by nn|)
401 -- Keeps track of the current scope (changed by nn:)
405 XR_Scope := Cur_Scope;
407 XR_Entity_Line := Get_Nat;
408 XR_Entity_Typ := Getc;
409 XR_Entity_Col := Get_Nat;
413 XR_Entity := new String'(Name_Str
(1 .. Name_Len
));
415 -- Initialize to scan items on one line
419 -- Loop through cross-references for this entity
434 exit when Nextc
/= '.';
462 SPARK_Xref_Table
.Append
(
463 (Entity_Name
=> XR_Entity
,
464 Entity_Line
=> XR_Entity_Line
,
465 Etype
=> XR_Entity_Typ
,
466 Entity_Col
=> XR_Entity_Col
,
468 Scope_Num
=> XR_Scope
,
478 -- No other SPARK lines are possible
484 -- For cross reference lines, the EOL character has been skipped already
491 -- Here with all Xrefs stored, complete last entries in File/Scope tables
493 if SPARK_File_Table
.Last
/= 0 then
494 SPARK_File_Table
.Table
(SPARK_File_Table
.Last
).To_Scope
:=
495 SPARK_Scope_Table
.Last
;
498 if Cur_Scope_Idx
/= 0 then
499 SPARK_Scope_Table
.Table
(Cur_Scope_Idx
).To_Xref
:= SPARK_Xref_Table
.Last
;