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