fixing pr42337
[official-gcc.git] / gcc / ada / get_scos.adb
blob733263adb0ab5217c7a2c6538f2ceed62e713a68
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT COMPILER COMPONENTS --
4 -- --
5 -- G E T _ S C O S --
6 -- --
7 -- B o d y --
8 -- --
9 -- Copyright (C) 2009, 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 SCOs; use SCOs;
27 with Types; use Types;
29 with Ada.IO_Exceptions; use Ada.IO_Exceptions;
31 procedure Get_SCOs is
32 Dnum : Nat;
33 C : Character;
34 Loc1 : Source_Location;
35 Loc2 : Source_Location;
36 Cond : Character;
37 Dtyp : Character;
39 use ASCII;
40 -- For CR/LF
42 procedure Check (C : Character);
43 -- Checks that file is positioned at given character, and if so skips past
44 -- it, If not, raises Data_Error.
46 function Get_Int return Int;
47 -- On entry the file is positioned to a digit. On return, the file is
48 -- positioned past the last digit, and the returned result is the decimal
49 -- value read. Data_Error is raised for overflow (value greater than
50 -- Int'Last), or if the initial character is not a digit.
52 procedure Get_Sloc_Range (Loc1, Loc2 : out Source_Location);
53 -- Skips initial spaces, then reads a source location range in the form
54 -- line:col-line:col and places the two source locations in Loc1 and Loc2.
55 -- Raises Data_Error if format does not match this requirement.
57 procedure Skip_EOL;
58 -- Called with the current character about to be read being LF or CR. Skips
59 -- past CR/LF characters until either a non-CR/LF character is found, or
60 -- the end of file is encountered.
62 procedure Skip_Spaces;
63 -- Skips zero or more spaces at the current position, leaving the file
64 -- positioned at the first non-blank character (or Types.EOF).
66 -----------
67 -- Check --
68 -----------
70 procedure Check (C : Character) is
71 begin
72 if Nextc = C then
73 Skipc;
74 else
75 raise Data_Error;
76 end if;
77 end Check;
79 -------------
80 -- Get_Int --
81 -------------
83 function Get_Int return Int is
84 Val : Int;
85 C : Character;
87 begin
88 C := Nextc;
89 Val := 0;
91 if C not in '0' .. '9' then
92 raise Data_Error;
93 end if;
95 -- Loop to read digits of integer value
97 loop
98 declare
99 pragma Unsuppress (Overflow_Check);
100 begin
101 Val := Val * 10 + (Character'Pos (C) - Character'Pos ('0'));
102 end;
104 Skipc;
105 C := Nextc;
107 exit when C not in '0' .. '9';
108 end loop;
110 return Val;
112 exception
113 when Constraint_Error =>
114 raise Data_Error;
115 end Get_Int;
117 --------------------
118 -- Get_Sloc_Range --
119 --------------------
121 procedure Get_Sloc_Range (Loc1, Loc2 : out Source_Location) is
122 pragma Unsuppress (Range_Check);
124 begin
125 Skip_Spaces;
127 Loc1.Line := Logical_Line_Number (Get_Int);
128 Check (':');
129 Loc1.Col := Column_Number (Get_Int);
131 Check ('-');
133 Loc2.Line := Logical_Line_Number (Get_Int);
134 Check (':');
135 Loc2.Col := Column_Number (Get_Int);
137 exception
138 when Constraint_Error =>
139 raise Data_Error;
140 end Get_Sloc_Range;
142 --------------
143 -- Skip_EOL --
144 --------------
146 procedure Skip_EOL is
147 C : Character;
149 begin
150 loop
151 Skipc;
152 C := Nextc;
153 exit when C /= LF and then C /= CR;
155 if C = ' ' then
156 Skip_Spaces;
157 C := Nextc;
158 exit when C /= LF and then C /= CR;
159 end if;
160 end loop;
161 end Skip_EOL;
163 -----------------
164 -- Skip_Spaces --
165 -----------------
167 procedure Skip_Spaces is
168 begin
169 while Nextc = ' ' loop
170 Skipc;
171 end loop;
172 end Skip_Spaces;
174 -- Start of processing for Get_Scos
176 begin
177 SCOs.Initialize;
179 -- Loop through lines of SCO information
181 while Nextc = 'C' loop
182 Skipc;
184 C := Getc;
186 -- Make sure first line is a header line
188 if SCO_Unit_Table.Last = 0 and then C /= ' ' then
189 raise Data_Error;
190 end if;
192 -- Otherwise dispatch on type of line
194 case C is
196 -- Header entry
198 when ' ' =>
200 -- Complete previous entry if any
202 if SCO_Unit_Table.Last /= 0 then
203 SCO_Unit_Table.Table (SCO_Unit_Table.Last).To :=
204 SCO_Table.Last;
205 end if;
207 -- Scan out dependency number and file name
209 declare
210 Ptr : String_Ptr := new String (1 .. 32768);
211 N : Integer;
213 begin
214 Skip_Spaces;
215 Dnum := Get_Int;
217 Skip_Spaces;
219 N := 0;
220 while Nextc > ' ' loop
221 N := N + 1;
222 Ptr.all (N) := Getc;
223 end loop;
225 -- Make new unit table entry (will fill in To later)
227 SCO_Unit_Table.Append (
228 (File_Name => new String'(Ptr.all (1 .. N)),
229 Dep_Num => Dnum,
230 From => SCO_Table.Last + 1,
231 To => 0));
233 Free (Ptr);
234 end;
236 -- Statement entry
238 when 'S' =>
239 Get_Sloc_Range (Loc1, Loc2);
240 Add_SCO (C1 => 'S', From => Loc1, To => Loc2);
242 -- Exit entry
244 when 'T' =>
245 Get_Sloc_Range (Loc1, Loc2);
246 Add_SCO (C1 => 'T', From => Loc1, To => Loc2);
248 -- Decision entry
250 when 'I' | 'E' | 'W' | 'X' =>
251 Dtyp := C;
252 Skip_Spaces;
253 C := Getc;
255 -- Case of simple condition
257 if C = 'c' or else C = 't' or else C = 'f' then
258 Cond := C;
259 Get_Sloc_Range (Loc1, Loc2);
260 Add_SCO
261 (C1 => Dtyp,
262 C2 => Cond,
263 From => Loc1,
264 To => Loc2,
265 Last => True);
267 -- Complex expression
269 else
270 Add_SCO (C1 => Dtyp, Last => False);
272 -- Loop through terms in complex expression
274 while C /= CR and then C /= LF loop
275 if C = 'c' or else C = 't' or else C = 'f' then
276 Cond := C;
277 Skipc;
278 Get_Sloc_Range (Loc1, Loc2);
279 Add_SCO
280 (C2 => Cond,
281 From => Loc1,
282 To => Loc2,
283 Last => False);
285 elsif C = '!' or else
286 C = '^' or else
287 C = '&' or else
288 C = '|'
289 then
290 Skipc;
291 Add_SCO (C1 => C, Last => False);
293 elsif C = ' ' then
294 Skip_Spaces;
296 else
297 raise Data_Error;
298 end if;
300 C := Nextc;
301 end loop;
303 -- Reset Last indication to True for last entry
305 SCO_Table.Table (SCO_Table.Last).Last := True;
306 end if;
308 when others =>
309 raise Data_Error;
310 end case;
312 Skip_EOL;
313 end loop;
315 -- Here with all SCO's stored, complete last SCO Unit table entry
317 SCO_Unit_Table.Table (SCO_Unit_Table.Last).To := SCO_Table.Last;
318 end Get_SCOs;