]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/ada/sinput-l.adb
2009-04-16 Thomas Quinot <quinot@adacore.com>
[thirdparty/gcc.git] / gcc / ada / sinput-l.adb
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT COMPILER COMPONENTS --
4 -- --
5 -- S I N P U T . L --
6 -- --
7 -- B o d y --
8 -- --
9 -- Copyright (C) 1992-2008, 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 Alloc;
27 with Atree; use Atree;
28 with Debug; use Debug;
29 with Einfo; use Einfo;
30 with Errout; use Errout;
31 with Fname; use Fname;
32 with Hostparm;
33 with Opt; use Opt;
34 with Osint; use Osint;
35 with Output; use Output;
36 with Prep; use Prep;
37 with Prepcomp; use Prepcomp;
38 with Scans; use Scans;
39 with Scn; use Scn;
40 with Sinfo; use Sinfo;
41 with Snames; use Snames;
42 with System; use System;
43
44 with System.OS_Lib; use System.OS_Lib;
45
46 with Unchecked_Conversion;
47
48 package body Sinput.L is
49
50 Prep_Buffer : Text_Buffer_Ptr := null;
51 -- A buffer to temporarily stored the result of preprocessing a source.
52 -- It is only allocated if there is at least one source to preprocess.
53
54 Prep_Buffer_Last : Text_Ptr := 0;
55 -- Index of the last significant character in Prep_Buffer
56
57 Initial_Size_Of_Prep_Buffer : constant := 10_000;
58 -- Size of Prep_Buffer when it is first allocated
59
60 -- When a file is to be preprocessed and the options to list symbols
61 -- has been selected (switch -s), Prep.List_Symbols is called with a
62 -- "foreword", a single line indicating what source the symbols apply to.
63 -- The following two constant String are the start and the end of this
64 -- foreword.
65
66 Foreword_Start : constant String :=
67 "Preprocessing Symbols for source """;
68
69 Foreword_End : constant String := """";
70
71 -----------------
72 -- Subprograms --
73 -----------------
74
75 procedure Put_Char_In_Prep_Buffer (C : Character);
76 -- Add one character in Prep_Buffer, extending Prep_Buffer if need be.
77 -- Used to initialize the preprocessor.
78
79 procedure New_EOL_In_Prep_Buffer;
80 -- Add an LF to Prep_Buffer (used to initialize the preprocessor)
81
82 function Load_File
83 (N : File_Name_Type;
84 T : Osint.File_Type) return Source_File_Index;
85 -- Load a source file, a configuration pragmas file or a definition file
86 -- Coding also allows preprocessing file, but not a library file ???
87
88 -------------------------------
89 -- Adjust_Instantiation_Sloc --
90 -------------------------------
91
92 procedure Adjust_Instantiation_Sloc (N : Node_Id; A : Sloc_Adjustment) is
93 Loc : constant Source_Ptr := Sloc (N);
94
95 begin
96 -- We only do the adjustment if the value is between the appropriate low
97 -- and high values. It is not clear that this should ever not be the
98 -- case, but in practice there seem to be some nodes that get copied
99 -- twice, and this is a defence against that happening.
100
101 if A.Lo <= Loc and then Loc <= A.Hi then
102 Set_Sloc (N, Loc + A.Adjust);
103 end if;
104 end Adjust_Instantiation_Sloc;
105
106 --------------------------------
107 -- Complete_Source_File_Entry --
108 --------------------------------
109
110 procedure Complete_Source_File_Entry is
111 CSF : constant Source_File_Index := Current_Source_File;
112
113 begin
114 Trim_Lines_Table (CSF);
115 Source_File.Table (CSF).Source_Checksum := Checksum;
116 end Complete_Source_File_Entry;
117
118 ---------------------------------
119 -- Create_Instantiation_Source --
120 ---------------------------------
121
122 procedure Create_Instantiation_Source
123 (Inst_Node : Entity_Id;
124 Template_Id : Entity_Id;
125 Inlined_Body : Boolean;
126 A : out Sloc_Adjustment)
127 is
128 Dnod : constant Node_Id := Declaration_Node (Template_Id);
129 Xold : Source_File_Index;
130 Xnew : Source_File_Index;
131
132 begin
133 Xold := Get_Source_File_Index (Sloc (Template_Id));
134 A.Lo := Source_File.Table (Xold).Source_First;
135 A.Hi := Source_File.Table (Xold).Source_Last;
136
137 Source_File.Append (Source_File.Table (Xold));
138 Xnew := Source_File.Last;
139
140 Source_File.Table (Xnew).Inlined_Body := Inlined_Body;
141 Source_File.Table (Xnew).Instantiation := Sloc (Inst_Node);
142 Source_File.Table (Xnew).Template := Xold;
143
144 -- Now we need to compute the new values of Source_First, Source_Last
145 -- and adjust the source file pointer to have the correct virtual
146 -- origin for the new range of values.
147
148 Source_File.Table (Xnew).Source_First :=
149 Source_File.Table (Xnew - 1).Source_Last + 1;
150 A.Adjust := Source_File.Table (Xnew).Source_First - A.Lo;
151 Source_File.Table (Xnew).Source_Last := A.Hi + A.Adjust;
152
153 Set_Source_File_Index_Table (Xnew);
154
155 Source_File.Table (Xnew).Sloc_Adjust :=
156 Source_File.Table (Xold).Sloc_Adjust - A.Adjust;
157
158 if Debug_Flag_L then
159 Write_Eol;
160 Write_Str ("*** Create instantiation source for ");
161
162 if Nkind (Dnod) in N_Proper_Body
163 and then Was_Originally_Stub (Dnod)
164 then
165 Write_Str ("subunit ");
166
167 elsif Ekind (Template_Id) = E_Generic_Package then
168 if Nkind (Dnod) = N_Package_Body then
169 Write_Str ("body of package ");
170 else
171 Write_Str ("spec of package ");
172 end if;
173
174 elsif Ekind (Template_Id) = E_Function then
175 Write_Str ("body of function ");
176
177 elsif Ekind (Template_Id) = E_Procedure then
178 Write_Str ("body of procedure ");
179
180 elsif Ekind (Template_Id) = E_Generic_Function then
181 Write_Str ("spec of function ");
182
183 elsif Ekind (Template_Id) = E_Generic_Procedure then
184 Write_Str ("spec of procedure ");
185
186 elsif Ekind (Template_Id) = E_Package_Body then
187 Write_Str ("body of package ");
188
189 else pragma Assert (Ekind (Template_Id) = E_Subprogram_Body);
190
191 if Nkind (Dnod) = N_Procedure_Specification then
192 Write_Str ("body of procedure ");
193 else
194 Write_Str ("body of function ");
195 end if;
196 end if;
197
198 Write_Name (Chars (Template_Id));
199 Write_Eol;
200
201 Write_Str (" new source index = ");
202 Write_Int (Int (Xnew));
203 Write_Eol;
204
205 Write_Str (" copying from file name = ");
206 Write_Name (File_Name (Xold));
207 Write_Eol;
208
209 Write_Str (" old source index = ");
210 Write_Int (Int (Xold));
211 Write_Eol;
212
213 Write_Str (" old lo = ");
214 Write_Int (Int (A.Lo));
215 Write_Eol;
216
217 Write_Str (" old hi = ");
218 Write_Int (Int (A.Hi));
219 Write_Eol;
220
221 Write_Str (" new lo = ");
222 Write_Int (Int (Source_File.Table (Xnew).Source_First));
223 Write_Eol;
224
225 Write_Str (" new hi = ");
226 Write_Int (Int (Source_File.Table (Xnew).Source_Last));
227 Write_Eol;
228
229 Write_Str (" adjustment factor = ");
230 Write_Int (Int (A.Adjust));
231 Write_Eol;
232
233 Write_Str (" instantiation location: ");
234 Write_Location (Sloc (Inst_Node));
235 Write_Eol;
236 end if;
237
238 -- For a given character in the source, a higher subscript will be used
239 -- to access the instantiation, which means that the virtual origin must
240 -- have a corresponding lower value. We compute this new origin by
241 -- taking the address of the appropriate adjusted element in the old
242 -- array. Since this adjusted element will be at a negative subscript,
243 -- we must suppress checks.
244
245 declare
246 pragma Suppress (All_Checks);
247
248 pragma Warnings (Off);
249 -- This unchecked conversion is aliasing safe, since it is never used
250 -- to create improperly aliased pointer values.
251
252 function To_Source_Buffer_Ptr is new
253 Unchecked_Conversion (Address, Source_Buffer_Ptr);
254
255 pragma Warnings (On);
256
257 begin
258 Source_File.Table (Xnew).Source_Text :=
259 To_Source_Buffer_Ptr
260 (Source_File.Table (Xold).Source_Text (-A.Adjust)'Address);
261 end;
262 end Create_Instantiation_Source;
263
264 ----------------------
265 -- Load_Config_File --
266 ----------------------
267
268 function Load_Config_File
269 (N : File_Name_Type) return Source_File_Index
270 is
271 begin
272 return Load_File (N, Osint.Config);
273 end Load_Config_File;
274
275 --------------------------
276 -- Load_Definition_File --
277 --------------------------
278
279 function Load_Definition_File
280 (N : File_Name_Type) return Source_File_Index
281 is
282 begin
283 return Load_File (N, Osint.Definition);
284 end Load_Definition_File;
285
286 ---------------
287 -- Load_File --
288 ---------------
289
290 function Load_File
291 (N : File_Name_Type;
292 T : Osint.File_Type) return Source_File_Index
293 is
294 Src : Source_Buffer_Ptr;
295 X : Source_File_Index;
296 Lo : Source_Ptr;
297 Hi : Source_Ptr;
298
299 Preprocessing_Needed : Boolean := False;
300
301 begin
302 -- If already there, don't need to reload file. An exception occurs
303 -- in multiple unit per file mode. It would be nice in this case to
304 -- share the same source file for each unit, but this leads to many
305 -- difficulties with assumptions (e.g. in the body of lib), that a
306 -- unit can be found by locating its source file index. Since we do
307 -- not expect much use of this mode, it's no big deal to waste a bit
308 -- of space and time by reading and storing the source multiple times.
309
310 if Multiple_Unit_Index = 0 then
311 for J in 1 .. Source_File.Last loop
312 if Source_File.Table (J).File_Name = N then
313 return J;
314 end if;
315 end loop;
316 end if;
317
318 -- Here we must build a new entry in the file table
319
320 -- But first, we must check if a source needs to be preprocessed,
321 -- because we may have to load and parse a definition file, and we want
322 -- to do that before we load the source, so that the buffer of the
323 -- source will be the last created, and we will be able to replace it
324 -- and modify Hi without stepping on another buffer.
325
326 if T = Osint.Source and then not Is_Internal_File_Name (N) then
327 Prepare_To_Preprocess
328 (Source => N, Preprocessing_Needed => Preprocessing_Needed);
329 end if;
330
331 Source_File.Increment_Last;
332 X := Source_File.Last;
333
334 if X = Source_File.First then
335 Lo := First_Source_Ptr;
336 else
337 Lo := Source_File.Table (X - 1).Source_Last + 1;
338 end if;
339
340 Osint.Read_Source_File (N, Lo, Hi, Src, T);
341
342 if Src = null then
343 Source_File.Decrement_Last;
344 return No_Source_File;
345
346 else
347 if Debug_Flag_L then
348 Write_Eol;
349 Write_Str ("*** Build source file table entry, Index = ");
350 Write_Int (Int (X));
351 Write_Str (", file name = ");
352 Write_Name (N);
353 Write_Eol;
354 Write_Str (" lo = ");
355 Write_Int (Int (Lo));
356 Write_Eol;
357 Write_Str (" hi = ");
358 Write_Int (Int (Hi));
359 Write_Eol;
360
361 Write_Str (" first 10 chars -->");
362
363 declare
364 procedure Wchar (C : Character);
365 -- Writes character or ? for control character
366
367 procedure Wchar (C : Character) is
368 begin
369 if C < ' ' or C in ASCII.DEL .. Character'Val (16#9F#) then
370 Write_Char ('?');
371 else
372 Write_Char (C);
373 end if;
374 end Wchar;
375
376 begin
377 for J in Lo .. Lo + 9 loop
378 Wchar (Src (J));
379 end loop;
380
381 Write_Str ("<--");
382 Write_Eol;
383
384 Write_Str (" last 10 chars -->");
385
386 for J in Hi - 10 .. Hi - 1 loop
387 Wchar (Src (J));
388 end loop;
389
390 Write_Str ("<--");
391 Write_Eol;
392
393 if Src (Hi) /= EOF then
394 Write_Str (" error: no EOF at end");
395 Write_Eol;
396 end if;
397 end;
398 end if;
399
400 declare
401 S : Source_File_Record renames Source_File.Table (X);
402 File_Type : Type_Of_File;
403
404 begin
405 case T is
406 when Osint.Source =>
407 File_Type := Sinput.Src;
408
409 when Osint.Library =>
410 raise Program_Error;
411
412 when Osint.Config =>
413 File_Type := Sinput.Config;
414
415 when Osint.Definition =>
416 File_Type := Def;
417
418 when Osint.Preprocessing_Data =>
419 File_Type := Preproc;
420 end case;
421
422 S := (Debug_Source_Name => N,
423 File_Name => N,
424 File_Type => File_Type,
425 First_Mapped_Line => No_Line_Number,
426 Full_Debug_Name => Osint.Full_Source_Name,
427 Full_File_Name => Osint.Full_Source_Name,
428 Full_Ref_Name => Osint.Full_Source_Name,
429 Identifier_Casing => Unknown,
430 Inlined_Body => False,
431 Instantiation => No_Location,
432 Keyword_Casing => Unknown,
433 Last_Source_Line => 1,
434 License => Unknown,
435 Lines_Table => null,
436 Lines_Table_Max => 1,
437 Logical_Lines_Table => null,
438 Num_SRef_Pragmas => 0,
439 Reference_Name => N,
440 Sloc_Adjust => 0,
441 Source_Checksum => 0,
442 Source_First => Lo,
443 Source_Last => Hi,
444 Source_Text => Src,
445 Template => No_Source_File,
446 Unit => No_Unit,
447 Time_Stamp => Osint.Current_Source_File_Stamp);
448
449 Alloc_Line_Tables (S, Opt.Table_Factor * Alloc.Lines_Initial);
450 S.Lines_Table (1) := Lo;
451 end;
452
453 -- Preprocess the source if it needs to be preprocessed
454
455 if Preprocessing_Needed then
456 if Opt.List_Preprocessing_Symbols then
457 Get_Name_String (N);
458
459 declare
460 Foreword : String (1 .. Foreword_Start'Length +
461 Name_Len + Foreword_End'Length);
462
463 begin
464 Foreword (1 .. Foreword_Start'Length) := Foreword_Start;
465 Foreword (Foreword_Start'Length + 1 ..
466 Foreword_Start'Length + Name_Len) :=
467 Name_Buffer (1 .. Name_Len);
468 Foreword (Foreword'Last - Foreword_End'Length + 1 ..
469 Foreword'Last) := Foreword_End;
470 Prep.List_Symbols (Foreword);
471 end;
472 end if;
473
474 declare
475 T : constant Nat := Total_Errors_Detected;
476 -- Used to check if there were errors during preprocessing
477
478 Save_Style_Check : Boolean;
479 -- Saved state of the Style_Check flag (which needs to be
480 -- temporarily set to False during preprocessing, see below).
481
482 Modified : Boolean;
483
484 begin
485 -- If this is the first time we preprocess a source, allocate
486 -- the preprocessing buffer.
487
488 if Prep_Buffer = null then
489 Prep_Buffer :=
490 new Text_Buffer (1 .. Initial_Size_Of_Prep_Buffer);
491 end if;
492
493 -- Make sure the preprocessing buffer is empty
494
495 Prep_Buffer_Last := 0;
496
497 -- Initialize the preprocessor hooks
498
499 Prep.Setup_Hooks
500 (Error_Msg => Errout.Error_Msg'Access,
501 Scan => Scn.Scanner.Scan'Access,
502 Set_Ignore_Errors => Errout.Set_Ignore_Errors'Access,
503 Put_Char => Put_Char_In_Prep_Buffer'Access,
504 New_EOL => New_EOL_In_Prep_Buffer'Access);
505
506 -- Initialize scanner and set its behavior for preprocessing,
507 -- then preprocess. Also disable style checks, since some of
508 -- them are done in the scanner (specifically, those dealing
509 -- with line length and line termination), and cannot be done
510 -- during preprocessing (because the source file index table
511 -- has not been set yet).
512
513 Scn.Scanner.Initialize_Scanner (X);
514
515 Scn.Scanner.Set_Special_Character ('#');
516 Scn.Scanner.Set_Special_Character ('$');
517 Scn.Scanner.Set_End_Of_Line_As_Token (True);
518 Save_Style_Check := Opt.Style_Check;
519 Opt.Style_Check := False;
520
521 -- Make sure that there will be no check of pragma Restrictions
522 -- for obsolescent features while preprocessing the source.
523
524 Scn.Set_Obsolescent_Check (False);
525 Preprocess (Modified);
526 Scn.Set_Obsolescent_Check (True);
527
528 -- Reset the scanner to its standard behavior, and restore the
529 -- Style_Checks flag.
530
531 Scn.Scanner.Reset_Special_Characters;
532 Scn.Scanner.Set_End_Of_Line_As_Token (False);
533 Opt.Style_Check := Save_Style_Check;
534
535 -- If there were errors during preprocessing, record an error
536 -- at the start of the file, and do not change the source
537 -- buffer.
538
539 if T /= Total_Errors_Detected then
540 Errout.Error_Msg
541 ("file could not be successfully preprocessed", Lo);
542 return No_Source_File;
543
544 else
545 -- Output the result of the preprocessing, if requested and
546 -- the source has been modified by the preprocessing.
547
548 if Generate_Processed_File and then Modified then
549 declare
550 FD : File_Descriptor;
551 NB : Integer;
552 Status : Boolean;
553
554 begin
555 Get_Name_String (N);
556
557 if Hostparm.OpenVMS then
558 Add_Str_To_Name_Buffer ("_prep");
559 else
560 Add_Str_To_Name_Buffer (".prep");
561 end if;
562
563 Delete_File (Name_Buffer (1 .. Name_Len), Status);
564
565 FD :=
566 Create_New_File (Name_Buffer (1 .. Name_Len), Text);
567
568 Status := FD /= Invalid_FD;
569
570 if Status then
571 NB :=
572 Write
573 (FD,
574 Prep_Buffer (1)'Address,
575 Integer (Prep_Buffer_Last));
576 Status := NB = Integer (Prep_Buffer_Last);
577 end if;
578
579 if Status then
580 Close (FD, Status);
581 end if;
582
583 if not Status then
584 Errout.Error_Msg
585 ("could not write processed file """ &
586 Name_Buffer (1 .. Name_Len) & '"',
587 Lo);
588 return No_Source_File;
589 end if;
590 end;
591 end if;
592
593 -- Set the new value of Hi
594
595 Hi := Lo + Source_Ptr (Prep_Buffer_Last);
596
597 -- Create the new source buffer
598
599 declare
600 subtype Actual_Source_Buffer is Source_Buffer (Lo .. Hi);
601 -- Physical buffer allocated
602
603 type Actual_Source_Ptr is access Actual_Source_Buffer;
604 -- Pointer type for the physical buffer allocated
605
606 Actual_Ptr : constant Actual_Source_Ptr :=
607 new Actual_Source_Buffer;
608 -- Actual physical buffer
609
610 begin
611 Actual_Ptr (Lo .. Hi - 1) :=
612 Prep_Buffer (1 .. Prep_Buffer_Last);
613 Actual_Ptr (Hi) := EOF;
614
615 -- Now we need to work out the proper virtual origin
616 -- pointer to return. This is Actual_Ptr (0)'Address, but
617 -- we have to be careful to suppress checks to compute
618 -- this address.
619
620 declare
621 pragma Suppress (All_Checks);
622
623 pragma Warnings (Off);
624 -- This unchecked conversion is aliasing safe, since
625 -- it is never used to create improperly aliased
626 -- pointer values.
627
628 function To_Source_Buffer_Ptr is new
629 Unchecked_Conversion (Address, Source_Buffer_Ptr);
630
631 pragma Warnings (On);
632
633 begin
634 Src := To_Source_Buffer_Ptr (Actual_Ptr (0)'Address);
635
636 -- Record in the table the new source buffer and the
637 -- new value of Hi.
638
639 Source_File.Table (X).Source_Text := Src;
640 Source_File.Table (X).Source_Last := Hi;
641
642 -- Reset Last_Line to 1, because the lines do not
643 -- have necessarily the same starts and lengths.
644
645 Source_File.Table (X).Last_Source_Line := 1;
646 end;
647 end;
648 end if;
649 end;
650 end if;
651
652 Set_Source_File_Index_Table (X);
653 return X;
654 end if;
655 end Load_File;
656
657 ----------------------------------
658 -- Load_Preprocessing_Data_File --
659 ----------------------------------
660
661 function Load_Preprocessing_Data_File
662 (N : File_Name_Type) return Source_File_Index
663 is
664 begin
665 return Load_File (N, Osint.Preprocessing_Data);
666 end Load_Preprocessing_Data_File;
667
668 ----------------------
669 -- Load_Source_File --
670 ----------------------
671
672 function Load_Source_File
673 (N : File_Name_Type) return Source_File_Index
674 is
675 begin
676 return Load_File (N, Osint.Source);
677 end Load_Source_File;
678
679 ----------------------------
680 -- New_EOL_In_Prep_Buffer --
681 ----------------------------
682
683 procedure New_EOL_In_Prep_Buffer is
684 begin
685 Put_Char_In_Prep_Buffer (ASCII.LF);
686 end New_EOL_In_Prep_Buffer;
687
688 -----------------------------
689 -- Put_Char_In_Prep_Buffer --
690 -----------------------------
691
692 procedure Put_Char_In_Prep_Buffer (C : Character) is
693 begin
694 -- If preprocessing buffer is not large enough, double it
695
696 if Prep_Buffer_Last = Prep_Buffer'Last then
697 declare
698 New_Prep_Buffer : constant Text_Buffer_Ptr :=
699 new Text_Buffer (1 .. 2 * Prep_Buffer_Last);
700
701 begin
702 New_Prep_Buffer (Prep_Buffer'Range) := Prep_Buffer.all;
703 Free (Prep_Buffer);
704 Prep_Buffer := New_Prep_Buffer;
705 end;
706 end if;
707
708 Prep_Buffer_Last := Prep_Buffer_Last + 1;
709 Prep_Buffer (Prep_Buffer_Last) := C;
710 end Put_Char_In_Prep_Buffer;
711
712 -----------------------------------
713 -- Source_File_Is_Pragma_No_Body --
714 -----------------------------------
715
716 function Source_File_Is_No_Body (X : Source_File_Index) return Boolean is
717 begin
718 Initialize_Scanner (No_Unit, X);
719
720 if Token /= Tok_Pragma then
721 return False;
722 end if;
723
724 Scan; -- past pragma
725
726 if Token /= Tok_Identifier
727 or else Chars (Token_Node) /= Name_No_Body
728 then
729 return False;
730 end if;
731
732 Scan; -- past No_Body
733
734 if Token /= Tok_Semicolon then
735 return False;
736 end if;
737
738 Scan; -- past semicolon
739
740 return Token = Tok_EOF;
741 end Source_File_Is_No_Body;
742
743 ----------------------------
744 -- Source_File_Is_Subunit --
745 ----------------------------
746
747 function Source_File_Is_Subunit (X : Source_File_Index) return Boolean is
748 begin
749 Initialize_Scanner (No_Unit, X);
750
751 -- We scan past junk to the first interesting compilation unit token, to
752 -- see if it is SEPARATE. We ignore WITH keywords during this and also
753 -- PRIVATE. The reason for ignoring PRIVATE is that it handles some
754 -- error situations, and also to handle PRIVATE WITH in Ada 2005 mode.
755
756 while Token = Tok_With
757 or else Token = Tok_Private
758 or else (Token not in Token_Class_Cunit and then Token /= Tok_EOF)
759 loop
760 Scan;
761 end loop;
762
763 return Token = Tok_Separate;
764 end Source_File_Is_Subunit;
765
766 end Sinput.L;