1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 2008-2012, 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 Einfo
; use Einfo
;
28 with Namet
; use Namet
;
29 with Nlists
; use Nlists
;
31 with Sinfo
; use Sinfo
;
32 with Sinput
; use Sinput
;
33 with Snames
; use Snames
;
34 with Uintp
; use Uintp
;
36 package body Pprint
is
38 List_Name_Count
: Integer := 0;
39 -- Counter used to prevent infinite recursion while computing name of
40 -- complex expressions.
42 ----------------------
43 -- Expression_Image --
44 ----------------------
46 function Expression_Image
(Expr
: Node_Id
; Default
: String)
48 Left
: Node_Id
:= Original_Node
(Expr
);
49 Right
: Node_Id
:= Original_Node
(Expr
);
50 From_Source
: constant Boolean :=
51 Comes_From_Source
(Expr
) and then not Opt
.Debug_Generated_Code
;
52 Append_Paren
: Boolean := False;
56 Take_Prefix
: Boolean := True;
57 Expand_Type
: Boolean := True) return String;
58 -- Return string corresponding to Expr. If no string can be extracted,
59 -- return "...". If Take_Prefix is True, go back to prefix when needed,
60 -- otherwise only consider the right-hand side of an expression. If
61 -- Expand_Type is True and Expr is a type, try to expand Expr (an
62 -- internally generated type) into a user understandable name.
64 Max_List
: constant := 3;
65 -- Limit number of list elements to dump
67 Max_Expr_Elements
: constant := 24;
68 -- Limit number of elements in an expression for use by Expr_Name
70 Num_Elements
: Natural := 0;
71 -- Current number of elements processed by Expr_Name
75 Add_Space
: Boolean := True;
76 Add_Paren
: Boolean := True) return String;
77 -- Return a string corresponding to List
81 Add_Space
: Boolean := True;
82 Add_Paren
: Boolean := True) return String
84 function Internal_List_Name
86 First
: Boolean := True;
87 Add_Space
: Boolean := True;
88 Add_Paren
: Boolean := True;
89 Num
: Natural := 1) return String;
91 ------------------------
92 -- Internal_List_Name --
93 ------------------------
95 function Internal_List_Name
97 First
: Boolean := True;
98 Add_Space
: Boolean := True;
99 Add_Paren
: Boolean := True;
100 Num
: Natural := 1) return String
102 function Prepend
(S
: String) return String;
108 function Prepend
(S
: String) return String is
123 -- Start of processing for Internal_List_Name
126 if not Present
(List
) then
127 if First
or else not Add_Paren
then
132 elsif Num
> Max_List
then
143 & Internal_List_Name
(Next
(List
),
145 Add_Paren
=> Add_Paren
,
148 return ", " & Expr_Name
(List
) &
152 Add_Paren
=> Add_Paren
,
155 end Internal_List_Name
;
157 -- Start of processing for List_Name
160 -- Prevent infinite recursion by limiting depth to 3
162 if List_Name_Count
> 3 then
166 List_Name_Count
:= List_Name_Count
+ 1;
168 Result
: constant String :=
170 (List
, Add_Space
=> Add_Space
, Add_Paren
=> Add_Paren
);
172 List_Name_Count
:= List_Name_Count
- 1;
183 Take_Prefix
: Boolean := True;
184 Expand_Type
: Boolean := True) return String
187 Num_Elements
:= Num_Elements
+ 1;
189 if Num_Elements
> Max_Expr_Elements
then
194 when N_Defining_Identifier | N_Identifier
=>
195 return Ident_Image
(Expr
, Expression_Image
.Expr
, Expand_Type
);
197 when N_Character_Literal
=>
199 Char
: constant Int
:=
200 UI_To_Int
(Char_Literal_Value
(Expr
));
202 if Char
in 32 .. 127 then
203 return "'" & Character'Val (Char
) & "'";
205 UI_Image
(Char_Literal_Value
(Expr
));
206 return "'\" & UI_Image_Buffer (1 .. UI_Image_Length)
211 when N_Integer_Literal =>
212 UI_Image (Intval (Expr));
213 return UI_Image_Buffer (1 .. UI_Image_Length);
215 when N_Real_Literal =>
216 return Real_Image (Realval (Expr));
218 when N_String_Literal =>
219 return String_Image (Strval (Expr));
222 return "new " & Expr_Name (Expression (Expr));
225 if Present (Sinfo.Expressions (Expr)) then
227 (First (Sinfo.Expressions (Expr)), Add_Space => False);
229 elsif Null_Record_Present (Expr) then
230 return ("(null record)");
234 (First (Component_Associations (Expr)),
235 Add_Space => False, Add_Paren => False);
238 when N_Extension_Aggregate =>
239 return "(" & Expr_Name (Ancestor_Part (Expr)) &
241 List_Name (First (Sinfo.Expressions (Expr)),
242 Add_Space => False, Add_Paren => False) &
245 when N_Attribute_Reference =>
248 Str : constant String := Expr_Name (Prefix (Expr))
249 & "'" & Get_Name_String (Attribute_Name (Expr));
250 Id : constant Attribute_Id :=
251 Get_Attribute_Id (Attribute_Name (Expr));
256 if (Id = Attribute_First or else Id = Attribute_Last)
257 and then Str (Str'First) = '$'
259 N := Associated_Node_For_Itype (Etype (Prefix (Expr)));
262 if Nkind (N) = N_Full_Type_Declaration then
263 N := Type_Definition (N);
266 if Nkind (N) = N_Subtype_Declaration then
267 Ranges := Constraints (Constraint
268 (Subtype_Indication (N)));
270 if List_Length (Ranges) = 1
274 N_Real_Range_Specification,
275 N_Signed_Integer_Type_Definition)
277 if Id = Attribute_First then
278 return Expression_Image
279 (Low_Bound (First (Ranges)), Str);
281 return Expression_Image
282 (High_Bound (First (Ranges)), Str);
292 return "'" & Get_Name_String (Attribute_Name (Expr));
295 when N_Explicit_Dereference =>
297 return Expr_Name (Prefix (Expr)) & ".all";
302 when N_Expanded_Name | N_Selected_Component =>
304 return Expr_Name (Prefix (Expr))
305 & "." & Expr_Name (Selector_Name (Expr));
307 return "." & Expr_Name (Selector_Name (Expr));
310 when N_Component_Association =>
312 & List_Name (First (Choices (Expr)),
313 Add_Space => False, Add_Paren => False)
314 & " => " & Expr_Name (Expression (Expr)) & ")";
316 when N_If_Expression =>
318 N : constant Node_Id := First (Sinfo.Expressions (Expr));
320 return "if " & Expr_Name (N) & " then " &
321 Expr_Name (Next (N)) & " else " &
322 Expr_Name (Next (Next (N)));
325 when N_Qualified_Expression =>
327 Mark : constant String :=
328 Expr_Name (Subtype_Mark (Expr), Expand_Type => False);
329 Str : constant String := Expr_Name (Expression (Expr));
331 if Str (Str'First) = '(' and then Str (Str'Last) = ')' then
332 return Mark & "'" & Str;
334 return Mark & "'(" & Str & ")";
338 when N_Unchecked_Expression | N_Expression_With_Actions =>
339 return Expr_Name (Expression (Expr));
341 when N_Raise_Constraint_Error =>
342 if Present (Condition (Expr)) then
343 return "[constraint_error when " &
344 Expr_Name (Condition (Expr)) & "]";
346 return "[constraint_error]";
349 when N_Raise_Program_Error =>
350 if Present (Condition (Expr)) then
351 return "[program_error when " &
352 Expr_Name (Condition (Expr)) & "]";
354 return "[program_error]";
358 return Expr_Name (Low_Bound (Expr)) & ".." &
359 Expr_Name (High_Bound (Expr));
362 return Expr_Name (Prefix (Expr)) & " (" &
363 Expr_Name (Discrete_Range (Expr)) & ")";
366 return Expr_Name (Left_Opnd (Expr)) & " and then " &
367 Expr_Name (Right_Opnd (Expr));
370 return Expr_Name (Left_Opnd (Expr)) & " in " &
371 Expr_Name (Right_Opnd (Expr));
374 return Expr_Name (Left_Opnd (Expr)) & " not in " &
375 Expr_Name (Right_Opnd (Expr));
378 return Expr_Name (Left_Opnd (Expr)) & " or else " &
379 Expr_Name (Right_Opnd (Expr));
382 return Expr_Name (Left_Opnd (Expr)) & " and " &
383 Expr_Name (Right_Opnd (Expr));
386 return Expr_Name (Left_Opnd (Expr)) & " or " &
387 Expr_Name (Right_Opnd (Expr));
390 return Expr_Name (Left_Opnd (Expr)) & " xor " &
391 Expr_Name (Right_Opnd (Expr));
394 return Expr_Name (Left_Opnd (Expr)) & " = " &
395 Expr_Name (Right_Opnd (Expr));
398 return Expr_Name (Left_Opnd (Expr)) & " /= " &
399 Expr_Name (Right_Opnd (Expr));
402 return Expr_Name (Left_Opnd (Expr)) & " < " &
403 Expr_Name (Right_Opnd (Expr));
406 return Expr_Name (Left_Opnd (Expr)) & " <= " &
407 Expr_Name (Right_Opnd (Expr));
410 return Expr_Name (Left_Opnd (Expr)) & " > " &
411 Expr_Name (Right_Opnd (Expr));
414 return Expr_Name (Left_Opnd (Expr)) & " >= " &
415 Expr_Name (Right_Opnd (Expr));
418 return Expr_Name (Left_Opnd (Expr)) & " + " &
419 Expr_Name (Right_Opnd (Expr));
421 when N_Op_Subtract =>
422 return Expr_Name (Left_Opnd (Expr)) & " - " &
423 Expr_Name (Right_Opnd (Expr));
425 when N_Op_Multiply =>
426 return Expr_Name (Left_Opnd (Expr)) & " * " &
427 Expr_Name (Right_Opnd (Expr));
430 return Expr_Name (Left_Opnd (Expr)) & " / " &
431 Expr_Name (Right_Opnd (Expr));
434 return Expr_Name (Left_Opnd (Expr)) & " mod " &
435 Expr_Name (Right_Opnd (Expr));
438 return Expr_Name (Left_Opnd (Expr)) & " rem " &
439 Expr_Name (Right_Opnd (Expr));
442 return Expr_Name (Left_Opnd (Expr)) & " ** " &
443 Expr_Name (Right_Opnd (Expr));
445 when N_Op_Shift_Left =>
446 return Expr_Name (Left_Opnd (Expr)) & " << " &
447 Expr_Name (Right_Opnd (Expr));
449 when N_Op_Shift_Right | N_Op_Shift_Right_Arithmetic =>
450 return Expr_Name (Left_Opnd (Expr)) & " >> " &
451 Expr_Name (Right_Opnd (Expr));
454 return Expr_Name (Left_Opnd (Expr)) & " & " &
455 Expr_Name (Right_Opnd (Expr));
458 return "+" & Expr_Name (Right_Opnd (Expr));
461 return "-" & Expr_Name (Right_Opnd (Expr));
464 return "abs " & Expr_Name (Right_Opnd (Expr));
467 return "not (" & Expr_Name (Right_Opnd (Expr)) & ")";
469 when N_Parameter_Association =>
470 return Expr_Name (Explicit_Actual_Parameter (Expr));
472 when N_Type_Conversion | N_Unchecked_Type_Conversion =>
474 -- Most conversions are not very interesting (used inside
475 -- expanded checks to convert to larger ranges), so skip them.
477 return Expr_Name (Expression (Expr));
479 when N_Indexed_Component =>
481 return Expr_Name (Prefix (Expr)) &
482 List_Name (First (Sinfo.Expressions (Expr)));
484 return List_Name (First (Sinfo.Expressions (Expr)));
487 when N_Function_Call =>
489 -- If Default = "", it means we're expanding the name of
490 -- a gnat temporary (and not really a function call), so add
491 -- parentheses around function call to mark it specially.
494 return '(' & Expr_Name (Name (Expr)) &
495 List_Name (First (Sinfo.Parameter_Associations (Expr))) &
498 return Expr_Name (Name (Expr)) &
499 List_Name (First (Sinfo.Parameter_Associations (Expr)));
505 when N_Others_Choice =>
513 -- Start of processing for Expression_Name
516 if not From_Source then
518 S : constant String := Expr_Name (Expr);
528 -- Compute left (start) and right (end) slocs for the expression
529 -- Consider using Sinput.Sloc_Range instead, except that it does not
530 -- work properly currently???
534 when N_Binary_Op | N_Membership_Test |
535 N_And_Then | N_Or_Else =>
536 Left := Original_Node (Left_Opnd (Left));
538 when N_Attribute_Reference | N_Expanded_Name |
539 N_Explicit_Dereference | N_Indexed_Component |
540 N_Reference | N_Selected_Component |
542 Left := Original_Node (Prefix (Left));
544 when N_Designator | N_Defining_Program_Unit_Name |
546 Left := Original_Node (Name (Left));
549 Left := Original_Node (Low_Bound (Left));
551 when N_Type_Conversion =>
552 Left := Original_Node (Subtype_Mark (Left));
554 -- For any other item, quit loop
562 case Nkind (Right) is
563 when N_Op | N_Membership_Test |
564 N_And_Then | N_Or_Else =>
565 Right := Original_Node (Right_Opnd (Right));
567 when N_Selected_Component | N_Expanded_Name =>
568 Right := Original_Node (Selector_Name (Right));
571 Right := Original_Node (Identifier (Right));
573 when N_Defining_Program_Unit_Name =>
574 Right := Original_Node (Defining_Identifier (Right));
577 Right := Original_Node (High_Bound (Right));
579 when N_Parameter_Association =>
580 Right := Original_Node (Explicit_Actual_Parameter (Right));
582 when N_Indexed_Component =>
583 Right := Original_Node (Last (Sinfo.Expressions (Right)));
584 Append_Paren := True;
586 when N_Function_Call =>
587 if Present (Sinfo.Parameter_Associations (Right)) then
590 (Last (Sinfo.Parameter_Associations (Right)));
591 Append_Paren := True;
593 -- Quit loop if no named associations
599 -- For all other items, quit the loop
607 Scn : Source_Ptr := Original_Location (Sloc (Left));
608 Src : constant Source_Buffer_Ptr :=
609 Source_Text (Get_Source_File_Index (Scn));
610 End_Sloc : constant Source_Ptr :=
611 Original_Location (Sloc (Right));
614 if Scn > End_Sloc then
619 Buffer : String (1 .. Natural (End_Sloc - Scn));
620 Skipping_Comment : Boolean := False;
621 Underscore : Boolean := False;
622 Index : Natural := 0;
625 if Right /= Expr then
626 while Scn < End_Sloc loop
628 when ' ' | ASCII.HT =>
629 if not Skipping_Comment and then not Underscore then
632 Buffer (Index) := ' ';
635 -- CR/LF/FF is the end of any comment
637 when ASCII.LF | ASCII.CR | ASCII.FF =>
638 Skipping_Comment := False;
643 if not Skipping_Comment then
647 if Src (Scn) = '-' and then Src (Scn + 1) = '-' then
648 Skipping_Comment := True;
652 Buffer (Index) := Src (Scn);
663 S : constant String := Expr_Name (Right);
672 elsif Append_Paren then
673 return Buffer (1 .. Index) & Expr_Name (Right, False) & ')';
676 return Buffer (1 .. Index) & Expr_Name (Right, False);
680 end Expression_Image;