Mercurial > hg > CbC > CbC_gcc
comparison gcc/ada/errutil.adb @ 111:04ced10e8804
gcc 7
author | kono |
---|---|
date | Fri, 27 Oct 2017 22:46:09 +0900 |
parents | |
children | 84e7813d76e9 |
comparison
equal
deleted
inserted
replaced
68:561a7518be6b | 111:04ced10e8804 |
---|---|
1 ------------------------------------------------------------------------------ | |
2 -- -- | |
3 -- GNAT COMPILER COMPONENTS -- | |
4 -- -- | |
5 -- E R R U T I L -- | |
6 -- -- | |
7 -- B o d y -- | |
8 -- -- | |
9 -- Copyright (C) 1991-2017, 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 ------------------------------------------------------------------------------ | |
25 | |
26 with Atree; use Atree; | |
27 with Err_Vars; use Err_Vars; | |
28 with Erroutc; use Erroutc; | |
29 with Namet; use Namet; | |
30 with Opt; use Opt; | |
31 with Output; use Output; | |
32 with Scans; use Scans; | |
33 with Sinput; use Sinput; | |
34 with Stringt; use Stringt; | |
35 with Stylesw; use Stylesw; | |
36 | |
37 package body Errutil is | |
38 | |
39 Errors_Must_Be_Ignored : Boolean := False; | |
40 -- Set to True by procedure Set_Ignore_Errors (True), when calls to | |
41 -- error message procedures should be ignored (when parsing irrelevant | |
42 -- text in sources being preprocessed). | |
43 | |
44 ----------------------- | |
45 -- Local Subprograms -- | |
46 ----------------------- | |
47 | |
48 procedure Error_Msg_AP (Msg : String); | |
49 -- Output a message just after the previous token | |
50 | |
51 procedure Output_Source_Line | |
52 (L : Physical_Line_Number; | |
53 Sfile : Source_File_Index; | |
54 Errs : Boolean; | |
55 Source_Type : String); | |
56 -- Outputs text of source line L, in file S, together with preceding line | |
57 -- number, as described above for Output_Line_Number. The Errs parameter | |
58 -- indicates if there are errors attached to the line, which forces | |
59 -- listing on, even in the presence of pragma List (Off). | |
60 | |
61 procedure Set_Msg_Insertion_Column; | |
62 -- Handle column number insertion (@ insertion character) | |
63 | |
64 procedure Set_Msg_Text (Text : String; Flag : Source_Ptr); | |
65 -- Add a sequence of characters to the current message. The characters may | |
66 -- be one of the special insertion characters (see documentation in spec). | |
67 -- Flag is the location at which the error is to be posted, which is used | |
68 -- to determine whether or not the # insertion needs a file name. The | |
69 -- variables Msg_Buffer, Msglen, Is_Style_Msg, Is_Warning_Msg, and | |
70 -- Is_Unconditional_Msg are set on return. | |
71 | |
72 ------------------ | |
73 -- Error_Msg_AP -- | |
74 ------------------ | |
75 | |
76 procedure Error_Msg_AP (Msg : String) is | |
77 S1 : Source_Ptr; | |
78 C : Character; | |
79 | |
80 begin | |
81 -- If we had saved the Scan_Ptr value after scanning the previous | |
82 -- token, then we would have exactly the right place for putting | |
83 -- the flag immediately at hand. However, that would add at least | |
84 -- two instructions to a Scan call *just* to service the possibility | |
85 -- of an Error_Msg_AP call. So instead we reconstruct that value. | |
86 | |
87 -- We have two possibilities, start with Prev_Token_Ptr and skip over | |
88 -- the current token, which is made harder by the possibility that this | |
89 -- token may be in error, or start with Token_Ptr and work backwards. | |
90 -- We used to take the second approach, but it's hard because of | |
91 -- comments, and harder still because things that look like comments | |
92 -- can appear inside strings. So now we take the first approach. | |
93 | |
94 -- Note: in the case where there is no previous token, Prev_Token_Ptr | |
95 -- is set to Source_First, which is a reasonable position for the | |
96 -- error flag in this situation. | |
97 | |
98 S1 := Prev_Token_Ptr; | |
99 C := Source (S1); | |
100 | |
101 -- If the previous token is a string literal, we need a special approach | |
102 -- since there may be white space inside the literal and we don't want | |
103 -- to stop on that white space. | |
104 | |
105 -- Note that it is not worth worrying about special UTF_32 line | |
106 -- terminator characters in this context, since this is only about | |
107 -- error recovery anyway. | |
108 | |
109 if Prev_Token = Tok_String_Literal then | |
110 loop | |
111 S1 := S1 + 1; | |
112 | |
113 if Source (S1) = C then | |
114 S1 := S1 + 1; | |
115 exit when Source (S1) /= C; | |
116 elsif Source (S1) in Line_Terminator then | |
117 exit; | |
118 end if; | |
119 end loop; | |
120 | |
121 -- Character literal also needs special handling | |
122 | |
123 elsif Prev_Token = Tok_Char_Literal then | |
124 S1 := S1 + 3; | |
125 | |
126 -- Otherwise we search forward for the end of the current token, marked | |
127 -- by a line terminator, white space, a comment symbol or if we bump | |
128 -- into the following token (i.e. the current token) | |
129 | |
130 -- Note that it is not worth worrying about special UTF_32 line | |
131 -- terminator characters in this context, since this is only about | |
132 -- error recovery anyway. | |
133 | |
134 else | |
135 while Source (S1) not in Line_Terminator | |
136 and then Source (S1) /= ' ' | |
137 and then Source (S1) /= ASCII.HT | |
138 and then (Source (S1) /= '-' or else Source (S1 + 1) /= '-') | |
139 and then S1 /= Token_Ptr | |
140 loop | |
141 S1 := S1 + 1; | |
142 end loop; | |
143 end if; | |
144 | |
145 -- S1 is now set to the location for the flag | |
146 | |
147 Error_Msg (Msg, S1); | |
148 | |
149 end Error_Msg_AP; | |
150 | |
151 --------------- | |
152 -- Error_Msg -- | |
153 --------------- | |
154 | |
155 procedure Error_Msg (Msg : String; Flag_Location : Source_Ptr) is | |
156 | |
157 Next_Msg : Error_Msg_Id; | |
158 -- Pointer to next message at insertion point | |
159 | |
160 Prev_Msg : Error_Msg_Id; | |
161 -- Pointer to previous message at insertion point | |
162 | |
163 Sptr : Source_Ptr renames Flag_Location; | |
164 -- Corresponds to the Sptr value in the error message object | |
165 | |
166 Optr : Source_Ptr renames Flag_Location; | |
167 -- Corresponds to the Optr value in the error message object. Note that | |
168 -- for this usage, Sptr and Optr always have the same value, since we do | |
169 -- not have to worry about generic instantiations. | |
170 | |
171 begin | |
172 if Errors_Must_Be_Ignored then | |
173 return; | |
174 end if; | |
175 | |
176 if Raise_Exception_On_Error /= 0 then | |
177 raise Error_Msg_Exception; | |
178 end if; | |
179 | |
180 Prescan_Message (Msg); | |
181 Set_Msg_Text (Msg, Sptr); | |
182 | |
183 -- Kill continuation if parent message killed | |
184 | |
185 if Continuation and Last_Killed then | |
186 return; | |
187 end if; | |
188 | |
189 -- Return without doing anything if message is killed and this is not | |
190 -- the first error message. The philosophy is that if we get a weird | |
191 -- error message and we already have had a message, then we hope the | |
192 -- weird message is a junk cascaded message | |
193 | |
194 -- Immediate return if warning message and warnings are suppressed. | |
195 -- Note that style messages are not warnings for this purpose. | |
196 | |
197 if Is_Warning_Msg and then Warnings_Suppressed (Sptr) /= No_String then | |
198 Cur_Msg := No_Error_Msg; | |
199 return; | |
200 end if; | |
201 | |
202 -- Otherwise build error message object for new message | |
203 | |
204 Errors.Append | |
205 (New_Val => | |
206 (Text => new String'(Msg_Buffer (1 .. Msglen)), | |
207 Next => No_Error_Msg, | |
208 Prev => No_Error_Msg, | |
209 Sfile => Get_Source_File_Index (Sptr), | |
210 Sptr => Sptr, | |
211 Optr => Optr, | |
212 Line => Get_Physical_Line_Number (Sptr), | |
213 Col => Get_Column_Number (Sptr), | |
214 Warn => Is_Warning_Msg, | |
215 Info => Is_Info_Msg, | |
216 Check => Is_Check_Msg, | |
217 Warn_Err => Warning_Mode = Treat_As_Error, | |
218 Warn_Chr => Warning_Msg_Char, | |
219 Style => Is_Style_Msg, | |
220 Serious => Is_Serious_Error, | |
221 Uncond => Is_Unconditional_Msg, | |
222 Msg_Cont => Continuation, | |
223 Deleted => False, | |
224 Node => Empty)); | |
225 | |
226 Cur_Msg := Errors.Last; | |
227 Prev_Msg := No_Error_Msg; | |
228 Next_Msg := First_Error_Msg; | |
229 | |
230 while Next_Msg /= No_Error_Msg loop | |
231 exit when | |
232 Errors.Table (Cur_Msg).Sfile < Errors.Table (Next_Msg).Sfile; | |
233 | |
234 if Errors.Table (Cur_Msg).Sfile = Errors.Table (Next_Msg).Sfile then | |
235 exit when Sptr < Errors.Table (Next_Msg).Sptr; | |
236 end if; | |
237 | |
238 Prev_Msg := Next_Msg; | |
239 Next_Msg := Errors.Table (Next_Msg).Next; | |
240 end loop; | |
241 | |
242 -- Now we insert the new message in the error chain. The insertion | |
243 -- point for the message is after Prev_Msg and before Next_Msg. | |
244 | |
245 -- The possible insertion point for the new message is after Prev_Msg | |
246 -- and before Next_Msg. However, this is where we do a special check | |
247 -- for redundant parsing messages, defined as messages posted on the | |
248 -- same line. The idea here is that probably such messages are junk | |
249 -- from the parser recovering. In full errors mode, we don't do this | |
250 -- deletion, but otherwise such messages are discarded at this stage. | |
251 | |
252 if Prev_Msg /= No_Error_Msg | |
253 and then Errors.Table (Prev_Msg).Line = | |
254 Errors.Table (Cur_Msg).Line | |
255 and then Errors.Table (Prev_Msg).Sfile = | |
256 Errors.Table (Cur_Msg).Sfile | |
257 then | |
258 -- Don't delete unconditional messages and at this stage, don't | |
259 -- delete continuation lines (we attempted to delete those earlier | |
260 -- if the parent message was deleted. | |
261 | |
262 if not Errors.Table (Cur_Msg).Uncond | |
263 and then not Continuation | |
264 then | |
265 | |
266 -- Don't delete if prev msg is warning and new msg is an error. | |
267 -- This is because we don't want a real error masked by a warning. | |
268 -- In all other cases (that is parse errors for the same line that | |
269 -- are not unconditional) we do delete the message. This helps to | |
270 -- avoid junk extra messages from cascaded parsing errors | |
271 | |
272 if not (Errors.Table (Prev_Msg).Warn | |
273 or else | |
274 Errors.Table (Prev_Msg).Style) | |
275 or else | |
276 (Errors.Table (Cur_Msg).Warn | |
277 or else | |
278 Errors.Table (Cur_Msg).Style) | |
279 then | |
280 -- All tests passed, delete the message by simply returning | |
281 -- without any further processing. | |
282 | |
283 if not Continuation then | |
284 Last_Killed := True; | |
285 end if; | |
286 | |
287 return; | |
288 end if; | |
289 end if; | |
290 end if; | |
291 | |
292 -- Come here if message is to be inserted in the error chain | |
293 | |
294 if not Continuation then | |
295 Last_Killed := False; | |
296 end if; | |
297 | |
298 if Prev_Msg = No_Error_Msg then | |
299 First_Error_Msg := Cur_Msg; | |
300 else | |
301 Errors.Table (Prev_Msg).Next := Cur_Msg; | |
302 end if; | |
303 | |
304 Errors.Table (Cur_Msg).Next := Next_Msg; | |
305 | |
306 -- Bump appropriate statistics counts | |
307 | |
308 if Errors.Table (Cur_Msg).Info then | |
309 | |
310 -- Could be (usually is) both "info" and "warning" | |
311 | |
312 if Errors.Table (Cur_Msg).Warn then | |
313 Warning_Info_Messages := Warning_Info_Messages + 1; | |
314 Warnings_Detected := Warnings_Detected + 1; | |
315 else | |
316 Report_Info_Messages := Report_Info_Messages + 1; | |
317 end if; | |
318 | |
319 elsif Errors.Table (Cur_Msg).Warn | |
320 or else Errors.Table (Cur_Msg).Style | |
321 then | |
322 Warnings_Detected := Warnings_Detected + 1; | |
323 | |
324 elsif Errors.Table (Cur_Msg).Check then | |
325 Check_Messages := Check_Messages + 1; | |
326 | |
327 else | |
328 Total_Errors_Detected := Total_Errors_Detected + 1; | |
329 | |
330 if Errors.Table (Cur_Msg).Serious then | |
331 Serious_Errors_Detected := Serious_Errors_Detected + 1; | |
332 end if; | |
333 end if; | |
334 | |
335 end Error_Msg; | |
336 | |
337 ----------------- | |
338 -- Error_Msg_S -- | |
339 ----------------- | |
340 | |
341 procedure Error_Msg_S (Msg : String) is | |
342 begin | |
343 Error_Msg (Msg, Scan_Ptr); | |
344 end Error_Msg_S; | |
345 | |
346 ------------------ | |
347 -- Error_Msg_SC -- | |
348 ------------------ | |
349 | |
350 procedure Error_Msg_SC (Msg : String) is | |
351 begin | |
352 -- If we are at end of file, post the flag after the previous token | |
353 | |
354 if Token = Tok_EOF then | |
355 Error_Msg_AP (Msg); | |
356 | |
357 -- For all other cases the message is posted at the current token | |
358 -- pointer position | |
359 | |
360 else | |
361 Error_Msg (Msg, Token_Ptr); | |
362 end if; | |
363 end Error_Msg_SC; | |
364 | |
365 ------------------ | |
366 -- Error_Msg_SP -- | |
367 ------------------ | |
368 | |
369 procedure Error_Msg_SP (Msg : String) is | |
370 begin | |
371 -- Note: in the case where there is no previous token, Prev_Token_Ptr | |
372 -- is set to Source_First, which is a reasonable position for the | |
373 -- error flag in this situation | |
374 | |
375 Error_Msg (Msg, Prev_Token_Ptr); | |
376 end Error_Msg_SP; | |
377 | |
378 -------------- | |
379 -- Finalize -- | |
380 -------------- | |
381 | |
382 procedure Finalize (Source_Type : String := "project") is | |
383 Cur : Error_Msg_Id; | |
384 Nxt : Error_Msg_Id; | |
385 E, F : Error_Msg_Id; | |
386 Err_Flag : Boolean; | |
387 | |
388 begin | |
389 -- Eliminate any duplicated error messages from the list. This is | |
390 -- done after the fact to avoid problems with Change_Error_Text. | |
391 | |
392 Cur := First_Error_Msg; | |
393 while Cur /= No_Error_Msg loop | |
394 Nxt := Errors.Table (Cur).Next; | |
395 | |
396 F := Nxt; | |
397 while F /= No_Error_Msg | |
398 and then Errors.Table (F).Sptr = Errors.Table (Cur).Sptr | |
399 loop | |
400 Check_Duplicate_Message (Cur, F); | |
401 F := Errors.Table (F).Next; | |
402 end loop; | |
403 | |
404 Cur := Nxt; | |
405 end loop; | |
406 | |
407 -- Brief Error mode | |
408 | |
409 if Brief_Output or (not Full_List and not Verbose_Mode) then | |
410 E := First_Error_Msg; | |
411 Set_Standard_Error; | |
412 | |
413 while E /= No_Error_Msg loop | |
414 if not Errors.Table (E).Deleted then | |
415 if Full_Path_Name_For_Brief_Errors then | |
416 Write_Name (Full_Ref_Name (Errors.Table (E).Sfile)); | |
417 else | |
418 Write_Name (Reference_Name (Errors.Table (E).Sfile)); | |
419 end if; | |
420 | |
421 Write_Char (':'); | |
422 Write_Int (Int (Physical_To_Logical | |
423 (Errors.Table (E).Line, | |
424 Errors.Table (E).Sfile))); | |
425 Write_Char (':'); | |
426 | |
427 if Errors.Table (E).Col < 10 then | |
428 Write_Char ('0'); | |
429 end if; | |
430 | |
431 Write_Int (Int (Errors.Table (E).Col)); | |
432 Write_Str (": "); | |
433 Output_Msg_Text (E); | |
434 Write_Eol; | |
435 end if; | |
436 | |
437 E := Errors.Table (E).Next; | |
438 end loop; | |
439 | |
440 Set_Standard_Output; | |
441 end if; | |
442 | |
443 -- Full source listing case | |
444 | |
445 if Full_List then | |
446 List_Pragmas_Index := 1; | |
447 List_Pragmas_Mode := True; | |
448 E := First_Error_Msg; | |
449 Write_Eol; | |
450 | |
451 -- First list initial main source file with its error messages | |
452 | |
453 for N in 1 .. Last_Source_Line (Main_Source_File) loop | |
454 Err_Flag := | |
455 E /= No_Error_Msg | |
456 and then Errors.Table (E).Line = N | |
457 and then Errors.Table (E).Sfile = Main_Source_File; | |
458 | |
459 Output_Source_Line (N, Main_Source_File, Err_Flag, Source_Type); | |
460 | |
461 if Err_Flag then | |
462 Output_Error_Msgs (E); | |
463 | |
464 Write_Eol; | |
465 end if; | |
466 end loop; | |
467 | |
468 -- Then output errors, if any, for subsidiary units | |
469 | |
470 while E /= No_Error_Msg | |
471 and then Errors.Table (E).Sfile /= Main_Source_File | |
472 loop | |
473 Write_Eol; | |
474 Output_Source_Line | |
475 (Errors.Table (E).Line, | |
476 Errors.Table (E).Sfile, | |
477 True, | |
478 Source_Type); | |
479 Output_Error_Msgs (E); | |
480 end loop; | |
481 end if; | |
482 | |
483 -- Verbose mode (error lines only with error flags) | |
484 | |
485 if Verbose_Mode then | |
486 E := First_Error_Msg; | |
487 | |
488 -- Loop through error lines | |
489 | |
490 while E /= No_Error_Msg loop | |
491 Write_Eol; | |
492 Output_Source_Line | |
493 (Errors.Table (E).Line, | |
494 Errors.Table (E).Sfile, | |
495 True, | |
496 Source_Type); | |
497 Output_Error_Msgs (E); | |
498 end loop; | |
499 end if; | |
500 | |
501 -- Output error summary if verbose or full list mode | |
502 | |
503 if Verbose_Mode or else Full_List then | |
504 | |
505 -- Extra blank line if error messages or source listing were output | |
506 | |
507 if Total_Errors_Detected + Warnings_Detected > 0 | |
508 or else Full_List | |
509 then | |
510 Write_Eol; | |
511 end if; | |
512 | |
513 -- Message giving number of lines read and number of errors detected. | |
514 -- This normally goes to Standard_Output. The exception is when brief | |
515 -- mode is not set, verbose mode (or full list mode) is set, and | |
516 -- there are errors. In this case we send the message to standard | |
517 -- error to make sure that *something* appears on standard error in | |
518 -- an error situation. | |
519 | |
520 -- Historical note: Formerly, only the "# errors" suffix was sent | |
521 -- to stderr, whereas "# lines:" appeared on stdout. This caused | |
522 -- some problems on now-obsolete ports, but there seems to be no | |
523 -- reason to revert this page since it would be incompatible. | |
524 | |
525 if Total_Errors_Detected + Warnings_Detected /= 0 | |
526 and then not Brief_Output | |
527 and then (Verbose_Mode or Full_List) | |
528 then | |
529 Set_Standard_Error; | |
530 end if; | |
531 | |
532 -- Message giving total number of lines | |
533 | |
534 Write_Str (" "); | |
535 Write_Int (Num_Source_Lines (Main_Source_File)); | |
536 | |
537 if Num_Source_Lines (Main_Source_File) = 1 then | |
538 Write_Str (" line: "); | |
539 else | |
540 Write_Str (" lines: "); | |
541 end if; | |
542 | |
543 if Total_Errors_Detected = 0 then | |
544 Write_Str ("No errors"); | |
545 | |
546 elsif Total_Errors_Detected = 1 then | |
547 Write_Str ("1 error"); | |
548 | |
549 else | |
550 Write_Int (Total_Errors_Detected); | |
551 Write_Str (" errors"); | |
552 end if; | |
553 | |
554 if Warnings_Detected - Warning_Info_Messages /= 0 then | |
555 Write_Str (", "); | |
556 Write_Int (Warnings_Detected - Warning_Info_Messages); | |
557 Write_Str (" warning"); | |
558 | |
559 if Warnings_Detected - Warning_Info_Messages /= 1 then | |
560 Write_Char ('s'); | |
561 end if; | |
562 | |
563 if Warning_Mode = Treat_As_Error then | |
564 Write_Str (" (treated as error"); | |
565 | |
566 if Warnings_Detected - Warning_Info_Messages /= 1 then | |
567 Write_Char ('s'); | |
568 end if; | |
569 | |
570 Write_Char (')'); | |
571 end if; | |
572 end if; | |
573 | |
574 Write_Eol; | |
575 Set_Standard_Output; | |
576 end if; | |
577 | |
578 if Maximum_Messages /= 0 then | |
579 if Warnings_Detected >= Maximum_Messages then | |
580 Set_Standard_Error; | |
581 Write_Line ("maximum number of warnings detected"); | |
582 Warning_Mode := Suppress; | |
583 end if; | |
584 | |
585 if Total_Errors_Detected >= Maximum_Messages then | |
586 Set_Standard_Error; | |
587 Write_Line ("fatal error: maximum errors reached"); | |
588 Set_Standard_Output; | |
589 end if; | |
590 end if; | |
591 | |
592 -- Even though Warning_Info_Messages are a subclass of warnings, they | |
593 -- must not be treated as errors when -gnatwe is in effect. | |
594 | |
595 if Warning_Mode = Treat_As_Error then | |
596 Total_Errors_Detected := | |
597 Total_Errors_Detected + Warnings_Detected - Warning_Info_Messages; | |
598 Warnings_Detected := Warning_Info_Messages; | |
599 end if; | |
600 | |
601 -- Prevent displaying the same messages again in the future | |
602 | |
603 First_Error_Msg := No_Error_Msg; | |
604 end Finalize; | |
605 | |
606 ---------------- | |
607 -- Initialize -- | |
608 ---------------- | |
609 | |
610 procedure Initialize is | |
611 begin | |
612 Errors.Init; | |
613 First_Error_Msg := No_Error_Msg; | |
614 Last_Error_Msg := No_Error_Msg; | |
615 Serious_Errors_Detected := 0; | |
616 Total_Errors_Detected := 0; | |
617 Warnings_Detected := 0; | |
618 Warning_Info_Messages := 0; | |
619 Report_Info_Messages := 0; | |
620 Cur_Msg := No_Error_Msg; | |
621 | |
622 -- Initialize warnings table, if all warnings are suppressed, supply | |
623 -- an initial dummy entry covering all possible source locations. | |
624 | |
625 Warnings.Init; | |
626 | |
627 if Warning_Mode = Suppress then | |
628 Warnings.Append | |
629 (New_Val => | |
630 (Start => Source_Ptr'First, | |
631 Stop => Source_Ptr'Last, | |
632 Reason => Null_String_Id)); | |
633 end if; | |
634 end Initialize; | |
635 | |
636 ------------------------ | |
637 -- Output_Source_Line -- | |
638 ------------------------ | |
639 | |
640 procedure Output_Source_Line | |
641 (L : Physical_Line_Number; | |
642 Sfile : Source_File_Index; | |
643 Errs : Boolean; | |
644 Source_Type : String) | |
645 is | |
646 S : Source_Ptr; | |
647 C : Character; | |
648 | |
649 Line_Number_Output : Boolean := False; | |
650 -- Set True once line number is output | |
651 | |
652 begin | |
653 if Sfile /= Current_Error_Source_File then | |
654 Write_Str ("==============Error messages for "); | |
655 Write_Str (Source_Type); | |
656 Write_Str (" file: "); | |
657 Write_Name (Full_File_Name (Sfile)); | |
658 Write_Eol; | |
659 Current_Error_Source_File := Sfile; | |
660 end if; | |
661 | |
662 if Errs then | |
663 Output_Line_Number (Physical_To_Logical (L, Sfile)); | |
664 Line_Number_Output := True; | |
665 end if; | |
666 | |
667 S := Line_Start (L, Sfile); | |
668 | |
669 loop | |
670 C := Source_Text (Sfile) (S); | |
671 exit when C = ASCII.LF or else C = ASCII.CR or else C = EOF; | |
672 | |
673 if Errs then | |
674 Write_Char (C); | |
675 end if; | |
676 | |
677 S := S + 1; | |
678 end loop; | |
679 | |
680 if Line_Number_Output then | |
681 Write_Eol; | |
682 end if; | |
683 end Output_Source_Line; | |
684 | |
685 ----------------------- | |
686 -- Set_Ignore_Errors -- | |
687 ----------------------- | |
688 | |
689 procedure Set_Ignore_Errors (To : Boolean) is | |
690 begin | |
691 Errors_Must_Be_Ignored := To; | |
692 end Set_Ignore_Errors; | |
693 | |
694 ------------------------------ | |
695 -- Set_Msg_Insertion_Column -- | |
696 ------------------------------ | |
697 | |
698 procedure Set_Msg_Insertion_Column is | |
699 begin | |
700 if RM_Column_Check then | |
701 Set_Msg_Str (" in column "); | |
702 Set_Msg_Int (Int (Error_Msg_Col) + 1); | |
703 end if; | |
704 end Set_Msg_Insertion_Column; | |
705 | |
706 ------------------ | |
707 -- Set_Msg_Text -- | |
708 ------------------ | |
709 | |
710 procedure Set_Msg_Text (Text : String; Flag : Source_Ptr) is | |
711 C : Character; -- Current character | |
712 P : Natural; -- Current index; | |
713 | |
714 begin | |
715 Manual_Quote_Mode := False; | |
716 Msglen := 0; | |
717 Flag_Source := Get_Source_File_Index (Flag); | |
718 P := Text'First; | |
719 | |
720 while P <= Text'Last loop | |
721 C := Text (P); | |
722 P := P + 1; | |
723 | |
724 -- Check for insertion character | |
725 | |
726 if C = '%' then | |
727 if P <= Text'Last and then Text (P) = '%' then | |
728 P := P + 1; | |
729 Set_Msg_Insertion_Name_Literal; | |
730 else | |
731 Set_Msg_Insertion_Name; | |
732 end if; | |
733 | |
734 elsif C = '$' then | |
735 | |
736 -- '$' is ignored | |
737 | |
738 null; | |
739 | |
740 elsif C = '{' then | |
741 Set_Msg_Insertion_File_Name; | |
742 | |
743 elsif C = '}' then | |
744 | |
745 -- '}' is ignored | |
746 | |
747 null; | |
748 | |
749 elsif C = '*' then | |
750 Set_Msg_Insertion_Reserved_Name; | |
751 | |
752 elsif C = '&' then | |
753 | |
754 -- '&' is ignored | |
755 | |
756 null; | |
757 | |
758 elsif C = '#' then | |
759 Set_Msg_Insertion_Line_Number (Error_Msg_Sloc, Flag); | |
760 | |
761 elsif C = '\' then | |
762 Continuation := True; | |
763 | |
764 elsif C = '@' then | |
765 Set_Msg_Insertion_Column; | |
766 | |
767 elsif C = '^' then | |
768 Set_Msg_Insertion_Uint; | |
769 | |
770 elsif C = '`' then | |
771 Manual_Quote_Mode := not Manual_Quote_Mode; | |
772 Set_Msg_Char ('"'); | |
773 | |
774 elsif C = '!' then | |
775 null; | |
776 | |
777 elsif C = '?' then | |
778 null; | |
779 | |
780 elsif C = '<' then | |
781 null; | |
782 | |
783 elsif C = '|' then | |
784 null; | |
785 | |
786 elsif C = ''' then | |
787 Set_Msg_Char (Text (P)); | |
788 P := P + 1; | |
789 | |
790 -- Upper case letter (start of reserved word if 2 or more) | |
791 | |
792 elsif C in 'A' .. 'Z' | |
793 and then P <= Text'Last | |
794 and then Text (P) in 'A' .. 'Z' | |
795 then | |
796 P := P - 1; | |
797 Set_Msg_Insertion_Reserved_Word (Text, P); | |
798 | |
799 elsif C = '~' then | |
800 Set_Msg_Str (Error_Msg_String (1 .. Error_Msg_Strlen)); | |
801 | |
802 -- Normal character with no special treatment | |
803 | |
804 else | |
805 Set_Msg_Char (C); | |
806 end if; | |
807 | |
808 end loop; | |
809 end Set_Msg_Text; | |
810 | |
811 end Errutil; |