]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gdbsupport/print-utils.cc
Update copyright year range in header of all files managed by GDB
[thirdparty/binutils-gdb.git] / gdbsupport / print-utils.cc
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 "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 }