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