167 lines
3.3 KiB
C++
167 lines
3.3 KiB
C++
#include "tier0/platform.h"
|
|
#include "tier0/lib.h"
|
|
#include "stdarg.h"
|
|
#include "unistd.h"
|
|
#include "sys/stat.h"
|
|
#include "dirent.h"
|
|
#include "time.h"
|
|
#ifdef __linux__
|
|
#include "dlfcn.h"
|
|
#include "execinfo.h"
|
|
#endif
|
|
#ifdef __WIN32__
|
|
#include "windows.h"
|
|
#include "dbghelp.h"
|
|
#endif
|
|
PLATFORM_INTERFACE void Plat_FatalErrorFunc(const char* szFormat, ...)
|
|
{
|
|
va_list list;
|
|
va_start(list, szFormat);
|
|
V_vprintf(szFormat, list);
|
|
va_end(list);
|
|
fflush(stdout);
|
|
_exit(1);
|
|
}
|
|
|
|
PLATFORM_INTERFACE void Plat_ListDirRecursive(const char* szPath, ListDirCallbackFn file, ListDirCallbackFn dir)
|
|
{
|
|
struct dirent *entry;
|
|
DIR *dp = opendir(szPath);
|
|
|
|
if (!dp) {
|
|
return;
|
|
}
|
|
|
|
while ((entry = readdir(dp)) != NULL) {
|
|
char full_path[1024];
|
|
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
|
|
continue;
|
|
|
|
snprintf(full_path, sizeof(full_path), "%s/%s", szPath, entry->d_name);
|
|
|
|
struct stat statbuf;
|
|
if (stat(full_path, &statbuf) == -1) {
|
|
continue;
|
|
}
|
|
|
|
if (S_ISDIR(statbuf.st_mode)) {
|
|
if (dir)
|
|
dir(full_path);
|
|
Plat_ListDirRecursive(full_path, file, dir);
|
|
} else {
|
|
if (file)
|
|
file(full_path);
|
|
}
|
|
}
|
|
|
|
closedir(dp);
|
|
}
|
|
PLATFORM_INTERFACE void Plat_ListDir(const char* szPath, ListDirCallbackFn file, ListDirCallbackFn dir)
|
|
{
|
|
|
|
}
|
|
|
|
PLATFORM_INTERFACE char *Plat_GetExtension( const char *szPath )
|
|
{
|
|
char *last = (char*)szPath + V_strlen(szPath) - 1;
|
|
while (last != szPath)
|
|
{
|
|
if (*last=='.')
|
|
{
|
|
break;
|
|
};
|
|
if (*last=='/')
|
|
{
|
|
return 0;
|
|
}
|
|
last--;
|
|
}
|
|
return last+1;
|
|
}
|
|
|
|
PLATFORM_INTERFACE void Plat_Backtrace( void )
|
|
{
|
|
#ifdef __linux__
|
|
void *buffer[64];
|
|
int nptrs = backtrace(buffer, 64);
|
|
char **symbols = backtrace_symbols(buffer, nptrs);
|
|
|
|
if (symbols == NULL) {
|
|
V_printf("Backtrace failed\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
for (int i = 0; i < nptrs; i++) {
|
|
V_printf(" [%d] %s\n", i, symbols[i]);
|
|
}
|
|
|
|
free(symbols);
|
|
#endif
|
|
#ifdef __WIN32__
|
|
void* buffer[64];
|
|
USHORT nptrs = CaptureStackBackTrace(0, 64, buffer, NULL);
|
|
|
|
HANDLE process = GetCurrentProcess();
|
|
SymInitialize(process, NULL, TRUE);
|
|
|
|
SYMBOL_INFO* symbol = (SYMBOL_INFO*)calloc(sizeof(SYMBOL_INFO) + 256, 1);
|
|
symbol->MaxNameLen = 255;
|
|
symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
|
|
|
|
if (!symbol) {
|
|
V_printf("Backtrace failed\n");
|
|
return;
|
|
}
|
|
|
|
for (USHORT i = 0; i < nptrs; i++) {
|
|
if (SymFromAddr(process, (DWORD64)(buffer[i]), 0, symbol)) {
|
|
V_printf(" [%d] %s - 0x%0llX\n", i, symbol->Name, symbol->Address);
|
|
} else {
|
|
V_printf(" [%d] ??? - 0x%0llX\n", i, (DWORD64)(buffer[i]));
|
|
}
|
|
}
|
|
|
|
free(symbol);
|
|
#endif
|
|
};
|
|
|
|
PLATFORM_INTERFACE void *Plat_LoadLibrary( const char *psz )
|
|
{
|
|
#ifdef __linux__
|
|
void *lib = dlopen(psz, RTLD_GLOBAL | RTLD_NOW);
|
|
if (!lib)
|
|
V_printf("Failed to open %s\n\t%s\n", psz, dlerror());
|
|
return lib;
|
|
#endif
|
|
#ifdef __WIN32__
|
|
return LoadLibraryA(psz);
|
|
#endif
|
|
}
|
|
PLATFORM_INTERFACE void *Plat_GetProc( void *lib, const char *psz )
|
|
{
|
|
#ifdef __linux__
|
|
return dlsym(lib, psz);
|
|
#endif
|
|
#ifdef __WIN32__
|
|
return (void*)GetProcAddress((HMODULE)lib, psz);
|
|
#endif
|
|
}
|
|
PLATFORM_INTERFACE void Plat_UnloadLibrary( void *lib )
|
|
{
|
|
#ifdef __linux__
|
|
dlclose(lib);
|
|
#endif
|
|
#ifdef __WIN32__
|
|
FreeLibrary((HMODULE)lib);
|
|
#endif
|
|
};
|
|
|
|
PLATFORM_INTERFACE double Plat_GetTime( void )
|
|
{
|
|
struct timespec tp;
|
|
clock_gettime(CLOCK_MONOTONIC, &tp);
|
|
static time_t s_starttime = tp.tv_sec;
|
|
|
|
return (tp.tv_sec-s_starttime)+tp.tv_nsec/1e9;
|
|
}
|