blob: e0c0566892448472d02abee39b5255fe2bc1a0ca [file] [log] [blame]
Petr Machata94078ec2012-01-05 18:07:02 +01001/*
2 * This file is part of ltrace.
3 * Copyright (C) 2011,2012 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
Steve Fink7bafff02006-08-07 04:50:42 +020024#include <ctype.h>
Juan Cespedes5e01f651998-03-08 22:31:44 +010025#include <stdlib.h>
Petr Machata94078ec2012-01-05 18:07:02 +010026#include <assert.h>
27#include <inttypes.h>
28#include <stdarg.h>
29#include <stdio.h>
Petr Machata307b90b2012-11-19 00:35:38 +010030#include <string.h>
Juan Cespedes5e01f651998-03-08 22:31:44 +010031
Petr Machata1721fc92013-01-21 16:14:20 +010032#include "bits.h"
Petr Machata366c2f42012-02-09 19:34:36 +010033#include "proc.h"
Petr Machata31af32c2012-01-08 02:36:50 +010034#include "lens_default.h"
Petr Machata94078ec2012-01-05 18:07:02 +010035#include "value.h"
36#include "expr.h"
Petr Machata000e3112012-01-03 17:03:39 +010037#include "type.h"
Petr Machata94078ec2012-01-05 18:07:02 +010038#include "common.h"
Petr Machatad7b22922012-01-06 18:34:22 +010039#include "zero.h"
Juan Cespedes5e01f651998-03-08 22:31:44 +010040
Petr Machata94078ec2012-01-05 18:07:02 +010041#define READER(NAME, TYPE) \
42 static int \
43 NAME(struct value *value, TYPE *ret, struct value_dict *arguments) \
44 { \
45 union { \
46 TYPE val; \
47 unsigned char buf[0]; \
48 } u; \
49 if (value_extract_buf(value, u.buf, arguments) < 0) \
50 return -1; \
51 *ret = u.val; \
52 return 0; \
Juan Cespedesa413e5b2007-09-04 17:34:53 +020053 }
Steve Fink65b53df2006-09-25 02:27:08 +020054
Petr Machata94078ec2012-01-05 18:07:02 +010055READER(read_float, float)
56READER(read_double, double)
57
58#undef READER
59
60#define HANDLE_WIDTH(BITS) \
61 do { \
62 long l; \
63 if (value_extract_word(value, &l, arguments) < 0) \
64 return -1; \
65 int##BITS##_t i = l; \
Petr Machatae773f632012-11-09 18:52:53 +010066 uint64_t v = (uint64_t)(uint##BITS##_t)i; \
Petr Machata94078ec2012-01-05 18:07:02 +010067 switch (format) { \
68 case INT_FMT_unknown: \
Petr Machatac1e41862012-08-31 15:13:16 +020069 if (l < -10000 || l > 10000) \
Petr Machata94078ec2012-01-05 18:07:02 +010070 case INT_FMT_x: \
Petr Machatae773f632012-11-09 18:52:53 +010071 return fprintf(stream, "%#"PRIx64, v); \
Petr Machata94078ec2012-01-05 18:07:02 +010072 case INT_FMT_i: \
Petr Machatae773f632012-11-09 18:52:53 +010073 case INT_FMT_default: \
Petr Machata94078ec2012-01-05 18:07:02 +010074 return fprintf(stream, "%"PRIi##BITS, i); \
75 case INT_FMT_u: \
Petr Machatae773f632012-11-09 18:52:53 +010076 return fprintf(stream, "%"PRIu64, v); \
Petr Machata94078ec2012-01-05 18:07:02 +010077 case INT_FMT_o: \
Petr Machatae773f632012-11-09 18:52:53 +010078 return fprintf(stream, "0%"PRIo64, v); \
Petr Machata94078ec2012-01-05 18:07:02 +010079 } \
80 } while (0)
81
82enum int_fmt_t
83{
84 INT_FMT_i,
85 INT_FMT_u,
86 INT_FMT_o,
87 INT_FMT_x,
88 INT_FMT_unknown,
Petr Machatae773f632012-11-09 18:52:53 +010089 INT_FMT_default,
Petr Machata94078ec2012-01-05 18:07:02 +010090};
91
92static int
93format_integer(FILE *stream, struct value *value, enum int_fmt_t format,
94 struct value_dict *arguments)
95{
96 switch (type_sizeof(value->inferior, value->type)) {
97
98 case 1: HANDLE_WIDTH(8);
99 case 2: HANDLE_WIDTH(16);
100 case 4: HANDLE_WIDTH(32);
101 case 8: HANDLE_WIDTH(64);
102
103 default:
104 assert(!"unsupported integer width");
105 abort();
106
107 case -1:
108 return -1;
109 }
110}
111
112#undef HANDLE_WIDTH
113
114static int
Petr Machata94078ec2012-01-05 18:07:02 +0100115acc_fprintf(int *countp, FILE *stream, const char *format, ...)
116{
117 va_list pa;
118 va_start(pa, format);
Petr Machataadec2012012-11-01 22:05:04 +0100119 int i = account_output(countp, vfprintf(stream, format, pa));
Petr Machata94078ec2012-01-05 18:07:02 +0100120 va_end(pa);
121
Petr Machata94078ec2012-01-05 18:07:02 +0100122 return i;
123}
124
125static int
126format_char(FILE *stream, struct value *value, struct value_dict *arguments)
127{
128 long lc;
129 if (value_extract_word(value, &lc, arguments) < 0)
130 return -1;
131 int c = (int)lc;
132
Petr Machata94078ec2012-01-05 18:07:02 +0100133 const char *fmt;
134 switch (c) {
135 case -1:
136 fmt = "EOF";
137 break;
138 case 0:
139 fmt = "\\0";
140 break;
141 case '\a':
142 fmt = "\\a";
143 break;
144 case '\b':
145 fmt = "\\b";
146 break;
147 case '\t':
148 fmt = "\\t";
149 break;
150 case '\n':
151 fmt = "\\n";
152 break;
153 case '\v':
154 fmt = "\\v";
155 break;
156 case '\f':
157 fmt = "\\f";
158 break;
159 case '\r':
160 fmt = "\\r";
161 break;
162 case '\\':
163 fmt = "\\\\";
164 break;
165 default:
166 if (isprint(c) || c == ' ')
167 fmt = "%c";
Petr Machata94078ec2012-01-05 18:07:02 +0100168 else
Petr Machata987d27b2012-01-17 19:04:04 +0100169 fmt = "\\%03o";
Petr Machata94078ec2012-01-05 18:07:02 +0100170 }
171
Petr Machata987d27b2012-01-17 19:04:04 +0100172 return fprintf(stream, fmt, c);
Petr Machatae3f4a982012-01-09 04:27:26 +0100173}
174
175static int
176format_naked_char(FILE *stream, struct value *value,
177 struct value_dict *arguments)
178{
179 int written = 0;
180 if (acc_fprintf(&written, stream, "'") < 0
Petr Machataadec2012012-11-01 22:05:04 +0100181 || account_output(&written,
182 format_char(stream, value, arguments)) < 0
Petr Machatae3f4a982012-01-09 04:27:26 +0100183 || acc_fprintf(&written, stream, "'") < 0)
Petr Machata94078ec2012-01-05 18:07:02 +0100184 return -1;
Petr Machatae3f4a982012-01-09 04:27:26 +0100185
Petr Machata94078ec2012-01-05 18:07:02 +0100186 return written;
187}
188
189static int
Petr Machataf1977272012-11-29 15:49:16 +0100190format_double(FILE *stream, double value, enum int_fmt_t format)
191{
192 if (format == INT_FMT_x)
193 return fprintf(stream, "%a", value);
194 else
195 return fprintf(stream, "%f", value);
196}
197
198static int
199format_floating(FILE *stream, struct value *value, struct value_dict *arguments,
200 enum int_fmt_t format)
Petr Machata94078ec2012-01-05 18:07:02 +0100201{
202 switch (value->type->type) {
203 float f;
204 double d;
205 case ARGTYPE_FLOAT:
206 if (read_float(value, &f, arguments) < 0)
207 return -1;
Petr Machataf1977272012-11-29 15:49:16 +0100208 return format_double(stream, f, format);
Petr Machata94078ec2012-01-05 18:07:02 +0100209 case ARGTYPE_DOUBLE:
210 if (read_double(value, &d, arguments) < 0)
211 return -1;
Petr Machataf1977272012-11-29 15:49:16 +0100212 return format_double(stream, d, format);
Petr Machata94078ec2012-01-05 18:07:02 +0100213 default:
214 abort();
215 }
216}
217
Petr Machataf7c46bb2012-11-01 22:15:45 +0100218struct format_argument_data
219{
220 struct value *value;
221 struct value_dict *arguments;
222};
223
224static int
225format_argument_cb(FILE *stream, void *ptr)
226{
227 struct format_argument_data *data = ptr;
228 return format_argument(stream, data->value, data->arguments);
229}
230
Petr Machata94078ec2012-01-05 18:07:02 +0100231static int
232format_struct(FILE *stream, struct value *value, struct value_dict *arguments)
233{
234 int written = 0;
235 if (acc_fprintf(&written, stream, "{ ") < 0)
236 return -1;
Petr Machataf7c46bb2012-11-01 22:15:45 +0100237
238 int need_delim = 0;
Petr Machata94078ec2012-01-05 18:07:02 +0100239 size_t i;
240 for (i = 0; i < type_struct_size(value->type); ++i) {
Petr Machata94078ec2012-01-05 18:07:02 +0100241 struct value element;
242 if (value_init_element(&element, value, i) < 0)
243 return -1;
Petr Machataf7c46bb2012-11-01 22:15:45 +0100244
245 struct format_argument_data data = { &element, arguments };
246 int o = delim_output(stream, &need_delim,
247 format_argument_cb, &data);
Petr Machata8904cdc2012-10-30 17:27:20 +0100248 value_destroy(&element);
Petr Machata94078ec2012-01-05 18:07:02 +0100249 if (o < 0)
250 return -1;
Petr Machataf7c46bb2012-11-01 22:15:45 +0100251
Petr Machata94078ec2012-01-05 18:07:02 +0100252 written += o;
253 }
254 if (acc_fprintf(&written, stream, " }") < 0)
255 return -1;
256 return written;
257}
258
259int
260format_pointer(FILE *stream, struct value *value, struct value_dict *arguments)
261{
Petr Machata26c0c942012-11-19 00:14:51 +0100262 if (value_is_zero(value, arguments))
263 return fprintf(stream, "nil");
264
Petr Machata307b90b2012-11-19 00:35:38 +0100265 /* The following is for detecting recursion. We keep track of
266 * the values that were already displayed. Each time a
267 * pointer should be dereferenced, we compare its value to the
268 * value of each of the pointers dereferenced so far. If one
269 * of them matches, instead of recursing, we just printf which
270 * superstructure this pointer recurses to. */
271 static struct vect pointers = {};
272 if (pointers.elt_size == 0)
273 VECT_INIT(&pointers, struct value *);
274
Petr Machata6248a0a2012-11-19 01:00:54 +0100275 /* Trim number of expanded structures of the same type. Even
276 * for non-recursive structure, we don't want to expand all of
277 * it if it's huge. */
Petr Machata307b90b2012-11-19 00:35:38 +0100278 size_t i;
Petr Machata6248a0a2012-11-19 01:00:54 +0100279 size_t len = vect_size(&pointers);
280 assert(value->type->type == ARGTYPE_POINTER);
281 struct arg_type_info *pointee = value->type->u.ptr_info.info;
282 if (pointee->type == ARGTYPE_STRUCT) {
283 size_t depth = 0;
284 for (i = 0; i < len; ++i) {
285 struct value *old
286 = *VECT_ELEMENT(&pointers, struct value *, i);
287 assert(old->type->type == ARGTYPE_POINTER);
288 struct arg_type_info *old_pointee
289 = old->type->u.ptr_info.info;
290 if (old_pointee == pointee)
291 depth++;
292 }
293 if (depth >= options.arraylen)
294 return fprintf(stream, "...");
295 }
296
Petr Machata307b90b2012-11-19 00:35:38 +0100297 for (i = len; i-- > 0 ;) {
298 struct value **old = VECT_ELEMENT(&pointers, struct value *, i);
299 int rc = value_equal(value, *old, arguments);
300 if (rc < 0)
301 return -1;
302 if (rc > 0) {
303 size_t reclevel = len - i - 1;
304 char buf[reclevel + 1];
305 memset(buf, '^', sizeof buf);
306 buf[reclevel] = 0;
307 return fprintf(stream, "recurse%s", buf);
308 }
309 }
310
311 /* OK, not a recursion. Remember this value for tracking. */
312 if (VECT_PUSHBACK(&pointers, &value) < 0)
313 return -1;
314
Petr Machata94078ec2012-01-05 18:07:02 +0100315 struct value element;
Petr Machata26c0c942012-11-19 00:14:51 +0100316 int o;
317 if (value_init_deref(&element, value) < 0) {
318 o = -1;
319 goto done;
320 }
321 o = format_argument(stream, &element, arguments);
Petr Machata8904cdc2012-10-30 17:27:20 +0100322 value_destroy(&element);
Petr Machata26c0c942012-11-19 00:14:51 +0100323
324done:
Petr Machatac28410e2012-11-23 18:35:05 +0100325 VECT_POPBACK(&pointers, struct value *, NULL, NULL);
Petr Machata8904cdc2012-10-30 17:27:20 +0100326 return o;
Steve Fink1150bc42006-08-07 06:04:43 +0200327}
328
329/*
Petr Machata94078ec2012-01-05 18:07:02 +0100330 * LENGTH is an expression whose evaluation will yield the actual
331 * length of the array.
Steve Fink1150bc42006-08-07 06:04:43 +0200332 *
Petr Machata94078ec2012-01-05 18:07:02 +0100333 * MAXLEN is the actual maximum length that we care about
334 *
335 * BEFORE if LENGTH>MAXLEN, we display ellipsis. We display it before
336 * the closing parenthesis if BEFORE, otherwise after it.
337 *
338 * OPEN, CLOSE, DELIM are opening and closing parenthesis and element
339 * delimiter.
Steve Fink1150bc42006-08-07 06:04:43 +0200340 */
Juan Cespedesf1350522008-12-16 18:19:58 +0100341int
Petr Machata94078ec2012-01-05 18:07:02 +0100342format_array(FILE *stream, struct value *value, struct value_dict *arguments,
343 struct expr_node *length, size_t maxlen, int before,
344 const char *open, const char *close, const char *delim)
Petr Machata000e3112012-01-03 17:03:39 +0100345{
Petr Machata94078ec2012-01-05 18:07:02 +0100346 /* We need "long" to be long enough to cover the whole address
347 * space. */
348 typedef char assert__long_enough_long[-(sizeof(long) < sizeof(void *))];
Petr Machata31af32c2012-01-08 02:36:50 +0100349 long l;
Petr Machatad7b22922012-01-06 18:34:22 +0100350 if (expr_eval_word(length, value, arguments, &l) < 0)
351 return -1;
Petr Machata94078ec2012-01-05 18:07:02 +0100352 size_t len = (size_t)l;
Steve Fink7bafff02006-08-07 04:50:42 +0200353
Petr Machata94078ec2012-01-05 18:07:02 +0100354 int written = 0;
355 if (acc_fprintf(&written, stream, "%s", open) < 0)
356 return -1;
Juan Cespedes5e01f651998-03-08 22:31:44 +0100357
Zachary T Welchba6aca22010-12-08 18:55:09 -0800358 size_t i;
Petr Machata94078ec2012-01-05 18:07:02 +0100359 for (i = 0; i < len && i <= maxlen; ++i) {
360 if (i == maxlen) {
361 if (before && acc_fprintf(&written, stream, "...") < 0)
362 return -1;
Juan Cespedes5e01f651998-03-08 22:31:44 +0100363 break;
364 }
Petr Machata94078ec2012-01-05 18:07:02 +0100365
366 if (i > 0 && acc_fprintf(&written, stream, "%s", delim) < 0)
367 return -1;
368
369 struct value element;
370 if (value_init_element(&element, value, i) < 0)
371 return -1;
Petr Machataf6ec08a2012-01-06 16:58:54 +0100372 int o = format_argument(stream, &element, arguments);
Petr Machata8904cdc2012-10-30 17:27:20 +0100373 value_destroy(&element);
Petr Machata94078ec2012-01-05 18:07:02 +0100374 if (o < 0)
375 return -1;
376 written += o;
Juan Cespedes5e01f651998-03-08 22:31:44 +0100377 }
Petr Machata94078ec2012-01-05 18:07:02 +0100378 if (acc_fprintf(&written, stream, "%s", close) < 0)
379 return -1;
380 if (i == maxlen && !before && acc_fprintf(&written, stream, "...") < 0)
381 return -1;
382
383 return written;
Juan Cespedes5e01f651998-03-08 22:31:44 +0100384}
385
Petr Machata31af32c2012-01-08 02:36:50 +0100386static int
387toplevel_format_lens(struct lens *lens, FILE *stream,
Petr Machatace034982012-01-09 04:25:31 +0100388 struct value *value, struct value_dict *arguments,
389 enum int_fmt_t int_fmt)
Petr Machata94078ec2012-01-05 18:07:02 +0100390{
Petr Machata94078ec2012-01-05 18:07:02 +0100391 switch (value->type->type) {
392 case ARGTYPE_VOID:
393 return fprintf(stream, "<void>");
394
Petr Machata94078ec2012-01-05 18:07:02 +0100395 case ARGTYPE_SHORT:
396 case ARGTYPE_INT:
397 case ARGTYPE_LONG:
Petr Machatace034982012-01-09 04:25:31 +0100398 return format_integer(stream, value, int_fmt, arguments);
Petr Machata94078ec2012-01-05 18:07:02 +0100399
400 case ARGTYPE_USHORT:
401 case ARGTYPE_UINT:
402 case ARGTYPE_ULONG:
Petr Machatae773f632012-11-09 18:52:53 +0100403 if (int_fmt == INT_FMT_i || int_fmt == INT_FMT_default)
Petr Machatace034982012-01-09 04:25:31 +0100404 int_fmt = INT_FMT_u;
405 return format_integer(stream, value, int_fmt, arguments);
Petr Machata94078ec2012-01-05 18:07:02 +0100406
407 case ARGTYPE_CHAR:
Petr Machatae773f632012-11-09 18:52:53 +0100408 if (int_fmt == INT_FMT_default)
409 return format_naked_char(stream, value, arguments);
410 return format_integer(stream, value, int_fmt, arguments);
Petr Machata94078ec2012-01-05 18:07:02 +0100411
412 case ARGTYPE_FLOAT:
413 case ARGTYPE_DOUBLE:
Petr Machataf1977272012-11-29 15:49:16 +0100414 return format_floating(stream, value, arguments, int_fmt);
Petr Machata94078ec2012-01-05 18:07:02 +0100415
416 case ARGTYPE_STRUCT:
417 return format_struct(stream, value, arguments);
418
419 case ARGTYPE_POINTER:
420 if (value->type->u.array_info.elt_type->type != ARGTYPE_VOID)
421 return format_pointer(stream, value, arguments);
Petr Machata94078ec2012-01-05 18:07:02 +0100422 return format_integer(stream, value, INT_FMT_x, arguments);
423
424 case ARGTYPE_ARRAY:
Petr Machata94078ec2012-01-05 18:07:02 +0100425 return format_array(stream, value, arguments,
426 value->type->u.array_info.length,
Petr Machatae3f4a982012-01-09 04:27:26 +0100427 options.arraylen, 1, "[ ", " ]", ", ");
Petr Machata94078ec2012-01-05 18:07:02 +0100428 }
429 abort();
430}
Petr Machata31af32c2012-01-08 02:36:50 +0100431
432static int
433default_lens_format_cb(struct lens *lens, FILE *stream,
434 struct value *value, struct value_dict *arguments)
435{
Petr Machatae773f632012-11-09 18:52:53 +0100436 return toplevel_format_lens(lens, stream, value, arguments,
437 INT_FMT_default);
Petr Machata31af32c2012-01-08 02:36:50 +0100438}
439
440struct lens default_lens = {
441 .format_cb = default_lens_format_cb,
442};
Petr Machatace034982012-01-09 04:25:31 +0100443
444
445static int
446blind_lens_format_cb(struct lens *lens, FILE *stream,
447 struct value *value, struct value_dict *arguments)
448{
449 return 0;
450}
451
452struct lens blind_lens = {
453 .format_cb = blind_lens_format_cb,
454};
455
456
457static int
458octal_lens_format_cb(struct lens *lens, FILE *stream,
459 struct value *value, struct value_dict *arguments)
460{
461 return toplevel_format_lens(lens, stream, value, arguments, INT_FMT_o);
462}
463
464struct lens octal_lens = {
465 .format_cb = octal_lens_format_cb,
466};
467
468
469static int
470hex_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_x);
474}
475
476struct lens hex_lens = {
477 .format_cb = hex_lens_format_cb,
478};
Petr Machatab7819162012-01-09 04:26:15 +0100479
480
481static int
Petr Machataec4ab252012-11-20 02:00:16 +0100482dec_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_u);
486}
487
488struct lens dec_lens = {
489 .format_cb = dec_lens_format_cb,
490};
491
492
493static int
Petr Machatab7819162012-01-09 04:26:15 +0100494guess_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,
498 INT_FMT_unknown);
499}
500
501struct lens guess_lens = {
502 .format_cb = guess_lens_format_cb,
503};
Petr Machatae3f4a982012-01-09 04:27:26 +0100504
505
506static int
Petr Machata38fb49b2012-01-09 04:28:46 +0100507bool_lens_format_cb(struct lens *lens, FILE *stream,
508 struct value *value, struct value_dict *arguments)
509{
510 switch (value->type->type) {
511 case ARGTYPE_VOID:
512 case ARGTYPE_FLOAT:
513 case ARGTYPE_DOUBLE:
514 case ARGTYPE_STRUCT:
515 case ARGTYPE_POINTER:
516 case ARGTYPE_ARRAY:
517 return toplevel_format_lens(lens, stream, value,
Petr Machatae773f632012-11-09 18:52:53 +0100518 arguments, INT_FMT_default);
Petr Machata38fb49b2012-01-09 04:28:46 +0100519
520 int zero;
Petr Machata38fb49b2012-01-09 04:28:46 +0100521 case ARGTYPE_SHORT:
522 case ARGTYPE_INT:
523 case ARGTYPE_LONG:
524 case ARGTYPE_USHORT:
525 case ARGTYPE_UINT:
526 case ARGTYPE_ULONG:
527 case ARGTYPE_CHAR:
528 if ((zero = value_is_zero(value, arguments)) < 0)
529 return -1;
530 if (zero)
531 return fprintf(stream, "false");
532 else
533 return fprintf(stream, "true");
534 }
535 abort();
536}
537
538struct lens bool_lens = {
539 .format_cb = bool_lens_format_cb,
540};
541
542
543static int
Petr Machatae3f4a982012-01-09 04:27:26 +0100544string_lens_format_cb(struct lens *lens, FILE *stream,
545 struct value *value, struct value_dict *arguments)
546{
547 switch (value->type->type) {
548 case ARGTYPE_POINTER:
549 /* This should really be written as either "string",
550 * or, if lens, then string(array(char, zero)*). But
551 * I suspect people are so used to the char * C idiom,
552 * that string(char *) might actually turn up. So
553 * let's just support it. */
554 if (value->type->u.ptr_info.info->type == ARGTYPE_CHAR) {
555 struct arg_type_info info[2];
556 type_init_array(&info[1],
557 value->type->u.ptr_info.info, 0,
558 expr_node_zero(), 0);
559 type_init_pointer(&info[0], &info[1], 0);
560 info->lens = lens;
561 info->own_lens = 0;
562 struct value tmp;
563 if (value_clone(&tmp, value) < 0)
564 return -1;
565 value_set_type(&tmp, info, 0);
566 int ret = string_lens_format_cb(lens, stream, &tmp,
567 arguments);
568 type_destroy(&info[0]);
569 type_destroy(&info[1]);
570 value_destroy(&tmp);
571 return ret;
572 }
573
574 /* fall-through */
575 case ARGTYPE_VOID:
576 case ARGTYPE_FLOAT:
577 case ARGTYPE_DOUBLE:
578 case ARGTYPE_STRUCT:
579 case ARGTYPE_SHORT:
580 case ARGTYPE_INT:
581 case ARGTYPE_LONG:
582 case ARGTYPE_USHORT:
583 case ARGTYPE_UINT:
584 case ARGTYPE_ULONG:
Petr Machatae3f4a982012-01-09 04:27:26 +0100585 return toplevel_format_lens(lens, stream, value,
Petr Machatae773f632012-11-09 18:52:53 +0100586 arguments, INT_FMT_default);
Petr Machatae3f4a982012-01-09 04:27:26 +0100587
588 case ARGTYPE_CHAR:
589 return format_char(stream, value, arguments);
590
591 case ARGTYPE_ARRAY:
592 return format_array(stream, value, arguments,
593 value->type->u.array_info.length,
594 options.strlen, 0, "\"", "\"", "");
595 }
596 abort();
597}
598
599struct lens string_lens = {
600 .format_cb = string_lens_format_cb,
601};
Petr Machataec4ab252012-11-20 02:00:16 +0100602
603static int
604out_bits(FILE *stream, size_t low, size_t high)
605{
606 if (low == high)
607 return fprintf(stream, "%zd", low);
608 else
609 return fprintf(stream, "%zd-%zd", low, high);
610}
611
Petr Machataec4ab252012-11-20 02:00:16 +0100612static int
613bitvect_lens_format_cb(struct lens *lens, FILE *stream,
614 struct value *value, struct value_dict *arguments)
615{
616 unsigned char *data = value_get_data(value, arguments);
617 if (data == NULL)
618 return -1;
619 size_t sz = type_sizeof(value->inferior, value->type);
620 if (sz == (size_t)-1)
621 return -1;
622
623 size_t i;
624 unsigned char buf[sz];
625 switch ((int)value->type->type) {
626 union bitvect_integral_64
627 {
628 uint8_t u8;
629 uint16_t u16;
630 uint32_t u32;
631 uint64_t u64;
632 unsigned char buf[0];
633 } bv;
634
635 case ARGTYPE_POINTER:
636 return format_pointer(stream, value, arguments);
637
638 case ARGTYPE_STRUCT:
639 case ARGTYPE_ARRAY:
640 break;
641
642 default:
643 assert(sz <= sizeof(bv));
644 memmove(bv.buf, data, sz);
645
646 if (sz == 1)
647 bv.u64 = bv.u8;
648 else if (sz == 2)
649 bv.u64 = bv.u16;
650 else if (sz == 4)
651 bv.u64 = bv.u32;
652
653 for (i = 0; i < sz; ++i) {
654 buf[i] = bv.u64 & 0xff;
655 bv.u64 >>= 8;
656 }
657 data = buf;
658 }
659
660 size_t bits = 0;
661 for (i = 0; i < sz; ++i)
662 bits += bitcount(data[i]);
663
664 /* If there's more 1's than 0's, show inverse. */
665 unsigned neg = bits > sz * 4 ? 0xff : 0x00;
666
667 int o = 0;
Andrey Zonov6bb42012013-02-14 12:32:06 +0100668 if (acc_fprintf(&o, stream, "%s<", &"~"[neg == 0x00]) < 0)
Petr Machataec4ab252012-11-20 02:00:16 +0100669 return -1;
670
671 size_t bitno = 0;
672 ssize_t low = -1;
673 for (i = 0; i < sz; ++i) {
674 unsigned char m;
675 unsigned char d = data[i] ^ neg;
676 for (m = 0x01; m != 0; m <<= 1) {
677 int bit = !!(m & d);
678 if (low < 0) {
679 if (bit) {
680 if (low == -2
681 && acc_fprintf(&o, stream, ",") < 0)
682 return -1;
683 low = bitno;
684 }
685 } else if (!bit) {
686 if (account_output(&o, out_bits(stream, low,
687 bitno-1)) < 0)
688 return -1;
689 low = -2;
690 }
691 bitno++;
692 }
693 }
694 if (low >= 0 && account_output(&o, out_bits(stream, low, bitno-1)) < 0)
695 return -1;
696
697 if (fputc('>', stream) < 0)
698 return -1;
699 o += 1;
700
701 return o;
702}
703
704struct lens bitvect_lens = {
705 .format_cb = bitvect_lens_format_cb,
706};