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