xref: /netbsd-src/external/gpl3/gdb/dist/gdbsupport/print-utils.cc (revision 32d1c65c71fbdb65a012e8392a62a757dd6853e9)
1 /* Cell-based print 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 "print-utils.h"
21 /* Temporary storage using circular buffer.  */
22 
23 /* Number of cells in the circular buffer.  */
24 #define NUMCELLS 16
25 
26 /* Return the next entry in the circular buffer.  */
27 
28 char *
29 get_print_cell (void)
30 {
31   static char buf[NUMCELLS][PRINT_CELL_SIZE];
32   static int cell = 0;
33 
34   if (++cell >= NUMCELLS)
35     cell = 0;
36   return buf[cell];
37 }
38 
39 static char *
40 decimal2str (const char *sign, ULONGEST addr, int width)
41 {
42   /* Steal code from valprint.c:print_decimal().  Should this worry
43      about the real size of addr as the above does?  */
44   unsigned long temp[3];
45   char *str = get_print_cell ();
46   int i = 0;
47 
48   do
49     {
50       temp[i] = addr % (1000 * 1000 * 1000);
51       addr /= (1000 * 1000 * 1000);
52       i++;
53       width -= 9;
54     }
55   while (addr != 0 && i < (sizeof (temp) / sizeof (temp[0])));
56 
57   width += 9;
58   if (width < 0)
59     width = 0;
60 
61   switch (i)
62     {
63     case 1:
64       xsnprintf (str, PRINT_CELL_SIZE, "%s%0*lu", sign, width, temp[0]);
65       break;
66     case 2:
67       xsnprintf (str, PRINT_CELL_SIZE, "%s%0*lu%09lu", sign, width,
68 		 temp[1], temp[0]);
69       break;
70     case 3:
71       xsnprintf (str, PRINT_CELL_SIZE, "%s%0*lu%09lu%09lu", sign, width,
72 		 temp[2], temp[1], temp[0]);
73       break;
74     default:
75       internal_error (_("failed internal consistency check"));
76     }
77 
78   return str;
79 }
80 
81 static char *
82 octal2str (ULONGEST addr, int width)
83 {
84   unsigned long temp[3];
85   char *str = get_print_cell ();
86   int i = 0;
87 
88   do
89     {
90       temp[i] = addr % (0100000 * 0100000);
91       addr /= (0100000 * 0100000);
92       i++;
93       width -= 10;
94     }
95   while (addr != 0 && i < (sizeof (temp) / sizeof (temp[0])));
96 
97   width += 10;
98   if (width < 0)
99     width = 0;
100 
101   switch (i)
102     {
103     case 1:
104       if (temp[0] == 0)
105 	xsnprintf (str, PRINT_CELL_SIZE, "%*o", width, 0);
106       else
107 	xsnprintf (str, PRINT_CELL_SIZE, "0%0*lo", width, temp[0]);
108       break;
109     case 2:
110       xsnprintf (str, PRINT_CELL_SIZE, "0%0*lo%010lo", width, temp[1], temp[0]);
111       break;
112     case 3:
113       xsnprintf (str, PRINT_CELL_SIZE, "0%0*lo%010lo%010lo", width,
114 		 temp[2], temp[1], temp[0]);
115       break;
116     default:
117       internal_error (_("failed internal consistency check"));
118     }
119 
120   return str;
121 }
122 
123 /* See print-utils.h.  */
124 
125 const char *
126 pulongest (ULONGEST u)
127 {
128   return decimal2str ("", u, 0);
129 }
130 
131 /* See print-utils.h.  */
132 
133 const char *
134 plongest (LONGEST l)
135 {
136   if (l < 0)
137     return decimal2str ("-", -l, 0);
138   else
139     return decimal2str ("", l, 0);
140 }
141 
142 /* Eliminate warning from compiler on 32-bit systems.  */
143 static int thirty_two = 32;
144 
145 /* See print-utils.h.  */
146 
147 const char *
148 phex (ULONGEST l, int sizeof_l)
149 {
150   char *str;
151 
152   switch (sizeof_l)
153     {
154     case 8:
155       str = get_print_cell ();
156       xsnprintf (str, PRINT_CELL_SIZE, "%08lx%08lx",
157 		 (unsigned long) (l >> thirty_two),
158 		 (unsigned long) (l & 0xffffffff));
159       break;
160     case 4:
161       str = get_print_cell ();
162       xsnprintf (str, PRINT_CELL_SIZE, "%08lx", (unsigned long) l);
163       break;
164     case 2:
165       str = get_print_cell ();
166       xsnprintf (str, PRINT_CELL_SIZE, "%04x", (unsigned short) (l & 0xffff));
167       break;
168     case 1:
169       str = get_print_cell ();
170       xsnprintf (str, PRINT_CELL_SIZE, "%02x", (unsigned short) (l & 0xff));
171       break;
172     default:
173       return phex (l, sizeof (l));
174       break;
175     }
176 
177   return str;
178 }
179 
180 /* See print-utils.h.  */
181 
182 const char *
183 phex_nz (ULONGEST l, int sizeof_l)
184 {
185   char *str;
186 
187   switch (sizeof_l)
188     {
189     case 8:
190       {
191 	unsigned long high = (unsigned long) (l >> thirty_two);
192 
193 	str = get_print_cell ();
194 	if (high == 0)
195 	  xsnprintf (str, PRINT_CELL_SIZE, "%lx",
196 		     (unsigned long) (l & 0xffffffff));
197 	else
198 	  xsnprintf (str, PRINT_CELL_SIZE, "%lx%08lx", high,
199 		     (unsigned long) (l & 0xffffffff));
200 	break;
201       }
202     case 4:
203       str = get_print_cell ();
204       xsnprintf (str, PRINT_CELL_SIZE, "%lx", (unsigned long) l);
205       break;
206     case 2:
207       str = get_print_cell ();
208       xsnprintf (str, PRINT_CELL_SIZE, "%x", (unsigned short) (l & 0xffff));
209       break;
210     case 1:
211       str = get_print_cell ();
212       xsnprintf (str, PRINT_CELL_SIZE, "%x", (unsigned short) (l & 0xff));
213       break;
214     default:
215       return phex_nz (l, sizeof (l));
216       break;
217     }
218 
219   return str;
220 }
221 
222 /* See print-utils.h.  */
223 
224 const char *
225 hex_string (LONGEST num)
226 {
227   char *result = get_print_cell ();
228 
229   xsnprintf (result, PRINT_CELL_SIZE, "0x%s", phex_nz (num, sizeof (num)));
230   return result;
231 }
232 
233 /* See print-utils.h.  */
234 
235 const char *
236 hex_string_custom (LONGEST num, int width)
237 {
238   char *result = get_print_cell ();
239   char *result_end = result + PRINT_CELL_SIZE - 1;
240   const char *hex = phex_nz (num, sizeof (num));
241   int hex_len = strlen (hex);
242 
243   if (hex_len > width)
244     width = hex_len;
245   if (width + 2 >= PRINT_CELL_SIZE)
246     internal_error (_("\
247 hex_string_custom: insufficient space to store result"));
248 
249   strcpy (result_end - width - 2, "0x");
250   memset (result_end - width, '0', width);
251   strcpy (result_end - hex_len, hex);
252   return result_end - width - 2;
253 }
254 
255 /* See print-utils.h.  */
256 
257 const char *
258 int_string (LONGEST val, int radix, int is_signed, int width,
259 	    int use_c_format)
260 {
261   switch (radix)
262     {
263     case 16:
264       {
265 	const char *result;
266 
267 	if (width == 0)
268 	  result = hex_string (val);
269 	else
270 	  result = hex_string_custom (val, width);
271 	if (! use_c_format)
272 	  result += 2;
273 	return result;
274       }
275     case 10:
276       {
277 	if (is_signed && val < 0)
278 	  /* Cast to unsigned before negating, to prevent runtime error:
279 	     negation of -9223372036854775808 cannot be represented in type
280 	     'long int'; cast to an unsigned type to negate this value to
281 	     itself.  */
282 	  return decimal2str ("-", -(ULONGEST)val, width);
283 	else
284 	  return decimal2str ("", val, width);
285       }
286     case 8:
287       {
288 	char *result = octal2str (val, width);
289 
290 	if (use_c_format || val == 0)
291 	  return result;
292 	else
293 	  return result + 1;
294       }
295     default:
296       internal_error (_("failed internal consistency check"));
297     }
298 }
299 
300 /* See print-utils.h.  */
301 
302 const char *
303 core_addr_to_string (const CORE_ADDR addr)
304 {
305   char *str = get_print_cell ();
306 
307   strcpy (str, "0x");
308   strcat (str, phex (addr, sizeof (addr)));
309   return str;
310 }
311 
312 /* See print-utils.h.  */
313 
314 const char *
315 core_addr_to_string_nz (const CORE_ADDR addr)
316 {
317   char *str = get_print_cell ();
318 
319   strcpy (str, "0x");
320   strcat (str, phex_nz (addr, sizeof (addr)));
321   return str;
322 }
323 
324 /* See print-utils.h.  */
325 
326 const char *
327 host_address_to_string_1 (const void *addr)
328 {
329   char *str = get_print_cell ();
330 
331   xsnprintf (str, PRINT_CELL_SIZE, "0x%s",
332 	     phex_nz ((uintptr_t) addr, sizeof (addr)));
333   return str;
334 }
335