blob: ed3d0e11a3b9c6100de159754288dda64f11f6b6 [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 Machata366c2f42012-02-09 19:34:36 +010032#include "proc.h"
Petr Machata31af32c2012-01-08 02:36:50 +010033#include "lens_default.h"
Petr Machata94078ec2012-01-05 18:07:02 +010034#include "value.h"
35#include "expr.h"
Petr Machata000e3112012-01-03 17:03:39 +010036#include "type.h"
Petr Machata94078ec2012-01-05 18:07:02 +010037#include "common.h"
Petr Machatad7b22922012-01-06 18:34:22 +010038#include "zero.h"
Juan Cespedes5e01f651998-03-08 22:31:44 +010039
Petr Machata94078ec2012-01-05 18:07:02 +010040#define READER(NAME, TYPE) \
41 static int \
42 NAME(struct value *value, TYPE *ret, struct value_dict *arguments) \
43 { \
44 union { \
45 TYPE val; \
46 unsigned char buf[0]; \
47 } u; \
48 if (value_extract_buf(value, u.buf, arguments) < 0) \
49 return -1; \
50 *ret = u.val; \
51 return 0; \
Juan Cespedesa413e5b2007-09-04 17:34:53 +020052 }
Steve Fink65b53df2006-09-25 02:27:08 +020053
Petr Machata94078ec2012-01-05 18:07:02 +010054READER(read_float, float)
55READER(read_double, double)
56
57#undef READER
58
59#define HANDLE_WIDTH(BITS) \
60 do { \
61 long l; \
62 if (value_extract_word(value, &l, arguments) < 0) \
63 return -1; \
64 int##BITS##_t i = l; \
Petr Machatae773f632012-11-09 18:52:53 +010065 uint64_t v = (uint64_t)(uint##BITS##_t)i; \
Petr Machata94078ec2012-01-05 18:07:02 +010066 switch (format) { \
67 case INT_FMT_unknown: \
Petr Machatac1e41862012-08-31 15:13:16 +020068 if (l < -10000 || l > 10000) \
Petr Machata94078ec2012-01-05 18:07:02 +010069 case INT_FMT_x: \
Petr Machatae773f632012-11-09 18:52:53 +010070 return fprintf(stream, "%#"PRIx64, v); \
Petr Machata94078ec2012-01-05 18:07:02 +010071 case INT_FMT_i: \
Petr Machatae773f632012-11-09 18:52:53 +010072 case INT_FMT_default: \
Petr Machata94078ec2012-01-05 18:07:02 +010073 return fprintf(stream, "%"PRIi##BITS, i); \
74 case INT_FMT_u: \
Petr Machatae773f632012-11-09 18:52:53 +010075 return fprintf(stream, "%"PRIu64, v); \
Petr Machata94078ec2012-01-05 18:07:02 +010076 case INT_FMT_o: \
Petr Machatae773f632012-11-09 18:52:53 +010077 return fprintf(stream, "0%"PRIo64, v); \
Petr Machata94078ec2012-01-05 18:07:02 +010078 } \
79 } while (0)
80
81enum int_fmt_t
82{
83 INT_FMT_i,
84 INT_FMT_u,
85 INT_FMT_o,
86 INT_FMT_x,
87 INT_FMT_unknown,
Petr Machatae773f632012-11-09 18:52:53 +010088 INT_FMT_default,
Petr Machata94078ec2012-01-05 18:07:02 +010089};
90
91static int
92format_integer(FILE *stream, struct value *value, enum int_fmt_t format,
93 struct value_dict *arguments)
94{
95 switch (type_sizeof(value->inferior, value->type)) {
96
97 case 1: HANDLE_WIDTH(8);
98 case 2: HANDLE_WIDTH(16);
99 case 4: HANDLE_WIDTH(32);
100 case 8: HANDLE_WIDTH(64);
101
102 default:
103 assert(!"unsupported integer width");
104 abort();
105
106 case -1:
107 return -1;
108 }
109}
110
111#undef HANDLE_WIDTH
112
113static int
Petr Machata94078ec2012-01-05 18:07:02 +0100114acc_fprintf(int *countp, FILE *stream, const char *format, ...)
115{
116 va_list pa;
117 va_start(pa, format);
Petr Machataadec2012012-11-01 22:05:04 +0100118 int i = account_output(countp, vfprintf(stream, format, pa));
Petr Machata94078ec2012-01-05 18:07:02 +0100119 va_end(pa);
120
Petr Machata94078ec2012-01-05 18:07:02 +0100121 return i;
122}
123
124static int
125format_char(FILE *stream, struct value *value, struct value_dict *arguments)
126{
127 long lc;
128 if (value_extract_word(value, &lc, arguments) < 0)
129 return -1;
130 int c = (int)lc;
131
Petr Machata94078ec2012-01-05 18:07:02 +0100132 const char *fmt;
133 switch (c) {
134 case -1:
135 fmt = "EOF";
136 break;
137 case 0:
138 fmt = "\\0";
139 break;
140 case '\a':
141 fmt = "\\a";
142 break;
143 case '\b':
144 fmt = "\\b";
145 break;
146 case '\t':
147 fmt = "\\t";
148 break;
149 case '\n':
150 fmt = "\\n";
151 break;
152 case '\v':
153 fmt = "\\v";
154 break;
155 case '\f':
156 fmt = "\\f";
157 break;
158 case '\r':
159 fmt = "\\r";
160 break;
161 case '\\':
162 fmt = "\\\\";
163 break;
164 default:
165 if (isprint(c) || c == ' ')
166 fmt = "%c";
Petr Machata94078ec2012-01-05 18:07:02 +0100167 else
Petr Machata987d27b2012-01-17 19:04:04 +0100168 fmt = "\\%03o";
Petr Machata94078ec2012-01-05 18:07:02 +0100169 }
170
Petr Machata987d27b2012-01-17 19:04:04 +0100171 return fprintf(stream, fmt, c);
Petr Machatae3f4a982012-01-09 04:27:26 +0100172}
173
174static int
175format_naked_char(FILE *stream, struct value *value,
176 struct value_dict *arguments)
177{
178 int written = 0;
179 if (acc_fprintf(&written, stream, "'") < 0
Petr Machataadec2012012-11-01 22:05:04 +0100180 || account_output(&written,
181 format_char(stream, value, arguments)) < 0
Petr Machatae3f4a982012-01-09 04:27:26 +0100182 || acc_fprintf(&written, stream, "'") < 0)
Petr Machata94078ec2012-01-05 18:07:02 +0100183 return -1;
Petr Machatae3f4a982012-01-09 04:27:26 +0100184
Petr Machata94078ec2012-01-05 18:07:02 +0100185 return written;
186}
187
188static int
Petr Machataf1977272012-11-29 15:49:16 +0100189format_double(FILE *stream, double value, enum int_fmt_t format)
190{
191 if (format == INT_FMT_x)
192 return fprintf(stream, "%a", value);
193 else
194 return fprintf(stream, "%f", value);
195}
196
197static int
198format_floating(FILE *stream, struct value *value, struct value_dict *arguments,
199 enum int_fmt_t format)
Petr Machata94078ec2012-01-05 18:07:02 +0100200{
201 switch (value->type->type) {
202 float f;
203 double d;
204 case ARGTYPE_FLOAT:
205 if (read_float(value, &f, arguments) < 0)
206 return -1;
Petr Machataf1977272012-11-29 15:49:16 +0100207 return format_double(stream, f, format);
Petr Machata94078ec2012-01-05 18:07:02 +0100208 case ARGTYPE_DOUBLE:
209 if (read_double(value, &d, arguments) < 0)
210 return -1;
Petr Machataf1977272012-11-29 15:49:16 +0100211 return format_double(stream, d, format);
Petr Machata94078ec2012-01-05 18:07:02 +0100212 default:
213 abort();
214 }
215}
216
Petr Machataf7c46bb2012-11-01 22:15:45 +0100217struct format_argument_data
218{
219 struct value *value;
220 struct value_dict *arguments;
221};
222
223static int
224format_argument_cb(FILE *stream, void *ptr)
225{
226 struct format_argument_data *data = ptr;
227 return format_argument(stream, data->value, data->arguments);
228}
229
Petr Machata94078ec2012-01-05 18:07:02 +0100230static int
231format_struct(FILE *stream, struct value *value, struct value_dict *arguments)
232{
233 int written = 0;
234 if (acc_fprintf(&written, stream, "{ ") < 0)
235 return -1;
Petr Machataf7c46bb2012-11-01 22:15:45 +0100236
237 int need_delim = 0;
Petr Machata94078ec2012-01-05 18:07:02 +0100238 size_t i;
239 for (i = 0; i < type_struct_size(value->type); ++i) {
Petr Machata94078ec2012-01-05 18:07:02 +0100240 struct value element;
241 if (value_init_element(&element, value, i) < 0)
242 return -1;
Petr Machataf7c46bb2012-11-01 22:15:45 +0100243
244 struct format_argument_data data = { &element, arguments };
245 int o = delim_output(stream, &need_delim,
246 format_argument_cb, &data);
Petr Machata8904cdc2012-10-30 17:27:20 +0100247 value_destroy(&element);
Petr Machata94078ec2012-01-05 18:07:02 +0100248 if (o < 0)
249 return -1;
Petr Machataf7c46bb2012-11-01 22:15:45 +0100250
Petr Machata94078ec2012-01-05 18:07:02 +0100251 written += o;
252 }
253 if (acc_fprintf(&written, stream, " }") < 0)
254 return -1;
255 return written;
256}
257
258int
259format_pointer(FILE *stream, struct value *value, struct value_dict *arguments)
260{
Petr Machata26c0c942012-11-19 00:14:51 +0100261 if (value_is_zero(value, arguments))
262 return fprintf(stream, "nil");
263
Petr Machata307b90b2012-11-19 00:35:38 +0100264 /* The following is for detecting recursion. We keep track of
265 * the values that were already displayed. Each time a
266 * pointer should be dereferenced, we compare its value to the
267 * value of each of the pointers dereferenced so far. If one
268 * of them matches, instead of recursing, we just printf which
269 * superstructure this pointer recurses to. */
270 static struct vect pointers = {};
271 if (pointers.elt_size == 0)
272 VECT_INIT(&pointers, struct value *);
273
Petr Machata6248a0a2012-11-19 01:00:54 +0100274 /* Trim number of expanded structures of the same type. Even
275 * for non-recursive structure, we don't want to expand all of
276 * it if it's huge. */
Petr Machata307b90b2012-11-19 00:35:38 +0100277 size_t i;
Petr Machata6248a0a2012-11-19 01:00:54 +0100278 size_t len = vect_size(&pointers);
279 assert(value->type->type == ARGTYPE_POINTER);
280 struct arg_type_info *pointee = value->type->u.ptr_info.info;
281 if (pointee->type == ARGTYPE_STRUCT) {
282 size_t depth = 0;
283 for (i = 0; i < len; ++i) {
284 struct value *old
285 = *VECT_ELEMENT(&pointers, struct value *, i);
286 assert(old->type->type == ARGTYPE_POINTER);
287 struct arg_type_info *old_pointee
288 = old->type->u.ptr_info.info;
289 if (old_pointee == pointee)
290 depth++;
291 }
292 if (depth >= options.arraylen)
293 return fprintf(stream, "...");
294 }
295
Petr Machata307b90b2012-11-19 00:35:38 +0100296 for (i = len; i-- > 0 ;) {
297 struct value **old = VECT_ELEMENT(&pointers, struct value *, i);
298 int rc = value_equal(value, *old, arguments);
299 if (rc < 0)
300 return -1;
301 if (rc > 0) {
302 size_t reclevel = len - i - 1;
303 char buf[reclevel + 1];
304 memset(buf, '^', sizeof buf);
305 buf[reclevel] = 0;
306 return fprintf(stream, "recurse%s", buf);
307 }
308 }
309
310 /* OK, not a recursion. Remember this value for tracking. */
311 if (VECT_PUSHBACK(&pointers, &value) < 0)
312 return -1;
313
Petr Machata94078ec2012-01-05 18:07:02 +0100314 struct value element;
Petr Machata26c0c942012-11-19 00:14:51 +0100315 int o;
316 if (value_init_deref(&element, value) < 0) {
317 o = -1;
318 goto done;
319 }
320 o = format_argument(stream, &element, arguments);
Petr Machata8904cdc2012-10-30 17:27:20 +0100321 value_destroy(&element);
Petr Machata26c0c942012-11-19 00:14:51 +0100322
323done:
Petr Machata307b90b2012-11-19 00:35:38 +0100324 vect_popback(&pointers);
Petr Machata8904cdc2012-10-30 17:27:20 +0100325 return o;
Steve Fink1150bc42006-08-07 06:04:43 +0200326}
327
328/*
Petr Machata94078ec2012-01-05 18:07:02 +0100329 * LENGTH is an expression whose evaluation will yield the actual
330 * length of the array.
Steve Fink1150bc42006-08-07 06:04:43 +0200331 *
Petr Machata94078ec2012-01-05 18:07:02 +0100332 * MAXLEN is the actual maximum length that we care about
333 *
334 * BEFORE if LENGTH>MAXLEN, we display ellipsis. We display it before
335 * the closing parenthesis if BEFORE, otherwise after it.
336 *
337 * OPEN, CLOSE, DELIM are opening and closing parenthesis and element
338 * delimiter.
Steve Fink1150bc42006-08-07 06:04:43 +0200339 */
Juan Cespedesf1350522008-12-16 18:19:58 +0100340int
Petr Machata94078ec2012-01-05 18:07:02 +0100341format_array(FILE *stream, struct value *value, struct value_dict *arguments,
342 struct expr_node *length, size_t maxlen, int before,
343 const char *open, const char *close, const char *delim)
Petr Machata000e3112012-01-03 17:03:39 +0100344{
Petr Machata94078ec2012-01-05 18:07:02 +0100345 /* We need "long" to be long enough to cover the whole address
346 * space. */
347 typedef char assert__long_enough_long[-(sizeof(long) < sizeof(void *))];
Petr Machata31af32c2012-01-08 02:36:50 +0100348 long l;
Petr Machatad7b22922012-01-06 18:34:22 +0100349 if (expr_eval_word(length, value, arguments, &l) < 0)
350 return -1;
Petr Machata94078ec2012-01-05 18:07:02 +0100351 size_t len = (size_t)l;
Steve Fink7bafff02006-08-07 04:50:42 +0200352
Petr Machata94078ec2012-01-05 18:07:02 +0100353 int written = 0;
354 if (acc_fprintf(&written, stream, "%s", open) < 0)
355 return -1;
Juan Cespedes5e01f651998-03-08 22:31:44 +0100356
Zachary T Welchba6aca22010-12-08 18:55:09 -0800357 size_t i;
Petr Machata94078ec2012-01-05 18:07:02 +0100358 for (i = 0; i < len && i <= maxlen; ++i) {
359 if (i == maxlen) {
360 if (before && acc_fprintf(&written, stream, "...") < 0)
361 return -1;
Juan Cespedes5e01f651998-03-08 22:31:44 +0100362 break;
363 }
Petr Machata94078ec2012-01-05 18:07:02 +0100364
365 if (i > 0 && acc_fprintf(&written, stream, "%s", delim) < 0)
366 return -1;
367
368 struct value element;
369 if (value_init_element(&element, value, i) < 0)
370 return -1;
Petr Machataf6ec08a2012-01-06 16:58:54 +0100371 int o = format_argument(stream, &element, arguments);
Petr Machata8904cdc2012-10-30 17:27:20 +0100372 value_destroy(&element);
Petr Machata94078ec2012-01-05 18:07:02 +0100373 if (o < 0)
374 return -1;
375 written += o;
Juan Cespedes5e01f651998-03-08 22:31:44 +0100376 }
Petr Machata94078ec2012-01-05 18:07:02 +0100377 if (acc_fprintf(&written, stream, "%s", close) < 0)
378 return -1;
379 if (i == maxlen && !before && acc_fprintf(&written, stream, "...") < 0)
380 return -1;
381
382 return written;
Juan Cespedes5e01f651998-03-08 22:31:44 +0100383}
384
Petr Machata31af32c2012-01-08 02:36:50 +0100385static int
386toplevel_format_lens(struct lens *lens, FILE *stream,
Petr Machatace034982012-01-09 04:25:31 +0100387 struct value *value, struct value_dict *arguments,
388 enum int_fmt_t int_fmt)
Petr Machata94078ec2012-01-05 18:07:02 +0100389{
Petr Machata94078ec2012-01-05 18:07:02 +0100390 switch (value->type->type) {
391 case ARGTYPE_VOID:
392 return fprintf(stream, "<void>");
393
Petr Machata94078ec2012-01-05 18:07:02 +0100394 case ARGTYPE_SHORT:
395 case ARGTYPE_INT:
396 case ARGTYPE_LONG:
Petr Machatace034982012-01-09 04:25:31 +0100397 return format_integer(stream, value, int_fmt, arguments);
Petr Machata94078ec2012-01-05 18:07:02 +0100398
399 case ARGTYPE_USHORT:
400 case ARGTYPE_UINT:
401 case ARGTYPE_ULONG:
Petr Machatae773f632012-11-09 18:52:53 +0100402 if (int_fmt == INT_FMT_i || int_fmt == INT_FMT_default)
Petr Machatace034982012-01-09 04:25:31 +0100403 int_fmt = INT_FMT_u;
404 return format_integer(stream, value, int_fmt, arguments);
Petr Machata94078ec2012-01-05 18:07:02 +0100405
406 case ARGTYPE_CHAR:
Petr Machatae773f632012-11-09 18:52:53 +0100407 if (int_fmt == INT_FMT_default)
408 return format_naked_char(stream, value, arguments);
409 return format_integer(stream, value, int_fmt, arguments);
Petr Machata94078ec2012-01-05 18:07:02 +0100410
411 case ARGTYPE_FLOAT:
412 case ARGTYPE_DOUBLE:
Petr Machataf1977272012-11-29 15:49:16 +0100413 return format_floating(stream, value, arguments, int_fmt);
Petr Machata94078ec2012-01-05 18:07:02 +0100414
415 case ARGTYPE_STRUCT:
416 return format_struct(stream, value, arguments);
417
418 case ARGTYPE_POINTER:
419 if (value->type->u.array_info.elt_type->type != ARGTYPE_VOID)
420 return format_pointer(stream, value, arguments);
Petr Machata94078ec2012-01-05 18:07:02 +0100421 return format_integer(stream, value, INT_FMT_x, arguments);
422
423 case ARGTYPE_ARRAY:
Petr Machata94078ec2012-01-05 18:07:02 +0100424 return format_array(stream, value, arguments,
425 value->type->u.array_info.length,
Petr Machatae3f4a982012-01-09 04:27:26 +0100426 options.arraylen, 1, "[ ", " ]", ", ");
Petr Machata94078ec2012-01-05 18:07:02 +0100427 }
428 abort();
429}
Petr Machata31af32c2012-01-08 02:36:50 +0100430
431static int
432default_lens_format_cb(struct lens *lens, FILE *stream,
433 struct value *value, struct value_dict *arguments)
434{
Petr Machatae773f632012-11-09 18:52:53 +0100435 return toplevel_format_lens(lens, stream, value, arguments,
436 INT_FMT_default);
Petr Machata31af32c2012-01-08 02:36:50 +0100437}
438
439struct lens default_lens = {
440 .format_cb = default_lens_format_cb,
441};
Petr Machatace034982012-01-09 04:25:31 +0100442
443
444static int
445blind_lens_format_cb(struct lens *lens, FILE *stream,
446 struct value *value, struct value_dict *arguments)
447{
448 return 0;
449}
450
451struct lens blind_lens = {
452 .format_cb = blind_lens_format_cb,
453};
454
455
456static int
457octal_lens_format_cb(struct lens *lens, FILE *stream,
458 struct value *value, struct value_dict *arguments)
459{
460 return toplevel_format_lens(lens, stream, value, arguments, INT_FMT_o);
461}
462
463struct lens octal_lens = {
464 .format_cb = octal_lens_format_cb,
465};
466
467
468static int
469hex_lens_format_cb(struct lens *lens, FILE *stream,
470 struct value *value, struct value_dict *arguments)
471{
472 return toplevel_format_lens(lens, stream, value, arguments, INT_FMT_x);
473}
474
475struct lens hex_lens = {
476 .format_cb = hex_lens_format_cb,
477};
Petr Machatab7819162012-01-09 04:26:15 +0100478
479
480static int
Petr Machataec4ab252012-11-20 02:00:16 +0100481dec_lens_format_cb(struct lens *lens, FILE *stream,
482 struct value *value, struct value_dict *arguments)
483{
484 return toplevel_format_lens(lens, stream, value, arguments, INT_FMT_u);
485}
486
487struct lens dec_lens = {
488 .format_cb = dec_lens_format_cb,
489};
490
491
492static int
Petr Machatab7819162012-01-09 04:26:15 +0100493guess_lens_format_cb(struct lens *lens, FILE *stream,
494 struct value *value, struct value_dict *arguments)
495{
496 return toplevel_format_lens(lens, stream, value, arguments,
497 INT_FMT_unknown);
498}
499
500struct lens guess_lens = {
501 .format_cb = guess_lens_format_cb,
502};
Petr Machatae3f4a982012-01-09 04:27:26 +0100503
504
505static int
Petr Machata38fb49b2012-01-09 04:28:46 +0100506bool_lens_format_cb(struct lens *lens, FILE *stream,
507 struct value *value, struct value_dict *arguments)
508{
509 switch (value->type->type) {
510 case ARGTYPE_VOID:
511 case ARGTYPE_FLOAT:
512 case ARGTYPE_DOUBLE:
513 case ARGTYPE_STRUCT:
514 case ARGTYPE_POINTER:
515 case ARGTYPE_ARRAY:
516 return toplevel_format_lens(lens, stream, value,
Petr Machatae773f632012-11-09 18:52:53 +0100517 arguments, INT_FMT_default);
Petr Machata38fb49b2012-01-09 04:28:46 +0100518
519 int zero;
Petr Machata38fb49b2012-01-09 04:28:46 +0100520 case ARGTYPE_SHORT:
521 case ARGTYPE_INT:
522 case ARGTYPE_LONG:
523 case ARGTYPE_USHORT:
524 case ARGTYPE_UINT:
525 case ARGTYPE_ULONG:
526 case ARGTYPE_CHAR:
527 if ((zero = value_is_zero(value, arguments)) < 0)
528 return -1;
529 if (zero)
530 return fprintf(stream, "false");
531 else
532 return fprintf(stream, "true");
533 }
534 abort();
535}
536
537struct lens bool_lens = {
538 .format_cb = bool_lens_format_cb,
539};
540
541
542static int
Petr Machatae3f4a982012-01-09 04:27:26 +0100543string_lens_format_cb(struct lens *lens, FILE *stream,
544 struct value *value, struct value_dict *arguments)
545{
546 switch (value->type->type) {
547 case ARGTYPE_POINTER:
548 /* This should really be written as either "string",
549 * or, if lens, then string(array(char, zero)*). But
550 * I suspect people are so used to the char * C idiom,
551 * that string(char *) might actually turn up. So
552 * let's just support it. */
553 if (value->type->u.ptr_info.info->type == ARGTYPE_CHAR) {
554 struct arg_type_info info[2];
555 type_init_array(&info[1],
556 value->type->u.ptr_info.info, 0,
557 expr_node_zero(), 0);
558 type_init_pointer(&info[0], &info[1], 0);
559 info->lens = lens;
560 info->own_lens = 0;
561 struct value tmp;
562 if (value_clone(&tmp, value) < 0)
563 return -1;
564 value_set_type(&tmp, info, 0);
565 int ret = string_lens_format_cb(lens, stream, &tmp,
566 arguments);
567 type_destroy(&info[0]);
568 type_destroy(&info[1]);
569 value_destroy(&tmp);
570 return ret;
571 }
572
573 /* fall-through */
574 case ARGTYPE_VOID:
575 case ARGTYPE_FLOAT:
576 case ARGTYPE_DOUBLE:
577 case ARGTYPE_STRUCT:
578 case ARGTYPE_SHORT:
579 case ARGTYPE_INT:
580 case ARGTYPE_LONG:
581 case ARGTYPE_USHORT:
582 case ARGTYPE_UINT:
583 case ARGTYPE_ULONG:
Petr Machatae3f4a982012-01-09 04:27:26 +0100584 return toplevel_format_lens(lens, stream, value,
Petr Machatae773f632012-11-09 18:52:53 +0100585 arguments, INT_FMT_default);
Petr Machatae3f4a982012-01-09 04:27:26 +0100586
587 case ARGTYPE_CHAR:
588 return format_char(stream, value, arguments);
589
590 case ARGTYPE_ARRAY:
591 return format_array(stream, value, arguments,
592 value->type->u.array_info.length,
593 options.strlen, 0, "\"", "\"", "");
594 }
595 abort();
596}
597
598struct lens string_lens = {
599 .format_cb = string_lens_format_cb,
600};
Petr Machataec4ab252012-11-20 02:00:16 +0100601
602static int
603out_bits(FILE *stream, size_t low, size_t high)
604{
605 if (low == high)
606 return fprintf(stream, "%zd", low);
607 else
608 return fprintf(stream, "%zd-%zd", low, high);
609}
610
611static unsigned
612bitcount(unsigned u)
613{
614 int c = 0;
615 for (; u > 0; u &= u - 1)
616 c++;
617 return c;
618}
619
620static int
621bitvect_lens_format_cb(struct lens *lens, FILE *stream,
622 struct value *value, struct value_dict *arguments)
623{
624 unsigned char *data = value_get_data(value, arguments);
625 if (data == NULL)
626 return -1;
627 size_t sz = type_sizeof(value->inferior, value->type);
628 if (sz == (size_t)-1)
629 return -1;
630
631 size_t i;
632 unsigned char buf[sz];
633 switch ((int)value->type->type) {
634 union bitvect_integral_64
635 {
636 uint8_t u8;
637 uint16_t u16;
638 uint32_t u32;
639 uint64_t u64;
640 unsigned char buf[0];
641 } bv;
642
643 case ARGTYPE_POINTER:
644 return format_pointer(stream, value, arguments);
645
646 case ARGTYPE_STRUCT:
647 case ARGTYPE_ARRAY:
648 break;
649
650 default:
651 assert(sz <= sizeof(bv));
652 memmove(bv.buf, data, sz);
653
654 if (sz == 1)
655 bv.u64 = bv.u8;
656 else if (sz == 2)
657 bv.u64 = bv.u16;
658 else if (sz == 4)
659 bv.u64 = bv.u32;
660
661 for (i = 0; i < sz; ++i) {
662 buf[i] = bv.u64 & 0xff;
663 bv.u64 >>= 8;
664 }
665 data = buf;
666 }
667
668 size_t bits = 0;
669 for (i = 0; i < sz; ++i)
670 bits += bitcount(data[i]);
671
672 /* If there's more 1's than 0's, show inverse. */
673 unsigned neg = bits > sz * 4 ? 0xff : 0x00;
674
675 int o = 0;
676 if (acc_fprintf(&o, stream, "%s<", "~" + (neg == 0x00)) < 0)
677 return -1;
678
679 size_t bitno = 0;
680 ssize_t low = -1;
681 for (i = 0; i < sz; ++i) {
682 unsigned char m;
683 unsigned char d = data[i] ^ neg;
684 for (m = 0x01; m != 0; m <<= 1) {
685 int bit = !!(m & d);
686 if (low < 0) {
687 if (bit) {
688 if (low == -2
689 && acc_fprintf(&o, stream, ",") < 0)
690 return -1;
691 low = bitno;
692 }
693 } else if (!bit) {
694 if (account_output(&o, out_bits(stream, low,
695 bitno-1)) < 0)
696 return -1;
697 low = -2;
698 }
699 bitno++;
700 }
701 }
702 if (low >= 0 && account_output(&o, out_bits(stream, low, bitno-1)) < 0)
703 return -1;
704
705 if (fputc('>', stream) < 0)
706 return -1;
707 o += 1;
708
709 return o;
710}
711
712struct lens bitvect_lens = {
713 .format_cb = bitvect_lens_format_cb,
714};