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