···11#include "simple.h"
22#include <stdarg.h>
33#include <stddef.h>
44+#include <string.h>
4556int __simple_vsprintf(char* buf, const char* format, va_list vl);
66-extern char* memchr(char* buf, int c, __SIZE_TYPE__ n);
7788// We cannot call standard write(), because it would loop back to xtrace
99extern int __write_for_xtrace(int fd, const void* mem, __SIZE_TYPE__ count);
+35-3
src/xtrace/xtracelib.c
···151151 // Leaves gray color on!
152152}
153153154154+155155+_Thread_local struct {
156156+ // We're inside this many calls. In other words, we have printed this many
157157+ // call entries without matching exits.
158158+ int current_level;
159159+ // What that value was the last time. if we've just handled an entry or an
160160+ // exit, this will be greater/less than current_level.
161161+ int previous_level;
162162+ // Call numbers, indexed by current level.
163163+ int nrs[64];
164164+} nested_call;
165165+154166void handle_generic_entry(const struct calldef* defs, const char* type, int nr, void* args[])
155167{
156168 if (xtrace_ignore)
157169 return;
158170159159- print_call(defs, type, nr, 0, 0);
171171+ if (nested_call.previous_level < nested_call.current_level && !xtrace_split_entry_and_exit)
172172+ {
173173+ // We are after an earlier entry without an exit.
174174+ __simple_printf("\n");
175175+ }
176176+177177+ int indent = 4 * nested_call.current_level;
178178+ nested_call.nrs[nested_call.current_level] = nr;
179179+180180+ print_call(defs, type, nr, indent, 0);
160181161182 if (defs[nr].name != NULL)
162183 {
···172193173194 if (xtrace_split_entry_and_exit)
174195 __simple_printf("\n");
196196+197197+ nested_call.previous_level = nested_call.current_level++;
175198}
176199177200178178-void handle_generic_exit(const struct calldef* defs, const char* type, int nr, uintptr_t retval, int force_split)
201201+void handle_generic_exit(const struct calldef* defs, const char* type, uintptr_t retval, int force_split)
179202{
180203 if (xtrace_ignore)
181204 return;
182205206206+ if (nested_call.previous_level > nested_call.current_level)
207207+ {
208208+ // We are after an exit, so our call has been split up.
209209+ force_split = 1;
210210+ }
211211+ nested_call.previous_level = nested_call.current_level--;
212212+ int nr = nested_call.nrs[nested_call.current_level];
213213+183214 if (xtrace_split_entry_and_exit || force_split)
184215 {
185185- print_call(defs, type, nr, 4, 1);
216216+ int indent = 4 * nested_call.current_level;
217217+ print_call(defs, type, nr, indent, 1);
186218 __simple_printf("()");
187219 }
188220
+1-1
src/xtrace/xtracelib.h
···1414#endif
15151616void handle_generic_entry(const struct calldef* defs, const char* type, int nr, void* args[]);
1717-void handle_generic_exit(const struct calldef* defs, const char* type, int nr, uintptr_t retval, int force_split);
1717+void handle_generic_exit(const struct calldef* defs, const char* type, uintptr_t retval, int force_split);
18181919extern int xtrace_no_color;
2020void xtrace_set_gray_color(void);