]> git.notmuchmail.org Git - apitrace/blobdiff - log.cpp
Cleanup generated log code.
[apitrace] / log.cpp
diff --git a/log.cpp b/log.cpp
index e1bc207e99cd53a6f675c349fad99005131cde0b..f0f194bae9e49ab1aab750c4079a1bd7fc961ac1 100644 (file)
--- a/log.cpp
+++ b/log.cpp
-/****************************************************************************
+/**************************************************************************
  *
- * Copyright 2008 Jose Fonseca
+ * 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 <zlib.h>
+
+#include "os.hpp"
 #include "log.hpp"
+#include "trace_format.hpp"
+
 
+namespace Log {
 
-File::File(const TCHAR *szName, const TCHAR *szExtension) {
-    m_hFile = INVALID_HANDLE_VALUE;
-    Open(szName, szExtension);
+
+static gzFile g_gzFile = NULL;
+static void _Close(void) {
+   if(g_gzFile != NULL) {
+      gzclose(g_gzFile);
+      g_gzFile = NULL;
+   }
 }
 
-File::~File() {
-    Close();
+static int reentrancy = 0;
+
+static void _Open(const char *szName, const char *szExtension) {
+   _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");
 }
 
-void File::Open(const TCHAR *szName, const TCHAR *szExtension) {
-    Close();
-    
-    DWORD dwCounter = 0;
-    do {
-        if(dwCounter)
-            _sntprintf(szFileName, MAX_PATH, TEXT("%s.%u.%s"), szName, dwCounter, szExtension);
-        else
-            _sntprintf(szFileName, MAX_PATH, TEXT("%s.%s"), szName, szExtension);
-
-        m_hFile = CreateFile(szFileName,
-                             GENERIC_WRITE,
-                             FILE_SHARE_WRITE,
-                             NULL,
-                             CREATE_NEW,
-                             FILE_ATTRIBUTE_NORMAL,
-                             NULL);
-        ++dwCounter;
-    } while(m_hFile == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_EXISTS);
-}
-
-void File::ReOpen(void) {
-    Close();
-    
-    m_hFile = CreateFile(szFileName,
-                         GENERIC_WRITE,
-                         0,
-                         NULL,
-                         OPEN_EXISTING,
-                         FILE_ATTRIBUTE_NORMAL,
-                         NULL);
-}
-
-void File::Close(void) {
-    if(m_hFile != INVALID_HANDLE_VALUE) {
-        CloseHandle(m_hFile);
-        m_hFile = INVALID_HANDLE_VALUE;
-    }
-}
-
-void File::Write(const char *szText) {
-    if(m_hFile == INVALID_HANDLE_VALUE)
-        return;
-    
-    DWORD dwBytesToWrite = (DWORD)strlen(szText);
-    DWORD dwBytesWritten = 0;
-    
-    while (dwBytesWritten < dwBytesToWrite) {
-        OVERLAPPED overlapped;
-        memset(&overlapped, 0, sizeof(OVERLAPPED));
-
-        /* Write to end of file */
-        overlapped.Offset = 0xffffffff;
-        overlapped.OffsetHigh = 0xffffffff;
-        
-        if(WriteFile(m_hFile,
-                     szText + dwBytesWritten,
-                     dwBytesToWrite - dwBytesWritten,
-                     &dwBytesWritten,
-                     &overlapped) == FALSE) {
-            Close();
-            Open(TEXT("extra"), TEXT("xml"));
-            return;
-        }
-    }
+static inline void Write(const void *sBuffer, size_t dwBytesToWrite) {
+   if(g_gzFile == NULL)
+      return;
+   
+   if (reentrancy > 1)
+      return;
+
+   gzwrite(g_gzFile, sBuffer, dwBytesToWrite);
+}
+
+static inline void 
+WriteByte(char c) {
+   Write(&c, 1);
 }
 
+void inline 
+WriteUInt(unsigned long long value) {
+   char buf[2 * sizeof value];
+   unsigned len;
 
-Log::Log(const TCHAR *szName) : File(szName, TEXT("xml")) {
-    Write("<?xml version='1.0' encoding='UTF-8'?>");
-    NewLine();
-    Write("<?xml-stylesheet type='text/xsl' href='d3dtrace.xsl'?>");
-    NewLine();
-    Write("<trace>");
-    NewLine();
+   len = 0;
+   do {
+      assert(len < sizeof buf);
+      buf[len] = 0x80 | (value & 0x7f);
+      value >>= 7;
+      ++len;
+   } while (value);
+
+   assert(len);
+   buf[len - 1] &= 0x7f;
+
+   Write(buf, len);
 }
 
-Log::~Log() {
-    Write("</trace>");
-    NewLine();
+static inline void 
+WriteFloat(float value) {
+   assert(sizeof value == 4);
+   Write((const char *)&value, sizeof value);
 }
 
-void Log::NewLine(void) {
-    Write("\r\n");
+static inline void 
+WriteDouble(double value) {
+   assert(sizeof value == 8);
+   Write((const char *)&value, sizeof value);
 }
 
-void Log::Tag(const char *name) {
-    Write("<");
-    Write(name);
-    Write("/>");
+static inline void 
+WriteString(const char *str) {
+   size_t len = strlen(str);
+   WriteUInt(len);
+   Write(str, len);
 }
 
-void Log::BeginTag(const char *name) {
-    Write("<");
-    Write(name);
-    Write(">");
+void Open(const char *name) {
+   _Open(name, "trace");
+   WriteUInt(TRACE_VERSION);
 }
 
-void Log::BeginTag(const char *name, 
-              const char *attr1, const char *value1) {
-    Write("<");
-    Write(name);
-    Write(" ");
-    Write(attr1);
-    Write("=\"");
-    Escape(value1);
-    Write("\">");
+void Close(void) {
+   _Close();
 }
 
-void Log::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 BeginCall(const char *function) {
+   OS::AcquireMutex();
+   ++reentrancy;
+   WriteString(function);
 }
 
-void Log::EndTag(const char *name) {
-    Write("</");
-    Write(name);
-    Write(">");
+void EndCall(void) {
+   WriteByte(Trace::CALL_END);
+   --reentrancy;
+   gzflush(g_gzFile, Z_SYNC_FLUSH);
+   OS::ReleaseMutex();
 }
 
-void Log::Text(const char *text) {
-    Escape(text);
+void BeginArg(const char *name) {
+   WriteByte(Trace::CALL_ARG);
+   WriteString(name);
 }
 
-void Log::TextF(const char *format, ...) {
-    char szBuffer[4196];
-    va_list ap;
-    va_start(ap, format);
-    vsnprintf(szBuffer, sizeof(szBuffer), format, ap);
-    va_end(ap);
-    Escape(szBuffer);
+void EndArg(void) { }
+
+void BeginReturn(void) {
+   WriteByte(Trace::CALL_RET);
 }
 
-void Log::BeginCall(const char *function) {
-    Write("\t");
-    BeginTag("call", "name", function);
-    NewLine();
+void EndReturn(void) { }
+
+void BeginArray(size_t length) {
+   WriteByte(Trace::TYPE_ARRAY);
+   WriteUInt(length);
 }
 
-void Log::EndCall(void) {
-    Write("\t");
-    EndTag("call");
-    NewLine();
+void EndArray(void) { }
+
+void BeginElement(void) { }
+
+void EndElement(void) { }
+
+void BeginStruct(const char *name) {
+   WriteByte(Trace::TYPE_STRUCT);
 }
 
-void Log::BeginParam(const char *name, const char *type) {
-    Write("\t\t");
-    BeginTag("param", "name", name, "type", type);
+void EndStruct(void) {
+   WriteString("");
 }
 
-void Log::EndParam(void) {
-    EndTag("param");
-    NewLine();
+void BeginMember(const char *name) {
+   WriteString(name);
 }
 
-void Log::BeginReturn(const char *type) {
-    Write("\t\t");
-    BeginTag("return", "type", type);
+void EndMember(void) { }
+
+void BeginBitmask(void) {
+   WriteByte(Trace::TYPE_BITMASK);
 }
 
-void Log::EndReturn(void) {
-    EndTag("return");
-    NewLine();
+void EndBitmask(void) {
+   WriteByte(Trace::TYPE_NULL);
 }
 
-void Log::Escape(const char *s) {
-    /* FIXME */
-    Write(s);
+void BeginPointer(const void *addr)
+{
+   WriteByte(Trace::TYPE_POINTER);
+   WriteUInt((size_t)addr);
 }
 
+void EndPointer(void) { }
+
+void LiteralBool(bool value) {
+   WriteByte(value ? Trace::TYPE_TRUE : Trace::TYPE_FALSE);
+}
+
+void LiteralSInt(signed long long value) {
+   if (value < 0) {
+      WriteByte(Trace::TYPE_SINT);
+      WriteUInt(-value);
+   } else {
+      WriteByte(Trace::TYPE_UINT);
+      WriteUInt(value);
+   }
+}
+
+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();
+}
 
-Log * g_pLog = NULL;
+} /* namespace Log */