output.c revision e3eb9aa37086f16c0c8c2778dcd8020a39a92564
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
90	tmp = list_of_functions;
91	while(tmp) {
92		if (!strcmp(tmp->name, name)) {
93			return tmp;
94		}
95		tmp = tmp->next;
96	}
97	return NULL;
98}
99
100void output_line(struct process * proc, char *fmt, ...)
101{
102	va_list args;
103
104	if (current_pid) {
105		fprintf(output, " <unfinished ...>\n");
106	}
107	current_pid=0;
108	if (!fmt) {
109		return;
110	}
111	begin_of_line(LT_TOF_NONE, proc);
112
113        va_start(args, fmt);
114        vfprintf(output, fmt, args);
115        fprintf(output, "\n");
116        va_end(args);
117	current_column=0;
118}
119
120static void tabto(int col)
121{
122	if (current_column < col) {
123		fprintf(output, "%*s", col-current_column, "");
124	}
125}
126
127void output_left(enum tof type, struct process * proc, char * function_name)
128{
129	struct function * func;
130
131	if (current_pid) {
132#if 0			/* FIXME: should I do this? */
133		if (current_pid == proc->pid
134			&& proc->type_being_displayed == LT_TOF_FUNCTION
135			&& proc->type_being_displayed == type) {
136				tabto(opt_a);
137				fprintf(output, "= ???\n");
138		} else
139#endif
140			fprintf(output, " <unfinished ...>\n");
141		current_pid=0;
142		current_column=0;
143	}
144	current_pid=proc->pid;
145	proc->type_being_displayed = type;
146	begin_of_line(type, proc);
147#if HAVE_LIBIBERTY
148	current_column += fprintf(output, "%s(", my_demangle(function_name));
149#else
150	current_column += fprintf(output, "%s(", function_name);
151#endif
152
153	func = name2func(function_name);
154	if (!func) {
155		int i;
156		for(i=0; i<4; i++) {
157			current_column += display_arg(type, proc, i, ARGTYPE_UNKNOWN);
158			current_column += fprintf(output, ", ");
159		}
160		current_column += display_arg(type, proc, 4, ARGTYPE_UNKNOWN);
161		return;
162	} else {
163		int i;
164		for(i=0; i< func->num_params - func->params_right - 1; i++) {
165			current_column += display_arg(type, proc, i, func->arg_types[i]);
166			current_column += fprintf(output, ", ");
167		}
168		if (func->num_params>func->params_right) {
169			current_column += display_arg(type, proc, i, func->arg_types[i]);
170			if (func->params_right) {
171				current_column += fprintf(output, ", ");
172			}
173		}
174		if (!func->params_right && func->return_type == ARGTYPE_VOID) {
175			current_column += fprintf(output, ") ");
176			tabto(opt_a);
177			fprintf(output, "= <void>\n");
178			current_pid = 0;
179			current_column = 0;
180		}
181	}
182}
183
184void output_right(enum tof type, struct process * proc, char * function_name)
185{
186	struct function * func = name2func(function_name);
187
188	if (func && func->params_right==0 && func->return_type == ARGTYPE_VOID) {
189		return;
190	}
191
192	if (current_pid && current_pid!=proc->pid) {
193		fprintf(output, " <unfinished ...>\n");
194		begin_of_line(type, proc);
195		current_column += fprintf(output, "<... %s resumed> ", function_name);
196	} else if (!current_pid) {
197		begin_of_line(type, proc);
198		current_column += fprintf(output, "<... %s resumed> ", function_name);
199	}
200
201	if (!func) {
202		current_column += fprintf(output, ") ");
203		tabto(opt_a);
204		fprintf(output, "= ");
205		display_arg(type, proc, -1, ARGTYPE_UNKNOWN);
206		fprintf(output, "\n");
207	} else {
208		int i;
209		for(i=func->num_params-func->params_right; i<func->num_params-1; i++) {
210			current_column += display_arg(type, proc, i, func->arg_types[i]);
211			current_column += fprintf(output, ", ");
212		}
213		if (func->params_right) {
214			current_column += display_arg(type, proc, i, func->arg_types[i]);
215		}
216		current_column += fprintf(output, ") ");
217			tabto(opt_a);
218			fprintf(output, "= ");
219		if (func->return_type == ARGTYPE_VOID) {
220			fprintf(output, "<void>");
221		} else {
222			display_arg(type, proc, -1, func->return_type);
223		}
224		fprintf(output, "\n");
225	}
226	current_pid=0;
227	current_column=0;
228}
229