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