PR c++/54038
[official-gcc.git] / gcc / ada / get_alfa.adb
bloba10637cd360af74234b3e2c3bd0efb4f31c927e4
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT COMPILER COMPONENTS --
4 -- --
5 -- G E T _ A L F A --
6 -- --
7 -- B o d y --
8 -- --
9 -- Copyright (C) 2011-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 ------------------------------------------------------------------------------
26 with Alfa; use Alfa;
27 with Types; use Types;
29 with Ada.IO_Exceptions; use Ada.IO_Exceptions;
31 procedure Get_Alfa is
32 C : Character;
34 use ASCII;
35 -- For CR/LF
37 Cur_File : Nat;
38 -- Dependency number for the current file
40 Cur_Scope : Nat;
41 -- Scope number for the current scope entity
43 Cur_File_Idx : File_Index;
44 -- Index in Alfa_File_Table of the current file
46 Cur_Scope_Idx : Scope_Index;
47 -- Index in Alfa_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.
75 procedure Get_Name;
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).
80 procedure Skip_EOL;
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).
89 ------------
90 -- At_EOL --
91 ------------
93 function At_EOL return Boolean is
94 begin
95 Skip_Spaces;
96 return Nextc = CR or else Nextc = LF;
97 end At_EOL;
99 -----------
100 -- Check --
101 -----------
103 procedure Check (C : Character) is
104 begin
105 if Nextc = C then
106 Skipc;
107 else
108 raise Data_Error;
109 end if;
110 end Check;
112 -------------
113 -- Get_Nat --
114 -------------
116 function Get_Nat return Nat is
117 Val : Nat;
118 C : Character;
120 begin
121 C := Nextc;
122 Val := 0;
124 if C not in '0' .. '9' then
125 raise Data_Error;
126 end if;
128 -- Loop to read digits of integer value
130 loop
131 declare
132 pragma Unsuppress (Overflow_Check);
133 begin
134 Val := Val * 10 + (Character'Pos (C) - Character'Pos ('0'));
135 end;
137 Skipc;
138 C := Nextc;
140 exit when C not in '0' .. '9';
141 end loop;
143 return Val;
145 exception
146 when Constraint_Error =>
147 raise Data_Error;
148 end Get_Nat;
150 --------------
151 -- Get_Name --
152 --------------
154 procedure Get_Name is
155 N : Integer;
157 begin
158 N := 0;
159 while Nextc > ' ' loop
160 N := N + 1;
161 Name_Str (N) := Getc;
162 end loop;
164 Name_Len := N;
165 end Get_Name;
167 --------------
168 -- Skip_EOL --
169 --------------
171 procedure Skip_EOL is
172 C : Character;
174 begin
175 loop
176 Skipc;
177 C := Nextc;
178 exit when C /= LF and then C /= CR;
180 if C = ' ' then
181 Skip_Spaces;
182 C := Nextc;
183 exit when C /= LF and then C /= CR;
184 end if;
185 end loop;
186 end Skip_EOL;
188 -----------------
189 -- Skip_Spaces --
190 -----------------
192 procedure Skip_Spaces is
193 begin
194 while Nextc = ' ' loop
195 Skipc;
196 end loop;
197 end Skip_Spaces;
199 -- Start of processing for Get_Alfa
201 begin
202 Initialize_Alfa_Tables;
204 Cur_File := 0;
205 Cur_Scope := 0;
206 Cur_File_Idx := 1;
207 Cur_Scope_Idx := 0;
209 -- Loop through lines of Alfa information
211 while Nextc = 'F' loop
212 Skipc;
214 C := Getc;
216 -- Make sure first line is a File line
218 if Alfa_File_Table.Last = 0 and then C /= 'D' then
219 raise Data_Error;
220 end if;
222 -- Otherwise dispatch on type of line
224 case C is
226 -- Header entry for scope section
228 when 'D' =>
230 -- Complete previous entry if any
232 if Alfa_File_Table.Last /= 0 then
233 Alfa_File_Table.Table (Alfa_File_Table.Last).To_Scope :=
234 Alfa_Scope_Table.Last;
235 end if;
237 -- Scan out dependency number and file name
239 Skip_Spaces;
240 Cur_File := Get_Nat;
241 Skip_Spaces;
243 Get_Name;
244 File_Name := new String'(Name_Str (1 .. Name_Len));
245 Skip_Spaces;
247 -- Scan out unit file name when present (for subunits)
249 if Nextc = '-' then
250 Skipc;
251 Check ('>');
252 Skip_Spaces;
253 Get_Name;
254 Unit_File_Name := new String'(Name_Str (1 .. Name_Len));
256 else
257 Unit_File_Name := null;
258 end if;
260 -- Make new File table entry (will fill in To_Scope later)
262 Alfa_File_Table.Append (
263 (File_Name => File_Name,
264 Unit_File_Name => Unit_File_Name,
265 File_Num => Cur_File,
266 From_Scope => Alfa_Scope_Table.Last + 1,
267 To_Scope => 0));
269 -- Initialize counter for scopes
271 Cur_Scope := 1;
273 -- Scope entry
275 when 'S' =>
276 declare
277 Spec_File : Nat;
278 Spec_Scope : Nat;
279 Scope : Nat;
280 Line : Nat;
281 Col : Nat;
282 Typ : Character;
284 begin
285 -- Scan out location
287 Skip_Spaces;
288 Check ('.');
289 Scope := Get_Nat;
290 Check (' ');
291 Line := Get_Nat;
292 Typ := Getc;
293 Col := Get_Nat;
295 pragma Assert (Scope = Cur_Scope);
296 pragma Assert (Typ = 'K'
297 or else Typ = 'V'
298 or else Typ = 'U');
300 -- Scan out scope entity name
302 Skip_Spaces;
303 Get_Name;
304 Skip_Spaces;
306 if Nextc = '-' then
307 Skipc;
308 Check ('>');
309 Skip_Spaces;
310 Spec_File := Get_Nat;
311 Check ('.');
312 Spec_Scope := Get_Nat;
314 else
315 Spec_File := 0;
316 Spec_Scope := 0;
317 end if;
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 Alfa_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,
330 Line => Line,
331 Stype => Typ,
332 Col => Col,
333 From_Xref => 1,
334 To_Xref => 0));
335 end;
337 -- Update counter for scopes
339 Cur_Scope := Cur_Scope + 1;
341 -- Header entry for cross-ref section
343 when 'X' =>
345 -- Scan out dependency number and file name (ignored)
347 Skip_Spaces;
348 Cur_File := Get_Nat;
349 Skip_Spaces;
350 Get_Name;
352 -- Update component From_Xref of current file if first reference
353 -- in this file.
355 while Alfa_File_Table.Table (Cur_File_Idx).File_Num /= Cur_File
356 loop
357 Cur_File_Idx := Cur_File_Idx + 1;
358 end loop;
360 -- Scan out scope entity number and entity name (ignored)
362 Skip_Spaces;
363 Check ('.');
364 Cur_Scope := Get_Nat;
365 Skip_Spaces;
366 Get_Name;
368 -- Update component To_Xref of previous scope
370 if Cur_Scope_Idx /= 0 then
371 Alfa_Scope_Table.Table (Cur_Scope_Idx).To_Xref :=
372 Alfa_Xref_Table.Last;
373 end if;
375 -- Update component From_Xref of current scope
377 Cur_Scope_Idx := Alfa_File_Table.Table (Cur_File_Idx).From_Scope;
379 while Alfa_Scope_Table.Table (Cur_Scope_Idx).Scope_Num /= Cur_Scope
380 loop
381 Cur_Scope_Idx := Cur_Scope_Idx + 1;
382 end loop;
384 Alfa_Scope_Table.Table (Cur_Scope_Idx).From_Xref :=
385 Alfa_Xref_Table.Last + 1;
387 -- Cross reference entry
389 when ' ' =>
390 declare
391 XR_Entity : String_Ptr;
392 XR_Entity_Line : Nat;
393 XR_Entity_Col : Nat;
394 XR_Entity_Typ : Character;
396 XR_File : Nat;
397 -- Keeps track of the current file (changed by nn|)
399 XR_Scope : Nat;
400 -- Keeps track of the current scope (changed by nn:)
402 begin
403 XR_File := Cur_File;
404 XR_Scope := Cur_Scope;
406 XR_Entity_Line := Get_Nat;
407 XR_Entity_Typ := Getc;
408 XR_Entity_Col := Get_Nat;
410 Skip_Spaces;
411 Get_Name;
412 XR_Entity := new String'(Name_Str (1 .. Name_Len));
414 -- Initialize to scan items on one line
416 Skip_Spaces;
418 -- Loop through cross-references for this entity
420 loop
422 declare
423 Line : Nat;
424 Col : Nat;
425 N : Nat;
426 Rtype : Character;
428 begin
429 Skip_Spaces;
431 if At_EOL then
432 Skip_EOL;
433 exit when Nextc /= '.';
434 Skipc;
435 Skip_Spaces;
436 end if;
438 if Nextc = '.' then
439 Skipc;
440 XR_Scope := Get_Nat;
441 Check (':');
443 else
444 N := Get_Nat;
446 if Nextc = '|' then
447 XR_File := N;
448 Skipc;
450 else
451 Line := N;
452 Rtype := Getc;
453 Col := Get_Nat;
455 pragma Assert
456 (Rtype = 'r' or else
457 Rtype = 'm' or else
458 Rtype = 's');
460 Alfa_Xref_Table.Append (
461 (Entity_Name => XR_Entity,
462 Entity_Line => XR_Entity_Line,
463 Etype => XR_Entity_Typ,
464 Entity_Col => XR_Entity_Col,
465 File_Num => XR_File,
466 Scope_Num => XR_Scope,
467 Line => Line,
468 Rtype => Rtype,
469 Col => Col));
470 end if;
471 end if;
472 end;
473 end loop;
474 end;
476 -- No other Alfa lines are possible
478 when others =>
479 raise Data_Error;
480 end case;
482 -- For cross reference lines, the EOL character has been skipped already
484 if C /= ' ' then
485 Skip_EOL;
486 end if;
487 end loop;
489 -- Here with all Xrefs stored, complete last entries in File/Scope tables
491 if Alfa_File_Table.Last /= 0 then
492 Alfa_File_Table.Table (Alfa_File_Table.Last).To_Scope :=
493 Alfa_Scope_Table.Last;
494 end if;
496 if Cur_Scope_Idx /= 0 then
497 Alfa_Scope_Table.Table (Cur_Scope_Idx).To_Xref := Alfa_Xref_Table.Last;
498 end if;
499 end Get_Alfa;