xref: /netbsd-src/external/gpl3/gdb/dist/gdbsupport/print-utils.cc (revision 9fb66d812c00ebfb445c0b47dea128f32aa6fe96)
1 /* Cell-based print utility routines for GDB, the GNU debugger.
2 
3    Copyright (C) 1986-2020 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 (__FILE__, __LINE__,
77 		      _("failed internal consistency check"));
78     }
79 
80   return str;
81 }
82 
83 static char *
84 octal2str (ULONGEST addr, int width)
85 {
86   unsigned long temp[3];
87   char *str = get_print_cell ();
88   int i = 0;
89 
90   do
91     {
92       temp[i] = addr % (0100000 * 0100000);
93       addr /= (0100000 * 0100000);
94       i++;
95       width -= 10;
96     }
97   while (addr != 0 && i < (sizeof (temp) / sizeof (temp[0])));
98 
99   width += 10;
100   if (width < 0)
101     width = 0;
102 
103   switch (i)
104     {
105     case 1:
106       if (temp[0] == 0)
107 	xsnprintf (str, PRINT_CELL_SIZE, "%*o", width, 0);
108       else
109 	xsnprintf (str, PRINT_CELL_SIZE, "0%0*lo", width, temp[0]);
110       break;
111     case 2:
112       xsnprintf (str, PRINT_CELL_SIZE, "0%0*lo%010lo", width, temp[1], temp[0]);
113       break;
114     case 3:
115       xsnprintf (str, PRINT_CELL_SIZE, "0%0*lo%010lo%010lo", width,
116 		 temp[2], temp[1], temp[0]);
117       break;
118     default:
119       internal_error (__FILE__, __LINE__,
120 		      _("failed internal consistency check"));
121     }
122 
123   return str;
124 }
125 
126 /* See print-utils.h.  */
127 
128 char *
129 pulongest (ULONGEST u)
130 {
131   return decimal2str ("", u, 0);
132 }
133 
134 /* See print-utils.h.  */
135 
136 char *
137 plongest (LONGEST l)
138 {
139   if (l < 0)
140     return decimal2str ("-", -l, 0);
141   else
142     return decimal2str ("", l, 0);
143 }
144 
145 /* Eliminate warning from compiler on 32-bit systems.  */
146 static int thirty_two = 32;
147 
148 /* See print-utils.h.  */
149 
150 char *
151 phex (ULONGEST l, int sizeof_l)
152 {
153   char *str;
154 
155   switch (sizeof_l)
156     {
157     case 8:
158       str = get_print_cell ();
159       xsnprintf (str, PRINT_CELL_SIZE, "%08lx%08lx",
160 		 (unsigned long) (l >> thirty_two),
161 		 (unsigned long) (l & 0xffffffff));
162       break;
163     case 4:
164       str = get_print_cell ();
165       xsnprintf (str, PRINT_CELL_SIZE, "%08lx", (unsigned long) l);
166       break;
167     case 2:
168       str = get_print_cell ();
169       xsnprintf (str, PRINT_CELL_SIZE, "%04x", (unsigned short) (l & 0xffff));
170       break;
171     default:
172       str = phex (l, sizeof (l));
173       break;
174     }
175 
176   return str;
177 }
178 
179 /* See print-utils.h.  */
180 
181 char *
182 phex_nz (ULONGEST l, int sizeof_l)
183 {
184   char *str;
185 
186   switch (sizeof_l)
187     {
188     case 8:
189       {
190 	unsigned long high = (unsigned long) (l >> thirty_two);
191 
192 	str = get_print_cell ();
193 	if (high == 0)
194 	  xsnprintf (str, PRINT_CELL_SIZE, "%lx",
195 		     (unsigned long) (l & 0xffffffff));
196 	else
197 	  xsnprintf (str, PRINT_CELL_SIZE, "%lx%08lx", high,
198 		     (unsigned long) (l & 0xffffffff));
199 	break;
200       }
201     case 4:
202       str = get_print_cell ();
203       xsnprintf (str, PRINT_CELL_SIZE, "%lx", (unsigned long) l);
204       break;
205     case 2:
206       str = get_print_cell ();
207       xsnprintf (str, PRINT_CELL_SIZE, "%x", (unsigned short) (l & 0xffff));
208       break;
209     default:
210       str = phex_nz (l, sizeof (l));
211       break;
212     }
213 
214   return str;
215 }
216 
217 /* See print-utils.h.  */
218 
219 char *
220 hex_string (LONGEST num)
221 {
222   char *result = get_print_cell ();
223 
224   xsnprintf (result, PRINT_CELL_SIZE, "0x%s", phex_nz (num, sizeof (num)));
225   return result;
226 }
227 
228 /* See print-utils.h.  */
229 
230 char *
231 hex_string_custom (LONGEST num, int width)
232 {
233   char *result = get_print_cell ();
234   char *result_end = result + PRINT_CELL_SIZE - 1;
235   const char *hex = phex_nz (num, sizeof (num));
236   int hex_len = strlen (hex);
237 
238   if (hex_len > width)
239     width = hex_len;
240   if (width + 2 >= PRINT_CELL_SIZE)
241     internal_error (__FILE__, __LINE__, _("\
242 hex_string_custom: insufficient space to store result"));
243 
244   strcpy (result_end - width - 2, "0x");
245   memset (result_end - width, '0', width);
246   strcpy (result_end - hex_len, hex);
247   return result_end - width - 2;
248 }
249 
250 /* See print-utils.h.  */
251 
252 char *
253 int_string (LONGEST val, int radix, int is_signed, int width,
254 	    int use_c_format)
255 {
256   switch (radix)
257     {
258     case 16:
259       {
260 	char *result;
261 
262 	if (width == 0)
263 	  result = hex_string (val);
264 	else
265 	  result = hex_string_custom (val, width);
266 	if (! use_c_format)
267 	  result += 2;
268 	return result;
269       }
270     case 10:
271       {
272 	if (is_signed && val < 0)
273 	  return decimal2str ("-", -val, width);
274 	else
275 	  return decimal2str ("", val, width);
276       }
277     case 8:
278       {
279 	char *result = octal2str (val, width);
280 
281 	if (use_c_format || val == 0)
282 	  return result;
283 	else
284 	  return result + 1;
285       }
286     default:
287       internal_error (__FILE__, __LINE__,
288 		      _("failed internal consistency check"));
289     }
290 }
291 
292 /* See print-utils.h.  */
293 
294 const char *
295 core_addr_to_string (const CORE_ADDR addr)
296 {
297   char *str = get_print_cell ();
298 
299   strcpy (str, "0x");
300   strcat (str, phex (addr, sizeof (addr)));
301   return str;
302 }
303 
304 /* See print-utils.h.  */
305 
306 const char *
307 core_addr_to_string_nz (const CORE_ADDR addr)
308 {
309   char *str = get_print_cell ();
310 
311   strcpy (str, "0x");
312   strcat (str, phex_nz (addr, sizeof (addr)));
313   return str;
314 }
315 
316 /* See print-utils.h.  */
317 
318 const char *
319 host_address_to_string_1 (const void *addr)
320 {
321   char *str = get_print_cell ();
322 
323   xsnprintf (str, PRINT_CELL_SIZE, "0x%s",
324 	     phex_nz ((uintptr_t) addr, sizeof (addr)));
325   return str;
326 }
327