/* Character set conversion support for GDB.
- Copyright (C) 2001-2016 Free Software Foundation, Inc.
+ Copyright (C) 2001-2020 Free Software Foundation, Inc.
This file is part of GDB.
#include "charset.h"
#include "gdbcmd.h"
#include "gdb_obstack.h"
-#include "gdb_wait.h"
+#include "gdbsupport/gdb_wait.h"
#include "charset-list.h"
-#include "vec.h"
-#include "environ.h"
+#include "gdbsupport/environ.h"
#include "arch-utils.h"
-#include "gdb_vecs.h"
+#include "gdbsupport/gdb_vecs.h"
#include <ctype.h>
#ifdef USE_WIN32API
static void
set_be_le_names (struct gdbarch *gdbarch)
{
- int i, len;
- const char *target_wide;
-
if (be_le_arch == gdbarch)
return;
be_le_arch = gdbarch;
target_wide_charset_le_name = "UTF-32LE";
target_wide_charset_be_name = "UTF-32BE";
#else
+ int i, len;
+ const char *target_wide;
+
target_wide_charset_le_name = NULL;
target_wide_charset_be_name = NULL;
/* This is the sfunc for the 'set charset' command. */
static void
-set_charset_sfunc (char *charset, int from_tty,
+set_charset_sfunc (const char *charset, int from_tty,
struct cmd_list_element *c)
{
/* CAREFUL: set the target charset here as well. */
/* 'set host-charset' command sfunc. We need a wrapper here because
the function needs to have a specific signature. */
static void
-set_host_charset_sfunc (char *charset, int from_tty,
+set_host_charset_sfunc (const char *charset, int from_tty,
struct cmd_list_element *c)
{
validate (get_current_arch ());
/* Wrapper for the 'set target-charset' command. */
static void
-set_target_charset_sfunc (char *charset, int from_tty,
+set_target_charset_sfunc (const char *charset, int from_tty,
struct cmd_list_element *c)
{
validate (get_current_arch ());
/* Wrapper for the 'set target-wide-charset' command. */
static void
-set_target_wide_charset_sfunc (char *charset, int from_tty,
+set_target_wide_charset_sfunc (const char *charset, int from_tty,
struct cmd_list_element *c)
{
validate (get_current_arch ());
\f
/* Public character management functions. */
-/* A cleanup function which is run to close an iconv descriptor. */
-
-static void
-cleanup_iconv (void *p)
+class iconv_wrapper
{
- iconv_t *descp = (iconv_t *) p;
- iconv_close (*descp);
-}
+public:
+
+ iconv_wrapper (const char *to, const char *from)
+ {
+ m_desc = iconv_open (to, from);
+ if (m_desc == (iconv_t) -1)
+ perror_with_name (_("Converting character sets"));
+ }
+
+ ~iconv_wrapper ()
+ {
+ iconv_close (m_desc);
+ }
+
+ size_t convert (ICONV_CONST char **inp, size_t *inleft, char **outp,
+ size_t *outleft)
+ {
+ return iconv (m_desc, inp, inleft, outp, outleft);
+ }
+
+private:
+
+ iconv_t m_desc;
+};
void
convert_between_encodings (const char *from, const char *to,
int width, struct obstack *output,
enum transliterations translit)
{
- iconv_t desc;
- struct cleanup *cleanups;
size_t inleft;
ICONV_CONST char *inp;
unsigned int space_request;
return;
}
- desc = iconv_open (to, from);
- if (desc == (iconv_t) -1)
- perror_with_name (_("Converting character sets"));
- cleanups = make_cleanup (cleanup_iconv, &desc);
+ iconv_wrapper desc (to, from);
inleft = num_bytes;
inp = (ICONV_CONST char *) bytes;
outp = (char *) obstack_base (output) + old_size;
outleft = space_request;
- r = iconv (desc, &inp, &inleft, &outp, &outleft);
+ r = desc.convert (&inp, &inleft, &outp, &outleft);
/* Now make sure that the object on the obstack only includes
bytes we have converted. */
- obstack_blank_fast (output, -outleft);
+ obstack_blank_fast (output, -(ssize_t) outleft);
if (r == (size_t) -1)
{
}
}
}
-
- do_cleanups (cleanups);
}
\f
++out_request;
if (out_request > m_out.size ())
- m_out.reserve (out_request);
+ m_out.resize (out_request);
continue;
case EINVAL:
return -1;
}
-\f
-/* The charset.c module initialization function. */
+struct charset_vector
+{
+ ~charset_vector ()
+ {
+ clear ();
+ }
-extern initialize_file_ftype _initialize_charset; /* -Wmissing-prototype */
+ void clear ()
+ {
+ for (char *c : charsets)
+ xfree (c);
-static VEC (char_ptr) *charsets;
+ charsets.clear ();
+ }
+
+ std::vector<char *> charsets;
+};
+
+static charset_vector charsets;
#ifdef PHONY_ICONV
static void
find_charset_names (void)
{
- VEC_safe_push (char_ptr, charsets, GDB_DEFAULT_HOST_CHARSET);
- VEC_safe_push (char_ptr, charsets, NULL);
+ charsets.charsets.push_back (xstrdup (GDB_DEFAULT_HOST_CHARSET));
+ charsets.charsets.push_back (NULL);
}
#else /* PHONY_ICONV */
unsigned int i;
for (i = 0; i < count; ++i)
- VEC_safe_push (char_ptr, charsets, xstrdup (names[i]));
+ charsets.charsets.push_back (xstrdup (names[i]));
return 0;
}
find_charset_names (void)
{
iconvlist (add_one, NULL);
- VEC_safe_push (char_ptr, charsets, NULL);
+
+ charsets.charsets.push_back (NULL);
}
#else
find_charset_names (void)
{
struct pex_obj *child;
- char *args[3];
+ const char *args[3];
int err, status;
int fail = 1;
int flags;
- struct gdb_environ *iconv_env;
+ gdb_environ iconv_env = gdb_environ::from_host_environ ();
char *iconv_program;
/* Older iconvs, e.g. 2.2.2, don't omit the intro text if stdout is
not a tty. We need to recognize it and ignore it. This text is
subject to translation, so force LANGUAGE=C. */
- iconv_env = make_environ ();
- init_environ (iconv_env);
- set_in_environ (iconv_env, "LANGUAGE", "C");
- set_in_environ (iconv_env, "LC_ALL", "C");
+ iconv_env.set ("LANGUAGE", "C");
+ iconv_env.set ("LC_ALL", "C");
child = pex_init (PEX_USE_PIPES, "iconv", NULL);
#ifdef ICONV_BIN
{
- char *iconv_dir = relocate_gdb_directory (ICONV_BIN,
- ICONV_BIN_RELOCATABLE);
- iconv_program = concat (iconv_dir, SLASH_STRING, "iconv", NULL);
- xfree (iconv_dir);
+ std::string iconv_dir = relocate_gdb_directory (ICONV_BIN,
+ ICONV_BIN_RELOCATABLE);
+ iconv_program = concat (iconv_dir.c_str(), SLASH_STRING, "iconv", NULL);
}
#else
iconv_program = xstrdup ("iconv");
#endif
/* Note that we simply ignore errors here. */
if (!pex_run_in_environment (child, flags,
- args[0], args, environ_vector (iconv_env),
+ args[0], const_cast<char **> (args),
+ iconv_env.envp (),
NULL, NULL, &err))
{
FILE *in = pex_read_output (child, 0);
break;
keep_going = *p;
*p = '\0';
- VEC_safe_push (char_ptr, charsets, xstrdup (start));
+ charsets.charsets.push_back (xstrdup (start));
if (!keep_going)
break;
/* Skip any extra spaces. */
xfree (iconv_program);
pex_free (child);
- free_environ (iconv_env);
if (fail)
{
/* Some error occurred, so drop the vector. */
- free_char_ptr_vec (charsets);
- charsets = NULL;
+ charsets.clear ();
}
else
- VEC_safe_push (char_ptr, charsets, NULL);
+ charsets.charsets.push_back (NULL);
}
#endif /* HAVE_ICONVLIST || HAVE_LIBICONVLIST */
#define ENDIAN_SUFFIX "LE"
#endif
-/* The code below serves to generate a compile time error if
- gdb_wchar_t type is not of size 2 nor 4, despite the fact that
- macro __STDC_ISO_10646__ is defined.
- This is better than a gdb_assert call, because GDB cannot handle
- strings correctly if this size is different. */
+/* GDB cannot handle strings correctly if this size is different. */
-extern char your_gdb_wchar_t_is_bogus[(sizeof (gdb_wchar_t) == 2
- || sizeof (gdb_wchar_t) == 4)
- ? 1 : -1];
+gdb_static_assert (sizeof (gdb_wchar_t) == 2 || sizeof (gdb_wchar_t) == 4);
/* intermediate_encoding returns the charset used internally by
GDB to convert between target and host encodings. As the test above
_initialize_charset (void)
{
/* The first element is always "auto". */
- VEC_safe_push (char_ptr, charsets, xstrdup ("auto"));
+ charsets.charsets.push_back (xstrdup ("auto"));
find_charset_names ();
- if (VEC_length (char_ptr, charsets) > 1)
- charset_enum = (const char **) VEC_address (char_ptr, charsets);
+ if (charsets.charsets.size () > 1)
+ charset_enum = (const char **) charsets.charsets.data ();
else
charset_enum = default_charset_names;