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