OSDN Git Service

2005-06-14 Doug Rupp <rupp@adacore.com>
[pf3gnuchains/gcc-fork.git] / gcc / ada / g-trasym-vms-ia64.adb
1 ------------------------------------------------------------------------------
2 --                                                                          --
3 --                         GNAT RUN-TIME COMPONENTS                         --
4 --                                                                          --
5 --             G N A T . T R A C E B A C K . S Y M B O L I C                --
6 --                                                                          --
7 --                                 B o d y                                  --
8 --                                                                          --
9 --             Copyright (C) 2005 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 2,  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 COPYING.  If not, write --
19 -- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
20 -- MA 02111-1307, USA.                                                      --
21 --                                                                          --
22 -- As a special exception,  if other files  instantiate  generics from this --
23 -- unit, or you link  this unit with other files  to produce an executable, --
24 -- this  unit  does not  by itself cause  the resulting  executable  to  be --
25 -- covered  by the  GNU  General  Public  License.  This exception does not --
26 -- however invalidate  any other reasons why  the executable file  might be --
27 -- covered by the  GNU Public License.                                      --
28 --                                                                          --
29 -- GNAT was originally developed  by the GNAT team at  New York University. --
30 -- Extensive contributions were provided by Ada Core Technologies Inc.      --
31 --                                                                          --
32 ------------------------------------------------------------------------------
33
34 --  Run-time symbolic traceback support for IA64/VMS
35
36 with Ada.Exceptions.Traceback; use Ada.Exceptions.Traceback;
37 with Interfaces.C;
38 with System;
39 with System.Aux_DEC;
40 with System.Soft_Links;
41 with System.Traceback_Entries;
42
43 package body GNAT.Traceback.Symbolic is
44
45    pragma Warnings (Off);
46    pragma Linker_Options ("--for-linker=sys$library:trace.exe");
47
48    use Interfaces.C;
49    use System;
50    use System.Aux_DEC;
51    use System.Traceback_Entries;
52
53    subtype User_Arg_Type is Unsigned_Longword;
54    subtype Cond_Value_Type is Unsigned_Longword;
55
56    type ASCIC is record
57       Count : unsigned_char;
58       Data  : char_array (1 .. 255);
59    end record;
60    pragma Convention (C, ASCIC);
61
62    for ASCIC use record
63       Count at 0 range 0 .. 7;
64       Data  at 1 range 0 .. 8 * 255 - 1;
65    end record;
66    for ASCIC'Size use 8 * 256;
67
68    function Fetch_ASCIC is new Fetch_From_Address (ASCIC);
69
70    procedure Symbolize
71      (Status         : out Cond_Value_Type;
72       Current_PC     : in Address;
73       Filename_Name  : out Address;
74       Library_Name   : out Address;
75       Record_Number  : out Integer;
76       Image_Name     : out Address;
77       Module_Name    : out Address;
78       Routine_Name   : out Address;
79       Line_Number    : out Integer;
80       Relative_PC    : out Address);
81
82    pragma Interface (External, Symbolize);
83
84    pragma Import_Valued_Procedure
85      (Symbolize, "TBK$I64_SYMBOLIZE",
86       (Cond_Value_Type, Address,
87        Address, Address, Integer,
88        Address, Address, Address, Integer,
89        Address),
90       (Value, Value,
91        Reference, Reference, Reference,
92        Reference, Reference, Reference, Reference,
93        Reference));
94
95    function Decode_Ada_Name (Encoded_Name : String) return String;
96    --  Decodes an Ada identifier name. Removes leading "_ada_" and trailing
97    --  __{DIGIT}+ or ${DIGIT}+, converts other "__" to '.'
98
99    ---------------------
100    -- Decode_Ada_Name --
101    ---------------------
102
103    function Decode_Ada_Name (Encoded_Name : String) return String is
104       Decoded_Name : String (1 .. Encoded_Name'Length);
105       Pos          : Integer := Encoded_Name'First;
106       Last         : Integer := Encoded_Name'Last;
107       DPos         : Integer := 1;
108
109    begin
110       if Pos > Last then
111          return "";
112       end if;
113
114       --  Skip leading _ada_
115
116       if Encoded_Name'Length > 4
117         and then Encoded_Name (Pos .. Pos + 4) = "_ada_"
118       then
119          Pos := Pos + 5;
120       end if;
121
122       --  Skip trailing __{DIGIT}+ or ${DIGIT}+
123
124       if Encoded_Name (Last) in '0' .. '9' then
125          for J in reverse Pos + 2 .. Last - 1 loop
126             case Encoded_Name (J) is
127                when '0' .. '9' =>
128                   null;
129                when '$' =>
130                   Last := J - 1;
131                   exit;
132                when '_' =>
133                   if Encoded_Name (J - 1) = '_' then
134                      Last := J - 2;
135                   end if;
136                   exit;
137                when others =>
138                   exit;
139             end case;
140          end loop;
141       end if;
142
143       --  Now just copy encoded name to decoded name, converting "__" to '.'
144
145       while Pos <= Last loop
146          if Encoded_Name (Pos) = '_' and then Encoded_Name (Pos + 1) = '_'
147            and then Pos /= Encoded_Name'First
148          then
149             Decoded_Name (DPos) := '.';
150             Pos := Pos + 2;
151
152          else
153             Decoded_Name (DPos) := Encoded_Name (Pos);
154             Pos := Pos + 1;
155          end if;
156
157          DPos := DPos + 1;
158       end loop;
159
160       return Decoded_Name (1 .. DPos - 1);
161    end Decode_Ada_Name;
162
163    ------------------------
164    -- Symbolic_Traceback --
165    ------------------------
166
167    function Symbolic_Traceback (Traceback : Tracebacks_Array) return String is
168       Status             : Cond_Value_Type;
169       Filename_Name_Addr : Address;
170       Library_Name_Addr  : Address;
171       Record_Number      : Integer;
172       Image_Name         : ASCIC;
173       Image_Name_Addr    : Address;
174       Module_Name        : ASCIC;
175       Module_Name_Addr   : Address;
176       Routine_Name       : ASCIC;
177       Routine_Name_Addr  : Address;
178       Line_Number        : Integer;
179       Relative_PC        : Address;
180       Res                : String (1 .. 256 * Traceback'Length);
181       Len                : Integer;
182
183    begin
184       if Traceback'Length > 0 then
185          Len := 0;
186
187          --  Since image computation is not thread-safe we need task lockout
188
189          System.Soft_Links.Lock_Task.all;
190
191          for J in Traceback'Range loop
192
193             Symbolize
194               (Status,
195                PC_For (Traceback (J)),
196                Filename_Name_Addr,
197                Library_Name_Addr,
198                Record_Number,
199                Image_Name_Addr,
200                Module_Name_Addr,
201                Routine_Name_Addr,
202                Line_Number,
203                Relative_PC);
204
205             Image_Name   := Fetch_ASCIC (Image_Name_Addr);
206             Module_Name  := Fetch_ASCIC (Module_Name_Addr);
207             Routine_Name := Fetch_ASCIC (Routine_Name_Addr);
208
209             declare
210                First : Integer := Len + 1;
211                Last  : Integer := First + 80 - 1;
212                Pos   : Integer;
213                Routine_Name_D : String := Decode_Ada_Name
214                  (To_Ada
215                     (Routine_Name.Data (1 .. size_t (Routine_Name.Count)),
216                      False));
217
218             begin
219                Res (First .. Last) := (others => ' ');
220
221                Res (First .. First + Integer (Image_Name.Count) - 1) :=
222                  To_Ada
223                   (Image_Name.Data (1 .. size_t (Image_Name.Count)),
224                    False);
225
226                Res (First + 10 ..
227                     First + 10 + Integer (Module_Name.Count) - 1) :=
228                  To_Ada
229                   (Module_Name.Data (1 .. size_t (Module_Name.Count)),
230                    False);
231
232                Res (First + 30 ..
233                     First + 30 + Routine_Name_D'Length - 1) :=
234                  Routine_Name_D;
235
236                --  If routine name doesn't fit 20 characters, output
237                --  the line number on next line at 50th position
238
239                if Routine_Name_D'Length > 20 then
240                   Pos := First + 30 + Routine_Name_D'Length;
241                   Res (Pos) := ASCII.LF;
242                   Last := Pos + 80;
243                   Res (Pos + 1 .. Last) := (others => ' ');
244                   Pos := Pos + 51;
245                else
246                   Pos := First + 50;
247                end if;
248
249                Res (Pos .. Pos + Integer'Image (Line_Number)'Length - 1) :=
250                  Integer'Image (Line_Number);
251
252                Res (Last) := ASCII.LF;
253                Len := Last;
254             end;
255          end loop;
256
257          System.Soft_Links.Unlock_Task.all;
258          return Res (1 .. Len);
259
260       else
261          return "";
262       end if;
263    end Symbolic_Traceback;
264
265    function Symbolic_Traceback (E : Exception_Occurrence) return String is
266    begin
267       return Symbolic_Traceback (Tracebacks (E));
268    end Symbolic_Traceback;
269
270 end GNAT.Traceback.Symbolic;