]> git.cworth.org Git - apitrace/blobdiff - log.cpp
Abstract process termination.
[apitrace] / log.cpp
diff --git a/log.cpp b/log.cpp
index ac1787b19184eb016112897c5a5178c4aa1895e2..ea306de5b4b8786405851ba061af9ab56911fd37 100644 (file)
--- a/log.cpp
+++ b/log.cpp
-/****************************************************************************
+/**************************************************************************
  *
- * Copyright 2008-2009 VMware, Inc.
+ * Copyright 2007-2009 VMware, Inc.
+ * All Rights Reserved.
  *
- * This program is free software: you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
  *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Lesser General Public License for more details.
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
  *
- ****************************************************************************/
+ **************************************************************************/
 
 
+#include <assert.h>
 #include <stdarg.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
-#include <windows.h>
-
 #include <zlib.h>
 
+#include "os.hpp"
 #include "log.hpp"
-
-
-#ifdef WIN32
-#ifndef PATH_MAX
-#define PATH_MAX _MAX_PATH
-#endif
-#ifndef snprintf
-#define snprintf _snprintf
-#endif
-#ifndef vsnprintf
-#define vsnprintf _vsnprintf
-#endif
-#endif
+#include "trace_format.hpp"
 
 
 namespace Log {
 
 
 static gzFile g_gzFile = NULL;
-static char g_szFileName[PATH_MAX];
-static CRITICAL_SECTION CriticalSection;
-
 static void _Close(void) {
-    if(g_gzFile != NULL) {
-        gzclose(g_gzFile);
-        g_gzFile = NULL;
-        DeleteCriticalSection(&CriticalSection);
-    }
+   if(g_gzFile != NULL) {
+      gzclose(g_gzFile);
+      g_gzFile = NULL;
+   }
 }
 
 static void _Open(const char *szName, const char *szExtension) {
-    _Close();
-    
-    static unsigned dwCounter = 0;
-
-    for(;;) {
-        FILE *file;
-        
-        if(dwCounter)
-            snprintf(g_szFileName, PATH_MAX, "%s.%u.%s.gz", szName, dwCounter, szExtension);
-        else
-            snprintf(g_szFileName, PATH_MAX, "%s.%s.gz", szName, szExtension);
-        
-        file = fopen(g_szFileName, "rb");
-        if(file == NULL)
-            break;
-        
-        fclose(file);
-        
-        ++dwCounter;
-    }
-
-    g_gzFile = gzopen(g_szFileName, "wb");
-    InitializeCriticalSection(&CriticalSection);
+   _Close();
+   
+   static unsigned dwCounter = 0;
+
+   char szProcessName[PATH_MAX];
+   char szFileName[PATH_MAX];
+
+   OS::GetProcessName(szProcessName, PATH_MAX);
+
+   for(;;) {
+      FILE *file;
+      
+      if(dwCounter)
+         snprintf(szFileName, PATH_MAX, "%s.%s.%u.%s", szProcessName, szName, dwCounter, szExtension);
+      else
+         snprintf(szFileName, PATH_MAX, "%s.%s.%s", szProcessName, szName, szExtension);
+      
+      file = fopen(szFileName, "rb");
+      if(file == NULL)
+         break;
+      
+      fclose(file);
+      
+      ++dwCounter;
+   }
+
+   fprintf(stderr, "Logging to %s\n", szFileName);
+   g_gzFile = gzopen(szFileName, "wb");
+}
+
+static inline void Write(const void *sBuffer, size_t dwBytesToWrite) {
+   if(g_gzFile == NULL)
+      return;
+   
+   gzwrite(g_gzFile, sBuffer, dwBytesToWrite);
 }
 
-static inline void _ReOpen(void) {
-    /* XXX */
+static inline void 
+WriteByte(char c) {
+   Write(&c, 1);
 }
 
-static inline void Write(const char *sBuffer, size_t dwBytesToWrite) {
-    if(g_gzFile == NULL)
-        return;
-    
-    gzwrite(g_gzFile, sBuffer, dwBytesToWrite);
-}
+void inline 
+WriteUInt(unsigned long long value) {
+   char buf[2 * sizeof value];
+   unsigned len;
+
+   len = 0;
+   do {
+      assert(len < sizeof buf);
+      buf[len] = 0x80 | (value & 0x7f);
+      value >>= 7;
+      ++len;
+   } while (value);
+
+   assert(len);
+   buf[len - 1] &= 0x7f;
 
-static inline void Write(const char *szText) {
-    Write(szText, strlen(szText));
+   Write(buf, len);
 }
 
 static inline void 
-Escape(const char *s) {
-    /* FIXME */
-    Write(s);
+WriteFloat(float value) {
+   assert(sizeof value == 4);
+   Write((const char *)&value, sizeof value);
 }
 
 static inline void 
-Indent(unsigned level) {
-    for(unsigned i = 0; i < level; ++i)
-        Write("\t");
+WriteDouble(double value) {
+   assert(sizeof value == 8);
+   Write((const char *)&value, sizeof value);
 }
 
 static inline void 
-NewLine(void) {
-    Write("\r\n");
+WriteString(const char *str) {
+   size_t len = strlen(str);
+   WriteUInt(len);
+   Write(str, len);
 }
 
-static inline void 
-Tag(const char *name) {
-    Write("<");
-    Write(name);
-    Write("/>");
+void Open(const char *name) {
+   _Open(name, "trace");
+   WriteUInt(TRACE_VERSION);
 }
 
-static inline void 
-BeginTag(const char *name) {
-    Write("<");
-    Write(name);
-    Write(">");
+void Close(void) {
+   _Close();
 }
 
-static inline void 
-BeginTag(const char *name, 
-         const char *attr1, const char *value1) {
-    Write("<");
-    Write(name);
-    Write(" ");
-    Write(attr1);
-    Write("=\"");
-    Escape(value1);
-    Write("\">");
+void BeginCall(const char *function) {
+   OS::AcquireMutex();
+   WriteString(function);
 }
 
-static inline void 
-BeginTag(const char *name, 
-         const char *attr1, const char *value1,
-         const char *attr2, const char *value2) {
-    Write("<");
-    Write(name);
-    Write(" ");
-    Write(attr1);
-    Write("=\"");
-    Escape(value1);
-    Write("\" ");
-    Write(attr2);
-    Write("=\"");
-    Escape(value2);
-    Write("\">");
+void EndCall(void) {
+   WriteByte(Trace::CALL_END);
+   gzflush(g_gzFile, Z_SYNC_FLUSH);
+   OS::ReleaseMutex();
 }
 
-static inline void 
-BeginTag(const char *name, 
-              const char *attr1, const char *value1,
-              const char *attr2, const char *value2,
-              const char *attr3, const char *value3) {
-    Write("<");
-    Write(name);
-    Write(" ");
-    Write(attr1);
-    Write("=\"");
-    Escape(value1);
-    Write("\" ");
-    Write(attr2);
-    Write("=\"");
-    Escape(value2);
-    Write("\" ");
-    Write(attr3);
-    Write("=\"");
-    Escape(value3);
-    Write("\">");
-}
-
-static inline void
-EndTag(const char *name) {
-    Write("</");
-    Write(name);
-    Write(">");
+void BeginArg(const char *type, const char *name) {
+   WriteByte(Trace::CALL_ARG);
+   WriteString(name);
 }
 
-void Open(const char *name) {
-    _Open(name, "xml");
-    Write("<?xml version='1.0' encoding='UTF-8'?>");
-    NewLine();
-    Write("<?xml-stylesheet type='text/xsl' href='apitrace.xsl'?>");
-    NewLine();
-    BeginTag("trace");
-    NewLine();
+void EndArg(void) { }
+
+void BeginReturn(const char *type) {
+   WriteByte(Trace::CALL_RET);
 }
 
-void ReOpen(void) {
-    _ReOpen();
+void EndReturn(void) { }
+
+void BeginArray(const char *type, size_t length) {
+   WriteByte(Trace::TYPE_ARRAY);
+   WriteUInt(length);
 }
 
-void Close(void) {
-    EndTag("trace");
-    NewLine();
-    _Close();
+void EndArray(void) { }
+
+void BeginElement(const char *type) { }
+
+void EndElement(void) { }
+
+void BeginStruct(const char *type) {
+   WriteByte(Trace::TYPE_STRUCT);
 }
 
-void Text(const char *text) {
-    Escape(text);
+void EndStruct(void) {
+   WriteString("");
 }
 
-static void TextChar(char c) {
-    char szText[2];
-    szText[0] = c;
-    szText[1] = 0;
-    Text(szText);
+void BeginMember(const char *type, const char *name) {
+   WriteString(name);
 }
 
-void TextF(const char *format, ...) {
-    char szBuffer[4196];
-    va_list ap;
-    va_start(ap, format);
-    vsnprintf(szBuffer, sizeof(szBuffer), format, ap);
-    va_end(ap);
-    Text(szBuffer);
+void EndMember(void) { }
+
+void BeginBitmask(const char *type) {
+   WriteByte(Trace::TYPE_BITMASK);
 }
 
-void BeginCall(const char *function) {
-    EnterCriticalSection(&CriticalSection); 
-    Indent(1);
-    BeginTag("call", "name", function);
-    NewLine();
+void EndBitmask(void) {
+   WriteByte(Trace::TYPE_NULL);
 }
 
-void EndCall(void) {
-    Indent(1);
-    EndTag("call");
-    NewLine();
-    gzflush(g_gzFile, Z_SYNC_FLUSH);
-    LeaveCriticalSection(&CriticalSection); 
+void BeginPointer(const char *type, const void *addr)
+{
+   WriteByte(Trace::TYPE_POINTER);
+   WriteUInt((size_t)addr);
 }
 
-void BeginArg(const char *type, const char *name) {
-    Indent(2);
-    BeginTag("arg", "type", type, "name", name);
+void EndPointer(void) { }
+
+void LiteralBool(bool value) {
+   WriteByte(value ? Trace::TYPE_TRUE : Trace::TYPE_FALSE);
 }
 
-void EndArg(void) {
-    EndTag("arg");
-    NewLine();
+void LiteralSInt(signed long long value) {
+   if (value < 0) {
+      WriteByte(Trace::TYPE_SINT);
+      WriteUInt(-value);
+   } else {
+      WriteByte(Trace::TYPE_UINT);
+      WriteUInt(value);
+   }
 }
 
-void BeginReturn(const char *type) {
-    Indent(2);
-    BeginTag("ret", "type", type);
-}
-
-void EndReturn(void) {
-    EndTag("ret");
-    NewLine();
-}
-
-void BeginElement(const char *type, const char *name) {
-    BeginTag("elem", "type", type, "name", name);
-}
-
-void BeginElement(const char *type) {
-    BeginTag("elem", "type", type);
-}
-
-void EndElement(void) {
-    EndTag("elem");
-}
-
-void BeginReference(const char *type, const void *addr) {
-    char saddr[256];
-    snprintf(saddr, sizeof(saddr), "%p", addr);
-    BeginTag("ref", "type", type, "addr", saddr);
-}
-
-void EndReference(void) {
-    EndTag("ref");
-}
-
-void DumpString(const char *str) {
-    const unsigned char *p = (const unsigned char *)str;
-    Log::Text("\"");
-    unsigned char c;
-    while((c = *p++) != 0) {
-        if(c == '\"')
-            Text("\\\"");
-        else if(c == '\\')
-            Text("\\\\");
-        else if(c >= 0x20 && c <= 0x7e)
-            TextChar(c);
-        else if(c == '\t')
-            Text("\\t");
-        else if(c == '\r')
-            Text("\\r");
-        else if(c == '\n')
-            Text("\\n");
-        else {
-            unsigned char octal0 = c & 0x7;
-            unsigned char octal1 = (c >> 3) & 0x7;
-            unsigned char octal2 = (c >> 3) & 0x7;
-            if(octal2)
-                TextF("\\%u%u%u", octal2, octal1, octal0);
-            else if(octal1)
-                TextF("\\%u%u", octal1, octal0);
-            else
-                TextF("\\%u", octal0);
-        }
-    }
-    Log::Text("\"");
-}
-
-void DumpWString(const wchar_t *str) {
-    const wchar_t *p = str;
-    Log::Text("L\"");
-    wchar_t c;
-    while((c = *p++) != 0) {
-        if(c == '\"')
-            Text("\\\"");
-        else if(c == '\\')
-            Text("\\\\");
-        else if(c >= 0x20 && c <= 0x7e)
-            TextChar((char)c);
-        else if(c == '\t')
-            Text("\\t");
-        else if(c == '\r')
-            Text("\\r");
-        else if(c == '\n')
-            Text("\\n");
-        else {
-            unsigned octal0 = c & 0x7;
-            unsigned octal1 = (c >> 3) & 0x7;
-            unsigned octal2 = (c >> 3) & 0x7;
-            if(octal2)
-                TextF("\\%u%u%u", octal2, octal1, octal0);
-            else if(octal1)
-                TextF("\\%u%u", octal1, octal0);
-            else
-                TextF("\\%u", octal0);
-        }
-    }
-    Log::Text("\"");
+void LiteralUInt(unsigned long long value) {
+   WriteByte(Trace::TYPE_UINT);
+   WriteUInt(value);
+}
+
+void LiteralFloat(float value) {
+   WriteByte(Trace::TYPE_FLOAT);
+   WriteFloat(value);
+}
+
+void LiteralFloat(double value) {
+   WriteByte(Trace::TYPE_DOUBLE);
+   WriteDouble(value);
+}
+
+void LiteralString(const char *str) {
+   if (!str) {
+      LiteralNull();
+      return;
+   }
+   WriteByte(Trace::TYPE_STRING);
+   WriteString(str);
+}
+
+void LiteralWString(const wchar_t *str) {
+   if (!str) {
+      LiteralNull();
+      return;
+   }
+   WriteByte(Trace::TYPE_STRING);
+   WriteString("<wide-string>");
+}
+   
+void LiteralBlob(const void *data, size_t size) {
+   if (!data) {
+      LiteralNull();
+      return;
+   }
+   WriteByte(Trace::TYPE_BLOB);
+   WriteUInt(size);
+   if (size) {
+      Write(data, size);
+   }
+}
+
+void LiteralNamedConstant(const char *name, long long value) {
+   WriteByte(Trace::TYPE_CONST);
+   WriteString(name);
+   LiteralSInt(value);
+}
+
+void LiteralNull(void) {
+   WriteByte(Trace::TYPE_NULL);
+}
+
+void LiteralOpaque(const void *addr) {
+   if (!addr) {
+      LiteralNull();
+      return;
+   }
+   WriteByte(Trace::TYPE_OPAQUE);
+   WriteUInt((size_t)addr);
+}
+
+void Abort(void) {
+    Close();
+    OS::Abort();
 }
 
 } /* namespace Log */