1 /*
2  * This file is part of ltrace.
3  * Copyright (C) 2011,2012,2013 Petr Machata, Red Hat Inc.
4  * Copyright (C) 1998,2004,2007,2008,2009 Juan Cespedes
5  * Copyright (C) 2006 Ian Wienand
6  * Copyright (C) 2006 Steve Fink
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of the
11  * License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21  * 02110-1301 USA
22  */
23 
24 #define _XOPEN_SOURCE /* For wcwidth from wchar.h.  */
25 
26 #include <ctype.h>
27 #include <stdlib.h>
28 #include <assert.h>
29 #include <inttypes.h>
30 #include <stdarg.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <wchar.h>
34 
35 #include "bits.h"
36 #include "expr.h"
37 #include "lens_default.h"
38 #include "options.h"
39 #include "output.h"
40 #include "type.h"
41 #include "value.h"
42 #include "zero.h"
43 
44 #define READER(NAME, TYPE)						\
45 	static int							\
46 	NAME(struct value *value, TYPE *ret, struct value_dict *arguments) \
47 	{								\
48 		union {							\
49 			TYPE val;					\
50 			unsigned char buf[0];				\
51 		} u;							\
52 		if (value_extract_buf(value, u.buf, arguments) < 0)	\
53 			return -1;					\
54 		*ret = u.val;						\
55 		return 0;						\
56 	}
57 
58 READER(read_float, float)
59 READER(read_double, double)
60 
61 #undef READER
62 
63 #define HANDLE_WIDTH(BITS)						\
64 	do {								\
65 		long l;							\
66 		if (value_extract_word(value, &l, arguments) < 0)	\
67 			return -1;					\
68 		int##BITS##_t i = l;					\
69 		uint64_t v = (uint64_t)(uint##BITS##_t)i;		\
70 		switch (format) {					\
71 		case INT_FMT_unknown:					\
72 			if (l < -10000 || l > 10000)			\
73 		case INT_FMT_x:						\
74 			return fprintf(stream, "%#"PRIx64, v);		\
75 		case INT_FMT_i:						\
76 		case INT_FMT_default:					\
77 			return fprintf(stream, "%"PRIi##BITS, i);	\
78 		case INT_FMT_u:						\
79 			return fprintf(stream, "%"PRIu64, v);		\
80 		case INT_FMT_o:						\
81 			return fprintf(stream, "0%"PRIo64, v);		\
82 		}							\
83 	} while (0)
84 
85 enum int_fmt_t
86 {
87 	INT_FMT_i,
88 	INT_FMT_u,
89 	INT_FMT_o,
90 	INT_FMT_x,
91 	INT_FMT_unknown,
92 	INT_FMT_default,
93 };
94 
95 static int
format_integer(FILE * stream,struct value * value,enum int_fmt_t format,struct value_dict * arguments)96 format_integer(FILE *stream, struct value *value, enum int_fmt_t format,
97 	       struct value_dict *arguments)
98 {
99 	switch (type_sizeof(value->inferior, value->type)) {
100 
101 	case 1: HANDLE_WIDTH(8);
102 	case 2: HANDLE_WIDTH(16);
103 	case 4: HANDLE_WIDTH(32);
104 	case 8: HANDLE_WIDTH(64);
105 
106 	default:
107 		assert(!"unsupported integer width");
108 		abort();
109 
110 	case -1:
111 		return -1;
112 	}
113 }
114 
115 #undef HANDLE_WIDTH
116 
117 static int
acc_fprintf(int * countp,FILE * stream,const char * format,...)118 acc_fprintf(int *countp, FILE *stream, const char *format, ...)
119 {
120 	va_list pa;
121 	va_start(pa, format);
122 	int i = account_output(countp, vfprintf(stream, format, pa));
123 	va_end(pa);
124 
125 	return i;
126 }
127 
128 static int
print_char(FILE * stream,int c)129 print_char(FILE *stream, int c)
130 {
131 	const char *fmt;
132 	switch (c) {
133 	case -1:
134 		fmt = "EOF";
135 		break;
136 	case 0:
137 		fmt = "\\0";
138 		break;
139 	case '\a':
140 		fmt = "\\a";
141 		break;
142 	case '\b':
143 		fmt = "\\b";
144 		break;
145 	case '\t':
146 		fmt = "\\t";
147 		break;
148 	case '\n':
149 		fmt = "\\n";
150 		break;
151 	case '\v':
152 		fmt = "\\v";
153 		break;
154 	case '\f':
155 		fmt = "\\f";
156 		break;
157 	case '\r':
158 		fmt = "\\r";
159 		break;
160 	case '\\':
161 		fmt = "\\\\";
162 		break;
163 	default:
164 		if (isprint(c) || c == ' ')
165 			fmt = "%c";
166 		else
167 			fmt = "\\%03o";
168 	}
169 
170 	return fprintf(stream, fmt, c);
171 }
172 
173 static int
format_char(FILE * stream,struct value * value,struct value_dict * arguments)174 format_char(FILE *stream, struct value *value, struct value_dict *arguments)
175 {
176 	long lc;
177 	if (value_extract_word(value, &lc, arguments) < 0)
178 		return -1;
179 	return print_char(stream, (int) lc);
180 }
181 
182 static int
format_naked(FILE * stream,struct value * value,struct value_dict * arguments,int (* what)(FILE *,struct value *,struct value_dict *))183 format_naked(FILE *stream, struct value *value,
184 	     struct value_dict *arguments,
185 	     int (*what)(FILE *, struct value *, struct value_dict *))
186 {
187 	int written = 0;
188 	if (acc_fprintf(&written, stream, "'") < 0
189 	    || account_output(&written,
190 			      what(stream, value, arguments)) < 0
191 	    || acc_fprintf(&written, stream, "'") < 0)
192 		return -1;
193 
194 	return written;
195 }
196 
197 static int
format_double(FILE * stream,double value,enum int_fmt_t format)198 format_double(FILE *stream, double value, enum int_fmt_t format)
199 {
200 	if (format == INT_FMT_x)
201 		return fprintf(stream, "%a", value);
202 	else
203 		return fprintf(stream, "%f", value);
204 }
205 
206 static int
format_floating(FILE * stream,struct value * value,struct value_dict * arguments,enum int_fmt_t format)207 format_floating(FILE *stream, struct value *value, struct value_dict *arguments,
208 		enum int_fmt_t format)
209 {
210 	switch (value->type->type) {
211 		float f;
212 		double d;
213 	case ARGTYPE_FLOAT:
214 		if (read_float(value, &f, arguments) < 0)
215 			return -1;
216 		return format_double(stream, f, format);
217 	case ARGTYPE_DOUBLE:
218 		if (read_double(value, &d, arguments) < 0)
219 			return -1;
220 		return format_double(stream, d, format);
221 	default:
222 		abort();
223 	}
224 }
225 
226 struct format_argument_data
227 {
228 	struct value *value;
229 	struct value_dict *arguments;
230 };
231 
232 static int
format_argument_cb(FILE * stream,void * ptr)233 format_argument_cb(FILE *stream, void *ptr)
234 {
235 	struct format_argument_data *data = ptr;
236 	return format_argument(stream, data->value, data->arguments);
237 }
238 
239 static int
format_struct(FILE * stream,struct value * value,struct value_dict * arguments)240 format_struct(FILE *stream, struct value *value, struct value_dict *arguments)
241 {
242 	int written = 0;
243 	if (acc_fprintf(&written, stream, "{ ") < 0)
244 		return -1;
245 
246 	int need_delim = 0;
247 	size_t i;
248 	for (i = 0; i < type_struct_size(value->type); ++i) {
249 		struct value element;
250 		if (value_init_element(&element, value, i) < 0)
251 			return -1;
252 
253 		struct format_argument_data data = { &element, arguments };
254 		int o = delim_output(stream, &need_delim,
255 				     format_argument_cb, &data);
256 		value_destroy(&element);
257 		if (o < 0)
258 			return -1;
259 
260 		written += o;
261 	}
262 	if (acc_fprintf(&written, stream, " }") < 0)
263 		return -1;
264 	return written;
265 }
266 
267 static const char null_message[] = "nil";
268 int
format_pointer(FILE * stream,struct value * value,struct value_dict * arguments)269 format_pointer(FILE *stream, struct value *value, struct value_dict *arguments)
270 {
271 	if (value_is_zero(value, arguments))
272 		return fprintf(stream, null_message);
273 
274 	/* The following is for detecting recursion.  We keep track of
275 	 * the values that were already displayed.  Each time a
276 	 * pointer should be dereferenced, we compare its value to the
277 	 * value of each of the pointers dereferenced so far.  If one
278 	 * of them matches, instead of recursing, we just printf which
279 	 * superstructure this pointer recurses to.  */
280 	static struct vect pointers = {};
281 	if (pointers.elt_size == 0)
282 		VECT_INIT(&pointers, struct value *);
283 
284 	/* Trim number of expanded structures of the same type.  Even
285 	 * for non-recursive structure, we don't want to expand all of
286 	 * it if it's huge.  */
287 	size_t i;
288 	size_t len = vect_size(&pointers);
289 	assert(value->type->type == ARGTYPE_POINTER);
290 	struct arg_type_info *pointee = value->type->u.ptr_info.info;
291 	if (pointee->type == ARGTYPE_STRUCT) {
292 		size_t depth = 0;
293 		for (i = 0; i < len; ++i) {
294 			struct value *old
295 				= *VECT_ELEMENT(&pointers, struct value *, i);
296 			assert(old->type->type == ARGTYPE_POINTER);
297 			struct arg_type_info *old_pointee
298 				= old->type->u.ptr_info.info;
299 			if (old_pointee == pointee)
300 				depth++;
301 		}
302 		if (depth >= options.arraylen)
303 			return fprintf(stream, "...");
304 	}
305 
306 	for (i = len; i-- > 0 ;) {
307 		struct value **old = VECT_ELEMENT(&pointers, struct value *, i);
308 		int rc = value_equal(value, *old, arguments);
309 		if (rc < 0)
310 			return -1;
311 		if (rc > 0) {
312 			size_t reclevel = len - i - 1;
313 			char buf[reclevel + 1];
314 			memset(buf, '^', sizeof buf);
315 			buf[reclevel] = 0;
316 			return fprintf(stream, "recurse%s", buf);
317 		}
318 	}
319 
320 	/* OK, not a recursion.  Remember this value for tracking.  */
321 	if (VECT_PUSHBACK(&pointers, &value) < 0)
322 		return -1;
323 
324 	struct value element;
325 	int o;
326 	if (value_init_deref(&element, value) < 0) {
327 		o = -1;
328 		goto done;
329 	}
330 	o = format_argument(stream, &element, arguments);
331 	value_destroy(&element);
332 
333 done:
334 	VECT_POPBACK(&pointers, struct value *, NULL, NULL);
335 	return o;
336 }
337 
338 /*
339  * LENGTH is an expression whose evaluation will yield the actual
340  *    length of the array.
341  *
342  * MAXLEN is the actual maximum length that we care about
343  *
344  * BEFORE if LENGTH>MAXLEN, we display ellipsis.  We display it before
345  *    the closing parenthesis if BEFORE, otherwise after it.
346  *
347  * OPEN, CLOSE, DELIM are opening and closing parenthesis and element
348  *    delimiter.
349  */
350 static int
format_array(FILE * stream,struct value * value,struct value_dict * arguments,struct expr_node * length,size_t maxlen,int before,const char * open,const char * close,const char * delim)351 format_array(FILE *stream, struct value *value, struct value_dict *arguments,
352 	     struct expr_node *length, size_t maxlen, int before,
353 	     const char *open, const char *close, const char *delim)
354 {
355 	/* We need "long" to be long enough to cover the whole address
356 	 * space.  */
357 	(void)sizeof(char[1 - 2*(sizeof(long) < sizeof(void *))]);
358 	long l;
359 	if (expr_eval_word(length, value, arguments, &l) < 0)
360 		return -1;
361 	size_t len = (size_t)l;
362 
363 	int written = 0;
364 	if (acc_fprintf(&written, stream, "%s", open) < 0)
365 		return -1;
366 
367 	size_t i;
368 	for (i = 0; i < len && i <= maxlen; ++i) {
369 		if (i == maxlen) {
370 			if (before && acc_fprintf(&written, stream, "...") < 0)
371 				return -1;
372 			break;
373 		}
374 
375 		if (i > 0 && acc_fprintf(&written, stream, "%s", delim) < 0)
376 			return -1;
377 
378 		struct value element;
379 		if (value_init_element(&element, value, i) < 0)
380 			return -1;
381 		int o = format_argument(stream, &element, arguments);
382 		value_destroy(&element);
383 		if (o < 0)
384 			return -1;
385 		written += o;
386 	}
387 	if (acc_fprintf(&written, stream, "%s", close) < 0)
388 		return -1;
389 	if (i == maxlen && !before && acc_fprintf(&written, stream, "...") < 0)
390 		return -1;
391 
392 	return written;
393 }
394 
395 static int
toplevel_format_lens(struct lens * lens,FILE * stream,struct value * value,struct value_dict * arguments,enum int_fmt_t int_fmt)396 toplevel_format_lens(struct lens *lens, FILE *stream,
397 		     struct value *value, struct value_dict *arguments,
398 		     enum int_fmt_t int_fmt)
399 {
400 	switch (value->type->type) {
401 	case ARGTYPE_VOID:
402 		return fprintf(stream, "<void>");
403 
404 	case ARGTYPE_SHORT:
405 	case ARGTYPE_INT:
406 	case ARGTYPE_LONG:
407 		return format_integer(stream, value, int_fmt, arguments);
408 
409 	case ARGTYPE_USHORT:
410 	case ARGTYPE_UINT:
411 	case ARGTYPE_ULONG:
412 		if (int_fmt == INT_FMT_i || int_fmt == INT_FMT_default)
413 			int_fmt = INT_FMT_u;
414 		return format_integer(stream, value, int_fmt, arguments);
415 
416 	case ARGTYPE_CHAR:
417 		if (int_fmt == INT_FMT_default)
418 			return format_naked(stream, value, arguments,
419 					    &format_char);
420 		return format_integer(stream, value, int_fmt, arguments);
421 
422 	case ARGTYPE_FLOAT:
423 	case ARGTYPE_DOUBLE:
424 		return format_floating(stream, value, arguments, int_fmt);
425 
426 	case ARGTYPE_STRUCT:
427 		return format_struct(stream, value, arguments);
428 
429 	case ARGTYPE_POINTER:
430 		if (value_is_zero(value, arguments))
431 			return fprintf(stream, null_message);
432 		if (value->type->u.array_info.elt_type->type != ARGTYPE_VOID)
433 			return format_pointer(stream, value, arguments);
434 		return format_integer(stream, value, INT_FMT_x, arguments);
435 
436 	case ARGTYPE_ARRAY:
437 		return format_array(stream, value, arguments,
438 				    value->type->u.array_info.length,
439 				    options.arraylen, 1, "[ ", " ]", ", ");
440 	}
441 	abort();
442 }
443 
444 static int
default_lens_format_cb(struct lens * lens,FILE * stream,struct value * value,struct value_dict * arguments)445 default_lens_format_cb(struct lens *lens, FILE *stream,
446 		       struct value *value, struct value_dict *arguments)
447 {
448 	return toplevel_format_lens(lens, stream, value, arguments,
449 				    INT_FMT_default);
450 }
451 
452 struct lens default_lens = {
453 	.format_cb = default_lens_format_cb,
454 };
455 
456 
457 static int
blind_lens_format_cb(struct lens * lens,FILE * stream,struct value * value,struct value_dict * arguments)458 blind_lens_format_cb(struct lens *lens, FILE *stream,
459 		     struct value *value, struct value_dict *arguments)
460 {
461 	return 0;
462 }
463 
464 struct lens blind_lens = {
465 	.format_cb = blind_lens_format_cb,
466 };
467 
468 
469 static int
octal_lens_format_cb(struct lens * lens,FILE * stream,struct value * value,struct value_dict * arguments)470 octal_lens_format_cb(struct lens *lens, FILE *stream,
471 		     struct value *value, struct value_dict *arguments)
472 {
473 	return toplevel_format_lens(lens, stream, value, arguments, INT_FMT_o);
474 }
475 
476 struct lens octal_lens = {
477 	.format_cb = octal_lens_format_cb,
478 };
479 
480 
481 static int
hex_lens_format_cb(struct lens * lens,FILE * stream,struct value * value,struct value_dict * arguments)482 hex_lens_format_cb(struct lens *lens, FILE *stream,
483 		   struct value *value, struct value_dict *arguments)
484 {
485 	return toplevel_format_lens(lens, stream, value, arguments, INT_FMT_x);
486 }
487 
488 struct lens hex_lens = {
489 	.format_cb = hex_lens_format_cb,
490 };
491 
492 
493 static int
dec_lens_format_cb(struct lens * lens,FILE * stream,struct value * value,struct value_dict * arguments)494 dec_lens_format_cb(struct lens *lens, FILE *stream,
495 		   struct value *value, struct value_dict *arguments)
496 {
497 	return toplevel_format_lens(lens, stream, value, arguments, INT_FMT_u);
498 }
499 
500 struct lens dec_lens = {
501 	.format_cb = dec_lens_format_cb,
502 };
503 
504 
505 static int
guess_lens_format_cb(struct lens * lens,FILE * stream,struct value * value,struct value_dict * arguments)506 guess_lens_format_cb(struct lens *lens, FILE *stream,
507 		     struct value *value, struct value_dict *arguments)
508 {
509 	return toplevel_format_lens(lens, stream, value, arguments,
510 				    INT_FMT_unknown);
511 }
512 
513 struct lens guess_lens = {
514 	.format_cb = guess_lens_format_cb,
515 };
516 
517 
518 static int
bool_lens_format_cb(struct lens * lens,FILE * stream,struct value * value,struct value_dict * arguments)519 bool_lens_format_cb(struct lens *lens, FILE *stream,
520 		    struct value *value, struct value_dict *arguments)
521 {
522 	switch (value->type->type) {
523 	case ARGTYPE_VOID:
524 	case ARGTYPE_FLOAT:
525 	case ARGTYPE_DOUBLE:
526 	case ARGTYPE_STRUCT:
527 	case ARGTYPE_POINTER:
528 	case ARGTYPE_ARRAY:
529 		return toplevel_format_lens(lens, stream, value,
530 					    arguments, INT_FMT_default);
531 
532 		int zero;
533 	case ARGTYPE_SHORT:
534 	case ARGTYPE_INT:
535 	case ARGTYPE_LONG:
536 	case ARGTYPE_USHORT:
537 	case ARGTYPE_UINT:
538 	case ARGTYPE_ULONG:
539 	case ARGTYPE_CHAR:
540 		if ((zero = value_is_zero(value, arguments)) < 0)
541 			return -1;
542 		if (zero)
543 			return fprintf(stream, "false");
544 		else
545 			return fprintf(stream, "true");
546 	}
547 	abort();
548 }
549 
550 struct lens bool_lens = {
551 	.format_cb = bool_lens_format_cb,
552 };
553 
554 static int
redispatch_as_array(struct lens * lens,FILE * stream,struct value * value,struct value_dict * arguments,int (* cb)(struct lens *,FILE *,struct value *,struct value_dict *))555 redispatch_as_array(struct lens *lens, FILE *stream,
556 		    struct value *value, struct value_dict *arguments,
557 		    int (*cb)(struct lens *, FILE *,
558 			      struct value *, struct value_dict *))
559 {
560 	struct arg_type_info info[2];
561 	type_init_array(&info[1], value->type->u.ptr_info.info, 0,
562 			expr_node_zero(), 0);
563 	type_init_pointer(&info[0], &info[1], 0);
564 	info->lens = lens;
565 	info->own_lens = 0;
566 	struct value tmp;
567 	if (value_clone(&tmp, value) < 0)
568 		return -1;
569 	value_set_type(&tmp, info, 0);
570 	int ret = cb(lens, stream, &tmp, arguments);
571 	type_destroy(&info[0]);
572 	type_destroy(&info[1]);
573 	value_destroy(&tmp);
574 	return ret;
575 }
576 
577 static int
format_wchar(FILE * stream,struct value * value,struct value_dict * arguments)578 format_wchar(FILE *stream, struct value *value, struct value_dict *arguments)
579 {
580 	long l;
581 	if (value_extract_word(value, &l, arguments) < 0)
582 		return -1;
583 	wchar_t wc = (wchar_t) l;
584 	char buf[MB_CUR_MAX + 1];
585 
586 	int c = wctomb(buf, wc);
587 	if (c < 0)
588 		return -1;
589 	if (c == 1)
590 		return print_char(stream, buf[0]);
591 
592 	buf[c] = 0;
593 	if (fprintf(stream, "%s", buf) < 0)
594 		return -1;
595 
596 	c = wcwidth(wc);
597 	return c >= 0 ? c : 0;
598 }
599 
600 static int
string_lens_format_cb(struct lens * lens,FILE * stream,struct value * value,struct value_dict * arguments)601 string_lens_format_cb(struct lens *lens, FILE *stream,
602 		      struct value *value, struct value_dict *arguments)
603 {
604 	switch (value->type->type) {
605 	case ARGTYPE_POINTER:
606 		/* This should really be written as either "string",
607 		 * or, if lens, then string(array(char, zero)*).  But
608 		 * I suspect people are so used to the char * C idiom,
609 		 * that string(char *) might actually turn up.  So
610 		 * let's just support it.  */
611 		switch ((int) value->type->u.ptr_info.info->type)
612 		case ARGTYPE_CHAR:
613 		case ARGTYPE_SHORT:
614 		case ARGTYPE_USHORT:
615 		case ARGTYPE_INT:
616 		case ARGTYPE_UINT:
617 		case ARGTYPE_LONG:
618 		case ARGTYPE_ULONG:
619 			return redispatch_as_array(lens, stream, value,
620 						   arguments,
621 						   &string_lens_format_cb);
622 
623 		/* Otherwise dispatch to whatever the default for the
624 		 * pointee is--most likely this will again be us.  */
625 		/* Fall through.  */
626 	case ARGTYPE_VOID:
627 	case ARGTYPE_FLOAT:
628 	case ARGTYPE_DOUBLE:
629 	case ARGTYPE_STRUCT:
630 		return toplevel_format_lens(lens, stream, value,
631 					    arguments, INT_FMT_default);
632 
633 	case ARGTYPE_SHORT:
634 	case ARGTYPE_INT:
635 	case ARGTYPE_LONG:
636 	case ARGTYPE_USHORT:
637 	case ARGTYPE_UINT:
638 	case ARGTYPE_ULONG:
639 		if (value->parent != NULL && value->type->lens == NULL)
640 			return format_wchar(stream, value, arguments);
641 		else
642 			return format_naked(stream, value, arguments,
643 					    &format_wchar);
644 
645 	case ARGTYPE_CHAR:
646 		return format_char(stream, value, arguments);
647 
648 	case ARGTYPE_ARRAY:
649 		return format_array(stream, value, arguments,
650 				    value->type->u.array_info.length,
651 				    options.strlen, 0, "\"", "\"", "");
652 	}
653 	abort();
654 }
655 
656 struct lens string_lens = {
657 	.format_cb = string_lens_format_cb,
658 };
659 
660 static int
out_bits(FILE * stream,size_t low,size_t high)661 out_bits(FILE *stream, size_t low, size_t high)
662 {
663 	if (low == high)
664 		return fprintf(stream, "%zd", low);
665 	else
666 		return fprintf(stream, "%zd-%zd", low, high);
667 }
668 
669 static int
bitvect_lens_format_cb(struct lens * lens,FILE * stream,struct value * value,struct value_dict * arguments)670 bitvect_lens_format_cb(struct lens *lens, FILE *stream,
671 		       struct value *value, struct value_dict *arguments)
672 {
673 	unsigned char *data = value_get_data(value, arguments);
674 	if (data == NULL)
675 		return -1;
676 	size_t sz = type_sizeof(value->inferior, value->type);
677 	if (sz == (size_t)-1)
678 		return -1;
679 
680 	size_t i;
681 	unsigned char buf[sz];
682 	switch ((int)value->type->type) {
683 		union bitvect_integral_64
684 		{
685 			uint8_t u8;
686 			uint16_t u16;
687 			uint32_t u32;
688 			uint64_t u64;
689 			unsigned char buf[0];
690 		} bv;
691 
692 	case ARGTYPE_POINTER:
693 		return format_pointer(stream, value, arguments);
694 
695 	case ARGTYPE_STRUCT:
696 	case ARGTYPE_ARRAY:
697 		break;
698 
699 	default:
700 		assert(sz <= sizeof(bv));
701 		memmove(bv.buf, data, sz);
702 
703 		if (sz == 1)
704 			bv.u64 = bv.u8;
705 		else if (sz == 2)
706 			bv.u64 = bv.u16;
707 		else if (sz == 4)
708 			bv.u64 = bv.u32;
709 
710 		for (i = 0; i < sz; ++i) {
711 			buf[i] = bv.u64 & 0xff;
712 			bv.u64 >>= 8;
713 		}
714 		data = buf;
715 	}
716 
717 	size_t bits = 0;
718 	for (i = 0; i < sz; ++i)
719 		bits += bitcount(data[i]);
720 
721 	/* If there's more 1's than 0's, show inverse.  */
722 	unsigned neg = bits > sz * 4 ? 0xff : 0x00;
723 
724 	int o = 0;
725 	if (acc_fprintf(&o, stream, "%s<", &"~"[neg == 0x00]) < 0)
726 		return -1;
727 
728 	size_t bitno = 0;
729 	ssize_t low = -1;
730 	for (i = 0; i < sz; ++i) {
731 		unsigned char m;
732 		unsigned char d = data[i] ^ neg;
733 		for (m = 0x01; m != 0; m <<= 1) {
734 			int bit = !!(m & d);
735 			if (low < 0) {
736 				if (bit) {
737 					if (low == -2
738 					    && acc_fprintf(&o, stream, ",") < 0)
739 						return -1;
740 					low = bitno;
741 				}
742 			} else if (!bit) {
743 				if (account_output(&o, out_bits(stream, low,
744 								bitno-1)) < 0)
745 					return -1;
746 				low = -2;
747 			}
748 			bitno++;
749 		}
750 	}
751 	if (low >= 0 && account_output(&o, out_bits(stream, low, bitno-1)) < 0)
752 		return -1;
753 
754 	if (fputc('>', stream) < 0)
755 		return -1;
756 	o += 1;
757 
758 	return o;
759 }
760 
761 struct lens bitvect_lens = {
762 	.format_cb = bitvect_lens_format_cb,
763 };
764