194078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata/*
294078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata * This file is part of ltrace.
3d8286ed3496bcd69cd4796f57a5b5c04859d2378Petr Machata * Copyright (C) 2011,2012,2013 Petr Machata, Red Hat Inc.
494078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata * Copyright (C) 1998,2004,2007,2008,2009 Juan Cespedes
594078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata * Copyright (C) 2006 Ian Wienand
694078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata * Copyright (C) 2006 Steve Fink
794078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata *
894078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata * This program is free software; you can redistribute it and/or
994078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata * modify it under the terms of the GNU General Public License as
1094078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata * published by the Free Software Foundation; either version 2 of the
1194078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata * License, or (at your option) any later version.
1294078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata *
1394078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata * This program is distributed in the hope that it will be useful, but
1494078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata * WITHOUT ANY WARRANTY; without even the implied warranty of
1594078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1694078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata * General Public License for more details.
1794078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata *
1894078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata * You should have received a copy of the GNU General Public License
1994078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata * along with this program; if not, write to the Free Software
2094078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
2194078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata * 02110-1301 USA
2294078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata */
2394078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata
24caccda07541df0790887311d898405b2e4d78a5fPetr Machata#define _XOPEN_SOURCE /* For wcwidth from wchar.h.  */
25caccda07541df0790887311d898405b2e4d78a5fPetr Machata
267bafff09cc66e23519512a54e2d1ebd3664a1a70Steve Fink#include <ctype.h>
275e01f654d83a95f2acffa86df57a4c2db9b0cae9Juan Cespedes#include <stdlib.h>
2894078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata#include <assert.h>
2994078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata#include <inttypes.h>
3094078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata#include <stdarg.h>
3194078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata#include <stdio.h>
32307b90b158b79ba3aae61d5c6612b4769b10be5fPetr Machata#include <string.h>
33caccda07541df0790887311d898405b2e4d78a5fPetr Machata#include <wchar.h>
345e01f654d83a95f2acffa86df57a4c2db9b0cae9Juan Cespedes
351721fc956dfe30fd5dc5a49238c376ccbfdfd9d9Petr Machata#include "bits.h"
3694078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata#include "expr.h"
37caccda07541df0790887311d898405b2e4d78a5fPetr Machata#include "lens_default.h"
38caccda07541df0790887311d898405b2e4d78a5fPetr Machata#include "options.h"
39caccda07541df0790887311d898405b2e4d78a5fPetr Machata#include "output.h"
40000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata#include "type.h"
41caccda07541df0790887311d898405b2e4d78a5fPetr Machata#include "value.h"
42d7b2292789462475ead5986c2dea25a0b8623f7dPetr Machata#include "zero.h"
435e01f654d83a95f2acffa86df57a4c2db9b0cae9Juan Cespedes
4494078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata#define READER(NAME, TYPE)						\
4594078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	static int							\
4694078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	NAME(struct value *value, TYPE *ret, struct value_dict *arguments) \
4794078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	{								\
4894078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		union {							\
4994078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata			TYPE val;					\
5094078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata			unsigned char buf[0];				\
5194078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		} u;							\
5294078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		if (value_extract_buf(value, u.buf, arguments) < 0)	\
5394078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata			return -1;					\
5494078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		*ret = u.val;						\
5594078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		return 0;						\
56a413e5b8880de643a83ad124d078091c0956fe1dJuan Cespedes	}
5765b53df7fa2577c4138aef86c115873eab684a0aSteve Fink
5894078ecce3a103c28457e6f90f1e5b0dacc61146Petr MachataREADER(read_float, float)
5994078ecce3a103c28457e6f90f1e5b0dacc61146Petr MachataREADER(read_double, double)
6094078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata
6194078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata#undef READER
6294078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata
6394078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata#define HANDLE_WIDTH(BITS)						\
6494078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	do {								\
6594078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		long l;							\
6694078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		if (value_extract_word(value, &l, arguments) < 0)	\
6794078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata			return -1;					\
6894078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		int##BITS##_t i = l;					\
69e773f634dc1283a47786788e747aa5217f61c6fcPetr Machata		uint64_t v = (uint64_t)(uint##BITS##_t)i;		\
7094078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		switch (format) {					\
7194078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		case INT_FMT_unknown:					\
72c1e4186bc03fff3ddc2682bc10b11075381a950bPetr Machata			if (l < -10000 || l > 10000)			\
7394078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		case INT_FMT_x:						\
74e773f634dc1283a47786788e747aa5217f61c6fcPetr Machata			return fprintf(stream, "%#"PRIx64, v);		\
7594078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		case INT_FMT_i:						\
76e773f634dc1283a47786788e747aa5217f61c6fcPetr Machata		case INT_FMT_default:					\
7794078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata			return fprintf(stream, "%"PRIi##BITS, i);	\
7894078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		case INT_FMT_u:						\
79e773f634dc1283a47786788e747aa5217f61c6fcPetr Machata			return fprintf(stream, "%"PRIu64, v);		\
8094078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		case INT_FMT_o:						\
81e773f634dc1283a47786788e747aa5217f61c6fcPetr Machata			return fprintf(stream, "0%"PRIo64, v);		\
8294078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		}							\
8394078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	} while (0)
8494078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata
8594078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machataenum int_fmt_t
8694078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata{
8794078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	INT_FMT_i,
8894078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	INT_FMT_u,
8994078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	INT_FMT_o,
9094078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	INT_FMT_x,
9194078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	INT_FMT_unknown,
92e773f634dc1283a47786788e747aa5217f61c6fcPetr Machata	INT_FMT_default,
9394078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata};
9494078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata
9594078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machatastatic int
9694078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machataformat_integer(FILE *stream, struct value *value, enum int_fmt_t format,
9794078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	       struct value_dict *arguments)
9894078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata{
9994078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	switch (type_sizeof(value->inferior, value->type)) {
10094078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata
10194078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	case 1: HANDLE_WIDTH(8);
10294078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	case 2: HANDLE_WIDTH(16);
10394078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	case 4: HANDLE_WIDTH(32);
10494078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	case 8: HANDLE_WIDTH(64);
10594078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata
10694078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	default:
10794078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		assert(!"unsupported integer width");
10894078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		abort();
10994078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata
11094078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	case -1:
11194078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		return -1;
11294078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	}
1136a48a6d7f428cd7f0796477a3892603a83fcce99Steve Fink}
1146a48a6d7f428cd7f0796477a3892603a83fcce99Steve Fink
11594078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata#undef HANDLE_WIDTH
11694078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata
117f13505251e6402460f6cc7ec84e0d8ca91607b4fJuan Cespedesstatic int
11894078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machataacc_fprintf(int *countp, FILE *stream, const char *format, ...)
11994078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata{
12094078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	va_list pa;
12194078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	va_start(pa, format);
122adec201a52c240cf4b533c05106aedddc911ca76Petr Machata	int i = account_output(countp, vfprintf(stream, format, pa));
12394078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	va_end(pa);
12494078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata
12594078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	return i;
1261150bc4b812f0150e832607b8724b023d6d7d575Steve Fink}
127a413e5b8880de643a83ad124d078091c0956fe1dJuan Cespedes
128f13505251e6402460f6cc7ec84e0d8ca91607b4fJuan Cespedesstatic int
129c00837c2928da53a3515b107399b742ea157e78aPetr Machataprint_char(FILE *stream, int c)
13094078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata{
13194078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	const char *fmt;
13294078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	switch (c) {
13394078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	case -1:
13494078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		fmt = "EOF";
13594078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		break;
13694078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	case 0:
13794078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		fmt = "\\0";
13894078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		break;
13994078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	case '\a':
14094078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		fmt = "\\a";
14194078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		break;
14294078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	case '\b':
14394078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		fmt = "\\b";
14494078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		break;
14594078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	case '\t':
14694078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		fmt = "\\t";
14794078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		break;
14894078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	case '\n':
14994078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		fmt = "\\n";
15094078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		break;
15194078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	case '\v':
15294078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		fmt = "\\v";
15394078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		break;
15494078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	case '\f':
15594078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		fmt = "\\f";
15694078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		break;
15794078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	case '\r':
15894078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		fmt = "\\r";
15994078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		break;
16094078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	case '\\':
16194078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		fmt = "\\\\";
16294078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		break;
16394078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	default:
16494078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		if (isprint(c) || c == ' ')
16594078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata			fmt = "%c";
16694078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		else
167987d27b3e97b208874ca967d536dc862dae2bd43Petr Machata			fmt = "\\%03o";
168a413e5b8880de643a83ad124d078091c0956fe1dJuan Cespedes	}
169a413e5b8880de643a83ad124d078091c0956fe1dJuan Cespedes
170987d27b3e97b208874ca967d536dc862dae2bd43Petr Machata	return fprintf(stream, fmt, c);
171e3f4a984db115979e09414b7281da98399dd8949Petr Machata}
172e3f4a984db115979e09414b7281da98399dd8949Petr Machata
173e3f4a984db115979e09414b7281da98399dd8949Petr Machatastatic int
174c00837c2928da53a3515b107399b742ea157e78aPetr Machataformat_char(FILE *stream, struct value *value, struct value_dict *arguments)
175c00837c2928da53a3515b107399b742ea157e78aPetr Machata{
176c00837c2928da53a3515b107399b742ea157e78aPetr Machata	long lc;
177c00837c2928da53a3515b107399b742ea157e78aPetr Machata	if (value_extract_word(value, &lc, arguments) < 0)
178c00837c2928da53a3515b107399b742ea157e78aPetr Machata		return -1;
179c00837c2928da53a3515b107399b742ea157e78aPetr Machata	return print_char(stream, (int) lc);
180c00837c2928da53a3515b107399b742ea157e78aPetr Machata}
181c00837c2928da53a3515b107399b742ea157e78aPetr Machata
182c00837c2928da53a3515b107399b742ea157e78aPetr Machatastatic int
183c00837c2928da53a3515b107399b742ea157e78aPetr Machataformat_naked(FILE *stream, struct value *value,
184c00837c2928da53a3515b107399b742ea157e78aPetr Machata	     struct value_dict *arguments,
185c00837c2928da53a3515b107399b742ea157e78aPetr Machata	     int (*what)(FILE *, struct value *, struct value_dict *))
186e3f4a984db115979e09414b7281da98399dd8949Petr Machata{
187e3f4a984db115979e09414b7281da98399dd8949Petr Machata	int written = 0;
188e3f4a984db115979e09414b7281da98399dd8949Petr Machata	if (acc_fprintf(&written, stream, "'") < 0
189adec201a52c240cf4b533c05106aedddc911ca76Petr Machata	    || account_output(&written,
190c00837c2928da53a3515b107399b742ea157e78aPetr Machata			      what(stream, value, arguments)) < 0
191e3f4a984db115979e09414b7281da98399dd8949Petr Machata	    || acc_fprintf(&written, stream, "'") < 0)
19294078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		return -1;
193e3f4a984db115979e09414b7281da98399dd8949Petr Machata
19494078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	return written;
195e4b3263fb2b32eb5ee0f693fc223ed8c363fbd69Steve Fink}
196e4b3263fb2b32eb5ee0f693fc223ed8c363fbd69Steve Fink
197f13505251e6402460f6cc7ec84e0d8ca91607b4fJuan Cespedesstatic int
198f197727e6247be1ee08d2a667931aee20512ae18Petr Machataformat_double(FILE *stream, double value, enum int_fmt_t format)
199f197727e6247be1ee08d2a667931aee20512ae18Petr Machata{
200f197727e6247be1ee08d2a667931aee20512ae18Petr Machata	if (format == INT_FMT_x)
201f197727e6247be1ee08d2a667931aee20512ae18Petr Machata		return fprintf(stream, "%a", value);
202f197727e6247be1ee08d2a667931aee20512ae18Petr Machata	else
203f197727e6247be1ee08d2a667931aee20512ae18Petr Machata		return fprintf(stream, "%f", value);
204f197727e6247be1ee08d2a667931aee20512ae18Petr Machata}
205f197727e6247be1ee08d2a667931aee20512ae18Petr Machata
206f197727e6247be1ee08d2a667931aee20512ae18Petr Machatastatic int
207f197727e6247be1ee08d2a667931aee20512ae18Petr Machataformat_floating(FILE *stream, struct value *value, struct value_dict *arguments,
208f197727e6247be1ee08d2a667931aee20512ae18Petr Machata		enum int_fmt_t format)
20994078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata{
21094078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	switch (value->type->type) {
21194078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		float f;
21294078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		double d;
21394078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	case ARGTYPE_FLOAT:
21494078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		if (read_float(value, &f, arguments) < 0)
21594078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata			return -1;
216f197727e6247be1ee08d2a667931aee20512ae18Petr Machata		return format_double(stream, f, format);
21794078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	case ARGTYPE_DOUBLE:
21894078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		if (read_double(value, &d, arguments) < 0)
21994078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata			return -1;
220f197727e6247be1ee08d2a667931aee20512ae18Petr Machata		return format_double(stream, d, format);
22194078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	default:
22294078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		abort();
223a413e5b8880de643a83ad124d078091c0956fe1dJuan Cespedes	}
2247bafff09cc66e23519512a54e2d1ebd3664a1a70Steve Fink}
2257bafff09cc66e23519512a54e2d1ebd3664a1a70Steve Fink
226f7c46bba61bb830e5a283ef8b0174f33c3989821Petr Machatastruct format_argument_data
227f7c46bba61bb830e5a283ef8b0174f33c3989821Petr Machata{
228f7c46bba61bb830e5a283ef8b0174f33c3989821Petr Machata	struct value *value;
229f7c46bba61bb830e5a283ef8b0174f33c3989821Petr Machata	struct value_dict *arguments;
230f7c46bba61bb830e5a283ef8b0174f33c3989821Petr Machata};
231f7c46bba61bb830e5a283ef8b0174f33c3989821Petr Machata
232f7c46bba61bb830e5a283ef8b0174f33c3989821Petr Machatastatic int
233f7c46bba61bb830e5a283ef8b0174f33c3989821Petr Machataformat_argument_cb(FILE *stream, void *ptr)
234f7c46bba61bb830e5a283ef8b0174f33c3989821Petr Machata{
235f7c46bba61bb830e5a283ef8b0174f33c3989821Petr Machata	struct format_argument_data *data = ptr;
236f7c46bba61bb830e5a283ef8b0174f33c3989821Petr Machata	return format_argument(stream, data->value, data->arguments);
237f7c46bba61bb830e5a283ef8b0174f33c3989821Petr Machata}
238f7c46bba61bb830e5a283ef8b0174f33c3989821Petr Machata
239f13505251e6402460f6cc7ec84e0d8ca91607b4fJuan Cespedesstatic int
24094078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machataformat_struct(FILE *stream, struct value *value, struct value_dict *arguments)
24194078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata{
24294078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	int written = 0;
24394078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	if (acc_fprintf(&written, stream, "{ ") < 0)
24494078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		return -1;
245f7c46bba61bb830e5a283ef8b0174f33c3989821Petr Machata
246f7c46bba61bb830e5a283ef8b0174f33c3989821Petr Machata	int need_delim = 0;
24794078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	size_t i;
24894078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	for (i = 0; i < type_struct_size(value->type); ++i) {
24994078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		struct value element;
25094078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		if (value_init_element(&element, value, i) < 0)
25194078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata			return -1;
252f7c46bba61bb830e5a283ef8b0174f33c3989821Petr Machata
253f7c46bba61bb830e5a283ef8b0174f33c3989821Petr Machata		struct format_argument_data data = { &element, arguments };
254f7c46bba61bb830e5a283ef8b0174f33c3989821Petr Machata		int o = delim_output(stream, &need_delim,
255f7c46bba61bb830e5a283ef8b0174f33c3989821Petr Machata				     format_argument_cb, &data);
2568904cdcbac783406d6f6d601d8447961b67068cePetr Machata		value_destroy(&element);
25794078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		if (o < 0)
25894078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata			return -1;
259f7c46bba61bb830e5a283ef8b0174f33c3989821Petr Machata
26094078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		written += o;
261a413e5b8880de643a83ad124d078091c0956fe1dJuan Cespedes	}
26294078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	if (acc_fprintf(&written, stream, " }") < 0)
26394078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		return -1;
26494078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	return written;
26594078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata}
2666a3e24dc1709530e59dd6ae3e91ced1c221fe1b9Steve Fink
267d8286ed3496bcd69cd4796f57a5b5c04859d2378Petr Machatastatic const char null_message[] = "nil";
26894078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machataint
26994078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machataformat_pointer(FILE *stream, struct value *value, struct value_dict *arguments)
27094078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata{
27126c0c9413c2558c3f95cb466b3734ea5ba57444dPetr Machata	if (value_is_zero(value, arguments))
272d8286ed3496bcd69cd4796f57a5b5c04859d2378Petr Machata		return fprintf(stream, null_message);
27326c0c9413c2558c3f95cb466b3734ea5ba57444dPetr Machata
274307b90b158b79ba3aae61d5c6612b4769b10be5fPetr Machata	/* The following is for detecting recursion.  We keep track of
275307b90b158b79ba3aae61d5c6612b4769b10be5fPetr Machata	 * the values that were already displayed.  Each time a
276307b90b158b79ba3aae61d5c6612b4769b10be5fPetr Machata	 * pointer should be dereferenced, we compare its value to the
277307b90b158b79ba3aae61d5c6612b4769b10be5fPetr Machata	 * value of each of the pointers dereferenced so far.  If one
278307b90b158b79ba3aae61d5c6612b4769b10be5fPetr Machata	 * of them matches, instead of recursing, we just printf which
279307b90b158b79ba3aae61d5c6612b4769b10be5fPetr Machata	 * superstructure this pointer recurses to.  */
280307b90b158b79ba3aae61d5c6612b4769b10be5fPetr Machata	static struct vect pointers = {};
281307b90b158b79ba3aae61d5c6612b4769b10be5fPetr Machata	if (pointers.elt_size == 0)
282307b90b158b79ba3aae61d5c6612b4769b10be5fPetr Machata		VECT_INIT(&pointers, struct value *);
283307b90b158b79ba3aae61d5c6612b4769b10be5fPetr Machata
2846248a0ac394b2aa3b2267eaa1220a90b609b6f86Petr Machata	/* Trim number of expanded structures of the same type.  Even
2856248a0ac394b2aa3b2267eaa1220a90b609b6f86Petr Machata	 * for non-recursive structure, we don't want to expand all of
2866248a0ac394b2aa3b2267eaa1220a90b609b6f86Petr Machata	 * it if it's huge.  */
287307b90b158b79ba3aae61d5c6612b4769b10be5fPetr Machata	size_t i;
2886248a0ac394b2aa3b2267eaa1220a90b609b6f86Petr Machata	size_t len = vect_size(&pointers);
2896248a0ac394b2aa3b2267eaa1220a90b609b6f86Petr Machata	assert(value->type->type == ARGTYPE_POINTER);
2906248a0ac394b2aa3b2267eaa1220a90b609b6f86Petr Machata	struct arg_type_info *pointee = value->type->u.ptr_info.info;
2916248a0ac394b2aa3b2267eaa1220a90b609b6f86Petr Machata	if (pointee->type == ARGTYPE_STRUCT) {
2926248a0ac394b2aa3b2267eaa1220a90b609b6f86Petr Machata		size_t depth = 0;
2936248a0ac394b2aa3b2267eaa1220a90b609b6f86Petr Machata		for (i = 0; i < len; ++i) {
2946248a0ac394b2aa3b2267eaa1220a90b609b6f86Petr Machata			struct value *old
2956248a0ac394b2aa3b2267eaa1220a90b609b6f86Petr Machata				= *VECT_ELEMENT(&pointers, struct value *, i);
2966248a0ac394b2aa3b2267eaa1220a90b609b6f86Petr Machata			assert(old->type->type == ARGTYPE_POINTER);
2976248a0ac394b2aa3b2267eaa1220a90b609b6f86Petr Machata			struct arg_type_info *old_pointee
2986248a0ac394b2aa3b2267eaa1220a90b609b6f86Petr Machata				= old->type->u.ptr_info.info;
2996248a0ac394b2aa3b2267eaa1220a90b609b6f86Petr Machata			if (old_pointee == pointee)
3006248a0ac394b2aa3b2267eaa1220a90b609b6f86Petr Machata				depth++;
3016248a0ac394b2aa3b2267eaa1220a90b609b6f86Petr Machata		}
3026248a0ac394b2aa3b2267eaa1220a90b609b6f86Petr Machata		if (depth >= options.arraylen)
3036248a0ac394b2aa3b2267eaa1220a90b609b6f86Petr Machata			return fprintf(stream, "...");
3046248a0ac394b2aa3b2267eaa1220a90b609b6f86Petr Machata	}
3056248a0ac394b2aa3b2267eaa1220a90b609b6f86Petr Machata
306307b90b158b79ba3aae61d5c6612b4769b10be5fPetr Machata	for (i = len; i-- > 0 ;) {
307307b90b158b79ba3aae61d5c6612b4769b10be5fPetr Machata		struct value **old = VECT_ELEMENT(&pointers, struct value *, i);
308307b90b158b79ba3aae61d5c6612b4769b10be5fPetr Machata		int rc = value_equal(value, *old, arguments);
309307b90b158b79ba3aae61d5c6612b4769b10be5fPetr Machata		if (rc < 0)
310307b90b158b79ba3aae61d5c6612b4769b10be5fPetr Machata			return -1;
311307b90b158b79ba3aae61d5c6612b4769b10be5fPetr Machata		if (rc > 0) {
312307b90b158b79ba3aae61d5c6612b4769b10be5fPetr Machata			size_t reclevel = len - i - 1;
313307b90b158b79ba3aae61d5c6612b4769b10be5fPetr Machata			char buf[reclevel + 1];
314307b90b158b79ba3aae61d5c6612b4769b10be5fPetr Machata			memset(buf, '^', sizeof buf);
315307b90b158b79ba3aae61d5c6612b4769b10be5fPetr Machata			buf[reclevel] = 0;
316307b90b158b79ba3aae61d5c6612b4769b10be5fPetr Machata			return fprintf(stream, "recurse%s", buf);
317307b90b158b79ba3aae61d5c6612b4769b10be5fPetr Machata		}
318307b90b158b79ba3aae61d5c6612b4769b10be5fPetr Machata	}
319307b90b158b79ba3aae61d5c6612b4769b10be5fPetr Machata
320307b90b158b79ba3aae61d5c6612b4769b10be5fPetr Machata	/* OK, not a recursion.  Remember this value for tracking.  */
321307b90b158b79ba3aae61d5c6612b4769b10be5fPetr Machata	if (VECT_PUSHBACK(&pointers, &value) < 0)
322307b90b158b79ba3aae61d5c6612b4769b10be5fPetr Machata		return -1;
323307b90b158b79ba3aae61d5c6612b4769b10be5fPetr Machata
32494078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	struct value element;
32526c0c9413c2558c3f95cb466b3734ea5ba57444dPetr Machata	int o;
32626c0c9413c2558c3f95cb466b3734ea5ba57444dPetr Machata	if (value_init_deref(&element, value) < 0) {
32726c0c9413c2558c3f95cb466b3734ea5ba57444dPetr Machata		o = -1;
32826c0c9413c2558c3f95cb466b3734ea5ba57444dPetr Machata		goto done;
32926c0c9413c2558c3f95cb466b3734ea5ba57444dPetr Machata	}
33026c0c9413c2558c3f95cb466b3734ea5ba57444dPetr Machata	o = format_argument(stream, &element, arguments);
3318904cdcbac783406d6f6d601d8447961b67068cePetr Machata	value_destroy(&element);
33226c0c9413c2558c3f95cb466b3734ea5ba57444dPetr Machata
33326c0c9413c2558c3f95cb466b3734ea5ba57444dPetr Machatadone:
334c28410e3f4bb4d40e48d58440800fbb080b2e3d6Petr Machata	VECT_POPBACK(&pointers, struct value *, NULL, NULL);
3358904cdcbac783406d6f6d601d8447961b67068cePetr Machata	return o;
3366a3e24dc1709530e59dd6ae3e91ced1c221fe1b9Steve Fink}
3376a3e24dc1709530e59dd6ae3e91ced1c221fe1b9Steve Fink
33894078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata/*
33994078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata * LENGTH is an expression whose evaluation will yield the actual
34094078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata *    length of the array.
34194078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata *
34294078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata * MAXLEN is the actual maximum length that we care about
34394078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata *
34494078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata * BEFORE if LENGTH>MAXLEN, we display ellipsis.  We display it before
34594078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata *    the closing parenthesis if BEFORE, otherwise after it.
34694078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata *
34794078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata * OPEN, CLOSE, DELIM are opening and closing parenthesis and element
34894078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata *    delimiter.
34994078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata */
350c00837c2928da53a3515b107399b742ea157e78aPetr Machatastatic int
35194078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machataformat_array(FILE *stream, struct value *value, struct value_dict *arguments,
35294078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	     struct expr_node *length, size_t maxlen, int before,
35394078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	     const char *open, const char *close, const char *delim)
35494078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata{
35594078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	/* We need "long" to be long enough to cover the whole address
35694078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	 * space.  */
357a77b267abb870c935f9b4187ca31409fa5eb9dcbPeter Wu	(void)sizeof(char[1 - 2*(sizeof(long) < sizeof(void *))]);
35831af32cfcd61671cbb5e567870103766b3231521Petr Machata	long l;
359d7b2292789462475ead5986c2dea25a0b8623f7dPetr Machata	if (expr_eval_word(length, value, arguments, &l) < 0)
360d7b2292789462475ead5986c2dea25a0b8623f7dPetr Machata		return -1;
36194078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	size_t len = (size_t)l;
36294078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata
36394078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	int written = 0;
36494078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	if (acc_fprintf(&written, stream, "%s", open) < 0)
36594078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		return -1;
3665e01f654d83a95f2acffa86df57a4c2db9b0cae9Juan Cespedes
36794078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	size_t i;
36894078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	for (i = 0; i < len && i <= maxlen; ++i) {
36994078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		if (i == maxlen) {
37094078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata			if (before && acc_fprintf(&written, stream, "...") < 0)
37194078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata				return -1;
37294078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata			break;
37394078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		}
37494078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata
37594078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		if (i > 0 && acc_fprintf(&written, stream, "%s", delim) < 0)
37694078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata			return -1;
37794078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata
37894078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		struct value element;
37994078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		if (value_init_element(&element, value, i) < 0)
38094078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata			return -1;
381f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata		int o = format_argument(stream, &element, arguments);
3828904cdcbac783406d6f6d601d8447961b67068cePetr Machata		value_destroy(&element);
38394078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		if (o < 0)
38494078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata			return -1;
38594078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		written += o;
38694078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	}
38794078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	if (acc_fprintf(&written, stream, "%s", close) < 0)
38894078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		return -1;
38994078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	if (i == maxlen && !before && acc_fprintf(&written, stream, "...") < 0)
39094078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		return -1;
39194078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata
39294078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	return written;
39394078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata}
39494078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata
39531af32cfcd61671cbb5e567870103766b3231521Petr Machatastatic int
39631af32cfcd61671cbb5e567870103766b3231521Petr Machatatoplevel_format_lens(struct lens *lens, FILE *stream,
397ce034981e2880eecb8a196c78182dfb4ae67850fPetr Machata		     struct value *value, struct value_dict *arguments,
398ce034981e2880eecb8a196c78182dfb4ae67850fPetr Machata		     enum int_fmt_t int_fmt)
39994078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata{
40094078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	switch (value->type->type) {
4012d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand	case ARGTYPE_VOID:
40294078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		return fprintf(stream, "<void>");
40394078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata
40494078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	case ARGTYPE_SHORT:
4052d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand	case ARGTYPE_INT:
4062d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand	case ARGTYPE_LONG:
407ce034981e2880eecb8a196c78182dfb4ae67850fPetr Machata		return format_integer(stream, value, int_fmt, arguments);
40894078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata
40994078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	case ARGTYPE_USHORT:
41094078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	case ARGTYPE_UINT:
4112d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand	case ARGTYPE_ULONG:
412e773f634dc1283a47786788e747aa5217f61c6fcPetr Machata		if (int_fmt == INT_FMT_i || int_fmt == INT_FMT_default)
413ce034981e2880eecb8a196c78182dfb4ae67850fPetr Machata			int_fmt = INT_FMT_u;
414ce034981e2880eecb8a196c78182dfb4ae67850fPetr Machata		return format_integer(stream, value, int_fmt, arguments);
41594078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata
4162d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand	case ARGTYPE_CHAR:
417e773f634dc1283a47786788e747aa5217f61c6fcPetr Machata		if (int_fmt == INT_FMT_default)
418c00837c2928da53a3515b107399b742ea157e78aPetr Machata			return format_naked(stream, value, arguments,
419c00837c2928da53a3515b107399b742ea157e78aPetr Machata					    &format_char);
420e773f634dc1283a47786788e747aa5217f61c6fcPetr Machata		return format_integer(stream, value, int_fmt, arguments);
42194078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata
42294078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	case ARGTYPE_FLOAT:
42394078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	case ARGTYPE_DOUBLE:
424f197727e6247be1ee08d2a667931aee20512ae18Petr Machata		return format_floating(stream, value, arguments, int_fmt);
42594078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata
426e4b3263fb2b32eb5ee0f693fc223ed8c363fbd69Steve Fink	case ARGTYPE_STRUCT:
42794078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		return format_struct(stream, value, arguments);
42894078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata
4297bafff09cc66e23519512a54e2d1ebd3664a1a70Steve Fink	case ARGTYPE_POINTER:
430d8286ed3496bcd69cd4796f57a5b5c04859d2378Petr Machata		if (value_is_zero(value, arguments))
431d8286ed3496bcd69cd4796f57a5b5c04859d2378Petr Machata			return fprintf(stream, null_message);
43294078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		if (value->type->u.array_info.elt_type->type != ARGTYPE_VOID)
43394078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata			return format_pointer(stream, value, arguments);
43494078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		return format_integer(stream, value, INT_FMT_x, arguments);
4357bafff09cc66e23519512a54e2d1ebd3664a1a70Steve Fink
43694078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	case ARGTYPE_ARRAY:
43794078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		return format_array(stream, value, arguments,
43894078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata				    value->type->u.array_info.length,
439e3f4a984db115979e09414b7281da98399dd8949Petr Machata				    options.arraylen, 1, "[ ", " ]", ", ");
4405e01f654d83a95f2acffa86df57a4c2db9b0cae9Juan Cespedes	}
44194078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	abort();
4425e01f654d83a95f2acffa86df57a4c2db9b0cae9Juan Cespedes}
44331af32cfcd61671cbb5e567870103766b3231521Petr Machata
44431af32cfcd61671cbb5e567870103766b3231521Petr Machatastatic int
44531af32cfcd61671cbb5e567870103766b3231521Petr Machatadefault_lens_format_cb(struct lens *lens, FILE *stream,
44631af32cfcd61671cbb5e567870103766b3231521Petr Machata		       struct value *value, struct value_dict *arguments)
44731af32cfcd61671cbb5e567870103766b3231521Petr Machata{
448e773f634dc1283a47786788e747aa5217f61c6fcPetr Machata	return toplevel_format_lens(lens, stream, value, arguments,
449e773f634dc1283a47786788e747aa5217f61c6fcPetr Machata				    INT_FMT_default);
45031af32cfcd61671cbb5e567870103766b3231521Petr Machata}
45131af32cfcd61671cbb5e567870103766b3231521Petr Machata
45231af32cfcd61671cbb5e567870103766b3231521Petr Machatastruct lens default_lens = {
45331af32cfcd61671cbb5e567870103766b3231521Petr Machata	.format_cb = default_lens_format_cb,
45431af32cfcd61671cbb5e567870103766b3231521Petr Machata};
455ce034981e2880eecb8a196c78182dfb4ae67850fPetr Machata
456ce034981e2880eecb8a196c78182dfb4ae67850fPetr Machata
457ce034981e2880eecb8a196c78182dfb4ae67850fPetr Machatastatic int
458ce034981e2880eecb8a196c78182dfb4ae67850fPetr Machatablind_lens_format_cb(struct lens *lens, FILE *stream,
459ce034981e2880eecb8a196c78182dfb4ae67850fPetr Machata		     struct value *value, struct value_dict *arguments)
460ce034981e2880eecb8a196c78182dfb4ae67850fPetr Machata{
461ce034981e2880eecb8a196c78182dfb4ae67850fPetr Machata	return 0;
462ce034981e2880eecb8a196c78182dfb4ae67850fPetr Machata}
463ce034981e2880eecb8a196c78182dfb4ae67850fPetr Machata
464ce034981e2880eecb8a196c78182dfb4ae67850fPetr Machatastruct lens blind_lens = {
465ce034981e2880eecb8a196c78182dfb4ae67850fPetr Machata	.format_cb = blind_lens_format_cb,
466ce034981e2880eecb8a196c78182dfb4ae67850fPetr Machata};
467ce034981e2880eecb8a196c78182dfb4ae67850fPetr Machata
468ce034981e2880eecb8a196c78182dfb4ae67850fPetr Machata
469ce034981e2880eecb8a196c78182dfb4ae67850fPetr Machatastatic int
470ce034981e2880eecb8a196c78182dfb4ae67850fPetr Machataoctal_lens_format_cb(struct lens *lens, FILE *stream,
471ce034981e2880eecb8a196c78182dfb4ae67850fPetr Machata		     struct value *value, struct value_dict *arguments)
472ce034981e2880eecb8a196c78182dfb4ae67850fPetr Machata{
473ce034981e2880eecb8a196c78182dfb4ae67850fPetr Machata	return toplevel_format_lens(lens, stream, value, arguments, INT_FMT_o);
474ce034981e2880eecb8a196c78182dfb4ae67850fPetr Machata}
475ce034981e2880eecb8a196c78182dfb4ae67850fPetr Machata
476ce034981e2880eecb8a196c78182dfb4ae67850fPetr Machatastruct lens octal_lens = {
477ce034981e2880eecb8a196c78182dfb4ae67850fPetr Machata	.format_cb = octal_lens_format_cb,
478ce034981e2880eecb8a196c78182dfb4ae67850fPetr Machata};
479ce034981e2880eecb8a196c78182dfb4ae67850fPetr Machata
480ce034981e2880eecb8a196c78182dfb4ae67850fPetr Machata
481ce034981e2880eecb8a196c78182dfb4ae67850fPetr Machatastatic int
482ce034981e2880eecb8a196c78182dfb4ae67850fPetr Machatahex_lens_format_cb(struct lens *lens, FILE *stream,
483ce034981e2880eecb8a196c78182dfb4ae67850fPetr Machata		   struct value *value, struct value_dict *arguments)
484ce034981e2880eecb8a196c78182dfb4ae67850fPetr Machata{
485ce034981e2880eecb8a196c78182dfb4ae67850fPetr Machata	return toplevel_format_lens(lens, stream, value, arguments, INT_FMT_x);
486ce034981e2880eecb8a196c78182dfb4ae67850fPetr Machata}
487ce034981e2880eecb8a196c78182dfb4ae67850fPetr Machata
488ce034981e2880eecb8a196c78182dfb4ae67850fPetr Machatastruct lens hex_lens = {
489ce034981e2880eecb8a196c78182dfb4ae67850fPetr Machata	.format_cb = hex_lens_format_cb,
490ce034981e2880eecb8a196c78182dfb4ae67850fPetr Machata};
491b781916d24d6ee96842c818b5e18af31808d427dPetr Machata
492b781916d24d6ee96842c818b5e18af31808d427dPetr Machata
493b781916d24d6ee96842c818b5e18af31808d427dPetr Machatastatic int
494ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machatadec_lens_format_cb(struct lens *lens, FILE *stream,
495ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata		   struct value *value, struct value_dict *arguments)
496ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata{
497ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata	return toplevel_format_lens(lens, stream, value, arguments, INT_FMT_u);
498ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata}
499ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata
500ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machatastruct lens dec_lens = {
501ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata	.format_cb = dec_lens_format_cb,
502ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata};
503ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata
504ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata
505ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machatastatic int
506b781916d24d6ee96842c818b5e18af31808d427dPetr Machataguess_lens_format_cb(struct lens *lens, FILE *stream,
507b781916d24d6ee96842c818b5e18af31808d427dPetr Machata		     struct value *value, struct value_dict *arguments)
508b781916d24d6ee96842c818b5e18af31808d427dPetr Machata{
509b781916d24d6ee96842c818b5e18af31808d427dPetr Machata	return toplevel_format_lens(lens, stream, value, arguments,
510b781916d24d6ee96842c818b5e18af31808d427dPetr Machata				    INT_FMT_unknown);
511b781916d24d6ee96842c818b5e18af31808d427dPetr Machata}
512b781916d24d6ee96842c818b5e18af31808d427dPetr Machata
513b781916d24d6ee96842c818b5e18af31808d427dPetr Machatastruct lens guess_lens = {
514b781916d24d6ee96842c818b5e18af31808d427dPetr Machata	.format_cb = guess_lens_format_cb,
515b781916d24d6ee96842c818b5e18af31808d427dPetr Machata};
516e3f4a984db115979e09414b7281da98399dd8949Petr Machata
517e3f4a984db115979e09414b7281da98399dd8949Petr Machata
518e3f4a984db115979e09414b7281da98399dd8949Petr Machatastatic int
51938fb49b852374d749bc91f1b8d91a2b5b2a57a10Petr Machatabool_lens_format_cb(struct lens *lens, FILE *stream,
52038fb49b852374d749bc91f1b8d91a2b5b2a57a10Petr Machata		    struct value *value, struct value_dict *arguments)
52138fb49b852374d749bc91f1b8d91a2b5b2a57a10Petr Machata{
52238fb49b852374d749bc91f1b8d91a2b5b2a57a10Petr Machata	switch (value->type->type) {
52338fb49b852374d749bc91f1b8d91a2b5b2a57a10Petr Machata	case ARGTYPE_VOID:
52438fb49b852374d749bc91f1b8d91a2b5b2a57a10Petr Machata	case ARGTYPE_FLOAT:
52538fb49b852374d749bc91f1b8d91a2b5b2a57a10Petr Machata	case ARGTYPE_DOUBLE:
52638fb49b852374d749bc91f1b8d91a2b5b2a57a10Petr Machata	case ARGTYPE_STRUCT:
52738fb49b852374d749bc91f1b8d91a2b5b2a57a10Petr Machata	case ARGTYPE_POINTER:
52838fb49b852374d749bc91f1b8d91a2b5b2a57a10Petr Machata	case ARGTYPE_ARRAY:
52938fb49b852374d749bc91f1b8d91a2b5b2a57a10Petr Machata		return toplevel_format_lens(lens, stream, value,
530e773f634dc1283a47786788e747aa5217f61c6fcPetr Machata					    arguments, INT_FMT_default);
53138fb49b852374d749bc91f1b8d91a2b5b2a57a10Petr Machata
53238fb49b852374d749bc91f1b8d91a2b5b2a57a10Petr Machata		int zero;
53338fb49b852374d749bc91f1b8d91a2b5b2a57a10Petr Machata	case ARGTYPE_SHORT:
53438fb49b852374d749bc91f1b8d91a2b5b2a57a10Petr Machata	case ARGTYPE_INT:
53538fb49b852374d749bc91f1b8d91a2b5b2a57a10Petr Machata	case ARGTYPE_LONG:
53638fb49b852374d749bc91f1b8d91a2b5b2a57a10Petr Machata	case ARGTYPE_USHORT:
53738fb49b852374d749bc91f1b8d91a2b5b2a57a10Petr Machata	case ARGTYPE_UINT:
53838fb49b852374d749bc91f1b8d91a2b5b2a57a10Petr Machata	case ARGTYPE_ULONG:
53938fb49b852374d749bc91f1b8d91a2b5b2a57a10Petr Machata	case ARGTYPE_CHAR:
54038fb49b852374d749bc91f1b8d91a2b5b2a57a10Petr Machata		if ((zero = value_is_zero(value, arguments)) < 0)
54138fb49b852374d749bc91f1b8d91a2b5b2a57a10Petr Machata			return -1;
54238fb49b852374d749bc91f1b8d91a2b5b2a57a10Petr Machata		if (zero)
54338fb49b852374d749bc91f1b8d91a2b5b2a57a10Petr Machata			return fprintf(stream, "false");
54438fb49b852374d749bc91f1b8d91a2b5b2a57a10Petr Machata		else
54538fb49b852374d749bc91f1b8d91a2b5b2a57a10Petr Machata			return fprintf(stream, "true");
54638fb49b852374d749bc91f1b8d91a2b5b2a57a10Petr Machata	}
54738fb49b852374d749bc91f1b8d91a2b5b2a57a10Petr Machata	abort();
54838fb49b852374d749bc91f1b8d91a2b5b2a57a10Petr Machata}
54938fb49b852374d749bc91f1b8d91a2b5b2a57a10Petr Machata
55038fb49b852374d749bc91f1b8d91a2b5b2a57a10Petr Machatastruct lens bool_lens = {
55138fb49b852374d749bc91f1b8d91a2b5b2a57a10Petr Machata	.format_cb = bool_lens_format_cb,
55238fb49b852374d749bc91f1b8d91a2b5b2a57a10Petr Machata};
55338fb49b852374d749bc91f1b8d91a2b5b2a57a10Petr Machata
554c00837c2928da53a3515b107399b742ea157e78aPetr Machatastatic int
555c00837c2928da53a3515b107399b742ea157e78aPetr Machataredispatch_as_array(struct lens *lens, FILE *stream,
556c00837c2928da53a3515b107399b742ea157e78aPetr Machata		    struct value *value, struct value_dict *arguments,
557c00837c2928da53a3515b107399b742ea157e78aPetr Machata		    int (*cb)(struct lens *, FILE *,
558c00837c2928da53a3515b107399b742ea157e78aPetr Machata			      struct value *, struct value_dict *))
559c00837c2928da53a3515b107399b742ea157e78aPetr Machata{
560c00837c2928da53a3515b107399b742ea157e78aPetr Machata	struct arg_type_info info[2];
561c00837c2928da53a3515b107399b742ea157e78aPetr Machata	type_init_array(&info[1], value->type->u.ptr_info.info, 0,
562c00837c2928da53a3515b107399b742ea157e78aPetr Machata			expr_node_zero(), 0);
563c00837c2928da53a3515b107399b742ea157e78aPetr Machata	type_init_pointer(&info[0], &info[1], 0);
564c00837c2928da53a3515b107399b742ea157e78aPetr Machata	info->lens = lens;
565c00837c2928da53a3515b107399b742ea157e78aPetr Machata	info->own_lens = 0;
566c00837c2928da53a3515b107399b742ea157e78aPetr Machata	struct value tmp;
567c00837c2928da53a3515b107399b742ea157e78aPetr Machata	if (value_clone(&tmp, value) < 0)
568c00837c2928da53a3515b107399b742ea157e78aPetr Machata		return -1;
569c00837c2928da53a3515b107399b742ea157e78aPetr Machata	value_set_type(&tmp, info, 0);
570c00837c2928da53a3515b107399b742ea157e78aPetr Machata	int ret = cb(lens, stream, &tmp, arguments);
571c00837c2928da53a3515b107399b742ea157e78aPetr Machata	type_destroy(&info[0]);
572c00837c2928da53a3515b107399b742ea157e78aPetr Machata	type_destroy(&info[1]);
573c00837c2928da53a3515b107399b742ea157e78aPetr Machata	value_destroy(&tmp);
574c00837c2928da53a3515b107399b742ea157e78aPetr Machata	return ret;
575c00837c2928da53a3515b107399b742ea157e78aPetr Machata}
576c00837c2928da53a3515b107399b742ea157e78aPetr Machata
577c00837c2928da53a3515b107399b742ea157e78aPetr Machatastatic int
578c00837c2928da53a3515b107399b742ea157e78aPetr Machataformat_wchar(FILE *stream, struct value *value, struct value_dict *arguments)
579c00837c2928da53a3515b107399b742ea157e78aPetr Machata{
580c00837c2928da53a3515b107399b742ea157e78aPetr Machata	long l;
581c00837c2928da53a3515b107399b742ea157e78aPetr Machata	if (value_extract_word(value, &l, arguments) < 0)
582c00837c2928da53a3515b107399b742ea157e78aPetr Machata		return -1;
583c00837c2928da53a3515b107399b742ea157e78aPetr Machata	wchar_t wc = (wchar_t) l;
584c00837c2928da53a3515b107399b742ea157e78aPetr Machata	char buf[MB_CUR_MAX + 1];
585c00837c2928da53a3515b107399b742ea157e78aPetr Machata
586c00837c2928da53a3515b107399b742ea157e78aPetr Machata	int c = wctomb(buf, wc);
587c00837c2928da53a3515b107399b742ea157e78aPetr Machata	if (c < 0)
588c00837c2928da53a3515b107399b742ea157e78aPetr Machata		return -1;
589c00837c2928da53a3515b107399b742ea157e78aPetr Machata	if (c == 1)
590c00837c2928da53a3515b107399b742ea157e78aPetr Machata		return print_char(stream, buf[0]);
591c00837c2928da53a3515b107399b742ea157e78aPetr Machata
592c00837c2928da53a3515b107399b742ea157e78aPetr Machata	buf[c] = 0;
593caccda07541df0790887311d898405b2e4d78a5fPetr Machata	if (fprintf(stream, "%s", buf) < 0)
594caccda07541df0790887311d898405b2e4d78a5fPetr Machata		return -1;
595caccda07541df0790887311d898405b2e4d78a5fPetr Machata
596caccda07541df0790887311d898405b2e4d78a5fPetr Machata	c = wcwidth(wc);
597caccda07541df0790887311d898405b2e4d78a5fPetr Machata	return c >= 0 ? c : 0;
598c00837c2928da53a3515b107399b742ea157e78aPetr Machata}
59938fb49b852374d749bc91f1b8d91a2b5b2a57a10Petr Machata
60038fb49b852374d749bc91f1b8d91a2b5b2a57a10Petr Machatastatic int
601e3f4a984db115979e09414b7281da98399dd8949Petr Machatastring_lens_format_cb(struct lens *lens, FILE *stream,
602e3f4a984db115979e09414b7281da98399dd8949Petr Machata		      struct value *value, struct value_dict *arguments)
603e3f4a984db115979e09414b7281da98399dd8949Petr Machata{
604e3f4a984db115979e09414b7281da98399dd8949Petr Machata	switch (value->type->type) {
605e3f4a984db115979e09414b7281da98399dd8949Petr Machata	case ARGTYPE_POINTER:
606e3f4a984db115979e09414b7281da98399dd8949Petr Machata		/* This should really be written as either "string",
607e3f4a984db115979e09414b7281da98399dd8949Petr Machata		 * or, if lens, then string(array(char, zero)*).  But
608e3f4a984db115979e09414b7281da98399dd8949Petr Machata		 * I suspect people are so used to the char * C idiom,
609e3f4a984db115979e09414b7281da98399dd8949Petr Machata		 * that string(char *) might actually turn up.  So
610e3f4a984db115979e09414b7281da98399dd8949Petr Machata		 * let's just support it.  */
611c00837c2928da53a3515b107399b742ea157e78aPetr Machata		switch ((int) value->type->u.ptr_info.info->type)
612c00837c2928da53a3515b107399b742ea157e78aPetr Machata		case ARGTYPE_CHAR:
613c00837c2928da53a3515b107399b742ea157e78aPetr Machata		case ARGTYPE_SHORT:
614c00837c2928da53a3515b107399b742ea157e78aPetr Machata		case ARGTYPE_USHORT:
615c00837c2928da53a3515b107399b742ea157e78aPetr Machata		case ARGTYPE_INT:
616c00837c2928da53a3515b107399b742ea157e78aPetr Machata		case ARGTYPE_UINT:
617c00837c2928da53a3515b107399b742ea157e78aPetr Machata		case ARGTYPE_LONG:
618c00837c2928da53a3515b107399b742ea157e78aPetr Machata		case ARGTYPE_ULONG:
619c00837c2928da53a3515b107399b742ea157e78aPetr Machata			return redispatch_as_array(lens, stream, value,
620c00837c2928da53a3515b107399b742ea157e78aPetr Machata						   arguments,
621c00837c2928da53a3515b107399b742ea157e78aPetr Machata						   &string_lens_format_cb);
622c00837c2928da53a3515b107399b742ea157e78aPetr Machata
623c00837c2928da53a3515b107399b742ea157e78aPetr Machata		/* Otherwise dispatch to whatever the default for the
624c00837c2928da53a3515b107399b742ea157e78aPetr Machata		 * pointee is--most likely this will again be us.  */
625c00837c2928da53a3515b107399b742ea157e78aPetr Machata		/* Fall through.  */
626e3f4a984db115979e09414b7281da98399dd8949Petr Machata	case ARGTYPE_VOID:
627e3f4a984db115979e09414b7281da98399dd8949Petr Machata	case ARGTYPE_FLOAT:
628e3f4a984db115979e09414b7281da98399dd8949Petr Machata	case ARGTYPE_DOUBLE:
629e3f4a984db115979e09414b7281da98399dd8949Petr Machata	case ARGTYPE_STRUCT:
630c00837c2928da53a3515b107399b742ea157e78aPetr Machata		return toplevel_format_lens(lens, stream, value,
631c00837c2928da53a3515b107399b742ea157e78aPetr Machata					    arguments, INT_FMT_default);
632c00837c2928da53a3515b107399b742ea157e78aPetr Machata
633e3f4a984db115979e09414b7281da98399dd8949Petr Machata	case ARGTYPE_SHORT:
634e3f4a984db115979e09414b7281da98399dd8949Petr Machata	case ARGTYPE_INT:
635e3f4a984db115979e09414b7281da98399dd8949Petr Machata	case ARGTYPE_LONG:
636e3f4a984db115979e09414b7281da98399dd8949Petr Machata	case ARGTYPE_USHORT:
637e3f4a984db115979e09414b7281da98399dd8949Petr Machata	case ARGTYPE_UINT:
638e3f4a984db115979e09414b7281da98399dd8949Petr Machata	case ARGTYPE_ULONG:
639c00837c2928da53a3515b107399b742ea157e78aPetr Machata		if (value->parent != NULL && value->type->lens == NULL)
640c00837c2928da53a3515b107399b742ea157e78aPetr Machata			return format_wchar(stream, value, arguments);
641c00837c2928da53a3515b107399b742ea157e78aPetr Machata		else
642c00837c2928da53a3515b107399b742ea157e78aPetr Machata			return format_naked(stream, value, arguments,
643c00837c2928da53a3515b107399b742ea157e78aPetr Machata					    &format_wchar);
644e3f4a984db115979e09414b7281da98399dd8949Petr Machata
645e3f4a984db115979e09414b7281da98399dd8949Petr Machata	case ARGTYPE_CHAR:
646e3f4a984db115979e09414b7281da98399dd8949Petr Machata		return format_char(stream, value, arguments);
647e3f4a984db115979e09414b7281da98399dd8949Petr Machata
648e3f4a984db115979e09414b7281da98399dd8949Petr Machata	case ARGTYPE_ARRAY:
649e3f4a984db115979e09414b7281da98399dd8949Petr Machata		return format_array(stream, value, arguments,
650e3f4a984db115979e09414b7281da98399dd8949Petr Machata				    value->type->u.array_info.length,
651e3f4a984db115979e09414b7281da98399dd8949Petr Machata				    options.strlen, 0, "\"", "\"", "");
652e3f4a984db115979e09414b7281da98399dd8949Petr Machata	}
653e3f4a984db115979e09414b7281da98399dd8949Petr Machata	abort();
654e3f4a984db115979e09414b7281da98399dd8949Petr Machata}
655e3f4a984db115979e09414b7281da98399dd8949Petr Machata
656e3f4a984db115979e09414b7281da98399dd8949Petr Machatastruct lens string_lens = {
657e3f4a984db115979e09414b7281da98399dd8949Petr Machata	.format_cb = string_lens_format_cb,
658e3f4a984db115979e09414b7281da98399dd8949Petr Machata};
659ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata
660ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machatastatic int
661ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machataout_bits(FILE *stream, size_t low, size_t high)
662ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata{
663ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata	if (low == high)
664ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata		return fprintf(stream, "%zd", low);
665ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata	else
666ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata		return fprintf(stream, "%zd-%zd", low, high);
667ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata}
668ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata
669ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machatastatic int
670ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machatabitvect_lens_format_cb(struct lens *lens, FILE *stream,
671ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata		       struct value *value, struct value_dict *arguments)
672ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata{
673ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata	unsigned char *data = value_get_data(value, arguments);
674ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata	if (data == NULL)
675ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata		return -1;
676ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata	size_t sz = type_sizeof(value->inferior, value->type);
677ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata	if (sz == (size_t)-1)
678ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata		return -1;
679ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata
680ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata	size_t i;
681ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata	unsigned char buf[sz];
682ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata	switch ((int)value->type->type) {
683ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata		union bitvect_integral_64
684ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata		{
685ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata			uint8_t u8;
686ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata			uint16_t u16;
687ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata			uint32_t u32;
688ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata			uint64_t u64;
689ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata			unsigned char buf[0];
690ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata		} bv;
691ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata
692ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata	case ARGTYPE_POINTER:
693ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata		return format_pointer(stream, value, arguments);
694ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata
695ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata	case ARGTYPE_STRUCT:
696ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata	case ARGTYPE_ARRAY:
697ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata		break;
698ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata
699ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata	default:
700ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata		assert(sz <= sizeof(bv));
701ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata		memmove(bv.buf, data, sz);
702ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata
703ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata		if (sz == 1)
704ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata			bv.u64 = bv.u8;
705ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata		else if (sz == 2)
706ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata			bv.u64 = bv.u16;
707ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata		else if (sz == 4)
708ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata			bv.u64 = bv.u32;
709ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata
710ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata		for (i = 0; i < sz; ++i) {
711ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata			buf[i] = bv.u64 & 0xff;
712ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata			bv.u64 >>= 8;
713ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata		}
714ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata		data = buf;
715ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata	}
716ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata
717ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata	size_t bits = 0;
718ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata	for (i = 0; i < sz; ++i)
719ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata		bits += bitcount(data[i]);
720ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata
721ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata	/* If there's more 1's than 0's, show inverse.  */
722ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata	unsigned neg = bits > sz * 4 ? 0xff : 0x00;
723ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata
724ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata	int o = 0;
7256bb420106f77ef8f134a1d4c001668e832f96cc9Andrey Zonov	if (acc_fprintf(&o, stream, "%s<", &"~"[neg == 0x00]) < 0)
726ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata		return -1;
727ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata
728ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata	size_t bitno = 0;
729ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata	ssize_t low = -1;
730ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata	for (i = 0; i < sz; ++i) {
731ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata		unsigned char m;
732ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata		unsigned char d = data[i] ^ neg;
733ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata		for (m = 0x01; m != 0; m <<= 1) {
734ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata			int bit = !!(m & d);
735ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata			if (low < 0) {
736ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata				if (bit) {
737ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata					if (low == -2
738ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata					    && acc_fprintf(&o, stream, ",") < 0)
739ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata						return -1;
740ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata					low = bitno;
741ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata				}
742ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata			} else if (!bit) {
743ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata				if (account_output(&o, out_bits(stream, low,
744ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata								bitno-1)) < 0)
745ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata					return -1;
746ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata				low = -2;
747ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata			}
748ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata			bitno++;
749ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata		}
750ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata	}
751ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata	if (low >= 0 && account_output(&o, out_bits(stream, low, bitno-1)) < 0)
752ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata		return -1;
753ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata
754ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata	if (fputc('>', stream) < 0)
755ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata		return -1;
756ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata	o += 1;
757ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata
758ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata	return o;
759ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata}
760ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata
761ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machatastruct lens bitvect_lens = {
762ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata	.format_cb = bitvect_lens_format_cb,
763ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207Petr Machata};
764