+void
+print_binary_chars (stream, valaddr, len)
+ GDB_FILE *stream;
+ unsigned char *valaddr;
+ unsigned len;
+{
+
+#define BITS_IN_BYTES 8
+
+ unsigned char *p;
+ int i;
+ int b;
+
+ /* Declared "int" so it will be signed.
+ * This ensures that right shift will shift in zeros.
+ */
+ const int mask = 0x080;
+
+ /* FIXME: We should be not printing leading zeroes in most cases. */
+
+ fprintf_filtered (stream, local_binary_format_prefix ());
+ if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+ {
+ for (p = valaddr;
+ p < valaddr + len;
+ p++)
+ {
+ /* Every byte has 8 binary characters; peel off
+ * and print from the MSB end.
+ */
+ for (i = 0; i < (BITS_IN_BYTES * sizeof (*p)); i++)
+ {
+ if (*p & (mask >> i))
+ b = 1;
+ else
+ b = 0;
+
+ fprintf_filtered (stream, "%1d", b);
+ }
+ }
+ }
+ else
+ {
+ for (p = valaddr + len - 1;
+ p >= valaddr;
+ p--)
+ {
+ for (i = 0; i < (BITS_IN_BYTES * sizeof (*p)); i++)
+ {
+ if (*p & (mask >> i))
+ b = 1;
+ else
+ b = 0;
+
+ fprintf_filtered (stream, "%1d", b);
+ }
+ }
+ }
+ fprintf_filtered (stream, local_binary_format_suffix ());
+}
+
+/* VALADDR points to an integer of LEN bytes.
+ * Print it in octal on stream or format it in buf.
+ */
+void
+print_octal_chars (stream, valaddr, len)
+ GDB_FILE *stream;
+ unsigned char *valaddr;
+ unsigned len;
+{
+ unsigned char *p;
+ unsigned char octa1, octa2, octa3, carry;
+ int cycle;
+
+ /* FIXME: We should be not printing leading zeroes in most cases. */
+
+
+ /* Octal is 3 bits, which doesn't fit. Yuk. So we have to track
+ * the extra bits, which cycle every three bytes:
+ *
+ * Byte side: 0 1 2 3
+ * | | | |
+ * bit number 123 456 78 | 9 012 345 6 | 78 901 234 | 567 890 12 |
+ *
+ * Octal side: 0 1 carry 3 4 carry ...
+ *
+ * Cycle number: 0 1 2
+ *
+ * But of course we are printing from the high side, so we have to
+ * figure out where in the cycle we are so that we end up with no
+ * left over bits at the end.
+ */
+#define BITS_IN_OCTAL 3
+#define HIGH_ZERO 0340
+#define LOW_ZERO 0016
+#define CARRY_ZERO 0003
+#define HIGH_ONE 0200
+#define MID_ONE 0160
+#define LOW_ONE 0016
+#define CARRY_ONE 0001
+#define HIGH_TWO 0300
+#define MID_TWO 0070
+#define LOW_TWO 0007
+
+ /* For 32 we start in cycle 2, with two bits and one bit carry;
+ * for 64 in cycle in cycle 1, with one bit and a two bit carry.
+ */
+ cycle = (len * BITS_IN_BYTES) % BITS_IN_OCTAL;
+ carry = 0;
+
+ fprintf_filtered (stream, local_octal_format_prefix ());
+ if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+ {
+ for (p = valaddr;
+ p < valaddr + len;
+ p++)
+ {
+ switch (cycle)
+ {
+ case 0:
+ /* No carry in, carry out two bits.
+ */
+ octa1 = (HIGH_ZERO & *p) >> 5;
+ octa2 = (LOW_ZERO & *p) >> 2;
+ carry = (CARRY_ZERO & *p);
+ fprintf_filtered (stream, "%o", octa1);
+ fprintf_filtered (stream, "%o", octa2);
+ break;
+
+ case 1:
+ /* Carry in two bits, carry out one bit.
+ */
+ octa1 = (carry << 1) | ((HIGH_ONE & *p) >> 7);
+ octa2 = (MID_ONE & *p) >> 4;
+ octa3 = (LOW_ONE & *p) >> 1;
+ carry = (CARRY_ONE & *p);
+ fprintf_filtered (stream, "%o", octa1);
+ fprintf_filtered (stream, "%o", octa2);
+ fprintf_filtered (stream, "%o", octa3);
+ break;
+
+ case 2:
+ /* Carry in one bit, no carry out.
+ */
+ octa1 = (carry << 2) | ((HIGH_TWO & *p) >> 6);
+ octa2 = (MID_TWO & *p) >> 3;
+ octa3 = (LOW_TWO & *p);
+ carry = 0;
+ fprintf_filtered (stream, "%o", octa1);
+ fprintf_filtered (stream, "%o", octa2);
+ fprintf_filtered (stream, "%o", octa3);
+ break;
+
+ default:
+ error ("Internal error in octal conversion;");
+ }
+
+ cycle++;
+ cycle = cycle % BITS_IN_OCTAL;
+ }
+ }
+ else
+ {
+ for (p = valaddr + len - 1;
+ p >= valaddr;
+ p--)
+ {
+ switch (cycle)
+ {
+ case 0:
+ /* Carry out, no carry in */
+ octa1 = (HIGH_ZERO & *p) >> 5;
+ octa2 = (LOW_ZERO & *p) >> 2;
+ carry = (CARRY_ZERO & *p);
+ fprintf_filtered (stream, "%o", octa1);
+ fprintf_filtered (stream, "%o", octa2);
+ break;
+
+ case 1:
+ /* Carry in, carry out */
+ octa1 = (carry << 1) | ((HIGH_ONE & *p) >> 7);
+ octa2 = (MID_ONE & *p) >> 4;
+ octa3 = (LOW_ONE & *p) >> 1;
+ carry = (CARRY_ONE & *p);
+ fprintf_filtered (stream, "%o", octa1);
+ fprintf_filtered (stream, "%o", octa2);
+ fprintf_filtered (stream, "%o", octa3);
+ break;
+
+ case 2:
+ /* Carry in, no carry out */
+ octa1 = (carry << 2) | ((HIGH_TWO & *p) >> 6);
+ octa2 = (MID_TWO & *p) >> 3;
+ octa3 = (LOW_TWO & *p);
+ carry = 0;
+ fprintf_filtered (stream, "%o", octa1);
+ fprintf_filtered (stream, "%o", octa2);
+ fprintf_filtered (stream, "%o", octa3);
+ break;
+
+ default:
+ error ("Internal error in octal conversion;");
+ }
+
+ cycle++;
+ cycle = cycle % BITS_IN_OCTAL;
+ }
+ }
+
+ fprintf_filtered (stream, local_octal_format_suffix ());
+}
+
+/* VALADDR points to an integer of LEN bytes.
+ * Print it in decimal on stream or format it in buf.
+ */
+void
+print_decimal_chars (stream, valaddr, len)
+ GDB_FILE *stream;
+ unsigned char *valaddr;
+ unsigned len;
+{
+#define TEN 10
+#define TWO_TO_FOURTH 16
+#define CARRY_OUT( x ) ((x) / TEN) /* extend char to int */
+#define CARRY_LEFT( x ) ((x) % TEN)
+#define SHIFT( x ) ((x) << 4)
+#define START_P \
+ ((TARGET_BYTE_ORDER == BIG_ENDIAN) ? valaddr : valaddr + len - 1)
+#define NOT_END_P \
+ ((TARGET_BYTE_ORDER == BIG_ENDIAN) ? (p < valaddr + len) : (p >= valaddr))
+#define NEXT_P \
+ ((TARGET_BYTE_ORDER == BIG_ENDIAN) ? p++ : p-- )
+#define LOW_NIBBLE( x ) ( (x) & 0x00F)
+#define HIGH_NIBBLE( x ) (((x) & 0x0F0) >> 4)
+
+ unsigned char *p;
+ unsigned char *digits;
+ int carry;
+ int decimal_len;
+ int i, j, decimal_digits;
+ int dummy;
+ int flip;
+
+ /* Base-ten number is less than twice as many digits
+ * as the base 16 number, which is 2 digits per byte.
+ */
+ decimal_len = len * 2 * 2;
+ digits = (unsigned char *) malloc (decimal_len);
+ if (digits == NULL)
+ error ("Can't allocate memory for conversion to decimal.");
+
+ for (i = 0; i < decimal_len; i++)
+ {
+ digits[i] = 0;
+ }
+
+ fprintf_filtered (stream, local_decimal_format_prefix ());
+
+ /* Ok, we have an unknown number of bytes of data to be printed in
+ * decimal.
+ *
+ * Given a hex number (in nibbles) as XYZ, we start by taking X and
+ * decemalizing it as "x1 x2" in two decimal nibbles. Then we multiply
+ * the nibbles by 16, add Y and re-decimalize. Repeat with Z.
+ *
+ * The trick is that "digits" holds a base-10 number, but sometimes
+ * the individual digits are > 10.
+ *
+ * Outer loop is per nibble (hex digit) of input, from MSD end to
+ * LSD end.
+ */
+ decimal_digits = 0; /* Number of decimal digits so far */
+ p = START_P;
+ flip = 0;
+ while (NOT_END_P)
+ {
+ /*
+ * Multiply current base-ten number by 16 in place.
+ * Each digit was between 0 and 9, now is between
+ * 0 and 144.
+ */
+ for (j = 0; j < decimal_digits; j++)
+ {
+ digits[j] = SHIFT (digits[j]);
+ }
+
+ /* Take the next nibble off the input and add it to what
+ * we've got in the LSB position. Bottom 'digit' is now
+ * between 0 and 159.
+ *
+ * "flip" is used to run this loop twice for each byte.
+ */
+ if (flip == 0)
+ {
+ /* Take top nibble.
+ */
+ digits[0] += HIGH_NIBBLE (*p);
+ flip = 1;
+ }
+ else
+ {
+ /* Take low nibble and bump our pointer "p".
+ */
+ digits[0] += LOW_NIBBLE (*p);
+ NEXT_P;
+ flip = 0;
+ }
+
+ /* Re-decimalize. We have to do this often enough
+ * that we don't overflow, but once per nibble is
+ * overkill. Easier this way, though. Note that the
+ * carry is often larger than 10 (e.g. max initial
+ * carry out of lowest nibble is 15, could bubble all
+ * the way up greater than 10). So we have to do
+ * the carrying beyond the last current digit.
+ */
+ carry = 0;
+ for (j = 0; j < decimal_len - 1; j++)
+ {
+ digits[j] += carry;
+
+ /* "/" won't handle an unsigned char with
+ * a value that if signed would be negative.
+ * So extend to longword int via "dummy".
+ */
+ dummy = digits[j];
+ carry = CARRY_OUT (dummy);
+ digits[j] = CARRY_LEFT (dummy);
+
+ if (j >= decimal_digits && carry == 0)
+ {
+ /*
+ * All higher digits are 0 and we
+ * no longer have a carry.
+ *
+ * Note: "j" is 0-based, "decimal_digits" is
+ * 1-based.
+ */
+ decimal_digits = j + 1;
+ break;
+ }
+ }
+ }
+
+ /* Ok, now "digits" is the decimal representation, with
+ * the "decimal_digits" actual digits. Print!
+ */
+ for (i = decimal_digits - 1; i >= 0; i--)
+ {
+ fprintf_filtered (stream, "%1d", digits[i]);
+ }
+ free (digits);
+
+ fprintf_filtered (stream, local_decimal_format_suffix ());
+}
+