diff options
author | charlet <charlet@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-10-29 08:17:50 +0000 |
---|---|---|
committer | charlet <charlet@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-10-29 08:17:50 +0000 |
commit | 060c84227e7faf3c4eb8fd831cba23a0829c077c (patch) | |
tree | 3caa525faf8065b32a7532321edc6d4d68e5c6ac /gcc | |
parent | 1efb1df046de1cd0fca45f0f1750503380ebb59d (diff) | |
download | gcc-060c84227e7faf3c4eb8fd831cba23a0829c077c.tar.gz |
* pprint.ads, pprint.adb: New.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@192909 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ada/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/ada/pprint.adb | 682 | ||||
-rw-r--r-- | gcc/ada/pprint.ads | 60 |
3 files changed, 746 insertions, 0 deletions
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 001a8d901f1..9058c9851fd 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,7 @@ +2012-10-29 Arnaud Charlet <charlet@adacore.com> + + * pprint.ads, pprint.adb: New. + 2012-10-23 Eric Botcazou <ebotcazou@adacore.com> * system-linux-mipsel.ads (Stack_Check_Probes): Set to True. diff --git a/gcc/ada/pprint.adb b/gcc/ada/pprint.adb new file mode 100644 index 00000000000..b01ac2657c9 --- /dev/null +++ b/gcc/ada/pprint.adb @@ -0,0 +1,682 @@ +------------------------------------------------------------------------------ +-- -- +-- GNAT COMPILER COMPONENTS -- +-- -- +-- P P R I N T -- +-- -- +-- B o d y -- +-- -- +-- Copyright (C) 2008-2012, Free Software Foundation, Inc. -- +-- -- +-- GNAT is free software; you can redistribute it and/or modify it under -- +-- terms of the GNU General Public License as published by the Free Soft- -- +-- ware Foundation; either version 3, or (at your option) any later ver- -- +-- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- +-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -- +-- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -- +-- for more details. You should have received a copy of the GNU General -- +-- Public License distributed with GNAT; see file COPYING3. If not, go to -- +-- http://www.gnu.org/licenses for a complete copy of the license. -- +-- -- +-- GNAT was originally developed by the GNAT team at New York University. -- +-- Extensive contributions were provided by Ada Core Technologies Inc. -- +-- -- +------------------------------------------------------------------------------ + +with Atree; use Atree; +with Einfo; use Einfo; +with Namet; use Namet; +with Nlists; use Nlists; +with Opt; use Opt; +with Sinfo; use Sinfo; +with Sinput; use Sinput; +with Snames; use Snames; +with Uintp; use Uintp; + +package body Pprint is + + List_Name_Count : Integer := 0; + -- Counter used to prevent infinite recursion while computing name of + -- complex expressions. + + ---------------------- + -- Expression_Image -- + ---------------------- + + function Expression_Image (Expr : Node_Id; Default : String) + return String is + Left : Node_Id := Original_Node (Expr); + Right : Node_Id := Original_Node (Expr); + From_Source : constant Boolean := + Comes_From_Source (Expr) and then not Opt.Debug_Generated_Code; + Append_Paren : Boolean := False; + + function Expr_Name + (Expr : Node_Id; + Take_Prefix : Boolean := True; + Expand_Type : Boolean := True) return String; + -- Return string corresponding to Expr. If no string can be extracted, + -- return "...". If Take_Prefix is True, go back to prefix when needed, + -- otherwise only consider the right-hand side of an expression. If + -- Expand_Type is True and Expr is a type, try to expand Expr (an + -- internally generated type) into a user understandable name. + + Max_List : constant := 3; + -- Limit number of list elements to dump + + Max_Expr_Elements : constant := 24; + -- Limit number of elements in an expression for use by Expr_Name + + Num_Elements : Natural := 0; + -- Current number of elements processed by Expr_Name + + function List_Name + (List : Node_Id; + Add_Space : Boolean := True; + Add_Paren : Boolean := True) return String; + -- Return a string corresponding to List + + function List_Name + (List : Node_Id; + Add_Space : Boolean := True; + Add_Paren : Boolean := True) return String + is + function Internal_List_Name + (List : Node_Id; + First : Boolean := True; + Add_Space : Boolean := True; + Add_Paren : Boolean := True; + Num : Natural := 1) return String; + + ------------------------ + -- Internal_List_Name -- + ------------------------ + + function Internal_List_Name + (List : Node_Id; + First : Boolean := True; + Add_Space : Boolean := True; + Add_Paren : Boolean := True; + Num : Natural := 1) return String + is + function Prepend (S : String) return String; + + ------------- + -- Prepend -- + ------------- + + function Prepend (S : String) return String is + begin + if Add_Space then + if Add_Paren then + return " (" & S; + else + return ' ' & S; + end if; + elsif Add_Paren then + return '(' & S; + else + return S; + end if; + end Prepend; + + -- Start of processing for Internal_List_Name + + begin + if not Present (List) then + if First or else not Add_Paren then + return ""; + else + return ")"; + end if; + elsif Num > Max_List then + if Add_Paren then + return ", ...)"; + else + return ", ..."; + end if; + end if; + + if First then + return Prepend + (Expr_Name (List) + & Internal_List_Name (Next (List), + First => False, + Add_Paren => Add_Paren, + Num => Num + 1)); + else + return ", " & Expr_Name (List) & + Internal_List_Name + (Next (List), + First => False, + Add_Paren => Add_Paren, + Num => Num + 1); + end if; + end Internal_List_Name; + + -- Start of processing for List_Name + + begin + -- Prevent infinite recursion by limiting depth to 3 + + if List_Name_Count > 3 then + return "..."; + end if; + + List_Name_Count := List_Name_Count + 1; + declare + Result : constant String := + Internal_List_Name + (List, Add_Space => Add_Space, Add_Paren => Add_Paren); + begin + List_Name_Count := List_Name_Count - 1; + return Result; + end; + end List_Name; + + --------------- + -- Expr_Name -- + --------------- + + function Expr_Name + (Expr : Node_Id; + Take_Prefix : Boolean := True; + Expand_Type : Boolean := True) return String + is + begin + Num_Elements := Num_Elements + 1; + + if Num_Elements > Max_Expr_Elements then + return "..."; + end if; + + case Nkind (Expr) is + when N_Defining_Identifier | N_Identifier => + return Ident_Image (Expr, Expression_Image.Expr, Expand_Type); + + when N_Character_Literal => + declare + Char : constant Int := + UI_To_Int (Char_Literal_Value (Expr)); + begin + if Char in 32 .. 127 then + return "'" & Character'Val (Char) & "'"; + else + UI_Image (Char_Literal_Value (Expr)); + return "'\" & UI_Image_Buffer (1 .. UI_Image_Length) + & "'"; + end if; + end; + + when N_Integer_Literal => + UI_Image (Intval (Expr)); + return UI_Image_Buffer (1 .. UI_Image_Length); + + when N_Real_Literal => + return Real_Image (Realval (Expr)); + + when N_String_Literal => + return String_Image (Strval (Expr)); + + when N_Allocator => + return "new " & Expr_Name (Expression (Expr)); + + when N_Aggregate => + if Present (Sinfo.Expressions (Expr)) then + return List_Name + (First (Sinfo.Expressions (Expr)), Add_Space => False); + + elsif Null_Record_Present (Expr) then + return ("(null record)"); + + else + return List_Name + (First (Component_Associations (Expr)), + Add_Space => False, Add_Paren => False); + end if; + + when N_Extension_Aggregate => + return "(" & Expr_Name (Ancestor_Part (Expr)) & + " with " & + List_Name (First (Sinfo.Expressions (Expr)), + Add_Space => False, Add_Paren => False) & + ")"; + + when N_Attribute_Reference => + if Take_Prefix then + declare + Str : constant String := Expr_Name (Prefix (Expr)) + & "'" & Get_Name_String (Attribute_Name (Expr)); + Id : constant Attribute_Id := + Get_Attribute_Id (Attribute_Name (Expr)); + Ranges : List_Id; + N : Node_Id; + + begin + if (Id = Attribute_First or else Id = Attribute_Last) + and then Str (Str'First) = '$' + then + N := Associated_Node_For_Itype (Etype (Prefix (Expr))); + + if Present (N) then + if Nkind (N) = N_Full_Type_Declaration then + N := Type_Definition (N); + end if; + + if Nkind (N) = N_Subtype_Declaration then + Ranges := Constraints (Constraint + (Subtype_Indication (N))); + + if List_Length (Ranges) = 1 + and then Nkind_In + (First (Ranges), + N_Range, + N_Real_Range_Specification, + N_Signed_Integer_Type_Definition) + then + if Id = Attribute_First then + return Expression_Image + (Low_Bound (First (Ranges)), Str); + else + return Expression_Image + (High_Bound (First (Ranges)), Str); + end if; + end if; + end if; + end if; + end if; + + return Str; + end; + else + return "'" & Get_Name_String (Attribute_Name (Expr)); + end if; + + when N_Explicit_Dereference => + if Take_Prefix then + return Expr_Name (Prefix (Expr)) & ".all"; + else + return ".all"; + end if; + + when N_Expanded_Name | N_Selected_Component => + if Take_Prefix then + return Expr_Name (Prefix (Expr)) + & "." & Expr_Name (Selector_Name (Expr)); + else + return "." & Expr_Name (Selector_Name (Expr)); + end if; + + when N_Component_Association => + return "(" + & List_Name (First (Choices (Expr)), + Add_Space => False, Add_Paren => False) + & " => " & Expr_Name (Expression (Expr)) & ")"; + + when N_If_Expression => + declare + N : constant Node_Id := First (Sinfo.Expressions (Expr)); + begin + return "if " & Expr_Name (N) & " then " & + Expr_Name (Next (N)) & " else " & + Expr_Name (Next (Next (N))); + end; + + when N_Qualified_Expression => + declare + Mark : constant String := + Expr_Name (Subtype_Mark (Expr), Expand_Type => False); + Str : constant String := Expr_Name (Expression (Expr)); + begin + if Str (Str'First) = '(' and then Str (Str'Last) = ')' then + return Mark & "'" & Str; + else + return Mark & "'(" & Str & ")"; + end if; + end; + + when N_Unchecked_Expression | N_Expression_With_Actions => + return Expr_Name (Expression (Expr)); + + when N_Raise_Constraint_Error => + if Present (Condition (Expr)) then + return "[constraint_error when " & + Expr_Name (Condition (Expr)) & "]"; + else + return "[constraint_error]"; + end if; + + when N_Raise_Program_Error => + if Present (Condition (Expr)) then + return "[program_error when " & + Expr_Name (Condition (Expr)) & "]"; + else + return "[program_error]"; + end if; + + when N_Range => + return Expr_Name (Low_Bound (Expr)) & ".." & + Expr_Name (High_Bound (Expr)); + + when N_Slice => + return Expr_Name (Prefix (Expr)) & " (" & + Expr_Name (Discrete_Range (Expr)) & ")"; + + when N_And_Then => + return Expr_Name (Left_Opnd (Expr)) & " and then " & + Expr_Name (Right_Opnd (Expr)); + + when N_In => + return Expr_Name (Left_Opnd (Expr)) & " in " & + Expr_Name (Right_Opnd (Expr)); + + when N_Not_In => + return Expr_Name (Left_Opnd (Expr)) & " not in " & + Expr_Name (Right_Opnd (Expr)); + + when N_Or_Else => + return Expr_Name (Left_Opnd (Expr)) & " or else " & + Expr_Name (Right_Opnd (Expr)); + + when N_Op_And => + return Expr_Name (Left_Opnd (Expr)) & " and " & + Expr_Name (Right_Opnd (Expr)); + + when N_Op_Or => + return Expr_Name (Left_Opnd (Expr)) & " or " & + Expr_Name (Right_Opnd (Expr)); + + when N_Op_Xor => + return Expr_Name (Left_Opnd (Expr)) & " xor " & + Expr_Name (Right_Opnd (Expr)); + + when N_Op_Eq => + return Expr_Name (Left_Opnd (Expr)) & " = " & + Expr_Name (Right_Opnd (Expr)); + + when N_Op_Ne => + return Expr_Name (Left_Opnd (Expr)) & " /= " & + Expr_Name (Right_Opnd (Expr)); + + when N_Op_Lt => + return Expr_Name (Left_Opnd (Expr)) & " < " & + Expr_Name (Right_Opnd (Expr)); + + when N_Op_Le => + return Expr_Name (Left_Opnd (Expr)) & " <= " & + Expr_Name (Right_Opnd (Expr)); + + when N_Op_Gt => + return Expr_Name (Left_Opnd (Expr)) & " > " & + Expr_Name (Right_Opnd (Expr)); + + when N_Op_Ge => + return Expr_Name (Left_Opnd (Expr)) & " >= " & + Expr_Name (Right_Opnd (Expr)); + + when N_Op_Add => + return Expr_Name (Left_Opnd (Expr)) & " + " & + Expr_Name (Right_Opnd (Expr)); + + when N_Op_Subtract => + return Expr_Name (Left_Opnd (Expr)) & " - " & + Expr_Name (Right_Opnd (Expr)); + + when N_Op_Multiply => + return Expr_Name (Left_Opnd (Expr)) & " * " & + Expr_Name (Right_Opnd (Expr)); + + when N_Op_Divide => + return Expr_Name (Left_Opnd (Expr)) & " / " & + Expr_Name (Right_Opnd (Expr)); + + when N_Op_Mod => + return Expr_Name (Left_Opnd (Expr)) & " mod " & + Expr_Name (Right_Opnd (Expr)); + + when N_Op_Rem => + return Expr_Name (Left_Opnd (Expr)) & " rem " & + Expr_Name (Right_Opnd (Expr)); + + when N_Op_Expon => + return Expr_Name (Left_Opnd (Expr)) & " ** " & + Expr_Name (Right_Opnd (Expr)); + + when N_Op_Shift_Left => + return Expr_Name (Left_Opnd (Expr)) & " << " & + Expr_Name (Right_Opnd (Expr)); + + when N_Op_Shift_Right | N_Op_Shift_Right_Arithmetic => + return Expr_Name (Left_Opnd (Expr)) & " >> " & + Expr_Name (Right_Opnd (Expr)); + + when N_Op_Concat => + return Expr_Name (Left_Opnd (Expr)) & " & " & + Expr_Name (Right_Opnd (Expr)); + + when N_Op_Plus => + return "+" & Expr_Name (Right_Opnd (Expr)); + + when N_Op_Minus => + return "-" & Expr_Name (Right_Opnd (Expr)); + + when N_Op_Abs => + return "abs " & Expr_Name (Right_Opnd (Expr)); + + when N_Op_Not => + return "not (" & Expr_Name (Right_Opnd (Expr)) & ")"; + + when N_Parameter_Association => + return Expr_Name (Explicit_Actual_Parameter (Expr)); + + when N_Type_Conversion | N_Unchecked_Type_Conversion => + + -- Most conversions are not very interesting (used inside + -- expanded checks to convert to larger ranges), so skip them. + + return Expr_Name (Expression (Expr)); + + when N_Indexed_Component => + if Take_Prefix then + return Expr_Name (Prefix (Expr)) & + List_Name (First (Sinfo.Expressions (Expr))); + else + return List_Name (First (Sinfo.Expressions (Expr))); + end if; + + when N_Function_Call => + + -- If Default = "", it means we're expanding the name of + -- a gnat temporary (and not really a function call), so add + -- parentheses around function call to mark it specially. + + if Default = "" then + return '(' & Expr_Name (Name (Expr)) & + List_Name (First (Sinfo.Parameter_Associations (Expr))) & + ')'; + else + return Expr_Name (Name (Expr)) & + List_Name (First (Sinfo.Parameter_Associations (Expr))); + end if; + + when N_Null => + return "null"; + + when N_Others_Choice => + return "others"; + + when others => + return "..."; + end case; + end Expr_Name; + + -- Start of processing for Expression_Name + + begin + if not From_Source then + declare + S : constant String := Expr_Name (Expr); + begin + if S = "..." then + return Default; + else + return S; + end if; + end; + end if; + + -- Compute left (start) and right (end) slocs for the expression + -- Consider using Sinput.Sloc_Range instead, except that it does not + -- work properly currently??? + + loop + case Nkind (Left) is + when N_Binary_Op | N_Membership_Test | + N_And_Then | N_Or_Else => + Left := Original_Node (Left_Opnd (Left)); + + when N_Attribute_Reference | N_Expanded_Name | + N_Explicit_Dereference | N_Indexed_Component | + N_Reference | N_Selected_Component | + N_Slice => + Left := Original_Node (Prefix (Left)); + + when N_Designator | N_Defining_Program_Unit_Name | + N_Function_Call => + Left := Original_Node (Name (Left)); + + when N_Range => + Left := Original_Node (Low_Bound (Left)); + + when N_Type_Conversion => + Left := Original_Node (Subtype_Mark (Left)); + + -- For any other item, quit loop + + when others => + exit; + end case; + end loop; + + loop + case Nkind (Right) is + when N_Op | N_Membership_Test | + N_And_Then | N_Or_Else => + Right := Original_Node (Right_Opnd (Right)); + + when N_Selected_Component | N_Expanded_Name => + Right := Original_Node (Selector_Name (Right)); + + when N_Designator => + Right := Original_Node (Identifier (Right)); + + when N_Defining_Program_Unit_Name => + Right := Original_Node (Defining_Identifier (Right)); + + when N_Range => + Right := Original_Node (High_Bound (Right)); + + when N_Parameter_Association => + Right := Original_Node (Explicit_Actual_Parameter (Right)); + + when N_Indexed_Component => + Right := Original_Node (Last (Sinfo.Expressions (Right))); + Append_Paren := True; + + when N_Function_Call => + if Present (Sinfo.Parameter_Associations (Right)) then + Right := + Original_Node + (Last (Sinfo.Parameter_Associations (Right))); + Append_Paren := True; + + -- Quit loop if no named associations + + else + exit; + end if; + + -- For all other items, quit the loop + + when others => + exit; + end case; + end loop; + + declare + Scn : Source_Ptr := Original_Location (Sloc (Left)); + Src : constant Source_Buffer_Ptr := + Source_Text (Get_Source_File_Index (Scn)); + End_Sloc : constant Source_Ptr := + Original_Location (Sloc (Right)); + + begin + if Scn > End_Sloc then + return Default; + end if; + + declare + Buffer : String (1 .. Natural (End_Sloc - Scn)); + Skipping_Comment : Boolean := False; + Underscore : Boolean := False; + Index : Natural := 0; + + begin + if Right /= Expr then + while Scn < End_Sloc loop + case Src (Scn) is + when ' ' | ASCII.HT => + if not Skipping_Comment and then not Underscore then + Underscore := True; + Index := Index + 1; + Buffer (Index) := ' '; + end if; + + -- CR/LF/FF is the end of any comment + + when ASCII.LF | ASCII.CR | ASCII.FF => + Skipping_Comment := False; + + when others => + Underscore := False; + + if not Skipping_Comment then + + -- Ignore comment + + if Src (Scn) = '-' and then Src (Scn + 1) = '-' then + Skipping_Comment := True; + + else + Index := Index + 1; + Buffer (Index) := Src (Scn); + end if; + end if; + end case; + + Scn := Scn + 1; + end loop; + end if; + + if Index < 1 then + declare + S : constant String := Expr_Name (Right); + begin + if S = "..." then + return Default; + else + return S; + end if; + end; + + elsif Append_Paren then + return Buffer (1 .. Index) & Expr_Name (Right, False) & ')'; + + else + return Buffer (1 .. Index) & Expr_Name (Right, False); + end if; + end; + end; + end Expression_Image; + +end Pprint; diff --git a/gcc/ada/pprint.ads b/gcc/ada/pprint.ads new file mode 100644 index 00000000000..8fc1036b1e4 --- /dev/null +++ b/gcc/ada/pprint.ads @@ -0,0 +1,60 @@ +------------------------------------------------------------------------------ +-- -- +-- GNAT COMPILER COMPONENTS -- +-- -- +-- P P R I N T -- +-- -- +-- S p e c -- +-- -- +-- Copyright (C) 2008-2012, Free Software Foundation, Inc. -- +-- -- +-- GNAT is free software; you can redistribute it and/or modify it under -- +-- terms of the GNU General Public License as published by the Free Soft- -- +-- ware Foundation; either version 3, or (at your option) any later ver- -- +-- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- +-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -- +-- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -- +-- for more details. You should have received a copy of the GNU General -- +-- Public License distributed with GNAT; see file COPYING3. If not, go to -- +-- http://www.gnu.org/licenses for a complete copy of the license. -- +-- -- +-- GNAT was originally developed by the GNAT team at New York University. -- +-- Extensive contributions were provided by Ada Core Technologies Inc. -- +-- -- +------------------------------------------------------------------------------ + +-- This package (pretty print) contains a routine for printing an expression +-- given its node in the syntax tree. Contrarily to the Sprint package, this +-- routine tries to obtain "pretty" output that can be used for e.g. error +-- messages. + +with Types; use Types; +with Urealp; use Urealp; + +package Pprint is + + generic + + -- ??? The generic parameters should be removed. + + with function Real_Image (U : Ureal) return String; + with function String_Image (S : String_Id) return String; + with function Ident_Image (Expr : Node_Id; + Orig_Expr : Node_Id; + Expand_Type : Boolean) + return String; + -- Will be called for printing N_Identifier and N_Defining_Identifier + -- nodes + -- ??? Expand_Type argument should be removed + + function Expression_Image (Expr : Node_Id; + Default : String) + return String; + -- Given a Node for an expression, return a String that is meaningful for + -- the programmer. If the expression comes from source, it is copied from + -- there. + -- Subexpressions outside of the maximum depth (3), the maximal number of + -- accepted nodes (24), and the maximal number of list elements (3), are + -- replaced by the default string. + +end Pprint; |