* prerequisites.xml: Refer to GCC (instead of gcc) and GNU/Linux.
[official-gcc.git] / gcc / ada / get_alfa.adb
blob8c90f754d9a4d64af0f2934a353ae2d6f2d176f4
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, 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 -----------------------
55 -- Local Subprograms --
56 -----------------------
58 function At_EOL return Boolean;
59 -- Skips any spaces, then checks if at the end of a line. If so, returns
60 -- True (but does not skip the EOL sequence). If not, then returns False.
62 procedure Check (C : Character);
63 -- Checks that file is positioned at given character, and if so skips past
64 -- it, If not, raises Data_Error.
66 function Get_Nat return Nat;
67 -- On entry the file is positioned to a digit. On return, the file is
68 -- positioned past the last digit, and the returned result is the decimal
69 -- value read. Data_Error is raised for overflow (value greater than
70 -- Int'Last), or if the initial character is not a digit.
72 procedure Get_Name;
73 -- On entry the file is positioned to a name. On return, the file is
74 -- positioned past the last character, and the name scanned is returned
75 -- in Name_Str (1 .. Name_Len).
77 procedure Skip_EOL;
78 -- Called with the current character about to be read being LF or CR. Skips
79 -- past CR/LF characters until either a non-CR/LF character is found, or
80 -- the end of file is encountered.
82 procedure Skip_Spaces;
83 -- Skips zero or more spaces at the current position, leaving the file
84 -- positioned at the first non-blank character (or Types.EOF).
86 ------------
87 -- At_EOL --
88 ------------
90 function At_EOL return Boolean is
91 begin
92 Skip_Spaces;
93 return Nextc = CR or else Nextc = LF;
94 end At_EOL;
96 -----------
97 -- Check --
98 -----------
100 procedure Check (C : Character) is
101 begin
102 if Nextc = C then
103 Skipc;
104 else
105 raise Data_Error;
106 end if;
107 end Check;
109 -------------
110 -- Get_Nat --
111 -------------
113 function Get_Nat return Nat is
114 Val : Nat;
115 C : Character;
117 begin
118 C := Nextc;
119 Val := 0;
121 if C not in '0' .. '9' then
122 raise Data_Error;
123 end if;
125 -- Loop to read digits of integer value
127 loop
128 declare
129 pragma Unsuppress (Overflow_Check);
130 begin
131 Val := Val * 10 + (Character'Pos (C) - Character'Pos ('0'));
132 end;
134 Skipc;
135 C := Nextc;
137 exit when C not in '0' .. '9';
138 end loop;
140 return Val;
142 exception
143 when Constraint_Error =>
144 raise Data_Error;
145 end Get_Nat;
147 --------------
148 -- Get_Name --
149 --------------
151 procedure Get_Name is
152 N : Integer;
154 begin
155 N := 0;
156 while Nextc > ' ' loop
157 N := N + 1;
158 Name_Str (N) := Getc;
159 end loop;
161 Name_Len := N;
162 end Get_Name;
164 --------------
165 -- Skip_EOL --
166 --------------
168 procedure Skip_EOL is
169 C : Character;
171 begin
172 loop
173 Skipc;
174 C := Nextc;
175 exit when C /= LF and then C /= CR;
177 if C = ' ' then
178 Skip_Spaces;
179 C := Nextc;
180 exit when C /= LF and then C /= CR;
181 end if;
182 end loop;
183 end Skip_EOL;
185 -----------------
186 -- Skip_Spaces --
187 -----------------
189 procedure Skip_Spaces is
190 begin
191 while Nextc = ' ' loop
192 Skipc;
193 end loop;
194 end Skip_Spaces;
196 -- Start of processing for Get_Alfa
198 begin
199 Initialize_Alfa_Tables;
201 Cur_File := 0;
202 Cur_Scope := 0;
203 Cur_File_Idx := 1;
204 Cur_Scope_Idx := 0;
206 -- Loop through lines of Alfa information
208 while Nextc = 'F' loop
209 Skipc;
211 C := Getc;
213 -- Make sure first line is a File line
215 if Alfa_File_Table.Last = 0 and then C /= 'D' then
216 raise Data_Error;
217 end if;
219 -- Otherwise dispatch on type of line
221 case C is
223 -- Header entry for scope section
225 when 'D' =>
227 -- Complete previous entry if any
229 if Alfa_File_Table.Last /= 0 then
230 Alfa_File_Table.Table (Alfa_File_Table.Last).To_Scope :=
231 Alfa_Scope_Table.Last;
232 end if;
234 -- Scan out dependency number and file name
236 Skip_Spaces;
237 Cur_File := Get_Nat;
238 Skip_Spaces;
239 Get_Name;
241 -- Make new File table entry (will fill in To_Scope later)
243 Alfa_File_Table.Append (
244 (File_Name => new String'(Name_Str (1 .. Name_Len)),
245 File_Num => Cur_File,
246 From_Scope => Alfa_Scope_Table.Last + 1,
247 To_Scope => 0));
249 -- Initialize counter for scopes
251 Cur_Scope := 1;
253 -- Scope entry
255 when 'S' =>
256 declare
257 Spec_File : Nat;
258 Spec_Scope : Nat;
259 Scope : Nat;
260 Line : Nat;
261 Col : Nat;
262 Typ : Character;
264 begin
265 -- Scan out location
267 Skip_Spaces;
268 Check ('.');
269 Scope := Get_Nat;
270 Check (' ');
271 Line := Get_Nat;
272 Typ := Getc;
273 Col := Get_Nat;
275 pragma Assert (Scope = Cur_Scope);
276 pragma Assert (Typ = 'K'
277 or else Typ = 'V'
278 or else Typ = 'U');
280 -- Scan out scope entity name
282 Skip_Spaces;
283 Get_Name;
284 Skip_Spaces;
286 if Nextc = '-' then
287 Skipc;
288 Check ('>');
289 Skip_Spaces;
290 Spec_File := Get_Nat;
291 Check ('.');
292 Spec_Scope := Get_Nat;
294 else
295 Spec_File := 0;
296 Spec_Scope := 0;
297 end if;
299 -- Make new scope table entry (will fill in From_Xref and
300 -- To_Xref later). Initial range (From_Xref .. To_Xref) is
301 -- empty for scopes without entities.
303 Alfa_Scope_Table.Append (
304 (Scope_Entity => Empty,
305 Scope_Name => new String'(Name_Str (1 .. Name_Len)),
306 File_Num => Cur_File,
307 Scope_Num => Cur_Scope,
308 Spec_File_Num => Spec_File,
309 Spec_Scope_Num => Spec_Scope,
310 Line => Line,
311 Stype => Typ,
312 Col => Col,
313 From_Xref => 1,
314 To_Xref => 0));
315 end;
317 -- Update counter for scopes
319 Cur_Scope := Cur_Scope + 1;
321 -- Header entry for cross-ref section
323 when 'X' =>
325 -- Scan out dependency number and file name (ignored)
327 Skip_Spaces;
328 Cur_File := Get_Nat;
329 Skip_Spaces;
330 Get_Name;
332 -- Update component From_Xref of current file if first reference
333 -- in this file.
335 while Alfa_File_Table.Table (Cur_File_Idx).File_Num /= Cur_File
336 loop
337 Cur_File_Idx := Cur_File_Idx + 1;
338 end loop;
340 -- Scan out scope entity number and entity name (ignored)
342 Skip_Spaces;
343 Check ('.');
344 Cur_Scope := Get_Nat;
345 Skip_Spaces;
346 Get_Name;
348 -- Update component To_Xref of previous scope
350 if Cur_Scope_Idx /= 0 then
351 Alfa_Scope_Table.Table (Cur_Scope_Idx).To_Xref :=
352 Alfa_Xref_Table.Last;
353 end if;
355 -- Update component From_Xref of current scope
357 Cur_Scope_Idx := Alfa_File_Table.Table (Cur_File_Idx).From_Scope;
359 while Alfa_Scope_Table.Table (Cur_Scope_Idx).Scope_Num /= Cur_Scope
360 loop
361 Cur_Scope_Idx := Cur_Scope_Idx + 1;
362 end loop;
364 Alfa_Scope_Table.Table (Cur_Scope_Idx).From_Xref :=
365 Alfa_Xref_Table.Last + 1;
367 -- Cross reference entry
369 when ' ' =>
370 declare
371 XR_Entity : String_Ptr;
372 XR_Entity_Line : Nat;
373 XR_Entity_Col : Nat;
374 XR_Entity_Typ : Character;
376 XR_File : Nat;
377 -- Keeps track of the current file (changed by nn|)
379 XR_Scope : Nat;
380 -- Keeps track of the current scope (changed by nn:)
382 begin
383 XR_File := Cur_File;
384 XR_Scope := Cur_Scope;
386 XR_Entity_Line := Get_Nat;
387 XR_Entity_Typ := Getc;
388 XR_Entity_Col := Get_Nat;
390 Skip_Spaces;
391 Get_Name;
392 XR_Entity := new String'(Name_Str (1 .. Name_Len));
394 -- Initialize to scan items on one line
396 Skip_Spaces;
398 -- Loop through cross-references for this entity
400 loop
402 declare
403 Line : Nat;
404 Col : Nat;
405 N : Nat;
406 Rtype : Character;
408 begin
409 Skip_Spaces;
411 if At_EOL then
412 Skip_EOL;
413 exit when Nextc /= '.';
414 Skipc;
415 Skip_Spaces;
416 end if;
418 if Nextc = '.' then
419 Skipc;
420 XR_Scope := Get_Nat;
421 Check (':');
423 else
424 N := Get_Nat;
426 if Nextc = '|' then
427 XR_File := N;
428 Skipc;
430 else
431 Line := N;
432 Rtype := Getc;
433 Col := Get_Nat;
435 pragma Assert
436 (Rtype = 'r' or else
437 Rtype = 'm' or else
438 Rtype = 's');
440 Alfa_Xref_Table.Append (
441 (Entity_Name => XR_Entity,
442 Entity_Line => XR_Entity_Line,
443 Etype => XR_Entity_Typ,
444 Entity_Col => XR_Entity_Col,
445 File_Num => XR_File,
446 Scope_Num => XR_Scope,
447 Line => Line,
448 Rtype => Rtype,
449 Col => Col));
450 end if;
451 end if;
452 end;
453 end loop;
454 end;
456 -- No other Alfa lines are possible
458 when others =>
459 raise Data_Error;
460 end case;
462 -- For cross reference lines, the EOL character has been skipped already
464 if C /= ' ' then
465 Skip_EOL;
466 end if;
467 end loop;
469 -- Here with all Xrefs stored, complete last entries in File/Scope tables
471 if Alfa_File_Table.Last /= 0 then
472 Alfa_File_Table.Table (Alfa_File_Table.Last).To_Scope :=
473 Alfa_Scope_Table.Last;
474 end if;
476 if Cur_Scope_Idx /= 0 then
477 Alfa_Scope_Table.Table (Cur_Scope_Idx).To_Xref := Alfa_Xref_Table.Last;
478 end if;
479 end Get_Alfa;