config/sparc/sol2-bi.h: Revert previous delta.
[official-gcc.git] / gcc / ada / scn-slit.adb
blob2e7df48d0ccc10956c1d464c9d4c60838922e806
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT COMPILER COMPONENTS --
4 -- --
5 -- S C N . S L I T --
6 -- --
7 -- B o d y --
8 -- --
9 -- --
10 -- Copyright (C) 1992-2001 Free Software Foundation, Inc. --
11 -- --
12 -- GNAT is free software; you can redistribute it and/or modify it under --
13 -- terms of the GNU General Public License as published by the Free Soft- --
14 -- ware Foundation; either version 2, or (at your option) any later ver- --
15 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
16 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
17 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
18 -- for more details. You should have received a copy of the GNU General --
19 -- Public License distributed with GNAT; see file COPYING. If not, write --
20 -- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, --
21 -- MA 02111-1307, USA. --
22 -- --
23 -- GNAT was originally developed by the GNAT team at New York University. --
24 -- Extensive contributions were provided by Ada Core Technologies Inc. --
25 -- --
26 ------------------------------------------------------------------------------
28 with Stringt; use Stringt;
30 separate (Scn)
31 procedure Slit is
33 Delimiter : Character;
34 -- Delimiter (first character of string)
36 C : Character;
37 -- Current source program character
39 Code : Char_Code;
40 -- Current character code value
42 Err : Boolean;
43 -- Error flag for Scan_Wide call
45 String_Literal_Id : String_Id;
46 -- Id for currently scanned string value
48 Wide_Character_Found : Boolean := False;
49 -- Set True if wide character found
51 procedure Error_Bad_String_Char;
52 -- Signal bad character in string/character literal. On entry Scan_Ptr
53 -- points to the improper character encountered during the scan. Scan_Ptr
54 -- is not modified, so it still points to the bad character on return.
56 procedure Error_Unterminated_String;
57 -- Procedure called if a line terminator character is encountered during
58 -- scanning a string, meaning that the string is not properly terminated.
60 procedure Set_String;
61 -- Procedure used to distinguish between string and operator symbol.
62 -- On entry the string has been scanned out, and its characters start
63 -- at Token_Ptr and end one character before Scan_Ptr. On exit Token
64 -- is set to Tok_String_Literal or Tok_Operator_Symbol as appropriate,
65 -- and Token_Node is appropriately initialized. In addition, in the
66 -- operator symbol case, Token_Name is appropriately set.
68 ---------------------------
69 -- Error_Bad_String_Char --
70 ---------------------------
72 procedure Error_Bad_String_Char is
73 C : constant Character := Source (Scan_Ptr);
75 begin
76 if C = HT then
77 Error_Msg_S ("horizontal tab not allowed in string");
79 elsif C = VT or else C = FF then
80 Error_Msg_S ("format effector not allowed in string");
82 elsif C in Upper_Half_Character then
83 Error_Msg_S ("(Ada 83) upper half character not allowed");
85 else
86 Error_Msg_S ("control character not allowed in string");
87 end if;
88 end Error_Bad_String_Char;
90 -------------------------------
91 -- Error_Unterminated_String --
92 -------------------------------
94 procedure Error_Unterminated_String is
95 begin
96 -- An interesting little refinement. Consider the following examples:
98 -- A := "this is an unterminated string;
99 -- A := "this is an unterminated string &
100 -- P(A, "this is a parameter that didn't get terminated);
102 -- We fiddle a little to do slightly better placement in these cases
103 -- also if there is white space at the end of the line we place the
104 -- flag at the start of this white space, not at the end. Note that
105 -- we only have to test for blanks, since tabs aren't allowed in
106 -- strings in the first place and would have caused an error message.
108 -- Two more cases that we treat specially are:
110 -- A := "this string uses the wrong terminator'
111 -- A := "this string uses the wrong terminator' &
113 -- In these cases we give a different error message as well
115 -- We actually reposition the scan pointer to the point where we
116 -- place the flag in these cases, since it seems a better bet on
117 -- the original intention.
119 while Source (Scan_Ptr - 1) = ' '
120 or else Source (Scan_Ptr - 1) = '&'
121 loop
122 Scan_Ptr := Scan_Ptr - 1;
123 Unstore_String_Char;
124 end loop;
126 -- Check for case of incorrect string terminator, but single quote is
127 -- not considered incorrect if the opening terminator misused a single
128 -- quote (error message already given).
130 if Delimiter /= '''
131 and then Source (Scan_Ptr - 1) = '''
132 then
133 Unstore_String_Char;
134 Error_Msg ("incorrect string terminator character", Scan_Ptr - 1);
135 return;
136 end if;
138 if Source (Scan_Ptr - 1) = ';' then
139 Scan_Ptr := Scan_Ptr - 1;
140 Unstore_String_Char;
142 if Source (Scan_Ptr - 1) = ')' then
143 Scan_Ptr := Scan_Ptr - 1;
144 Unstore_String_Char;
145 end if;
146 end if;
148 Error_Msg_S ("missing string quote");
149 end Error_Unterminated_String;
151 ----------------
152 -- Set_String --
153 ----------------
155 procedure Set_String is
156 Slen : Int := Int (Scan_Ptr - Token_Ptr - 2);
157 C1 : Character;
158 C2 : Character;
159 C3 : Character;
161 begin
162 -- Token_Name is currently set to Error_Name. The following section of
163 -- code resets Token_Name to the proper Name_Op_xx value if the string
164 -- is a valid operator symbol, otherwise it is left set to Error_Name.
166 if Slen = 1 then
167 C1 := Source (Token_Ptr + 1);
169 case C1 is
170 when '=' =>
171 Token_Name := Name_Op_Eq;
173 when '>' =>
174 Token_Name := Name_Op_Gt;
176 when '<' =>
177 Token_Name := Name_Op_Lt;
179 when '+' =>
180 Token_Name := Name_Op_Add;
182 when '-' =>
183 Token_Name := Name_Op_Subtract;
185 when '&' =>
186 Token_Name := Name_Op_Concat;
188 when '*' =>
189 Token_Name := Name_Op_Multiply;
191 when '/' =>
192 Token_Name := Name_Op_Divide;
194 when others =>
195 null;
196 end case;
198 elsif Slen = 2 then
199 C1 := Source (Token_Ptr + 1);
200 C2 := Source (Token_Ptr + 2);
202 if C1 = '*' and then C2 = '*' then
203 Token_Name := Name_Op_Expon;
205 elsif C2 = '=' then
207 if C1 = '/' then
208 Token_Name := Name_Op_Ne;
209 elsif C1 = '<' then
210 Token_Name := Name_Op_Le;
211 elsif C1 = '>' then
212 Token_Name := Name_Op_Ge;
213 end if;
215 elsif (C1 = 'O' or else C1 = 'o') and then -- OR
216 (C2 = 'R' or else C2 = 'r')
217 then
218 Token_Name := Name_Op_Or;
219 end if;
221 elsif Slen = 3 then
222 C1 := Source (Token_Ptr + 1);
223 C2 := Source (Token_Ptr + 2);
224 C3 := Source (Token_Ptr + 3);
226 if (C1 = 'A' or else C1 = 'a') and then -- AND
227 (C2 = 'N' or else C2 = 'n') and then
228 (C3 = 'D' or else C3 = 'd')
229 then
230 Token_Name := Name_Op_And;
232 elsif (C1 = 'A' or else C1 = 'a') and then -- ABS
233 (C2 = 'B' or else C2 = 'b') and then
234 (C3 = 'S' or else C3 = 's')
235 then
236 Token_Name := Name_Op_Abs;
238 elsif (C1 = 'M' or else C1 = 'm') and then -- MOD
239 (C2 = 'O' or else C2 = 'o') and then
240 (C3 = 'D' or else C3 = 'd')
241 then
242 Token_Name := Name_Op_Mod;
244 elsif (C1 = 'N' or else C1 = 'n') and then -- NOT
245 (C2 = 'O' or else C2 = 'o') and then
246 (C3 = 'T' or else C3 = 't')
247 then
248 Token_Name := Name_Op_Not;
250 elsif (C1 = 'R' or else C1 = 'r') and then -- REM
251 (C2 = 'E' or else C2 = 'e') and then
252 (C3 = 'M' or else C3 = 'm')
253 then
254 Token_Name := Name_Op_Rem;
256 elsif (C1 = 'X' or else C1 = 'x') and then -- XOR
257 (C2 = 'O' or else C2 = 'o') and then
258 (C3 = 'R' or else C3 = 'r')
259 then
260 Token_Name := Name_Op_Xor;
261 end if;
263 end if;
265 -- If it is an operator symbol, then Token_Name is set. If it is some
266 -- other string value, then Token_Name still contains Error_Name.
268 if Token_Name = Error_Name then
269 Token := Tok_String_Literal;
270 Token_Node := New_Node (N_String_Literal, Token_Ptr);
271 Set_Has_Wide_Character (Token_Node, Wide_Character_Found);
273 else
274 Token := Tok_Operator_Symbol;
275 Token_Node := New_Node (N_Operator_Symbol, Token_Ptr);
276 Set_Chars (Token_Node, Token_Name);
277 end if;
279 Set_Strval (Token_Node, String_Literal_Id);
281 end Set_String;
283 ----------
284 -- Slit --
285 ----------
287 begin
288 -- On entry, Scan_Ptr points to the opening character of the string which
289 -- is either a percent, double quote, or apostrophe (single quote). The
290 -- latter case is an error detected by the character literal circuit.
292 Delimiter := Source (Scan_Ptr);
293 Accumulate_Checksum (Delimiter);
294 Start_String;
295 Scan_Ptr := Scan_Ptr + 1;
297 -- Loop to scan out characters of string literal
299 loop
300 C := Source (Scan_Ptr);
302 if C = Delimiter then
303 Accumulate_Checksum (C);
304 Scan_Ptr := Scan_Ptr + 1;
305 exit when Source (Scan_Ptr) /= Delimiter;
306 Code := Get_Char_Code (C);
307 Accumulate_Checksum (C);
308 Scan_Ptr := Scan_Ptr + 1;
310 else
311 if C = '"' and then Delimiter = '%' then
312 Error_Msg_S ("quote not allowed in percent delimited string");
313 Code := Get_Char_Code (C);
314 Scan_Ptr := Scan_Ptr + 1;
316 elsif (C = ESC
317 and then
318 Wide_Character_Encoding_Method in WC_ESC_Encoding_Method)
319 or else
320 (C in Upper_Half_Character
321 and then
322 Upper_Half_Encoding)
323 or else
324 (C = '['
325 and then
326 Source (Scan_Ptr + 1) = '"'
327 and then
328 Identifier_Char (Source (Scan_Ptr + 2)))
329 then
330 Scan_Wide (Source, Scan_Ptr, Code, Err);
331 Accumulate_Checksum (Code);
333 if Err then
334 Error_Illegal_Wide_Character;
335 Code := Get_Char_Code (' ');
336 end if;
338 else
339 Accumulate_Checksum (C);
341 if C not in Graphic_Character then
342 if C in Line_Terminator then
343 Error_Unterminated_String;
344 exit;
346 elsif C in Upper_Half_Character then
347 if Ada_83 then
348 Error_Bad_String_Char;
349 end if;
351 else
352 Error_Bad_String_Char;
353 end if;
354 end if;
356 Code := Get_Char_Code (C);
357 Scan_Ptr := Scan_Ptr + 1;
358 end if;
359 end if;
361 Store_String_Char (Code);
363 if not In_Character_Range (Code) then
364 Wide_Character_Found := True;
365 end if;
366 end loop;
368 String_Literal_Id := End_String;
369 Set_String;
370 return;
372 end Slit;