1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
5 -- G E T _ S P A R K _ X R E F S --
9 -- Copyright (C) 2011-2016, 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
117 C
: Character := Nextc
;
121 if C
not in '0' .. '9' then
125 -- Loop to read digits of integer value
129 pragma Unsuppress
(Overflow_Check
);
131 Val
:= Val
* 10 + (Character'Pos (C
) - Character'Pos ('0'));
137 exit when C
not in '0' .. '9';
143 when Constraint_Error
=>
151 procedure Get_Name
is
155 while Nextc
> ' ' loop
157 Name_Str
(N
) := Getc
;
167 procedure Skip_EOL
is
174 exit when C
/= LF
and then C
/= CR
;
179 exit when C
/= LF
and then C
/= CR
;
188 procedure Skip_Spaces
is
190 while Nextc
= ' ' loop
195 -- Start of processing for Get_SPARK_Xrefs
198 Initialize_SPARK_Tables
;
205 -- Loop through lines of SPARK cross-reference information
207 while Nextc
= 'F' loop
212 -- Make sure first line is a File line
214 if SPARK_File_Table
.Last
= 0 and then C
/= 'D' then
218 -- Otherwise dispatch on type of line
222 -- Header entry for scope section
226 -- Complete previous entry if any
228 if SPARK_File_Table
.Last
/= 0 then
229 SPARK_File_Table
.Table
(SPARK_File_Table
.Last
).To_Scope
:=
230 SPARK_Scope_Table
.Last
;
233 -- Scan out dependency number and file name
240 File_Name
:= new String'(Name_Str (1 .. Name_Len));
243 -- Scan out unit file name when present (for subunits)
250 Unit_File_Name := new String'(Name_Str
(1 .. Name_Len
));
253 Unit_File_Name
:= null;
256 -- Make new File table entry (will fill in To_Scope later)
258 SPARK_File_Table
.Append
(
259 (File_Name
=> File_Name
,
260 Unit_File_Name
=> Unit_File_Name
,
261 File_Num
=> Cur_File
,
262 From_Scope
=> SPARK_Scope_Table
.Last
+ 1,
265 -- Initialize counter for scopes
291 pragma Assert
(Scope
= Cur_Scope
);
293 -- Scan out scope entity name
303 Spec_File
:= Get_Nat
;
305 Spec_Scope
:= Get_Nat
;
312 -- Make new scope table entry (will fill in From_Xref and
313 -- To_Xref later). Initial range (From_Xref .. To_Xref) is
314 -- empty for scopes without entities.
316 SPARK_Scope_Table
.Append
(
317 (Scope_Entity
=> Empty
,
318 Scope_Name
=> new String'(Name_Str (1 .. Name_Len)),
319 File_Num => Cur_File,
320 Scope_Num => Cur_Scope,
321 Spec_File_Num => Spec_File,
322 Spec_Scope_Num => Spec_Scope,
330 -- Update counter for scopes
332 Cur_Scope := Cur_Scope + 1;
334 -- Header entry for cross-ref section
338 -- Scan out dependency number and file name (ignored)
345 -- Update component From_Xref of current file if first reference
348 while SPARK_File_Table.Table (Cur_File_Idx).File_Num /= Cur_File
350 Cur_File_Idx := Cur_File_Idx + 1;
353 -- Scan out scope entity number and entity name (ignored)
357 Cur_Scope := Get_Nat;
361 -- Update component To_Xref of previous scope
363 if Cur_Scope_Idx /= 0 then
364 SPARK_Scope_Table.Table (Cur_Scope_Idx).To_Xref :=
365 SPARK_Xref_Table.Last;
368 -- Update component From_Xref of current scope
370 Cur_Scope_Idx := SPARK_File_Table.Table (Cur_File_Idx).From_Scope;
372 while SPARK_Scope_Table.Table (Cur_Scope_Idx).Scope_Num /=
375 Cur_Scope_Idx := Cur_Scope_Idx + 1;
378 SPARK_Scope_Table.Table (Cur_Scope_Idx).From_Xref :=
379 SPARK_Xref_Table.Last + 1;
381 -- Cross reference entry
385 XR_Entity : String_Ptr;
386 XR_Entity_Line : Nat;
388 XR_Entity_Typ : Character;
391 -- Keeps track of the current file (changed by nn|)
394 -- Keeps track of the current scope (changed by nn:)
398 XR_Scope := Cur_Scope;
400 XR_Entity_Line := Get_Nat;
401 XR_Entity_Typ := Getc;
402 XR_Entity_Col := Get_Nat;
406 XR_Entity := new String'(Name_Str
(1 .. Name_Len
));
408 -- Initialize to scan items on one line
412 -- Loop through cross-references for this entity
426 exit when Nextc
/= '.';
454 SPARK_Xref_Table
.Append
(
455 (Entity_Name
=> XR_Entity
,
456 Entity_Line
=> XR_Entity_Line
,
457 Etype
=> XR_Entity_Typ
,
458 Entity_Col
=> XR_Entity_Col
,
460 Scope_Num
=> XR_Scope
,
470 -- No other SPARK lines are possible
476 -- For cross reference lines, the EOL character has been skipped already
483 -- Here with all Xrefs stored, complete last entries in File/Scope tables
485 if SPARK_File_Table
.Last
/= 0 then
486 SPARK_File_Table
.Table
(SPARK_File_Table
.Last
).To_Scope
:=
487 SPARK_Scope_Table
.Last
;
490 if Cur_Scope_Idx
/= 0 then
491 SPARK_Scope_Table
.Table
(Cur_Scope_Idx
).To_Xref
:= SPARK_Xref_Table
.Last
;