198944Sobrien/* Generic code for supporting multiple C++ ABI's
2130803Smarcel   Copyright 2001, 2002, 2003 Free Software Foundation, Inc.
398944Sobrien
498944Sobrien   This file is part of GDB.
598944Sobrien
698944Sobrien   This program is free software; you can redistribute it and/or modify
798944Sobrien   it under the terms of the GNU General Public License as published by
898944Sobrien   the Free Software Foundation; either version 2 of the License, or
998944Sobrien   (at your option) any later version.
1098944Sobrien
1198944Sobrien   This program is distributed in the hope that it will be useful,
1298944Sobrien   but WITHOUT ANY WARRANTY; without even the implied warranty of
1398944Sobrien   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1498944Sobrien   GNU General Public License for more details.
1598944Sobrien
1698944Sobrien   You should have received a copy of the GNU General Public License
1798944Sobrien   along with this program; if not, write to the Free Software
1898944Sobrien   Foundation, Inc., 59 Temple Place - Suite 330,
1998944Sobrien   Boston, MA 02111-1307, USA.  */
2098944Sobrien
2198944Sobrien#include "defs.h"
2298944Sobrien#include "value.h"
2398944Sobrien#include "cp-abi.h"
24130803Smarcel#include "command.h"
25130803Smarcel#include "gdbcmd.h"
26130803Smarcel#include "ui-out.h"
2798944Sobrien
28130803Smarcel#include "gdb_string.h"
2998944Sobrien
30130803Smarcelstatic struct cp_abi_ops *find_cp_abi (const char *short_name);
3198944Sobrien
32130803Smarcelstatic struct cp_abi_ops current_cp_abi = { "", NULL };
33130803Smarcelstatic struct cp_abi_ops auto_cp_abi = { "auto", NULL };
3498944Sobrien
35130803Smarcel#define CP_ABI_MAX 8
36130803Smarcelstatic struct cp_abi_ops *cp_abis[CP_ABI_MAX];
37130803Smarcelstatic int num_cp_abis = 0;
38130803Smarcel
3998944Sobrienenum ctor_kinds
4098944Sobrienis_constructor_name (const char *name)
4198944Sobrien{
4298944Sobrien  if ((current_cp_abi.is_constructor_name) == NULL)
4398944Sobrien    error ("ABI doesn't define required function is_constructor_name");
4498944Sobrien  return (*current_cp_abi.is_constructor_name) (name);
4598944Sobrien}
4698944Sobrien
4798944Sobrienenum dtor_kinds
4898944Sobrienis_destructor_name (const char *name)
4998944Sobrien{
5098944Sobrien  if ((current_cp_abi.is_destructor_name) == NULL)
5198944Sobrien    error ("ABI doesn't define required function is_destructor_name");
5298944Sobrien  return (*current_cp_abi.is_destructor_name) (name);
5398944Sobrien}
5498944Sobrien
5598944Sobrienint
5698944Sobrienis_vtable_name (const char *name)
5798944Sobrien{
5898944Sobrien  if ((current_cp_abi.is_vtable_name) == NULL)
5998944Sobrien    error ("ABI doesn't define required function is_vtable_name");
6098944Sobrien  return (*current_cp_abi.is_vtable_name) (name);
6198944Sobrien}
6298944Sobrien
6398944Sobrienint
6498944Sobrienis_operator_name (const char *name)
6598944Sobrien{
6698944Sobrien  if ((current_cp_abi.is_operator_name) == NULL)
6798944Sobrien    error ("ABI doesn't define required function is_operator_name");
6898944Sobrien  return (*current_cp_abi.is_operator_name) (name);
6998944Sobrien}
7098944Sobrien
7198944Sobrienint
7298944Sobrienbaseclass_offset (struct type *type, int index, char *valaddr,
7398944Sobrien		  CORE_ADDR address)
7498944Sobrien{
7598944Sobrien  if (current_cp_abi.baseclass_offset == NULL)
7698944Sobrien    error ("ABI doesn't define required function baseclass_offset");
7798944Sobrien  return (*current_cp_abi.baseclass_offset) (type, index, valaddr, address);
7898944Sobrien}
7998944Sobrien
8098944Sobrienstruct value *
81130803Smarcelvalue_virtual_fn_field (struct value **arg1p, struct fn_field *f, int j,
82130803Smarcel			struct type *type, int offset)
8398944Sobrien{
8498944Sobrien  if ((current_cp_abi.virtual_fn_field) == NULL)
8598944Sobrien    return NULL;
8698944Sobrien  return (*current_cp_abi.virtual_fn_field) (arg1p, f, j, type, offset);
8798944Sobrien}
8898944Sobrien
8998944Sobrienstruct type *
9098944Sobrienvalue_rtti_type (struct value *v, int *full, int *top, int *using_enc)
9198944Sobrien{
9298944Sobrien  if ((current_cp_abi.rtti_type) == NULL)
9398944Sobrien    return NULL;
9498944Sobrien  return (*current_cp_abi.rtti_type) (v, full, top, using_enc);
9598944Sobrien}
9698944Sobrien
97130803Smarcel/* Set the current C++ ABI to SHORT_NAME.  */
98130803Smarcel
99130803Smarcelstatic int
100130803Smarcelswitch_to_cp_abi (const char *short_name)
101130803Smarcel{
102130803Smarcel  struct cp_abi_ops *abi;
103130803Smarcel
104130803Smarcel  abi = find_cp_abi (short_name);
105130803Smarcel  if (abi == NULL)
106130803Smarcel    return 0;
107130803Smarcel
108130803Smarcel  current_cp_abi = *abi;
109130803Smarcel  return 1;
110130803Smarcel}
111130803Smarcel
112130803Smarcel/* Add ABI to the list of supported C++ ABI's.  */
113130803Smarcel
11498944Sobrienint
115130803Smarcelregister_cp_abi (struct cp_abi_ops *abi)
11698944Sobrien{
117130803Smarcel  if (num_cp_abis == CP_ABI_MAX)
118130803Smarcel    internal_error (__FILE__, __LINE__,
119130803Smarcel		    "Too many C++ ABIs, please increase CP_ABI_MAX in cp-abi.c");
120130803Smarcel
12198944Sobrien  cp_abis[num_cp_abis++] = abi;
12298944Sobrien
12398944Sobrien  return 1;
124130803Smarcel}
12598944Sobrien
126130803Smarcel/* Set the ABI to use in "auto" mode to SHORT_NAME.  */
127130803Smarcel
128130803Smarcelvoid
129130803Smarcelset_cp_abi_as_auto_default (const char *short_name)
130130803Smarcel{
131130803Smarcel  char *new_longname, *new_doc;
132130803Smarcel  struct cp_abi_ops *abi = find_cp_abi (short_name);
133130803Smarcel
134130803Smarcel  if (abi == NULL)
135130803Smarcel    internal_error (__FILE__, __LINE__,
136130803Smarcel		    "Cannot find C++ ABI \"%s\" to set it as auto default.",
137130803Smarcel		    short_name);
138130803Smarcel
139130803Smarcel  if (auto_cp_abi.longname != NULL)
140130803Smarcel    xfree ((char *) auto_cp_abi.longname);
141130803Smarcel  if (auto_cp_abi.doc != NULL)
142130803Smarcel    xfree ((char *) auto_cp_abi.doc);
143130803Smarcel
144130803Smarcel  auto_cp_abi = *abi;
145130803Smarcel
146130803Smarcel  auto_cp_abi.shortname = "auto";
147130803Smarcel  new_longname = xmalloc (strlen ("currently ") + 1 + strlen (abi->shortname)
148130803Smarcel			  + 1 + 1);
149130803Smarcel  sprintf (new_longname, "currently \"%s\"", abi->shortname);
150130803Smarcel  auto_cp_abi.longname = new_longname;
151130803Smarcel
152130803Smarcel  new_doc = xmalloc (strlen ("Automatically selected; currently ")
153130803Smarcel		     + 1 + strlen (abi->shortname) + 1 + 1);
154130803Smarcel  sprintf (new_doc, "Automatically selected; currently \"%s\"", abi->shortname);
155130803Smarcel  auto_cp_abi.doc = new_doc;
156130803Smarcel
157130803Smarcel  /* Since we copy the current ABI into current_cp_abi instead of
158130803Smarcel     using a pointer, if auto is currently the default, we need to
159130803Smarcel     reset it.  */
160130803Smarcel  if (strcmp (current_cp_abi.shortname, "auto") == 0)
161130803Smarcel    switch_to_cp_abi ("auto");
16298944Sobrien}
16398944Sobrien
164130803Smarcel/* Return the ABI operations associated with SHORT_NAME.  */
165130803Smarcel
166130803Smarcelstatic struct cp_abi_ops *
167130803Smarcelfind_cp_abi (const char *short_name)
16898944Sobrien{
16998944Sobrien  int i;
170130803Smarcel
17198944Sobrien  for (i = 0; i < num_cp_abis; i++)
172130803Smarcel    if (strcmp (cp_abis[i]->shortname, short_name) == 0)
173130803Smarcel      return cp_abis[i];
174130803Smarcel
175130803Smarcel  return NULL;
17698944Sobrien}
17798944Sobrien
178130803Smarcel/* Display the list of registered C++ ABIs.  */
179130803Smarcel
180130803Smarcelstatic void
181130803Smarcellist_cp_abis (int from_tty)
182130803Smarcel{
183130803Smarcel  struct cleanup *cleanup_chain;
184130803Smarcel  int i;
185130803Smarcel  ui_out_text (uiout, "The available C++ ABIs are:\n");
186130803Smarcel
187130803Smarcel  cleanup_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "cp-abi-list");
188130803Smarcel  for (i = 0; i < num_cp_abis; i++)
189130803Smarcel    {
190130803Smarcel      char pad[14];
191130803Smarcel      int padcount;
192130803Smarcel
193130803Smarcel      ui_out_text (uiout, "  ");
194130803Smarcel      ui_out_field_string (uiout, "cp-abi", cp_abis[i]->shortname);
195130803Smarcel
196130803Smarcel      padcount = 16 - 2 - strlen (cp_abis[i]->shortname);
197130803Smarcel      pad[padcount] = 0;
198130803Smarcel      while (padcount > 0)
199130803Smarcel	pad[--padcount] = ' ';
200130803Smarcel      ui_out_text (uiout, pad);
201130803Smarcel
202130803Smarcel      ui_out_field_string (uiout, "doc", cp_abis[i]->doc);
203130803Smarcel      ui_out_text (uiout, "\n");
204130803Smarcel    }
205130803Smarcel  do_cleanups (cleanup_chain);
206130803Smarcel}
207130803Smarcel
208130803Smarcel/* Set the current C++ ABI, or display the list of options if no
209130803Smarcel   argument is given.  */
210130803Smarcel
211130803Smarcelstatic void
212130803Smarcelset_cp_abi_cmd (char *args, int from_tty)
213130803Smarcel{
214130803Smarcel  if (args == NULL)
215130803Smarcel    {
216130803Smarcel      list_cp_abis (from_tty);
217130803Smarcel      return;
218130803Smarcel    }
219130803Smarcel
220130803Smarcel  if (!switch_to_cp_abi (args))
221130803Smarcel    error ("Could not find \"%s\" in ABI list", args);
222130803Smarcel}
223130803Smarcel
224130803Smarcel/* Show the currently selected C++ ABI.  */
225130803Smarcel
226130803Smarcelstatic void
227130803Smarcelshow_cp_abi_cmd (char *args, int from_tty)
228130803Smarcel{
229130803Smarcel  ui_out_text (uiout, "The currently selected C++ ABI is \"");
230130803Smarcel
231130803Smarcel  ui_out_field_string (uiout, "cp-abi", current_cp_abi.shortname);
232130803Smarcel  ui_out_text (uiout, "\" (");
233130803Smarcel  ui_out_field_string (uiout, "longname", current_cp_abi.longname);
234130803Smarcel  ui_out_text (uiout, ").\n");
235130803Smarcel}
236130803Smarcel
237130803Smarcelextern initialize_file_ftype _initialize_cp_abi; /* -Wmissing-prototypes */
238130803Smarcel
239130803Smarcelvoid
240130803Smarcel_initialize_cp_abi (void)
241130803Smarcel{
242130803Smarcel  register_cp_abi (&auto_cp_abi);
243130803Smarcel  switch_to_cp_abi ("auto");
244130803Smarcel
245130803Smarcel  add_cmd ("cp-abi", class_obscure, set_cp_abi_cmd,
246130803Smarcel	   "Set the ABI used for inspecting C++ objects.\n"
247130803Smarcel	   "\"set cp-abi\" with no arguments will list the available ABIs.",
248130803Smarcel	   &setlist);
249130803Smarcel
250130803Smarcel  add_cmd ("cp-abi", class_obscure, show_cp_abi_cmd,
251130803Smarcel	   "Show the ABI used for inspecting C++ objects.", &showlist);
252130803Smarcel}
253