xref: /netbsd-src/external/gpl3/gdb/dist/gdbsupport/common-utils.cc (revision 5ba1f45f2a09259cc846f20c7c5501604d633c90)
18dffb485Schristos /* Shared general utility routines for GDB, the GNU debugger.
28dffb485Schristos 
3*5ba1f45fSchristos    Copyright (C) 1986-2024 Free Software Foundation, Inc.
48dffb485Schristos 
58dffb485Schristos    This file is part of GDB.
68dffb485Schristos 
78dffb485Schristos    This program is free software; you can redistribute it and/or modify
88dffb485Schristos    it under the terms of the GNU General Public License as published by
98dffb485Schristos    the Free Software Foundation; either version 3 of the License, or
108dffb485Schristos    (at your option) any later version.
118dffb485Schristos 
128dffb485Schristos    This program is distributed in the hope that it will be useful,
138dffb485Schristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
148dffb485Schristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
158dffb485Schristos    GNU General Public License for more details.
168dffb485Schristos 
178dffb485Schristos    You should have received a copy of the GNU General Public License
188dffb485Schristos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
198dffb485Schristos 
208dffb485Schristos #include "common-utils.h"
218dffb485Schristos #include "host-defs.h"
22*5ba1f45fSchristos #include "gdbsupport/gdb-safe-ctype.h"
234b169a6bSchristos #include "gdbsupport/gdb-xfree.h"
248dffb485Schristos 
258dffb485Schristos void *
268dffb485Schristos xzalloc (size_t size)
278dffb485Schristos {
288dffb485Schristos   return xcalloc (1, size);
298dffb485Schristos }
308dffb485Schristos 
318dffb485Schristos /* Like asprintf/vasprintf but get an internal_error if the call
328dffb485Schristos    fails. */
338dffb485Schristos 
344b169a6bSchristos gdb::unique_xmalloc_ptr<char>
358dffb485Schristos xstrprintf (const char *format, ...)
368dffb485Schristos {
378dffb485Schristos   va_list args;
388dffb485Schristos 
398dffb485Schristos   va_start (args, format);
404b169a6bSchristos   gdb::unique_xmalloc_ptr<char> ret = xstrvprintf (format, args);
418dffb485Schristos   va_end (args);
428dffb485Schristos   return ret;
438dffb485Schristos }
448dffb485Schristos 
454b169a6bSchristos gdb::unique_xmalloc_ptr<char>
468dffb485Schristos xstrvprintf (const char *format, va_list ap)
478dffb485Schristos {
488dffb485Schristos   char *ret = NULL;
498dffb485Schristos   int status = vasprintf (&ret, format, ap);
508dffb485Schristos 
518dffb485Schristos   /* NULL is returned when there was a memory allocation problem, or
528dffb485Schristos      any other error (for instance, a bad format string).  A negative
538dffb485Schristos      status (the printed length) with a non-NULL buffer should never
548dffb485Schristos      happen, but just to be sure.  */
558dffb485Schristos   if (ret == NULL || status < 0)
564b169a6bSchristos     internal_error (_("vasprintf call failed"));
574b169a6bSchristos   return gdb::unique_xmalloc_ptr<char> (ret);
588dffb485Schristos }
598dffb485Schristos 
608dffb485Schristos int
618dffb485Schristos xsnprintf (char *str, size_t size, const char *format, ...)
628dffb485Schristos {
638dffb485Schristos   va_list args;
648dffb485Schristos   int ret;
658dffb485Schristos 
668dffb485Schristos   va_start (args, format);
678dffb485Schristos   ret = vsnprintf (str, size, format, args);
688dffb485Schristos   gdb_assert (ret < size);
698dffb485Schristos   va_end (args);
708dffb485Schristos 
718dffb485Schristos   return ret;
728dffb485Schristos }
738dffb485Schristos 
748dffb485Schristos /* See documentation in common-utils.h.  */
758dffb485Schristos 
768dffb485Schristos std::string
778dffb485Schristos string_printf (const char* fmt, ...)
788dffb485Schristos {
798dffb485Schristos   va_list vp;
808dffb485Schristos   int size;
818dffb485Schristos 
828dffb485Schristos   va_start (vp, fmt);
838dffb485Schristos   size = vsnprintf (NULL, 0, fmt, vp);
848dffb485Schristos   va_end (vp);
858dffb485Schristos 
868dffb485Schristos   std::string str (size, '\0');
878dffb485Schristos 
888dffb485Schristos   /* C++11 and later guarantee std::string uses contiguous memory and
898dffb485Schristos      always includes the terminating '\0'.  */
908dffb485Schristos   va_start (vp, fmt);
918dffb485Schristos   vsprintf (&str[0], fmt, vp);	/* ARI: vsprintf */
928dffb485Schristos   va_end (vp);
938dffb485Schristos 
948dffb485Schristos   return str;
958dffb485Schristos }
968dffb485Schristos 
978dffb485Schristos /* See documentation in common-utils.h.  */
988dffb485Schristos 
998dffb485Schristos std::string
1008dffb485Schristos string_vprintf (const char* fmt, va_list args)
1018dffb485Schristos {
1028dffb485Schristos   va_list vp;
1038dffb485Schristos   size_t size;
1048dffb485Schristos 
1058dffb485Schristos   va_copy (vp, args);
1068dffb485Schristos   size = vsnprintf (NULL, 0, fmt, vp);
1078dffb485Schristos   va_end (vp);
1088dffb485Schristos 
1098dffb485Schristos   std::string str (size, '\0');
1108dffb485Schristos 
1118dffb485Schristos   /* C++11 and later guarantee std::string uses contiguous memory and
1128dffb485Schristos      always includes the terminating '\0'.  */
1138dffb485Schristos   vsprintf (&str[0], fmt, args); /* ARI: vsprintf */
1148dffb485Schristos 
1158dffb485Schristos   return str;
1168dffb485Schristos }
1178dffb485Schristos 
1188dffb485Schristos 
1198dffb485Schristos /* See documentation in common-utils.h.  */
1208dffb485Schristos 
1214b169a6bSchristos std::string &
1228dffb485Schristos string_appendf (std::string &str, const char *fmt, ...)
1238dffb485Schristos {
1248dffb485Schristos   va_list vp;
1258dffb485Schristos 
1268dffb485Schristos   va_start (vp, fmt);
1278dffb485Schristos   string_vappendf (str, fmt, vp);
1288dffb485Schristos   va_end (vp);
1294b169a6bSchristos 
1304b169a6bSchristos   return str;
1318dffb485Schristos }
1328dffb485Schristos 
1338dffb485Schristos 
1348dffb485Schristos /* See documentation in common-utils.h.  */
1358dffb485Schristos 
1364b169a6bSchristos std::string &
1378dffb485Schristos string_vappendf (std::string &str, const char *fmt, va_list args)
1388dffb485Schristos {
1398dffb485Schristos   va_list vp;
1408dffb485Schristos   int grow_size;
1418dffb485Schristos 
1428dffb485Schristos   va_copy (vp, args);
1438dffb485Schristos   grow_size = vsnprintf (NULL, 0, fmt, vp);
1448dffb485Schristos   va_end (vp);
1458dffb485Schristos 
1468dffb485Schristos   size_t curr_size = str.size ();
1478dffb485Schristos   str.resize (curr_size + grow_size);
1488dffb485Schristos 
1498dffb485Schristos   /* C++11 and later guarantee std::string uses contiguous memory and
1508dffb485Schristos      always includes the terminating '\0'.  */
1518dffb485Schristos   vsprintf (&str[curr_size], fmt, args); /* ARI: vsprintf */
1524b169a6bSchristos 
1534b169a6bSchristos   return str;
1548dffb485Schristos }
1558dffb485Schristos 
1568dffb485Schristos char *
1578dffb485Schristos savestring (const char *ptr, size_t len)
1588dffb485Schristos {
1598dffb485Schristos   char *p = (char *) xmalloc (len + 1);
1608dffb485Schristos 
1618dffb485Schristos   memcpy (p, ptr, len);
1628dffb485Schristos   p[len] = 0;
1638dffb485Schristos   return p;
1648dffb485Schristos }
1658dffb485Schristos 
1668dffb485Schristos /* See documentation in common-utils.h.  */
1678dffb485Schristos 
1688dffb485Schristos std::string
1698dffb485Schristos extract_string_maybe_quoted (const char **arg)
1708dffb485Schristos {
1718dffb485Schristos   bool squote = false;
1728dffb485Schristos   bool dquote = false;
1738dffb485Schristos   bool bsquote = false;
1748dffb485Schristos   std::string result;
1758dffb485Schristos   const char *p = *arg;
1768dffb485Schristos 
1778dffb485Schristos   /* Find the start of the argument.  */
1788dffb485Schristos   p = skip_spaces (p);
1798dffb485Schristos 
1808dffb485Schristos   /* Parse p similarly to gdb_argv buildargv function.  */
1818dffb485Schristos   while (*p != '\0')
1828dffb485Schristos     {
1834b169a6bSchristos       if (ISSPACE (*p) && !squote && !dquote && !bsquote)
1848dffb485Schristos 	break;
1858dffb485Schristos       else
1868dffb485Schristos 	{
1878dffb485Schristos 	  if (bsquote)
1888dffb485Schristos 	    {
1898dffb485Schristos 	      bsquote = false;
1908dffb485Schristos 	      result += *p;
1918dffb485Schristos 	    }
1928dffb485Schristos 	  else if (*p == '\\')
1938dffb485Schristos 	    bsquote = true;
1948dffb485Schristos 	  else if (squote)
1958dffb485Schristos 	    {
1968dffb485Schristos 	      if (*p == '\'')
1978dffb485Schristos 		squote = false;
1988dffb485Schristos 	      else
1998dffb485Schristos 		result += *p;
2008dffb485Schristos 	    }
2018dffb485Schristos 	  else if (dquote)
2028dffb485Schristos 	    {
2038dffb485Schristos 	      if (*p == '"')
2048dffb485Schristos 		dquote = false;
2058dffb485Schristos 	      else
2068dffb485Schristos 		result += *p;
2078dffb485Schristos 	    }
2088dffb485Schristos 	  else
2098dffb485Schristos 	    {
2108dffb485Schristos 	      if (*p == '\'')
2118dffb485Schristos 		squote = true;
2128dffb485Schristos 	      else if (*p == '"')
2138dffb485Schristos 		dquote = true;
2148dffb485Schristos 	      else
2158dffb485Schristos 		result += *p;
2168dffb485Schristos 	    }
2178dffb485Schristos 	  p++;
2188dffb485Schristos 	}
2198dffb485Schristos     }
2208dffb485Schristos 
2218dffb485Schristos   *arg = p;
2228dffb485Schristos   return result;
2238dffb485Schristos }
2248dffb485Schristos 
2258dffb485Schristos /* The bit offset of the highest byte in a ULONGEST, for overflow
2268dffb485Schristos    checking.  */
2278dffb485Schristos 
2288dffb485Schristos #define HIGH_BYTE_POSN ((sizeof (ULONGEST) - 1) * HOST_CHAR_BIT)
2298dffb485Schristos 
2308dffb485Schristos /* True (non-zero) iff DIGIT is a valid digit in radix BASE,
2318dffb485Schristos    where 2 <= BASE <= 36.  */
2328dffb485Schristos 
2338dffb485Schristos static int
2348dffb485Schristos is_digit_in_base (unsigned char digit, int base)
2358dffb485Schristos {
2364b169a6bSchristos   if (!ISALNUM (digit))
2378dffb485Schristos     return 0;
2388dffb485Schristos   if (base <= 10)
2394b169a6bSchristos     return (ISDIGIT (digit) && digit < base + '0');
2408dffb485Schristos   else
2414b169a6bSchristos     return (ISDIGIT (digit) || TOLOWER (digit) < base - 10 + 'a');
2428dffb485Schristos }
2438dffb485Schristos 
2448dffb485Schristos static int
2458dffb485Schristos digit_to_int (unsigned char c)
2468dffb485Schristos {
2474b169a6bSchristos   if (ISDIGIT (c))
2488dffb485Schristos     return c - '0';
2498dffb485Schristos   else
2504b169a6bSchristos     return TOLOWER (c) - 'a' + 10;
2518dffb485Schristos }
2528dffb485Schristos 
2538dffb485Schristos /* As for strtoul, but for ULONGEST results.  */
2548dffb485Schristos 
2558dffb485Schristos ULONGEST
2568dffb485Schristos strtoulst (const char *num, const char **trailer, int base)
2578dffb485Schristos {
2588dffb485Schristos   unsigned int high_part;
2598dffb485Schristos   ULONGEST result;
2608dffb485Schristos   int minus = 0;
2618dffb485Schristos   int i = 0;
2628dffb485Schristos 
2638dffb485Schristos   /* Skip leading whitespace.  */
2644b169a6bSchristos   while (ISSPACE (num[i]))
2658dffb485Schristos     i++;
2668dffb485Schristos 
2678dffb485Schristos   /* Handle prefixes.  */
2688dffb485Schristos   if (num[i] == '+')
2698dffb485Schristos     i++;
2708dffb485Schristos   else if (num[i] == '-')
2718dffb485Schristos     {
2728dffb485Schristos       minus = 1;
2738dffb485Schristos       i++;
2748dffb485Schristos     }
2758dffb485Schristos 
2768dffb485Schristos   if (base == 0 || base == 16)
2778dffb485Schristos     {
2788dffb485Schristos       if (num[i] == '0' && (num[i + 1] == 'x' || num[i + 1] == 'X'))
2798dffb485Schristos 	{
2808dffb485Schristos 	  i += 2;
2818dffb485Schristos 	  if (base == 0)
2828dffb485Schristos 	    base = 16;
2838dffb485Schristos 	}
2848dffb485Schristos     }
2858dffb485Schristos 
2868dffb485Schristos   if (base == 0 && num[i] == '0')
2878dffb485Schristos     base = 8;
2888dffb485Schristos 
2898dffb485Schristos   if (base == 0)
2908dffb485Schristos     base = 10;
2918dffb485Schristos 
2928dffb485Schristos   if (base < 2 || base > 36)
2938dffb485Schristos     {
2948dffb485Schristos       errno = EINVAL;
2958dffb485Schristos       return 0;
2968dffb485Schristos     }
2978dffb485Schristos 
2988dffb485Schristos   result = high_part = 0;
2998dffb485Schristos   for (; is_digit_in_base (num[i], base); i += 1)
3008dffb485Schristos     {
3018dffb485Schristos       result = result * base + digit_to_int (num[i]);
3028dffb485Schristos       high_part = high_part * base + (unsigned int) (result >> HIGH_BYTE_POSN);
3038dffb485Schristos       result &= ((ULONGEST) 1 << HIGH_BYTE_POSN) - 1;
3048dffb485Schristos       if (high_part > 0xff)
3058dffb485Schristos 	{
3068dffb485Schristos 	  errno = ERANGE;
3078dffb485Schristos 	  result = ~ (ULONGEST) 0;
3088dffb485Schristos 	  high_part = 0;
3098dffb485Schristos 	  minus = 0;
3108dffb485Schristos 	  break;
3118dffb485Schristos 	}
3128dffb485Schristos     }
3138dffb485Schristos 
3148dffb485Schristos   if (trailer != NULL)
3158dffb485Schristos     *trailer = &num[i];
3168dffb485Schristos 
3178dffb485Schristos   result = result + ((ULONGEST) high_part << HIGH_BYTE_POSN);
3188dffb485Schristos   if (minus)
3198dffb485Schristos     return -result;
3208dffb485Schristos   else
3218dffb485Schristos     return result;
3228dffb485Schristos }
3238dffb485Schristos 
3248dffb485Schristos /* See documentation in common-utils.h.  */
3258dffb485Schristos 
3268dffb485Schristos char *
3278dffb485Schristos skip_spaces (char *chp)
3288dffb485Schristos {
3298dffb485Schristos   if (chp == NULL)
3308dffb485Schristos     return NULL;
3314b169a6bSchristos   while (*chp && ISSPACE (*chp))
3328dffb485Schristos     chp++;
3338dffb485Schristos   return chp;
3348dffb485Schristos }
3358dffb485Schristos 
3368dffb485Schristos /* A const-correct version of the above.  */
3378dffb485Schristos 
3388dffb485Schristos const char *
3398dffb485Schristos skip_spaces (const char *chp)
3408dffb485Schristos {
3418dffb485Schristos   if (chp == NULL)
3428dffb485Schristos     return NULL;
3434b169a6bSchristos   while (*chp && ISSPACE (*chp))
3448dffb485Schristos     chp++;
3458dffb485Schristos   return chp;
3468dffb485Schristos }
3478dffb485Schristos 
3488dffb485Schristos /* See documentation in common-utils.h.  */
3498dffb485Schristos 
3508dffb485Schristos const char *
3518dffb485Schristos skip_to_space (const char *chp)
3528dffb485Schristos {
3538dffb485Schristos   if (chp == NULL)
3548dffb485Schristos     return NULL;
3554b169a6bSchristos   while (*chp && !ISSPACE (*chp))
3568dffb485Schristos     chp++;
3578dffb485Schristos   return chp;
3588dffb485Schristos }
3598dffb485Schristos 
3608dffb485Schristos /* See documentation in common-utils.h.  */
3618dffb485Schristos 
3628dffb485Schristos char *
3638dffb485Schristos skip_to_space (char *chp)
3648dffb485Schristos {
3658dffb485Schristos   return (char *) skip_to_space ((const char *) chp);
3668dffb485Schristos }
3678dffb485Schristos 
3688dffb485Schristos /* See gdbsupport/common-utils.h.  */
3698dffb485Schristos 
3708dffb485Schristos void
3718dffb485Schristos free_vector_argv (std::vector<char *> &v)
3728dffb485Schristos {
3738dffb485Schristos   for (char *el : v)
3748dffb485Schristos     xfree (el);
3758dffb485Schristos 
3768dffb485Schristos   v.clear ();
3778dffb485Schristos }
3788dffb485Schristos 
3798dffb485Schristos /* See gdbsupport/common-utils.h.  */
3808dffb485Schristos 
3818dffb485Schristos ULONGEST
3828dffb485Schristos align_up (ULONGEST v, int n)
3838dffb485Schristos {
3848dffb485Schristos   /* Check that N is really a power of two.  */
3858dffb485Schristos   gdb_assert (n && (n & (n-1)) == 0);
3868dffb485Schristos   return (v + n - 1) & -n;
3878dffb485Schristos }
3888dffb485Schristos 
3898dffb485Schristos /* See gdbsupport/common-utils.h.  */
3908dffb485Schristos 
3918dffb485Schristos ULONGEST
3928dffb485Schristos align_down (ULONGEST v, int n)
3938dffb485Schristos {
3948dffb485Schristos   /* Check that N is really a power of two.  */
3958dffb485Schristos   gdb_assert (n && (n & (n-1)) == 0);
3968dffb485Schristos   return (v & -n);
3978dffb485Schristos }
3984b169a6bSchristos 
3994b169a6bSchristos /* See gdbsupport/common-utils.h.  */
4004b169a6bSchristos 
4014b169a6bSchristos int
4024b169a6bSchristos fromhex (int a)
4034b169a6bSchristos {
4044b169a6bSchristos   if (a >= '0' && a <= '9')
4054b169a6bSchristos     return a - '0';
4064b169a6bSchristos   else if (a >= 'a' && a <= 'f')
4074b169a6bSchristos     return a - 'a' + 10;
4084b169a6bSchristos   else if (a >= 'A' && a <= 'F')
4094b169a6bSchristos     return a - 'A' + 10;
4104b169a6bSchristos   else
4114b169a6bSchristos     error (_("Invalid hex digit %d"), a);
4124b169a6bSchristos }
4134b169a6bSchristos 
4144b169a6bSchristos /* See gdbsupport/common-utils.h.  */
4154b169a6bSchristos 
4164b169a6bSchristos int
4174b169a6bSchristos hex2bin (const char *hex, gdb_byte *bin, int count)
4184b169a6bSchristos {
4194b169a6bSchristos   int i;
4204b169a6bSchristos 
4214b169a6bSchristos   for (i = 0; i < count; i++)
4224b169a6bSchristos     {
4234b169a6bSchristos       if (hex[0] == 0 || hex[1] == 0)
4244b169a6bSchristos 	{
4254b169a6bSchristos 	  /* Hex string is short, or of uneven length.
4264b169a6bSchristos 	     Return the count that has been converted so far.  */
4274b169a6bSchristos 	  return i;
4284b169a6bSchristos 	}
4294b169a6bSchristos       *bin++ = fromhex (hex[0]) * 16 + fromhex (hex[1]);
4304b169a6bSchristos       hex += 2;
4314b169a6bSchristos     }
4324b169a6bSchristos   return i;
4334b169a6bSchristos }
4344b169a6bSchristos 
4354b169a6bSchristos /* See gdbsupport/common-utils.h.  */
4364b169a6bSchristos 
4374b169a6bSchristos gdb::byte_vector
4384b169a6bSchristos hex2bin (const char *hex)
4394b169a6bSchristos {
4404b169a6bSchristos   size_t bin_len = strlen (hex) / 2;
4414b169a6bSchristos   gdb::byte_vector bin (bin_len);
4424b169a6bSchristos 
4434b169a6bSchristos   hex2bin (hex, bin.data (), bin_len);
4444b169a6bSchristos 
4454b169a6bSchristos   return bin;
4464b169a6bSchristos }
447*5ba1f45fSchristos 
448*5ba1f45fSchristos /* See gdbsupport/common-utils.h.  */
449*5ba1f45fSchristos 
450*5ba1f45fSchristos std::string
451*5ba1f45fSchristos bytes_to_string (gdb::array_view<const gdb_byte> bytes)
452*5ba1f45fSchristos {
453*5ba1f45fSchristos   std::string ret;
454*5ba1f45fSchristos 
455*5ba1f45fSchristos   for (size_t i = 0; i < bytes.size (); i++)
456*5ba1f45fSchristos     {
457*5ba1f45fSchristos       if (i == 0)
458*5ba1f45fSchristos 	ret += string_printf ("%02x", bytes[i]);
459*5ba1f45fSchristos       else
460*5ba1f45fSchristos 	ret += string_printf (" %02x", bytes[i]);
461*5ba1f45fSchristos     }
462*5ba1f45fSchristos 
463*5ba1f45fSchristos   return ret;
464*5ba1f45fSchristos }
465