Home | History | Annotate | Line # | Download | only in gdbsupport
      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