1 /****************************************************************************
3 * Copyright 2008-2009 VMware, Inc.
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.
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.
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/>.
18 ****************************************************************************/
35 #define PATH_MAX _MAX_PATH
38 #define snprintf _snprintf
41 #define vsnprintf _vsnprintf
49 static gzFile g_gzFile = NULL;
50 static char g_szFileName[PATH_MAX];
51 static CRITICAL_SECTION CriticalSection;
53 static void _Close(void) {
54 if(g_gzFile != NULL) {
57 DeleteCriticalSection(&CriticalSection);
61 static void _Open(const char *szName, const char *szExtension) {
64 static unsigned dwCounter = 0;
66 char szProcessPath[PATH_MAX];
70 GetModuleFileNameA(NULL, szProcessPath, sizeof(szProcessPath)/sizeof(szProcessPath[0]));
72 lpProcessName = strrchr(szProcessPath, '\\');
73 lpProcessName = lpProcessName ? lpProcessName + 1 : szProcessPath;
74 lpProcessExt = strrchr(lpProcessName, '.');
82 snprintf(g_szFileName, PATH_MAX, "%s.%s.%u.%s.gz", lpProcessName, szName, dwCounter, szExtension);
84 snprintf(g_szFileName, PATH_MAX, "%s.%s.%s.gz", lpProcessName, szName, szExtension);
86 file = fopen(g_szFileName, "rb");
95 g_gzFile = gzopen(g_szFileName, "wb");
96 InitializeCriticalSection(&CriticalSection);
99 static inline void _ReOpen(void) {
103 static inline void Write(const char *sBuffer, size_t dwBytesToWrite) {
107 gzwrite(g_gzFile, sBuffer, dwBytesToWrite);
110 static inline void Write(const char *szText) {
111 Write(szText, strlen(szText));
115 Escape(const char *s) {
121 Indent(unsigned level) {
122 for(unsigned i = 0; i < level; ++i)
132 Tag(const char *name) {
139 BeginTag(const char *name) {
146 BeginTag(const char *name,
147 const char *attr1, const char *value1) {
158 BeginTag(const char *name,
159 const char *attr1, const char *value1,
160 const char *attr2, const char *value2) {
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) {
197 EndTag(const char *name) {
203 void Open(const char *name) {
205 Write("<?xml version='1.0' encoding='UTF-8'?>");
207 Write("<?xml-stylesheet type='text/xsl' href='apitrace.xsl'?>");
223 void Text(const char *text) {
227 static void TextChar(char c) {
234 void TextF(const char *format, ...) {
237 va_start(ap, format);
238 vsnprintf(szBuffer, sizeof(szBuffer), format, ap);
243 static LARGE_INTEGER frequency = {0};
244 static LARGE_INTEGER startcounter;
246 void BeginCall(const char *function) {
247 EnterCriticalSection(&CriticalSection);
249 BeginTag("call", "name", function);
252 if(!frequency.QuadPart)
253 QueryPerformanceFrequency(&frequency);
255 QueryPerformanceCounter(&startcounter);
259 LARGE_INTEGER endcounter;
262 QueryPerformanceCounter(&endcounter);
263 usecs = (endcounter.QuadPart - startcounter.QuadPart)*1000000/frequency.QuadPart;
266 BeginTag("duration");
267 TextF("%llu", usecs);
274 gzflush(g_gzFile, Z_SYNC_FLUSH);
275 LeaveCriticalSection(&CriticalSection);
278 void BeginArg(const char *type, const char *name) {
280 BeginTag("arg", "type", type, "name", name);
288 void BeginReturn(const char *type) {
290 BeginTag("ret", "type", type);
293 void EndReturn(void) {
298 void BeginElement(const char *type, const char *name) {
299 BeginTag("elem", "type", type, "name", name);
302 void BeginElement(const char *type) {
303 BeginTag("elem", "type", type);
306 void EndElement(void) {
310 void BeginReference(const char *type, const void *addr) {
312 snprintf(saddr, sizeof(saddr), "%p", addr);
313 BeginTag("ref", "type", type, "addr", saddr);
316 void EndReference(void) {
320 void DumpString(const char *str) {
321 const unsigned char *p = (const unsigned char *)str;
324 while((c = *p++) != 0) {
329 else if(c >= 0x20 && c <= 0x7e)
338 unsigned char octal0 = c & 0x7;
339 unsigned char octal1 = (c >> 3) & 0x7;
340 unsigned char octal2 = (c >> 3) & 0x7;
342 TextF("\\%u%u%u", octal2, octal1, octal0);
344 TextF("\\%u%u", octal1, octal0);
346 TextF("\\%u", octal0);
352 void DumpWString(const wchar_t *str) {
353 const wchar_t *p = str;
356 while((c = *p++) != 0) {
361 else if(c >= 0x20 && c <= 0x7e)
370 unsigned octal0 = c & 0x7;
371 unsigned octal1 = (c >> 3) & 0x7;
372 unsigned octal2 = (c >> 3) & 0x7;
374 TextF("\\%u%u%u", octal2, octal1, octal0);
376 TextF("\\%u%u", octal1, octal0);
378 TextF("\\%u", octal0);
384 } /* namespace Log */