#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
+#include <string.h>
#ifdef _WIN32
#ifndef snprintf
#ifndef vsnprintf
#define vsnprintf _vsnprintf
#endif
-#define PATH_SEP '\\'
-#else /* !_WIN32 */
-#define PATH_SEP '/'
#endif /* !_WIN32 */
-#ifndef PATH_MAX
-#define PATH_MAX 1024
-#endif
-
namespace os {
void acquireMutex(void);
void releaseMutex(void);
-bool getProcessName(char *str, size_t size);
-bool getCurrentDir(char *str, size_t size);
-
void log(const char *format, ...)
#ifdef __GNUC__
__attribute__ ((format (printf, 1, 2)))
--- /dev/null
+/**************************************************************************
+ *
+ * Copyright 2011 Jose Fonseca
+ * All Rights Reserved.
+ *
+ * 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:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+/*
+ * Path manipulation.
+ */
+
+#ifndef _OS_PATH_HPP_
+#define _OS_PATH_HPP_
+
+
+#include <assert.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stddef.h>
+
+#ifdef __MINGW32__
+// Some versions of are missing _vscprintf's decleration, although still
+// provide the symbol in the import library.
+extern "C" _CRTIMP int _vscprintf(const char *format, va_list argptr);
+#endif
+
+#ifndef va_copy
+#ifdef __va_copy
+#define va_copy(dest, src) __va_copy((dest), (src))
+#else
+#define va_copy(dest, src) (dest) = (src)
+#endif
+#endif
+
+#include <vector>
+
+#include "os.hpp"
+
+
+#ifdef _WIN32
+#define OS_DIR_SEP '\\'
+#else /* !_WIN32 */
+#define OS_DIR_SEP '/'
+#endif /* !_WIN32 */
+
+
+namespace os {
+
+
+class Path {
+protected:
+ typedef std::vector<char> Buffer;
+ Buffer buffer;
+
+ Buffer::iterator rfind(char c) {
+ Buffer::iterator it = buffer.end();
+ assert(it != buffer.begin());
+ --it; // skill null
+ while (it != buffer.begin()) {
+ --it;
+ if (*it == c) {
+ return it;
+ }
+ }
+ return buffer.end();
+ }
+
+ Path(size_t size) :
+ buffer(size) {
+ }
+
+ char *buf(void) {
+ return &buffer[0];
+ }
+
+public:
+ Path() {
+ buffer.push_back(0);
+ }
+
+ Path(const char *s) :
+ buffer(s, s + strlen(s) + 1)
+ {}
+
+ template <class InputIterator>
+ Path(InputIterator first, InputIterator last) :
+ buffer(first, last)
+ {
+ buffer.push_back(0);
+ }
+
+ char *buf(size_t size) {
+ buffer.resize(size);
+ return &buffer[0];
+ }
+
+ void trimDirectory(void) {
+ Buffer::iterator sep = rfind(OS_DIR_SEP);
+ if (sep != buffer.end()) {
+ buffer.erase(buffer.begin(), sep + 1);
+ }
+ }
+
+ void trimExtension(void) {
+ Buffer::iterator dot = rfind('.');
+ if (dot != buffer.end()) {
+ buffer.erase(dot, buffer.end() - 1);
+ }
+ }
+
+ size_t length(void) const {
+ size_t size = buffer.size();
+ assert(size > 0);
+ assert(buffer[size - 1] == 0);
+ return size - 1;
+ }
+
+ void truncate(size_t length) {
+ assert(length < buffer.size());
+ buffer[length] = 0;
+ buffer.resize(length + 1);
+ }
+
+ void truncate(void) {
+ truncate(strlen(str()));
+ }
+
+ const char *str(void) const {
+ assert(buffer[buffer.size() - 1] == 0);
+ return &buffer[0];
+ }
+
+ operator const char *(void) const {
+ return str();
+ }
+
+ void join(const Path & other) {
+ size_t len = length();
+ if (len > 0 && buffer[len - 1] != OS_DIR_SEP) {
+ buffer.insert(buffer.begin() + len++, OS_DIR_SEP);
+ }
+ buffer.insert(buffer.begin() + len, other.buffer.begin(), other.buffer.end() - 1);
+ }
+
+ /**
+ * Create a path from a printf-like format string
+ */
+ static Path
+ format(const char *format, ...)
+#ifdef __GNUC__
+ __attribute__ ((format (printf, 1, 2)))
+#endif
+ {
+
+ va_list args;
+
+ va_start(args, format);
+
+ int length;
+ va_list args_copy;
+ va_copy(args_copy, args);
+#ifdef _WIN32
+ /* We need to use _vcsprintf to calculate the length as vsnprintf returns -1
+ * if the number of characters to write is greater than count.
+ */
+ length = _vscprintf(format, args_copy);
+#else
+ char dummy;
+ length = vsnprintf(&dummy, sizeof dummy, format, args_copy);
+#endif
+ va_end(args_copy);
+
+ assert(length >= 0);
+ size_t size = length + 1;
+
+ Path path(size);
+
+ va_start(args, format);
+ vsnprintf(path.buf(), size, format, args);
+ va_end(args);
+
+ return path;
+ }
+};
+
+
+Path getProcessName();
+Path getCurrentDir();
+
+
+} /* namespace os */
+
+#endif /* _OS_PATH_HPP_ */
#include <fcntl.h>
#include <signal.h>
+#if defined(__linux__)
+#include <linux/limits.h> // PATH_MAX
+#endif
+
#ifdef __APPLE__
+#include <sys/syslimits.h> // PATH_MAX
#include <mach-o/dyld.h>
#endif
+#ifndef PATH_MAX
+#warning PATH_MAX undefined
+#define PATH_MAX 4096
+#endif
+
#include "os.hpp"
+#include "os_path.hpp"
namespace os {
}
-bool
-getProcessName(char *str, size_t size)
+Path
+getProcessName(void)
{
- char szProcessPath[PATH_MAX + 1];
- char *lpProcessName;
+ Path path;
+ size_t size = PATH_MAX;
+ char *buf = path.buf(size);
// http://stackoverflow.com/questions/1023306/finding-current-executables-path-without-proc-self-exe
#ifdef __APPLE__
- uint32_t len = sizeof szProcessPath;
- if (_NSGetExecutablePath(szProcessPath, &len) != 0) {
- *str = 0;
- return false;
+ uint32_t len = size;
+ if (_NSGetExecutablePath(buf, &len) != 0) {
+ *buf = 0;
+ return path;
}
#else
ssize_t len;
- len = readlink("/proc/self/exe", szProcessPath, sizeof(szProcessPath) - 1);
+ len = readlink("/proc/self/exe", buf, size - 1);
if (len == -1) {
// /proc/self/exe is not available on setuid processes, so fallback to
// /proc/self/cmdline.
int fd = open("/proc/self/cmdline", O_RDONLY);
if (fd >= 0) {
- len = read(fd, szProcessPath, sizeof(szProcessPath) - 1);
+ len = read(fd, buf, size - 1);
close(fd);
}
}
if (len <= 0) {
- snprintf(str, size, "%i", (int)getpid());
- return true;
+ snprintf(buf, size, "%i", (int)getpid());
+ return path;
}
#endif
- szProcessPath[len] = 0;
-
- lpProcessName = strrchr(szProcessPath, '/');
- lpProcessName = lpProcessName ? lpProcessName + 1 : szProcessPath;
-
- strncpy(str, lpProcessName, size);
- if (size)
- str[size - 1] = 0;
+ path.truncate(len);
- return true;
+ return path;
}
-bool
-getCurrentDir(char *str, size_t size)
+Path
+getCurrentDir(void)
{
- char *ret;
- ret = getcwd(str, size);
- str[size - 1] = 0;
- return ret ? true : false;
+ Path path;
+ size_t size = PATH_MAX;
+ char *buf = path.buf(size);
+
+ getcwd(buf, size);
+ buf[size - 1] = 0;
+
+ path.truncate();
+ return path;
}
void
#include <stdio.h>
#include "os.hpp"
+#include "os_path.hpp"
namespace os {
}
-bool
-getProcessName(char *str, size_t size)
+Path
+getProcessName(void)
{
- char szProcessPath[PATH_MAX];
- char *lpProcessName;
- char *lpProcessExt;
+ Path path;
+ size_t size = MAX_PATH;
+ char *buf = path.buf(size);
- GetModuleFileNameA(NULL, szProcessPath, sizeof(szProcessPath)/sizeof(szProcessPath[0]));
+ DWORD nWritten = GetModuleFileNameA(NULL, buf, size);
+ (void)nWritten;
- lpProcessName = strrchr(szProcessPath, '\\');
- lpProcessName = lpProcessName ? lpProcessName + 1 : szProcessPath;
+ path.truncate();
- lpProcessExt = strrchr(lpProcessName, '.');
- if (lpProcessExt) {
- *lpProcessExt = '\0';
- }
-
- strncpy(str, lpProcessName, size);
-
- return true;
+ return path;
}
-bool
-getCurrentDir(char *str, size_t size)
+Path
+getCurrentDir(void)
{
- DWORD ret;
- ret = GetCurrentDirectoryA(size, str);
- str[size - 1] = 0;
- return ret == 0 ? false : true;
+ Path path;
+ size_t size = MAX_PATH;
+ char *buf = path.buf(size);
+
+ DWORD ret = GetCurrentDirectoryA(size, buf);
+ (void)ret;
+
+ buf[size - 1] = 0;
+ path.truncate();
+
+ return path;
}
void
#include <string.h>
#include "os.hpp"
+#include "os_path.hpp"
#include "trace_file.hpp"
#include "trace_writer.hpp"
#include "trace_format.hpp"
void
LocalWriter::open(void) {
+ os::Path szFileName;
- static unsigned dwCounter = 0;
-
- const char *szExtension = "trace";
- char szFileName[PATH_MAX];
const char *lpFileName;
lpFileName = getenv("TRACE_FILE");
- if (lpFileName) {
- strncpy(szFileName, lpFileName, PATH_MAX);
- }
- else {
- char szProcessName[PATH_MAX];
- char szCurrentDir[PATH_MAX];
- os::getProcessName(szProcessName, PATH_MAX);
- os::getCurrentDir(szCurrentDir, PATH_MAX);
+ if (!lpFileName) {
+ static unsigned dwCounter = 0;
+
+ os::Path process = os::getProcessName();
+#ifdef _WIN32
+ process.trimExtension();
+#endif
+ process.trimDirectory();
+
+ os::Path prefix = os::getCurrentDir();
+ prefix.join(process);
for (;;) {
FILE *file;
if (dwCounter)
- snprintf(szFileName, PATH_MAX, "%s%c%s.%u.%s", szCurrentDir, PATH_SEP, szProcessName, dwCounter, szExtension);
+ szFileName = os::Path::format("%s.%u.trace", prefix.str(), dwCounter);
else
- snprintf(szFileName, PATH_MAX, "%s%c%s.%s", szCurrentDir, PATH_SEP, szProcessName, szExtension);
+ szFileName = os::Path::format("%s.trace", prefix.str());
- file = fopen(szFileName, "rb");
+ lpFileName = szFileName;
+ file = fopen(lpFileName, "rb");
if (file == NULL)
break;
}
}
- os::log("apitrace: tracing to %s\n", szFileName);
+ os::log("apitrace: tracing to %s\n", lpFileName);
- Writer::open(szFileName);
+ Writer::open(lpFileName);
#if 0
// For debugging the exception handler
#include <string.h>
+#include "os_path.hpp"
#include "image.hpp"
#include "retrace.hpp"
#include "glproc.hpp"
image::Image *ref = NULL;
if (compare_prefix) {
- char filename[PATH_MAX];
- snprintf(filename, sizeof filename, "%s%010u.png", compare_prefix, call_no);
+ os::Path filename = os::Path::format("%s%010u.png", compare_prefix, call_no);
ref = image::readPNG(filename);
if (!ref) {
return;
snprintf(comment, sizeof comment, "%u", call_no);
src->writePNM(std::cout, comment);
} else {
- char filename[PATH_MAX];
- snprintf(filename, sizeof filename, "%s%010u.png", snapshot_prefix, call_no);
+ os::Path filename = os::Path::format("%s%010u.png", snapshot_prefix, call_no);
if (src->writePNG(filename) && retrace::verbosity >= 0) {
std::cout << "Wrote " << filename << "\n";
}
#include <assert.h>
#include <stdint.h>
+#include "os_path.hpp"
#include "image.hpp"
#include "glproc.hpp"
#include "glsize.hpp"
if (snapshot_prefix) {
image::Image *src = getDrawableImage();
if (src) {
- char filename[PATH_MAX];
- snprintf(filename, sizeof filename, "%s%010u.png", snapshot_prefix, call_no);
+ os::Path filename = os::Path::format("%s%010u.png", snapshot_prefix, call_no);
if (src->writePNG(filename)) {
- os::log("apitrace: wrote %s\n", filename);
+ os::log("apitrace: wrote %s\n", filename.str());
}
delete src;