]> git.cworth.org Git - apitrace/blob - log.cpp
2493ec1fb5d3054808b9753bfacc6b8d8d39d190
[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 <zlib.h>
33
34 #include "os.hpp"
35 #include "log.hpp"
36
37
38 namespace Log {
39
40
41 static gzFile g_gzFile = NULL;
42 static void _Close(void) {
43     if(g_gzFile != NULL) {
44         gzclose(g_gzFile);
45         g_gzFile = NULL;
46     }
47 }
48
49 static void _Open(const char *szName, const char *szExtension) {
50     _Close();
51     
52     static unsigned dwCounter = 0;
53
54     char szProcessName[PATH_MAX];
55     char szFileName[PATH_MAX];
56
57     OS::GetProcessName(szProcessName, PATH_MAX);
58
59     for(;;) {
60         FILE *file;
61         
62         if(dwCounter)
63             snprintf(szFileName, PATH_MAX, "%s.%s.%u.%s.gz", szProcessName, szName, dwCounter, szExtension);
64         else
65             snprintf(szFileName, PATH_MAX, "%s.%s.%s.gz", szProcessName, szName, szExtension);
66         
67         file = fopen(szFileName, "rb");
68         if(file == NULL)
69             break;
70         
71         fclose(file);
72         
73         ++dwCounter;
74     }
75
76     fprintf(stderr, "Logging to %s\n", szFileName);
77     g_gzFile = gzopen(szFileName, "wb");
78 }
79
80 static inline void _ReOpen(void) {
81     /* XXX */
82 }
83
84 static inline void Write(const char *sBuffer, size_t dwBytesToWrite) {
85     if(g_gzFile == NULL)
86         return;
87     
88     gzwrite(g_gzFile, sBuffer, dwBytesToWrite);
89 }
90
91 static inline void Write(const char *szText) {
92     Write(szText, strlen(szText));
93 }
94
95 static inline void Write(char c) 
96 {
97     Write(&c, 1);
98 }
99
100 static inline void
101 WriteF(const char *format, ...) 
102 {
103     char szBuffer[4096];
104     va_list ap;
105     va_start(ap, format);
106     vsnprintf(szBuffer, sizeof(szBuffer), format, ap);
107     va_end(ap);
108     Write(szBuffer);
109 }
110
111 static inline void 
112 Escape(char c) 
113 {
114     switch(c) {
115     case '&':
116         Write("&amp;");
117         break;
118     case '<':
119         Write("&lt;");
120         break;
121     case '>':
122         Write("&gt;");
123         break;
124     case '"':
125         Write("&quot;");
126         break;
127     case '\'':
128         Write("&apos;");
129         break;
130     default:
131         Write(c);
132     }
133 }
134
135 static inline void 
136 Escape(const char *s)
137 {
138     unsigned char c;
139     while((c = *s++) != 0) {
140         Escape(c);
141     }
142 }
143
144 static inline void
145 EscapeF(const char *format, ...)
146 {
147     char szBuffer[4096];
148     va_list ap;
149     va_start(ap, format);
150     vsnprintf(szBuffer, sizeof(szBuffer), format, ap);
151     va_end(ap);
152     Escape(szBuffer);
153 }
154
155 static inline void 
156 Indent(unsigned level) {
157     for(unsigned i = 0; i < level; ++i)
158         Write("\t");
159 }
160
161 static inline void 
162 NewLine(void) {
163     Write("\r\n");
164 }
165
166 static inline void 
167 Tag(const char *name) {
168     Write("<");
169     Write(name);
170     Write("/>");
171 }
172
173 static inline void 
174 BeginTag(const char *name) {
175     Write("<");
176     Write(name);
177     Write(">");
178 }
179
180 static inline void 
181 BeginTag(const char *name, 
182          const char *attr1, const char *value1) {
183     Write("<");
184     Write(name);
185     Write(" ");
186     Write(attr1);
187     Write("=\"");
188     Escape(value1);
189     Write("\">");
190 }
191
192 static inline void 
193 BeginTag(const char *name, 
194          const char *attr1, const char *value1,
195          const char *attr2, const char *value2) {
196     Write("<");
197     Write(name);
198     Write(" ");
199     Write(attr1);
200     Write("=\"");
201     Escape(value1);
202     Write("\" ");
203     Write(attr2);
204     Write("=\"");
205     Escape(value2);
206     Write("\">");
207 }
208
209 static inline void 
210 BeginTag(const char *name, 
211               const char *attr1, const char *value1,
212               const char *attr2, const char *value2,
213               const char *attr3, const char *value3) {
214     Write("<");
215     Write(name);
216     Write(" ");
217     Write(attr1);
218     Write("=\"");
219     Escape(value1);
220     Write("\" ");
221     Write(attr2);
222     Write("=\"");
223     Escape(value2);
224     Write("\" ");
225     Write(attr3);
226     Write("=\"");
227     Escape(value3);
228     Write("\">");
229 }
230
231 static inline void
232 EndTag(const char *name) {
233     Write("</");
234     Write(name);
235     Write(">");
236 }
237
238 void Open(const char *name) {
239     _Open(name, "xml");
240     Write("<?xml version='1.0' encoding='UTF-8'?>");
241     NewLine();
242     Write("<?xml-stylesheet type='text/xsl' href='apitrace.xsl'?>");
243     NewLine();
244     BeginTag("trace");
245     NewLine();
246 }
247
248 void ReOpen(void) {
249     _ReOpen();
250 }
251
252 void Close(void) {
253     EndTag("trace");
254     NewLine();
255     _Close();
256 }
257
258 void Text(const char *text) {
259     Escape(text);
260 }
261
262 void TextF(const char *format, ...) {
263     char szBuffer[4096];
264     va_list ap;
265     va_start(ap, format);
266     vsnprintf(szBuffer, sizeof(szBuffer), format, ap);
267     va_end(ap);
268     Escape(szBuffer);
269 }
270
271 void BeginCall(const char *function) {
272     OS::AcquireMutex();
273     Indent(1);
274     BeginTag("call", "name", function);
275     NewLine();
276 }
277
278 void EndCall(void) {
279     Indent(1);
280     EndTag("call");
281     NewLine();
282     gzflush(g_gzFile, Z_SYNC_FLUSH);
283     OS::ReleaseMutex();
284 }
285
286 void BeginArg(const char *type, const char *name) {
287     Indent(2);
288     BeginTag("arg", "type", type, "name", name);
289 }
290
291 void EndArg(void) {
292     EndTag("arg");
293     NewLine();
294 }
295
296 void BeginReturn(const char *type) {
297     Indent(2);
298     BeginTag("ret", "type", type);
299 }
300
301 void EndReturn(void) {
302     EndTag("ret");
303     NewLine();
304 }
305
306 void BeginElement(const char *type, const char *name) {
307     BeginTag("elem", "type", type, "name", name);
308 }
309
310 void BeginElement(const char *type) {
311     BeginTag("elem", "type", type);
312 }
313
314 void EndElement(void) {
315     EndTag("elem");
316 }
317
318 void BeginReference(const char *type, const void *addr) {
319     char saddr[256];
320     snprintf(saddr, sizeof(saddr), "%p", addr);
321     BeginTag("ref", "type", type, "addr", saddr);
322 }
323
324 void EndReference(void) {
325     EndTag("ref");
326 }
327
328 void DumpString(const char *str) {
329     const unsigned char *p = (const unsigned char *)str;
330     if (!str) {
331         Write("NULL");
332         return;
333     }
334     Write("\"");
335     unsigned char c;
336     while((c = *p++) != 0) {
337         if(c == '\"')
338             Write("\\\"");
339         else if(c == '\\')
340             Write("\\\\");
341         else if(c >= 0x20 && c <= 0x7e)
342             Write(c);
343         else if(c == '\t')
344             Write("&#09;");
345         else if(c == '\r')
346             Write("&#13;");
347         else if(c == '\n')
348             Write("&#10;");
349         else {
350             unsigned char octal0 = c & 0x7;
351             unsigned char octal1 = (c >> 3) & 0x7;
352             unsigned char octal2 = (c >> 3) & 0x7;
353             if(octal2)
354                 WriteF("\\%u%u%u", octal2, octal1, octal0);
355             else if(octal1)
356                 WriteF("\\%u%u", octal1, octal0);
357             else
358                 WriteF("\\%u", octal0);
359         }
360     }
361     Write("\"");
362 }
363
364 void DumpWString(const wchar_t *str) {
365     const wchar_t *p = str;
366     if (!str) {
367         Write("NULL");
368         return;
369     }
370     Write("L\"");
371     wchar_t c;
372     while((c = *p++) != 0) {
373         if(c == '\"')
374             Write("\\\"");
375         else if(c == '\\')
376             Write("\\\\");
377         else if(c >= 0x20 && c <= 0x7e)
378             Write((char)c);
379         else if(c == '\t')
380             Write("&#09;");
381         else if(c == '\r')
382             Write("&#13;");
383         else if(c == '\n')
384             Write("&#10;");
385         else {
386             unsigned octal0 = c & 0x7;
387             unsigned octal1 = (c >> 3) & 0x7;
388             unsigned octal2 = (c >> 3) & 0x7;
389             if(octal2)
390                 WriteF("\\%u%u%u", octal2, octal1, octal0);
391             else if(octal1)
392                 WriteF("\\%u%u", octal1, octal0);
393             else
394                 WriteF("\\%u", octal0);
395         }
396     }
397     Write("\"");
398 }
399
400 } /* namespace Log */