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