This commit was generated by cvs2svn to track changes on a CVS vendor
[external/binutils.git] / gdb / jv-typeprint.c
1 /* Support for printing Java types for GDB, the GNU debugger.
2    Copyright 1997, 1998, 1999 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 2 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, write to the Free Software
18    Foundation, Inc., 59 Temple Place - Suite 330,
19    Boston, MA 02111-1307, USA.  */
20
21
22 #include "defs.h"
23 #include "symtab.h"
24 #include "gdbtypes.h"
25 #include "value.h"
26 #include "demangle.h"
27 #include "jv-lang.h"
28 #include "gdb_string.h"
29 #include "typeprint.h"
30 #include "c-lang.h"
31
32 /* Local functions */
33
34 static void java_type_print_base PARAMS ((struct type * type, GDB_FILE * stream, int show, int level));
35
36 static void
37 java_type_print_derivation_info (stream, type)
38      GDB_FILE *stream;
39      struct type *type;
40 {
41   char *name;
42   int i;
43   int n_bases;
44   int prev;
45
46   n_bases = TYPE_N_BASECLASSES (type);
47
48   for (i = 0, prev = 0; i < n_bases; i++)
49     {
50       int kind;
51
52       kind = BASETYPE_VIA_VIRTUAL (type, i) ? 'I' : 'E';
53
54       fputs_filtered (kind == prev ? ", "
55                       : kind == 'I' ? " implements "
56                       : " extends ",
57                       stream);
58       prev = kind;
59       name = type_name_no_tag (TYPE_BASECLASS (type, i));
60
61       fprintf_filtered (stream, "%s", name ? name : "(null)");
62     }
63
64   if (i > 0)
65     fputs_filtered (" ", stream);
66 }
67
68 /* Print the name of the type (or the ultimate pointer target,
69    function value or array element), or the description of a
70    structure or union.
71
72    SHOW positive means print details about the type (e.g. enum values),
73    and print structure elements passing SHOW - 1 for show.
74    SHOW negative means just print the type name or struct tag if there is one.
75    If there is no name, print something sensible but concise like
76    "struct {...}".
77    SHOW zero means just print the type name or struct tag if there is one.
78    If there is no name, print something sensible but not as concise like
79    "struct {int x; int y;}".
80
81    LEVEL is the number of spaces to indent by.
82    We increase it for some recursive calls.  */
83
84 static void
85 java_type_print_base (type, stream, show, level)
86      struct type *type;
87      GDB_FILE *stream;
88      int show;
89      int level;
90 {
91   register int i;
92   register int len;
93   char *mangled_name;
94   char *demangled_name;
95   QUIT;
96
97   wrap_here ("    ");
98
99   if (type == NULL)
100     {
101       fputs_filtered ("<type unknown>", stream);
102       return;
103     }
104
105   /* When SHOW is zero or less, and there is a valid type name, then always
106      just print the type name directly from the type.  */
107
108   if (show <= 0
109       && TYPE_NAME (type) != NULL)
110     {
111       fputs_filtered (TYPE_NAME (type), stream);
112       return;
113     }
114
115   CHECK_TYPEDEF (type);
116
117   switch (TYPE_CODE (type))
118     {
119     case TYPE_CODE_PTR:
120       java_type_print_base (TYPE_TARGET_TYPE (type), stream, show, level);
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           fputs_filtered (name, stream);
128           free (name);
129           break;
130         }
131
132       if (show >= 0)
133         fprintf_filtered (stream, "class ");
134
135       if (TYPE_TAG_NAME (type) != NULL)
136         {
137           fputs_filtered (TYPE_TAG_NAME (type), stream);
138           if (show > 0)
139             fputs_filtered (" ", stream);
140         }
141
142       wrap_here ("    ");
143
144       if (show < 0)
145         {
146           /* If we just printed a tag name, no need to print anything else.  */
147           if (TYPE_TAG_NAME (type) == NULL)
148             fprintf_filtered (stream, "{...}");
149         }
150       else if (show > 0 || TYPE_TAG_NAME (type) == NULL)
151         {
152           java_type_print_derivation_info (stream, type);
153
154           fprintf_filtered (stream, "{\n");
155           if ((TYPE_NFIELDS (type) == 0) && (TYPE_NFN_FIELDS (type) == 0))
156             {
157               if (TYPE_FLAGS (type) & TYPE_FLAG_STUB)
158                 fprintfi_filtered (level + 4, stream, "<incomplete type>\n");
159               else
160                 fprintfi_filtered (level + 4, stream, "<no data fields>\n");
161             }
162
163           /* If there is a base class for this type,
164              do not print the field that it occupies.  */
165
166           len = TYPE_NFIELDS (type);
167           for (i = TYPE_N_BASECLASSES (type); i < len; i++)
168             {
169               QUIT;
170               /* Don't print out virtual function table.  */
171               if (STREQN (TYPE_FIELD_NAME (type, i), "_vptr", 5)
172                   && is_cplus_marker ((TYPE_FIELD_NAME (type, i))[5]))
173                 continue;
174
175               /* Don't print the dummy field "class". */
176               if (STREQN (TYPE_FIELD_NAME (type, i), "class", 5))
177                 continue;
178
179               print_spaces_filtered (level + 4, stream);
180
181               if (HAVE_CPLUS_STRUCT (type))
182                 {
183                   if (TYPE_FIELD_PROTECTED (type, i))
184                     fprintf_filtered (stream, "protected ");
185                   else if (TYPE_FIELD_PRIVATE (type, i))
186                     fprintf_filtered (stream, "private ");
187                   else
188                     fprintf_filtered (stream, "public ");
189                 }
190
191               if (TYPE_FIELD_STATIC (type, i))
192                 fprintf_filtered (stream, "static ");
193
194               java_print_type (TYPE_FIELD_TYPE (type, i),
195                                TYPE_FIELD_NAME (type, i),
196                                stream, show - 1, level + 4);
197
198               fprintf_filtered (stream, ";\n");
199             }
200
201           /* If there are both fields and methods, put a space between. */
202           len = TYPE_NFN_FIELDS (type);
203           if (len)
204             fprintf_filtered (stream, "\n");
205
206           /* Print out the methods */
207
208           for (i = 0; i < len; i++)
209             {
210               struct fn_field *f;
211               int j;
212               char *method_name;
213               char *name;
214               int is_constructor;
215               int n_overloads;
216
217               f = TYPE_FN_FIELDLIST1 (type, i);
218               n_overloads = TYPE_FN_FIELDLIST_LENGTH (type, i);
219               method_name = TYPE_FN_FIELDLIST_NAME (type, i);
220               name = type_name_no_tag (type);
221               is_constructor = name && STREQ (method_name, name);
222
223               for (j = 0; j < n_overloads; j++)
224                 {
225                   char *physname;
226                   int is_full_physname_constructor;
227
228                   physname = TYPE_FN_FIELD_PHYSNAME (f, j);
229
230                   is_full_physname_constructor =
231                     ((physname[0] == '_' && physname[1] == '_'
232                       && strchr ("0123456789Qt", physname[2]))
233                      || STREQN (physname, "__ct__", 6)
234                      || DESTRUCTOR_PREFIX_P (physname)
235                      || STREQN (physname, "__dt__", 6));
236
237                   QUIT;
238
239                   print_spaces_filtered (level + 4, stream);
240
241                   if (TYPE_FN_FIELD_PROTECTED (f, j))
242                     fprintf_filtered (stream, "protected ");
243                   else if (TYPE_FN_FIELD_PRIVATE (f, j))
244                     fprintf_filtered (stream, "private ");
245                   else if (TYPE_FN_FIELD_PUBLIC (f, j))
246                     fprintf_filtered (stream, "public ");
247
248                   if (TYPE_FN_FIELD_ABSTRACT (f, j))
249                     fprintf_filtered (stream, "abstract ");
250                   if (TYPE_FN_FIELD_STATIC (f, j))
251                     fprintf_filtered (stream, "static ");
252                   if (TYPE_FN_FIELD_FINAL (f, j))
253                     fprintf_filtered (stream, "final ");
254                   if (TYPE_FN_FIELD_SYNCHRONIZED (f, j))
255                     fprintf_filtered (stream, "synchronized ");
256                   if (TYPE_FN_FIELD_NATIVE (f, j))
257                     fprintf_filtered (stream, "native ");
258
259                   if (TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (f, j)) == 0)
260                     {
261                       /* Keep GDB from crashing here.  */
262                       fprintf_filtered (stream, "<undefined type> %s;\n",
263                                         TYPE_FN_FIELD_PHYSNAME (f, j));
264                       break;
265                     }
266                   else if (!is_constructor && !is_full_physname_constructor)
267                     {
268                       type_print (TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (f, j)),
269                                   "", stream, -1);
270                       fputs_filtered (" ", stream);
271                     }
272
273                   if (TYPE_FN_FIELD_STUB (f, j))
274                     /* Build something we can demangle.  */
275                     mangled_name = gdb_mangle_name (type, i, j);
276                   else
277                     mangled_name = TYPE_FN_FIELD_PHYSNAME (f, j);
278
279                   demangled_name =
280                     cplus_demangle (mangled_name,
281                                     DMGL_ANSI | DMGL_PARAMS | DMGL_JAVA);
282
283                   if (demangled_name == NULL)
284                     demangled_name = strdup (mangled_name);
285
286                   {
287                     char *demangled_no_class;
288                     char *ptr;
289
290                     ptr = demangled_no_class = demangled_name;
291
292                     while (1)
293                       {
294                         char c;
295
296                         c = *ptr++;
297
298                         if (c == 0 || c == '(')
299                           break;
300                         if (c == '.')
301                           demangled_no_class = ptr;
302                       }
303
304                     fputs_filtered (demangled_no_class, stream);
305                     free (demangled_name);
306                   }
307
308                   if (TYPE_FN_FIELD_STUB (f, j))
309                     free (mangled_name);
310
311                   fprintf_filtered (stream, ";\n");
312                 }
313             }
314
315           fprintfi_filtered (level, stream, "}");
316         }
317       break;
318
319     default:
320       c_type_print_base (type, stream, show, level);
321     }
322 }
323
324 /* LEVEL is the depth to indent lines by.  */
325
326 extern void
327 c_type_print_varspec_suffix PARAMS ((struct type *, GDB_FILE *, int, int, int));
328
329 void
330 java_print_type (type, varstring, stream, show, level)
331      struct type *type;
332      char *varstring;
333      GDB_FILE *stream;
334      int show;
335      int level;
336 {
337   int demangled_args;
338
339   java_type_print_base (type, stream, show, level);
340
341   if (varstring != NULL && *varstring != '\0')
342     {
343       fputs_filtered (" ", stream);
344       fputs_filtered (varstring, stream);
345     }
346
347   /* For demangled function names, we have the arglist as part of the name,
348      so don't print an additional pair of ()'s */
349
350   demangled_args = strchr (varstring, '(') != NULL;
351   c_type_print_varspec_suffix (type, stream, show, 0, demangled_args);
352 }