Add lens "bitvec" for displaying objects as bit vectors
diff --git a/lens_default.c b/lens_default.c
index 7ad2ee4..093b803 100644
--- a/lens_default.c
+++ b/lens_default.c
@@ -468,6 +468,18 @@
static int
+dec_lens_format_cb(struct lens *lens, FILE *stream,
+ struct value *value, struct value_dict *arguments)
+{
+ return toplevel_format_lens(lens, stream, value, arguments, INT_FMT_u);
+}
+
+struct lens dec_lens = {
+ .format_cb = dec_lens_format_cb,
+};
+
+
+static int
guess_lens_format_cb(struct lens *lens, FILE *stream,
struct value *value, struct value_dict *arguments)
{
@@ -576,3 +588,117 @@
struct lens string_lens = {
.format_cb = string_lens_format_cb,
};
+
+static int
+out_bits(FILE *stream, size_t low, size_t high)
+{
+ if (low == high)
+ return fprintf(stream, "%zd", low);
+ else
+ return fprintf(stream, "%zd-%zd", low, high);
+}
+
+static unsigned
+bitcount(unsigned u)
+{
+ int c = 0;
+ for (; u > 0; u &= u - 1)
+ c++;
+ return c;
+}
+
+static int
+bitvect_lens_format_cb(struct lens *lens, FILE *stream,
+ struct value *value, struct value_dict *arguments)
+{
+ unsigned char *data = value_get_data(value, arguments);
+ if (data == NULL)
+ return -1;
+ size_t sz = type_sizeof(value->inferior, value->type);
+ if (sz == (size_t)-1)
+ return -1;
+
+ size_t i;
+ unsigned char buf[sz];
+ switch ((int)value->type->type) {
+ union bitvect_integral_64
+ {
+ uint8_t u8;
+ uint16_t u16;
+ uint32_t u32;
+ uint64_t u64;
+ unsigned char buf[0];
+ } bv;
+
+ case ARGTYPE_POINTER:
+ return format_pointer(stream, value, arguments);
+
+ case ARGTYPE_STRUCT:
+ case ARGTYPE_ARRAY:
+ break;
+
+ default:
+ assert(sz <= sizeof(bv));
+ memmove(bv.buf, data, sz);
+
+ if (sz == 1)
+ bv.u64 = bv.u8;
+ else if (sz == 2)
+ bv.u64 = bv.u16;
+ else if (sz == 4)
+ bv.u64 = bv.u32;
+
+ for (i = 0; i < sz; ++i) {
+ buf[i] = bv.u64 & 0xff;
+ bv.u64 >>= 8;
+ }
+ data = buf;
+ }
+
+ size_t bits = 0;
+ for (i = 0; i < sz; ++i)
+ bits += bitcount(data[i]);
+
+ /* If there's more 1's than 0's, show inverse. */
+ unsigned neg = bits > sz * 4 ? 0xff : 0x00;
+
+ int o = 0;
+ if (acc_fprintf(&o, stream, "%s<", "~" + (neg == 0x00)) < 0)
+ return -1;
+
+ size_t bitno = 0;
+ ssize_t low = -1;
+ for (i = 0; i < sz; ++i) {
+ unsigned char m;
+ unsigned char d = data[i] ^ neg;
+ for (m = 0x01; m != 0; m <<= 1) {
+ int bit = !!(m & d);
+ if (low < 0) {
+ if (bit) {
+ if (low == -2
+ && acc_fprintf(&o, stream, ",") < 0)
+ return -1;
+ low = bitno;
+ }
+ } else if (!bit) {
+ if (account_output(&o, out_bits(stream, low,
+ bitno-1)) < 0)
+ return -1;
+ low = -2;
+ }
+ bitno++;
+ }
+ }
+ if (low >= 0 && account_output(&o, out_bits(stream, low, bitno-1)) < 0)
+ return -1;
+
+ if (fputc('>', stream) < 0)
+ return -1;
+ o += 1;
+
+ return o;
+}
+
+struct lens bitvect_lens = {
+ .format_cb = bitvect_lens_format_cb,
+};