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