]> git.cworth.org Git - apitrace/blob - log.cpp
Use date stamp instead of version.
[apitrace] / log.cpp
1 /**************************************************************************
2  *
3  * Copyright 2007-2009 VMware, Inc.
4  * All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  *
24  **************************************************************************/
25
26
27 #include <stdarg.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31
32 #include <windows.h>
33
34 #include <zlib.h>
35
36 #include "log.hpp"
37
38
39 #ifdef WIN32
40 #ifndef PATH_MAX
41 #define PATH_MAX _MAX_PATH
42 #endif
43 #ifndef snprintf
44 #define snprintf _snprintf
45 #endif
46 #ifndef vsnprintf
47 #define vsnprintf _vsnprintf
48 #endif
49 #endif
50
51
52 namespace Log {
53
54
55 static gzFile g_gzFile = NULL;
56 static char g_szFileName[PATH_MAX];
57 static CRITICAL_SECTION CriticalSection;
58
59 static void _Close(void) {
60     if(g_gzFile != NULL) {
61         gzclose(g_gzFile);
62         g_gzFile = NULL;
63         DeleteCriticalSection(&CriticalSection);
64     }
65 }
66
67 static void _Open(const char *szName, const char *szExtension) {
68     _Close();
69     
70     static unsigned dwCounter = 0;
71
72     char szProcessPath[PATH_MAX];
73     char *lpProcessName;
74     char *lpProcessExt;
75
76     GetModuleFileNameA(NULL, szProcessPath, sizeof(szProcessPath)/sizeof(szProcessPath[0]));
77
78     lpProcessName = strrchr(szProcessPath, '\\');
79     lpProcessName = lpProcessName ? lpProcessName + 1 : szProcessPath;
80     lpProcessExt = strrchr(lpProcessName, '.');
81     if(lpProcessExt)
82         *lpProcessExt = '\0';
83
84     for(;;) {
85         FILE *file;
86         
87         if(dwCounter)
88             snprintf(g_szFileName, PATH_MAX, "%s.%s.%u.%s.gz", lpProcessName, szName, dwCounter, szExtension);
89         else
90             snprintf(g_szFileName, PATH_MAX, "%s.%s.%s.gz", lpProcessName, szName, szExtension);
91         
92         file = fopen(g_szFileName, "rb");
93         if(file == NULL)
94             break;
95         
96         fclose(file);
97         
98         ++dwCounter;
99     }
100
101     g_gzFile = gzopen(g_szFileName, "wb");
102     InitializeCriticalSection(&CriticalSection);
103 }
104
105 static inline void _ReOpen(void) {
106     /* XXX */
107 }
108
109 static inline void Write(const char *sBuffer, size_t dwBytesToWrite) {
110     if(g_gzFile == NULL)
111         return;
112     
113     gzwrite(g_gzFile, sBuffer, dwBytesToWrite);
114 }
115
116 static inline void Write(const char *szText) {
117     Write(szText, strlen(szText));
118 }
119
120 static inline void 
121 Escape(const char *s) {
122     /* FIXME */
123     Write(s);
124 }
125
126 static inline void 
127 Indent(unsigned level) {
128     for(unsigned i = 0; i < level; ++i)
129         Write("\t");
130 }
131
132 static inline void 
133 NewLine(void) {
134     Write("\r\n");
135 }
136
137 static inline void 
138 Tag(const char *name) {
139     Write("<");
140     Write(name);
141     Write("/>");
142 }
143
144 static inline void 
145 BeginTag(const char *name) {
146     Write("<");
147     Write(name);
148     Write(">");
149 }
150
151 static inline void 
152 BeginTag(const char *name, 
153          const char *attr1, const char *value1) {
154     Write("<");
155     Write(name);
156     Write(" ");
157     Write(attr1);
158     Write("=\"");
159     Escape(value1);
160     Write("\">");
161 }
162
163 static inline void 
164 BeginTag(const char *name, 
165          const char *attr1, const char *value1,
166          const char *attr2, const char *value2) {
167     Write("<");
168     Write(name);
169     Write(" ");
170     Write(attr1);
171     Write("=\"");
172     Escape(value1);
173     Write("\" ");
174     Write(attr2);
175     Write("=\"");
176     Escape(value2);
177     Write("\">");
178 }
179
180 static inline void 
181 BeginTag(const char *name, 
182               const char *attr1, const char *value1,
183               const char *attr2, const char *value2,
184               const char *attr3, const char *value3) {
185     Write("<");
186     Write(name);
187     Write(" ");
188     Write(attr1);
189     Write("=\"");
190     Escape(value1);
191     Write("\" ");
192     Write(attr2);
193     Write("=\"");
194     Escape(value2);
195     Write("\" ");
196     Write(attr3);
197     Write("=\"");
198     Escape(value3);
199     Write("\">");
200 }
201
202 static inline void
203 EndTag(const char *name) {
204     Write("</");
205     Write(name);
206     Write(">");
207 }
208
209 void Open(const char *name) {
210     _Open(name, "xml");
211     Write("<?xml version='1.0' encoding='UTF-8'?>");
212     NewLine();
213     Write("<?xml-stylesheet type='text/xsl' href='apitrace.xsl'?>");
214     NewLine();
215     BeginTag("trace");
216     NewLine();
217 }
218
219 void ReOpen(void) {
220     _ReOpen();
221 }
222
223 void Close(void) {
224     EndTag("trace");
225     NewLine();
226     _Close();
227 }
228
229 void Text(const char *text) {
230     Escape(text);
231 }
232
233 static void TextChar(char c) {
234     char szText[2];
235     szText[0] = c;
236     szText[1] = 0;
237     Text(szText);
238 }
239
240 void TextF(const char *format, ...) {
241     char szBuffer[4196];
242     va_list ap;
243     va_start(ap, format);
244     vsnprintf(szBuffer, sizeof(szBuffer), format, ap);
245     va_end(ap);
246     Text(szBuffer);
247 }
248
249 static LARGE_INTEGER frequency = {0};
250 static LARGE_INTEGER startcounter;
251
252 void BeginCall(const char *function) {
253     EnterCriticalSection(&CriticalSection); 
254     Indent(1);
255     BeginTag("call", "name", function);
256     NewLine();
257
258     if(!frequency.QuadPart)
259         QueryPerformanceFrequency(&frequency);
260     
261     QueryPerformanceCounter(&startcounter);
262 }
263
264 void EndCall(void) {
265     LARGE_INTEGER endcounter;
266     LONGLONG usecs;
267
268     QueryPerformanceCounter(&endcounter);
269     usecs = (endcounter.QuadPart - startcounter.QuadPart)*1000000/frequency.QuadPart;
270
271     Indent(2);
272     BeginTag("duration");
273     TextF("%llu", usecs);
274     EndTag("duration");
275     NewLine();
276
277     Indent(1);
278     EndTag("call");
279     NewLine();
280     gzflush(g_gzFile, Z_SYNC_FLUSH);
281     LeaveCriticalSection(&CriticalSection); 
282 }
283
284 void BeginArg(const char *type, const char *name) {
285     Indent(2);
286     BeginTag("arg", "type", type, "name", name);
287 }
288
289 void EndArg(void) {
290     EndTag("arg");
291     NewLine();
292 }
293
294 void BeginReturn(const char *type) {
295     Indent(2);
296     BeginTag("ret", "type", type);
297 }
298
299 void EndReturn(void) {
300     EndTag("ret");
301     NewLine();
302 }
303
304 void BeginElement(const char *type, const char *name) {
305     BeginTag("elem", "type", type, "name", name);
306 }
307
308 void BeginElement(const char *type) {
309     BeginTag("elem", "type", type);
310 }
311
312 void EndElement(void) {
313     EndTag("elem");
314 }
315
316 void BeginReference(const char *type, const void *addr) {
317     char saddr[256];
318     snprintf(saddr, sizeof(saddr), "%p", addr);
319     BeginTag("ref", "type", type, "addr", saddr);
320 }
321
322 void EndReference(void) {
323     EndTag("ref");
324 }
325
326 void DumpString(const char *str) {
327     const unsigned char *p = (const unsigned char *)str;
328     if (!str) {
329         Log::Text("L\"");
330         return;
331     }
332     Log::Text("\"");
333     unsigned char c;
334     while((c = *p++) != 0) {
335         if(c == '\"')
336             Text("\\\"");
337         else if(c == '\\')
338             Text("\\\\");
339         else if(c >= 0x20 && c <= 0x7e)
340             TextChar(c);
341         else if(c == '\t')
342             Text("&#09;");
343         else if(c == '\r')
344             Text("&#13;");
345         else if(c == '\n')
346             Text("&#10;");
347         else {
348             unsigned char octal0 = c & 0x7;
349             unsigned char octal1 = (c >> 3) & 0x7;
350             unsigned char octal2 = (c >> 3) & 0x7;
351             if(octal2)
352                 TextF("\\%u%u%u", octal2, octal1, octal0);
353             else if(octal1)
354                 TextF("\\%u%u", octal1, octal0);
355             else
356                 TextF("\\%u", octal0);
357         }
358     }
359     Log::Text("\"");
360 }
361
362 void DumpWString(const wchar_t *str) {
363     const wchar_t *p = str;
364     if (!str) {
365         Log::Text("L\"");
366         return;
367     }
368     Log::Text("L\"");
369     wchar_t c;
370     while((c = *p++) != 0) {
371         if(c == '\"')
372             Text("\\\"");
373         else if(c == '\\')
374             Text("\\\\");
375         else if(c >= 0x20 && c <= 0x7e)
376             TextChar((char)c);
377         else if(c == '\t')
378             Text("&#09;");
379         else if(c == '\r')
380             Text("&#13;");
381         else if(c == '\n')
382             Text("&#10;");
383         else {
384             unsigned octal0 = c & 0x7;
385             unsigned octal1 = (c >> 3) & 0x7;
386             unsigned octal2 = (c >> 3) & 0x7;
387             if(octal2)
388                 TextF("\\%u%u%u", octal2, octal1, octal0);
389             else if(octal1)
390                 TextF("\\%u%u", octal1, octal0);
391             else
392                 TextF("\\%u", octal0);
393         }
394     }
395     Log::Text("\"");
396 }
397
398 } /* namespace Log */