lens_default.c revision adec201a52c240cf4b533c05106aedddc911ca76
1/*
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
24#include <ctype.h>
25#include <stdlib.h>
26#include <assert.h>
27#include <inttypes.h>
28#include <stdarg.h>
29#include <stdio.h>
30
31#include "proc.h"
32#include "lens_default.h"
33#include "value.h"
34#include "expr.h"
35#include "type.h"
36#include "common.h"
37#include "zero.h"
38
39#define READER(NAME, TYPE)						\
40	static int							\
41	NAME(struct value *value, TYPE *ret, struct value_dict *arguments) \
42	{								\
43		union {							\
44			TYPE val;					\
45			unsigned char buf[0];				\
46		} u;							\
47		if (value_extract_buf(value, u.buf, arguments) < 0)	\
48			return -1;					\
49		*ret = u.val;						\
50		return 0;						\
51	}
52
53READER(read_float, float)
54READER(read_double, double)
55
56#undef READER
57
58#define HANDLE_WIDTH(BITS)						\
59	do {								\
60		long l;							\
61		if (value_extract_word(value, &l, arguments) < 0)	\
62			return -1;					\
63		int##BITS##_t i = l;					\
64		switch (format) {					\
65		case INT_FMT_unknown:					\
66			if (l < -10000 || l > 10000)			\
67		case INT_FMT_x:						\
68			return fprintf(stream, "%#"PRIx##BITS, i);	\
69		case INT_FMT_i:						\
70			return fprintf(stream, "%"PRIi##BITS, i);	\
71		case INT_FMT_u:						\
72			return fprintf(stream, "%"PRIu##BITS, i);	\
73		case INT_FMT_o:						\
74			return fprintf(stream, "0%"PRIo##BITS, i);	\
75		}							\
76	} while (0)
77
78enum int_fmt_t
79{
80	INT_FMT_i,
81	INT_FMT_u,
82	INT_FMT_o,
83	INT_FMT_x,
84	INT_FMT_unknown,
85};
86
87static int
88format_integer(FILE *stream, struct value *value, enum int_fmt_t format,
89	       struct value_dict *arguments)
90{
91	switch (type_sizeof(value->inferior, value->type)) {
92
93	case 1: HANDLE_WIDTH(8);
94	case 2: HANDLE_WIDTH(16);
95	case 4: HANDLE_WIDTH(32);
96	case 8: HANDLE_WIDTH(64);
97
98	default:
99		assert(!"unsupported integer width");
100		abort();
101
102	case -1:
103		return -1;
104	}
105}
106
107#undef HANDLE_WIDTH
108
109static int
110acc_fprintf(int *countp, FILE *stream, const char *format, ...)
111{
112	va_list pa;
113	va_start(pa, format);
114	int i = account_output(countp, vfprintf(stream, format, pa));
115	va_end(pa);
116
117	return i;
118}
119
120static int
121format_char(FILE *stream, struct value *value, struct value_dict *arguments)
122{
123	long lc;
124	if (value_extract_word(value, &lc, arguments) < 0)
125		return -1;
126	int c = (int)lc;
127
128	const char *fmt;
129	switch (c) {
130	case -1:
131		fmt = "EOF";
132		break;
133	case 0:
134		fmt = "\\0";
135		break;
136	case '\a':
137		fmt = "\\a";
138		break;
139	case '\b':
140		fmt = "\\b";
141		break;
142	case '\t':
143		fmt = "\\t";
144		break;
145	case '\n':
146		fmt = "\\n";
147		break;
148	case '\v':
149		fmt = "\\v";
150		break;
151	case '\f':
152		fmt = "\\f";
153		break;
154	case '\r':
155		fmt = "\\r";
156		break;
157	case '\\':
158		fmt = "\\\\";
159		break;
160	default:
161		if (isprint(c) || c == ' ')
162			fmt = "%c";
163		else
164			fmt = "\\%03o";
165	}
166
167	return fprintf(stream, fmt, c);
168}
169
170static int
171format_naked_char(FILE *stream, struct value *value,
172		  struct value_dict *arguments)
173{
174	int written = 0;
175	if (acc_fprintf(&written, stream, "'") < 0
176	    || account_output(&written,
177			      format_char(stream, value, arguments)) < 0
178	    || acc_fprintf(&written, stream, "'") < 0)
179		return -1;
180
181	return written;
182}
183
184static int
185format_floating(FILE *stream, struct value *value, struct value_dict *arguments)
186{
187	switch (value->type->type) {
188		float f;
189		double d;
190	case ARGTYPE_FLOAT:
191		if (read_float(value, &f, arguments) < 0)
192			return -1;
193		return fprintf(stream, "%f", (double)f);
194	case ARGTYPE_DOUBLE:
195		if (read_double(value, &d, arguments) < 0)
196			return -1;
197		return fprintf(stream, "%f", d);
198	default:
199		abort();
200	}
201}
202
203static int
204format_struct(FILE *stream, struct value *value, struct value_dict *arguments)
205{
206	int written = 0;
207	if (acc_fprintf(&written, stream, "{ ") < 0)
208		return -1;
209	size_t i;
210	for (i = 0; i < type_struct_size(value->type); ++i) {
211		if (i > 0 && acc_fprintf(&written, stream, ", ") < 0)
212			return -1;
213
214		struct value element;
215		if (value_init_element(&element, value, i) < 0)
216			return -1;
217		int o = format_argument(stream, &element, arguments);
218		value_destroy(&element);
219		if (o < 0)
220			return -1;
221		written += o;
222	}
223	if (acc_fprintf(&written, stream, " }") < 0)
224		return -1;
225	return written;
226}
227
228int
229format_pointer(FILE *stream, struct value *value, struct value_dict *arguments)
230{
231	struct value element;
232	if (value_init_deref(&element, value) < 0)
233		return -1;
234	int o = format_argument(stream, &element, arguments);
235	value_destroy(&element);
236	return o;
237}
238
239/*
240 * LENGTH is an expression whose evaluation will yield the actual
241 *    length of the array.
242 *
243 * MAXLEN is the actual maximum length that we care about
244 *
245 * BEFORE if LENGTH>MAXLEN, we display ellipsis.  We display it before
246 *    the closing parenthesis if BEFORE, otherwise after it.
247 *
248 * OPEN, CLOSE, DELIM are opening and closing parenthesis and element
249 *    delimiter.
250 */
251int
252format_array(FILE *stream, struct value *value, struct value_dict *arguments,
253	     struct expr_node *length, size_t maxlen, int before,
254	     const char *open, const char *close, const char *delim)
255{
256	/* We need "long" to be long enough to cover the whole address
257	 * space.  */
258	typedef char assert__long_enough_long[-(sizeof(long) < sizeof(void *))];
259	long l;
260	if (expr_eval_word(length, value, arguments, &l) < 0)
261		return -1;
262	size_t len = (size_t)l;
263
264	int written = 0;
265	if (acc_fprintf(&written, stream, "%s", open) < 0)
266		return -1;
267
268	size_t i;
269	for (i = 0; i < len && i <= maxlen; ++i) {
270		if (i == maxlen) {
271			if (before && acc_fprintf(&written, stream, "...") < 0)
272				return -1;
273			break;
274		}
275
276		if (i > 0 && acc_fprintf(&written, stream, "%s", delim) < 0)
277			return -1;
278
279		struct value element;
280		if (value_init_element(&element, value, i) < 0)
281			return -1;
282		int o = format_argument(stream, &element, arguments);
283		value_destroy(&element);
284		if (o < 0)
285			return -1;
286		written += o;
287	}
288	if (acc_fprintf(&written, stream, "%s", close) < 0)
289		return -1;
290	if (i == maxlen && !before && acc_fprintf(&written, stream, "...") < 0)
291		return -1;
292
293	return written;
294}
295
296static int
297toplevel_format_lens(struct lens *lens, FILE *stream,
298		     struct value *value, struct value_dict *arguments,
299		     enum int_fmt_t int_fmt)
300{
301	switch (value->type->type) {
302	case ARGTYPE_VOID:
303		return fprintf(stream, "<void>");
304
305	case ARGTYPE_SHORT:
306	case ARGTYPE_INT:
307	case ARGTYPE_LONG:
308		return format_integer(stream, value, int_fmt, arguments);
309
310	case ARGTYPE_USHORT:
311	case ARGTYPE_UINT:
312	case ARGTYPE_ULONG:
313		if (int_fmt == INT_FMT_i)
314			int_fmt = INT_FMT_u;
315		return format_integer(stream, value, int_fmt, arguments);
316
317	case ARGTYPE_CHAR:
318		return format_naked_char(stream, value, arguments);
319
320	case ARGTYPE_FLOAT:
321	case ARGTYPE_DOUBLE:
322		return format_floating(stream, value, arguments);
323
324	case ARGTYPE_STRUCT:
325		return format_struct(stream, value, arguments);
326
327	case ARGTYPE_POINTER:
328		if (value->type->u.array_info.elt_type->type != ARGTYPE_VOID)
329			return format_pointer(stream, value, arguments);
330		return format_integer(stream, value, INT_FMT_x, arguments);
331
332	case ARGTYPE_ARRAY:
333		return format_array(stream, value, arguments,
334				    value->type->u.array_info.length,
335				    options.arraylen, 1, "[ ", " ]", ", ");
336	}
337	abort();
338}
339
340static int
341default_lens_format_cb(struct lens *lens, FILE *stream,
342		       struct value *value, struct value_dict *arguments)
343{
344	return toplevel_format_lens(lens, stream, value, arguments, INT_FMT_i);
345}
346
347struct lens default_lens = {
348	.format_cb = default_lens_format_cb,
349};
350
351
352static int
353blind_lens_format_cb(struct lens *lens, FILE *stream,
354		     struct value *value, struct value_dict *arguments)
355{
356	return 0;
357}
358
359struct lens blind_lens = {
360	.format_cb = blind_lens_format_cb,
361};
362
363
364static int
365octal_lens_format_cb(struct lens *lens, FILE *stream,
366		     struct value *value, struct value_dict *arguments)
367{
368	return toplevel_format_lens(lens, stream, value, arguments, INT_FMT_o);
369}
370
371struct lens octal_lens = {
372	.format_cb = octal_lens_format_cb,
373};
374
375
376static int
377hex_lens_format_cb(struct lens *lens, FILE *stream,
378		   struct value *value, struct value_dict *arguments)
379{
380	return toplevel_format_lens(lens, stream, value, arguments, INT_FMT_x);
381}
382
383struct lens hex_lens = {
384	.format_cb = hex_lens_format_cb,
385};
386
387
388static int
389guess_lens_format_cb(struct lens *lens, FILE *stream,
390		     struct value *value, struct value_dict *arguments)
391{
392	return toplevel_format_lens(lens, stream, value, arguments,
393				    INT_FMT_unknown);
394}
395
396struct lens guess_lens = {
397	.format_cb = guess_lens_format_cb,
398};
399
400
401static int
402bool_lens_format_cb(struct lens *lens, FILE *stream,
403		    struct value *value, struct value_dict *arguments)
404{
405	switch (value->type->type) {
406	case ARGTYPE_VOID:
407	case ARGTYPE_FLOAT:
408	case ARGTYPE_DOUBLE:
409	case ARGTYPE_STRUCT:
410	case ARGTYPE_POINTER:
411	case ARGTYPE_ARRAY:
412		return toplevel_format_lens(lens, stream, value,
413					    arguments, INT_FMT_i);
414
415		int zero;
416	case ARGTYPE_SHORT:
417	case ARGTYPE_INT:
418	case ARGTYPE_LONG:
419	case ARGTYPE_USHORT:
420	case ARGTYPE_UINT:
421	case ARGTYPE_ULONG:
422	case ARGTYPE_CHAR:
423		if ((zero = value_is_zero(value, arguments)) < 0)
424			return -1;
425		if (zero)
426			return fprintf(stream, "false");
427		else
428			return fprintf(stream, "true");
429	}
430	abort();
431}
432
433struct lens bool_lens = {
434	.format_cb = bool_lens_format_cb,
435};
436
437
438static int
439string_lens_format_cb(struct lens *lens, FILE *stream,
440		      struct value *value, struct value_dict *arguments)
441{
442	switch (value->type->type) {
443	case ARGTYPE_POINTER:
444		/* This should really be written as either "string",
445		 * or, if lens, then string(array(char, zero)*).  But
446		 * I suspect people are so used to the char * C idiom,
447		 * that string(char *) might actually turn up.  So
448		 * let's just support it.  */
449		if (value->type->u.ptr_info.info->type == ARGTYPE_CHAR) {
450			struct arg_type_info info[2];
451			type_init_array(&info[1],
452					value->type->u.ptr_info.info, 0,
453					expr_node_zero(), 0);
454			type_init_pointer(&info[0], &info[1], 0);
455			info->lens = lens;
456			info->own_lens = 0;
457			struct value tmp;
458			if (value_clone(&tmp, value) < 0)
459				return -1;
460			value_set_type(&tmp, info, 0);
461			int ret = string_lens_format_cb(lens, stream, &tmp,
462							arguments);
463			type_destroy(&info[0]);
464			type_destroy(&info[1]);
465			value_destroy(&tmp);
466			return ret;
467		}
468
469		/* fall-through */
470	case ARGTYPE_VOID:
471	case ARGTYPE_FLOAT:
472	case ARGTYPE_DOUBLE:
473	case ARGTYPE_STRUCT:
474	case ARGTYPE_SHORT:
475	case ARGTYPE_INT:
476	case ARGTYPE_LONG:
477	case ARGTYPE_USHORT:
478	case ARGTYPE_UINT:
479	case ARGTYPE_ULONG:
480		return toplevel_format_lens(lens, stream, value,
481					    arguments, INT_FMT_i);
482
483	case ARGTYPE_CHAR:
484		return format_char(stream, value, arguments);
485
486	case ARGTYPE_ARRAY:
487		return format_array(stream, value, arguments,
488				    value->type->u.array_info.length,
489				    options.strlen, 0, "\"", "\"", "");
490	}
491	abort();
492}
493
494struct lens string_lens = {
495	.format_cb = string_lens_format_cb,
496};
497