xref: /netbsd-src/external/gpl3/gdb.old/dist/gdbsupport/common-utils.cc (revision 6881a4007f077b54e5f51159c52b9b25f57deb0d)
17d62b00eSchristos /* Shared general utility routines for GDB, the GNU debugger.
27d62b00eSchristos 
3*6881a400Schristos    Copyright (C) 1986-2023 Free Software Foundation, Inc.
47d62b00eSchristos 
57d62b00eSchristos    This file is part of GDB.
67d62b00eSchristos 
77d62b00eSchristos    This program is free software; you can redistribute it and/or modify
87d62b00eSchristos    it under the terms of the GNU General Public License as published by
97d62b00eSchristos    the Free Software Foundation; either version 3 of the License, or
107d62b00eSchristos    (at your option) any later version.
117d62b00eSchristos 
127d62b00eSchristos    This program is distributed in the hope that it will be useful,
137d62b00eSchristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
147d62b00eSchristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
157d62b00eSchristos    GNU General Public License for more details.
167d62b00eSchristos 
177d62b00eSchristos    You should have received a copy of the GNU General Public License
187d62b00eSchristos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
197d62b00eSchristos 
207d62b00eSchristos #include "common-defs.h"
217d62b00eSchristos #include "common-utils.h"
227d62b00eSchristos #include "host-defs.h"
23*6881a400Schristos #include "safe-ctype.h"
24*6881a400Schristos #include "gdbsupport/gdb-xfree.h"
257d62b00eSchristos 
267d62b00eSchristos void *
277d62b00eSchristos xzalloc (size_t size)
287d62b00eSchristos {
297d62b00eSchristos   return xcalloc (1, size);
307d62b00eSchristos }
317d62b00eSchristos 
327d62b00eSchristos /* Like asprintf/vasprintf but get an internal_error if the call
337d62b00eSchristos    fails. */
347d62b00eSchristos 
35*6881a400Schristos gdb::unique_xmalloc_ptr<char>
367d62b00eSchristos xstrprintf (const char *format, ...)
377d62b00eSchristos {
387d62b00eSchristos   va_list args;
397d62b00eSchristos 
407d62b00eSchristos   va_start (args, format);
41*6881a400Schristos   gdb::unique_xmalloc_ptr<char> ret = xstrvprintf (format, args);
427d62b00eSchristos   va_end (args);
437d62b00eSchristos   return ret;
447d62b00eSchristos }
457d62b00eSchristos 
46*6881a400Schristos gdb::unique_xmalloc_ptr<char>
477d62b00eSchristos xstrvprintf (const char *format, va_list ap)
487d62b00eSchristos {
497d62b00eSchristos   char *ret = NULL;
507d62b00eSchristos   int status = vasprintf (&ret, format, ap);
517d62b00eSchristos 
527d62b00eSchristos   /* NULL is returned when there was a memory allocation problem, or
537d62b00eSchristos      any other error (for instance, a bad format string).  A negative
547d62b00eSchristos      status (the printed length) with a non-NULL buffer should never
557d62b00eSchristos      happen, but just to be sure.  */
567d62b00eSchristos   if (ret == NULL || status < 0)
57*6881a400Schristos     internal_error (_("vasprintf call failed"));
58*6881a400Schristos   return gdb::unique_xmalloc_ptr<char> (ret);
597d62b00eSchristos }
607d62b00eSchristos 
617d62b00eSchristos int
627d62b00eSchristos xsnprintf (char *str, size_t size, const char *format, ...)
637d62b00eSchristos {
647d62b00eSchristos   va_list args;
657d62b00eSchristos   int ret;
667d62b00eSchristos 
677d62b00eSchristos   va_start (args, format);
687d62b00eSchristos   ret = vsnprintf (str, size, format, args);
697d62b00eSchristos   gdb_assert (ret < size);
707d62b00eSchristos   va_end (args);
717d62b00eSchristos 
727d62b00eSchristos   return ret;
737d62b00eSchristos }
747d62b00eSchristos 
757d62b00eSchristos /* See documentation in common-utils.h.  */
767d62b00eSchristos 
777d62b00eSchristos std::string
787d62b00eSchristos string_printf (const char* fmt, ...)
797d62b00eSchristos {
807d62b00eSchristos   va_list vp;
817d62b00eSchristos   int size;
827d62b00eSchristos 
837d62b00eSchristos   va_start (vp, fmt);
847d62b00eSchristos   size = vsnprintf (NULL, 0, fmt, vp);
857d62b00eSchristos   va_end (vp);
867d62b00eSchristos 
877d62b00eSchristos   std::string str (size, '\0');
887d62b00eSchristos 
897d62b00eSchristos   /* C++11 and later guarantee std::string uses contiguous memory and
907d62b00eSchristos      always includes the terminating '\0'.  */
917d62b00eSchristos   va_start (vp, fmt);
927d62b00eSchristos   vsprintf (&str[0], fmt, vp);	/* ARI: vsprintf */
937d62b00eSchristos   va_end (vp);
947d62b00eSchristos 
957d62b00eSchristos   return str;
967d62b00eSchristos }
977d62b00eSchristos 
987d62b00eSchristos /* See documentation in common-utils.h.  */
997d62b00eSchristos 
1007d62b00eSchristos std::string
1017d62b00eSchristos string_vprintf (const char* fmt, va_list args)
1027d62b00eSchristos {
1037d62b00eSchristos   va_list vp;
1047d62b00eSchristos   size_t size;
1057d62b00eSchristos 
1067d62b00eSchristos   va_copy (vp, args);
1077d62b00eSchristos   size = vsnprintf (NULL, 0, fmt, vp);
1087d62b00eSchristos   va_end (vp);
1097d62b00eSchristos 
1107d62b00eSchristos   std::string str (size, '\0');
1117d62b00eSchristos 
1127d62b00eSchristos   /* C++11 and later guarantee std::string uses contiguous memory and
1137d62b00eSchristos      always includes the terminating '\0'.  */
1147d62b00eSchristos   vsprintf (&str[0], fmt, args); /* ARI: vsprintf */
1157d62b00eSchristos 
1167d62b00eSchristos   return str;
1177d62b00eSchristos }
1187d62b00eSchristos 
1197d62b00eSchristos 
1207d62b00eSchristos /* See documentation in common-utils.h.  */
1217d62b00eSchristos 
122*6881a400Schristos std::string &
1237d62b00eSchristos string_appendf (std::string &str, const char *fmt, ...)
1247d62b00eSchristos {
1257d62b00eSchristos   va_list vp;
1267d62b00eSchristos 
1277d62b00eSchristos   va_start (vp, fmt);
1287d62b00eSchristos   string_vappendf (str, fmt, vp);
1297d62b00eSchristos   va_end (vp);
130*6881a400Schristos 
131*6881a400Schristos   return str;
1327d62b00eSchristos }
1337d62b00eSchristos 
1347d62b00eSchristos 
1357d62b00eSchristos /* See documentation in common-utils.h.  */
1367d62b00eSchristos 
137*6881a400Schristos std::string &
1387d62b00eSchristos string_vappendf (std::string &str, const char *fmt, va_list args)
1397d62b00eSchristos {
1407d62b00eSchristos   va_list vp;
1417d62b00eSchristos   int grow_size;
1427d62b00eSchristos 
1437d62b00eSchristos   va_copy (vp, args);
1447d62b00eSchristos   grow_size = vsnprintf (NULL, 0, fmt, vp);
1457d62b00eSchristos   va_end (vp);
1467d62b00eSchristos 
1477d62b00eSchristos   size_t curr_size = str.size ();
1487d62b00eSchristos   str.resize (curr_size + grow_size);
1497d62b00eSchristos 
1507d62b00eSchristos   /* C++11 and later guarantee std::string uses contiguous memory and
1517d62b00eSchristos      always includes the terminating '\0'.  */
1527d62b00eSchristos   vsprintf (&str[curr_size], fmt, args); /* ARI: vsprintf */
153*6881a400Schristos 
154*6881a400Schristos   return str;
1557d62b00eSchristos }
1567d62b00eSchristos 
1577d62b00eSchristos char *
1587d62b00eSchristos savestring (const char *ptr, size_t len)
1597d62b00eSchristos {
1607d62b00eSchristos   char *p = (char *) xmalloc (len + 1);
1617d62b00eSchristos 
1627d62b00eSchristos   memcpy (p, ptr, len);
1637d62b00eSchristos   p[len] = 0;
1647d62b00eSchristos   return p;
1657d62b00eSchristos }
1667d62b00eSchristos 
1677d62b00eSchristos /* See documentation in common-utils.h.  */
1687d62b00eSchristos 
1697d62b00eSchristos std::string
1707d62b00eSchristos extract_string_maybe_quoted (const char **arg)
1717d62b00eSchristos {
1727d62b00eSchristos   bool squote = false;
1737d62b00eSchristos   bool dquote = false;
1747d62b00eSchristos   bool bsquote = false;
1757d62b00eSchristos   std::string result;
1767d62b00eSchristos   const char *p = *arg;
1777d62b00eSchristos 
1787d62b00eSchristos   /* Find the start of the argument.  */
1797d62b00eSchristos   p = skip_spaces (p);
1807d62b00eSchristos 
1817d62b00eSchristos   /* Parse p similarly to gdb_argv buildargv function.  */
1827d62b00eSchristos   while (*p != '\0')
1837d62b00eSchristos     {
184*6881a400Schristos       if (ISSPACE (*p) && !squote && !dquote && !bsquote)
1857d62b00eSchristos 	break;
1867d62b00eSchristos       else
1877d62b00eSchristos 	{
1887d62b00eSchristos 	  if (bsquote)
1897d62b00eSchristos 	    {
1907d62b00eSchristos 	      bsquote = false;
1917d62b00eSchristos 	      result += *p;
1927d62b00eSchristos 	    }
1937d62b00eSchristos 	  else if (*p == '\\')
1947d62b00eSchristos 	    bsquote = true;
1957d62b00eSchristos 	  else if (squote)
1967d62b00eSchristos 	    {
1977d62b00eSchristos 	      if (*p == '\'')
1987d62b00eSchristos 		squote = false;
1997d62b00eSchristos 	      else
2007d62b00eSchristos 		result += *p;
2017d62b00eSchristos 	    }
2027d62b00eSchristos 	  else if (dquote)
2037d62b00eSchristos 	    {
2047d62b00eSchristos 	      if (*p == '"')
2057d62b00eSchristos 		dquote = false;
2067d62b00eSchristos 	      else
2077d62b00eSchristos 		result += *p;
2087d62b00eSchristos 	    }
2097d62b00eSchristos 	  else
2107d62b00eSchristos 	    {
2117d62b00eSchristos 	      if (*p == '\'')
2127d62b00eSchristos 		squote = true;
2137d62b00eSchristos 	      else if (*p == '"')
2147d62b00eSchristos 		dquote = true;
2157d62b00eSchristos 	      else
2167d62b00eSchristos 		result += *p;
2177d62b00eSchristos 	    }
2187d62b00eSchristos 	  p++;
2197d62b00eSchristos 	}
2207d62b00eSchristos     }
2217d62b00eSchristos 
2227d62b00eSchristos   *arg = p;
2237d62b00eSchristos   return result;
2247d62b00eSchristos }
2257d62b00eSchristos 
2267d62b00eSchristos /* The bit offset of the highest byte in a ULONGEST, for overflow
2277d62b00eSchristos    checking.  */
2287d62b00eSchristos 
2297d62b00eSchristos #define HIGH_BYTE_POSN ((sizeof (ULONGEST) - 1) * HOST_CHAR_BIT)
2307d62b00eSchristos 
2317d62b00eSchristos /* True (non-zero) iff DIGIT is a valid digit in radix BASE,
2327d62b00eSchristos    where 2 <= BASE <= 36.  */
2337d62b00eSchristos 
2347d62b00eSchristos static int
2357d62b00eSchristos is_digit_in_base (unsigned char digit, int base)
2367d62b00eSchristos {
237*6881a400Schristos   if (!ISALNUM (digit))
2387d62b00eSchristos     return 0;
2397d62b00eSchristos   if (base <= 10)
240*6881a400Schristos     return (ISDIGIT (digit) && digit < base + '0');
2417d62b00eSchristos   else
242*6881a400Schristos     return (ISDIGIT (digit) || TOLOWER (digit) < base - 10 + 'a');
2437d62b00eSchristos }
2447d62b00eSchristos 
2457d62b00eSchristos static int
2467d62b00eSchristos digit_to_int (unsigned char c)
2477d62b00eSchristos {
248*6881a400Schristos   if (ISDIGIT (c))
2497d62b00eSchristos     return c - '0';
2507d62b00eSchristos   else
251*6881a400Schristos     return TOLOWER (c) - 'a' + 10;
2527d62b00eSchristos }
2537d62b00eSchristos 
2547d62b00eSchristos /* As for strtoul, but for ULONGEST results.  */
2557d62b00eSchristos 
2567d62b00eSchristos ULONGEST
2577d62b00eSchristos strtoulst (const char *num, const char **trailer, int base)
2587d62b00eSchristos {
2597d62b00eSchristos   unsigned int high_part;
2607d62b00eSchristos   ULONGEST result;
2617d62b00eSchristos   int minus = 0;
2627d62b00eSchristos   int i = 0;
2637d62b00eSchristos 
2647d62b00eSchristos   /* Skip leading whitespace.  */
265*6881a400Schristos   while (ISSPACE (num[i]))
2667d62b00eSchristos     i++;
2677d62b00eSchristos 
2687d62b00eSchristos   /* Handle prefixes.  */
2697d62b00eSchristos   if (num[i] == '+')
2707d62b00eSchristos     i++;
2717d62b00eSchristos   else if (num[i] == '-')
2727d62b00eSchristos     {
2737d62b00eSchristos       minus = 1;
2747d62b00eSchristos       i++;
2757d62b00eSchristos     }
2767d62b00eSchristos 
2777d62b00eSchristos   if (base == 0 || base == 16)
2787d62b00eSchristos     {
2797d62b00eSchristos       if (num[i] == '0' && (num[i + 1] == 'x' || num[i + 1] == 'X'))
2807d62b00eSchristos 	{
2817d62b00eSchristos 	  i += 2;
2827d62b00eSchristos 	  if (base == 0)
2837d62b00eSchristos 	    base = 16;
2847d62b00eSchristos 	}
2857d62b00eSchristos     }
2867d62b00eSchristos 
2877d62b00eSchristos   if (base == 0 && num[i] == '0')
2887d62b00eSchristos     base = 8;
2897d62b00eSchristos 
2907d62b00eSchristos   if (base == 0)
2917d62b00eSchristos     base = 10;
2927d62b00eSchristos 
2937d62b00eSchristos   if (base < 2 || base > 36)
2947d62b00eSchristos     {
2957d62b00eSchristos       errno = EINVAL;
2967d62b00eSchristos       return 0;
2977d62b00eSchristos     }
2987d62b00eSchristos 
2997d62b00eSchristos   result = high_part = 0;
3007d62b00eSchristos   for (; is_digit_in_base (num[i], base); i += 1)
3017d62b00eSchristos     {
3027d62b00eSchristos       result = result * base + digit_to_int (num[i]);
3037d62b00eSchristos       high_part = high_part * base + (unsigned int) (result >> HIGH_BYTE_POSN);
3047d62b00eSchristos       result &= ((ULONGEST) 1 << HIGH_BYTE_POSN) - 1;
3057d62b00eSchristos       if (high_part > 0xff)
3067d62b00eSchristos 	{
3077d62b00eSchristos 	  errno = ERANGE;
3087d62b00eSchristos 	  result = ~ (ULONGEST) 0;
3097d62b00eSchristos 	  high_part = 0;
3107d62b00eSchristos 	  minus = 0;
3117d62b00eSchristos 	  break;
3127d62b00eSchristos 	}
3137d62b00eSchristos     }
3147d62b00eSchristos 
3157d62b00eSchristos   if (trailer != NULL)
3167d62b00eSchristos     *trailer = &num[i];
3177d62b00eSchristos 
3187d62b00eSchristos   result = result + ((ULONGEST) high_part << HIGH_BYTE_POSN);
3197d62b00eSchristos   if (minus)
3207d62b00eSchristos     return -result;
3217d62b00eSchristos   else
3227d62b00eSchristos     return result;
3237d62b00eSchristos }
3247d62b00eSchristos 
3257d62b00eSchristos /* See documentation in common-utils.h.  */
3267d62b00eSchristos 
3277d62b00eSchristos char *
3287d62b00eSchristos skip_spaces (char *chp)
3297d62b00eSchristos {
3307d62b00eSchristos   if (chp == NULL)
3317d62b00eSchristos     return NULL;
332*6881a400Schristos   while (*chp && ISSPACE (*chp))
3337d62b00eSchristos     chp++;
3347d62b00eSchristos   return chp;
3357d62b00eSchristos }
3367d62b00eSchristos 
3377d62b00eSchristos /* A const-correct version of the above.  */
3387d62b00eSchristos 
3397d62b00eSchristos const char *
3407d62b00eSchristos skip_spaces (const char *chp)
3417d62b00eSchristos {
3427d62b00eSchristos   if (chp == NULL)
3437d62b00eSchristos     return NULL;
344*6881a400Schristos   while (*chp && ISSPACE (*chp))
3457d62b00eSchristos     chp++;
3467d62b00eSchristos   return chp;
3477d62b00eSchristos }
3487d62b00eSchristos 
3497d62b00eSchristos /* See documentation in common-utils.h.  */
3507d62b00eSchristos 
3517d62b00eSchristos const char *
3527d62b00eSchristos skip_to_space (const char *chp)
3537d62b00eSchristos {
3547d62b00eSchristos   if (chp == NULL)
3557d62b00eSchristos     return NULL;
356*6881a400Schristos   while (*chp && !ISSPACE (*chp))
3577d62b00eSchristos     chp++;
3587d62b00eSchristos   return chp;
3597d62b00eSchristos }
3607d62b00eSchristos 
3617d62b00eSchristos /* See documentation in common-utils.h.  */
3627d62b00eSchristos 
3637d62b00eSchristos char *
3647d62b00eSchristos skip_to_space (char *chp)
3657d62b00eSchristos {
3667d62b00eSchristos   return (char *) skip_to_space ((const char *) chp);
3677d62b00eSchristos }
3687d62b00eSchristos 
3697d62b00eSchristos /* See gdbsupport/common-utils.h.  */
3707d62b00eSchristos 
3717d62b00eSchristos void
3727d62b00eSchristos free_vector_argv (std::vector<char *> &v)
3737d62b00eSchristos {
3747d62b00eSchristos   for (char *el : v)
3757d62b00eSchristos     xfree (el);
3767d62b00eSchristos 
3777d62b00eSchristos   v.clear ();
3787d62b00eSchristos }
3797d62b00eSchristos 
3807d62b00eSchristos /* See gdbsupport/common-utils.h.  */
3817d62b00eSchristos 
3827d62b00eSchristos ULONGEST
3837d62b00eSchristos align_up (ULONGEST v, int n)
3847d62b00eSchristos {
3857d62b00eSchristos   /* Check that N is really a power of two.  */
3867d62b00eSchristos   gdb_assert (n && (n & (n-1)) == 0);
3877d62b00eSchristos   return (v + n - 1) & -n;
3887d62b00eSchristos }
3897d62b00eSchristos 
3907d62b00eSchristos /* See gdbsupport/common-utils.h.  */
3917d62b00eSchristos 
3927d62b00eSchristos ULONGEST
3937d62b00eSchristos align_down (ULONGEST v, int n)
3947d62b00eSchristos {
3957d62b00eSchristos   /* Check that N is really a power of two.  */
3967d62b00eSchristos   gdb_assert (n && (n & (n-1)) == 0);
3977d62b00eSchristos   return (v & -n);
3987d62b00eSchristos }
399*6881a400Schristos 
400*6881a400Schristos /* See gdbsupport/common-utils.h.  */
401*6881a400Schristos 
402*6881a400Schristos int
403*6881a400Schristos fromhex (int a)
404*6881a400Schristos {
405*6881a400Schristos   if (a >= '0' && a <= '9')
406*6881a400Schristos     return a - '0';
407*6881a400Schristos   else if (a >= 'a' && a <= 'f')
408*6881a400Schristos     return a - 'a' + 10;
409*6881a400Schristos   else if (a >= 'A' && a <= 'F')
410*6881a400Schristos     return a - 'A' + 10;
411*6881a400Schristos   else
412*6881a400Schristos     error (_("Invalid hex digit %d"), a);
413*6881a400Schristos }
414*6881a400Schristos 
415*6881a400Schristos /* See gdbsupport/common-utils.h.  */
416*6881a400Schristos 
417*6881a400Schristos int
418*6881a400Schristos hex2bin (const char *hex, gdb_byte *bin, int count)
419*6881a400Schristos {
420*6881a400Schristos   int i;
421*6881a400Schristos 
422*6881a400Schristos   for (i = 0; i < count; i++)
423*6881a400Schristos     {
424*6881a400Schristos       if (hex[0] == 0 || hex[1] == 0)
425*6881a400Schristos 	{
426*6881a400Schristos 	  /* Hex string is short, or of uneven length.
427*6881a400Schristos 	     Return the count that has been converted so far.  */
428*6881a400Schristos 	  return i;
429*6881a400Schristos 	}
430*6881a400Schristos       *bin++ = fromhex (hex[0]) * 16 + fromhex (hex[1]);
431*6881a400Schristos       hex += 2;
432*6881a400Schristos     }
433*6881a400Schristos   return i;
434*6881a400Schristos }
435*6881a400Schristos 
436*6881a400Schristos /* See gdbsupport/common-utils.h.  */
437*6881a400Schristos 
438*6881a400Schristos gdb::byte_vector
439*6881a400Schristos hex2bin (const char *hex)
440*6881a400Schristos {
441*6881a400Schristos   size_t bin_len = strlen (hex) / 2;
442*6881a400Schristos   gdb::byte_vector bin (bin_len);
443*6881a400Schristos 
444*6881a400Schristos   hex2bin (hex, bin.data (), bin_len);
445*6881a400Schristos 
446*6881a400Schristos   return bin;
447*6881a400Schristos }
448