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