1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 2008-2018, 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 ------------------------------------------------------------------------------
26 with Atree
; use Atree
;
27 with Csets
; use Csets
;
28 with Einfo
; use Einfo
;
29 with Namet
; use Namet
;
30 with Nlists
; use Nlists
;
32 with Sinfo
; use Sinfo
;
33 with Sinput
; use Sinput
;
34 with Snames
; use Snames
;
35 with Uintp
; use Uintp
;
37 package body Pprint
is
39 List_Name_Count
: Integer := 0;
40 -- Counter used to prevent infinite recursion while computing name of
41 -- complex expressions.
43 ----------------------
44 -- Expression_Image --
45 ----------------------
47 function Expression_Image
49 Default
: String) return String
51 From_Source
: constant Boolean :=
52 Comes_From_Source
(Expr
)
53 and then not Opt
.Debug_Generated_Code
;
54 Append_Paren
: Natural := 0;
55 Left
: Node_Id
:= Original_Node
(Expr
);
56 Right
: Node_Id
:= Original_Node
(Expr
);
60 Take_Prefix
: Boolean := True;
61 Expand_Type
: Boolean := True) return String;
62 -- Return string corresponding to Expr. If no string can be extracted,
63 -- return "...". If Take_Prefix is True, go back to prefix when needed,
64 -- otherwise only consider the right-hand side of an expression. If
65 -- Expand_Type is True and Expr is a type, try to expand Expr (an
66 -- internally generated type) into a user understandable name.
68 Max_List
: constant := 3;
69 -- Limit number of list elements to dump
71 Max_Expr_Elements
: constant := 24;
72 -- Limit number of elements in an expression for use by Expr_Name
74 Num_Elements
: Natural := 0;
75 -- Current number of elements processed by Expr_Name
79 Add_Space
: Boolean := True;
80 Add_Paren
: Boolean := True) return String;
81 -- Return a string corresponding to List
89 Add_Space
: Boolean := True;
90 Add_Paren
: Boolean := True) return String
92 function Internal_List_Name
94 First
: Boolean := True;
95 Add_Space
: Boolean := True;
96 Add_Paren
: Boolean := True;
97 Num
: Natural := 1) return String;
98 -- ??? what does this do
100 ------------------------
101 -- Internal_List_Name --
102 ------------------------
104 function Internal_List_Name
106 First
: Boolean := True;
107 Add_Space
: Boolean := True;
108 Add_Paren
: Boolean := True;
109 Num
: Natural := 1) return String
111 function Prepend
(S
: String) return String;
112 -- ??? what does this do
118 function Prepend
(S
: String) return String is
133 -- Start of processing for Internal_List_Name
136 if not Present
(List
) then
137 if First
or else not Add_Paren
then
142 elsif Num
> Max_List
then
150 -- ??? the Internal_List_Name calls can be factored out
153 return Prepend
(Expr_Name
(List
)
155 (List
=> Next
(List
),
157 Add_Paren
=> Add_Paren
,
160 return ", " & Expr_Name
(List
)
162 (List
=> Next
(List
),
164 Add_Paren
=> Add_Paren
,
167 end Internal_List_Name
;
169 -- Start of processing for List_Name
172 -- Prevent infinite recursion by limiting depth to 3
174 if List_Name_Count
> 3 then
178 List_Name_Count
:= List_Name_Count
+ 1;
181 Result
: constant String :=
184 Add_Space
=> Add_Space
,
185 Add_Paren
=> Add_Paren
);
187 List_Name_Count
:= List_Name_Count
- 1;
198 Take_Prefix
: Boolean := True;
199 Expand_Type
: Boolean := True) return String
202 Num_Elements
:= Num_Elements
+ 1;
204 if Num_Elements
> Max_Expr_Elements
then
209 when N_Defining_Identifier
212 return Ident_Image
(Expr
, Expression_Image
.Expr
, Expand_Type
);
214 when N_Character_Literal
=>
216 Char
: constant Int
:= UI_To_Int
(Char_Literal_Value
(Expr
));
218 if Char
in 32 .. 127 then
219 return "'" & Character'Val (Char
) & "'";
221 UI_Image
(Char_Literal_Value
(Expr
));
223 "'\" & UI_Image_Buffer (1 .. UI_Image_Length) & "'";
227 when N_Integer_Literal =>
228 UI_Image (Intval (Expr));
229 return UI_Image_Buffer (1 .. UI_Image_Length);
231 when N_Real_Literal =>
232 return Real_Image (Realval (Expr));
234 when N_String_Literal =>
235 return String_Image (Strval (Expr));
238 return "new " & Expr_Name (Expression (Expr));
241 if Present (Sinfo.Expressions (Expr)) then
244 (List => First (Sinfo.Expressions (Expr)),
247 -- Do not return empty string for (others => <>) aggregate
248 -- of a componentless record type. At least one caller (the
249 -- recursive call below in the N_Qualified_Expression case)
250 -- is not prepared to deal with a zero-length result.
252 elsif Null_Record_Present (Expr)
253 or else not Present (First (Component_Associations (Expr)))
255 return ("(null record)");
260 (List => First (Component_Associations (Expr)),
265 when N_Extension_Aggregate =>
266 return "(" & Expr_Name (Ancestor_Part (Expr)) & " with "
268 (List => First (Sinfo.Expressions (Expr)),
270 Add_Paren => False) & ")";
272 when N_Attribute_Reference =>
275 function To_Mixed_Case (S : String) return String;
276 -- Transform given string into the corresponding one in
283 function To_Mixed_Case (S : String) return String is
284 Result : String (S'Range);
285 Ucase : Boolean := True;
288 for J in S'Range loop
290 Result (J) := Fold_Upper (S (J));
292 Result (J) := Fold_Lower (S (J));
295 Ucase := (S (J) = '_
');
301 Id : constant Attribute_Id :=
302 Get_Attribute_Id (Attribute_Name (Expr));
304 -- Always use mixed case for attributes
306 Str : constant String :=
307 Expr_Name (Prefix (Expr))
310 (Get_Name_String (Attribute_Name (Expr)));
316 if (Id = Attribute_First or else Id = Attribute_Last)
317 and then Str (Str'First) = '$'
319 N := Associated_Node_For_Itype (Etype (Prefix (Expr)));
322 if Nkind (N) = N_Full_Type_Declaration then
323 N := Type_Definition (N);
326 if Nkind (N) = N_Subtype_Declaration then
329 (Constraint (Subtype_Indication (N)));
331 if List_Length (Ranges) = 1
336 N_Real_Range_Specification,
337 N_Signed_Integer_Type_Definition)
339 if Id = Attribute_First then
342 (Low_Bound (First (Ranges)), Str);
346 (High_Bound (First (Ranges)), Str);
356 return "'" & Get_Name_String (Attribute_Name (Expr));
359 when N_Explicit_Dereference =>
360 Explicit_Dereference : declare
361 function Deref_Suffix return String;
362 -- Usually returns ".all", but will return "" if
363 -- Hide_Temp_Derefs is true and the prefix is a use of a
364 -- not-from-source object declared as
365 -- X : constant Some_Access_Type := Some_Expr'Reference;
366 -- (as is sometimes done in Exp_Util.Remove_Side_Effects).
372 function Deref_Suffix return String is
377 and then Nkind (Prefix (Expr)) = N_Identifier
378 and then Nkind (Entity (Prefix (Expr))) =
379 N_Defining_Identifier
381 Decl := Parent (Entity (Prefix (Expr)));
384 and then Nkind (Decl) = N_Object_Declaration
385 and then not Comes_From_Source (Decl)
386 and then Constant_Present (Decl)
387 and then Present (Sinfo.Expression (Decl))
388 and then Nkind (Sinfo.Expression (Decl)) =
400 -- Start of processing for Explicit_Dereference
403 if Hide_Parameter_Blocks
404 and then Nkind (Prefix (Expr)) = N_Selected_Component
405 and then Present (Etype (Prefix (Expr)))
406 and then Is_Access_Type (Etype (Prefix (Expr)))
407 and then Is_Param_Block_Component_Type
408 (Etype (Prefix (Expr)))
410 -- Return "Foo" instead of "Parameter_Block.Foo.all"
412 return Expr_Name (Selector_Name (Prefix (Expr)));
414 elsif Take_Prefix then
415 return Expr_Name (Prefix (Expr)) & Deref_Suffix;
419 end Explicit_Dereference;
422 | N_Selected_Component
426 Expr_Name (Prefix (Expr)) & "." &
427 Expr_Name (Selector_Name (Expr));
429 return "." & Expr_Name (Selector_Name (Expr));
432 when N_Component_Association =>
435 (List => First (Choices (Expr)),
438 & " => " & Expr_Name (Expression (Expr)) & ")";
440 when N_If_Expression =>
442 N : constant Node_Id := First (Sinfo.Expressions (Expr));
445 "if " & Expr_Name (N) & " then "
446 & Expr_Name (Next (N)) & " else "
447 & Expr_Name (Next (Next (N)));
450 when N_Qualified_Expression =>
452 Mark : constant String :=
454 (Subtype_Mark (Expr), Expand_Type => False);
455 Str : constant String := Expr_Name (Expression (Expr));
457 if Str (Str'First) = '(' and then Str (Str'Last) = ')' then
458 return Mark & "'" & Str;
460 return Mark & "'(" & Str & ")";
464 when N_Expression_With_Actions
465 | N_Unchecked_Expression
467 return Expr_Name (Expression (Expr));
469 when N_Raise_Constraint_Error =>
470 if Present (Condition (Expr)) then
472 "[constraint_error when "
473 & Expr_Name (Condition (Expr)) & "]";
475 return "[constraint_error]";
478 when N_Raise_Program_Error =>
479 if Present (Condition (Expr)) then
481 "[program_error when "
482 & Expr_Name (Condition (Expr)) & "]";
484 return "[program_error]";
489 Expr_Name (Low_Bound (Expr)) & ".." &
490 Expr_Name (High_Bound (Expr));
494 Expr_Name (Prefix (Expr)) & " (" &
495 Expr_Name (Discrete_Range (Expr)) & ")";
499 Expr_Name (Left_Opnd (Expr)) & " and then " &
500 Expr_Name (Right_Opnd (Expr));
504 Expr_Name (Left_Opnd (Expr)) & " in " &
505 Expr_Name (Right_Opnd (Expr));
509 Expr_Name (Left_Opnd (Expr)) & " not in " &
510 Expr_Name (Right_Opnd (Expr));
514 Expr_Name (Left_Opnd (Expr)) & " or else " &
515 Expr_Name (Right_Opnd (Expr));
519 Expr_Name (Left_Opnd (Expr)) & " and " &
520 Expr_Name (Right_Opnd (Expr));
524 Expr_Name (Left_Opnd (Expr)) & " or " &
525 Expr_Name (Right_Opnd (Expr));
529 Expr_Name (Left_Opnd (Expr)) & " xor " &
530 Expr_Name (Right_Opnd (Expr));
534 Expr_Name (Left_Opnd (Expr)) & " = " &
535 Expr_Name (Right_Opnd (Expr));
539 Expr_Name (Left_Opnd (Expr)) & " /= " &
540 Expr_Name (Right_Opnd (Expr));
544 Expr_Name (Left_Opnd (Expr)) & " < " &
545 Expr_Name (Right_Opnd (Expr));
549 Expr_Name (Left_Opnd (Expr)) & " <= " &
550 Expr_Name (Right_Opnd (Expr));
554 Expr_Name (Left_Opnd (Expr)) & " > " &
555 Expr_Name (Right_Opnd (Expr));
559 Expr_Name (Left_Opnd (Expr)) & " >= " &
560 Expr_Name (Right_Opnd (Expr));
564 Expr_Name (Left_Opnd (Expr)) & " + " &
565 Expr_Name (Right_Opnd (Expr));
567 when N_Op_Subtract =>
569 Expr_Name (Left_Opnd (Expr)) & " - " &
570 Expr_Name (Right_Opnd (Expr));
572 when N_Op_Multiply =>
574 Expr_Name (Left_Opnd (Expr)) & " * " &
575 Expr_Name (Right_Opnd (Expr));
579 Expr_Name (Left_Opnd (Expr)) & " / " &
580 Expr_Name (Right_Opnd (Expr));
584 Expr_Name (Left_Opnd (Expr)) & " mod " &
585 Expr_Name (Right_Opnd (Expr));
589 Expr_Name (Left_Opnd (Expr)) & " rem " &
590 Expr_Name (Right_Opnd (Expr));
594 Expr_Name (Left_Opnd (Expr)) & " ** " &
595 Expr_Name (Right_Opnd (Expr));
597 when N_Op_Shift_Left =>
599 Expr_Name (Left_Opnd (Expr)) & " << " &
600 Expr_Name (Right_Opnd (Expr));
602 when N_Op_Shift_Right | N_Op_Shift_Right_Arithmetic =>
604 Expr_Name (Left_Opnd (Expr)) & " >> " &
605 Expr_Name (Right_Opnd (Expr));
609 Expr_Name (Left_Opnd (Expr)) & " & " &
610 Expr_Name (Right_Opnd (Expr));
613 return "+" & Expr_Name (Right_Opnd (Expr));
616 return "-" & Expr_Name (Right_Opnd (Expr));
619 return "abs " & Expr_Name (Right_Opnd (Expr));
622 return "not (" & Expr_Name (Right_Opnd (Expr)) & ")";
624 when N_Parameter_Association =>
625 return Expr_Name (Explicit_Actual_Parameter (Expr));
627 when N_Type_Conversion =>
629 -- Most conversions are not very interesting (used inside
630 -- expanded checks to convert to larger ranges), so skip them.
632 return Expr_Name (Expression (Expr));
634 when N_Unchecked_Type_Conversion =>
636 -- Only keep the type conversion in complex cases
638 if not Is_Scalar_Type (Etype (Expr))
639 or else not Is_Scalar_Type (Etype (Expression (Expr)))
640 or else Is_Modular_Integer_Type (Etype (Expr)) /=
641 Is_Modular_Integer_Type (Etype (Expression (Expr)))
643 return Expr_Name (Subtype_Mark (Expr)) &
644 "(" & Expr_Name (Expression (Expr)) & ")";
646 return Expr_Name (Expression (Expr));
649 when N_Indexed_Component =>
652 Expr_Name (Prefix (Expr))
653 & List_Name (First (Sinfo.Expressions (Expr)));
655 return List_Name (First (Sinfo.Expressions (Expr)));
658 when N_Function_Call =>
660 -- If Default = "", it means we're expanding the name of
661 -- a gnat temporary (and not really a function call), so add
662 -- parentheses around function call to mark it specially.
666 & Expr_Name (Name (Expr))
667 & List_Name (First (Sinfo.Parameter_Associations (Expr)))
671 Expr_Name (Name (Expr))
673 (First (Sinfo.Parameter_Associations (Expr)));
679 when N_Others_Choice =>
687 -- Start of processing for Expression_Name
690 if not From_Source then
692 S : constant String := Expr_Name (Expr);
702 -- Compute left (start) and right (end) slocs for the expression
703 -- Consider using Sinput.Sloc_Range instead, except that it does not
704 -- work properly currently???
713 Left := Original_Node (Left_Opnd (Left));
715 when N_Attribute_Reference
717 | N_Explicit_Dereference
718 | N_Indexed_Component
720 | N_Selected_Component
723 Left := Original_Node (Prefix (Left));
725 when N_Defining_Program_Unit_Name
729 Left := Original_Node (Name (Left));
732 Left := Original_Node (Low_Bound (Left));
734 when N_Qualified_Expression
737 Left := Original_Node (Subtype_Mark (Left));
739 -- For any other item, quit loop
747 case Nkind (Right) is
753 Right := Original_Node (Right_Opnd (Right));
756 | N_Selected_Component
758 Right := Original_Node (Selector_Name (Right));
760 when N_Qualified_Expression
763 Right := Original_Node (Expression (Right));
765 -- If argument does not already account for a closing
766 -- parenthesis, count one here.
768 if not Nkind_In (Right, N_Aggregate,
769 N_Quantified_Expression)
771 Append_Paren := Append_Paren + 1;
775 Right := Original_Node (Identifier (Right));
777 when N_Defining_Program_Unit_Name =>
778 Right := Original_Node (Defining_Identifier (Right));
781 Right := Original_Node (High_Bound (Right));
783 when N_Parameter_Association =>
784 Right := Original_Node (Explicit_Actual_Parameter (Right));
786 when N_Component_Association =>
787 if Present (Expression (Right)) then
788 Right := Expression (Right);
790 Right := Last (Choices (Right));
793 when N_Indexed_Component =>
794 Right := Original_Node (Last (Sinfo.Expressions (Right)));
795 Append_Paren := Append_Paren + 1;
797 when N_Function_Call =>
798 if Present (Sinfo.Parameter_Associations (Right)) then
804 -- Avoid source position confusion associated with
805 -- parameters for which Comes_From_Source is False.
807 Rover := First (Sinfo.Parameter_Associations (Right));
809 while Present (Rover) loop
810 if Comes_From_Source (Original_Node (Rover)) then
811 Right := Original_Node (Rover);
819 Append_Paren := Append_Paren + 1;
822 -- Quit loop if no Comes_From_Source parameters
827 -- Quit loop if no parameters
833 when N_Quantified_Expression =>
834 Right := Original_Node (Condition (Right));
835 Append_Paren := Append_Paren + 1;
839 Aggr : constant Node_Id := Right;
843 Sub := First (Expressions (Aggr));
844 while Present (Sub) loop
845 if Sloc (Sub) > Sloc (Right) then
852 Sub := First (Component_Associations (Aggr));
853 while Present (Sub) loop
854 if Sloc (Sub) > Sloc (Right) then
861 exit when Right = Aggr;
863 Append_Paren := Append_Paren + 1;
866 -- For all other items, quit the loop
874 Scn : Source_Ptr := Original_Location (Sloc (Left));
875 End_Sloc : constant Source_Ptr :=
876 Original_Location (Sloc (Right));
877 Src : constant Source_Buffer_Ptr :=
878 Source_Text (Get_Source_File_Index (Scn));
881 if Scn > End_Sloc then
886 Threshold : constant := 256;
887 Buffer : String (1 .. Natural (End_Sloc - Scn));
888 Index : Natural := 0;
889 Skipping_Comment : Boolean := False;
890 Underscore : Boolean := False;
893 if Right /= Expr then
894 while Scn < End_Sloc loop
897 -- Give up on non ASCII characters
899 when Character'Val (128) .. Character'Last =>
908 if not Skipping_Comment and then not Underscore then
911 Buffer (Index) := ' ';
914 -- CR/LF/FF is the end of any comment
920 Skipping_Comment := False;
925 if not Skipping_Comment then
929 if Src (Scn) = '-' and then Src (Scn + 1) = '-' then
930 Skipping_Comment := True;
934 Buffer (Index) := Src (Scn);
939 -- Give up on too long strings
941 if Index >= Threshold then
942 return Buffer (1 .. Index) & "...";
951 S : constant String := Expr_Name (Right);
963 & Expr_Name (Right, False)
964 & (1 .. Append_Paren => ')');
968 end Expression_Image;