xref: /dragonfly/contrib/gdb-7/gdb/jv-typeprint.c (revision de8e141f24382815c10a4012d209bbbf7abf1112)
1 /* Support for printing Java types for GDB, the GNU debugger.
2    Copyright (C) 1997-2013 Free Software Foundation, Inc.
3 
4    This file is part of GDB.
5 
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10 
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15 
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
18 
19 
20 #include "defs.h"
21 #include "symtab.h"
22 #include "gdbtypes.h"
23 #include "value.h"
24 #include "demangle.h"
25 #include "gdb-demangle.h"
26 #include "jv-lang.h"
27 #include "gdb_string.h"
28 #include "typeprint.h"
29 #include "c-lang.h"
30 #include "cp-abi.h"
31 #include "gdb_assert.h"
32 
33 /* Local functions */
34 
35 static void java_type_print_base (struct type * type,
36                                           struct ui_file *stream, int show,
37                                           int level,
38                                           const struct type_print_options *flags);
39 
40 static void
java_type_print_derivation_info(struct ui_file * stream,struct type * type)41 java_type_print_derivation_info (struct ui_file *stream, struct type *type)
42 {
43   const char *name;
44   int i;
45   int n_bases;
46   int prev;
47 
48   n_bases = TYPE_N_BASECLASSES (type);
49 
50   for (i = 0, prev = 0; i < n_bases; i++)
51     {
52       int kind;
53 
54       kind = BASETYPE_VIA_VIRTUAL (type, i) ? 'I' : 'E';
55 
56       fputs_filtered (kind == prev ? ", "
57                           : kind == 'I' ? " implements "
58                           : " extends ",
59                           stream);
60       prev = kind;
61       name = type_name_no_tag (TYPE_BASECLASS (type, i));
62 
63       fprintf_filtered (stream, "%s", name ? name : "(null)");
64     }
65 
66   if (i > 0)
67     fputs_filtered (" ", stream);
68 }
69 
70 /* Print the name of the type (or the ultimate pointer target,
71    function value or array element), or the description of a
72    structure or union.
73 
74    SHOW positive means print details about the type (e.g. enum values),
75    and print structure elements passing SHOW - 1 for show.
76    SHOW negative means just print the type name or struct tag if there is one.
77    If there is no name, print something sensible but concise like
78    "struct {...}".
79    SHOW zero means just print the type name or struct tag if there is one.
80    If there is no name, print something sensible but not as concise like
81    "struct {int x; int y;}".
82 
83    LEVEL is the number of spaces to indent by.
84    We increase it for some recursive calls.  */
85 
86 static void
java_type_print_base(struct type * type,struct ui_file * stream,int show,int level,const struct type_print_options * flags)87 java_type_print_base (struct type *type, struct ui_file *stream, int show,
88                           int level, const struct type_print_options *flags)
89 {
90   int i;
91   int len;
92   char *mangled_name;
93   char *demangled_name;
94 
95   QUIT;
96   wrap_here ("    ");
97 
98   if (type == NULL)
99     {
100       fputs_filtered ("<type unknown>", stream);
101       return;
102     }
103 
104   /* When SHOW is zero or less, and there is a valid type name, then always
105      just print the type name directly from the type.  */
106 
107   if (show <= 0
108       && TYPE_NAME (type) != NULL)
109     {
110       fputs_filtered (TYPE_NAME (type), stream);
111       return;
112     }
113 
114   CHECK_TYPEDEF (type);
115 
116   switch (TYPE_CODE (type))
117     {
118     case TYPE_CODE_PTR:
119       java_type_print_base (TYPE_TARGET_TYPE (type), stream, show, level,
120                                   flags);
121       break;
122 
123     case TYPE_CODE_STRUCT:
124       if (TYPE_TAG_NAME (type) != NULL && TYPE_TAG_NAME (type)[0] == '[')
125           {                             /* array type */
126             char *name = java_demangle_type_signature (TYPE_TAG_NAME (type));
127 
128             fputs_filtered (name, stream);
129             xfree (name);
130             break;
131           }
132 
133       if (show >= 0)
134           fprintf_filtered (stream, "class ");
135 
136       if (TYPE_TAG_NAME (type) != NULL)
137           {
138             fputs_filtered (TYPE_TAG_NAME (type), stream);
139             if (show > 0)
140               fputs_filtered (" ", stream);
141           }
142 
143       wrap_here ("    ");
144 
145       if (show < 0)
146           {
147             /* If we just printed a tag name, no need to print anything else.  */
148             if (TYPE_TAG_NAME (type) == NULL)
149               fprintf_filtered (stream, "{...}");
150           }
151       else if (show > 0 || TYPE_TAG_NAME (type) == NULL)
152           {
153             java_type_print_derivation_info (stream, type);
154 
155             fprintf_filtered (stream, "{\n");
156             if ((TYPE_NFIELDS (type) == 0) && (TYPE_NFN_FIELDS (type) == 0))
157               {
158                 if (TYPE_STUB (type))
159                     fprintfi_filtered (level + 4, stream, "<incomplete type>\n");
160                 else
161                     fprintfi_filtered (level + 4, stream, "<no data fields>\n");
162               }
163 
164             /* If there is a base class for this type,
165                do not print the field that it occupies.  */
166 
167             len = TYPE_NFIELDS (type);
168             for (i = TYPE_N_BASECLASSES (type); i < len; i++)
169               {
170                 QUIT;
171                 /* Don't print out virtual function table.  */
172                 if (strncmp (TYPE_FIELD_NAME (type, i), "_vptr", 5) == 0
173                       && is_cplus_marker ((TYPE_FIELD_NAME (type, i))[5]))
174                     continue;
175 
176                 /* Don't print the dummy field "class".  */
177                 if (strncmp (TYPE_FIELD_NAME (type, i), "class", 5) == 0)
178                     continue;
179 
180                 print_spaces_filtered (level + 4, stream);
181 
182                 if (HAVE_CPLUS_STRUCT (type))
183                     {
184                       if (TYPE_FIELD_PROTECTED (type, i))
185                         fprintf_filtered (stream, "protected ");
186                       else if (TYPE_FIELD_PRIVATE (type, i))
187                         fprintf_filtered (stream, "private ");
188                       else
189                         fprintf_filtered (stream, "public ");
190                     }
191 
192                 if (field_is_static (&TYPE_FIELD (type, i)))
193                     fprintf_filtered (stream, "static ");
194 
195                 java_print_type (TYPE_FIELD_TYPE (type, i),
196                                      TYPE_FIELD_NAME (type, i),
197                                      stream, show - 1, level + 4, flags);
198 
199                 fprintf_filtered (stream, ";\n");
200               }
201 
202             /* If there are both fields and methods, put a space between.  */
203             len = TYPE_NFN_FIELDS (type);
204             if (len)
205               fprintf_filtered (stream, "\n");
206 
207             /* Print out the methods.  */
208 
209             for (i = 0; i < len; i++)
210               {
211                 struct fn_field *f;
212                 int j;
213                 const char *method_name;
214                 const char *name;
215                 int is_constructor;
216                 int n_overloads;
217 
218                 f = TYPE_FN_FIELDLIST1 (type, i);
219                 n_overloads = TYPE_FN_FIELDLIST_LENGTH (type, i);
220                 method_name = TYPE_FN_FIELDLIST_NAME (type, i);
221                 name = type_name_no_tag (type);
222                 is_constructor = name && strcmp (method_name, name) == 0;
223 
224                 for (j = 0; j < n_overloads; j++)
225                     {
226                       const char *real_physname;
227                       char *physname, *p;
228                       int is_full_physname_constructor;
229 
230                       real_physname = TYPE_FN_FIELD_PHYSNAME (f, j);
231 
232                       /* The physname will contain the return type
233                          after the final closing parenthesis.  Strip it off.  */
234                       p = strrchr (real_physname, ')');
235                       gdb_assert (p != NULL);
236                       ++p;   /* Keep the trailing ')'.  */
237                       physname = alloca (p - real_physname + 1);
238                       memcpy (physname, real_physname, p - real_physname);
239                       physname[p - real_physname] = '\0';
240 
241                       is_full_physname_constructor
242                     = (TYPE_FN_FIELD_CONSTRUCTOR (f, j)
243                            || is_constructor_name (physname)
244                        || is_destructor_name (physname));
245 
246                       QUIT;
247 
248                       print_spaces_filtered (level + 4, stream);
249 
250                       if (TYPE_FN_FIELD_PROTECTED (f, j))
251                         fprintf_filtered (stream, "protected ");
252                       else if (TYPE_FN_FIELD_PRIVATE (f, j))
253                         fprintf_filtered (stream, "private ");
254                       else if (TYPE_FN_FIELD_PUBLIC (f, j))
255                         fprintf_filtered (stream, "public ");
256 
257                       if (TYPE_FN_FIELD_ABSTRACT (f, j))
258                         fprintf_filtered (stream, "abstract ");
259                       if (TYPE_FN_FIELD_STATIC (f, j))
260                         fprintf_filtered (stream, "static ");
261                       if (TYPE_FN_FIELD_FINAL (f, j))
262                         fprintf_filtered (stream, "final ");
263                       if (TYPE_FN_FIELD_SYNCHRONIZED (f, j))
264                         fprintf_filtered (stream, "synchronized ");
265                       if (TYPE_FN_FIELD_NATIVE (f, j))
266                         fprintf_filtered (stream, "native ");
267 
268                       if (TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (f, j)) == 0)
269                         {
270                           /* Keep GDB from crashing here.  */
271                           fprintf_filtered (stream, "<undefined type> %s;\n",
272                                                   TYPE_FN_FIELD_PHYSNAME (f, j));
273                           break;
274                         }
275                       else if (!is_constructor && !is_full_physname_constructor)
276                         {
277                           type_print (TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (f, j)),
278                                           "", stream, -1);
279                           fputs_filtered (" ", stream);
280                         }
281 
282                       if (TYPE_FN_FIELD_STUB (f, j))
283                         /* Build something we can demangle.  */
284                         mangled_name = gdb_mangle_name (type, i, j);
285                       else
286                         mangled_name = physname;
287 
288                       demangled_name =
289                         cplus_demangle (mangled_name,
290                                             DMGL_ANSI | DMGL_PARAMS | DMGL_JAVA);
291 
292                       if (demangled_name == NULL)
293                         demangled_name = xstrdup (mangled_name);
294 
295                       {
296                         char *demangled_no_class;
297                         char *ptr;
298 
299                         ptr = demangled_no_class = demangled_name;
300 
301                         while (1)
302                           {
303                               char c;
304 
305                               c = *ptr++;
306 
307                               if (c == 0 || c == '(')
308                                 break;
309                               if (c == '.')
310                                 demangled_no_class = ptr;
311                           }
312 
313                         fputs_filtered (demangled_no_class, stream);
314                         xfree (demangled_name);
315                       }
316 
317                       if (TYPE_FN_FIELD_STUB (f, j))
318                         xfree (mangled_name);
319 
320                       fprintf_filtered (stream, ";\n");
321                     }
322               }
323 
324             fprintfi_filtered (level, stream, "}");
325           }
326       break;
327 
328     default:
329       c_type_print_base (type, stream, show, level, flags);
330     }
331 }
332 
333 /* LEVEL is the depth to indent lines by.  */
334 
335 void
java_print_type(struct type * type,const char * varstring,struct ui_file * stream,int show,int level,const struct type_print_options * flags)336 java_print_type (struct type *type, const char *varstring,
337                      struct ui_file *stream, int show, int level,
338                      const struct type_print_options *flags)
339 {
340   int demangled_args;
341 
342   java_type_print_base (type, stream, show, level, flags);
343 
344   if (varstring != NULL && *varstring != '\0')
345     {
346       fputs_filtered (" ", stream);
347       fputs_filtered (varstring, stream);
348     }
349 
350   /* For demangled function names, we have the arglist as part of the name,
351      so don't print an additional pair of ()'s.  */
352 
353   demangled_args = varstring != NULL && strchr (varstring, '(') != NULL;
354   c_type_print_varspec_suffix (type, stream, show, 0, demangled_args, flags);
355 }
356