output.c revision 21c63a1469bc049d93444b8a15afd685ee251392
1#if HAVE_CONFIG_H
2#include "config.h"
3#endif
4
5#include <stdio.h>
6#include <stdarg.h>
7#include <string.h>
8#include <time.h>
9#include <sys/time.h>
10#include <unistd.h>
11
12#include "ltrace.h"
13#include "options.h"
14#include "output.h"
15
16#if HAVE_LIBIBERTY
17#include "demangle.h"
18#endif
19
20static pid_t current_pid = 0;
21static int current_column = 0;
22static int indent_count = 0;
23
24static void output_increase_indent(void)
25{
26	indent_count++;
27}
28
29static void output_decrease_indent(void)
30{
31	indent_count--;
32}
33
34static void output_indent(void)
35{
36	int i, j;
37	for (i = 0; i < indent_count; i++) {
38		for (j = 0; j < opt_n; j++) fprintf(output, " ");
39		current_column += opt_n;
40	}
41}
42
43static void begin_of_line(enum tof type, struct process * proc)
44{
45	current_column = 0;
46	if (!proc) {
47		return;
48	}
49	if ((output!=stderr) && (opt_p || opt_f)) {
50		current_column += fprintf(output, "%u ", proc->pid);
51	} else if (list_of_processes->next) {
52		current_column += fprintf(output, "[pid %u] ", proc->pid);
53	}
54	if (opt_r) {
55		struct timeval tv;
56		struct timezone tz;
57		static struct timeval old_tv={0,0};
58		struct timeval diff;
59
60		gettimeofday(&tv, &tz);
61
62		if (old_tv.tv_sec==0 && old_tv.tv_usec==0) {
63			old_tv.tv_sec=tv.tv_sec;
64			old_tv.tv_usec=tv.tv_usec;
65		}
66		diff.tv_sec = tv.tv_sec - old_tv.tv_sec;
67		if (tv.tv_usec >= old_tv.tv_usec) {
68			diff.tv_usec = tv.tv_usec - old_tv.tv_usec;
69		} else {
70			diff.tv_sec++;
71			diff.tv_usec = 1000000 + tv.tv_usec - old_tv.tv_usec;
72		}
73		old_tv.tv_sec = tv.tv_sec;
74		old_tv.tv_usec = tv.tv_usec;
75		current_column += fprintf(output, "%3lu.%06d ",
76			diff.tv_sec, (int)diff.tv_usec);
77	}
78	if (opt_t) {
79		struct timeval tv;
80		struct timezone tz;
81
82		gettimeofday(&tv, &tz);
83		if (opt_t>2) {
84			current_column += fprintf(output, "%lu.%06d ",
85				tv.tv_sec, (int)tv.tv_usec);
86		} else if (opt_t>1) {
87			struct tm * tmp = localtime(&tv.tv_sec);
88			current_column += fprintf(output, "%02d:%02d:%02d.%06d ",
89				tmp->tm_hour, tmp->tm_min, tmp->tm_sec, (int)tv.tv_usec);
90		} else {
91			struct tm * tmp = localtime(&tv.tv_sec);
92			current_column += fprintf(output, "%02d:%02d:%02d ",
93				tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
94		}
95	}
96	if (opt_i) {
97		if (type==LT_TOF_FUNCTION) {
98			current_column += fprintf(output, "[%08x] ",
99				(unsigned)proc->return_addr);
100		} else {
101			current_column += fprintf(output, "[%08x] ",
102				(unsigned)proc->instruction_pointer);
103		}
104	}
105	if (opt_n > 0) {
106		output_indent();
107	}
108}
109
110static struct function * name2func(char * name)
111{
112	struct function * tmp;
113	const char * str1, * str2;
114
115	tmp = list_of_functions;
116	while(tmp) {
117#if HAVE_LIBIBERTY
118		str1 = opt_C ? my_demangle(tmp->name) : tmp->name;
119		str2 = opt_C ? my_demangle(name) : name;
120#else
121		str1 = tmp->name;
122		str2 = name;
123#endif
124		if (!strcmp(str1, str2)) {
125
126			return tmp;
127		}
128		tmp = tmp->next;
129	}
130	return NULL;
131}
132
133void output_line(struct process * proc, char *fmt, ...)
134{
135	va_list args;
136
137	if (current_pid) {
138		fprintf(output, " <unfinished ...>\n");
139	}
140	current_pid=0;
141	if (!fmt) {
142		return;
143	}
144	begin_of_line(LT_TOF_NONE, proc);
145
146	va_start(args, fmt);
147	vfprintf(output, fmt, args);
148	fprintf(output, "\n");
149	va_end(args);
150	current_column=0;
151}
152
153static void tabto(int col)
154{
155	if (current_column < col) {
156		fprintf(output, "%*s", col-current_column, "");
157	}
158}
159
160void output_left(enum tof type, struct process * proc, char * function_name)
161{
162	struct function * func;
163
164	if (current_pid) {
165		fprintf(output, " <unfinished ...>\n");
166		current_pid=0;
167		current_column=0;
168	}
169	current_pid=proc->pid;
170	proc->type_being_displayed = type;
171	begin_of_line(type, proc);
172	output_increase_indent();
173#if HAVE_LIBIBERTY
174	current_column += fprintf(output, "%s(", opt_C ? my_demangle(function_name): function_name);
175#else
176	current_column += fprintf(output, "%s(", function_name);
177#endif
178
179	func = name2func(function_name);
180	if (!func) {
181		int i;
182		for(i=0; i<4; i++) {
183			current_column += display_arg(type, proc, i, ARGTYPE_UNKNOWN);
184			current_column += fprintf(output, ", ");
185		}
186		current_column += display_arg(type, proc, 4, ARGTYPE_UNKNOWN);
187		return;
188	} else {
189		int i;
190		for(i=0; i< func->num_params - func->params_right - 1; i++) {
191			current_column += display_arg(type, proc, i, func->arg_types[i]);
192			current_column += fprintf(output, ", ");
193		}
194		if (func->num_params>func->params_right) {
195			current_column += display_arg(type, proc, i, func->arg_types[i]);
196			if (func->params_right) {
197				current_column += fprintf(output, ", ");
198			}
199		}
200	}
201}
202
203void output_right(enum tof type, struct process * proc, char * function_name)
204{
205	struct function * func = name2func(function_name);
206
207	output_decrease_indent();
208
209	if (current_pid && current_pid!=proc->pid) {
210		fprintf(output, " <unfinished ...>\n");
211	}
212	if (current_pid != proc->pid) {
213		begin_of_line(type, proc);
214#if HAVE_LIBIBERTY
215		current_column += fprintf(output, "<... %s resumed> ", opt_C ? my_demangle(function_name) : function_name);
216#else
217		current_column += fprintf(output, "<... %s resumed> ", function_name);
218#endif
219	}
220
221	if (!func) {
222		current_column += fprintf(output, ") ");
223		tabto(opt_a);
224		fprintf(output, "= ");
225		display_arg(type, proc, -1, ARGTYPE_UNKNOWN);
226		fprintf(output, "\n");
227	} else {
228		int i;
229		for(i=func->num_params-func->params_right; i<func->num_params-1; i++) {
230			current_column += display_arg(type, proc, i, func->arg_types[i]);
231			current_column += fprintf(output, ", ");
232		}
233		if (func->params_right) {
234			current_column += display_arg(type, proc, i, func->arg_types[i]);
235		}
236		current_column += fprintf(output, ") ");
237			tabto(opt_a);
238			fprintf(output, "= ");
239		if (func->return_type == ARGTYPE_VOID) {
240			fprintf(output, "<void>");
241		} else {
242			display_arg(type, proc, -1, func->return_type);
243		}
244		fprintf(output, "\n");
245	}
246	current_pid=0;
247	current_column=0;
248}
249