00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00041 #include "pipe/p_config.h"
00042
00043 #if defined(PIPE_OS_LINUX)
00044 #include <stdlib.h>
00045 #endif
00046
00047 #include "pipe/p_compiler.h"
00048 #include "pipe/p_thread.h"
00049 #include "pipe/p_debug.h"
00050 #include "util/u_memory.h"
00051 #include "util/u_string.h"
00052 #include "util/u_stream.h"
00053
00054 #include "tr_dump.h"
00055
00056
00057 static struct util_stream *stream = NULL;
00058 static unsigned refcount = 0;
00059 static pipe_mutex call_mutex;
00060 static long unsigned call_no = 0;
00061
00062
00063 static INLINE void
00064 trace_dump_write(const char *buf, size_t size)
00065 {
00066 if(stream)
00067 util_stream_write(stream, buf, size);
00068 }
00069
00070
00071 static INLINE void
00072 trace_dump_writes(const char *s)
00073 {
00074 trace_dump_write(s, strlen(s));
00075 }
00076
00077
00078 static INLINE void
00079 trace_dump_writef(const char *format, ...)
00080 {
00081 static char buf[1024];
00082 unsigned len;
00083 va_list ap;
00084 va_start(ap, format);
00085 len = util_vsnprintf(buf, sizeof(buf), format, ap);
00086 va_end(ap);
00087 trace_dump_write(buf, len);
00088 }
00089
00090
00091 static INLINE void
00092 trace_dump_escape(const char *str)
00093 {
00094 const unsigned char *p = (const unsigned char *)str;
00095 unsigned char c;
00096 while((c = *p++) != 0) {
00097 if(c == '<')
00098 trace_dump_writes("<");
00099 else if(c == '>')
00100 trace_dump_writes(">");
00101 else if(c == '&')
00102 trace_dump_writes("&");
00103 else if(c == '\'')
00104 trace_dump_writes("'");
00105 else if(c == '\"')
00106 trace_dump_writes(""");
00107 else if(c >= 0x20 && c <= 0x7e)
00108 trace_dump_writef("%c", c);
00109 else
00110 trace_dump_writef("&#%u;", c);
00111 }
00112 }
00113
00114
00115 static INLINE void
00116 trace_dump_indent(unsigned level)
00117 {
00118 unsigned i;
00119 for(i = 0; i < level; ++i)
00120 trace_dump_writes("\t");
00121 }
00122
00123
00124 static INLINE void
00125 trace_dump_newline(void)
00126 {
00127 trace_dump_writes("\n");
00128 }
00129
00130
00131 static INLINE void
00132 trace_dump_tag(const char *name)
00133 {
00134 trace_dump_writes("<");
00135 trace_dump_writes(name);
00136 trace_dump_writes("/>");
00137 }
00138
00139
00140 static INLINE void
00141 trace_dump_tag_begin(const char *name)
00142 {
00143 trace_dump_writes("<");
00144 trace_dump_writes(name);
00145 trace_dump_writes(">");
00146 }
00147
00148 static INLINE void
00149 trace_dump_tag_begin1(const char *name,
00150 const char *attr1, const char *value1)
00151 {
00152 trace_dump_writes("<");
00153 trace_dump_writes(name);
00154 trace_dump_writes(" ");
00155 trace_dump_writes(attr1);
00156 trace_dump_writes("='");
00157 trace_dump_escape(value1);
00158 trace_dump_writes("'>");
00159 }
00160
00161
00162 static INLINE void
00163 trace_dump_tag_begin2(const char *name,
00164 const char *attr1, const char *value1,
00165 const char *attr2, const char *value2)
00166 {
00167 trace_dump_writes("<");
00168 trace_dump_writes(name);
00169 trace_dump_writes(" ");
00170 trace_dump_writes(attr1);
00171 trace_dump_writes("=\'");
00172 trace_dump_escape(value1);
00173 trace_dump_writes("\' ");
00174 trace_dump_writes(attr2);
00175 trace_dump_writes("=\'");
00176 trace_dump_escape(value2);
00177 trace_dump_writes("\'>");
00178 }
00179
00180
00181 static INLINE void
00182 trace_dump_tag_begin3(const char *name,
00183 const char *attr1, const char *value1,
00184 const char *attr2, const char *value2,
00185 const char *attr3, const char *value3)
00186 {
00187 trace_dump_writes("<");
00188 trace_dump_writes(name);
00189 trace_dump_writes(" ");
00190 trace_dump_writes(attr1);
00191 trace_dump_writes("=\'");
00192 trace_dump_escape(value1);
00193 trace_dump_writes("\' ");
00194 trace_dump_writes(attr2);
00195 trace_dump_writes("=\'");
00196 trace_dump_escape(value2);
00197 trace_dump_writes("\' ");
00198 trace_dump_writes(attr3);
00199 trace_dump_writes("=\'");
00200 trace_dump_escape(value3);
00201 trace_dump_writes("\'>");
00202 }
00203
00204
00205 static INLINE void
00206 trace_dump_tag_end(const char *name)
00207 {
00208 trace_dump_writes("</");
00209 trace_dump_writes(name);
00210 trace_dump_writes(">");
00211 }
00212
00213 static void
00214 trace_dump_trace_close(void)
00215 {
00216 if(stream) {
00217 trace_dump_writes("</trace>\n");
00218 util_stream_close(stream);
00219 stream = NULL;
00220 refcount = 0;
00221 call_no = 0;
00222 pipe_mutex_destroy(call_mutex);
00223 }
00224 }
00225
00226 boolean trace_dump_trace_begin()
00227 {
00228 const char *filename;
00229
00230 filename = debug_get_option("GALLIUM_TRACE", NULL);
00231 if(!filename)
00232 return FALSE;
00233
00234 if(!stream) {
00235
00236 stream = util_stream_create(filename, 0);
00237 if(!stream)
00238 return FALSE;
00239
00240 pipe_mutex_init(call_mutex);
00241
00242 trace_dump_writes("<?xml version='1.0' encoding='UTF-8'?>\n");
00243 trace_dump_writes("<?xml-stylesheet type='text/xsl' href='trace.xsl'?>\n");
00244 trace_dump_writes("<trace version='0.1'>\n");
00245
00246 #if defined(PIPE_OS_LINUX)
00247
00248
00249 atexit(trace_dump_trace_close);
00250 #endif
00251 }
00252
00253 ++refcount;
00254
00255 return TRUE;
00256 }
00257
00258 boolean trace_dump_enabled(void)
00259 {
00260 return stream ? TRUE : FALSE;
00261 }
00262
00263 void trace_dump_trace_end(void)
00264 {
00265 if(stream)
00266 if(!--refcount)
00267 trace_dump_trace_close();
00268 }
00269
00270 void trace_dump_call_begin(const char *klass, const char *method)
00271 {
00272 pipe_mutex_lock(call_mutex);
00273 ++call_no;
00274 trace_dump_indent(1);
00275 trace_dump_writes("<call no=\'");
00276 trace_dump_writef("%lu", call_no);
00277 trace_dump_writes("\' class =\'");
00278 trace_dump_escape(klass);
00279 trace_dump_writes("\' method=\'");
00280 trace_dump_escape(method);
00281 trace_dump_writes("\'>");
00282 trace_dump_newline();
00283 }
00284
00285 void trace_dump_call_end(void)
00286 {
00287 trace_dump_indent(1);
00288 trace_dump_tag_end("call");
00289 trace_dump_newline();
00290 util_stream_flush(stream);
00291 pipe_mutex_unlock(call_mutex);
00292 }
00293
00294 void trace_dump_arg_begin(const char *name)
00295 {
00296 trace_dump_indent(2);
00297 trace_dump_tag_begin1("arg", "name", name);
00298 }
00299
00300 void trace_dump_arg_end(void)
00301 {
00302 trace_dump_tag_end("arg");
00303 trace_dump_newline();
00304 }
00305
00306 void trace_dump_ret_begin(void)
00307 {
00308 trace_dump_indent(2);
00309 trace_dump_tag_begin("ret");
00310 }
00311
00312 void trace_dump_ret_end(void)
00313 {
00314 trace_dump_tag_end("ret");
00315 trace_dump_newline();
00316 }
00317
00318 void trace_dump_bool(int value)
00319 {
00320 trace_dump_writef("<bool>%c</bool>", value ? '1' : '0');
00321 }
00322
00323 void trace_dump_int(long long int value)
00324 {
00325 trace_dump_writef("<int>%lli</int>", value);
00326 }
00327
00328 void trace_dump_uint(long long unsigned value)
00329 {
00330 trace_dump_writef("<uint>%llu</uint>", value);
00331 }
00332
00333 void trace_dump_float(double value)
00334 {
00335 trace_dump_writef("<float>%g</float>", value);
00336 }
00337
00338 void trace_dump_bytes(const void *data,
00339 long unsigned size)
00340 {
00341 static const char hex_table[16] = "0123456789ABCDEF";
00342 const uint8_t *p = data;
00343 long unsigned i;
00344 trace_dump_writes("<bytes>");
00345 for(i = 0; i < size; ++i) {
00346 uint8_t byte = *p++;
00347 char hex[2];
00348 hex[0] = hex_table[byte >> 4];
00349 hex[1] = hex_table[byte & 0xf];
00350 trace_dump_write(hex, 2);
00351 }
00352 trace_dump_writes("</bytes>");
00353 }
00354
00355 void trace_dump_string(const char *str)
00356 {
00357 trace_dump_writes("<string>");
00358 trace_dump_escape(str);
00359 trace_dump_writes("</string>");
00360 }
00361
00362 void trace_dump_enum(const char *value)
00363 {
00364 trace_dump_writes("<enum>");
00365 trace_dump_escape(value);
00366 trace_dump_writes("</enum>");
00367 }
00368
00369 void trace_dump_array_begin(void)
00370 {
00371 trace_dump_writes("<array>");
00372 }
00373
00374 void trace_dump_array_end(void)
00375 {
00376 trace_dump_writes("</array>");
00377 }
00378
00379 void trace_dump_elem_begin(void)
00380 {
00381 trace_dump_writes("<elem>");
00382 }
00383
00384 void trace_dump_elem_end(void)
00385 {
00386 trace_dump_writes("</elem>");
00387 }
00388
00389 void trace_dump_struct_begin(const char *name)
00390 {
00391 trace_dump_writef("<struct name='%s'>", name);
00392 }
00393
00394 void trace_dump_struct_end(void)
00395 {
00396 trace_dump_writes("</struct>");
00397 }
00398
00399 void trace_dump_member_begin(const char *name)
00400 {
00401 trace_dump_writef("<member name='%s'>", name);
00402 }
00403
00404 void trace_dump_member_end(void)
00405 {
00406 trace_dump_writes("</member>");
00407 }
00408
00409 void trace_dump_null(void)
00410 {
00411 trace_dump_writes("<null/>");
00412 }
00413
00414 void trace_dump_ptr(const void *value)
00415 {
00416 if(value)
00417 trace_dump_writef("<ptr>0x%08lx</ptr>", (unsigned long)(uintptr_t)value);
00418 else
00419 trace_dump_null();
00420 }