]> git.cworth.org Git - apitrace/blob - log.cpp
Make autogenerated dump functions static.
[apitrace] / log.cpp
1 /****************************************************************************
2  *
3  * Copyright 2008-2009 VMware, Inc.
4  *
5  * This program is free software: you can redistribute it and/or modify it
6  * under the terms of the GNU Lesser General Public License as published
7  * by the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  *
18  ****************************************************************************/
19
20
21 #include <stdarg.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25
26 #include <windows.h>
27
28 #include <zlib.h>
29
30 #include "log.hpp"
31
32
33 #ifdef WIN32
34 #ifndef PATH_MAX
35 #define PATH_MAX _MAX_PATH
36 #endif
37 #ifndef snprintf
38 #define snprintf _snprintf
39 #endif
40 #ifndef vsnprintf
41 #define vsnprintf _vsnprintf
42 #endif
43 #endif
44
45
46 namespace Log {
47
48
49 static gzFile g_gzFile = NULL;
50 static char g_szFileName[PATH_MAX];
51 static CRITICAL_SECTION CriticalSection;
52
53 static void _Close(void) {
54     if(g_gzFile != NULL) {
55         gzclose(g_gzFile);
56         g_gzFile = NULL;
57         DeleteCriticalSection(&CriticalSection);
58     }
59 }
60
61 static void _Open(const char *szName, const char *szExtension) {
62     _Close();
63     
64     static unsigned dwCounter = 0;
65
66     char szProcessPath[PATH_MAX];
67     char *lpProcessName;
68     char *lpProcessExt;
69
70     GetModuleFileNameA(NULL, szProcessPath, sizeof(szProcessPath)/sizeof(szProcessPath[0]));
71
72     lpProcessName = strrchr(szProcessPath, '\\');
73     lpProcessName = lpProcessName ? lpProcessName + 1 : szProcessPath;
74     lpProcessExt = strrchr(lpProcessName, '.');
75     if(lpProcessExt)
76         *lpProcessExt = '\0';
77
78     for(;;) {
79         FILE *file;
80         
81         if(dwCounter)
82             snprintf(g_szFileName, PATH_MAX, "%s.%s.%u.%s.gz", lpProcessName, szName, dwCounter, szExtension);
83         else
84             snprintf(g_szFileName, PATH_MAX, "%s.%s.%s.gz", lpProcessName, szName, szExtension);
85         
86         file = fopen(g_szFileName, "rb");
87         if(file == NULL)
88             break;
89         
90         fclose(file);
91         
92         ++dwCounter;
93     }
94
95     g_gzFile = gzopen(g_szFileName, "wb");
96     InitializeCriticalSection(&CriticalSection);
97 }
98
99 static inline void _ReOpen(void) {
100     /* XXX */
101 }
102
103 static inline void Write(const char *sBuffer, size_t dwBytesToWrite) {
104     if(g_gzFile == NULL)
105         return;
106     
107     gzwrite(g_gzFile, sBuffer, dwBytesToWrite);
108 }
109
110 static inline void Write(const char *szText) {
111     Write(szText, strlen(szText));
112 }
113
114 static inline void 
115 Escape(const char *s) {
116     /* FIXME */
117     Write(s);
118 }
119
120 static inline void 
121 Indent(unsigned level) {
122     for(unsigned i = 0; i < level; ++i)
123         Write("\t");
124 }
125
126 static inline void 
127 NewLine(void) {
128     Write("\r\n");
129 }
130
131 static inline void 
132 Tag(const char *name) {
133     Write("<");
134     Write(name);
135     Write("/>");
136 }
137
138 static inline void 
139 BeginTag(const char *name) {
140     Write("<");
141     Write(name);
142     Write(">");
143 }
144
145 static inline void 
146 BeginTag(const char *name, 
147          const char *attr1, const char *value1) {
148     Write("<");
149     Write(name);
150     Write(" ");
151     Write(attr1);
152     Write("=\"");
153     Escape(value1);
154     Write("\">");
155 }
156
157 static inline void 
158 BeginTag(const char *name, 
159          const char *attr1, const char *value1,
160          const char *attr2, const char *value2) {
161     Write("<");
162     Write(name);
163     Write(" ");
164     Write(attr1);
165     Write("=\"");
166     Escape(value1);
167     Write("\" ");
168     Write(attr2);
169     Write("=\"");
170     Escape(value2);
171     Write("\">");
172 }
173
174 static inline void 
175 BeginTag(const char *name, 
176               const char *attr1, const char *value1,
177               const char *attr2, const char *value2,
178               const char *attr3, const char *value3) {
179     Write("<");
180     Write(name);
181     Write(" ");
182     Write(attr1);
183     Write("=\"");
184     Escape(value1);
185     Write("\" ");
186     Write(attr2);
187     Write("=\"");
188     Escape(value2);
189     Write("\" ");
190     Write(attr3);
191     Write("=\"");
192     Escape(value3);
193     Write("\">");
194 }
195
196 static inline void
197 EndTag(const char *name) {
198     Write("</");
199     Write(name);
200     Write(">");
201 }
202
203 void Open(const char *name) {
204     _Open(name, "xml");
205     Write("<?xml version='1.0' encoding='UTF-8'?>");
206     NewLine();
207     Write("<?xml-stylesheet type='text/xsl' href='apitrace.xsl'?>");
208     NewLine();
209     BeginTag("trace");
210     NewLine();
211 }
212
213 void ReOpen(void) {
214     _ReOpen();
215 }
216
217 void Close(void) {
218     EndTag("trace");
219     NewLine();
220     _Close();
221 }
222
223 void Text(const char *text) {
224     Escape(text);
225 }
226
227 static void TextChar(char c) {
228     char szText[2];
229     szText[0] = c;
230     szText[1] = 0;
231     Text(szText);
232 }
233
234 void TextF(const char *format, ...) {
235     char szBuffer[4196];
236     va_list ap;
237     va_start(ap, format);
238     vsnprintf(szBuffer, sizeof(szBuffer), format, ap);
239     va_end(ap);
240     Text(szBuffer);
241 }
242
243 static LARGE_INTEGER frequency = {0};
244 static LARGE_INTEGER startcounter;
245
246 void BeginCall(const char *function) {
247     EnterCriticalSection(&CriticalSection); 
248     Indent(1);
249     BeginTag("call", "name", function);
250     NewLine();
251
252     if(!frequency.QuadPart)
253         QueryPerformanceFrequency(&frequency);
254     
255     QueryPerformanceCounter(&startcounter);
256 }
257
258 void EndCall(void) {
259     LARGE_INTEGER endcounter;
260     LONGLONG usecs;
261
262     QueryPerformanceCounter(&endcounter);
263     usecs = (endcounter.QuadPart - startcounter.QuadPart)*1000000/frequency.QuadPart;
264
265     Indent(2);
266     BeginTag("duration");
267     TextF("%llu", usecs);
268     EndTag("duration");
269     NewLine();
270
271     Indent(1);
272     EndTag("call");
273     NewLine();
274     gzflush(g_gzFile, Z_SYNC_FLUSH);
275     LeaveCriticalSection(&CriticalSection); 
276 }
277
278 void BeginArg(const char *type, const char *name) {
279     Indent(2);
280     BeginTag("arg", "type", type, "name", name);
281 }
282
283 void EndArg(void) {
284     EndTag("arg");
285     NewLine();
286 }
287
288 void BeginReturn(const char *type) {
289     Indent(2);
290     BeginTag("ret", "type", type);
291 }
292
293 void EndReturn(void) {
294     EndTag("ret");
295     NewLine();
296 }
297
298 void BeginElement(const char *type, const char *name) {
299     BeginTag("elem", "type", type, "name", name);
300 }
301
302 void BeginElement(const char *type) {
303     BeginTag("elem", "type", type);
304 }
305
306 void EndElement(void) {
307     EndTag("elem");
308 }
309
310 void BeginReference(const char *type, const void *addr) {
311     char saddr[256];
312     snprintf(saddr, sizeof(saddr), "%p", addr);
313     BeginTag("ref", "type", type, "addr", saddr);
314 }
315
316 void EndReference(void) {
317     EndTag("ref");
318 }
319
320 void DumpString(const char *str) {
321     const unsigned char *p = (const unsigned char *)str;
322     Log::Text("\"");
323     unsigned char c;
324     while((c = *p++) != 0) {
325         if(c == '\"')
326             Text("\\\"");
327         else if(c == '\\')
328             Text("\\\\");
329         else if(c >= 0x20 && c <= 0x7e)
330             TextChar(c);
331         else if(c == '\t')
332             Text("\\t");
333         else if(c == '\r')
334             Text("\\r");
335         else if(c == '\n')
336             Text("&#10;");
337         else {
338             unsigned char octal0 = c & 0x7;
339             unsigned char octal1 = (c >> 3) & 0x7;
340             unsigned char octal2 = (c >> 3) & 0x7;
341             if(octal2)
342                 TextF("\\%u%u%u", octal2, octal1, octal0);
343             else if(octal1)
344                 TextF("\\%u%u", octal1, octal0);
345             else
346                 TextF("\\%u", octal0);
347         }
348     }
349     Log::Text("\"");
350 }
351
352 void DumpWString(const wchar_t *str) {
353     const wchar_t *p = str;
354     Log::Text("L\"");
355     wchar_t c;
356     while((c = *p++) != 0) {
357         if(c == '\"')
358             Text("\\\"");
359         else if(c == '\\')
360             Text("\\\\");
361         else if(c >= 0x20 && c <= 0x7e)
362             TextChar((char)c);
363         else if(c == '\t')
364             Text("\\t");
365         else if(c == '\r')
366             Text("\\r");
367         else if(c == '\n')
368             Text("&#10;");
369         else {
370             unsigned octal0 = c & 0x7;
371             unsigned octal1 = (c >> 3) & 0x7;
372             unsigned octal2 = (c >> 3) & 0x7;
373             if(octal2)
374                 TextF("\\%u%u%u", octal2, octal1, octal0);
375             else if(octal1)
376                 TextF("\\%u%u", octal1, octal0);
377             else
378                 TextF("\\%u", octal0);
379         }
380     }
381     Log::Text("\"");
382 }
383
384 } /* namespace Log */