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