1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 1992-2009, Free Software Foundation, Inc. --
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. --
21 -- GNAT was originally developed by the GNAT team at New York University. --
22 -- Extensive contributions were provided by Ada Core Technologies Inc. --
24 ------------------------------------------------------------------------------
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
;
34 with Osint
; use Osint
;
35 with Output
; use Output
;
37 with Prepcomp
; use Prepcomp
;
38 with Scans
; use Scans
;
40 with Sinfo
; use Sinfo
;
41 with Snames
; use Snames
;
42 with System
; use System
;
44 with System
.OS_Lib
; use System
.OS_Lib
;
46 with Unchecked_Conversion
;
48 package body Sinput
.L
is
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.
54 Prep_Buffer_Last
: Text_Ptr
:= 0;
55 -- Index of the last significant character in Prep_Buffer
57 Initial_Size_Of_Prep_Buffer
: constant := 10_000
;
58 -- Size of Prep_Buffer when it is first allocated
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
66 Foreword_Start
: constant String :=
67 "Preprocessing Symbols for source """;
69 Foreword_End
: constant String := """";
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.
79 procedure New_EOL_In_Prep_Buffer
;
80 -- Add an LF to Prep_Buffer (used to initialize the preprocessor)
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 ???
88 -------------------------------
89 -- Adjust_Instantiation_Sloc --
90 -------------------------------
92 procedure Adjust_Instantiation_Sloc
(N
: Node_Id
; A
: Sloc_Adjustment
) is
93 Loc
: constant Source_Ptr
:= Sloc
(N
);
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.
101 if A
.Lo
<= Loc
and then Loc
<= A
.Hi
then
102 Set_Sloc
(N
, Loc
+ A
.Adjust
);
104 end Adjust_Instantiation_Sloc
;
106 --------------------------------
107 -- Complete_Source_File_Entry --
108 --------------------------------
110 procedure Complete_Source_File_Entry
is
111 CSF
: constant Source_File_Index
:= Current_Source_File
;
114 Trim_Lines_Table
(CSF
);
115 Source_File
.Table
(CSF
).Source_Checksum
:= Checksum
;
116 end Complete_Source_File_Entry
;
118 ---------------------------------
119 -- Create_Instantiation_Source --
120 ---------------------------------
122 procedure Create_Instantiation_Source
123 (Inst_Node
: Entity_Id
;
124 Template_Id
: Entity_Id
;
125 Inlined_Body
: Boolean;
126 A
: out Sloc_Adjustment
)
128 Dnod
: constant Node_Id
:= Declaration_Node
(Template_Id
);
129 Xold
: Source_File_Index
;
130 Xnew
: Source_File_Index
;
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
;
137 Source_File
.Append
(Source_File
.Table
(Xold
));
138 Xnew
:= Source_File
.Last
;
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
;
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.
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
;
153 Set_Source_File_Index_Table
(Xnew
);
155 Source_File
.Table
(Xnew
).Sloc_Adjust
:=
156 Source_File
.Table
(Xold
).Sloc_Adjust
- A
.Adjust
;
160 Write_Str
("*** Create instantiation source for ");
162 if Nkind
(Dnod
) in N_Proper_Body
163 and then Was_Originally_Stub
(Dnod
)
165 Write_Str
("subunit ");
167 elsif Ekind
(Template_Id
) = E_Generic_Package
then
168 if Nkind
(Dnod
) = N_Package_Body
then
169 Write_Str
("body of package ");
171 Write_Str
("spec of package ");
174 elsif Ekind
(Template_Id
) = E_Function
then
175 Write_Str
("body of function ");
177 elsif Ekind
(Template_Id
) = E_Procedure
then
178 Write_Str
("body of procedure ");
180 elsif Ekind
(Template_Id
) = E_Generic_Function
then
181 Write_Str
("spec of function ");
183 elsif Ekind
(Template_Id
) = E_Generic_Procedure
then
184 Write_Str
("spec of procedure ");
186 elsif Ekind
(Template_Id
) = E_Package_Body
then
187 Write_Str
("body of package ");
189 else pragma Assert
(Ekind
(Template_Id
) = E_Subprogram_Body
);
191 if Nkind
(Dnod
) = N_Procedure_Specification
then
192 Write_Str
("body of procedure ");
194 Write_Str
("body of function ");
198 Write_Name
(Chars
(Template_Id
));
201 Write_Str
(" new source index = ");
202 Write_Int
(Int
(Xnew
));
205 Write_Str
(" copying from file name = ");
206 Write_Name
(File_Name
(Xold
));
209 Write_Str
(" old source index = ");
210 Write_Int
(Int
(Xold
));
213 Write_Str
(" old lo = ");
214 Write_Int
(Int
(A
.Lo
));
217 Write_Str
(" old hi = ");
218 Write_Int
(Int
(A
.Hi
));
221 Write_Str
(" new lo = ");
222 Write_Int
(Int
(Source_File
.Table
(Xnew
).Source_First
));
225 Write_Str
(" new hi = ");
226 Write_Int
(Int
(Source_File
.Table
(Xnew
).Source_Last
));
229 Write_Str
(" adjustment factor = ");
230 Write_Int
(Int
(A
.Adjust
));
233 Write_Str
(" instantiation location: ");
234 Write_Location
(Sloc
(Inst_Node
));
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.
246 pragma Suppress
(All_Checks
);
248 pragma Warnings
(Off
);
249 -- This unchecked conversion is aliasing safe, since it is never used
250 -- to create improperly aliased pointer values.
252 function To_Source_Buffer_Ptr
is new
253 Unchecked_Conversion
(Address
, Source_Buffer_Ptr
);
255 pragma Warnings
(On
);
258 Source_File
.Table
(Xnew
).Source_Text
:=
260 (Source_File
.Table
(Xold
).Source_Text
(-A
.Adjust
)'Address);
262 end Create_Instantiation_Source
;
264 ----------------------
265 -- Load_Config_File --
266 ----------------------
268 function Load_Config_File
269 (N
: File_Name_Type
) return Source_File_Index
272 return Load_File
(N
, Osint
.Config
);
273 end Load_Config_File
;
275 --------------------------
276 -- Load_Definition_File --
277 --------------------------
279 function Load_Definition_File
280 (N
: File_Name_Type
) return Source_File_Index
283 return Load_File
(N
, Osint
.Definition
);
284 end Load_Definition_File
;
292 T
: Osint
.File_Type
) return Source_File_Index
294 Src
: Source_Buffer_Ptr
;
295 X
: Source_File_Index
;
299 Preprocessing_Needed
: Boolean := False;
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.
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
318 -- Here we must build a new entry in the file table
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.
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
);
331 Source_File
.Increment_Last
;
332 X
:= Source_File
.Last
;
334 if X
= Source_File
.First
then
335 Lo
:= First_Source_Ptr
;
337 Lo
:= Source_File
.Table
(X
- 1).Source_Last
+ 1;
340 Osint
.Read_Source_File
(N
, Lo
, Hi
, Src
, T
);
343 Source_File
.Decrement_Last
;
344 return No_Source_File
;
349 Write_Str
("*** Build source file table entry, Index = ");
351 Write_Str
(", file name = ");
354 Write_Str
(" lo = ");
355 Write_Int
(Int
(Lo
));
357 Write_Str
(" hi = ");
358 Write_Int
(Int
(Hi
));
361 Write_Str
(" first 10 chars -->");
364 procedure Wchar
(C
: Character);
365 -- Writes character or ? for control character
371 procedure Wchar
(C
: Character) is
374 or else C
in ASCII
.DEL
.. Character'Val (16#
9F#
)
383 for J
in Lo
.. Lo
+ 9 loop
390 Write_Str
(" last 10 chars -->");
392 for J
in Hi
- 10 .. Hi
- 1 loop
399 if Src
(Hi
) /= EOF
then
400 Write_Str
(" error: no EOF at end");
407 S
: Source_File_Record
renames Source_File
.Table
(X
);
408 File_Type
: Type_Of_File
;
413 File_Type
:= Sinput
.Src
;
415 when Osint
.Library
=>
419 File_Type
:= Sinput
.Config
;
421 when Osint
.Definition
=>
424 when Osint
.Preprocessing_Data
=>
425 File_Type
:= Preproc
;
428 S
:= (Debug_Source_Name
=> N
,
430 File_Type
=> File_Type
,
431 First_Mapped_Line
=> No_Line_Number
,
432 Full_Debug_Name
=> Osint
.Full_Source_Name
,
433 Full_File_Name
=> Osint
.Full_Source_Name
,
434 Full_Ref_Name
=> Osint
.Full_Source_Name
,
435 Identifier_Casing
=> Unknown
,
436 Inlined_Body
=> False,
437 Instantiation
=> No_Location
,
438 Keyword_Casing
=> Unknown
,
439 Last_Source_Line
=> 1,
442 Lines_Table_Max
=> 1,
443 Logical_Lines_Table
=> null,
444 Num_SRef_Pragmas
=> 0,
447 Source_Checksum
=> 0,
451 Template
=> No_Source_File
,
453 Time_Stamp
=> Osint
.Current_Source_File_Stamp
);
455 Alloc_Line_Tables
(S
, Opt
.Table_Factor
* Alloc
.Lines_Initial
);
456 S
.Lines_Table
(1) := Lo
;
459 -- Preprocess the source if it needs to be preprocessed
461 if Preprocessing_Needed
then
463 -- Temporarily set the Source_File_Index_Table entries for the
464 -- source, to avoid crash when reporting an error.
466 Set_Source_File_Index_Table
(X
);
468 if Opt
.List_Preprocessing_Symbols
then
472 Foreword
: String (1 .. Foreword_Start
'Length +
473 Name_Len
+ Foreword_End
'Length);
476 Foreword
(1 .. Foreword_Start
'Length) := Foreword_Start
;
477 Foreword
(Foreword_Start
'Length + 1 ..
478 Foreword_Start
'Length + Name_Len
) :=
479 Name_Buffer
(1 .. Name_Len
);
480 Foreword
(Foreword
'Last - Foreword_End
'Length + 1 ..
481 Foreword
'Last) := Foreword_End
;
482 Prep
.List_Symbols
(Foreword
);
487 T
: constant Nat
:= Total_Errors_Detected
;
488 -- Used to check if there were errors during preprocessing
490 Save_Style_Check
: Boolean;
491 -- Saved state of the Style_Check flag (which needs to be
492 -- temporarily set to False during preprocessing, see below).
497 -- If this is the first time we preprocess a source, allocate
498 -- the preprocessing buffer.
500 if Prep_Buffer
= null then
502 new Text_Buffer
(1 .. Initial_Size_Of_Prep_Buffer
);
505 -- Make sure the preprocessing buffer is empty
507 Prep_Buffer_Last
:= 0;
509 -- Initialize the preprocessor hooks
512 (Error_Msg
=> Errout
.Error_Msg
'Access,
513 Scan
=> Scn
.Scanner
.Scan
'Access,
514 Set_Ignore_Errors
=> Errout
.Set_Ignore_Errors
'Access,
515 Put_Char
=> Put_Char_In_Prep_Buffer
'Access,
516 New_EOL
=> New_EOL_In_Prep_Buffer
'Access);
518 -- Initialize scanner and set its behavior for preprocessing,
519 -- then preprocess. Also disable style checks, since some of
520 -- them are done in the scanner (specifically, those dealing
521 -- with line length and line termination), and cannot be done
522 -- during preprocessing (because the source file index table
523 -- has not been set yet).
525 Scn
.Scanner
.Initialize_Scanner
(X
);
527 Scn
.Scanner
.Set_Special_Character
('#');
528 Scn
.Scanner
.Set_Special_Character
('$');
529 Scn
.Scanner
.Set_End_Of_Line_As_Token
(True);
530 Save_Style_Check
:= Opt
.Style_Check
;
531 Opt
.Style_Check
:= False;
533 -- Make sure that there will be no check of pragma Restrictions
534 -- for obsolescent features while preprocessing the source.
536 Scn
.Set_Obsolescent_Check
(False);
537 Preprocess
(Modified
);
538 Scn
.Set_Obsolescent_Check
(True);
540 -- Reset the scanner to its standard behavior, and restore the
541 -- Style_Checks flag.
543 Scn
.Scanner
.Reset_Special_Characters
;
544 Scn
.Scanner
.Set_End_Of_Line_As_Token
(False);
545 Opt
.Style_Check
:= Save_Style_Check
;
547 -- If there were errors during preprocessing, record an error
548 -- at the start of the file, and do not change the source
551 if T
/= Total_Errors_Detected
then
553 ("file could not be successfully preprocessed", Lo
);
554 return No_Source_File
;
557 -- Output the result of the preprocessing, if requested and
558 -- the source has been modified by the preprocessing.
560 if Generate_Processed_File
and then Modified
then
562 FD
: File_Descriptor
;
569 if Hostparm
.OpenVMS
then
570 Add_Str_To_Name_Buffer
("_prep");
572 Add_Str_To_Name_Buffer
(".prep");
575 Delete_File
(Name_Buffer
(1 .. Name_Len
), Status
);
578 Create_New_File
(Name_Buffer
(1 .. Name_Len
), Text
);
580 Status
:= FD
/= Invalid_FD
;
586 Prep_Buffer
(1)'Address,
587 Integer (Prep_Buffer_Last
));
588 Status
:= NB
= Integer (Prep_Buffer_Last
);
597 ("could not write processed file """ &
598 Name_Buffer
(1 .. Name_Len
) & '"',
600 return No_Source_File
;
605 -- Set the new value of Hi
607 Hi
:= Lo
+ Source_Ptr
(Prep_Buffer_Last
);
609 -- Create the new source buffer
612 subtype Actual_Source_Buffer
is Source_Buffer
(Lo
.. Hi
);
613 -- Physical buffer allocated
615 type Actual_Source_Ptr
is access Actual_Source_Buffer
;
616 -- Pointer type for the physical buffer allocated
618 Actual_Ptr
: constant Actual_Source_Ptr
:=
619 new Actual_Source_Buffer
;
620 -- Actual physical buffer
623 Actual_Ptr
(Lo
.. Hi
- 1) :=
624 Prep_Buffer
(1 .. Prep_Buffer_Last
);
625 Actual_Ptr
(Hi
) := EOF
;
627 -- Now we need to work out the proper virtual origin
628 -- pointer to return. This is Actual_Ptr (0)'Address, but
629 -- we have to be careful to suppress checks to compute
633 pragma Suppress
(All_Checks
);
635 pragma Warnings
(Off
);
636 -- This unchecked conversion is aliasing safe, since
637 -- it is never used to create improperly aliased
640 function To_Source_Buffer_Ptr
is new
641 Unchecked_Conversion
(Address
, Source_Buffer_Ptr
);
643 pragma Warnings
(On
);
646 Src
:= To_Source_Buffer_Ptr
(Actual_Ptr
(0)'Address);
648 -- Record in the table the new source buffer and the
651 Source_File
.Table
(X
).Source_Text
:= Src
;
652 Source_File
.Table
(X
).Source_Last
:= Hi
;
654 -- Reset Last_Line to 1, because the lines do not
655 -- have necessarily the same starts and lengths.
657 Source_File
.Table
(X
).Last_Source_Line
:= 1;
664 Set_Source_File_Index_Table
(X
);
669 ----------------------------------
670 -- Load_Preprocessing_Data_File --
671 ----------------------------------
673 function Load_Preprocessing_Data_File
674 (N
: File_Name_Type
) return Source_File_Index
677 return Load_File
(N
, Osint
.Preprocessing_Data
);
678 end Load_Preprocessing_Data_File
;
680 ----------------------
681 -- Load_Source_File --
682 ----------------------
684 function Load_Source_File
685 (N
: File_Name_Type
) return Source_File_Index
688 return Load_File
(N
, Osint
.Source
);
689 end Load_Source_File
;
691 ----------------------------
692 -- New_EOL_In_Prep_Buffer --
693 ----------------------------
695 procedure New_EOL_In_Prep_Buffer
is
697 Put_Char_In_Prep_Buffer
(ASCII
.LF
);
698 end New_EOL_In_Prep_Buffer
;
700 -----------------------------
701 -- Put_Char_In_Prep_Buffer --
702 -----------------------------
704 procedure Put_Char_In_Prep_Buffer
(C
: Character) is
706 -- If preprocessing buffer is not large enough, double it
708 if Prep_Buffer_Last
= Prep_Buffer
'Last then
710 New_Prep_Buffer
: constant Text_Buffer_Ptr
:=
711 new Text_Buffer
(1 .. 2 * Prep_Buffer_Last
);
714 New_Prep_Buffer
(Prep_Buffer
'Range) := Prep_Buffer
.all;
716 Prep_Buffer
:= New_Prep_Buffer
;
720 Prep_Buffer_Last
:= Prep_Buffer_Last
+ 1;
721 Prep_Buffer
(Prep_Buffer_Last
) := C
;
722 end Put_Char_In_Prep_Buffer
;
724 -----------------------------------
725 -- Source_File_Is_Pragma_No_Body --
726 -----------------------------------
728 function Source_File_Is_No_Body
(X
: Source_File_Index
) return Boolean is
730 Initialize_Scanner
(No_Unit
, X
);
732 if Token
/= Tok_Pragma
then
738 if Token
/= Tok_Identifier
739 or else Chars
(Token_Node
) /= Name_No_Body
744 Scan
; -- past No_Body
746 if Token
/= Tok_Semicolon
then
750 Scan
; -- past semicolon
752 return Token
= Tok_EOF
;
753 end Source_File_Is_No_Body
;
755 ----------------------------
756 -- Source_File_Is_Subunit --
757 ----------------------------
759 function Source_File_Is_Subunit
(X
: Source_File_Index
) return Boolean is
761 Initialize_Scanner
(No_Unit
, X
);
763 -- We scan past junk to the first interesting compilation unit token, to
764 -- see if it is SEPARATE. We ignore WITH keywords during this and also
765 -- PRIVATE. The reason for ignoring PRIVATE is that it handles some
766 -- error situations, and also to handle PRIVATE WITH in Ada 2005 mode.
768 while Token
= Tok_With
769 or else Token
= Tok_Private
770 or else (Token
not in Token_Class_Cunit
and then Token
/= Tok_EOF
)
775 return Token
= Tok_Separate
;
776 end Source_File_Is_Subunit
;