xref: /netbsd-src/external/gpl3/gdb/dist/gdbsupport/common-utils.cc (revision 32d1c65c71fbdb65a012e8392a62a757dd6853e9)
1 /* Shared general utility routines for GDB, the GNU debugger.
2 
3    Copyright (C) 1986-2024 Free Software Foundation, Inc.
4 
5    This file is part of GDB.
6 
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11 
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16 
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19 
20 #include "common-utils.h"
21 #include "host-defs.h"
22 #include "gdbsupport/gdb-safe-ctype.h"
23 #include "gdbsupport/gdb-xfree.h"
24 
25 void *
26 xzalloc (size_t size)
27 {
28   return xcalloc (1, size);
29 }
30 
31 /* Like asprintf/vasprintf but get an internal_error if the call
32    fails. */
33 
34 gdb::unique_xmalloc_ptr<char>
35 xstrprintf (const char *format, ...)
36 {
37   va_list args;
38 
39   va_start (args, format);
40   gdb::unique_xmalloc_ptr<char> ret = xstrvprintf (format, args);
41   va_end (args);
42   return ret;
43 }
44 
45 gdb::unique_xmalloc_ptr<char>
46 xstrvprintf (const char *format, va_list ap)
47 {
48   char *ret = NULL;
49   int status = vasprintf (&ret, format, ap);
50 
51   /* NULL is returned when there was a memory allocation problem, or
52      any other error (for instance, a bad format string).  A negative
53      status (the printed length) with a non-NULL buffer should never
54      happen, but just to be sure.  */
55   if (ret == NULL || status < 0)
56     internal_error (_("vasprintf call failed"));
57   return gdb::unique_xmalloc_ptr<char> (ret);
58 }
59 
60 int
61 xsnprintf (char *str, size_t size, const char *format, ...)
62 {
63   va_list args;
64   int ret;
65 
66   va_start (args, format);
67   ret = vsnprintf (str, size, format, args);
68   gdb_assert (ret < size);
69   va_end (args);
70 
71   return ret;
72 }
73 
74 /* See documentation in common-utils.h.  */
75 
76 std::string
77 string_printf (const char* fmt, ...)
78 {
79   va_list vp;
80   int size;
81 
82   va_start (vp, fmt);
83   size = vsnprintf (NULL, 0, fmt, vp);
84   va_end (vp);
85 
86   std::string str (size, '\0');
87 
88   /* C++11 and later guarantee std::string uses contiguous memory and
89      always includes the terminating '\0'.  */
90   va_start (vp, fmt);
91   vsprintf (&str[0], fmt, vp);	/* ARI: vsprintf */
92   va_end (vp);
93 
94   return str;
95 }
96 
97 /* See documentation in common-utils.h.  */
98 
99 std::string
100 string_vprintf (const char* fmt, va_list args)
101 {
102   va_list vp;
103   size_t size;
104 
105   va_copy (vp, args);
106   size = vsnprintf (NULL, 0, fmt, vp);
107   va_end (vp);
108 
109   std::string str (size, '\0');
110 
111   /* C++11 and later guarantee std::string uses contiguous memory and
112      always includes the terminating '\0'.  */
113   vsprintf (&str[0], fmt, args); /* ARI: vsprintf */
114 
115   return str;
116 }
117 
118 
119 /* See documentation in common-utils.h.  */
120 
121 std::string &
122 string_appendf (std::string &str, const char *fmt, ...)
123 {
124   va_list vp;
125 
126   va_start (vp, fmt);
127   string_vappendf (str, fmt, vp);
128   va_end (vp);
129 
130   return str;
131 }
132 
133 
134 /* See documentation in common-utils.h.  */
135 
136 std::string &
137 string_vappendf (std::string &str, const char *fmt, va_list args)
138 {
139   va_list vp;
140   int grow_size;
141 
142   va_copy (vp, args);
143   grow_size = vsnprintf (NULL, 0, fmt, vp);
144   va_end (vp);
145 
146   size_t curr_size = str.size ();
147   str.resize (curr_size + grow_size);
148 
149   /* C++11 and later guarantee std::string uses contiguous memory and
150      always includes the terminating '\0'.  */
151   vsprintf (&str[curr_size], fmt, args); /* ARI: vsprintf */
152 
153   return str;
154 }
155 
156 char *
157 savestring (const char *ptr, size_t len)
158 {
159   char *p = (char *) xmalloc (len + 1);
160 
161   memcpy (p, ptr, len);
162   p[len] = 0;
163   return p;
164 }
165 
166 /* See documentation in common-utils.h.  */
167 
168 std::string
169 extract_string_maybe_quoted (const char **arg)
170 {
171   bool squote = false;
172   bool dquote = false;
173   bool bsquote = false;
174   std::string result;
175   const char *p = *arg;
176 
177   /* Find the start of the argument.  */
178   p = skip_spaces (p);
179 
180   /* Parse p similarly to gdb_argv buildargv function.  */
181   while (*p != '\0')
182     {
183       if (ISSPACE (*p) && !squote && !dquote && !bsquote)
184 	break;
185       else
186 	{
187 	  if (bsquote)
188 	    {
189 	      bsquote = false;
190 	      result += *p;
191 	    }
192 	  else if (*p == '\\')
193 	    bsquote = true;
194 	  else if (squote)
195 	    {
196 	      if (*p == '\'')
197 		squote = false;
198 	      else
199 		result += *p;
200 	    }
201 	  else if (dquote)
202 	    {
203 	      if (*p == '"')
204 		dquote = false;
205 	      else
206 		result += *p;
207 	    }
208 	  else
209 	    {
210 	      if (*p == '\'')
211 		squote = true;
212 	      else if (*p == '"')
213 		dquote = true;
214 	      else
215 		result += *p;
216 	    }
217 	  p++;
218 	}
219     }
220 
221   *arg = p;
222   return result;
223 }
224 
225 /* The bit offset of the highest byte in a ULONGEST, for overflow
226    checking.  */
227 
228 #define HIGH_BYTE_POSN ((sizeof (ULONGEST) - 1) * HOST_CHAR_BIT)
229 
230 /* True (non-zero) iff DIGIT is a valid digit in radix BASE,
231    where 2 <= BASE <= 36.  */
232 
233 static int
234 is_digit_in_base (unsigned char digit, int base)
235 {
236   if (!ISALNUM (digit))
237     return 0;
238   if (base <= 10)
239     return (ISDIGIT (digit) && digit < base + '0');
240   else
241     return (ISDIGIT (digit) || TOLOWER (digit) < base - 10 + 'a');
242 }
243 
244 static int
245 digit_to_int (unsigned char c)
246 {
247   if (ISDIGIT (c))
248     return c - '0';
249   else
250     return TOLOWER (c) - 'a' + 10;
251 }
252 
253 /* As for strtoul, but for ULONGEST results.  */
254 
255 ULONGEST
256 strtoulst (const char *num, const char **trailer, int base)
257 {
258   unsigned int high_part;
259   ULONGEST result;
260   int minus = 0;
261   int i = 0;
262 
263   /* Skip leading whitespace.  */
264   while (ISSPACE (num[i]))
265     i++;
266 
267   /* Handle prefixes.  */
268   if (num[i] == '+')
269     i++;
270   else if (num[i] == '-')
271     {
272       minus = 1;
273       i++;
274     }
275 
276   if (base == 0 || base == 16)
277     {
278       if (num[i] == '0' && (num[i + 1] == 'x' || num[i + 1] == 'X'))
279 	{
280 	  i += 2;
281 	  if (base == 0)
282 	    base = 16;
283 	}
284     }
285 
286   if (base == 0 && num[i] == '0')
287     base = 8;
288 
289   if (base == 0)
290     base = 10;
291 
292   if (base < 2 || base > 36)
293     {
294       errno = EINVAL;
295       return 0;
296     }
297 
298   result = high_part = 0;
299   for (; is_digit_in_base (num[i], base); i += 1)
300     {
301       result = result * base + digit_to_int (num[i]);
302       high_part = high_part * base + (unsigned int) (result >> HIGH_BYTE_POSN);
303       result &= ((ULONGEST) 1 << HIGH_BYTE_POSN) - 1;
304       if (high_part > 0xff)
305 	{
306 	  errno = ERANGE;
307 	  result = ~ (ULONGEST) 0;
308 	  high_part = 0;
309 	  minus = 0;
310 	  break;
311 	}
312     }
313 
314   if (trailer != NULL)
315     *trailer = &num[i];
316 
317   result = result + ((ULONGEST) high_part << HIGH_BYTE_POSN);
318   if (minus)
319     return -result;
320   else
321     return result;
322 }
323 
324 /* See documentation in common-utils.h.  */
325 
326 char *
327 skip_spaces (char *chp)
328 {
329   if (chp == NULL)
330     return NULL;
331   while (*chp && ISSPACE (*chp))
332     chp++;
333   return chp;
334 }
335 
336 /* A const-correct version of the above.  */
337 
338 const char *
339 skip_spaces (const char *chp)
340 {
341   if (chp == NULL)
342     return NULL;
343   while (*chp && ISSPACE (*chp))
344     chp++;
345   return chp;
346 }
347 
348 /* See documentation in common-utils.h.  */
349 
350 const char *
351 skip_to_space (const char *chp)
352 {
353   if (chp == NULL)
354     return NULL;
355   while (*chp && !ISSPACE (*chp))
356     chp++;
357   return chp;
358 }
359 
360 /* See documentation in common-utils.h.  */
361 
362 char *
363 skip_to_space (char *chp)
364 {
365   return (char *) skip_to_space ((const char *) chp);
366 }
367 
368 /* See gdbsupport/common-utils.h.  */
369 
370 void
371 free_vector_argv (std::vector<char *> &v)
372 {
373   for (char *el : v)
374     xfree (el);
375 
376   v.clear ();
377 }
378 
379 /* See gdbsupport/common-utils.h.  */
380 
381 ULONGEST
382 align_up (ULONGEST v, int n)
383 {
384   /* Check that N is really a power of two.  */
385   gdb_assert (n && (n & (n-1)) == 0);
386   return (v + n - 1) & -n;
387 }
388 
389 /* See gdbsupport/common-utils.h.  */
390 
391 ULONGEST
392 align_down (ULONGEST v, int n)
393 {
394   /* Check that N is really a power of two.  */
395   gdb_assert (n && (n & (n-1)) == 0);
396   return (v & -n);
397 }
398 
399 /* See gdbsupport/common-utils.h.  */
400 
401 int
402 fromhex (int a)
403 {
404   if (a >= '0' && a <= '9')
405     return a - '0';
406   else if (a >= 'a' && a <= 'f')
407     return a - 'a' + 10;
408   else if (a >= 'A' && a <= 'F')
409     return a - 'A' + 10;
410   else
411     error (_("Invalid hex digit %d"), a);
412 }
413 
414 /* See gdbsupport/common-utils.h.  */
415 
416 int
417 hex2bin (const char *hex, gdb_byte *bin, int count)
418 {
419   int i;
420 
421   for (i = 0; i < count; i++)
422     {
423       if (hex[0] == 0 || hex[1] == 0)
424 	{
425 	  /* Hex string is short, or of uneven length.
426 	     Return the count that has been converted so far.  */
427 	  return i;
428 	}
429       *bin++ = fromhex (hex[0]) * 16 + fromhex (hex[1]);
430       hex += 2;
431     }
432   return i;
433 }
434 
435 /* See gdbsupport/common-utils.h.  */
436 
437 gdb::byte_vector
438 hex2bin (const char *hex)
439 {
440   size_t bin_len = strlen (hex) / 2;
441   gdb::byte_vector bin (bin_len);
442 
443   hex2bin (hex, bin.data (), bin_len);
444 
445   return bin;
446 }
447 
448 /* See gdbsupport/common-utils.h.  */
449 
450 std::string
451 bytes_to_string (gdb::array_view<const gdb_byte> bytes)
452 {
453   std::string ret;
454 
455   for (size_t i = 0; i < bytes.size (); i++)
456     {
457       if (i == 0)
458 	ret += string_printf ("%02x", bytes[i]);
459       else
460 	ret += string_printf (" %02x", bytes[i]);
461     }
462 
463   return ret;
464 }
465