]> git.cworth.org Git - apitrace/blob - log.cpp
Fix GetProcessName on POSIX.
[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 Write(const char *sBuffer, size_t dwBytesToWrite) {
81     if(g_gzFile == NULL)
82         return;
83     
84     gzwrite(g_gzFile, sBuffer, dwBytesToWrite);
85 }
86
87 static inline void Write(const char *szText) {
88     Write(szText, strlen(szText));
89 }
90
91 static inline void Write(char c) 
92 {
93     Write(&c, 1);
94 }
95
96 static inline void
97 WriteF(const char *format, ...) 
98 {
99     char szBuffer[4096];
100     va_list ap;
101     va_start(ap, format);
102     vsnprintf(szBuffer, sizeof(szBuffer), format, ap);
103     va_end(ap);
104     Write(szBuffer);
105 }
106
107 static inline void 
108 Escape(wchar_t c) 
109 {
110     switch(c) {
111     case '&':
112         Write("&amp;");
113         break;
114     case '<':
115         Write("&lt;");
116         break;
117     case '>':
118         Write("&gt;");
119         break;
120     case '"':
121         Write("&quot;");
122         break;
123     case '\'':
124         Write("&apos;");
125         break;
126     case '\t':
127         Write("&#09;");
128         break;
129     case '\r':
130         Write("&#13;");
131         break;
132     case '\n':
133         Write("&#10;");
134         break;
135     default:
136         if (c >= 0x20 && c <= 0x7e) {
137             Write((char)c);
138         } else {
139             Write('.');
140         }
141     }
142 }
143
144 static inline void 
145 Escape(const char *s)
146 {
147     unsigned char c;
148     while((c = *s++) != 0) {
149         Escape(c);
150     }
151 }
152
153 static inline void 
154 Escape(const wchar_t *s)
155 {
156     unsigned char c;
157     while((c = *s++) != 0) {
158         Escape(c);
159     }
160 }
161
162 static inline void
163 EscapeF(const char *format, ...)
164 {
165     char szBuffer[4096];
166     va_list ap;
167     va_start(ap, format);
168     vsnprintf(szBuffer, sizeof(szBuffer), format, ap);
169     va_end(ap);
170     Escape(szBuffer);
171 }
172
173 static inline void 
174 Indent(unsigned level) {
175     for(unsigned i = 0; i < level; ++i)
176         Write("\t");
177 }
178
179 static inline void 
180 NewLine(void) {
181     Write("\r\n");
182 }
183
184 static inline void 
185 Tag(const char *name) {
186     Write("<");
187     Write(name);
188     Write("/>");
189 }
190
191 static inline void 
192 BeginTag(const char *name) {
193     Write("<");
194     Write(name);
195     Write(">");
196 }
197
198 static inline void 
199 BeginTag(const char *name, 
200          const char *attr1, const char *value1) {
201     Write("<");
202     Write(name);
203     Write(" ");
204     Write(attr1);
205     Write("=\"");
206     Escape(value1);
207     Write("\">");
208 }
209
210 static inline void 
211 BeginTag(const char *name, 
212          const char *attr1, const char *value1,
213          const char *attr2, const char *value2) {
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 }
226
227 static inline void 
228 BeginTag(const char *name, 
229               const char *attr1, const char *value1,
230               const char *attr2, const char *value2,
231               const char *attr3, const char *value3) {
232     Write("<");
233     Write(name);
234     Write(" ");
235     Write(attr1);
236     Write("=\"");
237     Escape(value1);
238     Write("\" ");
239     Write(attr2);
240     Write("=\"");
241     Escape(value2);
242     Write("\" ");
243     Write(attr3);
244     Write("=\"");
245     Escape(value3);
246     Write("\">");
247 }
248
249 static inline void
250 EndTag(const char *name) {
251     Write("</");
252     Write(name);
253     Write(">");
254 }
255
256 void Open(const char *name) {
257     _Open(name, "xml");
258     Write("<?xml version='1.0' encoding='UTF-8'?>");
259     NewLine();
260     Write("<?xml-stylesheet type='text/xsl' href='apitrace.xsl'?>");
261     NewLine();
262     BeginTag("trace");
263     NewLine();
264 }
265
266 void Close(void) {
267     EndTag("trace");
268     NewLine();
269     _Close();
270 }
271
272 void BeginCall(const char *function) {
273     OS::AcquireMutex();
274     Indent(1);
275     BeginTag("call", "name", function);
276     NewLine();
277 }
278
279 void EndCall(void) {
280     Indent(1);
281     EndTag("call");
282     NewLine();
283     gzflush(g_gzFile, Z_SYNC_FLUSH);
284     OS::ReleaseMutex();
285 }
286
287 void BeginArg(const char *type, const char *name) {
288     Indent(2);
289     BeginTag("arg", "type", type, "name", name);
290 }
291
292 void EndArg(void) {
293     EndTag("arg");
294     NewLine();
295 }
296
297 void BeginReturn(const char *type) {
298     Indent(2);
299     BeginTag("ret", "type", type);
300 }
301
302 void EndReturn(void) {
303     EndTag("ret");
304     NewLine();
305 }
306
307 void BeginArray(const char *type, size_t length)
308 {
309     BeginTag("array", "type", type);
310 }
311
312 void EndArray(void)
313 {
314     EndTag("array");
315 }
316
317 void BeginElement(const char *type)
318 {
319     BeginTag("elem", "type", type);
320 }
321
322 void EndElement(void)
323 {
324     EndTag("elem");
325 }
326
327 void BeginStruct(const char *type)
328 {
329     BeginTag("struct", "type", type);
330 }
331
332 void EndStruct(void)
333 {
334     EndTag("struct");
335 }
336
337 void BeginMember(const char *type, const char *name)
338 {
339     BeginTag("member", "type", type, "name", name);
340 }
341
342 void EndMember(void)
343 {
344     EndTag("member");
345 }
346
347 void BeginBitmask(const char *type)
348 {
349     BeginTag("bitmask");
350 }
351
352 void EndBitmask(void)
353 {
354     EndTag("bitmask");
355 }
356
357 void BeginPointer(const char *type, const void *addr)
358 {
359     char saddr[256];
360     snprintf(saddr, sizeof(saddr), "%p", addr);
361     BeginTag("ref", "type", type, "addr", saddr);
362 }
363
364 void EndPointer(void)
365 {
366     EndTag("ref");
367 }
368
369 void LiteralBool(bool value)
370 {
371     BeginTag("bool");
372     WriteF("%u", value ? 0 : 1);
373     EndTag("bool");
374 }
375
376 void LiteralSInt(signed long long value)
377 {
378     BeginTag("int");
379     WriteF("%lli", value);
380     EndTag("int");
381 }
382
383 void LiteralUInt(unsigned long long value)
384 {
385     BeginTag("uint");
386     WriteF("%llu", value);
387     EndTag("uint");
388 }
389
390 void LiteralFloat(double value)
391 {
392     BeginTag("float");
393     WriteF("%f", value);
394     EndTag("float");
395 }
396
397 void LiteralString(const char *str)
398 {
399     if (!str) {
400         LiteralNull();
401         return;
402     }
403     BeginTag("string");
404     Escape(str);
405     EndTag("string");
406 }
407
408 void LiteralWString(const wchar_t *str)
409 {
410     if (!str) {
411         LiteralNull();
412         return;
413     }
414     BeginTag("wstring");
415     Escape(str);
416     EndTag("wstring");
417 }
418     
419 void LiteralNamedConstant(const char *str)
420 {
421     BeginTag("const");
422     Escape(str);
423     EndTag("const");
424 }
425
426 void LiteralNull(void)
427 {
428     Tag("null");
429 }
430
431 void LiteralOpaque(void)
432 {
433     Tag("opaque");
434 }
435
436 } /* namespace Log */